From e07d8459dec19fabb315a7da13c9cba7dcadb7fc Mon Sep 17 00:00:00 2001 From: JSDurand Date: Sun, 29 Aug 2021 11:09:23 +0800 Subject: 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. --- org-conf.el | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file 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 "\n\n")) contents) (insert "\n") - (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 "" orig-string) + (setq temp (match-end 0)) + (substring + orig-string + temp + (progn + (string-match "" 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 "
" nil t) + (search-forward "

" nil t) + (buffer-substring-no-properties + (1+ (point)) + (progn + (search-forward "

" 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 + " + +https://jsdurand.xyz/atom.xml +%s + +JSDurand + https://jsdurand.xyz +mmemmew@gmail.com + + +Copyright (c) 2021, JSDurand +%s +\ +Emacs\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 + " +%s +%s +%s + +%s + +%s + +") + +(defvar durand-org-atom-postamble nil + "The post-amble of an Atom feed.") + +(setq durand-org-atom-postamble + "") + +;;;;;; 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 - ) -- cgit v1.2.3-18-g5258