;; sign it with ;; gpg --local-user yann@esposito.host --output project.el.sig --detach-sign project.el (defvar websiteorigin "https://her.esy.fun") (defvar root-dir (projectile-project-root)) (defvar base-dir (concat root-dir "src")) (defvar publish-dir (concat root-dir "_site")) (defvar draft-publish-dir (concat root-dir "_full")) (defvar assets-dir (concat base-dir "/")) (defvar publish-assets-dir (concat publish-dir "/")) (defvar draft-publish-assets-dir (concat draft-publish-dir "/")) (defvar posts-dir (concat base-dir "/posts")) (defvar rss-title "Subscribe to articles") (defvar css-path "/css/y.css") (defvar author-name "Yann Esposito") (defvar author-email "yann@esposito.host") (require 'org) (require 'ox-publish) (require 'ox-html) (require 'org-element) ;; (setq org-link-file-path-type 'relative) (setq org-publish-timestamp-directory (concat (projectile-project-root) "_cache/")) (defvar org-blog-head (concat "" "" "")) (defun menu (lst) "Blog menu" (concat "")) (defun get-from-info (info k) (let ((i (car (plist-get info k)))) (when (and i (stringp i)) i))) (defun logo () (concat "
" "" "" "" "" "" "" "" "" "
")) (defun relative-link (output-file) "Given an output-file generate a link relative to the URL origin." (replace-regexp-in-string ".*/_site" "" output-file)) (defun gen-permalink (output-file) "Given the output-file generate a permalink" (format "%s%s" websiteorigin (relative-link output-file))) (defun gen-org-src (permalink) "Given a permalink generate the path to the asssociated .org source file" (replace-regexp-in-string "\.html$" ".org" permalink)) (defun org-blog-preamble (info) "Pre-amble for whole blog." (concat (logo) "
" "

" (format "%s" (car (plist-get info :title))) "

" (when-let ((subtitle (car (plist-get info :subtitle)))) (format "

%s

" subtitle)) (when-let ((date (plist-get info :date))) (concat "
" "Yann Esposito" "
" (format "%s" (format-time-string "%Y-%m-%d" (org-timestamp-to-time (car date)))) "
on " (format " Yann Esposito's blog" websiteorigin) (let ((permalink (gen-permalink (plist-get info :output-file)))) (concat " - " (let ((orgfile (gen-org-src permalink))) (format " source" orgfile)) " - " (format " §permalink" permalink))) "
")) (when-let ((description (plist-get info :description))) (format "
%s
" description)) "
")) (defun rand-obfs (c) (let ((r (% (random) 20))) (cond ;; ((eq 0 r) (format "%c" c)) ((<= 0 r 10) (format "&#%d;" c)) (t (format "&#x%X;" c))))) (defun obfuscate-html (txt) (apply 'concat (mapcar 'rand-obfs txt))) (defun keywords-to-html (keywords) (let ((keywords (split-string keywords ",\s*"))) (format " %s" (mapconcat (lambda (k) (format "#%s" k)) (cl-sort keywords 'string-lessp :key 'downcase) " ")))) (defun org-blog-postamble (info) "Post-amble for whole blog." (concat "
" ;; TODO install a comment system ;; (let ((url (format "%s%s" websiteorigin (replace-regexp-in-string base-dir "" (plist-get info :input-file))))) ;; (format "comment" ;; (url-hexify-string url))) "" (menu '("↑ Top ↑")) "
")) (defun date-format-entry (entry _style project) "Return string for each ENTRY in PROJECT." (when (string-match "posts/.*" entry) (let* ((file (org-publish--expand-file-name entry project)) (title (org-publish-find-title entry project)) (artdate (format-time-string "%Y-%m-%d" (org-publish-find-date entry project))) (description (org-publish-find-property entry :description project 'html))) (concat (format " @@html:%s@@: " artdate) (format " *[[file:%s][%s]]*" file title) (format " @@html:
%s
@@" description) (format " @@html:
@@ ") " @@html:
@@\n")))) (defun org-blog-sitemap-fn-descr (_descr title list) "Return sitemap using TITLE and LIST returned by `org-blog-sitemap-format-entry'." (concat "#+TITLE: " title "\n" "#+AUTHOR: " author-name "\n" "#+EMAIL: " author-email "\n" (concat "@@html:" (menu '()) "@@") "\n\n" (mapconcat (lambda (li) (format "%s" (car li))) (seq-filter #'car (cdr list)) "\n"))) (defun org-blog-prepare (project-plist) "With help from `https://github.com/howardabrams/dot-files'. Touch `archive.org' to rebuilt it. Argument `PROJECT-PLIST' contains information about the current project." (let* ((base-directory (plist-get project-plist :base-directory)) (buffer (find-file-noselect (expand-file-name "archive.org" base-directory) t))) (with-current-buffer buffer (set-buffer-modified-p t) (save-buffer 0)) (kill-buffer buffer))) (defun org-blog-publish-to-html (plist filename pub-dir) "Same as `org-html-publish-to-html' but modifies html before finishing." (let* ((file-path (org-html-publish-to-html plist filename pub-dir)) (mk-path (format "./%s.html" (replace-regexp-in-string ".*/\\([^/]*\\)\\.org$" "\\1" filename)))) (with-current-buffer (find-file-noselect file-path) (goto-char (point-min)) (search-forward "") (insert (mapconcat 'identity `("" "" "
" "
" "" "|" "" "
" "
" "
") "\n")) (goto-char (point-max)) (search-backward "") (insert "\n
\n") (save-buffer) (kill-buffer)) file-path)) (defun compress-image (filename dst-file) "Compress images using imagemagick" (shell-command (format (concat "~/.nix-profile/bin/convert" " %s" ;; source " -sampling-factor 4:2:0" " -strip" " -resize 300x300\\>" " -interlace Plane" " -quality 85" " -define filter:blur=0.75" " -filter Gaussian" " -ordered-dither o4x4,4" " %s" ;; dest ) filename dst-file))) (defun compress-css (root-dir filename dst-file) "Compress CSS usin compresscss.sh script" (shell-command (format "%s/engine/compresscss.sh %s %s" root-dir filename dst-file))) (defun org-blog-publish-attachment (plist filename pub-dir) "Publish a file with no transformation of any kind. FILENAME is the filename of the Org file to be published. PLIST is the property list for the given project. PUB-DIR is the publishing directory. Take care of minimizing the pictures using imagemagick. Return output file name." (unless (file-directory-p pub-dir) (make-directory pub-dir t)) (or (equal (expand-file-name (file-name-directory filename)) (file-name-as-directory (expand-file-name pub-dir))) (let ((dst-file (expand-file-name (file-name-nondirectory filename) pub-dir))) (cond ((string-match-p ".*\\.\\(png\\|jpg\\|jpeg\\|gif\\)$" filename) (compress-image filename dst-file)) ((string-match-p ".*\\.css$" filename) (compress-css root-dir filename dst-file)) (t (copy-file filename dst-file t)))))) (defalias 'org-blog-posts-sitemap-fn (apply-partially 'org-blog-sitemap-fn-descr "")) (setq org-html-htmlize-output-type 'css) (setq org-html-htmlize-font-prefix "org-") (setq org-publish-project-alist `(("orgfiles" :base-directory ,base-dir :exclude ".*drafts/.*" :base-extension "org" :publishing-directory ,publish-dir :recursive t :preparation-function org-blog-prepare :publishing-function org-blog-publish-to-html :with-toc nil :with-title nil :with-date t :section-numbers nil :html-doctype "html5" :html-html5-fancy t :html-head-include-default-style nil :html-head-include-scripts nil :htmlized-source t :html-head-extra ,org-blog-head :html-preamble org-blog-preamble :html-postamble org-blog-postamble :auto-sitemap t :sitemap-filename "archive.org" :sitemap-title "Articles" :sitemap-style list :sitemap-sort-files anti-chronologically :sitemap-format-entry date-format-entry :sitemap-function org-blog-posts-sitemap-fn) ("css" :base-directory ,assets-dir :base-extension "css" :publishing-directory ,publish-assets-dir :publishing-function org-blog-publish-attachment :recursive t) ("img" :base-directory ,assets-dir :base-extension "(jpg|png|gif|jpeg)" :publishing-directory ,publish-assets-dir :publishing-function org-blog-publish-attachment :recursive t) ("files" :base-directory ,assets-dir :base-extension ".*" :exclude ".*\.(org|css|jpg|png|gif|jpeg)$" :publishing-directory ,publish-assets-dir :publishing-function org-blog-publish-attachment :recursive t) ("draft-org-files" :base-directory ,base-dir :base-extension "org" :publishing-directory ,draft-publish-dir :recursive t :preparation-function org-blog-prepare :publishing-function org-blog-publish-to-html :with-toc nil :with-title nil :with-date t :section-numbers nil :html-doctype "html5" :html-html5-fancy t :html-head-include-default-style nil :html-head-include-scripts nil :htmlized-source t :html-head-extra ,org-blog-head :html-preamble org-blog-preamble :html-postamble org-blog-postamble) ("draft-css" :base-directory ,assets-dir :base-extension "css" :publishing-directory ,draft-publish-assets-dir :publishing-function org-blog-publish-attachment :recursive t) ("draft-img" :base-directory ,assets-dir :base-extension "(jpg|png|gif|jpeg)" :publishing-directory ,draft-publish-assets-dir :publishing-function org-blog-publish-attachment :recursive t) ("draft-files" :base-directory ,assets-dir :base-extension ".*" :include ".*\.(org|css|jpg|png|gif|jpeg)$" :publishing-directory ,draft-publish-assets-dir :publishing-function org-blog-publish-attachment :recursive t) ("assets" :components ("css" "img" "files")) ("blog" :components ("orgfiles" "assets")) ("draft-assets" :components ("draft-css" "draft-img" "draft-files")) ("draft" :components ("draft-org-files" "draft-assets")))) ;; add target=_blank and rel="noopener noreferrer" to all links by default (defun my-org-export-add-target-blank-to-http-links (text backend info) "Add target=\"_blank\" to external links." (when (and (org-export-derived-backend-p backend 'html) (string-match "href=\"http[^\"]+" text) (not (string-match "target=\"" text)) (not (string-match (concat "href=\"" websiteorigin "[^\"]*") text))) (string-match "