mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Add render hooks for inline and block passthrough snippets
Fixes #11927
This commit is contained in:
parent
1781b18427
commit
c6227f1d85
10 changed files with 328 additions and 34 deletions
2
go.mod
2
go.mod
|
@ -40,7 +40,7 @@ require (
|
||||||
github.com/gohugoio/hashstructure v0.1.0
|
github.com/gohugoio/hashstructure v0.1.0
|
||||||
github.com/gohugoio/httpcache v0.7.0
|
github.com/gohugoio/httpcache v0.7.0
|
||||||
github.com/gohugoio/hugo-goldmark-extensions/extras v0.2.0
|
github.com/gohugoio/hugo-goldmark-extensions/extras v0.2.0
|
||||||
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.2.0
|
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.3.0
|
||||||
github.com/gohugoio/locales v0.14.0
|
github.com/gohugoio/locales v0.14.0
|
||||||
github.com/gohugoio/localescompressed v1.0.1
|
github.com/gohugoio/localescompressed v1.0.1
|
||||||
github.com/gohugoio/testmodBuilder/mods v0.0.0-20190520184928-c56af20f2e95
|
github.com/gohugoio/testmodBuilder/mods v0.0.0-20190520184928-c56af20f2e95
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -235,6 +235,8 @@ github.com/gohugoio/hugo-goldmark-extensions/extras v0.2.0 h1:MNdY6hYCTQEekY0oAf
|
||||||
github.com/gohugoio/hugo-goldmark-extensions/extras v0.2.0/go.mod h1:oBdBVuiZ0fv9xd8xflUgt53QxW5jOCb1S+xntcN4SKo=
|
github.com/gohugoio/hugo-goldmark-extensions/extras v0.2.0/go.mod h1:oBdBVuiZ0fv9xd8xflUgt53QxW5jOCb1S+xntcN4SKo=
|
||||||
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.2.0 h1:PCtO5l++psZf48yen2LxQ3JiOXxaRC6v0594NeHvGZg=
|
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.2.0 h1:PCtO5l++psZf48yen2LxQ3JiOXxaRC6v0594NeHvGZg=
|
||||||
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.2.0/go.mod h1:g9CCh+Ci2IMbPUrVJuXbBTrA+rIIx5+hDQ4EXYaQDoM=
|
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.2.0/go.mod h1:g9CCh+Ci2IMbPUrVJuXbBTrA+rIIx5+hDQ4EXYaQDoM=
|
||||||
|
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.3.0 h1:7PY5PIJ2mck7v6R52yCFvvYHvsPMEbulgRviw3I9lP4=
|
||||||
|
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.3.0/go.mod h1:r8g5S7bHfdj0+9ShBog864ufCsVODKQZNjYYY8OnJpM=
|
||||||
github.com/gohugoio/locales v0.14.0 h1:Q0gpsZwfv7ATHMbcTNepFd59H7GoykzWJIxi113XGDc=
|
github.com/gohugoio/locales v0.14.0 h1:Q0gpsZwfv7ATHMbcTNepFd59H7GoykzWJIxi113XGDc=
|
||||||
github.com/gohugoio/locales v0.14.0/go.mod h1:ip8cCAv/cnmVLzzXtiTpPwgJ4xhKZranqNqtoIu0b/4=
|
github.com/gohugoio/locales v0.14.0/go.mod h1:ip8cCAv/cnmVLzzXtiTpPwgJ4xhKZranqNqtoIu0b/4=
|
||||||
github.com/gohugoio/localescompressed v1.0.1 h1:KTYMi8fCWYLswFyJAeOtuk/EkXR/KPTHHNN9OS+RTxo=
|
github.com/gohugoio/localescompressed v1.0.1 h1:KTYMi8fCWYLswFyJAeOtuk/EkXR/KPTHHNN9OS+RTxo=
|
||||||
|
|
|
@ -476,6 +476,11 @@ func (pco *pageContentOutput) initRenderHooks() error {
|
||||||
layoutDescriptor.Kind = "render-image"
|
layoutDescriptor.Kind = "render-image"
|
||||||
case hooks.HeadingRendererType:
|
case hooks.HeadingRendererType:
|
||||||
layoutDescriptor.Kind = "render-heading"
|
layoutDescriptor.Kind = "render-heading"
|
||||||
|
case hooks.PassthroughRendererType:
|
||||||
|
layoutDescriptor.Kind = "render-passthrough"
|
||||||
|
if id != nil {
|
||||||
|
layoutDescriptor.KindVariants = id.(string)
|
||||||
|
}
|
||||||
case hooks.CodeBlockRendererType:
|
case hooks.CodeBlockRendererType:
|
||||||
layoutDescriptor.Kind = "render-codeblock"
|
layoutDescriptor.Kind = "render-codeblock"
|
||||||
if id != nil {
|
if id != nil {
|
||||||
|
|
|
@ -915,6 +915,10 @@ func (hr hookRendererTemplate) RenderCodeblock(cctx context.Context, w hugio.Fle
|
||||||
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
|
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hr hookRendererTemplate) RenderPassthrough(cctx context.Context, w io.Writer, ctx hooks.PassthroughContext) error {
|
||||||
|
return hr.templateHandler.ExecuteWithContext(cctx, hr.templ, w, ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (hr hookRendererTemplate) ResolvePosition(ctx any) text.Position {
|
func (hr hookRendererTemplate) ResolvePosition(ctx any) text.Position {
|
||||||
return hr.resolvePosition(ctx)
|
return hr.resolvePosition(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,19 @@ type CodeblockContext interface {
|
||||||
Ordinal() int
|
Ordinal() int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PassThroughContext is the context passed to a passthrough render hook.
|
||||||
|
type PassthroughContext interface {
|
||||||
|
AttributesProvider
|
||||||
|
text.Positioner
|
||||||
|
PageProvider
|
||||||
|
|
||||||
|
// Currently one of "inline" or "block".
|
||||||
|
Type() string
|
||||||
|
|
||||||
|
// Zero-based ordinal for all passthrough elements in the document.
|
||||||
|
Ordinal() int
|
||||||
|
}
|
||||||
|
|
||||||
type AttributesOptionsSliceProvider interface {
|
type AttributesOptionsSliceProvider interface {
|
||||||
AttributesSlice() []attributes.Attribute
|
AttributesSlice() []attributes.Attribute
|
||||||
OptionsSlice() []attributes.Attribute
|
OptionsSlice() []attributes.Attribute
|
||||||
|
@ -91,6 +104,10 @@ type CodeBlockRenderer interface {
|
||||||
RenderCodeblock(cctx context.Context, w hugio.FlexiWriter, ctx CodeblockContext) error
|
RenderCodeblock(cctx context.Context, w hugio.FlexiWriter, ctx CodeblockContext) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PassthroughRenderer interface {
|
||||||
|
RenderPassthrough(cctx context.Context, w io.Writer, ctx PassthroughContext) error
|
||||||
|
}
|
||||||
|
|
||||||
type IsDefaultCodeBlockRendererProvider interface {
|
type IsDefaultCodeBlockRendererProvider interface {
|
||||||
IsDefaultCodeBlockRenderer() bool
|
IsDefaultCodeBlockRenderer() bool
|
||||||
}
|
}
|
||||||
|
@ -143,6 +160,7 @@ const (
|
||||||
ImageRendererType
|
ImageRendererType
|
||||||
HeadingRendererType
|
HeadingRendererType
|
||||||
CodeBlockRendererType
|
CodeBlockRendererType
|
||||||
|
PassthroughRendererType
|
||||||
)
|
)
|
||||||
|
|
||||||
type GetRendererFunc func(t RendererType, id any) any
|
type GetRendererFunc func(t RendererType, id any) any
|
||||||
|
|
|
@ -101,7 +101,6 @@ func (r *htmlRenderer) renderCodeBlock(w util.BufWriter, src []byte, node ast.No
|
||||||
attrtp = attributes.AttributesOwnerCodeBlockChroma
|
attrtp = attributes.AttributesOwnerCodeBlockChroma
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDefaultCodeBlockRendererProvider
|
|
||||||
attrs, attrStr, err := getAttributes(n.b, info)
|
attrs, attrStr, err := getAttributes(n.b, info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ast.WalkStop, &herrors.TextSegmentError{Err: err, Segment: attrStr}
|
return ast.WalkStop, &herrors.TextSegmentError{Err: err, Segment: attrStr}
|
||||||
|
@ -160,7 +159,7 @@ type codeBlockContext struct {
|
||||||
ordinal int
|
ordinal int
|
||||||
|
|
||||||
// This is only used in error situations and is expensive to create,
|
// This is only used in error situations and is expensive to create,
|
||||||
// to delay creation until needed.
|
// so delay creation until needed.
|
||||||
pos htext.Position
|
pos htext.Position
|
||||||
posInit sync.Once
|
posInit sync.Once
|
||||||
createPos func() htext.Position
|
createPos func() htext.Position
|
||||||
|
|
|
@ -18,15 +18,14 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo-goldmark-extensions/extras"
|
"github.com/gohugoio/hugo-goldmark-extensions/extras"
|
||||||
"github.com/gohugoio/hugo-goldmark-extensions/passthrough"
|
|
||||||
"github.com/gohugoio/hugo/markup/goldmark/hugocontext"
|
|
||||||
"github.com/yuin/goldmark/util"
|
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/markup/goldmark/codeblocks"
|
"github.com/gohugoio/hugo/markup/goldmark/codeblocks"
|
||||||
"github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
|
"github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
|
||||||
|
"github.com/gohugoio/hugo/markup/goldmark/hugocontext"
|
||||||
"github.com/gohugoio/hugo/markup/goldmark/images"
|
"github.com/gohugoio/hugo/markup/goldmark/images"
|
||||||
"github.com/gohugoio/hugo/markup/goldmark/internal/extensions/attributes"
|
"github.com/gohugoio/hugo/markup/goldmark/internal/extensions/attributes"
|
||||||
"github.com/gohugoio/hugo/markup/goldmark/internal/render"
|
"github.com/gohugoio/hugo/markup/goldmark/internal/render"
|
||||||
|
"github.com/gohugoio/hugo/markup/goldmark/passthrough"
|
||||||
|
"github.com/yuin/goldmark/util"
|
||||||
|
|
||||||
"github.com/yuin/goldmark"
|
"github.com/yuin/goldmark"
|
||||||
emoji "github.com/yuin/goldmark-emoji"
|
emoji "github.com/yuin/goldmark-emoji"
|
||||||
|
@ -177,32 +176,7 @@ func newMarkdown(pcfg converter.ProviderConfig) goldmark.Markdown {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Extensions.Passthrough.Enable {
|
if cfg.Extensions.Passthrough.Enable {
|
||||||
configuredInlines := cfg.Extensions.Passthrough.Delimiters.Inline
|
extensions = append(extensions, passthrough.New(cfg.Extensions.Passthrough))
|
||||||
configuredBlocks := cfg.Extensions.Passthrough.Delimiters.Block
|
|
||||||
|
|
||||||
inlineDelimiters := make([]passthrough.Delimiters, len(configuredInlines))
|
|
||||||
blockDelimiters := make([]passthrough.Delimiters, len(configuredBlocks))
|
|
||||||
|
|
||||||
for i, d := range configuredInlines {
|
|
||||||
inlineDelimiters[i] = passthrough.Delimiters{
|
|
||||||
Open: d[0],
|
|
||||||
Close: d[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, d := range configuredBlocks {
|
|
||||||
blockDelimiters[i] = passthrough.Delimiters{
|
|
||||||
Open: d[0],
|
|
||||||
Close: d[1],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions = append(extensions, passthrough.New(
|
|
||||||
passthrough.Config{
|
|
||||||
InlineDelimiters: inlineDelimiters,
|
|
||||||
BlockDelimiters: blockDelimiters,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if pcfg.Conf.EnableEmoji() {
|
if pcfg.Conf.EnableEmoji() {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"math/bits"
|
"math/bits"
|
||||||
|
|
||||||
"github.com/gohugoio/hugo/markup/converter"
|
"github.com/gohugoio/hugo/markup/converter"
|
||||||
|
"github.com/yuin/goldmark/ast"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BufWriter struct {
|
type BufWriter struct {
|
||||||
|
@ -40,9 +41,19 @@ func (b *BufWriter) Flush() error {
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
*BufWriter
|
*BufWriter
|
||||||
|
ContextData
|
||||||
positions []int
|
positions []int
|
||||||
pids []uint64
|
pids []uint64
|
||||||
ContextData
|
ordinals map[ast.NodeKind]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *Context) GetAndIncrementOrdinal(kind ast.NodeKind) int {
|
||||||
|
if ctx.ordinals == nil {
|
||||||
|
ctx.ordinals = make(map[ast.NodeKind]int)
|
||||||
|
}
|
||||||
|
i := ctx.ordinals[kind]
|
||||||
|
ctx.ordinals[kind]++
|
||||||
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *Context) PushPos(n int) {
|
func (ctx *Context) PushPos(n int) {
|
||||||
|
|
219
markup/goldmark/passthrough/passthrough.go
Normal file
219
markup/goldmark/passthrough/passthrough.go
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
// Copyright 2024 The Hugo Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package passthrough
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
htext "github.com/gohugoio/hugo/common/text"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo-goldmark-extensions/passthrough"
|
||||||
|
"github.com/gohugoio/hugo/markup/converter/hooks"
|
||||||
|
"github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
|
||||||
|
"github.com/gohugoio/hugo/markup/goldmark/internal/render"
|
||||||
|
"github.com/gohugoio/hugo/markup/internal/attributes"
|
||||||
|
"github.com/yuin/goldmark"
|
||||||
|
"github.com/yuin/goldmark/ast"
|
||||||
|
"github.com/yuin/goldmark/renderer"
|
||||||
|
"github.com/yuin/goldmark/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(cfg goldmark_config.Passthrough) goldmark.Extender {
|
||||||
|
if !cfg.Enable {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &passthroughExtension{cfg: cfg}
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
passthroughExtension struct {
|
||||||
|
cfg goldmark_config.Passthrough
|
||||||
|
}
|
||||||
|
htmlRenderer struct{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e *passthroughExtension) Extend(m goldmark.Markdown) {
|
||||||
|
configuredInlines := e.cfg.Delimiters.Inline
|
||||||
|
configuredBlocks := e.cfg.Delimiters.Block
|
||||||
|
|
||||||
|
inlineDelimiters := make([]passthrough.Delimiters, len(configuredInlines))
|
||||||
|
blockDelimiters := make([]passthrough.Delimiters, len(configuredBlocks))
|
||||||
|
|
||||||
|
for i, d := range configuredInlines {
|
||||||
|
inlineDelimiters[i] = passthrough.Delimiters{
|
||||||
|
Open: d[0],
|
||||||
|
Close: d[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, d := range configuredBlocks {
|
||||||
|
blockDelimiters[i] = passthrough.Delimiters{
|
||||||
|
Open: d[0],
|
||||||
|
Close: d[1],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pse := passthrough.New(
|
||||||
|
passthrough.Config{
|
||||||
|
InlineDelimiters: inlineDelimiters,
|
||||||
|
BlockDelimiters: blockDelimiters,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
pse.Extend(m)
|
||||||
|
|
||||||
|
// Set up render hooks if configured.
|
||||||
|
// Upstream passthrough inline = 101
|
||||||
|
// Upstream passthrough block = 99
|
||||||
|
m.Renderer().AddOptions(renderer.WithNodeRenderers(
|
||||||
|
util.Prioritized(newHTMLRenderer(), 90),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
func newHTMLRenderer() renderer.NodeRenderer {
|
||||||
|
r := &htmlRenderer{}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *htmlRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
||||||
|
reg.Register(passthrough.KindPassthroughBlock, r.renderPassthroughBlock)
|
||||||
|
reg.Register(passthrough.KindPassthroughInline, r.renderPassthroughBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *htmlRenderer) renderPassthroughBlock(w util.BufWriter, src []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||||
|
ctx := w.(*render.Context)
|
||||||
|
|
||||||
|
if entering {
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
s string
|
||||||
|
typ string
|
||||||
|
delims *passthrough.Delimiters
|
||||||
|
)
|
||||||
|
|
||||||
|
switch nn := node.(type) {
|
||||||
|
case *passthrough.PassthroughInline:
|
||||||
|
s = string(nn.Text(src))
|
||||||
|
typ = "inline"
|
||||||
|
delims = nn.Delimiters
|
||||||
|
case (*passthrough.PassthroughBlock):
|
||||||
|
l := nn.Lines().Len()
|
||||||
|
var buff bytes.Buffer
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
line := nn.Lines().At(i)
|
||||||
|
buff.Write(line.Value(src))
|
||||||
|
}
|
||||||
|
s = buff.String()
|
||||||
|
typ = "block"
|
||||||
|
delims = nn.Delimiters
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer := ctx.RenderContext().GetRenderer(hooks.PassthroughRendererType, typ)
|
||||||
|
if renderer == nil {
|
||||||
|
// Write the raw content if no renderer is found.
|
||||||
|
ctx.WriteString(s)
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inline and block passthroughs share the same ordinal counter.
|
||||||
|
ordinal := ctx.GetAndIncrementOrdinal(passthrough.KindPassthroughBlock)
|
||||||
|
|
||||||
|
// Trim the delimiters.
|
||||||
|
s = s[len(delims.Open) : len(s)-len(delims.Close)]
|
||||||
|
|
||||||
|
pctx := &passthroughContext{
|
||||||
|
ordinal: ordinal,
|
||||||
|
page: ctx.DocumentContext().Document,
|
||||||
|
pageInner: r.getPageInner(ctx),
|
||||||
|
inner: s,
|
||||||
|
typ: typ,
|
||||||
|
AttributesHolder: attributes.New(node.Attributes(), attributes.AttributesOwnerGeneral),
|
||||||
|
}
|
||||||
|
|
||||||
|
pctx.createPos = func() htext.Position {
|
||||||
|
if resolver, ok := renderer.(hooks.ElementPositionResolver); ok {
|
||||||
|
return resolver.ResolvePosition(pctx)
|
||||||
|
}
|
||||||
|
return htext.Position{
|
||||||
|
Filename: ctx.DocumentContext().Filename,
|
||||||
|
LineNumber: 1,
|
||||||
|
ColumnNumber: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pr := renderer.(hooks.PassthroughRenderer)
|
||||||
|
|
||||||
|
if err := pr.RenderPassthrough(ctx.RenderContext().Ctx, w, pctx); err != nil {
|
||||||
|
return ast.WalkStop, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast.WalkContinue, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *htmlRenderer) getPageInner(rctx *render.Context) any {
|
||||||
|
pid := rctx.PeekPid()
|
||||||
|
if pid > 0 {
|
||||||
|
if lookup := rctx.DocumentContext().DocumentLookup; lookup != nil {
|
||||||
|
if v := rctx.DocumentContext().DocumentLookup(pid); v != nil {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rctx.DocumentContext().Document
|
||||||
|
}
|
||||||
|
|
||||||
|
type passthroughContext struct {
|
||||||
|
page any
|
||||||
|
pageInner any
|
||||||
|
typ string // inner or block
|
||||||
|
inner string
|
||||||
|
ordinal int
|
||||||
|
|
||||||
|
// This is only used in error situations and is expensive to create,
|
||||||
|
// so delay creation until needed.
|
||||||
|
pos htext.Position
|
||||||
|
posInit sync.Once
|
||||||
|
createPos func() htext.Position
|
||||||
|
*attributes.AttributesHolder
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *passthroughContext) Page() any {
|
||||||
|
return p.page
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *passthroughContext) PageInner() any {
|
||||||
|
return p.pageInner
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *passthroughContext) Type() string {
|
||||||
|
return p.typ
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *passthroughContext) Inner() string {
|
||||||
|
return p.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *passthroughContext) Ordinal() int {
|
||||||
|
return p.ordinal
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *passthroughContext) Position() htext.Position {
|
||||||
|
p.posInit.Do(func() {
|
||||||
|
p.pos = p.createPos()
|
||||||
|
})
|
||||||
|
return p.pos
|
||||||
|
}
|
62
markup/goldmark/passthrough/passthrough_integration_test.go
Normal file
62
markup/goldmark/passthrough/passthrough_integration_test.go
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright 2024 The Hugo Authors. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package passthrough_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/hugolib"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPassthroughRenderHook(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
files := `
|
||||||
|
-- config.toml --
|
||||||
|
[markup.goldmark.extensions.passthrough]
|
||||||
|
enable = true
|
||||||
|
[markup.goldmark.extensions.passthrough.delimiters]
|
||||||
|
block = [['$$', '$$']]
|
||||||
|
inline = [['$', '$']]
|
||||||
|
-- content/p1.md --
|
||||||
|
---
|
||||||
|
title: "p1"
|
||||||
|
---
|
||||||
|
## LaTeX test
|
||||||
|
|
||||||
|
Some inline LaTeX 1: $a^*=x-b^*$.
|
||||||
|
|
||||||
|
Block equation that would be mangled by default parser:
|
||||||
|
|
||||||
|
$$a^*=x-b^*$$
|
||||||
|
|
||||||
|
Some inline LaTeX 2: $a^*=x-b^*$.
|
||||||
|
|
||||||
|
-- layouts/_default/single.html --
|
||||||
|
{{ .Content }}
|
||||||
|
-- layouts/_default/_markup/render-passthrough-block.html --
|
||||||
|
Passthrough block: {{ .Inner | safeHTML }}|{{ .Type }}|{{ .Ordinal }}:END
|
||||||
|
-- layouts/_default/_markup/render-passthrough-inline.html --
|
||||||
|
Passthrough inline: {{ .Inner | safeHTML }}|{{ .Type }}|{{ .Ordinal }}:END
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
b := hugolib.Test(t, files)
|
||||||
|
b.AssertFileContent("public/p1/index.html", `
|
||||||
|
Some inline LaTeX 1: Passthrough inline: a^*=x-b^*|inline|0:END
|
||||||
|
Passthrough block: a^*=x-b^*|block|1:END
|
||||||
|
Some inline LaTeX 2: Passthrough inline: a^*=x-b^*|inline|2:END
|
||||||
|
|
||||||
|
`)
|
||||||
|
}
|
Loading…
Reference in a new issue