;; -*- lexical-binding: t -*- (require 'ox) (require 'subr-x) (require 'xmlgen) (require 'ennum-lang) (defun expand-file-name* (name base-directory) (expand-file-name name (concat "/" base-directory))) (org-export-define-derived-backend 'ennum-html 'html :translate-alist '((inner-template . ennum-html-inner-template) (link . ennum-html-link)) :options-alist '((:summary "SUMMARY" nil nil parse) (:thumbnail "THUMBNAIL" nil nil t) (:translation-group "TRANSLATION_GROUP" nil nil t) (:html-doctype "HTML_DOCTYPE" nil "html5"))) (defun ennum-html-inner-template (contents info) (concat ;; Table of contents (let ((depth (plist-get info :with-toc))) (when depth (org-html-toc depth info))) ;; Beginning of h-entry "
" ;; Title (format "

%s

\n" (org-export-data (plist-get info :title) info)) ;; Author and date (let ((author (when (plist-get info :with-author) (plist-get info :author))) (date (when (plist-get info :with-date) (org-export-get-date info)))) (when (or author date) (xmlgen `(p "Published" ,@(when author `(" by " (a :class "p-author h-card" :href ,(ennum--absolute-uri "") ,(car (plist-get info :author))))) ,@(when date `(" on " (time :class "dt-published" :datetime ,(org-export-get-date info "%Y-%m-%d 12:00:00") ,(org-export-get-date info "%B %d, %Y")))))))) ;; Interlanguage language links (when-let (translations (ennum-post-translations (plist-get info :ennum-post))) (format "

In other languages: %s

" (mapconcat (pcase-lambda (`(,lang . ,slug)) (replace-regexp-in-string "Tags: %s

" (mapconcat (lambda (tag) (replace-regexp-in-string "
%s" (org-export-data (plist-get info :summary) info)) ;; Document contents (format "
%s
" contents) ;; Footnotes section (org-html-footnote-section info) "
")) (defun ennum-html-find-link (type path info) "Find link of TYPE and PATH in post object stored in :ennum-posts of property list INFO." (seq-find (lambda (link) (and (eq (ennum-link-type link) type) (string= (ennum-link-path link) path))) (ennum-post-links (plist-get info :ennum-post)))) (defun ennum-html-link (link desc info) ;; We override the html link transcoder to handle image, post and ;; video links differently. We cannot use the `:export' property of ;; `org-link-parameters' since those functions cannot access the ;; `info' communication channel. (let ((path (org-element-property :path link))) (pcase (org-element-property :type link) ("image" ;; Convert image links to file links, get them transcoded by ;; `org-html-link' and then remove the file:// scheme from the ;; URI. Finally insert the transcoded image link in a link to a ;; larger image as specified by the :image-link-width setting. (format "%s" (expand-file-name* (ennum-image-output-filename path (ennum-setting :image-link-width)) (ennum-setting :images-directory)) (replace-regexp-in-string (rx (group (or "src" "data")) "=\"file://") "\\1=\"" (org-html-link (org-element-put-property (org-element-put-property link :path (url-encode-url (expand-file-name* (ennum-image-output-filename path (ennum-setting :image-width)) (ennum-setting :images-directory)))) :type "file") desc info)))) ("post" (ennum-html-export-post path (or desc (ennum-post-link-target-title (ennum-html-find-link 'post path info))) (org-export-backend-name (plist-get info :back-end)))) ("video" (xmlgen `(video :src ,(url-encode-url (expand-file-name* path (ennum-setting :videos-directory))) :poster ,(url-encode-url (expand-file-name* (ennum-video-link-poster (ennum-html-find-link 'video path info)) (ennum-setting :images-directory))) :preload "none" :controls ""))) ;; Pass other link types to org-html-link (_ (org-html-link link desc info))))) (defmacro ennum-html-follow (path) `(ennum-with-current-directory (ennum-setting :working-directory) (find-file ,path))) ;; TODO: Pass title through org-export-data-with-backend or something ;; similar in order to export org syntax in title (defun ennum-html-export-post (path desc backend) (pcase backend ((or 'ennum-html 'html) (xmlgen `(a :href ,(url-encode-url (expand-file-name* path (ennum-setting :posts-directory))) ,desc))))) (defun ennum-html-follow-post (path) (ennum-html-follow (expand-file-name (concat path ".org") (ennum-setting :posts-directory)))) (org-link-set-parameters "post" :export 'ennum-html-export-post :follow 'ennum-html-follow-post) (defun ennum-html-follow-image (path) (ennum-html-follow (expand-file-name path (ennum-setting :images-directory)))) (org-link-set-parameters "image" :follow 'ennum-html-follow-image) (defun ennum-html-export-thumbnail (path _desc backend) (pcase backend ((or 'ennum-html 'html) (xmlgen `(img :src ,(url-encode-url (expand-file-name* (ennum-image-output-filename path (ennum-setting :image-thumbnail-width)) (ennum-setting :images-directory)))))))) (org-link-set-parameters "thumbnail" :export 'ennum-html-export-thumbnail :follow 'ennum-html-follow-image) (defun ennum-html-follow-video (path) (ennum-html-follow (expand-file-name path (ennum-setting :videos-directory)))) (org-link-set-parameters "video" :follow 'ennum-html-follow-video) (defun ennum-html-export-pdf (path desc backend) (pcase backend ((or 'ennum-html 'html) (xmlgen (let ((link-path (url-encode-url (expand-file-name* path (ennum-setting :static-directory))))) `(object :data ,link-path :type "application/pdf" :width ,(ennum-setting :pdf-width) :height ,(ennum-setting :pdf-height) "Download " (a :href ,link-path ,path))))))) (org-link-set-parameters "pdf" :export 'ennum-html-export-pdf) (defun ennum-html-export-static (path desc backend) (pcase backend ((or 'ennum-html 'html) (xmlgen `(a :href ,(url-encode-url (expand-file-name* path (ennum-setting :static-directory))) ,desc))))) (org-link-set-parameters "static" :export 'ennum-html-export-static) (org-link-set-parameters "tangle" :export 'ennum-html-export-static) (defun ennum-html-export-tag (tag desc backend) (pcase backend ((or 'ennum-html 'html) (xmlgen `(a :href ,(url-encode-url (expand-file-name* tag (ennum-setting :tag-directory))) ,(or desc tag)))))) (org-link-set-parameters "tag" :export 'ennum-html-export-tag) (provide 'ennum-html)