diff options
Diffstat (limited to 'hugolib/shortcode.go')
-rw-r--r-- | hugolib/shortcode.go | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/hugolib/shortcode.go b/hugolib/shortcode.go index 77c5b4e7e..c5125f717 100644 --- a/hugolib/shortcode.go +++ b/hugolib/shortcode.go @@ -28,6 +28,7 @@ import ( "sync" "github.com/gohugoio/hugo/common/herrors" + "github.com/gohugoio/hugo/common/types" "github.com/gohugoio/hugo/parser/pageparser" "github.com/gohugoio/hugo/resources/page" @@ -43,7 +44,7 @@ import ( var ( _ urls.RefLinker = (*ShortcodeWithPage)(nil) - _ pageWrapper = (*ShortcodeWithPage)(nil) + _ types.Unwrapper = (*ShortcodeWithPage)(nil) _ text.Positioner = (*ShortcodeWithPage)(nil) ) @@ -175,15 +176,16 @@ func (scp *ShortcodeWithPage) Get(key any) any { return x.Interface() } -func (scp *ShortcodeWithPage) page() page.Page { +// For internal use only. +func (scp *ShortcodeWithPage) Unwrapv() any { return scp.Page } // Note - this value must not contain any markup syntax const shortcodePlaceholderPrefix = "HAHAHUGOSHORTCODE" -func createShortcodePlaceholder(sid string, id, ordinal int) string { - return shortcodePlaceholderPrefix + strconv.Itoa(id) + sid + strconv.Itoa(ordinal) + "HBHB" +func createShortcodePlaceholder(sid string, id uint64, ordinal int) string { + return shortcodePlaceholderPrefix + strconv.FormatUint(id, 10) + sid + strconv.Itoa(ordinal) + "HBHB" } type shortcode struct { @@ -193,7 +195,6 @@ type shortcode struct { inner []any // string or nested shortcode params any // map or array ordinal int - err error indentation string // indentation from source. @@ -271,9 +272,8 @@ func (sc shortcode) String() string { } type shortcodeHandler struct { - p *pageState - - s *Site + filename string + s *Site // Ordered list of shortcodes for a page. shortcodes []*shortcode @@ -286,9 +286,9 @@ type shortcodeHandler struct { enableInlineShortcodes bool } -func newShortcodeHandler(p *pageState, s *Site) *shortcodeHandler { +func newShortcodeHandler(filename string, s *Site) *shortcodeHandler { sh := &shortcodeHandler{ - p: p, + filename: filename, s: s, enableInlineShortcodes: s.ExecHelper.Sec().EnableInlineShortcodes, shortcodes: make([]*shortcode, 0, 4), @@ -312,14 +312,16 @@ func prepareShortcode( sc *shortcode, parent *ShortcodeWithPage, p *pageState, + isRenderString bool, ) (shortcodeRenderer, error) { toParseErr := func(err error) error { - return p.parseError(fmt.Errorf("failed to render shortcode %q: %w", sc.name, err), p.source.parsed.Input(), sc.pos) + source := p.content.mustSource() + return p.parseError(fmt.Errorf("failed to render shortcode %q: %w", sc.name, err), source, sc.pos) } // Allow the caller to delay the rendering of the shortcode if needed. var fn shortcodeRenderFunc = func(ctx context.Context) ([]byte, bool, error) { - r, err := doRenderShortcode(ctx, level, s, tplVariants, sc, parent, p) + r, err := doRenderShortcode(ctx, level, s, tplVariants, sc, parent, p, isRenderString) if err != nil { return nil, false, toParseErr(err) } @@ -341,6 +343,7 @@ func doRenderShortcode( sc *shortcode, parent *ShortcodeWithPage, p *pageState, + isRenderString bool, ) (shortcodeRenderer, error) { var tmpl tpl.Template @@ -354,13 +357,16 @@ func doRenderShortcode( if !p.s.ExecHelper.Sec().EnableInlineShortcodes { return zeroShortcode, nil } - templName := path.Join("_inline_shortcode", p.File().Path(), sc.name) + templName := path.Join("_inline_shortcode", p.Path(), sc.name) if sc.isClosing { templStr := sc.innerString() var err error tmpl, err = s.TextTmpl().Parse(templName, templStr) if err != nil { + if isRenderString { + return zeroShortcode, p.wrapError(err) + } fe := herrors.NewFileErrorFromName(err, p.File().Filename()) pos := fe.Position() pos.LineNumber += p.posOffset(sc.pos).LineNumber @@ -376,6 +382,7 @@ func doRenderShortcode( return zeroShortcode, fmt.Errorf("no earlier definition of shortcode %q found", sc.name) } } + tmpl = tpl.AddIdentity(tmpl) } else { var found, more bool tmpl, found, more = s.Tmpl().LookupVariant(sc.name, tplVariants) @@ -398,7 +405,7 @@ func doRenderShortcode( case string: inner += innerData case *shortcode: - s, err := prepareShortcode(ctx, level+1, s, tplVariants, innerData, data, p) + s, err := prepareShortcode(ctx, level+1, s, tplVariants, innerData, data, p, isRenderString) if err != nil { return zeroShortcode, err } @@ -505,7 +512,7 @@ func (s *shortcodeHandler) hasName(name string) bool { return ok } -func (s *shortcodeHandler) prepareShortcodesForPage(ctx context.Context, p *pageState, f output.Format) (map[string]shortcodeRenderer, error) { +func (s *shortcodeHandler) prepareShortcodesForPage(ctx context.Context, p *pageState, f output.Format, isRenderString bool) (map[string]shortcodeRenderer, error) { rendered := make(map[string]shortcodeRenderer) tplVariants := tpl.TemplateVariants{ @@ -514,7 +521,7 @@ func (s *shortcodeHandler) prepareShortcodesForPage(ctx context.Context, p *page } for _, v := range s.shortcodes { - s, err := prepareShortcode(ctx, 0, s.s, tplVariants, v, nil, p) + s, err := prepareShortcode(ctx, 0, s.s, tplVariants, v, nil, p, isRenderString) if err != nil { return nil, err } @@ -525,6 +532,25 @@ func (s *shortcodeHandler) prepareShortcodesForPage(ctx context.Context, p *page return rendered, nil } +func posFromInput(filename string, input []byte, offset int) text.Position { + if offset < 0 { + return text.Position{ + Filename: filename, + } + } + lf := []byte("\n") + input = input[:offset] + lineNumber := bytes.Count(input, lf) + 1 + endOfLastLine := bytes.LastIndex(input, lf) + + return text.Position{ + Filename: filename, + LineNumber: lineNumber, + ColumnNumber: offset - endOfLastLine, + Offset: offset, + } +} + // pageTokens state: // - before: positioned just before the shortcode start // - after: shortcode(s) consumed (plural when they are nested) |