pseudohikiparser 0.0.3 → 0.0.4.develop
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.ja.md +132 -8
- data/README.md +134 -10
- data/lib/htmlelement.rb +42 -42
- data/lib/pseudohiki/autolink.rb +60 -0
- data/lib/pseudohiki/blockparser.rb +233 -125
- data/lib/pseudohiki/converter.rb +140 -81
- data/lib/pseudohiki/htmlformat.rb +156 -82
- data/lib/pseudohiki/htmlplugin.rb +9 -28
- data/lib/pseudohiki/inlineparser.rb +21 -24
- data/lib/pseudohiki/markdownformat.rb +94 -98
- data/lib/pseudohiki/plaintextformat.rb +67 -57
- data/lib/pseudohiki/sinatra_helpers.rb +23 -0
- data/lib/pseudohiki/treestack.rb +4 -4
- data/lib/pseudohiki/utils.rb +1 -2
- data/lib/pseudohiki/version.rb +1 -1
- data/lib/pseudohikiparser.rb +49 -28
- data/test/test_autolink.rb +104 -0
- data/test/test_blockparser.rb +78 -11
- data/test/test_htmlformat.rb +436 -0
- data/test/test_htmlplugin.rb +43 -0
- data/test/test_markdownformat.rb +156 -3
- data/test/test_plaintextformat.rb +85 -0
- data/test/test_pseudohiki2html.rb +82 -0
- data/test/test_pseudohikiparser.rb +286 -0
- data/test/test_utils.rb +1 -1
- metadata +22 -4
@@ -10,24 +10,31 @@ module PseudoHiki
|
|
10
10
|
include BlockParser::BlockElement
|
11
11
|
include TableRowParser::InlineElement
|
12
12
|
|
13
|
-
#for InlineParser
|
13
|
+
# for InlineParser
|
14
14
|
LINK, LITERAL, PLUGIN = %w(a code span)
|
15
15
|
BLANK, SPACE = "", " "
|
16
16
|
HREF, SRC, ALT, ID, CLASS, ROWSPAN, COLSPAN = %w(href src alt id class rowspan colspan)
|
17
|
-
#for BlockParser
|
17
|
+
# for BlockParser
|
18
18
|
DT, DD, LI = %w(dt dd li)
|
19
|
-
DescSep = [InlineParser::DescSep]
|
19
|
+
DescSep, LinkSep = [InlineParser::DescSep], [InlineParser::LinkSep]
|
20
20
|
|
21
21
|
Formatter = {}
|
22
22
|
|
23
|
+
class << self
|
24
|
+
attr_accessor :auto_link_in_verbatim
|
25
|
+
end
|
26
|
+
|
27
|
+
@auto_link_in_verbatim = true
|
28
|
+
|
23
29
|
attr_reader :element_name
|
24
|
-
attr_writer :generator, :formatter
|
30
|
+
attr_writer :generator, :formatter, :format_class
|
25
31
|
|
26
32
|
def self.setup_new_formatter(new_formatter, generator)
|
27
33
|
new_formatter.each do |node_class, formatter|
|
28
34
|
new_formatter[node_class] = formatter.clone
|
29
35
|
new_formatter[node_class].generator = generator
|
30
36
|
new_formatter[node_class].formatter = new_formatter
|
37
|
+
new_formatter[node_class].format_class = self
|
31
38
|
end
|
32
39
|
end
|
33
40
|
|
@@ -39,19 +46,29 @@ module PseudoHiki
|
|
39
46
|
self
|
40
47
|
end
|
41
48
|
|
42
|
-
def self.
|
43
|
-
|
49
|
+
def self.default_options
|
50
|
+
{ :auto_link_in_verbatim => @auto_link_in_verbatim }
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.format(tree, options=nil)
|
54
|
+
cur_auto_link_setting = @auto_link_in_verbatim
|
55
|
+
options = default_options unless options
|
56
|
+
@auto_link_in_verbatim = options[:auto_link_in_verbatim]
|
57
|
+
formatter = get_plain
|
44
58
|
tree.accept(formatter)
|
59
|
+
ensure
|
60
|
+
@auto_link_in_verbatim = cur_auto_link_setting
|
45
61
|
end
|
46
62
|
|
47
63
|
def initialize(element_name, generator=HtmlElement)
|
48
64
|
@element_name = element_name
|
49
65
|
@generator = generator
|
50
66
|
@formatter = Formatter
|
67
|
+
@format_class = self.class
|
51
68
|
end
|
52
69
|
|
53
70
|
def visited_result(element)
|
54
|
-
visitor = @formatter[element.class]
|
71
|
+
visitor = @formatter[element.class] || @formatter[PlainNode]
|
55
72
|
element.accept(visitor)
|
56
73
|
end
|
57
74
|
|
@@ -60,17 +77,19 @@ module PseudoHiki
|
|
60
77
|
end
|
61
78
|
|
62
79
|
def visit(tree)
|
63
|
-
htmlelement =
|
80
|
+
htmlelement = create_element(tree)
|
81
|
+
decorate(htmlelement, tree)
|
64
82
|
push_visited_results(htmlelement, tree)
|
65
83
|
htmlelement
|
66
84
|
end
|
67
85
|
|
68
|
-
def
|
86
|
+
def create_element(tree=nil)
|
69
87
|
@generator.create(@element_name)
|
70
88
|
end
|
71
89
|
|
72
90
|
def split_into_parts(tree, separator)
|
73
91
|
chunks = []
|
92
|
+
tree = tree.dup
|
74
93
|
while sep_index = tree.index(separator)
|
75
94
|
chunks.push tree.shift(sep_index)
|
76
95
|
tree.shift
|
@@ -78,45 +97,61 @@ module PseudoHiki
|
|
78
97
|
chunks.push tree
|
79
98
|
end
|
80
99
|
|
100
|
+
def decorate(htmlelement, tree)
|
101
|
+
each_decorator(htmlelement, tree) do |elm, decorator|
|
102
|
+
elm[CLASS] = HtmlElement.escape(decorator[CLASS].id) if decorator[CLASS]
|
103
|
+
if id_item = decorator[ID] || decorator[:id]
|
104
|
+
elm[ID] = HtmlElement.escape(id_item.id).upcase
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def each_decorator(element, tree)
|
110
|
+
return unless element.kind_of? HtmlElement
|
111
|
+
return unless tree.kind_of? BlockParser::BlockNode and tree.decorator
|
112
|
+
tree.decorator.tap {|decorator| yield element, decorator }
|
113
|
+
end
|
114
|
+
|
81
115
|
class ListLeafNodeFormatter < self
|
82
|
-
def
|
83
|
-
super(tree).tap do |
|
84
|
-
|
116
|
+
def create_element(tree)
|
117
|
+
super(tree).tap do |elm|
|
118
|
+
elm[ID] = tree.node_id.upcase if tree.node_id
|
85
119
|
end
|
86
120
|
end
|
87
121
|
end
|
88
122
|
|
89
|
-
[
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
123
|
+
[[EmNode, "em"],
|
124
|
+
[StrongNode, "strong"],
|
125
|
+
[DelNode, "del"],
|
126
|
+
[LiteralNode, LITERAL],
|
127
|
+
[PluginNode, PLUGIN],
|
128
|
+
[LinkNode, LINK],
|
129
|
+
[InlineLeaf, nil],
|
130
|
+
[PlainNode, nil], # Until here is for InlineParser
|
131
|
+
[DescNode, "dl"],
|
132
|
+
[QuoteNode, "blockquote"],
|
133
|
+
[TableNode, "table"],
|
134
|
+
[ParagraphNode, "p"],
|
135
|
+
[HrNode, "hr"],
|
136
|
+
[ListNode, "ul"],
|
137
|
+
[EnumNode, "ol"],
|
138
|
+
[TableLeaf, "tr"],
|
139
|
+
[VerbatimNode, "pre"],
|
140
|
+
[SectioningNode, "section"],
|
141
|
+
[CommentOutNode, nil],
|
142
|
+
[HeadingNode, "section"],
|
143
|
+
[DescLeaf, DT],
|
144
|
+
[TableCellNode, nil],
|
145
|
+
[HeadingLeaf, "h"], # Until here is for BlockParser
|
146
|
+
].each {|node_class, elm| Formatter[node_class] = new(elm) }
|
147
|
+
|
148
|
+
# for InlineParser
|
149
|
+
ImgFormat = new("img")
|
150
|
+
# for BlockParser
|
116
151
|
Formatter[ListWrapNode] = ListLeafNodeFormatter.new(LI)
|
117
152
|
Formatter[EnumWrapNode] = ListLeafNodeFormatter.new(LI)
|
118
153
|
|
119
|
-
#for InlineParser
|
154
|
+
# for InlineParser
|
120
155
|
|
121
156
|
class << Formatter[PluginNode]
|
122
157
|
def visit(tree)
|
@@ -134,31 +169,26 @@ module PseudoHiki
|
|
134
169
|
class << Formatter[LinkNode]
|
135
170
|
def visit(tree)
|
136
171
|
not_from_thumbnail = tree.first.class != LinkNode
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
rescue NoMethodError
|
142
|
-
raise NoMethodError unless tree.empty?
|
143
|
-
STDERR.puts "No uri is specified for #{caption}"
|
144
|
-
end
|
145
|
-
if ImageSuffix =~ ref and not_from_thumbnail
|
146
|
-
htmlelement = ImgFormat.create_self_element
|
147
|
-
htmlelement[SRC] = tree.join
|
172
|
+
caption, ref = caption_and_ref(tree)
|
173
|
+
if IMAGE_SUFFIX_RE =~ ref and not_from_thumbnail
|
174
|
+
htmlelement = ImgFormat.create_element
|
175
|
+
htmlelement[SRC] = ref
|
148
176
|
htmlelement[ALT] = caption.join if caption
|
149
177
|
else
|
150
|
-
htmlelement =
|
151
|
-
|
152
|
-
htmlelement
|
153
|
-
htmlelement.push caption||url
|
178
|
+
htmlelement = create_element
|
179
|
+
htmlelement[HREF] = ref.start_with?("#".freeze) ? ref.upcase : ref
|
180
|
+
htmlelement.push caption || ref
|
154
181
|
end
|
155
182
|
htmlelement
|
156
183
|
end
|
157
184
|
|
158
|
-
def
|
159
|
-
|
160
|
-
|
161
|
-
|
185
|
+
def caption_and_ref(tree)
|
186
|
+
caption, ref = split_into_parts(tree, LinkSep)
|
187
|
+
caption = ref ? caption.map {|token| visited_result(token) } : nil
|
188
|
+
return caption, (ref || tree).join
|
189
|
+
rescue NoMethodError
|
190
|
+
raise NoMethodError unless (ref || tree).empty?
|
191
|
+
STDERR.puts "No uri is specified for #{caption}"
|
162
192
|
end
|
163
193
|
end
|
164
194
|
|
@@ -169,20 +199,63 @@ module PseudoHiki
|
|
169
199
|
end
|
170
200
|
|
171
201
|
class << Formatter[PlainNode]
|
172
|
-
def
|
202
|
+
def create_element(tree=nil)
|
173
203
|
@generator::Children.new
|
174
204
|
end
|
175
205
|
end
|
176
206
|
|
177
|
-
#for BlockParser
|
207
|
+
# for BlockParser
|
208
|
+
|
209
|
+
class << Formatter[TableNode]
|
210
|
+
def decorate(htmlelement, tree)
|
211
|
+
each_decorator(htmlelement, tree) do |elm, decorator|
|
212
|
+
summary = decorator["summary"] && decorator["summary"].value.join
|
213
|
+
htmlelement["summary"] = HtmlElement.escape(summary) if summary
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
178
217
|
|
179
218
|
class << Formatter[VerbatimNode]
|
180
219
|
def visit(tree)
|
181
|
-
|
182
|
-
|
183
|
-
|
220
|
+
contents = add_link(@generator.escape(tree.join))
|
221
|
+
create_element.tap {|elm| elm.push contents }
|
222
|
+
end
|
223
|
+
|
224
|
+
def add_link(verbatim)
|
225
|
+
return verbatim unless @format_class.auto_link_in_verbatim
|
226
|
+
verbatim.gsub(AutoLink::URI_RE) do |url|
|
227
|
+
@generator.create(LINK, url, HREF => url).to_s
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
class << Formatter[SectioningNode]
|
233
|
+
ID_MARK = "#"
|
234
|
+
|
235
|
+
alias :orig_create_element :create_element
|
236
|
+
|
237
|
+
def section_with_id(tree, node_id)
|
238
|
+
orig_create_element(tree).tap do |elm|
|
239
|
+
elm[ID] = node_id[1..-1] # remove the first charactor from node_id
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def section_for_class(tree, node_id)
|
244
|
+
if HtmlElement::HTML5_TAGS.include? node_id
|
245
|
+
@generator.create(node_id)
|
246
|
+
else
|
247
|
+
orig_create_element(tree).tap do |elm|
|
248
|
+
elm[CLASS] = elm[CLASS] ? "#{elm[CLASS]} #{node_id}" : node_id
|
184
249
|
end
|
185
|
-
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def create_element(tree)
|
254
|
+
node_id = tree.node_id
|
255
|
+
if node_id.start_with? ID_MARK
|
256
|
+
section_with_id(tree, node_id)
|
257
|
+
else
|
258
|
+
section_for_class(tree, node_id)
|
186
259
|
end
|
187
260
|
end
|
188
261
|
end
|
@@ -192,46 +265,45 @@ module PseudoHiki
|
|
192
265
|
end
|
193
266
|
|
194
267
|
class << Formatter[HeadingNode]
|
195
|
-
def
|
196
|
-
super(tree).tap do |
|
197
|
-
heading_level = "h#{tree.first.
|
198
|
-
|
199
|
-
|
268
|
+
def create_element(tree)
|
269
|
+
super(tree).tap do |elm|
|
270
|
+
heading_level = "h#{tree.first.level}"
|
271
|
+
elm[CLASS] ||= heading_level
|
272
|
+
elm[CLASS] += SPACE + heading_level unless elm[CLASS] == heading_level
|
200
273
|
end
|
201
274
|
end
|
202
275
|
end
|
203
276
|
|
204
277
|
class << Formatter[DescLeaf]
|
205
278
|
def visit(tree)
|
206
|
-
|
207
|
-
element = @generator::Children.new
|
279
|
+
elm = @generator::Children.new
|
208
280
|
dt_part, dd_part = split_into_parts(tree, DescSep)
|
209
281
|
dt = super(dt_part)
|
210
|
-
|
282
|
+
elm.push dt
|
211
283
|
unless dd_part.nil? or dd_part.empty?
|
212
284
|
dd = @generator.create(DD)
|
213
285
|
push_visited_results(dd, dd_part)
|
214
|
-
|
286
|
+
elm.push dd
|
215
287
|
end
|
216
|
-
|
288
|
+
elm
|
217
289
|
end
|
218
290
|
end
|
219
291
|
|
220
292
|
class << Formatter[TableCellNode]
|
221
293
|
def visit(tree)
|
222
294
|
@element_name = tree.cell_type
|
223
|
-
super(tree).tap do |
|
224
|
-
|
225
|
-
|
226
|
-
#
|
295
|
+
super(tree).tap do |elm|
|
296
|
+
elm[ROWSPAN] = tree.rowspan if tree.rowspan > 1
|
297
|
+
elm[COLSPAN] = tree.colspan if tree.colspan > 1
|
298
|
+
# elm.push " " if elm.empty? #   = this line would be necessary for HTML 4 or XHTML 1.0
|
227
299
|
end
|
228
300
|
end
|
229
301
|
end
|
230
302
|
|
231
303
|
class << Formatter[HeadingLeaf]
|
232
|
-
def
|
233
|
-
@generator.create(@element_name+tree.
|
234
|
-
|
304
|
+
def create_element(tree)
|
305
|
+
@generator.create(@element_name + tree.level.to_s).tap do |elm|
|
306
|
+
elm[ID] = tree.node_id.upcase if tree.node_id
|
235
307
|
end
|
236
308
|
end
|
237
309
|
end
|
@@ -240,10 +312,12 @@ module PseudoHiki
|
|
240
312
|
class XhtmlFormat < HtmlFormat
|
241
313
|
Formatter = HtmlFormat::Formatter.dup
|
242
314
|
setup_new_formatter(Formatter, XhtmlElement)
|
315
|
+
@auto_link_in_verbatim = true
|
243
316
|
end
|
244
317
|
|
245
318
|
class Xhtml5Format < XhtmlFormat
|
246
319
|
Formatter = HtmlFormat::Formatter.dup
|
247
320
|
setup_new_formatter(Formatter, Xhtml5Element)
|
321
|
+
@auto_link_in_verbatim = true
|
248
322
|
end
|
249
323
|
end
|
@@ -9,7 +9,7 @@ module PseudoHiki
|
|
9
9
|
class HtmlFormat
|
10
10
|
class << Formatter[PluginNode]
|
11
11
|
def visit(leaf)
|
12
|
-
escape_inline_tags(leaf) { HtmlPlugin.new(@element_name,leaf.join).apply }
|
12
|
+
escape_inline_tags(leaf) { HtmlPlugin.new(@element_name, leaf.join).apply }
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -30,20 +30,19 @@ module PseudoHiki
|
|
30
30
|
NUMBER_RE = /(\d+)/
|
31
31
|
|
32
32
|
def parse(data)
|
33
|
-
result =
|
33
|
+
result = "".freeze
|
34
34
|
if PLUGIN_PAT =~ data
|
35
35
|
@plugin_name = $1
|
36
36
|
@with_paren = true if $2.chomp == "("
|
37
|
-
result = data.chomp.sub(PLUGIN_PAT,"")
|
38
|
-
result[-1,1] = "" if @with_paren
|
37
|
+
result = data.chomp.sub(PLUGIN_PAT, "")
|
38
|
+
result[-1, 1] = "" if @with_paren
|
39
39
|
else
|
40
40
|
@plugin_name = data.chomp
|
41
|
-
result = ""
|
42
41
|
end
|
43
42
|
result
|
44
43
|
end
|
45
44
|
|
46
|
-
def initialize(tag_type,parsed_data)
|
45
|
+
def initialize(tag_type, parsed_data)
|
47
46
|
@tag_type = tag_type
|
48
47
|
@plugin_name = nil
|
49
48
|
@with_paren = nil
|
@@ -66,14 +65,14 @@ module PseudoHiki
|
|
66
65
|
# end
|
67
66
|
|
68
67
|
def anchor
|
69
|
-
name, anchor_mark = @data.split(/,\s*/o,2)
|
68
|
+
name, anchor_mark = @data.split(/,\s*/o, 2)
|
70
69
|
anchor_mark = "_" if (anchor_mark.nil? or anchor_mark.empty?)
|
71
70
|
HtmlElement.create("a", anchor_mark,
|
72
71
|
"name" => name,
|
73
|
-
"href" => "#"+name)
|
72
|
+
"href" => "#" + name)
|
74
73
|
end
|
75
74
|
|
76
|
-
def HtmlPlugin.add_chemical_formula(chemical_formula="CO2",en_word="carbon dioxide")
|
75
|
+
def HtmlPlugin.add_chemical_formula(chemical_formula="CO2", en_word="carbon dioxide")
|
77
76
|
eval(<<-End)
|
78
77
|
def #{chemical_formula.downcase}
|
79
78
|
#(display=":cf",second_display=nil)
|
@@ -130,7 +129,7 @@ module PseudoHiki
|
|
130
129
|
@data.scan(/\A(\d+)([^\d].*)/o) do |data|
|
131
130
|
weight, molecule = data
|
132
131
|
if self.respond_to? molecule
|
133
|
-
return "<sup>#{weight}</sup>" + HtmlPlugin.new("",molecule).apply
|
132
|
+
return "<sup>#{weight}</sup>" + HtmlPlugin.new("", molecule).apply
|
134
133
|
else
|
135
134
|
return "<sup>#{weight}</sup>" + molecule
|
136
135
|
end
|
@@ -145,21 +144,3 @@ module PseudoHiki
|
|
145
144
|
end
|
146
145
|
end
|
147
146
|
end
|
148
|
-
|
149
|
-
if $0 == __FILE__
|
150
|
-
p HtmlPlugin.new("div","html(
|
151
|
-
<ul>
|
152
|
-
<li>list
|
153
|
-
<li>list
|
154
|
-
</ul>)").apply
|
155
|
-
p HtmlPlugin.new("div","inline(
|
156
|
-
*list
|
157
|
-
*list
|
158
|
-
)").apply
|
159
|
-
|
160
|
-
p HtmlPlugin.new("div","co2").apply
|
161
|
-
p HtmlPlugin.new("div","co2 :en").apply
|
162
|
-
p HtmlPlugin.new("div","cb(3km)").apply
|
163
|
-
p HtmlPlugin.new("div","per m").apply
|
164
|
-
p HtmlPlugin.new("div","iso 18co2").apply
|
165
|
-
end
|
@@ -7,11 +7,7 @@ module PseudoHiki
|
|
7
7
|
RELATIVE_PATH = /^\./o
|
8
8
|
ROOT_PATH = /^(\/|\\\\|[A-Za-z]:\\)/o
|
9
9
|
FILE_MARK = "file:///"
|
10
|
-
|
11
|
-
|
12
|
-
def self.subclass_of(parent_class, bound_env, subclass_names)
|
13
|
-
subclass_names. each {|name| eval "class #{name} < #{parent_class}; end", bound_env }
|
14
|
-
end
|
10
|
+
IMAGE_SUFFIX_RE = /\.(jpg|jpeg|gif|png|bmp)$/io
|
15
11
|
|
16
12
|
def self.compile_token_pat(*token_sets)
|
17
13
|
tokens = token_sets.flatten.uniq.sort do |x, y|
|
@@ -35,10 +31,11 @@ module PseudoHiki
|
|
35
31
|
module InlineElement
|
36
32
|
class InlineNode < InlineParser::Node; end
|
37
33
|
class InlineLeaf < InlineParser::Leaf; end
|
38
|
-
#
|
34
|
+
# class LinkSepLeaf < InlineLeaf; end
|
39
35
|
|
40
|
-
|
41
|
-
|
36
|
+
%w(LinkNode EmNode StrongNode DelNode PlainNode LiteralNode PluginNode).each do |subclass|
|
37
|
+
const_set(subclass, Class.new(InlineNode))
|
38
|
+
end
|
42
39
|
|
43
40
|
LinkSep, TableSep, DescSep = %w(| || :)
|
44
41
|
end
|
@@ -48,7 +45,7 @@ module PseudoHiki
|
|
48
45
|
TAIL = {}
|
49
46
|
NodeTypeToHead = {}
|
50
47
|
TokenPat = {}
|
51
|
-
|
48
|
+
|
52
49
|
[[LinkNode, "[[", "]]"],
|
53
50
|
[EmNode, "''", "''"],
|
54
51
|
[StrongNode, "'''", "'''"],
|
@@ -60,7 +57,7 @@ module PseudoHiki
|
|
60
57
|
NodeTypeToHead[type] = head
|
61
58
|
end
|
62
59
|
|
63
|
-
TokenPat[self] = PseudoHiki.compile_token_pat(HEAD.keys,TAIL.keys,[LinkSep, TableSep, DescSep])
|
60
|
+
TokenPat[self] = PseudoHiki.compile_token_pat(HEAD.keys, TAIL.keys, [LinkSep, TableSep, DescSep])
|
64
61
|
|
65
62
|
def initialize(str)
|
66
63
|
@tokens = PseudoHiki.split_into_tokens(str, TokenPat[self.class])
|
@@ -70,8 +67,8 @@ module PseudoHiki
|
|
70
67
|
def convert_last_node_into_leaf
|
71
68
|
last_node = remove_current_node
|
72
69
|
tag_head = NodeTypeToHead[last_node.class]
|
73
|
-
|
74
|
-
last_node.each {|leaf|
|
70
|
+
push InlineLeaf.create(tag_head)
|
71
|
+
last_node.each {|leaf| push_as_leaf leaf }
|
75
72
|
end
|
76
73
|
|
77
74
|
def node_in_ancestors?(node_class)
|
@@ -79,23 +76,23 @@ module PseudoHiki
|
|
79
76
|
end
|
80
77
|
|
81
78
|
def treated_as_node_end(token)
|
82
|
-
return
|
79
|
+
return pop if current_node.class == TAIL[token]
|
83
80
|
return nil unless node_in_ancestors?(TAIL[token])
|
84
81
|
convert_last_node_into_leaf until current_node.class == TAIL[token]
|
85
|
-
|
82
|
+
pop
|
86
83
|
end
|
87
84
|
|
88
85
|
def parse
|
89
86
|
while token = @tokens.shift
|
90
87
|
next if TAIL[token] and treated_as_node_end(token)
|
91
|
-
next if HEAD[token] and
|
92
|
-
|
88
|
+
next if HEAD[token] and push HEAD[token].new
|
89
|
+
push InlineLeaf.create(token)
|
93
90
|
end
|
94
91
|
self
|
95
92
|
end
|
96
93
|
|
97
94
|
def self.parse(str)
|
98
|
-
new(str).parse.tree #parser = new(str)
|
95
|
+
new(str).parse.tree # parser = new(str)
|
99
96
|
end
|
100
97
|
end
|
101
98
|
|
@@ -120,9 +117,9 @@ module PseudoHiki
|
|
120
117
|
|
121
118
|
class InlineElement::TableCellNode
|
122
119
|
def parse_cellspan(token_str)
|
123
|
-
|
124
|
-
|
125
|
-
@cell_type = TH if cell_modifiers
|
120
|
+
m = MODIFIED_CELL_PAT.match(token_str) and cell_modifiers = m[0]
|
121
|
+
return token_str if cell_modifiers.empty?
|
122
|
+
@cell_type = TH if cell_modifiers.start_with? TH_PAT
|
126
123
|
@rowspan = cell_modifiers.count(ROW_EXPANDER) + 1
|
127
124
|
@colspan = cell_modifiers.count(COL_EXPANDER) + 1
|
128
125
|
m.post_match
|
@@ -134,19 +131,19 @@ module PseudoHiki
|
|
134
131
|
end
|
135
132
|
|
136
133
|
def push(token)
|
137
|
-
return super(token) unless
|
134
|
+
return super(token) unless empty?
|
138
135
|
super(parse_first_token(token))
|
139
136
|
end
|
140
137
|
end
|
141
138
|
|
142
139
|
def treated_as_node_end(token)
|
143
140
|
return super(token) unless token == TableSep
|
144
|
-
|
145
|
-
|
141
|
+
pop
|
142
|
+
push TableCellNode.new
|
146
143
|
end
|
147
144
|
|
148
145
|
def parse
|
149
|
-
|
146
|
+
push TableCellNode.new
|
150
147
|
super
|
151
148
|
end
|
152
149
|
end
|