Alternate content in jekyll-feed

Hi folks. What would be a good way to put alternate content in the Atom feed created by jekyll-feed?

I’d like to have a blog post that embeds an Asciinema playback. This requires using CSS in the header and <script> tags in the body, as mentioned in the docs:

https://docs.asciinema.org/manual/player/quick-start/

This kind of content won’t work in an Atom feed because of the CSS and Javascript. I’d like to provide alternate content in the feed, like a static image link that takes you to the main site when clicked, but I don’t know of a good way to do that.

I was originally thinking a custom Liquid tag like {% asciinema ... %} could generate alternate content for the HTML and the feed. But as far as I can tell, a post cannot have alternate content. Another possibility may be to use a :post_render hook on the feed to replace the <script> tags with an <img> tag? But that would involve some tricky text matching and replacement.

Are there any options I have overlooked, or examples of doing something similar?

Thanks,

-Dave

PS: Here’s a sample of how to embed the Asciinema player using CSS and <script>:

Sample Asciinema Player HTML
<!DOCTYPE html>
<html>
<head>
  ...
  <link rel="stylesheet" type="text/css" href="/asciinema-player.css" />
  ...
</head>
<body>
  ...
  <div id="demo"></div>
  ...
  <script src="/asciinema-player.min.js"></script>
  <script>
    AsciinemaPlayer.create('/demo.cast', document.getElementById('demo'));
  </script>
</body>
</html>

Possibly you could put the static image in a <noscript> element? Something like:

<div id="demo"></div>
<noscript><a href=".."><img src=".." alt="an ASCII animation"></a></noscript>

I don’t know how feed readers handle <noscript>, so more research would be needed.

Another option would be to put the alt content inside the <div> and have the script delete it. Something like:

<div id="demo"><a href=".."><img src=".." alt="an ASCII animation"></a></div>
...
<script>
    document.getElementById('demo').replaceChildren();
    AsciinemaPlayer.create('/demo.cast', document.getElementById('demo'));
</script>

I believe the issue is that feed readers may not run the script at all, due to security concerns, and <script> (and <noscript>) should, ideally, not be used in a feed:

https://validator.w3.org/feed/docs/warning/SecurityRisk.html

The best I’ve come up with so far is to use a special comment in the Markdown like this:

<!-- asciinema sample-cast "A sample ASCII animation" -->

Then use a :post_render hook on :posts that would replace this with a <div> + <script>:

Jekyll::Hooks.register :posts, :post_render do |post, output, foo|
  post.output = replace_with_asciinema_script(post.output)
end

And a separate :post_render hook on :pages that would replace this with an <img> (the second argument would be the alt text):

Jekyll::Hooks.register :pages, :post_render do |page|
  if page.path == "feed.xml"
    page.output = replace_with_asciinema_img(page.output)
  end
end

Quick and dirty implementation of these functions:

Hook functions
def replace_with_asciinema_script(output)
  new_output = output.gsub(/<!-- asciinema(.*?)-->/) do |match|
    comment = $1
    args = comment.shellsplit
    id = args[0]

    content = <<~EOF.chomp
    <div id="#{id}"></div>
    <script>
    AsciinemaPlayer.create('/path/to/#{id}.cast', document.getElementById('#{id}'), {
        fit: "width"
    });
    </script>
    EOF
    next content
  end
  return new_output
end

def replace_with_asciinema_img(output)
  new_output = output.gsub(/<!-- asciinema(.*?)-->/) do |match|
    comment = $1
    args = comment.shellsplit
    id = args[0]
    alt = args[1]

    content = <<~EOF.chomp
    <img src='/path/to/#{id}.png' alt='#{alt}' />
    EOF
    next content
  end
  return new_output
end