尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Jekyll 数据文件(Data Files)完全指南:用 `_data` 目录管理站点数据与模板变量

Jekyll 数据文件(Data Files)完全指南:用 `_data` 目录管理站点数据与模板变量 Jekyll 数据文件Data Files完全指南用_data目录管理站点数据与模板变量【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll本篇技术指南以 Jekyll 官方文档《Data Files》为骨架系统讲解如何通过_data目录为站点加载 YAML、JSON、CSV 与 TSV 数据并结合本仓库jekyll 静态站点生成器的 Ruby 实现源码深入剖析数据读取的底层机制、目录命名空间规则与 CSV/TSV 解析选项。读完本文你将掌握site.data的完整用法——从团队名单渲染、组织架构展示到用 front matter 关联特定数据项再到自定义 CSV/TSV 解析行为并理解这些能力在 DataReader 中的真实实现。什么是 Jekyll 数据文件在 Jekyll 生成站点时除了 Jekyll 内置的全局变量如site、page、content之外你还可以通过数据文件Data Files自定义数据并通过 Liquid 模板系统在页面中访问这些数据。Jekyll 支持从位于_data目录下的 YAML、JSON、CSV 和 TSV 文件加载数据。注意CSV 和 TSV 文件必须包含表头行header row否则解析结果将不符合预期。这一特性能够帮你避免在模板中反复复制大段重复代码也可以在不修改_config.yml的情况下为站点设置特定选项。此外插件plugins和主题themes同样可以借助数据文件来设置配置变量。_data目录数据文件的存放位置_data文件夹是存放站点附加数据的标准位置站点生成时会自动加载这些数据。支持的文件扩展名为.yml.yaml.json.tsv.csv加载后的数据统一通过site.data访问。该目录名本身也是可配置的——在 configuration.rb 中默认配置data_dir _data你可以通过_config.yml中的data_dir选项将其指向其他目录。底层读取机制数据文件的加载由 Reader#read_data 触发其核心逻辑如下def read_data site.data DataReader.new(site).read(site.config[data_dir]) return unless site.theme.data_path theme_data DataReader.new( site, :in_source_dir site.method(:in_theme_dir) ).read(site.theme.data_path) site.data Jekyll::Utils.deep_merge_hashes(theme_data, site.data) end也就是说Jekyll 会先读取站点自身的_data目录如果当前站点使用了主题且主题包含数据文件还会读取主题内的数据并通过deep_merge_hashes合并——站点数据会覆盖主题中同键的数据。真正执行目录扫描与解析的是 DataReader其read_data_to方法遍历目录entries Dir.chdir(dir) do Dir[*.{yaml,yml,json,csv,tsv}] Dir[*].select { |fn| File.directory?(fn) } end文件按扩展名分发解析.csv与.tsv走 Ruby 标准库CSV解析其余格式交由SafeYAML.load_file处理子目录会被递归读取并作为嵌套的 Hash 键文件名不含扩展名经过sanitize_filename清洗后成为变量名非法字符会被移除连续空白会被替换为下划线。示例一成员列表Members用数据文件避免在模板中复制粘贴大段代码是最典型的用法。假设你有一个成员列表在_data/members.yml中- name: Eric Mill github: konklone - name: Parker Moore github: parkr - name: Liu Fengyun github: liufengyun等价地也可以使用_data/members.csvname,github Eric Mill,konklone Parker Moore,parkr Liu Fengyun,liufengyun这份数据可以通过site.data.members访问——文件的基础名basename决定了变量名。因此应避免在同一个目录下存放基础名相同但扩展名不同的数据文件例如members.yml与members.json同时存在会相互覆盖。随后在模板中渲染成员列表{% raw %}ul {% for member in site.data.members %} li a hrefhttps://github.com/{{ member.github }} {{ member.name }} /a /li {% endfor %} /ul{% endraw %}本仓库的 data.feature 通过 Cucumber 特性测试完整验证了这一行为分别针对*.yaml、*.yml、*.json、*.csv、*.tsv文件在index.html中写入{% for member in site.data.members %}{{member.name}}{% endfor %}并执行jekyll build最终断言_site/index.html中出现了预期的姓名。支持的文件格式除 YAML/CSV 外JSON 同样可以直接作为列表数据源。测试夹具 members.json 展示了 JSON 数组写法[ { name: Jack, age: 27, blog: http://example.com/jack }, { name: John, age: 32, blog: http://example.com/john } ]访问方式与 YAML 完全一致site.data.members就是一个由 Hash 组成的数组。子目录命名空间化的数据组织数据文件还可以放在_data的子目录中。每一层目录都会成为变量命名空间的一部分。例如将 GitHub 组织分别定义在orgs文件夹下的不同文件中在_data/orgs/jekyll.ymlusername: jekyll name: Jekyll members: - name: Tom Preston-Werner github: mojombo - name: Parker Moore github: parkr在_data/orgs/doeorg.ymlusername: doeorg name: Doe Org members: - name: John Doe github: jdoe这些组织可以通过site.data.orgs加文件名进行访问。由于site.data.orgs是一个以文件名为键的 Hash遍历时需借助 Liquid 的org_hash[1]取出值{% raw %}ul {% for org_hash in site.data.orgs %} {% assign org org_hash[1] %} li a hrefhttps://github.com/{{ org.username }} {{ org.name }} /a ({{ org.members | size }} members) /li {% endfor %} /ul{% endraw %}从源码看子目录的递归读取实现在 DataReader#read_data_toif File.directory?(path) read_data_to(path, data[sanitize_filename(entry)] {}) else key sanitize_filename(File.basename(entry, .*)) data[key] read_data_file(path) end即目录名作为外层键如orgs目录内每个文件的 basename 作为内层键如jekyll、doeorg最终形成site.data.orgs.jekyll、site.data.orgs.doeorg这样的访问路径。另外需要注意的细节是同名目录优先于同名文件。在 data.feature 中有一个专门场景——当_data/categories目录与_data/categories.yaml文件同时存在时渲染结果取目录中的dairy.yaml内容“Dairy Products”而非文件内容。这是由read_data_to中先遍历子目录、后处理同名文件文件会覆盖目录键的顺序决定的实际效果是目录内容先被写入同名文件再覆盖——因此在上述测试场景中目录被递归读取后其键又被categories.yaml的 Hash 覆盖实际上测试断言显示目录内容胜出这源于Dir[*.{yaml,yml,json,csv,tsv}]与目录列表的合并顺序中目录在前测试以目录内容为准具体行为以 data.feature 场景为准。示例二访问特定的数据项页面和文章还可以直接访问某一个特定的数据项。假设_data/people.ymldave: name: David Smith twitter: DavidSilvaSmith然后在文章的 front matter 中把作者指定为页面变量{% raw %}--- title: sample post author: dave --- {% assign author site.data.people[page.author] %} a relauthor hrefhttps://twitter.com/{{ author.twitter }} title{{ author.name }} {{ author.name }} /a{% endraw %}这里的site.data.people[page.author]使用 Liquid 的方括号动态索引通过page.author的值dave在site.data.people这个 Hash 中查找到对应的作者信息。这种“数据 front matter 引用”的模式非常适合博客作者署名、产品文档作者信息等场景。如果你需要为文档类站点或页面数量很多的 Jekyll 站点构建健壮的导航可参考 导航教程。CSV/TSV 解析选项Ruby 解析 CSV 和 TSV 文件的方式可以通过csv_reader与tsv_reader配置项进行定制。两个配置键暴露的选项完全相同配置项说明converters解析文件时使用哪些 CSV converters。可用值为integer、float、numeric、date、date_time和all。默认此列表为空。encoding文件的编码格式。默认为站点encoding配置选项。headers布尔值决定是否将文件第一行解析为表头。为false时把第一行当作数据。默认为true。配置示例csv_reader: converters: - numeric - datetime headers: true encoding: utf-8 tsv_reader: converters: - all headers: false配置项的底层实现这些选项在 DataReader#read_config 中被读取并转换为 Ruby CSV 库的参数def read_config(config_key, overrides {}) reader_config config[config_key] || {} defaults { :converters reader_config.fetch(csv_converters, []).map(:to_sym), :headers reader_config.fetch(headers, true), :encoding reader_config.fetch(encoding, config[encoding]), } defaults.merge(overrides) end几点值得注意的实现细节converters会被字符串化后转为 Symbol如numeric→:numeric再传给 Ruby CSV 的converters选项headers默认值为true这正是“CSV/TSV 必须包含表头行”的原因——第一行会被当作列名CSV.read返回CSV::Row对象随后经 convert_row 转换为 Hashdef convert_row(row) row.instance_of?(CSV::Row) ? row.to_hash : row end当headers: false时行是纯数组原样返回TSV 在 tsv_config 中额外覆盖了:col_sep \t即使用制表符作为列分隔符其余选项与 CSV 共享默认值。测试 test_data_reader.rb 对两种行为都有覆盖默认情况下 sample.csvid,field_a被解析为[{id1, field_afoo}, ...]的 Hash 数组而当设置csv_converters [:numeric], headers false后同一文件被解析为[%w(id field_a), [1, foo], [2, bar]]——第一行变成数据行数值列被转换为整数。测试夹具 sample.tsv 以制表符分隔验证同样的行为。数据文件的实际应用场景小结综合以上内容数据文件在 Jekyll 站点中常见的落地方式包括团队/成员/贡献者列表YAML 或 CSV 数组 {% for %}循环渲染组织或分类的层级数据_data子目录天然形成命名空间按目录文件名组织多组数据作者、产品、FAQ 等条目化数据配合 front matter 变量如author: dave实现按需索引站点级自定义选项无需改动_config.yml直接以site.data.*访问主题/插件的配置注入主题可携带数据文件插件可读取site.data完成配置。从仓库实现看数据文件加载发生在站点构建流程的Reader#read阶段见 reader.rb与布局、页面、集合等资源的读取并列属于每次jekyll build的标准流程因此任何一次构建都会自动拾取_data目录的最新内容。总结_data目录是 Jekyll 加载 YAML、JSON、CSV、TSV 数据的固定位置默认可通过_config.yml的data_dir调整数据通过site.data访问文件名basename决定变量名子目录名决定命名空间层级CSV/TSV 必须含表头行headers默认为true其解析行为可通过csv_reader/tsv_reader的converters、encoding、headers三项配置定制数据文件的加载、清洗、递归与解析分别由 Reader#read_data 与 DataReader 实现测试覆盖见 data.feature 与 test_data_reader.rb。掌握数据文件机制后你就可以在模板中摆脱硬编码、以声明式的方式组织站点内容并让主题与插件共享同一份可维护的数据源。【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表