pseudohikiparser 0.0.4 → 0.0.5.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.
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'optparse'
5
5
  require 'erb'
6
+ require 'pseudohiki/version'
6
7
  require 'pseudohiki/blockparser'
7
8
  require 'pseudohiki/autolink'
8
9
  require 'pseudohiki/htmlformat'
@@ -11,6 +12,7 @@ require 'pseudohiki/markdownformat'
11
12
  require 'pseudohiki/utils'
12
13
  require 'htmlelement/htmltemplate'
13
14
  require 'htmlelement'
15
+ require 'htmlelement/utils'
14
16
 
15
17
  module PseudoHiki
16
18
  class PageComposer
@@ -18,142 +20,189 @@ module PseudoHiki
18
20
 
19
21
  PlainFormat = PlainTextFormat.create
20
22
 
21
- def initialize(options)
22
- @options = options
23
- @is_toc_item_pat = proc_for_is_toc_item_pat
24
- end
23
+ class BaseComposer
24
+ def initialize(options)
25
+ @options = options
26
+ end
27
+
28
+ def compose_body(tree)
29
+ @options.formatter.format(tree)
30
+ end
25
31
 
26
- def proc_for_is_toc_item_pat
27
- proc do |node|
32
+ def create_style(path_to_css_file); "".freeze; end
33
+
34
+ private
35
+
36
+ def toc_item_pat?(node)
28
37
  node.kind_of?(PseudoHiki::BlockParser::HeadingLeaf) and
29
38
  (2..3).include? node.level and
30
39
  node.node_id
31
40
  end
32
- end
33
41
 
34
- def formatter
35
- @formatter ||= @options.html_template.new
36
- end
42
+ def collect_nodes_for_table_of_contents(tree)
43
+ Utils::NodeCollector.select(tree) {|node| toc_item_pat?(node) }
44
+ end
37
45
 
38
- def to_plain(line)
39
- PlainFormat.format(line).to_s
46
+ def to_plain(line)
47
+ PlainFormat.format(line).to_s
48
+ end
40
49
  end
41
50
 
42
- def collect_nodes_for_table_of_contents(tree)
43
- Utils::NodeCollector.select(tree) {|node| @is_toc_item_pat.call(node) }
44
- end
51
+ class HtmlComposer < BaseComposer
52
+ TABLE = "table"
45
53
 
46
- def create_plain_table_of_contents(tree)
47
- toc_lines = collect_nodes_for_table_of_contents(tree).map do |toc_node|
48
- ('*' * toc_node.level) + to_plain(toc_node)
54
+ def initialize(options)
55
+ super(options)
56
+ @link_manager = setup_link_manager(options)
57
+ @relative_link = options[:relative_link]
49
58
  end
50
59
 
51
- @options.formatter.format(BlockParser.parse(toc_lines))
52
- end
60
+ def compose_body(tree)
61
+ super(tree).tap do |html|
62
+ if @relative_link and @link_manager
63
+ @link_manager.use_relative_path_for_in_domain_links(html)
64
+ end
53
65
 
54
- def create_html_table_of_contents(tree)
55
- @options.formatter.format(create_html_toc_tree(tree)).tap do |toc|
56
- toc.traverse do |element|
57
- if element.kind_of? HtmlElement and element.tagname == "a"
58
- element["title"] = "toc_item: " + element.children.join.chomp
66
+ assign_table_header_scope(html) if @options[:accessibility]
67
+ end
68
+ end
69
+
70
+ def create_table_of_contents(tree)
71
+ @options.formatter.format(create_toc_tree(tree)).tap do |toc|
72
+ toc.traverse do |element|
73
+ if element.kind_of? HtmlElement and element.tagname == "a"
74
+ element["title"] = "toc_item: " + element.children.join.chomp
75
+ end
59
76
  end
60
77
  end
61
78
  end
62
- end
63
79
 
64
- def create_html_toc_tree(tree, newline=nil)
65
- toc_lines = collect_nodes_for_table_of_contents(tree).map do |line|
66
- format("%s[[%s|#%s]]#{newline}",
67
- '*' * line.level,
68
- to_plain(line).lstrip,
69
- line.node_id.upcase)
80
+ def create_main(toc, body, h1)
81
+ return nil unless @options[:toc]
82
+ main = formatter.create_element("section").tap do |element|
83
+ element["id"] = "main"
84
+ element.push h1 unless h1.empty?
85
+ element.push create_toc_container(toc)
86
+ element.push create_contents_container(body)
87
+ end
70
88
  end
71
- BlockParser.parse(toc_lines)
72
- end
73
89
 
74
- def gfm_id(heading_node)
75
- MarkDownFormat.convert_into_gfm_id_format(to_plain(heading_node).strip)
76
- end
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
77
98
 
78
- def create_gfm_table_of_contents(tree)
79
- toc_lines = collect_nodes_for_table_of_contents(tree).map do |toc_node|
80
- format("%s[[%s|#%s]]#{$/}",
81
- '*' * toc_node.level,
82
- to_plain(toc_node).strip,
83
- gfm_id(toc_node))
99
+ private
100
+
101
+ def setup_link_manager(options)
102
+ if options[:domain_name]
103
+ domain_name = @options[:domain_name]
104
+ alternative_names = @options[:alternative_domain_names]
105
+ HtmlElement::Utils::LinkManager.new(domain_name, alternative_names)
106
+ end
84
107
  end
85
108
 
86
- @options.formatter.format(BlockParser.parse(toc_lines))
87
- end
109
+ def assign_table_header_scope(html)
110
+ HtmlElement::Utils.collect_elements_by_name(html, TABLE).each do |table|
111
+ HtmlElement::Utils::TableManager.assign_scope(table)
112
+ end
113
+ end
88
114
 
89
- def create_table_of_contents(tree)
90
- return "" unless @options[:toc]
91
- gfm_chosen = @options[:html_version].version == "gfm"
92
- return create_gfm_table_of_contents(tree) if gfm_chosen
93
- return create_plain_table_of_contents(tree) unless @options.html_template
94
- create_html_table_of_contents(tree)
95
- end
115
+ def formatter
116
+ @formatter ||= @options.html_template.new
117
+ end
96
118
 
97
- def split_main_heading(input_lines)
98
- return "" unless @options[:split_main_heading]
99
- h1_pos = input_lines.find_index {|line| /^![^!]/o =~ line }
100
- return "" unless h1_pos
101
- tree = BlockParser.parse([input_lines.delete_at(h1_pos)])
102
- @options.formatter.format(tree)
103
- end
119
+ def create_toc_tree(tree, newline=nil)
120
+ toc_lines = collect_nodes_for_table_of_contents(tree).map do |line|
121
+ format("%s[[%s|#%s]]#{newline}",
122
+ '*' * line.level,
123
+ to_plain(line).lstrip,
124
+ line.node_id.upcase)
125
+ end
126
+ BlockParser.parse(toc_lines)
127
+ end
128
+
129
+ def create_toc_container(toc)
130
+ formatter.create_element("section").tap do |elm|
131
+ elm["id"] = "toc"
132
+ title = @options[:toc]
133
+ elm.push formatter.create_element("h2", title) unless title.empty?
134
+ elm.push toc
135
+ end
136
+ end
104
137
 
105
- def create_plain_main(toc, body, h1)
106
- contents = [body]
107
- contents.unshift toc unless toc.empty?
108
- if title = @options[:toc]
109
- toc_title = @options.formatter.format(BlockParser.parse("!!" + title))
110
- contents.unshift toc_title
138
+ def create_contents_container(body)
139
+ formatter.create_element("section").tap do |elm|
140
+ elm["id"] = "contents"
141
+ elm.push body
142
+ end
111
143
  end
112
- contents.unshift h1 unless h1.empty?
113
- contents.join($/)
114
144
  end
115
145
 
116
- def create_html_main(toc, body, h1)
117
- return nil unless @options[:toc]
118
- main = formatter.create_element("section").tap do |element|
119
- element["id"] = "main"
120
- element.push h1 unless h1.empty?
121
- element.push create_html_toc_container(toc)
122
- element.push create_html_contents_container(body)
146
+ class PlainComposer < BaseComposer
147
+ def create_table_of_contents(tree)
148
+ toc_lines = collect_nodes_for_table_of_contents(tree).map do |toc_node|
149
+ ('*' * toc_node.level) + to_plain(toc_node)
150
+ end
151
+
152
+ @options.formatter.format(BlockParser.parse(toc_lines))
123
153
  end
124
- end
125
154
 
126
- def create_html_toc_container(toc)
127
- formatter.create_element("section").tap do |elm|
128
- elm["id"] = "toc"
129
- title = @options[:toc]
130
- elm.push formatter.create_element("h2", title) unless title.empty?
131
- elm.push toc
155
+ def create_main(toc, body, h1)
156
+ contents = [body]
157
+ contents.unshift toc unless toc.empty?
158
+ if title = @options[:toc]
159
+ toc_title = @options.formatter.format(BlockParser.parse("!!" + title))
160
+ contents.unshift toc_title
161
+ end
162
+ contents.unshift h1 unless h1.empty?
163
+ contents.join($/)
132
164
  end
133
165
  end
134
166
 
135
- def create_html_contents_container(body)
136
- formatter.create_element("section").tap do |elm|
137
- elm["id"] = "contents"
138
- elm.push body
167
+ class GfmComposer < PlainComposer
168
+ def create_table_of_contents(tree)
169
+ toc_lines = collect_nodes_for_table_of_contents(tree).map do |toc_node|
170
+ format("%s[[%s|#%s]]#{$/}",
171
+ '*' * toc_node.level,
172
+ to_plain(toc_node).strip,
173
+ gfm_id(toc_node))
174
+ end
175
+
176
+ @options.formatter.format(BlockParser.parse(toc_lines))
177
+ end
178
+
179
+ private
180
+
181
+ def gfm_id(heading_node)
182
+ MarkDownFormat.convert_into_gfm_id_format(to_plain(heading_node).strip)
139
183
  end
140
184
  end
141
185
 
142
- def create_main(toc, body, h1)
143
- return create_plain_main(toc, body, h1) unless @options.html_template
144
- create_html_main(toc, body, h1)
186
+ def initialize(options)
187
+ @options = options
188
+ @composer = select_composer.new(options)
145
189
  end
146
190
 
147
- def create_style(path_to_css_file)
148
- style = formatter.create_element("style").tap do |element|
149
- element["type"] = "text/css"
150
- open(File.expand_path(path_to_css_file)) do |css_file|
151
- element.push css_file.read
152
- end
153
- end
191
+ def select_composer
192
+ return GfmComposer if @options[:html_version].version == "gfm"
193
+ @options.html_template ? HtmlComposer : PlainComposer
154
194
  end
155
195
 
156
- def compose_body(tree)
196
+ def create_table_of_contents(tree)
197
+ return "" unless @options[:toc]
198
+ @composer.create_table_of_contents(tree)
199
+ end
200
+
201
+ def split_main_heading(input_lines)
202
+ return "" unless @options[:split_main_heading]
203
+ h1_pos = input_lines.find_index {|line| /^![^!]/o =~ line }
204
+ return "" unless h1_pos
205
+ tree = BlockParser.parse([input_lines.delete_at(h1_pos)])
157
206
  @options.formatter.format(tree)
158
207
  end
159
208
 
@@ -162,9 +211,9 @@ module PseudoHiki
162
211
  css = @options[:css]
163
212
  tree = BlockParser.parse(input_lines)
164
213
  toc = create_table_of_contents(tree)
165
- body = compose_body(tree)
214
+ body = @composer.compose_body(tree)
166
215
  title = @options.title
167
- main = create_main(toc, body, h1)
216
+ main = @composer.create_main(toc, body, h1)
168
217
  choose_template(main, body, binding)
169
218
  end
170
219
 
@@ -174,7 +223,7 @@ module PseudoHiki
174
223
  else
175
224
  html = @options.create_html_template_with_current_options
176
225
  embed_css = @options[:embed_css]
177
- html.head.push create_style(embed_css) if embed_css
226
+ html.head.push @composer.create_style(embed_css) if embed_css
178
227
  html.push main || body
179
228
  end
180
229
 
@@ -238,6 +287,7 @@ module PseudoHiki
238
287
  attr_reader :input_file_basename
239
288
 
240
289
  def self.remove_bom(input=ARGF)
290
+ return if input == ARGF and input.filename == "-"
241
291
  bom = input.read(3)
242
292
  input.rewind unless BOM == bom
243
293
  end
@@ -323,17 +373,33 @@ instead of \"#{given_opt}\"."
323
373
  end
324
374
  end
325
375
 
326
- def set_encoding(given_opt)
376
+ def setup_ruby_encoding(given_opt)
327
377
  return nil unless String.new.respond_to? :encoding
328
378
  external, internal = given_opt.split(/:/o, 2)
329
379
  Encoding.default_external = external if external and not external.empty?
330
380
  Encoding.default_internal = internal if internal and not internal.empty?
331
381
  end
332
382
 
333
- def parse_command_line_options
383
+ def parse_opt_setup_ruby_encoding(opt)
384
+ opt.on("-E [ex[:in]]", "--encoding [=ex[:in]]",
385
+ "Specify the default external and internal character encodings \
386
+ (same as the option of MRI)") do |given_opt|
387
+ setup_ruby_encoding(given_opt)
388
+ end
389
+ end
390
+
391
+ def assign_opt_value(opt, key, short, long, description)
392
+ opt.on(short, long, description) {|val| self[key] = val }
393
+ end
394
+
395
+ def setup_command_line_options
334
396
  OptionParser.new("USAGE: #{File.basename($0)} [OPTION]... [FILE]...
335
397
  Convert texts written in a Hiki-like notation into another format.") do |opt|
336
- opt.on("-f [html_version]", "--format-version [=format_version]",
398
+ opt.version = PseudoHiki::VERSION
399
+
400
+ parse_opt_setup_ruby_encoding(opt)
401
+
402
+ opt.on("-f [format_version]", "--format-version [=format_version]",
337
403
  "Choose a formart for the output. Available options: \
338
404
  html4, xhtml1, html5, plain, plain_verbose, markdown or gfm \
339
405
  (default: #{self[:html_version].version})") do |version|
@@ -352,12 +418,6 @@ html4, xhtml1, html5, plain, plain_verbose, markdown or gfm \
352
418
  set_html_encoding(given_opt)
353
419
  end
354
420
 
355
- opt.on("-E [ex[:in]]", "--encoding [=ex[:in]]",
356
- "Specify the default external and internal character encodings \
357
- (same as the option of MRI") do |given_opt|
358
- set_encoding(given_opt)
359
- end
360
-
361
421
  # use '-w' to avoid the conflict with the short option for '[-t]emplate'
362
422
  opt.on("-w [(window) title]", "--title [=title]",
363
423
  "Set the value of the <title> element \
@@ -365,17 +425,15 @@ html4, xhtml1, html5, plain, plain_verbose, markdown or gfm \
365
425
  self[:title] = title if value_given?(title)
366
426
  end
367
427
 
368
- opt.on("-c [css]", "--css [=css]",
369
- "Set the path to a css file to be used \
370
- (default: #{self[:css]})") do |css|
371
- self[:css] = css
372
- end
428
+ assign_opt_value(opt, :css, "-c [css]",
429
+ "--css [=css]",
430
+ "Set the path to a css file to be used \
431
+ (default: #{self[:css]})")
373
432
 
374
- opt.on("-C [path_to_css_file]", "--embed-css [=path_to_css_file]",
375
- "Set the path to a css file to embed \
376
- (default: not to embed)") do |path_to_css_file|
377
- self[:embed_css] = path_to_css_file
378
- end
433
+ assign_opt_value(opt, :embed_css, "-C [path_to_css_file]",
434
+ "--embed-css [=path_to_css_file]",
435
+ "Set the path to a css file to embed \
436
+ (default: not to embed)")
379
437
 
380
438
  opt.on("-b [base]", "--base [=base]",
381
439
  "Specify the value of href attribute of the <base> element \
@@ -396,22 +454,17 @@ inside (default: not specified)") do |template|
396
454
  @need_output_file = true
397
455
  end
398
456
 
399
- opt.on("-F", "--force",
400
- "Force to apply command line options. \
401
- (default: false)") do |force|
402
- self[:force] = force
403
- end
457
+ assign_opt_value(opt, :force, "-F", "--force",
458
+ "Force to apply command line options. \
459
+ (default: false)")
404
460
 
405
- opt.on("-m [contents-title]", "--table-of-contents [=contents-title]",
406
- "Include the list of h2 and/or h3 headings with ids. \
407
- (default: nil)") do |toc_title|
408
- self[:toc] = toc_title
409
- end
461
+ assign_opt_value(opt, :toc, "-m [contents-title]",
462
+ "--table-of-contents [=contents-title]",
463
+ "Include the list of h2 and/or h3 headings with ids. \
464
+ (default: nil)")
410
465
 
411
- opt.on("-s", "--split-main-heading",
412
- "Split the first h1 element") do |should_be_split|
413
- self[:split_main_heading] = should_be_split
414
- end
466
+ assign_opt_value(opt, :split_main_heading, "-s", "--split-main-heading",
467
+ "Split the first h1 element")
415
468
 
416
469
  opt.on("-W", "--with-wikiname",
417
470
  "Use WikiNames") do |with_wikiname|
@@ -421,7 +474,21 @@ inside (default: not specified)") do |template|
421
474
  end
422
475
  end
423
476
 
424
- opt.parse!
477
+ opt.on("-d [domain_name(s)]", "--domain-name [=domain_name(s)]",
478
+ "Specify domain name(s)") do |domain_name|
479
+ names = domain_name.split(/;\s*/)
480
+ self[:domain_name] = names.shift
481
+ self[:alternative_domain_names] = names
482
+ end
483
+
484
+ assign_opt_value(opt, :relative_link, "-r", "--relative-links-in-html",
485
+ "Replace absolute paths with relative ones. \
486
+ *** THIS OPTION IS EXPERIMENTAL ***")
487
+
488
+ assign_opt_value(opt, :accessibility, "-a", "--accessibility",
489
+ "A bit improved accessibility")
490
+
491
+ opt
425
492
  end
426
493
  end
427
494
 
@@ -436,8 +503,10 @@ inside (default: not specified)") do |template|
436
503
  end
437
504
  end
438
505
 
439
- def set_options_from_command_line
440
- parse_command_line_options
506
+ def parse_command_line_options
507
+ opt = setup_command_line_options
508
+ yield opt if block_given?
509
+ opt.parse!
441
510
  check_argv
442
511
  @default_title = @input_file_basename
443
512
  end
@@ -78,6 +78,7 @@ module PseudoHiki
78
78
 
79
79
  def visit(tree)
80
80
  htmlelement = create_element(tree)
81
+ decorate(htmlelement, tree)
81
82
  push_visited_results(htmlelement, tree)
82
83
  htmlelement
83
84
  end
@@ -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],
@@ -189,6 +206,23 @@ module PseudoHiki
189
206
 
190
207
  # for BlockParser
191
208
 
209
+ class << Formatter[TableNode]
210
+ def decorate(htmlelement, tree)
211
+ each_decorator(htmlelement, tree) do |elm, decorator|
212
+ visited_value(decorator["summary"]) do |summary|
213
+ htmlelement["summary"] = HtmlElement.escape(summary.join.chomp)
214
+ end
215
+ visited_value(decorator["caption"]) do |caption|
216
+ htmlelement.push @generator.create("caption", caption)
217
+ end
218
+ end
219
+ end
220
+
221
+ def visited_value(decorator_item)
222
+ yield visited_result(decorator_item.value) if decorator_item
223
+ end
224
+ end
225
+
192
226
  class << Formatter[VerbatimNode]
193
227
  def visit(tree)
194
228
  contents = add_link(@generator.escape(tree.join))
@@ -203,6 +237,37 @@ 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
272
  def visit(tree); BLANK; end
208
273
  end
@@ -275,13 +275,14 @@ module PseudoHiki
275
275
  class VerbatimNodeFormatter < self
276
276
  def visit(tree)
277
277
  element = super(tree)
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,6 +290,12 @@ 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
@@ -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
@@ -29,5 +29,39 @@ module PseudoHiki
29
29
  end
30
30
  end
31
31
  end
32
+
33
+ class TableManager
34
+ TH, COL, ROW = %w(th col row)
35
+
36
+ def guess_header_scope(table)
37
+ col_scope?(table) or row_scope?(table)
38
+ end
39
+
40
+ private
41
+
42
+ def col_scope?(table)
43
+ table.each_with_index do |row, i|
44
+ row.each do |cell|
45
+ return if cell.rowspan > 1 or cell.colspan > 1
46
+ # The first row sould be consist of <th> elements
47
+ # and other rows should not include <th> elements
48
+ return unless (i == 0) == (cell.cell_type == TH)
49
+ end
50
+ end
51
+ COL
52
+ end
53
+
54
+ def row_scope?(table)
55
+ table.each do |row|
56
+ row.each_with_index do |cell, j|
57
+ return if cell.rowspan > 1 or cell.colspan > 1
58
+ # The first column sould be consist of <th> elements
59
+ # and other columns should not include <th> elements
60
+ return unless (j == 0) == (cell.cell_type == TH)
61
+ end
62
+ end
63
+ ROW
64
+ end
65
+ end
32
66
  end
33
67
  end
@@ -1,3 +1,3 @@
1
1
  module PseudoHiki
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5.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