diff options
-rw-r--r-- | tests/test_utils/swc.rs | 29 | ||||
-rw-r--r-- | tests/test_utils/to_document.rs | 60 | ||||
-rw-r--r-- | tests/test_utils/to_swc.rs | 2 | ||||
-rw-r--r-- | tests/xxx_document.rs | 30 | ||||
-rw-r--r-- | tests/xxx_swc.rs | 312 |
5 files changed, 234 insertions, 199 deletions
diff --git a/tests/test_utils/swc.rs b/tests/test_utils/swc.rs index c0fffa0..80376b8 100644 --- a/tests/test_utils/swc.rs +++ b/tests/test_utils/swc.rs @@ -3,8 +3,11 @@ extern crate swc_common; extern crate swc_ecma_ast; extern crate swc_ecma_parser; use micromark::{MdxExpressionKind, MdxSignal}; -use swc_common::{source_map::Pos, BytePos, FileName, SourceFile, Spanned}; +use swc_common::{ + source_map::Pos, sync::Lrc, BytePos, FileName, FilePathMapping, SourceFile, SourceMap, Spanned, +}; use swc_ecma_ast::{EsVersion, Expr, Module}; +use swc_ecma_codegen::{text_writer::JsWriter, Emitter}; use swc_ecma_parser::{ error::Error as SwcError, parse_file_as_expr, parse_file_as_module, EsConfig, Syntax, }; @@ -164,6 +167,30 @@ pub fn parse_expression_to_tree( } } +/// Serialize an SWC module. +/// To do: support comments. +#[allow(dead_code)] +pub fn serialize(module: &Module) -> String { + let mut buf = vec![]; + let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + // let comm = &program.comments as &dyn swc_common::comments::Comments; + { + let mut emitter = Emitter { + cfg: swc_ecma_codegen::Config { + ..Default::default() + }, + cm: cm.clone(), + // To do: figure out how to pass them. + comments: None, + wr: JsWriter::new(cm, "\n", &mut buf, None), + }; + + emitter.emit_module(module).unwrap(); + } + + String::from_utf8_lossy(&buf).to_string() +} + /// Check that the resulting AST of ESM is OK. /// /// This checks that only module declarations (import/exports) are used, not diff --git a/tests/test_utils/to_document.rs b/tests/test_utils/to_document.rs index b44d029..96e9d7f 100644 --- a/tests/test_utils/to_document.rs +++ b/tests/test_utils/to_document.rs @@ -186,8 +186,10 @@ pub fn to_document(mut program: Program, options: &Options) -> Result<Program, S swc_ecma_ast::DefaultDecl::Fn(func) => swc_ecma_ast::Expr::Fn(func), swc_ecma_ast::DefaultDecl::TsInterfaceDecl(_) => { // To do: improved error? Not sure what a real example of this is? - unreachable!("Cannot use TypeScript interface declarations as default export in MDX") - }, + unreachable!( + "Cannot use TypeScript interface declarations as default export in MDX" + ) + } })); } swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::ExportDefaultExpr( @@ -206,7 +208,9 @@ pub fn to_document(mut program: Program, options: &Options) -> Result<Program, S // export {a, b as c} from 'd' // export {a, b as c} // ``` - swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::ExportNamed(mut named_export)) => { + swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::ExportNamed( + mut named_export, + )) => { // SWC is currently crashing when generating code, w/o source // map, if an actual location is set on this node. named_export.span = swc_common::DUMMY_SP; @@ -220,8 +224,11 @@ pub fn to_document(mut program: Program, options: &Options) -> Result<Program, S // branch of this looks interesting, but as far as I // understand it *is not* valid ES. // `export a from 'b'` is a syntax error, even in SWC. - if let swc_ecma_ast::ExportSpecifier::Named(named) = &named_export.specifiers[index] { - if let Some(swc_ecma_ast::ModuleExportName::Ident(ident)) = &named.exported { + if let swc_ecma_ast::ExportSpecifier::Named(named) = + &named_export.specifiers[index] + { + if let Some(swc_ecma_ast::ModuleExportName::Ident(ident)) = &named.exported + { if ident.sym.as_ref() == "default" { // For some reason the AST supports strings // instead of identifiers. @@ -254,29 +261,33 @@ pub fn to_document(mut program: Program, options: &Options) -> Result<Program, S // If there was just a default export, we can drop the original node. if !named_export.specifiers.is_empty() { // Pass through. - replacements.push(swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::ExportNamed(named_export))); + replacements.push(swc_ecma_ast::ModuleItem::ModuleDecl( + swc_ecma_ast::ModuleDecl::ExportNamed(named_export), + )); } // It’s an `export {x} from 'y'`, so generate an import. if let Some(source) = source { - replacements.push(swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::Import(swc_ecma_ast::ImportDecl { - specifiers: vec![swc_ecma_ast::ImportSpecifier::Named( - swc_ecma_ast::ImportNamedSpecifier { - local: swc_ecma_ast::Ident { - sym: "MDXLayout".into(), - optional: false, + replacements.push(swc_ecma_ast::ModuleItem::ModuleDecl( + swc_ecma_ast::ModuleDecl::Import(swc_ecma_ast::ImportDecl { + specifiers: vec![swc_ecma_ast::ImportSpecifier::Named( + swc_ecma_ast::ImportNamedSpecifier { + local: swc_ecma_ast::Ident { + sym: "MDXLayout".into(), + optional: false, + span: swc_common::DUMMY_SP, + }, + imported: Some(swc_ecma_ast::ModuleExportName::Ident(id)), span: swc_common::DUMMY_SP, + is_type_only: false, }, - imported: Some(swc_ecma_ast::ModuleExportName::Ident( id)), - span: swc_common::DUMMY_SP, - is_type_only: false, - }, - )], - src: source, - type_only: false, - asserts: None, - span: swc_common::DUMMY_SP, - }))) + )], + src: source, + type_only: false, + asserts: None, + span: swc_common::DUMMY_SP, + }), + )) } // It’s an `export {x}`, so generate a variable declaration. else { @@ -284,13 +295,14 @@ pub fn to_document(mut program: Program, options: &Options) -> Result<Program, S } } else { // Pass through. - replacements.push(swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::ExportNamed(named_export))); + replacements.push(swc_ecma_ast::ModuleItem::ModuleDecl( + swc_ecma_ast::ModuleDecl::ExportNamed(named_export), + )); } } swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::Import(_)) | swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::ExportDecl(_)) | swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::ExportAll(_)) - // To do: handle TS things? | swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::TsImportEquals(_)) | swc_ecma_ast::ModuleItem::ModuleDecl(swc_ecma_ast::ModuleDecl::TsExportAssignment( _, diff --git a/tests/test_utils/to_swc.rs b/tests/test_utils/to_swc.rs index 59d60ee..6ed48b6 100644 --- a/tests/test_utils/to_swc.rs +++ b/tests/test_utils/to_swc.rs @@ -379,8 +379,6 @@ fn transform_root( } } - // To do: remove whitespace? - // To do: return a single child if there is one? Ok(Some(swc_ecma_ast::JSXElementChild::JSXFragment( create_fragment(nodes, node), ))) diff --git a/tests/xxx_document.rs b/tests/xxx_document.rs index 2d89f16..dcbb56b 100644 --- a/tests/xxx_document.rs +++ b/tests/xxx_document.rs @@ -5,37 +5,13 @@ extern crate swc_ecma_codegen; mod test_utils; use micromark::{micromark_to_mdast, Constructs, Options}; use pretty_assertions::assert_eq; -use swc_common::{sync::Lrc, FilePathMapping, SourceMap}; -use swc_ecma_codegen::{text_writer::JsWriter, Emitter}; use test_utils::{ - swc::{parse_esm, parse_expression}, + swc::{parse_esm, parse_expression, serialize}, to_document::{to_document, Options as DocumentOptions}, to_hast::to_hast, - to_swc::{to_swc, Program}, + to_swc::to_swc, }; -// To do: share with `xxx_swc`. -fn serialize(program: &Program) -> String { - let mut buf = vec![]; - let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - // let comm = &program.comments as &dyn swc_common::comments::Comments; - { - let mut emitter = Emitter { - cfg: swc_ecma_codegen::Config { - ..Default::default() - }, - cm: cm.clone(), - // To do: figure out how to pass them. - comments: None, - wr: JsWriter::new(cm, "\n", &mut buf, None), - }; - - emitter.emit_module(&program.module).unwrap(); - } - - String::from_utf8_lossy(&buf).to_string() -} - fn from_markdown(value: &str) -> Result<String, String> { let mdast = micromark_to_mdast( value, @@ -48,7 +24,7 @@ fn from_markdown(value: &str) -> Result<String, String> { )?; let hast = to_hast(&mdast); let program = to_document(to_swc(&hast)?, &DocumentOptions::default())?; - let value = serialize(&program); + let value = serialize(&program.module); Ok(value) } diff --git a/tests/xxx_swc.rs b/tests/xxx_swc.rs index 5504432..26814cf 100644 --- a/tests/xxx_swc.rs +++ b/tests/xxx_swc.rs @@ -4,35 +4,12 @@ extern crate swc_ecma_ast; extern crate swc_ecma_codegen; mod test_utils; use pretty_assertions::assert_eq; -use swc_common::{sync::Lrc, FilePathMapping, SourceMap}; -use swc_ecma_codegen::{text_writer::JsWriter, Emitter}; use test_utils::{ hast, + swc::serialize, to_swc::{to_swc, Program}, }; -// To do: share with `xxx_document`. -fn serialize(program: &Program) -> String { - let mut buf = vec![]; - let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - // let comm = &program.comments as &dyn swc_common::comments::Comments; - { - let mut emitter = Emitter { - cfg: swc_ecma_codegen::Config { - ..Default::default() - }, - cm: cm.clone(), - // To do: figure out how to pass them. - comments: None, - wr: JsWriter::new(cm, "\n", &mut buf, None), - }; - - emitter.emit_module(&program.module).unwrap(); - } - - String::from_utf8_lossy(&buf).to_string() -} - #[test] fn swc() -> Result<(), String> { let comment_ast = to_swc(&hast::Node::Comment(hast::Comment { @@ -83,7 +60,7 @@ fn swc() -> Result<(), String> { ); assert_eq!( - serialize(&comment_ast), + serialize(&comment_ast.module), // To do: comment should be in this. "<>{}</>;\n", "should support a `Comment` (serialize)", @@ -155,98 +132,119 @@ fn swc() -> Result<(), String> { ); assert_eq!( - serialize(&element_ast), + serialize(&element_ast.module), "<a className=\"b\"/>;\n", "should support an `Element` (serialize)", ); assert_eq!( - serialize(&to_swc(&hast::Node::Element(hast::Element { - tag_name: "a".into(), - properties: vec![], - children: vec![hast::Node::Text(hast::Text { - value: "a".into(), + serialize( + &to_swc(&hast::Node::Element(hast::Element { + tag_name: "a".into(), + properties: vec![], + children: vec![hast::Node::Text(hast::Text { + value: "a".into(), + position: None, + })], position: None, - })], - position: None, - }))?), + }))? + .module + ), "<a >{\"a\"}</a>;\n", "should support an `Element` w/ children", ); assert_eq!( - serialize(&to_swc(&hast::Node::Element(hast::Element { - tag_name: "a".into(), - properties: vec![("b".into(), hast::PropertyValue::String("c".into()),)], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::Element(hast::Element { + tag_name: "a".into(), + properties: vec![("b".into(), hast::PropertyValue::String("c".into()),)], + children: vec![], + position: None, + }))? + .module + ), "<a b=\"c\"/>;\n", "should support an `Element` w/ a string attribute", ); assert_eq!( - serialize(&to_swc(&hast::Node::Element(hast::Element { - tag_name: "a".into(), - properties: vec![("b".into(), hast::PropertyValue::Boolean(true),)], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::Element(hast::Element { + tag_name: "a".into(), + properties: vec![("b".into(), hast::PropertyValue::Boolean(true),)], + children: vec![], + position: None, + }))? + .module + ), "<a b/>;\n", "should support an `Element` w/ a boolean (true) attribute", ); assert_eq!( - serialize(&to_swc(&hast::Node::Element(hast::Element { - tag_name: "a".into(), - properties: vec![("b".into(), hast::PropertyValue::Boolean(false),)], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::Element(hast::Element { + tag_name: "a".into(), + properties: vec![("b".into(), hast::PropertyValue::Boolean(false),)], + children: vec![], + position: None, + }))? + .module + ), "<a />;\n", "should support an `Element` w/ a boolean (false) attribute", ); assert_eq!( - serialize(&to_swc(&hast::Node::Element(hast::Element { - tag_name: "a".into(), - properties: vec![( - "b".into(), - hast::PropertyValue::CommaSeparated(vec!["c".into(), "d".into()]), - )], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::Element(hast::Element { + tag_name: "a".into(), + properties: vec![( + "b".into(), + hast::PropertyValue::CommaSeparated(vec!["c".into(), "d".into()]), + )], + children: vec![], + position: None, + }))? + .module + ), "<a b=\"c, d\"/>;\n", "should support an `Element` w/ a comma-separated attribute", ); assert_eq!( - serialize(&to_swc(&hast::Node::Element(hast::Element { - tag_name: "a".into(), - properties: vec![ - ("data123".into(), hast::PropertyValue::Boolean(true),), - ("dataFoo".into(), hast::PropertyValue::Boolean(true),), - ("dataBAR".into(), hast::PropertyValue::Boolean(true),) - ], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::Element(hast::Element { + tag_name: "a".into(), + properties: vec![ + ("data123".into(), hast::PropertyValue::Boolean(true),), + ("dataFoo".into(), hast::PropertyValue::Boolean(true),), + ("dataBAR".into(), hast::PropertyValue::Boolean(true),) + ], + children: vec![], + position: None, + }))? + .module + ), "<a data-123 data-foo data-b-a-r/>;\n", "should support an `Element` w/ data attributes", ); assert_eq!( - serialize(&to_swc(&hast::Node::Element(hast::Element { - tag_name: "a".into(), - properties: vec![ - ("role".into(), hast::PropertyValue::Boolean(true),), - ("ariaValueNow".into(), hast::PropertyValue::Boolean(true),), - ("ariaDescribedBy".into(), hast::PropertyValue::Boolean(true),) - ], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::Element(hast::Element { + tag_name: "a".into(), + properties: vec![ + ("role".into(), hast::PropertyValue::Boolean(true),), + ("ariaValueNow".into(), hast::PropertyValue::Boolean(true),), + ("ariaDescribedBy".into(), hast::PropertyValue::Boolean(true),) + ], + children: vec![], + position: None, + }))? + .module + ), "<a role aria-valuenow aria-describedby/>;\n", "should support an `Element` w/ aria attributes", ); @@ -288,107 +286,131 @@ fn swc() -> Result<(), String> { ); assert_eq!( - serialize(&mdx_element_ast), + serialize(&mdx_element_ast.module), "<></>;\n", "should support an `MdxElement` (fragment, serialize)", ); assert_eq!( - serialize(&to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { - name: Some("a".into()), - attributes: vec![], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { + name: Some("a".into()), + attributes: vec![], + children: vec![], + position: None, + }))? + .module + ), "<a />;\n", "should support an `MdxElement` (element, no children)", ); assert_eq!( - serialize(&to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { - name: Some("a:b".into()), - attributes: vec![], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { + name: Some("a:b".into()), + attributes: vec![], + children: vec![], + position: None, + }))? + .module + ), "<a:b />;\n", "should support an `MdxElement` (element, namespace id)", ); assert_eq!( - serialize(&to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { - name: Some("a.b.c".into()), - attributes: vec![], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { + name: Some("a.b.c".into()), + attributes: vec![], + children: vec![], + position: None, + }))? + .module + ), "<a.b.c />;\n", "should support an `MdxElement` (element, member expression)", ); assert_eq!( - serialize(&to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { - name: Some("a".into()), - attributes: vec![], - children: vec![hast::Node::Text(hast::Text { - value: "b".into(), + serialize( + &to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { + name: Some("a".into()), + attributes: vec![], + children: vec![hast::Node::Text(hast::Text { + value: "b".into(), + position: None, + })], position: None, - })], - position: None, - }))?), + }))? + .module + ), "<a >{\"b\"}</a>;\n", "should support an `MdxElement` (element, children)", ); assert_eq!( - serialize(&to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { - name: Some("a".into()), - attributes: vec![hast::AttributeContent::Property(hast::MdxJsxAttribute { - name: "b".into(), - value: None - })], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { + name: Some("a".into()), + attributes: vec![hast::AttributeContent::Property(hast::MdxJsxAttribute { + name: "b".into(), + value: None + })], + children: vec![], + position: None, + }))? + .module + ), "<a b/>;\n", "should support an `MdxElement` (element, boolean attribute)", ); assert_eq!( - serialize(&to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { - name: Some("a".into()), - attributes: vec![hast::AttributeContent::Property(hast::MdxJsxAttribute { - name: "b".into(), - value: Some(hast::AttributeValue::Literal("c".into())) - })], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { + name: Some("a".into()), + attributes: vec![hast::AttributeContent::Property(hast::MdxJsxAttribute { + name: "b".into(), + value: Some(hast::AttributeValue::Literal("c".into())) + })], + children: vec![], + position: None, + }))? + .module + ), "<a b=\"c\"/>;\n", "should support an `MdxElement` (element, attribute w/ literal value)", ); assert_eq!( - serialize(&to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { - name: Some("a".into()), - attributes: vec![hast::AttributeContent::Property(hast::MdxJsxAttribute { - name: "b".into(), - value: Some(hast::AttributeValue::Expression("c".into())) - })], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { + name: Some("a".into()), + attributes: vec![hast::AttributeContent::Property(hast::MdxJsxAttribute { + name: "b".into(), + value: Some(hast::AttributeValue::Expression("c".into())) + })], + children: vec![], + position: None, + }))? + .module + ), "<a b={c}/>;\n", "should support an `MdxElement` (element, attribute w/ expression value)", ); assert_eq!( - serialize(&to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { - name: Some("a".into()), - attributes: vec![hast::AttributeContent::Expression("...c".into())], - children: vec![], - position: None, - }))?), + serialize( + &to_swc(&hast::Node::MdxJsxElement(hast::MdxJsxElement { + name: Some("a".into()), + attributes: vec![hast::AttributeContent::Expression("...c".into())], + children: vec![], + position: None, + }))? + .module + ), "<a {...c}/>;\n", "should support an `MdxElement` (element, expression attribute)", ); @@ -444,7 +466,7 @@ fn swc() -> Result<(), String> { ); assert_eq!( - serialize(&mdx_expression_ast), + serialize(&mdx_expression_ast.module), "<>{a}</>;\n", "should support an `MdxExpression` (serialize)", ); @@ -509,7 +531,7 @@ fn swc() -> Result<(), String> { ); assert_eq!( - serialize(&mdxjs_esm_ast), + serialize(&mdxjs_esm_ast.module), "import a from 'b';\n", "should support an `MdxjsEsm` (serialize)", ); @@ -565,7 +587,7 @@ fn swc() -> Result<(), String> { ); assert_eq!( - serialize(&root_ast), + serialize(&root_ast.module), "<>{\"a\"}</>;\n", "should support a `Root` (serialize)", ); @@ -618,7 +640,7 @@ fn swc() -> Result<(), String> { ); assert_eq!( - serialize(&text_ast), + serialize(&text_ast.module), "<>{\"a\"}</>;\n", "should support a `Text` (serialize)", ); |