From 5571dc766e2143e39762ff0b47c41d1c2e154f4c Mon Sep 17 00:00:00 2001 From: Benjamin Sanders Date: Sat, 11 Oct 2025 10:34:24 -0400 Subject: Vendor bundled gems for deployment --- .../lib/kramdown/parser/gfm.rb | 220 +++++++++++++++++++++ .../lib/kramdown/parser/gfm/options.rb | 60 ++++++ 2 files changed, 280 insertions(+) create mode 100644 vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm.rb create mode 100644 vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm/options.rb (limited to 'vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown') diff --git a/vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm.rb b/vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm.rb new file mode 100644 index 0000000..c803e12 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm.rb @@ -0,0 +1,220 @@ +# -*- 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 diff --git a/vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm/options.rb b/vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm/options.rb new file mode 100644 index 0000000..2fcd787 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/kramdown-parser-gfm-1.1.0/lib/kramdown/parser/gfm/options.rb @@ -0,0 +1,60 @@ +# -*- 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 -- cgit v1.2.3