mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
75 lines
2 KiB
Go
75 lines
2 KiB
Go
package images
|
|
|
|
import (
|
|
"github.com/yuin/goldmark"
|
|
"github.com/yuin/goldmark/ast"
|
|
"github.com/yuin/goldmark/parser"
|
|
"github.com/yuin/goldmark/text"
|
|
"github.com/yuin/goldmark/util"
|
|
)
|
|
|
|
type (
|
|
imagesExtension struct {
|
|
wrapStandAloneImageWithinParagraph bool
|
|
}
|
|
)
|
|
|
|
const (
|
|
// Used to signal to the rendering step that an image is used in a block context.
|
|
// Dont's change this; the prefix must match the internalAttrPrefix in the root goldmark package.
|
|
AttrIsBlock = "_h__isBlock"
|
|
AttrOrdinal = "_h__ordinal"
|
|
)
|
|
|
|
func New(wrapStandAloneImageWithinParagraph bool) goldmark.Extender {
|
|
return &imagesExtension{wrapStandAloneImageWithinParagraph: wrapStandAloneImageWithinParagraph}
|
|
}
|
|
|
|
func (e *imagesExtension) Extend(m goldmark.Markdown) {
|
|
m.Parser().AddOptions(
|
|
parser.WithASTTransformers(
|
|
util.Prioritized(&Transformer{wrapStandAloneImageWithinParagraph: e.wrapStandAloneImageWithinParagraph}, 300),
|
|
),
|
|
)
|
|
}
|
|
|
|
type Transformer struct {
|
|
wrapStandAloneImageWithinParagraph bool
|
|
}
|
|
|
|
// Transform transforms the provided Markdown AST.
|
|
func (t *Transformer) Transform(doc *ast.Document, reader text.Reader, pctx parser.Context) {
|
|
var ordinal int
|
|
ast.Walk(doc, func(node ast.Node, enter bool) (ast.WalkStatus, error) {
|
|
if !enter {
|
|
return ast.WalkContinue, nil
|
|
}
|
|
|
|
if n, ok := node.(*ast.Image); ok {
|
|
parent := n.Parent()
|
|
n.SetAttributeString(AttrOrdinal, ordinal)
|
|
ordinal++
|
|
|
|
if !t.wrapStandAloneImageWithinParagraph {
|
|
isBlock := parent.ChildCount() == 1
|
|
if isBlock {
|
|
n.SetAttributeString(AttrIsBlock, true)
|
|
}
|
|
|
|
if isBlock && parent.Kind() == ast.KindParagraph {
|
|
for _, attr := range parent.Attributes() {
|
|
// Transfer any attribute set down to the image.
|
|
// Image elements does not support attributes on its own,
|
|
// so it's safe to just set without checking first.
|
|
n.SetAttribute(attr.Name, attr.Value)
|
|
}
|
|
grandParent := parent.Parent()
|
|
grandParent.ReplaceChild(grandParent, parent, n)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return ast.WalkContinue, nil
|
|
})
|
|
}
|