问题
I'm experimenting with building a site using Jekyll for a friend.
I'm trying to transform front matter from files like /_events/2020-02-25-an-event.md
and /_events/2020-02-26-another-event.md
into something that can be easily embedded into the body of various building blocks of content and result in those pages, as viewed by a visitor, including <script type="application/ld+json">...</script>
tags conforming to schema.org event standards.
A file like /_events/2020-02-25-an-event.md
looks like this:
---
layout: event
title: An event
published: true
startdatetime: 2020-02-28
venue: Best Club Ever
---
Members of the events
collection are meant to render as individual viewable URLs and should have a snippet of JavaScript hiding in their rendered output like this:
<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>
I got that working by writing /_plugins/event_schema.rb
as follows:
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)
And then by writing /_layouts/event.html
(which looks up to "page" layout, which looks up to "default" layout) as:
---
layout: page
---
{{ page | event_single_schema_script }}
Unfortunately, if I write /index.md
like this, while I get a nice little array of upcoming events, it renders surrounded by <code>
...</code>
tags and shows up in the body of the home page:
---
title: Home Page
layout: default
---
# {{ page.title }}
{{ site.events | event_multiple_schema_script }}
The desire is to have this script be part of the DOM's JavaScript ... not part of the text on the page:
<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>
Moving {{ site.events | event_multiple_schema_script }}
to be the contents of /_includes/event_all_schema_script.html
and trying {% include event_all_schema_script.html %}
didn't help at all -- same problem.
Removing the call to {% include event_all_schema_script.html %}
from /index.md
and putting it into /_layouts/default.html
instead does render the way I want it to. But now it's on every page, including pages like https://example.com/events/2020-02-25-an-event/
, which is not what I want. But it does demonstrate that my problem is that I wrote something I can't just "inject" into the markdown of a ... thing ... that's going to become a web page.
Things that also work in /index.md
but aren't what I want to do:
- Hand-writing
<script>...</script>
code straight into it - Putting
{% include event_all_schema_script_hardcode.html %}
into it, where/_includes/event_all_schema_script_hardcode.html
is literally just<script>...</script>
text copy-pasted from the output I showed all of you.- If only "generators for dummies" material weren't so hard to find (Jekyll documentation isn't very extensive; Google is useless because the phrase "static site generator" is to prevalent), maybe I could write code that would make building such a file at build-time possible? This seems like a pretty high bar to get over, though., with my current Jekyll/Ruby knowledge.
I'm open to re-architecting this, by the way. Not attached to the idea of "filtering" things like site.events
, etc. This is just as far as I got in my "hello world."
The only principles I'm really attached to in a final design:
- All data entry into the calendar of "events" should be done through the front matter of items in the
events
collection (so I can get a CMS like Forestry.io or Netlify CMS to play nice with it). - The computation of the contents of the
<script>...</script>
block should happen in an "independent, insertable component."- I don't want to do a big Liquid loop inside
/_layouts/homepage.html
that I have to remind a web designer to copy/paste into/_layouts/better_homepage.html
. - Instead, I just want to be able to tell a web designer, "Hey, if you want to make a page's metadata include a feed of events, just drop
{% include event_all_schema_script.html %}
somewhere into it or its layout." - I want
{% include event_all_schema_script.html %}
, or whatever equivalent people here help me come up with, to work both in the body of pages/posts/collection-markdown and in layouts.
- I don't want to do a big Liquid loop inside
- I'm going to take what I learn from this to also write "plain-old DIVs for web designers to style as they see fit" like
/_includes/event_all_div.html
and/_includes/event_single_div.html
, and to let them be used anywhere that the web designer sees fit -- in markdown or in a layout.- Again, I'm not a web designer. I'm just the data-structure transformation person. My only goal is to generate nice, "boring" snippets of HTML that are ready for a proper web designer to reuse and style as they see fit.
Any thoughts on how I can improve this attempt at rendering HTML so it will be both layout- and markdown-friendly?
Thanks so much.
回答1:
I can't reproduce your problem but it certainly comes from the fact that Kramdown understands any line with four spaces indentation or more like a standard code block.
If you don't want to process some parts of your markdown files, you can use nomarkdown extension like this :
{::nomarkdown}
Any indented line or block
{:/nomarkdown}
Another workaround can be to switch to html files for your events.
来源:https://stackoverflow.com/questions/60441507/custom-jekyll-plugin-liquid-filter-rendering-script-tags-as-text-not-as-java