Markdown parser fork with extended syntax for personal use.
at hack 1327 lines 52 kB view raw
1mod test_utils; 2use markdown::{ 3 mdast::{ 4 AttributeContent, AttributeValue, AttributeValueExpression, Emphasis, MdxFlowExpression, 5 MdxJsxAttribute, MdxJsxExpressionAttribute, MdxJsxFlowElement, MdxJsxTextElement, Node, 6 Paragraph, Root, Text, 7 }, 8 message, to_html_with_options, to_mdast, 9 unist::Position, 10 Constructs, Options, ParseOptions, 11}; 12use pretty_assertions::assert_eq; 13use test_utils::swc::{parse_esm, parse_expression}; 14 15#[test] 16fn mdx_jsx_text_core() -> Result<(), message::Message> { 17 let mdx = Options { 18 parse: ParseOptions::mdx(), 19 ..Default::default() 20 }; 21 22 assert_eq!( 23 to_html_with_options("a <b> c", &mdx)?, 24 "<p>a c</p>", 25 "should support mdx jsx (text) if enabled" 26 ); 27 28 assert_eq!( 29 to_html_with_options("a <b/> c.", &mdx)?, 30 "<p>a c.</p>", 31 "should support a self-closing element" 32 ); 33 34 assert_eq!( 35 to_html_with_options("a <b></b> c.", &mdx)?, 36 "<p>a c.</p>", 37 "should support a closed element" 38 ); 39 40 assert_eq!( 41 to_html_with_options("a <></> c.", &mdx)?, 42 "<p>a c.</p>", 43 "should support fragments" 44 ); 45 46 assert_eq!( 47 to_html_with_options("a <b>*b*</b> c.", &mdx)?, 48 "<p>a <em>b</em> c.</p>", 49 "should support markdown inside elements" 50 ); 51 52 assert_eq!( 53 to_mdast("{1}<a/>", &mdx.parse)?, 54 Node::Root(Root { 55 children: vec![ 56 Node::MdxFlowExpression(MdxFlowExpression { 57 value: "1".into(), 58 position: Some(Position::new(1, 1, 0, 1, 4, 3)), 59 stops: vec![(0, 1)] 60 }), 61 Node::MdxJsxFlowElement(MdxJsxFlowElement { 62 name: Some("a".into()), 63 attributes: vec![], 64 children: vec![], 65 position: Some(Position::new(1, 4, 3, 1, 8, 7)) 66 }) 67 ], 68 position: Some(Position::new(1, 1, 0, 1, 8, 7)) 69 }), 70 "should support mdx jsx (text) with expression child" 71 ); 72 73 assert_eq!( 74 to_mdast("<a>{1}</a>", &mdx.parse)?, 75 Node::Root(Root { 76 children: vec![Node::MdxJsxFlowElement(MdxJsxFlowElement { 77 name: Some("a".into()), 78 attributes: vec![], 79 children: vec![Node::MdxFlowExpression(MdxFlowExpression { 80 value: "1".into(), 81 position: Some(Position::new(1, 4, 3, 1, 7, 6)), 82 stops: vec![(0, 4)] 83 })], 84 position: Some(Position::new(1, 1, 0, 1, 11, 10)) 85 }),], 86 position: Some(Position::new(1, 1, 0, 1, 11, 10)) 87 }), 88 "should support mdx jsx (text) with expression child" 89 ); 90 91 assert_eq!( 92 to_mdast("a <b /> c.", &mdx.parse)?, 93 Node::Root(Root { 94 children: vec![Node::Paragraph(Paragraph { 95 children: vec![ 96 Node::Text(Text { 97 value: "a ".into(), 98 position: Some(Position::new(1, 1, 0, 1, 3, 2)) 99 }), 100 Node::MdxJsxTextElement(MdxJsxTextElement { 101 name: Some("b".into()), 102 attributes: vec![], 103 children: vec![], 104 position: Some(Position::new(1, 3, 2, 1, 8, 7)) 105 }), 106 Node::Text(Text { 107 value: " c.".into(), 108 position: Some(Position::new(1, 8, 7, 1, 11, 10)) 109 }) 110 ], 111 position: Some(Position::new(1, 1, 0, 1, 11, 10)) 112 })], 113 position: Some(Position::new(1, 1, 0, 1, 11, 10)) 114 }), 115 "should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (self-closing)" 116 ); 117 118 assert_eq!( 119 to_mdast("a <b>*c*</b> d.", &mdx.parse)?, 120 Node::Root(Root { 121 children: vec![Node::Paragraph(Paragraph { 122 children: vec![ 123 Node::Text(Text { 124 value: "a ".into(), 125 position: Some(Position::new(1, 1, 0, 1, 3, 2)) 126 }), 127 Node::MdxJsxTextElement(MdxJsxTextElement { 128 name: Some("b".into()), 129 attributes: vec![], 130 children: vec![ 131 Node::Emphasis(Emphasis { 132 children: vec![ 133 Node::Text(Text { 134 value: "c".into(), 135 position: Some(Position::new(1, 7, 6, 1, 8, 7)) 136 }), 137 ], 138 position: Some(Position::new(1, 6, 5, 1, 9, 8)) 139 }), 140 ], 141 position: Some(Position::new(1, 3, 2, 1, 13, 12)) 142 }), 143 Node::Text(Text { 144 value: " d.".into(), 145 position: Some(Position::new(1, 13, 12, 1, 16, 15)) 146 }) 147 ], 148 position: Some(Position::new(1, 1, 0, 1, 16, 15)) 149 })], 150 position: Some(Position::new(1, 1, 0, 1, 16, 15)) 151 }), 152 "should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (matched open and close tags)" 153 ); 154 155 assert_eq!( 156 to_mdast("<a:b />.", &mdx.parse)?, 157 Node::Root(Root { 158 children: vec![Node::Paragraph(Paragraph { 159 children: vec![ 160 Node::MdxJsxTextElement(MdxJsxTextElement { 161 name: Some("a:b".into()), 162 attributes: vec![], 163 children: vec![], 164 position: Some(Position::new(1, 1, 0, 1, 8, 7)) 165 }), 166 Node::Text(Text { 167 value: ".".into(), 168 position: Some(Position::new(1, 8, 7, 1, 9, 8)) 169 }) 170 ], 171 position: Some(Position::new(1, 1, 0, 1, 9, 8)) 172 })], 173 position: Some(Position::new(1, 1, 0, 1, 9, 8)) 174 }), 175 "should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (namespace in tag name)" 176 ); 177 178 assert_eq!( 179 to_mdast("<a.b.c />.", &mdx.parse)?, 180 Node::Root(Root { 181 children: vec![Node::Paragraph(Paragraph { 182 children: vec![ 183 Node::MdxJsxTextElement(MdxJsxTextElement { 184 name: Some("a.b.c".into()), 185 attributes: vec![], 186 children: vec![], 187 position: Some(Position::new(1, 1, 0, 1, 10, 9)) 188 }), 189 Node::Text(Text { 190 value: ".".into(), 191 position: Some(Position::new(1, 10, 9, 1, 11, 10)) 192 }) 193 ], 194 position: Some(Position::new(1, 1, 0, 1, 11, 10)) 195 })], 196 position: Some(Position::new(1, 1, 0, 1, 11, 10)) 197 }), 198 "should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (members in tag name)" 199 ); 200 201 assert_eq!( 202 to_mdast("<a {...b} />.", &mdx.parse)?, 203 Node::Root(Root { 204 children: vec![Node::Paragraph(Paragraph { 205 children: vec![ 206 Node::MdxJsxTextElement(MdxJsxTextElement { 207 name: Some("a".into()), 208 attributes: vec![AttributeContent::Expression(MdxJsxExpressionAttribute { 209 value: "...b".into(), 210 stops: vec![(0, 4)] 211 })], 212 children: vec![], 213 position: Some(Position::new(1, 1, 0, 1, 13, 12)) 214 }), 215 Node::Text(Text { 216 value: ".".into(), 217 position: Some(Position::new(1, 13, 12, 1, 14, 13)) 218 }) 219 ], 220 position: Some(Position::new(1, 1, 0, 1, 14, 13)) 221 })], 222 position: Some(Position::new(1, 1, 0, 1, 14, 13)) 223 }), 224 "should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (attribute expression)" 225 ); 226 227 assert_eq!( 228 to_mdast("<a b c:d />.", &mdx.parse)?, 229 Node::Root(Root { 230 children: vec![Node::Paragraph(Paragraph { 231 children: vec![ 232 Node::MdxJsxTextElement(MdxJsxTextElement { 233 name: Some("a".into()), 234 attributes: vec![ 235 AttributeContent::Property(MdxJsxAttribute { 236 name: "b".into(), 237 value: None, 238 }), 239 AttributeContent::Property(MdxJsxAttribute { 240 name: "c:d".into(), 241 value: None, 242 }) 243 ], 244 children: vec![], 245 position: Some(Position::new(1, 1, 0, 1, 12, 11)) 246 }), 247 Node::Text(Text { 248 value: ".".into(), 249 position: Some(Position::new(1, 12, 11, 1, 13, 12)) 250 }) 251 ], 252 position: Some(Position::new(1, 1, 0, 1, 13, 12)) 253 })], 254 position: Some(Position::new(1, 1, 0, 1, 13, 12)) 255 }), 256 "should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (property names)" 257 ); 258 259 assert_eq!( 260 to_mdast("<a b='c' d=\"e\" f={g} />.", &mdx.parse)?, 261 Node::Root(Root { 262 children: vec![Node::Paragraph(Paragraph { 263 children: vec![ 264 Node::MdxJsxTextElement(MdxJsxTextElement { 265 name: Some("a".into()), 266 attributes: vec![ 267 AttributeContent::Property(MdxJsxAttribute { 268 name: "b".into(), 269 value: Some(AttributeValue::Literal("c".into())), 270 }), 271 AttributeContent::Property(MdxJsxAttribute { 272 name: "d".into(), 273 value: Some(AttributeValue::Literal("e".into())), 274 }), 275 AttributeContent::Property(MdxJsxAttribute { 276 name: "f".into(), 277 value: Some(AttributeValue::Expression(AttributeValueExpression { 278 value: "g".into(), 279 stops: vec![(0, 18)] 280 })), 281 }), 282 ], 283 children: vec![], 284 position: Some(Position::new(1, 1, 0, 1, 24, 23)) 285 }), 286 Node::Text(Text { 287 value: ".".into(), 288 position: Some(Position::new(1, 24, 23, 1, 25, 24)) 289 }) 290 ], 291 position: Some(Position::new(1, 1, 0, 1, 25, 24)) 292 })], 293 position: Some(Position::new(1, 1, 0, 1, 25, 24)) 294 }), 295 "should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (attribute values)" 296 ); 297 298 assert_eq!( 299 to_mdast("<a b='&nbsp; &amp; &copy; &AElig; &Dcaron; &frac34; &HilbertSpace; &DifferentialD; &ClockwiseContourIntegral; &ngE;' />.", &mdx.parse)?, 300 Node::Root(Root { 301 children: vec![Node::Paragraph(Paragraph { 302 children: vec![ 303 Node::MdxJsxTextElement(MdxJsxTextElement { 304 name: Some("a".into()), 305 attributes: vec![ 306 AttributeContent::Property(MdxJsxAttribute { 307 name: "b".into(), 308 value: Some(AttributeValue::Literal("\u{a0} & © Æ &Dcaron; ¾ &HilbertSpace; &DifferentialD; &ClockwiseContourIntegral; &ngE;".into())), 309 }), 310 ], 311 children: vec![], 312 position: Some(Position::new(1, 1, 0, 1, 120, 119)) 313 }), 314 Node::Text(Text { 315 value: ".".into(), 316 position: Some(Position::new(1, 120, 119, 1, 121, 120)) 317 }) 318 ], 319 position: Some(Position::new(1, 1, 0, 1, 121, 120)) 320 })], 321 position: Some(Position::new(1, 1, 0, 1, 121, 120)) 322 }), 323 "should support character references (HTML 4, named) in JSX attribute values" 324 ); 325 326 assert_eq!( 327 to_mdast( 328 "<a b='&#35; &#1234; &#992; &#0;' c='&#X22; &#XD06; &#xcab;' />.", 329 &mdx.parse 330 )?, 331 Node::Root(Root { 332 children: vec![Node::Paragraph(Paragraph { 333 children: vec![ 334 Node::MdxJsxTextElement(MdxJsxTextElement { 335 name: Some("a".into()), 336 attributes: vec![ 337 AttributeContent::Property(MdxJsxAttribute { 338 name: "b".into(), 339 value: Some(AttributeValue::Literal("# Ӓ Ϡ �".into())), 340 }), 341 AttributeContent::Property(MdxJsxAttribute { 342 name: "c".into(), 343 value: Some(AttributeValue::Literal("\" ആ ಫ".into())), 344 }), 345 ], 346 children: vec![], 347 position: Some(Position::new(1, 1, 0, 1, 63, 62)) 348 }), 349 Node::Text(Text { 350 value: ".".into(), 351 position: Some(Position::new(1, 63, 62, 1, 64, 63)) 352 }) 353 ], 354 position: Some(Position::new(1, 1, 0, 1, 64, 63)) 355 })], 356 position: Some(Position::new(1, 1, 0, 1, 64, 63)) 357 }), 358 "should support character references (numeric) in JSX attribute values" 359 ); 360 361 assert_eq!( 362 to_mdast("<a b='&nbsp &x; &#; &#x; &#987654321; &#abcdef0; &ThisIsNotDefined; &hi?;' />.", &mdx.parse)?, 363 Node::Root(Root { 364 children: vec![Node::Paragraph(Paragraph { 365 children: vec![ 366 Node::MdxJsxTextElement(MdxJsxTextElement { 367 name: Some("a".into()), 368 attributes: vec![ 369 AttributeContent::Property(MdxJsxAttribute { 370 name: "b".into(), 371 value: Some(AttributeValue::Literal("&nbsp &x; &#; &#x; &#987654321; &#abcdef0; &ThisIsNotDefined; &hi?;".into())), 372 }) 373 ], 374 children: vec![], 375 position: Some(Position::new(1, 1, 0, 1, 78, 77)) 376 }), 377 Node::Text(Text { 378 value: ".".into(), 379 position: Some(Position::new(1, 78, 77, 1, 79, 78)) 380 }) 381 ], 382 position: Some(Position::new(1, 1, 0, 1, 79, 78)) 383 })], 384 position: Some(Position::new(1, 1, 0, 1, 79, 78)) 385 }), 386 "should not support things that look like character references but aren’t" 387 ); 388 389 assert_eq!( 390 to_mdast("<a\u{3000}b \u{3000}c\u{3000} d\u{3000}/>.", &mdx.parse)?, 391 Node::Root(Root { 392 children: vec![Node::Paragraph(Paragraph { 393 children: vec![ 394 Node::MdxJsxTextElement(MdxJsxTextElement { 395 name: Some("a".into()), 396 attributes: vec![ 397 AttributeContent::Property(MdxJsxAttribute { 398 name: "b".into(), 399 value: None, 400 }), 401 AttributeContent::Property(MdxJsxAttribute { 402 name: "c".into(), 403 value: None, 404 }), 405 AttributeContent::Property(MdxJsxAttribute { 406 name: "d".into(), 407 value: None, 408 }) 409 ], 410 children: vec![], 411 position: Some(Position::new(1, 1, 0, 1, 22, 21)) 412 }), 413 Node::Text(Text { 414 value: ".".into(), 415 position: Some(Position::new(1, 22, 21, 1, 23, 22)) 416 }) 417 ], 418 position: Some(Position::new(1, 1, 0, 1, 23, 22)) 419 })], 420 position: Some(Position::new(1, 1, 0, 1, 23, 22)) 421 }), 422 "should support unicode whitespace in a lot of places" 423 ); 424 425 assert_eq!( 426 to_mdast("<a\nb \nc\n d\n/>.", &mdx.parse)?, 427 Node::Root(Root { 428 children: vec![Node::Paragraph(Paragraph { 429 children: vec![ 430 Node::MdxJsxTextElement(MdxJsxTextElement { 431 name: Some("a".into()), 432 attributes: vec![ 433 AttributeContent::Property(MdxJsxAttribute { 434 name: "b".into(), 435 value: None, 436 }), 437 AttributeContent::Property(MdxJsxAttribute { 438 name: "c".into(), 439 value: None, 440 }), 441 AttributeContent::Property(MdxJsxAttribute { 442 name: "d".into(), 443 value: None, 444 }) 445 ], 446 children: vec![], 447 position: Some(Position::new(1, 1, 0, 5, 3, 13)) 448 }), 449 Node::Text(Text { 450 value: ".".into(), 451 position: Some(Position::new(5, 3, 13, 5, 4, 14)) 452 }) 453 ], 454 position: Some(Position::new(1, 1, 0, 5, 4, 14)) 455 })], 456 position: Some(Position::new(1, 1, 0, 5, 4, 14)) 457 }), 458 "should support line endings in a lot of places" 459 ); 460 461 assert_eq!( 462 to_mdast("a </b> c", &mdx.parse).err().unwrap().to_string(), 463 "1:4: Unexpected closing slash `/` in tag, expected an open tag first (markdown-rs:unexpected-closing-slash)", 464 "should crash when building the ast on a closing tag if none is open" 465 ); 466 467 assert_eq!( 468 to_mdast("a <b> c </b/> d", &mdx.parse) 469 .err() 470 .unwrap() 471 .to_string(), 472 "1:12: Unexpected self-closing slash `/` in closing tag, expected the end of the tag (markdown-rs:unexpected-self-closing-slash)", 473 "should crash when building the ast on a closing tag with a self-closing slash" 474 ); 475 476 assert_eq!( 477 to_mdast("a <b> c </b d> e", &mdx.parse) 478 .err() 479 .unwrap() 480 .to_string(), 481 "1:13: Unexpected attribute in closing tag, expected the end of the tag (markdown-rs:unexpected-attribute)", 482 "should crash when building the ast on a closing tag with an attribute" 483 ); 484 485 assert_eq!( 486 to_mdast("a <>b</c> d", &mdx.parse) 487 .err() 488 .unwrap().to_string(), 489 "1:6-1:10: Unexpected closing tag `</c>`, expected corresponding closing tag for `<>` (1:3) (markdown-rs:end-tag-mismatch)", 490 "should crash when building the ast on mismatched tags (1)" 491 ); 492 493 assert_eq!( 494 to_mdast("a <b>c</> d", &mdx.parse) 495 .err() 496 .unwrap().to_string(), 497 "1:7-1:10: Unexpected closing tag `</>`, expected corresponding closing tag for `<b>` (1:3) (markdown-rs:end-tag-mismatch)", 498 "should crash when building the ast on mismatched tags (2)" 499 ); 500 501 assert_eq!( 502 to_mdast("*a <b>c* d</b>.", &mdx.parse) 503 .err() 504 .unwrap() 505 .to_string(), 506 "1:9: Expected a closing tag for `<b>` (1:4) before the end of `Emphasis` (markdown-rs:end-tag-mismatch)", 507 "should crash when building the ast on mismatched interleaving (1)" 508 ); 509 510 assert_eq!( 511 to_mdast("<a>b *c</a> d*.", &mdx.parse).err().unwrap().to_string(), 512 "1:8: Expected the closing tag `</a>` either before the start of `Emphasis` (1:6), or another opening tag after that start (markdown-rs:end-tag-mismatch)", 513 "should crash when building the ast on mismatched interleaving (2)" 514 ); 515 516 assert_eq!( 517 to_mdast("a <b>.", &mdx.parse).err().unwrap().to_string(), 518 "1:7: Expected a closing tag for `<b>` (1:3) before the end of `Paragraph` (markdown-rs:end-tag-mismatch)", 519 "should crash when building the ast on mismatched interleaving (3)" 520 ); 521 522 // Note: this is flow, not text. 523 assert_eq!( 524 to_mdast("<a>", &mdx.parse).err().unwrap().to_string(), 525 "1:4: Expected a closing tag for `<a>` (1:1) (markdown-rs:end-tag-mismatch)", 526 "should crash when building the ast on mismatched interleaving (4)" 527 ); 528 529 assert_eq!( 530 to_mdast("<a><b></b>", &mdx.parse) 531 .err() 532 .unwrap() 533 .to_string(), 534 "1:11: Expected a closing tag for `<a>` (1:1) (markdown-rs:end-tag-mismatch)", 535 "should crash on unclosed jsx after closed jsx" 536 ); 537 538 Ok(()) 539} 540 541#[test] 542fn mdx_jsx_text_agnosic() -> Result<(), message::Message> { 543 let mdx = Options { 544 parse: ParseOptions::mdx(), 545 ..Default::default() 546 }; 547 548 assert_eq!( 549 to_html_with_options("a <b /> c", &mdx)?, 550 "<p>a c</p>", 551 "should support a self-closing element" 552 ); 553 554 assert_eq!( 555 to_html_with_options("a <b> c </b> d", &mdx)?, 556 "<p>a c d</p>", 557 "should support a closed element" 558 ); 559 560 assert_eq!( 561 to_html_with_options("a <b> c", &mdx)?, 562 "<p>a c</p>", 563 "should support an unclosed element" 564 ); 565 566 assert_eq!( 567 to_html_with_options("a <b {1 + 1} /> c", &mdx)?, 568 "<p>a c</p>", 569 "should support an attribute expression" 570 ); 571 572 assert_eq!( 573 to_html_with_options("a <b c={1 + 1} /> d", &mdx)?, 574 "<p>a d</p>", 575 "should support an attribute value expression" 576 ); 577 578 Ok(()) 579} 580 581#[test] 582fn mdx_jsx_text_gnostic() -> Result<(), message::Message> { 583 let swc = Options { 584 parse: ParseOptions { 585 constructs: Constructs::mdx(), 586 mdx_esm_parse: Some(Box::new(parse_esm)), 587 mdx_expression_parse: Some(Box::new(parse_expression)), 588 ..Default::default() 589 }, 590 ..Default::default() 591 }; 592 593 assert_eq!( 594 to_html_with_options("a <b /> c", &swc)?, 595 "<p>a c</p>", 596 "should support a self-closing element" 597 ); 598 599 assert_eq!( 600 to_html_with_options("a <b> c </b> d", &swc)?, 601 "<p>a c d</p>", 602 "should support a closed element" 603 ); 604 605 assert_eq!( 606 to_html_with_options("a <b> c", &swc)?, 607 "<p>a c</p>", 608 "should support an unclosed element" 609 ); 610 611 assert_eq!( 612 to_html_with_options("a <b {...c} /> d", &swc)?, 613 "<p>a d</p>", 614 "should support an attribute expression" 615 ); 616 617 assert_eq!( 618 to_html_with_options("a <b {...{c: 1, d: Infinity, e: false}} /> f", &swc)?, 619 "<p>a f</p>", 620 "should support more complex attribute expression (1)" 621 ); 622 623 assert_eq!( 624 to_html_with_options("a <b {...[1, Infinity, false]} /> d", &swc)?, 625 "<p>a d</p>", 626 "should support more complex attribute expression (2)" 627 ); 628 629 assert_eq!( 630 to_html_with_options("a <b c={1 + 1} /> d", &swc)?, 631 "<p>a d</p>", 632 "should support an attribute value expression" 633 ); 634 635 assert_eq!( 636 to_html_with_options("a <b c={} /> d", &swc) 637 .err() 638 .unwrap() 639 .to_string(), 640 "1:15: Could not parse expression with swc: Unexpected eof (mdx:swc)", 641 "should crash on an empty attribute value expression" 642 ); 643 644 assert_eq!( 645 to_html_with_options("a <b {1 + 1} /> c", &swc) 646 .err() 647 .unwrap() 648 .to_string(), 649 "1:18: Could not parse expression with swc: Expected ',', got '}' (mdx:swc)", 650 "should crash on a non-spread attribute expression" 651 ); 652 653 assert_eq!( 654 to_html_with_options("a <b c={?} /> d", &swc) 655 .err() 656 .unwrap() 657 .to_string(), 658 "1:16: Could not parse expression with swc: Expression expected (mdx:swc)", 659 "should crash on invalid JS in an attribute value expression" 660 ); 661 662 assert_eq!( 663 to_html_with_options("a <b {?} /> c", &swc) 664 .err() 665 .unwrap().to_string(), 666 "1:14: Could not parse expression with swc: Unexpected token `?`. Expected identifier, string literal, numeric literal or [ for the computed key (mdx:swc)", 667 "should crash on invalid JS in an attribute expression" 668 ); 669 670 assert_eq!( 671 to_html_with_options("a <b{c=d}={}/> f", &swc) 672 .err() 673 .unwrap().to_string(), 674 "1:6: Unexpected prop in spread (such as `{x}`): only a spread is supported (such as `{...x}`) (mdx:swc)", 675 "should crash on invalid JS in an attribute expression (2)" 676 ); 677 678 assert_eq!( 679 to_html_with_options("a <b c={(2)} d={<e />} /> f", &swc)?, 680 "<p>a f</p>", 681 "should support parenthesized expressions" 682 ); 683 684 Ok(()) 685} 686 687#[test] 688fn mdx_jsx_text_complete() -> Result<(), message::Message> { 689 let mdx = Options { 690 parse: ParseOptions::mdx(), 691 ..Default::default() 692 }; 693 694 assert_eq!( 695 to_html_with_options("a <b> c", &mdx)?, 696 "<p>a c</p>", 697 "should support an unclosed element" 698 ); 699 700 assert_eq!( 701 to_html_with_options("a <> c", &mdx)?, 702 "<p>a c</p>", 703 "should support an unclosed fragment" 704 ); 705 706 assert_eq!( 707 to_html_with_options("a < \t>b</>", &mdx)?, 708 "<p>a &lt; \t&gt;b</p>", 709 "should *not* support whitespace in the opening tag (fragment)" 710 ); 711 712 assert_eq!( 713 to_html_with_options("a < \nb\t>b</b>", &mdx)?, 714 "<p>a &lt;\nb\t&gt;b</p>", 715 "should *not* support whitespace in the opening tag (named)" 716 ); 717 718 assert_eq!( 719 to_html_with_options("a <!> b", &mdx) 720 .err() 721 .unwrap().to_string(), 722 "1:4: Unexpected character `!` (U+0021) before name, expected a character that can start a name, such as a letter, `$`, or `_` (note: to create a comment in MDX, use `{/* text */}`) (markdown-rs:unexpected-character)", 723 "should crash on a nonconforming start identifier" 724 ); 725 726 assert_eq!( 727 to_html_with_options("a </(> b.", &mdx) 728 .err() 729 .unwrap().to_string(), 730 "1:5: Unexpected character `(` (U+0028) before name, expected a character that can start a name, such as a letter, `$`, or `_` (markdown-rs:unexpected-character)", 731 "should crash on a nonconforming start identifier in a closing tag" 732 ); 733 734 assert_eq!( 735 to_html_with_options("a <π /> b.", &mdx)?, 736 "<p>a b.</p>", 737 "should support non-ascii identifier start characters" 738 ); 739 740 assert_eq!( 741 to_html_with_options("a <© /> b.", &mdx) 742 .err() 743 .unwrap().to_string(), 744 "1:4: Unexpected character U+00A9 before name, expected a character that can start a name, such as a letter, `$`, or `_` (markdown-rs:unexpected-character)", 745 "should crash on non-conforming non-ascii identifier start characters" 746 ); 747 748 assert_eq!( 749 to_html_with_options("a <!--b-->", &mdx) 750 .err() 751 .unwrap().to_string(), 752 "1:4: Unexpected character `!` (U+0021) before name, expected a character that can start a name, such as a letter, `$`, or `_` (note: to create a comment in MDX, use `{/* text */}`) (markdown-rs:unexpected-character)", 753 "should crash nicely on what might be a comment" 754 ); 755 756 assert_eq!( 757 to_html_with_options("a <// b\nc/>", &mdx) 758 .err() 759 .unwrap().to_string(), 760 "1:5: Unexpected character `/` (U+002F) before name, expected a character that can start a name, such as a letter, `$`, or `_` (note: JS comments in JSX tags are not supported in MDX) (markdown-rs:unexpected-character)", 761 "should crash nicely on JS line comments inside tags (1)" 762 ); 763 764 assert_eq!( 765 to_html_with_options("a <b// c\nd/>", &mdx) 766 .err() 767 .unwrap().to_string(), 768 "1:6: Unexpected character `/` (U+002F) after self-closing slash, expected `>` to end the tag (note: JS comments in JSX tags are not supported in MDX) (markdown-rs:unexpected-character)", 769 "should crash nicely JS line comments inside tags (2)" 770 ); 771 772 assert_eq!( 773 to_html_with_options("a </*b*/c>", &mdx) 774 .err() 775 .unwrap().to_string(), 776 "1:5: Unexpected character `*` (U+002A) before name, expected a character that can start a name, such as a letter, `$`, or `_` (markdown-rs:unexpected-character)", 777 "should crash nicely JS multiline comments inside tags (1)" 778 ); 779 780 assert_eq!( 781 to_html_with_options("a <b/*c*/>", &mdx) 782 .err() 783 .unwrap().to_string(), 784 "1:6: Unexpected character `*` (U+002A) after self-closing slash, expected `>` to end the tag (markdown-rs:unexpected-character)", 785 "should crash nicely JS multiline comments inside tags (2)" 786 ); 787 788 assert_eq!( 789 to_html_with_options("a <a\u{200C}b /> b.", &mdx)?, 790 "<p>a b.</p>", 791 "should support non-ascii identifier continuation characters" 792 ); 793 794 assert_eq!( 795 to_html_with_options("a <a¬ /> b.", &mdx) 796 .err() 797 .unwrap().to_string(), 798 "1:5: Unexpected character U+00AC in name, expected a name character such as letters, digits, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 799 "should crash on non-conforming non-ascii identifier continuation characters" 800 ); 801 802 assert_eq!( 803 to_html_with_options("a <b@c.d>", &mdx) 804 .err() 805 .unwrap().to_string(), 806 "1:5: Unexpected character `@` (U+0040) in name, expected a name character such as letters, digits, `$`, or `_`; whitespace before attributes; or the end of the tag (note: to create a link in MDX, use `[text](url)`) (markdown-rs:unexpected-character)", 807 "should crash nicely on what might be an email link" 808 ); 809 810 assert_eq!( 811 to_html_with_options("a <a-->b</a-->.", &mdx)?, 812 "<p>a b.</p>", 813 "should support dashes in names" 814 ); 815 816 assert_eq!( 817 to_html_with_options("a <a?> c.", &mdx) 818 .err() 819 .unwrap().to_string(), 820 "1:5: Unexpected character `?` (U+003F) in name, expected a name character such as letters, digits, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 821 "should crash on nonconforming identifier continuation characters" 822 ); 823 824 assert_eq!( 825 to_html_with_options("a <abc . def.ghi>b</abc.def . ghi>.", &mdx)?, 826 "<p>a b.</p>", 827 "should support dots in names for method names" 828 ); 829 830 assert_eq!( 831 to_html_with_options("a <b.c@d.e>", &mdx) 832 .err() 833 .unwrap().to_string(), 834 "1:7: Unexpected character `@` (U+0040) in member name, expected a name character such as letters, digits, `$`, or `_`; whitespace before attributes; or the end of the tag (note: to create a link in MDX, use `[text](url)`) (markdown-rs:unexpected-character)", 835 "should crash nicely on what might be an email link in member names" 836 ); 837 838 assert_eq!( 839 to_html_with_options("a <svg: rect>b</ svg :rect>.", &mdx)?, 840 "<p>a b.</p>", 841 "should support colons in names for local names" 842 ); 843 844 assert_eq!( 845 to_html_with_options("a <a:+> c.", &mdx) 846 .err() 847 .unwrap().to_string(), 848 "1:6: Unexpected character `+` (U+002B) before local name, expected a character that can start a name, such as a letter, `$`, or `_` (note: to create a link in MDX, use `[text](url)`) (markdown-rs:unexpected-character)", 849 "should crash on a nonconforming character to start a local name" 850 ); 851 852 assert_eq!( 853 to_html_with_options("a <http://example.com>", &mdx) 854 .err() 855 .unwrap().to_string(), 856 "1:9: Unexpected character `/` (U+002F) before local name, expected a character that can start a name, such as a letter, `$`, or `_` (note: to create a link in MDX, use `[text](url)`) (markdown-rs:unexpected-character)", 857 "should crash nicely on what might be a protocol in local names" 858 ); 859 860 assert_eq!( 861 to_html_with_options("a <http: >", &mdx) 862 .err() 863 .unwrap().to_string(), 864 "1:10: Unexpected character `>` (U+003E) before local name, expected a character that can start a name, such as a letter, `$`, or `_` (markdown-rs:unexpected-character)", 865 "should crash nicely on what might be a protocol in local names" 866 ); 867 868 assert_eq!( 869 to_html_with_options("a <a:b|> c.", &mdx) 870 .err() 871 .unwrap().to_string(), 872 "1:7: Unexpected character `|` (U+007C) in local name, expected a name character such as letters, digits, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 873 "should crash on a nonconforming character in a local name" 874 ); 875 876 assert_eq!( 877 to_html_with_options("a <a..> c.", &mdx) 878 .err() 879 .unwrap().to_string(), 880 "1:6: Unexpected character `.` (U+002E) before member name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 881 "should crash on a nonconforming character to start a member name" 882 ); 883 884 assert_eq!( 885 to_html_with_options("a <a.b,> c.", &mdx) 886 .err() 887 .unwrap().to_string(), 888 "1:7: Unexpected character `,` (U+002C) in member name, expected a name character such as letters, digits, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 889 "should crash on a nonconforming character in a member name" 890 ); 891 892 assert_eq!( 893 to_html_with_options("a <a:b .> c.", &mdx) 894 .err() 895 .unwrap().to_string(), 896 "1:8: Unexpected character `.` (U+002E) after local name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 897 "should crash on a nonconforming character after a local name" 898 ); 899 900 assert_eq!( 901 to_html_with_options("a <a.b :> c.", &mdx) 902 .err() 903 .unwrap().to_string(), 904 "1:8: Unexpected character `:` (U+003A) after member name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 905 "should crash on a nonconforming character after a member name" 906 ); 907 908 assert_eq!( 909 to_html_with_options("a <a => c.", &mdx) 910 .err() 911 .unwrap().to_string(), 912 "1:6: Unexpected character `=` (U+003D) after name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 913 "should crash on a nonconforming character after name" 914 ); 915 916 assert_eq!( 917 to_html_with_options("a <b {...props} {...rest}>c</b>.", &mdx)?, 918 "<p>a c.</p>", 919 "should support attribute expressions" 920 ); 921 922 assert_eq!( 923 to_html_with_options("a <b {...{\"a\": \"b\"}}>c</b>.", &mdx)?, 924 "<p>a c.</p>", 925 "should support nested balanced braces in attribute expressions" 926 ); 927 928 assert_eq!( 929 to_html_with_options("<a{...b}/>.", &mdx)?, 930 "<p>.</p>", 931 "should support attribute expressions directly after a name" 932 ); 933 934 assert_eq!( 935 to_html_with_options("<a.b{...c}/>.", &mdx)?, 936 "<p>.</p>", 937 "should support attribute expressions directly after a member name" 938 ); 939 940 assert_eq!( 941 to_html_with_options("<a:b{...c}/>.", &mdx)?, 942 "<p>.</p>", 943 "should support attribute expressions directly after a local name" 944 ); 945 946 assert_eq!( 947 to_html_with_options("a <b c{...d}/>.", &mdx)?, 948 "<p>a .</p>", 949 "should support attribute expressions directly after boolean attributes" 950 ); 951 952 assert_eq!( 953 to_html_with_options("a <b c:d{...e}/>.", &mdx)?, 954 "<p>a .</p>", 955 "should support attribute expressions directly after boolean qualified attributes" 956 ); 957 958 assert_eq!( 959 to_html_with_options("a <b a {...props} b>c</b>.", &mdx)?, 960 "<p>a c.</p>", 961 "should support attribute expressions and normal attributes" 962 ); 963 964 assert_eq!( 965 to_html_with_options("a <b c d=\"d\"\t\tefg=\"e\">c</b>.", &mdx)?, 966 "<p>a c.</p>", 967 "should support attributes" 968 ); 969 970 assert_eq!( 971 to_html_with_options("a <b {...p}~>c</b>.", &mdx) 972 .err() 973 .unwrap().to_string(), 974 "1:12: Unexpected character `~` (U+007E) before attribute name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 975 "should crash on a nonconforming character before an attribute name" 976 ); 977 978 assert_eq!( 979 to_html_with_options("a <b {...", &mdx) 980 .err() 981 .unwrap().to_string(), 982 "1:10: Unexpected end of file in expression, expected a corresponding closing brace for `{` (markdown-rs:unexpected-eof)", 983 "should crash on a missing closing brace in attribute expression" 984 ); 985 986 assert_eq!( 987 to_html_with_options("a <a b@> c.", &mdx) 988 .err() 989 .unwrap().to_string(), 990 "1:7: Unexpected character `@` (U+0040) in attribute name, expected an attribute name character such as letters, digits, `$`, or `_`; `=` to initialize a value; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 991 "should crash on a nonconforming character in attribute name" 992 ); 993 994 assert_eq!( 995 to_html_with_options("a <b xml :\tlang\n= \"de-CH\" foo:bar>c</b>.", &mdx)?, 996 "<p>a c.</p>", 997 "should support prefixed attributes" 998 ); 999 1000 assert_eq!( 1001 to_html_with_options("a <b a b : c d : e = \"f\" g/>.", &mdx)?, 1002 "<p>a .</p>", 1003 "should support prefixed and normal attributes" 1004 ); 1005 1006 assert_eq!( 1007 to_html_with_options("a <a b 1> c.", &mdx) 1008 .err() 1009 .unwrap().to_string(), 1010 "1:8: Unexpected character `1` (U+0031) after attribute name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; `=` to initialize a value; or the end of the tag (markdown-rs:unexpected-character)", 1011 "should crash on a nonconforming character after an attribute name" 1012 ); 1013 1014 assert_eq!( 1015 to_html_with_options("a <a b:#> c.", &mdx) 1016 .err() 1017 .unwrap().to_string(), 1018 "1:8: Unexpected character `#` (U+0023) before local attribute name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; `=` to initialize a value; or the end of the tag (markdown-rs:unexpected-character)", 1019 "should crash on a nonconforming character to start a local attribute name" 1020 ); 1021 1022 assert_eq!( 1023 to_html_with_options("a <a b:c%> c.", &mdx) 1024 .err() 1025 .unwrap().to_string(), 1026 "1:9: Unexpected character `%` (U+0025) in local attribute name, expected an attribute name character such as letters, digits, `$`, or `_`; `=` to initialize a value; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 1027 "should crash on a nonconforming character in a local attribute name" 1028 ); 1029 1030 assert_eq!( 1031 to_html_with_options("a <a b:c ^> c.", &mdx) 1032 .err() 1033 .unwrap().to_string(), 1034 "1:10: Unexpected character `^` (U+005E) after local attribute name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; `=` to initialize a value; or the end of the tag (markdown-rs:unexpected-character)", 1035 "should crash on a nonconforming character after a local attribute name" 1036 ); 1037 1038 assert_eq!( 1039 to_html_with_options("a <b c={1 + 1}>c</b>.", &mdx)?, 1040 "<p>a c.</p>", 1041 "should support attribute value expressions" 1042 ); 1043 1044 assert_eq!( 1045 to_html_with_options("a <b c={1 + ({a: 1}).a}>c</b>.", &mdx)?, 1046 "<p>a c.</p>", 1047 "should support nested balanced braces in attribute value expressions" 1048 ); 1049 1050 assert_eq!( 1051 to_html_with_options("a <a b=``> c.", &mdx) 1052 .err() 1053 .unwrap().to_string(), 1054 "1:8: Unexpected character `` ` `` (U+0060) before attribute value, expected a character that can start an attribute value, such as `\"`, `'`, or `{` (markdown-rs:unexpected-character)", 1055 "should crash on a nonconforming character before an attribute value" 1056 ); 1057 1058 assert_eq!( 1059 to_html_with_options("a <a b=<c />> d.", &mdx) 1060 .err() 1061 .unwrap().to_string(), 1062 "1:8: Unexpected character `<` (U+003C) before attribute value, expected a character that can start an attribute value, such as `\"`, `'`, or `{` (note: to use an element or fragment as a prop value in MDX, use `{<element />}`) (markdown-rs:unexpected-character)", 1063 "should crash nicely on what might be a fragment, element as prop value" 1064 ); 1065 1066 assert_eq!( 1067 to_html_with_options("a <a b=\"> c.", &mdx) 1068 .err() 1069 .unwrap().to_string(), 1070 "1:13: Unexpected end of file in attribute value, expected a corresponding closing quote `\"` (U+0022) (markdown-rs:unexpected-eof)", 1071 "should crash on a missing closing quote in double quoted attribute value" 1072 ); 1073 1074 assert_eq!( 1075 to_html_with_options("a <a b=\"> c.", &mdx) 1076 .err() 1077 .unwrap().to_string(), 1078 "1:13: Unexpected end of file in attribute value, expected a corresponding closing quote `\"` (U+0022) (markdown-rs:unexpected-eof)", 1079 "should crash on a missing closing quote in single quoted attribute value" 1080 ); 1081 1082 assert_eq!( 1083 to_html_with_options("a <a b={> c.", &mdx) 1084 .err() 1085 .unwrap().to_string(), 1086 "1:13: Unexpected end of file in expression, expected a corresponding closing brace for `{` (markdown-rs:unexpected-eof)", 1087 "should crash on a missing closing brace in an attribute value expression" 1088 ); 1089 1090 assert_eq!( 1091 to_html_with_options("a <a b=\"\"*> c.", &mdx) 1092 .err() 1093 .unwrap().to_string(), 1094 "1:10: Unexpected character `*` (U+002A) before attribute name, expected a character that can start an attribute name, such as a letter, `$`, or `_`; whitespace before attributes; or the end of the tag (markdown-rs:unexpected-character)", 1095 "should crash on a nonconforming character after an attribute value" 1096 ); 1097 1098 assert_eq!( 1099 to_html_with_options("<a b=\"\"c/>.", &mdx)?, 1100 "<p>.</p>", 1101 "should support an attribute directly after a value" 1102 ); 1103 1104 assert_eq!( 1105 to_html_with_options("<a{...b}c/>.", &mdx)?, 1106 "<p>.</p>", 1107 "should support an attribute directly after an attribute expression" 1108 ); 1109 1110 assert_eq!( 1111 to_html_with_options("a <a/b> c.", &mdx) 1112 .err() 1113 .unwrap().to_string(), 1114 "1:6: Unexpected character `b` (U+0062) after self-closing slash, expected `>` to end the tag (markdown-rs:unexpected-character)", 1115 "should crash on a nonconforming character after a self-closing slash" 1116 ); 1117 1118 assert_eq!( 1119 to_html_with_options("<a/ \t>.", &mdx)?, 1120 "<p>.</p>", 1121 "should support whitespace directly after closing slash" 1122 ); 1123 1124 assert_eq!( 1125 to_html_with_options("a > c.", &mdx).err(), 1126 None, 1127 "should *not* crash on closing angle in text" 1128 ); 1129 1130 assert_eq!( 1131 to_html_with_options("a <>`<`</> c.", &mdx).err(), 1132 None, 1133 "should *not* crash on opening angle in tick code in an element" 1134 ); 1135 1136 assert_eq!( 1137 to_html_with_options("a <>`` ``` ``</>", &mdx).err(), 1138 None, 1139 "should *not* crash on ticks in tick code in an element" 1140 ); 1141 1142 assert_eq!( 1143 to_html_with_options("a </> c.", &mdx)?, 1144 "<p>a c.</p>", 1145 "should support a closing tag w/o open elements" 1146 ); 1147 1148 assert_eq!( 1149 to_html_with_options("a <></b>", &mdx)?, 1150 "<p>a </p>", 1151 "should support mismatched tags (1)" 1152 ); 1153 assert_eq!( 1154 to_html_with_options("a <b></>", &mdx)?, 1155 "<p>a </p>", 1156 "should support mismatched tags (2)" 1157 ); 1158 assert_eq!( 1159 to_html_with_options("a <a.b></a>", &mdx)?, 1160 "<p>a </p>", 1161 "should support mismatched tags (3)" 1162 ); 1163 assert_eq!( 1164 to_html_with_options("a <a></a.b>", &mdx)?, 1165 "<p>a </p>", 1166 "should support mismatched tags (4)" 1167 ); 1168 assert_eq!( 1169 to_html_with_options("a <a.b></a.c>", &mdx)?, 1170 "<p>a </p>", 1171 "should support mismatched tags (5)" 1172 ); 1173 assert_eq!( 1174 to_html_with_options("a <a:b></a>", &mdx)?, 1175 "<p>a </p>", 1176 "should support mismatched tags (6)" 1177 ); 1178 assert_eq!( 1179 to_html_with_options("a <a></a:b>", &mdx)?, 1180 "<p>a </p>", 1181 "should support mismatched tags (7)" 1182 ); 1183 assert_eq!( 1184 to_html_with_options("a <a:b></a:c>", &mdx)?, 1185 "<p>a </p>", 1186 "should support mismatched tags (8)" 1187 ); 1188 assert_eq!( 1189 to_html_with_options("a <a:b></a.b>", &mdx)?, 1190 "<p>a </p>", 1191 "should support mismatched tags (9)" 1192 ); 1193 1194 assert_eq!( 1195 to_html_with_options("a <a>b</a/>", &mdx)?, 1196 "<p>a b</p>", 1197 "should support a closing self-closing tag" 1198 ); 1199 1200 assert_eq!( 1201 to_html_with_options("a <a>b</a b>", &mdx)?, 1202 "<p>a b</p>", 1203 "should support a closing tag w/ attributes" 1204 ); 1205 1206 assert_eq!( 1207 to_html_with_options("a <>b <>c</> d</>.", &mdx)?, 1208 "<p>a b c d.</p>", 1209 "should support nested tags" 1210 ); 1211 1212 assert_eq!( 1213 to_html_with_options( 1214 "<x y=\"Character references can be used: &quot;, &apos;, &lt;, &gt;, &#x7B;, and &#x7D;, they can be named, decimal, or hexadecimal: &copy; &#8800; &#x1D306;\" />.", 1215 &mdx 1216 )?, 1217 "<p>.</p>", 1218 "should support character references in attribute values" 1219 ); 1220 1221 assert_eq!( 1222 to_html_with_options( 1223 "<x>Character references can be used: &quot;, &apos;, &lt;, &gt;, &#x7B;, and &#x7D;, they can be named, decimal, or hexadecimal: &copy; &#8800; &#x1D306;</x>.", 1224 &mdx 1225 )?, 1226 "<p>Character references can be used: &quot;, ', &lt;, &gt;, {, and }, they can be named, decimal, or hexadecimal: © ≠ 𝌆.</p>", 1227 "should support character references in text" 1228 ); 1229 1230 assert_eq!( 1231 to_html_with_options("<x />.", &mdx)?, 1232 "<p>.</p>", 1233 "should support as text if the closing tag is not the last thing" 1234 ); 1235 1236 assert_eq!( 1237 to_html_with_options("a <x />", &mdx)?, 1238 "<p>a </p>", 1239 "should support as text if the opening is not the first thing" 1240 ); 1241 1242 assert_eq!( 1243 to_html_with_options("a *open <b> close* </b> c.", &mdx)?, 1244 "<p>a <em>open close</em> c.</p>", 1245 "should not care about precedence between attention (emphasis)" 1246 ); 1247 1248 assert_eq!( 1249 to_html_with_options("a **open <b> close** </b> c.", &mdx)?, 1250 "<p>a <strong>open close</strong> c.</p>", 1251 "should not care about precedence between attention (strong)" 1252 ); 1253 1254 assert_eq!( 1255 to_html_with_options("a [open <b> close](c) </b> d.", &mdx)?, 1256 "<p>a <a href=\"c\">open close</a> d.</p>", 1257 "should not care about precedence between label (link)" 1258 ); 1259 1260 assert_eq!( 1261 to_html_with_options("a ![open <b> close](c) </b> d.", &mdx)?, 1262 "<p>a <img src=\"c\" alt=\"open close\" /> d.</p>", 1263 "should not care about precedence between label (image)" 1264 ); 1265 1266 assert_eq!( 1267 to_html_with_options("> a <b>\n> c </b> d.", &mdx)?, 1268 "<blockquote>\n<p>a \nc d.</p>\n</blockquote>", 1269 "should support line endings in elements" 1270 ); 1271 1272 assert_eq!( 1273 to_html_with_options("> a <b c=\"d\ne\" /> f", &mdx)?, 1274 "<blockquote>\n<p>a f</p>\n</blockquote>", 1275 "should support line endings in attribute values" 1276 ); 1277 1278 assert_eq!( 1279 to_html_with_options("> a <b c={d\ne} /> f", &mdx)?, 1280 "<blockquote>\n<p>a f</p>\n</blockquote>", 1281 "should support line endings in attribute value expressions" 1282 ); 1283 1284 assert_eq!( 1285 to_html_with_options("> a <b {c\nd} /> e", &mdx)?, 1286 "<blockquote>\n<p>a e</p>\n</blockquote>", 1287 "should support line endings in attribute expressions" 1288 ); 1289 1290 assert_eq!( 1291 to_html_with_options("> a <b\n/> c", &mdx)?, 1292 "<blockquote>\n<p>a c</p>\n</blockquote>", 1293 "should support lazy text (1)" 1294 ); 1295 1296 assert_eq!( 1297 to_html_with_options("> a <b c='\nd'/> e", &mdx)?, 1298 "<blockquote>\n<p>a e</p>\n</blockquote>", 1299 "should support lazy text (2)" 1300 ); 1301 1302 assert_eq!( 1303 to_html_with_options("> a <b c='d\n'/> e", &mdx)?, 1304 "<blockquote>\n<p>a e</p>\n</blockquote>", 1305 "should support lazy text (3)" 1306 ); 1307 1308 assert_eq!( 1309 to_html_with_options("> a <b c='d\ne'/> f", &mdx)?, 1310 "<blockquote>\n<p>a f</p>\n</blockquote>", 1311 "should support lazy text (4)" 1312 ); 1313 1314 assert_eq!( 1315 to_html_with_options("> a <b c={d\ne}/> f", &mdx)?, 1316 "<blockquote>\n<p>a f</p>\n</blockquote>", 1317 "should support lazy text (5)" 1318 ); 1319 1320 assert_eq!( 1321 to_html_with_options("1 < 3", &mdx)?, 1322 "<p>1 &lt; 3</p>", 1323 "should allow `<` followed by markdown whitespace as text in markdown" 1324 ); 1325 1326 Ok(()) 1327}