typemill / typemill

Typemill is a lightweight, flat-file CMS designed for simple, fast, and flexible website and eBook creation using Markdown.
https://typemill.net
MIT License
427 stars 60 forks source link

RSS feed for Folders with Posts #140

Closed Tekl closed 4 months ago

Tekl commented 4 years ago

As RSS isn't dead, an RSS feed for blog posts would be a nice service.

trendschau commented 4 years ago

Yes, it is on the roadmap for a long time, probably best done with a plugin.

Tekl commented 2 years ago

Which plugin could be a good start/inspiration for such a project?

trendschau commented 2 years ago

I think it would be pretty similar to the xml-sitemap: https://github.com/typemill/typemill/blob/master/system/Models/WriteSitemap.php

So one way is to create a plugin, listen to all events that create/publish/unpublish/delete pages and then update the rss feed accordingly. This might require some work to cover all cases and to select the correct content for the blog. Another way might be with a rss-template in the theme, but I have to check if it is possible that way. The idea is that you create a template that dynamically creates an rss-format for all folders that contain posts. Hope to find some time to check it next week but I don't think that I will find time to code it in near future.

Tekl commented 2 years ago

Thanks for your help. Maybe a rss-template could be a quicker solution for me as I don't really understand the plug-in stuff. Thanks for pointing me into that direction.

Tekl commented 2 years ago

Uh, more complicated than I thought. How do I merge two getPageList() results? The |merge() feature does not seem to work here. :-(

{% set pagelist1 = getPageList(navigation, "/news", base_url) %}
{% set pagelist2 = getPageList(navigation, "/blog", base_url) %}
{% set pagelist3 = pagelist2|merge(pagelist1) %}

Besides that, I can't get Twig to load the content of the pages. post.meta.description is easy, but a full content feed would be great.

I also haven't found out how to change the response header from 404 to 200 when using a custom URL. (site.com/rss)

Tekl commented 2 years ago

For the record. I've found solution for the merge:

{% set pagelist1 = getPageList(navigation, "/news", base_url) %}
{% set pagelist2 = getPageList(navigation, "/blog", base_url) %}
{% set contents = (pagelist1.folderContent|slice(0,7))|merge((pagelist2.folderContent|slice(0,7))) %}

I also fixed the 404 by creating a dummy page with the URL. ;-)

trendschau commented 2 years ago

great solution, I am happy to hear that!!

Tekl commented 2 years ago

This is my current solution but still only with meta.description as content 😢

{% if current_url == "/feed" %}
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
        {% set pagelist1 = getPageList(navigation, "/news", base_url) %}
        {% set pagelist2 = getPageList(navigation, "/blog", base_url) %}
        {% set contents = (pagelist1.folderContent|slice(0,7))|merge((pagelist2.folderContent|slice(0,7))) %}
        <author>
            <name>{{ settings.author }}</name>
        </author>
        <title>{{ settings.title }}</title>
        <icon>{{ base_url }}/favicon.ico</icon>
        <logo>{{ base_url }}/favicon.png</logo>
        <id>{{ base_url }}/</id>
        <link href="{{ base_url }}/"/>
        <link rel="self" type="application/atom+xml" href="{{ base_url }}/feed"/>

        {% for cnt in 1..7 %}
            {% set contents_sorted = contents|slice(0, 1, true) %}
            {% for element in contents|slice(1) %}
                {% if element.order < (contents_sorted|last).order %}
                    {% set contents_sorted = contents_sorted|merge([element]) %}    
                {% else %}
                    {% set contents_sorted = [element]|merge(contents_sorted) %}    
                {% endif %}
            {% endfor %}
            {% set contents = contents_sorted %}
        {% endfor %}

        {% for element in contents %}
            {% set post = getPageMeta(settings, element) %}
            {% set date = element.order[0:4] ~ '-' ~ element.order[4:2] ~ '-' ~ element.order[6:2] ~ 'T' ~ element.order[8:2] ~ ':' ~ element.order[10:2]  ~  ':00Z' %}
            {% if loop.index == 1 %}
                <updated>{{ date }}</updated>
                {% set firstpost = false %}
            {% endif %}
            <entry>
                <title>{{ post.meta.title }}</title>
                <link href="{{ element.urlAbs }}"/>
                <id>{{ element.urlAbs }}</id>
                <updated>{{ date }}</updated>
                <summary>{{ post.meta.description }}</summary>
                <author>
                    <name>{{ post.meta.author }}</name>
                </author>
                {% if post.meta.heroimage %}
                    <link rel="enclosure" type="image/png" href="{{ assets.image(post.meta.heroimage).resize(230,230).src() }}"/>
                {% endif %}
                <content type="xhtml">
                    <div xmlns="http://www.w3.org/1999/xhtml">
                        {% if post.meta.heroimage %}
                        <figure style="text-align: center">
                            <a href="{{ element.urlAbs }}"><img src="{{ base_url }}/{{ post.meta.heroimage }}" alt="{{ post.meta.heroimagealt }}" height="250" width="auto"/></a>
                        </figure>
                        {% endif %}
                        <p>{{ post.meta.description }}
                            <a href="{{ element.urlAbs }}">weiterlesen</a>
                        </p>
                    </div>
                </content>
            </entry>
        {% endfor %}
    </feed>
{% else %}
    <!DOCTYPE html>

As I combine two folders I had to implement a stupid sort routine (inside {% for cnt in 1..7 %}) to sort the mixed post chronologically. I tried it with Twig's own sort() but I don't understand how to let it sort by the order-property.

trendschau commented 2 years ago

great, thank you for sharing your solution!! I will add that to the documentation, maybe a kind of "cookbook" would be good for that.

Yes, it is only the meta-file, not the full content file. I will keep that in mind and check if there is a simple way to implement a getContentFile-function (as soon as I find some more time)...

trendschau commented 4 months ago

there was a rss-plugin for typemill v1 and I hope it will be updated for v2 too from contributor.