aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_utils/swc.rs
diff options
context:
space:
mode:
authorLibravatar Titus Wormer <tituswormer@gmail.com>2022-09-30 18:17:54 +0200
committerLibravatar Titus Wormer <tituswormer@gmail.com>2022-09-30 18:18:58 +0200
commit117cfc10c6d4a0a9346a29353860d1185d1ea224 (patch)
treea5ae0b1f36b7955016b83477b3f4dd455669d2af /tests/test_utils/swc.rs
parent9dd7a2ba67b7c35e9cd5c9105fdf36aec764fa6e (diff)
downloadmarkdown-rs-117cfc10c6d4a0a9346a29353860d1185d1ea224.tar.gz
markdown-rs-117cfc10c6d4a0a9346a29353860d1185d1ea224.tar.bz2
markdown-rs-117cfc10c6d4a0a9346a29353860d1185d1ea224.zip
Add support for turning hast into swc
Diffstat (limited to '')
-rw-r--r--tests/test_utils/swc.rs101
1 files changed, 97 insertions, 4 deletions
diff --git a/tests/test_utils/swc.rs b/tests/test_utils/swc.rs
index f08fe38..c0fffa0 100644
--- a/tests/test_utils/swc.rs
+++ b/tests/test_utils/swc.rs
@@ -13,7 +13,7 @@ use swc_ecma_parser::{
// Use lexer in the future:
// <https://docs.rs/swc_ecma_parser/0.99.1/swc_ecma_parser/lexer/index.html>
-/// Parse ESM in MDX with SWC.
+/// Lex ESM in MDX with SWC.
#[allow(dead_code)]
pub fn parse_esm(value: &str) -> MdxSignal {
let (file, syntax, version) = create_config(value.to_string());
@@ -35,7 +35,31 @@ pub fn parse_esm(value: &str) -> MdxSignal {
}
}
-/// Parse expressions in MDX with SWC.
+/// Parse ESM in MDX with SWC.
+/// To do: figure out how to fix positional info.
+#[allow(dead_code)]
+pub fn parse_esm_to_tree(value: &str) -> Result<swc_ecma_ast::Module, String> {
+ let (file, syntax, version) = create_config(value.to_string());
+ let mut errors = vec![];
+
+ let result = parse_file_as_module(&file, syntax, version, None, &mut errors);
+
+ match result {
+ Err(error) => Err(swc_error_to_string(&error)),
+ Ok(module) => {
+ if errors.is_empty() {
+ Ok(module)
+ } else {
+ if errors.len() > 1 {
+ println!("parse_esm_to_tree: todo: multiple errors? {:?}", errors);
+ }
+ Err(swc_error_to_string(&errors[0]))
+ }
+ }
+ }
+}
+
+/// Lex expressions in MDX with SWC.
#[allow(dead_code)]
pub fn parse_expression(value: &str, kind: &MdxExpressionKind) -> MdxSignal {
// Empty expressions are OK.
@@ -79,6 +103,67 @@ pub fn parse_expression(value: &str, kind: &MdxExpressionKind) -> MdxSignal {
}
}
+/// Parse ESM in MDX with SWC.
+/// To do: figure out how to fix positional info.
+#[allow(dead_code)]
+pub fn parse_expression_to_tree(
+ value: &str,
+ kind: &MdxExpressionKind,
+) -> Result<Box<swc_ecma_ast::Expr>, String> {
+ // For attribute expression, a spread is needed, for which we have to prefix
+ // and suffix the input.
+ // See `check_expression_ast` for how the AST is verified.
+ let (prefix, suffix) = if matches!(kind, MdxExpressionKind::AttributeExpression) {
+ ("({", "})")
+ } else {
+ ("", "")
+ };
+
+ let (file, syntax, version) = create_config(format!("{}{}{}", prefix, value, suffix));
+ let mut errors = vec![];
+ let result = parse_file_as_expr(&file, syntax, version, None, &mut errors);
+
+ match result {
+ Err(error) => Err(swc_error_to_string(&error)),
+ Ok(expr) => {
+ if errors.is_empty() {
+ if matches!(kind, MdxExpressionKind::AttributeExpression) {
+ let mut obj = None;
+
+ if let swc_ecma_ast::Expr::Paren(d) = *expr {
+ if let swc_ecma_ast::Expr::Object(d) = *d.expr {
+ obj = Some(d)
+ }
+ };
+
+ if let Some(mut obj) = obj {
+ if obj.props.len() > 1 {
+ Err("Unexpected extra content in spread: only a single spread is supported".into())
+ } else if let Some(swc_ecma_ast::PropOrSpread::Spread(d)) = obj.props.pop()
+ {
+ Ok(d.expr)
+ } else {
+ Err("Unexpected prop in spread: only a spread is supported".into())
+ }
+ } else {
+ Err("Expected an object spread (`{...spread}`)".into())
+ }
+ } else {
+ Ok(expr)
+ }
+ } else {
+ if errors.len() > 1 {
+ println!(
+ "parse_expression_to_tree: todo: multiple errors? {:?}",
+ errors
+ );
+ }
+ Err(swc_error_to_string(&errors[0]))
+ }
+ }
+ }
+}
+
/// Check that the resulting AST of ESM is OK.
///
/// This checks that only module declarations (import/exports) are used, not
@@ -138,9 +223,12 @@ fn swc_error_to_signal(
prefix_len: usize,
name: &str,
) -> MdxSignal {
- let message = error.kind().msg().to_string();
let place = fix_swc_position(error.span().hi.to_usize(), prefix_len);
- let message = format!("Could not parse {} with swc: {}", name, message);
+ let message = format!(
+ "Could not parse {} with swc: {}",
+ name,
+ swc_error_to_string(error)
+ );
if place >= value_len {
MdxSignal::Eof(message)
@@ -149,6 +237,11 @@ fn swc_error_to_signal(
}
}
+/// Turn an SWC error into a string.
+fn swc_error_to_string(error: &SwcError) -> String {
+ error.kind().msg().into()
+}
+
/// Move past JavaScript whitespace (well, actually ASCII whitespace) and
/// comments.
///