mirror of
https://github.com/danog/blackfriday.git
synced 2024-11-27 04:24:41 +01:00
Merge pull request #125 from halostatue/auto-header-id
Add a flag to turn on header ID generation.
This commit is contained in:
commit
7c8f3c1dcc
29
block.go
29
block.go
@ -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)
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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 |
|
||||
|
Loading…
Reference in New Issue
Block a user