def extract(text)
      escape_char = ::Asciidoctor::Substitutors::RS
      @callouts.clear

      text.each_line.with_index(1).map { |line, ln|
        line.gsub(@callout_rx) do
          match = $LAST_MATCH_INFO
          if match[1] == escape_char
            # We have to use sub since we aren't sure it's the first char.
            match[0].sub(escape_char, '')
          else
            (@callouts[ln] ||= []) << match[3].to_i
            nil
          end
        end
      }.join
    end
def extract(text)
      escape_char = ::Asciidoctor::Substitutors::RS
      @callouts.clear

      text.each_line.with_index(1).map { |line, ln|
        line.gsub(@callout_rx) do
          match = $LAST_MATCH_INFO
          if match[1] == escape_char
            # We have to use sub since we aren't sure it's the first char.
            match[0].sub(escape_char, '')
          else
            (@callouts[ln] ||= []) << match[3].to_i
            nil
          end
        end
      }.join
    end
Extracts and stashes callout markers from the given *text* for
 reinsertion after processing.

 This should be used prior passing the source to a code highlighter.

 @param text [#each_line] source of the listing block.
 @return [String] a copy of the *text* with callout marks removed.