Markdownをはてなブログ用に見出しを整える

はてなブログを書くときは、まずローカルで普通にMarkdownで記事を書いて、その後はてなブログに貼り付けて投稿している。

しかし、はてなブログMarkdownモードとローカルのMarkdownでは見出しが異なっていて、毎回貼り付けたあとに見出しを整えるのが面倒である。さらに、ローカルに置いておくMarkdownにはFront Matter(titleとdateだけ)を書いているので、これも投稿時には削除しておかないといけない。

そこでローカルで書いたMarkdownはてなブログ用に整えるmd2hatenamd.pyを書いた。

#!/usr/bin/env python

import re
import contextlib
import argparse


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-i",
        "--input_file",
        type=argparse.FileType("r"),
        default="-",
        help="input Markdown file",
    )
    args = parser.parse_args()

    with contextlib.closing(args.input_file) as f:
        l = f.readlines()

    IN_FRONTMATTER = False
    IN_CODEBLOCK = False

    for i in l:
        if re.match(r"^---", i) != None and not IN_FRONTMATTER:  # frontmatterを表示しない
            IN_FRONTMATTER = True
        if IN_FRONTMATTER and i == "\n":
            IN_FRONTMATTER = False
            continue
        if IN_FRONTMATTER:
            continue
        if re.match(r"^```", i) != None:  # コードブロック内では置換しない
            if IN_CODEBLOCK:
                IN_CODEBLOCK = False
            else:
                IN_CODEBLOCK = True
        if not IN_CODEBLOCK:
            i = re.sub(r"^###\s", r"##### ", i)  # 小見出し
            i = re.sub(r"^##\s", r"#### ", i)  # 中見出し
            i = re.sub(r"^#\s", r"### ", i)  # 大見出し
        print(i, end="")


if __name__ == "__main__":
    main()

これをローカルのパスの通っているところに配置して実行権限をつけて実行すれば、投稿用の記事が出力される。

$ md2hatenamd.py -i a.md

パイプでクリップボードにコピーしてしまえばそのまま投稿できて便利。

$ md2hatenamd.py -i a.md | pbcopy

ついでにMarkdownで投稿した記事をFront Matter付きのMarkdownに変換するhatenamd2md.pyも書いた。

#!/usr/bin/env python

import re
import contextlib
import argparse


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-i",
        "--input_file",
        type=argparse.FileType("r"),
        default="-",
        help="input Hatena Blog article written in Markdown mode",
    )
    args = parser.parse_args()

    with contextlib.closing(args.input_file) as f:
        l = f.readlines()

    IN_CODEBLOCK = False

    print("---\n", end="")  # front matterの表示
    print("title: \n", end="")
    print("date: \n", end="")
    print("---\n", end="")
    print("\n", end="")
    for i in l:
        if re.match(r"^```", i) != None:  # コードブロック内では置換しない
            if IN_CODEBLOCK:
                IN_CODEBLOCK = False
            else:
                IN_CODEBLOCK = True
        if not IN_CODEBLOCK:
            i = re.sub(r"^#####\s", r"### ", i)  # 小見出し
            i = re.sub(r"^####\s", r"## ", i)  # 中見出し
            i = re.sub(r"^###\s", r"# ", i)  # 大見出し
        print(i, end="")


if __name__ == "__main__":
    main()

ローカルにコピーしたMarkdownモードで書いたはてなブログの記事に対して実行すればOK。

$ hatenamd2md.py -i b.md

こっちもパイプでにクリップボードの中身を流すと便利かもしれない。

$ pbpaste | hatenamd2md.py > c.md

両方ともpoetryでパッケージにしたのでよかったら使ってみてください。

参考