mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-19 21:21:39 +02:00
Remove superfluous p-tags around shortcodes
This commit replaces the regexp driven `replaceShortcodeTokens` with a handwritten one. It wasnt't possible to handle the p-tags case without breaking performance. This fix actually improves in that area: ``` benchmark old ns/op new ns/op delta BenchmarkParsePage 142738 142667 -0.05% BenchmarkReplaceShortcodeTokens 665590 575645 -13.51% BenchmarkShortcodeLexer 176038 181074 +2.86% benchmark old allocs new allocs delta BenchmarkParsePage 87 87 +0.00% BenchmarkReplaceShortcodeTokens 9631 9424 -2.15% BenchmarkShortcodeLexer 274 274 +0.00% benchmark old bytes new bytes delta BenchmarkParsePage 141830 141830 +0.00% BenchmarkReplaceShortcodeTokens 52275 35219 -32.63% BenchmarkShortcodeLexer 30177 30178 +0.00% ``` Fixes #1148
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
package hugolib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"reflect"
|
||||
@@ -132,7 +134,7 @@ func HandleShortcodes(stringToParse string, page *Page, t tpl.Template) (string,
|
||||
}
|
||||
|
||||
if len(tmpShortcodes) > 0 {
|
||||
tmpContentWithTokensReplaced, err := replaceShortcodeTokens([]byte(tmpContent), shortcodePlaceholderPrefix, true, tmpShortcodes)
|
||||
tmpContentWithTokensReplaced, err := replaceShortcodeTokens([]byte(tmpContent), shortcodePlaceholderPrefix, tmpShortcodes)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Fail to replace short code tokens in %s:\n%s", page.BaseFileName(), err.Error())
|
||||
@@ -436,10 +438,10 @@ Loop:
|
||||
}
|
||||
|
||||
// replaceShortcodeTokensInsources calls replaceShortcodeTokens for every source given.
|
||||
func replaceShortcodeTokensInsources(prefix string, wrapped bool, replacements map[string]string, sources ...[]byte) (b [][]byte, err error) {
|
||||
func replaceShortcodeTokensInsources(prefix string, replacements map[string]string, sources ...[]byte) (b [][]byte, err error) {
|
||||
result := make([][]byte, len(sources))
|
||||
for i, s := range sources {
|
||||
b, err := replaceShortcodeTokens(s, prefix, wrapped, replacements)
|
||||
b, err := replaceShortcodeTokens(s, prefix, replacements)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -450,43 +452,65 @@ func replaceShortcodeTokensInsources(prefix string, wrapped bool, replacements m
|
||||
}
|
||||
|
||||
// Replace prefixed shortcode tokens (HUGOSHORTCODE-1, HUGOSHORTCODE-2) with the real content.
|
||||
// wrapped = true means that the token has been wrapped in {@{@/@}@}
|
||||
func replaceShortcodeTokens(source []byte, prefix string, wrapped bool, replacements map[string]string) (b []byte, err error) {
|
||||
var re *regexp.Regexp
|
||||
func replaceShortcodeTokens(source []byte, prefix string, replacements map[string]string) ([]byte, error) {
|
||||
|
||||
if wrapped {
|
||||
re, err = regexp.Compile(`\{@\{@` + regexp.QuoteMeta(prefix) + `-\d+@\}@\}`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
re, err = regexp.Compile(regexp.QuoteMeta(prefix) + `-(\d+)`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(replacements) == 0 {
|
||||
return source, nil
|
||||
}
|
||||
|
||||
// use panic/recover for reporting if an unknown
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
var ok bool
|
||||
b = nil
|
||||
err, ok = r.(error)
|
||||
if !ok {
|
||||
err = fmt.Errorf("unexpected panic during replaceShortcodeTokens: %v", r)
|
||||
var buff bytes.Buffer
|
||||
|
||||
sourceLen := len(source)
|
||||
width := 0
|
||||
start := 0
|
||||
|
||||
pre := []byte("{@{@" + prefix)
|
||||
post := []byte("@}@}")
|
||||
pStart := []byte("<p>")
|
||||
pEnd := []byte("</p>")
|
||||
|
||||
k := bytes.Index(source[start:], pre)
|
||||
|
||||
for k != -1 {
|
||||
j := start + k
|
||||
postIdx := bytes.Index(source[j:], post)
|
||||
if postIdx < 0 {
|
||||
// this should never happen, but let the caller decide to panic or not
|
||||
return nil, errors.New("illegal state in content; shortcode token missing end delim")
|
||||
}
|
||||
|
||||
end := j + postIdx + 4
|
||||
|
||||
newVal := []byte(replacements[string(source[j:end])])
|
||||
|
||||
// Issue #1148: Check for wrapping p-tags <p>
|
||||
if j >= 3 && bytes.Equal(source[j-3:j], pStart) {
|
||||
if (k+4) < sourceLen && bytes.Equal(source[end:end+4], pEnd) {
|
||||
j -= 3
|
||||
end += 4
|
||||
}
|
||||
}
|
||||
}()
|
||||
b = re.ReplaceAllFunc(source, func(m []byte) []byte {
|
||||
key := string(m)
|
||||
|
||||
if val, ok := replacements[key]; ok {
|
||||
return []byte(val)
|
||||
oldVal := source[j:end]
|
||||
w, err := buff.Write(source[start:j])
|
||||
if err != nil {
|
||||
return nil, errors.New("buff write failed")
|
||||
}
|
||||
panic(fmt.Errorf("unknown shortcode token %q", key))
|
||||
})
|
||||
width += w
|
||||
w, err = buff.Write(newVal)
|
||||
if err != nil {
|
||||
return nil, errors.New("buff write failed")
|
||||
}
|
||||
width += w
|
||||
start = j + len(oldVal)
|
||||
|
||||
return b, err
|
||||
k = bytes.Index(source[start:], pre)
|
||||
}
|
||||
_, err := buff.Write(source[start:])
|
||||
if err != nil {
|
||||
return nil, errors.New("buff write failed")
|
||||
}
|
||||
return buff.Bytes(), nil
|
||||
}
|
||||
|
||||
func getShortcodeTemplate(name string, t tpl.Template) *template.Template {
|
||||
|
Reference in New Issue
Block a user