From 2dff0864f0288984446b73c8d9f60fc441f48b3d Mon Sep 17 00:00:00 2001 From: Dave Johnston Date: Sat, 5 Apr 2014 20:42:58 +0100 Subject: [PATCH] Add header ID support and tests: # Header {#myid} --- block.go | 16 ++++++++++++++-- block_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ html.go | 6 ++++-- latex.go | 2 +- markdown.go | 3 ++- 5 files changed, 69 insertions(+), 6 deletions(-) diff --git a/block.go b/block.go index 8681e63..e73cf02 100644 --- a/block.go +++ b/block.go @@ -186,6 +186,18 @@ func (p *parser) prefixHeader(out *bytes.Buffer, data []byte) int { for end = i; data[end] != '\n'; end++ { } skip := end + id := "" + if p.flags&EXTENSION_HEADER_IDS != 0 { + j, k := 0, 0 + for j = i; j < end - 1 && data[j] != '{' && data[j+1] != '#'; j++ { + } + for k = j + 1; k < end && data[k] != '}'; k++ { + } + if j < end && k < end { + id = string(data[j+2:k]) + end = j + } + } for end > 0 && data[end-1] == '#' { end-- } @@ -197,7 +209,7 @@ func (p *parser) prefixHeader(out *bytes.Buffer, data []byte) int { p.inline(out, data[i:end]) return true } - p.r.Header(out, work, level) + p.r.Header(out, work, level, id) } return skip } @@ -1214,7 +1226,7 @@ func (p *parser) paragraph(out *bytes.Buffer, data []byte) int { 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' { diff --git a/block_test.go b/block_test.go index ae4e1cc..20f29a1 100644 --- a/block_test.go +++ b/block_test.go @@ -177,6 +177,54 @@ func TestPrefixHeaderSpaceExtension(t *testing.T) { doTestsBlock(t, tests, EXTENSION_SPACE_HEADERS) } +func TestPrefixHeaderIdExtension(t *testing.T) { + var tests = []string{ + "# Header 1 {#someid}\n", + "

Header 1

\n", + + "# Header 1 {#someid} \n", + "

Header 1

\n", + + "# Header 1 {#someid}\n", + "

Header 1

\n", + + "# Header 1 {#someid\n", + "

Header 1 {#someid

\n", + + "## Header 2 {#someid}\n", + "

Header 2

\n", + + "### Header 3 {#someid}\n", + "

Header 3

\n", + + "#### Header 4 {#someid}\n", + "

Header 4

\n", + + "##### Header 5 {#someid}\n", + "
Header 5
\n", + + "###### Header 6 {#someid}\n", + "
Header 6
\n", + + "####### Header 7 {#someid}\n", + "
# Header 7
\n", + + "Hello\n# Header 1\nGoodbye\n", + "

Hello

\n\n

Header 1

\n\n

Goodbye

\n", + + "* List\n# Header {#someid}\n* List\n", + "\n", + + "* List\n#Header {#someid}\n* List\n", + "\n", + + "* List\n * Nested list\n # Nested header {#someid}\n", + "\n", + } + doTestsBlock(t, tests, EXTENSION_HEADER_IDS) +} + func TestUnderlineHeaders(t *testing.T) { var tests = []string{ "Header 1\n========\n", diff --git a/html.go b/html.go index 41220f5..5bba2a5 100644 --- a/html.go +++ b/html.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("", level, id)) + } else if options.flags&HTML_TOC != 0 { // headerCount is incremented in htmlTocHeader out.WriteString(fmt.Sprintf("", level, options.headerCount)) } else { diff --git a/latex.go b/latex.go index da17234..8924aca 100644 --- a/latex.go +++ b/latex.go @@ -68,7 +68,7 @@ func (options *Latex) BlockHtml(out *bytes.Buffer, text []byte) { 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 { diff --git a/markdown.go b/markdown.go index 1b170e4..703bd88 100644 --- a/markdown.go +++ b/markdown.go @@ -39,6 +39,7 @@ const ( 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 @@ type Renderer interface { 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)