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('Hi from createPreprocessor');
+ const output = p.process(`
+
+ Hello World, from Vite!
+
+ `, {
+ 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 { Hello } "#,
@@ -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 = Hello } "#,
@@ -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 { Hello } "#,
@@ -209,6 +239,7 @@ test!(
|_| as_folder(TransformVisitor::new(
&Ident::new("template".into(), Default::default()),
None,
+ None,
)),
content_tag_export_default,
r#"Hello"#,
@@ -220,6 +251,7 @@ test!(
|_| as_folder(TransformVisitor::new(
&Ident::new("template".into(), Default::default()),
None,
+ None,
)),
inner_expression,
r#"let x = doIt(Hello)"#,
@@ -231,6 +263,7 @@ test!(
|_| as_folder(TransformVisitor::new(
&Ident::new("template".into(), Default::default()),
None,
+ None,
)),
backtick_in_template,
r#"let x = He`llo"#,
@@ -242,6 +275,7 @@ test!(
|_| as_folder(TransformVisitor::new(
&Ident::new("template".into(), Default::default()),
None,
+ None,
)),
dollar_in_template,
r#"let x = He${ll}o"#,
@@ -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 = Hello\nWorld\u1234"#,
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";
Hi`,
- { filename: 'path/to/my/component.gjs' }
+ { filename: "path/to/my/component.gjs" }
);
}).to.throw(`Parse Error at path/to/my/component.gjs:2:15: 2:15`);
});
diff --git a/test/process.test.js b/test/process.test.js
index e1d70de..bafbb99 100644
--- a/test/process.test.js
+++ b/test/process.test.js
@@ -9,6 +9,35 @@ const { expect } = chai;
const p = new Preprocessor();
describe(`process`, function () {
+ it("tmp", function () {
+ let output = p.process("Hi", {
+ transform: (src, type, utils) => {
+ console.log("Did it run?");
+ let t = "todo";
+ // let t = utils.bindImport("@ember/template-compiler", "template");
+
+ if (type === "expression") {
+ return `${t}("${utils.escapeStringLiteral(
+ src
+ )}", { eval() { console.log("hi"); return eval(arguments[0]) } }`;
+ } else {
+ return `static {
+ ${t}("${utils.escapeStringLiteral(src)}", {
+ eval() { return eval(arguments[0]) },
+ component: this,
+ })
+ }`;
+ }
+ },
+ });
+
+ expect(output).to
+ .equalCode(`import { template } from "@ember/template-compiler";
+ export default template(\`Hi\`, {
+ eval () { console.log("hi"); return eval(arguments[0]) }
+ });`);
+ });
+
it("works for a basic example", function () {
let output = p.process("Hi");
@@ -91,7 +120,9 @@ describe(`process`, function () {
});
it("Provides inline source maps if inline_source_map option is set to true", function () {
- let output = p.process(`Hi`, { inline_source_map: true });
+ let output = p.process(`Hi`, {
+ inline_source_map: true,
+ });
expect(output).to.match(
/sourceMappingURL=data:application\/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyI8dGVtcGxhdGU-SGk8L3RlbXBsYXRlPiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsZUFBQSxTQUFVLENBQUEsRUFBRSxDQUFBLEVBQUE7SUFBQTtRQUFBLE9BQUEsS0FBQSxTQUFBLENBQUEsRUFBVztJQUFEO0FBQUEsR0FBQyJ9/