Public: Methods for parsing Asciidoc input files and rendering documents using eRuby templates.
Asciidoc documents comprise a header followed by zero or more sections. Sections are composed of blocks of content. For example:
= Doc Title == Section 1 This is a paragraph block in the first section. == Section 2 This section has a paragraph block and an olist block. . Item 1 . Item 2
Examples:
Use built-in templates:
lines = File.readlines("your_file.asc") doc = Asciidoctor::Document.new(lines) html = doc.render File.open("your_file.html", "w+") do |file| file.puts html end
Use custom (Tilt-supported) templates:
lines = File.readlines("your_file.asc") doc = Asciidoctor::Document.new(lines, :template_dir => 'templates') html = doc.render File.open("your_file.html", "w+") do |file| file.puts html end
NOTE once we decide to make DocBook 5 the default, we'll load the files the other way around
Set of file extensions recognized as AsciiDoc documents (stored as a truth hash)
Pointers to the preferred version for a given backend.
NOTE allows for empty space in line as it could be left by the template engine
Flags to control compliance with the behavior of AsciiDoc
The backend determines the format of the rendered output, default to html5
The default document type Can influence markup generated by render templates
Default extensions for the respective base backends
Default page widths for calculating absolute widths
The endline character to use when rendering output
attributes which be changed within the content of the document (but not header) because it has semantic meaning; ex. numbered
Flag to indicate whether encoding of external strings needs to be forced to UTF-8 All input data must be force encoded to UTF-8 if Encoding.default_external is not UTF-8 Address failures performing string operations that are reported as “invalid byte sequence in US-ASCII” Ruby 1.8 doesn't seem to experience this problem (perhaps because it isn't validating the encodings)
Flag to indicate that line length should be calculated using a unicode mode hint
LIST_CONTEXTS = [:ulist, :olist, :dlist, :colist]
TODO validate use of explicit style name above ordered list (this list is for selecting an implicit style)
can appear anywhere
must be bordered by non-word characters
NOTE these substituions are processed in the order they appear here and the order in which they are replaced is important
The following pattern, which appears frequently, captures the contents between square brackets, ignoring escaped closing brackets (closing brackets prefixed with a backslash '' character)
Pattern: (?:[((?:\]|[^]])*?)]) Matches:
or [enclosed [text] here]
NOTE in Ruby 1.8.7, [^\] does not match start of line, so we need to match it explicitly order is significant
The root path of the Asciidoctor gem
Public: Parse the AsciiDoc source input into an Asciidoctor::Document
Accepts input as an IO (or StringIO), String or String Array object. If the input is a File, information about the file is stored in attributes on the Document object.
input - the AsciiDoc source as a IO, String or Array. options - a String, Array or Hash of options to control processing (default: {})
String and Array values are converted into a Hash. See Asciidoctor::Document#initialize for details about options.
returns the Asciidoctor::Document
# File lib/asciidoctor.rb, line 742 def self.load(input, options = {}) if (monitor = options.fetch(:monitor, false)) start = Time.now end attrs = (options[:attributes] ||= {}) if attrs.is_a?(Hash) || (RUBY_ENGINE == 'jruby' && attrs.is_a?(Java::JavaUtil::Map)) # all good; placed here as optimization elsif attrs.is_a? Array attrs = options[:attributes] = attrs.inject({}) do |accum, entry| k, v = entry.split '=', 2 accum[k] = v || '' accum end elsif attrs.is_a? String # convert non-escaped spaces into null character, so we split on the # correct spaces chars, and restore escaped spaces attrs = attrs.gsub(REGEXP[:space_delim], "\\1\00"").gsub(REGEXP[:escaped_space], '\1') attrs = options[:attributes] = attrs.split("\00"").inject({}) do |accum, entry| k, v = entry.split '=', 2 accum[k] = v || '' accum end elsif attrs.respond_to?('keys') && attrs.respond_to?('[]') # convert it to a Hash as we know it original_attrs = attrs attrs = options[:attributes] = {} original_attrs.keys.each do |key| attrs[key] = original_attrs[key] end else raise ArgumentError, "illegal type for attributes option: #{attrs.class.ancestors}" end lines = nil if input.is_a? File lines = input.readlines input_mtime = input.mtime input_path = File.expand_path(input.path) # hold off on setting infile and indir until we get a better sense of their purpose attrs['docfile'] = input_path attrs['docdir'] = File.dirname(input_path) attrs['docname'] = File.basename(input_path, File.extname(input_path)) attrs['docdate'] = input_mtime.strftime('%Y-%m-%d') attrs['doctime'] = input_mtime.strftime('%H:%M:%S %Z') attrs['docdatetime'] = [attrs['docdate'], attrs['doctime']] * ' ' elsif input.respond_to?(:readlines) input.rewind rescue nil lines = input.readlines elsif input.is_a?(String) lines = input.lines.entries elsif input.is_a?(Array) lines = input.dup else raise "Unsupported input type: #{input.class}" end if monitor read_time = Time.now - start start = Time.now end doc = Document.new(lines, options) if monitor parse_time = Time.now - start monitor[:read] = read_time monitor[:parse] = parse_time monitor[:load] = read_time + parse_time end doc end
Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document
Accepts input as an IO, String or String Array object. If the input is a File, information about the file is stored in attributes on the Document.
input - the String AsciiDoc source filename options - a String, Array or Hash of options to control processing (default: {})
String and Array values are converted into a Hash. See Asciidoctor::Document#initialize for details about options.
returns the Asciidoctor::Document
# File lib/asciidoctor.rb, line 827 def self.load_file(filename, options = {}) Asciidoctor.load(File.new(filename), options) end
Public: Parse the AsciiDoc source input into an Asciidoctor::Document and render it to the specified backend format
Accepts input as an IO, String or String Array object. If the input is a File, information about the file is stored in attributes on the Document.
If the :in_place option is true, and the input is a File, the output is written to a file adjacent to the input file, having an extension that corresponds to the backend format. Otherwise, if the :to_file option is specified, the file is written to that file. If :to_file is not an absolute path, it is resolved relative to :to_dir, if given, otherwise the Asciidoctor::Document#base_dir. If the target directory does not exist, it will not be created unless the :mkdirs option is set to true. If the file cannot be written because the target directory does not exist, or because it falls outside of the Asciidoctor::Document#base_dir in safe mode, an IOError is raised.
If the output is going to be written to a file, the header and footer are rendered unless specified otherwise (writing to a file implies creating a standalone document). Otherwise, the header and footer are not rendered by default and the rendered output is returned.
input - the String AsciiDoc source filename options - a String, Array or Hash of options to control processing (default: {})
String and Array values are converted into a Hash. See Asciidoctor::Document#initialize for details about options.
returns the Document object if the rendered result String is written to a file, otherwise the rendered result String
# File lib/asciidoctor.rb, line 860 def self.render(input, options = {}) in_place = options.delete(:in_place) || false to_file = options.delete(:to_file) to_dir = options.delete(:to_dir) mkdirs = options.delete(:mkdirs) || false monitor = options.fetch(:monitor, false) write_in_place = in_place && input.is_a?(File) write_to_target = to_file || to_dir stream_output = !to_file.nil? && to_file.respond_to?(:write) if write_in_place && write_to_target raise ArgumentError, 'the option :in_place cannot be used with either the :to_dir or :to_file option' end if !options.has_key?(:header_footer) && (write_in_place || write_to_target) options[:header_footer] = true end doc = Asciidoctor.load(input, options) if to_file == '/dev/null' return doc elsif write_in_place to_file = File.join(File.dirname(input.path), "#{doc.attributes['docname']}#{doc.attributes['outfilesuffix']}") elsif !stream_output && write_to_target working_dir = options.has_key?(:base_dir) ? File.expand_path(options[:base_dir]) : File.expand_path(Dir.pwd) # QUESTION should the jail be the working_dir or doc.base_dir??? jail = doc.safe >= SafeMode::SAFE ? working_dir : nil if to_dir to_dir = doc.normalize_system_path(to_dir, working_dir, jail, :target_name => 'to_dir', :recover => false) if to_file to_file = doc.normalize_system_path(to_file, to_dir, nil, :target_name => 'to_dir', :recover => false) # reestablish to_dir as the final target directory (in the case to_file had directory segments) to_dir = File.dirname(to_file) else to_file = File.join(to_dir, "#{doc.attributes['docname']}#{doc.attributes['outfilesuffix']}") end elsif to_file to_file = doc.normalize_system_path(to_file, working_dir, jail, :target_name => 'to_dir', :recover => false) # establish to_dir as the final target directory (in the case to_file had directory segments) to_dir = File.dirname(to_file) end if !File.directory? to_dir if mkdirs Helpers.require_library 'fileutils' FileUtils.mkdir_p to_dir else raise IOError, "target directory does not exist: #{to_dir}" end end end start = Time.now if monitor output = doc.render if monitor render_time = Time.now - start monitor[:render] = render_time monitor[:load_render] = monitor[:load] + render_time end if to_file start = Time.now if monitor if stream_output to_file.write output.rstrip # ensure there's a trailing endline to_file.write EOL else File.open(to_file, 'w') {|file| file.write output } # these assignments primarily for testing, diagnostics or reporting doc.attributes['outfile'] = outfile = File.expand_path(to_file) doc.attributes['outdir'] = File.dirname(outfile) end if monitor write_time = Time.now - start monitor[:write] = write_time monitor[:total] = monitor[:load_render] + write_time end # NOTE document cannot control this behavior if safe >= SafeMode::SERVER if !stream_output && doc.safe < SafeMode::SECURE && (doc.attr? 'basebackend-html') && (doc.attr? 'linkcss') && (doc.attr? 'copycss') copy_asciidoctor_stylesheet = DEFAULT_STYLESHEET_KEYS.include?(stylesheet = (doc.attr 'stylesheet')) #copy_user_stylesheet = !copy_asciidoctor_stylesheet && (doc.attr? 'copycss') copy_coderay_stylesheet = (doc.attr? 'source-highlighter', 'coderay') && (doc.attr 'coderay-css', 'class') == 'class' copy_pygments_stylesheet = (doc.attr? 'source-highlighter', 'pygments') && (doc.attr 'pygments-css', 'class') == 'class' if copy_asciidoctor_stylesheet || copy_coderay_stylesheet || copy_pygments_stylesheet Helpers.require_library 'fileutils' outdir = doc.attr('outdir') stylesdir = doc.normalize_system_path(doc.attr('stylesdir'), outdir, doc.safe >= SafeMode::SAFE ? outdir : nil) Helpers.mkdir_p stylesdir if mkdirs if copy_asciidoctor_stylesheet File.open(File.join(stylesdir, DEFAULT_STYLESHEET_NAME), 'w') {|f| f.write Asciidoctor::HTML5.default_asciidoctor_stylesheet } end #if copy_user_stylesheet #end if copy_coderay_stylesheet File.open(File.join(stylesdir, 'asciidoctor-coderay.css'), 'w') {|f| f.write Asciidoctor::HTML5.default_coderay_stylesheet } end if copy_pygments_stylesheet File.open(File.join(stylesdir, 'asciidoctor-pygments.css'), 'w') {|f| f.write Asciidoctor::HTML5.pygments_stylesheet(doc.attr 'pygments-style') } end end end doc else output end end
Public: Parse the contents of the AsciiDoc source file into an Asciidoctor::Document and render it to the specified backend format
input - the String AsciiDoc source filename options - a String, Array or Hash of options to control processing (default: {})
String and Array values are converted into a Hash. See Asciidoctor::Document#initialize for details about options.
returns the Document object if the rendered result String is written to a file, otherwise the rendered result String
# File lib/asciidoctor.rb, line 992 def self.render_file(filename, options = {}) Asciidoctor.render(File.new(filename), options) end