pseudohikiparser 0.0.0.8.develop → 0.0.0.9.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/README.md +30 -3
- data/bin/pseudohiki2html.rb +353 -261
- data/lib/pseudohiki/htmlformat.rb +68 -60
- data/lib/pseudohiki/inlineparser.rb +2 -1
- data/lib/pseudohiki/markdownformat.rb +29 -3
- data/lib/pseudohiki/plaintextformat.rb +9 -0
- data/lib/pseudohiki/version.rb +1 -1
- data/test/test_blockparser.rb +2 -2
- data/test/test_htmlelement.rb +2 -2
- data/test/test_htmlformat.rb +30 -3
- data/test/test_htmlplugin.rb +2 -2
- data/test/test_htmltemplate.rb +3 -3
- data/test/test_inlineparser.rb +4 -4
- data/test/test_markdownformat.rb +67 -2
- data/test/test_plaintextformat.rb +37 -3
- data/test/test_treestack.rb +3 -3
- metadata +17 -3
data/bin/pseudohiki2html.rb
CHANGED
@@ -6,331 +6,423 @@ require 'erb'
|
|
6
6
|
require 'pseudohiki/blockparser'
|
7
7
|
require 'pseudohiki/htmlformat'
|
8
8
|
require 'pseudohiki/plaintextformat'
|
9
|
+
require 'pseudohiki/markdownformat'
|
9
10
|
require 'htmlelement/htmltemplate'
|
10
11
|
require 'htmlelement'
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
:html_version => "html4",
|
16
|
-
:lang => 'en',
|
17
|
-
:encoding => 'utf8',
|
18
|
-
:title => nil,
|
19
|
-
:css => "default.css",
|
20
|
-
:embed_css => nil,
|
21
|
-
:base => nil,
|
22
|
-
:template => nil,
|
23
|
-
:output => nil,
|
24
|
-
:force => false,
|
25
|
-
:toc => nil,
|
26
|
-
:split_main_heading => false
|
27
|
-
}
|
28
|
-
|
29
|
-
ENCODING_REGEXP = {
|
30
|
-
/^u/io => 'utf8',
|
31
|
-
/^e/io => 'euc-jp',
|
32
|
-
/^s/io => 'sjis',
|
33
|
-
/^l[a-zA-Z]*1/io => 'latin1'
|
34
|
-
}
|
35
|
-
|
36
|
-
HTML_VERSIONS = %w(html4 xhtml1 html5)
|
37
|
-
|
38
|
-
FILE_HEADER_PAT = /^(\xef\xbb\xbf)?\/\//
|
39
|
-
WRITTEN_OPTION_PAT = {}
|
40
|
-
OPTIONS.keys.each {|opt| WRITTEN_OPTION_PAT[opt] = /^(\xef\xbb\xbf)?\/\/#{opt}:\s*(.*)$/ }
|
41
|
-
HEADING_WITH_ID_PAT = /^(!{2,3})\[([A-Za-z][0-9A-Za-z_\-.:]*)\]\s*/o
|
42
|
-
|
43
|
-
PlainFormat = PlainTextFormat.create
|
44
|
-
|
45
|
-
class InputManager
|
46
|
-
def formatter
|
47
|
-
@formatter ||= OPTIONS.html_template.new
|
48
|
-
end
|
13
|
+
module PseudoHiki
|
14
|
+
class PageComposer
|
15
|
+
HEADING_WITH_ID_PAT = /^(!{2,3})\[([A-Za-z][0-9A-Za-z_\-.:]*)\]\s*/o
|
49
16
|
|
50
|
-
|
51
|
-
PlainFormat.format(BlockParser.parse(line.lines.to_a)).to_s.chomp
|
52
|
-
end
|
17
|
+
PlainFormat = PlainTextFormat.create
|
53
18
|
|
54
|
-
|
55
|
-
|
56
|
-
toc_lines = lines.grep(HEADING_WITH_ID_PAT).map do |line|
|
57
|
-
m = HEADING_WITH_ID_PAT.match(line)
|
58
|
-
heading_depth, id = m[1].length, m[2].upcase
|
59
|
-
"%s[[%s|#%s]]"%['*'*heading_depth, to_plain(line.sub(HEADING_WITH_ID_PAT,'')), id]
|
19
|
+
def initialize(options)
|
20
|
+
@options = options
|
60
21
|
end
|
61
|
-
OPTIONS.formatter.format(BlockParser.parse(toc_lines))
|
62
|
-
end
|
63
22
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
return "" unless h1_pos
|
68
|
-
tree = BlockParser.parse([input_lines.delete_at(h1_pos)])
|
69
|
-
OPTIONS.formatter.format(tree)
|
70
|
-
end
|
23
|
+
def formatter
|
24
|
+
@formatter ||= @options.html_template.new
|
25
|
+
end
|
71
26
|
|
72
|
-
|
73
|
-
|
74
|
-
toc_container = formatter.create_element("section").tap do |element|
|
75
|
-
element["id"] = "toc"
|
76
|
-
element.push formatter.create_element("h2", OPTIONS[:toc]) unless OPTIONS[:toc].empty?
|
77
|
-
element.push toc
|
27
|
+
def to_plain(line)
|
28
|
+
PlainFormat.format(BlockParser.parse(line.lines.to_a)).to_s.chomp
|
78
29
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
30
|
+
|
31
|
+
def create_plain_table_of_contents(lines)
|
32
|
+
toc_lines = lines.grep(HEADING_WITH_ID_PAT).map do |line|
|
33
|
+
m = HEADING_WITH_ID_PAT.match(line)
|
34
|
+
heading_depth = m[1].length
|
35
|
+
line.sub(/^!+/o, '*'*heading_depth)
|
36
|
+
end
|
37
|
+
|
38
|
+
@options.formatter.format(BlockParser.parse(toc_lines))
|
82
39
|
end
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
40
|
+
|
41
|
+
def create_html_table_of_contents(lines)
|
42
|
+
toc_lines = lines.grep(HEADING_WITH_ID_PAT).map do |line|
|
43
|
+
m = HEADING_WITH_ID_PAT.match(line)
|
44
|
+
heading_depth, id = m[1].length, m[2].upcase
|
45
|
+
"%s[[%s|#%s]]"%['*'*heading_depth, to_plain(line.sub(HEADING_WITH_ID_PAT,'')), id]
|
46
|
+
end
|
47
|
+
@options.formatter.format(BlockParser.parse(toc_lines)).tap do |toc|
|
48
|
+
toc.traverse do |element|
|
49
|
+
if element.kind_of? HtmlElement and element.tagname == "a"
|
50
|
+
element["title"] = "toc_item: " + element.children.join.chomp
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_table_of_contents(lines)
|
57
|
+
return "" unless @options[:toc]
|
58
|
+
return create_plain_table_of_contents(lines) unless @options.html_template
|
59
|
+
create_html_table_of_contents(lines)
|
88
60
|
end
|
89
|
-
end
|
90
61
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
62
|
+
def split_main_heading(input_lines)
|
63
|
+
return "" unless @options[:split_main_heading]
|
64
|
+
h1_pos = input_lines.find_index {|line| /^![^!]/o =~ line }
|
65
|
+
return "" unless h1_pos
|
66
|
+
tree = BlockParser.parse([input_lines.delete_at(h1_pos)])
|
67
|
+
@options.formatter.format(tree)
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_plain_main(toc, body, h1)
|
71
|
+
contents = [body]
|
72
|
+
contents.unshift toc unless toc.empty?
|
73
|
+
contents.unshift @options.formatter.format(BlockParser.parse("!!" + @options[:toc])) if @options[:toc]
|
74
|
+
contents.unshift h1 unless h1.empty?
|
75
|
+
contents.join($/)
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_html_main(toc, body, h1)
|
79
|
+
return nil unless @options[:toc]
|
80
|
+
toc_container = formatter.create_element("section").tap do |element|
|
81
|
+
element["id"] = "toc"
|
82
|
+
element.push formatter.create_element("h2", @options[:toc]) unless @options[:toc].empty?
|
83
|
+
element.push toc
|
84
|
+
end
|
85
|
+
contents_container = formatter.create_element("section").tap do |element|
|
86
|
+
element["id"] = "contents"
|
87
|
+
element.push body
|
88
|
+
end
|
89
|
+
main = formatter.create_element("section").tap do |element|
|
90
|
+
element["id"] = "main"
|
91
|
+
element.push h1 unless h1.empty?
|
92
|
+
element.push toc_container
|
93
|
+
element.push contents_container
|
96
94
|
end
|
97
95
|
end
|
98
|
-
end
|
99
96
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
97
|
+
def create_main(toc, body, h1)
|
98
|
+
return create_plain_main(toc, body, h1) unless @options.html_template
|
99
|
+
create_html_main(toc, body, h1)
|
100
|
+
end
|
104
101
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
102
|
+
def create_style(path_to_css_file)
|
103
|
+
style = formatter.create_element("style").tap do |element|
|
104
|
+
element["type"] = "text/css"
|
105
|
+
open(File.expand_path(path_to_css_file)) do |css_file|
|
106
|
+
element.push css_file.read
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
112
110
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
else
|
117
|
-
html = OPTIONS.create_html_with_current_options
|
118
|
-
html.head.push create_style(OPTIONS[:embed_css]) if OPTIONS[:embed_css]
|
119
|
-
html.push main||body
|
111
|
+
def compose_body(input_lines)
|
112
|
+
tree = BlockParser.parse(input_lines)
|
113
|
+
@options.formatter.format(tree)
|
120
114
|
end
|
121
115
|
|
122
|
-
|
116
|
+
def compose_html(input_lines)
|
117
|
+
h1 = split_main_heading(input_lines)
|
118
|
+
css = @options[:css]
|
119
|
+
toc = create_table_of_contents(input_lines)
|
120
|
+
body = compose_body(input_lines)
|
121
|
+
title = @options.title
|
122
|
+
main = create_main(toc,body, h1)
|
123
|
+
|
124
|
+
if @options[:template]
|
125
|
+
erb = ERB.new(@options.read_template_file)
|
126
|
+
html = erb.result(binding)
|
127
|
+
else
|
128
|
+
html = @options.create_html_template_with_current_options
|
129
|
+
html.head.push create_style(@options[:embed_css]) if @options[:embed_css]
|
130
|
+
html.push main||body
|
131
|
+
end
|
132
|
+
|
133
|
+
html
|
134
|
+
end
|
123
135
|
end
|
124
|
-
end
|
125
136
|
|
126
|
-
|
127
|
-
|
128
|
-
end
|
137
|
+
class OptionManager
|
138
|
+
include HtmlElement::CHARSET
|
129
139
|
|
130
|
-
|
131
|
-
|
132
|
-
|
140
|
+
PlainVerboseFormat = PlainTextFormat.create(:verbose_mode => true)
|
141
|
+
MDFormat = MarkDownFormat.create
|
142
|
+
GFMFormat = MarkDownFormat.create(:gfm_style => true)
|
133
143
|
|
134
|
-
class
|
135
|
-
|
136
|
-
attr_accessor :need_output_file, :default_title
|
137
|
-
attr_reader :input_file_basename
|
144
|
+
class Formatter < Struct.new(:version, :formatter, :template, :ext, :opt_pat)
|
145
|
+
end
|
138
146
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
147
|
+
VERSIONS = [
|
148
|
+
["html4", HtmlFormat, HtmlTemplate, ".html", /^h/io],
|
149
|
+
["xhtml1", XhtmlFormat, XhtmlTemplate, ".html", /^x/io],
|
150
|
+
["html5", Xhtml5Format, Xhtml5Template, ".html", /^h5/io],
|
151
|
+
["plain", PageComposer::PlainFormat, nil, ".plain", /^p/io],
|
152
|
+
["plain_verbose", PlainVerboseFormat, nil, ".plain", /^pv/io],
|
153
|
+
["markdown", MDFormat, nil, ".md", /^m/io],
|
154
|
+
["gfm", GFMFormat, nil, ".md", /^g/io]
|
155
|
+
].map {|args| Formatter.new(*args) }
|
156
|
+
|
157
|
+
ENCODING_REGEXP = {
|
158
|
+
/^u/io => 'utf8',
|
159
|
+
/^e/io => 'euc-jp',
|
160
|
+
/^s/io => 'sjis',
|
161
|
+
/^l[a-zA-Z]*1/io => 'latin1'
|
162
|
+
}
|
163
|
+
|
164
|
+
BOM = "\xef\xbb\xbf"
|
165
|
+
BOM.force_encoding("ASCII-8BIT") if BOM.respond_to? :encoding
|
166
|
+
FILE_HEADER_PAT = /^\/\//
|
167
|
+
|
168
|
+
ENCODING_TO_CHARSET = {
|
169
|
+
'utf8' => UTF8,
|
170
|
+
'euc-jp' => EUC_JP,
|
171
|
+
'sjis' => SJIS,
|
172
|
+
'latin1' => LATIN1
|
173
|
+
}
|
174
|
+
|
175
|
+
attr_accessor :need_output_file, :default_title
|
176
|
+
attr_reader :input_file_basename
|
177
|
+
|
178
|
+
def self.remove_bom(input=ARGF)
|
179
|
+
bom = input.read(3)
|
180
|
+
input.rewind unless BOM == bom
|
181
|
+
end
|
145
182
|
|
146
|
-
|
147
|
-
|
183
|
+
def initialize(options=nil)
|
184
|
+
@options = options||{
|
185
|
+
:html_version => VERSIONS[0],
|
186
|
+
:lang => 'en',
|
187
|
+
:encoding => 'utf8',
|
188
|
+
:title => nil,
|
189
|
+
:css => "default.css",
|
190
|
+
:embed_css => nil,
|
191
|
+
:base => nil,
|
192
|
+
:template => nil,
|
193
|
+
:output => nil,
|
194
|
+
:force => false,
|
195
|
+
:toc => nil,
|
196
|
+
:split_main_heading => false
|
197
|
+
}
|
198
|
+
@written_option_pat = {}
|
199
|
+
@options.keys.each {|opt| @written_option_pat[opt] = /^\/\/#{opt}:\s*(.*)$/ }
|
200
|
+
end
|
148
201
|
|
149
|
-
|
150
|
-
|
151
|
-
|
202
|
+
def [](key)
|
203
|
+
@options[key]
|
204
|
+
end
|
152
205
|
|
153
|
-
|
154
|
-
|
155
|
-
|
206
|
+
def[]=(key, value)
|
207
|
+
@options[key] = value
|
208
|
+
end
|
156
209
|
|
157
|
-
|
158
|
-
|
159
|
-
|
210
|
+
def win32?
|
211
|
+
true if RUBY_PLATFORM =~ /win/i
|
212
|
+
end
|
160
213
|
|
161
|
-
|
162
|
-
|
163
|
-
if base_dir and base_dir !~ /[\/\\]\.*$/o
|
164
|
-
base_dir = File.join(base_dir,".")
|
165
|
-
base_dir = "file:///"+base_dir if base_dir !~ /^\./o and win32?
|
214
|
+
def value_given?(value)
|
215
|
+
value and not value.empty?
|
166
216
|
end
|
167
|
-
base_dir
|
168
|
-
end
|
169
217
|
|
170
|
-
|
171
|
-
|
172
|
-
|
218
|
+
def html_template
|
219
|
+
self[:html_version].template
|
220
|
+
end
|
173
221
|
|
174
|
-
|
175
|
-
|
176
|
-
|
222
|
+
def formatter
|
223
|
+
self[:html_version].formatter
|
224
|
+
end
|
177
225
|
|
178
|
-
|
179
|
-
|
180
|
-
self[:html_version] = version
|
181
|
-
else
|
182
|
-
case version
|
183
|
-
when /^x/io
|
184
|
-
self[:html_version] = HTML_VERSIONS[1] #xhtml1
|
185
|
-
when /^h5/io
|
186
|
-
self[:html_version] = HTML_VERSIONS[2] #html5
|
187
|
-
end
|
188
|
-
STDERR.puts "\"#{version}\" is an invalid option for --html_version. \"#{self[:html_version]}\" is chosen instead."
|
226
|
+
def charset
|
227
|
+
ENCODING_TO_CHARSET[self[:encoding]]
|
189
228
|
end
|
190
|
-
end
|
191
229
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
self[:encoding] = encoding if pat =~ given_opt
|
230
|
+
def base
|
231
|
+
base_dir = self[:base]
|
232
|
+
if base_dir and base_dir !~ /[\/\\]\.*$/o
|
233
|
+
base_dir = File.join(base_dir,".")
|
234
|
+
base_dir = "file:///"+base_dir if base_dir !~ /^\./o and win32?
|
198
235
|
end
|
199
|
-
|
236
|
+
base_dir
|
237
|
+
end
|
238
|
+
|
239
|
+
def title
|
240
|
+
self[:title]||@default_title||"-"
|
241
|
+
end
|
242
|
+
|
243
|
+
def read_template_file
|
244
|
+
File.read(File.expand_path(self[:template]), :encoding => self.charset)
|
200
245
|
end
|
201
|
-
end
|
202
246
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
self[opt] = $2
|
247
|
+
def set_html_version(version)
|
248
|
+
VERSIONS.each do |v|
|
249
|
+
if v.version == version
|
250
|
+
return self[:html_version] = v
|
251
|
+
else
|
252
|
+
self[:html_version] = v if v.opt_pat =~ version
|
210
253
|
end
|
211
254
|
end
|
255
|
+
STDERR.puts "\"#{version}\" is an invalid option for --format-version. \"#{self[:html_version].version}\" is chosen instead."
|
212
256
|
end
|
213
|
-
end
|
214
257
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
def read_input_filename(filename)
|
226
|
-
@input_file_dir, @input_file_name = File.split(File.expand_path(filename))
|
227
|
-
@input_file_basename = File.basename(@input_file_name,".*")
|
228
|
-
end
|
258
|
+
def set_html_encoding(given_opt)
|
259
|
+
if ENCODING_REGEXP.values.include? given_opt
|
260
|
+
self[:encoding] = given_opt
|
261
|
+
else
|
262
|
+
ENCODING_REGEXP.each do |pat, encoding|
|
263
|
+
self[:encoding] = encoding if pat =~ given_opt
|
264
|
+
end
|
265
|
+
STDERR.puts "\"#{self[:encoding]}\" is chosen as an encoding system, instead of \"#{given_opt}\"."
|
266
|
+
end
|
267
|
+
end
|
229
268
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
File.join(@input_file_dir, @input_file_basename+".html")
|
269
|
+
def set_encoding(given_opt)
|
270
|
+
return nil unless String.new.respond_to? :encoding
|
271
|
+
external, internal = given_opt.split(/:/o)
|
272
|
+
Encoding.default_external = external if external
|
273
|
+
Encoding.default_interanl = internal if internal
|
236
274
|
end
|
237
|
-
end
|
238
|
-
end
|
239
275
|
|
240
|
-
|
276
|
+
def parse_command_line_options
|
277
|
+
OptionParser.new("** Convert texts written in a Hiki-like notation into HTML **
|
241
278
|
USAGE: #{File.basename(__FILE__)} [options]") do |opt|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
279
|
+
opt.on("-f [html_version]", "--format-version [=format_version]",
|
280
|
+
"HTML version to be used. Choose html4, xhtml1, html5, plain, plain_verbose, markdown or gfm (default: #{self[:html_version].version})") do |version|
|
281
|
+
self.set_html_version(version)
|
282
|
+
end
|
246
283
|
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
284
|
+
opt.on("-l [lang]", "--lang [=lang]",
|
285
|
+
"Set the value of charset attributes (default: #{self[:lang]})") do |lang|
|
286
|
+
self[:lang] = lang if value_given?(lang)
|
287
|
+
end
|
251
288
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
289
|
+
opt.on("-e [encoding]", "--format-encoding [=encoding]",
|
290
|
+
"Available options: utf8, euc-jp, sjis, latin1 (default: #{self[:encoding]})") do |given_opt|
|
291
|
+
self.set_html_encoding(given_opt)
|
292
|
+
end
|
256
293
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
end
|
294
|
+
opt.on("-E [ex[:in]]", "--encoding [=ex[:in]]",
|
295
|
+
"Specify the default external and internal character encodings (same as the option of MRI") do |given_opt|
|
296
|
+
self.set_encoding(given_opt)
|
297
|
+
end
|
262
298
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
299
|
+
#use '-w' to avoid the conflict with the short option for '[-t]emplate'
|
300
|
+
opt.on("-w [(window) title]", "--title [=title]",
|
301
|
+
"Set the value of the <title> element (default: the basename of the input file)") do |title|
|
302
|
+
self[:title] = title if value_given?(title)
|
303
|
+
end
|
267
304
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
305
|
+
opt.on("-c [css]", "--css [=css]",
|
306
|
+
"Set the path to a css file to be used (default: #{self[:css]})") do |css|
|
307
|
+
self[:css] = css
|
308
|
+
end
|
272
309
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
310
|
+
opt.on("-C [path_to_css_file]", "--embed-css [=path_to_css_file]",
|
311
|
+
"Set the path to a css file to embed (default: not to embed)") do |path_to_css_file|
|
312
|
+
self[:embed_css] = path_to_css_file
|
313
|
+
end
|
277
314
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
315
|
+
opt.on("-b [base]", "--base [=base]",
|
316
|
+
"Specify the value of href attribute of the <base> element (default: not specified)") do |base_dir|
|
317
|
+
self[:base] = base_dir if value_given?(base_dir)
|
318
|
+
end
|
282
319
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
end
|
320
|
+
opt.on("-t [template]", "--template [=template]",
|
321
|
+
"Specify a template file written in eruby format with \"<%= body %>\" inside (default: not specified)") do |template|
|
322
|
+
self[:template] = template if value_given?(template)
|
323
|
+
end
|
288
324
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
325
|
+
opt.on("-o [output]", "--output [=output]",
|
326
|
+
"Output to the specified file. If no file is given, \"[input_file_basename].html\" will be used.(default: STDOUT)") do |output|
|
327
|
+
self[:output] = File.expand_path(output) if value_given?(output)
|
328
|
+
self.need_output_file = true
|
329
|
+
end
|
293
330
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
331
|
+
opt.on("-F", "--force",
|
332
|
+
"Force to apply command line options.(default: false)") do |force|
|
333
|
+
self[:force] = force
|
334
|
+
end
|
298
335
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
336
|
+
opt.on("-m [contents-title]", "--table-of-contents [=contents-title]",
|
337
|
+
"Include the list of h2 and/or h3 headings with ids.(default: nil)") do |toc_title|
|
338
|
+
self[:toc] = toc_title
|
339
|
+
end
|
303
340
|
|
304
|
-
|
305
|
-
|
341
|
+
opt.on("-s", "--split-main-heading",
|
342
|
+
"Split the first h1 element") do |should_be_split|
|
343
|
+
self[:split_main_heading] = should_be_split
|
344
|
+
end
|
306
345
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
end
|
311
|
-
end
|
346
|
+
opt.parse!
|
347
|
+
end
|
348
|
+
end
|
312
349
|
|
313
|
-
|
350
|
+
def check_argv
|
351
|
+
case ARGV.length
|
352
|
+
when 0
|
353
|
+
if self.need_output_file and not self[:output]
|
354
|
+
raise "You must specify a file name for output"
|
355
|
+
end
|
356
|
+
when 1
|
357
|
+
self.read_input_filename(ARGV[0])
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
def set_options_from_command_line
|
362
|
+
parse_command_line_options
|
363
|
+
check_argv
|
364
|
+
@default_title = @input_file_basename
|
365
|
+
end
|
314
366
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
367
|
+
def set_options_from_input_file(input_lines)
|
368
|
+
input_lines.each do |line|
|
369
|
+
break if FILE_HEADER_PAT !~ line
|
370
|
+
line = line.chomp
|
371
|
+
@options.keys.each do |opt|
|
372
|
+
if @written_option_pat[opt] =~ line and not self[:force]
|
373
|
+
self[opt] = $1
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
def create_html_template_with_current_options
|
380
|
+
return [] unless self.html_template
|
381
|
+
html = self.html_template.new
|
382
|
+
html.charset = self.charset
|
383
|
+
html.language = self[:lang]
|
384
|
+
html.default_css = self[:css] if self[:css]
|
385
|
+
html.base = self.base if self[:base]
|
386
|
+
html.title = self.title
|
387
|
+
html
|
388
|
+
end
|
389
|
+
|
390
|
+
def read_input_filename(filename)
|
391
|
+
@input_file_dir, @input_file_name = File.split(File.expand_path(filename))
|
392
|
+
@input_file_basename = File.basename(@input_file_name,".*")
|
393
|
+
end
|
394
|
+
|
395
|
+
def output_filename
|
396
|
+
return nil unless self.need_output_file
|
397
|
+
if self[:output]
|
398
|
+
File.expand_path(self[:output])
|
399
|
+
else
|
400
|
+
File.join(@input_file_dir, @input_file_basename + self[:html_version].ext)
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def open_output
|
405
|
+
if self.output_filename
|
406
|
+
open(self.output_filename, "w") {|f| yield f }
|
407
|
+
else
|
408
|
+
yield STDOUT
|
409
|
+
end
|
410
|
+
end
|
319
411
|
end
|
320
|
-
when 1
|
321
|
-
OPTIONS.read_input_filename(ARGV[0])
|
322
412
|
end
|
323
413
|
|
324
|
-
|
414
|
+
options = PseudoHiki::OptionManager.new
|
415
|
+
options.set_options_from_command_line
|
325
416
|
|
326
|
-
|
327
|
-
|
417
|
+
if $KCODE
|
418
|
+
PseudoHiki::OptionManager::ENCODING_REGEXP.each do |pat, encoding|
|
419
|
+
options[:encoding] = encoding if pat =~ $KCODE and not options[:force]
|
420
|
+
end
|
421
|
+
end
|
328
422
|
|
329
|
-
|
330
|
-
|
423
|
+
PseudoHiki::OptionManager.remove_bom
|
424
|
+
input_lines = ARGF.readlines.map {|line| line.encode(options.charset) }
|
425
|
+
options.set_options_from_input_file(input_lines)
|
426
|
+
html = PseudoHiki::PageComposer.new(options).compose_html(input_lines)
|
331
427
|
|
332
|
-
|
333
|
-
open(output_file_name, "w") {|f| f.puts html }
|
334
|
-
else
|
335
|
-
STDOUT.puts html
|
336
|
-
end
|
428
|
+
options.open_output {|out| out.puts html }
|