Class: Kramdown::Parser::GFM
- Inherits:
-
Kramdown
- Object
- Kramdown
- Kramdown::Parser::GFM
- Defined in:
- lib/kramdown/parser/gfm.rb
Overview
This class provides a parser implementation for the GFM dialect of Markdown.
Constant Summary collapse
- VERSION =
'1.1.0'
- NON_WORD_RE =
/[^\p{Word}\- \t]/.freeze
- ATX_HEADER_START =
/^(?<level>\#{1,6})[\t ]+(?<contents>.*)\n/.freeze
- FENCED_CODEBLOCK_START =
/^[ ]{0,3}[~`]{3,}/.freeze
- FENCED_CODEBLOCK_MATCH =
/^[ ]{0,3}(([~`]){3,})\s*?((\S+?)(?:\?\S*)?)?\s*?\n(.*?)^[ ]{0,3}\1\2*\s*?\n/m.freeze
- STRIKETHROUGH_DELIM =
/~~/.freeze
- STRIKETHROUGH_MATCH =
/#{STRIKETHROUGH_DELIM}(?!\s|~).*?[^\s~]#{STRIKETHROUGH_DELIM}/m.freeze
- LIST_TYPES =
[:ul, :ol].freeze
- ESCAPED_CHARS_GFM =
/\\([\\.*_+`<>()\[\]{}#!:\|"'\$=\-~])/.freeze
- PARAGRAPH_END_GFM =
Regexp.union( LAZY_END, LIST_START, ATX_HEADER_START, DEFINITION_LIST_START, BLOCKQUOTE_START, FENCED_CODEBLOCK_START )
Instance Attribute Summary collapse
-
#paragraph_end ⇒ Object
readonly
Returns the value of attribute paragraph_end.
Instance Method Summary collapse
- #generate_gfm_header_id(text) ⇒ Object
-
#initialize(source, options) ⇒ GFM
constructor
A new instance of GFM.
- #parse ⇒ Object
-
#parse_atx_header_gfm_quirk ⇒ Object
Copied from kramdown/parser/kramdown/header.rb, removed the first line.
-
#parse_list ⇒ Object
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).
- #parse_strikethrough_gfm ⇒ Object
- #update_elements(element) ⇒ Object
-
#update_raw_text(item) ⇒ Object
Update the raw text for automatic ID generation.
Constructor Details
#initialize(source, options) ⇒ GFM
Returns a new instance of GFM.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/kramdown/parser/gfm.rb', line 25 def initialize(source, ) 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 |
Instance Attribute Details
#paragraph_end ⇒ Object (readonly)
Returns the value of attribute paragraph_end.
23 24 25 |
# File 'lib/kramdown/parser/gfm.rb', line 23 def paragraph_end @paragraph_end end |
Instance Method Details
#generate_gfm_header_id(text) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/kramdown/parser/gfm.rb', line 108 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 ⇒ Object
55 56 57 58 |
# File 'lib/kramdown/parser/gfm.rb', line 55 def parse super update_elements(@root) end |
#parse_atx_header_gfm_quirk ⇒ Object
Copied from kramdown/parser/kramdown/header.rb, removed the first line
125 126 127 128 129 130 131 132 |
# File 'lib/kramdown/parser/gfm.rb', line 125 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 ⇒ Object
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).
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/kramdown/parser/gfm.rb', line 163 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 ⇒ Object
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/kramdown/parser/gfm.rb', line 142 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) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/kramdown/parser/gfm.rb', line 60 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.[:raw_text]) child else update_elements(child) child end end.flatten! end |
#update_raw_text(item) ⇒ Object
Update the raw text for automatic ID generation.
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/kramdown/parser/gfm.rb', line 77 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.[:raw_text] = raw_text end |