自定义 Jekyll 插件(液体过滤器?)将脚本标签呈现为文本,而不是 JavaScript

Posted

技术标签:

【中文标题】自定义 Jekyll 插件(液体过滤器?)将脚本标签呈现为文本,而不是 JavaScript【英文标题】:Custom Jekyll Plugin (Liquid Filter?) rendering script tags as text, not as JavaScript 【发布时间】:2020-02-27 20:46:32 【问题描述】:

我正在为朋友尝试使用 Jekyll 构建网站。

我正在尝试将前端内容从 /_events/2020-02-25-an-event.md/_events/2020-02-26-another-event.md 之类的文件转换为可以轻松嵌入到各种内容构建块的主体中​​并导致访问者查看的这些页面的内容,包括<script type="application/ld+json">...</script> 标签符合schema.org event 标准。

/_events/2020-02-25-an-event.md 这样的文件看起来像这样:

---
layout: event
title: An event
published: true
startdatetime: 2020-02-28
venue: Best Club Ever
---

events 集合的成员旨在呈现为单独的可查看 URL,并且应该在其呈现的输出中隐藏 javascript 的 sn-p,如下所示:

<script type="application/ld+json">
    [
        
            "@context" : "http://schema.org",
            "@type" : "Event",
            "name" : "An event",
            "startDate" : "2020-02-28",
            "location" : "Best Club Ever blah blah ... have address stuff to work out, still"
        
    ]
</script>

我通过编写/_plugins/event_schema.rb 来实现这一点,如下所示:

require 'liquid'

module EventSchemaFilters

  def do_not_use_me_directly_single_json_curly(input_object)
    %Q(
        
            "@context" : "http://schema.org",
            "@type" : "Event",
            "name" : "#input_object['title']",
            "startDate" : "#input_object['startdatetime']",
            "location" : "#input_object['venue']"
        
    )
  end

  def event_single_schema_script(input_object)
    %Q(
        <script type="application/ld+json">
        [
            #do_not_use_me_directly_single_json_curly(input_object)
        ]
        </script>
    )
  end

  def event_multiple_schema_script(input_object_array)
    %Q(
        <script type="application/ld+json">
        [
            #input_object_array.map(&method(:do_not_use_me_directly_single_json_curly)).join(',')
        ]
        </script>
    )
  end

  def event_multiple_schema_script(input_object_array)
    %Q(
        <script type="application/ld+json">
        [
            #input_object_array.map(&method(:do_not_use_me_directly_single_json_curly)).join(',')
        ]
        </script>
    )
  end

  end

Liquid::Template.register_filter(EventSchemaFilters)

然后写/_layouts/event.html(查找“页面”布局,查找“默认”布局)为:

---
layout: page
---

 page | event_single_schema_script 

不幸的是,如果我这样写/index.md,虽然我得到了一些即将发生的事件,但它会被&lt;code&gt;...&lt;/code&gt; 标签包围,并显示在主页的正文中:

---
title: Home Page
layout: default
---

#  page.title 

 site.events | event_multiple_schema_script 

希望这个脚本成为 DOM 的 JavaScript 的一部分……而不是页面上文本的一部分:

<script type="application/ld+json">
    [
        
            "@context" : "http://schema.org",
            "@type" : "Event",
            "name" : "An event",
            "startDate" : "2020-02-28",
            "location" : "Best Club Ever blah blah ... have address stuff to work out, still"
        
        ,
        
            "@context" : "http://schema.org",
            "@type" : "Event",
            "name" : "Another event",
            "startDate" : "2020-02-27",
            "location" : "Less Good Club blah blah ... have address stuff to work out, still"
        
    ]
</script>

site.events | event_multiple_schema_script 移动为/_includes/event_all_schema_script.html 的内容并尝试% include event_all_schema_script.html % 根本没有帮助——同样的问题。

/index.md 中删除对% include event_all_schema_script.html % 的调用并将其放入/_layouts/default.html,而不是确实按照我想要的方式呈现。但现在它在每一页上,包括像https://example.com/events/2020-02-25-an-event/ 这样的页面,这不是我想要的。但它确实表明我的问题是我写了一些我不能只是“注入”到降价中的东西......这将成为一个网页。

/index.md 中也有效但不是我想做的事情:

手写&lt;script&gt;...&lt;/script&gt;代码直接进入其中 将% include event_all_schema_script_hardcode.html % 放入其中,其中/_includes/event_all_schema_script_hardcode.html 实际上只是&lt;script&gt;...&lt;/script&gt; 从我向大家展示的输出中复制粘贴的文本。 如果“傻瓜生成器”材料不那么难找到(Jekyll 文档不是很丰富;Google 没用,因为“静态站点生成器”这个词很流行),也许我可以编写可以在构建时构建这样一个文件的代码?不过,就我目前的 Jekyll/Ruby 知识而言,这似乎是一个相当高的障碍。

顺便说一句,我愿意重新设计它。不依附于“过滤”诸如site.events 之类的东西的想法。这只是我在“hello world”中得到的。

我在最终设计中真正遵循的唯一原则:

“事件”日历中的所有数据输入都应通过 events 集合中的项目的前面事项完成(这样我就可以使用 Forestry.io 或 Netlify CMS 之类的 CMS 来配合它). &lt;script&gt;...&lt;/script&gt; 块内容的计算应该在“独立的、可插入的组件”中进行。 我不想在 /_layouts/homepage.html 内做一个大的 Liquid 循环,我必须提醒网页设计师复制/粘贴到 /_layouts/better_homepage.html。 相反,我只想告诉网页设计师,“嘿,如果您想让页面的元数据包含事件提要,只需将 % include event_all_schema_script.html % 拖放到页面或其布局中的某个位置即可。” 我希望 % include event_all_schema_script.html % 或这里的任何同等人员帮助我想出,同时在页面/帖子/收藏标记的正文和布局中工作。 我将利用我从中学到的知识编写“普通的 DIV,供网页设计师按照他们认为合适的方式设置样式”,例如 /_includes/event_all_div.html/_includes/event_single_div.html,并让它们在任何地方使用网页设计师认为合适 - 在降价或布局中。 再说一次,我不是网页设计师。我只是数据结构转换的人。我唯一的目标是生成漂亮、“乏味”的 HTML sn-ps,这些 HTML 格式可供适当的网页设计师重复使用并按照他们认为合适的方式设置样式。

我有什么想法可以改进这种呈现 HTML 的尝试,使其对布局和降价都友好吗?

非常感谢。

【问题讨论】:

使用/_includes/evnt.json 作为"@context" : "http://schema.org", "@type" : "Event", "name" : " include.event_name "/_includes/all_evts_script.html 作为&lt;script type="application/ld+json"&gt;[% for evt in site.events %% include evnt.json event_name=evt.title %% unless forloop.last %,% endunless %% endfor %]&lt;/script&gt;/_includes/single_evt_page_script.html 作为% if page.collection == 'events' %&lt;script type="application/ld+json"&gt;[% include evnt.json event_name=page.title %]&lt;/script&gt;% endif % 的解决方法,但仍然是?为什么函数调用在 Markdown 中渲染不好。 【参考方案1】:

我无法重现您的问题,但这肯定是因为 Kramdown 理解任何带有四个空格缩进或更像standard code block 的行。

如果你不想处理你的 Markdown 文件的某些部分,你可以像这样使用nomarkdown extension:

::nomarkdown  
     Any indented line or block
:/nomarkdown

另一种解决方法是为您的活动切换到 html 文件。

【讨论】:

哦,哇,那个 (缩进的东西) 太有意义了! .HTML 文件可以像 .MD 文件一样有前面的内容吗?这个想法是使用“事件”文件的前端,例如数据库中记录的值(计划使用 Netlify CMS 或 Forestry.io 让非技术人员将事件添加到日历中). 另外,昨天我对这项工作感到非常沮丧,以至于我最终使用了一个简单的参数化包含结构并删除了我编写的所有代码。所以我必须找到一些时间来重建它来测试你的建议是否有效。抱歉,我无法立即将答案标记为“已接受”——希望能在周末完成! 如果您不需要为您的收藏项目添加结构化内容(下面的内容),只需使用 .html 扩展名,这将避免降价时的缩进故障。否则,如果您必须包含来自 netlify cms 的降价内容,您可以在您的插件代码周围使用nomarkdown,它会运行良好。

以上是关于自定义 Jekyll 插件(液体过滤器?)将脚本标签呈现为文本,而不是 JavaScript的主要内容,如果未能解决你的问题,请参考以下文章

html 使用Jekyll _includes作为自定义液体功能

html Jekyll Casts - 液体:字符串过滤器

Jekyll 液体 if 语句混淆

在 YAML 变量中包含 jekyll / 液体模板数据?

使用 Jekyll 时出现“液体异常:液体语法错误”

html Jekyll Casts - 循环液体