强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第4章:Front Matter 详解

第4章:Front Matter 详解

4.1 什么是 Front Matter

Front Matter(前置数据)是 Jekyll 文件开头的 YAML 块,用于为页面和文章提供元数据。它是 Jekyll 处理文件的触发条件——只有包含 Front Matter 的文件才会被 Jekyll 处理。

基本语法

---
title: "我的文章"
date: 2025-01-15
layout: post
---

三横线 --- 标记 Front Matter 的开始和结束,中间是 YAML 格式的键值对。

触发规则

文件情况Jekyll 是否处理说明
有 Front Matter✅ 处理解析 Liquid、Markdown → HTML
无 Front Matter❌ 不处理直接复制到 _site/(仅限静态文件)
空 Front Matter✅ 处理---\n--- 也算有效
---
---
# 这个文件也会被 Jekyll 处理
即使 Front Matter 为空

注意事项:如果你的 .md.html 文件没有被 Jekyll 渲染,首先检查是否遗漏了 Front Matter。


4.2 预定义变量

Jekyll 内置了一系列预定义的 Front Matter 变量。

核心预定义变量

变量类型说明示例
layoutString使用的布局模板"post"
titleString页面/文章标题"Jekyll 入门"
dateDateTime发布日期2025-01-15 10:30:00
publishedBoolean是否发布(设为 false 则不生成)true
permalinkString自定义 URL"/my-page/"
categoriesString/List分类["ruby", "web"]
tagsList标签["tutorial", "beginner"]
descriptionString页面描述(SEO)"文章简介"
excerptString自定义摘要"这是摘要..."
commentsBoolean是否启用评论true
slugStringURL 中的文件名部分自动从文件名提取
extString文件扩展名.md
draftBoolean是否为草稿true

layout 变量

# 使用 _layouts/post.html
layout: post

# 使用 _layouts/page.html
layout: page

# 不使用布局(纯内容输出)
layout: null

# 嵌套布局(见第6章)
layout: default

date 变量

# 精确到秒
date: 2025-01-15 10:30:00 +0800

# 仅日期
date: 2025-01-15

# ISO 8601 格式
date: 2025-01-15T10:30:00+08:00

# 注意:文件名中的日期会作为默认值
# 文件:2025-01-15-my-post.md
# 如果 Front Matter 中没有 date,使用文件名中的 2025-01-15

categories 变量

# 单分类
categories: ruby

# 多分类(字符串方式,空格分隔)
categories: ruby web jekyll

# 多分类(列表方式,推荐)
categories:
  - ruby
  - web
  - jekyll

# 分类会反映在 URL 中
# permalink: /:categories/:year/:month/:day/:title/
# 输出: /ruby/web/2025/01/15/my-post/

tags 变量

# 标签列表
tags:
  - tutorial
  - beginner
  - jekyll

# 行内写法
tags: [tutorial, beginner, jekyll]

categories 与 tags 的区别

  • Categories(分类)是层级化的,可以嵌套:/category/subcategory/
  • Tags(标签)是扁平化的,没有层级关系
  • Categories 影响 URL 结构,Tags 不影响

4.3 自定义变量

你可以在 Front Matter 中定义任意自定义变量,在模板中通过 page.变量名 访问。

常见自定义变量

---
title: "深入理解 Jekyll"
date: 2025-01-15
layout: post

# 自定义变量
author: "张三"
author_email: "[email protected]"
thumbnail: "/images/jekyll-thumb.jpg"
reading_time: "8 min"
difficulty: "intermediate"
series: "Jekyll 完全指南"
series_number: 4
license: "CC BY-NC 4.0"
last_modified_at: 2025-02-01
math: true          # 启用数学公式
mermaid: true       # 启用 Mermaid 图表
toc: true           # 启用目录
---

在模板中使用自定义变量

<!-- _layouts/post.html -->

<article>
  <h1>{{ page.title }}</h1>

  <div class="meta">
    <span class="author">{{ page.author }}</span>
    <span class="reading-time">阅读时间:{{ page.reading_time }}</span>
    {% if page.difficulty %}
      <span class="badge {{ page.difficulty }}">{{ page.difficulty }}</span>
    {% endif %}
  </div>

  {% if page.thumbnail %}
    <img src="{{ page.thumbnail | relative_url }}" alt="{{ page.title }}">
  {% endif %}

  {% if page.toc %}
    <nav class="toc">{{ content | toc_only }}</nav>
  {% endif %}

  <div class="content">
    {{ content }}
  </div>

  {% if page.series %}
    <div class="series-nav">
      <h3>系列:{{ page.series }}</h3>
      <p>第 {{ page.series_number }} 篇</p>
    </div>
  {% endif %}
</article>

访问自定义变量的完整路径

<!-- 在文章/页面模板中 -->
{{ page.author }}

<!-- 在 _includes/ 中通过 include 传递 -->
{% include author-info.html author=page.author %}

<!-- 在 _data/ 循环中 -->
{% for post in site.posts %}
  {{ post.author }}
{% endfor %}

4.4 特殊用途的 Front Matter 变量

published: false

---
title: "未发布的文章"
published: false
---
# 这篇文章不会出现在 _site/ 中
# 也不会出现在 site.posts 中
# 区别于 draft:published 可以放在 _posts/ 中
# 文章级别永久链接
---
title: "关于我"
permalink: /about/
---
# 输出:_site/about/index.html
# 无论源文件在哪里

# 覆盖 _config.yml 的全局设置
permalink: /blog/:title/

redirect_from / redirect_to

# 需要 jekyll-redirect-from 插件
---
title: "我的文章"
redirect_from:
  - /old-url/
  - /another-old-url/
redirect_to: /new-page/   # 整个页面重定向到其他地址
---

sitemap

---
# 控制是否包含在 sitemap.xml 中(需 jekyll-sitemap 插件)
sitemap: false   # 排除此页面
---
---
# 用于排序(取决于主题实现)
nav_order: 3      # 导航菜单排序
weight: 10        # 列表排序权重
---

4.5 Front Matter 默认值(Defaults)

_config.yml 中配置默认值,避免在每个文件中重复声明。

基本配置

# _config.yml
defaults:
  # 为所有 posts 设置默认值
  - scope:
      path: ""
      type: "posts"
    values:
      layout: "post"
      author: "Site Admin"
      comments: true
      toc: true

  # 为所有 pages 设置默认值
  - scope:
      path: ""
      type: "pages"
    values:
      layout: "page"
      author: "Site Admin"

  # 为特定路径设置默认值
  - scope:
      path: "docs"
      type: "pages"
    values:
      layout: "docs"
      sidebar: true

  # 为特定文件设置默认值
  - scope:
      path: "about/index.html"
    values:
      layout: "about-page"

scope 的匹配规则

scope 字段说明示例
path文件路径前缀""(全部)、"docs""docs/api"
type内容类型"posts""pages""projects"(集合名)

优先级规则

文件的 Front Matter > _config.yml defaults > 主题默认值
# _config.yml defaults
defaults:
  - scope:
      type: "posts"
    values:
      layout: "post"
      author: "Default Author"

# _posts/2025-01-15-my-post.md
---
title: "My Post"
author: "Zhang San"    # 覆盖默认值
# layout: "post"       # 使用默认值
---

注意事项

  • Front Matter 中显式设置的值始终优先于 defaults
  • path 匹配是前缀匹配:"docs" 会匹配 "docs/api/guide.md"
  • type 可以是 "posts""pages" 或集合名称

4.6 全局 Front Matter

通过 jekyll-default-front-matter 插件可以为新文件自动添加 Front Matter。

方法一:使用插件

# Gemfile
gem "jekyll-default-front-matter"
# _config.yml
plugins:
  - jekyll-default-front-matter

default_front_matter:
  "*.md":
    author: "Admin"
    comments: true
  "_posts/*":
    layout: "post"
    tags: []

方法二:编辑器模板

# VS Code 设置(settings.json)
"files.associations": {
  "*.md": "markdown"
},
"editor.snippets": {
  "markdown": {
    "New Jekyll Post": {
      "prefix": "jpost",
      "body": [
        "---",
        "title: \"$1\"",
        "date: $CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE",
        "layout: post",
        "categories: [$2]",
        "tags: [$3]",
        "description: \"$4\"",
        "---",
        "",
        "# $1",
        "",
        "$0"
      ]
    }
  }
}

方法三:自定义 Rake 任务

# Rakefile
desc "Create a new post"
task :post, [:title] do |t, args|
  title = args[:title] || "New Post"
  slug = title.downcase.gsub(/\s+/, '-').gsub(/[^\w-]/, '')
  date = Time.now.strftime("%Y-%m-%d")
  filename = "_posts/#{date}-#{slug}.md"

  File.open(filename, 'w') do |f|
    f.puts "---"
    f.puts "title: \"#{title}\""
    f.puts "date: #{Time.now.strftime("%Y-%m-%d %H:%M:%S %z")}"
    f.puts "layout: post"
    f.puts "categories: []"
    f.puts "tags: []"
    f.puts "description: \"\""
    f.puts "---"
    f.puts ""
    f.puts "# #{title}"
    f.puts ""
  end

  puts "Created #{filename}"
end
# 使用 Rake 创建新文章
rake post["Jekyll Front Matter 详解"]

4.7 Front Matter 数据类型

---
# 字符串
title: "Hello World"
# 也可以不加引号
title: Hello World

# 多行字符串
description: >
  This is a very long
  description that spans
  multiple lines.

# 数字
reading_time: 8
priority: 1

# 布尔值
published: true
draft: false
comments: true

# 列表
tags: [jekyll, ruby, tutorial]
# 或
tags:
  - jekyll
  - ruby
  - tutorial

# 日期
date: 2025-01-15 10:30:00 +0800
last_modified_at: 2025-02-01

# 嵌套对象
meta:
  description: "SEO description"
  keywords: [jekyll, static site]
  og_image: "/images/social.png"

# 键值对映射
social_links:
  github: "https://github.com/username"
  twitter: "https://twitter.com/username"
---

4.8 Liquid 中访问 Front Matter

<!-- 访问当前页面的变量 -->
{{ page.title }}
{{ page.date | date: "%Y-%m-%d" }}
{{ page.author }}
{{ page.tags | join: ", " }}

<!-- 访问嵌套对象 -->
{{ page.meta.description }}
{{ page.social_links.github }}

<!-- 访问全局 site 配置 -->
{{ site.title }}
{{ site.description }}

<!-- 条件判断 -->
{% if page.toc %}
  <nav class="toc">...</nav>
{% endif %}

{% if page.math %}
  <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
  <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
{% endif %}

4.9 业务场景:多作者博客

# _config.yml
defaults:
  - scope:
      type: "posts"
    values:
      layout: "post"
      show_author: true

# _data/authors.yml
zhangsan:
  name: "张三"
  avatar: "/images/avatars/zhangsan.jpg"
  bio: "全栈开发者,关注 Web 技术"
  social:
    github: "zhangsan"
    twitter: "zhangsan_dev"

lisi:
  name: "李四"
  avatar: "/images/avatars/lisi.jpg"
  bio: "DevOps 工程师"
# _posts/2025-01-15-jekyll-guide.md
---
title: "Jekyll 入门指南"
author: "zhangsan"
---
<!-- _includes/author-box.html -->
{% assign author = site.data.authors[page.author] %}
{% if author %}
<div class="author-box">
  <img src="{{ author.avatar | relative_url }}" alt="{{ author.name }}">
  <div>
    <strong>{{ author.name }}</strong>
    <p>{{ author.bio }}</p>
  </div>
</div>
{% endif %}

4.10 扩展阅读


本章小结

要点说明
Front Matter 是触发器有 Front Matter 的文件才会被 Jekyll 处理
预定义变量layouttitledatecategoriestags
自定义变量任意键值对,通过 page.变量名 访问
默认值_config.ymldefaults 配置,减少重复
优先级文件 Front Matter > defaults > 主题默认

下一章:Liquid 模板语言