この記事は Emacs 精進 Advent Calendar 2025 1 日目の投稿です。
背景
2025 年 Qiita アドベントカレンダーの『完走賞』を狙って Emacs の記事を 25 本投稿します。審査は厳し目らしく、記事の品質を高めに保つ必要があります:
https://blog.qiita.com/adventcalendar-2025-qiitapresents/
とはいえガチガチの技術記事 25 本となると、読み書きともに現実的ではなくなります。流し読みできる程度の濃度で 25 本書いて行こうと思います。
対象読者
Emacs ユーザが主なターゲットです。設定の効果を主に紹介するため、環境構築全般に興味がある人も対象になるかと思います。
Qiita 執筆環境構築
初日は『Emacs 精進』の執筆環境を構築します。 12 月中に Markdown 記事を 25 本書くことになりますが、これらの記事を 1 つの org-mode ファイル内に記載したいと思います。
.org ファイルの構成
以下の .org ファイルに 25 記事を全て記載し、 .org ファイルから 25 個の Markdown ファイルを生成することにします:
#+TITLE: Emacs 精進
#+BOOK_DIR: ../public
#+FILETAGS: :emacs:
* Emacs 精進 01: 考える方が速いに決まってる
:PROPERTIES:
:EXPORT_FILE_NAME: emacs-2025-01
:END:
この記事は [[https://qiita.com/advent-calendar/2025/emacs-25][Emacs 精進 Advent Calendar 2025]] 1 日目の記事です。
..
* Emacs 精進 25: 最強の小指
:PROPERTIES:
:EXPORT_FILE_NAME: emacs-2025-25
:END:
#+BOOK_DIRおよびEXPORT_FILE_NAMEは独自のプロパティです。後ほど使用します。
BOOK_DIRで出力先のディレクトリを設定します。 (Zenn Book を意識した名前です)EXPORT_FILE_NAMEで出力先のファイル名を設定します。
Emacs 上では次のように見えます。各記事に相当する見出しを折り畳むことで、一連の投稿をエディタから一望できます:
ファイル構成
以下のファイル構成で、 increments/qiita-cli によりローカル環境でプレビューができます:
.
├── public
│ ├── emacs-2025-01.md
│ ├── ..
│ └── emacs-2025-25.md
└── org
└── emacs-2025.org
increments/qiita-cli はフラットなファイル構成を要求しますから、 public 内には Emacs 精進以外の記事も混ざっていますが、 emacs-2025.org には Emacs 精進の記事のみが入っています。
org-qiita-export-buffer-to-book の作成
後は .org ファイルからの Markdown ファイルの展開を実装します。幸い org ドキュメントの subtree に対する export という概念があり、 org-mode はこのような処理が得意です。
詳しくは Zenn Book における解説記事 に譲ることにして、 Qiita 版は次のようになりました:
記事の ID や更新時刻の同期は考えていません 。 GUI からの投稿を前提としています。
(leaf ox-qmd
:commands (org-qiita-export-buffer-to-book)
:config
;; Converts org-mode tags into front matter tag.
(defun qmd2-template-tags ()
(let ((tags (or (mapcar #'substring-no-properties (org-get-tags))
"")))
(string-join
(mapcar (lambda (s) (format "\"%s\"" s)) tags)
",")))
;; Markdown file template for `@qiita/qiita-cli'.
(defun qmd2-template (contents info)
(let* ((title (or (substring-no-properties (car (plist-get info :title))) ""))
(tags (qmd2-template-tags)))
(concat
"---\n"
"title: \"" title "\"\n"
"tags: [" tags "]\n"
"private: false\n"
"updated_at: \"\"\n"
"id: null\n"
"organization_url_name: null\n"
"slide: false\n"
"---\n\n"
contents)))
;; The Qiita Markdown export backend, built on top of `ox-qmd'.
(org-export-define-derived-backend 'qmd2 'qmd
:options-alist
'((:title "TITLE" nil nil t)
(:tags "TAGS" nil nil space))
:translate-alist '((template . qmd2-template)))
;; Exports a subtree of org file into a Markdown file.
(defun org-qmd2-export-to-markdown (&optional async subtreep visible-only)
(interactive)
(let ((outfile (org-export-output-file-name ".md" subtreep)))
(org-export-to-file 'qmd2 outfile async subtreep visible-only)))
;; Exports each level 1 heading into a Markdown file.
(defun org-qiita-export-buffer-to-book (&optional org-dir)
"Runs subtree export to each level 1 heading, respecting `#+BOOK_DIR'."
(interactive)
(require 'ox-qmd)
(let* ((default-dir default-directory)
(pub-dir (car (cdr (car (org-collect-keywords '("BOOK_DIR")))))))
(cd pub-dir)
(unwind-protect
(org-map-entries
(lambda ()
(let ((exports (org-entry-get nil "EXPORT_FILE_NAME")))
(when exports
(org-qmd2-export-to-markdown nil t))))
"LEVEL=1")
(cd default-dir)))))
Qiita CLI によるプレビューと Emacs (on Kitty & tmux) を並べると次のようになります:
これで org-mode と Qiita CLI が協調するようになりました。 Qiita が自分のフィールドになったような気がします。
なお Zenn 版のスクリプト の通り Zenn Book としても出力できます:
PDF 出力も可能です。
まとめ
『Emacs 精進』の執筆環境を構築しました。 25 記事が 1 つの org ファイルに収まり、あるべき姿でスタートを切れたと思います。
Qiita のコミュニティガイドラインも達成できたのではないでしょうか:
- 再利用性・汎用性がある
- メモや走り書きに留まらない
- 正確性の検証が十分である
それでは次の記事でお会いしましょう!

