pseudohikiparser 0.0.0.11.develop → 0.0.0.12.develop

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b41d1dc1538c8a205df9d0e3674ce36cfe7a269
4
- data.tar.gz: 4d41b79b26ea37bac306dcb392f9e413dfab0be5
3
+ metadata.gz: ab6d03f5f2b3131e62af81faa6540355f115b489
4
+ data.tar.gz: d95e43ed55af9b8b0ecb6868b7075315e1a8e5e2
5
5
  SHA512:
6
- metadata.gz: ad7e6d96413aebd099166d449b57c83ca4a816130daef33ed962c3d87f02d1fad5afeb1b7aed576034bb600121fe61590ebe0b4ec15d3f4daedcea7bc048f962
7
- data.tar.gz: 0320942f7181a5c045ea2a28d41a932ee0508d6dc5f438958e3e539a05861efd9f5c908d37f05ae8062551df174dfca8e4c5a69c9803b31d70e08dbc55877cd4
6
+ metadata.gz: 66e3bec04f94faa3cbbd21b6e945ad46e23e58d1ffd8b0e36cb1c400e4caee43a4e9ce55e0fdfd70bf5ce6b65a5bf877f979882ae6190f348db5cbdef7cea392
7
+ data.tar.gz: 7a0be29c24383e9ff375404413df96ca209d7c885dc13eec566828c84ad19dd7cbd9a6029e7cbb0cadaa280aa5746dad8c5bf34e0fc5620db99a2bf962c3d1ac
@@ -1,415 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
3
2
 
4
- require 'optparse'
5
- require 'erb'
6
- require 'pseudohiki/blockparser'
7
- require 'pseudohiki/htmlformat'
8
- require 'pseudohiki/plaintextformat'
9
- require 'pseudohiki/markdownformat'
10
- require 'htmlelement/htmltemplate'
11
- require 'htmlelement'
12
-
13
- module PseudoHiki
14
- class PageComposer
15
- HEADING_WITH_ID_PAT = /^(!{2,3})\[([A-Za-z][0-9A-Za-z_\-.:]*)\]\s*/o
16
-
17
- PlainFormat = PlainTextFormat.create
18
-
19
- def initialize(options)
20
- @options = options
21
- end
22
-
23
- def formatter
24
- @formatter ||= @options.html_template.new
25
- end
26
-
27
- def to_plain(line)
28
- PlainFormat.format(BlockParser.parse(line.lines.to_a)).to_s.chomp
29
- end
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))
39
- end
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)
60
- end
61
-
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
94
- end
95
- end
96
-
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
101
-
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
110
-
111
- def compose_body(input_lines)
112
- tree = BlockParser.parse(input_lines)
113
- @options.formatter.format(tree)
114
- end
115
-
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
135
- end
136
-
137
- class OptionManager
138
- include HtmlElement::CHARSET
139
-
140
- PlainVerboseFormat = PlainTextFormat.create(:verbose_mode => true)
141
- MDFormat = MarkDownFormat.create
142
- GFMFormat = MarkDownFormat.create(:gfm_style => true)
143
-
144
- class Formatter < Struct.new(:version, :formatter, :template, :ext, :opt_pat)
145
- end
146
-
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
182
-
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
201
-
202
- def [](key)
203
- @options[key]
204
- end
205
-
206
- def[]=(key, value)
207
- @options[key] = value
208
- end
209
-
210
- def win32?
211
- true if RUBY_PLATFORM =~ /win/i
212
- end
213
-
214
- def value_given?(value)
215
- value and not value.empty?
216
- end
217
-
218
- def html_template
219
- self[:html_version].template
220
- end
221
-
222
- def formatter
223
- self[:html_version].formatter
224
- end
225
-
226
- def charset
227
- ENCODING_TO_CHARSET[self[:encoding]]
228
- end
229
-
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?
235
- end
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)
245
- end
246
-
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
253
- end
254
- end
255
- STDERR.puts "\"#{version}\" is an invalid option for --format-version. \"#{self[:html_version].version}\" is chosen instead."
256
- end
257
-
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
268
-
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
274
- end
275
-
276
- def parse_command_line_options
277
- OptionParser.new("** Convert texts written in a Hiki-like notation into HTML **
278
- USAGE: #{File.basename(__FILE__)} [options]") do |opt|
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
283
-
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
288
-
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
293
-
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
298
-
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
304
-
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
309
-
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
314
-
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
319
-
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
324
-
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
330
-
331
- opt.on("-F", "--force",
332
- "Force to apply command line options.(default: false)") do |force|
333
- self[:force] = force
334
- end
335
-
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
340
-
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
345
-
346
- opt.parse!
347
- end
348
- end
349
-
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
366
-
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
411
- end
412
- end
3
+ require 'pseudohiki/converter'
413
4
 
414
5
  options = PseudoHiki::OptionManager.new
415
6
  options.set_options_from_command_line