- content_h1_to_h2 and generic_anchors on the settings row (migration
202610280001), Headings and links tab, config key
golem15.journal.content_h1_to_h2 used when no settings row exists
- classes.ConvertH1 on the x/net/html tokenizer; the Blog Editor types
convert while the setting is on and answer editor.h1_converted
- GET /posts/{slug} reports content_h1_to_h2 (additive key)
63 lines
1.6 KiB
Go
63 lines
1.6 KiB
Go
package classes
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
|
|
xhtml "golang.org/x/net/html"
|
|
)
|
|
|
|
// ConvertH1 turns every h1 element of html into an h2 and returns the
|
|
// result with the number of headings it converted. It works on the
|
|
// x/net/html tokenizer's raw tokens: only the tag name of an h1 start, end
|
|
// or self-closing tag changes, and every other byte (attributes, text,
|
|
// comments, the content of script or style) is copied as it is. Text that
|
|
// merely looks like a tag inside raw-text elements or comments is not a
|
|
// tag and is not touched. html without an h1 comes back unchanged with 0.
|
|
func ConvertH1(html string) (string, int) {
|
|
if !containsFold(html, "<h1") && !containsFold(html, "</h1") {
|
|
return html, 0
|
|
}
|
|
z := xhtml.NewTokenizer(strings.NewReader(html))
|
|
var b bytes.Buffer
|
|
b.Grow(len(html))
|
|
count := 0
|
|
for {
|
|
tt := z.Next()
|
|
if tt == xhtml.ErrorToken {
|
|
break
|
|
}
|
|
raw := z.Raw()
|
|
switch tt {
|
|
case xhtml.StartTagToken, xhtml.SelfClosingTagToken:
|
|
if name, _ := z.TagName(); string(name) == "h1" && len(raw) >= 3 {
|
|
b.WriteString("<h2")
|
|
b.Write(raw[3:])
|
|
count++
|
|
continue
|
|
}
|
|
case xhtml.EndTagToken:
|
|
if name, _ := z.TagName(); string(name) == "h1" && len(raw) >= 4 {
|
|
b.WriteString("</h2")
|
|
b.Write(raw[4:])
|
|
continue
|
|
}
|
|
}
|
|
b.Write(raw)
|
|
}
|
|
if count == 0 && b.String() == html {
|
|
return html, 0
|
|
}
|
|
return b.String(), count
|
|
}
|
|
|
|
// CountH1 is the number of h1 start tags in html, as ConvertH1 counts them.
|
|
func CountH1(html string) int {
|
|
_, n := ConvertH1(html)
|
|
return n
|
|
}
|
|
|
|
func containsFold(s, sub string) bool {
|
|
return strings.Contains(strings.ToLower(s), sub)
|
|
}
|