機能

org-mode 製ブログに新機能を追加しました。アスキーアートを綺麗に表示できます。

デモ

                             .|          /
                               !        /
                             .l    __/_
                               !   /  / \
                               ! /.   / _ノ  \
                             .l │.   /(● )(●)    俺が見えるか!
                             .| │  /  (__人__)
                               ! │. /    ` ⌒´ノ
                               ! │ /         }
                               | ノ./ヾ.ヘ     }
                         ..=ィ゙ニ| /、;i;i;ヾヘ  _ノ
               .       : :イ/{ / ̄ヾ}l!;i;i;iLc、>
               .       / '/,ム{ ∧  }ー-,-、《;i〈
               .       !:.,'〃´ハ{/  ハ::〃,=ヾミ;i
               .       :.:{/' 〃゙ヽ__ノヽi/´   }\
               .       :.:|!、/  ヽ::Y::/{  r、/ム .\
               .       !:.!ム    ヽj::ノ{   | ,';i;iム   ヽ.
               .       Ⅵマ\  _ ヽ';i乂__.ソ;i;i;i;i|     丶
               .       トj0l|Y´\{ }  Y;i;i;i;i;i;i;i;i;i;iト,     \
               .       `!0j;iト、  ヾ__.人;i;i;i;i;i;i;i;i;i;i;{         \
               .       〈ソ,∧ \  「 ! Y;i;i;i;i;i;i;i;i;iム
               .        j、;i;i;、  \___丿;i;i;i;i;i;i;i;i;i;iム
               .       /.:::∨;i;i`i.、___ノ;i\;i;i;i;i;i;i;i;i;i;i;iム
               .       ::::::::.∨;i;i|:;i;i;i;i;i;i;i;i;\;i;i;i;i;i;i;i;i;i;ム
               .       、_:::::::∨;i|:;i;i;i;i;i;i;i;i;i;i;i;丶:;i;i;i;i;i;i;i;ム
               .       ::ーニ=イ};i:!:;i;i;i;i;i;i;i;i;i;i;i;i;i;i\:;i;i;i;i;i;i;i〉
               .       ヽ:::::::::ノ;i:!:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i\:;i;i;/
               .        ヽ/;i;i:|:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i\:〉
               .       ../;i;i;i;i;i:|:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;\
               .       ,ゝ;i;i;i;i;i;i:|:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i/  丶
               .       i;i;i;i;i;i;i;i;i:|:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;/    \
               .       i;i;i;i;i;i;i;i;i:!:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i∧
               .       i;i;i;i;i;i;i;i;i:!:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i/. ム
               .       i;i;i;i;i;i;i;i;i:l:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i//マ___
               .       、i;i;i;i;i;i;i;i:|:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;}/イ;;;;;;;;;`!
               .       ';i;i;i;i;i;i;i;i:l:;i;i;i;i;i;i;i;i;i;i;i;i;i;i;i;iム.;;;;;;;;;;;;;;;;;〉

AA のフォントは aahub_light をお借りしました。

#+BEGIN_YARUO 構文

ソースファイル中では、以下のように #+BEGIN_YARUO, #+END_YARUO で AA を囲みます:

#+BEGIN_YARUO
等幅フォントで表示されるテキスト
#+END_YARUO

HTML 変換時は、以下のように元のテキストが <pre> タグ (preformatted text) で囲まれます:

<pre class="yaruo">等幅フォントで表示されるテキスト
</pre>

実装

HTML 変換時には、 AA のテキスト内容を保持します。改行を <br> タグに変換したり、記号をエスケープしないように気をつける必要があります。

ELisp

Emacs Lisp のコーナーです。 org-mode では、標準外の #+BEGIN_*** 構文を speical block と呼びます (たぶん) 。 Backend 定義の際に special block の translator を指定できるので、その中から #+BEGIN_YARUO の処理関数へ繋ぎます:

;; Backend 定義
(org-export-define-derived-backend
 ;; ~~ 一部省略
 :translate-alist
 '((template . my-org-html-template)
   ;; ~~ 一部省略
   ;; Special block (#+BEGIN_***) の処理関数を割り当てる
   (special-block . my-org-html-special-block)))

;; Special block (#+BEGIN_***) の処理関数
(defun my-org-html-special-block (special-block contents info)
  (let* ((block-type (org-element-property :type special-block)))
    (cond ( ;; #+BEGIN_DETAILS の処理関数を割り当てる
           (or (string= block-type "details") (string= block-type "DETAILS"))
           (my-org-html-details-block special-block contents info))
+          ( ;; #+BEGIN_YARUO の処理関数を割り当てる
+           (or (string= block-type "yaruo") (string= block-type "YARUO"))
+           (my-org-html-yaruo-block special-block contents info))
          (t ;; fallback する
           (org-html-special-block special-block contents info)))))

#+BEGIN_YARUO の処理関数では、元のテキストを取得して <pre> で囲みます:

(defun my-org-html-yaruo-block (yaruo-block contents info)
    (let* ((beg (org-element-property :contents-begin yaruo-block))
           (end (org-element-property :contents-end yaruo-block))
           (raw-content (buffer-substring-no-properties beg end)))
        (format "<pre class=\"yaruo\">
%s
</pre>" raw-content)))

yaruo-block 変数からは、 (org-element-property :value yaruo-block) を使って #+BEGIN_YARUO ~ #+END_YARUO までのテキストを取得できます。しかしこの :value は既に HTML へ変換されており、 <br> タグや HTML へのエスケープを含むため AA には使用できません。

HTML への変換を避けるため、むしろ export block (#+BEGIN_EXPORT yaruo) とするのが素直な実装ですが、今回は #+BEGIN_YARUO と書きたかったため、あくまで special block として実装しました。

CSS

<pre> タグのフォント設定をします:

/* aahub_light: https://qiita.com/scrpgil/items/b8bde1257a135d173585 */
@font-face {
  /* TODO: 40KB とはいえ遅延ロードにしたい */
  font-family: "aahub_light";
  src: url(/style/aahub_light.woff2) format("woff2");
  font-display: swap;
}

.yaruo {
  font-family: "aahub_light";
  font-size: 16px;
  line-height: 18px;
  text-indent: 0;
  /* これは外さない方が良いかも: */
  /* white-space: pre; */
}

なお MathJax はデフォルトで <pre> タグを無視するため、 AA の中で記号を使っても数式になることはありません。

振り返って

org-mode:contents-begin や HTML の <pre> タグを知らず、回り道しました。異常に軽量な aahub_light (43.9 KB) のおかげで、気兼ねなくポータブルに AA を表示できました。