| 1 | use once_cell::sync::Lazy; |
| 2 | |
| 3 | |
| 4 | #[test] |
| 5 | fn title_example() { |
| 6 | let parser = &mut markdown_it::MarkdownIt::new(); |
| 7 | markdown_it::plugins::cmark::add(parser); |
| 8 | |
| 9 | let ast = parser.parse("Hello **world**!"); |
| 10 | let html = ast.render(); |
| 11 | |
| 12 | assert_eq!(html, "<p>Hello <strong>world</strong>!</p>\n"); |
| 13 | } |
| 14 | |
| 15 | #[test] |
| 16 | fn lazy_singleton() { |
| 17 | static MD : Lazy<markdown_it::MarkdownIt> = Lazy::new(|| { |
| 18 | let mut parser = markdown_it::MarkdownIt::new(); |
| 19 | markdown_it::plugins::cmark::add(&mut parser); |
| 20 | parser |
| 21 | }); |
| 22 | |
| 23 | let ast = MD.parse("Hello **world**!"); |
| 24 | let html = ast.render(); |
| 25 | |
| 26 | assert_eq!(html, "<p>Hello <strong>world</strong>!</p>\n"); |
| 27 | } |
| 28 | |
| 29 | #[test] |
| 30 | fn no_plugins() { |
| 31 | let md = &mut markdown_it::MarkdownIt::new(); |
| 32 | let node = md.parse("hello\nworld"); |
| 33 | let result = node.render(); |
| 34 | assert_eq!(result, "hello\nworld\n"); |
| 35 | } |
| 36 | |
| 37 | #[test] |
| 38 | fn no_max_indent() { |
| 39 | let md = &mut markdown_it::MarkdownIt::new(); |
| 40 | markdown_it::plugins::cmark::block::paragraph::add(md); |
| 41 | markdown_it::plugins::cmark::block::list::add(md); |
| 42 | md.max_indent = i32::MAX; |
| 43 | let node = md.parse(" paragraph\n - item"); |
| 44 | let result = node.render(); |
| 45 | assert_eq!(result, "<p>paragraph</p>\n<ul>\n<li>item</li>\n</ul>\n"); |
| 46 | } |
| 47 | |
| 48 | |
| 49 | /*#[test] |
| 50 | fn no_block_parser() { |
| 51 | let md = &mut markdown_it::MarkdownIt::new(); |
| 52 | markdown_it::plugins::cmark::add(md); |
| 53 | md.remove_rule::<markdown_it::parser::block::builtin::BlockParserRule>(); |
| 54 | let node = md.parse("hello *world*"); |
| 55 | let result = node.render(); |
| 56 | assert_eq!(result, "hello <em>world</em>"); |
| 57 | }*/ |
| 58 | |
| 59 | fn run(input: &str, output: &str) { |
| 60 | let output = if output.is_empty() { "".to_owned() } else { output.to_owned() + "\n" }; |
| 61 | let md = &mut markdown_it::MarkdownIt::new(); |
| 62 | markdown_it::plugins::cmark::add(md); |
| 63 | markdown_it::plugins::html::add(md); |
| 64 | markdown_it::plugins::extra::beautify_links::add(md); |
| 65 | let node = md.parse(&(input.to_owned() + "\n")); |
| 66 | node.walk(|node, _| assert!(node.srcmap.is_some())); |
| 67 | let result = node.render(); |
| 68 | assert_eq!(result, output); |
| 69 | } |
| 70 | |
| 71 | mod markdown_it_rs_extras { |
| 72 | use super::run; |
| 73 | |
| 74 | #[test] |
| 75 | fn regression_test_img() { |
| 76 | // ! at end of line |
| 77 | run("Hello!", "<p>Hello!</p>"); |
| 78 | } |
| 79 | |
| 80 | #[test] |
| 81 | fn regression_list_markers() { |
| 82 | run("- foo\n- bar", "<ul>\n<li>foo</li>\n<li>bar</li>\n</ul>"); |
| 83 | run("1. foo\n1. bar", "<ol>\n<li>foo</li>\n<li>bar</li>\n</ol>"); |
| 84 | } |
| 85 | |
| 86 | #[test] |
| 87 | fn tab_offset_in_lists() { |
| 88 | run(" > -\tfoo\n >\n > foo\n", |
| 89 | r#"<blockquote> |
| 90 | <ul> |
| 91 | <li> |
| 92 | <p>foo</p> |
| 93 | <pre><code> foo |
| 94 | </code></pre> |
| 95 | </li> |
| 96 | </ul> |
| 97 | </blockquote>"#); |
| 98 | } |
| 99 | |
| 100 | #[test] |
| 101 | fn null_char_replacement() { |
| 102 | run("&#0;", "<p>\u{FFFD}</p>"); |
| 103 | run("\0", "<p>\u{FFFD}</p>"); |
| 104 | } |
| 105 | |
| 106 | #[test] |
| 107 | fn cr_only_newlines() { |
| 108 | run("foo\rbar", "<p>foo\nbar</p>"); |
| 109 | run(" foo\r bar", "<pre><code>foo\nbar\n</code></pre>"); |
| 110 | } |
| 111 | |
| 112 | #[test] |
| 113 | fn cr_lf_newlines() { |
| 114 | run("foo\r\nbar", "<p>foo\nbar</p>"); |
| 115 | run(" foo\r\n bar", "<pre><code>foo\nbar\n</code></pre>"); |
| 116 | } |
| 117 | |
| 118 | #[test] |
| 119 | fn beautify_links() { |
| 120 | run("<https://www.reddit.com/r/programming/comments/vxttiq/comment/ifyqsqt/?utm_source=reddit&utm_medium=web2x&context=3>", |
| 121 | "<p><a href=\"https://www.reddit.com/r/programming/comments/vxttiq/comment/ifyqsqt/?utm_source=reddit&amp;utm_medium=web2x&amp;context=3\">www.reddit.com/r/programming/comments/…/ifyqsqt/?…</a></p>"); |
| 122 | } |
| 123 | |
| 124 | #[test] |
| 125 | fn regression_test_newlines_with_images() { |
| 126 | run("There is a newline in this image ", |
| 127 | "<p>There is a newline in this image <img src=\"https://github.com/executablebooks/\" alt=\"here\nit is\"></p>"); |
| 128 | } |
| 129 | |
| 130 | #[test] |
| 131 | fn test_node_ext_propagation() { |
| 132 | use markdown_it::parser::block::{BlockRule, BlockState}; |
| 133 | use markdown_it::parser::core::CoreRule; |
| 134 | use markdown_it::parser::extset::NodeExt; |
| 135 | use markdown_it::parser::inline::{InlineRule, InlineState}; |
| 136 | use markdown_it::{MarkdownIt, Node}; |
| 137 | |
| 138 | #[derive(Debug, Default)] |
| 139 | struct NodeErrors(Vec<&'static str>); |
| 140 | impl NodeExt for NodeErrors {} |
| 141 | |
| 142 | struct MyInlineRule; |
| 143 | impl InlineRule for MyInlineRule { |
| 144 | const MARKER: char = '@'; |
| 145 | |
| 146 | fn run(state: &mut InlineState) -> Option<(Node, usize)> { |
| 147 | let err = state.node.ext.get_or_insert_default::<NodeErrors>(); |
| 148 | err.0.push("inline"); |
| 149 | None |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | struct MyBlockRule; |
| 154 | impl BlockRule for MyBlockRule { |
| 155 | fn run(state: &mut BlockState) -> Option<(Node, usize)> { |
| 156 | let err = state.node.ext.get_or_insert_default::<NodeErrors>(); |
| 157 | err.0.push("block"); |
| 158 | None |
| 159 | } |
| 160 | } |
| 161 | |
| 162 | struct MyCoreRule; |
| 163 | impl CoreRule for MyCoreRule { |
| 164 | fn run(root: &mut Node, _md: &MarkdownIt) { |
| 165 | let err = root.ext.get_or_insert_default::<NodeErrors>(); |
| 166 | err.0.push("core"); |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | let md = &mut markdown_it::MarkdownIt::new(); |
| 171 | markdown_it::plugins::cmark::add(md); |
| 172 | |
| 173 | md.inline.add_rule::<MyInlineRule>(); |
| 174 | md.block.add_rule::<MyBlockRule>(); |
| 175 | md.add_rule::<MyCoreRule>().after_all(); |
| 176 | |
| 177 | let text1 = r#"*hello @world*"#; |
| 178 | let ast = md.parse(text1); |
| 179 | let mut collected: Vec<&str> = vec![]; |
| 180 | |
| 181 | ast.walk_post(|node, _| { |
| 182 | if let Some(errors) = node.ext.get::<NodeErrors>() { |
| 183 | collected.extend(errors.0.iter()); |
| 184 | } |
| 185 | }); |
| 186 | |
| 187 | assert_eq!( |
| 188 | collected, |
| 189 | vec!["inline", "block", "core"], |
| 190 | ); |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | mod examples { |
| 195 | include!("../examples/ferris/main.rs"); |
| 196 | |
| 197 | #[test] |
| 198 | fn test_examples() { |
| 199 | main(); |
| 200 | } |
| 201 | } |
| 202 | |