mod support;
use accent_proust::ast::NodeType;
use accent_proust::parse::{find_tag_end, parse};
use support::{at, attribute, outline};
fn tag_end(example: &str) -> Option<usize> {
let end = find_tag_end(example, 0);
if let Some(end) = end {
assert_eq!(
example.as_bytes().get(end).copied(),
Some(b'%'),
"offset {end} of {example:?} is not the `%` of a closing delimiter"
);
}
end
}
#[test]
fn in_a_heading() {
assert_eq!(tag_end("# Testing {% #foo.bar baz=1 %}"), Some(28));
}
#[test]
fn with_string() {
assert_eq!(
tag_end("# Testing {% #foo.bar baz=\"example\" test=true %}"),
Some(46)
);
}
#[test]
fn with_object_literal_attribute_value() {
assert_eq!(
tag_end("# Testing {% #foo.bar baz={test: 1, foo: {test: \"asdf{\"}} %}"),
Some(58)
);
}
#[test]
fn in_a_simple_container() {
assert_eq!(tag_end("{% foo %}"), Some(7));
}
#[test]
fn in_a_container_with_shortcuts() {
assert_eq!(tag_end("{% foo .bar.baz#test %}"), Some(21));
}
#[test]
fn in_a_container_with_a_string_attribute() {
assert_eq!(tag_end("{% foo test=\"this is a test\" %}"), Some(29));
}
#[test]
fn for_an_invalid_container() {
assert_eq!(tag_end("{% foo .bar#baz"), None);
}
#[test]
fn in_a_complex_container() {
assert_eq!(
tag_end("{% #foo .bar .baz test=\"this} is \\\"{test}\\\" a test\" %} this is a test"),
Some(52)
);
}
#[test]
fn multiline_simple() {
let example = "\n {% test #foo.bar\n baz=1 %}\n ";
assert_eq!(tag_end(example), Some(46));
}
#[test]
fn multiline_with_string() {
let example = "\n {% test #foo.bar\
\n baz=\"this is a test\"\
\n example=1 %}\n ";
assert_eq!(tag_end(example), Some(85));
}
#[test]
fn multiline_with_string_and_escaped_quote() {
let example = "\n {% test #foo.bar\
\n baz=\"this \\\"is a test\"\
\n example=1 %}\n ";
assert_eq!(tag_end(example), Some(87));
}
#[test]
fn multiline_with_string_that_has_an_opening_brace() {
let example = "\n {% test #foo.bar\
\n baz=\"this {is a test\"\
\n example=1 %}\n ";
assert_eq!(tag_end(example), Some(86));
}
#[test]
fn multiline_with_string_that_has_escapes_and_braces() {
let example = "\n {% test #foo.bar\
\n baz=\"th\\\"is {is a \\\\te\\\"st\"\
\n example=1 %}\n ";
assert_eq!(tag_end(example), Some(92));
}
#[test]
fn multiline_with_an_object_literal_attribute_value() {
let example = "\n {% test #foo.bar\
\n foo={testing: \"this } is a test\", bar: {baz: 1}}\
\n example=1 another=\"test}\" %}\n ";
assert_eq!(tag_end(example), Some(129));
}
#[test]
fn multiline_with_an_invalid_object_literal_attribute_value() {
let example = "\n {test #foo.bar\
\n foo={testing: \"this } is a test\", bar: {baz: 1}\
\n example=1 another=\"test}\"}\n ";
assert_eq!(tag_end(example), None);
}
#[test]
fn a_tag_is_found_inside_a_run_of_text() {
let document = parse("this is a {% foo blah=\"asdf\" %}test{% /foo %} of template parsing");
assert_eq!(
outline(&document),
"document\n \
paragraph\n \
inline\n \
text content=\"this is a \"\n \
tag[foo] blah=\"asdf\"\n \
text content=\"test\"\n \
text content=\" of template parsing\"\n"
);
}
#[test]
fn a_tag_delimiter_inside_a_fence_is_left_alone() {
let document = parse("```\n{%a %b %c}\n```");
let fence = at(&document, &[0]);
assert_eq!(fence.node_type, NodeType::Fence);
assert_eq!(attribute(fence, "content"), "\"{%a %b %c}\\n\"");
assert!(fence.children.is_empty(), "a literal fence has no children");
assert!(
!document.walk().any(|node| node.node_type == NodeType::Tag),
"the fence's `{{%` was read as a tag"
);
}