kramdown-parser-gfm-1.1.0/0000755000175000017500000000000013705271207014756 5ustar boutilboutilkramdown-parser-gfm-1.1.0/kramdown-parser-gfm.gemspec0000644000175000017500000000560613705271207022215 0ustar boutilboutil######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: kramdown-parser-gfm 1.1.0 ruby lib Gem::Specification.new do |s| s.name = "kramdown-parser-gfm".freeze s.version = "1.1.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Thomas Leitner".freeze] s.date = "2019-05-29" s.email = "t_leitner@gmx.at".freeze s.files = ["CONTRIBUTERS".freeze, "COPYING".freeze, "VERSION".freeze, "lib/kramdown-parser-gfm.rb".freeze, "lib/kramdown/parser/gfm.rb".freeze, "lib/kramdown/parser/gfm/options.rb".freeze, "test/test_files.rb".freeze, "test/testcases/atx_header.html".freeze, "test/testcases/atx_header.text".freeze, "test/testcases/backticks_syntax.html".freeze, "test/testcases/backticks_syntax.options".freeze, "test/testcases/backticks_syntax.text".freeze, "test/testcases/codeblock_fenced.html".freeze, "test/testcases/codeblock_fenced.options".freeze, "test/testcases/codeblock_fenced.text".freeze, "test/testcases/hard_line_breaks.html".freeze, "test/testcases/hard_line_breaks.text".freeze, "test/testcases/hard_line_breaks_off.html".freeze, "test/testcases/hard_line_breaks_off.options".freeze, "test/testcases/hard_line_breaks_off.text".freeze, "test/testcases/header_ids.html".freeze, "test/testcases/header_ids.options".freeze, "test/testcases/header_ids.text".freeze, "test/testcases/header_ids_with_prefix.html".freeze, "test/testcases/header_ids_with_prefix.options".freeze, "test/testcases/header_ids_with_prefix.text".freeze, "test/testcases/no_typographic.html".freeze, "test/testcases/no_typographic.options".freeze, "test/testcases/no_typographic.text".freeze, "test/testcases/paragraph_end-disabled.html".freeze, "test/testcases/paragraph_end-disabled.options".freeze, "test/testcases/paragraph_end-disabled.text".freeze, "test/testcases/paragraph_end.html".freeze, "test/testcases/paragraph_end.text".freeze, "test/testcases/strikethrough.html".freeze, "test/testcases/strikethrough.text".freeze, "test/testcases/task_list.html".freeze, "test/testcases/task_list.text".freeze, "test/testcases/two_para_hard_line_breaks.html".freeze, "test/testcases/two_para_hard_line_breaks.text".freeze] s.homepage = "https://github.com/kramdown/parser-gfm".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3".freeze) s.rubygems_version = "3.1.2".freeze s.summary = "kramdown-parser-gfm provides a kramdown parser for the GFM dialect of Markdown".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_runtime_dependency(%q.freeze, ["~> 2.0"]) else s.add_dependency(%q.freeze, ["~> 2.0"]) end end kramdown-parser-gfm-1.1.0/test/0000755000175000017500000000000013705271207015735 5ustar boutilboutilkramdown-parser-gfm-1.1.0/test/testcases/0000755000175000017500000000000013705271207017733 5ustar boutilboutilkramdown-parser-gfm-1.1.0/test/testcases/two_para_hard_line_breaks.text0000644000175000017500000000012013705271207026002 0ustar boutilboutilThis is just a normal paragraph. Containing a line break. Another paragraph. kramdown-parser-gfm-1.1.0/test/testcases/two_para_hard_line_breaks.html0000644000175000017500000000014413705271207025770 0ustar boutilboutil

This is just a normal paragraph.
Containing a line break.

Another paragraph.

kramdown-parser-gfm-1.1.0/test/testcases/task_list.text0000644000175000017500000000057313705271207022643 0ustar boutilboutilunordered task list - [ ] first ul task item - [x] second ul task item - [X] third ul task item - [ ] fourth ul task item [ ] next unordered list - > first ul item - - test - second ul item ordered list 1. first ol item 2. second ol item ordered task list 1. [ ] first ol task item 2. [x] second ol task item 3. [X] third ol task item 4. [ ] fourth ol task item kramdown-parser-gfm-1.1.0/test/testcases/task_list.html0000644000175000017500000000276113705271207022624 0ustar boutilboutil

unordered task list

unordered list

ordered list

  1. first ol item
  2. second ol item

ordered task list

  1. first ol task item
  2. second ol task item
  3. third ol task item
  4. fourth ol task item
kramdown-parser-gfm-1.1.0/test/testcases/strikethrough.text0000644000175000017500000000104613705271207023544 0ustar boutilboutil~~This is a test~~ ~~~This is another test~~~ ~~This is yet another test~~~ ~~ This is a test of it NOT working ~~ ~~ This is a **multiline** test ~~ This is an ~~_inline_ **strikethrough**~~ test This is an \~~escaped~~ strikethrough. This is a ~~strikethrough with a ~ in the middle~~ I ~~don't even~~~ have an extra tilde. This should ~~not be struck. This ~~is a complex *strike* through *test ~~with nesting~~ involved* here~~. This ~~is a complex *strike* through *test~~ with apparent nesting ~~involved* here~~. ~~中文~~ ~~a~~ kramdown-parser-gfm-1.1.0/test/testcases/strikethrough.html0000644000175000017500000000145113705271207023524 0ustar boutilboutil

This is a test

~This is another test~

This is yet another test~

~~ This is a test of it NOT working ~~

~~
This
is
a
multiline
test
~~

This is an inline strikethrough test

This is an ~~escaped~~ strikethrough.

This is a strikethrough with a ~ in the middle

I don’t even~ have an extra tilde.

This should ~~not be struck.

This is a complex strike through *test ~~with nesting involved* here~~.

This is a complex strike through *test with apparent nesting involved* here.

中文

a

kramdown-parser-gfm-1.1.0/test/testcases/paragraph_end.text0000644000175000017500000000030313705271207023430 0ustar boutilboutilA - b This is a list - or is it blockquote > text header # text codeblock fenced ``` puts hello world ``` * level 1 some text begin level 2 * level 2 * level 2 # h1 ## h2 ### h3 kramdown-parser-gfm-1.1.0/test/testcases/paragraph_end.html0000644000175000017500000000066113705271207023417 0ustar boutilboutil

A

This is a list

blockquote

text

header

text

codeblock fenced

puts hello world

h1

h2

h3

kramdown-parser-gfm-1.1.0/test/testcases/paragraph_end-disabled.text0000644000175000017500000000030313705271207025175 0ustar boutilboutilA - b This is a list - or is it blockquote > text header # text codeblock fenced ``` puts hello world ``` * level 1 some text begin level 2 * level 2 * level 2 # h1 ## h2 ### h3 kramdown-parser-gfm-1.1.0/test/testcases/paragraph_end-disabled.options0000644000175000017500000000002013705271207025700 0ustar boutilboutil:gfm_quirks: [] kramdown-parser-gfm-1.1.0/test/testcases/paragraph_end-disabled.html0000644000175000017500000000054213705271207025162 0ustar boutilboutil

A
- b

This is a list
- or is it

blockquote
> text

header
# text

codeblock fenced
puts hello world

h1

## h2
### h3

kramdown-parser-gfm-1.1.0/test/testcases/no_typographic.text0000644000175000017500000000010413705271207023661 0ustar boutilboutil### Header with --ndash ### with --- << typographic >> ... symbols kramdown-parser-gfm-1.1.0/test/testcases/no_typographic.options0000644000175000017500000000004313705271207024372 0ustar boutilboutil:gfm_quirks: [no_auto_typographic] kramdown-parser-gfm-1.1.0/test/testcases/no_typographic.html0000644000175000017500000000023013705271207023641 0ustar boutilboutil

Header with --ndash

with --- << typographic >> ... symbols

kramdown-parser-gfm-1.1.0/test/testcases/header_ids_with_prefix.text0000644000175000017500000000002213705271207025332 0ustar boutilboutil# Header 1 # 123 kramdown-parser-gfm-1.1.0/test/testcases/header_ids_with_prefix.options0000644000175000017500000000005013705271207026042 0ustar boutilboutil:auto_ids: true :auto_id_prefix: hallo- kramdown-parser-gfm-1.1.0/test/testcases/header_ids_with_prefix.html0000644000175000017500000000010313705271207025312 0ustar boutilboutil

Header 1

123

kramdown-parser-gfm-1.1.0/test/testcases/header_ids.text0000644000175000017500000000044213705271207022730 0ustar boutilboutil### test {#myid} ### variable_name ### abc def öúß ### 192 abc 192 ### ;.;; ### variable_name ### variable_name ### ;; ### before after tab ### with `code` ### with  ä space ### With "smart" quotes ### with --- << typographic >> ... symbols ### with $$m=5$$ kramdown-parser-gfm-1.1.0/test/testcases/header_ids.options0000644000175000017500000000002013705271207023427 0ustar boutilboutil:auto_ids: true kramdown-parser-gfm-1.1.0/test/testcases/header_ids.html0000644000175000017500000000116213705271207022710 0ustar boutilboutil

test

variable_name

abc def öúß

192 abc 192

;.;;

variable_name

variable_name

;;

before after tab

with code

with  ä space

With “smart” quotes

with — « typographic » … symbols

with

kramdown-parser-gfm-1.1.0/test/testcases/hard_line_breaks_off.text0000644000175000017500000000020013705271207024737 0ustar boutilboutilThis is just a normal paragraph. Containing a manual line break above. It was the best of times,\ it was the worst of times. kramdown-parser-gfm-1.1.0/test/testcases/hard_line_breaks_off.options0000644000175000017500000000002213705271207025450 0ustar boutilboutil:hard_wrap: false kramdown-parser-gfm-1.1.0/test/testcases/hard_line_breaks_off.html0000644000175000017500000000022713705271207024730 0ustar boutilboutil

This is just a normal paragraph.
Containing a manual line break above.

It was the best of times,
it was the worst of times.

kramdown-parser-gfm-1.1.0/test/testcases/hard_line_breaks.text0000644000175000017500000000002013705271207024105 0ustar boutilboutilone _two_ three kramdown-parser-gfm-1.1.0/test/testcases/hard_line_breaks.html0000644000175000017500000000005213705271207024072 0ustar boutilboutil

one
two
three

kramdown-parser-gfm-1.1.0/test/testcases/codeblock_fenced.text0000644000175000017500000000034513705271207024074 0ustar boutilboutilnormal ```ruby require 'kramdown' Kramdown::Document.new(text).to_html ``` indent with tab ```ruby require 'kramdown' Kramdown::Document.new(text).to_html ``` indent with 2 spaces ```js console.log("hello"); ``` kramdown-parser-gfm-1.1.0/test/testcases/codeblock_fenced.options0000644000175000017500000000002713705271207024600 0ustar boutilboutil:enable_coderay: false kramdown-parser-gfm-1.1.0/test/testcases/codeblock_fenced.html0000644000175000017500000000157113705271207024056 0ustar boutilboutil

normal

require 'kramdown'

Kramdown::Document.new(text).to_html

indent with tab

```ruby
require 'kramdown'

Kramdown::Document.new(text).to_html
```

indent with 2 spaces

  console.log("hello");
kramdown-parser-gfm-1.1.0/test/testcases/backticks_syntax.text0000644000175000017500000000023313705271207024203 0ustar boutilboutil``` Three backticks ``` ```` Four backticks ```` ``` Unbalanced bottom heavy `````` ````ruby language no space ```` ```` ruby language with space ```` kramdown-parser-gfm-1.1.0/test/testcases/backticks_syntax.options0000644000175000017500000000002713705271207024713 0ustar boutilboutil:enable_coderay: false kramdown-parser-gfm-1.1.0/test/testcases/backticks_syntax.html0000644000175000017500000000105413705271207024165 0ustar boutilboutil
Three backticks
Four backticks
Unbalanced bottom heavy
language no space
language with space
kramdown-parser-gfm-1.1.0/test/testcases/atx_header.text0000644000175000017500000000002513705271207022742 0ustar boutilboutil# header #no header kramdown-parser-gfm-1.1.0/test/testcases/atx_header.html0000644000175000017500000000004313705271207022722 0ustar boutilboutil

header

#no header

kramdown-parser-gfm-1.1.0/test/test_files.rb0000644000175000017500000000204713705271207020426 0ustar boutilboutil# -*- coding: utf-8 -*- # #-- # Copyright (C) 2019 Thomas Leitner # # This file is part of kramdown-parser-gfm which is licensed under the MIT. #++ # require 'minitest/autorun' require 'kramdown' require 'kramdown/parser/gfm' require 'yaml' require 'tmpdir' Encoding.default_external = 'utf-8' class TestFiles < Minitest::Test # Generate test methods for gfm-to-html conversion Dir[__dir__ + '/testcases/**/*.text'].each do |text_file| basename = text_file.sub(/\.text$/, '') html_file = basename + '.html' next unless File.exist?(html_file) define_method('test_gfm_' + File.basename(text_file, '.*') + '_to_html') do opts_file = basename + '.options' opts_file = File.join(File.dirname(html_file), 'options') if !File.exist?(opts_file) options = File.exist?(opts_file) ? YAML::load(File.read(opts_file)) : {auto_ids: false, footnote_nr: 1} doc = Kramdown::Document.new(File.read(text_file), options.merge(input: 'GFM')) assert_equal(File.read(html_file), doc.to_html) end end end kramdown-parser-gfm-1.1.0/lib/0000755000175000017500000000000013705271207015524 5ustar boutilboutilkramdown-parser-gfm-1.1.0/lib/kramdown/0000755000175000017500000000000013705271207017346 5ustar boutilboutilkramdown-parser-gfm-1.1.0/lib/kramdown/parser/0000755000175000017500000000000013705271207020642 5ustar boutilboutilkramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm/0000755000175000017500000000000013705271207021413 5ustar boutilboutilkramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm/options.rb0000644000175000017500000000340113705271207023431 0ustar boutilboutil# -*- coding: utf-8; frozen_string_literal: true -*- # #-- # Copyright (C) 2019 Thomas Leitner # # This file is part of kramdown-parser-gfm which is licensed under the MIT. #++ # module Kramdown module Options define(:hard_wrap, Boolean, true, <<~EOF) Interprets line breaks literally Insert HTML `
` tags inside paragraphs where the original Markdown document had newlines (by default, Markdown ignores these newlines). Default: true Used by: GFM parser EOF define(:gfm_quirks, Object, [:paragraph_end], <<~EOF) do |val| Enables a set of GFM specific quirks The way how GFM is transformed on Github often differs from the way kramdown does things. Many of these differences are negligible but others are not. This option allows one to enable/disable certain GFM quirks, i.e. ways in which GFM parsing differs from kramdown parsing. The value has to be a list of quirk names that should be enabled, separated by commas. Possible names are: * paragraph_end Disables the kramdown restriction that at least one blank line has to be used after a paragraph before a new block element can be started. Note that if this quirk is used, lazy line wrapping does not fully work anymore! * no_auto_typographic Disables automatic conversion of some characters into their corresponding typographic symbols (like `--` to em-dash etc). This helps to achieve results closer to what GitHub Flavored Markdown produces. Default: paragraph_end Used by: GFM parser EOF val = simple_array_validator(val, :gfm_quirks) val.map! { |v| str_to_sym(v.to_s) } val end end end kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm.rb0000644000175000017500000001636113705271207021747 0ustar boutilboutil# -*- coding: utf-8; frozen_string_literal: true -*- # #-- # Copyright (C) 2019 Thomas Leitner # # This file is part of kramdown-parser-gfm which is licensed under the MIT. #++ # require 'kramdown/options' require 'kramdown/parser/kramdown' require_relative 'gfm/options' module Kramdown module Parser # This class provides a parser implementation for the GFM dialect of Markdown. class GFM < Kramdown::Parser::Kramdown VERSION = '1.1.0' attr_reader :paragraph_end 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 def parse super update_elements(@root) end 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 the raw text for automatic ID generation. 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 NON_WORD_RE = /[^\p{Word}\- \t]/.freeze 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 ATX_HEADER_START = /^(?\#{1,6})[\t ]+(?.*)\n/.freeze define_parser(:atx_header_gfm, ATX_HEADER_START, nil, 'parse_atx_header') define_parser(:atx_header_gfm_quirk, ATX_HEADER_START) # Copied from kramdown/parser/kramdown/header.rb, removed the first line 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 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 define_parser(:codeblock_fenced_gfm, FENCED_CODEBLOCK_START, nil, 'parse_codeblock_fenced') STRIKETHROUGH_DELIM = /~~/.freeze STRIKETHROUGH_MATCH = /#{STRIKETHROUGH_DELIM}(?!\s|~).*?[^\s~]#{STRIKETHROUGH_DELIM}/m.freeze define_parser(:strikethrough_gfm, STRIKETHROUGH_MATCH, '~~') 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 LIST_TYPES = [:ul, :ol].freeze # 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). def parse_list super current_list = @tree.children.select { |element| LIST_TYPES.include?(element.type) }.last is_tasklist = false box_unchecked = '' box_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 ESCAPED_CHARS_GFM = /\\([\\.*_+`<>()\[\]{}#!:\|"'\$=\-~])/.freeze define_parser(:escaped_chars_gfm, ESCAPED_CHARS_GFM, '\\\\', :parse_escaped_chars) PARAGRAPH_END_GFM = Regexp.union( LAZY_END, LIST_START, ATX_HEADER_START, DEFINITION_LIST_START, BLOCKQUOTE_START, FENCED_CODEBLOCK_START ) private 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 end end end kramdown-parser-gfm-1.1.0/lib/kramdown-parser-gfm.rb0000644000175000017500000000035613705271207021740 0ustar boutilboutil# -*- coding: utf-8; frozen_string_literal: true -*- # #-- # Copyright (C) 2019 Thomas Leitner # # This file is part of kramdown-parser-gfm which is licensed under the MIT. #++ # require_relative 'kramdown/parser/gfm' kramdown-parser-gfm-1.1.0/VERSION0000644000175000017500000000000613705271207016022 0ustar boutilboutil1.1.0 kramdown-parser-gfm-1.1.0/COPYING0000644000175000017500000000211113705271207016004 0ustar boutilboutilkramdown-parser-gfm Copyright (C) 2019 Thomas Leitner Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. kramdown-parser-gfm-1.1.0/CONTRIBUTERS0000644000175000017500000000015613705271207016626 0ustar boutilboutilCount Name ======= ==== 15 Ashwin Maroli 5 Thomas Leitner