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.
@@ -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
- include PseudoHiki
13
-
14
- OPTIONS = {
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
- def to_plain(line)
51
- PlainFormat.format(BlockParser.parse(line.lines.to_a)).to_s.chomp
52
- end
17
+ PlainFormat = PlainTextFormat.create
53
18
 
54
- def create_table_of_contents(lines)
55
- return "" unless OPTIONS[:toc]
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
- def split_main_heading(input_lines)
65
- return "" unless OPTIONS[:split_main_heading]
66
- h1_pos = input_lines.find_index {|line| /^![^!]/o =~ line }
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
- def create_main(toc, body, h1)
73
- return nil unless OPTIONS[:toc]
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
- contents_container = formatter.create_element("section").tap do |element|
80
- element["id"] = "contents"
81
- element.push body
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
- main = formatter.create_element("section").tap do |element|
84
- element["id"] = "main"
85
- element.push h1 unless h1.empty?
86
- element.push toc_container
87
- element.push contents_container
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
- def create_style(path_to_css_file)
92
- style = formatter.create_element("style").tap do |element|
93
- element["type"] = "text/css"
94
- open(File.expand_path(path_to_css_file)) do |css_file|
95
- element.push css_file.read
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
- def compose_body(input_lines)
101
- tree = BlockParser.parse(input_lines)
102
- OPTIONS.formatter.format(tree)
103
- end
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
- def compose_html(input_lines)
106
- h1 = split_main_heading(input_lines)
107
- css = OPTIONS[:css]
108
- toc = create_table_of_contents(input_lines)
109
- body = compose_body(input_lines)
110
- title = OPTIONS.title
111
- main = create_main(toc,body, h1)
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
- if OPTIONS[:template]
114
- erb = ERB.new(OPTIONS.read_template_file)
115
- html = erb.result(binding)
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
- html
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
- def win32?
127
- true if RUBY_PLATFORM =~ /win/i
128
- end
137
+ class OptionManager
138
+ include HtmlElement::CHARSET
129
139
 
130
- def value_given?(value)
131
- value and not value.empty?
132
- end
140
+ PlainVerboseFormat = PlainTextFormat.create(:verbose_mode => true)
141
+ MDFormat = MarkDownFormat.create
142
+ GFMFormat = MarkDownFormat.create(:gfm_style => true)
133
143
 
134
- class << OPTIONS
135
- include HtmlElement::CHARSET
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
- ENCODING_TO_CHARSET = {
140
- 'utf8' => UTF8,
141
- 'euc-jp' => EUC_JP,
142
- 'sjis' => SJIS,
143
- 'latin1' => LATIN1
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
- HTML_TEMPLATES = Hash[*HTML_VERSIONS.zip([HtmlTemplate, XhtmlTemplate, Xhtml5Template]).flatten]
147
- FORMATTERS = Hash[*HTML_VERSIONS.zip([HtmlFormat, XhtmlFormat, Xhtml5Format]).flatten]
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
- def html_template
150
- HTML_TEMPLATES[self[:html_version]]
151
- end
202
+ def [](key)
203
+ @options[key]
204
+ end
152
205
 
153
- def formatter
154
- FORMATTERS[self[:html_version]]
155
- end
206
+ def[]=(key, value)
207
+ @options[key] = value
208
+ end
156
209
 
157
- def charset
158
- ENCODING_TO_CHARSET[self[:encoding]]
159
- end
210
+ def win32?
211
+ true if RUBY_PLATFORM =~ /win/i
212
+ end
160
213
 
161
- def base
162
- base_dir = self[:base]
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
- def title
171
- OPTIONS[:title]||@default_title||"-"
172
- end
218
+ def html_template
219
+ self[:html_version].template
220
+ end
173
221
 
174
- def read_template_file
175
- File.read(File.expand_path(self[:template]))
176
- end
222
+ def formatter
223
+ self[:html_version].formatter
224
+ end
177
225
 
178
- def set_html_version(version)
179
- if HTML_VERSIONS.include? version
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
- def set_encoding(given_opt)
193
- if ENCODING_REGEXP.values.include? given_opt
194
- self[:encoding] = given_opt
195
- else
196
- ENCODING_REGEXP.each do |pat, encoding|
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
- STDERR.puts "\"#{self[:encoding]}\" is chosen as an encoding system, instead of \"#{given_opt}\"."
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
- def set_options_from_input_file(input_lines)
204
- input_lines.each do |line|
205
- break if FILE_HEADER_PAT !~ line
206
- line = line.chomp
207
- self.keys.each do |opt|
208
- if WRITTEN_OPTION_PAT[opt] =~ line and not self[:force]
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
- def create_html_with_current_options
216
- html = self.html_template.new
217
- html.charset = self.charset
218
- html.language = self[:lang]
219
- html.default_css = self[:css] if self[:css]
220
- html.base = self.base if self[:base]
221
- html.title = self.title
222
- html
223
- end
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
- def output_file_name
231
- return nil unless self.need_output_file
232
- if self[:output]
233
- File.expand_path(self[:output])
234
- else
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
- OptionParser.new("** Convert texts written in a Hiki-like notation into HTML **
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
- opt.on("-h [html_version]", "--html_version [=html_version]",
243
- "HTML version to be used. Choose html4, xhtml1 or html5 (default: #{OPTIONS[:html_version]})") do |version|
244
- OPTIONS.set_html_version(version)
245
- end
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
- opt.on("-l [lang]", "--lang [=lang]",
248
- "Set the value of charset attributes (default: #{OPTIONS[:lang]})") do |lang|
249
- OPTIONS[:lang] = lang if value_given?(lang)
250
- end
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
- opt.on("-e [encoding]", "--encoding [=encoding]",
253
- "Available options: utf8, euc-jp, sjis, latin1 (default: #{OPTIONS[:encoding]})") do |given_opt|
254
- OPTIONS.set_encoding(given_opt)
255
- end
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
- #use '-w' to avoid the conflict with the short option for '[-t]emplate'
258
- opt.on("-w [(window) title]", "--title [=title]",
259
- "Set the value of the <title> element (default: the basename of the input file)") do |title|
260
- OPTIONS[:title] = title if value_given?(title)
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
- opt.on("-c [css]", "--css [=css]",
264
- "Set the path to a css file to be used (default: #{OPTIONS[:css]})") do |css|
265
- OPTIONS[:css] = css
266
- end
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
- opt.on("-C [path_to_css_file]", "--embed-css [=path_to_css_file]",
269
- "Set the path to a css file to embed (default: not to embed)") do |path_to_css_file|
270
- OPTIONS[:embed_css] = path_to_css_file
271
- end
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
- opt.on("-b [base]", "--base [=base]",
274
- "Specify the value of href attribute of the <base> element (default: not specified)") do |base_dir|
275
- OPTIONS[:base] = base_dir if value_given?(base_dir)
276
- end
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
- opt.on("-t [template]", "--template [=template]",
279
- "Specify a template file written in eruby format with \"<%= body %>\" inside (default: not specified)") do |template|
280
- OPTIONS[:template] = template if value_given?(template)
281
- end
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
- opt.on("-o [output]", "--output [=output]",
284
- "Output to the specified file. If no file is given, \"[input_file_basename].html\" will be used.(default: STDOUT)") do |output|
285
- OPTIONS[:output] = File.expand_path(output) if value_given?(output)
286
- OPTIONS.need_output_file = true
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
- opt.on("-f", "--force",
290
- "Force to apply command line options.(default: false)") do |force|
291
- OPTIONS[:force] = force
292
- end
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
- opt.on("-m [contents-title]", "--table-of-contents [=contents-title]",
295
- "Include the list of h2 and/or h3 headings with ids.(default: nil)") do |toc_title|
296
- OPTIONS[:toc] = toc_title
297
- end
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
- opt.on("-s", "--split-main-heading",
300
- "Split the first h1 element") do |should_be_split|
301
- OPTIONS[:split_main_heading] = should_be_split
302
- end
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
- opt.parse!
305
- end
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
- if $KCODE
308
- ENCODING_REGEXP.each do |pat, encoding|
309
- OPTIONS[:encoding] = encoding if pat =~ $KCODE and not OPTIONS[:force]
310
- end
311
- end
346
+ opt.parse!
347
+ end
348
+ end
312
349
 
313
- input_manager = InputManager.new
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
- case ARGV.length
316
- when 0
317
- if OPTIONS.need_output_file and not OPTIONS[:output]
318
- raise "You must specify a file name for output"
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
- input_lines = ARGF.readlines
414
+ options = PseudoHiki::OptionManager.new
415
+ options.set_options_from_command_line
325
416
 
326
- OPTIONS.set_options_from_input_file(input_lines)
327
- OPTIONS.default_title = OPTIONS.input_file_basename
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
- html = input_manager.compose_html(input_lines)
330
- output_file_name = OPTIONS.output_file_name
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
- if output_file_name
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 }