Hi Fabio,
On 03 Mar 2025, Fabio Natali wrote:
Dear All,
I've got a little static website that gets built with the Org
publishing system. Recently I've been looking at ways to add a
full-text RSS feed with ox-rss.el[0].
[...]
There's a couple of things that I'm not sure about. My main
concern is around bullet point lists. Lists like this:
#+begin_src org
- One
- Two
- Three
#+end_src
get transformed to:
#+begin_src html
<div id="outline-container-org63baba9" class="outline-4">
<h4 id="org63baba9">One</h4>
<div class="outline-text-4" id="text-org63baba9">
</div>
</div>
<div id="outline-container-orgd30bd42" class="outline-4">
<h4 id="orgd30bd42">Two</h4>
<div class="outline-text-4" id="text-orgd30bd42">
</div>
</div>
<div id="outline-container-org3fb09c5" class="outline-4">
<h4 id="org3fb09c5">Three</h4>
<div class="outline-text-4" id="text-org3fb09c5">
</div>
</div>
#+end_src
whereas I'd expect a HTML UL block.
The problem seems to boil down to ~org-list-to-subtree~ and the
way the original Org files are merged into a single Org sitemap.
For instance, this:
#+begin_src emacs-lisp
(org-list-to-subtree '(unordered ("* Intro\n\n- one\n- two\n")))
#+end_src
returns:
#+begin_src text
,* * Intro
,** one
,** two
#+end_src
Whereas, I'd expect:
#+begin_src text
,** Intro
- one
- two
#+end_src
Anybody knows whether I'm not using ~org-list-to-subtree~
correctly or if there's a more clever way to define a
~my/rss-feed-generate~ function?
[...]
You're right, the ~org-list-to-subtree~ function treats lists as
outline items. You can try inserting lists as plain Org content
directly:
#+begin_src elisp
(defun extract-org-content (entry)
"Extract the Org content from an ENTRY list."
;; Skip the 'unordered' keyword
(when (and (listp entry) (> (length entry) 1))
(let* ((inner-list (cadr entry))
(content (if (and (listp inner-list) (listp (cadr
inner-list)))
(car (cadr inner-list))
inner-list)))
(unless (equal content "nil") content))))
(defun my/rss-feed-generate (title list)
"Generate the RSS feed as a string."
(with-temp-buffer
(insert "#+TITLE: " title "\n\n")
(dolist (entry list)
(let ((content (extract-org-content entry)))
(when content
;; Ensure each post title is correctly formatted as
level 1
(if (string-match "^\\* " content)
(insert "* " (string-trim (replace-regexp-in-string
"^\\*+" "**" content)) "\n")
(insert content "\n"))))) ;; Insert other content as
is
(buffer-string)))
#+end_src
This ensures that:
1. Post titles are kept as level 1
2. Subheadings are demoted correctly (* => **)
3. Unordered lists (- item) are preserved
Hope this helps!
--
Jonathan