| 1 | use markdown_it::parser::inline::{InlineRule, InlineState}; |
| 2 | use markdown_it::Node; |
| 3 | use oxc_allocator::Allocator; |
| 4 | use oxc_diagnostics::OxcDiagnostic; |
| 5 | use oxc_parser::Parser; |
| 6 | use oxc_span::{GetSpan, SourceType}; |
| 7 | |
| 8 | use crate::plugin::{ErrorBlock, RawBlock}; |
| 9 | |
| 10 | /// Inline rule for ${...} TypeScript expressions. |
| 11 | pub(crate) struct Rule; |
| 12 | |
| 13 | impl InlineRule for Rule { |
| 14 | const MARKER: char = '$'; |
| 15 | |
| 16 | fn run(state: &mut InlineState) -> Option<(Node, usize)> { |
| 17 | let input = &state.src[state.pos..state.pos_max]; |
| 18 | |
| 19 | if !input.starts_with("${") { |
| 20 | return None; |
| 21 | } |
| 22 | |
| 23 | let expr_source = &input["${".len()..]; |
| 24 | |
| 25 | let allocator = Allocator::default(); |
| 26 | let source_type = SourceType::default() |
| 27 | .with_module(true) |
| 28 | .with_typescript(true) |
| 29 | .with_jsx(false); |
| 30 | |
| 31 | let expr = match Parser::new(&allocator, expr_source, source_type).parse_expression() { |
| 32 | Ok(expr) => expr, |
| 33 | Err(errors) => { |
| 34 | return Some((Node::new(ErrorBlock { errors }), "${".len())); |
| 35 | } |
| 36 | }; |
| 37 | let mut length = expr.span().end as usize; |
| 38 | |
| 39 | // Verify the next character after whitespace is a } |
| 40 | while let Some(char) = expr_source.as_bytes().get(length) { |
| 41 | match char { |
| 42 | b' ' | b'\t' | b'\n' | b'\r' => length += 1, |
| 43 | _ => break, |
| 44 | } |
| 45 | } |
| 46 | if expr_source.as_bytes().get(length) != Some(&b'}') { |
| 47 | let error = OxcDiagnostic::error("Invalid template expression"); |
| 48 | return Some(( |
| 49 | Node::new(ErrorBlock { |
| 50 | errors: vec![error], |
| 51 | }), |
| 52 | input.len(), |
| 53 | )); |
| 54 | } |
| 55 | |
| 56 | let total_len = "${".len() + length + "}".len(); |
| 57 | let content = &input[..total_len]; |
| 58 | let node = Node::new(RawBlock { |
| 59 | content: content.to_string(), |
| 60 | }); |
| 61 | |
| 62 | Some((node, total_len)) |
| 63 | } |
| 64 | } |