首页 文章

Jekyll在另一个YAML文件中包含一个YAML文件

提问于
浏览
1

我有一个Jekyll项目,其中两个单独的页面(A.html和B.html)分别根据YAML文件A.yml和B.yml中的数据显示不同的内容 . 每个yml文件都有一堆相同定义的变量 . 我更喜欢将这个常见的变量列表保存在第三个文件C.yml中,并将其包含在A.yml和B.yml中 . 我怎样才能做到这一点?

我试过的事情:

  • 使用*来引用像 *site.data.C.vars 这样的全局数据 - 这没有解析 .

  • 将C.yml放在_includes目录中并使用前面的内容将页面视为液体模板并调用 {% include C.yml %} - 这已编译,但发出的html页面没有任何内容 .

编辑 - 示例用法

在多个视图中使用公共数据文件对我来说还不够,因为还需要在液体中使用名称解析逻辑来配合它 . 以下是我的数据可能如下所示的示例:

A.yml

ingredients:
  - avacado: &avacado
      name: Avacado
      color: Green
      foods:
        - *octopus_ceviche

B.yml

chefs:
  - anthony_bourdain: &anthony_bourdain
      name: Anthony Bourdain
      hobby: Brazilian Jiu-Jitsu
      foods:
        - *octopus_ceviche

C.yml

foods:
  - octopus_ceviche: &octopus_ceviche
      name: Octopus Ceviche
      taste: Delicious

如果没有办法在A和B中包含C.yml,那么所有食物都需要在两个地方共享 . 如果在md / html页面中使用了食物,则需要通过直接散列访问(例如 {{ site.data.foods[octopus_ceviche] }} )访问条目,其中a)似乎不起作用并且b)感觉对于视图来说太多逻辑 .

4 回答

  • 2

    由于Jekyll在加载数据文件时不会使用Liquid处理数据文件,因此无法在 {% include %} 中将一个YAML文件包含在另一个文件中 . YAML本身无法包含其他文件(因为它是基于流的,而不是基于文件的) .

    但是,它没有必要 . 如果将所有公共变量移动到 C.yml ,则可以在两个HTML文件中通过 {{ site.data.C.myvar }} 访问它们,而不需要在 A.ymlB.yml 中包含任何内容 .

  • 0

    基于编辑问题的新答案:

    *octupus_ceviche 是YAML别名,与Liquid无关 . 正如我所说,YAML文件不是用Liquid处理的 . 但是,YAML定义别名必须指向同一文档中的achors . 一个YAML文档必须驻留在一个流中,对于大多数YAML处理器而言,它意味着它不能分成多个文件 .

    话虽这么说,一个有效的选择是将所有数据放入一个YAML文件:

    C:
      foods:
        - octopus_ceviche: &octopus_ceviche
            name: Octopus Ceviche
            taste: Delicious
    A:
      ingredients:
        - avacado: &avacado
            name: Avacado
            color: Green
            foods:
              - *octopus_ceviche
    B:
      chefs:
        - anthony_bourdain: &anthony_bourdain
            name: Anthony Bourdain
            hobby: Brazilian Jiu-Jitsu
            foods:
              - *octopus_ceviche
    

    如果他们的子键在此示例中是不相交的,则可以省略 ABC . 但请注意,即使YAML定义映射键没有顺序,锚也必须始终位于别名前面(文本) . 这就是我在前面移动_1137917的原因 .

    Nota Bene:YAML中的锚和别名被设计用于序列化循环结构 . 使用它们作为命名,可重用的值通常很好 . 但实际上,您不需要包含所有已定义“变量”的列表,您也可以在第一次出现时定义它们 . 例:

    A:
      ingredients:
        - avocado: &avocado
            name: Avocado
            color: Green
            foods:
              - &octopus_ceviche
                name: Octopus Ceviche
                taste: Delicious
    B:
      chefs:
        - anthony_bourdain: &anthony_bourdain
            name: Anthony Bourdain
            hobby: Brazilian Jiu-Jitsu
            foods:
              - *octopus_ceviche
    

    但当然,这可能不太可读 . 因人而异 .

  • 2

    要有一个共同的键值变量列表,请定义第三个数据文件 _data/common.yml .

    然后在 A.htmlB.html 中,您可以访问所有 common.yml 变量:

    {{ site.data.common.myvar }}
    
  • 1

    由于上述问题的措辞,@ flyx是最合适的答案,但是考虑到外部约束(参见my other question),我结束了自己编写的plugin,让数据文件通过液体以文本方式相互包含 .

    这个插件的目标是让数据为:

    • DRY - (不要重复自己)每个模型只应定义一次 .

    • 分组 - 所有类似的数据应以相同的格式定义 .

    • 分离 - 应在不同的地方定义不同的数据 .

    @ flyx的解决方案失败了目标#2和#3,要求在同一个地方定义所有不同类型的数据,并且在第二个建议的情况下混合食物和成分的定义 .

    我提出的解决方案允许将一个数据文件文本包含到另一个数据文这允许在不同的文件中定义不同的模型,但是从其他文件引用,就好像它们是以相同的位置在任意顺序中定义的一样 . 应用于这个问题,我的解决方案是这样的:

    A.yml

    {% include_relative_once C.yml %}
    
     ingredients:
      - avacado: &avacado
          name: Avacado
          color: Green
          foods:
            - *octopus_ceviche
    

    B.yml

    {% include_relative_once C.yml %}
    
    chefs:
      - anthony_bourdain: &anthony_bourdain
          name: Anthony Bourdain
          hobby: Brazilian Jiu-Jitsu
          foods:
            - *octopus_ceviche
    

    C.yml

    foods:
      - octopus_ceviche: &octopus_ceviche
          name: Octopus Ceviche
          taste: Delicious
    

    对于插件本身,请参阅gist

相关问题