以前に 簡易なHTMLパーサ 2018秋 を作成しました。
以降、HTML形式のものを作るときは、まずYAML形式で作成。
それから自作のツールezhtml.pyを使って、YAML形式からHTML形式に変換するようになりました。
ですがここにきて、YAML形式の作成も「かったるく」なってしまいました。
例えば、次のような既存のテキストの場合
$ cat foo.txt Python2とPython3での日本語文字列対応について 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 結論 日本語を含む文字列処理で .foramt() や .join() を使いたい Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 Python3 では日本語の有無に関係なく、素直にstrのままでよし。 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい Python2 では素直に sys.stdin/sys.stdout を read/write。 Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 Python2 の世界には .buffer は存在しないので注意。
まずはYAML形式で
$ cat foo.yaml html: - head: - meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": / - title: py23str - style: 'pre{ background: lightgray; }' - style: 'img{ max-width: 100%; height: auto; }' - style: 'h3{ border-left: solid gray; padding: 1em 0.5em; }' - body: - h1: Python2とPython3での日本語文字列対応について - p: - 毎回、同じようにつまづいて、同じような感じで対応してます。 - p: - なので、いいかげん自分に判りやすいようにまとめておきます。 - p: - 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 - p: - データはYAML形式のファイルで用意。 - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回「うぅっ」とうなってます。 - h2: 結論 - h3: 日本語を含む文字列処理で .foramt() や .join() を使いたい - p: - Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - p: - Python2 では素直に sys.stdin/sys.stdout を read/write。 - p: - Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 - p: - Python2 の世界には .buffer は存在しないので注意。
を作成しておいて
$ ./ezhtml.py y < foo.yaml | nkf -j > foo.html $ nkf -g foo.html ISO-2022-JP $ cat foo.html | nkf -u <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <title>py23str</title> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style></head> <body><h1>Python2とPython3での日本語文字列対応について</h1> <p>毎回、同じようにつまづいて、同じような感じで対応してます。</p> <p>なので、いいかげん自分に判りやすいようにまとめておきます。</p> <p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p> <p>データはYAML形式のファイルで用意。</p> <p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。</p> <h2>結論</h2> <h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3> <p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p> <p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p> <h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3> <p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p> <p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p> <p>Python2 の世界には .buffer は存在しないので注意。</p></body></html>
に変換。
このように表示されます。
ですが、このYAML形式を作成するのが結構ツライです。
できれば foo.txt から foo.yaml の形式に変換できないものか...
世の中にはマークダウン形式の規格・仕様は存在します。
ですが、ここはひとつ目をつむって「簡易おれおれマークダウン」な仕様の 変換ツールを作ってみる事にします。
foo.yaml の段階で、headとbodyに分かれてます。
そしてbody以降は、最低スペース2つの字下げが必ず入ってます。
headでfoo.txtからの固有の情報は
- title: py23str
だけで、あとはほぼお決まりで固定です。
headのtilteはあとで編集するとして、bodyだけ何とか変換するように目指してみます。
まずは
を用意。
$ cat foo_head.yaml - meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": / - title: py23str - style: 'pre{ background: lightgray; }' - style: 'img{ max-width: 100%; height: auto; }' - style: 'h3{ border-left: solid gray; padding: 1em 0.5em; }'
そして foo.txt から、これから作成を目指すツールで、何とか foo_body.yaml を自動生成します。
$ cat foo_body.yaml - h1: Python2とPython3での日本語文字列対応について - p: - 毎回、同じようにつまづいて、同じような感じで対応してます。 - p: - なので、いいかげん自分に判りやすいようにまとめておきます。 - p: - 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 - p: - データはYAML形式のファイルで用意。 - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回「うぅっ」とうなってます。 - h2: 結論 - h3: 日本語を含む文字列処理で .foramt() や .join() を使いたい - p: - Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - p: - Python2 では素直に sys.stdin/sys.stdout を read/write。 - p: - Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 - p: - Python2 の世界には .buffer は存在しないので注意。
あとはスクリプトなり何なりで、例えば
$ ( echo '<html><head>' ; ./ezhtml.py y < foo_head.yaml ; echo '</head><body>' ; ./ezhtml.py y < foo_body.yaml ; echo '</body></html>' ) | nkf -j > foo2.html $ nkf -g foo2.html ISO-2022-JP $ nkf -u foo2.html <html><head> <meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp"> <title>py23str</title> <style>pre{ background: lightgray; }</style> <style>img{ max-width: 100%; height: auto; }</style> <style>h3{ border-left: solid gray; padding: 1em 0.5em; }</style> </head><body> <h1>Python2とPython3での日本語文字列対応について</h1> <p>毎回、同じようにつまづいて、同じような感じで対応してます。</p> <p>なので、いいかげん自分に判りやすいようにまとめておきます。</p> <p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p> <p>データはYAML形式のファイルで用意。</p> <p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。</p> <h2>結論</h2> <h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3> <p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p> <p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p> <h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3> <p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p> <p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p> <p>Python2 の世界には .buffer は存在しないので注意。</p> </body></html>
となります。
おれおれ仕様のツールなので、 自分がよく使うHTMLのタグだけ対応して、 滅多に使わないものは、最後に手動で編集する事にします。
HTMLのbodyの中で、自分がよく使うタグは何か?
とりあえず、このくらい。
最初はここから foo.txt の範囲だけに絞って
だけで骨組みを考えてみます。
foo.txt から foo_body.yaml を生成したい訳ですが、 テキストを、属してるタグで切り分けてみると
;;; --> h1 Python2とPython3での日本語文字列対応について ;;; <-- h1 ;;; --> p 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 ;;; <-- p ;;; --> h2 結論 ;;; <-- h2 ;;; --> h3 日本語を含む文字列処理で .foramt() や .join() を使いたい ;;; <-- h3 ;;; --> p Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 Python3 では日本語の有無に関係なく、素直にstrのままでよし。 ;;; <-- p ;;; --> h3 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい ;;; <-- h3 ;;; --> p Python2 では素直に sys.stdin/sys.stdout を read/write。 Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 Python2 の世界には .buffer は存在しないので注意。 ;;; <-- p
HTML形式だと、開始タグと終了タグで、まさにこのような感じで領域を指示します。
おれおれマークダウンでは、簡易な記述を目指すので、モード(状態)を持たせます。
テキストの先頭から末尾に向かって、状態を切り替えて、どのタグの領域かを指示する事にします。
例えば、次のように。
h1 Python2とPython3での日本語文字列対応について p 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 h2 結論 h3 日本語を含む文字列処理で .foramt() や .join() を使いたい p Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 Python3 では日本語の有無に関係なく、素直にstrのままでよし。 h3 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい p Python2 では素直に sys.stdin/sys.stdout を read/write。 Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 Python2 の世界には .buffer は存在しないので注意。
p, h1, h2, h3をモード名として、モード名だけの行が現れると、 現在のモードをそのモードに切り替えます。
他のモードに切り替わるまでの間の複数行のテキストについて
h1 Python2とPython3での日本語文字列対応について p
は
- h1: Python2とPython3での日本語文字列対応について
てな具合に。
他のモードに切り替わるまでの間の複数行のテキストについて
p 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 h2
は
- p: - 毎回、同じようにつまづいて、同じような感じで対応してます。 - p: - なので、いいかげん自分に判りやすいようにまとめておきます。 - p: - 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 - p: - データはYAML形式のファイルで用意。 - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回「うぅっ」とうなってます。
てな具合に。
ではこの仕様で、骨組みのコーディング。
$ cat ezmd.py #!/usr/bin/env python import yaml import nkf heads = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'h9' ] end = '$$$_end_$$$' modes = heads + [ 'p', end ] def do_mode(mode, buf, res): if mode in heads: buf = list( map( lambda s: s.strip(), buf ) ) buf = list( filter( lambda s: s!='', buf ) ) s = ''.join(buf) res.append( { mode: s } ) elif mode == 'p': buf = list( map( lambda s: s.strip(), buf ) ) buf.append('') (lsts, lst) = ( [], [] ) for s in buf: if s: lst.append(s) elif lst: lsts.append(lst) lst = [] for lst in lsts: res.append( { 'p': lst } ) def ezmd(lst): lst = ['p'] + lst + [end] (buf, res) = ( [], [] ) mode = '' while mode != end: s = lst.pop(0) if s in modes and s != mode: do_mode(mode, buf, res) mode = s buf = [] else: buf.append(s) return res if __name__ == "__main__": b = nkf.get_stdin() (s, nkf_opt) = nkf.to_str(b) lst = s.split('\n') lst = ezmd(lst) u8 = yaml.dump( lst, default_flow_style=False, allow_unicode=True, encoding='utf-8' ) b = nkf.cvt(u8, nkf_opt) if nkf_opt != '-u' else u8 nkf.put_stdout(b) # EOF
日本語の文字コードの問題やPython2, Python3の問題は、すべて nkf.py が吸収してくれてるはずと信じて、進めまてみます。
nkf.py は使いまわしつつ、互換性を保ちながらアップデートしてきたので、 テキスト配置ツール から最新版の
を配置しておきます。
おれおれ仕様のテキストファイルは
$ cat foo2.txt h1 Python2とPython3での日本語文字列対応について p 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 h2 結論 h3 日本語を含む文字列処理で .foramt() や .join() を使いたい p Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 Python3 では日本語の有無に関係なく、素直にstrのままでよし。 h3 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい p Python2 では素直に sys.stdin/sys.stdout を read/write。 Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 Python2 の世界には .buffer は存在しないので注意。
それでは実行。
$ ./ezmd.py < foo2.txt - h1: Python2とPython3での日本語文字列対応について - p: - 毎回、同じようにつまづいて、同じような感じで対応してます。 - p: - なので、いいかげん自分に判りやすいようにまとめておきます。 - p: - 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 - p: - データはYAML形式のファイルで用意。 - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回「うぅっ」とうなってます。 - h2: 結論 - h3: 日本語を含む文字列処理で .foramt() や .join() を使いたい - p: - Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - p: - Python2 では素直に sys.stdin/sys.stdout を read/write。 - p: - Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 - p: - Python2 の世界には .buffer は存在しないので注意。
出力されたHTML形式をさらにezhtml.pyにつないでHTML形式に。
$ ./ezmd.py < foo2.txt | ./ezhtml.py <h1>Python2とPython3での日本語文字列対応について</h1> <p>毎回、同じようにつまづいて、同じような感じで対応してます。</p> <p>なので、いいかげん自分に判りやすいようにまとめておきます。</p> <p>日本語対応といっても、ソースコード中に日本語を書くつもりはありません。</p> <p>データはYAML形式のファイルで用意。</p> <p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。</p> <h2>結論</h2> <h3>日本語を含む文字列処理で .foramt() や .join() を使いたい</h3> <p>Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。</p> <p>Python3 では日本語の有無に関係なく、素直にstrのままでよし。</p> <h3>日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</h3> <p>Python2 では素直に sys.stdin/sys.stdout を read/write。</p> <p>Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。</p> <p>Python2 の世界には .buffer は存在しないので注意。</p>
大丈夫そうですね。 headとつなげて仕上げを。
仕上げ用のツールを用意しときます。
$ cat to_html.py #!/usr/bin/env python import sys import subprocess if __name__ == "__main__": if len(sys.argv) < 3: print( 'Usage: {} head.yaml body.txt'.format( sys.argv[0] ) ) sys.exit(1) cmd = "( echo '<html><head>' ; ./ezhtml.py y < {} ; echo '</head><body>' ; ./ezmd.py < {} | ./ezhtml.py y ; echo '</body></html>' ) | nkf -j"; cmd = cmd.format( sys.argv[1], sys.argv[2] ) subprocess.call(cmd, shell=True) # EOF $ ./to_html.py foo_head.yaml foo2.txt > foo3.html $ nkf -g foo3.html ISO-2022-JP
OK。
todo
追加してみます。
preタグの場合、どこまでがpreタグの中か? 次のモードへの切り替えの判定が微妙です。
このモードは特別に、'/'だけの行でモード終了としてみます。
行頭に'/'だけ表示したい事はまぁ無いだろうし、 あったとしても、' ' + '/' にして行頭にスペースを入れてしのぐ事にします。
モードが終了するまでの間の複数行のテキストについて
preタグのYAMLへの変換は
簡易なHTMLパーサ 2018秋 preタグのyamlダンプ でこしらえた yaml_dump() を流用しておきます。
ezhtml.pyのオリジナルのyaml_dump()ではstrを返す仕様にしてました。 今回の場面ではUTF-8のままで良いので、そのように修正して使います。
モード終了指示の方式にすると、 '/' で終了してから、次のモードまでの滞空期間ができてしまいます。
モードが何者でもないその間は、とりあえずデフォルトのpモードで。
pモード中に何もテキストがなく、続く別のモードが始まれば、 デフォルトpモードでは何も表示しないので、大丈夫でしょう。
$ cat v2.patch | patch -p1
$ cat foo_2.txt h1 Python2とPython3での日本語文字列対応について p 毎回、同じようにつまづいて、同じような感じで対応してます。 なので、いいかげん自分に判りやすいようにまとめておきます。 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 データはYAML形式のファイルで用意。 そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回「うぅっ」とうなってます。 h2 結論 h3 日本語を含む文字列処理で .foramt() や .join() を使いたい p Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 Python3 では日本語の有無に関係なく、素直にstrのままでよし。 h3 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい p Python2 では素直に sys.stdin/sys.stdout を read/write。 Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 Python2 の世界には .buffer は存在しないので注意。 pre $ cat p2.py #!/usr/bin/env python2 import sys import yaml if __name__ == "__main__": s = sys.stdin.read() d = yaml.load(s) foo = d.get('foo') bar = d.get('bar') d['hoge'] = foo + ' ' + bar d['fuga'] = 'foo={} bar={}'.format(foo, bar) d['guha'] = '(^_^)'.join( d.values() ) s = yaml.dump(d, default_flow_style=False) sys.stdout.write(s) # EOF / ここはデフォルトp p ここは明示的にp pre ここはpre p ここもpre h1 ここもpre / p ここはp
実行してみます。
$ ./ezmd.py < foo_2.txt - h1: Python2とPython3での日本語文字列対応について - p: - 毎回、同じようにつまづいて、同じような感じで対応してます。 - p: - なので、いいかげん自分に判りやすいようにまとめておきます。 - p: - 日本語対応といっても、ソースコード中に日本語を書くつもりはありません。 - p: - データはYAML形式のファイルで用意。 - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回「うぅっ」とうなってます。 - h2: 結論 - h3: 日本語を含む文字列処理で .foramt() や .join() を使いたい - p: - Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - p: - Python2 では素直に sys.stdin/sys.stdout を read/write。 - p: - Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 - p: - Python2 の世界には .buffer は存在しないので注意。 - pre: | $ cat p2.py #!/usr/bin/env python2 import sys import yaml if __name__ == "__main__": s = sys.stdin.read() d = yaml.load(s) foo = d.get('foo') bar = d.get('bar') d['hoge'] = foo + ' ' + bar d['fuga'] = 'foo={} bar={}'.format(foo, bar) d['guha'] = '(^_^)'.join( d.values() ) s = yaml.dump(d, default_flow_style=False) sys.stdout.write(s) # EOF - p: - ここはデフォルトp - p: - ここは明示的にp - pre: | ここはpre p ここもpre h1 ここもpre - p: - ここはp
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_2.txt > foo_2.html
todo
追加してみます。
全体の簡単にするためにモードの開始、終了をトップレベルの状態の遷移だけにしました。
なので、基本的に「入れ子」の構造を諦めてます。
が、ですが、このulモードの中だけは「入れ子」を結構使ってます。
例えば
- ul: - li /: 標準入力からYAML形式のテキストを読み込み - li /: yaml.load()でテキストをデータに - li /: データの文字列2つを - li /: ごにょごにょいじって - ul: - li /: foo + ' ' + bar - li /: .format() - li /: .join() - li /: yaml.dump()でデータをYAML形式のテキストにして - li /: 標準出力に書き出し
こうして
<ul><li>標準入力からYAML形式のテキストを読み込み <li>yaml.load()でテキストをデータに <li>データの文字列2つを <li>ごにょごにょいじって <ul><li>foo + ' ' + bar <li>.format() <li>.join()</ul> <li>yaml.dump()でデータをYAML形式のテキストにして <li>標準出力に書き出し</ul>
こうなって
このように。
ここまでのモードの関連に従うならば、 例えば上記の結果になる元のテキストは
ul 標準入力からYAML形式のテキストを読み込み yaml.load()でテキストをデータに データの文字列2つを ごにょごにょいじって foo + ' ' + bar .format() .join() yaml.dump()でデータを \ YAML形式のテキストにして 標準出力に書き出し
こうありたい。
ulモード中では、行頭の字下げの数で「入れ子」の指示になるという仕様で、 何とか考えてみました。
$ cat v3.patch | patch -p1
$ cat foo_3.txt : p ここはp ul 標準入力からYAML形式のテキストを読み込み yaml.load()でテキストをデータに データの文字列2つを ごにょごにょいじって foo + ' ' + bar .format() .join() yaml.dump()でデータを \ YAML形式のテキストにして 標準出力に書き出し pre ここはpre
実行してみます。
$ ./ezmd.py < foo_3.txt : - p: - ここはp - ul: - li /: 標準入力からYAML形式のテキストを読み込み - li /: yaml.load()でテキストをデータに - li /: データの文字列2つを - li /: ごにょごにょいじって - ul: - li /: foo + ' ' + bar - li /: .format() - li /: .join() - li /: yaml.dump()でデータをYAML形式のテキストにして - li /: 標準出力に書き出し - pre: |2 ここはpre
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_3.txt > foo_3.html
todo
追加してみます。
自分のa href="xxx"タグの使い方を振り返ると、 ほとんどpタグの中かulタグの中です。
なのでとりあえず、pモードとulモードの文字列処理の箇所だけに、対応を入れてみます。
a (href)の場合、トップレベルのモードを遷移させるまでもなさそうです。
文字列中に [[ xxx | yyy ]] の記載があれば YAML形式の - a href="xxx": yyy を経て HTML形式で <a href="xxx"> yyy </a> に 文字列中に [[ xxx ]] の記載があれば YAML形式の - a href="xxx": xxx } を経て HTML形式で <a href="xxx"> xxx </a> に
このくらいの仕様でやってみます。
$ cat v4.patch | patch -p1
$ cat foo_4.txt : p ここは明示的にp [[v2.patch]] バージョン2のための[[ v2.patch | パッチ ]] となります。 [[http://kondoh.html.xdomain.jp/ezhtml/index.html | 簡易なHTMLパーサ 2018秋]] これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。 pre ここはpre p ここもpre h1 ここもpre / ul [[v2.patch]] [[v3.patch]] バージョン2のための[[ v2.patch | パッチ ]] となります。 これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。 p ここはp :
実行してみます。
$ ./ezmd.py < foo_4.txt : - p: - ここは明示的にp - p: - a href="v2.patch": v2.patch - p: - バージョン2のための - a href="v2.patch": パッチ - となります。 - p: - a href="http://kondoh.html.xdomain.jp/ezhtml/index.html": 簡易なHTMLパーサ 2018秋 - p: - これは - a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import": pythonのモジュールのインポート - について。 - pre: | ここはpre p ここもpre h1 ここもpre - ul: - li /: a href="v2.patch": v2.patch - li /: a href="v3.patch": v3.patch - li /: - バージョン2のための - a href="v2.patch": パッチ - となります。 - li /: - これは - a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import": pythonのモジュールのインポート - について。 - p: - ここはp
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_4.txt > foo_4.html
todo
追加してみます。
複数のハイフンだけの行が現れると、横線に変換する事にしてみます。
ハイフン2つだけとかなら他に何か意味ありそうなので、 一応4個以上の場合に有効とします。
自分のhrタグの使用箇所は、そのほとんどが
- p: { hr: / }
経ての
<p><hr></p>
として使ってます。
ハイフン4個以上の行が複数行続く場合も、その行数の横線になるように。
横線指示の直後にモード指定が無い場合は、 デフォルトのモード'p'として扱う事にします。
$ cat v5.patch | patch -p1
$ cat foo_5.txt : 毎回「うぅっ」とうなってます。 ---- h2 結論 : Python2 の世界には .buffer は存在しないので注意。 ---- pre $ cat p2.py #!/usr/bin/env python2 : p ここはp --- ---- ---- ここは暗黙のp h3 ここはh3 --- ---- ---- --- p ここはp ul 標準入力からYAML形式のテキストを読み込み :
実行してみます。
$ ./ezmd.py < foo_5.txt : - 毎回「うぅっ」とうなってます。 - p: hr: / - h2: 結論 : - p: - Python2 の世界には .buffer は存在しないので注意。 - p: hr: / - pre: | $ cat p2.py #!/usr/bin/env python2 : - p: - ここはp - p: - '---' - p: hr: / - p: hr: / - p: - ここは暗黙のp - h3: ここはh3--- - p: hr: / - p: hr: / - p: - '---' - p: - ここはp - ul: - li /: 標準入力からYAML形式のテキストを読み込み :
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_5.txt > foo_5.html
todo
追加してみます。
img, video ともに自分で使うときのパターンはほぼお決まりで、 a (href)タグと似たようなものです。
なので仕様もa (href)タグと同じような感じにします。
a (href)タグ同様に、pモードとulモードの文字列処理の箇所だけに、対応を入れます。
文字列中に [[ img | xxx ]] の記載があれば YAML形式の - img srcf="xxx": / を経て HTML形式で <img src="xxx"> に 文字列中に [[ video | xxx ]] の記載があれば YAML形式の - video src="xxx" controls playsinline: "" を経て HTML形式で <video src="xxx" controls playsinline></video> に
形式をa (href)タグの場合と合わせたので、 a (href)タグの箇所をちょっと改造するだけの対応になります。
$ cat v6.patch | patch -p1
$ cat foo_6.txt : p Python2 では素直に sys.stdin/sys.stdout を read/write。 Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 Python2 の世界には .buffer は存在しないので [[img|beat.jpg]] 注意。 : ul [[v2.patch]] [[v3.patch]] バージョン2のための[[ v2.patch | パッチ ]] となります。 これは[[http://kondoh.html.xdomain.jp/p3d/index.html#v3_import | pythonのモジュールのインポート]]について。 [[ img | beat.jpg ]] [[ video | cut.mp4 ]] p ここはp : p ここはp [[video|http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4]] ul 標準入力からYAML形式のテキストを読み込み :
実行してみます。
$ ./ezmd.py < foo_6.txt : - p: - Python2 では日本語を含む文字列は .encode('utf-8')して UTF-8 で保持。 - p: - Python3 では日本語の有無に関係なく、素直にstrのままでよし。 - h3: 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - p: - Python2 では素直に sys.stdin/sys.stdout を read/write。 - p: - Python3 では sys.stdin.buffer , sys.stdout.buffer を使う。 - p: - Python2 の世界には .buffer は存在しないので - img src="beat.jpg": / - 注意。 : - ul: - li /: a href="v2.patch": v2.patch - li /: a href="v3.patch": v3.patch - li /: - バージョン2のための - a href="v2.patch": パッチ - となります。 - li /: - これは - a href="http://kondoh.html.xdomain.jp/p3d/index.html#v3_import": pythonのモジュールのインポート - について。 - li /: img src="beat.jpg": / - li /: video src="cut.mp4" controls playsinline: '' - p: - ここはp : - p: - ここはp - p: - video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline: '' - ul: - li /: 標準入力からYAML形式のテキストを読み込み
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_6.txt > foo_6.html
todo
追加してみます。
sタグは「打ち消し線」の指定です。
これまた a (href)タグ同様に、pモードとulモードの文字列処理の箇所だけの対応で。
形式も強引にa (href)タグに合わせてしまいます。(^_^;
文字列中に [[ - | xxx ]] の記載があれば YAML形式の - s: xxx を経て HTML形式で <s> xxx </s> に
形式を強引にもa (href)タグの場合と合わせたので、 変更箇所は驚くほど軽微です。
$ cat v7.patch | patch -p1
$ cat foo_7.txt : そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回[[ - |「うぅっ」]] 「ぬはぁ」とうなってます。 ---- : ul 標準入力からYAML形式のテキストを読み込み yaml.load()でテキストをデータに [[-|データの文字列2つを]] ごにょごにょいじって :
実行してみます。
$ ./ezmd.py < foo_7.txt : - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回 - s: 「うぅっ」 - 「ぬはぁ」とうなってます。 - p: hr: / : - ul: - li /: 標準入力からYAML形式のテキストを読み込み - li /: yaml.load()でテキストをデータに - li /: s: データの文字列2つを - li /: ごにょごにょいじって :
大丈夫そうですね。
$ ./to_html.py foo_head.yaml foo_7.txt > foo_7.html
todo
目次を自動生成する機能を追加してみます。
さすがにこの機能は2 passになります。
'index'だけの行が現れると目次モード。
そこから他のモードになるまでの区間に目次を挿入します。
目次モード中の箇所に、目次作成のためのパラメータを指定します。
index パラメータ
パラメータは、目次にするヘッダタグの種別の範囲を指定します。
範囲指定はPythonのリストのスライスの指定のようにします。
index 2:5
lst[2:5] なので目次にする対象は h2, h3, h4
index 3:
lst[3:] なので、目次にする対象は h3, h4, ....
index :3
lst[:3] なので、目次にする対象は h1, h2
index
パラメータの指定がなければ lst[:] 扱いで、全てのヘッダタグを対象にします。
目次の形式は、ヘッダタグの階層に従って ulタグの入れ子の構成にします。
ulタグの処理は既に実装してるので、 ヘッダの番号に応じて字下げしたテキストデータを作り、 ulタグとして処理すれば楽チンですね。
$ cat v8.patch | patch -p1
$ cat foo_8.txt : そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回[[ - |「うぅっ」]] 「ぬはぁ」とうなってます。 ---- index ---- p 2: の場合 index 2: ---- p :4 の場合 index :4 ---- p 2:3 の場合 index 2:3 ---- p 2 の場合 index 2 ---- p 3 の場合 index 3 ---- h2 結論
実行してみます。
$ ./ezmd.py < foo_8.txt : - p: - そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 - 毎回 - s: 「うぅっ」 - 「ぬはぁ」とうなってます。 - p: hr: / - ul: - li /: a href="#c_1_0": Python2とPython3での日本語文字列対応について - ul: - li /: a href="#c_2_1": 結論 - ul: - li /: a href="#c_3_2": 日本語を含む文字列処理で .foramt() や .join() を使いたい - li /: a href="#c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - li /: a href="#c_3_4": ここはh3--- - p: hr: / - p: - '2: の場合' - ul: - li /: a href="#c_2_1": 結論 - ul: - li /: a href="#c_3_2": 日本語を含む文字列処理で .foramt() や .join() を使いたい - li /: a href="#c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - li /: a href="#c_3_4": ここはh3--- - p: hr: / - p: - :4 の場合 - ul: - li /: a href="#c_1_0": Python2とPython3での日本語文字列対応について - ul: - li /: a href="#c_2_1": 結論 - ul: - li /: a href="#c_3_2": 日本語を含む文字列処理で .foramt() や .join() を使いたい - li /: a href="#c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - li /: a href="#c_3_4": ここはh3--- - p: hr: / - p: - 2:3 の場合 - ul: - li /: a href="#c_2_1": 結論 - p: hr: / - p: - 2 の場合 - ul: - li /: a href="#c_2_1": 結論 - p: hr: / - p: - 3 の場合 - ul: - li /: a href="#c_3_2": 日本語を含む文字列処理で .foramt() や .join() を使いたい - li /: a href="#c_3_3": 日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい - li /: a href="#c_3_4": ここはh3--- - p: hr: / - h2: a name="c_2_1": 結論
さすがにこれは、パッとみて大丈夫かどうか分かりかねますね。
$ ./to_html.py foo_head.yaml foo_8.txt | tee foo_8.html | nkf -u : <p>そして、YAML形式データファイル中の文字列を、UTF-8で日本語に置き換えようとして、 毎回 <s>「うぅっ」</s> 「ぬはぁ」とうなってます。</p> <p><hr></p> <ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a> <ul><li><a href="#c_2_1">結論</a> <ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a> <li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a> <li><a href="#c_3_4">ここはh3---</a></ul></ul></ul> <p><hr></p> <p>2: の場合</p> <ul><li><a href="#c_2_1">結論</a> <ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a> <li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a> <li><a href="#c_3_4">ここはh3---</a></ul></ul> <p><hr></p> <p>:4 の場合</p> <ul><li><a href="#c_1_0">Python2とPython3での日本語文字列対応について</a> <ul><li><a href="#c_2_1">結論</a> <ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a> <li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a> <li><a href="#c_3_4">ここはh3---</a></ul></ul></ul> <p><hr></p> <p>2:3 の場合</p> <ul><li><a href="#c_2_1">結論</a></ul> <p><hr></p> <p>2 の場合</p> <ul><li><a href="#c_2_1">結論</a></ul> <p><hr></p> <p>3 の場合</p> <ul><li><a href="#c_3_2">日本語を含む文字列処理で .foramt() や .join() を使いたい</a> <li><a href="#c_3_3">日本語を含むUTF-8のテキストを標準入力、標準出力で扱いたい</a> <li><a href="#c_3_4">ここはh3---</a></ul> <p><hr></p> <h2><a name="c_2_1">結論</a></h2> :
むー、まぁ、百聞は一見にしかず
大丈夫そうですね。
todo
自分ではいつもheadタグには日本語は書かないので、 ここは安易に
$ cat v9.patch | patch -p1
実行してみます。
$ ./to_html.py Usage: ./to_html.py head.yaml body.txt [title] $ ./to_html.py foo_head.yaml foo_8.txt | grep title <title>py23str</title> $ ./to_html.py foo_head.yaml foo_8.txt 'sample page' | grep title <title>sample page</title> $ ./to_html.py foo_head.yaml foo_8.txt 'sample page' > foo_9.html
OK
todo
色々試してみて不具合でました。
ulタグの処理前に、字下げの絡みで行の結合をする箇所。
def esc_join(lst): res = [] for s in lst: if res and res[-1] and res[-1][-1] == '\\': t = res[-1][:-1] res[-1] = strip_tail(t) + strip_head(s) else: res.append(s) return res
res[-1]が空文字列''の場合に、''[-1]になってアクセスでエラーが出る事がありました。
- if res and res[-1][-1] == '\\': + if res and res[-1] and res[-1][-1] == '\\':
な修正をしておきます。
次の調整を入れておきます。
$ cat v10.patch | patch -p1
では満を持して、このページ自身もこの仕様のテキストで書いてみましょう。
このテキストファイルから
$ ./to_html.py head.yaml index.ez.txt ezmd > index.html
となります。
(再帰だ〜)
todo