emacs-love / weblorg

Static Site Generator for Emacs
https://emacs.love/weblorg
GNU General Public License v3.0
280 stars 21 forks source link

Question: How to explicitly set all posts in a route or site? #48

Open markokocic opened 3 years ago

markokocic commented 3 years ago

I want to have a list of all posts/pages matching some filter and have it available inside a route or site. Lets say I have a rout to render all posts:

(weblorg-route
 ;; route for rendering each post
 :site blog
 :name "posts"
 :input-pattern "posts/*.org"
 :template "post.html"
 :output "output/posts/{{ slug }}.html"
 :url "/posts/{{ slug }}.html")

I want to add two more variable to the each page, so that I can list links to pages in sidebar, and display 4 recent posts title in footer. For that I would like to have something like:

(weblorg-route
 ;; route for rendering each post
 :site blog
 :name "posts"
 :input-pattern "posts/*.org"
 :template "post.html"
 :output "output/posts/{{ slug }}.html"
 :url "/posts/{{ slug }}.html"
 :template-vars '(("all_posts" (some-function "posts/*.org"))
                  ("all_pages" (some-function "pages/*.org")))

or directly in weblorg-site, in order to avoid duplication for each route.

(weblorg-site
 :template-vars '(("all_posts" (some-function "posts/*.org"))
                  ("all_pages" (some-function "pages/*.org")))
)

Is something like this already possible in weblorg?

clarete commented 3 years ago

oh hi @markokocic you might be interested in trying out the experimental (and undocumented 😢) weblorg_route_posts.

Here's an example: https://github.com/emacs-love/weblorg/blob/main/themes/autodoc/templates/doc.html#L18-L26

It can take arbitrary route names and it will return all the posts of that route! Let me know if that works for you!

and sorry for taking so long to answer things! I'm catching up 😄

markokocic commented 3 years ago

Works like charm. Thanks 😊

clarete commented 3 years ago

Nice! I'll keep this open as a documentation issue then! Thank you for trying it out, @markokocic 🙇🏾

markokocic commented 3 years ago

Hi @clarete

Actually, after some testing I noticed that weblorg_route_posts doesn't really work.

I have the following snippet in my sidebar template which is included from the base template:

        <section>
          <h3>Recent Posts</h3>
          <ul>
            {% for recent in weblorg_route_posts("archive")|take(4) %}
            <li><a href="{{ url_for("posts", slug=recent.slug) }}">{{ recent.title }}</a></li>
            {% endfor %}
          </ul>
        </section>

I also have the following routes defined in publish.el:

(weblorg-route
 ;; route for rendering each post
 :site blog
 :name "posts"
 :input-pattern "posts/*.org"
 :template "post.html"
 :output "output/posts/{{ slug }}.html"
 :url "/posts/{{ slug }}.html")

(weblorg-route
 ;; route for rendering archive page
 :site blog
 :name "archive"
 :input-pattern "posts/*.org"
 :input-aggregate #'weblorg-input-aggregate-all-desc
 :template "archive.html"
 :output "output/archive.html"
 :url "/archive.html")

If I use weblorg_route_posts("posts") in the template, I get unordered list of all posts, but when I use weblorg_route_posts("archive") I get undefined in output.

Could be something to do with how the posts are aggregated, since the structure returned by weblorg_route_posts when using :input-aggregate option in route definition is different.

clarete commented 3 years ago

oh, thank you for the feedback on this @markokocic. I think you might be right about the relationship with how aggregation works. That's still a bit too entangled to just the Org-Mode parsing. I want to make it more generic so we can address this sort of use case you presented. Thank you for the good repro of the issue, I'll take a stab at fixing it!

markokocic commented 3 years ago

In the end I was able to list recent posts by using the following template.

        <section>
          <h3>Recent Posts</h3>
          <ul>
            {% for recent in weblorg_route_posts("archive") | attr("posts") | take(4) %}
            <li><a href="{{ url_for("posts", slug=recent.slug) }}">{{ recent.title }}</a></li>
            {% endfor %}
          </ul>
        </section>

It works, but the solution looks wrong.