pseudohikiparser 0.0.0.14.develop → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.ja.md +435 -0
- data/README.md +187 -79
- data/lib/pseudohiki/blockparser.rb +27 -64
- data/lib/pseudohiki/htmlformat.rb +0 -24
- data/lib/pseudohiki/markdownformat.rb +3 -9
- data/lib/pseudohiki/version.rb +1 -1
- data/lib/pseudohikiparser.rb +0 -2
- data/test/test_blockparser.rb +0 -29
- data/test/test_htmlformat.rb +0 -63
- data/test/test_markdownformat.rb +7 -60
- metadata +5 -5
- data/lib/pseudohiki/sinatra_helpers.rb +0 -23
@@ -37,15 +37,15 @@ module PseudoHiki
|
|
37
37
|
end
|
38
38
|
|
39
39
|
class BlockStack < TreeStack
|
40
|
-
def
|
41
|
-
self.current_node.parse_leafs
|
42
|
-
|
40
|
+
def pop
|
41
|
+
self.current_node.parse_leafs
|
42
|
+
super
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
46
|
class BlockLeaf < BlockStack::Leaf
|
47
47
|
@@head_re = {}
|
48
|
-
attr_accessor :nominal_level, :node_id
|
48
|
+
attr_accessor :nominal_level, :node_id
|
49
49
|
|
50
50
|
def self.head_re=(head_regex)
|
51
51
|
@self_head_re = @@head_re[self] = head_regex
|
@@ -85,7 +85,7 @@ module PseudoHiki
|
|
85
85
|
super(stack)
|
86
86
|
end
|
87
87
|
|
88
|
-
def parse_leafs
|
88
|
+
def parse_leafs
|
89
89
|
parsed = InlineParser.parse(self.join)
|
90
90
|
self.clear
|
91
91
|
self.concat(parsed)
|
@@ -135,10 +135,6 @@ module PseudoHiki
|
|
135
135
|
first.nominal_level if first # @cached_nominal_level ||= (first.nominal_level if first)
|
136
136
|
end
|
137
137
|
|
138
|
-
def decorator
|
139
|
-
first.decorator if first
|
140
|
-
end
|
141
|
-
|
142
138
|
def push_self(stack)
|
143
139
|
@stack = stack
|
144
140
|
super(stack)
|
@@ -148,7 +144,7 @@ module PseudoHiki
|
|
148
144
|
not (kind_of?(breaker.block) and nominal_level == breaker.nominal_level)
|
149
145
|
end
|
150
146
|
|
151
|
-
def parse_leafs
|
147
|
+
def parse_leafs; end
|
152
148
|
|
153
149
|
def in_link_tag?(preceding_str)
|
154
150
|
preceding_str[-2, 2] == "[[".freeze or preceding_str[-1, 1] == "|".freeze
|
@@ -160,7 +156,7 @@ module PseudoHiki
|
|
160
156
|
|
161
157
|
def add_leaf(line, blockparser)
|
162
158
|
leaf = create_leaf(line, blockparser)
|
163
|
-
blockparser.stack.
|
159
|
+
blockparser.stack.pop while blockparser.breakable?(leaf)
|
164
160
|
blockparser.stack.push leaf
|
165
161
|
end
|
166
162
|
|
@@ -172,8 +168,8 @@ module PseudoHiki
|
|
172
168
|
end
|
173
169
|
|
174
170
|
class NonNestedBlockNode < BlockNode
|
175
|
-
def parse_leafs
|
176
|
-
self.each {|leaf| leaf.parse_leafs
|
171
|
+
def parse_leafs
|
172
|
+
self.each {|leaf| leaf.parse_leafs }
|
177
173
|
end
|
178
174
|
end
|
179
175
|
|
@@ -193,11 +189,11 @@ module PseudoHiki
|
|
193
189
|
|
194
190
|
module BlockElement
|
195
191
|
{
|
196
|
-
BlockLeaf => %w(DescLeaf VerbatimLeaf TableLeaf CommentOutLeaf BlockNodeEnd HrLeaf
|
192
|
+
BlockLeaf => %w(DescLeaf VerbatimLeaf TableLeaf CommentOutLeaf BlockNodeEnd HrLeaf),
|
197
193
|
NonNestedBlockLeaf => %w(QuoteLeaf ParagraphLeaf),
|
198
194
|
NestedBlockLeaf => %w(HeadingLeaf),
|
199
195
|
ListTypeLeaf => %w(ListLeaf EnumLeaf),
|
200
|
-
BlockNode => %w(DescNode VerbatimNode TableNode CommentOutNode HrNode
|
196
|
+
BlockNode => %w(DescNode VerbatimNode TableNode CommentOutNode HrNode),
|
201
197
|
NonNestedBlockNode => %w(QuoteNode ParagraphNode),
|
202
198
|
NestedBlockNode => %w(HeadingNode),
|
203
199
|
ListTypeBlockNode => %w(ListNode EnumNode),
|
@@ -222,43 +218,15 @@ module PseudoHiki
|
|
222
218
|
attr_accessor :in_block_tag
|
223
219
|
|
224
220
|
def add_leaf(line, blockparser)
|
225
|
-
return @stack.
|
221
|
+
return @stack.pop if LINE_PAT::VERBATIM_END =~ line
|
226
222
|
return super(line, blockparser) unless @in_block_tag
|
227
223
|
line = " ".concat(line) if BlockElement::BlockNodeEnd.head_re =~ line and not @in_block_tag
|
228
224
|
@stack.push BlockElement::VerbatimLeaf.create(line, @in_block_tag)
|
229
225
|
end
|
230
226
|
end
|
231
227
|
|
232
|
-
class BlockElement::DecoratorNode
|
233
|
-
DECORATOR_PAT = /\A(?:([^\[\]:]+))?(?:\[([^\[\]]+)\])?(?::\s*(\S.*))?/o
|
234
|
-
|
235
|
-
class DecoratorItem < Struct.new(:string, :type, :id, :value)
|
236
|
-
def initialize(*args)
|
237
|
-
super
|
238
|
-
self.value = InlineParser.parse(self.value) if self.value
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
242
|
-
def parse_leafs(breaker)
|
243
|
-
decorator = {}
|
244
|
-
breaker.decorator = decorator
|
245
|
-
@stack.remove_current_node.each do |leaf|
|
246
|
-
m = DECORATOR_PAT.match(leaf.join)
|
247
|
-
return nil unless m
|
248
|
-
item = DecoratorItem.new(*(m.to_a))
|
249
|
-
decorator[item.type||:id] = item
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
def breakable?(breaker)
|
254
|
-
return super if breaker.kind_of?(BlockElement::DecoratorLeaf)
|
255
|
-
parse_leafs(breaker)
|
256
|
-
@stack.current_node.breakable?(breaker)
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
228
|
class BlockElement::QuoteNode
|
261
|
-
def parse_leafs
|
229
|
+
def parse_leafs
|
262
230
|
self[0] = BlockParser.parse(self[0])
|
263
231
|
end
|
264
232
|
end
|
@@ -316,8 +284,7 @@ module PseudoHiki
|
|
316
284
|
[ParagraphLeaf, ParagraphNode],
|
317
285
|
[HrLeaf, HrNode],
|
318
286
|
[ListLeaf, ListNode],
|
319
|
-
[EnumLeaf, EnumNode]
|
320
|
-
[DecoratorLeaf, DecoratorNode]
|
287
|
+
[EnumLeaf, EnumNode]
|
321
288
|
].each do |leaf, node|
|
322
289
|
ParentNode[leaf] = node
|
323
290
|
end
|
@@ -326,31 +293,28 @@ module PseudoHiki
|
|
326
293
|
|
327
294
|
def self.assign_head_re
|
328
295
|
irregular_leafs = [BlockNodeEnd, VerbatimLeaf, HrLeaf]
|
329
|
-
|
296
|
+
head_pats, leaf_types = [], [:entire_matched_part]
|
330
297
|
[['\r?\n?$', BlockNodeEnd],
|
331
|
-
['\s', VerbatimLeaf],
|
332
|
-
['*', ListLeaf],
|
333
|
-
['#', EnumLeaf],
|
334
298
|
[':', DescLeaf],
|
335
|
-
['
|
299
|
+
['\s', VerbatimLeaf],
|
336
300
|
['""', QuoteLeaf],
|
337
301
|
['||', TableLeaf],
|
338
|
-
['//@', DecoratorLeaf],
|
339
302
|
['//', CommentOutLeaf],
|
303
|
+
['!', HeadingLeaf],
|
304
|
+
['*', ListLeaf],
|
305
|
+
['#', EnumLeaf],
|
340
306
|
['----\s*$', HrLeaf]
|
341
307
|
].each do |head, leaf|
|
342
308
|
escaped_head = irregular_leafs.include?(leaf) ? head : Regexp.escape(head)
|
343
309
|
head_pat = leaf.with_depth? ? "#{escaped_head}+" : "#{escaped_head}"
|
344
310
|
leaf.head_re = Regexp.new('\\A'+head_pat)
|
345
|
-
|
346
|
-
|
347
|
-
regular_leaf_types.push head unless irregular_leafs.include?(leaf)
|
311
|
+
head_pats.push "(#{escaped_head})"
|
312
|
+
leaf_types.push leaf
|
348
313
|
end
|
349
|
-
|
350
|
-
return Regexp.new('\\A(?:'+irregular_head_pats.join('|')+')'), regular_leaf_types, head_to_leaf, irregular_leaf_types, irregular_leafs.length
|
314
|
+
return Regexp.new('\\A(?:'+head_pats.join('|')+')'), leaf_types, leaf_types.length - 1
|
351
315
|
end
|
352
316
|
|
353
|
-
|
317
|
+
LEAF_HEAD_PAT, NOT_PARAGRAPH_LEAF_TYPES, NUMBER_OF_NOT_PARAGRAPH_LEAF_TYPES = assign_head_re
|
354
318
|
|
355
319
|
def initialize
|
356
320
|
root_node = BlockNode.new
|
@@ -365,16 +329,15 @@ module PseudoHiki
|
|
365
329
|
end
|
366
330
|
|
367
331
|
def select_leaf_type(line)
|
368
|
-
matched =
|
369
|
-
|
370
|
-
|
371
|
-
ParagraphLeaf
|
332
|
+
matched = LEAF_HEAD_PAT.match(line)
|
333
|
+
return ParagraphLeaf unless matched
|
334
|
+
1.upto(NUMBER_OF_NOT_PARAGRAPH_LEAF_TYPES) {|i| return NOT_PARAGRAPH_LEAF_TYPES[i] if matched[i] }
|
372
335
|
end
|
373
336
|
|
374
337
|
def read_lines(lines)
|
375
338
|
each_line = lines.respond_to?(:each_line) ? :each_line : :each
|
376
339
|
lines.send(each_line) {|line| @stack.current_node.add_leaf(line, self) }
|
377
|
-
@stack.
|
340
|
+
@stack.pop
|
378
341
|
end
|
379
342
|
end
|
380
343
|
end
|
@@ -61,7 +61,6 @@ module PseudoHiki
|
|
61
61
|
|
62
62
|
def visit(tree)
|
63
63
|
htmlelement = create_self_element(tree)
|
64
|
-
decorate(htmlelement, tree)
|
65
64
|
push_visited_results(htmlelement, tree)
|
66
65
|
htmlelement
|
67
66
|
end
|
@@ -79,21 +78,6 @@ module PseudoHiki
|
|
79
78
|
chunks.push tree
|
80
79
|
end
|
81
80
|
|
82
|
-
def decorate(htmlelement, tree)
|
83
|
-
each_decorator(htmlelement, tree) do |element, decorator|
|
84
|
-
element[CLASS] = HtmlElement.escape(decorator[CLASS].id) if decorator[CLASS]
|
85
|
-
if id_item = decorator[ID]||decorator[:id]
|
86
|
-
element[ID] = HtmlElement.escape(id_item.id).upcase
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def each_decorator(element, tree)
|
92
|
-
return unless element.kind_of? HtmlElement
|
93
|
-
return unless tree.kind_of? BlockParser::BlockNode and tree.decorator
|
94
|
-
tree.decorator.tap {|decorator| yield element, decorator }
|
95
|
-
end
|
96
|
-
|
97
81
|
class ListLeafNodeFormatter < self
|
98
82
|
def create_self_element(tree)
|
99
83
|
super(tree).tap do |element|
|
@@ -191,14 +175,6 @@ module PseudoHiki
|
|
191
175
|
|
192
176
|
#for BlockParser
|
193
177
|
|
194
|
-
class << Formatter[TableNode]
|
195
|
-
def decorate(htmlelement, tree)
|
196
|
-
each_decorator(htmlelement, tree) do |element, decorator|
|
197
|
-
htmlelement["summary"] = HtmlElement.escape(decorator["summary"].value.join) if decorator["summary"]
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
178
|
class << Formatter[VerbatimNode]
|
203
179
|
def visit(tree)
|
204
180
|
create_self_element.tap do |element|
|
@@ -140,6 +140,7 @@ module PseudoHiki
|
|
140
140
|
|
141
141
|
class LinkNodeFormatter < self
|
142
142
|
def visit(tree)
|
143
|
+
not_from_thumbnail = tree.first.class != LinkNode
|
143
144
|
tree = tree.dup
|
144
145
|
element = create_self_element
|
145
146
|
caption = get_caption(tree)
|
@@ -149,7 +150,7 @@ module PseudoHiki
|
|
149
150
|
raise NoMethodError unless tree.empty?
|
150
151
|
STDERR.puts "No uri is specified for #{caption}"
|
151
152
|
end
|
152
|
-
element.push "!" if ImageSuffix =~ ref
|
153
|
+
element.push "!" if ImageSuffix =~ ref and not_from_thumbnail
|
153
154
|
element.push "[#{(caption||tree).join}](#{tree.join})"
|
154
155
|
element
|
155
156
|
end
|
@@ -243,14 +244,13 @@ module PseudoHiki
|
|
243
244
|
class VerbatimNodeFormatter < self
|
244
245
|
def visit(tree)
|
245
246
|
element = super(tree)
|
246
|
-
@language_name = language_name(tree)
|
247
247
|
return gfm_verbatim(element) if @options.gfm_style
|
248
248
|
md_verbatim(element)
|
249
249
|
end
|
250
250
|
|
251
251
|
def gfm_verbatim(element)
|
252
252
|
element.tap do |lines|
|
253
|
-
lines.unshift "```#{
|
253
|
+
lines.unshift "```#{$/}"
|
254
254
|
lines.push "```#{$/ * 2}"
|
255
255
|
end
|
256
256
|
end
|
@@ -258,12 +258,6 @@ module PseudoHiki
|
|
258
258
|
def md_verbatim(element)
|
259
259
|
element.join.gsub(/^/o, " ").sub(/ \Z/o, "").concat $/
|
260
260
|
end
|
261
|
-
|
262
|
-
def language_name(tree)
|
263
|
-
tree.decorator.tap do |decorator|
|
264
|
-
return decorator ? decorator["code"].id : ""
|
265
|
-
end
|
266
|
-
end
|
267
261
|
end
|
268
262
|
|
269
263
|
class QuoteNodeFormatter < self
|
data/lib/pseudohiki/version.rb
CHANGED
data/lib/pseudohikiparser.rb
CHANGED
data/test/test_blockparser.rb
CHANGED
@@ -311,35 +311,6 @@ TEXT
|
|
311
311
|
assert_equal([[[["heading"]]]],parsed)
|
312
312
|
end
|
313
313
|
|
314
|
-
|
315
|
-
def test_decorator
|
316
|
-
text = <<TEXT
|
317
|
-
//@class[section_name]
|
318
|
-
!!title of section
|
319
|
-
|
320
|
-
//@summary: Summary of the table
|
321
|
-
||!header 1||! header 2
|
322
|
-
||cell 1||cell 2
|
323
|
-
|
324
|
-
a paragraph.
|
325
|
-
|
326
|
-
//@class[class_name]
|
327
|
-
//@[id_name]
|
328
|
-
another paragraph.
|
329
|
-
TEXT
|
330
|
-
|
331
|
-
tree = PseudoHiki::BlockParser.parse(text.lines.to_a.map {|line| line.chomp })
|
332
|
-
assert_equal(PseudoHiki::BlockParser::BlockNode, tree.class)
|
333
|
-
assert_equal("section_name", tree[0].decorator["class"].id)
|
334
|
-
assert_equal(PseudoHiki::BlockParser::BlockElement::HeadingNode, tree[0].class)
|
335
|
-
assert_equal([[["title of section"]], [[[["header 1"]], [[" header 2"]]], [[["cell 1"]], [["cell 2"]]]], [[["a paragraph."]]], [[["another paragraph."]]]], tree[0])
|
336
|
-
assert_equal([["Summary of the table"]], tree[0][1].decorator["summary"].value)
|
337
|
-
assert_equal(PseudoHiki::BlockParser::BlockElement::TableNode, tree[0][1].class)
|
338
|
-
assert_equal(nil, tree[0][2].decorator)
|
339
|
-
assert_equal('id_name', tree[0][3].decorator[:id].id)
|
340
|
-
assert_equal('class_name', tree[0][3].decorator["class"].id)
|
341
|
-
end
|
342
|
-
|
343
314
|
def test_comment_out_followed_by_a_verbatim_block
|
344
315
|
text = <<TEXT
|
345
316
|
the first paragraph
|
data/test/test_htmlformat.rb
CHANGED
@@ -696,69 +696,6 @@ HTML
|
|
696
696
|
assert_equal(xhtml, XhtmlFormat.format(tree).to_s)
|
697
697
|
end
|
698
698
|
|
699
|
-
def test_decorator
|
700
|
-
text = <<TEXT
|
701
|
-
//@class[section_type]
|
702
|
-
!!title of section
|
703
|
-
|
704
|
-
a paragraph.
|
705
|
-
|
706
|
-
//@class[class_name]
|
707
|
-
//@id[id_name]
|
708
|
-
another paragraph.
|
709
|
-
TEXT
|
710
|
-
|
711
|
-
xhtml = <<HTML
|
712
|
-
<div class="section_type">
|
713
|
-
<h2>title of section</h2>
|
714
|
-
<p>
|
715
|
-
a paragraph.</p>
|
716
|
-
<p class="class_name" id="ID_NAME">
|
717
|
-
another paragraph.</p>
|
718
|
-
<!-- end of section_type -->
|
719
|
-
</div>
|
720
|
-
HTML
|
721
|
-
tree = BlockParser.parse(text.lines.to_a.map {|line| line.chomp })
|
722
|
-
assert_equal(xhtml, XhtmlFormat.format(tree).to_s)
|
723
|
-
end
|
724
|
-
|
725
|
-
def test_decorator_for_table
|
726
|
-
text = <<TEXT
|
727
|
-
//@summary: Summary of the table
|
728
|
-
||!header 1||! header 2
|
729
|
-
||cell 1||cell 2
|
730
|
-
TEXT
|
731
|
-
|
732
|
-
xhtml = <<HTML
|
733
|
-
<table summary="Summary of the table">
|
734
|
-
<tr><th>header 1</th><th> header 2</th></tr>
|
735
|
-
<tr><td>cell 1</td><td>cell 2</td></tr>
|
736
|
-
</table>
|
737
|
-
HTML
|
738
|
-
tree = BlockParser.parse(text.lines.to_a.map {|line| line.chomp })
|
739
|
-
assert_equal(xhtml, XhtmlFormat.format(tree).to_s)
|
740
|
-
end
|
741
|
-
|
742
|
-
def test_decorator_for_verbatim
|
743
|
-
text = <<TEXT
|
744
|
-
//@code[ruby]
|
745
|
-
def bonjour!
|
746
|
-
puts "Bonjour!"
|
747
|
-
end
|
748
|
-
TEXT
|
749
|
-
|
750
|
-
xhtml = <<HTML
|
751
|
-
<pre>
|
752
|
-
def bonjour!
|
753
|
-
puts "Bonjour!"
|
754
|
-
end
|
755
|
-
</pre>
|
756
|
-
HTML
|
757
|
-
|
758
|
-
tree = BlockParser.parse(text.lines.to_a)
|
759
|
-
assert_equal(xhtml, XhtmlFormat.format(tree).to_s)
|
760
|
-
end
|
761
|
-
|
762
699
|
def test_comment_out_followed_by_a_verbatim_block
|
763
700
|
text = <<TEXT
|
764
701
|
the first paragraph
|
data/test/test_markdownformat.rb
CHANGED
@@ -68,6 +68,13 @@ IMAGE
|
|
68
68
|
assert_equal("A test for a link to ![an image](image.png)\n#{$/}", @formatter.format(tree).to_s)
|
69
69
|
end
|
70
70
|
|
71
|
+
def test_link_from_image
|
72
|
+
text = "[[[[thumbnail of an image|http://www.example.org/image_thumb.png]]|http://www.example.org/image.png]]"
|
73
|
+
|
74
|
+
tree = BlockParser.parse(text.lines.to_a)
|
75
|
+
assert_equal("[![thumbnail of an image](http://www.example.org/image_thumb.png)](http://www.example.org/image.png)#{$/}", @formatter.format(tree).to_s)
|
76
|
+
end
|
77
|
+
|
71
78
|
def test_em
|
72
79
|
text = "string with ''emphasis'' "
|
73
80
|
tree = BlockParser.parse(text.lines.to_a)
|
@@ -501,65 +508,5 @@ TEXT
|
|
501
508
|
tree = BlockParser.parse(text.lines.to_a)
|
502
509
|
assert_equal(md_text, @formatter.format(tree).to_s)
|
503
510
|
end
|
504
|
-
|
505
|
-
def test_decorator_for_verbatim
|
506
|
-
text = <<TEXT
|
507
|
-
//@code[ruby]
|
508
|
-
def bonjour!
|
509
|
-
puts "Bonjour!"
|
510
|
-
end
|
511
|
-
TEXT
|
512
|
-
|
513
|
-
gfm_text =<<TEXT
|
514
|
-
```ruby
|
515
|
-
def bonjour!
|
516
|
-
puts "Bonjour!"
|
517
|
-
end
|
518
|
-
```
|
519
|
-
|
520
|
-
TEXT
|
521
|
-
|
522
|
-
md_text = <<TEXT
|
523
|
-
def bonjour!
|
524
|
-
puts "Bonjour!"
|
525
|
-
end
|
526
|
-
|
527
|
-
TEXT
|
528
|
-
|
529
|
-
tree = BlockParser.parse(text.lines.to_a)
|
530
|
-
assert_equal(gfm_text, @gfm_formatter.format(tree).to_s)
|
531
|
-
assert_equal(md_text, @formatter.format(tree).to_s)
|
532
|
-
end
|
533
|
-
|
534
|
-
def test_decorator_for_verbatim_block
|
535
|
-
text = <<TEXT
|
536
|
-
//@code[ruby]
|
537
|
-
<<<
|
538
|
-
def bonjour!
|
539
|
-
puts "Bonjour!"
|
540
|
-
end
|
541
|
-
>>>
|
542
|
-
TEXT
|
543
|
-
|
544
|
-
gfm_text =<<TEXT
|
545
|
-
```ruby
|
546
|
-
def bonjour!
|
547
|
-
puts "Bonjour!"
|
548
|
-
end
|
549
|
-
```
|
550
|
-
|
551
|
-
TEXT
|
552
|
-
|
553
|
-
md_text = <<TEXT
|
554
|
-
def bonjour!
|
555
|
-
puts "Bonjour!"
|
556
|
-
end
|
557
|
-
|
558
|
-
TEXT
|
559
|
-
|
560
|
-
tree = BlockParser.parse(text.lines.to_a)
|
561
|
-
assert_equal(gfm_text, @gfm_formatter.format(tree).to_s)
|
562
|
-
assert_equal(md_text, @formatter.format(tree).to_s)
|
563
|
-
end
|
564
511
|
end
|
565
512
|
|