class Kramdown::Parser::GFM
Constants
- ATX_HEADER_START
- ESCAPED_CHARS_GFM
- FENCED_CODEBLOCK_MATCH
- FENCED_CODEBLOCK_START
- NON_WORD_RE
- PARAGRAPH_END_GFM
- STRIKETHROUGH_DELIM
- STRIKETHROUGH_MATCH
Public Class Methods
new(source, options)
click to toggle source
Calls superclass method
Kramdown::Parser::Kramdown::new
# File lib/kramdown/parser/gfm.rb 16 def initialize(source, options) 17 super 18 @options[:auto_id_stripping] = true 19 @id_counter = Hash.new(-1) 20 21 @span_parsers.delete(:line_break) if @options[:hard_wrap] 22 @span_parsers.delete(:typographic_syms) if @options[:gfm_quirks].include?(:no_auto_typographic) 23 if @options[:gfm_quirks].include?(:paragraph_end) 24 atx_header_parser = :atx_header_gfm_quirk 25 @paragraph_end = self.class::PARAGRAPH_END_GFM 26 else 27 atx_header_parser = :atx_header_gfm 28 @paragraph_end = self.class::PARAGRAPH_END 29 end 30 31 {:codeblock_fenced => :codeblock_fenced_gfm, 32 :atx_header => atx_header_parser}.each do |current, replacement| 33 i = @block_parsers.index(current) 34 @block_parsers.delete(current) 35 @block_parsers.insert(i, replacement) 36 end 37 38 i = @span_parsers.index(:escaped_chars) 39 @span_parsers[i] = :escaped_chars_gfm if i 40 @span_parsers << :strikethrough_gfm 41 end
Public Instance Methods
generate_gfm_header_id(text)
click to toggle source
# File lib/kramdown/parser/gfm.rb 105 def generate_gfm_header_id(text) 106 result = text.downcase 107 result.gsub!(NON_WORD_RE, '') 108 result.tr!(" \t", '-') 109 @id_counter[result] += 1 110 result << (@id_counter[result] > 0 ? "-#{@id_counter[result]}" : '') 111 @options[:auto_id_prefix] + result 112 end
paragraph_end()
click to toggle source
# File lib/kramdown/parser/gfm.rb 181 def paragraph_end 182 @paragraph_end 183 end
parse()
click to toggle source
Calls superclass method
Kramdown::Parser::Kramdown#parse
# File lib/kramdown/parser/gfm.rb 43 def parse 44 super 45 update_elements(@root) 46 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 119 def parse_atx_header_gfm_quirk 120 text, id = parse_header_contents 121 text.sub!(/[\t ]#+\z/, '') && text.rstrip! 122 return false if text.empty? 123 add_header(@src["level"].length, text, id) 124 true 125 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
Kramdown::Parser::Kramdown#parse_list
# File lib/kramdown/parser/gfm.rb 153 def parse_list 154 super 155 current_list = @tree.children.select{ |element| [:ul, :ol].include?(element.type) }.last 156 157 is_tasklist = false 158 box_unchecked = '<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />' 159 box_checked = '<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />' 160 161 current_list.children.each do |li| 162 next unless li.children.size > 0 && li.children[0].type == :p 163 # li -> p -> raw_text 164 checked = li.children[0].children[0].value.gsub!(/\A\s*\[ \]\s+/, box_unchecked) 165 unchecked = li.children[0].children[0].value.gsub!(/\A\s*\[x\]\s+/i, box_checked) 166 is_tasklist ||= (!checked.nil? || !unchecked.nil?) 167 168 li.attr['class'] = 'task-list-item' if is_tasklist 169 end 170 171 current_list.attr['class'] = 'task-list' if is_tasklist 172 173 true 174 end
parse_strikethrough_gfm()
click to toggle source
# File lib/kramdown/parser/gfm.rb 135 def parse_strikethrough_gfm 136 line_number = @src.current_line_number 137 138 @src.pos += @src.matched_size 139 el = Element.new(:html_element, 'del', {}, :category => :span, :line => line_number) 140 @tree.children << el 141 142 env = save_env 143 reset_env(:src => Kramdown::Utils::StringScanner.new(@src.matched[2..-3], line_number), 144 :text_type => :text) 145 parse_spans(el) 146 restore_env(env) 147 148 el 149 end
update_elements(element)
click to toggle source
# File lib/kramdown/parser/gfm.rb 48 def update_elements(element) 49 element.children.map! do |child| 50 if child.type == :text && @options[:hard_wrap] && child.value =~ /\n/ 51 children = [] 52 lines = child.value.split(/\n/, -1) 53 omit_trailing_br = (Kramdown::Element.category(element) == :block && element.children[-1] == child && 54 lines[-1].empty?) 55 lines.each_with_index do |line, index| 56 new_element_options = { :location => child.options[:location] + index } 57 58 children << Element.new(:text, (index > 0 ? "\n#{line}" : line), nil, new_element_options) 59 children << Element.new(:br, nil, nil, new_element_options) if index < lines.size - 2 || 60 (index == lines.size - 2 && !omit_trailing_br) 61 end 62 children 63 elsif child.type == :html_element 64 child 65 elsif child.type == :header && @options[:auto_ids] && !child.attr.has_key?('id') 66 child.attr['id'] = generate_gfm_header_id(child.options[:raw_text]) 67 child 68 else 69 update_elements(child) 70 child 71 end 72 end.flatten! 73 end
update_raw_text(item)
click to toggle source
Update the raw text for automatic ID generation.
# File lib/kramdown/parser/gfm.rb 76 def update_raw_text(item) 77 raw_text = '' 78 79 append_text = lambda do |child| 80 if child.type == :text || child.type == :codespan || child.type ==:math 81 raw_text << child.value 82 elsif child.type == :entity 83 raw_text << child.value.char 84 elsif child.type == :smart_quote 85 raw_text << ::Kramdown::Utils::Entities.entity(child.value.to_s).char 86 elsif child.type == :typographic_sym 87 if child.value == :laquo_space 88 raw_text << "« " 89 elsif child.value == :raquo_space 90 raw_text << " »" 91 else 92 raw_text << ::Kramdown::Utils::Entities.entity(child.value.to_s).char 93 end 94 else 95 child.children.each {|c| append_text.call(c)} 96 end 97 end 98 99 append_text.call(item) 100 item.options[:raw_text] = raw_text 101 end