pseudohikiparser 0.0.5 → 0.0.6.develop

Sign up to get free protection for your applications and to get access to all the features.
@@ -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