all repos — grayfriday @ 8751c35d1a63b40e58fd9ed9eb32f04e9036a205

blackfriday fork with a few changes

add EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK flag to make it closer to GFM(Github flavor Markdown)
athom athom@126.com
Tue, 30 Jul 2013 10:32:11 +0800
commit

8751c35d1a63b40e58fd9ed9eb32f04e9036a205

parent

264c82ed4bab287d32187ebb0e5a3f6f2413ef0d

M .gitignore.gitignore

@@ -5,3 +5,4 @@ *.6

_obj _test* markdown +tags
M block.goblock.go

@@ -1230,6 +1230,17 @@ p.renderParagraph(out, data[:i])

return i } + // if there's a list after this, paragraph is over + if p.flags&EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK != 0 { + if p.uliPrefix(current) != 0 || + p.oliPrefix(current) != 0 || + p.quotePrefix(current) != 0 || + p.codePrefix(current) != 0 { + p.renderParagraph(out, data[:i]) + return i + } + } + // otherwise, scan to the beginning of the next line for data[i] != '\n' { i++
M block_test.goblock_test.go

@@ -692,3 +692,281 @@ "<table>\n<thead>\n<tr>\n<td>a</td>\n<td>b|c</td>\n<td>d</td>\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",

} doTestsBlock(t, tests, EXTENSION_TABLES) } + +func TestUnorderedListWith_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) { + var tests = []string{ + "* Hello\n", + "<ul>\n<li>Hello</li>\n</ul>\n", + + "* Yin\n* Yang\n", + "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n", + + "* Ting\n* Bong\n* Goo\n", + "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n", + + "* Yin\n\n* Yang\n", + "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n", + + "* Ting\n\n* Bong\n* Goo\n", + "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n", + + "+ Hello\n", + "<ul>\n<li>Hello</li>\n</ul>\n", + + "+ Yin\n+ Yang\n", + "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n", + + "+ Ting\n+ Bong\n+ Goo\n", + "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n", + + "+ Yin\n\n+ Yang\n", + "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n", + + "+ Ting\n\n+ Bong\n+ Goo\n", + "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n", + + "- Hello\n", + "<ul>\n<li>Hello</li>\n</ul>\n", + + "- Yin\n- Yang\n", + "<ul>\n<li>Yin</li>\n<li>Yang</li>\n</ul>\n", + + "- Ting\n- Bong\n- Goo\n", + "<ul>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ul>\n", + + "- Yin\n\n- Yang\n", + "<ul>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ul>\n", + + "- Ting\n\n- Bong\n- Goo\n", + "<ul>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ul>\n", + + "*Hello\n", + "<p>*Hello</p>\n", + + "* Hello \n", + "<ul>\n<li>Hello</li>\n</ul>\n", + + "* Hello \n Next line \n", + "<ul>\n<li>Hello\nNext line</li>\n</ul>\n", + + "Paragraph\n* No linebreak\n", + "<p>Paragraph</p>\n\n<ul>\n<li>No linebreak</li>\n</ul>\n", + + "Paragraph\n\n* Linebreak\n", + "<p>Paragraph</p>\n\n<ul>\n<li>Linebreak</li>\n</ul>\n", + + "* List\n * Nested list\n", + "<ul>\n<li>List\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n", + + "* List\n\n * Nested list\n", + "<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested list</li>\n</ul></li>\n</ul>\n", + + "* List\n Second line\n\n + Nested\n", + "<ul>\n<li><p>List\nSecond line</p>\n\n<ul>\n<li>Nested</li>\n</ul></li>\n</ul>\n", + + "* List\n + Nested\n\n Continued\n", + "<ul>\n<li><p>List</p>\n\n<ul>\n<li>Nested</li>\n</ul>\n\n<p>Continued</p></li>\n</ul>\n", + + "* List\n * shallow indent\n", + "<ul>\n<li>List\n\n<ul>\n<li>shallow indent</li>\n</ul></li>\n</ul>\n", + + "* List\n" + + " * shallow indent\n" + + " * part of second list\n" + + " * still second\n" + + " * almost there\n" + + " * third level\n", + "<ul>\n" + + "<li>List\n\n" + + "<ul>\n" + + "<li>shallow indent</li>\n" + + "<li>part of second list</li>\n" + + "<li>still second</li>\n" + + "<li>almost there\n\n" + + "<ul>\n" + + "<li>third level</li>\n" + + "</ul></li>\n" + + "</ul></li>\n" + + "</ul>\n", + + "* List\n extra indent, same paragraph\n", + "<ul>\n<li>List\n extra indent, same paragraph</li>\n</ul>\n", + + "* List\n\n code block\n", + "<ul>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ul>\n", + + "* List\n\n code block with spaces\n", + "<ul>\n<li><p>List</p>\n\n<pre><code> code block with spaces\n</code></pre></li>\n</ul>\n", + + "* List\n\n * sublist\n\n normal text\n\n * another sublist\n", + "<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", + } + doTestsBlock(t, tests, EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK) +} + +func TestOrderedList_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) { + var tests = []string{ + "1. Hello\n", + "<ol>\n<li>Hello</li>\n</ol>\n", + + "1. Yin\n2. Yang\n", + "<ol>\n<li>Yin</li>\n<li>Yang</li>\n</ol>\n", + + "1. Ting\n2. Bong\n3. Goo\n", + "<ol>\n<li>Ting</li>\n<li>Bong</li>\n<li>Goo</li>\n</ol>\n", + + "1. Yin\n\n2. Yang\n", + "<ol>\n<li><p>Yin</p></li>\n\n<li><p>Yang</p></li>\n</ol>\n", + + "1. Ting\n\n2. Bong\n3. Goo\n", + "<ol>\n<li><p>Ting</p></li>\n\n<li><p>Bong</p></li>\n\n<li><p>Goo</p></li>\n</ol>\n", + + "1 Hello\n", + "<p>1 Hello</p>\n", + + "1.Hello\n", + "<p>1.Hello</p>\n", + + "1. Hello \n", + "<ol>\n<li>Hello</li>\n</ol>\n", + + "1. Hello \n Next line \n", + "<ol>\n<li>Hello\nNext line</li>\n</ol>\n", + + "Paragraph\n1. No linebreak\n", + "<p>Paragraph</p>\n\n<ol>\n<li>No linebreak</li>\n</ol>\n", + + "Paragraph\n\n1. Linebreak\n", + "<p>Paragraph</p>\n\n<ol>\n<li>Linebreak</li>\n</ol>\n", + + "1. List\n 1. Nested list\n", + "<ol>\n<li>List\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n", + + "1. List\n\n 1. Nested list\n", + "<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested list</li>\n</ol></li>\n</ol>\n", + + "1. List\n Second line\n\n 1. Nested\n", + "<ol>\n<li><p>List\nSecond line</p>\n\n<ol>\n<li>Nested</li>\n</ol></li>\n</ol>\n", + + "1. List\n 1. Nested\n\n Continued\n", + "<ol>\n<li><p>List</p>\n\n<ol>\n<li>Nested</li>\n</ol>\n\n<p>Continued</p></li>\n</ol>\n", + + "1. List\n 1. shallow indent\n", + "<ol>\n<li>List\n\n<ol>\n<li>shallow indent</li>\n</ol></li>\n</ol>\n", + + "1. List\n" + + " 1. shallow indent\n" + + " 2. part of second list\n" + + " 3. still second\n" + + " 4. almost there\n" + + " 1. third level\n", + "<ol>\n" + + "<li>List\n\n" + + "<ol>\n" + + "<li>shallow indent</li>\n" + + "<li>part of second list</li>\n" + + "<li>still second</li>\n" + + "<li>almost there\n\n" + + "<ol>\n" + + "<li>third level</li>\n" + + "</ol></li>\n" + + "</ol></li>\n" + + "</ol>\n", + + "1. List\n extra indent, same paragraph\n", + "<ol>\n<li>List\n extra indent, same paragraph</li>\n</ol>\n", + + "1. List\n\n code block\n", + "<ol>\n<li><p>List</p>\n\n<pre><code>code block\n</code></pre></li>\n</ol>\n", + + "1. List\n\n code block with spaces\n", + "<ol>\n<li><p>List</p>\n\n<pre><code> code block with spaces\n</code></pre></li>\n</ol>\n", + + "1. List\n * Mixted list\n", + "<ol>\n<li>List\n\n<ul>\n<li>Mixted list</li>\n</ul></li>\n</ol>\n", + + "1. List\n * Mixed list\n", + "<ol>\n<li>List\n\n<ul>\n<li>Mixed list</li>\n</ul></li>\n</ol>\n", + + "* Start with unordered\n 1. Ordered\n", + "<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n", + + "* Start with unordered\n 1. Ordered\n", + "<ul>\n<li>Start with unordered\n\n<ol>\n<li>Ordered</li>\n</ol></li>\n</ul>\n", + + "1. numbers\n1. are ignored\n", + "<ol>\n<li>numbers</li>\n<li>are ignored</li>\n</ol>\n", + } + doTestsBlock(t, tests, EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK) +} + +func TestFencedCodeBlock_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) { + var tests = []string{ + "``` go\nfunc foo() bool {\n\treturn true;\n}\n```\n", + "<pre><code class=\"go\">func foo() bool {\n return true;\n}\n</code></pre>\n", + + "``` c\n/* special & char < > \" escaping */\n```\n", + "<pre><code class=\"c\">/* special &amp; char &lt; &gt; &quot; escaping */\n</code></pre>\n", + + "``` c\nno *inline* processing ~~of text~~\n```\n", + "<pre><code class=\"c\">no *inline* processing ~~of text~~\n</code></pre>\n", + + "```\nNo language\n```\n", + "<pre><code>No language\n</code></pre>\n", + + "``` {ocaml}\nlanguage in braces\n```\n", + "<pre><code class=\"ocaml\">language in braces\n</code></pre>\n", + + "``` {ocaml} \nwith extra whitespace\n```\n", + "<pre><code class=\"ocaml\">with extra whitespace\n</code></pre>\n", + + "```{ ocaml }\nwith extra whitespace\n```\n", + "<pre><code class=\"ocaml\">with extra whitespace\n</code></pre>\n", + + "~ ~~ java\nWith whitespace\n~~~\n", + "<p>~ ~~ java\nWith whitespace\n~~~</p>\n", + + "~~\nonly two\n~~\n", + "<p>~~\nonly two\n~~</p>\n", + + "```` python\nextra\n````\n", + "<pre><code class=\"python\">extra\n</code></pre>\n", + + "~~~ perl\nthree to start, four to end\n~~~~\n", + "<p>~~~ perl\nthree to start, four to end\n~~~~</p>\n", + + "~~~~ perl\nfour to start, three to end\n~~~\n", + "<p>~~~~ perl\nfour to start, three to end\n~~~</p>\n", + + "~~~ bash\ntildes\n~~~\n", + "<pre><code class=\"bash\">tildes\n</code></pre>\n", + + "``` lisp\nno ending\n", + "<p>``` lisp\nno ending</p>\n", + + "~~~ lisp\nend with language\n~~~ lisp\n", + "<p>~~~ lisp\nend with language\n~~~ lisp</p>\n", + + "```\nmismatched begin and end\n~~~\n", + "<p>```\nmismatched begin and end\n~~~</p>\n", + + "~~~\nmismatched begin and end\n```\n", + "<p>~~~\nmismatched begin and end\n```</p>\n", + + " ``` oz\nleading spaces\n```\n", + "<pre><code class=\"oz\">leading spaces\n</code></pre>\n", + + " ``` oz\nleading spaces\n ```\n", + "<pre><code class=\"oz\">leading spaces\n</code></pre>\n", + + " ``` oz\nleading spaces\n ```\n", + "<pre><code class=\"oz\">leading spaces\n</code></pre>\n", + + "``` oz\nleading spaces\n ```\n", + "<pre><code class=\"oz\">leading spaces\n</code></pre>\n", + + " ``` oz\nleading spaces\n ```\n", + "<pre><code>``` oz\n</code></pre>\n\n<p>leading spaces</p>\n\n<pre><code>```\n</code></pre>\n", + } + doTestsBlock(t, tests, EXTENSION_FENCED_CODE|EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK) +}
M markdown.gomarkdown.go

@@ -28,16 +28,17 @@

// These are the supported markdown parsing extensions. // OR these values together to select multiple extensions. const ( - EXTENSION_NO_INTRA_EMPHASIS = 1 << iota // ignore emphasis markers inside words - EXTENSION_TABLES // render tables - EXTENSION_FENCED_CODE // render fenced code blocks - EXTENSION_AUTOLINK // detect embedded URLs that are not explicitly marked - EXTENSION_STRIKETHROUGH // strikethrough text using ~~test~~ - EXTENSION_LAX_HTML_BLOCKS // loosen up HTML block parsing rules - EXTENSION_SPACE_HEADERS // be strict about prefix header rules - EXTENSION_HARD_LINE_BREAK // translate newlines into line breaks - EXTENSION_TAB_SIZE_EIGHT // expand tabs to eight spaces instead of four - EXTENSION_FOOTNOTES // Pandoc-style footnotes + EXTENSION_NO_INTRA_EMPHASIS = 1 << iota // ignore emphasis markers inside words + EXTENSION_TABLES // render tables + EXTENSION_FENCED_CODE // render fenced code blocks + EXTENSION_AUTOLINK // detect embedded URLs that are not explicitly marked + EXTENSION_STRIKETHROUGH // strikethrough text using ~~test~~ + EXTENSION_LAX_HTML_BLOCKS // loosen up HTML block parsing rules + EXTENSION_SPACE_HEADERS // be strict about prefix header rules + EXTENSION_HARD_LINE_BREAK // translate newlines into line breaks + EXTENSION_TAB_SIZE_EIGHT // expand tabs to eight spaces instead of four + EXTENSION_FOOTNOTES // Pandoc-style footnotes + EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK // No need to insert an empty line to start a (code, quote, order list, unorder list)block ) // These are the possible flag values for the link renderer.
A upskirtref/Hard-wrapped paragraphs with list-like lines no empty line before block.html

@@ -0,0 +1,14 @@

+<p>In Markdown 1.0.0 and earlier. Version</p> + +<ol> +<li>This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked like a +list item.</li> +</ol> + +<p>Here's one with a bullet.</p> + +<ul> +<li>criminey.</li> +</ul>
A upskirtref/Hard-wrapped paragraphs with list-like lines no empty line before block.text

@@ -0,0 +1,8 @@

+In Markdown 1.0.0 and earlier. Version +8. This line turns into a list item. +Because a hard-wrapped line in the +middle of a paragraph looked like a +list item. + +Here's one with a bullet. +* criminey.
M upskirtref_test.goupskirtref_test.go

@@ -19,12 +19,12 @@ "path/filepath"

"testing" ) -func runMarkdownReference(input string) string { +func runMarkdownReference(input string, flag int) string { renderer := HtmlRenderer(0, "", "") - return string(Markdown([]byte(input), renderer, 0)) + return string(Markdown([]byte(input), renderer, flag)) } -func doTestsReference(t *testing.T, files []string) { +func doTestsReference(t *testing.T, files []string, flag int) { // catch and report panics var candidate string defer func() {

@@ -50,7 +50,7 @@ continue

} expected := string(expectedBytes) - actual := string(runMarkdownReference(input)) + actual := string(runMarkdownReference(input, flag)) if actual != expected { t.Errorf("\n [%#v]\nExpected[%#v]\nActual [%#v]", basename+".text", expected, actual)

@@ -62,7 +62,7 @@ if !testing.Short() {

start := 0 for end := start + 1; end <= len(input); end++ { candidate = input[start:end] - _ = runMarkdownReference(candidate) + _ = runMarkdownReference(candidate, flag) } } }

@@ -93,5 +93,33 @@ "Strong and em together",

"Tabs", "Tidyness", } - doTestsReference(t, files) + doTestsReference(t, files, 0) +} + +func TestReference_EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK(t *testing.T) { + files := []string{ + "Amps and angle encoding", + "Auto links", + "Backslash escapes", + "Blockquotes with code blocks", + "Code Blocks", + "Code Spans", + "Hard-wrapped paragraphs with list-like lines no empty line before block", + "Horizontal rules", + "Inline HTML (Advanced)", + "Inline HTML (Simple)", + "Inline HTML comments", + "Links, inline style", + "Links, reference style", + "Links, shortcut references", + "Literal quotes in titles", + "Markdown Documentation - Basics", + "Markdown Documentation - Syntax", + "Nested blockquotes", + "Ordered and unordered lists", + "Strong and em together", + "Tabs", + "Tidyness", + } + doTestsReference(t, files, EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK) }