Jekyll Front Matter 详解:用 YAML 元数据驱动页面变量与 Liquid 模板渲染
【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll
本文基于 Jekyll 官方分步教程 03-front-matter.md 展开,系统讲解 Front Matter 的定义、语法与实战用法:如何在前置元数据中声明变量、如何在 Liquid 模板中通过page变量读取它们、以及为什么空 Front Matter 就是让 Jekyll 处理 Liquid 标签的"开关"。同时结合仓库源码(lib/jekyll/convertible.rb、lib/jekyll/document.rb),深入解析 Front Matter 的解析正则、YAML 安全加载、渲染流程判定与严格模式等底层实现。
什么是 Front Matter
Front Matter 是一段放置在文件开头、由两条三横线(---)包裹的 YAML 片段。它是 Jekyll 区分"普通静态文件"与"可处理文件"的核心标记——只要文件含有合法的 YAML Front Matter 块,Jekyll 就会把它当作特殊文件来处理。
基本形式如下:
--- my_number: 5 ---两个关键约束:
- 必须位于文件最顶部,且必须是合法 YAML;
- 两条三横线之间是键值对,可以写 Jekyll 预定义变量(见下文),也可以创建任意自定义变量。
这些变量不仅能在当前文件后续的 Liquid 标签中使用,还能在页面所依赖的任何布局和 include 中访问。
在 Liquid 中调用 Front Matter 变量
Front Matter 中的变量通过page对象在 Liquid 中引用。例如上面声明了my_number: 5,就可以在模板任意位置输出:
{{ page.my_number }}从源码结构看,这个映射关系来自 lib/jekyll/convertible.rb 中的to_liquid方法:它把 Front Matter 解析出的data(Hash)、site.frontmatter_defaults配置的默认值以及ATTRIBUTES_FOR_LIQUID中声明的属性合并为一个 Hash,作为 Liquid 的 payload 传入,page注册表正是其中的入口。
实战:用 Front Matter 修改页面标题
下面这个完整示例演示了 Front Matter 与 Liquid 的协作——把站点的<title>改为由 Front Matter 提供:
--- title: Home --- <!doctype html> <html> <head> <meta charset="utf-8"> <title>{{ page.title }}</title> </head> <body> <h1>{{ "Hello World!" | downcase }}</h1> </body> </html>其中{{ page.title }}输出 Front Matter 中定义的Home;downcase是 Liquid 过滤器,把字符串转为小写。
Front Matter 是 Liquid 处理的"开关"
官方教程中有一条重要提示:如果希望 Jekyll 处理页面上的任何 Liquid 标签,该页面必须包含 Front Matter(即使不定义任何变量)。
若只想让 Jekyll 处理页面而不定义变量,写一对空的三横线即可:
--- ---对 CSS 文件、RSS feed 等需要 Liquid 但无需变量的场景尤其有用。
在源码层面可以印证这一设计:lib/jekyll/convertible.rb 的render_with_liquid?方法中,只有当内容包含{%或{{(由 lib/jekyll/utils.rb 的has_liquid_construct?判断)时才会真正执行 Liquid 渲染;而 lib/jekyll/renderer.rb 的render_document正是以该方法的返回值决定是否调用render_liquid。也就是说,"有无 Front Matter + 有无 Liquid 语法"共同决定了渲染路径。
源码级解析:Jekyll 如何读取 Front Matter
Front Matter 的读取集中在 lib/jekyll/convertible.rb 的read_yaml方法中,流程为:
File.read读入文件全部内容到content;用
Document::YAML_FRONT_MATTER_REGEXP匹配头部。该正则定义在 lib/jekyll/document.rb:YAML_FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m.freeze它要求文件以
---起始、以---或 YAML 文档结束符...收尾;匹配成功后,
content被替换为匹配之外的剩余正文(Regexp.last_match.post_match),Front Matter 原文则交给SafeYAML.load解析并赋值给self.data。
这里有两个值得注意的实现细节:
- 使用
SafeYAML.load而非普通 YAML 加载,用于防御恶意 YAML 载荷(如反序列化构造任意对象),仓库中甚至有专门的测试夹具 test/fixtures/exploit_front_matter.erb 验证此类攻击载荷; - Front Matter 必须解析为 Hash:
validate_data!会在data不是 Hash 时抛出InvalidYAMLFrontMatterError("Invalid YAML front matter"),对应测试夹具 test/fixtures/broken_front_matter1.erb 等;validate_permalink!则禁止空的permalink值。
此外,lib/jekyll/utils.rb 中的has_yaml_header?只读取文件首行并匹配%r!\A---\s*\r?\n!,供读取器在列举文件时快速判断"该文件是否带 Front Matter",避免为判断头部而读入整个文件。
常用预定义变量
除了自定义变量,Jekyll 提供了一批开箱即用的 Front Matter 键。页面/文章通用的全局变量包括:
| 变量 | 说明 |
|---|---|
layout | 指定使用的布局文件名(不带扩展名),布局文件必须位于_layouts目录。设为null表示不使用布局(但文章若在 front matter defaults 中定义了 layout 则会被覆盖);自 3.5.0 起,文章中使用none将强制不使用布局(注意:页面中使用none会被当作名为 "none" 的布局查找) |
permalink | 覆盖站点默认的 URL 风格(默认/year/month/day/title.html),其值将直接作为最终输出 URL |
published | 设为false时,该文章不会出现在生成站点中 |
在源码中,published的判定实现于 lib/jekyll/convertible.rb 的published?方法:!(data.key?("published") && data["published"] == false),即仅当显式写入published: false时才视为未发布;预览未发布页面可用jekyll serve或jekyll build加--unpublished开关。
文章(post)专属的预定义变量:
| 变量 | 说明 |
|---|---|
date | 覆盖文件名中携带的日期,格式为YYYY-MM-DD HH:MM:SS +/-TTTT,时、分、秒和时区偏移均可省略,用于保证文章排序正确 |
category/categories | 为一个或多个分类声明文章归属,可写成 YAML 列表或空格分隔的字符串 |
tags | 用法与分类类似,可声明一个或多个标签,支持 YAML 列表或空格分隔字符串 |
若不想在每个文件里重复书写常用变量,可以在站点配置中定义 front matter defaults,仅按需覆盖。
错误处理与严格模式
解析 Front Matter 时,YAML 语法错误(Psych::SyntaxError)或其他标准错误默认只记录警告("YAML Exception reading ...")后继续构建;但可以通过配置开启严格模式——在 lib/jekyll/configuration.rb 中strict_front_matter默认为false,且 lib/jekyll/command.rb 提供了--strict_front_matter命令行选项。开启后,任何 Front Matter 解析异常都会直接raise,适合在 CI 中尽早暴露配置文件问题。
注意事项:UTF-8 BOM
官方 Front Matter 文档特别警告:如果使用 UTF-8 编码,务必确保文件中不含 BOM 头字符,否则会给 Jekyll 带来严重后果。这一点在 Windows 环境下尤其需要注意,因为部分 Windows 文本编辑器默认写入 BOM,导致---不再是文件真正的第一个字符,Front Matter 因此无法被识别。
小结与下一步
Front Matter 是 Jekyll 数据驱动渲染的基石:它既是声明元数据(标题、布局、发布状态、分类标签)的载体,也是激活 Liquid 处理的必要条件。掌握它之后,下一篇分步教程 04-layouts.md 将讲解布局(layouts)机制——理解为什么你的页面需要比纯 HTML 更多的源码,以及布局如何与 Front Matter 中的layout键协作工作。更多 Front Matter 细节可参阅 docs/_docs/front-matter.md,相关行为由 test/source/front_matter 夹具 与strict_front_matter选项在测试中持续验证。
【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考