class Kramdown::Parser::RFC2629Kramdown
def self.idref_cleanup(href)
def self.idref_cleanup(href) # can't start an IDREF with a number or reserved start if href =~ / / if $options.v3 warn "** space(s) in cross-reference '#{href}' -- are you trying to use section references?" else warn "** space(s) in cross-reference '#{href}' -- note that section references are supported in v3 mode only." end end href.gsub(/\A(?:[0-9]|section-|u-|figure-|table-|iref-)/) { "_#{$&}" } end
def handle_bares(s, attr, format, href, last_join = nil)
def handle_bares(s, attr, format, href, last_join = nil) if s.match(/\A(#{XREF_ANY}) and (#{XREF_ANY})\z/) handle_bares($1, {}, nil, href, " and ") handle_bares($2, {}, nil, href, " of ") return end href = href.split(' ')[0] # Remove any trailing (...) target1, target2 = href.split("@", 2) multi = last_join != nil (sn, s) = s.split(' ', 2) loop do m = s.match(/\A#{XREF_RE_M}(, (?:and )?| and )?/) break if not m if not multi and not m[2] and not m[3] and not target2 # Modify |attr| if there is a single reference. This can only be # used if there is only one section reference and the section part # has no title. attr['section'] = m[1] attr['sectionFormat'] = format attr['text'] = m[2] return end if sn @tree.children << Element.new(:text, "#{sn} ", {}) sn = nil end multi = true s[m[0]] = '' attr1 = { 'target' => target1, 'section' => m[1], 'sectionFormat' => 'bare', 'text' => m[2] } @tree.children << Element.new(:xref, nil, attr1) andof = m[3] || last_join || " of " if andof == " of " && target2 andof += rfc_mention(target1) end @tree.children << Element.new(:text, andof, {}) end end
def initialize(*doc)
def initialize(*doc) super @span_parsers.unshift(:xref) @span_parsers.unshift(:iref) @span_parsers.unshift(:span_pi) @block_parsers.unshift(:block_pi) end
def parse_block_pi
def parse_block_pi # warn [:BLOCK].inspect line = @src.current_line_number if (result = @src.scan(HTML_INSTRUCTION_RE)) @tree.children << Element.new(:xml_pi, result, nil, category: :block, location: line) @src.scan(TRAILING_WHITESPACE) true else false end end
def parse_iref
def parse_iref @src.pos += @src.matched_size href = @src[1] el = Element.new(:iref, nil, {'target' => href}) # XXX @tree.children << el end
def parse_span_pi
def parse_span_pi # warn [:SPAN].inspect line = @src.current_line_number if (result = @src.scan(HTML_INSTRUCTION_RE)) @tree.children << Element.new(:xml_pi, result, nil, category: :span, location: line) else add_text(@src.getch) end end
def parse_xref
otherwise be an ugly  or 
Introduce new {{target}} syntax for empty xrefs, which would
def parse_xref @src.pos += @src.matched_size unless @src[4] == "}}" warn "*** #{@src[0]}: unmatched braces #{@src[4].inspect}" end if contact_name = @src[1] attr = {'fullname' => contact_name.gsub("\n", " ")} if ascii_name = @src[2] attr["asciiFullname"] = ascii_name.gsub("\n", " ") end el = Element.new(:contact, nil, attr) else href = @src[3] attr = {} handled_subref = false if $options.v3 # match Section ... of ...; set section, sectionFormat case href.gsub(/[\u00A0\s]+/, ' ') # may need nbsp and/or newlines when /\A(#{SECTIONS_RE}) of (.*)\z/ href = $2 handle_bares($1, attr, "of", href) handled_subref = true when /\A(.*), (#{SECTIONS_RE})\z/ href = $1 handle_bares($2, attr, "comma", href) handled_subref = true when /\A(.*) \((#{SECTIONS_RE})\)\z/ href = $1 handle_bares($2, attr, "parens", href) handled_subref = true when /#{XREF_RE_M}<(.+)\z/ href = $3 if $2 attr['section'] = $2 attr['relative'] = "#" << $1 else attr['section'] = $1 end attr['sectionFormat'] = 'bare' when /\A<<(.+)\z/ href = $1 attr['format'] = 'title' when /\A<(.+)\z/ href = $1 attr['format'] = 'counter' end end if href.match(/#{XREF_RE_M}\z/) href = $1 attr['text'] = $2 end target1, target2 = href.split("@", 2) # should do this only for sectionref... if target2 href = target2 unless handled_subref @tree.children << Element.new(:text, rfc_mention(target1), {}) end end href = self.class.idref_cleanup(href) attr['target'] = href el = Element.new(:xref, nil, attr) end @tree.children << el end
def replace_abbreviations(el, regexps = nil)
def replace_abbreviations(el, regexps = nil) unless regexps # DUPLICATED AND MODIFIED CODE FROM UPSTREAM, CHECK ON UPSTREAM UPGRADE sorted_abbrevs = @root.options[:abbrev_defs].keys.sort {|a, b| b.length <=> a.length } regexps = [Regexp.union(*sorted_abbrevs.map {|k| /#{Regexp.escape(k).gsub(/\\\s/, "[\\s\\p{Z}]+").force_encoding(Encoding::UTF_8)}/})] regexps << /(?=(?:\W|^)#{regexps.first}(?!\w))/ # regexp should only match on word boundaries # warn regexps.inspect end super(el, regexps) end
def rfc_mention(target1) # only works for RFCnnnn
def rfc_mention(target1) # only works for RFCnnnn target1 =~ /\A([A-Z]*)(.*)\z/ "#$1 #$2 " end