mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
parent
ce9cf882a5
commit
588c9019cf
5 changed files with 114 additions and 26 deletions
2
go.mod
2
go.mod
|
@ -70,7 +70,7 @@ require (
|
||||||
github.com/tdewolff/minify/v2 v2.20.37
|
github.com/tdewolff/minify/v2 v2.20.37
|
||||||
github.com/tdewolff/parse/v2 v2.7.15
|
github.com/tdewolff/parse/v2 v2.7.15
|
||||||
github.com/tetratelabs/wazero v1.8.1
|
github.com/tetratelabs/wazero v1.8.1
|
||||||
github.com/yuin/goldmark v1.7.4
|
github.com/yuin/goldmark v1.7.8
|
||||||
github.com/yuin/goldmark-emoji v1.0.4
|
github.com/yuin/goldmark-emoji v1.0.4
|
||||||
go.uber.org/automaxprocs v1.5.3
|
go.uber.org/automaxprocs v1.5.3
|
||||||
gocloud.dev v0.39.0
|
gocloud.dev v0.39.0
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -472,6 +472,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
||||||
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
|
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
|
||||||
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
|
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
|
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
github.com/yuin/goldmark-emoji v1.0.4 h1:vCwMkPZSNefSUnOW2ZKRUjBSD5Ok3W78IXhGxxAEF90=
|
github.com/yuin/goldmark-emoji v1.0.4 h1:vCwMkPZSNefSUnOW2ZKRUjBSD5Ok3W78IXhGxxAEF90=
|
||||||
github.com/yuin/goldmark-emoji v1.0.4/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
|
github.com/yuin/goldmark-emoji v1.0.4/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
|
|
|
@ -43,6 +43,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// Don't change this. This pattern is lso used in the image render hooks.
|
||||||
internalAttrPrefix = "_h__"
|
internalAttrPrefix = "_h__"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,13 @@ package render
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
bp "github.com/gohugoio/hugo/bufferpool"
|
||||||
|
|
||||||
htext "github.com/gohugoio/hugo/common/text"
|
htext "github.com/gohugoio/hugo/common/text"
|
||||||
|
"github.com/gohugoio/hugo/tpl"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/markup/converter"
|
"github.com/gohugoio/hugo/markup/converter"
|
||||||
"github.com/gohugoio/hugo/markup/converter/hooks"
|
"github.com/gohugoio/hugo/markup/converter/hooks"
|
||||||
|
@ -258,3 +262,30 @@ func (c *hookBase) Position() htext.Position {
|
||||||
func (c *hookBase) PositionerSourceTarget() []byte {
|
func (c *hookBase) PositionerSourceTarget() []byte {
|
||||||
return c.getSourceSample()
|
return c.getSourceSample()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TextPlain returns a plain text representation of the given node.
|
||||||
|
// Goldmark's Node.Text was deprecated in 1.7.8.
|
||||||
|
func TextPlain(n ast.Node, source []byte) string {
|
||||||
|
buf := bp.GetBuffer()
|
||||||
|
defer bp.PutBuffer(buf)
|
||||||
|
|
||||||
|
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
|
||||||
|
textPlainTo(c, source, buf)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func textPlainTo(c ast.Node, source []byte, buf *bytes.Buffer) {
|
||||||
|
if c == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch c := c.(type) {
|
||||||
|
case *ast.RawHTML:
|
||||||
|
s := strings.TrimSpace(tpl.StripHTML(string(c.Segments.Value(source))))
|
||||||
|
buf.WriteString(s)
|
||||||
|
case *ast.Text:
|
||||||
|
buf.Write(c.Segment.Value(source))
|
||||||
|
default:
|
||||||
|
textPlainTo(c.FirstChild(), source, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -200,7 +200,7 @@ func (r *hookedRenderer) renderImage(w util.BufWriter, source []byte, node ast.N
|
||||||
destination: string(n.Destination),
|
destination: string(n.Destination),
|
||||||
title: string(n.Title),
|
title: string(n.Title),
|
||||||
text: hstring.HTML(text),
|
text: hstring.HTML(text),
|
||||||
plainText: string(n.Text(source)),
|
plainText: render.TextPlain(n, source),
|
||||||
AttributesHolder: attributes.New(attrs, attributes.AttributesOwnerGeneral),
|
AttributesHolder: attributes.New(attrs, attributes.AttributesOwnerGeneral),
|
||||||
},
|
},
|
||||||
ordinal: ordinal,
|
ordinal: ordinal,
|
||||||
|
@ -223,7 +223,7 @@ func (r *hookedRenderer) filterInternalAttributes(attrs []ast.Attribute) []ast.A
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to the default Goldmark render funcs. Method below borrowed from:
|
// Fall back to the default Goldmark render funcs. Method below borrowed from:
|
||||||
// https://github.com/yuin/goldmark/blob/b611cd333a492416b56aa8d94b04a67bf0096ab2/renderer/html/html.go#L404
|
// https://github.com/yuin/goldmark
|
||||||
func (r *hookedRenderer) renderImageDefault(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
func (r *hookedRenderer) renderImageDefault(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
if !entering {
|
if !entering {
|
||||||
return ast.WalkContinue, nil
|
return ast.WalkContinue, nil
|
||||||
|
@ -234,7 +234,7 @@ func (r *hookedRenderer) renderImageDefault(w util.BufWriter, source []byte, nod
|
||||||
_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
|
_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
|
||||||
}
|
}
|
||||||
_, _ = w.WriteString(`" alt="`)
|
_, _ = w.WriteString(`" alt="`)
|
||||||
_, _ = w.Write(nodeToHTMLText(n, source))
|
r.renderTexts(w, source, n)
|
||||||
_ = w.WriteByte('"')
|
_ = w.WriteByte('"')
|
||||||
if n.Title != nil {
|
if n.Title != nil {
|
||||||
_, _ = w.WriteString(` title="`)
|
_, _ = w.WriteString(` title="`)
|
||||||
|
@ -242,8 +242,7 @@ func (r *hookedRenderer) renderImageDefault(w util.BufWriter, source []byte, nod
|
||||||
_ = w.WriteByte('"')
|
_ = w.WriteByte('"')
|
||||||
}
|
}
|
||||||
if n.Attributes() != nil {
|
if n.Attributes() != nil {
|
||||||
attrs := r.filterInternalAttributes(n.Attributes())
|
html.RenderAttributes(w, n, html.ImageAttributeFilter)
|
||||||
attributes.RenderASTAttributes(w, attrs...)
|
|
||||||
}
|
}
|
||||||
if r.XHTML {
|
if r.XHTML {
|
||||||
_, _ = w.WriteString(" />")
|
_, _ = w.WriteString(" />")
|
||||||
|
@ -289,7 +288,7 @@ func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.No
|
||||||
destination: string(n.Destination),
|
destination: string(n.Destination),
|
||||||
title: string(n.Title),
|
title: string(n.Title),
|
||||||
text: hstring.HTML(text),
|
text: hstring.HTML(text),
|
||||||
plainText: string(n.Text(source)),
|
plainText: render.TextPlain(n, source),
|
||||||
AttributesHolder: attributes.Empty,
|
AttributesHolder: attributes.Empty,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -297,6 +296,79 @@ func (r *hookedRenderer) renderLink(w util.BufWriter, source []byte, node ast.No
|
||||||
return ast.WalkContinue, err
|
return ast.WalkContinue, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Borrowed from Goldmark's HTML renderer.
|
||||||
|
func (r *hookedRenderer) renderTexts(w util.BufWriter, source []byte, n ast.Node) {
|
||||||
|
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
|
||||||
|
if s, ok := c.(*ast.String); ok {
|
||||||
|
_, _ = r.renderString(w, source, s, true)
|
||||||
|
} else if t, ok := c.(*ast.Text); ok {
|
||||||
|
_, _ = r.renderText(w, source, t, true)
|
||||||
|
} else {
|
||||||
|
r.renderTexts(w, source, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Borrowed from Goldmark's HTML renderer.
|
||||||
|
func (r *hookedRenderer) renderString(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
|
if !entering {
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
n := node.(*ast.String)
|
||||||
|
if n.IsCode() {
|
||||||
|
_, _ = w.Write(n.Value)
|
||||||
|
} else {
|
||||||
|
if n.IsRaw() {
|
||||||
|
r.Writer.RawWrite(w, n.Value)
|
||||||
|
} else {
|
||||||
|
r.Writer.Write(w, n.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Borrowed from Goldmark's HTML renderer.
|
||||||
|
func (r *hookedRenderer) renderText(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
|
if !entering {
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
n := node.(*ast.Text)
|
||||||
|
segment := n.Segment
|
||||||
|
if n.IsRaw() {
|
||||||
|
r.Writer.RawWrite(w, segment.Value(source))
|
||||||
|
} else {
|
||||||
|
value := segment.Value(source)
|
||||||
|
r.Writer.Write(w, value)
|
||||||
|
if n.HardLineBreak() || (n.SoftLineBreak() && r.HardWraps) {
|
||||||
|
if r.XHTML {
|
||||||
|
_, _ = w.WriteString("<br />\n")
|
||||||
|
} else {
|
||||||
|
_, _ = w.WriteString("<br>\n")
|
||||||
|
}
|
||||||
|
} else if n.SoftLineBreak() {
|
||||||
|
// TODO(bep) we use these methods a fallback to default rendering when no image/link hooks are defined.
|
||||||
|
// I don't think the below is relevant in these situations, but if so, we need to create a PR
|
||||||
|
// upstream to export softLineBreak.
|
||||||
|
/*if r.EastAsianLineBreaks != html.EastAsianLineBreaksNone && len(value) != 0 {
|
||||||
|
sibling := node.NextSibling()
|
||||||
|
if sibling != nil && sibling.Kind() == ast.KindText {
|
||||||
|
if siblingText := sibling.(*ast.Text).Value(source); len(siblingText) != 0 {
|
||||||
|
thisLastRune := util.ToRune(value, len(value)-1)
|
||||||
|
siblingFirstRune, _ := utf8.DecodeRune(siblingText)
|
||||||
|
if r.EastAsianLineBreaks.softLineBreak(thisLastRune, siblingFirstRune) {
|
||||||
|
_ = w.WriteByte('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_ = w.WriteByte('\n')
|
||||||
|
}*/
|
||||||
|
_ = w.WriteByte('\n')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Fall back to the default Goldmark render funcs. Method below borrowed from:
|
// Fall back to the default Goldmark render funcs. Method below borrowed from:
|
||||||
// https://github.com/yuin/goldmark/blob/b611cd333a492416b56aa8d94b04a67bf0096ab2/renderer/html/html.go#L404
|
// https://github.com/yuin/goldmark/blob/b611cd333a492416b56aa8d94b04a67bf0096ab2/renderer/html/html.go#L404
|
||||||
func (r *hookedRenderer) renderLinkDefault(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
func (r *hookedRenderer) renderLinkDefault(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
|
@ -443,7 +515,7 @@ func (r *hookedRenderer) renderHeading(w util.BufWriter, source []byte, node ast
|
||||||
level: n.Level,
|
level: n.Level,
|
||||||
anchor: string(anchor),
|
anchor: string(anchor),
|
||||||
text: hstring.HTML(text),
|
text: hstring.HTML(text),
|
||||||
plainText: string(n.Text(source)),
|
plainText: render.TextPlain(n, source),
|
||||||
AttributesHolder: attributes.New(n.Attributes(), attributes.AttributesOwnerGeneral),
|
AttributesHolder: attributes.New(n.Attributes(), attributes.AttributesOwnerGeneral),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -478,21 +550,3 @@ func (e *links) Extend(m goldmark.Markdown) {
|
||||||
util.Prioritized(newLinkRenderer(e.cfg), 100),
|
util.Prioritized(newLinkRenderer(e.cfg), 100),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Borrowed from Goldmark.
|
|
||||||
func nodeToHTMLText(n ast.Node, source []byte) []byte {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
for c := n.FirstChild(); c != nil; c = c.NextSibling() {
|
|
||||||
if s, ok := c.(*ast.String); ok && s.IsCode() {
|
|
||||||
buf.Write(s.Text(source))
|
|
||||||
} else if !c.HasChildren() {
|
|
||||||
buf.Write(util.EscapeHTML(c.Text(source)))
|
|
||||||
if t, ok := c.(*ast.Text); ok && t.SoftLineBreak() {
|
|
||||||
buf.WriteByte('\n')
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buf.Write(nodeToHTMLText(c, source))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue