From 0a5d0ed2ffe56ae429a4105fa74329e0b646b366 Mon Sep 17 00:00:00 2001 From: "Yann Esposito (Yogsototh)" Date: Fri, 16 Aug 2019 22:51:11 +0200 Subject: [PATCH] Updates, fragment system to change theme. --- src/css/minimalist.css | 61 ++++- src/demo.org | 369 ++++++++++++++-------------- src/index.org | 4 +- src/posts/new-blog.org | 528 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 779 insertions(+), 183 deletions(-) diff --git a/src/css/minimalist.css b/src/css/minimalist.css index 5d36b8d..92b17de 100644 --- a/src/css/minimalist.css +++ b/src/css/minimalist.css @@ -48,11 +48,11 @@ li { } ul > li:before { content: "– "; - font-weight: bold; opacity: 0.5; float: left; position: relative; left: -20px; + text-align: right; width: 0; } ol { @@ -61,12 +61,18 @@ ol { ol > li:before { content: counter(ol) ". "; counter-increment: ol; - font-weight: bold; float: left; + text-align: right; position: relative; left: -20px; width: 0; } +ol > li:nth-child(n+10) { + padding-left:28px; +} +ol > li:nth-child(n+10):before { + left: -28px; +} img { max-width: 100%; max-height: 800px; @@ -314,6 +320,7 @@ navigation > a { body > input { display:none; } /* Light theme checked */ +input#light:target ~ .main, input#light:checked ~ .main { --main-background: #fefaf0; /* 0.5 lighter than #fdf6e3 */ --main-foreground: var(--base01); @@ -323,12 +330,14 @@ input#light:checked ~ .main { --border-color: var(--base2); --todo-txt: #FFF; } +input#light:target ~ #labels, input#light:checked ~ #labels { background: #fefaf0; color: var(--base00); } /* Dark theme checked */ +input#dark:target ~ .main, input#dark:checked ~ .main { --main-background: var(--base03); /* 0.5 darker than #002b36; */ --main-foreground: var(--base1); @@ -338,12 +347,14 @@ input#dark:checked ~ .main { --border-color: var(--base02); --todo-txt: #000; } +input#dark:target ~ #labels, input#dark:checked ~ #labels { background: var(--base03); color: var(--base0); } /* Light raw theme checked */ +input#raw:target ~ .main, input#raw:checked ~ .main { --main-background: #fff; --main-foreground: #000; @@ -361,16 +372,20 @@ input#raw:checked ~ .main { --color-link: var(--magenta); font-family: monospace; } +input#raw:target ~ #labels, input#raw:checked ~ #labels { background: #fff; color: #000; } +input#raw:target ~ .main code, +input#raw:target ~ .main pre, input#raw:checked ~ .main code, input#raw:checked ~ .main pre { font-family: monospace; } /* Light modern theme checked */ +input#modern:target ~ .main, input#modern:checked ~ .main { --main-background: #fff; --main-foreground: #444; @@ -385,10 +400,27 @@ input#modern:checked ~ .main { font-size: 16px; line-height: 24px; } +input#modern:target ~ .main .content, +input#modern:target ~ .main #content, input#modern:checked ~ .main .content, input#modern:checked ~ .main #content { margin: 0 auto; } + +input#modern:target ~ .main blockquote:after, +input#modern:checked ~ .main blockquote:after { + display: none; +} +input#modern:target ~ .main blockquote, +input#modern:checked ~ .main blockquote { + font-family: "Hoefler Text", Georgia, serif; + font-style: italic; + font-size: 20px; + line-height: 30px; + border-left: solid 10px; +} +input#modern:target ~ .main h1, +input#modern:target ~ .main h2, input#modern:checked ~ .main h1, input#modern:checked ~ .main h2 { font-family: "Hoefler Text", Georgia, serif; @@ -397,6 +429,10 @@ input#modern:checked ~ .main h2 { margin: 1em 0; } +input#modern:target ~ .main h3, +input#modern:target ~ .main h4, +input#modern:target ~ .main h5, +input#modern:target ~ .main h6, input#modern:checked ~ .main h3, input#modern:checked ~ .main h4, input#modern:checked ~ .main h5, @@ -405,9 +441,16 @@ input#modern:checked ~ .main h6 { font-size: 1.5em; margin: 1em 0; } +input#modern:target ~ .main #preamble h1, input#modern:checked ~ .main #preamble h1 { font-size: 4em; } +input#modern:target ~ .main h1::before, +input#modern:target ~ .main h2::before, +input#modern:target ~ .main h3::before, +input#modern:target ~ .main h4::before, +input#modern:target ~ .main h5::before, +input#modern:target ~ .main h6::before, input#modern:checked ~ .main h1::before, input#modern:checked ~ .main h2::before, input#modern:checked ~ .main h3::before, @@ -416,37 +459,48 @@ input#modern:checked ~ .main h5::before, input#modern:checked ~ .main h6::before { content: ""; } +input#modern:target ~ .main pre, input#modern:checked ~ .main pre { font-size: 14px; line-height; 21px; border-left: solid 4px var(--soft-foreground); padding-left: 1em; } +input#modern:target ~ .main pre::before, +input#modern:target ~ .main pre::after, input#modern:checked ~ .main pre::before, input#modern:checked ~ .main pre::after { content: ""; } +input#modern:target ~ .main #preamble, +input#modern:target ~ .main #postamble, input#modern:checked ~ .main #preamble, input#modern:checked ~ .main #postamble { background-color: var(--cyan); padding: 2em 0; } +input#modern:target ~ .main #postamble code, input#modern:checked ~ .main #postamble code { background-color: transparent; } +input#modern:target ~ .main #preamble *, +input#modern:target ~ .main #postamble *, input#modern:checked ~ .main #preamble *, input#modern:checked ~ .main #postamble * { color: #fff; } +input#modern:target ~ #labels, input#modern:checked ~ #labels { background: var(--cyan); color: #fff; } +input#modern:target ~ #labels .content, input#modern:checked ~ #labels .content { margin: 0 auto; } /* Dark raw theme checked */ +input#darkraw:target ~ .main, input#darkraw:checked ~ .main { --main-background: #000; --main-foreground: #fff; @@ -464,10 +518,13 @@ input#darkraw:checked ~ .main { --color-link: var(--yellow); font-family: monospace; } +input#darkraw:target ~ #labels, input#darkraw:checked ~ #labels { background: #000; color: #fff; } +input#darkraw:target ~ .main code, +input#darkraw:target ~ .main pre, input#darkraw:checked ~ .main code, input#darkraw:checked ~ .main pre { diff --git a/src/demo.org b/src/demo.org index cdc5dc3..0c541ac 100644 --- a/src/demo.org +++ b/src/demo.org @@ -4,7 +4,7 @@ #+KEYWORDS: programming #+DESCRIPTION: css demonstration #+OPTIONS: H:5 -#+OPTIONS: auto-id:t +#+OPTIONS: auto-id:t toc:t * Level 1 in org-mode :PROPERTIES: @@ -18,7 +18,7 @@ Here is a [[file:index.html][link to another page]]. There should be whitespace between paragraphs. -Mulitples lines +Multiples lines in the source code should be set as a single @@ -26,96 +26,156 @@ paragraph. But if I use a double space There should be a forced newline. -* Lorem Ipsum - :PROPERTIES: - :CUSTOM_ID: lorem-ipsum - :END: - - #+begin_src http :pretty - GET https://jaspervdj.be/lorem-markdownum/markdown.txt - #+end_src - -** Deos illo sacrum perque victorem eurytus paterque - :PROPERTIES: - :CUSTOM_ID: deos-illo-sacrum-perque-victorem-eurytus-paterque - :END: - -*** Haec tela discedentem femina - :PROPERTIES: - :CUSTOM_ID: haec-tela-discedentem-femina - :END: - -Lorem markdownum invidiosa iactor! Fidem utque indeploratum pariter. - -#+BEGIN_SRC javascript - var port = tooltipPimThreading; - if (pinterest_net_koffice) { - format -= installer; - buffer = 4; - office_device(2, ssh + model); - } else { - website_controller_linux.gigabyte = clone; - } - fileProtocol = driverOcr; -#+END_SRC - -*** Duorum habuisse horrentia de noceat - :PROPERTIES: - :CUSTOM_ID: duorum-habuisse-horrentia-de-noceat - :END: - -Patriam vocalibus peraget robore recursus diruta ut ergo signa factis, -nigrum, attonitas, in Solis. Mugit [[http://news.ycombinator.com][non -carpe sed]] ceperunt dextra ausum; sanguine durior. Soror Cinyras illos -remugis; super quia somno nunc retemptat oracula cumque. Id Helicen -primum, proles turis nemus claudit molior naturalique deciperetur qua -sulcat et, ad volui. - -1. Tubas gener -2. Ad pacta -3. Vetantis ferrum pugnabant quoque -4. Diomede pallida boum membra - -Saepe /mihi/? Tum comae iurasse statione morsus vigilans, ergo. Ipse dum -sunt Hymettia: fecit cum et coactis, potae carmine lynca fertur -descenderat. - -*** Subitis de luce et poenas cum - :PROPERTIES: - :CUSTOM_ID: subitis-de-luce-et-poenas-cum - :END: - -Cladem adit ergo es tecto sit visa dryades vota quos, prima ligno ficta. -Ibat supplex, /est/ costis oblita, elisi regis captum Phoebi tandem -conchaeque! Aera et Aello genetrix. - -Et caelo adspexit, cornua et Iuppiter inmensae /abies/. Micabant Paeonas -meliora constitit, ut expers *artisque* adspicit fretum, vulnere -oppidaque, tenuit arma, haec velamine unda. Retinentia iudice, *quos -moras* comitata aliquid prospiciens cepit cum iustius sua cur truncis -ausus unde partibus marisque et grave. Fui opertis liquor laudatae di -erat, repellit conspectos manibus. - -Auresque longius res Fando es /nil nec ora/ vixque et tot pendens maius -in et meliora! Flentibus verba nostro agmenque: dedit est regis virque -post Talia telumque, sol *et lanient* perierunt timido. Fitque variare -truncas Phoebus agros, salictis tam pumice facti! Post et neque et -vidit, Lycaeo incautus, latratus terrae thalamique ulta. - * Math :PROPERTIES: :CUSTOM_ID: math :END: - - \(x^y / \log(x)\) +Let also try to write some math inside the text $\pi_1(X,x_0)$ + +\(x^y / \log(x)\) \[ \prod_{i=0}^n \sum_{x_i\in E} \frac{1}{x_i} \] +* Blocks +:PROPERTIES: +:CUSTOM_ID: blocks +:END: +** Notes +:PROPERTIES: +:CUSTOM_ID: notes +:END: +#+begin_notes +This is some note. +With a bit of information and text. +Perhaps a list: + +- thing +- another thing +#+end_notes + +** Examples +:PROPERTIES: +:CUSTOM_ID: examples +:END: + +#+begin_example +This is an example. +We can say a few things. +Perhaps a list: + +- thing +- another thing +#+end_example + + +* Lists +:PROPERTIES: +:CUSTOM_ID: lists +:END: +** Ordered lists +:PROPERTIES: +:CUSTOM_ID: ordered-lists +:END: +1. counting with very very long lines. Just to check that everything is all + right regarding very long lines inside list, but also nested lists. +2. foo +3. bar +4. baz +5. counting +6. up +7. to +8. a +9. big +10. number enough +11. to have two +12. digits +13. The simplest example of a homotopy group is the /fundamental group/ of + a space, which is written $\pi_1(X,x_0)$: Given a space $X$ and a point + $x_0$ in it, one can make a group whose elements are loops at $x_0$ + (continuous paths from $x_0$ to $x_0$), considered up to homotopy, with + the group operations given by the identity path (standing still), path + concatenation, and path reversal. For example, the fundamental group of + the $2$-sphere is trivial, but the fundamental group of the torus is + not, which shows that the sphere and the torus are not homotopy + equivalent. The intuition is that every loop on the sphere is homotopic + to the identity, because its inside can be filled in. In contrast, a + loop on the torus that goes through the donut's hole is not homotopic + to the identity, so there are non-trivial elements in the fundamental + group. +14. Lot of things. +** Unordered list +:PROPERTIES: +:CUSTOM_ID: unordered-list +:END: +- counting with very very long lines. Just to check that everything is all + right regarding very long lines inside list, but also nested lists. +- foo +- bar +- baz +- counting +- up +- to +- a +- big +- number enough +- to have two +- digits +- The simplest example of a homotopy group is the /fundamental group/ of + a space, which is written $\pi_1(X,x_0)$: Given a space $X$ and a point + $x_0$ in it, one can make a group whose elements are loops at $x_0$ + (continuous paths from $x_0$ to $x_0$), considered up to homotopy, with + the group operations given by the identity path (standing still), path + concatenation, and path reversal. For example, the fundamental group of + the $2$-sphere is trivial, but the fundamental group of the torus is + not, which shows that the sphere and the torus are not homotopy + equivalent. The intuition is that every loop on the sphere is homotopic + to the identity, because its inside can be filled in. In contrast, a + loop on the torus that goes through the donut's hole is not homotopic + to the identity, so there are non-trivial elements in the fundamental + group. +- Lot of things. +** Nested +:PROPERTIES: +:CUSTOM_ID: nested +:END: + +- counting with very very long lines. Just to check that everything is all + right regarding very long lines inside list, but also nested lists. +- foo + - bar + - baz + - quux +- The simplest example of a homotopy group is the /fundamental group/ of + a space, which is written $\pi_1(X,x_0)$: Given a space $X$ and a point + $x_0$ in it, one can make a group whose elements are loops at $x_0$ + (continuous paths from $x_0$ to $x_0$), considered up to homotopy, with + the group operations given by the identity path (standing still), path + concatenation, and path reversal. + 1. counting with very very long lines. Just to check that everything is all + right regarding very long lines inside list, but also nested lists. + 2. foo + 1. Something else to nest. + 2. For example, the fundamental group of the $2$-sphere is trivial, + but the fundamental group of the torus is not, which shows that the + sphere and the torus are not homotopy equivalent. The intuition is + that every loop on the sphere is homotopic to the identity, because + its inside can be filled in. In contrast, a loop on the torus that + goes through the donut's hole is not homotopic to the identity, so + there are non-trivial elements in the fundamental group. + 3. The simplest example of a homotopy group is the /fundamental group/ of + a space, which is written $\pi_1(X,x_0)$: Given a space $X$ and a point + $x_0$ in it, one can make a group whose elements are loops at $x_0$ + (continuous paths from $x_0$ to $x_0$), considered up to homotopy, with + the group operations given by the identity path (standing still), path + concatenation, and path reversal. + 4. Lot of things. +- Lot of things. + * Level 1 :PROPERTIES: :CUSTOM_ID: level-1 :END: -** Level 2 +** Level 2 - paragraph :PROPERTIES: :CUSTOM_ID: level-2-85fc :END: @@ -124,7 +184,7 @@ vidit, Lycaeo incautus, latratus terrae thalamique ulta. GitHub is a code hosting platform for version control and collaboration. It lets you and others work together on projects from anywhere. -*** Level 3 +*** Level 3 - blockquote :PROPERTIES: :CUSTOM_ID: level-3 :END: @@ -136,7 +196,7 @@ vidit, Lycaeo incautus, latratus terrae thalamique ulta. favor. #+end_quote -**** Level 4 +**** Level 4 - source code :PROPERTIES: :CUSTOM_ID: level-4 :END: @@ -172,39 +232,10 @@ vidit, Lycaeo incautus, latratus terrae thalamique ulta. putStrLn $ "Hello " <> name <> "!" #+end_src -***** Level 5 - :PROPERTIES: - :CUSTOM_ID: level-5 - :END: - - - this is an unordered list following a header. - - this is an unordered list following a header. This time with quite a long - text that should goes to the line. Let's write a bit more text with some - =code= here, just to be sure that it use many lines. - - this is an unordered list following a header. - - 1. this is an ordered list. - 2. this is an ordered list that will use many lines. I will fill it with a bit - of random text. Also I will but some =code= inside it, with /italic/ and *bold* - text just to check the line-height. - - sub unordered - - sub sub unordered - - Ok, Haxx0r ipsum concurrently malloc leet new injection bin epoch daemon - system Leslie Lamport shell spoof. Finally boolean continue mutex endif - it’s a feature gobble packet public irc race condition grep ifdef I’m - compiling. Try catch bar bytes I’m sorry Dave, I’m afraid I can’t do - that pragma win sql gnu kilo deadlock blob try catch exception Donald - Knuth brute force. - - unordered - 1. ordered again - 2. yep :) - 3. this is an ordered list following a header. - 1. sub ordered - 2. second - 1. sub sub ordered - 2. still - 3. here - 4. this is an ordered list following a header. +***** Level 5 - table and rules +:PROPERTIES: +:CUSTOM_ID: level-5 +:END: | head1 | head two | |-----------+---------------------------| @@ -227,32 +258,10 @@ Bad too wide table... ------ -*** Here is an unordered list: - :PROPERTIES: - :CUSTOM_ID: here-is-an-unordered-list- - :END: - - - level 1 item - - level 2 item - - level 2 item - - level 2 item - - level 3 item - - level 3 item - - level 1 item - - level 2 item - - level 3 item - - level 3 item - - level 2 item - - level 2 item - - level 1 item - - level 2 item - - level 2 item - - level 2 item - -**** Image test - :PROPERTIES: - :CUSTOM_ID: image-test - :END: +* Image +:PROPERTIES: +:CUSTOM_ID: image +:END: an image: @@ -268,41 +277,43 @@ just to check. - [[../img/a.png]] item with img - [[../img/a.png]] item with img - - [[../img/a.png]] item with img - - [[../img/a.png]] item with img -***** TODO todo - :PROPERTIES: - :CUSTOM_ID: todo - :END: -****** IN-PROGRESS in-progress - :PROPERTIES: - :CUSTOM_ID: in-progress - :END: -******* IN-REVIEW in-review - :PROPERTIES: - :CUSTOM_ID: in-review - :END: -****** HOLD on hold state - :PROPERTIES: - :CUSTOM_ID: on-hold-state - :END: - - State "HOLD" from "IN-REVIEW" [2019-07-09 Tue 13:44] \\ - some reason -****** WAITING waiting status - :PROPERTIES: - :CUSTOM_ID: waiting-status - :END: - - State "WAITING" from [2019-07-09 Tue 13:44] \\ - waitin for someone -****** DONE done status - :PROPERTIES: - :CUSTOM_ID: done-status - :END: -****** CANCELED canceled status - CLOSED: [2019-07-09 Tue 13:45] - :PROPERTIES: - :CUSTOM_ID: canceled-status - :END: - - State "CANCELED" from [2019-07-09 Tue 13:45] \\ - cancel reason +* TODOs +:PROPERTIES: +:CUSTOM_ID: todos +:END: +****** TODO todo +:PROPERTIES: +:CUSTOM_ID: todo +:END: +******* IN-PROGRESS in-progress +:PROPERTIES: +:CUSTOM_ID: in-progress +:END: +******** IN-REVIEW in-review +:PROPERTIES: +:CUSTOM_ID: in-review +:END: +******* HOLD on hold state +:PROPERTIES: +:CUSTOM_ID: on-hold-state +:END: +- State "HOLD" from "IN-REVIEW" [2019-07-09 Tue 13:44] \\ + some reason +******* WAITING waiting status +:PROPERTIES: +:CUSTOM_ID: waiting-status +:END: +- State "WAITING" from [2019-07-09 Tue 13:44] \\ + waiting for someone +******* DONE done status +:PROPERTIES: +:CUSTOM_ID: done-status +:END: +******* CANCELED canceled status +CLOSED: [2019-07-09 Tue 13:45] +:PROPERTIES: +:CUSTOM_ID: canceled-status +:END: +- State "CANCELED" from [2019-07-09 Tue 13:45] \\ +cancel reason diff --git a/src/index.org b/src/index.org index 6b7ec5f..374f179 100644 --- a/src/index.org +++ b/src/index.org @@ -18,7 +18,9 @@ priority: 1. *Respect Privacy*; no tracker of any sort (no ads, no google analytics, no referrer for all external links, etc...) -2. *javascript free*; no js at all, yes even the theme changer +2. *almost javascript free*; no js at all except for a single exception, + pages containing Math formula are displayed using mathjax. That means + that event the CSS theme switcher does not use javascript. 3. *disability friendly*; should be easy to read on a text browser so people with disabilities could easily consume it 4. *nerdy*; should feel mostly like markdown text in a terminal and source code diff --git a/src/posts/new-blog.org b/src/posts/new-blog.org index 21efd13..d657fe5 100644 --- a/src/posts/new-blog.org +++ b/src/posts/new-blog.org @@ -27,7 +27,9 @@ priority: 1. *Respect Privacy*; no tracker of any sort (no ads, no google analytics, no referrer for all external links, etc...) -2. *javascript free*; no js at all, yes even the theme changer +2. *nearly no javascript*; no js at all except for a single exception, + pages containing Math formula are displayed using mathjax. That means + that event the CSS theme switcher does not use javascript. 3. *Accessible*; should be easy to read on a text browser so people with disabilities could easily consume it 4. *nerdy*; should feel mostly like markdown text in a terminal and source @@ -188,6 +190,24 @@ Finally in the CSS you can write things like: } #+end_src +I also added a system to support theme using fragment in the URL. + +#+begin_src css + input#light:target ~ .main, + input#light:checked ~ .main { + background-color: var(--light-color); + color: var(--dark-color); + } + input#dark:target ~ .main, + input#dark:checked ~ .main { + background-color: var(--dark-color); + color: var(--light-color); + } +#+end_src + +Unfortunately, the fragment system take full priority other the checkbox +mechanism. + Regarding selecting the user preferred theme, there are plenty of tutorial on the internet, you could also simply steal my CSS. @@ -204,3 +224,509 @@ Because a website is mostly, export all of file in org-mode format (easier to write and manipulate than raw HTML) to HTML. In fact, there are numerous details that make this task not this straightforward. +You want: + +1. from a tree of org-mode files, generate an equivalent file tree of HTML + files generated from the org-mode files. This is the main purpose of org-publish. +2. We also want to set specific headers, a CSS file, a favicon, link to RSS + file, mobile friendly directives. +3. Have common header/footer (preamble, postamble) if possible with a menu. +4. An archive page with a list of posts. +5. Generate an RSS file +6. Niceties: + - obfuscate your email to prevent spam + - link to your email with a link to the current page integrated in the body/subject + - replace your external link to open in a new tab securely (=noopener / noreferrer=). + +*** Tree of files +:PROPERTIES: +:CUSTOM_ID: tree-of-files +:END: +#+begin_src elisp + (setq domainname "https://her.esy.fun") + (setq base-dir (concat (projectile-project-root) "src")) + (setq publish-dir (concat (projectile-project-root) "_site")) + (setq assets-dir (concat base-dir "/")) + (setq publish-assets-dir (concat publish-dir "/")) + (setq rss-dir base-dir) + (setq rss-title "Subscribe to articles") + (setq publish-rss-dir publish-dir) + (setq publish-rss-img (concat domainname "/rss.png")) + (setq css-path "/css/minimalist.css") + (setq author-name "Yann Esposito") + (setq author-email "yann@esposito.host") + + (require 'org) + (require 'ox-publish) + (require 'ox-html) + (require 'org-element) + (require 'ox-rss) + + (setq org-link-file-path-type 'relative) + (setq org-publish-timestamp-directory + (concat (projectile-project-root) "_cache/")) + + (setq org-publish-project-alist + `(("orgfiles" + :base-directory ,base-dir + :exclude ".*drafts/.*" + :base-extension "org" + :publishing-directory ,publish-dir + :recursive t + :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 "Blog Posts" + :sitemap-style list + :sitemap-sort-files anti-chronologically + :sitemap-format-entry org-blog-sitemap-format-entry + :sitemap-function org-blog-sitemap-function) + + ("assets" + :base-directory ,assets-dir + :base-extension ".*" + :exclude ".*\.org$" + :publishing-directory ,publish-assets-dir + :publishing-function org-publish-attachment + :recursive t) + + ("rss" + :base-directory ,rss-dir + :base-extension "org" + :html-link-home ,domainname + :html-link-use-abs-url t + :rss-extension "xml" + :rss-image-url ,publish-rss-img + :publishing-directory ,publish-rss-dir + :publishing-function (org-rss-publish-to-rss) + :exclude ".*" + :include ("archive.org") + :section-numbers nil + :table-of-contents nil) + + ("blog" :components ("orgfiles" "assets" "rss")))) +#+end_src +*** HTML Headers +:PROPERTIES: +:CUSTOM_ID: html-headers +:END: + +#+begin_src elisp + (defvar org-blog-head + (concat + "" + "" + "" + "")) + +#+end_src +*** Preamble & Postamble +:PROPERTIES: +:CUSTOM_ID: preamble---postamble +:END: +#+begin_src elisp +(defun menu (lst) + "Blog menu" + (concat + "" + (mapconcat 'identity + (append + '("Home" + "Posts" + "About") + lst) + " | ") + "")) + + (defun get-from-info (info k) + (let ((i (car (plist-get info k)))) + (when (and i (stringp i)) + i))) + + (defun org-blog-preamble (info) + "Pre-amble for whole blog." + (concat + "
" + (menu '("↓ bottom ↓")) + "

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

" + (when-let ((date (plist-get info :date))) + (format "%s" + (format-time-string "%Y-%m-%d" + (org-timestamp-to-time + (car date))))) + (when-let ((subtitle (car (plist-get info :subtitle)))) + (format "

%s

" subtitle)) + "
")) + + (defun org-blog-postamble (info) + "Post-amble for whole blog." + (concat + "
" + ;; TODO install a comment system + ;; (let ((url (format "%s%s" domainname (replace-regexp-in-string base-dir "" (plist-get info :input-file))))) + ;; (format "comment" + ;; (url-hexify-string url))) + "
" + (when-let ((author (get-from-info info :author))) + (if-let ((email (plist-get info :email))) + (let* ((obfs-email (obfuscate-html email)) + (obfs-author (obfuscate-html author)) + (obfs-title (obfuscate-html (get-from-info info :title))) + (full-email (format "%s <%s>" obfs-author obfs-email))) + (format "
Author: %s
" + (obfuscate-html "mailto:") + full-email + (obfuscate-html "?subject=yblog: ") + obfs-title + full-email)) + (format "
Author: %s
" author))) + (when-let ((date (plist-get info :date))) + (format "
Created: %s
" + (format-time-string "%Y-%m-%d" + (org-timestamp-to-time + (car date))))) + (when-let ((keywords (plist-get info :keywords))) + (format "
Keywords: %s
" keywords)) + (format "
Generated: %s
" + (format-time-string "%Y-%m-%d %H:%M:%S")) + (format (concat "
Generated with " + "Emacs %s, " + "Spacemacs %s, " + "Org Mode %s" + "
") + emacs-version spacemacs-version org-version) + "
" + (menu '("↑ Top ↑")) + "
")) +#+end_src +*** RSS +:PROPERTIES: +:CUSTOM_ID: rss-db16 +:END: +#+begin_src elisp + ("rss" + :base-directory ,rss-dir + :base-extension "org" + :html-link-home ,domainname + :html-link-use-abs-url t + :rss-extension "xml" + :publishing-directory ,publish-rss-dir + :publishing-function (org-rss-publish-to-rss) + :exclude ".*" + :include ("archive.org") + :section-numbers nil + :table-of-contents nil) +#+end_src +*** Obfuscate email +:PROPERTIES: +:CUSTOM_ID: obfuscate-email +:END: +#+begin_src elisp + (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))) +#+end_src +*** Specific email subject +:PROPERTIES: +:CUSTOM_ID: specific-email-subject +:END: +#+begin_src elisp + (let* ((obfs-email (obfuscate-html email)) + (obfs-author (obfuscate-html author)) + (obfs-title (obfuscate-html (get-from-info info :title))) + (full-email (format "%s <%s>" obfs-author obfs-email))) + (format "
Author: %s
" + (obfuscate-html "mailto:") + full-email + (obfuscate-html "?subject=yblog: ") + obfs-title + full-email)) +#+end_src +*** Nice external links +:PROPERTIES: +:CUSTOM_ID: nice-external-links +:END: + +#+begin_src elisp + ;; 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=\"" domainname "[^\"]*") text))) + (string-match "" + "" + "" + "")) + + (defun menu (lst) + "Blog menu" + (concat + "" + (mapconcat 'identity + (append + '("Home" + "Posts" + "About") + lst) + " | ") + "")) + + (defun get-from-info (info k) + (let ((i (car (plist-get info k)))) + (when (and i (stringp i)) + i))) + + (defun org-blog-preamble (info) + "Pre-amble for whole blog." + (concat + "
" + (menu '("↓ bottom ↓")) + "

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

" + (when-let ((date (plist-get info :date))) + (format "%s" + (format-time-string "%Y-%m-%d" + (org-timestamp-to-time + (car date))))) + (when-let ((subtitle (car (plist-get info :subtitle)))) + (format "

%s

" subtitle)) + "
")) + + (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 org-blog-postamble (info) + "Post-amble for whole blog." + (concat + "
" + ;; TODO install a comment system + ;; (let ((url (format "%s%s" domainname (replace-regexp-in-string base-dir "" (plist-get info :input-file))))) + ;; (format "comment" + ;; (url-hexify-string url))) + "
" + (when-let ((author (get-from-info info :author))) + (if-let ((email (plist-get info :email))) + (let* ((obfs-email (obfuscate-html email)) + (obfs-author (obfuscate-html author)) + (obfs-title (obfuscate-html (get-from-info info :title))) + (full-email (format "%s <%s>" obfs-author obfs-email))) + (format "
Author: %s
" + (obfuscate-html "mailto:") + full-email + (obfuscate-html "?subject=yblog: ") + obfs-title + full-email)) + (format "
Author: %s
" author))) + (when-let ((date (plist-get info :date))) + (format "
Created: %s
" + (format-time-string "%Y-%m-%d" + (org-timestamp-to-time + (car date))))) + (when-let ((keywords (plist-get info :keywords))) + (format "
Keywords: %s
" keywords)) + (format "
Generated: %s
" + (format-time-string "%Y-%m-%d %H:%M:%S")) + (format (concat "
Generated with " + "Emacs %s, " + "Spacemacs %s, " + "Org Mode %s" + "
") + emacs-version spacemacs-version org-version) + "
" + (menu '("↑ Top ↑")) + "
")) + + (defun org-blog-sitemap-format-entry (entry _style project) + "Return string for each ENTRY in PROJECT." + (when (s-starts-with-p "posts/" entry) + (format (concat "@@html:" + "@@ %s: @@html:@@" + " [[file:%s][%s]]" + " @@html:@@") + (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)) + entry + (org-publish-find-title entry project)))) + + (defun org-blog-sitemap-function (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" + "\n#+begin_archive\n" + (mapconcat (lambda (li) + (format "@@html:
  • @@ %s @@html:
  • @@" (car li))) + (seq-filter #'car (cdr list)) + "\n") + "\n#+end_archive\n")) + + (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))) + (with-current-buffer (find-file-noselect file-path) + (goto-char (point-min)) + (search-forward "") + (insert (mapconcat 'identity + '("" + "" + "" + "" + "
    " + "
    " + "Change theme: " + "" + "()" + " / " + "" + "()" + "
    " + "
    " + "
    ") + "\n")) + (goto-char (point-max)) + (search-backward "") + (insert "\n
    \n") + (save-buffer) + (kill-buffer)) + file-path)) + + (setq org-publish-project-alist + `(("orgfiles" + :base-directory ,base-dir + :exclude ".*drafts/.*" + :base-extension "org" + :publishing-directory ,publish-dir + + :recursive t + :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 "Blog Posts" + :sitemap-style list + :sitemap-sort-files anti-chronologically + :sitemap-format-entry org-blog-sitemap-format-entry + :sitemap-function org-blog-sitemap-function) + + ("assets" + :base-directory ,assets-dir + :base-extension ".*" + :exclude ".*\.org$" + :publishing-directory ,publish-assets-dir + :publishing-function org-publish-attachment + :recursive t) + + ("rss" + :base-directory ,rss-dir + :base-extension "org" + :html-link-home ,domainname + :html-link-use-abs-url t + :rss-extension "xml" + :rss-image-url ,publish-rss-img + :publishing-directory ,publish-rss-dir + :publishing-function (org-rss-publish-to-rss) + :exclude ".*" + :include ("archive.org") + :section-numbers nil + :table-of-contents nil) + + ("blog" :components ("orgfiles" "assets" "rss")))) + + ;; 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=\"" domainname "[^\"]*") text))) + (string-match "