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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5ebc8c1ea077d8299c8d99b805fbed3ddc4f45e4
4
- data.tar.gz: 02fc8e556784f1bbbe63c6e2a0bcf369c4b0ec04
3
+ metadata.gz: 98aa9c74058bd6a6da9f43b9f2c7d73872db41c9
4
+ data.tar.gz: d921304c72c05629e616d47899b28e09c7fc91ab
5
5
  SHA512:
6
- metadata.gz: c48347a4e2cd673bbc426c0623255d8a64088d393730a5bdbba4962ca626b5ab8dad09bdb48abc64fd0fd307551d69dac7ae99a053ac7d230406ff9dc94ccc94
7
- data.tar.gz: ca8187e15865fd7bd5e9d5def177dcf11f4ce843af06412f79e14b44cfdc649eece0487c7ab3f6397057afa1a2c45165b91153198697b79fceb9c4128f791c63
6
+ metadata.gz: 4f1a030cee17f773f7f9489270874d462c4d1da7c6fa57b86830910a13018e5ee0757155d97e8e07de503cd2f22237bd515151de3583d187ac62aaf703120d37
7
+ data.tar.gz: 793b3d2c14b5b36fc6ee964c838f9f630a017c3a78cc7e35ab2457fed631c405487ecf0c489da88fd2a5f3342ebb9425831eebd8bb28293682bfdf2834df8481
data/bin/pseudohiki2html CHANGED
@@ -7,29 +7,10 @@ options.parse_command_line_options
7
7
 
8
8
  if $KCODE
9
9
  PseudoHiki::OptionManager::ENCODING_REGEXP.each do |pat, encoding|
10
- options[:encoding] = encoding if pat =~ $KCODE and not options[:force]
10
+ options[:encoding] = encoding if pat.match? $KCODE and not options[:force]
11
11
  end
12
12
  end
13
13
 
14
- unless String.new.respond_to? :encode
15
- require 'iconv'
16
-
17
- def choose_input_encoding_using_kcode
18
- PseudoHiki::OptionManager::ENCODING_REGEXP.each do |pat, encoding|
19
- return PseudoHiki::OptionManager::ENCODING_TO_CHARSET[encoding] if pat =~ $KCODE
20
- end
21
- HtmlElement::CHARSET::UTF8
22
- end
23
- private :choose_input_encoding_using_kcode
24
-
25
- def encode(to, from=choose_input_encoding_using_kcode)
26
- iconv = Iconv.new(to, from)
27
- str = iconv.iconv(self)
28
- str << iconv.iconv(nil)
29
- end
30
- public :encode
31
- end
32
-
33
14
  PseudoHiki::OptionManager.remove_bom
34
15
  input_lines = ARGF.readlines.map {|line| line.encode(options.charset) }
35
16
  options.set_options_from_input_file(input_lines)
@@ -23,6 +23,11 @@ class HtmlTemplate
23
23
  @title = nil
24
24
  @title_element = create_element("title")
25
25
  @body = create_element("body")
26
+ @default_skip_link_labels = {
27
+ "en" => "Skip to Content",
28
+ "ja" => "\u{672c}\u{6587}\u{3078}", # honbun he
29
+ "fr" => "Aller au contenu"
30
+ }
26
31
  @html.push @head
27
32
  @html.push @body
28
33
  [ @content_language,
@@ -36,7 +41,7 @@ class HtmlTemplate
36
41
  @head.push element
37
42
  end
38
43
  end
39
- attr_reader :title, :head
44
+ attr_reader :title, :head, :body
40
45
 
41
46
  def create_element(*params)
42
47
  ELEMENT[self.class].create(*params)
@@ -70,6 +75,12 @@ class HtmlTemplate
70
75
  @default_css_link["href"] = file_path
71
76
  end
72
77
 
78
+ def embed_style(css)
79
+ style = create_element("style", nil, "type" => "text/css")
80
+ @head.push style
81
+ style.push format_css(css)
82
+ end
83
+
73
84
  def title=(title)
74
85
  @title_element.pop until @title_element.empty?
75
86
  @title = title
@@ -103,6 +114,10 @@ class HtmlTemplate
103
114
  @html].join("")
104
115
  end
105
116
 
117
+ def add_skip_link(to="contents", from=@body,label=default_skip_link_label)
118
+ skip_link_container(from).unshift create_element("a", label, "href" => "##{to}")
119
+ end
120
+
106
121
  private
107
122
 
108
123
  def create_meta(type, content)
@@ -126,6 +141,23 @@ class HtmlTemplate
126
141
  return "" unless base_uri
127
142
  create_element("base", nil, "href" => base_uri)
128
143
  end
144
+
145
+ def format_css(css)
146
+ ["<!--", css.rstrip, "-->", ""].join($/)
147
+ end
148
+
149
+ def skip_link_container(from)
150
+ return from unless from == @body
151
+ create_element("div").tap do |div|
152
+ div["class"] = "skip-link"
153
+ @body.unshift div
154
+ end
155
+ end
156
+
157
+ def default_skip_link_label
158
+ @default_skip_link_labels[@html["lang"]] ||
159
+ @default_skip_link_labels["en"]
160
+ end
129
161
  end
130
162
 
131
163
  class XhtmlTemplate < HtmlTemplate
@@ -141,6 +173,12 @@ class XhtmlTemplate < HtmlTemplate
141
173
  super(language)
142
174
  @html["xml:lang"] = language
143
175
  end
176
+
177
+ private
178
+
179
+ def format_css(css)
180
+ css.rstrip + $/
181
+ end
144
182
  end
145
183
 
146
184
  class Xhtml5Template < XhtmlTemplate
data/lib/htmlelement.rb CHANGED
@@ -123,7 +123,21 @@ class HtmlElement
123
123
  end
124
124
 
125
125
  def pop
126
- @children.pop
126
+ last_child = @children.pop
127
+ last_child.parent = nil if last_child.kind_of? HtmlElement
128
+ last_child
129
+ end
130
+
131
+ def unshift(child)
132
+ @children.unshift child
133
+ child.parent = self if child.kind_of? HtmlElement
134
+ self
135
+ end
136
+
137
+ def shift
138
+ first_child = @children.shift
139
+ first_child.parent = nil if first_child.kind_of? HtmlElement
140
+ first_child
127
141
  end
128
142
 
129
143
  def []=(attribute, value)
@@ -47,7 +47,7 @@ module PseudoHiki
47
47
  end
48
48
 
49
49
  def link_wiki_name(line)
50
- return line if WIKI_NAME_RE !~ line or VERBATIM_LEAF_HEAD_RE =~ line
50
+ return line if not WIKI_NAME_RE.match? line or VERBATIM_LEAF_HEAD_RE.match? line
51
51
  line.gsub(WIKI_NAME_RE) {|url| in_link_tag?($`) ? url : add_tag(url) }
52
52
  end
53
53
 
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'pseudohiki/shim'
3
4
  require 'pseudohiki/treestack'
4
5
  require 'pseudohiki/inlineparser'
5
6
 
@@ -38,14 +39,21 @@ module PseudoHiki
38
39
  end
39
40
 
40
41
  class BlockStack < TreeStack
41
- def pop
42
- current_node.parse_leafs
43
- super
42
+ attr_reader :stack
43
+
44
+ def pop_with_breaker(breaker=nil)
45
+ current_node.parse_leafs(breaker)
46
+ pop
47
+ end
48
+
49
+ def current_heading_level
50
+ i = @stack.rindex {|node| node.kind_of? BlockElement::HeadingNode }
51
+ @stack[i].level || 0
44
52
  end
45
53
  end
46
54
 
47
55
  class BlockLeaf < BlockStack::Leaf
48
- attr_accessor :level, :node_id
56
+ attr_accessor :level, :node_id, :decorator
49
57
 
50
58
  class << self
51
59
  attr_accessor :head_re
@@ -81,7 +89,7 @@ module PseudoHiki
81
89
  super(stack)
82
90
  end
83
91
 
84
- def parse_leafs
92
+ def parse_leafs(breaker)
85
93
  parsed = InlineParser.parse(join)
86
94
  clear
87
95
  concat(parsed)
@@ -131,6 +139,10 @@ module PseudoHiki
131
139
  first.level if first # @cached_level ||= (first.level if first)
132
140
  end
133
141
 
142
+ def decorator
143
+ first.decorator if first
144
+ end
145
+
134
146
  def push_self(stack)
135
147
  @stack = stack
136
148
  super(stack)
@@ -140,24 +152,24 @@ module PseudoHiki
140
152
  not (kind_of? breaker.block and level == breaker.level)
141
153
  end
142
154
 
143
- def parse_leafs; end
155
+ def parse_leafs(breaker); end
144
156
 
145
157
  def add_leaf(line, blockparser)
146
158
  leaf = create_leaf(line, blockparser)
147
- blockparser.stack.pop while blockparser.breakable?(leaf)
159
+ blockparser.stack.pop_with_breaker(leaf) while blockparser.breakable?(leaf)
148
160
  blockparser.stack.push leaf
149
161
  end
150
162
 
151
163
  def create_leaf(line, blockparser)
152
- return BlockElement::VerbatimLeaf.create("".freeze, true) if VERBATIM_BEGIN =~ line
164
+ return BlockElement::VerbatimLeaf.create("".freeze, true) if VERBATIM_BEGIN.match? line
153
165
  line = blockparser.auto_linker.link(line)
154
166
  blockparser.select_leaf_type(line).create(line)
155
167
  end
156
168
  end
157
169
 
158
170
  class NonNestedBlockNode < BlockNode
159
- def parse_leafs
160
- each {|leaf| leaf.parse_leafs }
171
+ def parse_leafs(breaker)
172
+ each {|leaf| leaf.parse_leafs(breaker) }
161
173
  end
162
174
  end
163
175
 
@@ -175,13 +187,15 @@ module PseudoHiki
175
187
  end
176
188
  end
177
189
 
190
+ class UnmatchedSectioningTagError < StandardError; end
191
+
178
192
  module BlockElement
179
193
  {
180
- BlockLeaf => %w(DescLeaf VerbatimLeaf TableLeaf CommentOutLeaf BlockNodeEnd HrLeaf),
194
+ BlockLeaf => %w(DescLeaf VerbatimLeaf TableLeaf CommentOutLeaf BlockNodeEnd HrLeaf DecoratorLeaf SectioningNodeEnd),
181
195
  NonNestedBlockLeaf => %w(QuoteLeaf ParagraphLeaf),
182
196
  NestedBlockLeaf => %w(HeadingLeaf),
183
197
  ListTypeLeaf => %w(ListLeaf EnumLeaf),
184
- BlockNode => %w(DescNode VerbatimNode TableNode CommentOutNode HrNode),
198
+ BlockNode => %w(DescNode VerbatimNode TableNode CommentOutNode HrNode DecoratorNode SectioningNode),
185
199
  NonNestedBlockNode => %w(QuoteNode ParagraphNode),
186
200
  NestedBlockNode => %w(HeadingNode),
187
201
  ListTypeBlockNode => %w(ListNode EnumNode),
@@ -204,15 +218,100 @@ module PseudoHiki
204
218
  attr_accessor :in_block_tag
205
219
 
206
220
  def add_leaf(line, blockparser)
207
- return @stack.pop if VERBATIM_END =~ line
221
+ return @stack.pop_with_breaker if VERBATIM_END.match? line
208
222
  return super(line, blockparser) unless @in_block_tag
209
- line = " #{line}" if BlockNodeEnd.head_re =~ line and not @in_block_tag
223
+ line = " #{line}" if BlockNodeEnd.head_re.match? line and not @in_block_tag
210
224
  @stack.push VerbatimLeaf.create(line, @in_block_tag)
211
225
  end
212
226
  end
213
227
 
228
+ class DecoratorNode
229
+ DECORATOR_PAT = /\A(?:([^\[\]:]+))?(?:\[([^\[\]]+)\])?(?::\s*(\S.*))?/o
230
+ LABEL_SEP = [":"]
231
+
232
+ class DecoratorItem < Struct.new(:string, :type, :id, :value)
233
+ def self.create(leaf)
234
+ m = DECORATOR_PAT.match(leaf.join)
235
+ return nil unless m
236
+ args = m.to_a
237
+ if i = leaf.index(LABEL_SEP)
238
+ value = leaf.dup
239
+ value.shift(i + 1)
240
+ args[-1] = lstrip_value!(value)
241
+ end
242
+ self.new(*args)
243
+ end
244
+
245
+ def self.lstrip_value!(value)
246
+ head_val = value[0][0]
247
+ if head_val.kind_of? String and head_val.start_with? " ".freeze
248
+ value[0][0] = head_val.lstrip
249
+ end
250
+ value
251
+ end
252
+ end
253
+
254
+ def parse_leafs(breaker)
255
+ decorator = {}
256
+ breaker.decorator = decorator
257
+ @stack.remove_current_node.each do |leaf|
258
+ if item = DecoratorItem.create(leaf)
259
+ decorator[item.type || :id] = item
260
+ end
261
+ end
262
+ end
263
+
264
+ def breakable?(breaker)
265
+ return super if breaker.kind_of? DecoratorLeaf
266
+ parse_leafs(breaker)
267
+ @stack.current_node.breakable?(breaker)
268
+ end
269
+ end
270
+
271
+ class DecoratorLeaf
272
+ def push_sectioning_node(stack, node_class)
273
+ node = node_class.new
274
+ m = DecoratorNode::DECORATOR_PAT.match(join)
275
+ node.node_id = m[2]
276
+ node.section_level = stack.current_heading_level if node.kind_of? SectioningNode
277
+ stack.push(node)
278
+ end
279
+
280
+ def push_self(stack)
281
+ decorator_type = self[0][0]
282
+ if decorator_type.start_with? "begin[".freeze
283
+ push_sectioning_node(stack, SectioningNode)
284
+ elsif decorator_type.start_with? "end[".freeze
285
+ push_sectioning_node(stack, SectioningNodeEnd)
286
+ else
287
+ super
288
+ end
289
+ end
290
+ end
291
+
292
+ class SectioningNode
293
+ attr_accessor :section_level
294
+
295
+ def breakable?(breaker)
296
+ breaker.kind_of? HeadingLeaf and @section_level >= breaker.level
297
+ end
298
+ end
299
+
300
+ class SectioningNodeEnd
301
+ def push_self(stack)
302
+ n = stack.stack.rindex do |node|
303
+ node.kind_of? SectioningNode and node.node_id == node_id
304
+ end
305
+ raise UnmatchedSectioningTagError unless n
306
+ stack.pop until stack.stack.length == n
307
+ rescue UnmatchedSectioningTagError => e
308
+ STDERR.puts "#{e}: The start tag for '#{node_id}' is not found."
309
+ # FIXME: The handling of this error should be changed appropriately.
310
+ end
311
+ end
312
+
214
313
  class QuoteNode
215
- def parse_leafs
314
+ def parse_leafs(breaker)
216
315
  self[0] = BlockParser.parse(self[0], AutoLink::Off)
217
316
  end
218
317
  end
@@ -273,7 +372,8 @@ module PseudoHiki
273
372
  [HrLeaf, HrNode],
274
373
  [ListLeaf, ListNode],
275
374
  [EnumLeaf, EnumNode],
276
- [BlockNodeEnd, BlockNodeEnd] # special case
375
+ [BlockNodeEnd, BlockNodeEnd], # special case
376
+ [DecoratorLeaf, DecoratorNode]
277
377
  ].each do |leaf, node|
278
378
  PARENT_NODE[leaf] = node
279
379
  end
@@ -286,6 +386,7 @@ module PseudoHiki
286
386
  ['!', HeadingLeaf],
287
387
  ['""', QuoteLeaf],
288
388
  ['||', TableLeaf],
389
+ ['//@', DecoratorLeaf],
289
390
  ['//', CommentOutLeaf],
290
391
  ['----\s*$', HrLeaf]]
291
392
 
@@ -331,7 +432,7 @@ module PseudoHiki
331
432
  def read_lines(lines)
332
433
  each_line = lines.respond_to?(:each_line) ? :each_line : :each
333
434
  lines.send(each_line) {|line| @stack.current_node.add_leaf(line, self) }
334
- @stack.pop
435
+ @stack.pop_with_breaker
335
436
  end
336
437
  end
337
438
 
@@ -356,7 +457,7 @@ module PseudoHiki
356
457
  end
357
458
 
358
459
  def self.link(line)
359
- return line unless URI_RE =~ line and VERBATIM_LEAF_HEAD_RE !~ line
460
+ return line unless URI_RE.match? line and not VERBATIM_LEAF_HEAD_RE.match? line
360
461
  line.gsub(URI_RE) {|url| in_link_tag?($`) ? url : "[[#{url}]]" }
361
462
  end
362
463
 
@@ -29,8 +29,6 @@ module PseudoHiki
29
29
  @options.formatter.format(tree)
30
30
  end
31
31
 
32
- def create_style(path_to_css_file); "".freeze; end
33
-
34
32
  private
35
33
 
36
34
  def toc_item_pat?(node)
@@ -87,15 +85,6 @@ module PseudoHiki
87
85
  end
88
86
  end
89
87
 
90
- def create_style(path_to_css_file)
91
- style = formatter.create_element("style").tap do |element|
92
- element["type"] = "text/css"
93
- open(File.expand_path(path_to_css_file)) do |css_file|
94
- element.push css_file.read
95
- end
96
- end
97
- end
98
-
99
88
  private
100
89
 
101
90
  def setup_link_manager(options)
@@ -200,7 +189,7 @@ module PseudoHiki
200
189
 
201
190
  def split_main_heading(input_lines)
202
191
  return "" unless @options[:split_main_heading]
203
- h1_pos = input_lines.find_index {|line| /^![^!]/o =~ line }
192
+ h1_pos = input_lines.find_index {|line| /^![^!]/o.match? line }
204
193
  return "" unless h1_pos
205
194
  tree = BlockParser.parse([input_lines.delete_at(h1_pos)])
206
195
  @options.formatter.format(tree)
@@ -223,8 +212,9 @@ module PseudoHiki
223
212
  else
224
213
  html = @options.create_html_template_with_current_options
225
214
  embed_css = @options[:embed_css]
226
- html.head.push @composer.create_style(embed_css) if embed_css
215
+ html.embed_style(File.read(File.expand_path(embed_css))) if embed_css
227
216
  html.push main || body
217
+ html.add_skip_link if html.kind_of?(HtmlTemplate) and main
228
218
  end
229
219
 
230
220
  html
@@ -313,7 +303,7 @@ module PseudoHiki
313
303
  end
314
304
 
315
305
  def win32?
316
- true if RUBY_PLATFORM =~ /win/i
306
+ true if RUBY_PLATFORM.match? /win/i
317
307
  end
318
308
 
319
309
  def value_given?(value)
@@ -334,9 +324,9 @@ module PseudoHiki
334
324
 
335
325
  def base
336
326
  base_dir = self[:base]
337
- if base_dir and base_dir !~ /[\/\\]\.*$/o
327
+ if base_dir and not /[\/\\]\.*$/o.match? base_dir
338
328
  base_dir = File.join(base_dir, ".")
339
- base_dir = "file:///" + base_dir if base_dir !~ /^\./o and win32?
329
+ base_dir = "file:///" + base_dir if not /^\./o.match? base_dir and win32?
340
330
  end
341
331
  base_dir
342
332
  end
@@ -354,7 +344,7 @@ module PseudoHiki
354
344
  if v.version == version
355
345
  return self[:html_version] = v
356
346
  else
357
- self[:html_version] = v if v.opt_pat =~ version
347
+ self[:html_version] = v if v.opt_pat.match? version
358
348
  end
359
349
  end
360
350
  STDERR.puts "\"#{version}\" is an invalid option for --format-version. \
@@ -366,7 +356,7 @@ module PseudoHiki
366
356
  self[:encoding] = given_opt
367
357
  else
368
358
  ENCODING_REGEXP.each do |pat, encoding|
369
- self[:encoding] = encoding if pat =~ given_opt
359
+ self[:encoding] = encoding if pat.match? given_opt
370
360
  end
371
361
  STDERR.puts "\"#{self[:encoding]}\" is chosen as an encoding system, \
372
362
  instead of \"#{given_opt}\"."
@@ -513,7 +503,7 @@ inside (default: not specified)") do |template|
513
503
 
514
504
  def set_options_from_input_file(input_lines)
515
505
  input_lines.each do |line|
516
- break if FILE_HEADER_PAT !~ line
506
+ break unless FILE_HEADER_PAT.match? line
517
507
  line = line.chomp
518
508
  @options.keys.each do |opt|
519
509
  next if self[opt] and self[:force]
@@ -50,12 +50,12 @@ module PseudoHiki
50
50
  { :auto_link_in_verbatim => @auto_link_in_verbatim }
51
51
  end
52
52
 
53
- def self.format(tree, options=nil)
53
+ def self.format(tree, options=nil, memo=nil)
54
54
  cur_auto_link_setting = @auto_link_in_verbatim
55
55
  options = default_options unless options
56
56
  @auto_link_in_verbatim = options[:auto_link_in_verbatim]
57
57
  formatter = get_plain
58
- tree.accept(formatter)
58
+ tree.accept(formatter, memo)
59
59
  ensure
60
60
  @auto_link_in_verbatim = cur_auto_link_setting
61
61
  end
@@ -67,18 +67,19 @@ module PseudoHiki
67
67
  @format_class = self.class
68
68
  end
69
69
 
70
- def visited_result(element)
70
+ def visited_result(element, memo)
71
71
  visitor = @formatter[element.class] || @formatter[PlainNode]
72
- element.accept(visitor)
72
+ element.accept(visitor, memo)
73
73
  end
74
74
 
75
- def push_visited_results(element, tree)
76
- tree.each {|token| element.push visited_result(token) }
75
+ def push_visited_results(element, tree, memo)
76
+ tree.each {|token| element.push visited_result(token, memo) }
77
77
  end
78
78
 
79
- def visit(tree)
79
+ def visit(tree, memo)
80
80
  htmlelement = create_element(tree)
81
- push_visited_results(htmlelement, tree)
81
+ decorate(htmlelement, tree)
82
+ push_visited_results(htmlelement, tree, memo)
82
83
  htmlelement
83
84
  end
84
85
 
@@ -96,6 +97,21 @@ module PseudoHiki
96
97
  chunks.push tree
97
98
  end
98
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
+
99
115
  class ListLeafNodeFormatter < self
100
116
  def create_element(tree)
101
117
  super(tree).tap do |elm|
@@ -121,6 +137,7 @@ module PseudoHiki
121
137
  [EnumNode, "ol"],
122
138
  [TableLeaf, "tr"],
123
139
  [VerbatimNode, "pre"],
140
+ [SectioningNode, "section"],
124
141
  [CommentOutNode, nil],
125
142
  [HeadingNode, "section"],
126
143
  [DescLeaf, DT],
@@ -137,8 +154,8 @@ module PseudoHiki
137
154
  # for InlineParser
138
155
 
139
156
  class << Formatter[PluginNode]
140
- def visit(tree)
141
- escape_inline_tags(tree) { super(tree) }
157
+ def visit(tree, memo)
158
+ escape_inline_tags(tree) { super(tree, memo) }
142
159
  end
143
160
 
144
161
  def escape_inline_tags(tree)
@@ -150,10 +167,10 @@ module PseudoHiki
150
167
  end
151
168
 
152
169
  class << Formatter[LinkNode]
153
- def visit(tree)
170
+ def visit(tree, memo)
154
171
  not_from_thumbnail = tree.first.class != LinkNode
155
- caption, ref = caption_and_ref(tree)
156
- if IMAGE_SUFFIX_RE =~ ref and not_from_thumbnail
172
+ caption, ref = caption_and_ref(tree, memo)
173
+ if IMAGE_SUFFIX_RE.match? ref and not_from_thumbnail
157
174
  htmlelement = ImgFormat.create_element
158
175
  htmlelement[SRC] = ref
159
176
  htmlelement[ALT] = caption.join if caption
@@ -165,9 +182,9 @@ module PseudoHiki
165
182
  htmlelement
166
183
  end
167
184
 
168
- def caption_and_ref(tree)
185
+ def caption_and_ref(tree, memo)
169
186
  caption, ref = split_into_parts(tree, LinkSep)
170
- caption = ref ? caption.map {|token| visited_result(token) } : nil
187
+ caption = ref ? caption.map {|token| visited_result(token, memo) } : nil
171
188
  return caption, (ref || tree).join
172
189
  rescue NoMethodError
173
190
  raise NoMethodError unless (ref || tree).empty?
@@ -176,7 +193,7 @@ module PseudoHiki
176
193
  end
177
194
 
178
195
  class << Formatter[InlineLeaf]
179
- def visit(leaf)
196
+ def visit(leaf, memo)
180
197
  @generator.escape(leaf.first)
181
198
  end
182
199
  end
@@ -189,8 +206,25 @@ module PseudoHiki
189
206
 
190
207
  # for BlockParser
191
208
 
209
+ class << Formatter[TableNode]
210
+ def decorate(htmlelement, tree, memo=nil)
211
+ each_decorator(htmlelement, tree) do |elm, decorator|
212
+ visited_value(decorator["summary"], memo) do |summary|
213
+ htmlelement["summary"] = HtmlElement.escape(summary.join.chomp)
214
+ end
215
+ visited_value(decorator["caption"], memo) do |caption|
216
+ htmlelement.push @generator.create("caption", caption)
217
+ end
218
+ end
219
+ end
220
+
221
+ def visited_value(decorator_item, memo)
222
+ yield visited_result(decorator_item.value, memo) if decorator_item
223
+ end
224
+ end
225
+
192
226
  class << Formatter[VerbatimNode]
193
- def visit(tree)
227
+ def visit(tree, memo)
194
228
  contents = add_link(@generator.escape(tree.join))
195
229
  create_element.tap {|elm| elm.push contents }
196
230
  end
@@ -203,8 +237,39 @@ module PseudoHiki
203
237
  end
204
238
  end
205
239
 
240
+ class << Formatter[SectioningNode]
241
+ ID_MARK = "#"
242
+
243
+ alias :orig_create_element :create_element
244
+
245
+ def section_with_id(tree, node_id)
246
+ orig_create_element(tree).tap do |elm|
247
+ elm[ID] = node_id[1..-1] # remove the first charactor from node_id
248
+ end
249
+ end
250
+
251
+ def section_for_class(tree, node_id)
252
+ if HtmlElement::HTML5_TAGS.include? node_id
253
+ @generator.create(node_id)
254
+ else
255
+ orig_create_element(tree).tap do |elm|
256
+ elm[CLASS] = elm[CLASS] ? "#{elm[CLASS]} #{node_id}" : node_id
257
+ end
258
+ end
259
+ end
260
+
261
+ def create_element(tree)
262
+ node_id = tree.node_id
263
+ if node_id.start_with? ID_MARK
264
+ section_with_id(tree, node_id)
265
+ else
266
+ section_for_class(tree, node_id)
267
+ end
268
+ end
269
+ end
270
+
206
271
  class << Formatter[CommentOutNode]
207
- def visit(tree); BLANK; end
272
+ def visit(tree, memo); BLANK; end
208
273
  end
209
274
 
210
275
  class << Formatter[HeadingNode]
@@ -218,14 +283,14 @@ module PseudoHiki
218
283
  end
219
284
 
220
285
  class << Formatter[DescLeaf]
221
- def visit(tree)
286
+ def visit(tree, memo)
222
287
  elm = @generator::Children.new
223
288
  dt_part, dd_part = split_into_parts(tree, DescSep)
224
- dt = super(dt_part)
289
+ dt = super(dt_part, memo)
225
290
  elm.push dt
226
291
  unless dd_part.nil? or dd_part.empty?
227
292
  dd = @generator.create(DD)
228
- push_visited_results(dd, dd_part)
293
+ push_visited_results(dd, dd_part, memo)
229
294
  elm.push dd
230
295
  end
231
296
  elm
@@ -233,9 +298,9 @@ module PseudoHiki
233
298
  end
234
299
 
235
300
  class << Formatter[TableCellNode]
236
- def visit(tree)
301
+ def visit(tree, memo)
237
302
  @element_name = tree.cell_type
238
- super(tree).tap do |elm|
303
+ super(tree, memo).tap do |elm|
239
304
  elm[ROWSPAN] = tree.rowspan if tree.rowspan > 1
240
305
  elm[COLSPAN] = tree.colspan if tree.colspan > 1
241
306
  # elm.push "&#160;" if elm.empty? # &#160; = &nbsp; this line would be necessary for HTML 4 or XHTML 1.0