use text_document::{DjotImportOptions, TABLE_ANCHOR, TextDocument, djot_to_plain_text};
fn plain(djot: &str) -> String {
let doc = TextDocument::new();
doc.set_djot(djot).unwrap().wait().unwrap();
doc.to_plain_text().unwrap()
}
#[test]
fn a_blockquote_is_not_hoisted_to_the_end() {
assert_eq!(
plain("> a0\n\na"),
"a0\na",
"the quotation is written first, so it must be read first"
);
}
#[test]
fn quotes_and_paragraphs_keep_their_interleaving() {
assert_eq!(plain("p1\n\n> q1\n\np2\n\n> q2"), "p1\nq1\np2\nq2");
assert_eq!(plain("a\n\n> a0\n\nb"), "a\na0\nb");
assert_eq!(plain("> a0\n\na\n\n> a1"), "a0\na\na1");
assert_eq!(plain("> a0\n\n> a1\n\na"), "a0\na1\na");
}
#[test]
fn a_quote_is_not_hoisted_past_a_heading_a_list_or_a_fence() {
assert_eq!(plain("> a0\n\n# h"), "a0\nh");
assert_eq!(plain("> a0\n\n- item"), "a0\nitem");
assert_eq!(plain("> a0\n\n```\ncode\n```"), "a0\ncode");
}
#[test]
fn nested_and_multi_block_quotes_stay_in_place() {
assert_eq!(
plain("> outer\n>\n> > inner\n\nafter"),
"outer\ninner\nafter"
);
assert_eq!(
plain("> p1\n>\n> p2\n\nafter"),
"p1\np2\nafter",
"a quote's own blocks stay in order AND stay before what follows the quote"
);
}
#[test]
fn a_table_stays_where_it_was_written() {
assert_eq!(
plain("intro\n\n| a | b |\n| - | - |\n| c | d |\n\nafter"),
"intro\na\nb\nc\nd\nafter"
);
}
#[test]
fn the_human_view_is_the_addressable_view_minus_its_anchors() {
for src in [
"> a0\n\na",
"p1\n\n> q1\n\np2\n\n> q2",
"intro\n\n| a | b |\n| - | - |\n| c | d |\n\nafter",
"> quoted\n\n# head\n\n- item\n\n| x |\n| - |\n| y |",
"a\n\nb\n\nc",
] {
let addressable = djot_to_plain_text(src, &DjotImportOptions::default());
let without_anchors: Vec<&str> = addressable
.split('\n')
.filter(|line| *line != TABLE_ANCHOR)
.collect();
assert_eq!(
plain(src),
without_anchors.join("\n"),
"to_plain_text() and the document's addressable text disagree about more than \
anchors, for {src:?} — the only sanctioned difference is the object anchors"
);
}
}
fn plain_indented(djot: &str) -> String {
let doc = TextDocument::new();
doc.set_djot(djot).unwrap().wait().unwrap();
doc.to_plain_text_indented().unwrap()
}
#[test]
fn the_indented_export_sets_quoted_blocks_in() {
assert_eq!(plain_indented("> a0\n\na"), " a0\na");
assert_eq!(
plain_indented("p1\n\n> q1\n\np2"),
"p1\n q1\np2",
"only the quoted block moves; the surrounding prose stays flush"
);
}
#[test]
fn the_indented_export_nests() {
assert_eq!(plain_indented("> > deep"), " deep");
}
#[test]
fn the_plain_export_stays_flush_so_offsets_survive() {
for src in ["> a0\n\na", "p1\n\n> q1\n\np2\n\n> q2", "> > deep"] {
let flush = plain(src);
assert!(
!flush.lines().any(|l| l.starts_with(' ')),
"to_plain_text() must not indent {src:?}, it is the addressable view: {flush:?}"
);
assert_ne!(
flush,
plain_indented(src),
"the indented export must actually differ for {src:?}, or it is doing nothing"
);
}
}
#[test]
fn an_epigraph_indents_as_one_unit_attribution_included() {
assert_eq!(
plain_indented("> The sea is a going.\n>\n> — Anon.\n\nThe first paragraph."),
" The sea is a going.\n — Anon.\nThe first paragraph."
);
}
const EPIGRAPH_DJOT: &str =
"> {semantic_role=epigraph}\n> The sea is a going.\n>\n> {alignment=right}\n> — Anon.";
fn doc_of(djot: &str) -> TextDocument {
let doc = TextDocument::new();
doc.set_djot(djot).unwrap().wait().unwrap();
doc
}
#[test]
fn the_semantic_role_round_trips_through_djot() {
let out = doc_of(EPIGRAPH_DJOT).to_djot().unwrap();
assert!(
out.contains("semantic_role=epigraph"),
"the role must be written back: {out}"
);
}
#[test]
fn an_epigraph_is_marked_up_semantically_in_html() {
let html = doc_of(EPIGRAPH_DJOT).to_html().unwrap();
assert!(html.contains(r#"epub:type="epigraph""#), "{html}");
assert!(html.contains(r#"role="doc-epigraph""#), "{html}");
}
#[test]
fn a_plain_quotation_is_not_marked_as_an_epigraph() {
let html = doc_of("> Just a quotation.").to_html().unwrap();
assert!(html.contains("<blockquote>"), "still a blockquote: {html}");
assert!(!html.contains("epigraph"), "but not an epigraph: {html}");
}
#[test]
fn an_unknown_semantic_role_degrades_to_a_plain_quotation() {
let html = doc_of("> {semantic_role=colophon}\n> From the future.")
.to_html()
.unwrap();
assert!(html.contains("<blockquote>"), "{html}");
assert!(!html.contains("colophon"), "{html}");
}