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

Introduce new (((target))) syntax for irefs
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

(I'd rather use [[target]], but that somehow clashes with links.)
otherwise be an ugly ![!](target) or ![ ](target)
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

only works for RFCnnnn
def rfc_mention(target1)  # only works for RFCnnnn
  target1 =~ /\A([A-Z]*)(.*)\z/
  "#$1 #$2 "
end