aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ennu-html.el4
-rw-r--r--ennu.el193
2 files changed, 92 insertions, 105 deletions
diff --git a/ennu-html.el b/ennu-html.el
index 36796d1..9a24f9c 100644
--- a/ennu-html.el
+++ b/ennu-html.el
@@ -18,11 +18,11 @@
;; TODO: Pass title through org-export-data-with-backend or something
;; similar in order to export org syntax in title
(defun ennu-export-post (path desc backend)
- (let ((post (concat (expand-file-name path (ennu-setting :posts-directory))
+ (let ((filename (concat (expand-file-name path (ennu-setting :posts-directory))
".org")))
(xmlgen `(a :href ,(expand-file-name*
path (ennu-setting :posts-directory))
- ,(or desc (plist-get (ennu-post-metadata post) :title))))))
+ ,(or desc (ennu-post-title (ennu-read-post filename)))))))
(org-link-set-parameters
"post" :export 'ennu-export-post)
diff --git a/ennu.el b/ennu.el
index c24739e..04017ba 100644
--- a/ennu.el
+++ b/ennu.el
@@ -12,6 +12,64 @@
(defvar ennu-version "0.1.0"
"Ennu version string")
+(cl-defstruct (ennu-post (:constructor ennu-make-post)
+ (:copier nil))
+ filename author date language links
+ summary tags thumbnail title translation-group)
+
+(defun ennu-posts (posts-directory)
+ (sort (seq-map 'ennu-read-post
+ (file-expand-wildcards
+ (concat (file-name-as-directory
+ (ennu-setting :posts-directory))
+ "*.org")))
+ 'ennu-later-post-p))
+
+(defun ennu-later-post-p (post1 post2)
+ (time-less-p (ennu-post-date post2)
+ (ennu-post-date post1)))
+
+(defun ennu-read-post (filename)
+ (ennu--read-post
+ filename (file-attribute-modification-time
+ (file-attributes filename))))
+
+(defmemoize ennu--read-post (filename last-modified)
+ (ennu-with-file-contents filename
+ (let ((metadata (org-export-get-environment 'ennu-html))
+ (export (apply-partially 'org-export-with-backend 'ennu-html)))
+ (seq-do (lambda (key)
+ (unless (plist-member metadata key)
+ (user-error "Metadata %s not specified" key)))
+ ennu-mandatory-metadata)
+ (let ((links (org-element-map (org-element-parse-buffer) 'link
+ (lambda (link)
+ (pcase link
+ (`(link ,properties . ,_)
+ (let ((link-type (org-element-property :type link)))
+ (when (member link-type (list "image" "static" "video"))
+ (cons link-type (org-element-property :path link))))))))))
+ (ennu-make-post
+ :filename filename
+ :author (funcall export (first (plist-get metadata :author)))
+ :date (org-timestamp-to-time (first (plist-get metadata :date)))
+ :language (plist-get metadata :language)
+ :links links
+ :summary (funcall export (first (plist-get metadata :summary)))
+ :tags (plist-get metadata :filetags)
+ :thumbnail (or (plist-get metadata :thumbnail)
+ (seq-some (lambda (link)
+ (pcase link
+ (`("image" . ,path) path)
+ (`("video" . ,path) (ennu-video-poster path))))
+ links))
+ :title (funcall export (first (plist-get metadata :title)))
+ :translation-group (or (plist-get metadata :translation-group)
+ (file-name-base filename)))))))
+
+(defvar ennu-mandatory-metadata
+ (list :title :date))
+
(defmacro ennu-with-file-contents (file &rest body)
"Create a temporary buffer, insert contents of FILE into that
buffer and evaluate BODY. The value returned is the value of the
@@ -26,10 +84,10 @@ last form in BODY."
(defun ennu-publish-post (post)
;; TODO: Tangle post
- `((,post)
- (,(ennu--org-output-filename post))
+ `((,(ennu-post-filename post))
+ (,(ennu--org-output-filename (ennu-post-filename post)))
,(lambda (output-file)
- (ennu-with-file-contents post
+ (ennu-with-file-contents (ennu-post-filename post)
(org-export-to-file 'ennu-html output-file))
;; (when-let (tangle-dir (or (plist-get posts-plist :valai-tangle-directory)
;; valai-tangle-directory))
@@ -61,14 +119,6 @@ last form in BODY."
(`(,poster . ,_) poster)
(`() (user-error "Poster for %s not found" video))))
-(defun ennu-post-thumbnail (post)
- (or (plist-get (ennu-post-metadata post) :thumbnail)
- (seq-some (lambda (link)
- (pcase link
- (`("image" . ,path) path)
- (`("video" . ,path) (ennu-video-poster path))))
- (ennu-post-links post))))
-
(defun ennu-add-tongue-suffix (filename tongue)
(pcase tongue
("en" filename)
@@ -88,7 +138,7 @@ last form in BODY."
(defun ennu-publish-index (filename-prefix tongue title posts-per-page posts)
(let* ((number-of-pages (ceiling (length posts) posts-per-page))
(page-numbers (number-sequence 1 number-of-pages)))
- `(,posts
+ `(,(seq-map 'ennu-post-filename posts)
,(cons (ennu-add-tongue-suffix (format "%s.html" filename-prefix) tongue)
(seq-map (apply-partially 'ennu-index-filename filename-prefix tongue "html")
page-numbers))
@@ -100,23 +150,22 @@ last form in BODY."
(insert (format "#+LANGUAGE: %s\n" tongue))
(insert "#+OPTIONS: num:nil toc:nil\n\n")
(seq-do (lambda (post)
- (let ((metadata (ennu-post-metadata post)))
- (insert (format "* [[post:%s]]\n" (file-name-base post)))
- (insert (format-time-string
- "/%b %e, %Y/\n\n"
- (plist-get metadata :date)))
- (when-let ((thumbnail (ennu-post-thumbnail post)))
- (insert (format "[[thumbnail:%s]]\n\n" thumbnail)))
- (when-let ((summary (plist-get metadata :summary)))
- (insert summary)
- (insert "\n\n"))
- (when-let ((tags (plist-get metadata :filetags)))
- (insert "Tags: ")
- (insert
- (string-join (seq-map (apply-partially 'format "[[tag:%s]]")
- tags)
- ", "))
- (insert "\n\n"))))
+ (insert (format "* [[post:%s]]\n" (file-name-base (ennu-post-filename post))))
+ (insert (format-time-string
+ "/%b %e, %Y/\n\n"
+ (ennu-post-date post)))
+ (when-let ((thumbnail (ennu-post-thumbnail post)))
+ (insert (format "[[thumbnail:%s]]\n\n" thumbnail)))
+ (when-let ((summary (ennu-post-summary post)))
+ (insert summary)
+ (insert "\n\n"))
+ (when-let ((tags (ennu-post-tags post)))
+ (insert "Tags: ")
+ (insert
+ (string-join (seq-map (apply-partially 'format "[[tag:%s]]")
+ tags)
+ ", "))
+ (insert "\n\n")))
posts)
(unless (= page-number 1)
(insert (format "[[./%s][Newer posts]]\n"
@@ -142,7 +191,7 @@ last form in BODY."
(format-time-string "%Y-%m-%dT%H:%M:%SZ" date))
(defun ennu-publish-feed (feed-file title rights posts)
- `(,posts
+ `(,(seq-map 'ennu-post-filename posts)
(,feed-file)
,(lambda (output-file)
(with-temp-file output-file
@@ -151,7 +200,7 @@ last form in BODY."
`(feed :xmlns "http://www.w3.org/2005/Atom"
(id ,(ennu--absolute-uri ""))
(title ,title)
- (updated ,(ennu--atom-date (plist-get (ennu-post-metadata (first posts)) :date)))
+ (updated ,(ennu--atom-date (ennu-post-date (first posts))))
(link :rel "self" :href ,(ennu--absolute-uri feed-file))
(generator
,(format "Emacs %d.%d Org-mode %s ennu %s"
@@ -160,21 +209,20 @@ last form in BODY."
,@(seq-map 'ennu--feed-entry posts))))))))
(defun ennu--feed-entry (post)
- (let* ((metadata (ennu-post-metadata post))
- (lang (plist-get metadata :lang))
- (link (ennu--absolute-uri (ennu--org-output-filename post))))
+ (let ((link (ennu--absolute-uri (ennu--org-output-filename
+ (ennu-post-filename post)))))
`(entry (id ,link)
- (title :xml:lang ,lang ,(plist-get metadata :title))
- (updated ,(ennu--atom-date (plist-get metadata :date)))
+ (title :xml:lang ,(ennu-post-language post) ,(ennu-post-title post))
+ (updated ,(ennu--atom-date (ennu-post-date post)))
(author
- (name ,(plist-get metadata :author))
+ (name ,(ennu-post-author post))
(email ,user-mail-address))
- (content :type "html" :xml:lang ,lang
- ,(ennu-with-file-contents post
+ (content :type "html" :xml:lang ,(ennu-post-language post)
+ ,(ennu-with-file-contents (ennu-post-filename post)
(org-export-as 'ennu-html nil nil t)))
(link :rel "alternate" :href ,link)
,@(seq-map (lambda (tag) `(category :term ,tag))
- (plist-get metadata :filetags)))))
+ (ennu-post-tags post)))))
(defun ennu-setting (property)
(pcase property
@@ -233,50 +281,6 @@ last form in BODY."
(defun ennu-publish-copy (file)
`((,file) (,file) ,(apply-partially 'copy-file file)))
-(defun ennu-post-links (post)
- (ennu-with-file-contents post
- (org-element-map (org-element-parse-buffer) 'link
- (lambda (link)
- (pcase link
- (`(link ,properties . ,_)
- (let ((link-type (org-element-property :type link)))
- (when (member link-type (list "image" "static" "video"))
- (cons link-type (org-element-property :path link))))))))))
-
-(defun ennu-plist-map-to-plist (function plist)
- "Apply FUNCTION to each key-value pair of PLIST and return the
-result as a plist with keys being the keys in PLIST and the
-values being the values returned by FUNCTION. FUNCTION is called
-with two arguments -- the key and the value."
- (seq-mapcat
- (pcase-lambda (`(,key ,value))
- (list key (funcall function key value)))
- (seq-partition plist 2)))
-
-(defun ennu-post-metadata (post)
- (ennu--post-metadata-memoized
- post (file-attribute-modification-time
- (file-attributes post))))
-
-(defmemoize ennu--post-metadata-memoized (post last-modified)
- (ennu-with-file-contents post
- (let ((metadata (org-export-get-environment 'ennu-html))
- (export (apply-partially 'org-export-with-backend 'ennu-html)))
- (seq-do (lambda (key)
- (unless (plist-member metadata key)
- (user-error "Metadata %s not specified" key)))
- ennu-mandatory-metadata)
- (ennu-plist-map-to-plist
- (lambda (key value)
- (pcase key
- ((or :author :summary :title)
- (funcall export (first (plist-get metadata key))))
- (:date (org-timestamp-to-time (first (plist-get metadata :date))))))
- metadata))))
-
-(defvar ennu-mandatory-metadata
- (list :title :date))
-
(defun newest-file (files)
(pcase files
(`(,head . ,tail)
@@ -318,20 +322,9 @@ with two arguments -- the key and the value."
(seq-map 'file-name-directory absolute-output-files)))
(apply publish absolute-output-files))))))))
-(defun ennu--later-post (post1 post2)
- (time-less-p (plist-get (ennu-post-metadata post2) :date)
- (plist-get (ennu-post-metadata post1) :date)))
-
(defun ennu-publish-static-file (file)
`((,file) (,file) ,(apply-partially 'copy-file file)))
-(defun ennu-posts (posts-directory)
- (sort (file-expand-wildcards
- (concat (file-name-as-directory
- (ennu-setting :posts-directory))
- "*.org"))
- 'ennu--later-post))
-
(defun ennu-publish-link (link)
(pcase link
(`("image" . ,path)
@@ -346,12 +339,6 @@ with two arguments -- the key and the value."
(ennu-publish-copy (ennu--expand-relative (ennu-video-poster path)
(ennu-setting :images-directory))))))
-(defun ennu-post-tags (post)
- (plist-get (ennu-post-metadata post) :filetags))
-
-(defun ennu-post-tongue (post)
- (plist-get (ennu-post-metadata post) :language))
-
(defmacro ennu-with-current-directory (directory &rest body)
"Change to DIRECTORY, evaluate BODY and restore the current
working directory. The value returned is the value of the last
@@ -412,7 +399,7 @@ as keys. Keys are compared using `equal'."
(seq-map
(pcase-lambda (`(,tongue . ,posts))
(ennu-publish-index "index" tongue blog-title posts-per-page posts))
- (seq-group-by 'ennu-post-tongue posts))
+ (seq-group-by 'ennu-post-language posts))
(seq-mapcat
(pcase-lambda (`(,tag . ,posts))
(seq-map
@@ -420,7 +407,7 @@ as keys. Keys are compared using `equal'."
(ennu-publish-index
(ennu--expand-relative tag (ennu-setting :tag-directory))
tongue tag posts-per-page posts))
- (seq-group-by 'ennu-post-tongue posts)))
+ (seq-group-by 'ennu-post-language posts)))
(ennu-many-to-many-group-by 'ennu-post-tags posts))
;; Publish links
(seq-map 'ennu-publish-link