main
  1<!DOCTYPE html>
  2<html lang="en">
  3 <head>
  4  <meta name="viewport" content="width=device-width, initial-scale=1">
  5  <meta charset="utf-8">
  6  <meta name="viewport" content="width=device-width, initial-scale=1">
  7  <title>
  8   Migrating to an org-mode website
  9  </title>
 10  <meta name="author" content="Vincent Demeester">
 11  <meta name="generator" content="Org Mode">
 12  <meta name="viewport" content="width=device-width, initial-scale=1">
 13  <link href="/index.xml" rel="alternate" type="application/rss+xml" title="Vincent Demeester">
 14  <script src="/flux.js" defer=""></script>
 15  <link rel="stylesheet" href="/style.css" type="text/css">
 16 </head>
 17 <body>
 18  <div class="site-controls">
 19   <button class="theme-toggle" id="theme-toggle" title="Toggle dark/light mode">☀️</button>
 20  </div>
 21  <main id="content" class="content">
 22   <header>
 23    <h1 class="title">
 24     Migrating to an org-mode website
 25    </h1>
 26   </header>
 27   <section id="outline-container-introduction" class="outline-2">
 28    <h2 id="introduction">
 29     <a href="#introduction" class="anchor">§</a>Introduction
 30    </h2>
 31    <div id="text-introduction" class="outline-text-2">
 32     <p>
 33      This is a story… a story of me changing the way I code and publish my website. In the
 34past, I’ve switch from <a href="https://vincent.demeester.fr/posts/2012-05-07-reinit-and-jekyll/">Jekyll</a> to <a href="https://vincent.demeester.fr/posts/2015-05-01-orgmode-et-jekyll/"><code>orgmode</code> and Jekyll”</a> to <a href="https://vincent.demeester.fr/posts/2015-05-09-migration-to-hugo/">Hugo</a> (sorry those are written
 35in french). The past year, I’ve written and documented myself a little bit about
 36<a href="https://www.theminimalists.com/minimalism/">minimalism</a> and <a href="https://www.goodreads.com/book/show/40672036-digital-minimalism">digital minimalism</a>. Although I don’t see myself as a minimalist, it helped
 37me realize some issues I had.
 38     </p>
 39     <p>
 40      I also realized if I want to write more, I need to lower the barrier between writing and
 41publishing my content ; <i>if I want it to be published, of course</i>. This <i>post</i> is about
 42what I’m putting in place for this, with a premise : I spend my life in <a href="https://www.gnu.org/software/emacs/">Emacs</a> and thus in
 43<a href="https://orgmode.org/"><code>orgmode</code></a>. And <a href="https://orgmode.org/"><code>orgmode</code></a> is feature-full and has this badass feature : <code>org-publish</code>.
 44     </p>
 45     <p>
 46      To build and publish this website, we will <i>try</i> to rely on a reproducible setup, meaning
 47<a href="https://www.gnu.org/software/emacs/">Emacs</a> and <a href="https://orgmode.org/"><code>orgmode</code></a> of course, <a href="https://www.gnu.org/software/make/">GNU Make</a> of course <b>but</b> most importantly, <a href="https://nixos.org/nix/">Nix</a> (in the near
 48future 👼).
 49     </p>
 50     <div class="drawer update">
 51      <h6>
 52       Update
 53      </h6>
 54      <p>
 55       There is now an article about it, that uses literate programming: <a href="../articles/meta_publishing_this_website.html">publishing this
 56website</a>. The content of the post might no be up-to-date at some point.
 57      </p>
 58     </div>
 59    </div>
 60   </section>
 61   <section id="outline-container-requirements" class="outline-2">
 62    <h2 id="requirements">
 63     <a href="#requirements" class="anchor">§</a>Requirements
 64    </h2>
 65    <div id="text-requirements" class="outline-text-2">
 66     <p>
 67      Let’s list the requirements I feel I have for my website:
 68     </p>
 69     <dl class="org-dl">
 70      <dt>
 71       Full control over the URL of the published posts.
 72      </dt>
 73      <dd>
 74       This is a golden rule of the web: should I change the publishing system, I want to be
 75able to stick to the same URLs or else all external references would be broken. This is
 76a big no-no and in my opinion it makes most blogging systems unacceptable.
 77      </dd>
 78      <dt>
 79       Top-notch Org support.
 80      </dt>
 81      <dd>
 82       I believe generators like Jekyll and Hugo only have partial Org support. You end up
 83requiring some conversion tooling to get the job done.
 84      </dd>
 85      <dt>
 86       Simple publishing pipeline.
 87      </dt>
 88      <dd>
 89       I want the generation process to be as simple as possible. This is important for
 90maintenance. Should I someday switch host, I want to be sure that I can set up the same
 91pipeline.
 92      </dd>
 93      <dt>
 94       Full control over the publishing system.
 95      </dt>
 96      <dd>
 97       I want maximum control over the generation process. I don’t want to be restricted by a
 98non-Turing-complete configuration file or a dumb programming language.
 99      </dd>
100      <dt>
101       Ease of use.
102      </dt>
103      <dd>
104       The process as a whole must be as immediate and friction-less as possible, or else I
105take the risk of feeling too lazy to publish new posts and update the content.
106      </dd>
107      <dt>
108       Hackability.
109      </dt>
110      <dd>
111       Last but not least, and this probably supersedes all other requirements: The system must
112be hackable. Lisp-based systems are prime contenders in that area.
113      </dd>
114     </dl>
115    </div>
116   </section>
117   <section id="outline-container-done-organizing" class="outline-2">
118    <h2 id="done-organizing">
119     <a href="#done-organizing" class="anchor">§</a><span class="done DONE">DONE</span> Organizing
120    </h2>
121    <div id="text-done-organizing" class="outline-text-2">
122     <div class="drawer logbook">
123      <h6>
124       Logbook
125      </h6>
126      <ul class="org-ul">
127       <li>
128        State “DONE”       from “TODO”       <span class="timestamp-wrapper"><span class="timestamp">[2020-03-21 Sat 17:57]</span></span>
129       </li>
130      </ul>
131     </div>
132     <p>
133      Let’s describe what I do want to publish here:
134     </p>
135     <dl class="org-dl">
136      <dt>
137       Posts
138      </dt>
139      <dd>
140       this is what we call <i>blog</i> these days : short to medium article that are valid
141at a point of time, as may contain <i>deprecated</i> content, or content that do not reflect
142my views at a later point in time.
143      </dd>
144      <dt>
145       Articles
146      </dt>
147      <dd>
148       medium to long article about a topic. Those should be up-to-date or
149explicitly mark as deprecated or invalid. <i>In a ideal world this is my <b>ready for the
150public</b> knowledge database, a bit like <a href="https://braindump.jethro.dev/">Jethro’s Braindump</a></i>.
151      </dd>
152      <dt>
153       Configurations
154      </dt>
155      <dd>
156       medium to long article about my configurations. Those are base on my
157<code>home</code> <i>configuration</i> mono-repository, and usually follow literate programming
158principles.
159      </dd>
160      <dt>
161       About
162      </dt>
163      <dd>
164       an about page about the author of the website (aka <a href="https://vincent.demeester.fr">me</a>), linking external
165contributions (GitHub/Gitlab/… profiles, Talks, …).
166      </dd>
167     </dl>
168    </div>
169   </section>
170   <section id="outline-container-done-publishing" class="outline-2">
171    <h2 id="done-publishing">
172     <a href="#done-publishing" class="anchor">§</a><span class="done DONE">DONE</span> Publishing
173    </h2>
174    <div id="text-done-publishing" class="outline-text-2">
175     <div class="drawer logbook">
176      <h6>
177       Logbook
178      </h6>
179      <ul class="org-ul">
180       <li>
181        State “DONE”       from “TODO”       <span class="timestamp-wrapper"><span class="timestamp">[2020-03-25 Wed 15:54]</span></span>
182       </li>
183      </ul>
184     </div>
185     <p>
186      As said above, the goal is to publish everything using only <a href="https://www.gnu.org/software/emacs/">Emacs</a> and <a href="https://orgmode.org/"><code>orgmode</code></a> (with the
187help of some standard GNU tools).
188     </p>
189     <p>
190      The <a href="file:///home/vincent/src/sbr/publish.el"><code>publish.el</code></a> file is where all the magic happens:
191     </p>
192     <ul class="org-ul">
193      <li>
194       <p>
195        I want to generate something that is <code>html5</code> (almost?). The <i>preamble</i>, <i>content</i> and
196<i>postamble</i> <code>div</code> can be customized using <code>org-html-div</code>. Same goes for the <i>container</i>
197element that is used for “wrapping top level sections”, it is customized using
198<code>org-html-container-helement</code> (we want <code>&lt;section&gt;</code>). There is a few additional variable
199that I might document one day 😛.
200       </p>
201       <div class="org-src-container">
202        <pre class="src src-emacs-lisp">(setq org-export-use-babel nil)
203(setq org-link-abbrev-alist '(("att" . org-attach-expand-link)))
204
205;; setting to nil, avoids "Author: x" at the bottom
206(setq org-export-with-section-numbers nil
207      org-export-with-smart-quotes t
208      org-export-with-toc nil)
209
210(defvar sbr-date-format "%b %d, %Y")
211
212(setq org-html-divs '((preamble "header" "top")
213                      (content "main" "content")
214                      (postamble "footer" "postamble"))
215      org-html-container-element "section"
216      org-html-metadata-timestamp-format sbr-date-format
217      org-html-checkbox-type 'unicode
218      org-html-html5-fancy t
219      org-html-doctype "html5"
220      org-html-htmlize-output-type 'css
221      org-html-htmlize-font-prefix "org-"
222      org-src-fontify-natively t
223      org-html-coding-system 'utf-8-unix)
224</pre>
225       </div>
226      </li>
227      <li>
228       Part of the <code>&lt;head&gt;</code>, preamble and postamble are customized for the website.
229       <dl class="org-dl">
230        <dt>
231         <code>head</code>
232        </dt>
233        <dd>
234         <div class="org-src-container">
235          <pre class="src src-emacs-lisp">(defvar sbr-website-html-head
236  "&lt;link rel='icon' type='image/x-icon' href='/images/favicon.ico'/&gt;
237&lt;meta name='viewport' content='width=device-width, initial-scale=1'&gt;
238&lt;link rel='stylesheet' href='/css/new.css' type='text/css'/&gt;
239&lt;link rel='stylesheet' href='/css/syntax.css' type='text/css'/&gt;
240&lt;link href='/index.xml' rel='alternate' type='application/rss+xml' title='Vincent Demeester' /&gt;")
241</pre>
242         </div>
243        </dd>
244        <dt>
245         premable
246        </dt>
247        <dd>
248         <div class="org-src-container">
249          <pre class="src src-emacs-lisp">(defun sbr-website-html-preamble (plist)
250  "PLIST: An entry."
251  ;; Skip adding subtitle to the post if :KEYWORDS don't have 'post' has a
252  ;; keyword
253  (when (string-match-p "post" (format "%s" (plist-get plist :keywords)))
254    (plist-put plist
255               :subtitle (format "Published on %s by %s."
256                                 (org-export-get-date plist sbr-date-format)
257                                 (car (plist-get plist :author)))))
258
259  ;; Below content will be added anyways
260  "&lt;nav&gt;
261&lt;img src=\"/images/favicon.ico\" id=\"sitelogo\"/&gt; &lt;a href='/'&gt;home&lt;/a&gt; /
262&lt;a href='/posts/'&gt;posts&lt;/a&gt; (&lt;a href='/index.xml'&gt;rss&lt;/a&gt;) /
263&lt;a href='/articles/'&gt;articles&lt;/a&gt; /
264&lt;a href='/configurations/'&gt;configurations&lt;/a&gt; /
265&lt;a href='https://dl.sbr.pm/'&gt;files&lt;/a&gt; /
266&lt;a href='/about/'&gt;about&lt;/a&gt;&lt;/li&gt;
267&lt;/nav&gt;")
268</pre>
269         </div>
270        </dd>
271        <dt>
272         postamble
273        </dt>
274        <dd>
275         <div class="org-src-container">
276          <pre class="src src-emacs-lisp">(defvar sbr-website-html-postamble
277  "&lt;footer&gt;
278     &lt;span class='questions'&gt;Questions, comments ? Please use my &lt;a href=\"https://lists.sr.ht/~vdemeester/public-inbox\"&gt;public inbox&lt;/a&gt; by sending a plain-text email to &lt;a href=\"mailto:~vdemeester/public-inbox@lists.sr.ht\"&gt;~vdemeester/public-inbox@lists.sr.ht&lt;/a&gt;.&lt;/span&gt;
279     &lt;span class='opinions'&gt;Opinions stated here are my own and do not express the views of my employer, spouse, children, pets, neighbors, secret crushes, favorite authors, or anyone else who is not me. And maybe not even me, depending on how old this is.&lt;/span&gt;
280     &lt;span class='copyright'&gt;
281      Content and design by Vincent Demeester
282      (&lt;a rel='licence' href='http://creativecommons.org/licenses/by-nc-sa/3.0/'&gt;Some rights reserved&lt;/a&gt;)
283    &lt;/span&gt;&lt;br /&gt;
284    &lt;span class='engine'&gt;
285      Powered by &lt;a href='https://www.gnu.org/software/emacs/'&gt;Gnu Emacs&lt;/a&gt; and &lt;a href='https://orgmode.org'&gt;orgmode&lt;/a&gt;
286    &lt;/span&gt;
287&lt;/footer&gt;")
288</pre>
289         </div>
290        </dd>
291       </dl>
292      </li>
293      <li>
294       <p>
295        <code>orgmode</code> is able to generate a site-map. This is what we are going to use to generate
296the index files for <code>posts/</code> and <code>articles</code> mainly.
297       </p>
298       <div class="org-src-container">
299        <pre class="src src-emacs-lisp">(defun sbr/org-sitemap-format-entry (entry style project)
300  "Format posts with author and published data in the index page.
301
302ENTRY: file-name
303STYLE:
304PROJECT: `posts in this case."
305  (cond ((not (directory-name-p entry))
306         (format "%s — [[file:%s][%s]]
307                 :PROPERTIES:
308                 :PUBDATE: [%s]
309                 :END:"
310                 (format-time-string "%Y-%m-%d"
311                                     (org-publish-find-date entry project))
312                 entry
313                 (org-publish-find-title entry project)
314                 (format-time-string "%Y-%m-%d"
315                                     (org-publish-find-date entry project))))
316        ((eq style 'tree) (file-name-nondirectory (directory-file-name entry)))
317        (t entry)))
318
319(defun sbr/org-publish-sitemap (title list)
320  ""
321  (concat "#+TITLE: " title "\n\n"
322          (org-list-to-subtree list)))
323</pre>
324       </div>
325      </li>
326      <li>
327       <p>
328        <code>orgmode</code> is able to generate a rss, with <code>ox-rss</code>. This is what we are going to use to
329generate the rss files for <code>posts</code> and <code>articles</code>. This is <span class="underline">heavily</span> customized.
330       </p>
331       <div class="org-src-container">
332        <pre class="src src-emacs-lisp">(defun sbr/org-get-first-paragraph (file)
333  "Get string content of first paragraph of file."
334  (ignore-errors
335    (with-temp-buffer
336    (insert-file-contents file)
337    (goto-char (point-min))
338    (show-all)
339    (let ((first-begin (progn
340                         (org-forward-heading-same-level 1)
341                         (next-line)
342                         (point)))
343          (first-end (progn
344                       (org-next-visible-heading 1)
345                       (point))))
346      (buffer-substring first-begin first-end)))))
347
348(defun sbr/org-rss-publish-to-rss (plist filename pub-dir)
349  "Prepare rss.org file before exporting."
350  (let* ((postsdir (plist-get plist :base-directory)))
351    (with-current-buffer (find-file filename)
352      (erase-buffer)
353      (insert "#+TITLE: Posts\n")
354      (insert "#+AUTHOR: Vincent Demeester\n")
355      (insert "#+OPTIONS: toc:nil\n")
356      (let* ((files-all
357              (reverse (directory-files "." nil
358                                        "[0-9-]+.*\\.org$")))
359             (files (subseq files-all 0 (min (length files-all) 30))))
360        (message (format "foo: %s" filename))
361        (dolist (post files)
362          (let* ((post-file post)
363                 (post-title (org-publish-find-title post-file plist))
364                 (preview-str (sbr/org-get-first-paragraph post-file))
365                 (date (replace-regexp-in-string
366                        "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)-.*"
367                        "\\1" post)))
368            (insert (concat "* [[file:" postsdir "/" post "][" post-title "]]\n\n"))
369            (org-set-property "ID" post)
370            (org-set-property "RSS_TITLE" post-title)
371            ;; ox-rss prepends html-link-home to permalink
372            (org-set-property "RSS_PERMALINK"
373                              (concat postsdir "/"
374                                      (file-name-sans-extension post)
375                                      ".html"))
376            (org-set-property
377             "PUBDATE"
378             (format-time-string
379              "&lt;%Y-%m-%d %a %H:%M&gt;"
380              (org-time-string-to-time
381               (replace-regexp-in-string
382                "\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)-.*"
383                "\\1" post))))
384            (insert preview-str)
385            (newline 1)
386            (insert (concat "[[file:" postsdir "/" post "][(Read more)]]\n\n"))))
387        (save-buffer))))
388  (let ((user-mail-address "t")
389        (org-export-with-broken-links t)
390        (org-rss-use-entry-url-as-guid nil))
391    (org-rss-publish-to-rss plist filename pub-dir)))
392</pre>
393       </div>
394      </li>
395      <li>
396       <p>
397        Finally let’s set the <code>org-publish-project-alist</code> to publish our projects
398       </p>
399       <div class="org-src-container">
400        <pre class="src src-emacs-lisp">(setq org-publish-project-alist
401      `(("posts"
402         :base-directory "posts"
403         :base-extension "org"
404         :recursive t
405         :publishing-function org-html-publish-to-html
406         :publishing-directory "./public/posts"
407         :exclude ,(regexp-opt '("README.org" "draft"))
408         :auto-sitemap t
409         :with-footnotes t
410         :with-toc nil
411         :with-drawers t
412         :sitemap-filename "index.org"
413         :sitemap-title "Posts"
414         :sitemap-format-entry sbr/org-sitemap-format-entry
415         :sitemap-style list
416         :sitemap-sort-files anti-chronologically
417         :sitemap-function sbr/org-publish-sitemap
418         :html-head-include-scripts nil
419         :html-head-include-default-style nil
420         :html-head ,sbr-website-html-head
421         :html-preamble sbr-website-html-preamble
422         :html-postamble ,sbr-website-html-postamble)
423        ("posts-rss"
424         :base-directory "posts"
425         :base-extension "org"
426         :recursive t
427         :html-link-home "https://vincent.demeester.fr/"
428         :rss-link-home "https://vincent.demeester.fr/posts/"
429         :html-link-use-abs-url t
430         :rss-extension "xml"
431         :publishing-directory "./public"
432         :publishing-function (sbr/org-rss-publish-to-rss)
433         :section-number nil
434         :exclude ".*"
435         :include ("index.org"))
436        ("articles"
437         :base-directory "articles"
438         :base-extension "org"
439         :recursive t
440         :publishing-function org-html-publish-to-html
441         :publishing-directory "./public/articles"
442         :exclude ,(regexp-opt '("README.org" "draft"))
443         :auto-sitemap t
444         :with-footnotes t
445         :with-toc nil
446         :with-drawers t
447         :sitemap-filename "sitemap.org"
448         :sitemap-title "Articles"
449         :sitemap-style tree
450         :sitemap-sort-files anti-chronologically
451         ;;:sitemap-format-entry sbr/org-sitemap-format-entry
452         ;;:sitemap-function sbr/org-publish-sitemap
453         :html-head-include-scripts nil
454         :html-head-include-default-style nil
455         :html-head ,sbr-website-html-head
456         :html-preamble sbr-website-html-preamble
457         :html-postamble ,sbr-website-html-postamble)
458        ("articles-assets"
459         :exclude ,(regexp-opt '("*.org"))
460         :base-directory "articles"
461         :base-extension ,site-attachments
462         :publishing-directory "./public/articles"
463         :publishing-function org-publish-attachment
464         :recursive t)
465        ("about"
466         :base-directory "about"
467         :base-extension "org"
468         :exclude ,(regexp-opt '("README.org" "draft"))
469         :index-filename "index.org"
470         :recursive nil
471         :with-footnotes t
472         :with-toc nil
473         :with-drawers t
474         :publishing-function org-html-publish-to-html
475         :publishing-directory "./public/about"
476         :html-head-include-scripts nil
477         :html-head-include-default-style nil
478         :html-head ,sbr-website-html-head
479         :html-preamble sbr-website-html-preamble
480         :html-postamble ,sbr-website-html-postamble)
481        ("index"
482         :base-directory ""
483         :base-extension "org"
484         :exclude ,(regexp-opt '("README.org" "draft"))
485         :index-filename "index.org"
486         :recursive nil
487         :with-footnotes t
488         :with-toc nil
489         :with-drawers t
490         :with-title nil
491         :publishing-function org-html-publish-to-html
492         :publishing-directory "./public"
493         :html-head-include-scripts nil
494         :html-head-include-default-style nil
495         :html-head ,sbr-website-html-head
496         :html-preamble sbr-website-html-preamble
497         :html-postamble ,sbr-website-html-postamble)
498        ("css"
499         :base-directory "./css"
500         :base-extension ,site-attachments
501         :recursive t
502         :publishing-directory "./public/css"
503         :publishing-function org-publish-attachment
504         :recursive t)
505        ("images"
506         :base-directory "./images"
507         :base-extension ,site-attachments
508         :publishing-directory "./public/images"
509         :publishing-function org-publish-attachment
510         :recursive t)
511        ("assets"
512         :base-directory "./assets"
513         :base-extension ,site-attachments
514         :publishing-directory "./public/assets"
515         :publishing-function org-publish-attachment
516         :recursive t)
517        ("legacy"
518         :base-directory "./legacy"
519         :base-extension ,site-attachments
520         :publishing-directory "./public/"
521         :publishing-function org-publish-attachment
522         :recursive t)
523        ("all" :components ("posts" "about" "index" "articles" "articles-assets" "css" "images" "assets" "legacy" "posts-rss"))))
524</pre>
525       </div>
526      </li>
527     </ul>
528     <p>
529      Here are some <i>inspiration</i> I took for this publishing code:
530     </p>
531     <ul class="org-ul">
532      <li>
533       <a href="https://thibaultmarin.github.io/blog/posts/2016-11-13-Personal_website_in_org.html">Personal website in org</a>
534      </li>
535      <li>
536       <a href="https://vicarie.in/posts/blogging-with-org.html">Blogging with Org publishing</a>
537      </li>
538      <li>
539       <a href="https://ambrevar.xyz/blog-architecture/">A blog in pure Org/Lisp</a>
540      </li>
541      <li>
542       <a href="https://zngguvnf.org/2017-07-13--blogging-with-org-static-blog.html">Blogging with org-static-blog</a>
543      </li>
544      <li>
545       <a href="https://bastibe.de/2013-11-13-blogging-with-emacs.html">Blogging with Emacs</a>
546      </li>
547      <li>
548       <a href="https://gjhenrique.com/meta.html">Blogging with org-mode and Gitlab Pages</a>
549      </li>
550     </ul>
551    </div>
552   </section>
553   <section id="outline-container-done-styling" class="outline-2">
554    <h2 id="done-styling">
555     <a href="#done-styling" class="anchor">§</a><span class="done DONE">DONE</span> Styling
556    </h2>
557    <div id="text-done-styling" class="outline-text-2">
558     <div class="drawer logbook">
559      <h6>
560       Logbook
561      </h6>
562      <ul class="org-ul">
563       <li>
564        State “DONE”       from “STARTED”    <span class="timestamp-wrapper"><span class="timestamp">[2020-03-23 Mon 19:02]</span></span>
565       </li>
566      </ul>
567     </div>
568     <p>
569      The style of the website has be as simple as possible, and also really light. This means:
570     </p>
571     <ul class="org-ul">
572      <li>
573       use default system font as much as possible
574      </li>
575      <li>
576       have a small stylesheet, rely on the default as much as we can
577      </li>
578     </ul>
579     <p>
580      In addition, I want support for:
581     </p>
582     <ul class="org-ul">
583      <li>
584       side notes
585      </li>
586      <li>
587       code syntax highlight
588      </li>
589      <li>
590       table of content
591      </li>
592     </ul>
593     <p>
594      The inspiration for this website, in term of style are the following:
595     </p>
596     <ul class="org-ul">
597      <li>
598       <a href="https://vincent.demeester.fr/posts/2018-08-16-gotest-tools-assertions/">Vincent Demeester</a>
599      </li>
600      <li>
601       <a href="https://braindump.jethro.dev/zettels/zettelkasten/">Jethro’s Braindump</a>
602      </li>
603      <li>
604       <a href="https://hamberg.no/gtd/">GTD in 15 minutes – A Pragmatic Guide to Getting Things Done</a>
605      </li>
606      <li>
607       <a href="https://www.inkandswitch.com/local-first.html">Local-first software: You own your data, in spite of the cloud</a>
608      </li>
609      <li>
610       <a href="https://archive.casouri.cat/note/2018/blog-in-org-mode-revisited/index.html">Blog in Org Mode, Revisited</a>
611      </li>
612      <li>
613       <a href="https://kind.sigs.k8s.io/">kind</a>
614      </li>
615      <li>
616       <a href="http://willcrichton.net/notes/idioms-of-dynamic-languages/">Idioms of Dynamic Languages | Will Crichton</a>
617      </li>
618      <li>
619       <a href="https://peter.bourgon.org/blog/2019/09/11/programming-with-errors.html">Peter Bourgon · Programming with errors</a>
620      </li>
621      <li>
622       <a href="https://johv.dk/blog/bare-metal-assembly-tutorial.html">Getting started with bare-metal assembly — Jonas Hvid</a>
623      </li>
624     </ul>
625     <p>
626      To be able to define the style a bit, let’s try some things below. From this point on,
627this is random content just to try my style out. 👼
628     </p>
629     <p>
630      There is more in <a href="../articles/sandbox.html">the sandbox</a>.
631     </p>
632     <hr>
633     <div class="abstract" id="org026d63b">
634      <p>
635       Let’s dig into how I setup my development environment when working on <code>tektoncd/pipeline</code>
636      </p>
637     </div>
638     <nav id="table-of-contents" role="doc-toc">
639      <h2 id="table-of-contents">
640       <a href="#table-of-contents" class="anchor">§</a>Table of Contents
641      </h2>
642      <div id="text-table-of-contents" role="doc-toc">
643       <ul>
644        <li>
645         <a href="#Introduction">Introduction</a>
646        </li>
647        <li>
648         <a href="#Requirements">Requirements</a>
649        </li>
650        <li>
651         <a href="#Organizing"><span class="done DONE">DONE</span> Organizing</a>
652        </li>
653        <li>
654         <a href="#Publishing"><span class="done DONE">DONE</span> Publishing</a>
655        </li>
656        <li>
657         <a href="#Styling"><span class="done DONE">DONE</span> Styling</a>
658         <ul>
659          <li>
660           <a href="#sub-heading%201">sub-heading 1</a>
661          </li>
662          <li>
663           <a href="#sub-heading%202">sub-heading 2</a>
664          </li>
665         </ul>
666        </li>
667        <li>
668         <a href="#What%27s%20next%20%3F">What’s next ?</a>
669        </li>
670       </ul>
671      </div>
672     </nav>
673    </div>
674    <div id="outline-container-sub-heading%201" class="outline-3">
675     <h3 id="sub-heading-1">
676      <a href="#sub-heading-1" class="anchor">§</a>sub-heading 1
677     </h3>
678     <div id="text-sub-heading-1" class="outline-text-3">
679      <p>
680       Checking for errors is <b>very common</b> in Go, having <code>Comparison</code> function for it was a requirement.
681      </p>
682      <aside id="org13d2778">
683       <p>
684        This is a side note. If collection is a string, item must also be a string, and is
685compared using <code>strings.Contains()</code>. If collection is a Map, contains will succeed if item
686is a key in the map.
687       </p>
688      </aside>
689      <ul class="org-ul">
690       <li>
691        <code>Error</code> fails if the error is <code>nil</code> <b>or</b> the error message is not the expected one.
692       </li>
693       <li>
694        <code>ErrorContains</code> fails if the error is <code>nil</code> <b>or</b> the error message does not contain the expected substring.
695       </li>
696       <li>
697        <code>ErrorType</code> fails if the error is <code>nil</code> <b>or</b> the error type is not the expected type.
698       </li>
699      </ul>
700      <p>
701       Let’s first look at the most used : <code>Error</code> and <code>ErrorContains</code>.
702When you’re working on <code>pipeline</code>, usually you want :
703      </p>
704      <ol class="org-ol">
705       <li>
706        make sure it compiles : <code>go build -v ./..</code>
707       </li>
708       <li>
709        Running unit tests : <code>go test ./...</code> (bonus use <a href="https://github.com/vdemeester/ram"><code>ram</code></a> for continuous testing)
710       </li>
711       <li>
712        <p>
713         End-to-end tests : <code>go test -tags e2e ./...</code> (or simply using `./test/` package)
714        </p>
715        <p>
716         <b>Make sure you re-deploy before running the e2e tests</b> using <code>ko apply -f ./config</code>,
717otherwise you’re testing the wrong code.
718        </p>
719       </li>
720      </ol>
721      <div class="org-src-container">
722       <pre class="src src-go">var err error
723// will fail with : expected an error, got nil
724assert.Check(t, cmp.Error(err, "message in a bottle"))
725err = errors.Wrap(errors.New("other"), "wrapped")
726// will fail with : expected error "other", got "wrapped: other"
727assert.Check(t, cmp.Error(err, "other"))
728// will succeed
729assert.Check(t, cmp.ErrorContains(err, "other"))
730</pre>
731      </div>
732      <figure id="org202916a">
733       <img src="../images/emacs/2020-02-29-13-46-08.png" alt="2020-02-29-13-46-08.png" width="100%">
734       <figcaption>
735        <span class="figure-number">Figure 1: </span>This is the caption for the next figure link (or table)
736       </figcaption>
737      </figure>
738      <p>
739       If this is the case, then what makes dynamic languages feel easy? Can we take what we learn in answering this question and improve the ergonomics of our static languages? For example, in 2018, I don’t think there’s as strong an argument for “you don’t have to write out the types,” since modern type inference eliminates most of the keystrokes required (even though many major languages still lack such facilities). Plus, saving a few keystrokes does not seem like a critical bottleneck in the programming process.
740      </p>
741      <figure id="org079eac9">
742       <img src="../images/emacs/2020-02-29-14-41-59.png" alt="2020-02-29-14-41-59.png">
743      </figure>
744     </div>
745    </div>
746    <div id="outline-container-sub-heading%202" class="outline-3">
747     <h3 id="sub-heading-2">
748      <a href="#sub-heading-2" class="anchor">§</a>sub-heading 2
749     </h3>
750     <div id="text-sub-heading-2" class="outline-text-3">
751      <p>
752       Some content from my other org-mode files.
753      </p>
754      <div class="description" id="orga53ead1">
755       <p>
756        I already wrote 2 previous posts about golang and testing. It’s something I care deeply about and I wanted to continue
757writing about it. It took me a bit more time than I thought, but getting back to it. Since the <a href="http://vincent.demeester.fr/posts/2017-04-22-golang-testing-golden-file/">last post</a>, Daniel
758Nephin
759and I worked (but mainly Daniel 🤗) on bootstrapping a testing helper library.
760       </p>
761      </div>
762      <blockquote>
763       <p>
764        Package assert provides assertions for comparing expected values to actual values. When
765assertion fails a helpful error message is printed.
766       </p>
767      </blockquote>
768      <p>
769       There is already some good <code>testing</code> helpers in the Go ecosystem : <a href="https://github.com/stretchr/testify"><code>testify</code></a>, <a href="http://labix.org/gocheck"><code>gocheck</code></a>,
770<a href="https://github.com/onsi/ginkgo"><code>ginkgo</code></a> and a lot more — so why create a new one ? There is multiple reason for it, most
771of them can be seen in the following <a href="https://github.com/gotestyourself/gotest.tools/issues/49#issuecomment-362436026">GitHub issue</a>.
772      </p>
773      <p>
774       <a href="https://github.com/dnephin/">Daniel</a> also wrote a very useful <sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup>converter if your code base is currently using <code>testify</code> :
775<code>gty-migrate-from-testify</code>.
776      </p>
777      <div class="org-src-container">
778       <pre class="src src-sh">$ go get -u gotest.tools/assert/cmd/gty-migrate-from-testify
779# […]
780$ go list \
781     -f '{{.ImportPath}} {{if .XTestGoFiles}}{{"\n"}}{{.ImportPath}}_test{{end}}' \
782     ./... | xargs gty-migrate-from-testify
783</pre>
784      </div>
785      <p>
786       We’ll Use <code>Assert</code> for the rest of the section but any example here would work with
787<code>Check</code> too. When we said <code>Comparison</code> above, it’s mainly the <a href="https://godoc.org/gotest.tools/assert#BoolOrComparison">BoolOrComparison</a> interface —
788it can either be a boolean expression, or a <a href="https://godoc.org/gotest.tools/assert/cmp#Comparison">cmp.Comparison</a> type. <code>Assert</code> and <code>Check</code> code
789will be <i>smart</i> enough to detect which one it is.
790      </p>
791      <div class="org-src-container">
792       <pre class="src src-go">assert.Assert(t, ok)
793assert.Assert(t, err != nil)
794assert.Assert(t, foo.IsBar())
795</pre>
796      </div>
797     </div>
798    </div>
799   </section>
800   <section id="outline-container-what-s-next" class="outline-2">
801    <h2 id="what-s-next">
802     <a href="#what-s-next" class="anchor">§</a>What’s next ?
803    </h2>
804    <div id="text-what-s-next" class="outline-text-2">
805     <p>
806      One thing is to import old blog posts from <a href="https://vincent.demeester.fr">vincent.demeester.fr</a>. This is easily done with
807<a href="https://pandoc.org/">Pandoc</a> and a small bash loop — and some manual adjusting later on 😛.
808     </p>
809     <div class="org-src-container">
810      <pre class="src src-bash">for post in ~/src/github.com/vdemeester/blog/content/posts/*.md; do
811    pandoc -f markdown -t org -o posts/$(basename -s .md ${post}).org ${post}
812done
813</pre>
814     </div>
815     <p>
816      What is still <i>to do</i> after this initial take.
817     </p>
818     <ul class="org-ul">
819      <li class="off">
820       ☐ List <code>FILETAGS</code> for taximony
821      </li>
822      <li class="off">
823       ☐ Maybe use <a href="https://css-tricks.com/snippets/css/complete-guide-grid/">css grid</a> for the UI
824      </li>
825     </ul>
826    </div>
827   </section>
828   <div id="footnotes">
829    <h2 id="footnotes" class="footnotes">
830     <a href="#footnotes" class="anchor">§</a>Footnotes:
831    </h2>
832    <div id="text-footnotes">
833     <div class="footdef">
834      <sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup>
835      <div class="footpara" role="doc-footnote">
836       <p class="footpara">
837        foo is bar, bar is baz
838       </p>
839      </div>
840     </div>
841    </div>
842   </div>
843  </main>
844  <footer id="postamble" class="status">
845   <footer>
846    <small><a href="/" rel="history">Index</a><a href="/sitemap.html">Sitemap</a><a href="https://dl.sbr.pm/">Files</a></small><br>
847     <small class="questions">Questions, comments ? Please use my <a href="https://lists.sr.ht/~vdemeester/public-inbox">public inbox</a> by sending a plain-text email to <a href="mailto:~vdemeester/public-inbox@lists.sr.ht">~vdemeester/public-inbox@lists.sr.ht</a>.</small><br>
848     <small class="copyright">
849      Content and design by Vincent Demeester
850      (<a rel="licence" href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Some rights reserved</a>)
851    </small><br>
852   </footer>
853  </footer>
854 </body>
855</html>