PythonでMarkdownからEPUBをつくろう

この連載について

 この連載は、『PythonでMarkdownからEPUBをつくろう』を一部抜粋して編集したものです。

 本編には、全てのソースコードや、生成する原稿のサンプルが付属しています。ぜひ、こちらもご購入ください。

 姉妹版の『PythonとPygameで作る レトロ風RPG 全コード』もあります。

目次に戻る

8-1 原稿ページの構築

公開:2025-05-29

 mod/doc/doc.pyでは、Markdown形式で書いた原稿からXHTMLファイルを作成します。

 このファイルでは作成の流れを書いており、細かな処理は他のファイルに書いています。

▶ ファイル構成
▶ mod/doc/doc.py
 1import re, sys, traceback
 2from mod.util import file as uf
 3from mod.doc import md, toc_title
 4
 5# Markdown関連の構築
 6def build(data):
 7    dir = data['dirs']
 8    con = data['config']
 9
10    # 目次用データの初期化(XHTMLファイル名、タイトル)
11    con['titles'] = [
12        {'file': 'cover.xhtml', 'title': con['coverTitle'], 'level': 1, 'children': []},
13        {'file': 'toc.xhtml', 'title': con['tocTitle'], 'level': 1, 'children': []}
14    ]
15
16    # 各Markdownファイルに対して処理
17    for i, fnm in enumerate(con['docs']):
18        try:
19            # パス作成
20            fnm_src = fnm['src']
21            fnm_dst = fnm['dst']
22            p_src = uf.join(dir['input'], fnm_src)
23            p_dst = uf.join(dir['outputXhtml'], fnm_dst)
24
25            # XHTML作成
26            t = uf.read(p_src)          # ファイル読み込み
27            body = md.convert(t)        # Markdown変換
28            xhtml = apply_template(con, i, body)    # テンプレート適用
29            xhtml = re.sub('(?s)<!--.*?-->', '', xhtml) # コメント削除
30            uf.write(p_dst, xhtml)  # ファイル保存
31
32            # 目次用データの作成(XHTMLファイル名、タイトル)
33            title, level, children = toc_title.get(i, t)
34            con['titles'].append({
35                'file': fnm_dst,    # XHTMLファイル名
36                'title': title,     # タイトル
37                'level': level,     # レベル
38                'children': children    # 子要素
39            })
40
41        except Exception as e:
42            print(f'## {fnm_src} ##')
43            traceback.print_exc()
44            sys.exit()
45
46# テンプレート適用
47def apply_template(con, i, body):
48    t = con['templateLoaded']
49    t = t.replace('@lang@', con['lang'])
50    t = t.replace('@title@', str(i + 1))
51    t = t.replace('@body@', body)
52    return t

 ここではconfig.yamldocsに書いたMarkdownファイルを1つずつXHTMLファイルに変換していきます。またその過程で、目次用データも作っていきます。

処理の流れ

 doc.pyでの処理の流れを箇条書きにします。

 主な処理はMarkdown変換です。

 テンプレートの適用は、template-h.xhtml@lang@@title@@body@の値を書き換えます。

例外処理

 例外処理について説明しておきます。try~except~の部分です。

▶ 例外処理
try:
    処理A
except Exception as e:
    処理B
    print(f'## {fnm_src} ##')
    traceback.print_exc()
    sys.exit()

 上のように書くと、処理Aの途中で何らかのエラーが発生した場合は処理を中断して、処理Bの場所に移動します。

 build()関数の処理Aの部分では、さまざまなファイルを読み書きしたり、記述内容を変換したりします。そのためエラーが発生しやすいです。

 エラーが発生したら、エラーの内容をtraceback.print_exc()関数で出力して、sys.exit()関数でプログラムを終了します。

正規表現による置換

 次のプログラムの部分です。

▶ 正規表現による置換
xhtml = re.sub('(?s)<!--.*?-->', '', xhtml) # コメント削除

 re.sub()関数は、正規表現でテキストを置換します。事前にimport reで、Pythonの標準ライブラリーre(Regular Expression:正規表現)を読み込んでおく必要があります。

 正規表現は、記号を使ってテキストを抽象化して検索したり置換したりするためのものです。Pythonだけでなくほとんどのプログラミング言語で利用できます。

 re.sub(A, B, C)と書くことで、テキストCに対して、正規表現で書いた検索対象Aを、Bのテキストで置換した結果を返します。

 ここで書いた正規表現(?s)<!--.+?-->の内容を解説します。

 (?s)は、.(ドット)の文字の挙動を変えるフラグです。通常.は改行以外の何か1文字を表します。(?s)を書くと改行も含めて何か1文字を表します。

 .+?は、.で何か1文字、+で事前の文字を1回以上繰り返す、?でなるべく短く、という意味になります。繋げると「何か1文字以上をなるべく短くマッチさせる」という意味になります。こう書くことで、<!---->に挟まれた対象にマッチします。

 第2引数は''という空文字(0文字のテキスト)です。そのため「<!---->に挟まれた部分を削除する」という意味になります。


目次に戻る

この連載について

 この連載は、『PythonでMarkdownからEPUBをつくろう』を一部抜粋して編集したものです。

 本編には、全てのソースコードや、生成する原稿のサンプルが付属しています。ぜひ、こちらもご購入ください。

 姉妹版の『PythonとPygameで作る レトロ風RPG 全コード』もあります。

 技術系同人誌など まとめページ


トップページに戻る
Cronus Crown(クロノス・クラウン)のトップページに戻る
(c)2002-2025 Cronus Crown (c)1997-2025 Masakazu Yanai
ご意見・お問い合わせはサイト情報 弊社への連絡までお願いします
個人情報の取り扱い、利用者情報の外部送信について