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.
 
 
 

1533 lines
44 KiB

  1. //
  2. // Blackfriday Markdown Processor
  3. // Available at http://github.com/russross/blackfriday
  4. //
  5. // Copyright © 2011 Russ Ross <russ@russross.com>.
  6. // Distributed under the Simplified BSD License.
  7. // See README.md for details.
  8. //
  9. //
  10. // Unit tests for block parsing
  11. //
  12. package blackfriday
  13. import (
  14. "strings"
  15. "testing"
  16. )
  17. func runMarkdownBlockWithRenderer(input string, extensions int, renderer Renderer) string {
  18. return string(Markdown([]byte(input), renderer, extensions))
  19. }
  20. func runMarkdownBlock(input string, extensions int) string {
  21. htmlFlags := 0
  22. htmlFlags |= HTML_USE_XHTML
  23. renderer := HtmlRenderer(htmlFlags, "", "")
  24. return runMarkdownBlockWithRenderer(input, extensions, renderer)
  25. }
  26. func runnerWithRendererParameters(parameters HtmlRendererParameters) func(string, int) string {
  27. return func(input string, extensions int) string {
  28. htmlFlags := 0
  29. htmlFlags |= HTML_USE_XHTML
  30. renderer := HtmlRendererWithParameters(htmlFlags, "", "", parameters)
  31. return runMarkdownBlockWithRenderer(input, extensions, renderer)
  32. }
  33. }
  34. func doTestsBlock(t *testing.T, tests []string, extensions int) {
  35. doTestsBlockWithRunner(t, tests, extensions, runMarkdownBlock)
  36. }
  37. func doTestsBlockWithRunner(t *testing.T, tests []string, extensions int, runner func(string, int) string) {
  38. // catch and report panics
  39. var candidate string
  40. defer func() {
  41. if err := recover(); err != nil {
  42. t.Errorf("\npanic while processing [%#v]: %s\n", candidate, err)
  43. }
  44. }()
  45. for i := 0; i+1 < len(tests); i += 2 {
  46. input := tests[i]
  47. candidate = input
  48. expected := tests[i+1]
  49. actual := runner(candidate, extensions)
  50. if actual != expected {
  51. t.Errorf("\nInput [%#v]\nExpected[%#v]\nActual [%#v]",
  52. candidate, expected, actual)
  53. }
  54. // now test every substring to stress test bounds checking
  55. if !testing.Short() {
  56. for start := 0; start < len(input); start++ {
  57. for end := start + 1; end <= len(input); end++ {
  58. candidate = input[start:end]
  59. _ = runMarkdownBlock(candidate, extensions)
  60. }
  61. }
  62. }
  63. }
  64. }
  65. func TestPrefixHeaderNoExtensions(t *testing.T) {
  66. var tests = []string{
  67. "# Header 1\n",
  68. "<h1>Header 1</h1>\n",
  69. "## Header 2\n",
  70. "<h2>Header 2</h2>\n",
  71. "### Header 3\n",
  72. "<h3>Header 3</h3>\n",
  73. "#### Header 4\n",
  74. "<h4>Header 4</h4>\n",
  75. "##### Header 5\n",
  76. "<h5>Header 5</h5>\n",
  77. "###### Header 6\n",
  78. "<h6>Header 6</h6>\n",
  79. "####### Header 7\n",
  80. "<h6># Header 7</h6>\n",
  81. "#Header 1\n",
  82. "<h1>Header 1</h1>\n",
  83. "##Header 2\n",
  84. "<h2>Header 2</h2>\n",
  85. "###Header 3\n",
  86. "<h3>Header 3</h3>\n",
  87. "####Header 4\n",
  88. "<h4>Header 4</h4>\n",
  89. "#####Header 5\n",
  90. "<h5>Header 5</h5>\n",
  91. "######Header 6\n",
  92. "<h6>Header 6</h6>\n",
  93. "#######Header 7\n",
  94. "<h6>#Header 7</h6>\n",
  95. "Hello\n# Header 1\nGoodbye\n",
  96. "<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
  97. "* List\n# Header\n* List\n",
  98. "<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  99. "* List\n#Header\n* List\n",
  100. "<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  101. "* List\n * Nested list\n # Nested header\n",
  102. "<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
  103. "<h1>Nested header</h1></li>\n</ul></li>\n</ul>\n",
  104. "#Header 1 \\#\n",
  105. "<h1>Header 1 #</h1>\n",
  106. "#Header 1 \\# foo\n",
  107. "<h1>Header 1 # foo</h1>\n",
  108. "#Header 1 #\\##\n",
  109. "<h1>Header 1 ##</h1>\n",
  110. }
  111. doTestsBlock(t, tests, 0)
  112. }
  113. func TestPrefixHeaderSpaceExtension(t *testing.T) {
  114. var tests = []string{
  115. "# Header 1\n",
  116. "<h1>Header 1</h1>\n",
  117. "## Header 2\n",
  118. "<h2>Header 2</h2>\n",
  119. "### Header 3\n",
  120. "<h3>Header 3</h3>\n",
  121. "#### Header 4\n",
  122. "<h4>Header 4</h4>\n",
  123. "##### Header 5\n",
  124. "<h5>Header 5</h5>\n",
  125. "###### Header 6\n",
  126. "<h6>Header 6</h6>\n",
  127. "####### Header 7\n",
  128. "<p>####### Header 7</p>\n",
  129. "#Header 1\n",
  130. "<p>#Header 1</p>\n",
  131. "##Header 2\n",
  132. "<p>##Header 2</p>\n",
  133. "###Header 3\n",
  134. "<p>###Header 3</p>\n",
  135. "####Header 4\n",
  136. "<p>####Header 4</p>\n",
  137. "#####Header 5\n",
  138. "<p>#####Header 5</p>\n",
  139. "######Header 6\n",
  140. "<p>######Header 6</p>\n",
  141. "#######Header 7\n",
  142. "<p>#######Header 7</p>\n",
  143. "Hello\n# Header 1\nGoodbye\n",
  144. "<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
  145. "* List\n# Header\n* List\n",
  146. "<ul>\n<li><p>List</p>\n\n<h1>Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  147. "* List\n#Header\n* List\n",
  148. "<ul>\n<li>List\n#Header</li>\n<li>List</li>\n</ul>\n",
  149. "* List\n * Nested list\n # Nested header\n",
  150. "<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
  151. "<h1>Nested header</h1></li>\n</ul></li>\n</ul>\n",
  152. }
  153. doTestsBlock(t, tests, EXTENSION_SPACE_HEADERS)
  154. }
  155. func TestPrefixHeaderIdExtension(t *testing.T) {
  156. var tests = []string{
  157. "# Header 1 {#someid}\n",
  158. "<h1 id=\"someid\">Header 1</h1>\n",
  159. "# Header 1 {#someid} \n",
  160. "<h1 id=\"someid\">Header 1</h1>\n",
  161. "# Header 1 {#someid}\n",
  162. "<h1 id=\"someid\">Header 1</h1>\n",
  163. "# Header 1 {#someid\n",
  164. "<h1>Header 1 {#someid</h1>\n",
  165. "# Header 1 {#someid\n",
  166. "<h1>Header 1 {#someid</h1>\n",
  167. "# Header 1 {#someid}}\n",
  168. "<h1 id=\"someid\">Header 1</h1>\n\n<p>}</p>\n",
  169. "## Header 2 {#someid}\n",
  170. "<h2 id=\"someid\">Header 2</h2>\n",
  171. "### Header 3 {#someid}\n",
  172. "<h3 id=\"someid\">Header 3</h3>\n",
  173. "#### Header 4 {#someid}\n",
  174. "<h4 id=\"someid\">Header 4</h4>\n",
  175. "##### Header 5 {#someid}\n",
  176. "<h5 id=\"someid\">Header 5</h5>\n",
  177. "###### Header 6 {#someid}\n",
  178. "<h6 id=\"someid\">Header 6</h6>\n",
  179. "####### Header 7 {#someid}\n",
  180. "<h6 id=\"someid\"># Header 7</h6>\n",
  181. "# Header 1 # {#someid}\n",
  182. "<h1 id=\"someid\">Header 1</h1>\n",
  183. "## Header 2 ## {#someid}\n",
  184. "<h2 id=\"someid\">Header 2</h2>\n",
  185. "Hello\n# Header 1\nGoodbye\n",
  186. "<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n",
  187. "* List\n# Header {#someid}\n* List\n",
  188. "<ul>\n<li><p>List</p>\n\n<h1 id=\"someid\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  189. "* List\n#Header {#someid}\n* List\n",
  190. "<ul>\n<li><p>List</p>\n\n<h1 id=\"someid\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  191. "* List\n * Nested list\n # Nested header {#someid}\n",
  192. "<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
  193. "<h1 id=\"someid\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
  194. }
  195. doTestsBlock(t, tests, EXTENSION_HEADER_IDS)
  196. }
  197. func TestPrefixHeaderIdExtensionWithPrefixAndSuffix(t *testing.T) {
  198. var tests = []string{
  199. "# header 1 {#someid}\n",
  200. "<h1 id=\"PRE:someid:POST\">header 1</h1>\n",
  201. "## header 2 {#someid}\n",
  202. "<h2 id=\"PRE:someid:POST\">header 2</h2>\n",
  203. "### header 3 {#someid}\n",
  204. "<h3 id=\"PRE:someid:POST\">header 3</h3>\n",
  205. "#### header 4 {#someid}\n",
  206. "<h4 id=\"PRE:someid:POST\">header 4</h4>\n",
  207. "##### header 5 {#someid}\n",
  208. "<h5 id=\"PRE:someid:POST\">header 5</h5>\n",
  209. "###### header 6 {#someid}\n",
  210. "<h6 id=\"PRE:someid:POST\">header 6</h6>\n",
  211. "####### header 7 {#someid}\n",
  212. "<h6 id=\"PRE:someid:POST\"># header 7</h6>\n",
  213. "# header 1 # {#someid}\n",
  214. "<h1 id=\"PRE:someid:POST\">header 1</h1>\n",
  215. "## header 2 ## {#someid}\n",
  216. "<h2 id=\"PRE:someid:POST\">header 2</h2>\n",
  217. "* List\n# Header {#someid}\n* List\n",
  218. "<ul>\n<li><p>List</p>\n\n<h1 id=\"PRE:someid:POST\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  219. "* List\n#Header {#someid}\n* List\n",
  220. "<ul>\n<li><p>List</p>\n\n<h1 id=\"PRE:someid:POST\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  221. "* List\n * Nested list\n # Nested header {#someid}\n",
  222. "<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
  223. "<h1 id=\"PRE:someid:POST\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
  224. }
  225. parameters := HtmlRendererParameters{
  226. HeaderIDPrefix: "PRE:",
  227. HeaderIDSuffix: ":POST",
  228. }
  229. doTestsBlockWithRunner(t, tests, EXTENSION_HEADER_IDS, runnerWithRendererParameters(parameters))
  230. }
  231. func TestPrefixAutoHeaderIdExtension(t *testing.T) {
  232. var tests = []string{
  233. "# Header 1\n",
  234. "<h1 id=\"header-1\">Header 1</h1>\n",
  235. "# Header 1 \n",
  236. "<h1 id=\"header-1\">Header 1</h1>\n",
  237. "## Header 2\n",
  238. "<h2 id=\"header-2\">Header 2</h2>\n",
  239. "### Header 3\n",
  240. "<h3 id=\"header-3\">Header 3</h3>\n",
  241. "#### Header 4\n",
  242. "<h4 id=\"header-4\">Header 4</h4>\n",
  243. "##### Header 5\n",
  244. "<h5 id=\"header-5\">Header 5</h5>\n",
  245. "###### Header 6\n",
  246. "<h6 id=\"header-6\">Header 6</h6>\n",
  247. "####### Header 7\n",
  248. "<h6 id=\"header-7\"># Header 7</h6>\n",
  249. "Hello\n# Header 1\nGoodbye\n",
  250. "<p>Hello</p>\n\n<h1 id=\"header-1\">Header 1</h1>\n\n<p>Goodbye</p>\n",
  251. "* List\n# Header\n* List\n",
  252. "<ul>\n<li><p>List</p>\n\n<h1 id=\"header\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  253. "* List\n#Header\n* List\n",
  254. "<ul>\n<li><p>List</p>\n\n<h1 id=\"header\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  255. "* List\n * Nested list\n # Nested header\n",
  256. "<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
  257. "<h1 id=\"nested-header\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
  258. "# Header\n\n# Header\n",
  259. "<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n",
  260. "# Header 1\n\n# Header 1",
  261. "<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
  262. "# Header\n\n# Header 1\n\n# Header\n\n# Header",
  263. "<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header</h1>\n\n<h1 id=\"header-1-2\">Header</h1>\n",
  264. }
  265. doTestsBlock(t, tests, EXTENSION_AUTO_HEADER_IDS)
  266. }
  267. func TestPrefixAutoHeaderIdExtensionWithPrefixAndSuffix(t *testing.T) {
  268. var tests = []string{
  269. "# Header 1\n",
  270. "<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n",
  271. "# Header 1 \n",
  272. "<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n",
  273. "## Header 2\n",
  274. "<h2 id=\"PRE:header-2:POST\">Header 2</h2>\n",
  275. "### Header 3\n",
  276. "<h3 id=\"PRE:header-3:POST\">Header 3</h3>\n",
  277. "#### Header 4\n",
  278. "<h4 id=\"PRE:header-4:POST\">Header 4</h4>\n",
  279. "##### Header 5\n",
  280. "<h5 id=\"PRE:header-5:POST\">Header 5</h5>\n",
  281. "###### Header 6\n",
  282. "<h6 id=\"PRE:header-6:POST\">Header 6</h6>\n",
  283. "####### Header 7\n",
  284. "<h6 id=\"PRE:header-7:POST\"># Header 7</h6>\n",
  285. "Hello\n# Header 1\nGoodbye\n",
  286. "<p>Hello</p>\n\n<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<p>Goodbye</p>\n",
  287. "* List\n# Header\n* List\n",
  288. "<ul>\n<li><p>List</p>\n\n<h1 id=\"PRE:header:POST\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  289. "* List\n#Header\n* List\n",
  290. "<ul>\n<li><p>List</p>\n\n<h1 id=\"PRE:header:POST\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
  291. "* List\n * Nested list\n # Nested header\n",
  292. "<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
  293. "<h1 id=\"PRE:nested-header:POST\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
  294. "# Header\n\n# Header\n",
  295. "<h1 id=\"PRE:header:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1:POST\">Header</h1>\n",
  296. "# Header 1\n\n# Header 1",
  297. "<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<h1 id=\"PRE:header-1-1:POST\">Header 1</h1>\n",
  298. "# Header\n\n# Header 1\n\n# Header\n\n# Header",
  299. "<h1 id=\"PRE:header:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<h1 id=\"PRE:header-1-1:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1-2:POST\">Header</h1>\n",
  300. }
  301. parameters := HtmlRendererParameters{
  302. HeaderIDPrefix: "PRE:",
  303. HeaderIDSuffix: ":POST",
  304. }
  305. doTestsBlockWithRunner(t, tests, EXTENSION_AUTO_HEADER_IDS, runnerWithRendererParameters(parameters))
  306. }
  307. func TestPrefixMultipleHeaderExtensions(t *testing.T) {
  308. var tests = []string{
  309. "# Header\n\n# Header {#header}\n\n# Header 1",
  310. "<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
  311. }
  312. doTestsBlock(t, tests, EXTENSION_AUTO_HEADER_IDS|EXTENSION_HEADER_IDS)
  313. }
  314. func TestUnderlineHeaders(t *testing.T) {
  315. var tests = []string{
  316. "Header 1\n========\n",
  317. "<h1>Header 1</h1>\n",
  318. "Header 2\n--------\n",
  319. "<h2>Header 2</h2>\n",
  320. "A\n=\n",
  321. "<h1>A</h1>\n",
  322. "B\n-\n",
  323. "<h2>B</h2>\n",
  324. "Paragraph\nHeader\n=\n",
  325. "<p>Paragraph</p>\n\n<h1>Header</h1>\n",
  326. "Header\n===\nParagraph\n",
  327. "<h1>Header</h1>\n\n<p>Paragraph</p>\n",
  328. "Header\n===\nAnother header\n---\n",
  329. "<h1>Header</h1>\n\n<h2>Another header</h2>\n",
  330. " Header\n======\n",
  331. "<h1>Header</h1>\n",
  332. " Code\n========\n",
  333. "<pre><code>Code\n</code></pre>\n\n<p>========</p>\n",
  334. "Header with *inline*\n=====\n",
  335. "<h1>Header with <em>inline</em></h1>\n",
  336. "* List\n * Sublist\n Not a header\n ------\n",
  337. "<ul>\n<li>List\n\n<ul>\n<li>Sublist\nNot a header\n------</li>\n</ul></li>\n</ul>\n",
  338. "Paragraph\n\n\n\n\nHeader\n===\n",
  339. "<p>Paragraph</p>\n\n<h1>Header</h1>\n",
  340. "Trailing space \n==== \n\n",
  341. "<h1>Trailing space</h1>\n",
  342. "Trailing spaces\n==== \n\n",
  343. "<h1>Trailing spaces</h1>\n",
  344. "Double underline\n=====\n=====\n",
  345. "<h1>Double underline</h1>\n\n<p>=====</p>\n",
  346. }
  347. doTestsBlock(t, tests, 0)
  348. }
  349. func TestUnderlineHeadersAutoIDs(t *testing.T) {
  350. var tests = []string{
  351. "Header 1\n========\n",
  352. "<h1 id=\"header-1\">Header 1</h1>\n",
  353. "Header 2\n--------\n",
  354. "<h2 id=\"header-2\">Header 2</h2>\n",
  355. "A\n=\n",
  356. "<h1 id=\"a\">A</h1>\n",
  357. "B\n-\n",
  358. "<h2 id=\"b\">B</h2>\n",
  359. "Paragraph\nHeader\n=\n",
  360. "<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
  361. "Header\n===\nParagraph\n",
  362. "<h1 id=\"header\">Header</h1>\n\n<p>Paragraph</p>\n",
  363. "Header\n===\nAnother header\n---\n",
  364. "<h1 id=\"header\">Header</h1>\n\n<h2 id=\"another-header\">Another header</h2>\n",
  365. " Header\n======\n",
  366. "<h1 id=\"header\">Header</h1>\n",
  367. "Header with *inline*\n=====\n",
  368. "<h1 id=\"header-with-inline\">Header with <em>inline</em></h1>\n",
  369. "Paragraph\n\n\n\n\nHeader\n===\n",
  370. "<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
  371. "Trailing space \n==== \n\n",
  372. "<h1 id=\"trailing-space\">Trailing space</h1>\n",
  373. "Trailing spaces\n==== \n\n",
  374. "<h1 id=\"trailing-spaces\">Trailing spaces</h1>\n",
  375. "Double underline\n=====\n=====\n",
  376. "<h1 id=\"double-underline\">Double underline</h1>\n\n<p>=====</p>\n",
  377. "Header\n======\n\nHeader\n======\n",
  378. "<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n",
  379. "Header 1\n========\n\nHeader 1\n========\n",
  380. "<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n",
  381. }
  382. doTestsBlock(t, tests, EXTENSION_AUTO_HEADER_IDS)
  383. }
  384. func TestHorizontalRule(t *testing.T) {
  385. var tests = []string{
  386. "-\n",
  387. "<p>-</p>\n",
  388. "--\n",
  389. "<p>--</p>\n",
  390. "---\n",
  391. "<hr />\n",
  392. "----\n",
  393. "<hr />\n",
  394. "*\n",
  395. "<p>*</p>\n",
  396. "**\n",
  397. "<p>**</p>\n",
  398. "***\n",
  399. "<hr />\n",
  400. "****\n",
  401. "<hr />\n",
  402. "_\n",
  403. "<p>_</p>\n",
  404. "__\n",
  405. "<p>__</p>\n",
  406. "___\n",
  407. "<hr />\n",
  408. "____\n",
  409. "<hr />\n",
  410. "-*-\n",
  411. "<p>-*-</p>\n",
  412. "- - -\n",
  413. "<hr />\n",
  414. "* * *\n",
  415. "<hr />\n",
  416. "_ _ _\n",
  417. "<hr />\n",
  418. "-----*\n",
  419. "<p>-----*</p>\n",
  420. " ------ \n",
  421. "<hr />\n",
  422. "Hello\n***\n",
  423. "<p>Hello</p>\n\n<hr />\n",
  424. "---\n***\n___\n",
  425. "<hr />\n\n<hr />\n\n<hr />\n",
  426. }
  427. doTestsBlock(t, tests, 0)
  428. }
  429. func TestUnorderedList(t *testing.T) {
  430. var tests = []string{
  431. "* Hello\n",
  432. "<ul>\n<li>Hello</li>\n</ul>\n",
  433. "* Yin\n* Yang\n",
  434. "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
  435. "* Ting\n* Bong\n* Goo\n",
  436. "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
  437. "* Yin\n\n* Yang\n",
  438. "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
  439. "* Ting\n\n* Bong\n* Goo\n",
  440. "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
  441. "+ Hello\n",
  442. "<ul>\n<li>Hello</li>\n</ul>\n",
  443. "+ Yin\n+ Yang\n",
  444. "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
  445. "+ Ting\n+ Bong\n+ Goo\n",
  446. "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
  447. "+ Yin\n\n+ Yang\n",
  448. "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
  449. "+ Ting\n\n+ Bong\n+ Goo\n",
  450. "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
  451. "- Hello\n",
  452. "<ul>\n<li>Hello</li>\n</ul>\n",
  453. "- Yin\n- Yang\n",
  454. "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
  455. "- Ting\n- Bong\n- Goo\n",
  456. "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
  457. "- Yin\n\n- Yang\n",
  458. "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
  459. "- Ting\n\n- Bong\n- Goo\n",
  460. "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
  461. "*Hello\n",
  462. "<p>*Hello</p>\n",
  463. "* Hello \n",
  464. "<ul>\n<li>Hello</li>\n</ul>\n",
  465. "* Hello \n Next line \n",
  466. "<ul>\n<li>Hello\nNext line</li>\n</ul>\n",
  467. "Paragraph\n* No linebreak\n",
  468. "<p>Paragraph\n* No linebreak</p>\n",
  469. "Paragraph\n\n* Linebreak\n",
  470. "<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n",
  471. "* List\n * Nested list\n",
  472. "<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
  473. "* List\n\n * Nested list\n",
  474. "<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
  475. "* List\n Second line\n\n + Nested\n",
  476. "<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n",
  477. "* List\n + Nested\n\n Continued\n",
  478. "<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n",
  479. "* List\n * shallow indent\n",
  480. "<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n",
  481. "* List\n" +
  482. " * shallow indent\n" +
  483. " * part of second list\n" +
  484. " * still second\n" +
  485. " * almost there\n" +
  486. " * third level\n",
  487. "<ul>\n" +
  488. "<li>List\n\n" +
  489. "<ul>\n" +
  490. "<li>shallow indent</li>\n" +
  491. "<li>part of second list</li>\n" +
  492. "<li>still second</li>\n" +
  493. "<li>almost there\n\n" +
  494. "<ul>\n" +
  495. "<li>third level</li>\n" +
  496. "</ul></li>\n" +
  497. "</ul></li>\n" +
  498. "</ul>\n",
  499. "* List\n extra indent, same paragraph\n",
  500. "<ul>\n<li>List\n extra indent, same paragraph</li>\n</ul>\n",
  501. "* List\n\n code block\n",
  502. "<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n",
  503. "* List\n\n code block with spaces\n",
  504. "<ul>\n<li><p>List</p>\n\n<pre><code> code block with spaces\n</code></pre></li>\n</ul>\n",
  505. "* List\n\n * sublist\n\n normal text\n\n * another sublist\n",
  506. "<ul>\n<li><p>List</p>\n\n<ul>\n<li>sublist</li>\n</ul>\n\n<p>normal text</p>\n\n<ul>\n<li>another sublist</li>\n</ul></li>\n</ul>\n",
  507. }
  508. doTestsBlock(t, tests, 0)
  509. }
  510. func TestOrderedList(t *testing.T) {
  511. var tests = []string{
  512. "1. Hello\n",
  513. "<ol>\n<li>Hello</li>\n</ol>\n",
  514. "1. Yin\n2. Yang\n",
  515. "<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n",
  516. "1. Ting\n2. Bong\n3. Goo\n",
  517. "<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n",
  518. "1. Yin\n\n2. Yang\n",
  519. "<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n",
  520. "1. Ting\n\n2. Bong\n3. Goo\n",
  521. "<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n",
  522. "1 Hello\n",
  523. "<p>1 Hello</p>\n",
  524. "1.Hello\n",
  525. "<p>1.Hello</p>\n",
  526. "1. Hello \n",
  527. "<ol>\n<li>Hello</li>\n</ol>\n",
  528. "1. Hello \n Next line \n",
  529. "<ol>\n<li>Hello\nNext line</li>\n</ol>\n",
  530. "Paragraph\n1. No linebreak\n",
  531. "<p>Paragraph\n1. No linebreak</p>\n",
  532. "Paragraph\n\n1. Linebreak\n",
  533. "<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n",
  534. "1. List\n 1. Nested list\n",
  535. "<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
  536. "1. List\n\n 1. Nested list\n",
  537. "<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
  538. "1. List\n Second line\n\n 1. Nested\n",
  539. "<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n",
  540. "1. List\n 1. Nested\n\n Continued\n",
  541. "<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n",
  542. "1. List\n 1. shallow indent\n",
  543. "<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n",
  544. "1. List\n" +
  545. " 1. shallow indent\n" +
  546. " 2. part of second list\n" +
  547. " 3. still second\n" +
  548. " 4. almost there\n" +
  549. " 1. third level\n",
  550. "<ol>\n" +
  551. "<li>List\n\n" +
  552. "<ol>\n" +
  553. "<li>shallow indent</li>\n" +
  554. "<li>part of second list</li>\n" +
  555. "<li>still second</li>\n" +
  556. "<li>almost there\n\n" +
  557. "<ol>\n" +
  558. "<li>third level</li>\n" +
  559. "</ol></li>\n" +
  560. "</ol></li>\n" +
  561. "</ol>\n",
  562. "1. List\n extra indent, same paragraph\n",
  563. "<ol>\n<li>List\n extra indent, same paragraph</li>\n</ol>\n",
  564. "1. List\n\n code block\n",
  565. "<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n",
  566. "1. List\n\n code block with spaces\n",
  567. "<ol>\n<li><p>List</p>\n\n<pre><code> code block with spaces\n</code></pre></li>\n</ol>\n",
  568. "1. List\n * Mixted list\n",
  569. "<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n",
  570. "1. List\n * Mixed list\n",
  571. "<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n",
  572. "* Start with unordered\n 1. Ordered\n",
  573. "<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
  574. "* Start with unordered\n 1. Ordered\n",
  575. "<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
  576. "1. numbers\n1. are ignored\n",
  577. "<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n",
  578. }
  579. doTestsBlock(t, tests, 0)
  580. }
  581. func TestDefinitionList(t *testing.T) {
  582. var tests = []string{
  583. "Term 1\n: Definition a\n",
  584. "<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
  585. "Term 1\n: Definition a \n",
  586. "<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
  587. "Term 1\n: Definition a\n: Definition b\n",
  588. "<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n<dd>Definition b</dd>\n</dl>\n",
  589. "Term 1\n: Definition a\n\nTerm 2\n: Definition b\n",
  590. "<dl>\n" +
  591. "<dt>Term 1</dt>\n" +
  592. "<dd>Definition a</dd>\n" +
  593. "<dt>Term 2</dt>\n" +
  594. "<dd>Definition b</dd>\n" +
  595. "</dl>\n",
  596. "Term 1\n: Definition a\n\nTerm 2\n: Definition b\n\nTerm 3\n: Definition c\n",
  597. "<dl>\n" +
  598. "<dt>Term 1</dt>\n" +
  599. "<dd>Definition a</dd>\n" +
  600. "<dt>Term 2</dt>\n" +
  601. "<dd>Definition b</dd>\n" +
  602. "<dt>Term 3</dt>\n" +
  603. "<dd>Definition c</dd>\n" +
  604. "</dl>\n",
  605. "Term 1\n: Definition a\n: Definition b\n\nTerm 2\n: Definition c\n",
  606. "<dl>\n" +
  607. "<dt>Term 1</dt>\n" +
  608. "<dd>Definition a</dd>\n" +
  609. "<dd>Definition b</dd>\n" +
  610. "<dt>Term 2</dt>\n" +
  611. "<dd>Definition c</dd>\n" +
  612. "</dl>\n",
  613. "Term 1\n\n: Definition a\n\nTerm 2\n\n: Definition b\n",
  614. "<dl>\n" +
  615. "<dt>Term 1</dt>\n" +
  616. "<dd><p>Definition a</p></dd>\n" +
  617. "<dt>Term 2</dt>\n" +
  618. "<dd><p>Definition b</p></dd>\n" +
  619. "</dl>\n",
  620. "Term 1\n\n: Definition a\n\n: Definition b\n\nTerm 2\n\n: Definition c\n",
  621. "<dl>\n" +
  622. "<dt>Term 1</dt>\n" +
  623. "<dd><p>Definition a</p></dd>\n" +
  624. "<dd><p>Definition b</p></dd>\n" +
  625. "<dt>Term 2</dt>\n" +
  626. "<dd><p>Definition c</p></dd>\n" +
  627. "</dl>\n",
  628. "Term 1\n: Definition a\nNext line\n",
  629. "<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
  630. "Term 1\n: Definition a\n Next line\n",
  631. "<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
  632. "Term 1\n: Definition a \n Next line \n",
  633. "<dl>\n<dt>Term 1</dt>\n<dd>Definition a\nNext line</dd>\n</dl>\n",
  634. "Term 1\n: Definition a\nNext line\n\nTerm 2\n: Definition b",
  635. "<dl>\n" +
  636. "<dt>Term 1</dt>\n" +
  637. "<dd>Definition a\nNext line</dd>\n" +
  638. "<dt>Term 2</dt>\n" +
  639. "<dd>Definition b</dd>\n" +
  640. "</dl>\n",
  641. "Term 1\n: Definition a\n",
  642. "<dl>\n<dt>Term 1</dt>\n<dd>Definition a</dd>\n</dl>\n",
  643. "Term 1\n:Definition a\n",
  644. "<p>Term 1\n:Definition a</p>\n",
  645. "Term 1\n\n: Definition a\n\nTerm 2\n\n: Definition b\n\nText 1",
  646. "<dl>\n" +
  647. "<dt>Term 1</dt>\n" +
  648. "<dd><p>Definition a</p></dd>\n" +
  649. "<dt>Term 2</dt>\n" +
  650. "<dd><p>Definition b</p></dd>\n" +
  651. "</dl>\n" +
  652. "\n<p>Text 1</p>\n",
  653. "Term 1\n\n: Definition a\n\nText 1\n\nTerm 2\n\n: Definition b\n\nText 2",
  654. "<dl>\n" +
  655. "<dt>Term 1</dt>\n" +
  656. "<dd><p>Definition a</p></dd>\n" +
  657. "</dl>\n" +
  658. "\n<p>Text 1</p>\n" +
  659. "\n<dl>\n" +
  660. "<dt>Term 2</dt>\n" +
  661. "<dd><p>Definition b</p></dd>\n" +
  662. "</dl>\n" +
  663. "\n<p>Text 2</p>\n",
  664. }
  665. doTestsBlock(t, tests, EXTENSION_DEFINITION_LISTS)
  666. }
  667. func TestPreformattedHtml(t *testing.T) {
  668. var tests = []string{
  669. "<div></div>\n",
  670. "<div></div>\n",
  671. "<div>\n</div>\n",
  672. "<div>\n</div>\n",
  673. "<div>\n</div>\nParagraph\n",
  674. "<p><div>\n</div>\nParagraph</p>\n",
  675. "<div class=\"foo\">\n</div>\n",
  676. "<div class=\"foo\">\n</div>\n",
  677. "<div>\nAnything here\n</div>\n",
  678. "<div>\nAnything here\n</div>\n",
  679. "<div>\n Anything here\n</div>\n",
  680. "<div>\n Anything here\n</div>\n",
  681. "<div>\nAnything here\n </div>\n",
  682. "<div>\nAnything here\n </div>\n",
  683. "<div>\nThis is *not* &proceessed\n</div>\n",
  684. "<div>\nThis is *not* &proceessed\n</div>\n",
  685. "<faketag>\n Something\n</faketag>\n",
  686. "<p><faketag>\n Something\n</faketag></p>\n",
  687. "<div>\n Something here\n</divv>\n",
  688. "<p><div>\n Something here\n</divv></p>\n",
  689. "Paragraph\n<div>\nHere? >&<\n</div>\n",
  690. "<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div></p>\n",
  691. "Paragraph\n\n<div>\nHow about here? >&<\n</div>\n",
  692. "<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n",
  693. "Paragraph\n<div>\nHere? >&<\n</div>\nAnd here?\n",
  694. "<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div>\nAnd here?</p>\n",
  695. "Paragraph\n\n<div>\nHow about here? >&<\n</div>\nAnd here?\n",
  696. "<p>Paragraph</p>\n\n<p><div>\nHow about here? &gt;&amp;&lt;\n</div>\nAnd here?</p>\n",
  697. "Paragraph\n<div>\nHere? >&<\n</div>\n\nAnd here?\n",
  698. "<p>Paragraph\n<div>\nHere? &gt;&amp;&lt;\n</div></p>\n\n<p>And here?</p>\n",
  699. "Paragraph\n\n<div>\nHow about here? >&<\n</div>\n\nAnd here?\n",
  700. "<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
  701. }
  702. doTestsBlock(t, tests, 0)
  703. }
  704. func TestPreformattedHtmlLax(t *testing.T) {
  705. var tests = []string{
  706. "Paragraph\n<div>\nHere? >&<\n</div>\n",
  707. "<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n",
  708. "Paragraph\n\n<div>\nHow about here? >&<\n</div>\n",
  709. "<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n",
  710. "Paragraph\n<div>\nHere? >&<\n</div>\nAnd here?\n",
  711. "<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n\n<p>And here?</p>\n",
  712. "Paragraph\n\n<div>\nHow about here? >&<\n</div>\nAnd here?\n",
  713. "<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
  714. "Paragraph\n<div>\nHere? >&<\n</div>\n\nAnd here?\n",
  715. "<p>Paragraph</p>\n\n<div>\nHere? >&<\n</div>\n\n<p>And here?</p>\n",
  716. "Paragraph\n\n<div>\nHow about here? >&<\n</div>\n\nAnd here?\n",
  717. "<p>Paragraph</p>\n\n<div>\nHow about here? >&<\n</div>\n\n<p>And here?</p>\n",
  718. }
  719. doTestsBlock(t, tests, EXTENSION_LAX_HTML_BLOCKS)
  720. }
  721. func TestFencedCodeBlock(t *testing.T) {
  722. var tests = []string{
  723. "``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n",
  724. "<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
  725. "``` c\n/* special & char < > \" escaping */\n```\n",
  726. "<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",
  727. "``` c\nno *inline* processing ~~of text~~\n```\n",
  728. "<pre><code class=\"language-c\">no *inline* processing ~~of text~~\n</code></pre>\n",
  729. "```\nNo language\n```\n",
  730. "<pre><code>No language\n</code></pre>\n",
  731. "``` {ocaml}\nlanguage in braces\n```\n",
  732. "<pre><code class=\"language-ocaml\">language in braces\n</code></pre>\n",
  733. "``` {ocaml} \nwith extra whitespace\n```\n",
  734. "<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
  735. "```{ ocaml }\nwith extra whitespace\n```\n",
  736. "<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
  737. "~ ~~ java\nWith whitespace\n~~~\n",
  738. "<p>~ ~~ java\nWith whitespace\n~~~</p>\n",
  739. "~~\nonly two\n~~\n",
  740. "<p>~~\nonly two\n~~</p>\n",
  741. "```` python\nextra\n````\n",
  742. "<pre><code class=\"language-python\">extra\n</code></pre>\n",
  743. "~~~ perl\nthree to start, four to end\n~~~~\n",
  744. "<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n",
  745. "~~~~ perl\nfour to start, three to end\n~~~\n",
  746. "<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n",
  747. "~~~ bash\ntildes\n~~~\n",
  748. "<pre><code class=\"language-bash\">tildes\n</code></pre>\n",
  749. "``` lisp\nno ending\n",
  750. "<p>``` lisp\nno ending</p>\n",
  751. "~~~ lisp\nend with language\n~~~ lisp\n",
  752. "<p>~~~ lisp\nend with language\n~~~ lisp</p>\n",
  753. "```\nmismatched begin and end\n~~~\n",
  754. "<p>```\nmismatched begin and end\n~~~</p>\n",
  755. "~~~\nmismatched begin and end\n```\n",
  756. "<p>~~~\nmismatched begin and end\n```</p>\n",
  757. " ``` oz\nleading spaces\n```\n",
  758. "<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
  759. " ``` oz\nleading spaces\n ```\n",
  760. "<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
  761. " ``` oz\nleading spaces\n ```\n",
  762. "<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
  763. "``` oz\nleading spaces\n ```\n",
  764. "<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
  765. " ``` oz\nleading spaces\n ```\n",
  766. "<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces\n ```</p>\n",
  767. "Bla bla\n\n``` oz\ncode blocks breakup paragraphs\n```\n\nBla Bla\n",
  768. "<p>Bla bla</p>\n\n<pre><code class=\"language-oz\">code blocks breakup paragraphs\n</code></pre>\n\n<p>Bla Bla</p>\n",
  769. "Some text before a fenced code block\n``` oz\ncode blocks breakup paragraphs\n```\nAnd some text after a fenced code block",
  770. "<p>Some text before a fenced code block</p>\n\n<pre><code class=\"language-oz\">code blocks breakup paragraphs\n</code></pre>\n\n<p>And some text after a fenced code block</p>\n",
  771. "`",
  772. "<p>`</p>\n",
  773. "Bla bla\n\n``` oz\ncode blocks breakup paragraphs\n```\n\nBla Bla\n\n``` oz\nmultiple code blocks work okay\n```\n\nBla Bla\n",
  774. "<p>Bla bla</p>\n\n<pre><code class=\"language-oz\">code blocks breakup paragraphs\n</code></pre>\n\n<p>Bla Bla</p>\n\n<pre><code class=\"language-oz\">multiple code blocks work okay\n</code></pre>\n\n<p>Bla Bla</p>\n",
  775. "Some text before a fenced code block\n``` oz\ncode blocks breakup paragraphs\n```\nSome text in between\n``` oz\nmultiple code blocks work okay\n```\nAnd some text after a fenced code block",
  776. "<p>Some text before a fenced code block</p>\n\n<pre><code class=\"language-oz\">code blocks breakup paragraphs\n</code></pre>\n\n<p>Some text in between</p>\n\n<pre><code class=\"language-oz\">multiple code blocks work okay\n</code></pre>\n\n<p>And some text after a fenced code block</p>\n",
  777. }
  778. doTestsBlock(t, tests, EXTENSION_FENCED_CODE)
  779. }
  780. func TestFencedCodeInsideBlockquotes(t *testing.T) {
  781. cat := func(s ...string) string { return strings.Join(s, "\n") }
  782. var tests = []string{
  783. cat("> ```go",
  784. "package moo",
  785. "",
  786. "```",
  787. ""),
  788. `<blockquote>
  789. <pre><code class="language-go">package moo
  790. </code></pre>
  791. </blockquote>
  792. `,
  793. // -------------------------------------------
  794. cat("> foo",
  795. "> ",
  796. "> ```go",
  797. "package moo",
  798. "```",
  799. "> ",
  800. "> goo.",
  801. ""),
  802. `<blockquote>
  803. <p>foo</p>
  804. <pre><code class="language-go">package moo
  805. </code></pre>
  806. <p>goo.</p>
  807. </blockquote>
  808. `,
  809. // -------------------------------------------
  810. cat("> foo",
  811. "> ",
  812. "> quote",
  813. "continues",
  814. "```",
  815. ""),
  816. `<blockquote>
  817. <p>foo</p>
  818. <p>quote
  819. continues
  820. ` + "```" + `</p>
  821. </blockquote>
  822. `,
  823. // -------------------------------------------
  824. cat("> foo",
  825. "> ",
  826. "> ```go",
  827. "package moo",
  828. "```",
  829. "> ",
  830. "> goo.",
  831. "> ",
  832. "> ```go",
  833. "package zoo",
  834. "```",
  835. "> ",
  836. "> woo.",
  837. ""),
  838. `<blockquote>
  839. <p>foo</p>
  840. <pre><code class="language-go">package moo
  841. </code></pre>
  842. <p>goo.</p>
  843. <pre><code class="language-go">package zoo
  844. </code></pre>
  845. <p>woo.</p>
  846. </blockquote>
  847. `,
  848. }
  849. // These 2 alternative forms of blockquoted fenced code blocks should produce same output.
  850. forms := [2]string{
  851. cat("> plain quoted text",
  852. "> ```fenced",
  853. "code",
  854. " with leading single space correctly preserved",
  855. "okay",
  856. "```",
  857. "> rest of quoted text"),
  858. cat("> plain quoted text",
  859. "> ```fenced",
  860. "> code",
  861. "> with leading single space correctly preserved",
  862. "> okay",
  863. "> ```",
  864. "> rest of quoted text"),
  865. }
  866. want := `<blockquote>
  867. <p>plain quoted text</p>
  868. <pre><code class="language-fenced">code
  869. with leading single space correctly preserved
  870. okay
  871. </code></pre>
  872. <p>rest of quoted text</p>
  873. </blockquote>
  874. `
  875. tests = append(tests, forms[0], want)
  876. tests = append(tests, forms[1], want)
  877. doTestsBlock(t, tests, EXTENSION_FENCED_CODE)
  878. }
  879. func TestTable(t *testing.T) {
  880. var tests = []string{
  881. "a | b\n---|---\nc | d\n",
  882. "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n</tr>\n</thead>\n\n" +
  883. "<tbody>\n<tr>\n<td>c</td>\n<td>d</td>\n</tr>\n</tbody>\n</table>\n",
  884. "a | b\n---|--\nc | d\n",
  885. "<p>a | b\n---|--\nc | d</p>\n",
  886. "|a|b|c|d|\n|----|----|----|---|\n|e|f|g|h|\n",
  887. "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n<th>d</th>\n</tr>\n</thead>\n\n" +
  888. "<tbody>\n<tr>\n<td>e</td>\n<td>f</td>\n<td>g</td>\n<td>h</td>\n</tr>\n</tbody>\n</table>\n",
  889. "*a*|__b__|[c](C)|d\n---|---|---|---\ne|f|g|h\n",
  890. "<table>\n<thead>\n<tr>\n<th><em>a</em></th>\n<th><strong>b</strong></th>\n<th><a href=\"C\">c</a></th>\n<th>d</th>\n</tr>\n</thead>\n\n" +
  891. "<tbody>\n<tr>\n<td>e</td>\n<td>f</td>\n<td>g</td>\n<td>h</td>\n</tr>\n</tbody>\n</table>\n",
  892. "a|b|c\n---|---|---\nd|e|f\ng|h\ni|j|k|l|m\nn|o|p\n",
  893. "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n" +
  894. "<tbody>\n<tr>\n<td>d</td>\n<td>e</td>\n<td>f</td>\n</tr>\n\n" +
  895. "<tr>\n<td>g</td>\n<td>h</td>\n<td></td>\n</tr>\n\n" +
  896. "<tr>\n<td>i</td>\n<td>j</td>\n<td>k</td>\n</tr>\n\n" +
  897. "<tr>\n<td>n</td>\n<td>o</td>\n<td>p</td>\n</tr>\n</tbody>\n</table>\n",
  898. "a|b|c\n---|---|---\n*d*|__e__|f\n",
  899. "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n" +
  900. "<tbody>\n<tr>\n<td><em>d</em></td>\n<td><strong>e</strong></td>\n<td>f</td>\n</tr>\n</tbody>\n</table>\n",
  901. "a|b|c|d\n:--|--:|:-:|---\ne|f|g|h\n",
  902. "<table>\n<thead>\n<tr>\n<th align=\"left\">a</th>\n<th align=\"right\">b</th>\n" +
  903. "<th align=\"center\">c</th>\n<th>d</th>\n</tr>\n</thead>\n\n" +
  904. "<tbody>\n<tr>\n<td align=\"left\">e</td>\n<td align=\"right\">f</td>\n" +
  905. "<td align=\"center\">g</td>\n<td>h</td>\n</tr>\n</tbody>\n</table>\n",
  906. "a|b|c\n---|---|---\n",
  907. "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n</tr>\n</thead>\n\n<tbody>\n</tbody>\n</table>\n",
  908. "a| b|c | d | e\n---|---|---|---|---\nf| g|h | i |j\n",
  909. "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b</th>\n<th>c</th>\n<th>d</th>\n<th>e</th>\n</tr>\n</thead>\n\n" +
  910. "<tbody>\n<tr>\n<td>f</td>\n<td>g</td>\n<td>h</td>\n<td>i</td>\n<td>j</td>\n</tr>\n</tbody>\n</table>\n",
  911. "a|b\\|c|d\n---|---|---\nf|g\\|h|i\n",
  912. "<table>\n<thead>\n<tr>\n<th>a</th>\n<th>b|c</th>\n<th>d</th>\n</tr>\n</thead>\n\n<tbody>\n<tr>\n<td>f</td>\n<td>g|h</td>\n<td>i</td>\n</tr>\n</tbody>\n</table>\n",
  913. }
  914. doTestsBlock(t, tests, EXTENSION_TABLES)
  915. }
  916. func TestUnorderedListWith_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
  917. var tests = []string{
  918. "* Hello\n",
  919. "<ul>\n<li>Hello</li>\n</ul>\n",
  920. "* Yin\n* Yang\n",
  921. "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
  922. "* Ting\n* Bong\n* Goo\n",
  923. "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
  924. "* Yin\n\n* Yang\n",
  925. "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
  926. "* Ting\n\n* Bong\n* Goo\n",
  927. "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
  928. "+ Hello\n",
  929. "<ul>\n<li>Hello</li>\n</ul>\n",
  930. "+ Yin\n+ Yang\n",
  931. "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
  932. "+ Ting\n+ Bong\n+ Goo\n",
  933. "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
  934. "+ Yin\n\n+ Yang\n",
  935. "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
  936. "+ Ting\n\n+ Bong\n+ Goo\n",
  937. "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
  938. "- Hello\n",
  939. "<ul>\n<li>Hello</li>\n</ul>\n",
  940. "- Yin\n- Yang\n",
  941. "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n",
  942. "- Ting\n- Bong\n- Goo\n",
  943. "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n",
  944. "- Yin\n\n- Yang\n",
  945. "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n",
  946. "- Ting\n\n- Bong\n- Goo\n",
  947. "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n",
  948. "*Hello\n",
  949. "<p>*Hello</p>\n",
  950. "* Hello \n",
  951. "<ul>\n<li>Hello</li>\n</ul>\n",
  952. "* Hello \n Next line \n",
  953. "<ul>\n<li>Hello\nNext line</li>\n</ul>\n",
  954. "Paragraph\n* No linebreak\n",
  955. "<p>Paragraph</p>\n\n<ul>\n<li>No linebreak</li>\n</ul>\n",
  956. "Paragraph\n\n* Linebreak\n",
  957. "<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n",
  958. "* List\n * Nested list\n",
  959. "<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
  960. "* List\n\n * Nested list\n",
  961. "<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n",
  962. "* List\n Second line\n\n + Nested\n",
  963. "<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n",
  964. "* List\n + Nested\n\n Continued\n",
  965. "<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n",
  966. "* List\n * shallow indent\n",
  967. "<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n",
  968. "* List\n" +
  969. " * shallow indent\n" +
  970. " * part of second list\n" +
  971. " * still second\n" +
  972. " * almost there\n" +
  973. " * third level\n",
  974. "<ul>\n" +
  975. "<li>List\n\n" +
  976. "<ul>\n" +
  977. "<li>shallow indent</li>\n" +
  978. "<li>part of second list</li>\n" +
  979. "<li>still second</li>\n" +
  980. "<li>almost there\n\n" +
  981. "<ul>\n" +
  982. "<li>third level</li>\n" +
  983. "</ul></li>\n" +
  984. "</ul></li>\n" +
  985. "</ul>\n",
  986. "* List\n extra indent, same paragraph\n",
  987. "<ul>\n<li>List\n extra indent, same paragraph</li>\n</ul>\n",
  988. "* List\n\n code block\n",
  989. "<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n",
  990. "* List\n\n code block with spaces\n",
  991. "<ul>\n<li><p>List</p>\n\n<pre><code> code block with spaces\n</code></pre></li>\n</ul>\n",
  992. "* List\n\n * sublist\n\n normal text\n\n * another sublist\n",
  993. "<ul>\n<li><p>List</p>\n\n<ul>\n<li>sublist</li>\n</ul>\n\n<p>normal text</p>\n\n<ul>\n<li>another sublist</li>\n</ul></li>\n</ul>\n",
  994. }
  995. doTestsBlock(t, tests, EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK)
  996. }
  997. func TestOrderedList_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
  998. var tests = []string{
  999. "1. Hello\n",
  1000. "<ol>\n<li>Hello</li>\n</ol>\n",
  1001. "1. Yin\n2. Yang\n",
  1002. "<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n",
  1003. "1. Ting\n2. Bong\n3. Goo\n",
  1004. "<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n",
  1005. "1. Yin\n\n2. Yang\n",
  1006. "<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n",
  1007. "1. Ting\n\n2. Bong\n3. Goo\n",
  1008. "<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n",
  1009. "1 Hello\n",
  1010. "<p>1 Hello</p>\n",
  1011. "1.Hello\n",
  1012. "<p>1.Hello</p>\n",
  1013. "1. Hello \n",
  1014. "<ol>\n<li>Hello</li>\n</ol>\n",
  1015. "1. Hello \n Next line \n",
  1016. "<ol>\n<li>Hello\nNext line</li>\n</ol>\n",
  1017. "Paragraph\n1. No linebreak\n",
  1018. "<p>Paragraph</p>\n\n<ol>\n<li>No linebreak</li>\n</ol>\n",
  1019. "Paragraph\n\n1. Linebreak\n",
  1020. "<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n",
  1021. "1. List\n 1. Nested list\n",
  1022. "<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
  1023. "1. List\n\n 1. Nested list\n",
  1024. "<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n",
  1025. "1. List\n Second line\n\n 1. Nested\n",
  1026. "<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n",
  1027. "1. List\n 1. Nested\n\n Continued\n",
  1028. "<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n",
  1029. "1. List\n 1. shallow indent\n",
  1030. "<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n",
  1031. "1. List\n" +
  1032. " 1. shallow indent\n" +
  1033. " 2. part of second list\n" +
  1034. " 3. still second\n" +
  1035. " 4. almost there\n" +
  1036. " 1. third level\n",
  1037. "<ol>\n" +
  1038. "<li>List\n\n" +
  1039. "<ol>\n" +
  1040. "<li>shallow indent</li>\n" +
  1041. "<li>part of second list</li>\n" +
  1042. "<li>still second</li>\n" +
  1043. "<li>almost there\n\n" +
  1044. "<ol>\n" +
  1045. "<li>third level</li>\n" +
  1046. "</ol></li>\n" +
  1047. "</ol></li>\n" +
  1048. "</ol>\n",
  1049. "1. List\n extra indent, same paragraph\n",
  1050. "<ol>\n<li>List\n extra indent, same paragraph</li>\n</ol>\n",
  1051. "1. List\n\n code block\n",
  1052. "<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n",
  1053. "1. List\n\n code block with spaces\n",
  1054. "<ol>\n<li><p>List</p>\n\n<pre><code> code block with spaces\n</code></pre></li>\n</ol>\n",
  1055. "1. List\n * Mixted list\n",
  1056. "<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n",
  1057. "1. List\n * Mixed list\n",
  1058. "<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n",
  1059. "* Start with unordered\n 1. Ordered\n",
  1060. "<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
  1061. "* Start with unordered\n 1. Ordered\n",
  1062. "<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n",
  1063. "1. numbers\n1. are ignored\n",
  1064. "<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n",
  1065. }
  1066. doTestsBlock(t, tests, EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK)
  1067. }
  1068. func TestFencedCodeBlock_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) {
  1069. var tests = []string{
  1070. "``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n",
  1071. "<pre><code class=\"language-go\">func foo() bool {\n\treturn true;\n}\n</code></pre>\n",
  1072. "``` c\n/* special & char < > \" escaping */\n```\n",
  1073. "<pre><code class=\"language-c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n",
  1074. "``` c\nno *inline* processing ~~of text~~\n```\n",
  1075. "<pre><code class=\"language-c\">no *inline* processing ~~of text~~\n</code></pre>\n",
  1076. "```\nNo language\n```\n",
  1077. "<pre><code>No language\n</code></pre>\n",
  1078. "``` {ocaml}\nlanguage in braces\n```\n",
  1079. "<pre><code class=\"language-ocaml\">language in braces\n</code></pre>\n",
  1080. "``` {ocaml} \nwith extra whitespace\n```\n",
  1081. "<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
  1082. "```{ ocaml }\nwith extra whitespace\n```\n",
  1083. "<pre><code class=\"language-ocaml\">with extra whitespace\n</code></pre>\n",
  1084. "~ ~~ java\nWith whitespace\n~~~\n",
  1085. "<p>~ ~~ java\nWith whitespace\n~~~</p>\n",
  1086. "~~\nonly two\n~~\n",
  1087. "<p>~~\nonly two\n~~</p>\n",
  1088. "```` python\nextra\n````\n",
  1089. "<pre><code class=\"language-python\">extra\n</code></pre>\n",
  1090. "~~~ perl\nthree to start, four to end\n~~~~\n",
  1091. "<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n",
  1092. "~~~~ perl\nfour to start, three to end\n~~~\n",
  1093. "<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n",
  1094. "~~~ bash\ntildes\n~~~\n",
  1095. "<pre><code class=\"language-bash\">tildes\n</code></pre>\n",
  1096. "``` lisp\nno ending\n",
  1097. "<p>``` lisp\nno ending</p>\n",
  1098. "~~~ lisp\nend with language\n~~~ lisp\n",
  1099. "<p>~~~ lisp\nend with language\n~~~ lisp</p>\n",
  1100. "```\nmismatched begin and end\n~~~\n",
  1101. "<p>```\nmismatched begin and end\n~~~</p>\n",
  1102. "~~~\nmismatched begin and end\n```\n",
  1103. "<p>~~~\nmismatched begin and end\n```</p>\n",
  1104. " ``` oz\nleading spaces\n```\n",
  1105. "<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
  1106. " ``` oz\nleading spaces\n ```\n",
  1107. "<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
  1108. " ``` oz\nleading spaces\n ```\n",
  1109. "<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
  1110. "``` oz\nleading spaces\n ```\n",
  1111. "<pre><code class=\"language-oz\">leading spaces\n</code></pre>\n",
  1112. " ``` oz\nleading spaces\n ```\n",
  1113. "<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces</p>\n\n<pre><code>```\n</code></pre>\n",
  1114. }
  1115. doTestsBlock(t, tests, EXTENSION_FENCED_CODE|EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK)
  1116. }
  1117. func TestTitleBlock_EXTENSION_TITLEBLOCK(t *testing.T) {
  1118. var tests = []string{
  1119. "% Some title\n" +
  1120. "% Another title line\n" +
  1121. "% Yep, more here too\n",
  1122. "<h1 class=\"title\">" +
  1123. "Some title\n" +
  1124. "Another title line\n" +
  1125. "Yep, more here too\n" +
  1126. "</h1>",
  1127. }
  1128. doTestsBlock(t, tests, EXTENSION_TITLEBLOCK)
  1129. }
  1130. func TestBlockComments(t *testing.T) {
  1131. var tests = []string{
  1132. "Some text\n\n<!-- comment -->\n",
  1133. "<p>Some text</p>\n\n<!-- comment -->\n",
  1134. "Some text\n\n<!--\n\nmultiline\ncomment\n-->\n",
  1135. "<p>Some text</p>\n\n<!--\n\nmultiline\ncomment\n-->\n",
  1136. "Some text\n\n<!--\n\n<div><p>Commented</p>\n<span>html</span></div>\n-->\n",
  1137. "<p>Some text</p>\n\n<!--\n\n<div><p>Commented</p>\n<span>html</span></div>\n-->\n",
  1138. }
  1139. doTestsBlock(t, tests, 0)
  1140. }