hitomalu_formatter 0.1.2 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/Gemfile.lock +1 -1
- data/lib/hitomalu_formatter/formatter.rb +46 -11
- data/lib/hitomalu_formatter/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92b65e324f9f9163600a9af6e03d864592d0a7780f6d040201d203756b746c25
|
4
|
+
data.tar.gz: 6071e129eab94156b61d2715c7e7d7bc296cebb28ca32988ff97af415c5af861
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38a235ffe10dddd9d1535f4de5db56fe69f5f21a656566b917abd943acf193728921e30975418b04f2fb43092cf70e2493ccd1072bd65f271c479d8e447bc8a2
|
7
|
+
data.tar.gz: 121844e97893f54f05d3ffb4f1f5d6a254a6c72fd49a444667ca3f8d8d7b506b95e7b790abe74e23a4507aa9846631a3520b969cefa15dc2f69e00a4677fe56c
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -7,7 +7,14 @@ module Hitomalu
|
|
7
7
|
# cf. https://developer.mozilla.org/ja/docs/Web/HTML/Inline_elements
|
8
8
|
# rp と rt は上に記載がないが、改行させたくないので追加
|
9
9
|
# node.name が 'comment' であるコメントノードもインライン扱い
|
10
|
-
INLINE_TAGS = [ 'a', 'abbr', 'acronym', 'audio', 'b', 'bdi', 'bdo', 'big', 'br', 'button', 'canvas', 'cite', 'code', 'comment', 'data', 'datalist', 'del', 'dfn', 'em', 'embed', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'mark', 'meter', 'noscript', 'object', 'output', 'picture', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'select', 'slot', 'small', 'span', 'strong', 'sub', 'sup', 'svg', 'template', 'textarea', 'time', 'u', 'tt', 'var', 'video', 'wbr' ]
|
10
|
+
INLINE_TAGS = [ 'a', 'abbr', 'acronym', 'audio', 'b', 'bdi', 'bdo', 'big', 'br', 'button', 'canvas', 'cite', 'code', 'comment', 'data', 'datalist', 'del', 'dfn', 'em', 'embed', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'mark', 'meter', 'nobr', 'noscript', 'object', 'output', 'picture', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'select', 'slot', 'small', 'span', 'strong', 'sub', 'sup', 'svg', 'template', 'text', 'textarea', 'time', 'u', 'tt', 'var', 'video', 'wbr' ]
|
11
|
+
INLINE_TAGS_REGEXP = INLINE_TAGS.join('|')
|
12
|
+
|
13
|
+
ADD_BREAK_LINE_TAGS = [ 'br', 'hr', 'col' ]
|
14
|
+
ADD_BREAK_LINE_TAGS_REGEXP = ADD_BREAK_LINE_TAGS.join('|')
|
15
|
+
|
16
|
+
# フォーマットで改行が増えないタグ (改行が増えるタグで改行増殖を抑えるために使う)
|
17
|
+
BREAK_LINE_NOT_INCREASE_TAGS = INLINE_TAGS - ADD_BREAK_LINE_TAGS
|
11
18
|
|
12
19
|
def self.format(html)
|
13
20
|
# 改行コード \n を \r\n に統一しておく
|
@@ -22,17 +29,29 @@ module Hitomalu
|
|
22
29
|
body = doc.at_css('body')
|
23
30
|
|
24
31
|
body.traverse { |node|
|
32
|
+
# テキストノードが空白文字以外を含み、親が非インライン要素(=ブロックノード)でもpreでもないならば中身の先頭と最後のスペースを消す
|
33
|
+
# (親のブロック要素に接しているところ = 兄弟がいない方向のみ)
|
34
|
+
if node.instance_of?(Nokogiri::XML::Text) && /\S/.match(node.content) && !(INLINE_TAGS + CONTENT_NO_MODIFY_TAGS).include?(node.parent.name)
|
35
|
+
if node.previous_sibling.nil?
|
36
|
+
node.content = node.content.gsub(/(\A\s+)/, "")
|
37
|
+
end
|
38
|
+
if node.next_sibling.nil?
|
39
|
+
node.content = node.content.gsub(/(\s+\Z)/, "")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
25
44
|
# 中身がないと、li などの閉じタグ省略可能なタグについてNokogiriが閉じタグ省略を行い、整形をかけるたびに閉じタグがついたりなくなったりするので、
|
26
45
|
# 中身がないかスペースだけの場合、仮文字列にして最後に空文字列に置換する
|
27
|
-
# ただし、 <img src="1.jpg"> <img src="2.jpg"> のようなインライン要素の間のスペースと改行は保持する必要があるので保持する。
|
28
46
|
# <li></li> の中に |mykaramojiretsu| を入れるために + ではなく * が必要
|
29
|
-
if /\A[ ]*\Z/.match?(node.content)
|
30
|
-
node.content = "|mykaramojiretsu|"
|
47
|
+
if /\A[ ]*\Z/.match?(node.content)
|
48
|
+
node.content = node.content + "|mykaramojiretsu|"
|
31
49
|
end
|
32
50
|
|
33
51
|
# インライン要素は、ブロック内先頭やテキストノードやインライン要素の次では改行しない
|
34
52
|
# (前がブロック要素の終わりやコメントノードだと改行する)
|
35
|
-
|
53
|
+
# (前が最後に改行を足すタグの場合、|nobreakline| を足すとスペースが増えて、フォーマットをかける度に結果が変わるので、|nobreakline| を足しません)
|
54
|
+
if INLINE_TAGS.include?(node.name) && (node.previous_sibling.nil? || (INLINE_TAGS.include?(node.previous_sibling.name) && !ADD_BREAK_LINE_TAGS.include?(node.previous_sibling.name)))
|
36
55
|
node.add_previous_sibling("|nobreakline|")
|
37
56
|
end
|
38
57
|
|
@@ -54,9 +73,24 @@ module Hitomalu
|
|
54
73
|
node.next_sibling.content = "|mykaigyo|"
|
55
74
|
end
|
56
75
|
|
76
|
+
# この下の処理で先頭改行をスペースに置換している & ブロック要素閉じタグの後には改行を入れる処理の関係上、
|
77
|
+
# </summary>\r\nnakami のような ブロック要素閉じタグ直後に改行が来ている場合、スペースが増殖してしまう (= 2回フォーマットをかけると結果が変わってしまう)
|
78
|
+
# それを防ぐため、ブロック要素閉じタグ直後の場合は先頭の改行を削除する
|
79
|
+
if node.instance_of?(Nokogiri::XML::Text) && !node.previous_sibling.nil? && !BREAK_LINE_NOT_INCREASE_TAGS.include?(node.previous_sibling.name) && !CONTENT_NO_MODIFY_TAGS.include?(node.parent.name)
|
80
|
+
node.content = node.content.gsub(/\A *(\r\n|\n)*/, "")
|
81
|
+
end
|
82
|
+
|
83
|
+
# 上の事を、直後がブロック要素開始タグの場合にも末尾の改行についてする
|
84
|
+
if node.instance_of?(Nokogiri::XML::Text) && !node.next_sibling.nil? && !BREAK_LINE_NOT_INCREASE_TAGS.include?(node.next_sibling.name) && !CONTENT_NO_MODIFY_TAGS.include?(node.parent.name)
|
85
|
+
node.content = node.content.gsub(/ *(\r\n|\n)*\Z/, "")
|
86
|
+
end
|
87
|
+
|
57
88
|
# タグの中身を整形する(見やすくするため)
|
58
|
-
|
59
|
-
|
89
|
+
# 英文など、スペースが重要な言語があるので、stripはしない (Hello <a href="#world">world</a> のような文でスペースが、stripで無くなってしまう)
|
90
|
+
# \r\n を 2文字で1つのもの扱いにするため \s ではなく () で列挙している
|
91
|
+
# 連続する改行・スペースをスペース1つにし、先頭と最後の改行・スペースを除去し、文中の改行を除去する
|
92
|
+
if node.instance_of?(Nokogiri::XML::Text) && (CONTENT_NO_MODIFY_TAGS & node.ancestors.map do |ancestor| ancestor.name end).empty?
|
93
|
+
node.content = node.content.gsub(/(\r\n|\n| |\t|\f){2,}/, " ").gsub(/(\A ?(\r\n|\n) ?| ?(\r\n|\n) ?\Z)/, " ").gsub("\r\n", " ")
|
60
94
|
end
|
61
95
|
|
62
96
|
# 閉じタグとテキストノードの間に改行がなければ入れる(見やすくするため)
|
@@ -73,19 +107,20 @@ module Hitomalu
|
|
73
107
|
body_str = body.to_s.gsub(/(\|mykaigyo\|)+/, "\r\n").gsub('|myspace|', ' ').gsub(/(<\/wbr>|\|mykaramojiretsu\||\A<body>(\n|\r\n)*|(\n|\r\n)*<\/body>\Z)/, "").gsub(/(?<!\r)\n/, "\r\n")
|
74
108
|
|
75
109
|
# </span></div> のような閉じタグの間に改行が無かったら改行を入れる (Nokogiri の add_next_sibling は 20000回するとメモリを6GB以上使うので文字列処理でやる)
|
76
|
-
#
|
110
|
+
# ただし、片方または両方がインライン要素の閉じタグだったら入れない
|
77
111
|
prev_str = ""
|
78
112
|
while body_str != prev_str do
|
79
113
|
prev_str = body_str
|
80
|
-
body_str = body_str.gsub(/(<\/[a-z]+>)(<\/(?!
|
114
|
+
body_str = body_str.gsub(/(<\/(?!(#{INLINE_TAGS_REGEXP}))[a-z]+>)(<\/(?!(#{INLINE_TAGS_REGEXP}))[a-z]+>)/, "\\1\r\n\\3")
|
81
115
|
end
|
82
116
|
|
83
117
|
# 開始タグの前に改行がなければ改行を入れる (add_prev_sibling は重いので文字列処理でやる) (文章の先頭からは消す)
|
84
118
|
# その後、使い終わった改行しない印を消す
|
85
|
-
|
119
|
+
# また、閉じタグしか無い行の先頭のスペースを消す (閉じタグで改行されるのはブロック要素の閉じタグだけであるため、pre以外ならスペースを消して問題ない)
|
120
|
+
body_str = body_str.gsub(/(?<!\r\n)(?<!\|nobreakline\|)(?<!\|nobreakline\| )<(?!\/)/, "\r\n<").gsub(/(\A\r\n|\|nobreakline\|)/, "").gsub(/^ *(?!<\/pre>)(<\/[a-z]+>)$/, "\\1")
|
86
121
|
|
87
122
|
# <br> や <hr> や <col> の後ろに改行がなければ改行を入れる (add_next_sibling は重いので文字列処理でやる)
|
88
|
-
body_str = body_str.gsub(/(<(
|
123
|
+
body_str = body_str.gsub(/(<(?:#{ADD_BREAK_LINE_TAGS_REGEXP})>)(?!\r\n)/, "\\1\r\n")
|
89
124
|
end
|
90
125
|
end
|
91
126
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hitomalu_formatter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- t-hazawa
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-08-
|
11
|
+
date: 2022-08-16 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: []
|