diff --git a/index.html b/index.html index 924b37f..79903bf 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,15 @@ import {Preprocessor} from 'content-tag'; const p = new Preprocessor(); - const output = p.process(''); + const output = p.process(` + + `, { + transform: (src, type) => { + return `hi: ${type} src: ${src}`; + } + }); document.querySelector('#output').innerHTML = output; diff --git a/package-lock.json b/package-lock.json index ee67ef5..4d6c947 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "content-tag", - "version": "1.2.2", + "version": "2.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "content-tag", - "version": "1.2.2", + "version": "2.0.1", "license": "MIT", "devDependencies": { "@arethetypeswrong/cli": "^0.13.2", diff --git a/src/bindings.rs b/src/bindings.rs index afd7669..470964a 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -38,17 +38,28 @@ impl Options { None }; + let option_transform = Reflect::get(&options, &"transform".into()).unwrap(); + // NOTE: That this will be None if this value was passed but not as a valid transform + // We probably want to error here. + let transform = option_transform.dyn_into::().ok(); + // transform + // .call1(&JsValue::NULL, &JsValue::from("hi")) + // .unwrap(); + Self { // unwrap is justified here for the same reasons as commented above inline_source_map: js_boolean( &Reflect::get(&options, &"inline_source_map".into()).unwrap(), ), filename, + transform, } } else { Self { inline_source_map: false, filename: None, + // transform: Default? + transform: None, } } } diff --git a/src/lib.rs b/src/lib.rs index 295b09e..f5a945a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,11 +7,11 @@ use base64::{engine::general_purpose, Engine as _}; use std::path::PathBuf; use swc_common::comments::SingleThreadedComments; use swc_common::source_map::SourceMapGenConfig; -use swc_common::{self, sync::Lrc, FileName, SourceMap, Mark}; +use swc_common::{self, sync::Lrc, FileName, Mark, SourceMap}; use swc_core::common::GLOBALS; use swc_ecma_ast::{ - Ident, ImportDecl, ImportNamedSpecifier, ImportSpecifier, Module, ModuleDecl, - ModuleExportName, ModuleItem, + Ident, ImportDecl, ImportNamedSpecifier, ImportSpecifier, Module, ModuleDecl, ModuleExportName, + ModuleItem, }; use swc_ecma_codegen::Emitter; use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig}; @@ -21,14 +21,15 @@ use swc_ecma_utils::private_ident; use swc_ecma_visit::{as_folder, VisitMutWith, VisitWith}; mod bindings; +mod locate; mod snippets; mod transform; -mod locate; #[derive(Default)] pub struct Options { pub filename: Option, pub inline_source_map: bool, + pub transform: Option, } pub struct Preprocessor { @@ -47,7 +48,6 @@ impl SourceMapGenConfig for SourceMapConfig { } } - impl Preprocessor { pub fn new() -> Self { Self { @@ -123,6 +123,7 @@ impl Preprocessor { parsed_module.visit_mut_with(&mut as_folder(transform::TransformVisitor::new( &id, Some(&mut needs_import), + options.transform, ))); if !had_id_already && needs_import { @@ -281,12 +282,9 @@ fn simplify_imports(parsed_module: &mut Module) { } } - - #[cfg(test)] mod test_helpers; - macro_rules! testcase { ($test_name:ident, $input:expr, $expected:expr) => { #[test] diff --git a/src/main.rs b/src/main.rs index 475bf03..f271724 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,6 +23,7 @@ fn main() { Options { filename: Some(filename), inline_source_map: true, + transform: None, }, ); diff --git a/src/transform.rs b/src/transform.rs index 322d13e..867d48b 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -17,13 +17,19 @@ use swc_atoms::Atom; pub struct TransformVisitor<'a> { template_identifier: Ident, found_it: Option<&'a mut bool>, + transform: Option, } impl<'a> TransformVisitor<'a> { - pub fn new(id: &Ident, found_it: Option<&'a mut bool>) -> Self { + pub fn new( + id: &Ident, + found_it: Option<&'a mut bool>, + transform: Option, + ) -> Self { TransformVisitor { template_identifier: id.clone(), found_it, + transform, } } fn set_found_it(&mut self) { @@ -40,6 +46,22 @@ impl<'a> TransformVisitor<'a> { .. } = expr; + // Replace the entirety of the expression + // with the results of the transform call + if let Some(transform) = self.transform.as_ref() { + let content = transform + .call2( + &wasm_bindgen::JsValue::NULL, + &wasm_bindgen::JsValue::from(&contents.value.to_string()), + &wasm_bindgen::JsValue::from("expression"), + /* utils ( for bindImport )*/ + ) + .unwrap(); + + // TODO: error if content is not a string + return Expr::Lit(content.as_string().unwrap().into()); + } + Expr::Call(CallExpr { span: *span, callee: Callee::Expr(Box::new(Expr::Ident(self.template_identifier.clone()))), @@ -67,7 +89,11 @@ impl<'a> TransformVisitor<'a> { } fn escape_template_literal(input: &Atom) -> Atom { - input.replace("\\", "\\\\").replace("`", "\\`").replace("$", "\\$").into() + input + .replace("\\", "\\\\") + .replace("`", "\\`") + .replace("$", "\\$") + .into() } impl<'a> VisitMut for TransformVisitor<'a> { @@ -154,6 +180,7 @@ test!( as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )) }, content_tag_template_expression, @@ -166,6 +193,7 @@ test!( |_| as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )), content_tag_template_member, r#"class X { } "#, @@ -181,6 +209,7 @@ test!( |_| as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )), expression_inside_class_member, r#"class X { thing = } "#, @@ -194,6 +223,7 @@ test!( |_| as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )), class_member_inside_expression, r#"let x = class { } "#, @@ -209,6 +239,7 @@ test!( |_| as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )), content_tag_export_default, r#""#, @@ -220,6 +251,7 @@ test!( |_| as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )), inner_expression, r#"let x = doIt()"#, @@ -231,6 +263,7 @@ test!( |_| as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )), backtick_in_template, r#"let x = "#, @@ -242,6 +275,7 @@ test!( |_| as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )), dollar_in_template, r#"let x = "#, @@ -253,6 +287,7 @@ test!( |_| as_folder(TransformVisitor::new( &Ident::new("template".into(), Default::default()), None, + None, )), do_not_interpret_js_escapes_in_hbs, r#"let x = "#, diff --git a/test/parse.test.js b/test/parse.test.js index ac4b25a..2734c3e 100644 --- a/test/parse.test.js +++ b/test/parse.test.js @@ -173,7 +173,7 @@ describe(`parse`, function () { p.process( `const thing = "face";