class Asciidoctor::Rouge::CalloutsSubstitutor

A substitutor for processing callouts inside a source listing block.

Attributes

callouts[R]

@return [Hash<Integer, Array<Integer>>]

Public Class Methods

create(node) click to toggle source

@param node [Asciidoctor::AbstractNode] @return [CalloutsSubstitutor] a callouts substitutor for the given node.

# File lib/asciidoctor/rouge/callouts_substitutor.rb, line 17
def self.create(node)
  new(node)
end
new(node) click to toggle source

(see .create)

# File lib/asciidoctor/rouge/callouts_substitutor.rb, line 62
def initialize(node)
  @node = node
  @callouts = {}

  @callout_rx = if node.attr? 'line-comment'
    comment_rx = ::Regexp.escape(node.attr('line-comment'))
    # Copied from Asciidoctor::CalloutExtractRxt (0db74cd)
    /(?:#{comment_rx} )?(\\)?<()(\d+|\.)>(?=(?: ?\\?<(?:\d+|\.)>)*$)/
  else
    # Copied from Asciidoctor::CalloutExtractRx (0db74cd)
    %r((?:(?://|#|--|;;) ?)?(\\)?<!?(|--)(\d+|\.)\2>(?=(?: ?\\?<!?\2(?:\d+|\.)\2>)*$))
  end
end

Public Instance Methods

convert_line(line_num) click to toggle source

Converts the extracted callout markers for the specified line.

@param line_num [Integer] the line number (1-based). @return [String] converted callout markers for the line_num,

or an empty string if there are no callouts for that line.
# File lib/asciidoctor/rouge/callouts_substitutor.rb, line 51
def convert_line(line_num)
  return '' unless @callouts.key? line_num

  @callouts[line_num]
    .map { |num| convert_callout(num) }
    .join(' ')
end
extract(text) click to toggle source

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.

# File lib/asciidoctor/rouge/callouts_substitutor.rb, line 28
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

Protected Instance Methods

convert_callout(number) click to toggle source

@param number [Integer] callout number. @return [String] an HTML markup of a callout marker with the given number.

# File lib/asciidoctor/rouge/callouts_substitutor.rb, line 78
def convert_callout(number)
  ::Asciidoctor::Inline.new(@node, :callout, number, id: next_callout_id).convert
end
next_callout_id() click to toggle source

@return [Integer] an unique ID for callout.

# File lib/asciidoctor/rouge/callouts_substitutor.rb, line 83
def next_callout_id
  (@doc_callouts ||= @node.document.callouts).read_next_id
end