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.
- checksums.yaml +4 -4
- data/bin/pseudohiki2html +1 -20
- data/lib/htmlelement/htmltemplate.rb +39 -1
- data/lib/htmlelement.rb +15 -1
- data/lib/pseudohiki/autolink.rb +1 -1
- data/lib/pseudohiki/blockparser.rb +119 -18
- data/lib/pseudohiki/converter.rb +9 -19
- data/lib/pseudohiki/htmlformat.rb +88 -23
- data/lib/pseudohiki/htmlplugin.rb +3 -3
- data/lib/pseudohiki/inlineparser.rb +29 -18
- data/lib/pseudohiki/markdownformat.rb +71 -64
- data/lib/pseudohiki/plaintextformat.rb +25 -25
- data/lib/pseudohiki/shim.rb +30 -0
- data/lib/pseudohiki/sinatra_helpers.rb +23 -0
- data/lib/pseudohiki/treestack.rb +4 -4
- data/lib/pseudohiki/utils.rb +2 -2
- data/lib/pseudohiki/version.rb +1 -1
- data/lib/pseudohikiparser.rb +2 -0
- data/test/test_blockparser.rb +67 -0
- data/test/test_htmlelement.rb +34 -0
- data/test/test_htmlelement_utils.rb +11 -0
- data/test/test_htmlformat.rb +413 -0
- data/test/test_htmltemplate.rb +84 -0
- data/test/test_inlineparser.rb +4 -4
- data/test/test_markdownformat.rb +157 -4
- data/test/test_plaintextformat.rb +85 -0
- data/test/test_pseudohiki2html.rb +24 -7
- metadata +8 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 98aa9c74058bd6a6da9f43b9f2c7d73872db41c9
|
4
|
+
data.tar.gz: d921304c72c05629e616d47899b28e09c7fc91ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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)
|
data/lib/pseudohiki/autolink.rb
CHANGED
@@ -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
|
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
|
-
|
42
|
-
|
43
|
-
|
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.
|
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
|
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.
|
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
|
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.
|
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
|
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
|
|
data/lib/pseudohiki/converter.rb
CHANGED
@@ -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
|
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.
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
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 " " if elm.empty? #   = this line would be necessary for HTML 4 or XHTML 1.0
|