This commit is contained in:
fido-node 2024-10-19 16:09:53 +00:00
parent 6d06ef4787
commit b79bf211ac
18 changed files with 1144 additions and 1153 deletions

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Personal page with a blog about my adventures in a world of tech things"/><meta property="og:description" content="Personal page with a blog about my adventures in a world of tech things"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/index.org.png"/><meta property="og:title" content="Alex Mikhailov"/><meta name="twitter:description" content="Personal page with a blog about my adventures in a world of tech things"/><meta name="twitter:title" content="Alex Mikhailov"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/index.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Alex Mikhailov</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Personal page with a blog about my adventures in a world of tech things"/><meta property="og:description" content="Personal page with a blog about my adventures in a world of tech things"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/index.org.png"/><meta property="og:title" content="Alex Mikhailov"/><meta name="twitter:description" content="Personal page with a blog about my adventures in a world of tech things"/><meta name="twitter:title" content="Alex Mikhailov"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/index.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Alex Mikhailov</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div class="figure"> <div id="orgcf577cf" class="figure">
<p><img src="./resources/images/index/avatar.jpg" alt="avatar.jpg" /> <p><img src="./resources/images/index/avatar.jpg" alt="avatar.jpg" />
</p> </p>
</div> </div>
<div id="outline-container-org585312b" class="outline-2"> <div id="outline-container-org4b7dad9" class="outline-2">
<h2 id="org585312b">&nbsp;</h2> <h2 id="org4b7dad9">&nbsp;</h2>
<div class="outline-text-2" id="text-org585312b"> <div class="outline-text-2" id="text-org4b7dad9">
<p> <p>
Full stack engineer Full stack engineer
FP-curious | λ-affected FP-curious | λ-affected
@ -13,9 +13,9 @@ Wanna be rustacean 🦀 and/or secops guy 🔒
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-orgc81584d" class="outline-2"> <div id="outline-container-org1441250" class="outline-2">
<h2 id="orgc81584d">Experience</h2> <h2 id="org1441250">Experience</h2>
<div class="outline-text-2" id="text-orgc81584d"> <div class="outline-text-2" id="text-org1441250">
<ul class="org-ul"> <ul class="org-ul">
<li>Current position <a href="https://www.samsungfood.com/">@SamsungFood</a>. <li>Current position <a href="https://www.samsungfood.com/">@SamsungFood</a>.
Internal tools engineer for data platform ➡ Internal tools engineer for developers.</li> Internal tools engineer for data platform ➡ Internal tools engineer for developers.</li>
@ -24,9 +24,9 @@ Fullstack engineer.</li>
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-orgea940b5" class="outline-2"> <div id="outline-container-org57e06b9" class="outline-2">
<h2 id="orgea940b5">Technologies</h2> <h2 id="org57e06b9">Technologies</h2>
<div class="outline-text-2" id="text-orgea940b5"> <div class="outline-text-2" id="text-org57e06b9">
<p> <p>
Work with: Work with:
</p> </p>
@ -43,9 +43,9 @@ Work with:
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-orgb0f26c7" class="outline-2"> <div id="outline-container-org8a463cc" class="outline-2">
<h2 id="orgb0f26c7">Contacts</h2> <h2 id="org8a463cc">Contacts</h2>
<div class="outline-text-2" id="text-orgb0f26c7"> <div class="outline-text-2" id="text-org8a463cc">
<p> <p>
Contact me via: Contact me via:
</p> </p>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Index page for my blog"/><meta property="og:description" content="Index page for my blog"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts.org.png"/><meta property="og:title" content="Alex Mikhailov - Blog"/><meta name="twitter:description" content="Index page for my blog"/><meta name="twitter:title" content="Alex Mikhailov - Blog"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Alex Mikhailov - Blog</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Index page for my blog"/><meta property="og:description" content="Index page for my blog"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts.org.png"/><meta property="og:title" content="Alex Mikhailov - Blog"/><meta name="twitter:description" content="Index page for my blog"/><meta name="twitter:title" content="Alex Mikhailov - Blog"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Alex Mikhailov - Blog</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-orgd2fb22f" class="outline-2"> <div id="outline-container-org888d131" class="outline-2">
<h2 id="orgd2fb22f">Posts</h2> <h2 id="org888d131">Posts</h2>
<div class="outline-text-2" id="text-orgd2fb22f"> <div class="outline-text-2" id="text-org888d131">
</div> </div>
<div id="outline-container-orgac0fed9" class="outline-3"> <div id="outline-container-orgefd6e03" class="outline-3">
<h3 id="orgac0fed9"><a href="./posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h3> <h3 id="orgefd6e03"><a href="./posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h3>
<div class="outline-text-3" id="text-orgac0fed9"> <div class="outline-text-3" id="text-orgefd6e03">
<p> <p>
Let's add tags to blog posts Let's add tags to blog posts
</p> </p>
@ -20,9 +20,9 @@ drafted on 2024-07-05
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org9499b6e" class="outline-3"> <div id="outline-container-org3227fe7" class="outline-3">
<h3 id="org9499b6e"><a href="./posts/posts_preview.html">Posts preview</a></h3> <h3 id="org3227fe7"><a href="./posts/posts_preview.html">Posts preview</a></h3>
<div class="outline-text-3" id="text-org9499b6e"> <div class="outline-text-3" id="text-org3227fe7">
<p> <p>
Add post preview for OpenGraph cards Add post preview for OpenGraph cards
</p> </p>
@ -37,9 +37,9 @@ drafted on 2024-06-28
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-orgd34c669" class="outline-3"> <div id="outline-container-orgff565b2" class="outline-3">
<h3 id="orgd34c669"><a href="./posts/improve_code_blocks.html">Improve code blocks</a></h3> <h3 id="orgff565b2"><a href="./posts/improve_code_blocks.html">Improve code blocks</a></h3>
<div class="outline-text-3" id="text-orgd34c669"> <div class="outline-text-3" id="text-orgff565b2">
<p> <p>
Use highlight.js for code syntax highlighting Use highlight.js for code syntax highlighting
</p> </p>
@ -54,9 +54,9 @@ drafted on 2024-06-25
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org730cf0d" class="outline-3"> <div id="outline-container-orgf927a81" class="outline-3">
<h3 id="org730cf0d"><a href="./posts/add_rss_to_blog.html">Org blog with RSS</a></h3> <h3 id="orgf927a81"><a href="./posts/add_rss_to_blog.html">Org blog with RSS</a></h3>
<div class="outline-text-3" id="text-org730cf0d"> <div class="outline-text-3" id="text-orgf927a81">
<p> <p>
Let's add RSS feed to blog Let's add RSS feed to blog
</p> </p>
@ -71,9 +71,9 @@ drafted on 2024-06-23
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org010452c" class="outline-3"> <div id="outline-container-org806a8c4" class="outline-3">
<h3 id="org010452c"><a href="./posts/about_blog.html">Org to HTML and back</a></h3> <h3 id="org806a8c4"><a href="./posts/about_blog.html">Org to HTML and back</a></h3>
<div class="outline-text-3" id="text-org010452c"> <div class="outline-text-3" id="text-org806a8c4">
<p> <p>
Blog post about publishing my blog with Org Mode Blog post about publishing my blog with Org Mode
</p> </p>
@ -88,9 +88,9 @@ drafted on 2024-06-22
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org5ed71f2" class="outline-3"> <div id="outline-container-org489279f" class="outline-3">
<h3 id="org5ed71f2"><a href="./posts/keeb.html">My keyboard journey</a></h3> <h3 id="org489279f"><a href="./posts/keeb.html">My keyboard journey</a></h3>
<div class="outline-text-3" id="text-org5ed71f2"> <div class="outline-text-3" id="text-org489279f">
<p> <p>
Blog post about my keyboards Blog post about my keyboards
</p> </p>
@ -106,33 +106,33 @@ drafted on 2024-06-05
</div> </div>
</div> </div>
</div> </div>
<div id="outline-container-orgdfa2937" class="outline-2"> <div id="outline-container-org385852d" class="outline-2">
<h2 id="orgdfa2937">Tags</h2> <h2 id="org385852d">Tags</h2>
<div class="outline-text-2" id="text-orgdfa2937"> <div class="outline-text-2" id="text-org385852d">
</div> </div>
<div id="outline-container-org21ce92d" class="outline-3"> <div id="outline-container-org134cb71" class="outline-3">
<h3 id="org21ce92d"><a href="./tags/@org-mode.html">@org-mode</a> (5)</h3> <h3 id="org134cb71"><a href="./tags/@org-mode.html">@org-mode</a> (5)</h3>
</div> </div>
<div id="outline-container-org25bbcc9" class="outline-3"> <div id="outline-container-orgc494966" class="outline-3">
<h3 id="org25bbcc9"><a href="./tags/@elisp.html">@elisp</a> (4)</h3> <h3 id="orgc494966"><a href="./tags/@elisp.html">@elisp</a> (4)</h3>
</div> </div>
<div id="outline-container-org034f5f7" class="outline-3"> <div id="outline-container-org3946909" class="outline-3">
<h3 id="org034f5f7"><a href="./tags/@rss.html">@rss</a> (1)</h3> <h3 id="org3946909"><a href="./tags/@rss.html">@rss</a> (1)</h3>
</div> </div>
<div id="outline-container-org3417858" class="outline-3"> <div id="outline-container-org66b19f0" class="outline-3">
<h3 id="org3417858"><a href="./tags/@tags.html">@tags</a> (1)</h3> <h3 id="org66b19f0"><a href="./tags/@tags.html">@tags</a> (1)</h3>
</div> </div>
<div id="outline-container-org8841fde" class="outline-3"> <div id="outline-container-orgf9b9d88" class="outline-3">
<h3 id="org8841fde"><a href="./tags/@highlightjs.html">@highlightjs</a> (1)</h3> <h3 id="orgf9b9d88"><a href="./tags/@highlightjs.html">@highlightjs</a> (1)</h3>
</div> </div>
<div id="outline-container-orgb04fb9f" class="outline-3"> <div id="outline-container-org37f2f66" class="outline-3">
<h3 id="orgb04fb9f"><a href="./tags/@keeb.html">@keeb</a> (1)</h3> <h3 id="org37f2f66"><a href="./tags/@keeb.html">@keeb</a> (1)</h3>
</div> </div>
<div id="outline-container-org17c6e8b" class="outline-3"> <div id="outline-container-org250b554" class="outline-3">
<h3 id="org17c6e8b"><a href="./tags/@diy.html">@diy</a> (1)</h3> <h3 id="org250b554"><a href="./tags/@diy.html">@diy</a> (1)</h3>
</div> </div>
<div id="outline-container-orgc7f623e" class="outline-3"> <div id="outline-container-org8221c64" class="outline-3">
<h3 id="orgc7f623e"><a href="./tags/@imagemagick.html">@imagemagick</a> (1)</h3> <h3 id="org8221c64"><a href="./tags/@imagemagick.html">@imagemagick</a> (1)</h3>
</div> </div>
</div> </div>
</main><footer class="footer"><div class="container"><hr/><small><p>Alex Mikhailov</p><p>Built with: <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> <a href="https://orgmode.org/">Org Mode</a> <a href="https://picocss.com/">picocss</a></p></small></div></footer></body></html> </main><footer class="footer"><div class="container"><hr/><small><p>Alex Mikhailov</p><p>Built with: <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> <a href="https://orgmode.org/">Org Mode</a> <a href="https://picocss.com/">picocss</a></p></small></div></footer></body></html>

View File

@ -1,45 +1,45 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Blog post about publishing my blog with Org Mode"/><meta property="og:description" content="Blog post about publishing my blog with Org Mode"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/about_blog.org.png"/><meta property="og:title" content="Org to HTML and back"/><meta name="twitter:description" content="Blog post about publishing my blog with Org Mode"/><meta name="twitter:title" content="Org to HTML and back"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/about_blog.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Org to HTML and back</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Org to HTML and back</h1><p>Blog post about publishing my blog with Org Mode</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li></ul></nav></hgroup><div id="table-of-contents"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Blog post about publishing my blog with Org Mode"/><meta property="og:description" content="Blog post about publishing my blog with Org Mode"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/about_blog.org.png"/><meta property="og:title" content="Org to HTML and back"/><meta name="twitter:description" content="Blog post about publishing my blog with Org Mode"/><meta name="twitter:title" content="Org to HTML and back"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/about_blog.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Org to HTML and back</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Org to HTML and back</h1><p>Blog post about publishing my blog with Org Mode</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li></ul></nav></hgroup><div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2> <h2>Table of Contents</h2>
<div id="text-table-of-contents"> <div id="text-table-of-contents" role="doc-toc">
<ul> <ul>
<li><a href="#orgd34f4f9">Disclaimer</a></li> <li><a href="#org0e3ee32">Disclaimer</a></li>
<li><a href="#org8754b76">What is Org?</a></li> <li><a href="#org22ac3b4">What is Org?</a></li>
<li><a href="#orgce51245">Why Org Mode?</a></li> <li><a href="#org2f6ee1a">Why Org Mode?</a></li>
<li><a href="#orgdbfd7a2">Render Org to blog or whatever</a> <li><a href="#org5bbcb68">Render Org to blog or whatever</a>
<ul> <ul>
<li><a href="#orgb4e4058">Render HTML</a></li> <li><a href="#orgc4790ce">Render HTML</a></li>
<li><a href="#org58d0894">Static files</a></li> <li><a href="#org4f9b6c6">Static files</a></li>
<li><a href="#org0da0fc5">Whole build script</a></li> <li><a href="#org9487c4f">Whole build script</a></li>
</ul> </ul>
</li> </li>
<li><a href="#orgf0a7513">Publish through GitHub Action</a> <li><a href="#orgfcde14b">Publish through GitHub Action</a>
<ul> <ul>
<li><a href="#org84d42fe">Install Emacs</a></li> <li><a href="#org69c76c7">Install Emacs</a></li>
<li><a href="#org5ca4886">Just bring everything</a></li> <li><a href="#org3ae34f7">Just bring everything</a></li>
<li><a href="#org06431a5">BTW I use GNU Emacs</a></li> <li><a href="#orgc297b9d">BTW I use GNU Emacs</a></li>
</ul> </ul>
</li> </li>
<li><a href="#org8e91c91">What is next</a> <li><a href="#org1251e16">What is next</a>
<ul> <ul>
<li><a href="#org4df21fb">RSS Feed</a></li> <li><a href="#org76a230d">RSS Feed</a></li>
<li><a href="#orgc469690">Open Graph image preview</a></li> <li><a href="#orgcb0b75a">Open Graph image preview</a></li>
<li><a href="#orgb0a6b6c">Code highlighting</a></li> <li><a href="#org0512465">Code highlighting</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-orgd34f4f9" class="outline-2"> <div id="outline-container-org0e3ee32" class="outline-2">
<h2 id="orgd34f4f9">Disclaimer</h2> <h2 id="org0e3ee32">Disclaimer</h2>
<div class="outline-text-2" id="text-orgd34f4f9"> <div class="outline-text-2" id="text-org0e3ee32">
<p> <p>
I'm neither proficient in Org Mode (further on "Org"), nor a good front-end engineer. I think that a simple solution is better than no solution. If you see a mistake, you can contact me via <a href="mailto:iam@fidonode.me">iam@fidonode.me</a>. I'm neither proficient in Org Mode (further on "Org"), nor a good front-end engineer. I think that a simple solution is better than no solution. If you see a mistake, you can contact me via <a href="mailto:iam@fidonode.me">iam@fidonode.me</a>.
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org8754b76" class="outline-2"> <div id="outline-container-org22ac3b4" class="outline-2">
<h2 id="org8754b76">What is Org?</h2> <h2 id="org22ac3b4">What is Org?</h2>
<div class="outline-text-2" id="text-org8754b76"> <div class="outline-text-2" id="text-org22ac3b4">
<blockquote> <blockquote>
<p> <p>
Your life in plain text Your life in plain text
@ -55,9 +55,9 @@ Everything you can do in Org is to write a text. With a special markup, of cours
</div> </div>
</div> </div>
<div id="outline-container-orgce51245" class="outline-2"> <div id="outline-container-org2f6ee1a" class="outline-2">
<h2 id="orgce51245">Why Org Mode?</h2> <h2 id="org2f6ee1a">Why Org Mode?</h2>
<div class="outline-text-2" id="text-orgce51245"> <div class="outline-text-2" id="text-org2f6ee1a">
<ol class="org-ol"> <ol class="org-ol">
<li>Plain text. <li>Plain text.
Plain text as a data source offers significant versatility. You can read and understand what happens in org files without needing Emacs.</li> Plain text as a data source offers significant versatility. You can read and understand what happens in org files without needing Emacs.</li>
@ -69,16 +69,16 @@ I do not have a habit of collecting and keeping information. I believe that disc
</div> </div>
</div> </div>
<div id="outline-container-orgdbfd7a2" class="outline-2"> <div id="outline-container-org5bbcb68" class="outline-2">
<h2 id="orgdbfd7a2">Render Org to blog or whatever</h2> <h2 id="org5bbcb68">Render Org to blog or whatever</h2>
<div class="outline-text-2" id="text-orgdbfd7a2"> <div class="outline-text-2" id="text-org5bbcb68">
<p> <p>
Org already has a way to render files into HTML, allowing you to create simple HTML files with minimal styling. I'm not interesting in styling from org, so I decide to use <a href="https://picocss.com">picocss</a> framework. Org already has a way to render files into HTML, allowing you to create simple HTML files with minimal styling. I'm not interesting in styling from org, so I decide to use <a href="https://picocss.com">picocss</a> framework.
</p> </p>
</div> </div>
<div id="outline-container-orgb4e4058" class="outline-3"> <div id="outline-container-orgc4790ce" class="outline-3">
<h3 id="orgb4e4058">Render HTML</h3> <h3 id="orgc4790ce">Render HTML</h3>
<div class="outline-text-3" id="text-orgb4e4058"> <div class="outline-text-3" id="text-orgc4790ce">
<p> <p>
I want to change some templates here and there. I've found <code>esxml</code> package. It is a decent DSL for writing XML/HTML. I want to change some templates here and there. I've found <code>esxml</code> package. It is a decent DSL for writing XML/HTML.
Here is how page header and footer look in this DSL. Here is how page header and footer look in this DSL.
@ -89,7 +89,7 @@ Here is how page header and footer look in this DSL.
(ul (ul
(li (li
(strong (strong
,(org-export-data (plist-get info :title) info)))) ,(org-export-data (plist-get info :title) info))))
(ul (ul
(li (a (@ (href &quot;/index.html&quot;)) &quot;About&quot;)) (li (a (@ (href &quot;/index.html&quot;)) &quot;About&quot;))
(li (a (@ (href &quot;/blog.html&quot;)) &quot;Blog&quot;)) (li (a (@ (href &quot;/blog.html&quot;)) &quot;Blog&quot;))
@ -123,7 +123,7 @@ Whole template wiring looks like that. Not much, but it works and easy to mainta
(meta (@ (charset &quot;utf-8&quot;))) (meta (@ (charset &quot;utf-8&quot;)))
(meta (@ (author &quot;Alex Mikhailov&quot;))) (meta (@ (author &quot;Alex Mikhailov&quot;)))
(meta (@ (name &quot;viewport&quot;) (meta (@ (name &quot;viewport&quot;)
(content &quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;))) (content &quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;)))
(meta (@ (name &quot;color-scheme&quot;) (content &quot;light dark&quot;))) (meta (@ (name &quot;color-scheme&quot;) (content &quot;light dark&quot;)))
(meta (@ (http-equiv &quot;content-language&quot;) (content &quot;en-us&quot;))) (meta (@ (http-equiv &quot;content-language&quot;) (content &quot;en-us&quot;)))
(meta (@ (name &quot;description&quot;) (content &quot;Personal page with a blog about my technical adventures&quot;))) (meta (@ (name &quot;description&quot;) (content &quot;Personal page with a blog about my technical adventures&quot;)))
@ -135,10 +135,10 @@ Whole template wiring looks like that. Not much, but it works and easy to mainta
(body (body
(main (@ (class &quot;container&quot;)) (main (@ (class &quot;container&quot;))
,(my/header info) ,(my/header info)
(*RAW-STRING* ,contents) (*RAW-STRING* ,contents)
,(my/footer info) ,(my/footer info)
) )
)) ))
)) ))
) )
@ -152,7 +152,7 @@ Ok, now we need some additional steps to wire these templating function.
(org-export-define-derived-backend &apos;my-html &apos;html (org-export-define-derived-backend &apos;my-html &apos;html
:translate-alist &apos;((template . my/template) :translate-alist &apos;((template . my/template)
)) ))
;; Define publish function which uses our freshly derived backend ;; Define publish function which uses our freshly derived backend
(defun my/publish-to-html (plist filename pub-dir) (defun my/publish-to-html (plist filename pub-dir)
@ -167,37 +167,37 @@ So everything is almost done. Time to use our custom publishing function in proj
<pre><code class="language-lisp">(setq org-publish-project-alist <pre><code class="language-lisp">(setq org-publish-project-alist
(list (list
(list &quot;blog&quot; (list &quot;blog&quot;
:recursive t :recursive t
:base-directory my/blog-src-path :base-directory my/blog-src-path
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:publishing-function &apos;my/publish-to-html :publishing-function &apos;my/publish-to-html
:html-html5-fancy t :html-html5-fancy t
:htmlized-source t :htmlized-source t
:with-author nil :with-author nil
:with-creator t :with-creator t
:with-toc t :with-toc t
:section-numbers nil :section-numbers nil
:time-stamp-file nil :time-stamp-file nil
) )
)) ))
</code></pre> </code></pre>
</div> </div>
</div> </div>
<div id="outline-container-org58d0894" class="outline-3"> <div id="outline-container-org4f9b6c6" class="outline-3">
<h3 id="org58d0894">Static files</h3> <h3 id="org4f9b6c6">Static files</h3>
<div class="outline-text-3" id="text-org58d0894"> <div class="outline-text-3" id="text-org4f9b6c6">
<p> <p>
Yep, you may want to publish some photos with your blog or any other static files. Yep, you may want to publish some photos with your blog or any other static files.
</p> </p>
<pre><code class="language-nil">(setq org-publish-project-alist <pre><code class="language-nil">(setq org-publish-project-alist
(list (list
(list &quot;static&quot; (list &quot;static&quot;
:base-directory my/blog-src-path :base-directory my/blog-src-path
:base-extension &quot;css\\|js\\|png\\|jpg\\|jpeg\\|gif\\|pdf\\|ico\\|txt&quot; :base-extension &quot;css\\|js\\|png\\|jpg\\|jpeg\\|gif\\|pdf\\|ico\\|txt&quot;
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:recursive t :recursive t
:publishing-function &apos;org-publish-attachment :publishing-function &apos;org-publish-attachment
) )
)) ))
</code></pre> </code></pre>
<p> <p>
@ -205,9 +205,9 @@ Looks self explanatory.
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org0da0fc5" class="outline-3"> <div id="outline-container-org9487c4f" class="outline-3">
<h3 id="org0da0fc5">Whole build script</h3> <h3 id="org9487c4f">Whole build script</h3>
<div class="outline-text-3" id="text-org0da0fc5"> <div class="outline-text-3" id="text-org9487c4f">
<p> <p>
Here is the whole elisp script which I use to publish my blog. It have some additional quirks to work with <code class="src src-sh">doomscript ./build-site.el</code>. Here is the whole elisp script which I use to publish my blog. It have some additional quirks to work with <code class="src src-sh">doomscript ./build-site.el</code>.
</p> </p>
@ -220,7 +220,7 @@ Here is the whole elisp script which I use to publish my blog. It have some addi
(normal-top-level-add-subdirs-to-load-path)) (normal-top-level-add-subdirs-to-load-path))
(add-to-list &apos;custom-theme-load-path (add-to-list &apos;custom-theme-load-path
(concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/doom-themes&quot;)) (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/doom-themes&quot;))
(add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/base16-theme&quot;)) (add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/base16-theme&quot;))
(add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/moe-theme&quot;)) (add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/moe-theme&quot;))
@ -263,7 +263,7 @@ Here is the whole elisp script which I use to publish my blog. It have some addi
(ul (ul
(li (li
(strong (strong
,(org-export-data (plist-get info :title) info)))) ,(org-export-data (plist-get info :title) info))))
(ul (ul
(li (a (@ (href &quot;/index.html&quot;)) &quot;About&quot;)) (li (a (@ (href &quot;/index.html&quot;)) &quot;About&quot;))
(li (a (@ (href &quot;/blog.html&quot;)) &quot;Blog&quot;)) (li (a (@ (href &quot;/blog.html&quot;)) &quot;Blog&quot;))
@ -281,7 +281,7 @@ Here is the whole elisp script which I use to publish my blog. It have some addi
(meta (@ (charset &quot;utf-8&quot;))) (meta (@ (charset &quot;utf-8&quot;)))
(meta (@ (author &quot;Alex Mikhailov&quot;))) (meta (@ (author &quot;Alex Mikhailov&quot;)))
(meta (@ (name &quot;viewport&quot;) (meta (@ (name &quot;viewport&quot;)
(content &quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;))) (content &quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;)))
(meta (@ (name &quot;color-scheme&quot;) (content &quot;light dark&quot;))) (meta (@ (name &quot;color-scheme&quot;) (content &quot;light dark&quot;)))
(meta (@ (http-equiv &quot;content-language&quot;) (content &quot;en-us&quot;))) (meta (@ (http-equiv &quot;content-language&quot;) (content &quot;en-us&quot;)))
(meta (@ (name &quot;description&quot;) (content &quot;Personal page with a blog about my technical adventures&quot;))) (meta (@ (name &quot;description&quot;) (content &quot;Personal page with a blog about my technical adventures&quot;)))
@ -293,10 +293,10 @@ Here is the whole elisp script which I use to publish my blog. It have some addi
(body (body
(main (@ (class &quot;container&quot;)) (main (@ (class &quot;container&quot;))
,(my/header info) ,(my/header info)
(*RAW-STRING* ,contents) (*RAW-STRING* ,contents)
,(my/footer info) ,(my/footer info)
) )
)) ))
)) ))
) )
@ -304,7 +304,7 @@ Here is the whole elisp script which I use to publish my blog. It have some addi
(org-export-define-derived-backend &apos;my-html &apos;html (org-export-define-derived-backend &apos;my-html &apos;html
:translate-alist &apos;((template . my/template) :translate-alist &apos;((template . my/template)
)) ))
(defun my/publish-to-html (plist filename pub-dir) (defun my/publish-to-html (plist filename pub-dir)
&quot;Publish an Org file to HTML using the custom backend.&quot; &quot;Publish an Org file to HTML using the custom backend.&quot;
@ -333,25 +333,25 @@ Here is the whole elisp script which I use to publish my blog. It have some addi
(setq org-publish-project-alist (setq org-publish-project-alist
(list (list
(list &quot;static&quot; (list &quot;static&quot;
:base-directory my/blog-src-path :base-directory my/blog-src-path
:base-extension &quot;css\\|js\\|png\\|jpg\\|jpeg\\|gif\\|pdf\\|ico\\|txt&quot; :base-extension &quot;css\\|js\\|png\\|jpg\\|jpeg\\|gif\\|pdf\\|ico\\|txt&quot;
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:recursive t :recursive t
:publishing-function &apos;org-publish-attachment :publishing-function &apos;org-publish-attachment
) )
(list &quot;blog&quot; (list &quot;blog&quot;
:recursive t :recursive t
:base-directory my/blog-src-path :base-directory my/blog-src-path
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:publishing-function &apos;my/publish-to-html :publishing-function &apos;my/publish-to-html
:html-html5-fancy t :html-html5-fancy t
:htmlized-source t :htmlized-source t
:with-author nil :with-author nil
:with-creator t :with-creator t
:with-toc t :with-toc t
:section-numbers nil :section-numbers nil
:time-stamp-file nil :time-stamp-file nil
) )
)) ))
@ -365,9 +365,9 @@ Here is the whole elisp script which I use to publish my blog. It have some addi
</div> </div>
</div> </div>
<div id="outline-container-orgf0a7513" class="outline-2"> <div id="outline-container-orgfcde14b" class="outline-2">
<h2 id="orgf0a7513">Publish through GitHub Action</h2> <h2 id="orgfcde14b">Publish through GitHub Action</h2>
<div class="outline-text-2" id="text-orgf0a7513"> <div class="outline-text-2" id="text-orgfcde14b">
<p> <p>
With all previous preparations, this step sounds simple like: <code class="src src-sh">emacs -Q --script ./build-site.el</code> With all previous preparations, this step sounds simple like: <code class="src src-sh">emacs -Q --script ./build-site.el</code>
I've chosen a pretty standard way to publish static sites through GitHub Pages. Since I keep my Org files in a private repo, I need some additional steps to address it. I use the <code>peaceiris/actions-gh-pages@v3</code> action to publish from my Org repo to the Pages repo. I've chosen a pretty standard way to publish static sites through GitHub Pages. Since I keep my Org files in a private repo, I need some additional steps to address it. I use the <code>peaceiris/actions-gh-pages@v3</code> action to publish from my Org repo to the Pages repo.
@ -375,9 +375,9 @@ However, since I use <code>Doom Emacs</code> as my configuration framework, we n
</p> </p>
</div> </div>
<div id="outline-container-org84d42fe" class="outline-3"> <div id="outline-container-org69c76c7" class="outline-3">
<h3 id="org84d42fe">Install Emacs</h3> <h3 id="org69c76c7">Install Emacs</h3>
<div class="outline-text-3" id="text-org84d42fe"> <div class="outline-text-3" id="text-org69c76c7">
<p> <p>
If you want to run <code>Emacs Lisp</code>, you need the whole Emacs, at least without GUI. In a GitHub Action, you can simply run: If you want to run <code>Emacs Lisp</code>, you need the whole Emacs, at least without GUI. In a GitHub Action, you can simply run:
</p> </p>
@ -388,9 +388,9 @@ This way has a downside - you will install Emacs on each action run since the sy
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org5ca4886" class="outline-3"> <div id="outline-container-org3ae34f7" class="outline-3">
<h3 id="org5ca4886">Just bring everything</h3> <h3 id="org3ae34f7">Just bring everything</h3>
<div class="outline-text-3" id="text-org5ca4886"> <div class="outline-text-3" id="text-org3ae34f7">
<p> <p>
I need to take extra steps since I use Doom Emacs and have my configs in Org. You may also need to install dependencies for your configuration. I need to take extra steps since I use Doom Emacs and have my configs in Org. You may also need to install dependencies for your configuration.
</p> </p>
@ -426,9 +426,9 @@ Of course, I use a caching step to make the whole process faster:
</div> </div>
</div> </div>
<div id="outline-container-org06431a5" class="outline-3"> <div id="outline-container-orgc297b9d" class="outline-3">
<h3 id="org06431a5">BTW I use GNU Emacs</h3> <h3 id="orgc297b9d">BTW I use GNU Emacs</h3>
<div class="outline-text-3" id="text-org06431a5"> <div class="outline-text-3" id="text-orgc297b9d">
<p> <p>
Here's the whole publishing workflow. Here's the whole publishing workflow.
</p> </p>
@ -450,78 +450,78 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v1 uses: actions/checkout@v1
#Install emacs without GUI components #Install emacs without GUI components
- name: Install Emacs - name: Install Emacs
run: sudo apt install emacs-nox --yes run: sudo apt install emacs-nox --yes
#Clone doomemacs. Yep, always the most fresh master. Let it fire. #Clone doomemacs. Yep, always the most fresh master. Let it fire.
- name: Install doom - name: Install doom
run: git clone --depth 1 https://github.com/doomemacs/doomemacs ~/.config/emacs run: git clone --depth 1 https://github.com/doomemacs/doomemacs ~/.config/emacs
# Use cached files to shave some time # Use cached files to shave some time
- name: Restore cached doom-emacs - name: Restore cached doom-emacs
id: cache-doom-restore id: cache-doom-restore
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
with: with:
path: ~/.config/emacs path: ~/.config/emacs
key: ${{ runner.os }}-doom key: ${{ runner.os }}-doom
- name: Create folder - name: Create folder
run: mkdir -p ~/.config/doom/ run: mkdir -p ~/.config/doom/
# I use literate config, so we need some extra steps to botstrap my config # I use literate config, so we need some extra steps to botstrap my config
- name: Put template for literate config - name: Put template for literate config
run: echo &apos;(doom! :config literate)&apos; &amp;gt; ~/.config/doom/init.el run: echo &apos;(doom! :config literate)&apos; &amp;gt; ~/.config/doom/init.el
# Yep. I also keep my emacs config in org in my org repo # Yep. I also keep my emacs config in org in my org repo
- name: Propagate org conf - name: Propagate org conf
run: echo &apos;(setq +literate-config-file &quot;&apos;$(pwd)&apos;/config/config.org&quot;)&apos; &amp;gt; ~/.config/doom/cli.el run: echo &apos;(setq +literate-config-file &quot;&apos;$(pwd)&apos;/config/config.org&quot;)&apos; &amp;gt; ~/.config/doom/cli.el
# Build doomemacs deps. Should be relativelly fast, cause almost everything cached. # Build doomemacs deps. Should be relativelly fast, cause almost everything cached.
- name: Sync doom - name: Sync doom
run: ~/.config/emacs/bin/doom sync -B run: ~/.config/emacs/bin/doom sync -B
#Put files into cache #Put files into cache
- name: Cache doom-emacs - name: Cache doom-emacs
uses: actions/cache@v4 uses: actions/cache@v4
id: cache-doom-save id: cache-doom-save
with: with:
path: ~/.config/emacs path: ~/.config/emacs
key: ${{ runner.os }}-doom key: ${{ runner.os }}-doom
- name: Build the site - name: Build the site
run: ~/.config/emacs/bin/doomscript ./build-site.el run: ~/.config/emacs/bin/doomscript ./build-site.el
# Deploy from this repo to that ~external_repository~ # Deploy from this repo to that ~external_repository~
- name: Deploy - name: Deploy
uses: peaceiris/actions-gh-pages@v3 uses: peaceiris/actions-gh-pages@v3
with: with:
deploy_key: ${{ secrets.PRIVATE_KEY }} deploy_key: ${{ secrets.PRIVATE_KEY }}
external_repository: fido-node/fido-node.github.io external_repository: fido-node/fido-node.github.io
publish_branch: gh-pages publish_branch: gh-pages
publish_dir: ./public publish_dir: ./public
</code></pre> </code></pre>
</div> </div>
</div> </div>
</div> </div>
<div id="outline-container-org8e91c91" class="outline-2"> <div id="outline-container-org1251e16" class="outline-2">
<h2 id="org8e91c91">What is next</h2> <h2 id="org1251e16">What is next</h2>
<div class="outline-text-2" id="text-org8e91c91"> <div class="outline-text-2" id="text-org1251e16">
<p> <p>
I have a plans to make posts about next features: I have a plans to make posts about next features:
</p> </p>
</div> </div>
<div id="outline-container-org4df21fb" class="outline-3"> <div id="outline-container-org76a230d" class="outline-3">
<h3 id="org4df21fb"><a href="./add_rss_to_blog.html">RSS Feed</a></h3> <h3 id="org76a230d"><a href="./add_rss_to_blog.html">RSS Feed</a></h3>
</div> </div>
<div id="outline-container-orgc469690" class="outline-3"> <div id="outline-container-orgcb0b75a" class="outline-3">
<h3 id="orgc469690"><a href="./posts_preview.html">Open Graph image preview</a></h3> <h3 id="orgcb0b75a"><a href="./posts_preview.html">Open Graph image preview</a></h3>
</div> </div>
<div id="outline-container-orgb0a6b6c" class="outline-3"> <div id="outline-container-org0512465" class="outline-3">
<h3 id="orgb0a6b6c"><a href="./improve_code_blocks.html">Code highlighting</a></h3> <h3 id="org0512465"><a href="./improve_code_blocks.html">Code highlighting</a></h3>
</div> </div>
</div> </div>
</main><footer class="footer"><div class="container"><hr/><small><p>Alex Mikhailov</p><p>Built with: <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> <a href="https://orgmode.org/">Org Mode</a> <a href="https://picocss.com/">picocss</a></p></small></div></footer></body></html> </main><footer class="footer"><div class="container"><hr/><small><p>Alex Mikhailov</p><p>Built with: <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> <a href="https://orgmode.org/">Org Mode</a> <a href="https://picocss.com/">picocss</a></p></small></div></footer></body></html>

View File

@ -1,57 +1,57 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Let&apos;s add RSS feed to blog"/><meta property="og:description" content="Let&apos;s add RSS feed to blog"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/add_rss_to_blog.org.png"/><meta property="og:title" content="Org blog with RSS"/><meta name="twitter:description" content="Let&apos;s add RSS feed to blog"/><meta name="twitter:title" content="Org blog with RSS"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/add_rss_to_blog.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Org blog with RSS</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Org blog with RSS</h1><p>Let&apos;s add RSS feed to blog</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li><li><mark><a href="/tags/@elisp.html" class="secondary">@elisp</a></mark></li><li><mark><a href="/tags/@rss.html" class="secondary">@rss</a></mark></li></ul></nav></hgroup><div id="table-of-contents"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Let&apos;s add RSS feed to blog"/><meta property="og:description" content="Let&apos;s add RSS feed to blog"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/add_rss_to_blog.org.png"/><meta property="og:title" content="Org blog with RSS"/><meta name="twitter:description" content="Let&apos;s add RSS feed to blog"/><meta name="twitter:title" content="Org blog with RSS"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/add_rss_to_blog.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Org blog with RSS</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Org blog with RSS</h1><p>Let&apos;s add RSS feed to blog</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li><li><mark><a href="/tags/@elisp.html" class="secondary">@elisp</a></mark></li><li><mark><a href="/tags/@rss.html" class="secondary">@rss</a></mark></li></ul></nav></hgroup><div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2> <h2>Table of Contents</h2>
<div id="text-table-of-contents"> <div id="text-table-of-contents" role="doc-toc">
<ul> <ul>
<li><a href="#org3c0d63b">Why do you even need RSS?</a></li> <li><a href="#org727a4e0">Why do you even need RSS?</a></li>
<li><a href="#org81a47c8">Add RSS feed</a> <li><a href="#orgede8a74">Add RSS feed</a>
<ul> <ul>
<li><a href="#orgb87e193">Use sitemap backend in the build</a></li> <li><a href="#org0dc6a0a">Use sitemap backend in the build</a></li>
<li><a href="#orgadd2b67">Publishing and formatting functions</a></li> <li><a href="#org7fdc0cd">Publishing and formatting functions</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-org3c0d63b" class="outline-2"> <div id="outline-container-org727a4e0" class="outline-2">
<h2 id="org3c0d63b">Why do you even need RSS?</h2> <h2 id="org727a4e0">Why do you even need RSS?</h2>
<div class="outline-text-2" id="text-org3c0d63b"> <div class="outline-text-2" id="text-org727a4e0">
<p> <p>
RSS might seem like an outdated, marginal thing. But it still has at least one benefit—you can use an RSS feed as a sitemap for search engines. Plus, it's pretty geeky. RSS might seem like an outdated, marginal thing. But it still has at least one benefit—you can use an RSS feed as a sitemap for search engines. Plus, it's pretty geeky.
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org81a47c8" class="outline-2"> <div id="outline-container-orgede8a74" class="outline-2">
<h2 id="org81a47c8">Add RSS feed</h2> <h2 id="orgede8a74">Add RSS feed</h2>
<div class="outline-text-2" id="text-org81a47c8"> <div class="outline-text-2" id="text-orgede8a74">
<p> <p>
So, what's happening here? Let's start by integrating our templating functions into the build. So, what's happening here? Let's start by integrating our templating functions into the build.
</p> </p>
</div> </div>
<div id="outline-container-orgb87e193" class="outline-3"> <div id="outline-container-org0dc6a0a" class="outline-3">
<h3 id="orgb87e193">Use sitemap backend in the build</h3> <h3 id="org0dc6a0a">Use sitemap backend in the build</h3>
<div class="outline-text-3" id="text-orgb87e193"> <div class="outline-text-3" id="text-org0dc6a0a">
<pre><code class="language-lisp">(setq org-publish-project-alist <pre><code class="language-lisp">(setq org-publish-project-alist
(list (list
(list &quot;blog-rss&quot; (list &quot;blog-rss&quot;
:author &quot;Alex M&quot; :author &quot;Alex M&quot;
:email &quot;iam@fidonode.me&quot; :email &quot;iam@fidonode.me&quot;
:base-directory my/blog-src-path :base-directory my/blog-src-path
:base-extension &quot;org&quot; :base-extension &quot;org&quot;
:recursive t :recursive t
:exclude (regexp-opt &apos;(&quot;rss.org&quot; &quot;index.org&quot; &quot;404.org&quot; &quot;posts.org&quot;)) :exclude (regexp-opt &apos;(&quot;rss.org&quot; &quot;index.org&quot; &quot;404.org&quot; &quot;posts.org&quot;))
:publishing-function &apos;my/publish-to-rss :publishing-function &apos;my/publish-to-rss
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:rss-extension &quot;xml&quot; :rss-extension &quot;xml&quot;
:html-link-home my/url :html-link-home my/url
:html-link-use-abs-url t :html-link-use-abs-url t
:html-link-org-files-as-html t :html-link-org-files-as-html t
:auto-sitemap t :auto-sitemap t
:sitemap-filename &quot;rss.org&quot; :sitemap-filename &quot;rss.org&quot;
:sitemap-title &quot;rss&quot; :sitemap-title &quot;rss&quot;
:sitemap-style &apos;list :sitemap-style &apos;list
:sitemap-sort-files &apos;anti-chronologically :sitemap-sort-files &apos;anti-chronologically
:sitemap-function &apos;my/format-rss-feed :sitemap-function &apos;my/format-rss-feed
:sitemap-format-entry &apos;my/format-rss-feed-entry) :sitemap-format-entry &apos;my/format-rss-feed-entry)
)) ))
</code></pre> </code></pre>
<p> <p>
@ -59,9 +59,9 @@ How does it work? As you can see, we use the default sitemap generator from Org
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-orgadd2b67" class="outline-3"> <div id="outline-container-org7fdc0cd" class="outline-3">
<h3 id="orgadd2b67">Publishing and formatting functions</h3> <h3 id="org7fdc0cd">Publishing and formatting functions</h3>
<div class="outline-text-3" id="text-orgadd2b67"> <div class="outline-text-3" id="text-org7fdc0cd">
<p> <p>
We need a mandatory dependency because we don't want to mess with forming correct XML by ourselves. We need a mandatory dependency because we don't want to mess with forming correct XML by ourselves.
</p> </p>
@ -75,31 +75,31 @@ Here's the core of the process. We need to prepare entries before feeding them t
ENTRY is a file name. STYLE is either &apos;list&apos; or &apos;tree&apos;. ENTRY is a file name. STYLE is either &apos;list&apos; or &apos;tree&apos;.
PROJECT is the current project.&quot; PROJECT is the current project.&quot;
(cond ((not (directory-name-p entry)) (cond ((not (directory-name-p entry))
(let* ((file (org-publish--expand-file-name entry project)) (let* ((file (org-publish--expand-file-name entry project))
(title (org-publish-find-title entry project)) (title (org-publish-find-title entry project))
(date (format-time-string &quot;%Y-%m-%d&quot; (org-publish-find-date entry project))) (date (format-time-string &quot;%Y-%m-%d&quot; (org-publish-find-date entry project)))
(link (concat (file-name-sans-extension entry) &quot;.html&quot;))) (link (concat (file-name-sans-extension entry) &quot;.html&quot;)))
(with-temp-buffer (with-temp-buffer
(org-mode) (org-mode)
(insert (format &quot;* [[file:%s][%s]]\n&quot; file title)) (insert (format &quot;* [[file:%s][%s]]\n&quot; file title))
(org-set-property &quot;RSS_PERMALINK&quot; link) (org-set-property &quot;RSS_PERMALINK&quot; link)
(org-set-property &quot;RSS_TITLE&quot; title) (org-set-property &quot;RSS_TITLE&quot; title)
(org-set-property &quot;PUBDATE&quot; date) (org-set-property &quot;PUBDATE&quot; date)
(let ((first-two-lines (with-temp-buffer (let ((first-two-lines (with-temp-buffer
(insert-file-contents file) (insert-file-contents file)
(buffer-substring-no-properties (buffer-substring-no-properties
(point-min) (point-min)
(progn (forward-line 2) (point)))))) (progn (forward-line 2) (point))))))
(if (string-suffix-p &quot;\n&quot; first-two-lines) (if (string-suffix-p &quot;\n&quot; first-two-lines)
(setq first-two-lines (substring first-two-lines 0 -1))) (setq first-two-lines (substring first-two-lines 0 -1)))
(insert first-two-lines)) (insert first-two-lines))
(goto-char (point-max)) (goto-char (point-max))
(insert &quot;...&quot;) (insert &quot;...&quot;)
(buffer-string)))) (buffer-string))))
((eq style &apos;tree) ((eq style &apos;tree)
;; Return only last subdir. ;; Return only last subdir.
(file-name-nondirectory (directory-file-name entry))) (file-name-nondirectory (directory-file-name entry)))
(t entry))) (t entry)))
</code></pre> </code></pre>
<p> <p>
@ -111,8 +111,8 @@ TITLE is the title of the RSS feed. LIST is an internal
representation for the files to include, as returned by representation for the files to include, as returned by
`org-list-to-lisp&apos;. PROJECT is the current project.&quot; `org-list-to-lisp&apos;. PROJECT is the current project.&quot;
(concat &quot;#+TITLE: &quot; title &quot;\n&quot; (concat &quot;#+TITLE: &quot; title &quot;\n&quot;
&quot;#+STARTUP: showall \n\n&quot; &quot;#+STARTUP: showall \n\n&quot;
(org-list-to-subtree list 1 &apos;(:icount &quot;&quot; :istart &quot;&quot;)))) (org-list-to-subtree list 1 &apos;(:icount &quot;&quot; :istart &quot;&quot;))))
</code></pre> </code></pre>
<p> <p>
This function replaces the default publishing function to filter everything except the intermediate file before publishing. This function replaces the default publishing function to filter everything except the intermediate file before publishing.

View File

@ -1,32 +1,32 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Let&apos;s add tags to blog posts"/><meta property="og:description" content="Let&apos;s add tags to blog posts"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/blog_index_and_tags_automation.org.png"/><meta property="og:title" content="Blog index and tags automation"/><meta name="twitter:description" content="Let&apos;s add tags to blog posts"/><meta name="twitter:title" content="Blog index and tags automation"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/blog_index_and_tags_automation.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Blog index and tags automation</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Blog index and tags automation</h1><p>Let&apos;s add tags to blog posts</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li><li><mark><a href="/tags/@elisp.html" class="secondary">@elisp</a></mark></li><li><mark><a href="/tags/@tags.html" class="secondary">@tags</a></mark></li></ul></nav></hgroup><div id="table-of-contents"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Let&apos;s add tags to blog posts"/><meta property="og:description" content="Let&apos;s add tags to blog posts"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/blog_index_and_tags_automation.org.png"/><meta property="og:title" content="Blog index and tags automation"/><meta name="twitter:description" content="Let&apos;s add tags to blog posts"/><meta name="twitter:title" content="Blog index and tags automation"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/blog_index_and_tags_automation.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Blog index and tags automation</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Blog index and tags automation</h1><p>Let&apos;s add tags to blog posts</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li><li><mark><a href="/tags/@elisp.html" class="secondary">@elisp</a></mark></li><li><mark><a href="/tags/@tags.html" class="secondary">@tags</a></mark></li></ul></nav></hgroup><div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2> <h2>Table of Contents</h2>
<div id="text-table-of-contents"> <div id="text-table-of-contents" role="doc-toc">
<ul> <ul>
<li><a href="#org178294f">Tags.</a> <li><a href="#orgc69b18e">Tags.</a>
<ul> <ul>
<li><a href="#org5d49955">Automate tags.</a></li> <li><a href="#orgb84823f">Automate tags.</a></li>
</ul> </ul>
</li> </li>
<li><a href="#org579e8fb">Posts index.</a> <li><a href="#org93c6894">Posts index.</a>
<ul> <ul>
<li><a href="#orgd6ed0d6">Posts index automation.</a></li> <li><a href="#org419080d">Posts index automation.</a></li>
</ul> </ul>
</li> </li>
<li><a href="#org6126832">Cons.</a></li> <li><a href="#org63bc12c">Cons.</a></li>
<li><a href="#org2a98d2f">Whole config.</a></li> <li><a href="#orga13ebc1">Whole config.</a></li>
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-org178294f" class="outline-2"> <div id="outline-container-orgc69b18e" class="outline-2">
<h2 id="org178294f">Tags.</h2> <h2 id="orgc69b18e">Tags.</h2>
<div class="outline-text-2" id="text-org178294f"> <div class="outline-text-2" id="text-orgc69b18e">
<p> <p>
Tags are a nice and easy way to organize posts without explicit search. In the simplest way, you have a list of tags in posts, and each tag links to a page with all posts having the corresponding tag. It is also helpful to have a page with all tags available in the blog. And, of course, I don't want to maintain the list of tags manually. Tags are a nice and easy way to organize posts without explicit search. In the simplest way, you have a list of tags in posts, and each tag links to a page with all posts having the corresponding tag. It is also helpful to have a page with all tags available in the blog. And, of course, I don't want to maintain the list of tags manually.
</p> </p>
</div> </div>
<div id="outline-container-org5d49955" class="outline-3"> <div id="outline-container-orgb84823f" class="outline-3">
<h3 id="org5d49955">Automate tags.</h3> <h3 id="orgb84823f">Automate tags.</h3>
<div class="outline-text-3" id="text-org5d49955"> <div class="outline-text-3" id="text-orgb84823f">
<p> <p>
Simple idea - go through all files, collect titles, dates and descriptions, render into org files. Easy peazy lemon squezy. Simple idea - go through all files, collect titles, dates and descriptions, render into org files. Easy peazy lemon squezy.
Let me show you parts of function body. Let me show you parts of function body.
@ -51,34 +51,34 @@ Create folder for tags files. Than we go through each file and collect plists wi
(with-temp-buffer (with-temp-buffer
(insert-file-contents file) (insert-file-contents file)
(let* ((parsed-info (list :parse-tree (org-element-parse-buffer))) (let* ((parsed-info (list :parse-tree (org-element-parse-buffer)))
(tags (split-string (my/org-get-property &quot;TAGS&quot; parsed-info))) (tags (split-string (my/org-get-property &quot;TAGS&quot; parsed-info)))
(title (my/org-get-property &quot;TITLE&quot; parsed-info)) (title (my/org-get-property &quot;TITLE&quot; parsed-info))
(date (my/org-get-property &quot;DATE&quot; parsed-info)) (date (my/org-get-property &quot;DATE&quot; parsed-info))
(description (my/org-get-property &quot;DESCRIPTION&quot; parsed-info)) (description (my/org-get-property &quot;DESCRIPTION&quot; parsed-info))
(published (my/org-get-property &quot;PUBLISHED&quot; parsed-info)) (published (my/org-get-property &quot;PUBLISHED&quot; parsed-info))
(preview (with-temp-buffer (preview (with-temp-buffer
(insert-file-contents file) (insert-file-contents file)
(my/get-first-two-meaningful-lines))) (my/get-first-two-meaningful-lines)))
) )
(if (and published (string= published &quot;true&quot;)) (if (and published (string= published &quot;true&quot;))
(progn (progn
(setq link-plist (setq link-plist
(list (list
:title title :title title
:description description :description description
:preview preview :preview preview
:file file :file file
:date date)) :date date))
(push link-plist posts-list) (push link-plist posts-list)
(dolist (tag tags) (dolist (tag tags)
(puthash tag (cons link-plist (gethash tag tag-map)) tag-map)) (puthash tag (cons link-plist (gethash tag tag-map)) tag-map))
(setq posts-list (setq posts-list
(sort posts-list (sort posts-list
(lambda (a b) (lambda (a b)
(date-less-p (plist-get b :date) (plist-get a :date)))))))))) (date-less-p (plist-get b :date) (plist-get a :date))))))))))
</code></pre> </code></pre>
<p> <p>
Go through resulting map and render org files for each tag. Go through resulting map and render org files for each tag.
@ -94,17 +94,17 @@ Go through resulting map and render org files for each tag.
(insert (format &quot;* %s\n&quot; tag)) (insert (format &quot;* %s\n&quot; tag))
(dolist (link-plist link-plists) (dolist (link-plist link-plists)
(let* (let*
((title (plist-get link-plist :title)) ((title (plist-get link-plist :title))
(description (plist-get link-plist :description)) (description (plist-get link-plist :description))
(file (plist-get link-plist :file)) (file (plist-get link-plist :file))
(date (plist-get link-plist :date)) (date (plist-get link-plist :date))
(preview (plist-get link-plist :preview)) (preview (plist-get link-plist :preview))
(relative-file (file-relative-name file (file-name-directory tag-file)))) (relative-file (file-relative-name file (file-name-directory tag-file))))
(insert (format &quot;** [[file:%s][%s]]\n&quot; relative-file title)) (insert (format &quot;** [[file:%s][%s]]\n&quot; relative-file title))
(insert (format &quot;%s\n&quot; description)) (insert (format &quot;%s\n&quot; description))
(insert (format &quot;#+BEGIN_QUOTE\n%s ...\n#+END_QUOTE\n&quot; preview)) (insert (format &quot;#+BEGIN_QUOTE\n%s ...\n#+END_QUOTE\n&quot; preview))
(insert (format &quot;%s\n&quot; (my/date-format date)))))))) (insert (format &quot;%s\n&quot; (my/date-format date))))))))
tag-map) tag-map)
</code></pre> </code></pre>
<p> <p>
@ -113,54 +113,54 @@ Resulting page example: <a href="https://fidonode.me/tags/@org-mode">@org-mode</
</div> </div>
</div> </div>
</div> </div>
<div id="outline-container-org579e8fb" class="outline-2"> <div id="outline-container-org93c6894" class="outline-2">
<h2 id="org579e8fb">Posts index.</h2> <h2 id="org93c6894">Posts index.</h2>
<div class="outline-text-2" id="text-org579e8fb"> <div class="outline-text-2" id="text-org93c6894">
<p> <p>
Previously, I maintained a list of posts manually. Now that I have more than 5 posts, I no longer want to do it by hand. So, after introducing tags, I've decided to automate the page with the list of posts. The same idea, almost the same data, will be integrated into the same file. Pagination has not yet been implemented and is not planned. Previously, I maintained a list of posts manually. Now that I have more than 5 posts, I no longer want to do it by hand. So, after introducing tags, I've decided to automate the page with the list of posts. The same idea, almost the same data, will be integrated into the same file. Pagination has not yet been implemented and is not planned.
</p> </p>
</div> </div>
<div id="outline-container-orgd6ed0d6" class="outline-3"> <div id="outline-container-org419080d" class="outline-3">
<h3 id="orgd6ed0d6">Posts index automation.</h3> <h3 id="org419080d">Posts index automation.</h3>
<div class="outline-text-3" id="text-orgd6ed0d6"> <div class="outline-text-3" id="text-org419080d">
<p> <p>
Here is the part of function which renders list of posts and list of tags with number of posts in each tag category. Here is the part of function which renders list of posts and list of tags with number of posts in each tag category.
</p> </p>
<pre><code class="language-lisp">(let <pre><code class="language-lisp">(let
((index-file (concat base-dir &quot;/posts.org&quot;))) ((index-file (concat base-dir &quot;/posts.org&quot;)))
(with-temp-file index-file (with-temp-file index-file
(org-mode) (org-mode)
(insert &quot;#+TITLE: Alex Mikhailov - Blog\n&quot;) (insert &quot;#+TITLE: Alex Mikhailov - Blog\n&quot;)
(insert &quot;#+AUTHOR: Aleksandr Mikhailov\n&quot;) (insert &quot;#+AUTHOR: Aleksandr Mikhailov\n&quot;)
(insert &quot;#+DESCRIPTION: Index page for my blog\n&quot;) (insert &quot;#+DESCRIPTION: Index page for my blog\n&quot;)
(insert &quot;#+OPTIONS: toc:nil\n\n&quot;) (insert &quot;#+OPTIONS: toc:nil\n\n&quot;)
(insert &quot;* Posts\n&quot;) (insert &quot;* Posts\n&quot;)
(dolist (post posts-list) (dolist (post posts-list)
(let* (let*
((title (plist-get post :title)) ((title (plist-get post :title))
(description (plist-get post :description)) (description (plist-get post :description))
(file (plist-get post :file)) (file (plist-get post :file))
(date (plist-get post :date)) (date (plist-get post :date))
(preview (plist-get post :preview)) (preview (plist-get post :preview))
(relative-file (file-relative-name file (file-name-directory file)))) (relative-file (file-relative-name file (file-name-directory file))))
(insert (format &quot;** [[file:./posts/%s][%s]]\n&quot; relative-file title)) (insert (format &quot;** [[file:./posts/%s][%s]]\n&quot; relative-file title))
(insert (format &quot;%s\n&quot; description)) (insert (format &quot;%s\n&quot; description))
(insert (format &quot;#+BEGIN_QUOTE\n%s ...\n#+END_QUOTE\n&quot; preview)) (insert (format &quot;#+BEGIN_QUOTE\n%s ...\n#+END_QUOTE\n&quot; preview))
(insert (format &quot;%s\n&quot; (my/date-format date))) (insert (format &quot;%s\n&quot; (my/date-format date)))
) )
) )
(insert &quot;* Tags\n&quot;) (insert &quot;* Tags\n&quot;)
(maphash (maphash
(lambda (tag posts) (lambda (tag posts)
(insert (format &quot;** [[file:./tags/%s.org][%s]] (%d) \n&quot; tag tag (length posts))) ) (insert (format &quot;** [[file:./tags/%s.org][%s]] (%d) \n&quot; tag tag (length posts))) )
tag-map tag-map
) )
) )
) )
</code></pre> </code></pre>
@ -170,17 +170,17 @@ Here is an example of resulting page: <a href="https://fidonode.me/posts">Posts<
</div> </div>
</div> </div>
</div> </div>
<div id="outline-container-org6126832" class="outline-2"> <div id="outline-container-org63bc12c" class="outline-2">
<h2 id="org6126832">Cons.</h2> <h2 id="org63bc12c">Cons.</h2>
<div class="outline-text-2" id="text-org6126832"> <div class="outline-text-2" id="text-org63bc12c">
<p> <p>
Now, with the way the rendering function is integrated into the process, it is called when going through each Org file found by Org-Export. This introduces O(n<sup>2</sup>) complexity. It's not ideal, but never mind, I will redo it before reaching the 100th post. Now, with the way the rendering function is integrated into the process, it is called when going through each Org file found by Org-Export. This introduces O(n<sup>2</sup>) complexity. It's not ideal, but never mind, I will redo it before reaching the 100th post.
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org2a98d2f" class="outline-2"> <div id="outline-container-orga13ebc1" class="outline-2">
<h2 id="org2a98d2f">Whole config.</h2> <h2 id="orga13ebc1">Whole config.</h2>
<div class="outline-text-2" id="text-org2a98d2f"> <div class="outline-text-2" id="text-orga13ebc1">
<p> <p>
As usual, between posts, I decided to tackle a whole bunch of small tasks, so here is the entire config. I'm thinking about splitting the exporter into modules and maybe open-sourcing it properly. As usual, between posts, I decided to tackle a whole bunch of small tasks, so here is the entire config. I'm thinking about splitting the exporter into modules and maybe open-sourcing it properly.
A neat thing I've implemented is a way to filter out unpublished posts using a <code>PUBLISHED</code> property. This allows me to work on drafts without affecting the blog's current state. A neat thing I've implemented is a way to filter out unpublished posts using a <code>PUBLISHED</code> property. This allows me to work on drafts without affecting the blog's current state.
@ -201,7 +201,7 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(normal-top-level-add-subdirs-to-load-path)) (normal-top-level-add-subdirs-to-load-path))
(add-to-list &apos;custom-theme-load-path (add-to-list &apos;custom-theme-load-path
(concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/doom-themes&quot;)) (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/doom-themes&quot;))
(add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/base16-theme&quot;)) (add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/base16-theme&quot;))
(add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/moe-theme&quot;)) (add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/moe-theme&quot;))
@ -232,71 +232,71 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(defun my/footer (info) (defun my/footer (info)
`(footer ((class . &quot;footer&quot;)) `(footer ((class . &quot;footer&quot;))
(div ((class . &quot;container&quot;)) (div ((class . &quot;container&quot;))
(hr () ) (hr () )
(small () (small ()
(p () &quot;Alex Mikhailov&quot;) (p () &quot;Alex Mikhailov&quot;)
(p () &quot;Built with: &quot; (p () &quot;Built with: &quot;
(a ((href . &quot;https://www.gnu.org/software/emacs/&quot;)) &quot;GNU Emacs&quot;) &quot; &quot; (a ((href . &quot;https://www.gnu.org/software/emacs/&quot;)) &quot;GNU Emacs&quot;) &quot; &quot;
(a ((href . &quot;https://orgmode.org/&quot;)) &quot;Org Mode&quot;) &quot; &quot; (a ((href . &quot;https://orgmode.org/&quot;)) &quot;Org Mode&quot;) &quot; &quot;
(a ((href . &quot;https://picocss.com/&quot;)) &quot;picocss&quot;) (a ((href . &quot;https://picocss.com/&quot;)) &quot;picocss&quot;)
))))) )))))
(defun my/header (info) (defun my/header (info)
(let ((title-str (org-export-data (plist-get info :title) info))) (let ((title-str (org-export-data (plist-get info :title) info)))
`(header ((class . &quot;header&quot;)) `(header ((class . &quot;header&quot;))
(div ((class . &quot;container&quot;)) (div ((class . &quot;container&quot;))
(nav () (nav ()
(ul () (ul ()
(li () (li ()
(strong () ,&quot;Alex Mikhailov&quot;))) (strong () ,&quot;Alex Mikhailov&quot;)))
(ul () (ul ()
(li () (a ((href . &quot;/index.html&quot;)) &quot;About&quot;)) (li () (a ((href . &quot;/index.html&quot;)) &quot;About&quot;))
(li () (a ((href . &quot;/posts.html&quot;)) &quot;Blog&quot;)) (li () (a ((href . &quot;/posts.html&quot;)) &quot;Blog&quot;))
(li () (a ((href . &quot;/rss.xml&quot;)) &quot;RSS&quot;)) (li () (a ((href . &quot;/rss.xml&quot;)) &quot;RSS&quot;))
)))))) ))))))
(defun my/src-block (src-block contents info) (defun my/src-block (src-block contents info)
&quot;Translate SRC-BLOCK element into HTML. &quot;Translate SRC-BLOCK element into HTML.
CONTENTS is nil. INFO is a plist holding contextual information.&quot; CONTENTS is nil. INFO is a plist holding contextual information.&quot;
(let* ( (let* (
(org-language (format &quot;language-%s&quot; (org-element-property :language src-block))) (org-language (format &quot;language-%s&quot; (org-element-property :language src-block)))
(language (my/replace-substrings org-language)) (language (my/replace-substrings org-language))
(code (org-element-property :value src-block))) (code (org-element-property :value src-block)))
(esxml-to-xml (esxml-to-xml
`(pre () `(pre ()
(code ((class . ,language)) (code ((class . ,language))
,(org-html-encode-plain-text code) ,(org-html-encode-plain-text code)
))))) )))))
(defun my/render-preview (file-name title description) (defun my/render-preview (file-name title description)
(let* ((has-imagemagick (executable-find &quot;magick&quot;)) (let* ((has-imagemagick (executable-find &quot;magick&quot;))
(full-file-path (file-truename(format &quot;%s%s/resources/images/preview/%s.png&quot; script-directory my/blog-src-path file-name ))) (full-file-path (file-truename(format &quot;%s%s/resources/images/preview/%s.png&quot; script-directory my/blog-src-path file-name )))
(file-dir (file-name-directory full-file-path)) (file-dir (file-name-directory full-file-path))
(has-dir (file-directory-p file-dir)) (has-dir (file-directory-p file-dir))
(has-file (file-exists-p full-file-path)) (has-file (file-exists-p full-file-path))
(path-to-script-root (format &quot;%shelpers&quot; script-directory)) (path-to-script-root (format &quot;%shelpers&quot; script-directory))
(path-to-script (format &quot;%s/og_image_gen.sh&quot; path-to-script-root))) (path-to-script (format &quot;%s/og_image_gen.sh&quot; path-to-script-root)))
(if (and has-imagemagick (if (and has-imagemagick
(and description (not (string= description &quot;&quot;)))) (and description (not (string= description &quot;&quot;))))
(progn (progn
(when (not has-file) (when (not has-file)
(progn (progn
(when (not has-dir) (when (not has-dir)
(make-directory file-dir t)) (make-directory file-dir t))
(shell-command (format &quot;bash &apos;%s&apos; &apos;%s&apos; &apos;%s&apos; &apos;%s&apos; &apos;%s&apos;&quot; path-to-script title description full-file-path path-to-script-root)) (shell-command (format &quot;bash &apos;%s&apos; &apos;%s&apos; &apos;%s&apos; &apos;%s&apos; &apos;%s&apos;&quot; path-to-script title description full-file-path path-to-script-root))
) )
)) ))
(message &quot;Imagemagick is not installed. Preview generation skipped.&quot;) (message &quot;Imagemagick is not installed. Preview generation skipped.&quot;)
))) )))
(defun my/html-header (info) (defun my/html-header (info)
(let* ((title-str (org-export-data (plist-get info :title) info)) (let* ((title-str (org-export-data (plist-get info :title) info))
(description-str (org-export-data (plist-get info :description) info)) (description-str (org-export-data (plist-get info :description) info))
(file-path-str (org-export-data (plist-get info :input-file) info)) (file-path-str (org-export-data (plist-get info :input-file) info))
(base-directory-str (org-export-data (plist-get info :base-directory) info)) (base-directory-str (org-export-data (plist-get info :base-directory) info))
(file-name-str (file-relative-name file-path-str (format &quot;%s/%s&quot; script-directory base-directory-str))) (file-name-str (file-relative-name file-path-str (format &quot;%s/%s&quot; script-directory base-directory-str)))
(img-link-str (format &quot;%s/resources/images/preview/%s.png&quot; my/url file-name-str)) (img-link-str (format &quot;%s/resources/images/preview/%s.png&quot; my/url file-name-str))
(has-src-blocks (my/org-has-src-blocks-p info))) (has-src-blocks (my/org-has-src-blocks-p info)))
(my/render-preview file-name-str title-str description-str) (my/render-preview file-name-str title-str description-str)
@ -309,7 +309,7 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(meta ((charset . &quot;utf-8&quot;))) (meta ((charset . &quot;utf-8&quot;)))
(meta ((author . &quot;Alex Mikhailov&quot;))) (meta ((author . &quot;Alex Mikhailov&quot;)))
(meta ((name . &quot;viewport&quot;) (meta ((name . &quot;viewport&quot;)
(content . &quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;))) (content . &quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;)))
(meta ((name . &quot;color-scheme&quot;) (content . &quot;light dark&quot;))) (meta ((name . &quot;color-scheme&quot;) (content . &quot;light dark&quot;)))
(meta ((http-equiv . &quot;content-language&quot;) (content . &quot;en-us&quot;))) (meta ((http-equiv . &quot;content-language&quot;) (content . &quot;en-us&quot;)))
;; OG block ;; OG block
@ -329,13 +329,13 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(title () ,title-str) (title () ,title-str)
,@(when has-src-blocks ,@(when has-src-blocks
(list (list
`(link ((id . &quot;highlight-theme&quot;) (rel . &quot;stylesheet&quot;) (type . &quot;text/css&quot;))) `(link ((id . &quot;highlight-theme&quot;) (rel . &quot;stylesheet&quot;) (type . &quot;text/css&quot;)))
`(script ((src . &quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js&quot;)) ()) `(script ((src . &quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js&quot;)) ())
`(script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js&quot;)) ()) `(script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js&quot;)) ())
`(script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js&quot;)) ()) `(script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js&quot;)) ())
`(script ((src . &quot;/resources/js/theme-selector.js&quot;)) ()) `(script ((src . &quot;/resources/js/theme-selector.js&quot;)) ())
))))) )))))
(defun my/regular-template (contents info) (defun my/regular-template (contents info)
`(main ((class . &quot;container&quot;)) `(main ((class . &quot;container&quot;))
@ -343,18 +343,18 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(defun my/blog-post-template (contents info) (defun my/blog-post-template (contents info)
(let* ((title-str (org-export-data (plist-get info :title) info)) (let* ((title-str (org-export-data (plist-get info :title) info))
(description-str (org-export-data (plist-get info :description) info)) (description-str (org-export-data (plist-get info :description) info))
(tags (split-string (my/org-get-property &quot;TAGS&quot; info))) (tags (split-string (my/org-get-property &quot;TAGS&quot; info)))
(tags-html (cl-map &apos;list (lambda (tag) (tags-html (cl-map &apos;list (lambda (tag)
`(li () (mark () (a ((href . ,(format &quot;/tags/%s.html&quot; tag)) (class . &quot;secondary&quot;)) ,(format &quot;%s&quot; tag))))) tags)) `(li () (mark () (a ((href . ,(format &quot;/tags/%s.html&quot; tag)) (class . &quot;secondary&quot;)) ,(format &quot;%s&quot; tag))))) tags))
) )
`(main ((class . &quot;container blog-post&quot;)) `(main ((class . &quot;container blog-post&quot;))
(hgroup () (hgroup ()
(h1 () ,title-str) (h1 () ,title-str)
(p () ,description-str) (p () ,description-str)
(nav () (ul () (li () &quot;Tags:&quot;) ,@tags-html)) (nav () (ul () (li () &quot;Tags:&quot;) ,@tags-html))
) )
(raw-string ,contents) (raw-string ,contents)
))) )))
@ -366,21 +366,21 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
&quot;&amp;lt;!DOCTYPE html&amp;gt;&quot; &quot;&amp;lt;!DOCTYPE html&amp;gt;&quot;
(esxml-to-xml (esxml-to-xml
`(html ((lang . &quot;en&quot;)) `(html ((lang . &quot;en&quot;))
,(my/html-header info) ,(my/html-header info)
(body () (body ()
,(my/header info) ,(my/header info)
,(if (string-match-p &quot;\/posts\/&quot; file-path-str) ,(if (string-match-p &quot;\/posts\/&quot; file-path-str)
(my/blog-post-template contents info) (my/blog-post-template contents info)
(my/regular-template contents info)) (my/regular-template contents info))
,(my/footer info) ,(my/footer info)
)))))) ))))))
(org-export-define-derived-backend &apos;my-html &apos;html (org-export-define-derived-backend &apos;my-html &apos;html
:translate-alist &apos;( :translate-alist &apos;(
(template . my/template) (template . my/template)
(src-block . my/src-block) (src-block . my/src-block)
)) ))
(defun my/publish-to-html (plist filename pub-dir) (defun my/publish-to-html (plist filename pub-dir)
&quot;Publish an Org file to HTML using the custom backend.&quot; &quot;Publish an Org file to HTML using the custom backend.&quot;
@ -394,12 +394,12 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
&quot;Process all Org files in &apos;posts&apos; and &apos;tags&apos; directories, create index file, and insert links.&quot; &quot;Process all Org files in &apos;posts&apos; and &apos;tags&apos; directories, create index file, and insert links.&quot;
(let* ((base-dir (plist-get plist :base-directory) ) (let* ((base-dir (plist-get plist :base-directory) )
(tag-dir (concat base-dir &quot;/tags/&quot;)) (tag-dir (concat base-dir &quot;/tags/&quot;))
(posts-dir (concat base-dir &quot;/posts&quot;)) (posts-dir (concat base-dir &quot;/posts&quot;))
(post-org-files (directory-files-recursively posts-dir &quot;\\.org$&quot;)) (post-org-files (directory-files-recursively posts-dir &quot;\\.org$&quot;))
(tag-map (make-hash-table :test &apos;equal)) (tag-map (make-hash-table :test &apos;equal))
(posts-list (list)) (posts-list (list))
) )
;; Ensure tag directory exists ;; Ensure tag directory exists
(unless (file-directory-p tag-dir) (unless (file-directory-p tag-dir)
@ -408,72 +408,72 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
;; Scan all org files and collect tags ;; Scan all org files and collect tags
(dolist (file post-org-files) (dolist (file post-org-files)
(with-temp-buffer (with-temp-buffer
(insert-file-contents file) (insert-file-contents file)
(let* ((parsed-info (list :parse-tree (org-element-parse-buffer))) (let* ((parsed-info (list :parse-tree (org-element-parse-buffer)))
(tags (split-string (my/org-get-property &quot;TAGS&quot; parsed-info))) (tags (split-string (my/org-get-property &quot;TAGS&quot; parsed-info)))
(title (my/org-get-property &quot;TITLE&quot; parsed-info)) (title (my/org-get-property &quot;TITLE&quot; parsed-info))
(date (my/org-get-property &quot;DATE&quot; parsed-info)) (date (my/org-get-property &quot;DATE&quot; parsed-info))
(description (my/org-get-property &quot;DESCRIPTION&quot; parsed-info)) (description (my/org-get-property &quot;DESCRIPTION&quot; parsed-info))
(published (my/org-get-property &quot;PUBLISHED&quot; parsed-info)) (published (my/org-get-property &quot;PUBLISHED&quot; parsed-info))
(preview (with-temp-buffer (preview (with-temp-buffer
(insert-file-contents file) (insert-file-contents file)
(my/get-first-two-meaningful-lines))) (my/get-first-two-meaningful-lines)))
) )
(if (and published (string= published &quot;true&quot;)) (if (and published (string= published &quot;true&quot;))
(progn (progn
(setq link-plist (setq link-plist
(list (list
:title title :title title
:description description :description description
:preview preview :preview preview
:file file :file file
:date date)) :date date))
(push link-plist posts-list) (push link-plist posts-list)
(dolist (tag tags) (dolist (tag tags)
(puthash tag (cons link-plist (gethash tag tag-map)) tag-map)) (puthash tag (cons link-plist (gethash tag tag-map)) tag-map))
(setq posts-list (setq posts-list
(sort posts-list (sort posts-list
(lambda (a b) (lambda (a b)
(date-less-p (plist-get b :date) (plist-get a :date)))))))))) (date-less-p (plist-get b :date) (plist-get a :date))))))))))
(let (let
((index-file (concat base-dir &quot;/posts.org&quot;))) ((index-file (concat base-dir &quot;/posts.org&quot;)))
(with-temp-file index-file (with-temp-file index-file
(org-mode) (org-mode)
(insert &quot;#+TITLE: Alex Mikhailov - Blog\n&quot;) (insert &quot;#+TITLE: Alex Mikhailov - Blog\n&quot;)
(insert &quot;#+AUTHOR: Aleksandr Mikhailov\n&quot;) (insert &quot;#+AUTHOR: Aleksandr Mikhailov\n&quot;)
(insert &quot;#+DESCRIPTION: Index page for my blog\n&quot;) (insert &quot;#+DESCRIPTION: Index page for my blog\n&quot;)
(insert &quot;#+OPTIONS: toc:nil\n\n&quot;) (insert &quot;#+OPTIONS: toc:nil\n\n&quot;)
(insert &quot;* Posts\n&quot;) (insert &quot;* Posts\n&quot;)
(dolist (post posts-list) (dolist (post posts-list)
(let* (let*
((title (plist-get post :title)) ((title (plist-get post :title))
(description (plist-get post :description)) (description (plist-get post :description))
(file (plist-get post :file)) (file (plist-get post :file))
(date (plist-get post :date)) (date (plist-get post :date))
(preview (plist-get post :preview)) (preview (plist-get post :preview))
(relative-file (file-relative-name file (file-name-directory file)))) (relative-file (file-relative-name file (file-name-directory file))))
(insert (format &quot;** [[file:./posts/%s][%s]]\n&quot; relative-file title)) (insert (format &quot;** [[file:./posts/%s][%s]]\n&quot; relative-file title))
(insert (format &quot;%s\n&quot; description)) (insert (format &quot;%s\n&quot; description))
(insert (format &quot;#+BEGIN_QUOTE\n%s ...\n#+END_QUOTE\n&quot; preview)) (insert (format &quot;#+BEGIN_QUOTE\n%s ...\n#+END_QUOTE\n&quot; preview))
(insert (format &quot;%s\n&quot; (my/date-format date))) (insert (format &quot;%s\n&quot; (my/date-format date)))
) )
) )
(insert &quot;* Tags\n&quot;) (insert &quot;* Tags\n&quot;)
(maphash (maphash
(lambda (tag posts) (lambda (tag posts)
(insert (format &quot;** [[file:./tags/%s.org][%s]] (%d) \n&quot; tag tag (length posts))) ) (insert (format &quot;** [[file:./tags/%s.org][%s]] (%d) \n&quot; tag tag (length posts))) )
tag-map tag-map
) )
) )
) )
@ -481,24 +481,24 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(maphash (maphash
(lambda (tag link-plists) (lambda (tag link-plists)
(let (let
((tag-file (concat tag-dir tag &quot;.org&quot;))) ((tag-file (concat tag-dir tag &quot;.org&quot;)))
(with-temp-file tag-file (with-temp-file tag-file
(insert (format &quot;#+TITLE: Tag: %s\n&quot; tag)) (insert (format &quot;#+TITLE: Tag: %s\n&quot; tag))
(insert &quot;#+OPTIONS: toc:nil\n\n&quot;) (insert &quot;#+OPTIONS: toc:nil\n\n&quot;)
(insert (format &quot;* %s\n&quot; tag)) (insert (format &quot;* %s\n&quot; tag))
(dolist (link-plist link-plists) (dolist (link-plist link-plists)
(let* (let*
((title (plist-get link-plist :title)) ((title (plist-get link-plist :title))
(description (plist-get link-plist :description)) (description (plist-get link-plist :description))
(file (plist-get link-plist :file)) (file (plist-get link-plist :file))
(date (plist-get link-plist :date)) (date (plist-get link-plist :date))
(preview (plist-get link-plist :preview)) (preview (plist-get link-plist :preview))
(relative-file (file-relative-name file (file-name-directory tag-file)))) (relative-file (file-relative-name file (file-name-directory tag-file))))
(insert (format &quot;** [[file:%s][%s]]\n&quot; relative-file title)) (insert (format &quot;** [[file:%s][%s]]\n&quot; relative-file title))
(insert (format &quot;%s\n&quot; description)) (insert (format &quot;%s\n&quot; description))
(insert (format &quot;#+BEGIN_QUOTE\n%s ...\n#+END_QUOTE\n&quot; preview)) (insert (format &quot;#+BEGIN_QUOTE\n%s ...\n#+END_QUOTE\n&quot; preview))
(insert (format &quot;%s\n&quot; (my/date-format date)))))))) (insert (format &quot;%s\n&quot; (my/date-format date))))))))
tag-map) tag-map)
) )
) )
@ -511,31 +511,31 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
ENTRY is a file name. STYLE is either &apos;list&apos; or &apos;tree&apos;. ENTRY is a file name. STYLE is either &apos;list&apos; or &apos;tree&apos;.
PROJECT is the current project.&quot; PROJECT is the current project.&quot;
(cond ((not (directory-name-p entry)) (cond ((not (directory-name-p entry))
(let* ((file (org-publish--expand-file-name entry project)) (let* ((file (org-publish--expand-file-name entry project))
(title (org-publish-find-title entry project)) (title (org-publish-find-title entry project))
(date (format-time-string &quot;%Y-%m-%d&quot; (org-publish-find-date entry project))) (date (format-time-string &quot;%Y-%m-%d&quot; (org-publish-find-date entry project)))
(link (concat (file-name-sans-extension entry) &quot;.html&quot;))) (link (concat (file-name-sans-extension entry) &quot;.html&quot;)))
(with-temp-buffer (with-temp-buffer
(org-mode) (org-mode)
(insert (format &quot;* [[file:%s][%s]]\n&quot; file title)) (insert (format &quot;* [[file:%s][%s]]\n&quot; file title))
(org-set-property &quot;RSS_PERMALINK&quot; link) (org-set-property &quot;RSS_PERMALINK&quot; link)
(org-set-property &quot;RSS_TITLE&quot; title) (org-set-property &quot;RSS_TITLE&quot; title)
(org-set-property &quot;PUBDATE&quot; date) (org-set-property &quot;PUBDATE&quot; date)
(let ((first-two-lines (with-temp-buffer (let ((first-two-lines (with-temp-buffer
(insert-file-contents file) (insert-file-contents file)
(buffer-substring-no-properties (buffer-substring-no-properties
(point-min) (point-min)
(progn (forward-line 2) (point)))))) (progn (forward-line 2) (point))))))
(if (string-suffix-p &quot;\n&quot; first-two-lines) (if (string-suffix-p &quot;\n&quot; first-two-lines)
(setq first-two-lines (substring first-two-lines 0 -1))) (setq first-two-lines (substring first-two-lines 0 -1)))
(insert first-two-lines)) (insert first-two-lines))
(goto-char (point-max)) (goto-char (point-max))
(insert &quot;...&quot;) (insert &quot;...&quot;)
(buffer-string)))) (buffer-string))))
((eq style &apos;tree) ((eq style &apos;tree)
;; Return only last subdir. ;; Return only last subdir.
(file-name-nondirectory (directory-file-name entry))) (file-name-nondirectory (directory-file-name entry)))
(t entry))) (t entry)))
(defun my/format-rss-feed (title list) (defun my/format-rss-feed (title list)
&quot;Generate RSS feed, as a string. &quot;Generate RSS feed, as a string.
@ -543,8 +543,8 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
representation for the files to include, as returned by representation for the files to include, as returned by
`org-list-to-lisp&apos;. PROJECT is the current project.&quot; `org-list-to-lisp&apos;. PROJECT is the current project.&quot;
(concat &quot;#+TITLE: &quot; title &quot;\n&quot; (concat &quot;#+TITLE: &quot; title &quot;\n&quot;
&quot;#+STARTUP: showall \n\n&quot; &quot;#+STARTUP: showall \n\n&quot;
(org-list-to-subtree list 1 &apos;(:icount &quot;&quot; :istart &quot;&quot;)))) (org-list-to-subtree list 1 &apos;(:icount &quot;&quot; :istart &quot;&quot;))))
(defun my/publish-to-rss (plist filename pub-dir) (defun my/publish-to-rss (plist filename pub-dir)
&quot;Publish RSS with PLIST, only when FILENAME is &apos;rss.org&apos;. &quot;Publish RSS with PLIST, only when FILENAME is &apos;rss.org&apos;.
@ -573,24 +573,24 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
;; Now read and return the first two meaningful lines ;; Now read and return the first two meaningful lines
(cleanup-org-line (buffer-substring-no-properties (cleanup-org-line (buffer-substring-no-properties
(point) (point)
(progn (forward-line 2) (point))) (progn (forward-line 2) (point)))
)) ))
) )
(defun date-less-p (date1 date2) (defun date-less-p (date1 date2)
&quot;Return t if DATE1 is less than DATE2. &quot;Return t if DATE1 is less than DATE2.
DATE1 and DATE2 should be strings in the format &amp;lt;YYYY-MM-DD Day&amp;gt;.&quot; DATE1 and DATE2 should be strings in the format &amp;lt;YYYY-MM-DD Day&amp;gt;.&quot;
(let* ((date1 (substring date1 1 11)) ; Extract the date part (let* ((date1 (substring date1 1 11)) ; Extract the date part
(date2 (substring date2 1 11)) (date2 (substring date2 1 11))
(time1 (apply &apos;encode-time (parse-time-string (concat date1 &quot; 00:00:00&quot;)))) (time1 (apply &apos;encode-time (parse-time-string (concat date1 &quot; 00:00:00&quot;))))
(time2 (apply &apos;encode-time (parse-time-string (concat date2 &quot; 00:00:00&quot;))))) (time2 (apply &apos;encode-time (parse-time-string (concat date2 &quot; 00:00:00&quot;)))))
(time-less-p time1 time2))) (time-less-p time1 time2)))
(defun my/date-format (org-date) (defun my/date-format (org-date)
&quot;Convert an Org-mode date string ORG-DATE to a formatted date string.&quot; &quot;Convert an Org-mode date string ORG-DATE to a formatted date string.&quot;
(let* ((parsed-time (org-parse-time-string org-date)) (let* ((parsed-time (org-parse-time-string org-date))
(time (apply &apos;encode-time parsed-time))) (time (apply &apos;encode-time parsed-time)))
(format-time-string &quot;posted on %Y-%m-%d&quot; time))) (format-time-string &quot;posted on %Y-%m-%d&quot; time)))
(defun my/format-date-subtitle (file project) (defun my/format-date-subtitle (file project)
@ -618,7 +618,7 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(org-element-map (plist-get info :parse-tree) &apos;keyword (org-element-map (plist-get info :parse-tree) &apos;keyword
(lambda (keyword) (lambda (keyword)
(when (string= (org-element-property :key keyword) property) (when (string= (org-element-property :key keyword) property)
(org-element-property :value keyword))) (org-element-property :value keyword)))
nil t)) nil t))
(defun my/org-has-src-blocks-p (info) (defun my/org-has-src-blocks-p (info)
@ -632,8 +632,8 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(let ((output-string input-string)) (let ((output-string input-string))
(dolist (pair my/lang-substitution-map) (dolist (pair my/lang-substitution-map)
(let ((old (regexp-quote (car pair))) (let ((old (regexp-quote (car pair)))
(new (cdr pair))) (new (cdr pair)))
(setq output-string (replace-regexp-in-string old new output-string)))) (setq output-string (replace-regexp-in-string old new output-string))))
output-string)) output-string))
;; ;;
@ -650,51 +650,51 @@ A neat thing I've implemented is a way to filter out unpublished posts using a <
(setq org-publish-project-alist (setq org-publish-project-alist
(list (list
(list &quot;blog-index&quot; (list &quot;blog-index&quot;
:base-directory my/blog-src-path :base-directory my/blog-src-path
:base-extension &quot;org&quot; :base-extension &quot;org&quot;
:recursive t :recursive t
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:publishing-function &apos;my/publish-blog-index) :publishing-function &apos;my/publish-blog-index)
(list &quot;static&quot; (list &quot;static&quot;
:base-directory my/blog-src-path :base-directory my/blog-src-path
:base-extension &quot;css\\|js\\|png\\|jpg\\|jpeg\\|gif\\|pdf\\|ico\\|txt&quot; :base-extension &quot;css\\|js\\|png\\|jpg\\|jpeg\\|gif\\|pdf\\|ico\\|txt&quot;
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:recursive t :recursive t
:publishing-function &apos;org-publish-attachment :publishing-function &apos;org-publish-attachment
) )
(list &quot;blog&quot; (list &quot;blog&quot;
:recursive t :recursive t
:base-directory my/blog-src-path :base-directory my/blog-src-path
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:publishing-function &apos;my/publish-to-html :publishing-function &apos;my/publish-to-html
:html-html5-fancy t :html-html5-fancy t
:htmlized-source t :htmlized-source t
:with-author nil :with-author nil
:with-creator t :with-creator t
:with-toc t :with-toc t
:section-numbers nil :section-numbers nil
:time-stamp-file nil :time-stamp-file nil
) )
(list &quot;blog-rss&quot; (list &quot;blog-rss&quot;
:author &quot;Alex M&quot; :author &quot;Alex M&quot;
:email &quot;iam@fidonode.me&quot; :email &quot;iam@fidonode.me&quot;
:base-directory my/blog-src-path :base-directory my/blog-src-path
:base-extension &quot;org&quot; :base-extension &quot;org&quot;
:recursive t :recursive t
:exclude (regexp-opt &apos;(&quot;rss.org&quot; &quot;index.org&quot; &quot;404.org&quot; &quot;posts.org&quot;)) :exclude (regexp-opt &apos;(&quot;rss.org&quot; &quot;index.org&quot; &quot;404.org&quot; &quot;posts.org&quot;))
:publishing-function &apos;my/publish-to-rss :publishing-function &apos;my/publish-to-rss
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:rss-extension &quot;xml&quot; :rss-extension &quot;xml&quot;
:html-link-home my/url :html-link-home my/url
:html-link-use-abs-url t :html-link-use-abs-url t
:html-link-org-files-as-html t :html-link-org-files-as-html t
:auto-sitemap t :auto-sitemap t
:sitemap-filename &quot;rss.org&quot; :sitemap-filename &quot;rss.org&quot;
:sitemap-title &quot;rss&quot; :sitemap-title &quot;rss&quot;
:sitemap-style &apos;list :sitemap-style &apos;list
:sitemap-sort-files &apos;anti-chronologically :sitemap-sort-files &apos;anti-chronologically
:sitemap-function &apos;my/format-rss-feed :sitemap-function &apos;my/format-rss-feed
:sitemap-format-entry &apos;my/format-rss-feed-entry) :sitemap-format-entry &apos;my/format-rss-feed-entry)
)) ))

View File

@ -1,34 +1,34 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Use highlight.js for code syntax highlighting"/><meta property="og:description" content="Use highlight.js for code syntax highlighting"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/improve_code_blocks.org.png"/><meta property="og:title" content="Improve code blocks"/><meta name="twitter:description" content="Use highlight.js for code syntax highlighting"/><meta name="twitter:title" content="Improve code blocks"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/improve_code_blocks.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Improve code blocks</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Improve code blocks</h1><p>Use highlight.js for code syntax highlighting</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li><li><mark><a href="/tags/@elisp.html" class="secondary">@elisp</a></mark></li><li><mark><a href="/tags/@highlightjs.html" class="secondary">@highlightjs</a></mark></li></ul></nav></hgroup><div id="table-of-contents"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Use highlight.js for code syntax highlighting"/><meta property="og:description" content="Use highlight.js for code syntax highlighting"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/improve_code_blocks.org.png"/><meta property="og:title" content="Improve code blocks"/><meta name="twitter:description" content="Use highlight.js for code syntax highlighting"/><meta name="twitter:title" content="Improve code blocks"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/improve_code_blocks.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Improve code blocks</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Improve code blocks</h1><p>Use highlight.js for code syntax highlighting</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li><li><mark><a href="/tags/@elisp.html" class="secondary">@elisp</a></mark></li><li><mark><a href="/tags/@highlightjs.html" class="secondary">@highlightjs</a></mark></li></ul></nav></hgroup><div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2> <h2>Table of Contents</h2>
<div id="text-table-of-contents"> <div id="text-table-of-contents" role="doc-toc">
<ul> <ul>
<li><a href="#orgf7f6f93">What is the problem with default highlighting?</a></li> <li><a href="#org3567b5d">What is the problem with default highlighting?</a></li>
<li><a href="#org95957be">Highlight.js</a> <li><a href="#org1bd0b7d">Highlight.js</a>
<ul> <ul>
<li><a href="#orgeaa2164">Change code block template</a></li> <li><a href="#org0ce0a2e">Change code block template</a></li>
<li><a href="#org0243f67">Plug Highlight.js</a></li> <li><a href="#org4a7b320">Plug Highlight.js</a></li>
<li><a href="#org504e851">Respect prefers-color-scheme</a></li> <li><a href="#orgcb4c7b7">Respect prefers-color-scheme</a></li>
</ul> </ul>
</li> </li>
<li><a href="#orgca490d8">Whole config</a></li> <li><a href="#org9e61d2d">Whole config</a></li>
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-orgf7f6f93" class="outline-2"> <div id="outline-container-org3567b5d" class="outline-2">
<h2 id="orgf7f6f93">What is the problem with default highlighting?</h2> <h2 id="org3567b5d">What is the problem with default highlighting?</h2>
<div class="outline-text-2" id="text-orgf7f6f93"> <div class="outline-text-2" id="text-org3567b5d">
<p> <p>
Htmlize works poorly with headless publishing. It lacks extensibility, including features like line numbers, a copy button, and the ability to highlight predefined parts of the code. Htmlize works poorly with headless publishing. It lacks extensibility, including features like line numbers, a copy button, and the ability to highlight predefined parts of the code.
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org95957be" class="outline-2"> <div id="outline-container-org1bd0b7d" class="outline-2">
<h2 id="org95957be">Highlight.js</h2> <h2 id="org1bd0b7d">Highlight.js</h2>
<div class="outline-text-2" id="text-org95957be"> <div class="outline-text-2" id="text-org1bd0b7d">
</div> </div>
<div id="outline-container-orgeaa2164" class="outline-3"> <div id="outline-container-org0ce0a2e" class="outline-3">
<h3 id="orgeaa2164">Change code block template</h3> <h3 id="org0ce0a2e">Change code block template</h3>
<div class="outline-text-3" id="text-orgeaa2164"> <div class="outline-text-3" id="text-org0ce0a2e">
<p> <p>
We need to make small changes in how code blocks are rendered. By default, Org Export exports code blocks as <code>&lt;pre&gt;&lt;/pre&gt;</code>. For Highlight.js, we need <code>&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;</code>. Additionally, we need to set the correct language name in the class attribute. Since Highlight.js does not support <code>elisp</code>, I rewrite it to regular <code>lisp</code> using the <code>my/replace-substring</code> function. We need to make small changes in how code blocks are rendered. By default, Org Export exports code blocks as <code>&lt;pre&gt;&lt;/pre&gt;</code>. For Highlight.js, we need <code>&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;</code>. Additionally, we need to set the correct language name in the class attribute. Since Highlight.js does not support <code>elisp</code>, I rewrite it to regular <code>lisp</code> using the <code>my/replace-substring</code> function.
</p> </p>
@ -40,38 +40,38 @@ We need to make small changes in how code blocks are rendered. By default, Org E
(let ((output-string input-string)) (let ((output-string input-string))
(dolist (pair my/lang-substitution-map) (dolist (pair my/lang-substitution-map)
(let ((old (regexp-quote (car pair))) (let ((old (regexp-quote (car pair)))
(new (cdr pair))) (new (cdr pair)))
(setq output-string (replace-regexp-in-string old new output-string)))) (setq output-string (replace-regexp-in-string old new output-string))))
output-string)) output-string))
(defun my/src-block (src-block contents info) (defun my/src-block (src-block contents info)
&quot;Translate SRC-BLOCK element into HTML. &quot;Translate SRC-BLOCK element into HTML.
CONTENTS is nil. INFO is a plist holding contextual information.&quot; CONTENTS is nil. INFO is a plist holding contextual information.&quot;
(let* ( (let* (
(org-language (format &quot;language-%s&quot; (org-element-property :language src-block))) (org-language (format &quot;language-%s&quot; (org-element-property :language src-block)))
(language (my/replace-substrings org-language)) (language (my/replace-substrings org-language))
(code (org-element-property :value src-block))) (code (org-element-property :value src-block)))
(esxml-to-xml (esxml-to-xml
`(pre () `(pre ()
(code ((class . ,language)) (code ((class . ,language))
,(org-html-encode-plain-text code) ,(org-html-encode-plain-text code)
)) ))
) )
) )
) )
(org-export-define-derived-backend &apos;my-html &apos;html (org-export-define-derived-backend &apos;my-html &apos;html
:translate-alist &apos;( :translate-alist &apos;(
(template . my/template) (template . my/template)
(src-block . my/src-block) (src-block . my/src-block)
)) ))
</code></pre> </code></pre>
</div> </div>
</div> </div>
<div id="outline-container-org0243f67" class="outline-3"> <div id="outline-container-org4a7b320" class="outline-3">
<h3 id="org0243f67">Plug Highlight.js</h3> <h3 id="org4a7b320">Plug Highlight.js</h3>
<div class="outline-text-3" id="text-org0243f67"> <div class="outline-text-3" id="text-org4a7b320">
<p> <p>
I do not want to load Highlight.js on every page, so I need to check if the initial Org file contains code blocks. Depending on this, we will render the part of the tree with JavaScript or not. I do not want to load Highlight.js on every page, so I need to check if the initial Org file contains code blocks. Depending on this, we will render the part of the tree with JavaScript or not.
</p> </p>
@ -84,20 +84,20 @@ I do not want to load Highlight.js on every page, so I need to check if the init
(defun my/template (contents info) (defun my/template (contents info)
(let* ((title-str (org-export-data (plist-get info :title) info)) (let* ((title-str (org-export-data (plist-get info :title) info))
... ...
(has-src-blocks (my/org-has-src-blocks-p info))) (has-src-blocks (my/org-has-src-blocks-p info)))
... ...
(script ((defer . &quot;true&quot;) (src . &quot;https://umami.dokutsu.xyz/script.js&quot;) (data-website-id . &quot;d52d9af1-0c7d-4531-84c6-0b9c2850011f&quot;)) ()) (script ((defer . &quot;true&quot;) (src . &quot;https://umami.dokutsu.xyz/script.js&quot;) (data-website-id . &quot;d52d9af1-0c7d-4531-84c6-0b9c2850011f&quot;)) ())
,(when has-src-blocks ,(when has-src-blocks
`(nil () `(nil ()
(link ((id . &quot;highlight-theme&quot;) (rel . &quot;stylesheet&quot;) (type . &quot;text/css&quot;))) (link ((id . &quot;highlight-theme&quot;) (rel . &quot;stylesheet&quot;) (type . &quot;text/css&quot;)))
(script ((src . &quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js&quot;)) ()) (script ((src . &quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js&quot;)) ())
(script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js&quot;)) ()) (script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js&quot;)) ())
(script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js&quot;)) ()) (script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js&quot;)) ())
(script ((src . &quot;/resources/js/theme-selector.js&quot;)) ()) (script ((src . &quot;/resources/js/theme-selector.js&quot;)) ())
) )
) )
(title () ,title-str) (title () ,title-str)
@ -105,9 +105,9 @@ I do not want to load Highlight.js on every page, so I need to check if the init
</code></pre> </code></pre>
</div> </div>
</div> </div>
<div id="outline-container-org504e851" class="outline-3"> <div id="outline-container-orgcb4c7b7" class="outline-3">
<h3 id="org504e851">Respect prefers-color-scheme</h3> <h3 id="orgcb4c7b7">Respect prefers-color-scheme</h3>
<div class="outline-text-3" id="text-org504e851"> <div class="outline-text-3" id="text-orgcb4c7b7">
<p> <p>
Additionally, I think it's a good idea to respect the <code>prefers-color-scheme</code> property of the user's browser. We can switch CSS files based on this property. We should also subscribe to changes in this property to handle the edge case when it switches while reading the page. Additionally, I think it's a good idea to respect the <code>prefers-color-scheme</code> property of the user's browser. We can switch CSS files based on this property. We should also subscribe to changes in this property to handle the edge case when it switches while reading the page.
</p> </p>
@ -142,9 +142,9 @@ window
</div> </div>
</div> </div>
<div id="outline-container-orgca490d8" class="outline-2"> <div id="outline-container-org9e61d2d" class="outline-2">
<h2 id="orgca490d8">Whole config</h2> <h2 id="org9e61d2d">Whole config</h2>
<div class="outline-text-2" id="text-orgca490d8"> <div class="outline-text-2" id="text-org9e61d2d">
<p> <p>
In between posts I've switched from <code>sxml</code> to <code>esxml</code> so here is the current config. In between posts I've switched from <code>sxml</code> to <code>esxml</code> so here is the current config.
</p> </p>
@ -157,7 +157,7 @@ In between posts I've switched from <code>sxml</code> to <code>esxml</code> so h
(normal-top-level-add-subdirs-to-load-path)) (normal-top-level-add-subdirs-to-load-path))
(add-to-list &apos;custom-theme-load-path (add-to-list &apos;custom-theme-load-path
(concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/doom-themes&quot;)) (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/doom-themes&quot;))
(add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/base16-theme&quot;)) (add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/base16-theme&quot;))
(add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/moe-theme&quot;)) (add-to-list &apos;custom-theme-load-path (concat &quot;~/.config/emacs/.local/straight/build-&quot; emacs-version &quot;/moe-theme&quot;))
@ -189,28 +189,28 @@ In between posts I've switched from <code>sxml</code> to <code>esxml</code> so h
`(footer ((class . &quot;footer&quot;)) `(footer ((class . &quot;footer&quot;))
(hr () ) (hr () )
(small () (small ()
(p () &quot;Alex Mikhailov&quot;) (p () &quot;Alex Mikhailov&quot;)
(p () &quot;Built with: &quot; (p () &quot;Built with: &quot;
(a ((href . &quot;https://www.gnu.org/software/emacs/&quot;)) &quot;GNU Emacs&quot;) &quot; &quot; (a ((href . &quot;https://www.gnu.org/software/emacs/&quot;)) &quot;GNU Emacs&quot;) &quot; &quot;
(a ((href . &quot;https://orgmode.org/&quot;)) &quot;Org Mode&quot;) &quot; &quot; (a ((href . &quot;https://orgmode.org/&quot;)) &quot;Org Mode&quot;) &quot; &quot;
(a ((href . &quot;https://picocss.com/&quot;)) &quot;picocss&quot;) (a ((href . &quot;https://picocss.com/&quot;)) &quot;picocss&quot;)
) )
) )
)) ))
(defun my/header (info) (defun my/header (info)
(let ((title-str (org-export-data (plist-get info :title) info))) (let ((title-str (org-export-data (plist-get info :title) info)))
`(header ((class . &quot;header&quot;)) `(header ((class . &quot;header&quot;))
(nav () (nav ()
(ul () (ul ()
(li () (li ()
(strong () ,title-str))) (strong () ,title-str)))
(ul () (ul ()
(li () (a ((href . &quot;/index.html&quot;)) &quot;About&quot;)) (li () (a ((href . &quot;/index.html&quot;)) &quot;About&quot;))
(li () (a ((href . &quot;/posts.html&quot;)) &quot;Blog&quot;)) (li () (a ((href . &quot;/posts.html&quot;)) &quot;Blog&quot;))
(li () (a ((href . &quot;/rss.xml&quot;)) &quot;RSS&quot;)) (li () (a ((href . &quot;/rss.xml&quot;)) &quot;RSS&quot;))
) )
)) ))
) )
) )
@ -218,14 +218,14 @@ In between posts I've switched from <code>sxml</code> to <code>esxml</code> so h
&quot;Translate SRC-BLOCK element into HTML. &quot;Translate SRC-BLOCK element into HTML.
CONTENTS is nil. INFO is a plist holding contextual information.&quot; CONTENTS is nil. INFO is a plist holding contextual information.&quot;
(let* ( (let* (
(org-language (format &quot;language-%s&quot; (org-element-property :language src-block))) (org-language (format &quot;language-%s&quot; (org-element-property :language src-block)))
(language (my/replace-substrings org-language)) (language (my/replace-substrings org-language))
(code (org-element-property :value src-block))) (code (org-element-property :value src-block)))
(esxml-to-xml (esxml-to-xml
`(pre () `(pre ()
(code ((class . ,language)) (code ((class . ,language))
,(org-html-encode-plain-text code) ,(org-html-encode-plain-text code)
)) ))
) )
) )
) )
@ -234,12 +234,12 @@ CONTENTS is nil. INFO is a plist holding contextual information.&quot;
(defun my/template (contents info) (defun my/template (contents info)
(let* ((title-str (org-export-data (plist-get info :title) info)) (let* ((title-str (org-export-data (plist-get info :title) info))
(description-str (org-export-data (plist-get info :description) info)) (description-str (org-export-data (plist-get info :description) info))
(file-path-str (org-export-data (plist-get info :input-file) info)) (file-path-str (org-export-data (plist-get info :input-file) info))
(base-directory-str (org-export-data (plist-get info :base-directory) info)) (base-directory-str (org-export-data (plist-get info :base-directory) info))
(file-name-str (file-relative-name file-path-str (format &quot;%s/%s&quot; script-directory base-directory-str))) (file-name-str (file-relative-name file-path-str (format &quot;%s/%s&quot; script-directory base-directory-str)))
(img-link-str (format &quot;%s/resources/images/%s.png&quot; my/url file-name-str)) (img-link-str (format &quot;%s/resources/images/%s.png&quot; my/url file-name-str))
(has-src-blocks (my/org-has-src-blocks-p info))) (has-src-blocks (my/org-has-src-blocks-p info)))
(set-text-properties 0 (length title-str) nil title-str) (set-text-properties 0 (length title-str) nil title-str)
(set-text-properties 0 (length description-str) nil description-str) (set-text-properties 0 (length description-str) nil description-str)
@ -249,57 +249,57 @@ CONTENTS is nil. INFO is a plist holding contextual information.&quot;
&quot;&amp;lt;!DOCTYPE html&amp;gt;&quot; &quot;&amp;lt;!DOCTYPE html&amp;gt;&quot;
(esxml-to-xml (esxml-to-xml
`(html ((lang . &quot;en&quot;)) `(html ((lang . &quot;en&quot;))
(head () (head ()
(meta ((charset . &quot;utf-8&quot;))) (meta ((charset . &quot;utf-8&quot;)))
(meta ((author . &quot;Alex Mikhailov&quot;))) (meta ((author . &quot;Alex Mikhailov&quot;)))
(meta ((name . &quot;viewport&quot;) (meta ((name . &quot;viewport&quot;)
(content . &quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;))) (content . &quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;)))
(meta ((name . &quot;color-scheme&quot;) (content . &quot;light dark&quot;))) (meta ((name . &quot;color-scheme&quot;) (content . &quot;light dark&quot;)))
(meta ((http-equiv . &quot;content-language&quot;) (content . &quot;en-us&quot;))) (meta ((http-equiv . &quot;content-language&quot;) (content . &quot;en-us&quot;)))
;; OG block ;; OG block
;; &quot;Personal page with a blog about my technical adventures&quot; ;; &quot;Personal page with a blog about my technical adventures&quot;
(meta ((name . &quot;description&quot;) (content . ,description-str))) (meta ((name . &quot;description&quot;) (content . ,description-str)))
(meta ((name . &quot;og:description&quot;) (content . ,description-str))) (meta ((name . &quot;og:description&quot;) (content . ,description-str)))
(meta ((name . &quot;twitter:description&quot;) (content . ,description-str))) (meta ((name . &quot;twitter:description&quot;) (content . ,description-str)))
(meta ((name . &quot;og:image&quot;) (content . ,img-link-str))) (meta ((name . &quot;og:image&quot;) (content . ,img-link-str)))
(meta ((name . &quot;twitter:image&quot;) (content . ,img-link-str))) (meta ((name . &quot;twitter:image&quot;) (content . ,img-link-str)))
(meta ((name . &quot;og:title&quot;) (content . ,title-str))) (meta ((name . &quot;og:title&quot;) (content . ,title-str)))
(meta ((name . &quot;twitter:title&quot;) (content . ,title-str))) (meta ((name . &quot;twitter:title&quot;) (content . ,title-str)))
(meta ((name . &quot;twitter:card&quot;) (content . &quot;summary_large_image&quot;))) (meta ((name . &quot;twitter:card&quot;) (content . &quot;summary_large_image&quot;)))
(link ((rel . &quot;icon&quot;) (type . &quot;image/x-icon&quot;) (href . &quot;/resources/favicon.ico&quot;))) (link ((rel . &quot;icon&quot;) (type . &quot;image/x-icon&quot;) (href . &quot;/resources/favicon.ico&quot;)))
(link ((rel . &quot;stylesheet&quot;) (type . &quot;text/css&quot;) (href . &quot;/resources/css/pico.sand.min.css&quot;))) (link ((rel . &quot;stylesheet&quot;) (type . &quot;text/css&quot;) (href . &quot;/resources/css/pico.sand.min.css&quot;)))
(script ((defer . &quot;true&quot;) (src . &quot;https://umami.dokutsu.xyz/script.js&quot;) (data-website-id . &quot;d52d9af1-0c7d-4531-84c6-0b9c2850011f&quot;)) ()) (script ((defer . &quot;true&quot;) (src . &quot;https://umami.dokutsu.xyz/script.js&quot;) (data-website-id . &quot;d52d9af1-0c7d-4531-84c6-0b9c2850011f&quot;)) ())
,(when has-src-blocks ,(when has-src-blocks
`(nil () `(nil ()
(link ((id . &quot;highlight-theme&quot;) (rel . &quot;stylesheet&quot;) (type . &quot;text/css&quot;))) (link ((id . &quot;highlight-theme&quot;) (rel . &quot;stylesheet&quot;) (type . &quot;text/css&quot;)))
(script ((src . &quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js&quot;)) ()) (script ((src . &quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js&quot;)) ())
(script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js&quot;)) ()) (script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js&quot;)) ())
(script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js&quot;)) ()) (script ((src . &quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js&quot;)) ())
(script ((src . &quot;/resources/js/theme-selector.js&quot;)) ()) (script ((src . &quot;/resources/js/theme-selector.js&quot;)) ())
) )
) )
(title () ,title-str) (title () ,title-str)
) )
(body () (body ()
(main ((class . &quot;container&quot;)) (main ((class . &quot;container&quot;))
,(my/header info) ,(my/header info)
(raw-string ,contents) (raw-string ,contents)
,(my/footer info) ,(my/footer info)
) )
)) ))
)) ))
)) ))
(org-export-define-derived-backend &apos;my-html &apos;html (org-export-define-derived-backend &apos;my-html &apos;html
:translate-alist &apos;( :translate-alist &apos;(
(template . my/template) (template . my/template)
(src-block . my/src-block) (src-block . my/src-block)
)) ))
(defun my/publish-to-html (plist filename pub-dir) (defun my/publish-to-html (plist filename pub-dir)
&quot;Publish an Org file to HTML using the custom backend.&quot; &quot;Publish an Org file to HTML using the custom backend.&quot;
@ -312,31 +312,31 @@ CONTENTS is nil. INFO is a plist holding contextual information.&quot;
ENTRY is a file name. STYLE is either &apos;list&apos; or &apos;tree&apos;. ENTRY is a file name. STYLE is either &apos;list&apos; or &apos;tree&apos;.
PROJECT is the current project.&quot; PROJECT is the current project.&quot;
(cond ((not (directory-name-p entry)) (cond ((not (directory-name-p entry))
(let* ((file (org-publish--expand-file-name entry project)) (let* ((file (org-publish--expand-file-name entry project))
(title (org-publish-find-title entry project)) (title (org-publish-find-title entry project))
(date (format-time-string &quot;%Y-%m-%d&quot; (org-publish-find-date entry project))) (date (format-time-string &quot;%Y-%m-%d&quot; (org-publish-find-date entry project)))
(link (concat (file-name-sans-extension entry) &quot;.html&quot;))) (link (concat (file-name-sans-extension entry) &quot;.html&quot;)))
(with-temp-buffer (with-temp-buffer
(org-mode) (org-mode)
(insert (format &quot;* [[file:%s][%s]]\n&quot; file title)) (insert (format &quot;* [[file:%s][%s]]\n&quot; file title))
(org-set-property &quot;RSS_PERMALINK&quot; link) (org-set-property &quot;RSS_PERMALINK&quot; link)
(org-set-property &quot;RSS_TITLE&quot; title) (org-set-property &quot;RSS_TITLE&quot; title)
(org-set-property &quot;PUBDATE&quot; date) (org-set-property &quot;PUBDATE&quot; date)
(let ((first-two-lines (with-temp-buffer (let ((first-two-lines (with-temp-buffer
(insert-file-contents file) (insert-file-contents file)
(buffer-substring-no-properties (buffer-substring-no-properties
(point-min) (point-min)
(progn (forward-line 2) (point)))))) (progn (forward-line 2) (point))))))
(if (string-suffix-p &quot;\n&quot; first-two-lines) (if (string-suffix-p &quot;\n&quot; first-two-lines)
(setq first-two-lines (substring first-two-lines 0 -1))) (setq first-two-lines (substring first-two-lines 0 -1)))
(insert first-two-lines)) (insert first-two-lines))
(goto-char (point-max)) (goto-char (point-max))
(insert &quot;...&quot;) (insert &quot;...&quot;)
(buffer-string)))) (buffer-string))))
((eq style &apos;tree) ((eq style &apos;tree)
;; Return only last subdir. ;; Return only last subdir.
(file-name-nondirectory (directory-file-name entry))) (file-name-nondirectory (directory-file-name entry)))
(t entry))) (t entry)))
(defun my/format-rss-feed (title list) (defun my/format-rss-feed (title list)
&quot;Generate RSS feed, as a string. &quot;Generate RSS feed, as a string.
@ -344,8 +344,8 @@ TITLE is the title of the RSS feed. LIST is an internal
representation for the files to include, as returned by representation for the files to include, as returned by
`org-list-to-lisp&apos;. PROJECT is the current project.&quot; `org-list-to-lisp&apos;. PROJECT is the current project.&quot;
(concat &quot;#+TITLE: &quot; title &quot;\n&quot; (concat &quot;#+TITLE: &quot; title &quot;\n&quot;
&quot;#+STARTUP: showall \n\n&quot; &quot;#+STARTUP: showall \n\n&quot;
(org-list-to-subtree list 1 &apos;(:icount &quot;&quot; :istart &quot;&quot;)))) (org-list-to-subtree list 1 &apos;(:icount &quot;&quot; :istart &quot;&quot;))))
(defun my/publish-to-rss (plist filename pub-dir) (defun my/publish-to-rss (plist filename pub-dir)
&quot;Publish RSS with PLIST, only when FILENAME is &apos;rss.org&apos;. &quot;Publish RSS with PLIST, only when FILENAME is &apos;rss.org&apos;.
@ -387,8 +387,8 @@ PUB-DIR is when the output will be placed.&quot;
(let ((output-string input-string)) (let ((output-string input-string))
(dolist (pair my/lang-substitution-map) (dolist (pair my/lang-substitution-map)
(let ((old (regexp-quote (car pair))) (let ((old (regexp-quote (car pair)))
(new (cdr pair))) (new (cdr pair)))
(setq output-string (replace-regexp-in-string old new output-string)))) (setq output-string (replace-regexp-in-string old new output-string))))
output-string)) output-string))
;; ;;
@ -405,45 +405,45 @@ PUB-DIR is when the output will be placed.&quot;
(setq org-publish-project-alist (setq org-publish-project-alist
(list (list
(list &quot;static&quot; (list &quot;static&quot;
:base-directory my/blog-src-path :base-directory my/blog-src-path
:base-extension &quot;css\\|js\\|png\\|jpg\\|jpeg\\|gif\\|pdf\\|ico\\|txt&quot; :base-extension &quot;css\\|js\\|png\\|jpg\\|jpeg\\|gif\\|pdf\\|ico\\|txt&quot;
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:recursive t :recursive t
:publishing-function &apos;org-publish-attachment :publishing-function &apos;org-publish-attachment
) )
(list &quot;blog&quot; (list &quot;blog&quot;
:recursive t :recursive t
:base-directory my/blog-src-path :base-directory my/blog-src-path
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:publishing-function &apos;my/publish-to-html :publishing-function &apos;my/publish-to-html
:html-html5-fancy t :html-html5-fancy t
:htmlized-source t :htmlized-source t
:with-author nil :with-author nil
:with-creator t :with-creator t
:with-toc t :with-toc t
:section-numbers nil :section-numbers nil
:time-stamp-file nil :time-stamp-file nil
) )
(list &quot;blog-rss&quot; (list &quot;blog-rss&quot;
:author &quot;Alex M&quot; :author &quot;Alex M&quot;
:email &quot;iam@fidonode.me&quot; :email &quot;iam@fidonode.me&quot;
:base-directory my/blog-src-path :base-directory my/blog-src-path
:base-extension &quot;org&quot; :base-extension &quot;org&quot;
:recursive t :recursive t
:exclude (regexp-opt &apos;(&quot;rss.org&quot; &quot;index.org&quot; &quot;404.org&quot; &quot;posts.org&quot;)) :exclude (regexp-opt &apos;(&quot;rss.org&quot; &quot;index.org&quot; &quot;404.org&quot; &quot;posts.org&quot;))
:publishing-function &apos;my/publish-to-rss :publishing-function &apos;my/publish-to-rss
:publishing-directory my/web-export-path :publishing-directory my/web-export-path
:rss-extension &quot;xml&quot; :rss-extension &quot;xml&quot;
:html-link-home my/url :html-link-home my/url
:html-link-use-abs-url t :html-link-use-abs-url t
:html-link-org-files-as-html t :html-link-org-files-as-html t
:auto-sitemap t :auto-sitemap t
:sitemap-filename &quot;rss.org&quot; :sitemap-filename &quot;rss.org&quot;
:sitemap-title &quot;rss&quot; :sitemap-title &quot;rss&quot;
:sitemap-style &apos;list :sitemap-style &apos;list
:sitemap-sort-files &apos;anti-chronologically :sitemap-sort-files &apos;anti-chronologically
:sitemap-function &apos;my/format-rss-feed :sitemap-function &apos;my/format-rss-feed
:sitemap-format-entry &apos;my/format-rss-feed-entry) :sitemap-format-entry &apos;my/format-rss-feed-entry)
)) ))

View File

@ -1,59 +1,59 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Blog post about my keyboards"/><meta property="og:description" content="Blog post about my keyboards"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/keeb.org.png"/><meta property="og:title" content="My keyboard journey"/><meta name="twitter:description" content="Blog post about my keyboards"/><meta name="twitter:title" content="My keyboard journey"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/keeb.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>My keyboard journey</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>My keyboard journey</h1><p>Blog post about my keyboards</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@keeb.html" class="secondary">@keeb</a></mark></li><li><mark><a href="/tags/@diy.html" class="secondary">@diy</a></mark></li></ul></nav></hgroup><div id="table-of-contents"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Blog post about my keyboards"/><meta property="og:description" content="Blog post about my keyboards"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/keeb.org.png"/><meta property="og:title" content="My keyboard journey"/><meta name="twitter:description" content="Blog post about my keyboards"/><meta name="twitter:title" content="My keyboard journey"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/keeb.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>My keyboard journey</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>My keyboard journey</h1><p>Blog post about my keyboards</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@keeb.html" class="secondary">@keeb</a></mark></li><li><mark><a href="/tags/@diy.html" class="secondary">@diy</a></mark></li></ul></nav></hgroup><div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2> <h2>Table of Contents</h2>
<div id="text-table-of-contents"> <div id="text-table-of-contents" role="doc-toc">
<ul> <ul>
<li><a href="#orge7c0367">My end-game (at least I hope) keyboard</a> <li><a href="#orgc1d02ca">My end-game (at least I hope) keyboard</a>
<ul> <ul>
<li><a href="#orga39c824">Keebs path</a> <li><a href="#org80c6fc0">Keebs path</a>
<ul> <ul>
<li><a href="#orgb20e1c0">Dactyl manuform</a></li> <li><a href="#orgf25fdc9">Dactyl manuform</a></li>
<li><a href="#org6970fcb">Moonlander</a></li> <li><a href="#org0f8e531">Moonlander</a></li>
<li><a href="#orgef1b2f6">Custom Corne</a></li> <li><a href="#orgd206bf9">Custom Corne</a></li>
<li><a href="#org0414f11">Dactyl manuform again</a></li> <li><a href="#org9e97c61">Dactyl manuform again</a></li>
</ul> </ul>
</li> </li>
<li><a href="#org7189206">Hardware</a> <li><a href="#org0e00f11">Hardware</a>
<ul> <ul>
<li><a href="#org4898606">Body</a></li> <li><a href="#orgddb041c">Body</a></li>
<li><a href="#org615e880">Switches and caps</a></li> <li><a href="#orge6d28f1">Switches and caps</a></li>
<li><a href="#orgdafbd11">Controllers</a></li> <li><a href="#org324aa24">Controllers</a></li>
<li><a href="#org7c42229">Amoeba things</a></li> <li><a href="#org399d344">Amoeba things</a></li>
</ul> </ul>
</li> </li>
<li><a href="#orgab34fe9">Software</a> <li><a href="#org62edd8c">Software</a>
<ul> <ul>
<li><a href="#orgbe03b8f">Plain default - QMK</a></li> <li><a href="#org90dd15d">Plain default - QMK</a></li>
<li><a href="#orge8f2d0c">Make own layout</a></li> <li><a href="#orge4b81a7">Make own layout</a></li>
</ul> </ul>
</li> </li>
<li><a href="#org71af41b">Whats next?</a></li> <li><a href="#org0af2266">Whats next?</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-orge7c0367" class="outline-2"> <div id="outline-container-orgc1d02ca" class="outline-2">
<h2 id="orge7c0367">My end-game (at least I hope) keyboard</h2> <h2 id="orgc1d02ca">My end-game (at least I hope) keyboard</h2>
<div class="outline-text-2" id="text-orge7c0367"> <div class="outline-text-2" id="text-orgc1d02ca">
</div> </div>
<div id="outline-container-orga39c824" class="outline-3"> <div id="outline-container-org80c6fc0" class="outline-3">
<h3 id="orga39c824">Keebs path</h3> <h3 id="org80c6fc0">Keebs path</h3>
<div class="outline-text-3" id="text-orga39c824"> <div class="outline-text-3" id="text-org80c6fc0">
<p> <p>
Sometimes I think about the long journey I've made with keebs. In childhood, I had decent membrane keyboards, most of which had an ergonomic profile like the MS. Not sure if it somehow affected my taste because I started my career with the simplest, cheapest board and typed countless lines of code on such keebs. Then I heard about clickity-clack mechanical keyboards and decided to try one. It was a simple Chinese keeb with a thick metal body, double-shot caps, and Cherry Brown switches. A decent thing to annoy everyone around you. I think this purchase marked my dive into mech keebs Sometimes I think about the long journey I've made with keebs. In childhood, I had decent membrane keyboards, most of which had an ergonomic profile like the MS. Not sure if it somehow affected my taste because I started my career with the simplest, cheapest board and typed countless lines of code on such keebs. Then I heard about clickity-clack mechanical keyboards and decided to try one. It was a simple Chinese keeb with a thick metal body, double-shot caps, and Cherry Brown switches. A decent thing to annoy everyone around you. I think this purchase marked my dive into mech keebs
I'm not a geeky aficionado who thinks you can fix everything with a new keyboard, but I built a couple of them. I hope I've finally built the last one for quite some time. I'm not a geeky aficionado who thinks you can fix everything with a new keyboard, but I built a couple of them. I hope I've finally built the last one for quite some time.
</p> </p>
</div> </div>
<div id="outline-container-orgb20e1c0" class="outline-4"> <div id="outline-container-orgf25fdc9" class="outline-4">
<h4 id="orgb20e1c0">Dactyl manuform</h4> <h4 id="orgf25fdc9">Dactyl manuform</h4>
<div class="outline-text-4" id="text-orgb20e1c0"> <div class="outline-text-4" id="text-orgf25fdc9">
<p> <p>
Almost all of the time, I struggle with my maximalism. So I decided to build the ultimate mechanical ergonomic split keyboard and chose the Dactyl Manuform. Sounds like a crazy idea. Zero experience with QMK, zero experience with hand-wired keyboards, and zero experience in 3D printing. Almost all of the time, I struggle with my maximalism. So I decided to build the ultimate mechanical ergonomic split keyboard and chose the Dactyl Manuform. Sounds like a crazy idea. Zero experience with QMK, zero experience with hand-wired keyboards, and zero experience in 3D printing.
The last problem was the easiest one; I just asked my friend to print the bodies from PETG polymer, and Bob's your uncle. I got two pieces of rough-layered plastic with all the support structures. God, it was a nightmare to clean these prints from supports and small artifacts, but I was happy. The last problem was the easiest one; I just asked my friend to print the bodies from PETG polymer, and Bob's your uncle. I got two pieces of rough-layered plastic with all the support structures. God, it was a nightmare to clean these prints from supports and small artifacts, but I was happy.
</p> </p>
<div class="figure"> <div id="org55b754e" class="figure">
<p><img src="../resources/images/keeb/dactyl-manuform-6.jpg" alt="dactyl-manuform-6.jpg" /> <p><img src="../resources/images/keeb/dactyl-manuform-6.jpg" alt="dactyl-manuform-6.jpg" />
</p> </p>
</div> </div>
@ -63,25 +63,25 @@ I ordered a set of Kailh Brown switches, cheap no-name DSA caps, two controllers
</p> </p>
<div class="figure"> <div id="org4f2ca31" class="figure">
<p><img src="../resources/images/keeb/dactyl-manuform-5.jpg" alt="dactyl-manuform-5.jpg" /> <p><img src="../resources/images/keeb/dactyl-manuform-5.jpg" alt="dactyl-manuform-5.jpg" />
</p> </p>
</div> </div>
<div class="figure"> <div id="orgffe075e" class="figure">
<p><img src="../resources/images/keeb/dactyl-manuform-4.jpg" alt="dactyl-manuform-4.jpg" /> <p><img src="../resources/images/keeb/dactyl-manuform-4.jpg" alt="dactyl-manuform-4.jpg" />
</p> </p>
</div> </div>
<div class="figure"> <div id="orga15c836" class="figure">
<p><img src="../resources/images/keeb/dactyl-manuform-3.jpg" alt="dactyl-manuform-3.jpg" /> <p><img src="../resources/images/keeb/dactyl-manuform-3.jpg" alt="dactyl-manuform-3.jpg" />
</p> </p>
</div> </div>
<div class="figure"> <div id="org4023586" class="figure">
<p><img src="../resources/images/keeb/dactyl-manuform-2.jpg" alt="dactyl-manuform-2.jpg" /> <p><img src="../resources/images/keeb/dactyl-manuform-2.jpg" alt="dactyl-manuform-2.jpg" />
</p> </p>
</div> </div>
@ -92,37 +92,37 @@ To be honest, this keeb was ugly, and I decided that I wanted a beautiful factor
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org6970fcb" class="outline-4"> <div id="outline-container-org0f8e531" class="outline-4">
<h4 id="org6970fcb">Moonlander</h4> <h4 id="org0f8e531">Moonlander</h4>
<div class="outline-text-4" id="text-org6970fcb"> <div class="outline-text-4" id="text-org0f8e531">
<p> <p>
Nothing special. Ordered, paid, got it, tried it. Everything worked. Looked good. Happy year of typing. Bored. Annoyed. Too big and chunky. No concave. Quality not the best. Started planning the next one. Nothing special. Ordered, paid, got it, tried it. Everything worked. Looked good. Happy year of typing. Bored. Annoyed. Too big and chunky. No concave. Quality not the best. Started planning the next one.
</p> </p>
<div class="figure"> <div id="orgcbbd6c4" class="figure">
<p><img src="../resources/images/keeb/moonlander.jpg" alt="moonlander.jpg" /> <p><img src="../resources/images/keeb/moonlander.jpg" alt="moonlander.jpg" />
</p> </p>
</div> </div>
</div> </div>
</div> </div>
<div id="outline-container-orgef1b2f6" class="outline-4"> <div id="outline-container-orgd206bf9" class="outline-4">
<h4 id="orgef1b2f6">Custom Corne</h4> <h4 id="orgd206bf9">Custom Corne</h4>
<div class="outline-text-4" id="text-orgef1b2f6"> <div class="outline-text-4" id="text-orgd206bf9">
<p> <p>
This journey started with discovering the Jian keyboard. It is a niche keeb from the Ru community focused on full support of the whole Russian layout. It was originally created by KGOH. I missed the group buy and decided that I could easily patch a Corne board with two additional keys to mimic the Jian. This journey started with discovering the Jian keyboard. It is a niche keeb from the Ru community focused on full support of the whole Russian layout. It was originally created by KGOH. I missed the group buy and decided that I could easily patch a Corne board with two additional keys to mimic the Jian.
Interesting journey. I learned how to use KiCad, and how to export gerbers. Interesting journey. I learned how to use KiCad, and how to export gerbers.
</p> </p>
<div class="figure"> <div id="org8c6495e" class="figure">
<p><img src="../resources/images/keeb/jirne-5.png" alt="jirne-5.png" /> <p><img src="../resources/images/keeb/jirne-5.png" alt="jirne-5.png" />
</p> </p>
</div> </div>
<div class="figure"> <div id="orgccd0848" class="figure">
<p><img src="../resources/images/keeb/jirne-6.png" alt="jirne-6.png" /> <p><img src="../resources/images/keeb/jirne-6.png" alt="jirne-6.png" />
</p> </p>
</div> </div>
@ -132,13 +132,13 @@ I've ordered PCBs at JLCPCB.
</p> </p>
<div class="figure"> <div id="org35543fa" class="figure">
<p><img src="../resources/images/keeb/jirne-8.jpeg" alt="jirne-8.jpeg" /> <p><img src="../resources/images/keeb/jirne-8.jpeg" alt="jirne-8.jpeg" />
</p> </p>
</div> </div>
<div class="figure"> <div id="org929593f" class="figure">
<p><img src="../resources/images/keeb/jirne-9.jpeg" alt="jirne-9.jpeg" /> <p><img src="../resources/images/keeb/jirne-9.jpeg" alt="jirne-9.jpeg" />
</p> </p>
</div> </div>
@ -148,7 +148,7 @@ The build came out pretty decent. I was happy. RGB underglow. Low-profile switch
</p> </p>
<div class="figure"> <div id="org676c6b7" class="figure">
<p><img src="../resources/images/keeb/jirne-7.jpeg" alt="jirne-7.jpeg" /> <p><img src="../resources/images/keeb/jirne-7.jpeg" alt="jirne-7.jpeg" />
</p> </p>
</div> </div>
@ -158,15 +158,15 @@ Daily driver for ~6 months. Then the world changed, and I decided to leave my ho
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org0414f11" class="outline-4"> <div id="outline-container-org9e97c61" class="outline-4">
<h4 id="org0414f11">Dactyl manuform again</h4> <h4 id="org9e97c61">Dactyl manuform again</h4>
<div class="outline-text-4" id="text-org0414f11"> <div class="outline-text-4" id="text-org9e97c61">
<p> <p>
Two years late I've settled down in new country and decide that I want to bring back my dactyl manuform experience. Two years late I've settled down in new country and decide that I want to bring back my dactyl manuform experience.
</p> </p>
<div class="figure"> <div id="org7863216" class="figure">
<p><img src="../resources/images/keeb/dactyl-pitch.jpeg" alt="dactyl-pitch.jpeg" /> <p><img src="../resources/images/keeb/dactyl-pitch.jpeg" alt="dactyl-pitch.jpeg" />
</p> </p>
</div> </div>
@ -174,26 +174,26 @@ Two years late I've settled down in new country and decide that I want to bring
</div> </div>
</div> </div>
<div id="outline-container-org7189206" class="outline-3"> <div id="outline-container-org0e00f11" class="outline-3">
<h3 id="org7189206">Hardware</h3> <h3 id="org0e00f11">Hardware</h3>
<div class="outline-text-3" id="text-org7189206"> <div class="outline-text-3" id="text-org0e00f11">
</div> </div>
<div id="outline-container-org4898606" class="outline-4"> <div id="outline-container-orgddb041c" class="outline-4">
<h4 id="org4898606">Body</h4> <h4 id="orgddb041c">Body</h4>
<div class="outline-text-4" id="text-org4898606"> <div class="outline-text-4" id="text-orgddb041c">
<p> <p>
I've choose to use a <a href="https://ryanis.cool/dactyl/#manuform">Ryan's generator</a> and generate body on top of Corne preset with all keys in last row and disabled stagger for the last two columns. <a href="https://ryanis.cool/dactyl/#manuform:CiUIBhAEGgp0aHJlZS1taW5pIgRmdWxsKgNib3gyBm5vcm1pZTgAGgoIARIEbm9uZRgAIhdVAACAQBgAIABdAADgQGUAAEBAQABIADL5AZUDAAAgQJ0DAACAP4ADAIgDAA0AAAAAFQAAAAAdMzMzQCUAANDALQAAUME1AADAQD0AAAAARQAAAABNAADAQFUAAEDAXQAA4EBlMzNhwm0zMy3CdQAAvMF45wKAAc0YiAHIJJUBMzMXwp0BMzNdwqUBZmbKwagBnwuwAZkXuAH8JcUBAABQws0BAADQwdUBAABAwdgBnATgAfMX6AGQHPUBAADowf0BAAAkwoUCAABQwYgCmwSQAvMXmALgIaUCAAAMwq0CAABwwbUCAAAAwLgChAfAApUQyAKEB9UCAABAwd0CAACAweUCAABAQOgChAfwApUQ+AKEBw==">Generator preset</a> I've choose to use a <a href="https://ryanis.cool/dactyl/#manuform">Ryan's generator</a> and generate body on top of Corne preset with all keys in last row and disabled stagger for the last two columns. <a href="https://ryanis.cool/dactyl/#manuform:CiUIBhAEGgp0aHJlZS1taW5pIgRmdWxsKgNib3gyBm5vcm1pZTgAGgoIARIEbm9uZRgAIhdVAACAQBgAIABdAADgQGUAAEBAQABIADL5AZUDAAAgQJ0DAACAP4ADAIgDAA0AAAAAFQAAAAAdMzMzQCUAANDALQAAUME1AADAQD0AAAAARQAAAABNAADAQFUAAEDAXQAA4EBlMzNhwm0zMy3CdQAAvMF45wKAAc0YiAHIJJUBMzMXwp0BMzNdwqUBZmbKwagBnwuwAZkXuAH8JcUBAABQws0BAADQwdUBAABAwdgBnATgAfMX6AGQHPUBAADowf0BAAAkwoUCAABQwYgCmwSQAvMXmALgIaUCAAAMwq0CAABwwbUCAAAAwLgChAfAApUQyAKEB9UCAABAwd0CAACAweUCAABAQOgChAfwApUQ+AKEBw==">Generator preset</a>
The body was printed by JLC3DP (JLCPCB printing department). I've choose <a href="https://jlc3dp.com/help/article/502-Precimid-1172-Pro">SLS from nylon</a>. Print has minor artifacts; I expected better quality. The body was printed by JLC3DP (JLCPCB printing department). I've choose <a href="https://jlc3dp.com/help/article/502-Precimid-1172-Pro">SLS from nylon</a>. Print has minor artifacts; I expected better quality.
</p> </p>
<div class="figure"> <div id="org62ffcc3" class="figure">
<p><img src="../resources/images/keeb/dactyl-body-2.jpeg" alt="dactyl-body-2.jpeg" /> <p><img src="../resources/images/keeb/dactyl-body-2.jpeg" alt="dactyl-body-2.jpeg" />
</p> </p>
</div> </div>
<div class="figure"> <div id="orgc12677c" class="figure">
<p><img src="../resources/images/keeb/dactyl-body-1.jpeg" alt="dactyl-body-1.jpeg" /> <p><img src="../resources/images/keeb/dactyl-body-1.jpeg" alt="dactyl-body-1.jpeg" />
</p> </p>
</div> </div>
@ -203,28 +203,28 @@ Overall, I'm happy with results. I also printed bottom plates and <a href="https
</p> </p>
<div class="figure"> <div id="orgf3a3914" class="figure">
<p><img src="../resources/images/keeb/dactyl-body-3.jpeg" alt="dactyl-body-3.jpeg" /> <p><img src="../resources/images/keeb/dactyl-body-3.jpeg" alt="dactyl-body-3.jpeg" />
</p> </p>
</div> </div>
<div class="figure"> <div id="org118582c" class="figure">
<p><img src="../resources/images/keeb/dactyl-body-4.jpeg" alt="dactyl-body-4.jpeg" /> <p><img src="../resources/images/keeb/dactyl-body-4.jpeg" alt="dactyl-body-4.jpeg" />
</p> </p>
</div> </div>
</div> </div>
</div> </div>
<div id="outline-container-org615e880" class="outline-4"> <div id="outline-container-orge6d28f1" class="outline-4">
<h4 id="org615e880">Switches and caps</h4> <h4 id="orge6d28f1">Switches and caps</h4>
<div class="outline-text-4" id="text-org615e880"> <div class="outline-text-4" id="text-orge6d28f1">
<p> <p>
I've chosen Kailh BOX Navy switches. I really like the clickity-clack sound. They have a dedicated clickbar to produce this sound, and the box profile helps with moving down perpendicularly. I've chosen Kailh BOX Navy switches. I really like the clickity-clack sound. They have a dedicated clickbar to produce this sound, and the box profile helps with moving down perpendicularly.
</p> </p>
<div class="figure"> <div id="orgf4e2a69" class="figure">
<p><img src="../resources/images/keeb/kailh-box.jpg" alt="kailh-box.jpg" /> <p><img src="../resources/images/keeb/kailh-box.jpg" alt="kailh-box.jpg" />
</p> </p>
</div> </div>
@ -234,30 +234,30 @@ The caps are inherited from the Moonlander. They are thick, double-shot caps wit
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-orgdafbd11" class="outline-4"> <div id="outline-container-org324aa24" class="outline-4">
<h4 id="orgdafbd11">Controllers</h4> <h4 id="org324aa24">Controllers</h4>
<div class="outline-text-4" id="text-orgdafbd11"> <div class="outline-text-4" id="text-org324aa24">
<p> <p>
I used a bootleg Pro Micro called Tenstar Robot, based on the ATmega32u4. It's perfectly supported by QMK, pin-to-pin and size-compatible with the Pro Micro. I used a bootleg Pro Micro called Tenstar Robot, based on the ATmega32u4. It's perfectly supported by QMK, pin-to-pin and size-compatible with the Pro Micro.
</p> </p>
<div class="figure"> <div id="orgfe8b8d0" class="figure">
<p><img src="../resources/images/keeb/dactyl-all-3.jpg" alt="dactyl-all-3.jpg" /> <p><img src="../resources/images/keeb/dactyl-all-3.jpg" alt="dactyl-all-3.jpg" />
</p> </p>
</div> </div>
</div> </div>
</div> </div>
<div id="outline-container-org7c42229" class="outline-4"> <div id="outline-container-org399d344" class="outline-4">
<h4 id="org7c42229">Amoeba things</h4> <h4 id="org399d344">Amoeba things</h4>
<div class="outline-text-4" id="text-org7c42229"> <div class="outline-text-4" id="text-org399d344">
<p> <p>
During this build, I decided that I did not want to make a big mess of wires and chose Amoeba single-switch PCBs. During this build, I decided that I did not want to make a big mess of wires and chose Amoeba single-switch PCBs.
</p> </p>
<div class="figure"> <div id="orge507644" class="figure">
<p><img src="../resources/images/keeb/amoeba.jpg" alt="amoeba.jpg" /> <p><img src="../resources/images/keeb/amoeba.jpg" alt="amoeba.jpg" />
</p> </p>
</div> </div>
@ -267,13 +267,13 @@ They are nice, have diodes on board, and simplify wiring. However, they have the
</p> </p>
<div class="figure"> <div id="org0ce9a77" class="figure">
<p><img src="../resources/images/keeb/dactyl-all-1.jpg" alt="dactyl-all-1.jpg" /> <p><img src="../resources/images/keeb/dactyl-all-1.jpg" alt="dactyl-all-1.jpg" />
</p> </p>
</div> </div>
<div class="figure"> <div id="orgb40214e" class="figure">
<p><img src="../resources/images/keeb/dactyl-all-5.jpg" alt="dactyl-all-5.jpg" /> <p><img src="../resources/images/keeb/dactyl-all-5.jpg" alt="dactyl-all-5.jpg" />
</p> </p>
</div> </div>
@ -281,13 +281,13 @@ They are nice, have diodes on board, and simplify wiring. However, they have the
</div> </div>
</div> </div>
<div id="outline-container-orgab34fe9" class="outline-3"> <div id="outline-container-org62edd8c" class="outline-3">
<h3 id="orgab34fe9">Software</h3> <h3 id="org62edd8c">Software</h3>
<div class="outline-text-3" id="text-orgab34fe9"> <div class="outline-text-3" id="text-org62edd8c">
</div> </div>
<div id="outline-container-orgbe03b8f" class="outline-4"> <div id="outline-container-org90dd15d" class="outline-4">
<h4 id="orgbe03b8f">Plain default - QMK</h4> <h4 id="org90dd15d">Plain default - QMK</h4>
<div class="outline-text-4" id="text-orgbe03b8f"> <div class="outline-text-4" id="text-org90dd15d">
<p> <p>
Prerequiremets: Prerequiremets:
<a href="https://docs.qmk.fm/cli">QMK CLI</a> <a href="https://docs.qmk.fm/cli">QMK CLI</a>
@ -309,9 +309,9 @@ You may want to create a separate keyboard entry in QMK.
</div> </div>
</div> </div>
<div id="outline-container-orge8f2d0c" class="outline-4"> <div id="outline-container-orge4b81a7" class="outline-4">
<h4 id="orge8f2d0c">Make own layout</h4> <h4 id="orge4b81a7">Make own layout</h4>
<div class="outline-text-4" id="text-orge8f2d0c"> <div class="outline-text-4" id="text-orge4b81a7">
<p> <p>
I'll try to go through setting of my personal layout. It is based on <a href="http://www.keyboard-layout-editor.com/#/gists/4b6c2af67148f58ddd6c6b2976c4370f">Jian layout</a>. I'll try to go through setting of my personal layout. It is based on <a href="http://www.keyboard-layout-editor.com/#/gists/4b6c2af67148f58ddd6c6b2976c4370f">Jian layout</a>.
</p> </p>
@ -354,17 +354,17 @@ RGB underglow configuration.
&quot;led_count&quot;: 16, &quot;led_count&quot;: 16,
&quot;led_map&quot;: [7, 6, 5, 4, 3, 2, 1, 0, 8, 9, 10, 11, 12, 13, 14, 15], &quot;led_map&quot;: [7, 6, 5, 4, 3, 2, 1, 0, 8, 9, 10, 11, 12, 13, 14, 15],
&quot;animations&quot;: { &quot;animations&quot;: {
&quot;static_light&quot;: true, &quot;static_light&quot;: true,
&quot;breathing&quot;: true, &quot;breathing&quot;: true,
&quot;rainbow_mood&quot;: true, &quot;rainbow_mood&quot;: true,
&quot;snake&quot;: false &quot;snake&quot;: false
}, },
&quot;layers&quot;: { &quot;layers&quot;: {
&quot;enabled&quot;: true, &quot;enabled&quot;: true,
&quot;blink&quot;: true &quot;blink&quot;: true
}, },
&quot;default&quot;: { &quot;default&quot;: {
&quot;animation&quot;: &quot;rainbow_mood&quot; &quot;animation&quot;: &quot;rainbow_mood&quot;
}, },
&quot;split&quot;: true, &quot;split&quot;: true,
&quot;split_count&quot;: [8, 8] &quot;split_count&quot;: [8, 8]
@ -384,12 +384,12 @@ Turn on split feature, assign pin for halves communication, choose what to sync.
&quot;enabled&quot;: true, &quot;enabled&quot;: true,
&quot;soft_serial_pin&quot;: &quot;D2&quot;, &quot;soft_serial_pin&quot;: &quot;D2&quot;,
&quot;transport&quot;: { &quot;transport&quot;: {
&quot;protocol&quot;: &quot;serial&quot;, &quot;protocol&quot;: &quot;serial&quot;,
&quot;sync&quot;: { &quot;sync&quot;: {
&quot;layer_state&quot;: true, &quot;layer_state&quot;: true,
&quot;indicators&quot;: true, &quot;indicators&quot;: true,
&quot;modifiers&quot;: true &quot;modifiers&quot;: true
} }
} }
}, },
</code></pre> </code></pre>
@ -413,13 +413,13 @@ This is the <code>keymaps/default/keymap.c</code> file.
#define _S 3 #define _S 3
const rgblight_segment_t PROGMEM system_layer[] = RGBLIGHT_LAYER_SEGMENTS({0, 4, HSV_RED}, const rgblight_segment_t PROGMEM system_layer[] = RGBLIGHT_LAYER_SEGMENTS({0, 4, HSV_RED},
{12, 4, HSV_RED}); {12, 4, HSV_RED});
const rgblight_segment_t PROGMEM lower_layer[] = RGBLIGHT_LAYER_SEGMENTS({5, 6, HSV_CYAN}); const rgblight_segment_t PROGMEM lower_layer[] = RGBLIGHT_LAYER_SEGMENTS({5, 6, HSV_CYAN});
const rgblight_segment_t PROGMEM raise_layer[] = RGBLIGHT_LAYER_SEGMENTS({5, 6, HSV_PURPLE}); const rgblight_segment_t PROGMEM raise_layer[] = RGBLIGHT_LAYER_SEGMENTS({5, 6, HSV_PURPLE});
const rgblight_segment_t* const PROGMEM my_rgb_layers[] = RGBLIGHT_LAYERS_LIST(system_layer, const rgblight_segment_t* const PROGMEM my_rgb_layers[] = RGBLIGHT_LAYERS_LIST(system_layer,
lower_layer, lower_layer,
raise_layer raise_layer
); );
void keyboard_post_init_user(void) { void keyboard_post_init_user(void) {
@ -436,30 +436,30 @@ layer_state_t layer_state_set_user(layer_state_t state) {
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// clang-format off // clang-format off
[_B] = LAYOUT_split_4x7_3( [_B] = LAYOUT_split_4x7_3(
KC_GRAVE, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LEFT_BRACKET, KC_GRAVE, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LEFT_BRACKET,
KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, RCTL_T(KC_QUOTE), KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, RCTL_T(KC_QUOTE),
KC_LALT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLASH, RALT_T(KC_BACKSLASH), KC_LALT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLASH, RALT_T(KC_BACKSLASH),
KC_CAPS, KC_NO, KC_NO, KC_LEFT_GUI, LT(_R, KC_TAB), LSFT_T(KC_SPC), LT(_L, KC_ENT), LSFT_T(KC_BSPC), LT(_R, KC_DEL), LGUI_T(KC_RCBR), KC_D, KC_E, KC_F, LT(_L, KC_ESC) KC_CAPS, KC_NO, KC_NO, KC_LEFT_GUI, LT(_R, KC_TAB), LSFT_T(KC_SPC), LT(_L, KC_ENT), LSFT_T(KC_BSPC), LT(_R, KC_DEL), LGUI_T(KC_RCBR), KC_D, KC_E, KC_F, LT(_L, KC_ESC)
), ),
[_L] = LAYOUT_split_4x7_3( [_L] = LAYOUT_split_4x7_3(
KC_UNDS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_UNDS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11,
LCTL_T(KC_PLUS), KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, RCTL_T(KC_KP_MINUS), LCTL_T(KC_PLUS), KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, RCTL_T(KC_KP_MINUS),
LALT_T(KC_PEQL), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_RALT, LALT_T(KC_PEQL), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_RALT,
KC_NO, KC_NO, KC_NO, KC_LEFT_GUI, KC_TRNS, LSFT_T(KC_SPC), KC_TRNS, LSFT_T(KC_BSPC), KC_TRNS, LGUI_T(KC_F12), KC_NO, KC_NO, KC_NO, KC_TRNS KC_NO, KC_NO, KC_NO, KC_LEFT_GUI, KC_TRNS, LSFT_T(KC_SPC), KC_TRNS, LSFT_T(KC_BSPC), KC_TRNS, LGUI_T(KC_F12), KC_NO, KC_NO, KC_NO, KC_TRNS
), ),
[_R] = LAYOUT_split_4x7_3( [_R] = LAYOUT_split_4x7_3(
KC_NUM, KC_PSLS, KC_7, KC_8, KC_9, KC_PMNS, KC_VOLU, KC_HOME, KC_PSCR, KC_PGUP, KC_SCRL, KC_CAPS, KC_NUM, KC_PSLS, KC_7, KC_8, KC_9, KC_PMNS, KC_VOLU, KC_HOME, KC_PSCR, KC_PGUP, KC_SCRL, KC_CAPS,
LCTL_T(KC_PEQL), KC_PAST, KC_4, KC_5, KC_6, KC_PPLS, KC_MUTE, KC_LEFT, KC_UP, KC_RIGHT, KC_INS, RCTL_T(KC_APP), LCTL_T(KC_PEQL), KC_PAST, KC_4, KC_5, KC_6, KC_PPLS, KC_MUTE, KC_LEFT, KC_UP, KC_RIGHT, KC_INS, RCTL_T(KC_APP),
KC_LALT, KC_0, KC_1, KC_2, KC_3, KC_PDOT, KC_VOLD, KC_END, KC_DOWN, KC_PGDN, KC_PAUS, KC_RALT, KC_LALT, KC_0, KC_1, KC_2, KC_3, KC_PDOT, KC_VOLD, KC_END, KC_DOWN, KC_PGDN, KC_PAUS, KC_RALT,
KC_NO, KC_NO, KC_NO, KC_LEFT_GUI, KC_TRNS, LSFT_T(KC_SPC), KC_TRNS, LSFT_T(KC_BSPC), KC_TRNS, KC_LGUI, KC_NO, KC_NO, KC_NO, KC_TRNS KC_NO, KC_NO, KC_NO, KC_LEFT_GUI, KC_TRNS, LSFT_T(KC_SPC), KC_TRNS, LSFT_T(KC_BSPC), KC_TRNS, KC_LGUI, KC_NO, KC_NO, KC_NO, KC_TRNS
), ),
[_S] = LAYOUT_split_4x7_3( [_S] = LAYOUT_split_4x7_3(
DB_TOGG, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, DB_TOGG, DB_TOGG, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, DB_TOGG,
QK_BOOT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, QK_BOOT, QK_BOOT, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, QK_BOOT,
RGB_MOD, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, RGB_MOD, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO,
RGB_RMOD, KC_NO, KC_NO, QK_RBT, KC_TRNS, KC_NO, KC_TRNS, KC_NO, KC_TRNS, QK_RBT, KC_NO, KC_NO, KC_NO, KC_TRNS RGB_RMOD, KC_NO, KC_NO, QK_RBT, KC_TRNS, KC_NO, KC_TRNS, KC_NO, KC_TRNS, QK_RBT, KC_NO, KC_NO, KC_NO, KC_TRNS
), ),
// clang-format on // clang-format on
}; };
@ -468,8 +468,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
</div> </div>
</div> </div>
</div> </div>
<div id="outline-container-org71af41b" class="outline-3"> <div id="outline-container-org0af2266" class="outline-3">
<h3 id="org71af41b">Whats next?</h3> <h3 id="org0af2266">Whats next?</h3>
</div> </div>
</div> </div>
</main><footer class="footer"><div class="container"><hr/><small><p>Alex Mikhailov</p><p>Built with: <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> <a href="https://orgmode.org/">Org Mode</a> <a href="https://picocss.com/">picocss</a></p></small></div></footer></body></html> </main><footer class="footer"><div class="container"><hr/><small><p>Alex Mikhailov</p><p>Built with: <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> <a href="https://orgmode.org/">Org Mode</a> <a href="https://picocss.com/">picocss</a></p></small></div></footer></body></html>

View File

@ -1,32 +1,32 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Add post preview for OpenGraph cards"/><meta property="og:description" content="Add post preview for OpenGraph cards"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/posts_preview.org.png"/><meta property="og:title" content="Posts preview"/><meta name="twitter:description" content="Add post preview for OpenGraph cards"/><meta name="twitter:title" content="Posts preview"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/posts_preview.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Posts preview</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Posts preview</h1><p>Add post preview for OpenGraph cards</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li><li><mark><a href="/tags/@elisp.html" class="secondary">@elisp</a></mark></li><li><mark><a href="/tags/@imagemagick.html" class="secondary">@imagemagick</a></mark></li></ul></nav></hgroup><div id="table-of-contents"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Add post preview for OpenGraph cards"/><meta property="og:description" content="Add post preview for OpenGraph cards"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/posts/posts_preview.org.png"/><meta property="og:title" content="Posts preview"/><meta name="twitter:description" content="Add post preview for OpenGraph cards"/><meta name="twitter:title" content="Posts preview"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/posts/posts_preview.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Posts preview</title><link id="highlight-theme" rel="stylesheet" type="text/css"/><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/bash.min.js"></script><script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/languages/lisp.min.js"></script><script src="/resources/js/theme-selector.js"></script></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container blog-post"><hgroup><h1>Posts preview</h1><p>Add post preview for OpenGraph cards</p><nav><ul><li>Tags:</li><li><mark><a href="/tags/@org-mode.html" class="secondary">@org-mode</a></mark></li><li><mark><a href="/tags/@elisp.html" class="secondary">@elisp</a></mark></li><li><mark><a href="/tags/@imagemagick.html" class="secondary">@imagemagick</a></mark></li></ul></nav></hgroup><div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2> <h2>Table of Contents</h2>
<div id="text-table-of-contents"> <div id="text-table-of-contents" role="doc-toc">
<ul> <ul>
<li><a href="#orgd56a941">What is imagemagick</a></li> <li><a href="#orgd9023df">What is imagemagick</a></li>
<li><a href="#org453a689">Basic idea of this process</a></li> <li><a href="#org0a8dc9a">Basic idea of this process</a></li>
<li><a href="#orgf2af64f">Integrate into build</a></li> <li><a href="#org49ae5aa">Integrate into build</a></li>
<li><a href="#org245c7d6">Whats next?</a> <li><a href="#org6fa54e8">Whats next?</a>
<ul> <ul>
<li><a href="#org53411a1">Tags</a></li> <li><a href="#org6687a34">Tags</a></li>
<li><a href="#org4f4168c">Post series</a></li> <li><a href="#orgba5a520">Post series</a></li>
<li><a href="#orgff1333a">Adopt/fix htmlize.el</a></li> <li><a href="#org486f0a7">Adopt/fix htmlize.el</a></li>
<li><a href="#org35ab4a0">Show more meta on posts index page.</a></li> <li><a href="#org6d2d4a6">Show more meta on posts index page.</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-orgd56a941" class="outline-2"> <div id="outline-container-orgd9023df" class="outline-2">
<h2 id="orgd56a941">What is imagemagick</h2> <h2 id="orgd9023df">What is imagemagick</h2>
<div class="outline-text-2" id="text-orgd56a941"> <div class="outline-text-2" id="text-orgd9023df">
<p> <p>
<a href="https://imagemagick.org">Imagemagick</a> is a ffmpeg of the image world. You can do a lot of fun things with it. For example you can take a picture, cut corners on it, place it on top of another image, add some text and get final result. So it is looks like a good tool for making previews from code. <a href="https://imagemagick.org">Imagemagick</a> is a ffmpeg of the image world. You can do a lot of fun things with it. For example you can take a picture, cut corners on it, place it on top of another image, add some text and get final result. So it is looks like a good tool for making previews from code.
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org453a689" class="outline-2"> <div id="outline-container-org0a8dc9a" class="outline-2">
<h2 id="org453a689">Basic idea of this process</h2> <h2 id="org0a8dc9a">Basic idea of this process</h2>
<div class="outline-text-2" id="text-org453a689"> <div class="outline-text-2" id="text-org0a8dc9a">
<p> <p>
I want to hook a process of rendering post. Since this function called on each run of publishing and for each post it is a good idea to cache resulting images. I gonna simply check presence of preview image and use it as guard for running image generation. After that I gonna extract <code>#+TITLE</code> and <code>#+DESCRIPTION</code> properties from Org file. Each Org file I have, has next header: I want to hook a process of rendering post. Since this function called on each run of publishing and for each post it is a good idea to cache resulting images. I gonna simply check presence of preview image and use it as guard for running image generation. After that I gonna extract <code>#+TITLE</code> and <code>#+DESCRIPTION</code> properties from Org file. Each Org file I have, has next header:
</p> </p>
@ -48,30 +48,30 @@ So I with all these data I can generate my previews with simple script:
</div> </div>
</div> </div>
<div id="outline-container-orgf2af64f" class="outline-2"> <div id="outline-container-org49ae5aa" class="outline-2">
<h2 id="orgf2af64f">Integrate into build</h2> <h2 id="org49ae5aa">Integrate into build</h2>
<div class="outline-text-2" id="text-orgf2af64f"> <div class="outline-text-2" id="text-org49ae5aa">
<p> <p>
As I already mention I gonna skip file generation when file already here. Here is the whole function. Pretty simple. Just prepare pathes, check some dependencies, create pathes and execute script which calls imagemagick. As I already mention I gonna skip file generation when file already here. Here is the whole function. Pretty simple. Just prepare pathes, check some dependencies, create pathes and execute script which calls imagemagick.
</p> </p>
<pre><code class="language-lisp">(defun my/render-preview (file-name title description) <pre><code class="language-lisp">(defun my/render-preview (file-name title description)
(let* ((has-imagemagick (executable-find &quot;magick&quot;)) (let* ((has-imagemagick (executable-find &quot;magick&quot;))
(full-file-path (file-truename(format &quot;%s%s/resources/images/preview/%s.png&quot; script-directory my/blog-src-path file-name ))) (full-file-path (file-truename(format &quot;%s%s/resources/images/preview/%s.png&quot; script-directory my/blog-src-path file-name )))
(file-dir (file-name-directory full-file-path)) (file-dir (file-name-directory full-file-path))
(has-dir (file-directory-p file-dir)) (has-dir (file-directory-p file-dir))
(has-file (file-exists-p full-file-path)) (has-file (file-exists-p full-file-path))
(path-to-script-root (format &quot;%shelpers&quot; script-directory)) (path-to-script-root (format &quot;%shelpers&quot; script-directory))
(path-to-script (format &quot;%s/og_image_gen.sh&quot; path-to-script-root))) (path-to-script (format &quot;%s/og_image_gen.sh&quot; path-to-script-root)))
(if (and has-imagemagick (if (and has-imagemagick
(and description (not (string= description &quot;&quot;)))) (and description (not (string= description &quot;&quot;))))
(progn (progn
(when (not has-file) (when (not has-file)
(progn (progn
(when (not has-dir) (when (not has-dir)
(make-directory file-dir t)) (make-directory file-dir t))
(shell-command (format &quot;bash &apos;%s&apos; &apos;%s&apos; &apos;%s&apos; &apos;%s&apos; &apos;%s&apos;&quot; path-to-script title description full-file-path path-to-script-root)) (shell-command (format &quot;bash &apos;%s&apos; &apos;%s&apos; &apos;%s&apos; &apos;%s&apos; &apos;%s&apos;&quot; path-to-script title description full-file-path path-to-script-root))
) )
)) ))
(message &quot;Imagemagick is not installed. Preview generation skipped.&quot;) (message &quot;Imagemagick is not installed. Preview generation skipped.&quot;)
))) )))
</code></pre> </code></pre>
@ -82,11 +82,11 @@ And here is the part of <code>my/template</code> function related to OpenGraph m
<pre><code class="language-lisp">(defun my/template (contents info) <pre><code class="language-lisp">(defun my/template (contents info)
(let* ((title-str (org-export-data (plist-get info :title) info)) (let* ((title-str (org-export-data (plist-get info :title) info))
(description-str (org-export-data (plist-get info :description) info)) (description-str (org-export-data (plist-get info :description) info))
(file-path-str (org-export-data (plist-get info :input-file) info)) (file-path-str (org-export-data (plist-get info :input-file) info))
(base-directory-str (org-export-data (plist-get info :base-directory) info)) (base-directory-str (org-export-data (plist-get info :base-directory) info))
(file-name-str (file-relative-name file-path-str (format &quot;%s/%s&quot; script-directory base-directory-str))) (file-name-str (file-relative-name file-path-str (format &quot;%s/%s&quot; script-directory base-directory-str)))
(img-link-str (format &quot;%s/resources/images/preview/%s.png&quot; my/url file-name-str)) (img-link-str (format &quot;%s/resources/images/preview/%s.png&quot; my/url file-name-str))
(my/render-preview file-name-str title-str description-str) (my/render-preview file-name-str title-str description-str)
@ -94,18 +94,18 @@ And here is the part of <code>my/template</code> function related to OpenGraph m
(set-text-properties 0 (length description-str) nil description-str) (set-text-properties 0 (length description-str) nil description-str)
(set-text-properties 0 (length img-link-str) nil img-link-str) (set-text-properties 0 (length img-link-str) nil img-link-str)
... ...
;; OG block ;; OG block
(meta ((name . &quot;description&quot;) (content . ,description-str))) (meta ((name . &quot;description&quot;) (content . ,description-str)))
(meta ((name . &quot;og:description&quot;) (content . ,description-str))) (meta ((name . &quot;og:description&quot;) (content . ,description-str)))
(meta ((name . &quot;twitter:description&quot;) (content . ,description-str))) (meta ((name . &quot;twitter:description&quot;) (content . ,description-str)))
(meta ((name . &quot;og:image&quot;) (content . ,img-link-str))) (meta ((name . &quot;og:image&quot;) (content . ,img-link-str)))
(meta ((name . &quot;twitter:image&quot;) (content . ,img-link-str))) (meta ((name . &quot;twitter:image&quot;) (content . ,img-link-str)))
(meta ((name . &quot;og:title&quot;) (content . ,title-str))) (meta ((name . &quot;og:title&quot;) (content . ,title-str)))
(meta ((name . &quot;twitter:title&quot;) (content . ,title-str))) (meta ((name . &quot;twitter:title&quot;) (content . ,title-str)))
(meta ((name . &quot;twitter:card&quot;) (content . &quot;summary_large_image&quot;))) (meta ((name . &quot;twitter:card&quot;) (content . &quot;summary_large_image&quot;)))
</code></pre> </code></pre>
<p> <p>
@ -113,38 +113,38 @@ You can check whole function in previous post <a href="./improve_code_blocks.htm
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org245c7d6" class="outline-2"> <div id="outline-container-org6fa54e8" class="outline-2">
<h2 id="org245c7d6">Whats next?</h2> <h2 id="org6fa54e8">Whats next?</h2>
<div class="outline-text-2" id="text-org245c7d6"> <div class="outline-text-2" id="text-org6fa54e8">
</div> </div>
<div id="outline-container-org53411a1" class="outline-3"> <div id="outline-container-org6687a34" class="outline-3">
<h3 id="org53411a1">Tags</h3> <h3 id="org6687a34">Tags</h3>
<div class="outline-text-3" id="text-org53411a1"> <div class="outline-text-3" id="text-org6687a34">
<p> <p>
Show tags, show posts by tag. Show tags, show posts by tag.
<a href="./blog_index_and_tags_automation.html">Blog index and tags automation</a> <a href="./blog_index_and_tags_automation.html">Blog index and tags automation</a>
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org4f4168c" class="outline-3"> <div id="outline-container-orgba5a520" class="outline-3">
<h3 id="org4f4168c">Post series</h3> <h3 id="orgba5a520">Post series</h3>
<div class="outline-text-3" id="text-org4f4168c"> <div class="outline-text-3" id="text-orgba5a520">
<p> <p>
Dunno how, but I'll figure out something. Dunno how, but I'll figure out something.
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-orgff1333a" class="outline-3"> <div id="outline-container-org486f0a7" class="outline-3">
<h3 id="orgff1333a">Adopt/fix htmlize.el</h3> <h3 id="org486f0a7">Adopt/fix htmlize.el</h3>
<div class="outline-text-3" id="text-orgff1333a"> <div class="outline-text-3" id="text-org486f0a7">
<p> <p>
I want to highlight code during publishing step. I want to highlight code during publishing step.
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org35ab4a0" class="outline-3"> <div id="outline-container-org6d2d4a6" class="outline-3">
<h3 id="org35ab4a0">Show more meta on posts index page.</h3> <h3 id="org6d2d4a6">Show more meta on posts index page.</h3>
<div class="outline-text-3" id="text-org35ab4a0"> <div class="outline-text-3" id="text-org6d2d4a6">
<p> <p>
Creation date, preview, tags, whatever. Creation date, preview, tags, whatever.
<a href="./blog_index_and_tags_automation.html">Blog index and tags automation</a> <a href="./blog_index_and_tags_automation.html">Blog index and tags automation</a>

142
rss.html
View File

@ -1,87 +1,93 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/rss.org.png"/><meta property="og:title" content="rss"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="rss"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/rss.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>rss</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"><div id="table-of-contents"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content="Slice of my technical life"/><meta property="og:description" content="Slice of my technical life"/><meta property="og:image" content="https://fidonode.me/resources/images/preview/rss.org.png"/><meta property="og:title" content="Alex&apos;s M Personal Blog"/><meta name="twitter:description" content="Slice of my technical life"/><meta name="twitter:title" content="Alex&apos;s M Personal Blog"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/rss.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Alex&apos;s M Personal Blog</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"><div id="table-of-contents" role="doc-toc">
<h2>Table of Contents</h2> <h2>Table of Contents</h2>
<div id="text-table-of-contents"> <div id="text-table-of-contents" role="doc-toc">
<ul> <ul>
<li><a href="#orgbd7ff36">Tag: @tags</a></li> <li><a href="#org5e745d5">Blog index and tags automation</a></li>
<li><a href="#org74c6991">Tag: @imagemagick</a></li> <li><a href="#org630a1df">Posts preview</a></li>
<li><a href="#org480932d">Tag: @diy</a></li> <li><a href="#orgec123c4">Improve code blocks</a></li>
<li><a href="#orgf79d9f3">Tag: @keeb</a></li> <li><a href="#orgdb75fda">Org blog with RSS</a></li>
<li><a href="#orgc2ee2cb">Tag: @highlightjs</a></li> <li><a href="#org2dd3caf">Org to HTML and back</a></li>
<li><a href="#orgeef2cf6">Tag: @elisp</a></li> <li><a href="#org285ca55">My keyboard journey</a></li>
<li><a href="#org5f707ae">Tag: @org-mode</a></li>
<li><a href="#orga8fe16d">Blog index and tags automation</a></li>
<li><a href="#orgafb47e4">Posts preview</a></li>
<li><a href="#orgbda4cc1">Improve code blocks</a></li>
<li><a href="#orgf131630">Org blog with RSS</a></li>
<li><a href="#org46b2cf2">Org to HTML and back</a></li>
<li><a href="#orgc9734a0">My keyboard journey</a></li>
</ul> </ul>
</div> </div>
</div> </div>
<div id="outline-container-orgbd7ff36" class="outline-2"> <div id="outline-container-org5e745d5" class="outline-2">
<h2 id="orgbd7ff36"><a href="file:///home/fido-node/org/home/05 Blog/tags/@tags.html">Tag: @tags</a></h2> <h2 id="org5e745d5"><a href="file:///home/fido-node/org/home/05 Blog/posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h2>
<div class="outline-text-2" id="text-orgbd7ff36"> <div class="outline-text-2" id="text-org5e745d5">
<p>
Let's add tags to blog posts
</p>
<p>
Tags are a nice and easy way to organize posts without explicit search. In the simplest way, you have a list of tags in posts, and each tag links to a page with all posts having the corresponding tag. It is also helpful to have a page with all tags available in the blog. And, of course, I don't want to maintain the list of tags manually.
Automate tags&#x2026;.
</p>
</div> </div>
</div> </div>
<div id="outline-container-org74c6991" class="outline-2"> <div id="outline-container-org630a1df" class="outline-2">
<h2 id="org74c6991"><a href="file:///home/fido-node/org/home/05 Blog/tags/@imagemagick.html">Tag: @imagemagick</a></h2> <h2 id="org630a1df"><a href="file:///home/fido-node/org/home/05 Blog/posts/posts_preview.html">Posts preview</a></h2>
<div class="outline-text-2" id="text-org74c6991"> <div class="outline-text-2" id="text-org630a1df">
<p>
Add post preview for OpenGraph cards
</p>
<p>
<a href="https://imagemagick.org">Imagemagick</a> is a ffmpeg of the image world. You can do a lot of fun things with it. For example you can take a picture, cut corners on it, place it on top of another image, add some text and get final result. So it is looks like a good tool for making previews from code.
Basic idea of this process&#x2026;
</p>
</div> </div>
</div> </div>
<div id="outline-container-org480932d" class="outline-2"> <div id="outline-container-orgec123c4" class="outline-2">
<h2 id="org480932d"><a href="file:///home/fido-node/org/home/05 Blog/tags/@diy.html">Tag: @diy</a></h2> <h2 id="orgec123c4"><a href="file:///home/fido-node/org/home/05 Blog/posts/improve_code_blocks.html">Improve code blocks</a></h2>
<div class="outline-text-2" id="text-org480932d"> <div class="outline-text-2" id="text-orgec123c4">
<p>
Use highlight.js for code syntax highlighting
</p>
<p>
Htmlize works poorly with headless publishing. It lacks extensibility, including features like line numbers, a copy button, and the ability to highlight predefined parts of the code.
Highlight.js&#x2026;
</p>
</div> </div>
</div> </div>
<div id="outline-container-orgf79d9f3" class="outline-2"> <div id="outline-container-orgdb75fda" class="outline-2">
<h2 id="orgf79d9f3"><a href="file:///home/fido-node/org/home/05 Blog/tags/@keeb.html">Tag: @keeb</a></h2> <h2 id="orgdb75fda"><a href="file:///home/fido-node/org/home/05 Blog/posts/add_rss_to_blog.html">Org blog with RSS</a></h2>
<div class="outline-text-2" id="text-orgf79d9f3"> <div class="outline-text-2" id="text-orgdb75fda">
<p>
Let's add RSS feed to blog
</p>
<p>
RSS might seem like an outdated, marginal thing. But it still has at least one benefit—you can use an RSS feed as a sitemap for search engines. Plus, it's pretty geeky.
Add RSS feed&#x2026;
</p>
</div> </div>
</div> </div>
<div id="outline-container-orgc2ee2cb" class="outline-2"> <div id="outline-container-org2dd3caf" class="outline-2">
<h2 id="orgc2ee2cb"><a href="file:///home/fido-node/org/home/05 Blog/tags/@highlightjs.html">Tag: @highlightjs</a></h2> <h2 id="org2dd3caf"><a href="file:///home/fido-node/org/home/05 Blog/posts/about_blog.html">Org to HTML and back</a></h2>
<div class="outline-text-2" id="text-orgc2ee2cb"> <div class="outline-text-2" id="text-org2dd3caf">
<p>
Blog post about publishing my blog with Org Mode
</p>
<p>
I'm neither proficient in Org Mode (further on "Org"), nor a good front-end engineer. I think that a simple solution is better than no solution. If you see a mistake, you can contact me via <a href="mailto:iam@fidonode.me">iam@fidonode.me</a>.
What is Org?&#x2026;
</p>
</div> </div>
</div> </div>
<div id="outline-container-orgeef2cf6" class="outline-2"> <div id="outline-container-org285ca55" class="outline-2">
<h2 id="orgeef2cf6"><a href="file:///home/fido-node/org/home/05 Blog/tags/@elisp.html">Tag: @elisp</a></h2> <h2 id="org285ca55"><a href="file:///home/fido-node/org/home/05 Blog/posts/keeb.html">My keyboard journey</a></h2>
<div class="outline-text-2" id="text-orgeef2cf6"> <div class="outline-text-2" id="text-org285ca55">
</div> <p>
</div> Blog post about my keyboards
<div id="outline-container-org5f707ae" class="outline-2"> </p>
<h2 id="org5f707ae"><a href="file:///home/fido-node/org/home/05 Blog/tags/@org-mode.html">Tag: @org-mode</a></h2>
<div class="outline-text-2" id="text-org5f707ae"> <p>
</div> Sometimes I think about the long journey I've made with keebs. In childhood, I had decent membrane keyboards, most of which had an ergonomic profile like the MS. Not sure if it somehow affected my taste because I started my career with the simplest, cheapest board and typed countless lines of code on such keebs. Then I heard about clickity-clack mechanical keyboards and decided to try one. It was a simple Chinese keeb with a thick metal body, double-shot caps, and Cherry Brown switches. A decent thing to annoy everyone around you. I think this purchase marked my dive into mech keebs
</div> I'm not a geeky aficionado who thinks you can fix everything with a new keyboard, but I built a couple of them. I hope I've finally built the last one for quite some time&#x2026;.
<div id="outline-container-orga8fe16d" class="outline-2"> </p>
<h2 id="orga8fe16d"><a href="file:///home/fido-node/org/home/05 Blog/posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h2>
<div class="outline-text-2" id="text-orga8fe16d">
</div>
</div>
<div id="outline-container-orgafb47e4" class="outline-2">
<h2 id="orgafb47e4"><a href="file:///home/fido-node/org/home/05 Blog/posts/posts_preview.html">Posts preview</a></h2>
<div class="outline-text-2" id="text-orgafb47e4">
</div>
</div>
<div id="outline-container-orgbda4cc1" class="outline-2">
<h2 id="orgbda4cc1"><a href="file:///home/fido-node/org/home/05 Blog/posts/improve_code_blocks.html">Improve code blocks</a></h2>
<div class="outline-text-2" id="text-orgbda4cc1">
</div>
</div>
<div id="outline-container-orgf131630" class="outline-2">
<h2 id="orgf131630"><a href="file:///home/fido-node/org/home/05 Blog/posts/add_rss_to_blog.html">Org blog with RSS</a></h2>
<div class="outline-text-2" id="text-orgf131630">
</div>
</div>
<div id="outline-container-org46b2cf2" class="outline-2">
<h2 id="org46b2cf2"><a href="file:///home/fido-node/org/home/05 Blog/posts/about_blog.html">Org to HTML and back</a></h2>
<div class="outline-text-2" id="text-org46b2cf2">
</div>
</div>
<div id="outline-container-orgc9734a0" class="outline-2">
<h2 id="orgc9734a0"><a href="file:///home/fido-node/org/home/05 Blog/posts/keeb.html">My keyboard journey</a></h2>
<div class="outline-text-2" id="text-orgc9734a0">
</div> </div>
</div> </div>
</main><footer class="footer"><div class="container"><hr/><small><p>Alex Mikhailov</p><p>Built with: <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> <a href="https://orgmode.org/">Org Mode</a> <a href="https://picocss.com/">picocss</a></p></small></div></footer></body></html> </main><footer class="footer"><div class="container"><hr/><small><p>Alex Mikhailov</p><p>Built with: <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a> <a href="https://orgmode.org/">Org Mode</a> <a href="https://picocss.com/">picocss</a></p></small></div></footer></body></html>

137
rss.xml
View File

@ -9,85 +9,22 @@
xmlns:georss="http://www.georss.org/georss" xmlns:georss="http://www.georss.org/georss"
xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
xmlns:media="http://search.yahoo.com/mrss/"><channel> xmlns:media="http://search.yahoo.com/mrss/"><channel>
<title>rss</title> <title>Alex's M Personal Blog</title>
<atom:link href="https://fidonode.me/rss.xml" rel="self" type="application/rss+xml" /> <atom:link href="https://fidonode.me/rss.xml" rel="self" type="application/rss+xml" />
<link>https://fidonode.me</link> <link>https://fidonode.me</link>
<description><![CDATA[]]></description> <description><![CDATA[Slice of my technical life]]></description>
<language>en</language> <language>en</language>
<pubDate>Sun, 07 Jul 2024 09:10:01 +0000</pubDate> <pubDate>Sat, 19 Oct 2024 16:09:51 +0000</pubDate>
<lastBuildDate>Sun, 07 Jul 2024 09:10:01 +0000</lastBuildDate> <lastBuildDate>Sat, 19 Oct 2024 16:09:51 +0000</lastBuildDate>
<generator>Emacs 27.1 Org-mode 9.3</generator> <generator>Emacs 29.3 Org-mode 9.6.15</generator>
<webMaster>iam@fidonode.me (Alex M)</webMaster> <webMaster>iam@fidonode.me (Alex M)</webMaster>
<image> <image>
<url>https://orgmode.org/img/org-mode-unicorn-logo.png</url> <url>https://fidonode.me/resources/images/index/avatar.jpg</url>
<title>rss</title> <title>Alex's M Personal Blog</title>
<link>https://fidonode.me</link> <link>https://fidonode.me</link>
</image> </image>
<item>
<title>Tag: @imagemagick</title>
<link>https://fidonode.me/tags/@imagemagick.html</link>
<author>iam@fidonode.me (Alex M)</author>
<guid isPermaLink="false">https://fidonode.me/tags/@imagemagick.html</guid>
<pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description>
</item>
<item>
<title>Tag: @diy</title>
<link>https://fidonode.me/tags/@diy.html</link>
<author>iam@fidonode.me (Alex M)</author>
<guid isPermaLink="false">https://fidonode.me/tags/@diy.html</guid>
<pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description>
</item>
<item>
<title>Tag: @org-mode</title>
<link>https://fidonode.me/tags/@org-mode.html</link>
<author>iam@fidonode.me (Alex M)</author>
<guid isPermaLink="false">https://fidonode.me/tags/@org-mode.html</guid>
<pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description>
</item>
<item>
<title>Tag: @keeb</title>
<link>https://fidonode.me/tags/@keeb.html</link>
<author>iam@fidonode.me (Alex M)</author>
<guid isPermaLink="false">https://fidonode.me/tags/@keeb.html</guid>
<pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description>
</item>
<item>
<title>Tag: @highlightjs</title>
<link>https://fidonode.me/tags/@highlightjs.html</link>
<author>iam@fidonode.me (Alex M)</author>
<guid isPermaLink="false">https://fidonode.me/tags/@highlightjs.html</guid>
<pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description>
</item>
<item>
<title>Tag: @tags</title>
<link>https://fidonode.me/tags/@tags.html</link>
<author>iam@fidonode.me (Alex M)</author>
<guid isPermaLink="false">https://fidonode.me/tags/@tags.html</guid>
<pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description>
</item>
<item>
<title>Tag: @elisp</title>
<link>https://fidonode.me/tags/@elisp.html</link>
<author>iam@fidonode.me (Alex M)</author>
<guid isPermaLink="false">https://fidonode.me/tags/@elisp.html</guid>
<pubDate>Sun, 07 Jul 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description>
</item>
<item> <item>
<title>Blog index and tags automation</title> <title>Blog index and tags automation</title>
<link>https://fidonode.me/posts/blog_index_and_tags_automation.html</link> <link>https://fidonode.me/posts/blog_index_and_tags_automation.html</link>
@ -95,7 +32,15 @@
<guid isPermaLink="false">https://fidonode.me/posts/blog_index_and_tags_automation.html</guid> <guid isPermaLink="false">https://fidonode.me/posts/blog_index_and_tags_automation.html</guid>
<pubDate>Fri, 05 Jul 2024 00:00:00 +0000</pubDate> <pubDate>Fri, 05 Jul 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description> <description><![CDATA[<p>
Let's add tags to blog posts
</p>
<p>
Tags are a nice and easy way to organize posts without explicit search. In the simplest way, you have a list of tags in posts, and each tag links to a page with all posts having the corresponding tag. It is also helpful to have a page with all tags available in the blog. And, of course, I don't want to maintain the list of tags manually.
Automate tags....
</p>
]]></description>
</item> </item>
<item> <item>
<title>Posts preview</title> <title>Posts preview</title>
@ -104,7 +49,15 @@
<guid isPermaLink="false">https://fidonode.me/posts/posts_preview.html</guid> <guid isPermaLink="false">https://fidonode.me/posts/posts_preview.html</guid>
<pubDate>Fri, 28 Jun 2024 00:00:00 +0000</pubDate> <pubDate>Fri, 28 Jun 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description> <description><![CDATA[<p>
Add post preview for OpenGraph cards
</p>
<p>
<a href="https://imagemagick.org">Imagemagick</a> is a ffmpeg of the image world. You can do a lot of fun things with it. For example you can take a picture, cut corners on it, place it on top of another image, add some text and get final result. So it is looks like a good tool for making previews from code.
Basic idea of this process...
</p>
]]></description>
</item> </item>
<item> <item>
<title>Improve code blocks</title> <title>Improve code blocks</title>
@ -113,7 +66,15 @@
<guid isPermaLink="false">https://fidonode.me/posts/improve_code_blocks.html</guid> <guid isPermaLink="false">https://fidonode.me/posts/improve_code_blocks.html</guid>
<pubDate>Tue, 25 Jun 2024 00:00:00 +0000</pubDate> <pubDate>Tue, 25 Jun 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description> <description><![CDATA[<p>
Use highlight.js for code syntax highlighting
</p>
<p>
Htmlize works poorly with headless publishing. It lacks extensibility, including features like line numbers, a copy button, and the ability to highlight predefined parts of the code.
Highlight.js...
</p>
]]></description>
</item> </item>
<item> <item>
<title>Org blog with RSS</title> <title>Org blog with RSS</title>
@ -122,7 +83,15 @@
<guid isPermaLink="false">https://fidonode.me/posts/add_rss_to_blog.html</guid> <guid isPermaLink="false">https://fidonode.me/posts/add_rss_to_blog.html</guid>
<pubDate>Sun, 23 Jun 2024 00:00:00 +0000</pubDate> <pubDate>Sun, 23 Jun 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description> <description><![CDATA[<p>
Let's add RSS feed to blog
</p>
<p>
RSS might seem like an outdated, marginal thing. But it still has at least one benefit—you can use an RSS feed as a sitemap for search engines. Plus, it's pretty geeky.
Add RSS feed...
</p>
]]></description>
</item> </item>
<item> <item>
<title>Org to HTML and back</title> <title>Org to HTML and back</title>
@ -131,7 +100,15 @@
<guid isPermaLink="false">https://fidonode.me/posts/about_blog.html</guid> <guid isPermaLink="false">https://fidonode.me/posts/about_blog.html</guid>
<pubDate>Sat, 22 Jun 2024 00:00:00 +0000</pubDate> <pubDate>Sat, 22 Jun 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description> <description><![CDATA[<p>
Blog post about publishing my blog with Org Mode
</p>
<p>
I'm neither proficient in Org Mode (further on "Org"), nor a good front-end engineer. I think that a simple solution is better than no solution. If you see a mistake, you can contact me via <a href="mailto:iam@fidonode.me">iam@fidonode.me</a>.
What is Org?...
</p>
]]></description>
</item> </item>
<item> <item>
<title>My keyboard journey</title> <title>My keyboard journey</title>
@ -140,7 +117,15 @@
<guid isPermaLink="false">https://fidonode.me/posts/keeb.html</guid> <guid isPermaLink="false">https://fidonode.me/posts/keeb.html</guid>
<pubDate>Wed, 05 Jun 2024 00:00:00 +0000</pubDate> <pubDate>Wed, 05 Jun 2024 00:00:00 +0000</pubDate>
<description><![CDATA[]]></description> <description><![CDATA[<p>
Blog post about my keyboards
</p>
<p>
Sometimes I think about the long journey I've made with keebs. In childhood, I had decent membrane keyboards, most of which had an ergonomic profile like the MS. Not sure if it somehow affected my taste because I started my career with the simplest, cheapest board and typed countless lines of code on such keebs. Then I heard about clickity-clack mechanical keyboards and decided to try one. It was a simple Chinese keeb with a thick metal body, double-shot caps, and Cherry Brown switches. A decent thing to annoy everyone around you. I think this purchase marked my dive into mech keebs
I'm not a geeky aficionado who thinks you can fix everything with a new keyboard, but I built a couple of them. I hope I've finally built the last one for quite some time....
</p>
]]></description>
</item> </item>
</channel> </channel>
</rss> </rss>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@diy.org.png"/><meta property="og:title" content="Tag: @diy"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @diy"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@diy.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @diy</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@diy.org.png"/><meta property="og:title" content="Tag: @diy"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @diy"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@diy.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @diy</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-org7808393" class="outline-2"> <div id="outline-container-org742916c" class="outline-2">
<h2 id="org7808393">@diy</h2> <h2 id="org742916c">@diy</h2>
<div class="outline-text-2" id="text-org7808393"> <div class="outline-text-2" id="text-org742916c">
</div> </div>
<div id="outline-container-orgfacd41a" class="outline-3"> <div id="outline-container-orga6d546f" class="outline-3">
<h3 id="orgfacd41a"><a href="../posts/keeb.html">My keyboard journey</a></h3> <h3 id="orga6d546f"><a href="../posts/keeb.html">My keyboard journey</a></h3>
<div class="outline-text-3" id="text-orgfacd41a"> <div class="outline-text-3" id="text-orga6d546f">
<p> <p>
Blog post about my keyboards Blog post about my keyboards
</p> </p>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@elisp.org.png"/><meta property="og:title" content="Tag: @elisp"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @elisp"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@elisp.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @elisp</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@elisp.org.png"/><meta property="og:title" content="Tag: @elisp"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @elisp"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@elisp.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @elisp</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-orgf0d2c0a" class="outline-2"> <div id="outline-container-org6cd2a90" class="outline-2">
<h2 id="orgf0d2c0a">@elisp</h2> <h2 id="org6cd2a90">@elisp</h2>
<div class="outline-text-2" id="text-orgf0d2c0a"> <div class="outline-text-2" id="text-org6cd2a90">
</div> </div>
<div id="outline-container-org98b2e7b" class="outline-3"> <div id="outline-container-orgb29dd49" class="outline-3">
<h3 id="org98b2e7b"><a href="../posts/posts_preview.html">Posts preview</a></h3> <h3 id="orgb29dd49"><a href="../posts/posts_preview.html">Posts preview</a></h3>
<div class="outline-text-3" id="text-org98b2e7b"> <div class="outline-text-3" id="text-orgb29dd49">
<p> <p>
Add post preview for OpenGraph cards Add post preview for OpenGraph cards
</p> </p>
@ -20,9 +20,9 @@ drafted on 2024-06-28
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-orgc3aee28" class="outline-3"> <div id="outline-container-orga3e9e64" class="outline-3">
<h3 id="orgc3aee28"><a href="../posts/improve_code_blocks.html">Improve code blocks</a></h3> <h3 id="orga3e9e64"><a href="../posts/improve_code_blocks.html">Improve code blocks</a></h3>
<div class="outline-text-3" id="text-orgc3aee28"> <div class="outline-text-3" id="text-orga3e9e64">
<p> <p>
Use highlight.js for code syntax highlighting Use highlight.js for code syntax highlighting
</p> </p>
@ -37,9 +37,9 @@ drafted on 2024-06-25
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-orgac3616a" class="outline-3"> <div id="outline-container-org93608eb" class="outline-3">
<h3 id="orgac3616a"><a href="../posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h3> <h3 id="org93608eb"><a href="../posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h3>
<div class="outline-text-3" id="text-orgac3616a"> <div class="outline-text-3" id="text-org93608eb">
<p> <p>
Let's add tags to blog posts Let's add tags to blog posts
</p> </p>
@ -54,9 +54,9 @@ drafted on 2024-07-05
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org749819f" class="outline-3"> <div id="outline-container-org13eea71" class="outline-3">
<h3 id="org749819f"><a href="../posts/add_rss_to_blog.html">Org blog with RSS</a></h3> <h3 id="org13eea71"><a href="../posts/add_rss_to_blog.html">Org blog with RSS</a></h3>
<div class="outline-text-3" id="text-org749819f"> <div class="outline-text-3" id="text-org13eea71">
<p> <p>
Let's add RSS feed to blog Let's add RSS feed to blog
</p> </p>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@highlightjs.org.png"/><meta property="og:title" content="Tag: @highlightjs"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @highlightjs"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@highlightjs.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @highlightjs</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@highlightjs.org.png"/><meta property="og:title" content="Tag: @highlightjs"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @highlightjs"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@highlightjs.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @highlightjs</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-org92172b5" class="outline-2"> <div id="outline-container-org418feb1" class="outline-2">
<h2 id="org92172b5">@highlightjs</h2> <h2 id="org418feb1">@highlightjs</h2>
<div class="outline-text-2" id="text-org92172b5"> <div class="outline-text-2" id="text-org418feb1">
</div> </div>
<div id="outline-container-orgab1af87" class="outline-3"> <div id="outline-container-orgd837fac" class="outline-3">
<h3 id="orgab1af87"><a href="../posts/improve_code_blocks.html">Improve code blocks</a></h3> <h3 id="orgd837fac"><a href="../posts/improve_code_blocks.html">Improve code blocks</a></h3>
<div class="outline-text-3" id="text-orgab1af87"> <div class="outline-text-3" id="text-orgd837fac">
<p> <p>
Use highlight.js for code syntax highlighting Use highlight.js for code syntax highlighting
</p> </p>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@imagemagick.org.png"/><meta property="og:title" content="Tag: @imagemagick"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @imagemagick"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@imagemagick.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @imagemagick</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@imagemagick.org.png"/><meta property="og:title" content="Tag: @imagemagick"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @imagemagick"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@imagemagick.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @imagemagick</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-orge20ef47" class="outline-2"> <div id="outline-container-orgdbba833" class="outline-2">
<h2 id="orge20ef47">@imagemagick</h2> <h2 id="orgdbba833">@imagemagick</h2>
<div class="outline-text-2" id="text-orge20ef47"> <div class="outline-text-2" id="text-orgdbba833">
</div> </div>
<div id="outline-container-org30557f5" class="outline-3"> <div id="outline-container-orged21164" class="outline-3">
<h3 id="org30557f5"><a href="../posts/posts_preview.html">Posts preview</a></h3> <h3 id="orged21164"><a href="../posts/posts_preview.html">Posts preview</a></h3>
<div class="outline-text-3" id="text-org30557f5"> <div class="outline-text-3" id="text-orged21164">
<p> <p>
Add post preview for OpenGraph cards Add post preview for OpenGraph cards
</p> </p>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@keeb.org.png"/><meta property="og:title" content="Tag: @keeb"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @keeb"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@keeb.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @keeb</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@keeb.org.png"/><meta property="og:title" content="Tag: @keeb"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @keeb"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@keeb.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @keeb</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-org75dfd14" class="outline-2"> <div id="outline-container-org0e28837" class="outline-2">
<h2 id="org75dfd14">@keeb</h2> <h2 id="org0e28837">@keeb</h2>
<div class="outline-text-2" id="text-org75dfd14"> <div class="outline-text-2" id="text-org0e28837">
</div> </div>
<div id="outline-container-orge7a4df4" class="outline-3"> <div id="outline-container-orgbb9dd14" class="outline-3">
<h3 id="orge7a4df4"><a href="../posts/keeb.html">My keyboard journey</a></h3> <h3 id="orgbb9dd14"><a href="../posts/keeb.html">My keyboard journey</a></h3>
<div class="outline-text-3" id="text-orge7a4df4"> <div class="outline-text-3" id="text-orgbb9dd14">
<p> <p>
Blog post about my keyboards Blog post about my keyboards
</p> </p>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@org-mode.org.png"/><meta property="og:title" content="Tag: @org-mode"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @org-mode"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@org-mode.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @org-mode</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@org-mode.org.png"/><meta property="og:title" content="Tag: @org-mode"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @org-mode"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@org-mode.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @org-mode</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-orgcb05e49" class="outline-2"> <div id="outline-container-org0ebb92c" class="outline-2">
<h2 id="orgcb05e49">@org-mode</h2> <h2 id="org0ebb92c">@org-mode</h2>
<div class="outline-text-2" id="text-orgcb05e49"> <div class="outline-text-2" id="text-org0ebb92c">
</div> </div>
<div id="outline-container-org532f1ed" class="outline-3"> <div id="outline-container-org4c37b93" class="outline-3">
<h3 id="org532f1ed"><a href="../posts/posts_preview.html">Posts preview</a></h3> <h3 id="org4c37b93"><a href="../posts/posts_preview.html">Posts preview</a></h3>
<div class="outline-text-3" id="text-org532f1ed"> <div class="outline-text-3" id="text-org4c37b93">
<p> <p>
Add post preview for OpenGraph cards Add post preview for OpenGraph cards
</p> </p>
@ -20,9 +20,9 @@ drafted on 2024-06-28
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org7add88d" class="outline-3"> <div id="outline-container-org21cf4da" class="outline-3">
<h3 id="org7add88d"><a href="../posts/improve_code_blocks.html">Improve code blocks</a></h3> <h3 id="org21cf4da"><a href="../posts/improve_code_blocks.html">Improve code blocks</a></h3>
<div class="outline-text-3" id="text-org7add88d"> <div class="outline-text-3" id="text-org21cf4da">
<p> <p>
Use highlight.js for code syntax highlighting Use highlight.js for code syntax highlighting
</p> </p>
@ -37,9 +37,9 @@ drafted on 2024-06-25
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-orgda26cc2" class="outline-3"> <div id="outline-container-orgd79bd92" class="outline-3">
<h3 id="orgda26cc2"><a href="../posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h3> <h3 id="orgd79bd92"><a href="../posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h3>
<div class="outline-text-3" id="text-orgda26cc2"> <div class="outline-text-3" id="text-orgd79bd92">
<p> <p>
Let's add tags to blog posts Let's add tags to blog posts
</p> </p>
@ -54,9 +54,9 @@ drafted on 2024-07-05
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org2d7148e" class="outline-3"> <div id="outline-container-orgc637e97" class="outline-3">
<h3 id="org2d7148e"><a href="../posts/add_rss_to_blog.html">Org blog with RSS</a></h3> <h3 id="orgc637e97"><a href="../posts/add_rss_to_blog.html">Org blog with RSS</a></h3>
<div class="outline-text-3" id="text-org2d7148e"> <div class="outline-text-3" id="text-orgc637e97">
<p> <p>
Let's add RSS feed to blog Let's add RSS feed to blog
</p> </p>
@ -71,9 +71,9 @@ drafted on 2024-06-23
</p> </p>
</div> </div>
</div> </div>
<div id="outline-container-org98e4fa2" class="outline-3"> <div id="outline-container-org56b406d" class="outline-3">
<h3 id="org98e4fa2"><a href="../posts/about_blog.html">Org to HTML and back</a></h3> <h3 id="org56b406d"><a href="../posts/about_blog.html">Org to HTML and back</a></h3>
<div class="outline-text-3" id="text-org98e4fa2"> <div class="outline-text-3" id="text-org56b406d">
<p> <p>
Blog post about publishing my blog with Org Mode Blog post about publishing my blog with Org Mode
</p> </p>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@rss.org.png"/><meta property="og:title" content="Tag: @rss"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @rss"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@rss.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @rss</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@rss.org.png"/><meta property="og:title" content="Tag: @rss"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @rss"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@rss.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @rss</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-org92ac227" class="outline-2"> <div id="outline-container-org17cdd99" class="outline-2">
<h2 id="org92ac227">@rss</h2> <h2 id="org17cdd99">@rss</h2>
<div class="outline-text-2" id="text-org92ac227"> <div class="outline-text-2" id="text-org17cdd99">
</div> </div>
<div id="outline-container-org4bc0f9a" class="outline-3"> <div id="outline-container-orgf908f6e" class="outline-3">
<h3 id="org4bc0f9a"><a href="../posts/add_rss_to_blog.html">Org blog with RSS</a></h3> <h3 id="orgf908f6e"><a href="../posts/add_rss_to_blog.html">Org blog with RSS</a></h3>
<div class="outline-text-3" id="text-org4bc0f9a"> <div class="outline-text-3" id="text-orgf908f6e">
<p> <p>
Let's add RSS feed to blog Let's add RSS feed to blog
</p> </p>

View File

@ -1,11 +1,11 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@tags.org.png"/><meta property="og:title" content="Tag: @tags"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @tags"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@tags.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @tags</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container"> <!DOCTYPE html><html lang="en"><head><meta charset="utf-8"/><meta author="Alex Mikhailov"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="color-scheme" content="light dark"/><meta http-equiv="content-language" content="en-us"/><meta name="description" content=""/><meta property="og:description" content=""/><meta property="og:image" content="https://fidonode.me/resources/images/preview/tags/@tags.org.png"/><meta property="og:title" content="Tag: @tags"/><meta name="twitter:description" content=""/><meta name="twitter:title" content="Tag: @tags"/><meta name="twitter:image" content="https://fidonode.me/resources/images/preview/tags/@tags.org.png"/><meta name="twitter:card" content="summary_large_image"/><link rel="icon" type="image/x-icon" href="/resources/favicon.ico"/><link rel="stylesheet" type="text/css" href="/resources/css/pico.sand.min.css"/><script defer="true" src="https://umami.dokutsu.xyz/script.js" data-website-id="d52d9af1-0c7d-4531-84c6-0b9c2850011f"></script><title>Tag: @tags</title></head><body><header class="header"><div class="container"><nav><ul><li><strong>Alex Mikhailov</strong></li></ul><ul><li><a href="/index.html">About</a></li><li><a href="/posts.html">Blog</a></li><li><a href="/rss.xml">RSS</a></li></ul></nav></div></header><main class="container">
<div id="outline-container-org485f3d6" class="outline-2"> <div id="outline-container-org7c64e9e" class="outline-2">
<h2 id="org485f3d6">@tags</h2> <h2 id="org7c64e9e">@tags</h2>
<div class="outline-text-2" id="text-org485f3d6"> <div class="outline-text-2" id="text-org7c64e9e">
</div> </div>
<div id="outline-container-org8892cfd" class="outline-3"> <div id="outline-container-org9ae829f" class="outline-3">
<h3 id="org8892cfd"><a href="../posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h3> <h3 id="org9ae829f"><a href="../posts/blog_index_and_tags_automation.html">Blog index and tags automation</a></h3>
<div class="outline-text-3" id="text-org8892cfd"> <div class="outline-text-3" id="text-org9ae829f">
<p> <p>
Let's add tags to blog posts Let's add tags to blog posts
</p> </p>