Merge pull request #125 from halostatue/auto-header-id

Add a flag to turn on header ID generation.
pull/128/head
Vytautas Šaltenis 2014-10-28 16:34:49 +02:00
commit 7c8f3c1dcc
3 changed files with 114 additions and 2 deletions

View File

@ -13,7 +13,10 @@
package blackfriday
import "bytes"
import (
"bytes"
"unicode"
)
// Parse block-level data.
// Note: this function and many that it calls assume that
@ -223,6 +226,9 @@ func (p *parser) prefixHeader(out *bytes.Buffer, data []byte) int {
end--
}
if end > i {
if id == "" && p.flags&EXTENSION_AUTO_HEADER_IDS != 0 {
id = createSanitizedAnchorName(string(data[i:end]))
}
work := func() bool {
p.inline(out, data[i:end])
return true
@ -1267,7 +1273,13 @@ func (p *parser) paragraph(out *bytes.Buffer, data []byte) int {
return true
}
}(out, p, data[prev:eol])
p.r.Header(out, work, level, "")
id := ""
if p.flags&EXTENSION_AUTO_HEADER_IDS != 0 {
id = createSanitizedAnchorName(string(data[prev:eol]))
}
p.r.Header(out, work, level, id)
// find the end of the underline
for data[i] != '\n' {
@ -1313,3 +1325,16 @@ func (p *parser) paragraph(out *bytes.Buffer, data []byte) int {
p.renderParagraph(out, data[:i])
return i
}
func createSanitizedAnchorName(text string) string {
var anchorName []rune
for _, r := range []rune(text) {
switch {
case r == ' ':
anchorName = append(anchorName, '-')
case unicode.IsLetter(r) || unicode.IsNumber(r):
anchorName = append(anchorName, unicode.ToLower(r))
}
}
return string(anchorName)
}

View File

@ -237,6 +237,48 @@ func TestPrefixHeaderIdExtension(t *testing.T) {
doTestsBlock(t, tests, EXTENSION_HEADER_IDS)
}
func TestPrefixAutoHeaderIdExtension(t *testing.T) {
var tests = []string{
"# Header 1\n",
"<h1 id=\"header-1\">Header 1</h1>\n",
"# Header 1 \n",
"<h1 id=\"header-1\">Header 1</h1>\n",
"## Header 2\n",
"<h2 id=\"header-2\">Header 2</h2>\n",
"### Header 3\n",
"<h3 id=\"header-3\">Header 3</h3>\n",
"#### Header 4\n",
"<h4 id=\"header-4\">Header 4</h4>\n",
"##### Header 5\n",
"<h5 id=\"header-5\">Header 5</h5>\n",
"###### Header 6\n",
"<h6 id=\"header-6\">Header 6</h6>\n",
"####### Header 7\n",
"<h6 id=\"-header-7\"># Header 7</h6>\n",
"Hello\n# Header 1\nGoodbye\n",
"<p>Hello</p>\n\n<h1 id=\"header-1\">Header 1</h1>\n\n<p>Goodbye</p>\n",
"* List\n# Header\n* List\n",
"<ul>\n<li><p>List</p>\n\n<h1 id=\"header\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
"* List\n#Header\n* List\n",
"<ul>\n<li><p>List</p>\n\n<h1 id=\"header\">Header</h1></li>\n\n<li><p>List</p></li>\n</ul>\n",
"* List\n * Nested list\n # Nested header\n",
"<ul>\n<li><p>List</p>\n\n<ul>\n<li><p>Nested list</p>\n\n" +
"<h1 id=\"nested-header\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
}
doTestsBlock(t, tests, EXTENSION_AUTO_HEADER_IDS)
}
func TestUnderlineHeaders(t *testing.T) {
var tests = []string{
"Header 1\n========\n",
@ -287,6 +329,50 @@ func TestUnderlineHeaders(t *testing.T) {
doTestsBlock(t, tests, 0)
}
func TestUnderlineHeadersAutoIDs(t *testing.T) {
var tests = []string{
"Header 1\n========\n",
"<h1 id=\"header-1\">Header 1</h1>\n",
"Header 2\n--------\n",
"<h2 id=\"header-2\">Header 2</h2>\n",
"A\n=\n",
"<h1 id=\"a\">A</h1>\n",
"B\n-\n",
"<h2 id=\"b\">B</h2>\n",
"Paragraph\nHeader\n=\n",
"<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
"Header\n===\nParagraph\n",
"<h1 id=\"header\">Header</h1>\n\n<p>Paragraph</p>\n",
"Header\n===\nAnother header\n---\n",
"<h1 id=\"header\">Header</h1>\n\n<h2 id=\"another-header\">Another header</h2>\n",
" Header\n======\n",
"<h1 id=\"header\">Header</h1>\n",
"Header with *inline*\n=====\n",
"<h1 id=\"header-with-inline\">Header with <em>inline</em></h1>\n",
"Paragraph\n\n\n\n\nHeader\n===\n",
"<p>Paragraph</p>\n\n<h1 id=\"header\">Header</h1>\n",
"Trailing space \n==== \n\n",
"<h1 id=\"trailing-space\">Trailing space</h1>\n",
"Trailing spaces\n==== \n\n",
"<h1 id=\"trailing-spaces\">Trailing spaces</h1>\n",
"Double underline\n=====\n=====\n",
"<h1 id=\"double-underline\">Double underline</h1>\n\n<p>=====</p>\n",
}
doTestsBlock(t, tests, EXTENSION_AUTO_HEADER_IDS)
}
func TestHorizontalRule(t *testing.T) {
var tests = []string{
"-\n",

View File

@ -41,6 +41,7 @@ const (
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}
EXTENSION_TITLEBLOCK // Titleblock ala pandoc
EXTENSION_AUTO_HEADER_IDS // Create the header ID from the text
commonHtmlFlags = 0 |
HTML_USE_XHTML |