home

Adding an RSS Feed to This Blog

Quick OCaml hack to generate some old-school XML.

A blog needs an RSS feed; a good old standard that just works.

I found the rss function of my previous blog (see ocaml.rss); untouched for 9 years. It still works but I didn't want to go back to that dirty pile of sprintf.

This current blog already depends on Tyxml and the module Tyxml.Xml has everything we need.

Sometimes a piece of code is just dump and obvious; RSS is a easy as this (uses Base and Fmt):

module Rss_feed = struct
  type item = unit -> Tyxml.Xml.elt
  (* ⮤ Laziness not really useful in this use-case, only makes
     merlin/error-messages use the right name without a module type. *)

  type t = Tyxml.Xml.elt

  let item ~title ~description ~link ~guid ~pub_date : item =
   fun () ->
    let open Tyxml.Xml in
    node "item"
      [ node "title" [pcdata title]
      ; node "description" [pcdata description]
      ; node "link" [pcdata link]
      ; node "guid" [pcdata guid]
      ; node "pubDate" [pcdata pub_date] ]

  let make ~title ~description ~last_build_date ~pub_date ~link items : t =
    let open Tyxml.Xml in
    let doc =
      let channel =
        [ node "title" [pcdata title]
        ; node "description" [pcdata description]
        ; node "link" [pcdata link]
        ; node "lastBuildDate" [pcdata last_build_date]
        ; node "pubDate" [pcdata pub_date]
        ; Fmt.kstr comment "RSS Feed for %s" title ]
      in
      node "rss"
        [node "channel" (channel @ List.map ~f:(fun x -> x ()) items)]
        ~a:[string_attrib "version" "2.0"]
    in
    doc

  let pp : t Fmt.t =
    let header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" in
    Fmt.(const string header ++ cut ++ Tyxml.Xml.pp ~indent:true () ++ cut)
  (* ⮤ Format all the things! *)

  let test () =
    let example =
      make ~title:"Example RSS feed"
        ~last_build_date:"Tue, 30 Jun 2020 22:17:46 -0400"
        ~pub_date:"Tue, 30 Jun 2020 22:17:57 -0400"
        ~link:"https://seb.mondet.org/b/"
        ~description:"The description of the example RSS feed."
        [ item ~title:"Ttlee 1" ~description:"some description"
            ~link:"https://seb.mondet.org/b/0000-zerozero.html"
            ~guid:"https://seb.mondet.org/b/0000-zerozero.html"
            ~pub_date:"Tue, 30 Jun 2020 22:26:59 -0400"
        ; item ~title:"Ttlee 2nd" ~description:"some other description"
            ~link:"https://seb.mondet.org/b/000z-zzzjzerozero.html"
            ~guid:"https://seb.mondet.org/b/000z-zzzjzerozero.html"
            ~pub_date:"Tue, 30 Jun 2020 22:26:59 -0400" ]
    in
    Fmt.pr "%a\n%!" pp example
end

Just don't forget that dates have to be “Email Dates” (a.k.a. RFC 5322 or date -R (for GNU date).)

Even the RSS validator “dot CGI” still works also after a couple of decades: https://validator.w3.org/feed/check.cgi.

Then, it is just about iterating over the blog-posts to collect the tags and generate an RSS file for each of them, deploy, on https://seb.mondet.org/b/:

Screenshot of the blog-index page.

Then add OCaml.rss to The OCaml Planet (→ PR ocaml/ocaml.org#1133).

After 8 years of blograstination, this is post #4 of my attempt at not getting too fast lagging behind on the #100DaysToOffload “challenge” … Let's see where this goes.