pseudohikiparser 0.0.0.11.develop → 0.0.0.12.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.
@@ -0,0 +1,411 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
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_internal = 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
+ next if self[opt] and self[:force]
373
+ self[opt] = $1 if @written_option_pat[opt] =~ line
374
+ end
375
+ end
376
+ end
377
+
378
+ def create_html_template_with_current_options
379
+ return [] unless self.html_template
380
+ html = self.html_template.new
381
+ html.charset = self.charset
382
+ html.language = self[:lang]
383
+ html.default_css = self[:css] if self[:css]
384
+ html.base = self.base if self[:base]
385
+ html.title = self.title
386
+ html
387
+ end
388
+
389
+ def read_input_filename(filename)
390
+ @input_file_dir, @input_file_name = File.split(File.expand_path(filename))
391
+ @input_file_basename = File.basename(@input_file_name,".*")
392
+ end
393
+
394
+ def output_filename
395
+ return nil unless self.need_output_file
396
+ if self[:output]
397
+ File.expand_path(self[:output])
398
+ else
399
+ File.join(@input_file_dir, @input_file_basename + self[:html_version].ext)
400
+ end
401
+ end
402
+
403
+ def open_output
404
+ if self.output_filename
405
+ open(self.output_filename, "w") {|f| yield f }
406
+ else
407
+ yield STDOUT
408
+ end
409
+ end
410
+ end
411
+ end
@@ -35,6 +35,10 @@ module PseudoHiki
35
35
  self::Formatter[PlainNode]
36
36
  end
37
37
 
38
+ def self.create(options=nil)
39
+ self
40
+ end
41
+
38
42
  def self.format(tree)
39
43
  formatter = self.get_plain
40
44
  tree.accept(formatter)
@@ -14,6 +14,16 @@ module PseudoHiki
14
14
  end
15
15
  end
16
16
 
17
+ class XhtmlFormat < HtmlFormat
18
+ Formatter = HtmlFormat::Formatter.dup
19
+ setup_new_formatter(Formatter, XhtmlElement)
20
+ end
21
+
22
+ class Xhtml5Format < XhtmlFormat
23
+ Formatter = HtmlFormat::Formatter.dup
24
+ setup_new_formatter(Formatter, Xhtml5Element)
25
+ end
26
+
17
27
  class HtmlPlugin
18
28
 
19
29
  PLUGIN_PAT = /^(\w+)([\s\(]+)/
@@ -126,13 +126,10 @@ module PseudoHiki
126
126
  def parse_cellspan(token_str)
127
127
  return token_str if m = MODIFIED_CELL_PAT.match(token_str) and m[0].empty? #if token.kind_of? String
128
128
  cell_modifiers = m[0]
129
- if cell_modifiers[0].chr == TH_PAT
130
- cell_modifiers[0] = ""
131
- @cell_type = TH
132
- end
129
+ @cell_type = TH if cell_modifiers[0].chr == TH_PAT
133
130
  @rowspan = cell_modifiers.count(ROW_EXPANDER) + 1
134
131
  @colspan = cell_modifiers.count(COL_EXPANDER) + 1
135
- token_str.sub(MODIFIED_CELL_PAT, "")
132
+ m.post_match
136
133
  end
137
134
 
138
135
  def parse_first_token(orig_tokens)
@@ -281,12 +281,6 @@ module PseudoHiki
281
281
  super(tree)
282
282
  end
283
283
 
284
- def deep_copy_tree(tree)
285
- tree.dup.clear.tap do |new_tree|
286
- new_tree.concat tree.map {|node| node.dup }
287
- end
288
- end
289
-
290
284
  def choose_expander_of_col_and_row
291
285
  ["", ""]
292
286
  end
@@ -11,10 +11,22 @@ module PseudoHiki
11
11
 
12
12
  DescSep = [InlineParser::DescSep]
13
13
 
14
+ Formatters = {}
15
+
14
16
  class Node < Array
15
17
  alias to_s join
16
18
  end
17
19
 
20
+ def self.format(tree, options={ :verbose_mode => false })
21
+ if Formatters.empty?
22
+ default_options = { :verbose_mode => false }
23
+ Formatters[default_options] = create(default_options)
24
+ end
25
+
26
+ Formatters[options] ||= create(options)
27
+ Formatters[options].format(tree)
28
+ end
29
+
18
30
  def initialize(formatter={}, options = { :verbose_mode=> false })
19
31
  @formatter = formatter
20
32
  options_given_via_block = nil
@@ -152,19 +164,17 @@ ERROR_TEXT
152
164
  max_col = tree.map{|row| row.reduce(0) {|sum, cell| sum + cell.colspan }}.max - 1
153
165
  max_row = rows.length - 1
154
166
  cur_row = nil
155
- each_cell_with_index(table, max_row, max_col) do |cell, r, c|
167
+ each_cell_index(max_row, max_col) do |r, c|
156
168
  cur_row = rows.shift if c == 0
157
169
  next if table[r][c]
158
- unless cell
159
- begin
160
- raise MalFormedTableError.new(ERROR_MESSAGE%[table[r].inspect]) if cur_row.empty?
161
- table[r][c] = cur_row.shift
162
- fill_expand(table, r, c, table[r][c])
163
- rescue
164
- raise if @options.strict_mode
165
- STDERR.puts ERROR_MESSAGE%[table[r].inspect]
166
- next
167
- end
170
+ begin
171
+ raise MalFormedTableError.new(ERROR_MESSAGE%[table[r].inspect]) if cur_row.empty?
172
+ table[r][c] = cur_row.shift
173
+ fill_expand(table, r, c, table[r][c])
174
+ rescue
175
+ raise if @options.strict_mode
176
+ STDERR.puts ERROR_MESSAGE%[table[r].inspect]
177
+ next
168
178
  end
169
179
  end
170
180
  format_table(table, tree)
@@ -176,10 +186,10 @@ ERROR_TEXT
176
186
  end
177
187
  end
178
188
 
179
- def each_cell_with_index(table, max_row, max_col, initial_row=0, initial_col=0)
189
+ def each_cell_index(max_row, max_col, initial_row=0, initial_col=0)
180
190
  initial_row.upto(max_row) do |r|
181
191
  initial_col.upto(max_col) do |c|
182
- yield table[r][c], r, c
192
+ yield r, c
183
193
  end
184
194
  end
185
195
  end
@@ -188,8 +198,8 @@ ERROR_TEXT
188
198
  row_expand, col_expand = choose_expander_of_col_and_row
189
199
  max_row = initial_row + cur_cell.rowspan - 1
190
200
  max_col = initial_col + cur_cell.colspan - 1
191
- each_cell_with_index(table, max_row, max_col,
192
- initial_row, initial_col) do |cell, r, c|
201
+ each_cell_index(max_row, max_col,
202
+ initial_row, initial_col) do |r, c|
193
203
  if initial_row == r and initial_col == c
194
204
  table[r][c] = visited_result(cur_cell).join.lstrip.chomp
195
205
  next
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ module Sinatra
5
+ module PseudoHikiParserHelpers
6
+ XHTML5_CONTENT_TYPE = 'application/xhtml+xml'
7
+ def phiki(hiki_data, &block)
8
+ case content_type
9
+ when XHTML5_CONTENT_TYPE
10
+ PseudoHiki::Format.to_html5(hiki_data, &block)
11
+ else
12
+ PseudoHiki::Format.to_xhtml(hiki_data, &block)
13
+ end
14
+ end
15
+ end
16
+
17
+ class Base
18
+ helpers PseudoHikiParserHelpers
19
+ end
20
+ end
21
+ rescue
22
+ #Sinatra is not available
23
+ end
@@ -1,3 +1,3 @@
1
1
  module PseudoHiki
2
- VERSION = "0.0.0.11.develop"
2
+ VERSION = "0.0.0.12.develop"
3
3
  end
@@ -2,5 +2,100 @@
2
2
 
3
3
  require "pseudohiki/htmlformat"
4
4
  require "pseudohiki/plaintextformat"
5
+ require "pseudohiki/markdownformat"
5
6
  require "pseudohiki/version"
6
7
 
8
+ # = PseudoHikiParser -- A converter of texts written in a Hiki-like notation into HTML or other formats.
9
+ #
10
+ # You may find more detailed information at {PseudoHikiParser Wiki}[https://github.com/nico-hn/PseudoHikiParser/wiki]
11
+ #
12
+ module PseudoHiki
13
+ # This class provides class methods for converting texts written in a Hiki-like notation into HTML or other formats.
14
+ #
15
+ class Format
16
+ Formatter = {} # :nodoc:
17
+ PRESET_OPTIONS = {} # :nodoc:
18
+ TYPE_TO_FORMATTER = {} # :nodoc:
19
+
20
+ [
21
+ [:html, HtmlFormat, nil],
22
+ [:xhtml, XhtmlFormat, nil],
23
+ [:html5, Xhtml5Format, nil],
24
+ [:plain, PlainTextFormat, {:verbose_mode => false }],
25
+ [:plain_verbose, PlainTextFormat, {:verbose_mode => true }],
26
+ [:markdown, MarkDownFormat, { :strict_mode=> false, :gfm_style => false }],
27
+ [:gfm, MarkDownFormat, { :strict_mode=> false, :gfm_style => true }]
28
+ ].each do |type, formatter, options|
29
+ preset_options = [type, nil]
30
+ Formatter[preset_options] = formatter.create(options)
31
+ PRESET_OPTIONS[type] = preset_options
32
+ TYPE_TO_FORMATTER[type] = formatter
33
+ end
34
+
35
+ class << self
36
+ # Converts <hiki_data> into a format specified by <format_type>
37
+ #
38
+ # <hiki_data> should be a string or an array of strings
39
+ #
40
+ # Options for <format_type> are:
41
+ # [:html] HTML4.1
42
+ # [:xhtml] XHTML1.0
43
+ # [:html5] HTML5
44
+ # [:plain] remove all of tags
45
+ # [:plain_verbose] similar to :plain, but certain information such as urls in link tags will be kept
46
+ # [:markdown] Markdown
47
+ # [:gfm] GitHub Flavored Markdown
48
+ #
49
+ def format(hiki_data, format_type, options=nil, &block)
50
+ tree = BlockParser.parse(hiki_data)
51
+
52
+ if options
53
+ Formatter[[format_type, options]] ||= TYPE_TO_FORMATTER[format_type].create(options)
54
+ else
55
+ Formatter[PRESET_OPTIONS[format_type]]
56
+ end.format(tree).tap do |formatted|
57
+ block.call(formatted) if block
58
+ end.to_s
59
+ end
60
+
61
+ # Converts <hiki_data> into HTML4.1
62
+ #
63
+ #
64
+ def to_html(hiki_data, &block)
65
+ format(hiki_data, :html, options=nil, &block)
66
+ end
67
+
68
+ # Converts <hiki_data> into XHTML1.0
69
+ #
70
+ def to_xhtml(hiki_data, &block)
71
+ format(hiki_data, :xhtml, options=nil, &block)
72
+ end
73
+
74
+ # Converts <hiki_data> into HTML5
75
+ #
76
+ def to_html5(hiki_data, &block)
77
+ format(hiki_data, :html5, options=nil, &block)
78
+ end
79
+
80
+ # Converts <hiki_data> into plain texts without tags
81
+ #
82
+ def to_plain(hiki_data, &block)
83
+ format(hiki_data, :plain, options=nil, &block)
84
+ end
85
+
86
+ # Converts <hiki_data> into Markdown
87
+ #
88
+ def to_markdown(hiki_data, &block)
89
+ format(hiki_data, :markdown, options=nil, &block)
90
+ end
91
+
92
+ # Converts <hiki_data> into GitHub Flavored Markdown
93
+ #
94
+ def to_gfm(hiki_data, &block)
95
+ format(hiki_data, :gfm, options=nil, &block)
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ require 'pseudohiki/sinatra_helpers'if defined? Sinatra
@@ -761,4 +761,8 @@ HTML
761
761
  tree = BlockParser.parse(text.lines.to_a)
762
762
  assert_equal(xhtml, XhtmlFormat.format(tree).to_s)
763
763
  end
764
+
765
+ def test_self_create
766
+ assert_equal(XhtmlFormat, XhtmlFormat.create)
767
+ end
764
768
  end