class Kramdown::Parser::GFM
This class provides a parser implementation for the GFM
dialect of Markdown.
Constants
- ATX_HEADER_START
- ESCAPED_CHARS_GFM
- FENCED_CODEBLOCK_MATCH
- FENCED_CODEBLOCK_START
- LIST_TYPES
- NON_WORD_RE
- PARAGRAPH_END_GFM
- STRIKETHROUGH_DELIM
- STRIKETHROUGH_MATCH
- VERSION
Attributes
paragraph_end[R]
Public Class Methods
new(source, options)
click to toggle source
Calls superclass method
# File lib/kramdown/parser/gfm.rb, line 24 def initialize(source, options) super @options[:auto_id_stripping] = true @id_counter = Hash.new(-1) @span_parsers.delete(:line_break) if @options[:hard_wrap] @span_parsers.delete(:typographic_syms) if @options[:gfm_quirks].include?(:no_auto_typographic) if @options[:gfm_quirks].include?(:paragraph_end) atx_header_parser = :atx_header_gfm_quirk @paragraph_end = self.class::PARAGRAPH_END_GFM else atx_header_parser = :atx_header_gfm @paragraph_end = self.class::PARAGRAPH_END end {codeblock_fenced: :codeblock_fenced_gfm, atx_header: atx_header_parser}.each do |current, replacement| i = @block_parsers.index(current) @block_parsers.delete(current) @block_parsers.insert(i, replacement) end i = @span_parsers.index(:escaped_chars) @span_parsers[i] = :escaped_chars_gfm if i @span_parsers << :strikethrough_gfm @hard_line_break = "#{@options[:hard_wrap] ? '' : '\\'}\n" end
Public Instance Methods
generate_gfm_header_id(text)
click to toggle source
# File lib/kramdown/parser/gfm.rb, line 107 def generate_gfm_header_id(text) result = text.downcase result.gsub!(NON_WORD_RE, '') result.tr!(" \t", '-') @id_counter[result] += 1 counter_result = @id_counter[result] result << "-#{counter_result}" if counter_result > 0 @options[:auto_id_prefix] + result end
parse()
click to toggle source
Calls superclass method
# File lib/kramdown/parser/gfm.rb, line 54 def parse super update_elements(@root) end
parse_atx_header_gfm_quirk()
click to toggle source
Copied from kramdown/parser/kramdown/header.rb, removed the first line
# File lib/kramdown/parser/gfm.rb, line 124 def parse_atx_header_gfm_quirk text, id = parse_header_contents text.sub!(/[\t ]#+\z/, '') && text.rstrip! return false if text.empty? add_header(@src["level"].length, text, id) true end
parse_list()
click to toggle source
To handle task-lists we override the parse method for lists, converting matching text into checkbox input elements where necessary (as well as applying classes to the ul/ol and li elements).
Calls superclass method
# File lib/kramdown/parser/gfm.rb, line 162 def parse_list super current_list = @tree.children.select { |element| LIST_TYPES.include?(element.type) }.last is_tasklist = false box_unchecked = '<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />' box_checked = '<input type="checkbox" class="task-list-item-checkbox" ' \ 'disabled="disabled" checked="checked" />' current_list.children.each do |li| list_items = li.children next unless !list_items.empty? && list_items[0].type == :p # li -> p -> raw_text descendant = list_items[0].children[0].value checked = descendant.gsub!(/\A\s*\[ \]\s+/, box_unchecked) unchecked = descendant.gsub!(/\A\s*\[x\]\s+/i, box_checked) is_tasklist ||= checked || unchecked li.attr['class'] = 'task-list-item' if is_tasklist end current_list.attr['class'] = 'task-list' if is_tasklist true end
parse_strikethrough_gfm()
click to toggle source
# File lib/kramdown/parser/gfm.rb, line 141 def parse_strikethrough_gfm line_number = @src.current_line_number @src.pos += @src.matched_size el = Element.new(:html_element, 'del', {}, category: :span, line: line_number) @tree.children << el env = save_env reset_env(src: Kramdown::Utils::StringScanner.new(@src.matched[2..-3], line_number), text_type: :text) parse_spans(el) restore_env(env) el end
update_elements(element)
click to toggle source
# File lib/kramdown/parser/gfm.rb, line 59 def update_elements(element) element.children.map! do |child| if child.type == :text && child.value.include?(@hard_line_break) update_text_type(element, child) elsif child.type == :html_element child elsif child.type == :header && @options[:auto_ids] && !child.attr.key?('id') child.attr['id'] = generate_gfm_header_id(child.options[:raw_text]) child else update_elements(child) child end end.flatten! end
update_raw_text(item)
click to toggle source
Update the raw text for automatic ID generation.
# File lib/kramdown/parser/gfm.rb, line 76 def update_raw_text(item) raw_text = +'' append_text = lambda do |child| case child.type when :text, :codespan, :math raw_text << child.value when :entity raw_text << child.value.char when :smart_quote raw_text << ::Kramdown::Utils::Entities.entity(child.value.to_s).char when :typographic_sym raw_text << case child.value when :laquo_space "« " when :raquo_space " »" else ::Kramdown::Utils::Entities.entity(child.value.to_s).char end else child.children.each { |c| append_text.call(c) } end end append_text.call(item) item.options[:raw_text] = raw_text end
Private Instance Methods
update_text_type(element, child)
click to toggle source
# File lib/kramdown/parser/gfm.rb, line 199 def update_text_type(element, child) children = [] lines = child.value.split(@hard_line_break, -1) omit_trailing_br = (lines[-1].empty? && Kramdown::Element.category(element) == :block && element.children[-1] == child) lines.each_with_index do |line, index| new_element_options = {location: child.options[:location] + index} children << Element.new(:text, (index > 0 ? "\n#{line}" : line), nil, new_element_options) if index < lines.size - 2 || (index == lines.size - 2 && !omit_trailing_br) children << Element.new(:br, nil, nil, new_element_options) end end children end