Markdown parser fork with extended syntax for personal use.
at hack 356 lines 12 kB view raw
1use markdown::{ 2 mdast::{Definition, Image, ImageReference, Node, Paragraph, ReferenceKind, Root, Text}, 3 message, to_html, to_html_with_options, to_mdast, 4 unist::Position, 5 CompileOptions, Constructs, Options, ParseOptions, 6}; 7use pretty_assertions::assert_eq; 8 9#[test] 10fn image() -> Result<(), message::Message> { 11 assert_eq!( 12 to_html("[link](/uri \"title\")"), 13 "<p><a href=\"/uri\" title=\"title\">link</a></p>", 14 "should support links" 15 ); 16 assert_eq!( 17 to_html("![foo](/url \"title\")"), 18 "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>", 19 "should support image w/ resource" 20 ); 21 22 assert_eq!( 23 to_html("[foo *bar*]: train.jpg \"train & tracks\"\n\n![foo *bar*]"), 24 "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>", 25 "should support image as shortcut reference" 26 ); 27 28 assert_eq!( 29 to_html("![foo ![bar](/url)](/url2)"), 30 "<p><img src=\"/url2\" alt=\"foo bar\" /></p>", 31 "should “support” images in images" 32 ); 33 34 assert_eq!( 35 to_html("![foo [bar](/url)](/url2)"), 36 "<p><img src=\"/url2\" alt=\"foo bar\" /></p>", 37 "should “support” links in images" 38 ); 39 40 assert_eq!( 41 to_html("[foo *bar*]: train.jpg \"train & tracks\"\n\n![foo *bar*][]"), 42 "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>", 43 "should support “content” in images" 44 ); 45 46 assert_eq!( 47 to_html("[FOOBAR]: train.jpg \"train & tracks\"\n\n![foo *bar*][foobar]"), 48 "<p><img src=\"train.jpg\" alt=\"foo bar\" title=\"train &amp; tracks\" /></p>", 49 "should support “content” in images" 50 ); 51 52 assert_eq!( 53 to_html("![foo](train.jpg)"), 54 "<p><img src=\"train.jpg\" alt=\"foo\" /></p>", 55 "should support images w/o title" 56 ); 57 58 assert_eq!( 59 to_html("My ![foo bar](/path/to/train.jpg \"title\" )"), 60 "<p>My <img src=\"/path/to/train.jpg\" alt=\"foo bar\" title=\"title\" /></p>", 61 "should support images w/ lots of whitespace" 62 ); 63 64 assert_eq!( 65 to_html("![foo](<url>)"), 66 "<p><img src=\"url\" alt=\"foo\" /></p>", 67 "should support images w/ enclosed destinations" 68 ); 69 70 assert_eq!( 71 to_html("![](/url)"), 72 "<p><img src=\"/url\" alt=\"\" /></p>", 73 "should support images w/ empty labels" 74 ); 75 76 assert_eq!( 77 to_html("[bar]: /url\n\n![foo][bar]"), 78 "<p><img src=\"/url\" alt=\"foo\" /></p>", 79 "should support full references (1)" 80 ); 81 82 assert_eq!( 83 to_html("[BAR]: /url\n\n![foo][bar]"), 84 "<p><img src=\"/url\" alt=\"foo\" /></p>", 85 "should support full references (2)" 86 ); 87 88 assert_eq!( 89 to_html("[foo]: /url \"title\"\n\n![foo][]"), 90 "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>", 91 "should support collapsed references (1)" 92 ); 93 94 assert_eq!( 95 to_html("[*foo* bar]: /url \"title\"\n\n![*foo* bar][]"), 96 "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>", 97 "should support collapsed references (2)" 98 ); 99 100 assert_eq!( 101 to_html("[foo]: /url \"title\"\n\n![Foo][]"), 102 "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>", 103 "should support case-insensitive labels" 104 ); 105 106 assert_eq!( 107 to_html("[foo]: /url \"title\"\n\n![foo] \n[]"), 108 "<p><img src=\"/url\" alt=\"foo\" title=\"title\" />\n[]</p>", 109 "should not support whitespace between sets of brackets" 110 ); 111 112 assert_eq!( 113 to_html("[foo]: /url \"title\"\n\n![foo]"), 114 "<p><img src=\"/url\" alt=\"foo\" title=\"title\" /></p>", 115 "should support shortcut references (1)" 116 ); 117 118 assert_eq!( 119 to_html("[*foo* bar]: /url \"title\"\n\n![*foo* bar]"), 120 "<p><img src=\"/url\" alt=\"foo bar\" title=\"title\" /></p>", 121 "should support shortcut references (2)" 122 ); 123 124 assert_eq!( 125 to_html("[[foo]]: /url \"title\"\n\n![[foo]]"), 126 "<p>[[foo]]: /url &quot;title&quot;</p>\n<p>![[foo]]</p>", 127 "should not support link labels w/ unescaped brackets" 128 ); 129 130 assert_eq!( 131 to_html("[foo]: /url \"title\"\n\n![Foo]"), 132 "<p><img src=\"/url\" alt=\"Foo\" title=\"title\" /></p>", 133 "should support case-insensitive label matching" 134 ); 135 136 assert_eq!( 137 to_html("[foo]: /url \"title\"\n\n!\\[foo]"), 138 "<p>![foo]</p>", 139 "should “support” an escaped bracket instead of an image" 140 ); 141 142 assert_eq!( 143 to_html("[foo]: /url \"title\"\n\n\\![foo]"), 144 "<p>!<a href=\"/url\" title=\"title\">foo</a></p>", 145 "should support an escaped bang instead of an image, but still have a link" 146 ); 147 148 // Extra 149 assert_eq!( 150 to_html("![foo]()"), 151 "<p><img src=\"\" alt=\"foo\" /></p>", 152 "should support images w/o destination" 153 ); 154 155 assert_eq!( 156 to_html("![foo](<>)"), 157 "<p><img src=\"\" alt=\"foo\" /></p>", 158 "should support images w/ explicit empty destination" 159 ); 160 161 assert_eq!( 162 to_html("![](example.png)"), 163 "<p><img src=\"example.png\" alt=\"\" /></p>", 164 "should support images w/o alt" 165 ); 166 167 assert_eq!( 168 to_html("![alpha](bravo.png \"\")"), 169 "<p><img src=\"bravo.png\" alt=\"alpha\" /></p>", 170 "should support images w/ empty title (1)" 171 ); 172 173 assert_eq!( 174 to_html("![alpha](bravo.png '')"), 175 "<p><img src=\"bravo.png\" alt=\"alpha\" /></p>", 176 "should support images w/ empty title (2)" 177 ); 178 179 assert_eq!( 180 to_html("![alpha](bravo.png ())"), 181 "<p><img src=\"bravo.png\" alt=\"alpha\" /></p>", 182 "should support images w/ empty title (3)" 183 ); 184 185 assert_eq!( 186 to_html("![&amp;&copy;&](example.com/&amp;&copy;& \"&amp;&copy;&\")"), 187 "<p><img src=\"example.com/&amp;%C2%A9&amp;\" alt=\"&amp;©&amp;\" title=\"&amp;©&amp;\" /></p>", 188 "should support character references in images" 189 ); 190 191 // Extra 192 // See: <https://github.com/commonmark/commonmark.js/issues/192> 193 assert_eq!( 194 to_html("![](<> \"\")"), 195 "<p><img src=\"\" alt=\"\" /></p>", 196 "should ignore an empty title" 197 ); 198 199 assert_eq!( 200 to_html_with_options( 201 "![x]()", 202 &Options { 203 parse: ParseOptions { 204 constructs: Constructs { 205 label_start_image: false, 206 ..Default::default() 207 }, 208 ..Default::default() 209 }, 210 ..Default::default() 211 } 212 )?, 213 "<p>!<a href=\"\">x</a></p>", 214 "should support turning off label start (image)" 215 ); 216 217 assert_eq!( 218 to_html("![](javascript:alert(1))"), 219 "<p><img src=\"\" alt=\"\" /></p>", 220 "should ignore non-http protocols by default" 221 ); 222 223 assert_eq!( 224 to_html_with_options( 225 "![](javascript:alert(1))", 226 &Options { 227 compile: CompileOptions { 228 allow_dangerous_protocol: true, 229 ..Default::default() 230 }, 231 ..Default::default() 232 } 233 )?, 234 "<p><img src=\"javascript:alert(1)\" alt=\"\" /></p>", 235 "should allow non-http protocols w/ `allowDangerousProtocol`" 236 ); 237 238 assert_eq!( 239 to_html_with_options( 240 "![](javascript:alert(1))", 241 &Options { 242 compile: CompileOptions { 243 allow_any_img_src: true, 244 allow_dangerous_protocol: false, 245 ..Default::default() 246 }, 247 ..Default::default() 248 } 249 )?, 250 "<p><img src=\"javascript:alert(1)\" alt=\"\" /></p>", 251 "should allow non-http protocols with the `allow_any_img_src` option" 252 ); 253 254 assert_eq!( 255 to_mdast( 256 "a ![alpha]() b ![bravo](charlie 'delta') c.", 257 &Default::default() 258 )?, 259 Node::Root(Root { 260 children: vec![Node::Paragraph(Paragraph { 261 children: vec![ 262 Node::Text(Text { 263 value: "a ".into(), 264 position: Some(Position::new(1, 1, 0, 1, 3, 2)) 265 }), 266 Node::Image(Image { 267 alt: "alpha".into(), 268 url: String::new(), 269 title: None, 270 position: Some(Position::new(1, 3, 2, 1, 13, 12)) 271 }), 272 Node::Text(Text { 273 value: " b ".into(), 274 position: Some(Position::new(1, 13, 12, 1, 16, 15)) 275 }), 276 Node::Image(Image { 277 alt: "bravo".into(), 278 url: "charlie".into(), 279 title: Some("delta".into()), 280 position: Some(Position::new(1, 16, 15, 1, 41, 40)) 281 }), 282 Node::Text(Text { 283 value: " c.".into(), 284 position: Some(Position::new(1, 41, 40, 1, 44, 43)) 285 }) 286 ], 287 position: Some(Position::new(1, 1, 0, 1, 44, 43)) 288 })], 289 position: Some(Position::new(1, 1, 0, 1, 44, 43)) 290 }), 291 "should support image (resource) as `Image`s in mdast" 292 ); 293 294 assert_eq!( 295 to_mdast( 296 "[x]: y\n\na ![x] b ![x][] c ![d][x] e.", 297 &Default::default() 298 )?, 299 Node::Root(Root { 300 children: vec![ 301 Node::Definition(Definition { 302 identifier: "x".into(), 303 label: Some("x".into()), 304 url: "y".into(), 305 title: None, 306 position: Some(Position::new(1, 1, 0, 1, 7, 6)) 307 }), 308 Node::Paragraph(Paragraph { 309 children: vec![ 310 Node::Text(Text { 311 value: "a ".into(), 312 position: Some(Position::new(3, 1, 8, 3, 3, 10)) 313 }), 314 Node::ImageReference(ImageReference { 315 reference_kind: ReferenceKind::Shortcut, 316 identifier: "x".into(), 317 label: Some("x".into()), 318 alt: "x".into(), 319 position: Some(Position::new(3, 3, 10, 3, 7, 14)) 320 }), 321 Node::Text(Text { 322 value: " b ".into(), 323 position: Some(Position::new(3, 7, 14, 3, 10, 17)) 324 }), 325 Node::ImageReference(ImageReference { 326 reference_kind: ReferenceKind::Collapsed, 327 identifier: "x".into(), 328 label: Some("x".into()), 329 alt: "x".into(), 330 position: Some(Position::new(3, 10, 17, 3, 16, 23)) 331 }), 332 Node::Text(Text { 333 value: " c ".into(), 334 position: Some(Position::new(3, 16, 23, 3, 19, 26)) 335 }), 336 Node::ImageReference(ImageReference { 337 reference_kind: ReferenceKind::Full, 338 identifier: "x".into(), 339 label: Some("x".into()), 340 alt: "d".into(), 341 position: Some(Position::new(3, 19, 26, 3, 26, 33)) 342 }), 343 Node::Text(Text { 344 value: " e.".into(), 345 position: Some(Position::new(3, 26, 33, 3, 29, 36)) 346 }), 347 ], 348 position: Some(Position::new(3, 1, 8, 3, 29, 36)) 349 }), 350 ], 351 position: Some(Position::new(1, 1, 0, 3, 29, 36)) 352 }), 353 "should support image (reference) as `ImageReference`s in mdast" 354 ); 355 Ok(()) 356}