summaryrefslogtreecommitdiff
path: root/bin/export.el
diff options
context:
space:
mode:
Diffstat (limited to 'bin/export.el')
-rw-r--r--bin/export.el379
1 files changed, 379 insertions, 0 deletions
diff --git a/bin/export.el b/bin/export.el
new file mode 100644
index 0000000..92e4fc3
--- /dev/null
+++ b/bin/export.el
@@ -0,0 +1,379 @@
1(require 'ox-publish)
2(add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/ox-rss")
3(add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/htmlize")
4(add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/f")
5(add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/s")
6(add-to-list 'load-path "/home/cmmm/.config/emacs/elpaca/builds/dash")
7(require 'ox-rss)
8(require 'htmlize)
9(require 'project)
10(require 'f)
11
12(setq org-html-htmlize-output-type 'css
13 org-html-validation-link nil
14 org-html-head "<link rel=\"stylesheet\" href=\"/custom.css\"/>"
15 org-html-head-extra nil
16 org-html-head-include-default-style nil
17 org-html-head-include-scripts nil
18 org-html-preamble nil
19 org-html-postamble nil
20 org-html-use-infojs nil
21 org-html-self-link-headlines t
22 org-html-allow-name-attribute-in-anchors t
23
24 org-confirm-babel-evaluate nil
25 org-babel-default-header-args '((:session . "none")
26 (:results . "replace")
27 (:exports . "code")
28 (:cache . "no")
29 (:noweb . "no")
30 (:hlines . "no")
31 (:tangle . "no")
32 (:mkdirp . "yes"))
33
34 org-export-with-author nil
35 org-export-with-email nil
36 org-export-with-creator t
37 org-export-with-toc nil
38 org-export-with-section-numbers nil
39 org-export-with-time-stamp-file t
40 org-export-with-todo-keywords t
41 org-export-with-statistics-cookies t
42 org-export-with-broken-link t
43 org-export-with-sub-superscripts '{}
44
45 org-publish-sitemap-sort-files 'anti-chronologically
46
47 org-rss-extension "xml")
48
49
50(defun cmmm/org-list-flatten (list)
51 `(unordered (,(caadr list)
52 ,(cons 'unordered (mapcar (lambda (e) (cadadr e)) (cddr list))))))
53
54(defun cmmm/org-publish-org-sitemap (title list)
55 "Sitemap generation function."
56 (concat "#+title: " title "\n\n"
57 (org-list-to-org (cmmm/org-list-flatten list))))
58
59(defun cmmm/org-publish-org-sitemap-format-with-date (entry style project)
60 "Custom sitemap entry formatting: add date"
61 (cond ((not (directory-name-p entry))
62 (format "[[file:%s][(%s) %s]]" entry
63 (format-time-string
64 "%Y-%m-%d" (org-publish-find-date entry project))
65 (org-publish-find-title entry project)))
66 ((eq style 'tree)
67 ;; Return only last subdir.
68 (file-name-nondirectory (directory-file-name entry)))
69 (t entry)))
70
71(defun cmmm/org-get-first-paragraph (file)
72 "Get string content of first paragraph of file."
73 (with-temp-buffer
74 (insert-file-contents file)
75 (goto-char (point-min))
76 (show-all)
77 (let ((first-begin (progn
78 (org-forward-heading-same-level 1)
79 (point)))
80 (first-end (progn
81 (org-next-visible-heading 1)
82 (point))))
83 (buffer-substring first-begin first-end))))
84
85;; (defun cmmm/org-rss-publish-to-rss (plist filename pub-dir)
86;; "Prepare rss.org file before exporting."
87;; (let* ((postsdir "posts"))
88;; (with-current-buffer (find-file filename)
89;; (erase-buffer)
90;; (insert "#+TITLE: Web Log RSS\n")
91;; ;; (insert "#+SETUPFILE: setup.org\n")
92;; ;; (insert "#+INCLUDE: source-blocks.org\n")
93;; ;; (insert "#+OPTIONS: toc:nil\n")
94;; (let* ((files-all
95;; (reverse (directory-files postsdir nil
96;; "[0-9-]+.*\\.org$")))
97;; (files (cl-subseq files-all 0 (min (length files-all) 30))))
98;; (dolist (post files)
99;; (let* ((post-file (concat (file-name-as-directory postsdir) post))
100;; (post-title (org-publish-find-title post-file plist))
101;; (preview-str (cmmm/org-get-first-paragraph post-file))
102;; (date (replace-regexp-in-string
103;; "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)-.*"
104;; "\\1" post)))
105;; (insert (concat "* [[file:posts/" post "][" post-title "]]\n\n"))
106;; (org-set-property "ID" post)
107;; ;; ox-rss prepends html-link-home to permalink
108;; (org-set-property "RSS_PERMALINK"
109;; (concat "../posts/"
110;; (file-name-sans-extension post)
111;; ".html"))
112;; (org-set-property
113;; "PUBDATE"
114;; (format-time-string
115;; "<%Y-%m-%d %a %H:%M>"
116;; (org-time-string-to-time
117;; (replace-regexp-in-string
118;; "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)-.*"
119;; "\\1" post))))
120;; (insert "*")
121;; (insert preview-str)
122;; (newline 1)
123;; (insert (concat "[[file:./web-log/" post "][(Read more)]]\n\n"))))
124;; (save-buffer))))
125;; (let ((user-mail-address "t")
126;; (org-export-with-broken-links t)
127;; (org-rss-use-entry-url-as-guid nil))
128;; (org-rss-publish-to-rss plist filename pub-dir)))
129
130;; (setcdr
131;; (assq 'path org-html-mathjax-options)
132;; '("https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"))
133
134(defvar cmmm/org-tangle-list-cache nil)
135(defun cmmm/org-export-collect-tangle (backend)
136 ;; Remove hook to ensure it does not get called recursively
137 (remove-hook 'org-export-before-processing-hook
138 'cmmm/org-export-collect-tangle)
139 (when (equal backend 'cmmm/html)
140 (setq cmmm/org-tangle-list-cache nil)
141 (save-excursion
142 (save-restriction
143 (widen)
144 (show-all)
145 (let ((src-blocks (org-babel-tangle-collect-blocks)))
146 (dolist (src-lang src-blocks)
147 (dolist (src-block (cdr src-lang))
148 (let ((src-block-name (nth 4 src-block))
149 (src-block-tangle (cdr (assoc :tangle (nth 5 src-block)))))
150 (add-to-list 'cmmm/org-tangle-list-cache
151 `(,src-block-name . ,src-block-tangle))))))))))
152
153(defun cmmm/html-src-block (src-block contents info)
154 "Transcode a SRC-BLOCK element from Org to HTML.
155CONTENTS is nil. INFO is a plist used as a communication
156 channel. Add name of tangle file to source block (this
157 requires a preprocessing hook to be added with
158 `cmmm/org-export-collect-tangle')."
159 (let* ((src-block-name (org-element-property :name src-block))
160 (src-block-language (org-element-property :language src-block))
161 (src-block-tangle
162 (when cmmm/org-tangle-list-cache
163 (cdr (assoc src-block-name cmmm/org-tangle-list-cache))))
164 (export-out (org-export-with-backend
165 'html src-block contents info)))
166 (when (and src-block-tangle (> (length src-block-tangle) 0)
167 (not (string= src-block-tangle "no")))
168 (let ((src-start-pat "\\(<pre class=\"src src-[^>]+>\\)"))
169 (setq export-out
170 (replace-regexp-in-string
171 src-start-pat
172 (concat "<div class=\"src-label\">"
173 "<span>" src-block-language "</span>"
174 "<span>[<a href=./"
175 src-block-tangle ">" src-block-tangle "</a>]"
176 "</span></div>\n"
177 "\\1\n")
178 export-out))))
179 export-out))
180
181(org-export-define-derived-backend 'cmmm/html 'html
182 :translate-alist '((src-block . cmmm/html-src-block)))
183
184(defun cmmm/org-html-head-extra (filename)
185 "Construct org-html-preamble with site navigation."
186 (let* ((src (f-join (f-full (project-root (project-current))) "src/"))
187 (relative (file-name-as-directory
188 (string-remove-prefix src (f-dirname filename))))
189 (forward (substring relative (string-search "/" relative)))
190 (backward (mapconcat (lambda (e) "../") (f-split relative)))
191 (networks '(("https://www.michalec.dev/" . www)
192 ("http://ygg.michalec.dev/" . ygg)
193 ("http://michalec.i2p/" . i2p)))
194 (languages '(en ru sk es))
195 ;; (language-paths (mapcar (lambda (language)
196 ;; (cons language
197 ;; (if (eq language 'en)
198 ;; "/" (format "/%s/" language))))
199 ;; languages))
200 (up '((en . "up")
201 (ru . "вверх")
202 (sk . "hore")
203 (es . "subir")))
204 (home '((en . "home")
205 (ru . "домой")
206 (sk . "domov")
207 (es . "inicio")))
208 (language (intern (car (f-split relative)))))
209 (string-join
210 (append
211 `("<nav>"
212 "<ul>"
213 "<li><span>navigation:</span>"
214 "<ul>"
215 ,(format "<li>[<a accesskey=\"h\" href=\"/%s/\">%s</a>]</li>"
216 language (alist-get language home (alist-get 'en home)))
217 ,(format "<li>[<a accesskey=\"u\" href=\"%s\">%s</a>]</li>"
218 (if (string-equal relative (format "%s/" language)) "." "../")
219 (alist-get language up (alist-get 'en up)))
220 "</ul>"
221 "</li>"
222 "<li><span>networks:</span>"
223 "<ul>")
224 (mapcar (lambda (network)
225 (format "<li>[<a href=\"%s\">%s</a>]</li>"
226 (concat (car network) relative)
227 (cdr network)))
228 networks)
229 '("</ul>" "</li>")
230 (append
231 '("<li><span>languages:</span>" "<ul>")
232 (mapcar (lambda (language)
233 (format "<li>[<a href=\"%s%s%s\">%s</a>]</li>"
234 backward language forward language))
235 languages)
236 '("</ul>"
237 "</li>"
238 "</ul>"
239 "</nav>")))
240 "\n")))
241
242(defun cmmm/org-html-publish-to-html (plist filename pub-dir)
243 "Publish an org file to HTML.
244
245FILENAME is the filename of the Org file to be published. PLIST
246is the property list for the given project. PUB-DIR is the
247publishing directory.
248
249Return output file name."
250 (add-hook 'org-export-before-processing-hook
251 'cmmm/org-export-collect-tangle)
252 (let ((res (org-publish-org-to
253 'cmmm/html filename (concat "."
254 (or (plist-get plist :html-extension)
255 org-html-extension
256 "html"))
257 (append plist
258 `(:html-head-extra ,(cmmm/org-html-head-extra filename)))
259 pub-dir)))
260 (remove-hook 'org-export-before-processing-hook
261 'cmmm/org-export-collect-tangle)
262 res))
263
264(defun cmmm/org-babel-tangle-publish (_ filename pub-dir)
265 "Tangle FILENAME and place the results in PUB-DIR."
266 (let ((org-dir (file-name-as-directory (f-dirname filename))))
267 (mapc (lambda (tangled-file)
268 (let* ((tangled-file-relative (string-remove-prefix org-dir tangled-file))
269 (tangled-file-pub (f-join pub-dir tangled-file-relative))
270 (tangled-file-pub-dir (f-dirname tangled-file-pub)))
271 (unless (file-exists-p tangled-file-pub-dir)
272 (make-directory tangled-file-pub-dir t))
273 (rename-file tangled-file tangled-file-pub t)))
274 (org-babel-tangle-file filename))))
275
276(setq org-publish-project-alist
277 (append
278 (mapcar
279 (lambda (language)
280 (let ((sitemap '((en . "Sitemap")
281 (ru . "Карта сайта")
282 (sk . "Mapa Stránky")
283 (es . "Mapa del Sitio"))))
284 `(,(format "%s-site" language)
285 :language ,(symbol-name language)
286 :base-directory ,(format "./src/%s/" language)
287 :recursive t
288 :base-extension "org"
289 :exclude "setup\\.org"
290 :with-toc t
291 :auto-sitemap t
292 :sitemap-title ,(alist-get language sitemap (alist-get 'en sitemap))
293 ;; :sitemap-function cmmm/org-publish-org-sitemap
294 :publishing-directory ,(format "./pub/%s/" language)
295 :publishing-function (cmmm/org-html-publish-to-html
296 org-org-publish-to-org))))
297 '(en ru sk es))
298
299 (mapcar
300 (lambda (language)
301 (let ((sitemap '((en . "Sitemap")
302 (ru . "Карта сайта")
303 (sk . "Mapa Stránky")
304 (es . "Mapa del Sitio"))))
305 `(,(format "%s-site-articles" language)
306 :language ,(symbol-name language)
307 :base-directory ,(format "./src/%s/articles/" language)
308 :recursive t
309 :base-extension "org"
310 :exclude "setup\\.org\\|rss\\.org"
311 :with-toc t
312 :section-numbers t
313 :auto-sitemap t
314 :sitemap-title ,(alist-get language sitemap (alist-get 'en sitemap))
315 :sitemap-function cmmm/org-publish-org-sitemap
316 :publishing-directory ,(format "./pub/%s/articles/" language)
317 :publishing-function (cmmm/org-html-publish-to-html
318 org-org-publish-to-org
319 cmmm/org-babel-tangle-publish))))
320 '(en ru sk es))
321
322 (mapcar
323 (lambda (language)
324 (let ((sitemap '((en . "Sitemap")
325 (ru . "Карта сайта")
326 (sk . "Mapa Stránky")
327 (es . "Mapa del Sitio"))))
328 `(,(format "%s-site-web-log" language)
329 :language ,(symbol-name language)
330 :base-directory ,(format "./src/%s/web-log/" language)
331 :recursive t
332 :base-extension "org"
333 :exclude "setup\\.org\\|rss\\.org"
334 :with-toc t
335 :auto-sitemap t
336 :sitemap-title ,(alist-get language sitemap (alist-get 'en sitemap))
337 :sitemap-function cmmm/org-publish-org-sitemap
338 :publishing-directory ,(format "./pub/%s/web-log/" language)
339 :publishing-function (cmmm/org-html-publish-to-html
340 org-org-publish-to-org
341 cmmm/org-babel-tangle-publish))))
342 '(en ru sk es))
343
344 ;; ("site-web-log-rss"
345 ;; :base-directory "./src/web-log"
346 ;; :base-extension "org"
347 ;; :include ("rss.org")
348 ;; :exclude ".*"
349 ;; :with-todo-keywords nil
350 ;; :with-statistics-cookies nil
351 ;; :with-broken-link t
352 ;; :with-email nil
353 ;; :html-link-use-abs-url t
354 ;; :html-link-home "/web-log/index.html"
355 ;; :publishing-directory "./pub/web-log/"
356 ;; :publishing-function cmmm/org-rss-publish-to-rss)
357
358 '(("site-attachments"
359 :base-directory "./src/"
360 :recursive t
361 :base-extension "css\\|woff2\\|png\\|jpg\\|gif\\|pdf\\|mp3"
362 :publishing-directory "./pub/"
363 :publishing-function org-publish-attachment)
364
365 ("site-aux"
366 :base-directory "./src/aux"
367 :recursive t
368 :base-extension any
369 :publishing-directory "./pub/aux/"
370 :publishing-function org-publish-attachment)
371
372 ("site-private"
373 :base-directory "./src/private"
374 :recursive t
375 :base-extension any
376 :publishing-directory "./pub/private/"
377 :publishing-function org-publish-attachment))))
378
379(org-publish-all t)