blob: bfcb3de16fa0e1dc938b47d2832b1366fd42af48 [file] [log] [blame]
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);
}