この連載は、『PythonでMarkdownからEPUBをつくろう』を一部抜粋して編集したものです。
本編には、全てのソースコードや、生成する原稿のサンプルが付属しています。ぜひ、こちらもご購入ください。
姉妹版の『PythonとPygameで作る レトロ風RPG 全コード』もあります。
≫ 目次に戻る mod/doc/doc.py
では、Markdown形式で書いた原稿からXHTMLファイルを作成します。
このファイルでは作成の流れを書いており、細かな処理は他のファイルに書いています。
gen-epub/
main.py
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.yaml
のdocs
に書いたMarkdownファイルを1つずつXHTMLファイルに変換していきます。またその過程で、目次用データも作っていきます。
doc.py
での処理の流れを箇条書きにします。
cover.xhtml
、toc.xhtml
の情報をあらかじめ設定主な処理は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 全コード』もあります。