十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Hugo 短代码 .Inner:在开闭标签之间提取与渲染内容

Hugo 短代码 .Inner:在开闭标签之间提取与渲染内容 Hugo 短代码 .Inner在开闭标签之间提取与渲染内容【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo导读.Inner是 Hugo 短代码shortcode模板中的核心变量之一它返回短代码开标签与闭标签之间的原始内容适用于任何带闭标签的短代码调用。本文以 docs/content/en/methods/shortcode/Inner.md 为骨架结合 hugolib/shortcode.go 等源码系统讲解.Inner的数据结构、取用姿势、空白字符处理以及通过RenderString、markdownify或将整个短代码按 Markdown 渲染{{% %}}写法来把 Inner 内容从纯文本升级为真正的 HTML并给出可直接复制的完整示例。一、.Inner 是什么在 Hugo 中短代码有两种常见调用形态自闭合无内容与成对有内容。当你在 Markdown 源文件中写成对短代码时比如{{/* card titleProduct Design */}} We design the **best** widgets in the world. {{/* /card */}}开标签{{/* card ... */}}与闭标签{{/* /card */}}之间的所有内容——We design the **best** widgets in the world.——就是该短代码的Inner 内容。在短代码模板中通过.Inner即可取用这段内容。从源码看.Inner的类型是template.HTML由 hugolib/shortcode.go 中ShortcodeWithPage结构体定义// ShortcodeWithPage is the . context in a shortcode template. type ShortcodeWithPage struct { Params any Inner template.HTML Page page.Page Parent *ShortcodeWithPage Name string IsNamedParams bool // ... }ShortcodeWithPage就是短代码模板执行时的.上下文因此模板里可以同时访问成员含义.Inner开闭标签之间的原始内容template.HTML类型.Get title按键取短代码参数hugolib/shortcode.go 中的Get方法.Params全部参数.Page当前页面对象.Parent父级短代码上下文支持嵌套短代码.Ordinal该短代码在页面中的零基序号.Store短代码作用域的临时存储替代已废弃的.Scratch需要留意.Inner只有在对短代码的调用包含闭标签时才有效。如果调用是自闭合的没有闭标签、没有内容.Inner为空。源码 hugolib/shortcode.go 甚至会抛出错误提示shortcode %q does not evaluate .Inner or .InnerDeindent, yet a closing tag was provided即模板中使用了.Inner却未提供闭标签时会收到明确的构建错误方便你定位问题。1.1 相关的 InnerDeindent在 hugolib/shortcode.go 中还有一个InnerDeindent()方法当短代码在源文件中带有缩进时它返回去除缩进后的 Inner 内容。它按行遍历把以scp.indentation开标签前的缩进开头的行去掉该前缀。若没有缩进则直接返回.Inner。如果你的短代码内容会被嵌入到缩进敏感的场景如 Markdown 代码块可以考虑使用InnerDeindent而非Inner。二、基础用法把 Inner 作为纯文本输出最直接的用法是在短代码模板中直接输出.Inner。例如定义一个卡片短代码 layouts/_shortcodes/card.html对应前面content/services.md中的调用div classcard {{ with .Get title }} div classcard-title{{ . }}/div {{ end }} div classcard-content {{ .Inner | strings.TrimSpace }} /div /div渲染结果div classcard div classcard-titleProduct Design/div div classcard-content We design the **best** widgets in the world. /div /div这里有两个要点用strings.TrimSpace处理换行。开闭标签之间的内容在 Markdown 中常带有前导/尾随换行取决于书写位置直接输出会破坏布局。strings.TrimSpace会移除首尾的空白包括回车与换行使 Inner 内容紧贴card-content。对应的模板函数定义可参考 tpl/strings/strings.go 的 TrimSpace 实现。默认情况下 Inner 中的 Markdown 不会被渲染。示例里**best**是 Markdown 加粗语法但输出仍是字面**best**——因为.Inner只是原始内容template.HTMLHugo 不会自动对它做 Markdown 转换。2.1 源码视角Inner 内容的收集在 hugolib/shortcode.go 的渲染逻辑中Hugo 会遍历解析出的 inner 数据段普通字符串直接拼接遇到嵌套短代码则递归渲染后拼接最终写入data.Inner。同时对于以 Markdown 渲染模式{{% %}}见下文调用、且内容不含换行的场景源码还会用正则\Ap(.*)/p\n\z剥离包裹的p标签hugolib/shortcode.go避免单行内容被包成段落块。这解释了为什么“按 Markdown 渲染”时单行与多行 Inner 的输出形态会不同。三、用 RenderString 把 Inner 渲染成 HTML要让 Inner 中的 Markdown 真正变成 HTML最简单的方式是把它交给Page.RenderString方法处理。修改上面的模板div classcard {{ with .Get title }} div classcard-title{{ . }}/div {{ end }} div classcard-content {{ .Inner | strings.TrimSpace | .Page.RenderString }} /div /div渲染结果div classcard div classcard-titleProduct design/div div classcard-content We produce the strongbest/strong widgets in the world. /div /divRenderString把 Inner 中经过 TrimSpace 处理后的 Markdown 文本渲染为 HTML**best**→strongbest/strong。关于RenderString的完整说明可参考 docs/content/en/methods/page/RenderString.md。注意示例标题从 Product Design 变为 Product design这只是示例文案本身的差异并非RenderString的副作用——RenderString只负责把 Markdown 渲染为 HTML不会改写标题文本。3.1 markdownify 与 RenderString 的取舍原文档明确指出你也可以用markdownify函数替代RenderString方法但后者更灵活。从 tpl/transform/transform.go 的实现可以看到// Markdownify renders s from Markdown to HTML. func (ns *Namespace) Markdownify(ctx context.Context, s any) (template.HTML, error) { home : ns.deps.Site.Home() if home nil { panic(home must not be nil) } ss, err : home.RenderString(ctx, s) if err ! nil { return , err } // Strip if this is a short inline type of text. bb : ns.deps.ContentSpec.TrimShortHTML([]byte(ss), markdown) return helpers.BytesToHTML(bb), nil }从源码看markdownify内部本质上是基于 Home 页面调用RenderString并额外通过TrimShortHTML对短小行内文本做p剥离处理。而RenderString是Page对象的方法允许指定渲染器与上下文如使用当前页面的配置因此在需要精确控制渲染行为、处理块级内容时更具灵活性。简单行内文本可用markdownify复杂块级内容建议用Page.RenderString。四、替代写法用 {{% %}} 按 Markdown 渲染整个短代码除了在模板内用RenderString二次加工Hugo 还提供第二种思路把整个短代码调用声明为 Markdown 渲染模式。将内容中的{{/* */}}改为{{%/* */%}}记号docs/content/en/content-management/shortcodes 中有完整记号说明{{%/* card titleProduct Design */%}} We design the **best** widgets in the world. {{%/* /card */%}}此时 Hugo 会把整个短代码包括输出结果作为 Markdown 渲染因此需要做两处配合修改。4.1 第一步允许 raw HTML由于短代码模板输出的是 HTML而整体又要走 Markdown 渲染管线必须先在配置中放行 raw HTML{{ code-toggle filehugo }} [markup.goldmark.renderer] unsafe true {{ /code-toggle }}对应hugo.toml的写法[markup.goldmark.renderer] unsafe true安全说明此配置之所以unsafe是因为它允许 Markdown 内容中嵌入未经转义的原始 HTML如果你完全掌控内容源例如个人站点或可信作者团队风险可控。Hugo 的安全模型可参考 docs/content/en/about/security/_index.md。4.2 第二步遵循 CommonMark 缩进与 HTML 块规则因为整个短代码被当作 Markdown 渲染模板输出必须符合 CommonMark 规范 中关于缩进代码块与原始 HTML 块的规则div classcard {{ with .Get title }} div classcard-title{{ . }}/div {{ end }} div classcard-content {{ .Inner | strings.TrimSpace }} /div /div与基础版模板对比差异是微妙但必须的见下面对照--- layouts/_shortcodes/a.html layouts/_shortcodes/b.html -1,8 1,9 div classcard {{ with .Get title }} - div classcard-title{{ . }}/div div classcard-title{{ . }}/div {{ end }} div classcard-content - {{ .Inner | strings.TrimSpace | .Page.RenderString }} {{ .Inner | strings.TrimSpace }} /div /div具体变化有三处调整缩进.card-title从 4 空格缩进改为 2 空格避免被 CommonMark 识别为缩进代码块4 空格及以上会被当作代码块处理。添加空行在.Inner前增加空行确保 Inner 内容作为独立的 HTML 块处理而不是与相邻标签粘连。移除RenderString在{{% %}}记号下不要再对 Inner 做RenderString或markdownify处理——因为整个短代码已经被 Hugo 作为 Markdown 渲染Inner 的 Markdown 会在这一轮渲染中自然转换。若再手动调用RenderString会造成双重渲染。[!NOTE] 使用 Markdown 记号{{% %}}调用短代码时不要用RenderString或markdownify处理 Inner 值。五、两种方案的对比与选择维度方案 A.Inner | .Page.RenderString方案 B{{% %}} unsafe调用记号{{/* */}}{{%/* */%}}是否需配置unsafe true否是是否需遵循 CommonMark 缩进/HTML 块规则否模板输出即最终 HTML是Inner 中 Markdown 渲染方式在模板内显式调用RenderString/markdownify由整段短代码的 Markdown 渲染自动完成灵活性高可精确控制渲染时机、上下文与输出结构低输出受 Markdown 渲染管线约束典型场景内容块、卡片、引用等需要精细控制的组件希望在短代码内外统一走 Markdown 处理流程想要精确控制、不引入全局配置选方案 ARenderString。希望 Markdown 与短代码输出统一处理、且内容源可信选方案 B{{% %}}unsafe true。无论哪种方案都建议对.Inner先做strings.TrimSpace避免开闭标签旁的多余换行影响布局。六、易错点小结忘记闭标签模板里用到.Inner而调用处没有闭标签Hugo 会报错shortcode does not evaluate .Inner ... yet a closing tag was providedhugolib/shortcode.go。Inner 默认不渲染 Markdown直接输出.Inner得到的是字面文本含**等 Markdown 语法需要RenderString或markdownify或在{{% %}}模式下自动处理。未处理首尾换行开闭标签之间的换行会原样进入 Inner记得strings.TrimSpace。{{% %}}模式下重复渲染已整体按 Markdown 渲染时再对 Inner 调用RenderString/markdownify会双重转换。CommonMark 缩进陷阱{{% %}}模式下模板输出的 4 空格缩进可能被当作代码块务必保持 2 空格缩进并正确使用空行分隔 HTML 块。参考资料与源码索引本文核心依据docs/content/en/methods/shortcode/Inner.md.Inner字段定义与InnerDeindent实现hugolib/shortcode.goInner 内容收集与渲染含p剥离逻辑hugolib/shortcode.go、hugolib/shortcode.gomarkdownify实现内部调用RenderStringtpl/transform/transform.goPage.RenderString方法docs/content/en/methods/page/RenderString.md短代码记号说明docs/content/en/content-management/shortcodesHugo 安全模型docs/content/en/about/security/_index.md短代码模板目录约定layouts/_shortcodes/【免费下载链接】hugoThe world’s fastest framework for building websites.项目地址: https://gitcode.com/gh_mirrors/hu/hugo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表