I want to structure the content of my Atom feed using headings:
atom_feed do |feed|
feed.title "#{Page.model_name.human(count: :other)} - #{t('app.name')}"
feed.updated(@pages[0].created_at) if @pages.length > 0
@pages.each do |page|
feed.entry(page) do |entry|
entry.title(page.title)
entry.content(type: 'html') do |html|
html.h1 t('.position_in_hierarchy')
html.p page.ancestors.reverse.map(&:title).join ': '
html.h1 Page.human_attribute_name :lead
html.div markdown page.lead
html.h1 Page.human_attribute_name :content
html.div markdown page.content
end
end
end
end
For each of my pages, this results in the following generated XML:
<entry>
<id>tag:localhost,2005:PageDecorator/1</id>
<published>2017-02-24T18:11:26+01:00</published>
<updated>2017-04-05T09:58:42+02:00</updated>
<link rel="alternate" type="text/html" href="http://localhost:3001/en/pages/1"/>
<title>Preparation</title>
<content type="html">
<h1>Position in page hierarchy</h1>
<p>Preparation</p>
<h1>Lead</h1>
<div><p>This the lead.</p></div>
<h1>Content</h1>
<div><p>This is some content!</p>
<h2 id="with-a-heading">With a heading</h2>
<p><a href="http://www.example.com">And a link!</a></p></div>
<h1>Notice about Atom feed</h1>
<p>Your feed reader has downloaded version 14 of the current page, which was current at April 05, 2017 09:58. Meanwhile there could be an updated version of the page available online. Visit the original page to see the most current version!</p>
</content>
</entry>
As you can see, the html.h1
calls are rendered as plain <h1>
. But interestingly, my feed reader Vienna doesn't display them! More interestingly, the content of html.div
, which is markdown rendered by my custom markdown
method, is html escaped... and this stuff is rendered by Vienna!
The markdown
method itself escapes HTML:
def markdown(string)
PandocRuby.convert(string, to: :html).html_safe
end
So I'm pretty unsure now what to do to make my other HTML markup work in Vienna, too.
As Kris pointed out in his comment, the content needs to be escaped: https://validator.w3.org/feed/docs/atom.html#text
The easiest thing to do this is just rendering a partial like this:
entry.content(render(page), type: 'html')
This will render _page.atom.slim
(or .erb
or whatever) and automatically escape the HTML.