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 官方 Step-by-Step 教程第六步「Data Files」展开讲解如何通过_data目录中的 YAML、JSON、CSV、TSV 文件存储站点内容再经由site.data在 Liquid 模板中读取与遍历。读完本文你将掌握数据文件的存放规则、site.data命名空间映射、子文件夹组织方式、CSV/TSV 解析选项并能在导航、成员列表、作者信息等真实场景中把「内容」与「结构」分离让站点更易维护。为什么需要数据文件Jekyll 是一个博客感知的静态站点生成器Ruby 实现它的核心理念之一是「内容与代码分离」。在 Step 5Includes 中导航条被提取到了_includes/navigation.html但链接仍然是硬编码的nav a href/ {% if page.url / %}stylecolor: red;{% endif %}Home/a a href/about.html {% if page.url /about.html %}stylecolor: red;{% endif %}About/a /nav问题很明显每新增一个导航项都要复制粘贴一行a标签要改变高亮颜色得同时改动多处。Jekyll 的数据文件Data Files正是为解决这类重复而设计——把「导航项是什么」放进数据文件把「导航项怎么渲染」留在模板两者解耦。Jekyll 支持加载位于_data目录下的 YAML、JSON、CSV 与 TSV 文件这些文件在构建时被解析通过site.data暴露给 Liquid 模板系统。这一特性除了减少模板中的重复代码还可以设置站点级选项而无需改动_config.yml插件与主题同样可以借助数据文件来承载配置变量详见 Data Files 官方文档。实战第一步把导航内容存入_data/navigation.yml在站点根目录创建_data/navigation.yml用 YAML 存储一个由「名称 链接」组成的数组- name: Home link: / - name: About link: /about.htmlYAML 是 Ruby 生态中非常常见的格式。这里每个-开头的条目都是一个列表元素每个元素含两个键值对name和link。创建完成后Jekyll 会把这个文件暴露为site.data.navigation变量名取自文件的基本名即不含扩展名的部分。于是_includes/navigation.html就可以改为遍历数据文件{% raw %}nav {% for item in site.data.navigation %} a href{{ item.link }} {% if page.url item.link %}stylecolor: red;{% endif %} {{ item.name }} /a {% endfor %} /nav{% endraw %}渲染输出与硬编码版本完全一致但维护体验天差地别新增导航项只需在navigation.yml中追加一行- name: xxx和link: xxx无需触碰 HTML调整 HTML 结构只改模板一处所有导航项同步生效当前页高亮通过page.url item.link判断规则集中在模板中。这正是数据文件的核心价值把数据与视图分离降低重复、提升可维护性。_data目录支持的格式与命名规则完整的规则见 Data Files 官方文档如下_data目录位于站点源目录下专门存放供 Jekyll 生成站点时使用的额外数据支持的文件扩展名.yml、.yaml、.json、.csv、.tsv所有文件通过site.data访问CSV 与 TSV 文件必须包含表头行默认情况下首行被解析为表头可通过配置关闭见下文「CSV/TSV 解析选项」数据文件的基本名决定变量名_data/members.yml→site.data.members。因此同一目录下应避免出现基本名相同、仅扩展名不同的数据文件如members.yml与members.yaml并存否则会相互覆盖。从源码看DataReader 在读取时正是用File.basename(entry, .*)去掉扩展名作为 Hash 键目录同样会被递归读入键名经sanitize_filename处理移除非法字符、空格转下划线见 test_data_reader.rb 中对sanitize_filename的测试。完整示例用数据文件渲染成员列表这是官方文档给出的最经典用例把一组人员信息放进数据文件避免在模板里复制粘贴大段结构相同的 HTML。_data/members.ymlYAML 写法- name: Eric Mill github: konklone - name: Parker Moore github: parkr - name: Liu Fengyun github: liufengyun_data/members.csv等价的 CSV 写法name,github Eric Mill,konklone Parker Moore,parkr Liu Fengyun,liufengyun两者都可通过site.data.members访问。在模板中渲染{% raw %}ul {% for member in site.data.members %} li a hrefhttps://github.com/{{ member.github }} {{ member.name }} /a /li {% endfor %} /ul{% endraw %}注意CSV 的每一行经过解析后成为一个映射列名即键名name、github与 YAML 中的键保持一致因此两种格式可以无缝切换。仓库测试夹具中的 products.yml- name: sugar / price: 5.3就是这类「列表 键值」结构的真实样例。用子文件夹组织数据命名空间逐级展开数据文件数量增多后可以放进_data的子文件夹中。每一级文件夹都会成为site.data命名空间中的一层。例如_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.jekyll、site.data.orgs.doeorg。由于orgs下每个文件本身是一个 Hash遍历时需要取出每个 Hash 的「值」{% 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 %}org_hash是site.data.orgs中的每一对「键文件名→ 值文件内容」[1]取出值部分再通过点号访问其属性。这与源码中read_data_to的递归行为一致遇到子目录时先为目录名创建嵌套 Hash再继续向下读取data_reader.rb。按需读取通过 front matter 变量定位具体数据项数据文件不仅可以在模板中整体遍历页面与文章还可以按 key 精确访问某一条数据。官方示例_data/people.ymldave: name: David Smith twitter: DavidSilvaSmith在文章的 front matter 中声明作者--- title: sample post author: dave ---模板中用page.author作为下标取回对应数据{% raw %}{% assign author site.data.people[page.author] %} a relauthor hrefhttps://twitter.com/{{ author.twitter }} title{{ author.name }} {{ author.name }} /a{% endraw %}这种「front matter 存 key、数据文件存内容」的模式非常适合多作者博客、多语言站点等场景文章只声明author: dave作者的完整资料名字、主页、头像等统一维护在people.yml中。CSV/TSV 解析选项csv_reader与tsv_readerRuby 解析 CSV/TSV 的方式可以通过_config.yml中的csv_reader与tsv_reader两个配置键自定义二者暴露完全相同的选项配置键说明可选值默认值converters解析时应用的 CSV 转换器integer、float、numeric、date、date_time、all空列表encoding文件编码任意 Ruby 支持的编码名如utf-8站点的encoding配置项headers是否将首行解析为表头true/falsetrue配置示例csv_reader: converters: - numeric - datetime headers: true encoding: utf-8 tsv_reader: converters: - all headers: false源码实现位于 data_reader.rbcsv_config与tsv_config分别读取csv_reader/tsv_reader配置后者额外强制col_sep: \t制表符分隔read_config中converters被映射为 Symbol 数组headers默认trueencoding回退到站点级encoding。读取时.csv与.tsv文件走CSV.read(path, **config)分支其余格式YAML/JSON走SafeYAML.load_filedata_reader.rb。值得注意的两个行为当headers: true时每一行被转换为CSV::Row再to_hash列名成为键convert_row方法data_reader.rb当headers: false时首行被当作普通数据每行是一个数组此时converters: numeric会把数字字符串转成数值——这正是 test_data_reader.rb 中「with csv options set」用例验证的行为id从1变为整数1。源码视角数据文件如何被加载进site.data在构建流程中Site#processsite.rb按read → generate → render → cleanup → write的顺序执行数据读取发生在read阶段。核心实现是Jekyll::DataReaderread(dir)以_data为入口调用read_data_toread_data_to枚举目录中*.{yaml,yml,json,csv,tsv}文件以及子目录跳过符号链接entry_filter.symlink?子目录递归调用自身并将目录名作为下一层 Hash 的键普通文件以基本名作为键、解析结果作为值解析时按扩展名分发CSV/TSV 用CSV.read加对应配置YAML/JSON 用SafeYAML.load_file。这一实现直接决定了你使用数据文件时的几个「边界」数据文件的键是去扩展名后的基本名且经sanitize_filename清洗所以命名应避免特殊字符子目录层级决定命名空间深度深层嵌套会得到site.data.a.b.c式的访问路径_data下的符号链接会被跳过不会参与数据加载。进阶基于数据文件构建健壮导航本教程的数据文件导航是基础形态对于文档站点这类页数众多的场景Navigation 教程提供了更完整的方案体系核心思路与本文一脉相承用 YAML 数据源驱动导航而不是硬编码链接。该教程覆盖了按标题排序sort过滤器、二级/三级嵌套导航、通过page.sidebar等 front matter 变量动态选择数据列表、为当前页添加active类、按版本字段条件渲染条目以及用group_bysort对页面按分类分组等场景值得在掌握基础后继续深入。此外也可参考 Collections 文档了解另一种「按 front matter 属性检索内容」的组织方式。小结与下一步至此你已经完成了数据文件的完整实战在_data/navigation.yml中用 YAML 存储导航数据通过site.data.navigation在 Includes 导航模板 中遍历渲染输出与硬编码一致但更易维护掌握了 YAML/JSON/CSV/TSV 四种格式、命名规则、子文件夹命名空间与按 key 访问学会了用csv_reader/tsv_reader定制 CSV/TSV 的解析行为并理解了DataReader的底层加载逻辑。一个只有文字没有样式的站点显然不够完整。教程的下一步是 Step 7Assets将介绍如何在 Jekyll 中处理 CSS、JavaScript 与图片等静态资源。【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考