pseudohikiparser 0.0.5 → 0.0.6.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.
@@ -8,12 +8,12 @@ require 'pseudohiki/htmlformat'
8
8
  module PseudoHiki
9
9
  class HtmlFormat
10
10
  class << Formatter[PluginNode]
11
- def visit(leaf)
11
+ def visit(leaf, memo)
12
12
  escape_inline_tags(leaf) { HtmlPlugin.new(@element_name, leaf.join).apply }
13
13
  end
14
14
  end
15
15
  end
16
-
16
+
17
17
  class XhtmlFormat < HtmlFormat
18
18
  Formatter = HtmlFormat::Formatter.dup
19
19
  setup_new_formatter(Formatter, XhtmlElement)
@@ -48,7 +48,7 @@ module PseudoHiki
48
48
  @with_paren = nil
49
49
  @data = parse(parsed_data.to_s)
50
50
  end
51
-
51
+
52
52
  def apply
53
53
  self.send @plugin_name
54
54
  end
@@ -27,7 +27,24 @@ module PseudoHiki
27
27
  tokens
28
28
  end
29
29
 
30
+ def self.associate_nodes_with_tags(node_tag_table)
31
+ from_head, from_tail, to_head, to_tail = {}, {}, {}, {}
32
+
33
+ node_tag_table.each do |node_type, head, tail|
34
+ from_head[head] = node_type
35
+ from_tail[tail] = node_type
36
+ to_head[node_type] = head
37
+ to_tail[node_type] = tail
38
+ end
39
+
40
+ return from_head, from_tail, to_head, to_tail
41
+ end
42
+
30
43
  class InlineParser < TreeStack
44
+ class << self
45
+ attr_reader :token_pat
46
+ end
47
+
31
48
  module InlineElement
32
49
  class InlineNode < InlineParser::Node; end
33
50
  class InlineLeaf < InlineParser::Leaf; end
@@ -41,26 +58,20 @@ module PseudoHiki
41
58
  end
42
59
  include InlineElement
43
60
 
44
- HEAD = {}
45
- TAIL = {}
46
- NodeTypeToHead = {}
47
- TokenPat = {}
48
-
49
- [[LinkNode, "[[", "]]"],
50
- [EmNode, "''", "''"],
51
- [StrongNode, "'''", "'''"],
52
- [DelNode, "==", "=="],
53
- [LiteralNode, "``", "``"],
54
- [PluginNode, "{{", "}}"]].each do |type, head, tail|
55
- HEAD[head] = type
56
- TAIL[tail] = type
57
- NodeTypeToHead[type] = head
58
- end
61
+ @node_tag_table = [
62
+ [LinkNode, "[[", "]]"],
63
+ [EmNode, "''", "''"],
64
+ [StrongNode, "'''", "'''"],
65
+ [DelNode, "==", "=="],
66
+ [LiteralNode, "``", "``"],
67
+ [PluginNode, "{{", "}}"]]
68
+
69
+ HEAD, TAIL, NodeTypeToHead, _ = PseudoHiki.associate_nodes_with_tags(@node_tag_table)
59
70
 
60
- TokenPat[self] = PseudoHiki.compile_token_pat(HEAD.keys, TAIL.keys, [LinkSep, TableSep, DescSep])
71
+ @token_pat = PseudoHiki.compile_token_pat(HEAD.keys, TAIL.keys, [LinkSep, TableSep, DescSep])
61
72
 
62
73
  def initialize(str)
63
- @tokens = PseudoHiki.split_into_tokens(str, TokenPat[self.class])
74
+ @tokens = PseudoHiki.split_into_tokens(str, self.class.token_pat)
64
75
  super()
65
76
  end
66
77
 
@@ -113,7 +124,7 @@ module PseudoHiki
113
124
  include InlineElement
114
125
 
115
126
  TAIL[TableSep] = TableCellNode
116
- TokenPat[self] = InlineParser::TokenPat[InlineParser]
127
+ @token_pat = InlineParser.token_pat
117
128
 
118
129
  class InlineElement::TableCellNode
119
130
  def parse_cellspan(token_str)
@@ -36,7 +36,7 @@ module PseudoHiki
36
36
 
37
37
  def self.convert_into_gfm_id_format(heading)
38
38
  heading.gsub(GFM_STRIPPED_CHARS_PAT) do |char|
39
- /\A\s+\Z/o =~ char ? '-'.freeze : ''.freeze
39
+ /\A\s+\Z/o.match?(char) ? '-'.freeze : ''.freeze
40
40
  end.downcase
41
41
  end
42
42
 
@@ -53,21 +53,23 @@ module PseudoHiki
53
53
  HtmlElement::Children.new
54
54
  end
55
55
 
56
- def visited_result(node)
56
+ def visited_result(node, memo)
57
57
  visitor = @formatter[node.class] || @formatter[PlainNode]
58
- node.accept(visitor)
58
+ node.accept(visitor, memo)
59
59
  end
60
60
 
61
- def push_visited_results(element, tree)
62
- tree.each {|token| element.push visited_result(token) }
61
+ def push_visited_results(element, tree, memo)
62
+ tree.each {|token| element.push visited_result(token, memo) }
63
63
  end
64
64
 
65
- def visit(tree)
65
+ def visit(tree, memo)
66
66
  element = create_self_element(tree)
67
- push_visited_results(element, tree)
68
- element
67
+ push_visited_results(element, tree, memo)
68
+ element.tap {|elm| tap_element_in_visit(elm, tree, memo) }
69
69
  end
70
70
 
71
+ def tap_element_in_visit(elm, tree, memo); end
72
+
71
73
  def get_plain
72
74
  @formatter[PlainNode]
73
75
  end
@@ -80,7 +82,7 @@ module PseudoHiki
80
82
 
81
83
  def list_mark(tree, mark)
82
84
  mark = mark.dup
83
- mark << " " if /^ /o !~ tree.join
85
+ mark << " " unless /^ /o.match? tree.join
84
86
  " " * (tree.level - 1) * 2 + mark
85
87
  end
86
88
 
@@ -151,7 +153,7 @@ module PseudoHiki
151
153
  ## Definitions of subclasses of MarkDownFormat begins here.
152
154
 
153
155
  class InlineLeafFormatter < self
154
- def visit(leaf)
156
+ def visit(leaf, memo)
155
157
  leaf.map do |str|
156
158
  escaped_str = str.gsub(/([_*])/o, "\\\\\\1")
157
159
  if @options.gfm_style
@@ -166,12 +168,12 @@ module PseudoHiki
166
168
  class LinkNodeFormatter < self
167
169
  attr_writer :id_conv_table
168
170
 
169
- def visit(tree)
171
+ def visit(tree, memo)
170
172
  not_from_thumbnail = tree.first.class != LinkNode
171
173
  tree = tree.dup
172
174
  element = create_self_element
173
- caption = get_caption(tree)
174
- if IMAGE_SUFFIX_RE =~ ref_tail(tree, caption) and not_from_thumbnail
175
+ caption = get_caption(tree, memo)
176
+ if IMAGE_SUFFIX_RE.match? ref_tail(tree, caption) and not_from_thumbnail
175
177
  element.push "!"
176
178
  end
177
179
  link = format_link(tree)
@@ -179,18 +181,18 @@ module PseudoHiki
179
181
  element
180
182
  end
181
183
 
182
- def get_caption(tree)
184
+ def get_caption(tree, memo)
183
185
  link_sep_index = tree.find_index([LinkSep])
184
186
  return nil unless link_sep_index
185
187
  caption_part = tree.shift(link_sep_index)
186
188
  tree.shift
187
- caption_part.map {|element| visited_result(element) }
189
+ caption_part.map {|element| visited_result(element, memo) }
188
190
  end
189
191
 
190
192
  def format_link(tree)
191
193
  link = tree.join
192
194
  return link unless @id_conv_table
193
- if /\A#/o =~ link and gfm_link = @id_conv_table[link[1..-1]]
195
+ if /\A#/o.match? link and gfm_link = @id_conv_table[link[1..-1]]
194
196
  "#".concat gfm_link
195
197
  else
196
198
  link
@@ -206,65 +208,63 @@ module PseudoHiki
206
208
  end
207
209
 
208
210
  class EmNodeFormatter < self
209
- def visit(tree)
210
- super(tree).tap do |element|
211
- enclose_in(element, "_")
212
- end
211
+ def tap_element_in_visit(element, tree, memo)
212
+ enclose_in(element, "_")
213
213
  end
214
214
  end
215
215
 
216
216
  class StrongNodeFormatter < self
217
- def visit(tree)
218
- super(tree).tap do |element|
217
+ def visit(tree, memo)
218
+ super(tree, memo).tap do |element|
219
219
  enclose_in(element, "**")
220
220
  end
221
221
  end
222
222
  end
223
223
 
224
224
  class DelNodeFormatter < self
225
- def visit(tree)
226
- "~~#{super(tree).join.strip}~~"
225
+ def visit(tree, memo)
226
+ "~~#{super(tree, memo).join.strip}~~"
227
227
  end
228
228
  end
229
229
 
230
230
  class LiteralNodeFormatter < self
231
- def visit(tree)
232
- "`#{super(tree).join.strip}`"
231
+ def visit(tree, memo)
232
+ "`#{super(tree, memo).join.strip}`"
233
233
  end
234
234
  end
235
235
 
236
236
  class PluginNodeFormatter < self
237
- def visit(tree)
237
+ def visit(tree, memo)
238
238
  str = tree.join
239
239
  return str.strip * 2 if str == " {" or str == "} "
240
- super(tree)
240
+ super(tree, memo)
241
241
  end
242
242
  end
243
243
 
244
244
  class VerbatimLeafFormatter < InlineLeafFormatter
245
- def visit(leaf)
245
+ def visit(leaf, memo)
246
246
  leaf.join
247
247
  end
248
248
  end
249
249
 
250
250
  class CommentOutLeafFormatter < self
251
- def visit(tree); ""; end
251
+ def visit(tree, memo); ""; end
252
252
  end
253
253
 
254
254
  class HeadingLeafFormatter < self
255
- def visit(tree)
256
- super(tree).tap {|element| element.push $/ }
255
+ def tap_element_in_visit(element, tree, memo)
256
+ element.push $/
257
257
  end
258
258
  end
259
259
 
260
260
  class HrLeafFormatter < self
261
- def visit(tree)
261
+ def visit(tree, memo)
262
262
  "----#{$/}"
263
263
  end
264
264
  end
265
265
 
266
266
  class DescNodeFormatter < self
267
- def visit(tree)
267
+ def visit(tree, memo)
268
268
  desc_list = HtmlElement.create("dl").tap do |element|
269
269
  element.push HtmlFormat.format(tree)
270
270
  end
@@ -273,15 +273,16 @@ module PseudoHiki
273
273
  end
274
274
 
275
275
  class VerbatimNodeFormatter < self
276
- def visit(tree)
277
- element = super(tree)
276
+ def visit(tree, memo)
277
+ element = super(tree, memo)
278
+ @language_name = language_name(tree)
278
279
  return gfm_verbatim(element) if @options.gfm_style
279
280
  md_verbatim(element)
280
281
  end
281
282
 
282
283
  def gfm_verbatim(element)
283
284
  element.tap do |lines|
284
- lines.unshift "```#{$/}"
285
+ lines.unshift "```#{@language_name + $/}"
285
286
  lines.push "```#{$/ * 2}"
286
287
  end
287
288
  end
@@ -289,11 +290,17 @@ module PseudoHiki
289
290
  def md_verbatim(element)
290
291
  element.join.gsub(/^/o, " ").sub(/ \Z/o, "").concat $/
291
292
  end
293
+
294
+ def language_name(tree)
295
+ tree.decorator.tap do |decorator|
296
+ return decorator ? decorator["code"].id : ""
297
+ end
298
+ end
292
299
  end
293
300
 
294
301
  class QuoteNodeFormatter < self
295
- def visit(tree)
296
- element = super(tree)
302
+ def visit(tree, memo)
303
+ element = super(tree, memo)
297
304
  element.join.gsub(/^/o, "> ").sub(/> \Z/o, "")
298
305
  end
299
306
  end
@@ -301,9 +308,9 @@ module PseudoHiki
301
308
  class TableNodeFormatter < PlainTextFormat::TableNodeFormatter
302
309
  class NotConformantStyleError < StandardError; end
303
310
 
304
- def visit(tree)
311
+ def visit(tree, memo)
305
312
  @options.gfm_conformant = check_conformance_with_gfm_style(tree)
306
- super(tree)
313
+ super(tree, memo)
307
314
  end
308
315
 
309
316
  def choose_expander_of_col_and_row
@@ -376,50 +383,50 @@ ERROR
376
383
  end
377
384
 
378
385
  class HeadingNodeFormatter < self
379
- def visit(tree)
380
- super(tree).tap do |element|
381
- heading_mark = "#" * tree.first.level
382
- heading_mark << " " if /^ /o !~ tree.join
383
- element.unshift heading_mark
384
- end
386
+ def tap_element_in_visit(element, tree, memo)
387
+ heading_mark = "#" * tree.first.level
388
+ heading_mark << " " unless /^ /o.match? tree.join
389
+ element.unshift heading_mark
385
390
  end
386
391
  end
387
392
 
388
393
  class ParagraphNodeFormatter < self
389
- def visit(tree)
390
- super(tree).tap {|element| element.push $/ }
394
+ def tap_element_in_visit(element, tree, memo)
395
+ element.push $/
391
396
  end
392
397
  end
393
398
 
394
399
  class ListNodeFormatter < self
395
- def visit(tree)
396
- super(tree).tap do |element|
397
- element.push $/ if /\A\*/o =~ element.first.join
398
- end
400
+ def tap_element_in_visit(element, tree, memo)
401
+ element.push $/ if /\A\*/o.match? element.first.join
399
402
  end
400
403
  end
401
404
 
402
405
  class EnumNodeFormatter < self
403
- def visit(tree)
404
- super(tree).tap do |element|
405
- element.push $/ if /\A\d/o =~ element.first.join
406
+ def push_visited_results(element, tree, memo)
407
+ memo_with_enum_count = { :original => memo, :enum_item_count => 0 }
408
+ tree.each do |token|
409
+ if token.kind_of? EnumWrapNode
410
+ memo_with_enum_count[:enum_item_count] += 1
411
+ end
412
+ element.push visited_result(token, memo_with_enum_count)
406
413
  end
407
414
  end
415
+
416
+ def tap_element_in_visit(element, tree, memo)
417
+ element.push $/ if /\A\d/o.match? element.first.join
418
+ end
408
419
  end
409
420
 
410
421
  class ListWrapNodeFormatter < self
411
- def visit(tree)
412
- super(tree).tap do |element|
413
- element.unshift list_mark(tree, "*")
414
- end
422
+ def tap_element_in_visit(element, tree, memo)
423
+ element.unshift list_mark(tree, "*")
415
424
  end
416
425
  end
417
426
 
418
427
  class EnumWrapNodeFormatter < self
419
- def visit(tree)
420
- super(tree).tap do |element|
421
- element.unshift list_mark(tree, "#{tree.level}.")
422
- end
428
+ def tap_element_in_visit(element, tree, item_num)
429
+ element.unshift list_mark(tree, "#{item_num[:enum_item_count]}.")
423
430
  end
424
431
  end
425
432
  end
@@ -40,18 +40,18 @@ module PseudoHiki
40
40
  Node.new
41
41
  end
42
42
 
43
- def visited_result(node)
43
+ def visited_result(node, memo)
44
44
  visitor = @formatter[node.class] || @formatter[PlainNode]
45
- node.accept(visitor)
45
+ node.accept(visitor, memo)
46
46
  end
47
47
 
48
- def push_visited_results(element, tree)
49
- tree.each {|token| element.push visited_result(token) }
48
+ def push_visited_results(element, tree, memo)
49
+ tree.each {|token| element.push visited_result(token, memo) }
50
50
  end
51
51
 
52
- def visit(tree)
52
+ def visit(tree, memo)
53
53
  element = create_self_element(tree)
54
- push_visited_results(element, tree)
54
+ push_visited_results(element, tree, memo)
55
55
  element
56
56
  end
57
57
 
@@ -99,16 +99,16 @@ module PseudoHiki
99
99
  ## Definitions of subclasses of PlainTextFormat begins here.
100
100
 
101
101
  class InlineLeafFormatter < self
102
- def visit(leaf)
102
+ def visit(leaf, memo)
103
103
  leaf.join
104
104
  end
105
105
  end
106
106
 
107
107
  class LinkNodeFormatter < self
108
- def visit(tree)
108
+ def visit(tree, memo)
109
109
  element = Node.new
110
- caption, ref = get_caption(tree)
111
- if IMAGE_SUFFIX_RE =~ ref_tail(ref, caption)
110
+ caption, ref = get_caption(tree, memo)
111
+ if IMAGE_SUFFIX_RE.match? ref_tail(ref, caption)
112
112
  element.push (caption || ref).join
113
113
  else
114
114
  element.push caption || ref.join
@@ -117,9 +117,9 @@ module PseudoHiki
117
117
  element
118
118
  end
119
119
 
120
- def get_caption(tree)
120
+ def get_caption(tree, memo)
121
121
  caption, ref_part = split_into_parts(tree, [LinkSep])
122
- caption = caption.map {|element| visited_result(element) } if caption
122
+ caption = caption.map {|element| visited_result(element, memo) } if caption
123
123
  return caption, ref_part
124
124
  end
125
125
 
@@ -132,18 +132,18 @@ module PseudoHiki
132
132
  end
133
133
 
134
134
  class DelNodeFormatter < self
135
- def visit(tree)
135
+ def visit(tree, memo)
136
136
  return "" unless @options.verbose_mode
137
- "[deleted:#{tree.map {|token| visited_result(token) }.join}]"
137
+ "[deleted:#{tree.map {|token| visited_result(token, memo) }.join}]"
138
138
  end
139
139
  end
140
140
 
141
141
  class DescLeafFormatter < self
142
- def visit(tree)
142
+ def visit(tree, memo)
143
143
  element = create_self_element(tree)
144
144
  dt_part, dd_part = split_into_parts(tree, DescSep)
145
- push_visited_results(element, dt_part) if dt_part
146
- dd = dd_part.map {|token| visited_result(token) }.join.lstrip
145
+ push_visited_results(element, dt_part, memo) if dt_part
146
+ dd = dd_part.map {|token| visited_result(token, memo) }.join.lstrip
147
147
  unless dd.empty?
148
148
  element.push element.empty? ? "\t" : ":\t"
149
149
  element.push dd
@@ -153,7 +153,7 @@ module PseudoHiki
153
153
  end
154
154
 
155
155
  class VerbatimNodeFormatter < self
156
- def visit(tree)
156
+ def visit(tree, memo)
157
157
  tree.join
158
158
  end
159
159
  end
@@ -165,14 +165,14 @@ module PseudoHiki
165
165
  !! Please recheck if it is really what you want.
166
166
  ERROR_TEXT
167
167
 
168
- def visit(tree)
168
+ def visit(tree, memo)
169
169
  table = create_self_element(tree)
170
170
  tree.length.times { table.push create_self_element(tree) }
171
171
  max_col = tree.map {|row| row.reduce(0) {|sum, cell| sum + cell.colspan }}.max - 1
172
172
  max_row = tree.length - 1
173
173
  each_empty_cell_index(max_row, max_col, tree, table) do |r, c, cur_row|
174
174
  cur_cell = cur_row.shift
175
- table[r][c] = visited_result(cur_cell).join.lstrip.chomp
175
+ table[r][c] = visited_result(cur_cell, memo).join.lstrip.chomp
176
176
  fill_expand(table, r, c, cur_cell)
177
177
  end
178
178
  format_table(table, tree)
@@ -234,20 +234,20 @@ ERROR_TEXT
234
234
  end
235
235
 
236
236
  class CommentOutNodeFormatter < self
237
- def visit(tree); ""; end
237
+ def visit(tree, memo); ""; end
238
238
  end
239
239
 
240
240
  class ParagraphNodeFormatter < self
241
- def visit(tree)
242
- super(tree).join + $/
241
+ def visit(tree, memo)
242
+ super(tree, memo).join + $/
243
243
  end
244
244
  end
245
245
 
246
246
  class PluginNodeFormatter < self
247
- def visit(tree)
247
+ def visit(tree, memo)
248
248
  str = tree.join
249
249
  return str.strip * 2 if str == " {" or str == "} "
250
- super(tree)
250
+ super(tree, memo)
251
251
  end
252
252
  end
253
253
  end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ unless //.respond_to? :match?
4
+ class Regexp
5
+ def match?(str)
6
+ self === str
7
+ end
8
+ end
9
+ end
10
+
11
+ unless String.new.respond_to? :encode
12
+ require 'iconv'
13
+
14
+ class String
15
+ def choose_input_encoding_using_kcode
16
+ PseudoHiki::OptionManager::ENCODING_REGEXP.each do |pat, encoding|
17
+ return PseudoHiki::OptionManager::ENCODING_TO_CHARSET[encoding] if pat.match? $KCODE
18
+ end
19
+ HtmlElement::CHARSET::UTF8
20
+ end
21
+ private :choose_input_encoding_using_kcode
22
+
23
+ def encode(to, from=choose_input_encoding_using_kcode)
24
+ iconv = Iconv.new(to, from)
25
+ str = iconv.iconv(self)
26
+ str << iconv.iconv(nil)
27
+ end
28
+ public :encode
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ module Sinatra
5
+ module PseudoHikiParserHelpers
6
+ XHTML5_CONTENT_TYPE = 'application/xhtml+xml'
7
+ def phiki(hiki_data, &block)
8
+ case content_type
9
+ when XHTML5_CONTENT_TYPE
10
+ PseudoHiki::Format.to_html5(hiki_data, &block)
11
+ else
12
+ PseudoHiki::Format.to_xhtml(hiki_data, &block)
13
+ end
14
+ end
15
+ end
16
+
17
+ class Base
18
+ helpers PseudoHikiParserHelpers
19
+ end
20
+ end
21
+ rescue
22
+ #Sinatra is not available
23
+ end
@@ -11,8 +11,8 @@ class TreeStack
11
11
  module TreeElement
12
12
  attr_accessor :depth
13
13
 
14
- def accept(visitor)
15
- visitor.visit(self)
14
+ def accept(visitor, memo=nil)
15
+ visitor.visit(self, memo)
16
16
  end
17
17
  end
18
18
 
@@ -107,7 +107,7 @@ class TreeStack
107
107
  removed_node
108
108
  end
109
109
 
110
- def accept(visitor)
111
- visitor.visit(tree)
110
+ def accept(visitor, memo=nil)
111
+ visitor.visit(tree, memo)
112
112
  end
113
113
  end
@@ -19,12 +19,12 @@ module PseudoHiki
19
19
  @condition = condition
20
20
  end
21
21
 
22
- def visit(tree)
22
+ def visit(tree, memo=nil)
23
23
  if @condition.call(tree)
24
24
  @nodes.push tree
25
25
  else
26
26
  tree.each do |node|
27
- node.accept(self) if node.respond_to? :accept
27
+ node.accept(self, memo) if node.respond_to? :accept
28
28
  end
29
29
  end
30
30
  end
@@ -1,3 +1,3 @@
1
1
  module PseudoHiki
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6.develop"
3
3
  end
@@ -150,3 +150,5 @@ module PseudoHiki
150
150
  end
151
151
  end
152
152
  end
153
+
154
+ require 'pseudohiki/sinatra_helpers' if defined? Sinatra