You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

markdown.rs 20KB

7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. extern crate tera;
  2. extern crate front_matter;
  3. extern crate templates;
  4. extern crate rendering;
  5. extern crate config;
  6. use std::collections::HashMap;
  7. use std::path::Path;
  8. use tera::Tera;
  9. use config::Config;
  10. use front_matter::InsertAnchor;
  11. use templates::GUTENBERG_TERA;
  12. use rendering::{RenderContext, render_content};
  13. #[test]
  14. fn can_do_render_content_simple() {
  15. let tera_ctx = Tera::default();
  16. let permalinks_ctx = HashMap::new();
  17. let config = Config::default();
  18. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  19. let res = render_content("hello", &context).unwrap();
  20. assert_eq!(res.body, "<p>hello</p>\n");
  21. }
  22. #[test]
  23. fn doesnt_highlight_code_block_with_highlighting_off() {
  24. let tera_ctx = Tera::default();
  25. let permalinks_ctx = HashMap::new();
  26. let mut config = Config::default();
  27. config.highlight_code = false;
  28. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  29. let res = render_content("```\n$ gutenberg server\n```", &context).unwrap();
  30. assert_eq!(
  31. res.body,
  32. "<pre><code>$ gutenberg server\n</code></pre>\n"
  33. );
  34. }
  35. #[test]
  36. fn can_highlight_code_block_no_lang() {
  37. let tera_ctx = Tera::default();
  38. let permalinks_ctx = HashMap::new();
  39. let config = Config::default();
  40. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  41. let res = render_content("```\n$ gutenberg server\n$ ping\n```", &context).unwrap();
  42. assert_eq!(
  43. res.body,
  44. "<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">$ gutenberg server\n</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">$ ping\n</span></pre>"
  45. );
  46. }
  47. #[test]
  48. fn can_highlight_code_block_with_lang() {
  49. let tera_ctx = Tera::default();
  50. let permalinks_ctx = HashMap::new();
  51. let config = Config::default();
  52. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  53. let res = render_content("```python\nlist.append(1)\n```", &context).unwrap();
  54. assert_eq!(
  55. res.body,
  56. "<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">list.</span><span style=\"background-color:#2b303b;color:#bf616a;\">append</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">(</span><span style=\"background-color:#2b303b;color:#d08770;\">1</span><span style=\"background-color:#2b303b;color:#c0c5ce;\">)\n</span></pre>"
  57. );
  58. }
  59. #[test]
  60. fn can_higlight_code_block_with_unknown_lang() {
  61. let tera_ctx = Tera::default();
  62. let permalinks_ctx = HashMap::new();
  63. let config = Config::default();
  64. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  65. let res = render_content("```yolo\nlist.append(1)\n```", &context).unwrap();
  66. // defaults to plain text
  67. assert_eq!(
  68. res.body,
  69. "<pre style=\"background-color:#2b303b\">\n<span style=\"background-color:#2b303b;color:#c0c5ce;\">list.append(1)\n</span></pre>"
  70. );
  71. }
  72. #[test]
  73. fn can_render_shortcode() {
  74. let permalinks_ctx = HashMap::new();
  75. let config = Config::default();
  76. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  77. let res = render_content(r#"
  78. Hello
  79. {{ youtube(id="ub36ffWAqgQ") }}
  80. "#, &context).unwrap();
  81. assert!(res.body.contains("<p>Hello</p>\n<div >"));
  82. assert!(res.body.contains(r#"<iframe src="https://www.youtube.com/embed/ub36ffWAqgQ""#));
  83. }
  84. #[test]
  85. fn can_render_shortcode_with_markdown_char_in_args_name() {
  86. let permalinks_ctx = HashMap::new();
  87. let config = Config::default();
  88. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  89. let input = vec![
  90. "name",
  91. "na_me",
  92. "n_a_me",
  93. "n1",
  94. ];
  95. for i in input {
  96. let res = render_content(&format!("{{{{ youtube(id=\"hey\", {}=1) }}}}", i), &context).unwrap();
  97. assert!(res.body.contains(r#"<iframe src="https://www.youtube.com/embed/hey""#));
  98. }
  99. }
  100. #[test]
  101. fn can_render_shortcode_with_markdown_char_in_args_value() {
  102. let permalinks_ctx = HashMap::new();
  103. let config = Config::default();
  104. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  105. let input = vec![
  106. "ub36ffWAqgQ-hey",
  107. "ub36ffWAqgQ_hey",
  108. "ub36ffWAqgQ_he_y",
  109. "ub36ffWAqgQ*hey",
  110. "ub36ffWAqgQ#hey",
  111. ];
  112. for i in input {
  113. let res = render_content(&format!("{{{{ youtube(id=\"{}\") }}}}", i), &context).unwrap();
  114. assert!(res.body.contains(&format!(r#"<iframe src="https://www.youtube.com/embed/{}""#, i)));
  115. }
  116. }
  117. #[test]
  118. fn can_render_body_shortcode_with_markdown_char_in_name() {
  119. let permalinks_ctx = HashMap::new();
  120. let mut tera = Tera::default();
  121. tera.extend(&GUTENBERG_TERA).unwrap();
  122. let input = vec![
  123. "quo_te",
  124. "qu_o_te",
  125. ];
  126. let config = Config::default();
  127. for i in input {
  128. tera.add_raw_template(&format!("shortcodes/{}.html", i), "<blockquote>{{ body }} - {{ author}}</blockquote>").unwrap();
  129. let context = RenderContext::new(&tera, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  130. let res = render_content(&format!("{{% {}(author=\"Bob\") %}}\nhey\n{{% end %}}", i), &context).unwrap();
  131. println!("{:?}", res);
  132. assert!(res.body.contains("<blockquote>hey - Bob</blockquote>"));
  133. }
  134. }
  135. #[test]
  136. fn can_render_body_shortcode_and_paragraph_after() {
  137. let permalinks_ctx = HashMap::new();
  138. let mut tera = Tera::default();
  139. tera.extend(&GUTENBERG_TERA).unwrap();
  140. let shortcode = "<p>{{ body }}</p>";
  141. let markdown_string = r#"
  142. {% figure() %}
  143. This is a figure caption.
  144. {% end %}
  145. Here is another paragraph.
  146. "#;
  147. let expected = "<p>This is a figure caption.</p>
  148. <p>Here is another paragraph.</p>
  149. ";
  150. tera.add_raw_template(&format!("shortcodes/{}.html", "figure"), shortcode).unwrap();
  151. let config = Config::default();
  152. let context = RenderContext::new(&tera, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  153. let res = render_content(markdown_string, &context).unwrap();
  154. println!("{:?}", res);
  155. assert_eq!(res.body, expected);
  156. }
  157. #[test]
  158. fn can_render_two_body_shortcode_and_paragraph_after_with_line_break_between() {
  159. let permalinks_ctx = HashMap::new();
  160. let mut tera = Tera::default();
  161. tera.extend(&GUTENBERG_TERA).unwrap();
  162. let shortcode = "<p>{{ body }}</p>";
  163. let markdown_string = r#"
  164. {% figure() %}
  165. This is a figure caption.
  166. {% end %}
  167. {% figure() %}
  168. This is a figure caption.
  169. {% end %}
  170. Here is another paragraph.
  171. "#;
  172. let expected = "<p>This is a figure caption.</p>
  173. <p>This is a figure caption.</p>
  174. <p>Here is another paragraph.</p>
  175. ";
  176. tera.add_raw_template(&format!("shortcodes/{}.html", "figure"), shortcode).unwrap();
  177. let config = Config::default();
  178. let context = RenderContext::new(&tera, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  179. let res = render_content(markdown_string, &context).unwrap();
  180. println!("{:?}", res);
  181. assert_eq!(res.body, expected);
  182. }
  183. #[test]
  184. fn can_render_several_shortcode_in_row() {
  185. let permalinks_ctx = HashMap::new();
  186. let config = Config::default();
  187. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  188. let res = render_content(r#"
  189. Hello
  190. {{ youtube(id="ub36ffWAqgQ") }}
  191. {{ youtube(id="ub36ffWAqgQ", autoplay=true) }}
  192. {{ vimeo(id="210073083") }}
  193. {{ streamable(id="c0ic") }}
  194. {{ gist(url="https://gist.github.com/Keats/32d26f699dcc13ebd41b") }}
  195. "#, &context).unwrap();
  196. assert!(res.body.contains("<p>Hello</p>\n<div >"));
  197. assert!(res.body.contains(r#"<iframe src="https://www.youtube.com/embed/ub36ffWAqgQ""#));
  198. assert!(res.body.contains(r#"<iframe src="https://www.youtube.com/embed/ub36ffWAqgQ?autoplay=1""#));
  199. assert!(res.body.contains(r#"<iframe src="https://www.streamable.com/e/c0ic""#));
  200. assert!(res.body.contains(r#"//player.vimeo.com/video/210073083""#));
  201. }
  202. #[test]
  203. fn doesnt_render_ignored_shortcodes() {
  204. let permalinks_ctx = HashMap::new();
  205. let mut config = Config::default();
  206. config.highlight_code = false;
  207. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  208. let res = render_content(r#"```{{/* youtube(id="w7Ft2ymGmfc") */}}```"#, &context).unwrap();
  209. assert_eq!(res.body, "<p><code>{{ youtube(id=&quot;w7Ft2ymGmfc&quot;) }}</code></p>\n");
  210. }
  211. #[test]
  212. fn can_render_shortcode_with_body() {
  213. let mut tera = Tera::default();
  214. tera.extend(&GUTENBERG_TERA).unwrap();
  215. tera.add_raw_template("shortcodes/quote.html", "<blockquote>{{ body }} - {{ author }}</blockquote>").unwrap();
  216. let permalinks_ctx = HashMap::new();
  217. let config = Config::default();
  218. let context = RenderContext::new(&tera, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  219. let res = render_content(r#"
  220. Hello
  221. {% quote(author="Keats") %}
  222. A quote
  223. {% end %}
  224. "#, &context).unwrap();
  225. assert_eq!(res.body, "<p>Hello</p>\n<blockquote>A quote - Keats</blockquote>\n");
  226. }
  227. #[test]
  228. fn errors_rendering_unknown_shortcode() {
  229. let tera_ctx = Tera::default();
  230. let permalinks_ctx = HashMap::new();
  231. let config = Config::default();
  232. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  233. let res = render_content("{{ hello(flash=true) }}", &context);
  234. assert!(res.is_err());
  235. }
  236. #[test]
  237. fn can_make_valid_relative_link() {
  238. let mut permalinks = HashMap::new();
  239. permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about".to_string());
  240. let tera_ctx = Tera::default();
  241. let config = Config::default();
  242. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks, Path::new("something"), InsertAnchor::None);
  243. let res = render_content(
  244. r#"[rel link](./pages/about.md), [abs link](https://vincent.is/about)"#,
  245. &context,
  246. ).unwrap();
  247. assert!(
  248. res.body.contains(r#"<p><a href="https://vincent.is/about">rel link</a>, <a href="https://vincent.is/about">abs link</a></p>"#)
  249. );
  250. }
  251. #[test]
  252. fn can_make_relative_links_with_anchors() {
  253. let mut permalinks = HashMap::new();
  254. permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about".to_string());
  255. let tera_ctx = Tera::default();
  256. let config = Config::default();
  257. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks, Path::new("something"), InsertAnchor::None);
  258. let res = render_content(r#"[rel link](./pages/about.md#cv)"#, &context).unwrap();
  259. assert!(
  260. res.body.contains(r#"<p><a href="https://vincent.is/about#cv">rel link</a></p>"#)
  261. );
  262. }
  263. #[test]
  264. fn errors_relative_link_inexistant() {
  265. let tera_ctx = Tera::default();
  266. let permalinks_ctx = HashMap::new();
  267. let config = Config::default();
  268. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  269. let res = render_content("[rel link](./pages/about.md)", &context);
  270. assert!(res.is_err());
  271. }
  272. #[test]
  273. fn can_add_id_to_headers() {
  274. let tera_ctx = Tera::default();
  275. let permalinks_ctx = HashMap::new();
  276. let config = Config::default();
  277. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  278. let res = render_content(r#"# Hello"#, &context).unwrap();
  279. assert_eq!(res.body, "<h1 id=\"hello\">Hello</h1>\n");
  280. }
  281. #[test]
  282. fn can_add_id_to_headers_same_slug() {
  283. let tera_ctx = Tera::default();
  284. let permalinks_ctx = HashMap::new();
  285. let config = Config::default();
  286. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  287. let res = render_content("# Hello\n# Hello", &context).unwrap();
  288. assert_eq!(res.body, "<h1 id=\"hello\">Hello</h1>\n<h1 id=\"hello-1\">Hello</h1>\n");
  289. }
  290. #[test]
  291. fn can_insert_anchor_left() {
  292. let permalinks_ctx = HashMap::new();
  293. let config = Config::default();
  294. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::Left);
  295. let res = render_content("# Hello", &context).unwrap();
  296. assert_eq!(
  297. res.body,
  298. "<h1 id=\"hello\"><a class=\"gutenberg-anchor\" href=\"#hello\" aria-label=\"Anchor link for: hello\">🔗</a>\nHello</h1>\n"
  299. );
  300. }
  301. #[test]
  302. fn can_insert_anchor_right() {
  303. let permalinks_ctx = HashMap::new();
  304. let config = Config::default();
  305. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::Right);
  306. let res = render_content("# Hello", &context).unwrap();
  307. assert_eq!(
  308. res.body,
  309. "<h1 id=\"hello\">Hello<a class=\"gutenberg-anchor\" href=\"#hello\" aria-label=\"Anchor link for: hello\">🔗</a>\n</h1>\n"
  310. );
  311. }
  312. // See https://github.com/Keats/gutenberg/issues/42
  313. #[test]
  314. fn can_insert_anchor_with_exclamation_mark() {
  315. let permalinks_ctx = HashMap::new();
  316. let config = Config::default();
  317. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::Left);
  318. let res = render_content("# Hello!", &context).unwrap();
  319. assert_eq!(
  320. res.body,
  321. "<h1 id=\"hello\"><a class=\"gutenberg-anchor\" href=\"#hello\" aria-label=\"Anchor link for: hello\">🔗</a>\nHello!</h1>\n"
  322. );
  323. }
  324. // See https://github.com/Keats/gutenberg/issues/53
  325. #[test]
  326. fn can_insert_anchor_with_link() {
  327. let permalinks_ctx = HashMap::new();
  328. let config = Config::default();
  329. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::Left);
  330. let res = render_content("## [Rust](https://rust-lang.org)", &context).unwrap();
  331. assert_eq!(
  332. res.body,
  333. "<h2 id=\"rust\"><a class=\"gutenberg-anchor\" href=\"#rust\" aria-label=\"Anchor link for: rust\">🔗</a>\n<a href=\"https://rust-lang.org\">Rust</a></h2>\n"
  334. );
  335. }
  336. #[test]
  337. fn can_insert_anchor_with_other_special_chars() {
  338. let permalinks_ctx = HashMap::new();
  339. let config = Config::default();
  340. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::Left);
  341. let res = render_content("# Hello*_()", &context).unwrap();
  342. assert_eq!(
  343. res.body,
  344. "<h1 id=\"hello\"><a class=\"gutenberg-anchor\" href=\"#hello\" aria-label=\"Anchor link for: hello\">🔗</a>\nHello*_()</h1>\n"
  345. );
  346. }
  347. #[test]
  348. fn can_make_toc() {
  349. let permalinks_ctx = HashMap::new();
  350. let config = Config::default();
  351. let context = RenderContext::new(
  352. &GUTENBERG_TERA,
  353. &config,
  354. "https://mysite.com/something",
  355. &permalinks_ctx,
  356. Path::new("something"),
  357. InsertAnchor::Left,
  358. );
  359. let res = render_content(r#"
  360. # Header 1
  361. ## Header 2
  362. ## Another Header 2
  363. ### Last one
  364. "#, &context).unwrap();
  365. let toc = res.toc;
  366. assert_eq!(toc.len(), 1);
  367. assert_eq!(toc[0].children.len(), 2);
  368. assert_eq!(toc[0].children[1].children.len(), 1);
  369. }
  370. #[test]
  371. fn can_understand_backtick_in_titles() {
  372. let permalinks_ctx = HashMap::new();
  373. let config = Config::default();
  374. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  375. let res = render_content("# `Hello`", &context).unwrap();
  376. assert_eq!(
  377. res.body,
  378. "<h1 id=\"hello\"><code>Hello</code></h1>\n"
  379. );
  380. }
  381. #[test]
  382. fn can_understand_backtick_in_paragraphs() {
  383. let permalinks_ctx = HashMap::new();
  384. let config = Config::default();
  385. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  386. let res = render_content("Hello `world`", &context).unwrap();
  387. assert_eq!(
  388. res.body,
  389. "<p>Hello <code>world</code></p>\n"
  390. );
  391. }
  392. // https://github.com/Keats/gutenberg/issues/297
  393. #[test]
  394. fn can_understand_links_in_header() {
  395. let permalinks_ctx = HashMap::new();
  396. let config = Config::default();
  397. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  398. let res = render_content("# [Rust](https://rust-lang.org)", &context).unwrap();
  399. assert_eq!(
  400. res.body,
  401. "<h1 id=\"rust\"><a href=\"https://rust-lang.org\">Rust</a></h1>\n"
  402. );
  403. }
  404. #[test]
  405. fn can_understand_link_with_title_in_header() {
  406. let permalinks_ctx = HashMap::new();
  407. let config = Config::default();
  408. let context = RenderContext::new(&GUTENBERG_TERA, &config, "", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  409. let res = render_content("# [Rust](https://rust-lang.org \"Rust homepage\")", &context).unwrap();
  410. assert_eq!(
  411. res.body,
  412. "<h1 id=\"rust\"><a href=\"https://rust-lang.org\" title=\"Rust homepage\">Rust</a></h1>\n"
  413. );
  414. }
  415. #[test]
  416. fn can_make_valid_relative_link_in_header() {
  417. let mut permalinks = HashMap::new();
  418. permalinks.insert("pages/about.md".to_string(), "https://vincent.is/about/".to_string());
  419. let tera_ctx = Tera::default();
  420. let config = Config::default();
  421. let context = RenderContext::new(&tera_ctx, &config, "", &permalinks, Path::new("something"), InsertAnchor::None);
  422. let res = render_content(
  423. r#" # [rel link](./pages/about.md)"#,
  424. &context,
  425. ).unwrap();
  426. assert_eq!(
  427. res.body,
  428. "<h1 id=\"rel-link\"><a href=\"https://vincent.is/about/\">rel link</a></h1>\n"
  429. );
  430. }
  431. #[test]
  432. fn can_make_permalinks_with_colocated_assets_for_link() {
  433. let permalinks_ctx = HashMap::new();
  434. let config = Config::default();
  435. let context = RenderContext::new(&GUTENBERG_TERA, &config, "https://vincent.is/about/", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  436. let res = render_content("[an image](image.jpg)", &context).unwrap();
  437. assert_eq!(
  438. res.body,
  439. "<p><a href=\"https://vincent.is/about/image.jpg\">an image</a></p>\n"
  440. );
  441. }
  442. #[test]
  443. fn can_make_permalinks_with_colocated_assets_for_image() {
  444. let permalinks_ctx = HashMap::new();
  445. let config = Config::default();
  446. let context = RenderContext::new(&GUTENBERG_TERA, &config, "https://vincent.is/about/", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  447. let res = render_content("![alt text](image.jpg)", &context).unwrap();
  448. assert_eq!(
  449. res.body,
  450. "<p><img src=\"https://vincent.is/about/image.jpg\" alt=\"alt text\" /></p>\n"
  451. );
  452. }
  453. #[test]
  454. fn markdown_doesnt_wrap_html_in_paragraph() {
  455. let permalinks_ctx = HashMap::new();
  456. let config = Config::default();
  457. let context = RenderContext::new(&GUTENBERG_TERA, &config, "https://vincent.is/about/", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  458. let res = render_content(r#"
  459. Some text
  460. <h1>Helo</h1>
  461. <div>
  462. <a href="mobx-flow.png">
  463. <img src="mobx-flow.png" alt="MobX flow">
  464. </a>
  465. </div>
  466. "#, &context).unwrap();
  467. assert_eq!(
  468. res.body,
  469. "<p>Some text</p>\n<h1>Helo</h1>\n<div>\n<a href=\"mobx-flow.png\">\n <img src=\"mobx-flow.png\" alt=\"MobX flow\">\n </a>\n</div>\n"
  470. );
  471. }
  472. #[test]
  473. fn can_validate_valid_external_links() {
  474. let permalinks_ctx = HashMap::new();
  475. let mut config = Config::default();
  476. config.check_external_links = true;
  477. let context = RenderContext::new(&GUTENBERG_TERA, &config, "https://vincent.is/about/", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  478. let res = render_content("[a link](http://google.com)", &context).unwrap();
  479. assert_eq!(
  480. res.body,
  481. "<p><a href=\"http://google.com\">a link</a></p>\n"
  482. );
  483. }
  484. #[test]
  485. fn can_show_error_message_for_invalid_external_links() {
  486. let permalinks_ctx = HashMap::new();
  487. let mut config = Config::default();
  488. config.check_external_links = true;
  489. let context = RenderContext::new(&GUTENBERG_TERA, &config, "https://vincent.is/about/", &permalinks_ctx, Path::new("something"), InsertAnchor::None);
  490. let res = render_content("[a link](http://google.comy)", &context);
  491. assert!(res.is_err());
  492. let err = res.unwrap_err();
  493. assert!(err.description().contains("Link http://google.comy is not valid"));
  494. }