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

Reply via email to