diff options
author | JSDurand <mmemmew@gmail.com> | 2021-08-29 11:09:23 +0800 |
---|---|---|
committer | JSDurand <mmemmew@gmail.com> | 2021-08-29 11:09:23 +0800 |
commit | e07d8459dec19fabb315a7da13c9cba7dcadb7fc (patch) | |
tree | 17fe66feff7bc0cca440e678b1261445cedc9b41 | |
parent | 69b94225ed37613df6fcb158ab07427b0c496ad4 (diff) |
Generate Atom feeds for the website
* org-conf.el (durand-sitemap-custom-string-alist)
(durand-org-publish-sitemap): Add links to the atom files.
(durand-org-post-process): Call `durand-org-generate-atom-feed' in
this function.
(durand-org-atom-titles-alist): Associate titles and feed files with
the project name.
(durand-org-atom-preamble, durand-org-atom-entry-template)
(durand-org-atom-postamble): The generated Atom file is controlled by
these template variables.
(durand-org-atom-format-time): The zone of the time should be in a
specific format that no time format string provides. So I write this
function to provide this formatting.
(durand-org-generate-atom-feed): Apply the templates to generate the
Atom feed files.
-rw-r--r-- | org-conf.el | 220 |
1 files changed, 194 insertions, 26 deletions
diff --git a/org-conf.el b/org-conf.el index 68d4de7..bf1d50d 100644 --- a/org-conf.el +++ b/org-conf.el @@ -709,14 +709,17 @@ href='https://jsdurand.xyz/favicon.ico'/>") (setq durand-sitemap-custom-string-alist (list - (cons "About coding" + (list "About coding" "This is my coding blog. It contains my coding experiments, or \ -one might think of them as development diaries.") - (cons "My life" +one might think of them as development diaries." + "code-atom.xml") + (list "My life" "This is my casual blog. It contains articles about my plain \ -life.") - (cons "Mathematics" - "My Mathematics-related articles are put here."))) +life." + "life-atom.xml") + (list "Mathematics" + "My Mathematics-related articles are put here." + "math-atom.xml"))) ;;;;;; Custom sitemap function @@ -729,17 +732,19 @@ project. Use such functions as `org-list-to-org' or `org-list-to-subtree' to transform it." (format "#+TITLE: %s\n#+AUTHOR: JSDurand\n%s#+DATE: <%s>\n\n%s\n\n\ #+ATTR_HTML: :border nil :rules nil :frame nil\n\ -%s" +%s\n\n\ +[[https://jsdurand.xyz/%s][Web feed]]" title "#+HTML_LINK_UP: index.html" (format-time-string "%F %a %R") - (cdr (assoc title durand-sitemap-custom-string-alist #'string=)) + (cadr (assoc title durand-sitemap-custom-string-alist #'string=)) ;; generate a table (org-list-to-generic rep '(:ustart "|---|" :uend "|---|" - :isep "|---|")))) + :isep "|---|")) + (caddr (assoc title durand-sitemap-custom-string-alist #'string=)))) ;;;;;; Custom sitemap format @@ -812,7 +817,9 @@ are present." (defun durand-org-post-process (project) "Generate a proper index page and Atom feeds. Also shorten the date strings in the sitemap files, and store the -completion information in an attribute." +completion information in an attribute. + +The feeds are generated by the function `durand-org-generate-atom-feed'." (let* ((project-plist (cdr (assoc project org-publish-project-alist #'string=))) (components (durand-org-publish-plist-get :components project-plist)) @@ -831,7 +838,7 @@ completion information in an attribute." ;; depth-first recursion (components (setq contents (apply #'append - (delete nil (mapcar #'durand-org-post-process components)))) + (delete nil (mapcar #'durand-org-post-process components)))) ;; We only want some items (setq contents (durand-take @@ -875,9 +882,7 @@ completion information in an attribute." (insert "</td>\n</tr>\n")) contents) (insert "</tbody>\n</table>") - (setq contents (buffer-substring-no-properties - (point-min) (point-max)))) - (write-region contents nil index-file)))) + (write-region nil nil index-file))))) ((and publish-sitemap-file (stringp publish-sitemap-file) (file-exists-p publish-sitemap-file)) @@ -943,21 +948,184 @@ completion information in an attribute." (setq temp (cons - (cons temp-time - (progn - (re-search-forward regexp) - (setq pos (point)) - (search-forward "</t") - (buffer-substring-no-properties - pos (match-beginning 0)))) + (cons + temp-time + (progn + (re-search-forward regexp) + (setq pos (point)) + (search-forward "</t") + (buffer-substring-no-properties + pos (match-beginning 0)))) temp))) + (durand-org-generate-atom-feed + project + (expand-file-name (concat project "-atom.xml") + publishing-dir) + (mapcar + (lambda (cell) + (let* ((orig-string (cdr cell)) + (temp 0) + (title + (progn + (string-match ">" orig-string) + (setq temp (match-end 0)) + (substring + orig-string + temp + (progn + (string-match "</a>" orig-string temp) + (match-beginning 0))))) + (file-name + (progn + (string-match "href=\"" orig-string) + (setq temp (match-end 0)) + (substring + orig-string + temp + (progn + (string-match "\">" orig-string temp) + (match-beginning 0))))) + (content + (with-temp-buffer + (insert-file-contents + (expand-file-name file-name publishing-dir)) + (goto-char (point-min)) + (search-forward "<div id=\"content\">" nil t) + (search-forward "<p>" nil t) + (buffer-substring-no-properties + (1+ (point)) + (progn + (search-forward "</p>" nil t) + (match-beginning 0))))) + ;; escape html + (content + (replace-regexp-in-string + ">" ">" + (replace-regexp-in-string + "<" "<" + (replace-regexp-in-string + "&" "&" content))))) + (list + title + (durand-org-atom-format-time + (file-attribute-modification-time + (file-attributes + (expand-file-name file-name publishing-dir)))) + (concat "https://jsdurand.xyz/" file-name) + (concat "https://jsdurand.xyz/" file-name) + (durand-org-atom-format-time (car cell)) + content))) + (reverse temp))) (reverse temp))))))) ;;;;; Atom feed -;; The Atom feeds are generated in this function. +;;;;;; Fixed pre-amble, template, and post-amble. + +(defvar durand-org-atom-titles-alist nil + "An assocuation list of Atom feed titles with the project name.") + +(setq durand-org-atom-titles-alist + (list + (list "code" "JSDurand's codes" "https://jsdurand.xyz/code-atom.xml") + (list "math" "Math articles of JSDurand" + "https://jsdurand.xyz/math-atom.xml") + (list "life" "JSDurand's life" + "https://jsdurand.xyz/life-atom.xml"))) + +(defvar durand-org-atom-preamble nil + "The preamble of an Atom feed.") + +(setq durand-org-atom-preamble + "<?xml version=\"1.0\" encoding=\"utf-8\" ?> +<feed xmlns=\"http://www.w3.org/2005/Atom\"> +<id>https://jsdurand.xyz/atom.xml</id> +<title>%s</title> +<author> +<name>JSDurand</name> +<uri> https://jsdurand.xyz </uri> +<email>mmemmew@gmail.com</email> +</author> +<link rel=\"self\" type=\"applicatoin/atom+xml\" href=\"%s\"/> +<rights>Copyright (c) 2021, JSDurand</rights> +<updated>%s</updated> +<generator uri=\"https://www.gnu.org/software/emacs/\" version=\"28.0.50\">\ +Emacs</generator>\n") + +(defvar durand-org-atom-entry-template nil + "The template for an Atom entry. +It HAS to be formatted with 6 arguments in the following order: + +TITLE: the title. Note this does not have a subtitle. + +UPDATED-TIME: the newest updated time. + +ID: I think I will use the URL as the ID directly. + +LINK: Link to this entry. + +PUBLISHED-TIME: the time this is published. + +CONTENT: a short content. +") + +(setq durand-org-atom-entry-template + "<entry> +<title type=\"text\">%s</title> +<updated>%s</updated> +<id>%s</id> +<link rel=\"self\" type=\"text/html\" href=\"%s\"/> +<published>%s</published> +<content type=\"html\"> +%s +</content> +</entry>") + +(defvar durand-org-atom-postamble nil + "The post-amble of an Atom feed.") + +(setq durand-org-atom-postamble + "</feed>") + +;;;;;; Format time easily + +(defun durand-org-atom-format-time (time) + "Format TIME in an acceptable way." + (concat + (format-time-string + "%FT%T" time) + (format "%s%02d:%02d" + (cond ((> (car (current-time-zone)) 0) "+") + ("-")) + (/ (car (current-time-zone)) 3600) + (% (car (current-time-zone)) 3600)))) + +;;;;;; The Atom feeds are generated in this function. + +(defun durand-org-generate-atom-feed (project file-name entries) + "Generate an Atom feed for ENTRIES and save in FILE-NAME. +PROJECT is the name of the subproject. + +ENTRIES is a list of entries. + +An entry is a list of the form (TITLE UPTIME ID LINK PUBTIME CONTENT). +See the documentation string for `durand-org-atom-entry-template' for more." + (with-temp-buffer + (insert (apply #'format + durand-org-atom-preamble + (append + (cdr + (assoc project durand-org-atom-titles-alist + #'string=)) + (list (durand-org-atom-format-time nil)))) + "\n") + (mapc + (lambda (entry) + (insert (apply #'format durand-org-atom-entry-template + entry) + "\n")) + entries) + (insert durand-org-atom-postamble) + (write-region nil nil file-name))) + -(defun durand-org-generate-atom-feed (project) - "Generate an Atom feed for PROJECT." - ;; TODO - ) |