Markdown parser fork with extended syntax for personal use.
at main 376 lines 12 kB view raw
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}