(require 'ox-publish) (add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/ox-rss") (add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/htmlize") (add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/f") (add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/s") (add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/dash") (require 'ox-rss) (require 'htmlize) (require 'project) (require 'f) (setq org-html-htmlize-output-type 'css org-html-validation-link nil org-html-head "" org-html-head-extra nil org-html-head-include-default-style nil org-html-head-include-scripts nil org-html-preamble nil org-html-postamble nil org-html-use-infojs nil org-html-self-link-headlines t org-html-allow-name-attribute-in-anchors t org-confirm-babel-evaluate nil org-babel-default-header-args '((:session . "none") (:results . "replace") (:exports . "code") (:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "no") (:mkdirp . "yes")) org-export-with-author nil org-export-with-email nil org-export-with-creator t org-export-with-toc nil org-export-with-section-numbers nil org-export-with-time-stamp-file t org-export-with-todo-keywords t org-export-with-statistics-cookies t org-export-with-broken-link t org-export-with-sub-superscripts '{} org-publish-sitemap-sort-files 'anti-chronologically org-rss-extension "xml") (defun cmmm/org-list-flatten (list) `(unordered (,(caadr list) ,(cons 'unordered (mapcar (lambda (e) (cadadr e)) (cddr list)))))) (defun cmmm/org-publish-org-sitemap (title list) "Sitemap generation function." (concat "#+title: " title "\n\n" (org-list-to-org (cmmm/org-list-flatten list)))) (defun cmmm/org-publish-org-sitemap-format-with-date (entry style project) "Custom sitemap entry formatting: add date" (cond ((not (directory-name-p entry)) (format "[[file:%s][(%s) %s]]" entry (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)) (org-publish-find-title entry project))) ((eq style 'tree) ;; Return only last subdir. (file-name-nondirectory (directory-file-name entry))) (t entry))) (defun cmmm/org-get-first-paragraph (file) "Get string content of first paragraph of file." (with-temp-buffer (insert-file-contents file) (goto-char (point-min)) (show-all) (let ((first-begin (progn (org-forward-heading-same-level 1) (point))) (first-end (progn (org-next-visible-heading 1) (point)))) (buffer-substring first-begin first-end)))) ;; (defun cmmm/org-rss-publish-to-rss (plist filename pub-dir) ;; "Prepare rss.org file before exporting." ;; (let* ((postsdir "posts")) ;; (with-current-buffer (find-file filename) ;; (erase-buffer) ;; (insert "#+TITLE: Web Log RSS\n") ;; ;; (insert "#+SETUPFILE: setup.org\n") ;; ;; (insert "#+INCLUDE: source-blocks.org\n") ;; ;; (insert "#+OPTIONS: toc:nil\n") ;; (let* ((files-all ;; (reverse (directory-files postsdir nil ;; "[0-9-]+.*\\.org$"))) ;; (files (cl-subseq files-all 0 (min (length files-all) 30)))) ;; (dolist (post files) ;; (let* ((post-file (concat (file-name-as-directory postsdir) post)) ;; (post-title (org-publish-find-title post-file plist)) ;; (preview-str (cmmm/org-get-first-paragraph post-file)) ;; (date (replace-regexp-in-string ;; "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)-.*" ;; "\\1" post))) ;; (insert (concat "* [[file:posts/" post "][" post-title "]]\n\n")) ;; (org-set-property "ID" post) ;; ;; ox-rss prepends html-link-home to permalink ;; (org-set-property "RSS_PERMALINK" ;; (concat "../posts/" ;; (file-name-sans-extension post) ;; ".html")) ;; (org-set-property ;; "PUBDATE" ;; (format-time-string ;; "<%Y-%m-%d %a %H:%M>" ;; (org-time-string-to-time ;; (replace-regexp-in-string ;; "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)-.*" ;; "\\1" post)))) ;; (insert "*") ;; (insert preview-str) ;; (newline 1) ;; (insert (concat "[[file:./web-log/" post "][(Read more)]]\n\n")))) ;; (save-buffer)))) ;; (let ((user-mail-address "t") ;; (org-export-with-broken-links t) ;; (org-rss-use-entry-url-as-guid nil)) ;; (org-rss-publish-to-rss plist filename pub-dir))) ;; (setcdr ;; (assq 'path org-html-mathjax-options) ;; '("https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML")) (defvar cmmm/org-tangle-list-cache nil) (defun cmmm/org-export-collect-tangle (backend) ;; Remove hook to ensure it does not get called recursively (remove-hook 'org-export-before-processing-hook 'cmmm/org-export-collect-tangle) (when (equal backend 'cmmm/html) (setq cmmm/org-tangle-list-cache nil) (save-excursion (save-restriction (widen) (show-all) (let ((src-blocks (org-babel-tangle-collect-blocks))) (dolist (src-lang src-blocks) (dolist (src-block (cdr src-lang)) (let ((src-block-name (nth 4 src-block)) (src-block-tangle (cdr (assoc :tangle (nth 5 src-block))))) (add-to-list 'cmmm/org-tangle-list-cache `(,src-block-name . ,src-block-tangle)))))))))) (defun cmmm/html-src-block (src-block contents info) "Transcode a SRC-BLOCK element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel. Add name of tangle file to source block (this requires a preprocessing hook to be added with `cmmm/org-export-collect-tangle')." (let* ((src-block-name (org-element-property :name src-block)) (src-block-language (org-element-property :language src-block)) (src-block-tangle (when cmmm/org-tangle-list-cache (cdr (assoc src-block-name cmmm/org-tangle-list-cache)))) (export-out (org-export-with-backend 'html src-block contents info))) (when (and src-block-tangle (> (length src-block-tangle) 0) (not (string= src-block-tangle "no"))) (let ((src-start-pat "\\(
]+>\\)"))
        (setq export-out
              (replace-regexp-in-string
               src-start-pat
               (concat "
" "" src-block-language "" "[" src-block-tangle "]" "
\n" "\\1\n") export-out)))) export-out)) (org-export-define-derived-backend 'cmmm/html 'html :translate-alist '((src-block . cmmm/html-src-block))) (defun cmmm/org-html-head-extra (filename) "Construct org-html-preamble with site navigation." (let* ((src (f-join (f-full (project-root (project-current))) "src/")) (relative (file-name-as-directory (string-remove-prefix src (f-dirname filename)))) (forward (substring relative (string-search "/" relative))) (backward (mapconcat (lambda (e) "../") (f-split relative))) (networks '(("https://www.michalec.dev/" . www) ("http://ygg.michalec.dev/" . ygg) ("http://michalec.i2p/" . i2p))) (languages '(en ru sk es)) ;; (language-paths (mapcar (lambda (language) ;; (cons language ;; (if (eq language 'en) ;; "/" (format "/%s/" language)))) ;; languages)) (up '((en . "up") (ru . "вверх") (sk . "hore") (es . "subir"))) (home '((en . "home") (ru . "домой") (sk . "domov") (es . "inicio"))) (language (intern (car (f-split relative))))) (string-join (append `(""))) "\n"))) (defun cmmm/org-html-publish-to-html (plist filename pub-dir) "Publish an org file to HTML. 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. Return output file name." (add-hook 'org-export-before-processing-hook 'cmmm/org-export-collect-tangle) (let ((res (org-publish-org-to 'cmmm/html filename (concat "." (or (plist-get plist :html-extension) org-html-extension "html")) (append plist `(:html-head-extra ,(cmmm/org-html-head-extra filename))) pub-dir))) (remove-hook 'org-export-before-processing-hook 'cmmm/org-export-collect-tangle) res)) (defun cmmm/org-babel-tangle-publish (_ filename pub-dir) "Tangle FILENAME and place the results in PUB-DIR." (let ((org-dir (file-name-as-directory (f-dirname filename)))) (mapc (lambda (tangled-file) (let* ((tangled-file-relative (string-remove-prefix org-dir tangled-file)) (tangled-file-pub (f-join pub-dir tangled-file-relative)) (tangled-file-pub-dir (f-dirname tangled-file-pub))) (unless (file-exists-p tangled-file-pub-dir) (make-directory tangled-file-pub-dir t)) (rename-file tangled-file tangled-file-pub t))) (org-babel-tangle-file filename)))) (setq org-publish-project-alist (append (mapcar (lambda (language) (let ((sitemap '((en . "Sitemap") (ru . "Карта сайта") (sk . "Mapa Stránky") (es . "Mapa del Sitio")))) `(,(format "%s-site" language) :language ,(symbol-name language) :base-directory ,(format "./src/%s/" language) :recursive t :base-extension "org" :exclude "setup\\.org" :with-toc t :auto-sitemap t :sitemap-title ,(alist-get language sitemap (alist-get 'en sitemap)) ;; :sitemap-function cmmm/org-publish-org-sitemap :publishing-directory ,(format "./pub/%s/" language) :publishing-function (cmmm/org-html-publish-to-html org-org-publish-to-org)))) '(en ru sk es)) (mapcar (lambda (language) (let ((sitemap '((en . "Sitemap") (ru . "Карта сайта") (sk . "Mapa Stránky") (es . "Mapa del Sitio")))) `(,(format "%s-site-articles" language) :language ,(symbol-name language) :base-directory ,(format "./src/%s/articles/" language) :recursive t :base-extension "org" :exclude "setup\\.org\\|rss\\.org" :with-toc t :section-numbers t :auto-sitemap t :sitemap-title ,(alist-get language sitemap (alist-get 'en sitemap)) :sitemap-function cmmm/org-publish-org-sitemap :publishing-directory ,(format "./pub/%s/articles/" language) :publishing-function (cmmm/org-html-publish-to-html org-org-publish-to-org cmmm/org-babel-tangle-publish)))) '(en ru sk es)) (mapcar (lambda (language) (let ((sitemap '((en . "Sitemap") (ru . "Карта сайта") (sk . "Mapa Stránky") (es . "Mapa del Sitio")))) `(,(format "%s-site-web-log" language) :language ,(symbol-name language) :base-directory ,(format "./src/%s/web-log/" language) :recursive t :base-extension "org" :exclude "setup\\.org\\|rss\\.org" :with-toc t :auto-sitemap t :sitemap-title ,(alist-get language sitemap (alist-get 'en sitemap)) :sitemap-function cmmm/org-publish-org-sitemap :publishing-directory ,(format "./pub/%s/web-log/" language) :publishing-function (cmmm/org-html-publish-to-html org-org-publish-to-org cmmm/org-babel-tangle-publish)))) '(en ru sk es)) ;; ("site-web-log-rss" ;; :base-directory "./src/web-log" ;; :base-extension "org" ;; :include ("rss.org") ;; :exclude ".*" ;; :with-todo-keywords nil ;; :with-statistics-cookies nil ;; :with-broken-link t ;; :with-email nil ;; :html-link-use-abs-url t ;; :html-link-home "/web-log/index.html" ;; :publishing-directory "./pub/web-log/" ;; :publishing-function cmmm/org-rss-publish-to-rss) '(("site-attachments" :base-directory "./src/" :recursive t :base-extension "css\\|woff2\\|png\\|jpg\\|gif\\|pdf\\|mp3" :publishing-directory "./pub/" :publishing-function org-publish-attachment) ("site-aux" :base-directory "./src/aux" :recursive t :base-extension any :publishing-directory "./pub/aux/" :publishing-function org-publish-attachment) ("site-private" :base-directory "./src/private" :recursive t :base-extension any :publishing-directory "./pub/private/" :publishing-function org-publish-attachment)))) (org-publish-all t)