Categories: sharing

RSS - Atom - Subscribe via email

This is a test post from Org Mode to 11ty

| blogging, org, emacs

At the moment, my Org file needs to be in the proper content directory. I'm planning to copy the way ox-hugo allows me to export to a different directory and export filename. In the meantime, this is a start.

;;; ox-11ty.el --- Eleventy export for Emacs Org Mode  -*- lexical-binding: t -*-

;; Copyright (C) 2021 Sacha Chua

;; Author: Sacha Chua <sacha@sachachua.com>
;; Version: 2.17.0
;; Package-Requires: ((emacs "27"))
;; Keywords: org, eleventy, 11ty
;; Homepage: https://github.com/sachac/ox-11ty

;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;; A very rough starting point for exporting to 11ty from Org Mode.
;;

;;; Code:

(require 'ox-html)

(defun org-11ty-template (contents info)
  (let* ((date (org-export-data (plist-get info :date) info))
         (title (org-export-data (plist-get info :title) info))
         (permalink (org-export-data (plist-get info :permalink) info))
         (categories (org-export-data (plist-get info :categories) info))
         (collections (org-export-data (plist-get info :collections) info))
         (front-matter (json-encode
                        (list :permalink permalink
                              :date date
                              :title title
                              :categories (split-string categories)
                              :tags (split-string collections)))))
    (format
     "module.exports = class {
  data() {
    return %s;
  }
  render() {
    return %s;
  }
}"
     front-matter
     (json-encode-string contents))))

(defun org-11ty-export-as-11ty (&optional async subtreep visible-only body-only ext-plist)
  "Export current buffer as 11ty file."
  (interactive)
  (org-export-to-buffer '11ty "*org 11ty export*" async subtreep visible-only body-only ext-plist))

(defun org-11ty-export-to-11ty (&optional async subtreep visible-only body-only ext-plist)
  (interactive)
  (let* ((info
          (org-combine-plists
           (org-export--get-export-attributes '11ty subtreep visible-only)
           (org-export--get-buffer-attributes)
           (org-export-get-environment '11ty subtreep)))
         (base-file-name (concat (or
                                  (and (plist-get info :file-name)
                                       (if (string= (file-name-base (plist-get info :file-name)) "")
                                           (concat (plist-get info :file-name) "index")
                                         (plist-get info :file-name)))
                                  (org-export-output-file-name "" subtreep))
                                 ".11ty.js"))
         (file
          (if (plist-get info :base-dir)
              (expand-file-name base-file-name (plist-get info :base-dir))
            base-file-name)))
    (when (file-name-directory file)
      (make-directory (file-name-directory file) :parents))
    (org-export-to-file '11ty file
      async subtreep visible-only body-only ext-plist)))

(org-export-define-derived-backend '11ty 'html
  :menu-entry
  '(?1 "Export to 11ty JS"
       ((?b "As buffer" org-11ty-export-as-11ty) 
        (?1 "To file" org-11ty-export-to-11ty)))
  :translate-alist
  '((template . org-11ty-template))
  :options-alist
  '((:permalink "PERMALINK" nil nil)
    (:categories "CATEGORIES" nil 'split)
    (:base-dir "ELEVENTY_BASE_DIR" nil nil)
    (:file-name "FILE_NAME" nil nil)
    (:collections "ELEVENTY_COLLECTIONS" nil 'split)))

;;; ox-11ty.el ends here

https://github.com/sachac/ox-11ty/

View or add comments

Statically generating my blog with Eleventy

| blogging

Things will probably be a little strange on my blog for the next few days, as I've decided to experiment with statically generating my blog with Eleventy. It's a little complicated because I wanted to keep as many of my posts and category/tag feeds as possible.

To speed things up, I usually work with a subset of my posts. Generating a partial copy of my site results in 557 files and takes 3.73 seconds. When I generate the full copy of my site, it writes 13358 files in 96.73 seconds.

With any luck, I'll be able to get most of the things working before the next Emacs News post. Let's see!

View or add comments

Sharing more of my discretionary time

Posted: - Modified: | writing

Depending on what time A- finally goes to bed, I might have around 1-2 hours of discretionary time that I can use to focus on a small task and complete it. If I pick something that’s too big, I get tempted to stay up late, which often makes me grumpy the next day. So a good approach might be to have a number of reasonably small tasks that give me as quick a payoff as possible, especially if those tasks can result in compounding improvements.

Now that I can post Org Mode headings to my journal from Emacs, it’s easier to log finished tasks as journal entries that will get picked up during my weekly and monthly review. The next step might be to figure out how to flesh out those lines into more useful posts. That way, I can find things again by searching my blog. Also, if other people can pick up ideas from my posts, I might be able to benefit from their improvements.

There’s a lot of room for growth in terms of my workflow for doing stuff, learning stuff, and sharing stuff. Here’s what a possible learning path might be like:

sharing-path.png

  • Planning: I’ve just started excavating the Org files that I’ve been tossing ideas into over the last 5+ years of limited discretionary time. Now things are mostly refiled, and I’ve got quite a few projects on my priority list. I might spend a bit of non-computer time mulling over 1-3 possibilities throughout the day, and then work on the most interesting one after processing my inbox. I find that in the course of a week, I tend to focus on one or two projects in order to take advantage of momentum. It’s also good to set aside planning/improvement/review time instead of getting tempted to prioritize coding all the time, as fun as it is to write stuff.

    I don’t have to optimize this. Most tasks are good to work on and move me forward, so I don’t have to spend a lot of time trying to analyze the best effort/reward ratio. I can usually just go with whatever I feel like working on.

  • Coding: I usually work with Emacs Lisp or Javascript, with a little bit of Python. I have some technical debt in Ruby that I don’t have the brainspace to dig into at the moment. It may have to wait until A- goes to in-person school. For Emacs Lisp, my next workflow improvement might be to get the hang of Lispy. For my personal projects, infrastructure is the main thing tripping me up. I need to spend some time setting up a proper development environment and learning more about workflows so that I can reduce risk when I’m working on stop-and-go things.
  • Writing: Dictation is out for now, since I don’t feel much like talking at night. It’s nice to be quiet after a whole day of talking with a kiddo. When I get the Georgi keyboard I ordered, stenography might be an interesting long-term skill investment. The bottleneck is probably still my thinking speed, though. That means I could probably:
    • embrace lists and outlines as a way of getting fragmented thoughts down (possibly over several sessions) and then shuffling them around into some form of coherence (yay Org Mode)
    • lower my threshold for posting; it’s better to think out loud
  • Screenshots: I recently tweaked my shortcuts for inserting screenshots. Now I just need to make them part of muscle memory.
  • Drawings: I can sketch things out on my Lenovo X220 tablet PC, although flipping the screen is a little annoying. One option might be to leave my screen rotated and then use a Bluetooth keyboard to type and use shortcuts. The keyboard isn’t as comfortable to type on as my laptop is, though. Hmm… org-krita doesn’t quite fit my workflow, so I need to write my own. I want to be able to quickly sketch something. If I like it, I want to convert it, rename it with a caption, and add it to my sketches.

(defun my/org-insert-drawing-as-link ()
  (interactive)
  (let ((file (make-temp-file "/tmp/image" nil ".psd")))
    (copy-file my/index-card-template-file file t)
    (insert (org-link-make-string (format "file:%s" file)))
    (my/open-images-in-krita (list file))))

(defun my/preview-in-other-buffer (file)
  (with-current-buffer (find-file-noselect file)
    (display-buffer (current-buffer))))

(defun my/org-convert-sketch-at-point (&optional two-col)
  (interactive "p")
  (let* ((link (org-element-context))
         (file (org-element-property :path link))
         date
         (intermediate (concat (file-name-sans-extension file) ".png"))
         new-file new-link)
    (unless (eq (org-element-type link) 'link)
      (error "Not at a link"))
    ;; (call-process "krita" nil nil nil file "--export" "--export-filename" intermediate)
    (call-process "convert" nil nil nil (concat file "[0]") intermediate)
    (my/preview-in-other-buffer intermediate)
    (setq
     date (org-read-date)
     caption (read-string "Caption: ")
     new-file (expand-file-name (format "%s %s.png" date caption) my/sketches-directory)
     new-link (concat "#+CAPTION: " date " " caption "\n"
                      (org-link-make-string (concat "sketch:" (file-name-base new-file)))))
    (rename-file intermediate new-file t)
    (delete-region (org-element-property :begin link)
                   (org-element-property :end link))
    (if two-col
        (progn (insert
                (format  "#+begin_columns
#+begin_column50
%s
#+end_column50
#+begin_column50
"
                         new-link))
               (save-excursion (insert "
#+end_column50
#+end_columns
")))
      (insert new-link "\n"))))

(defun my/reload-sketches ()
  (interactive)
  (url-retrieve "https://sketches.sachachua.com/reload" (lambda (&rest args) (message "Updated sketches."))))

What are drawings useful for? Nonlinear thinking, sharing, flipping through, building up, visual shorthand, fun. Text is nicer for searching, linking, and dealing with stop-and-go thoughts.

W-‘s offered to let me use his iPad. Concepts and Procreate are both pretty cool, and I have a reasonable workflow for sending files back to my computer and getting them into my Org file. My X220 is still the fastest for quickly switching between text and drawing. I guess either will do.

Also, graphviz is pretty handy for quick diagrams, and it will probably be even more useful as I dig into it and other text-based diagram tools. The diagram at the beginning of this post was generated with:

#+begin_src dot :file "sharing-path.png" :cmdline -Kdot -Tpng -Nfontname=sachacHand -Nfontsize=30
digraph {
  rankdir=LR;
  node [shape=box];
  "Planning" -> "Coding" -> "Writing" -> "Screenshots" -> "Drawings" -> "GIFs?" -> "Video" -> "Streaming";
  "Planning" -> "Reading" -> "Writing";
  "Planning" -> "Writing";
}
#+end_src

Animated GIFs, videos, and streaming may have to wait until I have more brainspace. Plenty to tweak even now!

View or add comments

Python, Org Mode, and writing Org tables to CSVs so that I can read them back

| emacs, org, writing

I’ve been getting deeper into Python so that I can model our personal finances. I really like using the pandas library to manipulate data. All those years I spent trying to juggle increasing complex spreadsheets… Working with Python code in Org Babel blocks is just so much more fun. I like being able to keep my assumptions in tables without having to fuss around with naming cells for easy-to-read formulas, slice and summarize parts of my data frames, organize my notes in outlines and add commentary, and define more complicated functions that I don’t have to squeeze into a single line.

I haven’t quite been able to tempt W- into the world of Org Babel Python blocks. Still, I don’t want to give up the awesomeness of having pretty tables that I can easily edit and use. So I have a bunch of named tables (using #+NAME:), and some code that exports my tables to CSVs:

#+NAME: tables
| Table         | Key                 |
|---------------+---------------------|
| assets_w      | Description         |
| assets_s      | Description         |
| tax_rates     |                     |
| disposition   | Asset               |
| probate_rates | Asset               |
| basic         | Client information  |
| base_expenses | Category            |
| general       | General assumptions |

#+begin_src emacs-lisp :results silent :var tables=tables :tangle no
  (defun my-tbl-export (row)
    "Search for table named `NAME` and export."
    (interactive "s")
    (save-excursion
      (goto-char (point-min))
      (let ((case-fold-search t))
        (when (search-forward-regexp (concat "#\\+NAME: +" (car row)) nil t)
          (next-line)
          (org-table-export (format "%s.csv" (car row)) "orgtbl-to-csv")))))
  (mapc 'my-tbl-export tables)
#+end_src

and some code that imports them back in, and formats tables nicely if I’m displaying them in Org. The in_org block doesn’t get tangled into index.py, so I don’t clutter command-line use with Org table markup.

#+begin_src python :results silent :tangle no
  in_org=1
#+end_src

#+begin_src python :results silent :exports code
  import pandas as pd
  import numpy as np
  import orgbabelhelper as ob
  def out(df, **kwargs):
    if 'in_org' in globals():
      print(ob.dataframe_to_orgtable(df, **kwargs))
    else:
      print(df)
    return df
#+end_src

#+begin_src python :results silent :var tables=tables :colnames yes
  for row in tables:
    table = row[0]
    index = row[1] 
    if row[1] == '':
      index = None
    globals()[table] = pd.read_csv(table + '.csv', index_col=index).apply(pd.to_numeric, errors='ignore')
    # print(globals()[table])
#+end_src

Then I can use C-c C-v C-b (org-babel-execute-buffer) to update everything if I change the table in my Org file, and I can use C-c C-v C-t (org-babel-tangle) to create an index.py that W- can read through or run without needing Org.

View or add comments

Making an 8-page 7″x4.25″ captioned photo book with Org Mode and LaTeX

| emacs, org, publishing

Here’s another technique that makes a simple photo book. I wanted to
make an 8-page book that could be printed 4 pages to a 8.5″x14″ sheet
(duplex, flip along the short edge), with a final page size of
7″x4.25″.

Sample with my own photos:

out.jpg

Prerequisites

  • ImageMagick
  • Texlive (probably)
  • latex-beamer
  • Org Mode and Emacs

Process

We can define the labels and their captions in a named table like this:

Let’s Go for a Walk  
   
Caption for photo 1 placeholder.png
Caption for photo 2 placeholder.png
Caption for photo 3 placeholder.png
Caption for photo 4 placeholder.png
Caption for photo 5 placeholder.png
   

Note that the first page is row #1 this time, instead of starting with
the last page.

Then we generate the LaTeX code with some Emacs Lisp, like so:

#+begin_src emacs-lisp :var pages=story :results value latex :exports results
(mapconcat (lambda (row) (format "\\graphicframe{%s}{%s}" (cadr row) (org-export-string-as (car row) 'latex t))) pages "\n")
#+end_src

I put that in a subtree for easier exporting with C-c C-e C-s l b (org-export-dispatch, subtree, LaTeX, Beamer).

Story

Process

  • Set up Org Mode export to Beamer
    (eval-after-load "ox-latex"
      ;; update the list of LaTeX classes and associated header (encoding, etc.)
      ;; and structure
      '(add-to-list 'org-latex-classes
                    `("beamer"
                      ,(concat "\\documentclass[presentation]{beamer}\n"
                               "[DEFAULT-PACKAGES]"
                               "[PACKAGES]"
                               "[EXTRA]\n")
                      ("\\section{%s}" . "\\section*{%s}")
                      ("\\subsection{%s}" . "\\subsection*{%s}")
                      ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))
    
  • Set up the header.tex

    This file gets included in the LaTeX file for the children’s book.
    Tweak it to change the appearance. In this example, I use black serif
    text text on the left side of a picture, both occupying roughly half
    of the page. I also experimented with using a different font this time, which you might need to install (for me, I did apt-get install texlive-fonts-extra).

    \geometry{paperwidth=7in,paperheight=4.25in,left=0.5in,right=0.5in}
    \beamertemplatenavigationsymbolsempty
    \usepackage{etoolbox}
    \usepackage[T1]{fontenc}
    \usepackage{Alegreya}
    \usefonttheme{serif}
    \setbeamercolor{normal text}{fg=black,bg=white}
    \setbeamercolor{structure}{fg=black,bg=white}
    %% \setbeamertemplate{frametitle}
    %% {
    %%   \begin{center}
    %%   \noindent
    %%   \insertframetitle
    %%   \end{center}
    %% }
    \newcommand{\graphicframe}[2] {
       {
       %% \if #1\empty 
       %% \usebackgroundtemplate{}
       %% \fi
       \ifstrempty{#1}{
       \begin{frame}[plain]
         \begin{center}
         \noindent
         \textbf{\huge{#2}}
         \end{center}
       \end{frame}
       }{
       \begin{frame}[plain]
          \begin{columns}
          \begin{column}{0.48\textwidth}
          \huge{#2}
          \end{column}
          \begin{column}{0.48\textwidth}
          \includegraphics[height=\textheight,width=\textwidth,keepaspectratio=true]{#1}
          \end{column}
          \end{columns}
       \end{frame}
       }
       }
    }
    \usepackage[noframe]{showframe}
    \renewcommand{\maketitle}{}
    
  • Create the PDF
    pdflatex index.tex
    
  • Create one PNG per page
    mkdir pages
    convert -density 300 index.pdf -quality 100 pages/page%d.png
    
  • Create the 4-up imposition

    The diagram at https://pressnostress.com/iw/howto/booklets/1.html was helpful.

    montage \( page4.png -rotate 180 \) \( page3.png -rotate 180 \) page7.png page0.png -tile 2x2 -mode Concatenate front.png
    montage \( page2.png -rotate 180 \) \( page5.png -rotate 180 \) page1.png page6.png -tile 2x2 -mode Concatenate back.png
    convert front.png back.png -density 300 ../print.pdf
    

Other notes

Placeholder image from https://en.wikipedia.org/wiki/File:Portrait_placeholder.png – public domain.

View or add comments

Using Org Mode, LaTeX, Beamer, and Medibang Paint to make a children’s book

| drawing, emacs, geek, org, publishing

Story

  • It’s time to make a smoothie!
  • I pour blueberries into the blender.
  • Mama adds hemp seeds.
  • I add spinach.
  • Mama blends it all with some water.
  • I peel and add a banana.
  • I add some yogurt.
  • Mama blends it again.
  • Yum yum!

Thumbnails

spread0.png spread1.png spread2.png spread3.png spread4.png spread5.png

Process

  • Prerequisites

    • ImageMagick
    • Texlive (probably)
    • latex-beamer
    • Org Mode and Emacs
  • Set up Org Mode export to Beamer

    (eval-after-load "ox-latex"
      ;; update the list of LaTeX classes and associated header (encoding, etc.)
      ;; and structure
      '(add-to-list 'org-latex-classes
                    `("beamer"
                      ,(concat "\\documentclass[presentation]{beamer}\n"
                               "[DEFAULT-PACKAGES]"
                               "[PACKAGES]"
                               "[EXTRA]\n")
                      ("\\section{%s}" . "\\section*{%s}")
                      ("\\subsection{%s}" . "\\subsection*{%s}")
                      ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))
    

  • Set up image directories

    mkdir text-pages blank-spreads drawn drawn-pages
    

    text-pages Will contain one image per page of just the plain text.
    blank-spreads Will contain text spreads ready for drawing
    drawn Export one image per spread (without the text layers) from your drawing program
    drawn-pages Will contain one image per page combining text and drawing
  • Tweak the header.tex

    This file gets included in the LaTeX file for the children’s book. Tweak it to change the appearance. In this example, I use black serif text at the bottom of the page.

    \geometry{paperwidth=7in,paperheight=8.5in,left=0.5in,top=0.5in,right=0.5in,bottom=0.5in}
    \setbeamercolor{normal text}{fg=black,bg=white}
    \setbeamercolor{structure}{fg=black,bg=white}
    \usefonttheme{serif}
    \setbeamertemplate{frametitle}
    {
      \begin{center}
      \vspace{0.7\textheight}                    
      \noindent
      \insertframetitle
      \end{center}
    }
    \usepackage[noframe]{showframe}
    \renewcommand{\maketitle}{}
    

  • Write the story

    I used Org Mode to make it easy to write the story.

    Some considerations:

    • Because we’re printing this as a saddle-stitched booklet, the number of lines should be a multiple of four. Sixteen is probably a good maximum.
    • The first heading is actually for the last page.
    • The second heading is for the cover page.
    • The third heading is for the first inner page, the fourth heading is for the second inner page, and so on.
    #+OPTIONS:   TeX:t LaTeX:t skip:nil d:nil todo:t pri:nil tags:not-in-toc author:nil date:nil
    #+OPTIONS: H:1
    #+startup: beamer
    #+LaTeX_CLASS: beamer
    #+LaTeX_CLASS_OPTIONS: [20pt]
    #+BEAMER_FRAME_LEVEL: 1
    #+LATEX_HEADER: \input{header.tex}
    #+PROPERTY: header-args :var pages=12
    
    * Story
    
    ** 
    ** 
    ** 
    ** It's time to make a smoothie!
    ** I pour blueberries into the blender.
    ** Mama adds hemp seeds.
    ** I add spinach.
    ** Mama blends it all with some water.
    ** I peel and add a banana.
    ** I add some yogurt. 
    ** Mama blends it again.
    ** Yum yum!
    

  • Make the tex, PDF, page PNGs, and spread PNGs

    1. Go to the subtree for the story and use M-x org-export-dispatch (C-c C-e) with the subtree option (C-s) to export it as a Beamer file (option l b).
    2. Use pdflatex to convert the .tex to PDF.

      pdflatex index.tex
      

    3. Create one PNG per text page with:

      convert -density 300 index.pdf -quality 100 text-pages/page%02d.png
      

    4. Create spreads to draw on with:

      montage text-pages/page*.png -tile 2x1 -mode Concatenate blank-spreads/spread%d.png
      

    5. Optionally, create a layered PSD with:

      convert blank-spreads/spread*.png \( -clone 1,0 -background white -flatten -alpha off \) -reverse spreads-for-drawing.psd
      

  • Draw

    I imported the PNG layers into MediBang Paint on a Samsung Note 8 Android phone, and then:

    • imported photos
    • traced them
    • painted and shaded them
    • hid the text layers
    • exported one PNG per spread to QuickPic, renamed them, and uploaded them to Dropbox, because I couldn’t figure out how to export to Dropbox directly

    Layer folders were handy for organizing spread-related images. I couldn’t seem to move all of the layers in a layer folder together on Android, but the iPad was able to do so. If I didn’t have the iPad handy, I combined the layers by exporting a PNG and then importeing it back into MediBang Paint.

    This was a decent setup that allowed me to draw and paint even when I was in bed nursing A- and waiting for her to fall asleep. I held the phone with one hand and rotated the canvas as needed so that it was easier for me to draw lines with my right. Because of the awkward position and the small screen size, the lines are not as smooth as I might like, but the important thing is that they’re there. Whee! =)

    It turns out to be possible to use the free MediBang Pro drawing program under Wine on Linux to import the PSD and save it to the cloud. I was also sometimes able to switch to drawing with iPad Pro with Pencil, but it was harder to find time to do that because that usually made A- want to draw too.

    Anyway, after I drew and exported the PNGs, the next step was to…

  • Convert the drawn spreads back to pages and combine them with the text

    Here’s some code that combines the drawing and the text. Keeping the drawing and the text separate until this stage (instead of exporting the PNGs with the text) makes it easier to change the text later by recreating the text PNGs and running this step.

    (defun my/combine-spread-drawing-and-text (page num-pages)
      (let ((gravity (if (= (% page 2) 1) "West" "East"))
            (spread (/ (% page num-pages) 2)))
        (shell-command
          (format 
           (concat "convert \\( "
                   "drawn/spread%d.png -gravity %s "
                   "-chop 50%%x0 +repage \\) "
                   "text-pages/page%02d.png -compose darken "
                   "-composite drawn-pages/page%02d.png")
           spread gravity page page))))
    
    (cl-loop for i from 0 to (1- pages) do
             (my/combine-spread-drawing-and-text i pages))
    

  • Create print spreads for saddle-stitching

    This code pairs up the drawn pages into a PDF that can be printed duplex. Make sure to choose the option to flip along the short edge. I hard-coded the page orders for 4-, 8-, 12-, and 16-page booklets.

    (let* ((page-order
            '((0 1 2 3)   ; hard-coded page sequences
              (0 1 2 7 6 3 4 5)
              (0 1 2 11 10 3 4 9 8 5 6 7)
              (0 1 2 15 14 3 4 13 12 5 6 11 10 7 8 9)))
           (sequence
            (mapconcat (lambda (d) (format "drawn-pages/page%02d.png" d))
                       (elt page-order (1- (/ pages 4))) " ")))
      (shell-command
       (format
        "montage %s -tile 2x1 -mode Concatenate print-duplex-short-edge-flip.pdf"
        sequence)))
    

  • Print and bind

    After printing and folding the book, I used tape to make the book hold together. Tada!

  • Create on-screen PDF for reading

    A little bit of manipulation so that the last page is in the right place:

    (shell-command
      (format "convert %s onscreen.pdf" 
        (mapconcat 'identity (cl-loop for i from 1 to pages 
          collect (format "drawn-pages/page%02d.png" (% i pages))) " ")))
    

  • Create thumbnails of spreads

    (cl-loop
     for i from 0 to (1- (/ pages 2)) do 
     (shell-command
      (format 
       (concat "convert "
               "\\( blank-spreads/spread%d.png "
               "drawn/spread%d.png "
               "-compose darken "
               "-resize %dx -flatten \\) "
               "\\( +clone -background black -shadow 50x1+%d+%d \\) "
               "+swap -compose src-over -composite "
               "thumbnails/spread%d.png")
       i i width shadow shadow i)))
    

  • Ideas for next steps

    • Better thumbnails for easy previews
    • PDF for online reading
    • More layout possibilities (photos, verses, etc.)
    • Smaller books:

      • crop marks on a full-page print, or
      • the right imposition rules to print more pages on a sheet
View or add comments

Making books for A-

| drawing, parenting, publishing, writing

A- loves being read to. She picks up new words and ideas from the books we read, requests both favourites and new books again and again, and can identify objects in photographs and drawings. I borrowed a few children’s books from the library in case reading about upcoming changes or challenges helps her understand. The books were okay, but didn’t quite fit the words we use or the way we like to handle things. So this week, I decided to make my own books for A-, especially since there are few books that cover things like microphthalmia.

The first book I made was about night weaning, since we might have to do that in preparation for dental surgery under anaesthesia. I sketched it using ZoomNotes on my iPad, exported the SVG, tinkered with it in Inkscape, exported PNGs, combined the PNGs with ImageMagick, and created a 12-page PDF with 7″x8.5″ pages. That let me print the book out on legal-size paper (8.5″x14″), 2 pages per sheet, duplex printing set to flip on the short side, using this page order:
12, 1, 2, 11, 10, 3, 4, 9, 8, 5, 6, 7. I folded each sheet in half. Instead of hand-sewing the binding, I just taped the pages together. And just like that, I had a book that I could page through properly: “No More Nursing, Time to Sleep.”

I read the new book to A-. She asked me to reread it several times. She pointed to the book and said, “A-!” She pointed to the stick figure for me and said, “Mama!” Success!

The next thing I wanted to try was printing in colour. We recently replaced our printer with an HP M277dw colour laser printer that could print duplex, so I was looking forward to giving that a try. I wanted to make a book about the conformer in A-‘s little eye. This time, I drew the pages of the book using layers in Medibang Paint. I drew on the bus home from Riverdale Farm, working around a sleeping A- snuggled in my carrier. I exported each layer as a PNG, used ImageMagick to convert pairs of pages into what I needed to print (page order: 8, 1, 2, 7, 6, 3, 4, 5), combined those into a PDF. I couldn’t figure out how to get the HP app to properly scale the document and print in duplex, but printing from Linux worked fine. I quickly had another book in my hands: “My Conformer.”

She’s starting to echo phrases from the to books, and it’s been only a few days. Wow!

I’m working on a third book now. Time for something fun: “Let’s Make a Smoothie,” since she enjoys making and drinking them. She already knows all the words, so this is more about enjoyment. This time, I’m going to make a workflow that lets me draw on two-page spreads. I don’t have any wide drawings planned yet, but it could be handy for later. I made an Inkscape template to help me keep margins in mind. I learned how to use Medibang Paint’s folders to organize all the layers, and I’m getting the hang of digitally tracing and painting the photos I took.

I’m looking forward to making even more books and refining my workflow along the way. Here are a few things I want to try:

  • Flat colour
  • Painting
  • Programmatically adding text
  • Printing photos
  • Two-page drawing
  • Parametric templates
  • Smaller format by cutting
  • Programmatically adding photos
  • Heavier-weight paper
  • Board book replacement
  • Printing at Staples or similar
  • Print-on-demand book
  • Handstitching
  • Binding with a cover
  • Smaller format by folding and gluing
  • Mobile workflow
  • Vector drawing

And a few quick ideas for possible next books:

  • Potty Time
  • Brushing Teeth
  • Feelings
  • When I Feel Nervous
  • When I Feel Sad
  • Going to Sleep at the Dentist
  • My Life
  • My Day
  • Going Out
  • At Home
  • I Can…
  • I Can Draw
  • Waiting
  • Try Again
  • Dressing Up
  • Alimango sa Dagat
  • Leron Leron Sinta
View or add comments