LoginSignup
9
7

More than 3 years have passed since last update.

1つの org ファイルから Hugo と Qiita の Markdown を生成する

Last updated at Posted at 2019-11-06

普段、技術的なメモは Emacs の org-mode で書いたものを 自身の Github リポジトリ に公開している。ただ、これはあくまで個人的なメモなので、それほど他人が見ることを意識したものではない。より見やすい記事として公開するために、個人のブログを、静的サイトジェネレーターの Hugo + Netlify で開始したが、力を入れて書いた技術記事は Qiita にも公開して、広く読んでもらえるようにしたい。

そこで、これまで通り、org ファイルは同じリポジトリで管理しつつ、1 つの org ファイルから個人ブログ向けと Qiita 向けの Markdown をエクスポートできないか試してみた。

生成されるファイル

まずは、結論から。個人ブログ向け・ Qiita 向け、それぞれの出力結果がこちらである。いくつかの機能差分はあるが、普段よく使う内容については概ね Hugo/Qiita どちらも Markdown として出力できそうなことがわかった。

  1. 元となる org ファイル@github
  2. 個人ブログの記事 (Markdown ファイル@github)
  3. Qiita の記事 (Markdown ファイル@github)

なお .org.md を Github 上で閲覧すると github/markup によって自動的にレンダリングされるので、ソースは「Raw」から見てほしい。

ここから、具体的に設定項目、org-mode との機能差分を見ていく。

動作確認バージョン

ソフトウェア バージョン
OS Ubuntu 18.04
Emacs 26.3
org-mode 9.2.6
Hugo 0.59.1/extended

Qiita 向けの Markdown Exporter の選択

Hugo 向けの Exporter は ox-hugo 一択でよいだろう。Qiita 向けの Markdown の生成には、いつくかの候補を検討した後に、最も機能の差分が少なかった ox-gfm を選択した。他の選択肢としては、標準の ox-md や、こちらの記事で紹介されている ox-qmd などがある。特に ox-qmd はそのものズバリで、最も org-mode から Qiita への再現性が高いと思われた。しかし、自分の設定が悪いのか、org の table が HTML として出力されてしまい、その結果、文字修飾が有効にならないという問題があったため断念した。他にも ox-pandoc からも Markdown を出力できるが、今回は試していない。

ox-hugo と ox-gfm のインストール

ox-hugoox-gfm のインストールは非常に簡単で、特に必要な設定項目はない。 load-path に追加して読み込むだけで完了である。

(add-to-list 'load-path "/path/to/ox-hugo")
(require 'ox-hugo)

(add-to-list 'load-path "/path/to/ox-gfm")
(require 'ox-gfm)

M-x org-export-dispatch のメニューに "Export to Hugo-compatible Markdown""Export to Github Flavored Markdown" が表示されていれば、インストール成功だ。

ox-hugo の設定

ox-hugo から Hugo ブログを生成する方法として、2 つの方式がある

  1. "One post per Org subtree" 方式: 1 つの org ファイルから、複数の Markdown を生成する
  2. "One post oer Org file" 方式: 1 つの org ファイルから 1 つの Markdown を生成する

1 の方式が ox-hugo の売りのひとつでもあるが ox-gfm との併用を考えると 2 の方式を選択せざるを得ない。

また ox-hugo のサンプルには、見出しの下に :PROPERTIES: を設定している例が見られるが、そうしてしまうと ox-gfm でエクスポートした際に、そのまま記事として出力されてしまうため、必要な設定項目は全て最初の見出しより上に記載する必要がある。

この記事を例にヘッダーでの Hugo に関連する設定項目を見てみよう。

#+OPTIONS: author:nil H:6 toc:nil
#+HUGO_BASE_DIR: ~/Dropbox/repos/github/five-dots/blog
#+HUGO_SECTION: post/2019/11/

#+TITLE: 1 つの org ファイルから Hugo と Qiita の Markdown を生成する
#+DATE: 2019-11-05
#+HUGO_CATEGORIES: emacs
#+HUGO_TAGS: org-mode markdown hugo
#+HUGO_CUSTOM_FRONT_MATTER: :toc true

以下本文...
  • :OPTIONS: author:nil H:6 toc:nil
    • ここに記載されているように auther:nil にすることで "著者名が配列として cast できないエラー" を回避している
    • 後述するように、デフォルトでは h4 までしか出力されないため H:6 で h6 までの出力に変更している
    • Qiita では自動で ToC が生成されるので、 toc:nil に設定することで、不要な ox-gfm 側での ToC を生成を止めている
  • #+HUGO_BASE_DIR: ~/Dropbox/repos/github/five-dots/blog
    • org ファイルと blog 自体のリポジトリを分けているので、絶対パスで出力場所を指定している
  • #+HUGO_CUSTOM_FRONT_MATTER: :toc true
    • Hugo 側にはこの項目で ToC が自動で生成されるようにしている

Qiita への投稿フロー

現状は、org ファイルがある同じディレクトリに同名の .md としてエクスポートし、Qiita の投稿画面に手動で貼り付けている。こちらの記事で紹介されていた qiita.el はまだきちんと試すことができていないが、Qiita への投稿頻度が増えてきたら、導入を検討したい。

org-mode の出力確認

以降の章で、org-mode の記法毎に出力結果を確認していく。両者に共通して利用できるものに絞って記事を作成することで、二重管理を避けていくことが主目的だ。

Hugo テーマは Even を利用している。その他のテーマでは、この記事と異なる結果になる可能性もあるので、その点は注意が必要だ。

見出し

Hugo=h2 / Qiita=h1

Hugo=h3 / Qiita=h2

Hugo=h4 / Qiita=h3

Hugo=h5 / Qiita=h4

Hugo=h6 / Qiita=h5

メモ

  • Hugo
    • Hugo では * がタイトルとして扱われるため、 ** (h2) から見出しとして機能する。そのため Qiita とは 1 階層ずれるが、大きな問題にはならない
    • org-mode のデフォルトでは、h4 までしか出力されないため、それ以上の深さが必要な場合は #+OPTIONS: H:6 のように追加で設定が必要
    • Even theme では h6 が最小

表・文字修飾

項目 org-mode 結果
太字 *bold* bold
イタリック /italic/ italic
下線 _underline_ underline
取り消し線 +strikethrough+ strikethrough
コード ~code~ code
逐語 =verbatim= verbatim
上付き hoge^{super} hogesuper
下付き hoge_{sub} hogesub
ギリシャ文字 \alpha α

メモ

  • Hugo
    • 下線は span.underline {text-decoration: underline;}static/css/custom.css に追加した場合の表示結果
    • コードは (setq org-hugo-use-code-for-kbd t) に設定した場合の表示結果
  • Qiita
    • 下線・コードは有効でない

リスト

順序なしリスト

  • hoge
    • hoge
    • fuga
    • piyo
  • fuga
  • piyo

チェックボックス

  • [ ] hoge
  • fuga
  • [ ] piyo

順序ありリスト

  1. hoge
    1. hoge
    2. fuga
    3. piyo
  2. fuga
  3. piyo

定義リスト

  • リンゴ: 赤いフルーツ
  • オレンジ: 橙色フルーツ

メモ

  • Hugo
    • チェックボックスは、チェックをつけてしまうとなぜか表示されなくなってしまう
  • Qiita
    • チェックボックス自体が有効にならない

引用

Everything should be made as simple as possible, but not any simpler —Albert Einstein

メモ

  • Hugo/Qiita ともに問題なく表示されている

数式

インライン

$y=f(x)$

$y=f(x)$

ブロック

$$y=f(x)$$

$$y=f(x)$$

メモ

  • Qiita
    • ox-gfm のエクスポート時に Latex Fragment の $ ... $\( ... \)$$ ... $$\[ ... \] に変換されてしまう
    • Qiita の数式記法 では、この記法に対応していないので、公式ここここを参考にフィルタを作成して再変換する
(require 's)
(require 'dash)

(defun my/org-replace-latex-wrap (text backend _info)
  (when (org-export-derived-backend-p backend 'gfm)
    (cond
     ((s-starts-with? "\\(" text)
      (--> text
           (s-chop-prefix "\\(" it)
           (s-chop-suffix "\\)" it)
           (s-wrap it "$")))
     ((s-starts-with? "\\[" text)
      (--> text
           (s-chop-prefix "\\[" it)
           (s-chop-suffix "\\]" it)
           (s-wrap it "$$"))))))
(add-to-list 'org-export-filter-latex-fragment-functions 'my/org-replace-latex-wrap)

脚注

  • org-mode1 [fn:name]

メモ

  • Qiita
    • Qiita では有効でない

水平線

-----


メモ

  • Hugo
    • 5 つの - で Markdown 側では --- に変換される

コードブロック

Emacs Lisp

(emacs-version)
GNU Emacs 26.3 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.30)
 of 2019-09-17

R

コード出力

R.version
               _                           
platform       x86_64-pc-linux-gnu         
arch           x86_64                      
os             linux-gnu                   
system         x86_64, linux-gnu           
status                                     
major          3                           
minor          6.1                         
year           2019                        
month          07                          
day            05                          
svn rev        76782                       
language       R                           
version.string R version 3.6.1 (2019-07-05)
nickname       Action of the Toes

library(tidyverse)
head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
4.6 3.1 1.5 0.2 setosa
5 3.6 1.4 0.2 setosa
5.4 3.9 1.7 0.4 setosa

プロット

library(ggplot2)
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width)) + geom_point()

img

メモ

  • Qiita
    • Hugo 向けには ox-hugo が自動で画像ファイルを static/ox-hugo/ へ移動してくれるが、Qiita へは手動で画像をアップロードする必要がある
    • そのため org-babel からプロット画像を出力する先を Dropbox フォルダに設定し、共有リンク機能を利用して画像を公開する
    • org-babel は :exports code に設定することで、ファイルリンク出力を抑制しつつ、手元ではプロットをインライン画像で確認できる
    • ここの記事を参考に、Dropbox の直リンクに変換し、以下のように HTML として出力する
    • 将来的には Dropbox API + Emacs Lisp で自動化したい
#+attr_html:
[[https://dl.dropboxusercontent.com/s/4j5jstkg1fsvdiw/iris.png]]

Python

import sys
sys.version
3.6.8 (default, Oct  7 2019, 12:59:55) 
[GCC 8.3.0]

まとめ

一部、Qiita 側で有効にならない記法が見られたが、無いと致命的、という項目はなかった。また、不足している項目も (org-export-filter-TYPE-funstions) を利用すれば、それほど苦労もなくカスタマイズしていけそう、ということもわかった。これから快適なブログライフを送っていきたい。

それでは Happy blogging !!

参考

9
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7