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 =~ / /
    warn "** space(s) in cross-reference '#{href}' -- are you trying to use section references?"
  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 (...)
  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]
      # 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' => href, 'section' => m[1], 'sectionFormat' => 'bare', 'text' => m[2] }
    @tree.children << Element.new(:xref, nil, attr1)
    @tree.children << Element.new(:text, m[3] || last_join || " of ", {})
  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}
    if ascii_name = @src[2]
      attr["asciiFullname"] = ascii_name
    end
    el = Element.new(:contact, nil, attr)
  else
    href = @src[3]
    attr = {}
    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)
      when /\A(.*), (#{SECTIONS_RE})\z/
        href = $1
        handle_bares($2, attr, "comma", href)
      when /\A(.*) \((#{SECTIONS_RE})\)\z/
        href = $1
        handle_bares($2, attr, "parens", href)
      when /\A(#{XREF_BASE})<(.+)\z/
        href = $2
        attr['section'] = $1
        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
    href = self.class.idref_cleanup(href)
    attr['target'] = href
    el = Element.new(:xref, nil, attr)
  end
  @tree.children << el
end