1328 lines
50 KiB
Rust
1328 lines
50 KiB
Rust
mod test_utils;
|
||
use markdown::{
|
||
mdast::{
|
||
AttributeContent, AttributeValue, AttributeValueExpression, Emphasis, MdxFlowExpression,
|
||
MdxJsxAttribute, MdxJsxExpressionAttribute, MdxJsxFlowElement, MdxJsxTextElement, Node,
|
||
Paragraph, Root, Text,
|
||
},
|
||
message, to_html_with_options, to_mdast,
|
||
unist::Position,
|
||
Constructs, Options, ParseOptions,
|
||
};
|
||
use pretty_assertions::assert_eq;
|
||
use test_utils::swc::{parse_esm, parse_expression};
|
||
|
||
#[test]
|
||
fn mdx_jsx_text_core() -> Result<(), message::Message> {
|
||
let mdx = Options {
|
||
parse: ParseOptions::mdx(),
|
||
..Default::default()
|
||
};
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b> c", &mdx)?,
|
||
"<p>a c</p>",
|
||
"should support mdx jsx (text) if enabled"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b/> c.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support a self-closing element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b></b> c.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support a closed element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <></> c.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support fragments"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b>*b*</b> c.", &mdx)?,
|
||
"<p>a <em>b</em> c.</p>",
|
||
"should support markdown inside elements"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("{1}<a/>", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![
|
||
Node::MdxFlowExpression(MdxFlowExpression {
|
||
value: "1".into(),
|
||
position: Some(Position::new(1, 1, 0, 1, 4, 3)),
|
||
stops: vec![(0, 1)]
|
||
}),
|
||
Node::MdxJsxFlowElement(MdxJsxFlowElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 4, 3, 1, 8, 7))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 8, 7))
|
||
}),
|
||
"should support mdx jsx (text) with expression child"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a>{1}</a>", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::MdxJsxFlowElement(MdxJsxFlowElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![],
|
||
children: vec![Node::MdxFlowExpression(MdxFlowExpression {
|
||
value: "1".into(),
|
||
position: Some(Position::new(1, 4, 3, 1, 7, 6)),
|
||
stops: vec![(0, 4)]
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 11, 10))
|
||
}),],
|
||
position: Some(Position::new(1, 1, 0, 1, 11, 10))
|
||
}),
|
||
"should support mdx jsx (text) with expression child"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("a <b /> c.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::Text(Text {
|
||
value: "a ".into(),
|
||
position: Some(Position::new(1, 1, 0, 1, 3, 2))
|
||
}),
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("b".into()),
|
||
attributes: vec![],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 3, 2, 1, 8, 7))
|
||
}),
|
||
Node::Text(Text {
|
||
value: " c.".into(),
|
||
position: Some(Position::new(1, 8, 7, 1, 11, 10))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 11, 10))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 11, 10))
|
||
}),
|
||
"should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (self-closing)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("a <b>*c*</b> d.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::Text(Text {
|
||
value: "a ".into(),
|
||
position: Some(Position::new(1, 1, 0, 1, 3, 2))
|
||
}),
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("b".into()),
|
||
attributes: vec![],
|
||
children: vec![
|
||
Node::Emphasis(Emphasis {
|
||
children: vec![
|
||
Node::Text(Text {
|
||
value: "c".into(),
|
||
position: Some(Position::new(1, 7, 6, 1, 8, 7))
|
||
}),
|
||
],
|
||
position: Some(Position::new(1, 6, 5, 1, 9, 8))
|
||
}),
|
||
],
|
||
position: Some(Position::new(1, 3, 2, 1, 13, 12))
|
||
}),
|
||
Node::Text(Text {
|
||
value: " d.".into(),
|
||
position: Some(Position::new(1, 13, 12, 1, 16, 15))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 16, 15))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 16, 15))
|
||
}),
|
||
"should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (matched open and close tags)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a:b />.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a:b".into()),
|
||
attributes: vec![],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 8, 7))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 8, 7, 1, 9, 8))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 9, 8))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 9, 8))
|
||
}),
|
||
"should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (namespace in tag name)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a.b.c />.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a.b.c".into()),
|
||
attributes: vec![],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 10, 9))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 10, 9, 1, 11, 10))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 11, 10))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 11, 10))
|
||
}),
|
||
"should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (members in tag name)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a {...b} />.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![AttributeContent::Expression(MdxJsxExpressionAttribute {
|
||
value: "...b".into(),
|
||
stops: vec![(0, 4)]
|
||
})],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 13, 12))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 13, 12, 1, 14, 13))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 14, 13))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 14, 13))
|
||
}),
|
||
"should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (attribute expression)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a b c:d />.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "b".into(),
|
||
value: None,
|
||
}),
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "c:d".into(),
|
||
value: None,
|
||
})
|
||
],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 12, 11))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 12, 11, 1, 13, 12))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 13, 12))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 13, 12))
|
||
}),
|
||
"should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (property names)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a b='c' d=\"e\" f={g} />.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "b".into(),
|
||
value: Some(AttributeValue::Literal("c".into())),
|
||
}),
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "d".into(),
|
||
value: Some(AttributeValue::Literal("e".into())),
|
||
}),
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "f".into(),
|
||
value: Some(AttributeValue::Expression(AttributeValueExpression {
|
||
value: "g".into(),
|
||
stops: vec![(0, 18)]
|
||
})),
|
||
}),
|
||
],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 24, 23))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 24, 23, 1, 25, 24))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 25, 24))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 25, 24))
|
||
}),
|
||
"should support mdx jsx (text) as `MdxJsxTextElement`s in mdast (attribute values)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a b=' & © Æ Ď ¾ ℋ ⅆ ∲ ≧̸' />.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "b".into(),
|
||
value: Some(AttributeValue::Literal("\u{a0} & © Æ Ď ¾ ℋ ⅆ ∲ ≧̸".into())),
|
||
}),
|
||
],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 120, 119))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 120, 119, 1, 121, 120))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 121, 120))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 121, 120))
|
||
}),
|
||
"should support character references (HTML 4, named) in JSX attribute values"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast(
|
||
"<a b='# Ӓ Ϡ �' c='" ആ ಫ' />.",
|
||
&mdx.parse
|
||
)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "b".into(),
|
||
value: Some(AttributeValue::Literal("# Ӓ Ϡ �".into())),
|
||
}),
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "c".into(),
|
||
value: Some(AttributeValue::Literal("\" ആ ಫ".into())),
|
||
}),
|
||
],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 63, 62))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 63, 62, 1, 64, 63))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 64, 63))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 64, 63))
|
||
}),
|
||
"should support character references (numeric) in JSX attribute values"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a b='  &x; &#; &#x; � &#abcdef0; &ThisIsNotDefined; &hi?;' />.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "b".into(),
|
||
value: Some(AttributeValue::Literal("  &x; &#; &#x; � &#abcdef0; &ThisIsNotDefined; &hi?;".into())),
|
||
})
|
||
],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 78, 77))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 78, 77, 1, 79, 78))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 79, 78))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 79, 78))
|
||
}),
|
||
"should not support things that look like character references but aren’t"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a\u{3000}b \u{3000}c\u{3000} d\u{3000}/>.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "b".into(),
|
||
value: None,
|
||
}),
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "c".into(),
|
||
value: None,
|
||
}),
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "d".into(),
|
||
value: None,
|
||
})
|
||
],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 1, 22, 21))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(1, 22, 21, 1, 23, 22))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 1, 23, 22))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 1, 23, 22))
|
||
}),
|
||
"should support unicode whitespace in a lot of places"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a\nb \nc\n d\n/>.", &mdx.parse)?,
|
||
Node::Root(Root {
|
||
children: vec![Node::Paragraph(Paragraph {
|
||
children: vec![
|
||
Node::MdxJsxTextElement(MdxJsxTextElement {
|
||
name: Some("a".into()),
|
||
attributes: vec![
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "b".into(),
|
||
value: None,
|
||
}),
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "c".into(),
|
||
value: None,
|
||
}),
|
||
AttributeContent::Property(MdxJsxAttribute {
|
||
name: "d".into(),
|
||
value: None,
|
||
})
|
||
],
|
||
children: vec![],
|
||
position: Some(Position::new(1, 1, 0, 5, 3, 13))
|
||
}),
|
||
Node::Text(Text {
|
||
value: ".".into(),
|
||
position: Some(Position::new(5, 3, 13, 5, 4, 14))
|
||
})
|
||
],
|
||
position: Some(Position::new(1, 1, 0, 5, 4, 14))
|
||
})],
|
||
position: Some(Position::new(1, 1, 0, 5, 4, 14))
|
||
}),
|
||
"should support line endings in a lot of places"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("a </b> c", &mdx.parse).err().unwrap().to_string(),
|
||
"1:4: Unexpected closing slash `/` in tag, expected an open tag first (markdown-rs:unexpected-closing-slash)",
|
||
"should crash when building the ast on a closing tag if none is open"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("a <b> c </b/> d", &mdx.parse)
|
||
.err()
|
||
.unwrap()
|
||
.to_string(),
|
||
"1:12: Unexpected self-closing slash `/` in closing tag, expected the end of the tag (markdown-rs:unexpected-self-closing-slash)",
|
||
"should crash when building the ast on a closing tag with a self-closing slash"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("a <b> c </b d> e", &mdx.parse)
|
||
.err()
|
||
.unwrap()
|
||
.to_string(),
|
||
"1:13: Unexpected attribute in closing tag, expected the end of the tag (markdown-rs:unexpected-attribute)",
|
||
"should crash when building the ast on a closing tag with an attribute"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("a <>b</c> d", &mdx.parse)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:6-1:10: Unexpected closing tag `</c>`, expected corresponding closing tag for `<>` (1:3) (markdown-rs:end-tag-mismatch)",
|
||
"should crash when building the ast on mismatched tags (1)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("a <b>c</> d", &mdx.parse)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:7-1:10: Unexpected closing tag `</>`, expected corresponding closing tag for `<b>` (1:3) (markdown-rs:end-tag-mismatch)",
|
||
"should crash when building the ast on mismatched tags (2)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("*a <b>c* d</b>.", &mdx.parse)
|
||
.err()
|
||
.unwrap()
|
||
.to_string(),
|
||
"1:9: Expected a closing tag for `<b>` (1:4) before the end of `Emphasis` (markdown-rs:end-tag-mismatch)",
|
||
"should crash when building the ast on mismatched interleaving (1)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a>b *c</a> d*.", &mdx.parse).err().unwrap().to_string(),
|
||
"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)",
|
||
"should crash when building the ast on mismatched interleaving (2)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("a <b>.", &mdx.parse).err().unwrap().to_string(),
|
||
"1:7: Expected a closing tag for `<b>` (1:3) before the end of `Paragraph` (markdown-rs:end-tag-mismatch)",
|
||
"should crash when building the ast on mismatched interleaving (3)"
|
||
);
|
||
|
||
// Note: this is flow, not text.
|
||
assert_eq!(
|
||
to_mdast("<a>", &mdx.parse).err().unwrap().to_string(),
|
||
"1:4: Expected a closing tag for `<a>` (1:1) (markdown-rs:end-tag-mismatch)",
|
||
"should crash when building the ast on mismatched interleaving (4)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_mdast("<a><b></b>", &mdx.parse)
|
||
.err()
|
||
.unwrap()
|
||
.to_string(),
|
||
"1:11: Expected a closing tag for `<a>` (1:1) (markdown-rs:end-tag-mismatch)",
|
||
"should crash on unclosed jsx after closed jsx"
|
||
);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
#[test]
|
||
fn mdx_jsx_text_agnosic() -> Result<(), message::Message> {
|
||
let mdx = Options {
|
||
parse: ParseOptions::mdx(),
|
||
..Default::default()
|
||
};
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b /> c", &mdx)?,
|
||
"<p>a c</p>",
|
||
"should support a self-closing element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b> c </b> d", &mdx)?,
|
||
"<p>a c d</p>",
|
||
"should support a closed element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b> c", &mdx)?,
|
||
"<p>a c</p>",
|
||
"should support an unclosed element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {1 + 1} /> c", &mdx)?,
|
||
"<p>a c</p>",
|
||
"should support an attribute expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c={1 + 1} /> d", &mdx)?,
|
||
"<p>a d</p>",
|
||
"should support an attribute value expression"
|
||
);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
#[test]
|
||
fn mdx_jsx_text_gnostic() -> Result<(), message::Message> {
|
||
let swc = Options {
|
||
parse: ParseOptions {
|
||
constructs: Constructs::mdx(),
|
||
mdx_esm_parse: Some(Box::new(parse_esm)),
|
||
mdx_expression_parse: Some(Box::new(parse_expression)),
|
||
..Default::default()
|
||
},
|
||
..Default::default()
|
||
};
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b /> c", &swc)?,
|
||
"<p>a c</p>",
|
||
"should support a self-closing element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b> c </b> d", &swc)?,
|
||
"<p>a c d</p>",
|
||
"should support a closed element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b> c", &swc)?,
|
||
"<p>a c</p>",
|
||
"should support an unclosed element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {...c} /> d", &swc)?,
|
||
"<p>a d</p>",
|
||
"should support an attribute expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {...{c: 1, d: Infinity, e: false}} /> f", &swc)?,
|
||
"<p>a f</p>",
|
||
"should support more complex attribute expression (1)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {...[1, Infinity, false]} /> d", &swc)?,
|
||
"<p>a d</p>",
|
||
"should support more complex attribute expression (2)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c={1 + 1} /> d", &swc)?,
|
||
"<p>a d</p>",
|
||
"should support an attribute value expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c={} /> d", &swc)
|
||
.err()
|
||
.unwrap()
|
||
.to_string(),
|
||
"1:15: Could not parse expression with swc: Unexpected eof (mdx:swc)",
|
||
"should crash on an empty attribute value expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {1 + 1} /> c", &swc)
|
||
.err()
|
||
.unwrap()
|
||
.to_string(),
|
||
"1:18: Could not parse expression with swc: Expected ',', got '}' (mdx:swc)",
|
||
"should crash on a non-spread attribute expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c={?} /> d", &swc)
|
||
.err()
|
||
.unwrap()
|
||
.to_string(),
|
||
"1:16: Could not parse expression with swc: Expression expected (mdx:swc)",
|
||
"should crash on invalid JS in an attribute value expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {?} /> c", &swc)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:14: Could not parse expression with swc: Unexpected token `?`. Expected identifier, string literal, numeric literal or [ for the computed key (mdx:swc)",
|
||
"should crash on invalid JS in an attribute expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b{c=d}={}/> f", &swc)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:6: Unexpected prop in spread (such as `{x}`): only a spread is supported (such as `{...x}`) (mdx:swc)",
|
||
"should crash on invalid JS in an attribute expression (2)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c={(2)} d={<e />} /> f", &swc)?,
|
||
"<p>a f</p>",
|
||
"should support parenthesized expressions"
|
||
);
|
||
|
||
Ok(())
|
||
}
|
||
|
||
#[test]
|
||
fn mdx_jsx_text_complete() -> Result<(), message::Message> {
|
||
let mdx = Options {
|
||
parse: ParseOptions::mdx(),
|
||
..Default::default()
|
||
};
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b> c", &mdx)?,
|
||
"<p>a c</p>",
|
||
"should support an unclosed element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <> c", &mdx)?,
|
||
"<p>a c</p>",
|
||
"should support an unclosed fragment"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a < \t>b</>", &mdx)?,
|
||
"<p>a < \t>b</p>",
|
||
"should *not* support whitespace in the opening tag (fragment)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a < \nb\t>b</b>", &mdx)?,
|
||
"<p>a <\nb\t>b</p>",
|
||
"should *not* support whitespace in the opening tag (named)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <!> b", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming start identifier"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a </(> b.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming start identifier in a closing tag"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <π /> b.", &mdx)?,
|
||
"<p>a b.</p>",
|
||
"should support non-ascii identifier start characters"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <© /> b.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on non-conforming non-ascii identifier start characters"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <!--b-->", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely on what might be a comment"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <// b\nc/>", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely on JS line comments inside tags (1)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b// c\nd/>", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely JS line comments inside tags (2)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a </*b*/c>", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely JS multiline comments inside tags (1)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b/*c*/>", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:6: Unexpected character `*` (U+002A) after self-closing slash, expected `>` to end the tag (markdown-rs:unexpected-character)",
|
||
"should crash nicely JS multiline comments inside tags (2)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a\u{200C}b /> b.", &mdx)?,
|
||
"<p>a b.</p>",
|
||
"should support non-ascii identifier continuation characters"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a¬ /> b.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on non-conforming non-ascii identifier continuation characters"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b@c.d>", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely on what might be an email link"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a-->b</a-->.", &mdx)?,
|
||
"<p>a b.</p>",
|
||
"should support dashes in names"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a?> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on nonconforming identifier continuation characters"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <abc . def.ghi>b</abc.def . ghi>.", &mdx)?,
|
||
"<p>a b.</p>",
|
||
"should support dots in names for method names"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b.c@d.e>", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely on what might be an email link in member names"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <svg: rect>b</ svg :rect>.", &mdx)?,
|
||
"<p>a b.</p>",
|
||
"should support colons in names for local names"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a:+> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character to start a local name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <http://example.com>", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely on what might be a protocol in local names"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <http: >", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely on what might be a protocol in local names"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a:b|> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character in a local name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a..> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character to start a member name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a.b,> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character in a member name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a:b .> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character after a local name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a.b :> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character after a member name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a => c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character after name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {...props} {...rest}>c</b>.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support attribute expressions"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {...{\"a\": \"b\"}}>c</b>.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support nested balanced braces in attribute expressions"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("<a{...b}/>.", &mdx)?,
|
||
"<p>.</p>",
|
||
"should support attribute expressions directly after a name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("<a.b{...c}/>.", &mdx)?,
|
||
"<p>.</p>",
|
||
"should support attribute expressions directly after a member name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("<a:b{...c}/>.", &mdx)?,
|
||
"<p>.</p>",
|
||
"should support attribute expressions directly after a local name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c{...d}/>.", &mdx)?,
|
||
"<p>a .</p>",
|
||
"should support attribute expressions directly after boolean attributes"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c:d{...e}/>.", &mdx)?,
|
||
"<p>a .</p>",
|
||
"should support attribute expressions directly after boolean qualified attributes"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b a {...props} b>c</b>.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support attribute expressions and normal attributes"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c d=\"d\"\t\tefg=\"e\">c</b>.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support attributes"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {...p}~>c</b>.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character before an attribute name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b {...", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:10: Unexpected end of file in expression, expected a corresponding closing brace for `{` (markdown-rs:unexpected-eof)",
|
||
"should crash on a missing closing brace in attribute expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b@> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character in attribute name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b xml :\tlang\n= \"de-CH\" foo:bar>c</b>.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support prefixed attributes"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b a b : c d : e = \"f\" g/>.", &mdx)?,
|
||
"<p>a .</p>",
|
||
"should support prefixed and normal attributes"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b 1> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character after an attribute name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b:#> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character to start a local attribute name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b:c%> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character in a local attribute name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b:c ^> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character after a local attribute name"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c={1 + 1}>c</b>.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support attribute value expressions"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <b c={1 + ({a: 1}).a}>c</b>.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support nested balanced braces in attribute value expressions"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b=``> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character before an attribute value"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b=<c />> d.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash nicely on what might be a fragment, element as prop value"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b=\"> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:13: Unexpected end of file in attribute value, expected a corresponding closing quote `\"` (U+0022) (markdown-rs:unexpected-eof)",
|
||
"should crash on a missing closing quote in double quoted attribute value"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b=\"> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:13: Unexpected end of file in attribute value, expected a corresponding closing quote `\"` (U+0022) (markdown-rs:unexpected-eof)",
|
||
"should crash on a missing closing quote in single quoted attribute value"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b={> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:13: Unexpected end of file in expression, expected a corresponding closing brace for `{` (markdown-rs:unexpected-eof)",
|
||
"should crash on a missing closing brace in an attribute value expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a b=\"\"*> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"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)",
|
||
"should crash on a nonconforming character after an attribute value"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("<a b=\"\"c/>.", &mdx)?,
|
||
"<p>.</p>",
|
||
"should support an attribute directly after a value"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("<a{...b}c/>.", &mdx)?,
|
||
"<p>.</p>",
|
||
"should support an attribute directly after an attribute expression"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a/b> c.", &mdx)
|
||
.err()
|
||
.unwrap().to_string(),
|
||
"1:6: Unexpected character `b` (U+0062) after self-closing slash, expected `>` to end the tag (markdown-rs:unexpected-character)",
|
||
"should crash on a nonconforming character after a self-closing slash"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("<a/ \t>.", &mdx)?,
|
||
"<p>.</p>",
|
||
"should support whitespace directly after closing slash"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a > c.", &mdx).err(),
|
||
None,
|
||
"should *not* crash on closing angle in text"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <>`<`</> c.", &mdx).err(),
|
||
None,
|
||
"should *not* crash on opening angle in tick code in an element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <>`` ``` ``</>", &mdx).err(),
|
||
None,
|
||
"should *not* crash on ticks in tick code in an element"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a </> c.", &mdx)?,
|
||
"<p>a c.</p>",
|
||
"should support a closing tag w/o open elements"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <></b>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (1)"
|
||
);
|
||
assert_eq!(
|
||
to_html_with_options("a <b></>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (2)"
|
||
);
|
||
assert_eq!(
|
||
to_html_with_options("a <a.b></a>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (3)"
|
||
);
|
||
assert_eq!(
|
||
to_html_with_options("a <a></a.b>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (4)"
|
||
);
|
||
assert_eq!(
|
||
to_html_with_options("a <a.b></a.c>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (5)"
|
||
);
|
||
assert_eq!(
|
||
to_html_with_options("a <a:b></a>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (6)"
|
||
);
|
||
assert_eq!(
|
||
to_html_with_options("a <a></a:b>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (7)"
|
||
);
|
||
assert_eq!(
|
||
to_html_with_options("a <a:b></a:c>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (8)"
|
||
);
|
||
assert_eq!(
|
||
to_html_with_options("a <a:b></a.b>", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support mismatched tags (9)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a>b</a/>", &mdx)?,
|
||
"<p>a b</p>",
|
||
"should support a closing self-closing tag"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <a>b</a b>", &mdx)?,
|
||
"<p>a b</p>",
|
||
"should support a closing tag w/ attributes"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <>b <>c</> d</>.", &mdx)?,
|
||
"<p>a b c d.</p>",
|
||
"should support nested tags"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options(
|
||
"<x y=\"Character references can be used: ", ', <, >, {, and }, they can be named, decimal, or hexadecimal: © ≠ 𝌆\" />.",
|
||
&mdx
|
||
)?,
|
||
"<p>.</p>",
|
||
"should support character references in attribute values"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options(
|
||
"<x>Character references can be used: ", ', <, >, {, and }, they can be named, decimal, or hexadecimal: © ≠ 𝌆</x>.",
|
||
&mdx
|
||
)?,
|
||
"<p>Character references can be used: ", ', <, >, {, and }, they can be named, decimal, or hexadecimal: © ≠ 𝌆.</p>",
|
||
"should support character references in text"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("<x />.", &mdx)?,
|
||
"<p>.</p>",
|
||
"should support as text if the closing tag is not the last thing"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a <x />", &mdx)?,
|
||
"<p>a </p>",
|
||
"should support as text if the opening is not the first thing"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a *open <b> close* </b> c.", &mdx)?,
|
||
"<p>a <em>open close</em> c.</p>",
|
||
"should not care about precedence between attention (emphasis)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a **open <b> close** </b> c.", &mdx)?,
|
||
"<p>a <strong>open close</strong> c.</p>",
|
||
"should not care about precedence between attention (strong)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a [open <b> close](c) </b> d.", &mdx)?,
|
||
"<p>a <a href=\"c\">open close</a> d.</p>",
|
||
"should not care about precedence between label (link)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("a  </b> d.", &mdx)?,
|
||
"<p>a <img src=\"c\" alt=\"open close\" /> d.</p>",
|
||
"should not care about precedence between label (image)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b>\n> c </b> d.", &mdx)?,
|
||
"<blockquote>\n<p>a \nc d.</p>\n</blockquote>",
|
||
"should support line endings in elements"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b c=\"d\ne\" /> f", &mdx)?,
|
||
"<blockquote>\n<p>a f</p>\n</blockquote>",
|
||
"should support line endings in attribute values"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b c={d\ne} /> f", &mdx)?,
|
||
"<blockquote>\n<p>a f</p>\n</blockquote>",
|
||
"should support line endings in attribute value expressions"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b {c\nd} /> e", &mdx)?,
|
||
"<blockquote>\n<p>a e</p>\n</blockquote>",
|
||
"should support line endings in attribute expressions"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b\n/> c", &mdx)?,
|
||
"<blockquote>\n<p>a c</p>\n</blockquote>",
|
||
"should support lazy text (1)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b c='\nd'/> e", &mdx)?,
|
||
"<blockquote>\n<p>a e</p>\n</blockquote>",
|
||
"should support lazy text (2)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b c='d\n'/> e", &mdx)?,
|
||
"<blockquote>\n<p>a e</p>\n</blockquote>",
|
||
"should support lazy text (3)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b c='d\ne'/> f", &mdx)?,
|
||
"<blockquote>\n<p>a f</p>\n</blockquote>",
|
||
"should support lazy text (4)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("> a <b c={d\ne}/> f", &mdx)?,
|
||
"<blockquote>\n<p>a f</p>\n</blockquote>",
|
||
"should support lazy text (5)"
|
||
);
|
||
|
||
assert_eq!(
|
||
to_html_with_options("1 < 3", &mdx)?,
|
||
"<p>1 < 3</p>",
|
||
"should allow `<` followed by markdown whitespace as text in markdown"
|
||
);
|
||
|
||
Ok(())
|
||
}
|