Fix all headings wrongly referred to as headers I've left test cases alone since can't lean on the compiler for crosschecking there. Fixes #330.
@@ -224,7 +224,7 @@ are a few of note:
* [github_flavored_markdown](https://godoc.org/github.com/shurcooL/github_flavored_markdown): provides a GitHub Flavored Markdown renderer with fenced code block - highlighting, clickable header anchor links. + highlighting, clickable heading anchor links. It's not customizable, and its goal is to produce HTML output equivalent to the [GitHub Markdown API endpoint](https://developer.github.com/v3/markdown/#render-a-markdown-document-in-raw-mode),
@@ -43,14 +43,14 @@ p.nesting++
// parse out one block-level construct at a time for len(data) > 0 { - // prefixed header: + // prefixed heading: // - // # Header 1 - // ## Header 2 + // # Heading 1 + // ## Heading 2 // ... - // ###### Header 6 - if p.isPrefixHeader(data) { - data = data[p.prefixHeader(data):] + // ###### Heading 6 + if p.isPrefixHeading(data) { + data = data[p.prefixHeading(data):] continue }@@ -190,7 +190,7 @@ }
} // anything else must look like a normal paragraph - // note: this finds underlined headers, too + // note: this finds underlined headings, too data = data[p.paragraph(data):] }@@ -204,12 +204,12 @@ container.content = content
return container } -func (p *parser) isPrefixHeader(data []byte) bool { +func (p *parser) isPrefixHeading(data []byte) bool { if data[0] != '#' { return false } - if p.flags&SpaceHeaders != 0 { + if p.flags&SpaceHeadings != 0 { level := 0 for level < 6 && level < len(data) && data[level] == '#' { level++@@ -221,7 +221,7 @@ }
return true } -func (p *parser) prefixHeader(data []byte) int { +func (p *parser) prefixHeading(data []byte) int { level := 0 for level < 6 && level < len(data) && data[level] == '#' { level++@@ -230,14 +230,14 @@ i := skipChar(data, level, ' ')
end := skipUntilChar(data, i, '\n') skip := end id := "" - if p.flags&HeaderIDs != 0 { + if p.flags&HeadingIDs != 0 { j, k := 0, 0 - // find start/end of header id + // find start/end of heading 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 + // extract heading id iff found if j < end && k < end { id = string(data[j+2 : k]) end = j@@ -257,18 +257,18 @@ for end > 0 && data[end-1] == ' ' {
end-- } if end > i { - if id == "" && p.flags&AutoHeaderIDs != 0 { + if id == "" && p.flags&AutoHeadingIDs != 0 { id = sanitized_anchor_name.Create(string(data[i:end])) } - block := p.addBlock(Header, data[i:end]) - block.HeaderID = id + block := p.addBlock(Heading, data[i:end]) + block.HeadingID = id block.Level = level } return skip } -func (p *parser) isUnderlinedHeader(data []byte) int { - // test of level 1 header +func (p *parser) isUnderlinedHeading(data []byte) int { + // test of level 1 heading if data[0] == '=' { i := skipChar(data, 1, '=') i = skipChar(data, i, ' ')@@ -278,7 +278,7 @@ }
return 0 } - // test of level 2 header + // test of level 2 heading if data[0] == '-' { i := skipChar(data, 1, '-') i = skipChar(data, i, ' ')@@ -308,7 +308,7 @@ data = bytes.Join(splitData[0:i], []byte("\n"))
consumed := len(data) data = bytes.TrimPrefix(data, []byte("% ")) data = bytes.Replace(data, []byte("\n% "), []byte("\n"), -1) - block := p.addBlock(Header, data) + block := p.addBlock(Heading, data) block.Level = 1 block.IsTitleblock = true@@ -1301,9 +1301,9 @@ if sublist == 0 {
sublist = raw.Len() } - // is this a nested prefix header? - case p.isPrefixHeader(chunk): - // if the header is not indented, it is not nested in the list + // is this a nested prefix heading? + case p.isPrefixHeading(chunk): + // if the heading is not indented, it is not nested in the list // and thus ends the list if containsBlankLine && indent < 4 { *flags |= ListItemEndOfList@@ -1445,9 +1445,9 @@ p.renderParagraph(data[:i])
return i + n } - // an underline under some text marks a header, so our paragraph ended on prev line + // an underline under some text marks a heading, so our paragraph ended on prev line if i > 0 { - if level := p.isUnderlinedHeader(current); level > 0 { + if level := p.isUnderlinedHeading(current); level > 0 { // render the paragraph p.renderParagraph(data[:prev])@@ -1461,13 +1461,13 @@ eol--
} id := "" - if p.flags&AutoHeaderIDs != 0 { + if p.flags&AutoHeadingIDs != 0 { id = sanitized_anchor_name.Create(string(data[prev:eol])) } - block := p.addBlock(Header, data[prev:eol]) + block := p.addBlock(Heading, data[prev:eol]) block.Level = level - block.HeaderID = id + block.HeadingID = id // find the end of the underline for i < len(data) && data[i] != '\n' {@@ -1486,8 +1486,8 @@ return i
} } - // if there's a prefixed header or a horizontal rule after this, paragraph is over - if p.isPrefixHeader(current) || p.isHRule(current) { + // if there's a prefixed heading or a horizontal rule after this, paragraph is over + if p.isPrefixHeading(current) || p.isHRule(current) { p.renderParagraph(data[:i]) return i }
@@ -144,7 +144,7 @@ "* 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>Nested header</h1></li>\n</ul></li>\n</ul>\n", } - doTestsBlock(t, tests, SpaceHeaders) + doTestsBlock(t, tests, SpaceHeadings) } func TestPrefixHeaderIdExtension(t *testing.T) {@@ -204,7 +204,7 @@ "* 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, HeaderIDs) + doTestsBlock(t, tests, HeadingIDs) } func TestPrefixHeaderIdExtensionWithPrefixAndSuffix(t *testing.T) {@@ -248,12 +248,12 @@ "<h1 id=\"PRE:someid:POST\">Nested header</h1></li>\n</ul></li>\n</ul>\n",
} parameters := HTMLRendererParameters{ - HeaderIDPrefix: "PRE:", - HeaderIDSuffix: ":POST", + HeadingIDPrefix: "PRE:", + HeadingIDSuffix: ":POST", } doTestsParam(t, tests, TestParams{ - Options: Options{Extensions: HeaderIDs}, + Options: Options{Extensions: HeadingIDs}, HTMLFlags: UseXHTML, HTMLRendererParameters: parameters, })@@ -307,7 +307,7 @@
"# Header\n\n# Header 1\n\n# Header\n\n# Header", "<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header</h1>\n\n<h1 id=\"header-1-2\">Header</h1>\n", } - doTestsBlock(t, tests, AutoHeaderIDs) + doTestsBlock(t, tests, AutoHeadingIDs) } func TestPrefixAutoHeaderIdExtensionWithPrefixAndSuffix(t *testing.T) {@@ -360,12 +360,12 @@ "<h1 id=\"PRE:header:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1:POST\">Header 1</h1>\n\n<h1 id=\"PRE:header-1-1:POST\">Header</h1>\n\n<h1 id=\"PRE:header-1-2:POST\">Header</h1>\n",
} parameters := HTMLRendererParameters{ - HeaderIDPrefix: "PRE:", - HeaderIDSuffix: ":POST", + HeadingIDPrefix: "PRE:", + HeadingIDSuffix: ":POST", } doTestsParam(t, tests, TestParams{ - Options: Options{Extensions: AutoHeaderIDs}, + Options: Options{Extensions: AutoHeadingIDs}, HTMLFlags: UseXHTML, HTMLRendererParameters: parameters, })@@ -376,7 +376,7 @@ var tests = []string{
"# Header\n\n# Header {#header}\n\n# Header 1", "<h1 id=\"header\">Header</h1>\n\n<h1 id=\"header-1\">Header</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n", } - doTestsBlock(t, tests, AutoHeaderIDs|HeaderIDs) + doTestsBlock(t, tests, AutoHeadingIDs|HeadingIDs) } func TestUnderlineHeaders(t *testing.T) {@@ -476,7 +476,7 @@
"Header 1\n========\n\nHeader 1\n========\n", "<h1 id=\"header-1\">Header 1</h1>\n\n<h1 id=\"header-1-1\">Header 1</h1>\n", } - doTestsBlock(t, tests, AutoHeaderIDs) + doTestsBlock(t, tests, AutoHeadingIDs) } func TestHorizontalRule(t *testing.T) {
@@ -80,11 +80,11 @@ // Show this text inside the <a> tag for a footnote return link, if the
// HTML_FOOTNOTE_RETURN_LINKS flag is enabled. If blank, the string // <sup>[return]</sup> is used. FootnoteReturnLinkContents string - // If set, add this text to the front of each Header ID, to ensure + // If set, add this text to the front of each Heading ID, to ensure // uniqueness. - HeaderIDPrefix string - // If set, add this text to the back of each Header ID, to ensure uniqueness. - HeaderIDSuffix string + HeadingIDPrefix string + // If set, add this text to the back of each Heading ID, to ensure uniqueness. + HeadingIDSuffix string Title string // Document title (used if CompletePage is set) CSS string // Optional CSS file URL (used if CompletePage is set)@@ -101,8 +101,8 @@ HTMLRendererParameters
closeTag string // how to end singleton tags: either " />" or ">" - // Track header IDs to prevent ID collision in a single generation. - headerIDs map[string]int + // Track heading IDs to prevent ID collision in a single generation. + headingIDs map[string]int lastOutputLen int disableTags int@@ -131,8 +131,8 @@
return &HTMLRenderer{ HTMLRendererParameters: params, - closeTag: closeTag, - headerIDs: make(map[string]int), + closeTag: closeTag, + headingIDs: make(map[string]int), sr: NewSmartypantsRenderer(params.Flags), }@@ -238,20 +238,20 @@
return false } -func (r *HTMLRenderer) ensureUniqueHeaderID(id string) string { - for count, found := r.headerIDs[id]; found; count, found = r.headerIDs[id] { +func (r *HTMLRenderer) ensureUniqueHeadingID(id string) string { + for count, found := r.headingIDs[id]; found; count, found = r.headingIDs[id] { tmp := fmt.Sprintf("%s-%d", id, count+1) - if _, tmpFound := r.headerIDs[tmp]; !tmpFound { - r.headerIDs[id] = count + 1 + if _, tmpFound := r.headingIDs[tmp]; !tmpFound { + r.headingIDs[id] = count + 1 id = tmp } else { id = id + "-1" } } - if _, found := r.headerIDs[id]; !found { - r.headerIDs[id] = 0 + if _, found := r.headingIDs[id]; !found { + r.headingIDs[id] = 0 } return id@@ -457,7 +457,7 @@ footnotesDivBytes = []byte("\n<div class=\"footnotes\">\n\n")
footnotesCloseDivBytes = []byte("\n</div>\n") ) -func headerTagsFromLevel(level int) ([]byte, []byte) { +func headingTagsFromLevel(level int) ([]byte, []byte) { switch level { case 1: return h1Tag, h1CloseTag@@ -619,7 +619,7 @@ // TODO: untangle this clusterfuck about when the newlines need
// to be added and when not. if node.Prev != nil { switch node.Prev.Type { - case HTMLBlock, List, Paragraph, Header, CodeBlock, BlockQuote, HorizontalRule: + case HTMLBlock, List, Paragraph, Heading, CodeBlock, BlockQuote, HorizontalRule: r.cr(w) } }@@ -648,19 +648,19 @@ }
r.cr(w) r.out(w, node.Literal) r.cr(w) - case Header: - openTag, closeTag := headerTagsFromLevel(node.Level) + case Heading: + openTag, closeTag := headingTagsFromLevel(node.Level) if entering { if node.IsTitleblock { attrs = append(attrs, `class="title"`) } - if node.HeaderID != "" { - id := r.ensureUniqueHeaderID(node.HeaderID) - if r.HeaderIDPrefix != "" { - id = r.HeaderIDPrefix + id + if node.HeadingID != "" { + id := r.ensureUniqueHeadingID(node.HeadingID) + if r.HeadingIDPrefix != "" { + id = r.HeadingIDPrefix + id } - if r.HeaderIDSuffix != "" { - id = id + r.HeaderIDSuffix + if r.HeadingIDSuffix != "" { + id = id + r.HeadingIDSuffix } attrs = append(attrs, fmt.Sprintf(`id="%s"`, id)) }@@ -870,15 +870,15 @@
func (r *HTMLRenderer) writeTOC(w *bytes.Buffer, ast *Node) { buf := bytes.Buffer{} - inHeader := false + inHeading := false tocLevel := 0 - headerCount := 0 + headingCount := 0 ast.Walk(func(node *Node, entering bool) WalkStatus { - if node.Type == Header && !node.HeaderData.IsTitleblock { - inHeader = entering + if node.Type == Heading && !node.HeadingData.IsTitleblock { + inHeading = entering if entering { - node.HeaderID = fmt.Sprintf("toc_%d", headerCount) + node.HeadingID = fmt.Sprintf("toc_%d", headingCount) if node.Level == tocLevel { buf.WriteString("</li>\n\n<li>") } else if node.Level < tocLevel {@@ -894,15 +894,15 @@ buf.WriteString("\n<ul>\n<li>")
} } - fmt.Fprintf(&buf, `<a href="#toc_%d">`, headerCount) - headerCount++ + fmt.Fprintf(&buf, `<a href="#toc_%d">`, headingCount) + headingCount++ } else { buf.WriteString("</a>") } return GoToNext } - if inHeader { + if inHeading { return r.RenderNode(&buf, node, entering) }
@@ -36,14 +36,14 @@ FencedCode // Render fenced code blocks
Autolink // Detect embedded URLs that are not explicitly marked Strikethrough // Strikethrough text using ~~test~~ LaxHTMLBlocks // Loosen up HTML block parsing rules - SpaceHeaders // Be strict about prefix header rules + SpaceHeadings // Be strict about prefix heading rules HardLineBreak // Translate newlines into line breaks TabSizeEight // Expand tabs to eight spaces instead of four Footnotes // Pandoc-style footnotes NoEmptyLineBeforeBlock // No need to insert an empty line to start a (code, quote, ordered list, unordered list) block - HeaderIDs // specify header IDs with {#id} + HeadingIDs // specify heading IDs with {#id} Titleblock // Titleblock ala pandoc - AutoHeaderIDs // Create the header ID from the text + AutoHeadingIDs // Create the heading ID from the text BackslashLineBreak // Translate trailing backslashes into line breaks DefinitionLists // Render definition lists@@ -51,7 +51,7 @@ CommonHTMLFlags HTMLFlags = UseXHTML | Smartypants |
SmartypantsFractions | SmartypantsDashes | SmartypantsLatexDashes CommonExtensions Extensions = NoIntraEmphasis | Tables | FencedCode | - Autolink | Strikethrough | SpaceHeaders | HeaderIDs | + Autolink | Strikethrough | SpaceHeadings | HeadingIDs | BackslashLineBreak | DefinitionLists )@@ -310,9 +310,9 @@ // * Autolinking
// // * Strikethrough support // -// * Strict header parsing +// * Strict heading parsing // -// * Custom Header IDs +// * Custom Heading IDs func MarkdownCommon(input []byte) []byte { // set up the HTML renderer renderer := NewHTMLRenderer(HTMLRendererParameters{@@ -392,7 +392,7 @@ p.finalize(p.tip)
} // Walk the tree again and process inline markdown in each block p.doc.Walk(func(node *Node, entering bool) WalkStatus { - if node.Type == Paragraph || node.Type == Header || node.Type == TableCell { + if node.Type == Paragraph || node.Type == Heading || node.Type == TableCell { p.inline(node, node.content) node.content = nil }@@ -433,7 +433,7 @@ above := block.Parent
finalizeList(block) p.tip = above block.Walk(func(node *Node, entering bool) WalkStatus { - if node.Type == Paragraph || node.Type == Header { + if node.Type == Paragraph || node.Type == Heading { p.inline(node, node.content) node.content = nil }
@@ -17,7 +17,7 @@ BlockQuote
List Item Paragraph - Header + Heading HorizontalRule Emph Strong@@ -44,7 +44,7 @@ BlockQuote: "BlockQuote",
List: "List", Item: "Item", Paragraph: "Paragraph", - Header: "Header", + Heading: "Heading", HorizontalRule: "HorizontalRule", Emph: "Emph", Strong: "Strong",@@ -102,10 +102,10 @@ IsHeader bool // This tells if it's under the header row
Align CellAlignFlags // This holds the value for align attribute } -// HeaderData contains fields relevant to a Header node type. -type HeaderData struct { +// HeadingData contains fields relevant to a Heading node type. +type HeadingData struct { Level int // This holds the heading level number - HeaderID string // This might hold header ID, if present + HeadingID string // This might hold heading ID, if present IsTitleblock bool // Specifies whether it's a title block }@@ -122,7 +122,7 @@ Next *Node // Next sibling; nil if it's the last child
Literal []byte // Text contents of the leaf nodes - HeaderData // Populated if Type is Header + HeadingData // Populated if Type is Heading ListData // Populated if Type is List CodeBlockData // Populated if Type is CodeBlock LinkData // Populated if Type is Link@@ -211,7 +211,7 @@ case Item:
fallthrough case Paragraph: fallthrough - case Header: + case Heading: fallthrough case Emph: fallthrough