Markdown parser fork with extended syntax for personal use.
1mod test_utils;
2use markdown::{
3 mdast::{Blockquote, MdxTextExpression, Node, Paragraph, Root, Text},
4 message, to_html_with_options, to_mdast,
5 unist::Position,
6 Constructs, Options, ParseOptions,
7};
8use pretty_assertions::assert_eq;
9use test_utils::swc::{parse_esm, parse_expression};
10
11/// Note: these tests are also in `micromark/micromark-extension-mdx-expression`
12/// at `tests/index.js`.
13#[test]
14fn mdx_expression() -> Result<(), message::Message> {
15 let swc = Options {
16 parse: ParseOptions {
17 constructs: Constructs::mdx(),
18 mdx_esm_parse: Some(Box::new(parse_esm)),
19 mdx_expression_parse: Some(Box::new(parse_expression)),
20 ..Default::default()
21 },
22 ..Default::default()
23 };
24
25 assert_eq!(
26 to_html_with_options("a {} b", &swc)?,
27 "<p>a b</p>",
28 "should support an empty expression (1)"
29 );
30
31 assert_eq!(
32 to_html_with_options("a { \t\r\n} b", &swc)?,
33 "<p>a b</p>",
34 "should support an empty expression (2)"
35 );
36
37 assert_eq!(
38 to_html_with_options("a {/**/} b", &swc)?,
39 "<p>a b</p>",
40 "should support a multiline comment (1)"
41 );
42
43 assert_eq!(
44 to_html_with_options("a { /*\n*/\t} b", &swc)?,
45 "<p>a b</p>",
46 "should support a multiline comment (2)"
47 );
48
49 assert_eq!(
50 to_html_with_options("a {/*b*//*c*/} d", &swc)?,
51 "<p>a d</p>",
52 "should support a multiline comment (3)"
53 );
54
55 assert_eq!(
56 to_html_with_options("a {b/*c*/} d", &swc)?,
57 "<p>a d</p>",
58 "should support a multiline comment (4)"
59 );
60
61 assert_eq!(
62 to_html_with_options("a {/*b*/c} d", &swc)?,
63 "<p>a d</p>",
64 "should support a multiline comment (5)"
65 );
66
67 assert_eq!(
68 to_html_with_options("a {//} b", &swc)
69 .err()
70 .unwrap()
71 .to_string(),
72 "1:9: Could not parse expression with swc: Unexpected eof (mdx:swc)",
73 "should crash on an incorrect line comment (1)"
74 );
75
76 assert_eq!(
77 to_html_with_options("a { // b } c", &swc)
78 .err()
79 .unwrap()
80 .to_string(),
81 "1:13: Could not parse expression with swc: Unexpected eof (mdx:swc)",
82 "should crash on an incorrect line comment (2)"
83 );
84
85 assert_eq!(
86 to_html_with_options("a {//\n} b", &swc)?,
87 "<p>a b</p>",
88 "should support a line comment followed by a line ending"
89 );
90
91 assert_eq!(
92 to_html_with_options("a {// b\nc} d", &swc)?,
93 "<p>a d</p>",
94 "should support a line comment followed by a line ending and an expression"
95 );
96
97 assert_eq!(
98 to_html_with_options("a {b// c\n} d", &swc)?,
99 "<p>a d</p>",
100 "should support an expression followed by a line comment and a line ending"
101 );
102
103 assert_eq!(
104 to_html_with_options("a {/*b*/ // c\n} d", &swc)?,
105 "<p>a d</p>",
106 "should support comments"
107 );
108
109 assert_eq!(
110 to_html_with_options("a {b.c} d", &swc)?,
111 "<p>a d</p>",
112 "should support expression statements (1)"
113 );
114
115 assert_eq!(
116 to_html_with_options("a {1 + 1} b", &swc)?,
117 "<p>a b</p>",
118 "should support expression statements (2)"
119 );
120
121 assert_eq!(
122 to_html_with_options("a {function () {}} b", &swc)?,
123 "<p>a b</p>",
124 "should support expression statements (3)"
125 );
126
127 assert_eq!(
128 to_html_with_options("a {var b = \"c\"} d", &swc)
129 .err()
130 .unwrap()
131 .to_string(),
132 "1:4: Could not parse expression with swc: Expression expected (mdx:swc)",
133 "should crash on non-expressions"
134 );
135
136 assert_eq!(
137 to_html_with_options("> a {\n> b} c", &swc)?,
138 "<blockquote>\n<p>a c</p>\n</blockquote>",
139 "should support expressions in containers"
140 );
141
142 assert_eq!(
143 to_html_with_options("> a {\n> b<} c", &swc)
144 .err()
145 .unwrap()
146 .to_string(),
147 "2:8: Could not parse expression with swc: Unexpected eof (mdx:swc)",
148 "should crash on incorrect expressions in containers (1)"
149 );
150
151 assert_eq!(
152 to_html_with_options("> a {\n> b\n> c} d", &swc)
153 .err()
154 .unwrap()
155 .to_string(),
156 "3:7: Could not parse expression with swc: Unexpected content after expression (mdx:swc)",
157 "should crash on incorrect expressions in containers (2)"
158 );
159
160 Ok(())
161}
162
163/// Note: these tests are also in `micromark/micromark-extension-mdx-expression`
164/// at `tests/index.js`.
165#[test]
166fn mdx_expression_text_agnostic() -> Result<(), message::Message> {
167 let mdx = Options {
168 parse: ParseOptions::mdx(),
169 ..Default::default()
170 };
171
172 assert_eq!(
173 to_html_with_options("a {b} c", &mdx)?,
174 "<p>a c</p>",
175 "should support an expression"
176 );
177
178 assert_eq!(
179 to_html_with_options("a {} b", &mdx)?,
180 "<p>a b</p>",
181 "should support an empty expression"
182 );
183
184 assert_eq!(
185 to_html_with_options("a {b c", &mdx)
186 .err()
187 .unwrap()
188 .to_string(),
189 "1:7: Unexpected end of file in expression, expected a corresponding closing brace for `{` (markdown-rs:unexpected-eof)",
190 "should crash if no closing brace is found (1)"
191 );
192
193 assert_eq!(
194 to_html_with_options("a {b { c } d", &mdx)
195 .err()
196 .unwrap().to_string(),
197 "1:13: Unexpected end of file in expression, expected a corresponding closing brace for `{` (markdown-rs:unexpected-eof)",
198 "should crash if no closing brace is found (2)"
199 );
200
201 assert_eq!(
202 to_html_with_options("a {\n} b", &mdx)?,
203 "<p>a b</p>",
204 "should support a line ending in an expression"
205 );
206
207 assert_eq!(
208 to_html_with_options("a } b", &mdx)?,
209 "<p>a } b</p>",
210 "should support just a closing brace"
211 );
212
213 assert_eq!(
214 to_html_with_options("{ a } b", &mdx)?,
215 "<p> b</p>",
216 "should support expressions as the first thing when following by other things"
217 );
218
219 assert_eq!(
220 to_mdast("a {alpha} b.", &mdx.parse)?,
221 Node::Root(Root {
222 children: vec![Node::Paragraph(Paragraph {
223 children: vec![
224 Node::Text(Text {
225 value: "a ".into(),
226 position: Some(Position::new(1, 1, 0, 1, 3, 2))
227 }),
228 Node::MdxTextExpression(MdxTextExpression {
229 value: "alpha".into(),
230 position: Some(Position::new(1, 3, 2, 1, 10, 9)),
231 stops: vec![(0, 3)]
232 }),
233 Node::Text(Text {
234 value: " b.".into(),
235 position: Some(Position::new(1, 10, 9, 1, 13, 12))
236 })
237 ],
238 position: Some(Position::new(1, 1, 0, 1, 13, 12))
239 })],
240 position: Some(Position::new(1, 1, 0, 1, 13, 12))
241 }),
242 "should support mdx expressions (text) as `MdxTextExpression`s in mdast"
243 );
244
245 Ok(())
246}
247
248/// Note: these tests are also in `micromark/micromark-extension-mdx-expression`
249/// at `tests/index.js`.
250#[test]
251fn mdx_expression_text_gnostic() -> Result<(), message::Message> {
252 let swc = Options {
253 parse: ParseOptions {
254 constructs: Constructs::mdx(),
255 mdx_esm_parse: Some(Box::new(parse_esm)),
256 mdx_expression_parse: Some(Box::new(parse_expression)),
257 ..Default::default()
258 },
259 ..Default::default()
260 };
261
262 assert_eq!(
263 to_html_with_options("a {b} c", &swc)?,
264 "<p>a c</p>",
265 "should support an expression"
266 );
267
268 assert_eq!(
269 to_html_with_options("a {??} b", &swc)
270 .err()
271 .unwrap()
272 .to_string(),
273 "1:9: Could not parse expression with swc: Unexpected eof (mdx:swc)",
274 "should crash on an incorrect expression"
275 );
276
277 assert_eq!(
278 to_html_with_options("a {} b", &swc)?,
279 "<p>a b</p>",
280 "should support an empty expression"
281 );
282
283 assert_eq!(
284 to_html_with_options("a {b c", &swc)
285 .err()
286 .unwrap()
287 .to_string(),
288 "1:7: Unexpected end of file in expression, expected a corresponding closing brace for `{` (markdown-rs:unexpected-eof)",
289 "should crash if no closing brace is found (1)"
290 );
291
292 assert_eq!(
293 to_html_with_options("a {b { c } d", &swc)
294 .err()
295 .unwrap()
296 .to_string(),
297 "1:13: Could not parse expression with swc: Unexpected content after expression (mdx:swc)",
298 "should crash if no closing brace is found (2)"
299 );
300
301 assert_eq!(
302 to_html_with_options("a {\n} b", &swc)?,
303 "<p>a b</p>",
304 "should support a line ending in an expression"
305 );
306
307 assert_eq!(
308 to_html_with_options("a } b", &swc)?,
309 "<p>a } b</p>",
310 "should support just a closing brace"
311 );
312
313 assert_eq!(
314 to_html_with_options("{ a } b", &swc)?,
315 "<p> b</p>",
316 "should support expressions as the first thing when following by other things"
317 );
318
319 assert_eq!(
320 to_html_with_options("a { /* { */ } b", &swc)?,
321 "<p>a b</p>",
322 "should support an unbalanced opening brace (if JS permits)"
323 );
324
325 assert_eq!(
326 to_html_with_options("a { /* } */ } b", &swc)?,
327 "<p>a b</p>",
328 "should support an unbalanced closing brace (if JS permits)"
329 );
330
331 assert_eq!(
332 to_mdast(
333 "> alpha {`\n> bravo\n> charlie\n> delta\n> echo\n> `} foxtrot.",
334 &swc.parse
335 )?,
336 Node::Root(Root {
337 children: vec![Node::Blockquote(Blockquote {
338 children: vec![Node::Paragraph(Paragraph {
339 children: vec![
340 Node::Text(Text {
341 value: "alpha ".into(),
342 position: Some(Position::new(1, 3, 2, 1, 9, 8)),
343 }),
344 Node::MdxTextExpression(MdxTextExpression {
345 value: "`\nbravo\ncharlie\ndelta\n echo\n`".into(),
346 position: Some(Position::new(1, 9, 8, 6, 5, 54)),
347 stops: vec![
348 (0, 9),
349 (1, 10),
350 (2, 13),
351 (7, 18),
352 (8, 22),
353 (15, 29),
354 (16, 34),
355 (21, 39),
356 (22, 44),
357 (27, 49),
358 (28, 52)
359 ]
360 }),
361 Node::Text(Text {
362 value: " foxtrot.".into(),
363 position: Some(Position::new(6, 5, 54, 6, 14, 63)),
364 }),
365 ],
366 position: Some(Position::new(1, 3, 2, 6, 14, 63))
367 })],
368 position: Some(Position::new(1, 1, 0, 6, 14, 63))
369 })],
370 position: Some(Position::new(1, 1, 0, 6, 14, 63))
371 }),
372 "should keep the correct number of spaces in a blockquote (text)"
373 );
374
375 Ok(())
376}