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