k..
k..

Reputation: 401

Custom Jekyll Plugin (Liquid Filter?) rendering script tags as text, not as JavaScript

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:

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:

Any thoughts on how I can improve this attempt at rendering HTML so it will be both layout- and markdown-friendly?

Thanks so much.

Upvotes: 1

Views: 628

Answers (1)

David Jacquel
David Jacquel

Reputation: 52789

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.

Upvotes: 2

Related Questions