all repos — grayfriday @ c5ece173ad8a086a3ea27a54b0a2ee82028fb274

blackfriday fork with a few changes

Merge pull request #59 from johnsto/master

Header ID specifiers
Vytautas Ĺ altenis vytas@rtfb.lt
Fri, 11 Apr 2014 21:31:27 +0300
commit

c5ece173ad8a086a3ea27a54b0a2ee82028fb274

parent

1fd57a277b99d4dd17f280779aa32c337931b8d0

5 files changed, 90 insertions(+), 6 deletions(-)

jump to
M block.goblock.go

@@ -186,6 +186,24 @@ }

for end = i; data[end] != '\n'; end++ { } skip := end + id := "" + if p.flags&EXTENSION_HEADER_IDS != 0 { + j, k := 0, 0 + // find start/end of header id + for j = i; j < end - 1 && (data[j] != '{' || data[j+1] != '#'); j++ { + } + for k = j + 1; k < end && data[k] != '}'; k++ { + } + // extract header id iff found + if j < end && k < end { + id = string(data[j+2:k]) + end = j + skip = k + 1 + for end > 0 && data[end-1] == ' ' { + end-- + } + } + } for end > 0 && data[end-1] == '#' { end-- }

@@ -197,7 +215,7 @@ work := func() bool {

p.inline(out, data[i:end]) return true } - p.r.Header(out, work, level) + p.r.Header(out, work, level, id) } return skip }

@@ -1218,7 +1236,7 @@ pp.inline(o, d)

return true } }(out, p, data[prev:eol]) - p.r.Header(out, work, level) + p.r.Header(out, work, level, "") // find the end of the underline for data[i] != '\n' {
M block_test.goblock_test.go

@@ -177,6 +177,66 @@ }

doTestsBlock(t, tests, EXTENSION_SPACE_HEADERS) } +func TestPrefixHeaderIdExtension(t *testing.T) { + var tests = []string{ + "# Header 1 {#someid}\n", + "<h1 id=\"someid\">Header 1</h1>\n", + + "# Header 1 {#someid} \n", + "<h1 id=\"someid\">Header 1</h1>\n", + + "# Header 1 {#someid}\n", + "<h1 id=\"someid\">Header 1</h1>\n", + + "# Header 1 {#someid\n", + "<h1>Header 1 {#someid</h1>\n", + + "# Header 1 {#someid\n", + "<h1>Header 1 {#someid</h1>\n", + + "# Header 1 {#someid}}\n", + "<h1 id=\"someid\">Header 1</h1>\n\n<p>}</p>\n", + + "## Header 2 {#someid}\n", + "<h2 id=\"someid\">Header 2</h2>\n", + + "### Header 3 {#someid}\n", + "<h3 id=\"someid\">Header 3</h3>\n", + + "#### Header 4 {#someid}\n", + "<h4 id=\"someid\">Header 4</h4>\n", + + "##### Header 5 {#someid}\n", + "<h5 id=\"someid\">Header 5</h5>\n", + + "###### Header 6 {#someid}\n", + "<h6 id=\"someid\">Header 6</h6>\n", + + "####### Header 7 {#someid}\n", + "<h6 id=\"someid\"># Header 7</h6>\n", + + "# Header 1 # {#someid}\n", + "<h1 id=\"someid\">Header 1</h1>\n", + + "## Header 2 ## {#someid}\n", + "<h2 id=\"someid\">Header 2</h2>\n", + + "Hello\n# Header 1\nGoodbye\n", + "<p>Hello</p>\n\n<h1>Header 1</h1>\n\n<p>Goodbye</p>\n", + + "* List\n# Header {#someid}\n* List\n", + "<ul>\n<li><p>List</p>\n\n<h1 id=\"someid\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n", + + "* List\n#Header {#someid}\n* List\n", + "<ul>\n<li><p>List</p>\n\n<h1 id=\"someid\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n", + + "* List\n * Nested list\n # Nested header {#someid}\n", + "<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" + + "<h1 id=\"someid\">Nested header</h1></li>\n</ul></li>\n</ul>\n", + } + doTestsBlock(t, tests, EXTENSION_HEADER_IDS) +} + func TestUnderlineHeaders(t *testing.T) { var tests = []string{ "Header 1\n========\n",
M html.gohtml.go

@@ -181,11 +181,13 @@ func (options *Html) GetFlags() int {

return options.flags } -func (options *Html) Header(out *bytes.Buffer, text func() bool, level int) { +func (options *Html) Header(out *bytes.Buffer, text func() bool, level int, id string) { marker := out.Len() doubleSpace(out) - if options.flags&HTML_TOC != 0 { + if id != "" { + out.WriteString(fmt.Sprintf("<h%d id=\"%s\">", level, id)) + } else if options.flags&HTML_TOC != 0 { // headerCount is incremented in htmlTocHeader out.WriteString(fmt.Sprintf("<h%d id=\"toc_%d\">", level, options.headerCount)) } else {
M latex.golatex.go

@@ -68,7 +68,7 @@ out.Write(text)

out.WriteString("\n\\end{verbatim}\n") } -func (options *Latex) Header(out *bytes.Buffer, text func() bool, level int) { +func (options *Latex) Header(out *bytes.Buffer, text func() bool, level int, id string) { marker := out.Len() switch level {
M markdown.gomarkdown.go

@@ -39,6 +39,7 @@ 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 + EXTENSION_HEADER_IDS // specify header IDs with {#id} ) // These are the possible flag values for the link renderer.

@@ -133,7 +134,7 @@ // block-level callbacks

BlockCode(out *bytes.Buffer, text []byte, lang string) BlockQuote(out *bytes.Buffer, text []byte) BlockHtml(out *bytes.Buffer, text []byte) - Header(out *bytes.Buffer, text func() bool, level int) + Header(out *bytes.Buffer, text func() bool, level int, id string) HRule(out *bytes.Buffer) List(out *bytes.Buffer, text func() bool, flags int) ListItem(out *bytes.Buffer, text []byte, flags int)

@@ -226,6 +227,8 @@ //

// * Strikethrough support // // * Strict header parsing +// +// * Custom Header IDs func MarkdownCommon(input []byte) []byte { // set up the HTML renderer htmlFlags := 0

@@ -244,6 +247,7 @@ extensions |= EXTENSION_FENCED_CODE

extensions |= EXTENSION_AUTOLINK extensions |= EXTENSION_STRIKETHROUGH extensions |= EXTENSION_SPACE_HEADERS + extensions |= EXTENSION_HEADER_IDS return Markdown(input, renderer, extensions) }