簡易なHTMLパーサ 2018秋

2021/FEB/23

更新履歴
日付 変更内容
2018秋 新規作成
2018/SEP/17 漢字
入力データのHTML自動判定
HTMLからYAMLへの変換
2018/SEP/18 preタグのyamlダンプ
liタグの改行の辺りを
fileコマンドの判定の甘さ対策
大きいデータの標準入力への書き込み対応
2018/SEP/20 preタグの中のタグの改行対応
タグ中のタグの中身はstirp()かけない対応
コメント対応
2020/FEB/01 kon_ut対応
2021/FEB/23 bare対応

目次

自分のページのHTMLは、簡素で限られたHTMLタグしか使われてません。

なぜか?

HTMLを手打ちしてるからです。

別に凝ったことはしないので「まぁこれでいいか」と。

にしても、HTMLのタグのタイプにボチボチ疲れてきました。

後でちょっと手を加えたいときなど、今どこにいるのか、ちょいちょい迷子になることしばしば。

どうせ自分で使う分には、限られたパターンしか使ってないし、 HTML形式を簡単にYAML形式に変換できないものか?

HTMLからYAMLに変換して、編集して、またYAMLからHTMLに戻せれないものか?

という事でpythonでツールを作ってみます。


YAML形式

HTMLのタグと文字列をYAML形式でどう表現すべしか?

私の中では「YAML形式」イコール「pythonの辞書とリストと文字列」

pythonのオブジェクトとしてどう保持したら良いか?

辞書は便利そうですが順番が保証されません。 かと言ってリストだけでは、ネスとが深くなると訳が分からなくなりそうです。

方針

これくらいで行けそうかな?

「/」という一文字の文字列を特別な値として使うので、 例えば <p>/</p> を読み込んだとすると、 終了タグがない <p>/ の扱いになりますね。

まぁ自分でそんなパターンを使う事は滅多にないだろうし、 後でもし困ったら何とかすれば良いでしょ。

例えば

ck1.html
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>foo</h1>

<p>bar hoge</p>

<pre>
fuga
  guha
</pre>

<p><hr></p>
</body>
</html>

の場合のYAML形式は

ck1.yaml
- html:
  - head:
      title: Title
  - body:
    - h1: foo
    - p: bar hoge
    - pre: |

        fuga
          guha
    - p:
        hr: /

てな具合に。

このYAML形式への「慣れ」が必要ですが、かなりスッキリした感じに見えます。


YAMLからHTMLのダンプから

まずは、こちら方向の変換から。

これは、チョー簡単です。

ezhtml.py
#!/usr/bin/env python

import sys
import yaml
import six

def cv_amp(s, d='enc'):
	lst = [ ('&','&amp;'), ('<','&lt;'), ('>','&gt;') ]
	if d != 'enc':
		lst = reversed(lst)
	for (f, t) in lst:
		if d != 'enc':
			(f, t) = (t, f)
		s = s.replace(f, t)
	return s

def html_dump(o):
	if not o:
		return ''
	if type(o) == list:
		return '\n'.join( map(html_dump, o) )
	if type(o) == dict:
		(tag, v) = list( o.items() )[0]
		s = '<' + tag + '>'
		if v != '/':
			s += html_dump(v) + '</' + tag.split(' ')[0] + '>'
		return s
	return cv_amp(o)

if __name__ == "__main__":
	fi = sys.stdin if six.PY2 else sys.stdin.buffer
	s = fi.read()
	s = unicode(s, 'utf-8') if six.PY2 else s.decode()

	o = yaml.load(s)

	s = html_dump(o) + '\n'
	s = s.encode('utf-8') if six.PY2 else s.encode()

	fo = sys.stdout if six.PY2 else sys.stdout.buffer
	fo.write(s)
# EOF

python2, python3 でも動くようにとした箇所がちょっと煩雑ですが、 核心部分はシンプルです。

$ cat ck1.yaml | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p><hr></p></body></html>

$ cat ck1.html
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>foo</h1>

<p>bar hoge</p>

<pre>
fuga
  guha
</pre>

<p><hr></p>
</body>
</html>

改行の違いはしょうがないのでOK。


漢字

漢字が扱えるように対応しておきます。

nkfのお力を借ります。

pythonでとりあえずutf-8で読み込んで、内部はunicodeで処理します。

python2 と python3 で、その辺りの文字列の取り扱いの変更がややこしそうですが...

nkf.py を作ってみたので、ここで吸収させる事にします。

v2.patch
diff -urN v1/ezhtml.py v2/ezhtml.py
--- v1/ezhtml.py	2018-09-16 16:32:39.000000000 +0900
+++ v2/ezhtml.py	2018-09-17 00:15:20.000000000 +0900
@@ -3,6 +3,7 @@
 import sys
 import yaml
 import six
+import nkf

 def cv_amp(s, d='enc'):
 	lst = [ ('&','&amp;'), ('<','&lt;'), ('>','&gt;') ]
@@ -28,15 +29,16 @@
 	return cv_amp(o)

 if __name__ == "__main__":
-	fi = sys.stdin if six.PY2 else sys.stdin.buffer
-	s = fi.read()
-	s = unicode(s, 'utf-8') if six.PY2 else s.decode()
+	b = nkf.get_stdin()
+	opt = nkf.guess(b)
+	u8 = nkf.cvt(b, '-u')
+	s = nkf.dec(u8)

 	o = yaml.load(s)

 	s = html_dump(o) + '\n'
-	s = s.encode('utf-8') if six.PY2 else s.encode()

-	fo = sys.stdout if six.PY2 else sys.stdout.buffer
-	fo.write(s)
+	u8 = nkf.enc(s)
+	b = nkf.cvt(u8, opt)
+	nkf.put_stdout(b)
 # EOF
diff -urN v1/nkf.py v2/nkf.py
--- v1/nkf.py	1970-01-01 09:00:00.000000000 +0900
+++ v2/nkf.py	2018-09-17 00:15:20.000000000 +0900
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+
+import sys
+import six
+import subprocess
+
+PIPE = subprocess.PIPE
+
+enc = lambda s: s.encode('utf-8') if six.PY2 else s.encode()
+dec = lambda b: unicode(b, 'utf-8') if six.PY2 else b.decode()
+
+def do_cmd(cmd, in_b):
+	cmd = enc(cmd)
+	proc = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE)
+	proc.stdin.write(in_b)
+	proc.stdin.close()
+	r = proc.stdout.read()
+	proc.wait()
+	return r # out_b
+
+def get_stdin():
+	fi = sys.stdin if six.PY2 else sys.stdin.buffer
+	return fi.read() # b
+
+def put_stdout(b):
+	fo = sys.stdout if six.PY2 else sys.stdout.buffer
+	fo.write(b)
+
+def guess(b):
+	b = do_cmd('nkf -g', b)
+	return dec(b).strip()
+
+def cvt(b, opt):
+	if opt == 'ASCII':
+		return b
+	d = {
+		'ISO-2022-JP': '-j',
+		'EUC-JP': '-e',
+		'Shift_JIS': '-s',
+		'UTF-8': '-u',
+	}
+	if opt not in d.values():
+		opt = d.get(opt, '-u')
+	return do_cmd('nkf ' + opt, b)
+
+if __name__ == "__main__":
+	b = get_stdin()
+	opt = guess(b)
+	u8 = cvt(b, '-u')
+	s = dec(u8)
+	# ...
+	u8 = enc(s)
+	b = cvt(u8, opt)
+	put_stdout(b)
+# EOF

$ cat v2.patch | patch -p1

$ cat nkf.py
#!/usr/bin/env python

import sys
import six
import subprocess

PIPE = subprocess.PIPE

enc = lambda s: s.encode('utf-8') if six.PY2 else s.encode()
dec = lambda b: unicode(b, 'utf-8') if six.PY2 else b.decode()

def do_cmd(cmd, in_b):
        cmd = enc(cmd)
        proc = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE)
        proc.stdin.write(in_b)
        proc.stdin.close()
        r = proc.stdout.read()
        proc.wait()
        return r # out_b

def get_stdin():
        fi = sys.stdin if six.PY2 else sys.stdin.buffer
        return fi.read() # b

def put_stdout(b):
        fo = sys.stdout if six.PY2 else sys.stdout.buffer
        fo.write(b)

def guess(b):
        b = do_cmd('nkf -g', b)
        return dec(b).strip()

def cvt(b, opt):
        if opt == 'ASCII':
                return b
        d = {
                'ISO-2022-JP': '-j',
                'EUC-JP': '-e',
                'Shift_JIS': '-s',
                'UTF-8': '-u',
        }
        if opt not in d.values():
                opt = d.get(opt, '-u')
        return do_cmd('nkf ' + opt, b)

if __name__ == "__main__":
        b = get_stdin()
        opt = guess(b)
        u8 = cvt(b, '-u')
        s = dec(u8)
        # ...
        u8 = enc(s)
        b = cvt(u8, opt)
        put_stdout(b)
# EOF
$

mainの箇所の例では

jis.yaml

$ cat jis.yaml | nkf -g
ISO-2022-JP

$ cat jis.yaml | nkf -u
- html:
  - head:
      title: タイトル
  - body:
    - h1: ふー
    - p: ばー ほげ
    - pre: |

        ふが
          ぐは
    - p:
        hr: /

$ chmod +x nkf.py

$ cat jis.yaml | ./nkf.py | nkf -g
ISO-2022-JP

$ cat jis.yaml | ./nkf.py | diff jis.yaml -
$

JISコードからUTF-8, unicode を経て UTF-8, JISコードに戻って、一致。

同様にEUCの場合も

$ cat jis.yaml | nkf -e | tee euc.yaml | ./nkf.py | nkf -g
EUC-JP

$ cat euc.yaml | ./nkf.py | diff euc.yaml -
$

その他

$ cat jis.yaml | nkf -s | tee sjis.yaml | ./nkf.py | nkf -g
Shift_JIS

$ cat sjis.yaml | ./nkf.py | diff sjis.yaml -
$

$ cat jis.yaml | nkf -u | tee utf8.yaml | ./nkf.py | nkf -g
UTF-8

$ cat utf8.yaml | ./nkf.py | diff utf8.yaml -
$

$ cat ck1.yaml
- html:
  - head:
      title: Title
  - body:
    - h1: foo
    - p: bar hoge
    - pre: |

        fuga
          guha
    - p:
        hr: /

$ cat ck1.yaml | nkf -g
ASCII

$ cat ck1.yaml | ./nkf.py
- html:
  - head:
      title: Title
  - body:
    - h1: foo
    - p: bar hoge
    - pre: |

        fuga
          guha
    - p:
        hr: /

$ cat ck1.yaml | ./nkf.py | diff ck1.yaml -
$

上記はpython3の環境で試しているので、同じ事をpython2でも確認しておきます。

$ cat jis.yaml | python2 ./nkf.py | diff jis.yaml -
$ cat euc.yaml | python2 ./nkf.py | diff euc.yaml -
$ cat sjis.yaml | python2 ./nkf.py | diff sjis.yaml -
$ cat utf8.yaml | python2 ./nkf.py | diff utf8.yaml -
$ cat ck1.yaml | python2 ./nkf.py | diff ck1.yaml -
$

大丈夫そうですね。

このnkf.pyをezhtml.pyから使うように変更してみました。

$ cat jis.yaml | ./ezhtml.py | nkf -u
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat jis.yaml | ./ezhtml.py | nkf -g
ISO-2022-JP

$ cat euc.yaml | ./ezhtml.py | nkf -g
EUC-JP

$ cat sjis.yaml | ./ezhtml.py | nkf -g
Shift_JIS

$ cat utf8.yaml | ./ezhtml.py | nkf -g
UTF-8

$ cat ck1.yaml | ./ezhtml.py | nkf -g
ASCII

$ cat ck1.yaml | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p><hr></p></body></html>

一応 python2 でも同様に

$ cat jis.yaml | python2 ./ezhtml.py | nkf -u
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat jis.yaml | python2 ./ezhtml.py | nkf -g
ISO-2022-JP

$ cat euc.yaml | python2 ./ezhtml.py | nkf -g
EUC-JP

$ cat sjis.yaml | python2 ./ezhtml.py | nkf -g
Shift_JIS

$ cat utf8.yaml | python2 ./ezhtml.py | nkf -g
UTF-8

$ cat ck1.yaml | python2 ./ezhtml.py | nkf -g
ASCII

OK。


入力データのHTML自動判定

標準入力からのデータの形式を自動判定させてみます。

HTMLならYAMLに変換して出力し、HTML以外ならYAMLとみなしてHTMLに変換して出力するようにしてみます。

といっても、今のところはYAMLからHTMLの方向の変換しか実装してませんが...

v3.patch
diff -urN v2/ezhtml.py v3/ezhtml.py
--- v2/ezhtml.py	2018-09-17 00:15:20.000000000 +0900
+++ v3/ezhtml.py	2018-09-17 20:15:22.000000000 +0900
@@ -28,15 +28,23 @@
 		return s
 	return cv_amp(o)

+def html_load(s):
+	# ...
+	return { 'html': { 'body': { 'p': 'to be continued' } } }
+
 if __name__ == "__main__":
 	b = nkf.get_stdin()
 	opt = nkf.guess(b)
+	html = nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
 	u8 = nkf.cvt(b, '-u')
 	s = nkf.dec(u8)

-	o = yaml.load(s)
-
-	s = html_dump(o) + '\n'
+	if html:
+		o = html_load(s)
+		s = yaml.dump( o, default_flow_style=False )
+	else:
+		o = yaml.load(s)
+		s = html_dump(o) + '\n'

 	u8 = nkf.enc(s)
 	b = nkf.cvt(u8, opt)

$ cat v3.patch | patch -p1

$ cat v3.patch
   :
 if __name__ == "__main__":
        b = nkf.get_stdin()
        opt = nkf.guess(b)
+       html = nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
        u8 = nkf.cvt(b, '-u')
        s = nkf.dec(u8)
   :

この1行でHTML形式かどうかを判定します。

fileコマンドの標準入力にデータを与えて、結果の文字列からgrepコマンドでhtmlの文字列を大文字小文字を無視して探します。

$ cat ck1.yaml
- html:
  - head:
      title: Title
  - body:
    - h1: foo
    - p: bar hoge
    - pre: |

        fuga
          guha
    - p:
        hr: /

$ cat ck1.yaml | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p><hr></p></body></html>

$ cat ck1.yaml | ./ezhtml.py | ./ezhtml.py
html:
  body:
    p: to be continued

HTMLからYAMLへの変換は、乞うご期待。

漢字の確認もいくつか

$ cat jis.yaml | nkf -u
- html:
  - head:
      title: タイトル
  - body:
    - h1: ふー
    - p: ばー ほげ
    - pre: |

        ふが
          ぐは
    - p:
        hr: /

$ cat jis.yaml | ./ezhtml.py | nkf -u
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat jis.yaml | ./ezhtml.py | ./ezhtml.py | nkf -u
html:
  body:
    p: to be continued

$ cat jis.yaml | nkf -u | ./ezhtml.py
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat jis.yaml | nkf -u | ./ezhtml.py | ./ezhtml.py
html:
  body:
    p: to be continued

$ cat jis.yaml | nkf -u | python2 ./ezhtml.py
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat jis.yaml | nkf -u | python2 ./ezhtml.py | python2 ./ezhtml.py
html:
  body:
    p: to be continued

OK。


HTMLからYAMLへの変換

HTMLからYAMLへの変換。

すなわち、HTMLをロードしてpythonのオブジェクトで保持して、 それをPyYAMLでdumpとなります。

とりあえず一発目のHTMLのロードを書いてみました。

v4.patch
diff -urN v3/ezhtml.py v4/ezhtml.py
--- v3/ezhtml.py	2018-09-17 20:15:22.000000000 +0900
+++ v4/ezhtml.py	2018-09-17 23:46:44.000000000 +0900
@@ -28,9 +28,107 @@
 		return s
 	return cv_amp(o)

+def get_tag(s):
+	(p, tag) = ('', [])
+
+	while '<' in s:
+		i = s.index('<')
+		(t, s) = ( s[:i], s[i+1:] )
+		p += t
+		tag.append('<')
+		n = s[:1]
+		if n == '/':
+			tag.append('/')
+			s = s[1:]
+			n = s[:1]
+		if n.isalpha():
+			if '>' not in s:
+				err( "not found '>'", 'tag={}'.format(tag) )
+			i = s.index('>')
+			tag = tag[1:] + s[:i].split(' ')
+			s = s[i+1:]
+			break
+		p += ''.join(tag)
+		tag = []
+
+	if not tag:
+		(p, s) = (p+s, '')
+
+	return (p, tag, s)
+
+def start_idx(stk, s):
+	for i in reversed( range( len(stk) ) ):
+		e = stk[i]
+		if type(e) == list and e[0] == s:
+			return i
+	return -1
+
+def solo_tag(e):
+	if type(e) == list:
+		(h, e) = ( '/', e[1:] ) if e[0] == '/' else ('', e)
+		return { h + ' '.join(e): '/' }
+	return e
+
+def solo_tags(lst):
+	return list( map( solo_tag, lst ) )
+
+def untabify(s, n=8):
+	def f(s):
+		r = ''
+		for c in s:
+			if c == '\t':
+				c = ' ' * ( n - len(r) % n )
+			r += c
+		return r
+
+	lst = s.split('\n')
+	lst = map(f, lst)
+	return '\n'.join(lst)
+
+def strip_lst(lst, pre=False):
+	def f(e):
+		if type(e) == dict:
+			return e
+		if pre:
+			while ' \n' in e:
+				e = e.replace(' \n', '\n')
+			return untabify(e)
+		return e.replace('\n', ' ').strip()
+
+	return list( filter( lambda e: e != '', map(f, lst) ) )
+
+def close_tag(lst):
+	tag = lst[0]
+	lst = solo_tags( lst[1:] )
+	lst = strip_lst( lst, tag[0].lower() == 'pre' )
+	v = lst
+	if len(lst) == 1:
+		v = lst[0]
+	elif not lst:
+		v = ''
+	return { ' '.join(tag): v }
+
 def html_load(s):
-	# ...
-	return { 'html': { 'body': { 'p': 'to be continued' } } }
+	stk = []
+	while True:
+		(p, tag, s) = get_tag(s)
+		if not tag:
+			break
+		if p:
+			stk.append( cv_amp(p, 'dec') )
+		if tag[0] != '/':
+			stk.append(tag)
+			continue
+		i = start_idx( stk, tag[1] )
+		if i >= 0:
+			stk = stk[:i] + [ close_tag( stk[i:] ) ]
+		else:
+			stk.append( solo_tag(tag) )
+
+	o = strip_lst( solo_tags(stk) )
+	while type(o) == list and len(o) == 1:
+		o = o[0]
+	return o

 if __name__ == "__main__":
 	b = nkf.get_stdin()

$ cat v4.patch | patch -p1

逆方向のHTMLのダンプに比べるとコードが多いですが、 できるだけシンプルにまとめてみました。

$ cat ck1.html
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>foo</h1>

<p>bar hoge</p>

<pre>
fuga
  guha
</pre>

<p><hr></p>
</body>
</html>

$ cat ck1.html | ./ezhtml.py | tee ck2.yaml
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: "\nfuga\n  guha\n"
  - p:
      hr: /

$ diff ck1.yaml ck2.yaml
1,12c1,9
< - html:
<   - head:
<       title: Title
<   - body:
<     - h1: foo
<     - p: bar hoge
<     - pre: |
<
<         fuga
<           guha
<     - p:
<         hr: /
---
> html:
> - head:
>     title: Title
> - body:
>   - h1: foo
>   - p: bar hoge
>   - pre: "\nfuga\n  guha\n"
>   - p:
>       hr: /

おっと、最初に手打ちで作ったck1.yaml。 全体を要素数1のリストにしてましたが、 htmlタグ1つなので、全体を辞書にしても大丈夫でした。

あとpreタグ。縦棒「|」の形式でダンプさせたいところ...

$ cat ck2.yaml
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: "\nfuga\n  guha\n"
  - p:
      hr: /

$ cat ck2.yaml | ./ezhtml.py | tee ck2.html
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p><hr></p></body></html>

$ cat ck1.yaml | ./ezhtml.py | diff ck2.html -
$

$ cat ck2.yaml | ./ezhtml.py | diff ck2.html -
$

$ cat ck2.html | ./ezhtml.py | diff ck2.yaml -
$

$ cat ck2.html
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p><hr></p></body></html>

$ cat ck2.html | ./ezhtml.py
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: "\nfuga\n  guha\n"
  - p:
      hr: /

$ cat ck2.html | ./ezhtml.py | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p><hr></p></body></html>

$ cat ck2.html | ./ezhtml.py | ./ezhtml.py | ./ezhtml.py
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: "\nfuga\n  guha\n"
  - p:
      hr: /

とりあえず動いて嬉しいです。

TODO


preタグのyamlダンプ

preタグのyamlダンプを「|」形式に。

PyYAMLに頼ってる箇所ではありますが...どうしたものか? ぐぐってみると、ヒントが。

「PyYAMLで改行含む文字列の出力結果を変えたい(`|` を使いたい)」

まさにそうです!

参考にさせて頂きました。ありがとうございます。

v5.patch
diff -urN v4/ezhtml.py v5/ezhtml.py
--- v4/ezhtml.py	2018-09-17 23:46:44.000000000 +0900
+++ v5/ezhtml.py	2018-09-18 00:31:27.000000000 +0900
@@ -130,6 +130,18 @@
 		o = o[0]
 	return o

+def yaml_dump(o):
+	def represent_str(dumper, instance):
+		tag = 'tag:yaml.org,2002:str'
+		style = '|' if '\n' in instance else None
+		return dumper.represent_scalar( tag, instance, style=style )
+
+	for typ in [ str ] + ( [ unicode ] if six.PY2 else [] ):
+		yaml.add_representer(typ, represent_str)
+
+	u8 = yaml.dump( o, default_flow_style=False, allow_unicode=True, encoding='utf-8' )
+	return nkf.dec(u8)
+
 if __name__ == "__main__":
 	b = nkf.get_stdin()
 	opt = nkf.guess(b)
@@ -139,7 +151,7 @@

 	if html:
 		o = html_load(s)
-		s = yaml.dump( o, default_flow_style=False )
+		s = yaml_dump(o)
 	else:
 		o = yaml.load(s)
 		s = html_dump(o) + '\n'

$ cat v5.patch | patch -p1

他 allow_unicode, encoding の引数指定追加で yaml.dump()の漢字対応もしてます。

これでyaml.dump()がutf-8にまで変換してくれるようになったのですが、 後続の共通処理でのutf-8への変換を残しときたいので、 nkf.dec()でunicodeの状態に戻してから、後続に渡すようにしてます。

$ cat ck1.html
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>foo</h1>

<p>bar hoge</p>

<pre>
fuga
  guha
</pre>

<p><hr></p>
</body>
</html>

$ cat ck1.html | ./ezhtml.py
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |2

      fuga
        guha
  - p:
      hr: /

$ cat ck1.html | ./ezhtml.py | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p><hr></p></body></html>

$ cat ck1.html | ./ezhtml.py | ./ezhtml.py | ./ezhtml.py
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |2

      fuga
        guha
  - p:
      hr: /

なんか「|」に「2」とか付いてます。

字下げの数を明示的に指定だそうです。ふむふむ。

$ cat jis.html | nkf -u
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat jis.html | ./ezhtml.py | nkf -u
html:
- head:
    title: タイトル
- body:
  - h1: ふー
  - p: ばー ほげ
  - pre: |2

      ふが
        ぐは
  - p:
      hr: /

$ cat jis.html | ./ezhtml.py | ./ezhtml.py | nkf -u
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat jis.html | ./ezhtml.py | ./ezhtml.py | ./ezhtml.py | nkf -u
html:
- head:
    title: タイトル
- body:
  - h1: ふー
  - p: ばー ほげ
  - pre: |2

      ふが
        ぐは
  - p:
      hr: /

大丈夫そうですね。

$ cat jis.html | ./ezhtml.py > jis.yaml

$ cat jis.yaml | ./ezhtml.py | diff jis.html -
$

$ cat jis.html | ./ezhtml.py | ./ezhtml.py | diff jis.html -

$ cat jis.html | python2 ./ezhtml.py | python2 ./ezhtml.py | diff jis.html -

$ cat jis.html | nkf -e > euc.html
$ cat euc.html | nkf -g
EUC-JP

$ cat euc.html | ./ezhtml.py | ./ezhtml.py | diff euc.html  -
$

cat euc.html | python2 ./ezhtml.py | python2 ./ezhtml.py | diff euc.html  -
$

OK。

それではひとつ、それがしの トップページ なぞを。

$ wget -q -O- http://kondoh.html.xdomain.jp/index.html | tee top.html | nkf -u
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title> kon </title>
</head>
<body>

<h1> kon page </h1>

<p><hr></p>

<p><img src="beat.jpg"></p>

<p><hr></p>

<ul>
<li><a href="bike-kon.html"> バイク </a>
<li><a href=hist.html> 更新履歴 </a>
<li><a href=me.html> 自己紹介 </a>
<li><a href=java/index.html> Javaのテスト </a>
<li><a href=color-sample.html> 色見本 </a>
<li><a href=qP2240018.jpg> ライトネス Qちゃん 2002年頃 </a>
<li><a href="murakami-sho-ji-090329/index.html"> 村上商事 2009 </a>
<li><a href="copen-090419.jpg"> Copen 2009 湯っぷる </a>
<li><a href="txtbl.html"> 簡単なテキストの表組みツール (C言語) </a>
<li><a href="txtblcnt.html"> TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール) </a>
<li><a href="midi.html"> SMFを読み込み音の波形データを作るプログラム (C言語) </a>
<li><a href="cui14/index.html"> CUI14 </a>
<li><a href="wf.html"> ワイヤーフレームのプログラム </a>
<li><a href="es16/index.html"> Pythonで作るなんちゃってCインタプリタ </a>
<li><a href="nand17/index.html"> Pythonで作るなんちゃってNANDゲートシミュレータ </a>
<li><a href="tete17/index.html"> テテリス2017夏 </a>
<li><a href="pac/index.html"> パックマンもどき2017秋 </a>
<li><a href="bktool/index.html"> バックアップツール </a>
<li><a href="http://kondoh2.html.xdomain.jp/rt/index.html"> レイトレーシング 2018春 </a>
<li><a href="py3.html"> python3 対応のメモ </a>
<li><a href="ezyaml/index.html"> 簡易なYAMLパーサ 2018夏 </a>
<li><a href="ezhtml/index.html"> 簡易なHTMLパーサ 2018秋 </a>
</ul>

<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v62/cut.mp4" controls playsinline></video></p>

<p><hr></p>
</body>
</html>

$ cat top.html | ./ezhtml.py | tee top.yaml | nkf -u
html:
- head:
  - meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
  - title: kon
- body:
  - h1: kon page
  - p:
      hr: /
  - p:
      img src="beat.jpg": /
  - p:
      hr: /
  - ul:
    - li: /
    - a href="bike-kon.html": バイク
    - li: /
    - a href=hist.html: 更新履歴
    - li: /
    - a href=me.html: 自己紹介
    - li: /
    - a href=java/index.html: Javaのテスト
    - li: /
    - a href=color-sample.html: 色見本
    - li: /
    - a href=qP2240018.jpg: ライトネス Qちゃん 2002年頃
    - li: /
    - a href="murakami-sho-ji-090329/index.html": 村上商事 2009
    - li: /
    - a href="copen-090419.jpg": Copen 2009 湯っぷる
    - li: /
    - a href="txtbl.html": 簡単なテキストの表組みツール (C言語)
    - li: /
    - a href="txtblcnt.html": TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)
    - li: /
    - a href="midi.html": SMFを読み込み音の波形データを作るプログラム (C言語)
    - li: /
    - a href="cui14/index.html": CUI14
    - li: /
    - a href="wf.html": ワイヤーフレームのプログラム
    - li: /
    - a href="es16/index.html": Pythonで作るなんちゃってCインタプリタ
    - li: /
    - a href="nand17/index.html": Pythonで作るなんちゃってNANDゲートシミュレータ
    - li: /
    - a href="tete17/index.html": テテリス2017夏
    - li: /
    - a href="pac/index.html": パックマンもどき2017秋
    - li: /
    - a href="bktool/index.html": バックアップツール
    - li: /
    - a href="http://kondoh2.html.xdomain.jp/rt/index.html": レイトレーシング 2018春
    - li: /
    - a href="py3.html": python3 対応のメモ
    - li: /
    - a href="ezyaml/index.html": 簡易なYAMLパーサ 2018夏
    - li: /
    - a href="ezhtml/index.html": 簡易なHTMLパーサ 2018秋
  - p:
      video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline: ''
  - p:
      video src="http://kondoh2.html.xdomain.jp/rt/out_v62/cut.mp4" controls playsinline: ''
  - p:
      hr: /

$ cat top.html | ./ezhtml.py | ./ezhtml.py | tee top2.html | nkf -u
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>kon</title></head>
<body><h1>kon page</h1>
<p><hr></p>
<p><img src="beat.jpg"></p>
<p><hr></p>
<ul><li>
<a href="bike-kon.html">バイク</a>
<li>
<a href=hist.html>更新履歴</a>
<li>
<a href=me.html>自己紹介</a>
<li>
<a href=java/index.html>Javaのテスト</a>
<li>
<a href=color-sample.html>色見本</a>
<li>
<a href=qP2240018.jpg>ライトネス Qちゃん 2002年頃</a>
<li>
<a href="murakami-sho-ji-090329/index.html">村上商事 2009</a>
<li>
<a href="copen-090419.jpg">Copen 2009 湯っぷる</a>
<li>
<a href="txtbl.html">簡単なテキストの表組みツール (C言語)</a>
<li>
<a href="txtblcnt.html">TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)</a>
<li>
<a href="midi.html">SMFを読み込み音の波形データを作るプログラム (C言語)</a>
<li>
<a href="cui14/index.html">CUI14</a>
<li>
<a href="wf.html">ワイヤーフレームのプログラム</a>
<li>
<a href="es16/index.html">Pythonで作るなんちゃってCインタプリタ</a>
<li>
<a href="nand17/index.html">Pythonで作るなんちゃってNANDゲートシミュレータ</a>
<li>
<a href="tete17/index.html">テテリス2017夏</a>
<li>
<a href="pac/index.html">パックマンもどき2017秋</a>
<li>
<a href="bktool/index.html">バックアップツール</a>
<li>
<a href="http://kondoh2.html.xdomain.jp/rt/index.html">レイトレーシング 2018春</a>
<li>
<a href="py3.html">python3 対応のメモ</a>
<li>
<a href="ezyaml/index.html">簡易なYAMLパーサ 2018夏</a>
<li>
<a href="ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></ul>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v62/cut.mp4" controls playsinline></video></p>
<p><hr></p></body></html>

liタグの改行がアダとなって、逆に視認性が落ちてるような気がしなくもない...?

一応この top2.html をサイトのホームディレクトリにアップロードしてみました。

内容的には大丈夫そうですね。

TODO


liタグの改行の辺りを

それがしの トップページ でHTMLからYAMLの変換を試してみると

<ul>
<li><a href="bike-kon.html"> バイク </a>
<li><a href=hist.html> 更新履歴 </a>
<li><a href=me.html> 自己紹介 </a>
  :
<li><a href="ezhtml/index.html"> 簡易なHTMLパーサ 2018秋 </a>
</ul>

な箇所が

- ul:
  - li: /
  - a href="bike-kon.html": バイク
  - li: /
  - a href=hist.html: 更新履歴
  - li: /
  - a href=me.html: 自己紹介
     :
  - li: /
  - a href="ezhtml/index.html": 簡易なHTMLパーサ 2018秋

てな具合に改行が入って、さらにこのYAMLをHTMLに変換しなおすと

<ul><li>
<a href="bike-kon.html">バイク</a>
<li>
<a href=hist.html>更新履歴</a>
<li>
<a href=me.html>自己紹介</a>
  :
<li>
<a href="ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></ul>

ブラウザで表示される内容は同じとは言え、 何とか改行を入れないようにできないでしょうか?

通常のタグは

<tag>foo</tag>

な形式で、'/'で始まる終了タグがついてます。

変換するYAML形式では

tag: foo

の辞書にしてます。

HTMLの場合、この終了タグがないパターンがある訳で、 その場合のYAML形式は

tag: /

の辞書にしてます。

よく考えると終了タグがないパターンは2通りあります。

開始タグだけで意味が完結してる

<tag>

のパターン。

もう一つは

<tag>foo</tag>

で意味が完結するところだが、終了タグが省略されている

<tag>foo

のパターン。

前者はこれまでの対応がふさわしく。

さらに後者のパターンの対応を追加してみます。

これまでの方針

に加えて

先のulタグ、liタグの場合ならば

ul:
- li: /
- foo
- li: /
- bar

ul:
- li /: foo
- li /: bar

あるいは

ul:
- li/: foo
- li/: bar

も許す事にしてみます。

まずはダンプ側の対応から。こちら側の変更は簡単。

v6.patch
diff -urN v5/ezhtml.py v6/ezhtml.py
--- v5/ezhtml.py	2018-09-18 00:31:27.000000000 +0900
+++ v6/ezhtml.py	2018-09-18 21:51:22.000000000 +0900
@@ -15,6 +15,19 @@
 		s = s.replace(f, t)
 	return s

+def dump_tag(tag, v):
+	lst = bak = tag.split(' ')
+	if lst[-1] == '/':
+		lst = lst[:-1]
+	if lst[0][-1] == '/':
+		lst = [ lst[0][:-1] ] + lst[1:]
+	s = '<' + ' '.join(lst) + '>'
+	if v != '/':
+		s += html_dump(v)
+		if lst == bak:
+			s += '</' + lst[0] + '>'
+	return s
+
 def html_dump(o):
 	if not o:
 		return ''
@@ -22,10 +35,7 @@
 		return '\n'.join( map(html_dump, o) )
 	if type(o) == dict:
 		(tag, v) = list( o.items() )[0]
-		s = '<' + tag + '>'
-		if v != '/':
-			s += html_dump(v) + '</' + tag.split(' ')[0] + '>'
-		return s
+		return dump_tag(tag, v)
 	return cv_amp(o)

 def get_tag(s):

$ cat v6.patch
diff -urN v5/ezhtml.py v6/ezhtml.py
--- v5/ezhtml.py        2018-09-18 00:31:27.000000000 +0900
+++ v6/ezhtml.py        2018-09-18 21:51:22.000000000 +0900
@@ -15,6 +15,19 @@
                s = s.replace(f, t)
        return s

+def dump_tag(tag, v):
+       lst = bak = tag.split(' ')
+       if lst[-1] == '/':
+               lst = lst[:-1]
+       if lst[0][-1] == '/':
+               lst = [ lst[0][:-1] ] + lst[1:]
+       s = '<' + ' '.join(lst) + '>'
+       if v != '/':
+               s += html_dump(v)
+               if lst == bak:
+                       s += '</' + lst[0] + '>'
+       return s
+
 def html_dump(o):
        if not o:
                return ''
@@ -22,10 +35,7 @@
                return '\n'.join( map(html_dump, o) )
        if type(o) == dict:
                (tag, v) = list( o.items() )[0]
-               s = '<' + tag + '>'
-               if v != '/':
-                       s += html_dump(v) + '</' + tag.split(' ')[0] + '>'
-               return s
+               return dump_tag(tag, v)
        return cv_amp(o)

 def get_tag(s):


$ cat v6.patch | patch -p1

ck3.yaml
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |

      fuga
        guha
  - p: gundam
  - ul:
    - li: /
    - zaku
    - li /: gufu
    - li/: dom
  - p:
      hr: /

もう一丁変換すると...

$ cat ck3.yaml | ./ezhtml.py | ./ezhtml.py
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |2

      fuga
        guha
  - p: gundam
  - ul:
    - li: /
    - zaku
    - li: /
    - gufu
    - li: /
    - dom
  - p:
      hr: /

こちら方向の変換は未対応なので、この形式に戻ってしまいます。

では、ロード側。

パース処理の駆動原理は

終了タグの無い場合に、従来の { tag: / } 形式とするか、新設した { tag /: xxx } 形式とするか?

これはもうHTMLのタグの仕様の意味に依ります。

終了タグの省略が許されてる一覧を、データとして持たせる事にします。

すぐ思い当たるのはliタグですが、他には?

それがしの ワイヤーフレーム のページで、終了タグのないものを調べてみます。

$ wget -q -O- http://kondoh.html.xdomain.jp/wf.html | ./ezhtml.py | grep ': /' | sed 's/ *//' | sort | uniq
- a: /
- br: /
- li: /
- meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
hr: /
img src="wf/img/g1.gif": /
img src="wf/img/g10.gif": /
  :
img src="wf/img/w9.png": /

aタグ?

$ wget -q -O- http://kondoh.html.xdomain.jp/wf.html | ./ezhtml.py | less
   :
  - a: /
  - a name="try_repeat_copy":
      h2: 繰り返しのパターンを試す
   :

対応箇所は

<a> <a name="try_repeat_copy">
<h2> 繰り返しのパターンを試す </h2>
</a>

あぁ... 確かに、なんか間違ってる。orz

他は、br, li, meta, hr, img

後続の内容を意味的に含んでいて、終了タグが省略されてるパターンはli。

他のHTMLファイル、例えば

$ wget -q -O- http://kondoh.html.xdomain.jp/py3.html | ./ezhtml.py
Traceback (most recent call last):
  File "./ezhtml.py", line 166, in <module>
    o = yaml.load(s)
  File "/usr/lib/python2.7/dist-packages/yaml/__init__.py", line 71, in load
    return loader.get_single_data()
  File "/usr/lib/python2.7/dist-packages/yaml/constructor.py", line 37, in get_single_data
    node = self.get_single_node()
  File "/usr/lib/python2.7/dist-packages/yaml/composer.py", line 36, in get_single_node
    document = self.compose_document()
  File "/usr/lib/python2.7/dist-packages/yaml/composer.py", line 58, in compose_document
    self.get_event()
  File "/usr/lib/python2.7/dist-packages/yaml/parser.py", line 118, in get_event
    self.current_event = self.state()
  File "/usr/lib/python2.7/dist-packages/yaml/parser.py", line 193, in parse_document_end
    token = self.peek_token()
  File "/usr/lib/python2.7/dist-packages/yaml/scanner.py", line 128, in peek_token
    self.fetch_more_tokens()
  File "/usr/lib/python2.7/dist-packages/yaml/scanner.py", line 220, in fetch_more_tokens
    return self.fetch_value()
  File "/usr/lib/python2.7/dist-packages/yaml/scanner.py", line 576, in fetch_value
    self.get_mark())
yaml.scanner.ScannerError: mapping values are not allowed here
  in "<unicode string>", line 5, column 24:
    <style> pre{ background: lightgray; } </style>
                           ^

おおっと。

HTML食わせてるのにyaml.load()?

$ wget -q -O- http://kondoh.html.xdomain.jp/py3.html | file -
/dev/stdin: Python script, ASCII text executable, with escape sequences

py3.htmlの内容をfileコマンドがHTMLと思ってくれてない (T_T)

とりあえず、このデータ形式の自動判定の問題は後回し...

$ wget -q -O- http://kondoh.html.xdomain.jp/midi.html | ./ezhtml.py
Traceback (most recent call last):
  File "./ezhtml.py", line 158, in <module>
    html = nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
  File "/raid5/kondoh/hobby/ezhtml/nkf.py", line 15, in do_cmd
    proc.stdin.write(in_b)
IOError: [Errno 32] Broken pipe

$ wget -q -O- http://kondoh.html.xdomain.jp/midi.html | file -
/dev/stdin: HTML document, ASCII text, with very long lines, with escape sequences

これはfileコマンドもHTMLと思っているけど

def do_cmd(cmd, in_b):
        cmd = enc(cmd)
        proc = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE)
        proc.stdin.write(in_b)

データ大き過ぎ?

$ wget -q -O- http://kondoh.html.xdomain.jp/midi.html | wc -l
29020

かも知れません。comunicateを使うべし? 一旦後回し...

とりあえず、終了タグ省略パターンは当面liだけ。 発見次第随時追加という事で。

v7.patch
diff -urN v6/ezhtml.py v7/ezhtml.py
--- v6/ezhtml.py	2018-09-18 21:51:22.000000000 +0900
+++ v7/ezhtml.py	2018-09-18 21:52:05.000000000 +0900
@@ -79,6 +79,39 @@
 		return { h + ' '.join(e): '/' }
 	return e

+def is_solo_tag_has_v(e):
+	lst = ['li']
+	if type(e) != dict:
+		return False
+	(tag, v) = e.items()[0]
+	return v == '/' and tag.split(' ')[0] in lst
+
+def solo_tag_has_v_idx(lst):
+	for i in range( len(lst) ):
+		if is_solo_tag_has_v( lst[i] ):
+			return i
+	return -1
+
+def strip_lst1(o):
+	while type(o) == list and len(o) == 1:
+		o = o[0]
+	return o
+
+def solo_tags_modify(lst):
+	def div_lst(lst):
+		i = solo_tag_has_v_idx(lst)
+		return ( lst[:i], lst[i:] ) if i >= 0 else ( lst, [] )
+	r = []
+	while lst:
+		(p, lst) = div_lst(lst)
+		r += p
+		if lst:
+			(e, lst) = ( lst[0], lst[1:] )
+			(tag, v) = e.items()[0] # v == '/'
+			(p, lst) = div_lst(lst)
+			r += [ { tag + ' /': strip_lst1(p) } ]
+	return r
+
 def solo_tags(lst):
 	return list( map( solo_tag, lst ) )

@@ -95,7 +128,7 @@
 	lst = map(f, lst)
 	return '\n'.join(lst)

-def strip_lst(lst, pre=False):
+def strip_lst(lst, pre):
 	def f(e):
 		if type(e) == dict:
 			return e
@@ -107,10 +140,16 @@

 	return list( filter( lambda e: e != '', map(f, lst) ) )

+def close_solo_tag(lst, pre=False):
+	lst = solo_tags(lst)
+	lst = strip_lst(lst, pre)
+	lst = solo_tags_modify(lst)
+	return lst
+
 def close_tag(lst):
-	tag = lst[0]
-	lst = solo_tags( lst[1:] )
-	lst = strip_lst( lst, tag[0].lower() == 'pre' )
+	(tag, lst) = ( lst[0], lst[1:] )
+	lst = close_solo_tag( lst, tag[0].lower() == 'pre' )
+
 	v = lst
 	if len(lst) == 1:
 		v = lst[0]
@@ -135,10 +174,8 @@
 		else:
 			stk.append( solo_tag(tag) )

-	o = strip_lst( solo_tags(stk) )
-	while type(o) == list and len(o) == 1:
-		o = o[0]
-	return o
+	o = close_solo_tag(stk)
+	return strip_lst1(o)

 def yaml_dump(o):
 	def represent_str(dumper, instance):

$ cat v7.patch | patch -p1

is_solo_tag_has_v()冒頭の lst = ['li'] が終了タグ省略パターンのデータです。

$ cat ck3.yaml
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |

      fuga
        guha
  - p: gundam
  - ul:
    - li: /
    - zaku
    - li /: gufu
    - li/: dom
  - p:
      hr: /

$ cat ck3.yaml | ./ezhtml.py | tee ck3.html
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p>gundam</p>
<ul><li>
zaku
<li>gufu
<li>dom</ul>
<p><hr></p></body></html>

$ cat ck3.yaml | ./ezhtml.py | ./ezhtml.py
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |2

      fuga
        guha
  - p: gundam
  - ul:
    - li /: zaku
    - li /: gufu
    - li /: dom
  - p:
      hr: /

$ cat ck3.yaml | ./ezhtml.py | ./ezhtml.py | diff ck3.yaml -
7c7
<   - pre: |
---
>   - pre: |2
13,14c13
<     - li: /
<     - zaku
---
>     - li /: zaku
16c15
<     - li/: dom
---
>     - li /: dom

$ cat ck3.yaml | ./ezhtml.py | ./ezhtml.py | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p>gundam</p>
<ul><li>zaku
<li>gufu
<li>dom</ul>
<p><hr></p></body></html>

$ cat ck3.yaml | ./ezhtml.py | ./ezhtml.py | ./ezhtml.py | diff ck3.html -
9,10c9
< <ul><li>
< zaku
---
> <ul><li>zaku

なんとも...徐々に、liタグまわりの形式や改行が統一されてきます。

では トップページ で確認

$ wget -q -O- http://kondoh.html.xdomain.jp/index.html | tee top.html | nkf -u
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title> kon </title>
</head>
<body>

<h1> kon page </h1>

<p><hr></p>

<p><img src="beat.jpg"></p>

<p><hr></p>

<ul>
<li><a href="bike-kon.html"> バイク </a>
<li><a href=hist.html> 更新履歴 </a>
<li><a href=me.html> 自己紹介 </a>
<li><a href=java/index.html> Javaのテスト </a>
<li><a href=color-sample.html> 色見本 </a>
<li><a href=qP2240018.jpg> ライトネス Qちゃん 2002年頃 </a>
<li><a href="murakami-sho-ji-090329/index.html"> 村上商事 2009 </a>
<li><a href="copen-090419.jpg"> Copen 2009 湯っぷる </a>
<li><a href="txtbl.html"> 簡単なテキストの表組みツール (C言語) </a>
<li><a href="txtblcnt.html"> TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール) </a>
<li><a href="midi.html"> SMFを読み込み音の波形データを作るプログラム (C言語) </a>
<li><a href="cui14/index.html"> CUI14 </a>
<li><a href="wf.html"> ワイヤーフレームのプログラム </a>
<li><a href="es16/index.html"> Pythonで作るなんちゃってCインタプリタ </a>
<li><a href="nand17/index.html"> Pythonで作るなんちゃってNANDゲートシミュレータ </a>
<li><a href="tete17/index.html"> テテリス2017夏 </a>
<li><a href="pac/index.html"> パックマンもどき2017秋 </a>
<li><a href="bktool/index.html"> バックアップツール </a>
<li><a href="http://kondoh2.html.xdomain.jp/rt/index.html"> レイトレーシング 2018春 </a>
<li><a href="py3.html"> python3 対応のメモ </a>
<li><a href="ezyaml/index.html"> 簡易なYAMLパーサ 2018夏 </a>
<li><a href="ezhtml/index.html"> 簡易なHTMLパーサ 2018秋 </a>
</ul>

<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v62/cut.mp4" controls playsinline></video></p>

<p><hr></p>
</body>
</html>

$ cat top.html | ./ezhtml.py | tee top.yaml | nkf -u
html:
- head:
  - meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
  - title: kon
- body:
  - h1: kon page
  - p:
      hr: /
  - p:
      img src="beat.jpg": /
  - p:
      hr: /
  - ul:
    - li /:
        a href="bike-kon.html": バイク
    - li /:
        a href=hist.html: 更新履歴
    - li /:
        a href=me.html: 自己紹介
    - li /:
        a href=java/index.html: Javaのテスト
    - li /:
        a href=color-sample.html: 色見本
    - li /:
        a href=qP2240018.jpg: ライトネス Qちゃん 2002年頃
    - li /:
        a href="murakami-sho-ji-090329/index.html": 村上商事 2009
    - li /:
        a href="copen-090419.jpg": Copen 2009 湯っぷる
    - li /:
        a href="txtbl.html": 簡単なテキストの表組みツール (C言語)
    - li /:
        a href="txtblcnt.html": TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)
    - li /:
        a href="midi.html": SMFを読み込み音の波形データを作るプログラム (C言語)
    - li /:
        a href="cui14/index.html": CUI14
    - li /:
        a href="wf.html": ワイヤーフレームのプログラム
    - li /:
        a href="es16/index.html": Pythonで作るなんちゃってCインタプリタ
    - li /:
        a href="nand17/index.html": Pythonで作るなんちゃってNANDゲートシミュレータ
    - li /:
        a href="tete17/index.html": テテリス2017夏
    - li /:
        a href="pac/index.html": パックマンもどき2017秋
    - li /:
        a href="bktool/index.html": バックアップツール
    - li /:
        a href="http://kondoh2.html.xdomain.jp/rt/index.html": レイトレーシング 2018春
    - li /:
        a href="py3.html": python3 対応のメモ
    - li /:
        a href="ezyaml/index.html": 簡易なYAMLパーサ 2018夏
    - li /:
        a href="ezhtml/index.html": 簡易なHTMLパーサ 2018秋
  - p:
      video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline: ''
  - p:
      video src="http://kondoh2.html.xdomain.jp/rt/out_v62/cut.mp4" controls playsinline: ''
  - p:
      hr: /

あぁ、aタグが入る場合は結局改行するのか...

- ul:
  - li /: { a href="bike-kon.html": バイク }
  - li /: { a href=hist.html: 更新履歴 }
   :

などとフロースタイルと混ぜて手打ちすれば、改行なしにもできますが...

ここまですると、かえって見にくいように思えます。

liタグは一旦ここまで。

$ cat top.html | ./ezhtml.py | ./ezhtml.py | nkf -u
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>kon</title></head>
<body><h1>kon page</h1>
<p><hr></p>
<p><img src="beat.jpg"></p>
<p><hr></p>
<ul><li><a href="bike-kon.html">バイク</a>
<li><a href=hist.html>更新履歴</a>
<li><a href=me.html>自己紹介</a>
<li><a href=java/index.html>Javaのテスト</a>
<li><a href=color-sample.html>色見本</a>
<li><a href=qP2240018.jpg>ライトネス Qちゃん 2002年頃</a>
<li><a href="murakami-sho-ji-090329/index.html">村上商事 2009</a>
<li><a href="copen-090419.jpg">Copen 2009 湯っぷる</a>
<li><a href="txtbl.html">簡単なテキストの表組みツール (C言語)</a>
<li><a href="txtblcnt.html">TXTBLCNT (簡単なテキストの表組みツールのためのさらなるツール)</a>
<li><a href="midi.html">SMFを読み込み音の波形データを作るプログラム (C言語)</a>
<li><a href="cui14/index.html">CUI14</a>
<li><a href="wf.html">ワイヤーフレームのプログラム</a>
<li><a href="es16/index.html">Pythonで作るなんちゃってCインタプリタ</a>
<li><a href="nand17/index.html">Pythonで作るなんちゃってNANDゲートシミュレータ</a>
<li><a href="tete17/index.html">テテリス2017夏</a>
<li><a href="pac/index.html">パックマンもどき2017秋</a>
<li><a href="bktool/index.html">バックアップツール</a>
<li><a href="http://kondoh2.html.xdomain.jp/rt/index.html">レイトレーシング 2018春</a>
<li><a href="py3.html">python3 対応のメモ</a>
<li><a href="ezyaml/index.html">簡易なYAMLパーサ 2018夏</a>
<li><a href="ezhtml/index.html">簡易なHTMLパーサ 2018秋</a></ul>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v44/fix_1.mp4" controls playsinline></video></p>
<p><video src="http://kondoh2.html.xdomain.jp/rt/out_v62/cut.mp4" controls playsinline></video></p>
<p><hr></p></body></html>

もう一度変換してHTMLに戻すと、良い感じ。

TODO


fileコマンドの判定の甘さ対策

python3 対応のメモ のHTMLデータをfileコマンドがHTMLと思ってくれない問題について

$ wget -q -O- http://kondoh.html.xdomain.jp/py3.html | file -
/dev/stdin: Python script, ASCII text executable, with escape sequences

HTMLじゃなくてpythonのソースと思ってるもよう。

ちょっと試してみると、逆にYAMLデータでも簡単にHTMLと思ってしまうようです。

ck4.yaml
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: <html><head></head><body></body></html>

# EOF

コマンド引数オプションで、強制ありにします。

h の指定があると入力データをHTMLとして扱い、 y の指定があると入力データをYAMLとして扱うようにします。

v8.patch
diff -urN v7/ezhtml.py v8/ezhtml.py
--- v7/ezhtml.py	2018-09-18 21:52:05.000000000 +0900
+++ v8/ezhtml.py	2018-09-18 21:52:28.000000000 +0900
@@ -192,7 +192,10 @@
 if __name__ == "__main__":
 	b = nkf.get_stdin()
 	opt = nkf.guess(b)
-	html = nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
+
+	is_html = lambda : nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
+	html = True if 'h' in sys.argv else False if 'y' in sys.argv else is_html()
+
 	u8 = nkf.cvt(b, '-u')
 	s = nkf.dec(u8)

$ cat v8.patch
diff -urN v7/ezhtml.py v8/ezhtml.py
--- v7/ezhtml.py        2018-09-18 21:52:05.000000000 +0900
+++ v8/ezhtml.py        2018-09-18 21:52:28.000000000 +0900
@@ -192,7 +192,10 @@
 if __name__ == "__main__":
        b = nkf.get_stdin()
        opt = nkf.guess(b)
-       html = nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
+
+       is_html = lambda : nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
+       html = True if 'h' in sys.argv else False if 'y' in sys.argv else is_html()
+
        u8 = nkf.cvt(b, '-u')
        s = nkf.dec(u8)


$ cat v8.patch | patch -p1

ck4.yamlから

$ cat ck4.yaml | ./ezhtml.py
- 'html: - head:     title: Title - body:   - h1: foo   - p:'
- html:
  - head: ''
  - body: ''

YAMLなのにfileコマンドがHTMLと判定してるので、意味不明の出力してますが...

y を指定すると

$ cat ck4.yaml | ./ezhtml.py y | tee ck4.html
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html>

OK。

一応

ck4.html
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html>

py3.html では逆に

$ wget -q -O- http://kondoh.html.xdomain.jp/py3.html | ./ezhtml.py
Traceback (most recent call last):
  File "./ezhtml.py", line 206, in <module>
    o = yaml.load(s)
  :
yaml.scanner.ScannerError: mapping values are not allowed here
  in "<unicode string>", line 5, column 24:
    <style> pre{ background: lightgray; } </style>
                     ^

HTMLをfileコマンドがHTML以外と判定してるので、エラー発生。

h を指定すると

$ wget -q -O- http://kondoh.html.xdomain.jp/py3.html | ./ezhtml.py h | nkf -u
html:
- head:
  - meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
  - title: python3
  - style: 'pre{ background: lightgray; }'
- body:
  - h1: python3 対応のメモ
  - p:
    - a href="http://kondoh2.html.xdomain.jp/rt/index.html": レイトレーシング 2018春
    - の
  :
      >>> print((1,2))
      (1, 2)
      >>> print ((1,2))
      (1, 2)
  - p:
      hr: /

OK。

TODO


大きいデータの標準入力への書き込み対応

SMFを読み込み音の波形データを作るプログラム (C言語)

のHTMLが巨大で顕在化した問題を対策しておきます。

$ wget -q -O- http://kondoh.html.xdomain.jp/midi.html | wc -l
29020

$ wget -q -O- http://kondoh.html.xdomain.jp/midi.html | ./ezhtml.py
Traceback (most recent call last):
  File "./ezhtml.py", line 158, in <module>
    html = nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
  File "/raid5/kondoh/hobby/ezhtml/nkf.py", line 15, in do_cmd
    proc.stdin.write(in_b)
IOError: [Errno 32] Broken pipe

nkf.py の do_cmd() でproc.communicate()を使うように変更してみました。

ついでに python3 で辞書のitems()がlistを返さないため、 うまく動いてなかったバグを、しれっと直しておきます。

v9.patch
diff -urN v8/ezhtml.py v9/ezhtml.py
--- v8/ezhtml.py	2018-09-18 21:52:28.000000000 +0900
+++ v9/ezhtml.py	2018-09-18 22:19:51.000000000 +0900
@@ -28,13 +28,16 @@
 			s += '</' + lst[0] + '>'
 	return s

+def get_tag_v(d):
+	return list( d.items() )[0]
+
 def html_dump(o):
 	if not o:
 		return ''
 	if type(o) == list:
 		return '\n'.join( map(html_dump, o) )
 	if type(o) == dict:
-		(tag, v) = list( o.items() )[0]
+		(tag, v) = get_tag_v(o)
 		return dump_tag(tag, v)
 	return cv_amp(o)

@@ -83,7 +86,7 @@
 	lst = ['li']
 	if type(e) != dict:
 		return False
-	(tag, v) = e.items()[0]
+	(tag, v) = get_tag_v(e)
 	return v == '/' and tag.split(' ')[0] in lst

 def solo_tag_has_v_idx(lst):
@@ -107,7 +110,7 @@
 		r += p
 		if lst:
 			(e, lst) = ( lst[0], lst[1:] )
-			(tag, v) = e.items()[0] # v == '/'
+			(tag, v) = get_tag_v(e) # v == '/'
 			(p, lst) = div_lst(lst)
 			r += [ { tag + ' /': strip_lst1(p) } ]
 	return r
diff -urN v8/nkf.py v9/nkf.py
--- v8/nkf.py	2018-09-17 00:15:20.000000000 +0900
+++ v9/nkf.py	2018-09-18 22:20:22.000000000 +0900
@@ -12,11 +12,7 @@
 def do_cmd(cmd, in_b):
 	cmd = enc(cmd)
 	proc = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE)
-	proc.stdin.write(in_b)
-	proc.stdin.close()
-	r = proc.stdout.read()
-	proc.wait()
-	return r # out_b
+	return proc.communicate(in_b)[0]

 def get_stdin():
 	fi = sys.stdin if six.PY2 else sys.stdin.buffer

$ cat v9.patch
diff -urN v8/ezhtml.py v9/ezhtml.py
--- v8/ezhtml.py        2018-09-18 21:52:28.000000000 +0900
+++ v9/ezhtml.py        2018-09-18 22:19:51.000000000 +0900
@@ -28,13 +28,16 @@
                        s += '</' + lst[0] + '>'
        return s

+def get_tag_v(d):
+       return list( d.items() )[0]
+
 def html_dump(o):
        if not o:
                return ''
        if type(o) == list:
                return '\n'.join( map(html_dump, o) )
        if type(o) == dict:
-               (tag, v) = list( o.items() )[0]
+               (tag, v) = get_tag_v(o)
                return dump_tag(tag, v)
        return cv_amp(o)

@@ -83,7 +86,7 @@
        lst = ['li']
        if type(e) != dict:
                return False
-       (tag, v) = e.items()[0]
+       (tag, v) = get_tag_v(e)
        return v == '/' and tag.split(' ')[0] in lst

 def solo_tag_has_v_idx(lst):
@@ -107,7 +110,7 @@
                r += p
                if lst:
                        (e, lst) = ( lst[0], lst[1:] )
-                       (tag, v) = e.items()[0] # v == '/'
+                       (tag, v) = get_tag_v(e) # v == '/'
                        (p, lst) = div_lst(lst)
                        r += [ { tag + ' /': strip_lst1(p) } ]
        return r
diff -urN v8/nkf.py v9/nkf.py
--- v8/nkf.py   2018-09-17 00:15:20.000000000 +0900
+++ v9/nkf.py   2018-09-18 22:20:22.000000000 +0900
@@ -12,11 +12,7 @@
 def do_cmd(cmd, in_b):
        cmd = enc(cmd)
        proc = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE)
-       proc.stdin.write(in_b)
-       proc.stdin.close()
-       r = proc.stdout.read()
-       proc.wait()
-       return r # out_b
+       return proc.communicate(in_b)[0]

 def get_stdin():
        fi = sys.stdin if six.PY2 else sys.stdin.buffer


$ cat v9.patch | patch -p1

では確認

$ wget -q -O- http://kondoh.html.xdomain.jp/midi.html | ./ezhtml.py | tee midi.yaml | nkf -u
html:
- head:
  - meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
  - title: midi
  - style: 'pre{ background: lightgray; }'
- body:
  - h1: SMFを読み込み音の波形データを作るプログラム (C言語)
  - pre:
    - "\n\n  | "
    - font color="#FFFFFF" style="background-color:#000000": ''
    - X
  :
  - p:
      hr: /
  - p: 工事中...
  - p:
      hr: /
  - <!--  memo  $ env RAW_CH=1 ./midi.sh jrt2-sawari.raw jrt2-test  ---  jrt2.mp3  $
    mpg123 -w b.wav jrt2.mp3 $ sox b.wav -t raw -c 1 - > jrt2-mono.raw  -rw-rw-r--  1
    kondoh     root   50379264 Jun 25 jrt2-mono.raw -rw-rw-r--  1 kondoh     root  100758572
    Jun 25 b.wav  -->

$ wc -l midi.yaml
   25140 midi.yaml

25,000行のYAMLファイルが生成できました。

HTMLに戻してみます。

$ cat midi.yaml | ./ezhtml.py | tee midi2.html | nkf -u
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>midi</title>
<style>pre{ background: lightgray; }</style></head>
<body><h1>SMFを読み込み音の波形データを作るプログラム (C言語)</h1>
<pre>

  |
<font color="#FFFFFF" style="background-color:#000000"></font>
X
  :
<p><hr></p>
<p>工事中...</p>
<p><hr></p>
&lt;!--  memo  $ env RAW_CH=1 ./midi.sh jrt2-sawari.raw jrt2-test  ---  jrt2.mp3  $ mpg123 -w b.wav jrt2.mp3 $ sox b.wav -t raw -c 1 - &gt; jrt2-mono.raw  -rw-rw-r--  1 kondoh     root   50379264 Jun 25 jrt2-mono.raw -rw-rw-r--  1 kondoh     root  100758572 Jun 25 b.wav  --&gt;</body></html>

$ wc -l midi2.html
   24633 midi2.html

24,000行のHTMLファイル生成。

midi2.html 置いてみました。

冒頭の鍵盤の表示が?

<pre>

  | <font color="#FFFFFF" style="background-color:#000000"> </font>X<font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"><u>X</u></font> <font color="#FFFFFF" style="background-color:#000000"> </font>X<font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> |

から

<pre>

  |
<font color="#FFFFFF" style="background-color:#000000"></font>
X
<font color="#FFFFFF" style="background-color:#000000"></font>
 |
<font color="#FFFFFF" style="background-color:#000000"><u>X</u></font>

<font color="#FFFFFF" style="background-color:#000000"></font>
X
<font color="#FFFFFF" style="background-color:#000000"></font>
 |
<font color="#FFFFFF" style="background-color:#000000"></font>

<font color="#FFFFFF" style="background-color:#000000"></font>
 |
<font color="#FFFFFF" style="background-color:#000000"></font>

<font color="#FFFFFF" style="background-color:#000000"></font>

<font color="#FFFFFF" style="background-color:#000000"></font>
 |

に。あー、preタグの中でfontタグが開いて閉じて、改行入ったか。

他はちゃんと表示されてるか...? 巨大過ぎますね。

最後のHTMLのコメントだった箇所が見えてる?

$ tail midi.yaml
        :
  - p:
      hr: /
  - p: 工事中...
  - p:
      hr: /
  - <!--  memo  $ env RAW_CH=1 ./midi.sh jrt2-sawari.raw jrt2-test  ---  jrt2.mp3  $
    mpg123 -w b.wav jrt2.mp3 $ sox b.wav -t raw -c 1 - > jrt2-mono.raw  -rw-rw-r--  1
    kondoh     root   50379264 Jun 25 jrt2-mono.raw -rw-rw-r--  1 kondoh     root  100758572
    Jun 25 b.wav  -->

なんかhtml_load()で文字列としてスタックに積まれてる?

いづれにせよ、HTMLのコメントはノーマークでした。

TODO


preタグの中のタグの改行対応

SMFを読み込み音の波形データを作るプログラム (C言語) をYAMLに変換して、HTMLに変換しなおしたものを、 midi2.html として置いてみたのですが、冒頭の鍵盤の表示が...?

preタグの中にさらにタグがあると、改行が入ってしまってる問題の対策です。

v10.patch
diff -urN v9/ezhtml.py v10/ezhtml.py
--- v9/ezhtml.py	2018-09-18 22:19:51.000000000 +0900
+++ v10/ezhtml.py	2018-09-20 03:53:08.000000000 +0900
@@ -15,7 +15,7 @@
 		s = s.replace(f, t)
 	return s

-def dump_tag(tag, v):
+def dump_tag(tag, v, pre):
 	lst = bak = tag.split(' ')
 	if lst[-1] == '/':
 		lst = lst[:-1]
@@ -23,7 +23,7 @@
 		lst = [ lst[0][:-1] ] + lst[1:]
 	s = '<' + ' '.join(lst) + '>'
 	if v != '/':
-		s += html_dump(v)
+		s += html_dump( v, lst[0].lower() == 'pre' )
 		if lst == bak:
 			s += '</' + lst[0] + '>'
 	return s
@@ -31,14 +31,15 @@
 def get_tag_v(d):
 	return list( d.items() )[0]

-def html_dump(o):
+def html_dump(o, pre=False):
 	if not o:
 		return ''
 	if type(o) == list:
-		return '\n'.join( map(html_dump, o) )
+		delim = '' if pre else '\n'
+		return delim.join( map( lambda e: html_dump(e, pre), o ) )
 	if type(o) == dict:
 		(tag, v) = get_tag_v(o)
-		return dump_tag(tag, v)
+		return dump_tag(tag, v, pre)
 	return cv_amp(o)

 def get_tag(s):

$ cat v10.patch
diff -urN v9/ezhtml.py v10/ezhtml.py
--- v9/ezhtml.py        2018-09-18 22:19:51.000000000 +0900
+++ v10/ezhtml.py       2018-09-20 03:53:08.000000000 +0900
@@ -15,7 +15,7 @@
                s = s.replace(f, t)
        return s

-def dump_tag(tag, v):
+def dump_tag(tag, v, pre):
        lst = bak = tag.split(' ')
        if lst[-1] == '/':
                lst = lst[:-1]
@@ -23,7 +23,7 @@
                lst = [ lst[0][:-1] ] + lst[1:]
        s = '<' + ' '.join(lst) + '>'
        if v != '/':
-               s += html_dump(v)
+               s += html_dump( v, lst[0].lower() == 'pre' )
                if lst == bak:
                        s += '</' + lst[0] + '>'
        return s
@@ -31,14 +31,15 @@
 def get_tag_v(d):
        return list( d.items() )[0]

-def html_dump(o):
+def html_dump(o, pre=False):
        if not o:
                return ''
        if type(o) == list:
-               return '\n'.join( map(html_dump, o) )
+               delim = '' if pre else '\n'
+               return delim.join( map( lambda e: html_dump(e, pre), o ) )
        if type(o) == dict:
                (tag, v) = get_tag_v(o)
-               return dump_tag(tag, v)
+               return dump_tag(tag, v, pre)
        return cv_amp(o)

 def get_tag(s):


$ cat v10.patch | patch -p1

早速、巨大なHTML SMFを読み込み音の波形データを作るプログラム (C言語) で確認

$ wget -q -O- http://kondoh.html.xdomain.jp/midi.html | ./ezhtml.py | ./ezhtml.py | tee midi3.html | nkf -
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>midi</title>
<style>pre{ background: lightgray; }</style></head>
<body><h1>SMFを読み込み音の波形データを作るプログラム (C言語)</h1>
<pre>

  | <font color="#FFFFFF" style="background-color:#000000"></font>X<font color="#FFFFFF" style="background-color:#000000"></font> | <font color="#FFFFFF" style="background-color:#000000"><u>X</u></font> <font color="#FFFFFF" style="background-color:#000000"></font>X<font color="#FFFFFF" style="background-color:#000000"></font> | <font color="#FFFFFF" style="background-color:#000000"></font> <font color="#FFFFFF" style="background-color:#000000"></font> | <font color="#FFFFFF" style="background-color:#000000"></font> <font color="#FFFFFF" style="background-color:#000000"></font> <font color="#FFFFFF" style="background-color:#000000"></font> |
  <u>| | | | | | | | | | | | | | |</u>

</pre>
<p><hr></p>
  :

改行は消えてる様子。

midi3.html 置いてみました。

それでも鍵盤の表示が...変です。

| <font color="#FFFFFF" style="background-color:#000000"> </font>X

に対して

| <font color="#FFFFFF" style="background-color:#000000"></font>

fontタグのスペース1つだけの文字列が消えてました。

preタグ中の他のタグの中身は、strip()したらダメか。

TODO


タグ中のタグの中身はstirp()かけない対応

midi3.html で、それでも鍵盤の表示がおかしい問題。

preタグの中でスペースがstrip()で消えてるようです。

小さいデータで再現確認

$ echo '<html><body><pre>foo<u> </u>bar</pre></body></html>' | file -
/dev/stdin: HTML document text

$ echo '<html><body><pre>foo<u> </u>bar</pre></body></html>' | ./ezhtml.py | ./ezhtml.py
<html><body><pre>foo<u></u>bar</pre></body></html>

確かに<u>と</u>の間のスペースが消えてます。

YAMLに変換した段階は?

$ echo '<html><body><pre>foo<u> </u>bar</pre></body></html>' | ./ezhtml.py
html:
  body:
    pre:
    - foo
    - u: ''
    - bar

「- u: ''」になってます。

という事はdump側じゃなくてload側の問題。

def strip_lst(lst, pre):
        def f(e):
                if type(e) == dict:
                        return e
                if pre:
                        while ' \n' in e:
                                e = e.replace(' \n', '\n')
                        return untabify(e)
                return e.replace('\n', ' ').strip()

        return list( filter( lambda e: e != '', map(f, lst) ) )

ここでpreタグの場合はstrip()通らないはず?

ちょっとdebug out追加してみます

def strip_lst(lst, pre):
        def f(e):
                if type(e) == dict:
                        return e
                if pre:
                        while ' \n' in e:
                                e = e.replace(' \n', '\n')
                        return untabify(e)
                return e.replace('\n', ' ').strip()

        print('lst={} pre={}'.format(lst, pre)) # !!! debug
        return list( filter( lambda e: e != '', map(f, lst) ) )
$ echo '<html><body><pre>foo<u> </u>bar</pre></body></html>' | ./ezhtml.py
lst=[' '] pre=False
lst=['foo', {'u': ''}, 'bar'] pre=True
lst=[{'pre': ['foo', {'u': ''}, 'bar']}] pre=False
lst=[{'body': {'pre': ['foo', {'u': ''}, 'bar']}}] pre=False
lst=[{'html': {'body': {'pre': ['foo', {'u': ''}, 'bar']}}}] pre=False
html:
  body:
    pre:
    - foo
    - u: ''
    - bar

ふーむ。uタグを処理する段階ではpre == False。

preの終了タグを見つけた時に、preをTrueにしてスタックを遡りますが、 そのときは既にuタグは処理済...

なのでpreの開始タグでpreをTrueにせねばなりません。

v11.patch
diff -urN v10/ezhtml.py v11/ezhtml.py
--- v10/ezhtml.py	2018-09-20 03:53:08.000000000 +0900
+++ v11/ezhtml.py	2018-09-20 21:28:26.000000000 +0900
@@ -150,9 +150,9 @@
 	lst = solo_tags_modify(lst)
 	return lst

-def close_tag(lst):
+def close_tag(lst, pre):
 	(tag, lst) = ( lst[0], lst[1:] )
-	lst = close_solo_tag( lst, tag[0].lower() == 'pre' )
+	lst = close_solo_tag(lst, pre)

 	v = lst
 	if len(lst) == 1:
@@ -163,6 +163,12 @@

 def html_load(s):
 	stk = []
+	pre_cnt = 0
+
+	def add_cnt(tag):
+		pre = ( tag[1] if tag[0] == '/' else tag[0] ).lower() == 'pre'
+		return ( -1 if tag[0] == '/' else 1 ) if pre else 0
+
 	while True:
 		(p, tag, s) = get_tag(s)
 		if not tag:
@@ -171,14 +177,16 @@
 			stk.append( cv_amp(p, 'dec') )
 		if tag[0] != '/':
 			stk.append(tag)
+			pre_cnt += add_cnt(tag)
 			continue
 		i = start_idx( stk, tag[1] )
 		if i >= 0:
-			stk = stk[:i] + [ close_tag( stk[i:] ) ]
+			stk = stk[:i] + [ close_tag( stk[i:], pre_cnt > 0 ) ]
+			pre_cnt += add_cnt(tag)
 		else:
 			stk.append( solo_tag(tag) )

-	o = close_solo_tag(stk)
+	o = close_solo_tag( stk, pre_cnt > 0 )
 	return strip_lst1(o)

 def yaml_dump(o):

debug out行は削除して元に戻して

$ cat v11.patch | patch -p1

もっかいdebug out行をつけ直して

def strip_lst(lst, pre):
        def f(e):
                if type(e) == dict:
                        return e
                if pre:
                        while ' \n' in e:
                                e = e.replace(' \n', '\n')
                        return untabify(e)
                return e.replace('\n', ' ').strip()

        print('lst={} pre={}'.format(lst, pre)) # !!! debug
        return list( filter( lambda e: e != '', map(f, lst) ) )
$ echo '<html><body><pre>foo<u> </u>bar</pre></body></html>' | ./ezhtml.py
lst=[' '] pre=True
lst=['foo', {'u': ' '}, 'bar'] pre=True
lst=[{'pre': ['foo', {'u': ' '}, 'bar']}] pre=False
lst=[{'body': {'pre': ['foo', {'u': ' '}, 'bar']}}] pre=False
lst=[{'html': {'body': {'pre': ['foo', {'u': ' '}, 'bar']}}}] pre=False
html:
  body:
    pre:
    - foo
    - u: ' '
    - bar

OK。

またdebut out削除して...

$ cat midi.html | ./ezhtml.py | tee midi4.yaml | nkf -u
html:
- head:
  - meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp": /
  - title: midi
  - style: 'pre{ background: lightgray; }'
- body:
  - h1: SMFを読み込み音の波形データを作るプログラム (C言語)
  - pre:
    - "\n\n  | "
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - X
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - ' | '
    - font color="#FFFFFF" style="background-color:#000000":
        u: X
    - ' '
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - X
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - ' | '
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - ' '
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - ' | '
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - ' '
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - ' '
    - font color="#FFFFFF" style="background-color:#000000": ' '
    - " |\n  "
    - u: '| | | | | | | | | | | | | | | '
    - |2+
  :

$ cat midi4.yaml | ./ezhtml.py | tee midi4.html | nkf -u
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-2022-jp">
<title>midi</title>
<style>pre{ background: lightgray; }</style></head>
<body><h1>SMFを読み込み音の波形データを作るプログラム (C言語)</h1>
<pre>

  | <font color="#FFFFFF" style="background-color:#000000"> </font>X<font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"><u>X</u></font> <font color="#FFFFFF" style="background-color:#000000"> </font>X<font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> |
  <u>| | | | | | | | | | | | | | | </u>

</pre>
  :

OK。

$ diff midi3.html midi4.html | nkf -u | less
7,8c7,8
<   | <font color="#FFFFFF" style="background-color:#000000"></font>X<font color="#FFFFFF" style="background-color:#000000"></font> | <font color="#FFFFFF" style="background-color:#000000"><u>X</u></font> <font color="#FFFFFF" style="background-color:#000000"></font>X<font color="#FFFFFF" style="background-color:#000000"></font> | <font color="#FFFFFF" style="background-color:#000000"></font> <font color="#FFFFFF" style="background-color:#000000"></font> | <font color="#FFFFFF" style="background-color:#000000"></font> <font color="#FFFFFF" style="background-color:#000000"></font> <font color="#FFFFFF" style="background-color:#000000"></font> |
<   <u>| | | | | | | | | | | | | | |</u>
---
>   | <font color="#FFFFFF" style="background-color:#000000"> </font>X<font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"><u>X</u></font> <font color="#FFFFFF" style="background-color:#000000"> </font>X<font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> | <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> <font color="#FFFFFF" style="background-color:#000000"> </font> |
>   <u>| | | | | | | | | | | | | | | </u>
2746c2746,2748
< <p><a href="midi_mp3_early/prog8_xaa.mp3">prog8_xaa.mp3</a>
---
> <p>
>
> <a href="midi_mp3_early/prog8_xaa.mp3"> prog8_xaa.mp3 </a>
2748,2749c2750,2755
< <a href="midi_mp3_early/prog8_xab.mp3">prog8_xab.mp3</a>
< <br></p>
---
>
>
> <a href="midi_mp3_early/prog8_xab.mp3"> prog8_xab.mp3 </a>
> <br>
>
> </p>
6260c6266
< |  midi ch : <u>0</u>|                                           |
---
> |  midi ch : <u>0  </u>|                                           |

  :

15550c15556
< <a href="midi_mp3/ryd-7.mp3">ryd-7.mp3</a>
---
> <a href="midi_mp3/ryd-7.mp3"> ryd-7.mp3 </a>


$ diff midi3.html midi4.html | wc -l
828

結構違いが出てますが...

該当箇所を元のmidi.htmlであたると、確かにpreタグの中。

midi4.html 置いてみました。

鍵盤はOK。

他、簡単なデータでデグレないか見ておきます。

$ cat ck1.yaml
- html:
  - head:
      title: Title
  - body:
    - h1: foo
    - p: bar hoge
    - pre: |

        fuga
          guha
    - p:
        hr: /

$ cat ck1.yaml | ./ezhtml.py | tee tmp1.html
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p><hr></p></body></html>

$ cat tmp1.html | ./ezhtml.py | tee tmp1.yaml
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |2

      fuga
        guha
  - p:
      hr: /

$ cat tmp1.html | ./ezhtml.py | diff tmp1.yaml -
$

$ cat tmp1.yaml | ./ezhtml.py | diff tmp1.html -
$

$ cat jis.yaml | nkf -u
- html:
  - head:
      title: タイトル
  - body:
    - h1: ふー
    - p: ばー ほげ
    - pre: |2

        ふが
          ぐは
    - p:
        hr: /

$ cat jis.yaml | ./ezhtml.py | tee tmp_jis.html | nkf -u
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat tmp_jis.html | ./ezhtml.py | tee tmp_jis.yaml | nkf -u
html:
- head:
    title: タイトル
- body:
  - h1: ふー
  - p: ばー ほげ
  - pre: |2

      ふが
        ぐは
  - p:
      hr: /

$ cat tmp_jis.yaml | ./ezhtml.py | diff tmp_jis.html -
$

$ cat tmp_jis.html | ./ezhtml.py | diff tmp_jis.yaml -
$

$ cat utf8.yaml
- html:
  - head:
      title: タイトル
  - body:
    - h1: ふー
    - p: ばー ほげ
    - pre: |

        ふが
          ぐは
    - p:
        hr: /

$ cat utf8.yaml | ./ezhtml.py | tee tmp_utf8.html
<html><head><title>タイトル</title></head>
<body><h1>ふー</h1>
<p>ばー ほげ</p>
<pre>
ふが
  ぐは
</pre>
<p><hr></p></body></html>

$ cat tmp_utf8.html | ./ezhtml.py | tee tmp_utf8.yaml
html:
- head:
    title: タイトル
- body:
  - h1: ふー
  - p: ばー ほげ
  - pre: |2

      ふが
        ぐは
  - p:
      hr: /

$ cat tmp_utf8.yaml | ./ezhtml.py | diff tmp_utf8.html -
$

$ cat tmp_utf8.html | ./ezhtml.py | diff tmp_utf8.yaml -
$

$ cat ck3.yaml
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |

      fuga
        guha
  - p: gundam
  - ul:
    - li: /
    - zaku
    - li /: gufu
    - li/: dom
  - p:
      hr: /

$ cat ck3.yaml | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p>gundam</p>
<ul><li>
zaku
<li>gufu
<li>dom</ul>
<p><hr></p></body></html>

$ cat ck3.yaml | ./ezhtml.py | ./ezhtml.py
html:
- head:
    title: Title
- body:
  - h1: foo
  - p: bar hoge
  - pre: |2

      fuga
        guha
  - p: gundam
  - ul:
    - li /: zaku
    - li /: gufu
    - li /: dom
  - p:
      hr: /

$ cat ck3.yaml | ./ezhtml.py | ./ezhtml.py | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>bar hoge</p>
<pre>
fuga
  guha
</pre>
<p>gundam</p>
<ul><li>zaku
<li>gufu
<li>dom</ul>
<p><hr></p></body></html>

$ cat ck4.yaml | ./ezhtml.py
- 'html: - head:     title: Title - body:   - h1: foo   - p:'
- html:
  - head: ''
  - body: ''

$ cat ck4.yaml | ./ezhtml.py y
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<p>&lt;html&gt;&lt;head&gt;&lt;/head&gt;&lt;body&gt;&lt;/body&gt;&lt;/html&gt;</p></body></html>

$ cat ck4.yaml | ./ezhtml.py y | diff ck4.html -
$

OK。

TODO


コメント対応

HTMLが進化してきたバージョンと、 コメントの規定の変遷の歴史は「微妙で複雑」です。

ここでは「ごちゃごちゃはヌキ」。

簡単なHTMLで現状の動作を確認

comment.html
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>foo</h1>

<!-- comment 1 -->

<p>bar</p>

<!--comment2-->

<!--
<p>hoge</p>
  fuga
-->

<pre>
guha
  geha
</pre>

<!-- <comment3> -->

</body>
</html>

だめです。

コメントの中のつもりの「<p>hoge</p>」が生きてるし、 そもそも'<!-- ...' が文字列として解釈されてます。

'<!-- xxx -->'はタグと認識しないのだろうか?

def get_tag(s):
        (p, tag) = ('', [])

        while '<' in s:
                i = s.index('<')
                (t, s) = ( s[:i], s[i+1:] )
                p += t
                tag.append('<')
                n = s[:1]
                if n == '/':
                        tag.append('/')
                        s = s[1:]
                        n = s[:1]
                if n.isalpha():
                        if '>' not in s:
                                err( "not found '>'", 'tag={}'.format(tag) )
                        i = s.index('>')
                        tag = tag[1:] + s[:i].split(' ')
                        s = s[i+1:]
                        break
                p += ''.join(tag)
                tag = []

        if not tag:
                (p, s) = (p+s, '')

        return (p, tag, s)

get_tag() の n.isalpha() の箇所。ここで「はねて」いました。

'<' に続く文字列がアルファベットで始まってなければ、 タグと認識しません。

しかしながらコメントを、 通常の'<'で始まり'>'で終るタグの一種として、簡単に扱ってしまうと

<!--
<p>hoge</p>
-->

の場合に、'<p>'の'>'で閉じてしまいます。

終りはちゃんと '-->' で見てやらねばなりません。

あとコメントは、改行も何もかも保持したままでYAMLに変換。 YAMLからHTMLに戻すときに、 正しく元のコメントとして復帰させねばなりません。

オブジェクトの段階ではpreタグのような感じで、 タグ名にあたる辞書のキーはとりあえず '!--' で。

v12.patch
diff -urN v11/ezhtml.py v12/ezhtml.py
--- v11/ezhtml.py	2018-09-20 21:28:26.000000000 +0900
+++ v12/ezhtml.py	2018-09-20 21:28:51.000000000 +0900
@@ -16,6 +16,8 @@
 	return s

 def dump_tag(tag, v, pre):
+	if tag == '!--':
+		return '<!--' + v + '-->'
 	lst = bak = tag.split(' ')
 	if lst[-1] == '/':
 		lst = lst[:-1]
@@ -49,6 +51,13 @@
 		i = s.index('<')
 		(t, s) = ( s[:i], s[i+1:] )
 		p += t
+		if s[:3] == '!--' and '-->' in s[3:]:
+			tag.append('!--')
+			s = s[3:]
+			i = s.index('-->')
+			tag.append( s[:i] )
+			s = s[i+3:]
+			break
 		tag.append('<')
 		n = s[:1]
 		if n == '/':
@@ -79,6 +88,8 @@

 def solo_tag(e):
 	if type(e) == list:
+		if e[0] == '!--':
+			return { '!--': e[1] }
 		(h, e) = ( '/', e[1:] ) if e[0] == '/' else ('', e)
 		return { h + ' '.join(e): '/' }
 	return e

$ cat v12.patch
diff -urN v11/ezhtml.py v12/ezhtml.py
--- v11/ezhtml.py       2018-09-20 21:28:26.000000000 +0900
+++ v12/ezhtml.py       2018-09-20 21:28:51.000000000 +0900
@@ -16,6 +16,8 @@
        return s

 def dump_tag(tag, v, pre):
+       if tag == '!--':
+               return '<!--' + v + '-->'
        lst = bak = tag.split(' ')
        if lst[-1] == '/':
                lst = lst[:-1]
@@ -49,6 +51,13 @@
                i = s.index('<')
                (t, s) = ( s[:i], s[i+1:] )
                p += t
+               if s[:3] == '!--' and '-->' in s[3:]:
+                       tag.append('!--')
+                       s = s[3:]
+                       i = s.index('-->')
+                       tag.append( s[:i] )
+                       s = s[i+3:]
+                       break
                tag.append('<')
                n = s[:1]
                if n == '/':
@@ -79,6 +88,8 @@

 def solo_tag(e):
        if type(e) == list:
+               if e[0] == '!--':
+                       return { '!--': e[1] }
                (h, e) = ( '/', e[1:] ) if e[0] == '/' else ('', e)
                return { h + ' '.join(e): '/' }
        return e


$ cat v12.patch | patch -p1

簡単なデータから

$ cat comment.html
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>foo</h1>

<!-- comment 1 -->

<p>bar</p>

<!--comment2-->

<!--
<p>hoge</p>
  fuga
-->

<pre>
guha
  geha
</pre>

<!-- <comment3> -->

</body>
</html>

$ cat comment.html | ./ezhtml.py
html:
- head:
    title: Title
- body:
  - h1: foo
  - '!--': ' comment 1 '
  - p: bar
  - '!--': comment2
  - '!--': |2

      <p>hoge</p>
        fuga
  - pre: |2

      guha
        geha
  - '!--': ' <comment3> '

わりと狙い通りなYAML。

$ cat comment.html | ./ezhtml.py | ./ezhtml.py
<html><head><title>Title</title></head>
<body><h1>foo</h1>
<!-- comment 1 -->
<p>bar</p>
<!--comment2-->
<!--
<p>hoge</p>
  fuga
-->
<pre>
guha
  geha
</pre>
<!-- <comment3> --></body></html>

コメント中の改行も再現できてるようですね。

では、大きなデータで

$ cat midi.html | grep '!--' | head
<!-- 04192200 -->
<!-- 04202200 -->
<!-- 04220000 -->
<!-- 04220000 -->
<!-- 04220100 -->
<!-- 04232300 -->
<!-- 04232330 -->
<!-- 04240000 -->
<!-- 04240100 -->
<!-- 04242300 -->

$ cat midi.html | grep '!--' | tail
<!-- 150909000000 -->
<!-- 150910000000 -->
<!-- 150911000000 -->
o<!-- 150925000000 -->
<!-- 150926000000 -->
<!-- 150927000000 -->
<!-- 150930000000 -->
<!-- 151001000000 -->
<!-- 151015000000 -->
<!--

$ cat midi.html | grep '!--' | wc -l
92

コメントたくさんありますが、末尾の以外は単純っぽいです。

$ cat midi.html | ./ezhtml.py | tee midi.yaml | nkf -u
  :
  - p:
    - cui_midi.c の差分です
    - a href="midi_src/cui_midi7.patch": cui_midi7.patch
    - '!--': ' 04192200 '
  :
  - p:
      hr: /
  - p: 工事中...
  - p:
      hr: /
  - '!--': |2+


      memo

      $ env RAW_CH=1 ./midi.sh jrt2-sawari.raw jrt2-test

      ---

      jrt2.mp3

      $ mpg123 -w b.wav jrt2.mp3
      $ sox b.wav -t raw -c 1 - > jrt2-mono.raw

      -rw-rw-r--  1 kondoh     root   50379264 Jun 25 jrt2-mono.raw
      -rw-rw-r--  1 kondoh     root  100758572 Jun 25 b.wav

...

HTMLに戻してみて

$ cat midi.yaml | ./ezhtml.py > midi5.htm

$ tail -20 midi5.html | nkf -u
<p><hr></p>
<p>工事中...</p>
<p><hr></p>
<!--

memo

$ env RAW_CH=1 ./midi.sh jrt2-sawari.raw jrt2-test

---

jrt2.mp3

$ mpg123 -w b.wav jrt2.mp3
$ sox b.wav -t raw -c 1 - > jrt2-mono.raw

-rw-rw-r--  1 kondoh     root   50379264 Jun 25 jrt2-mono.raw
-rw-rw-r--  1 kondoh     root  100758572 Jun 25 b.wav

--></body></html>

オリジナルのmidi.htmlは

$ tail -20 midi.html | nkf -u
<!--

memo

$ env RAW_CH=1 ./midi.sh jrt2-sawari.raw jrt2-test

---

jrt2.mp3

$ mpg123 -w b.wav jrt2.mp3
$ sox b.wav -t raw -c 1 - > jrt2-mono.raw

-rw-rw-r--  1 kondoh     root   50379264 Jun 25 jrt2-mono.raw
-rw-rw-r--  1 kondoh     root  100758572 Jun 25 b.wav

-->

</body>
</html>

コメント中の改行も問題なさそう。

midi5.html 置いてみました。

OK?

TODO


kon_ut対応

pythonのユーティリティ・プログラム 2020冬 でうかつにnkf.pyを更新してしまったために、ezhtml.pyでエラーが出る場合がありました。

$ cat ezmhtml.py
  :
	is_html = lambda : nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
  :

このnkf.do_cmd()がもう消えてしまってました。

ezhtml.pyもkon_utを使うように変更しておきます。

v13.patch
diff -ur v12/ezhtml.py v13/ezhtml.py
--- v12/ezhtml.py	2018-09-20 21:28:51.000000000 +0900
+++ v13/ezhtml.py	2020-02-01 01:15:52.000000000 +0900
@@ -4,6 +4,7 @@
 import yaml
 import six
 import nkf
+import cmd_ut

 def cv_amp(s, d='enc'):
 	lst = [ ('&','&amp;'), ('<','&lt;'), ('>','&gt;') ]
@@ -216,7 +217,7 @@
 	b = nkf.get_stdin()
 	opt = nkf.guess(b)

-	is_html = lambda : nkf.dec( nkf.do_cmd('file - | grep -i html', b) ).strip()
+	is_html = lambda : nkf.dec( cmd_ut.call_comm('file - | grep -i html', b) ).strip()
 	html = True if 'h' in sys.argv else False if 'y' in sys.argv else is_html()

 	u8 = nkf.cvt(b, '-u')

$ cat v13.patch | patch -p1


bare対応

前回の更新から1年以上経ってますが、久々に更新してみます。

簡易なおれおれマークダウン 2019秋 の方でも更新してて、それとのセットになります。

タグに独自のプロパティ'bare'を追加します。

YAML形式的にはタグのプロパティは、タグ名の部分に押し込められています。

YAML形式で、bare="True" のプロパティがついてると、 &", "<", ">" の3つの文字について、"&amp;", "&lt;", "&gt; のエンコード処理をせずに素通ししてHTMLを生成します。

v14.patch
diff -ur v13/ezhtml.py v14/ezhtml.py
--- v13/ezhtml.py	2020-02-01 01:15:52.000000000 +0900
+++ v14/ezhtml.py	2021-02-23 16:59:50.000000000 +0900
@@ -24,9 +24,17 @@
 		lst = lst[:-1]
 	if lst[0][-1] == '/':
 		lst = [ lst[0][:-1] ] + lst[1:]
+
+	t = 'bare="True"'
+	bare = t in lst
+	if bare:
+		lst.remove(t)
+		if t in bak:
+			bak.remove(t)
+
 	s = '<' + ' '.join(lst) + '>'
 	if v != '/':
-		s += html_dump( v, lst[0].lower() == 'pre' )
+		s += html_dump( v, lst[0].lower() == 'pre', bare=bare )
 		if lst == bak:
 			s += '</' + lst[0] + '>'
 	return s
@@ -34,7 +42,7 @@
 def get_tag_v(d):
 	return list( d.items() )[0]

-def html_dump(o, pre=False):
+def html_dump(o, pre=False, bare=False):
 	if not o:
 		return ''
 	if type(o) == list:
@@ -43,7 +51,7 @@
 	if type(o) == dict:
 		(tag, v) = get_tag_v(o)
 		return dump_tag(tag, v, pre)
-	return cv_amp(o)
+	return o if bare else cv_amp(o)

 def get_tag(s):
 	(p, tag) = ('', [])

$ cat v14.patch | patch -p1

$ ./ezhtml.py <<EOF
> - pre: |
>     abc
>     xyz <u> foo </u>
>     bar
> - pre bare="True": |
>     abc
>     xyz <u> foo </u>
>     bar
> EOF
<pre>abc
xyz &lt;u&gt; foo &lt;/u&gt;
bar
</pre>
<pre>abc
xyz <u> foo </u>
bar
</pre>
$