mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
401 lines
11 KiB
Rust
401 lines
11 KiB
Rust
use ParseOpt as PO;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_parse_simple() {
|
|
let buf = "**abcd** rest";
|
|
let (t, r) = parse_simple_pat(buf.as_bytes(), b"**", b"**", PO::None, MdTree::Strong).unwrap();
|
|
assert_eq!(t, MdTree::Strong("abcd"));
|
|
assert_eq!(r, b" rest");
|
|
|
|
// Escaping should fail
|
|
let buf = r"**abcd\** rest";
|
|
let res = parse_simple_pat(buf.as_bytes(), b"**", b"**", PO::None, MdTree::Strong);
|
|
assert!(res.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_comment() {
|
|
let opt = PO::TrimNoEsc;
|
|
let buf = "<!-- foobar! -->rest";
|
|
let (t, r) = parse_simple_pat(buf.as_bytes(), CMT_S, CMT_E, opt, MdTree::Comment).unwrap();
|
|
assert_eq!(t, MdTree::Comment("foobar!"));
|
|
assert_eq!(r, b"rest");
|
|
|
|
let buf = r"<!-- foobar! \-->rest";
|
|
let (t, r) = parse_simple_pat(buf.as_bytes(), CMT_S, CMT_E, opt, MdTree::Comment).unwrap();
|
|
assert_eq!(t, MdTree::Comment(r"foobar! \"));
|
|
assert_eq!(r, b"rest");
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_heading() {
|
|
let buf1 = "# Top level\nrest";
|
|
let (t, r) = parse_heading(buf1.as_bytes()).unwrap();
|
|
assert_eq!(t, MdTree::Heading(1, vec![MdTree::PlainText("Top level")].into()));
|
|
assert_eq!(r, b"\nrest");
|
|
|
|
let buf1 = "# Empty";
|
|
let (t, r) = parse_heading(buf1.as_bytes()).unwrap();
|
|
assert_eq!(t, MdTree::Heading(1, vec![MdTree::PlainText("Empty")].into()));
|
|
assert_eq!(r, b"");
|
|
|
|
// Combo
|
|
let buf2 = "### Top `level` _woo_\nrest";
|
|
let (t, r) = parse_heading(buf2.as_bytes()).unwrap();
|
|
assert_eq!(
|
|
t,
|
|
MdTree::Heading(
|
|
3,
|
|
vec![
|
|
MdTree::PlainText("Top "),
|
|
MdTree::CodeInline("level"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::Emphasis("woo"),
|
|
]
|
|
.into()
|
|
)
|
|
);
|
|
assert_eq!(r, b"\nrest");
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_code_inline() {
|
|
let buf1 = "`abcd` rest";
|
|
let (t, r) = parse_codeinline(buf1.as_bytes()).unwrap();
|
|
assert_eq!(t, MdTree::CodeInline("abcd"));
|
|
assert_eq!(r, b" rest");
|
|
|
|
// extra backticks, newline
|
|
let buf2 = "```ab\ncd``` rest";
|
|
let (t, r) = parse_codeinline(buf2.as_bytes()).unwrap();
|
|
assert_eq!(t, MdTree::CodeInline("ab\ncd"));
|
|
assert_eq!(r, b" rest");
|
|
|
|
// test no escaping
|
|
let buf3 = r"`abcd\` rest";
|
|
let (t, r) = parse_codeinline(buf3.as_bytes()).unwrap();
|
|
assert_eq!(t, MdTree::CodeInline(r"abcd\"));
|
|
assert_eq!(r, b" rest");
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_code_block() {
|
|
let buf1 = "```rust\ncode\ncode\n```\nleftovers";
|
|
let (t, r) = parse_codeblock(buf1.as_bytes());
|
|
assert_eq!(t, MdTree::CodeBlock { txt: "code\ncode", lang: Some("rust") });
|
|
assert_eq!(r, b"\nleftovers");
|
|
|
|
let buf2 = "`````\ncode\ncode````\n`````\nleftovers";
|
|
let (t, r) = parse_codeblock(buf2.as_bytes());
|
|
assert_eq!(t, MdTree::CodeBlock { txt: "code\ncode````", lang: None });
|
|
assert_eq!(r, b"\nleftovers");
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_link() {
|
|
let simple = "[see here](docs.rs) other";
|
|
let (t, r) = parse_any_link(simple.as_bytes(), false).unwrap();
|
|
assert_eq!(t, MdTree::Link { disp: "see here", link: "docs.rs" });
|
|
assert_eq!(r, b" other");
|
|
|
|
let simple_toplevel = "[see here](docs.rs) other";
|
|
let (t, r) = parse_any_link(simple_toplevel.as_bytes(), true).unwrap();
|
|
assert_eq!(t, MdTree::Link { disp: "see here", link: "docs.rs" });
|
|
assert_eq!(r, b" other");
|
|
|
|
let reference = "[see here] other";
|
|
let (t, r) = parse_any_link(reference.as_bytes(), true).unwrap();
|
|
assert_eq!(t, MdTree::RefLink { disp: "see here", id: None });
|
|
assert_eq!(r, b" other");
|
|
|
|
let reference_full = "[see here][docs-rs] other";
|
|
let (t, r) = parse_any_link(reference_full.as_bytes(), false).unwrap();
|
|
assert_eq!(t, MdTree::RefLink { disp: "see here", id: Some("docs-rs") });
|
|
assert_eq!(r, b" other");
|
|
|
|
let reference_def = "[see here]: docs.rs\nother";
|
|
let (t, r) = parse_any_link(reference_def.as_bytes(), true).unwrap();
|
|
assert_eq!(t, MdTree::LinkDef { id: "see here", link: "docs.rs" });
|
|
assert_eq!(r, b"\nother");
|
|
}
|
|
|
|
const IND1: &str = r"test standard
|
|
ind
|
|
ind2
|
|
not ind";
|
|
const IND2: &str = r"test end of stream
|
|
1
|
|
2
|
|
";
|
|
const IND3: &str = r"test empty lines
|
|
1
|
|
2
|
|
|
|
not ind";
|
|
|
|
#[test]
|
|
fn test_indented_section() {
|
|
let (t, r) = get_indented_section(IND1.as_bytes());
|
|
assert_eq!(str::from_utf8(t).unwrap(), "test standard\n ind\n ind2");
|
|
assert_eq!(str::from_utf8(r).unwrap(), "\nnot ind");
|
|
|
|
let (txt, rest) = get_indented_section(IND2.as_bytes());
|
|
assert_eq!(str::from_utf8(txt).unwrap(), "test end of stream\n 1\n 2\n");
|
|
assert_eq!(str::from_utf8(rest).unwrap(), "");
|
|
|
|
let (txt, rest) = get_indented_section(IND3.as_bytes());
|
|
assert_eq!(str::from_utf8(txt).unwrap(), "test empty lines\n 1\n 2\n");
|
|
assert_eq!(str::from_utf8(rest).unwrap(), "\nnot ind");
|
|
}
|
|
|
|
const HBT: &str = r"# Heading
|
|
|
|
content";
|
|
|
|
#[test]
|
|
fn test_heading_breaks() {
|
|
let expected = vec![
|
|
MdTree::Heading(1, vec![MdTree::PlainText("Heading")].into()),
|
|
MdTree::PlainText("content"),
|
|
]
|
|
.into();
|
|
let res = entrypoint(HBT);
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
const NL1: &str = r"start
|
|
|
|
end";
|
|
const NL2: &str = r"start
|
|
|
|
|
|
end";
|
|
const NL3: &str = r"start
|
|
|
|
|
|
|
|
end";
|
|
|
|
#[test]
|
|
fn test_newline_breaks() {
|
|
let expected =
|
|
vec![MdTree::PlainText("start"), MdTree::ParagraphBreak, MdTree::PlainText("end")].into();
|
|
for (idx, check) in [NL1, NL2, NL3].iter().enumerate() {
|
|
let res = entrypoint(check);
|
|
assert_eq!(res, expected, "failed {idx}");
|
|
}
|
|
}
|
|
|
|
const WRAP: &str = "plain _italics
|
|
italics_";
|
|
|
|
#[test]
|
|
fn test_wrap_pattern() {
|
|
let expected = vec![
|
|
MdTree::PlainText("plain "),
|
|
MdTree::Emphasis("italics"),
|
|
MdTree::Emphasis(" "),
|
|
MdTree::Emphasis("italics"),
|
|
]
|
|
.into();
|
|
let res = entrypoint(WRAP);
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
const WRAP_NOTXT: &str = r"_italics_
|
|
**bold**";
|
|
|
|
#[test]
|
|
fn test_wrap_notxt() {
|
|
let expected =
|
|
vec![MdTree::Emphasis("italics"), MdTree::PlainText(" "), MdTree::Strong("bold")].into();
|
|
let res = entrypoint(WRAP_NOTXT);
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
const MIXED_LIST: &str = r"start
|
|
- _italics item_
|
|
<!-- comment -->
|
|
- **bold item**
|
|
second line [link1](foobar1)
|
|
third line [link2][link-foo]
|
|
- :crab:
|
|
extra indent
|
|
end
|
|
[link-foo]: foobar2
|
|
";
|
|
|
|
#[test]
|
|
fn test_list() {
|
|
let expected = vec![
|
|
MdTree::PlainText("start"),
|
|
MdTree::ParagraphBreak,
|
|
MdTree::UnorderedListItem(vec![MdTree::Emphasis("italics item")].into()),
|
|
MdTree::LineBreak,
|
|
MdTree::UnorderedListItem(
|
|
vec![
|
|
MdTree::Strong("bold item"),
|
|
MdTree::PlainText(" second line "),
|
|
MdTree::Link { disp: "link1", link: "foobar1" },
|
|
MdTree::PlainText(" third line "),
|
|
MdTree::Link { disp: "link2", link: "foobar2" },
|
|
]
|
|
.into(),
|
|
),
|
|
MdTree::LineBreak,
|
|
MdTree::UnorderedListItem(
|
|
vec![MdTree::PlainText("🦀"), MdTree::PlainText(" extra indent")].into(),
|
|
),
|
|
MdTree::ParagraphBreak,
|
|
MdTree::PlainText("end"),
|
|
]
|
|
.into();
|
|
let res = entrypoint(MIXED_LIST);
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
const SMOOSHED: &str = r#"
|
|
start
|
|
### heading
|
|
1. ordered item
|
|
```rust
|
|
println!("Hello, world!");
|
|
```
|
|
`inline`
|
|
``end``
|
|
"#;
|
|
|
|
#[test]
|
|
fn test_without_breaks() {
|
|
let expected = vec![
|
|
MdTree::PlainText("start"),
|
|
MdTree::ParagraphBreak,
|
|
MdTree::Heading(3, vec![MdTree::PlainText("heading")].into()),
|
|
MdTree::OrderedListItem(1, vec![MdTree::PlainText("ordered item")].into()),
|
|
MdTree::ParagraphBreak,
|
|
MdTree::CodeBlock { txt: r#"println!("Hello, world!");"#, lang: Some("rust") },
|
|
MdTree::ParagraphBreak,
|
|
MdTree::CodeInline("inline"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::CodeInline("end"),
|
|
]
|
|
.into();
|
|
let res = entrypoint(SMOOSHED);
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
const CODE_STARTLINE: &str = r#"
|
|
start
|
|
`code`
|
|
middle
|
|
`more code`
|
|
end
|
|
"#;
|
|
|
|
#[test]
|
|
fn test_code_at_start() {
|
|
let expected = vec![
|
|
MdTree::PlainText("start"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::CodeInline("code"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::PlainText("middle"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::CodeInline("more code"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::PlainText("end"),
|
|
]
|
|
.into();
|
|
let res = entrypoint(CODE_STARTLINE);
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_code_in_parens() {
|
|
let expected =
|
|
vec![MdTree::PlainText("("), MdTree::CodeInline("Foo"), MdTree::PlainText(")")].into();
|
|
let res = entrypoint("(`Foo`)");
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
const LIST_WITH_SPACE: &str = "
|
|
para
|
|
* l1
|
|
* l2
|
|
";
|
|
|
|
#[test]
|
|
fn test_list_with_space() {
|
|
let expected = vec![
|
|
MdTree::PlainText("para"),
|
|
MdTree::ParagraphBreak,
|
|
MdTree::UnorderedListItem(vec![MdTree::PlainText("l1")].into()),
|
|
MdTree::LineBreak,
|
|
MdTree::UnorderedListItem(vec![MdTree::PlainText("l2")].into()),
|
|
]
|
|
.into();
|
|
let res = entrypoint(LIST_WITH_SPACE);
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
const SNAKE_CASE: &str = "
|
|
foo*bar*
|
|
foo**bar**
|
|
foo_bar_
|
|
foo__bar__
|
|
";
|
|
|
|
#[test]
|
|
fn test_snake_case() {
|
|
let expected = vec![
|
|
MdTree::PlainText("foo"),
|
|
MdTree::Emphasis("bar"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::PlainText("foo"),
|
|
MdTree::Strong("bar"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::PlainText("foo_bar_"),
|
|
MdTree::PlainText(" "),
|
|
MdTree::PlainText("foo__bar__"),
|
|
]
|
|
.into();
|
|
let res = entrypoint(SNAKE_CASE);
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn test_codeblock_trailing_whitespace() {
|
|
let buf = "```rust\ncode\n``` \nrest";
|
|
let (t, r) = parse_codeblock(buf.as_bytes());
|
|
assert_eq!(t, MdTree::CodeBlock { txt: "code", lang: Some("rust") });
|
|
assert_eq!(r, b"\nrest");
|
|
|
|
let buf = "```rust\ncode\n```abc\nrest";
|
|
let (t, r) = parse_codeblock(buf.as_bytes());
|
|
assert_eq!(t, MdTree::CodeBlock { txt: "code\n```abc\nrest", lang: Some("rust") });
|
|
assert_eq!(r, b"");
|
|
}
|
|
|
|
#[test]
|
|
fn test_list_item_leading_whitespace() {
|
|
// extra spaces after marker
|
|
let buf = "- hello";
|
|
let (t, r) = parse_unordered_li(buf.as_bytes());
|
|
assert_eq!(t, MdTree::UnorderedListItem(vec![MdTree::PlainText("hello")].into()));
|
|
assert_eq!(r, b"");
|
|
|
|
// tab after the marker space
|
|
let buf = "- \thello";
|
|
let (t, r) = parse_unordered_li(buf.as_bytes());
|
|
assert_eq!(t, MdTree::UnorderedListItem(vec![MdTree::PlainText("hello")].into()));
|
|
assert_eq!(r, b"");
|
|
|
|
// ordered list
|
|
let buf = "1. hello";
|
|
let (t, r) = parse_ordered_li(buf.as_bytes());
|
|
assert_eq!(t, MdTree::OrderedListItem(1, vec![MdTree::PlainText("hello")].into()));
|
|
assert_eq!(r, b"");
|
|
}
|