class Kramdown::Parser::Base
Have a look at the Base::parse, Base::new and Base#parse methods for additional information!
the parsing code.
parser works correctly. Then you need to implement the #parse
method which has to contain
in the Kramdown::Parser module – the latter is needed so that the auto-detection of the new
Implementing a new parser is rather easy: just derive a new class from this class and put it
== Implementing a parser
only use the Base::parse method.
state information during parsing. Therefore one can’t instantiate a parser object directly but
A parser object is used as a throw-away object, i.e. it is only used for storing the needed
used by all parsers, especially by those using StringScanner(Kramdown) for parsing.
This class serves as base class for parsers. It provides common methods that can/should be
== Base class for parsers
def self.parse(source, options = {})
Initializes a new instance of the calling class and then calls the +#parse+ method that must
return the root element of the element tree and an array with warning messages.
Parse the +source+ string into an element tree, possibly using the parsing +options+, and
def self.parse(source, options = {}) parser = new(source, options) parser.parse [parser.root, parser.warnings] end
def adapt_source(source)
Modify the string +source+ to be usable by the parser (unifies line ending characters to
def adapt_source(source) unless source.valid_encoding? raise "The source text contains invalid characters for the used encoding #{source.encoding}" end source = source.encode('UTF-8') source.gsub!(/\r\n?/, "\n") source.chomp! source << "\n" end
def add_text(text, tree = @tree, type = @text_type)
This helper method adds the given +text+ either to the last element in the +tree+ if it is a
def add_text(text, tree = @tree, type = @text_type) last = tree.children.last if last && last.type == type last.value << text elsif !text.empty? location = (last && last.options[:location] || tree.options[:location]) tree.children << Element.new(type, text, nil, location: location) end end
def extract_string(range, strscan)
Extract the part of the StringScanner +strscan+ backed string specified by the +range+. This
def extract_string(range, strscan) result = nil begin enc = strscan.string.encoding strscan.string.force_encoding('ASCII-8BIT') result = strscan.string[range].force_encoding(enc) ensure strscan.string.force_encoding(enc) end result end
def initialize(source, options)
The @root element, the @warnings array and @text_type (specifies the default type for newly
Initialize the parser object with the +source+ string and the parsing +options+.
def initialize(source, options) @source = source @options = Kramdown::Options.merge(options) @root = Element.new(:root, nil, nil, encoding: (source.encoding rescue nil), location: 1, options: {}, abbrev_defs: {}, abbrev_attr: {}) @root.options[:abbrev_defs].default_proc = @root.options[:abbrev_attr].default_proc = lambda do |h, k| k_mod = k.gsub(/[\s\p{Z}]+/, " ") k != k_mod ? h[k_mod] : nil end @warnings = [] @text_type = :text end
def parse
root of which should be @root.
The parsing code should parse the source provided in @source and build an element tree the
Parse the source string into an element tree.
def parse raise NotImplementedError end
def warning(text)
def warning(text) @warnings << text # TODO: add position information end