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 +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
|