summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2021-08-29 11:09:23 +0800
committerJSDurand <mmemmew@gmail.com>2021-08-29 11:09:23 +0800
commite07d8459dec19fabb315a7da13c9cba7dcadb7fc (patch)
tree17fe66feff7bc0cca440e678b1261445cedc9b41
parent69b94225ed37613df6fcb158ab07427b0c496ad4 (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.el220
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
+ ">" "&gt;"
+ (replace-regexp-in-string
+ "<" "&lt;"
+ (replace-regexp-in-string
+ "&" "&amp;" 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
- )