class Asciidoctor::IncludeExt::IncludeProcessor
Asciidoctor
preprocessor for processing `include::<target>[]` directives in the source document.
Attributes
Public Class Methods
@param selectors [Array<Class>] an array of selectors that can filter
specified portions of the document to include (see <http://asciidoctor.org/docs/user-manual#include-partial>).
@param logger [Logger] the logger to use for logging warning and errors
from this object and selectors.
# File lib/asciidoctor/include_ext/include_processor.rb, line 25 def initialize(selectors: [LinenoLinesSelector, TagLinesSelector], logger: Logging.default_logger, **) super @selectors = selectors.dup.freeze @logger = logger end
Public Instance Methods
@param reader [Asciidoctor::Reader] @param target [String] name of the source file to include as specified
in the target slot of the `include::[]` directive.
@param attributes [Hash<String, String>] parsed attributes of the
`include::[]` directive.
# File lib/asciidoctor/include_ext/include_processor.rb, line 37 def process(_, reader, target, attributes) unless include_allowed? target, reader reader.unshift_line("link:#{target}[]") return end if (max_depth = reader.exceeded_max_depth?) logger.error "#{reader.line_info}: maximum include depth of #{max_depth} exceeded" return end unless (path = resolve_target_path(target, reader)) if attributes.key? 'optional-option' reader.shift else logger.error "#{reader.line_info}: include target not found: #{target}" unresolved_include!(target, reader) end return end selector = lines_selector_for(target, attributes) begin lines = read_lines(path, selector) rescue => e # rubocop:disable RescueWithoutErrorClass logger.error "#{reader.line_info}: failed to read include file: #{path}: #{e}" unresolved_include!(target, reader) return end if selector && selector.respond_to?(:first_included_lineno) incl_offset = selector.first_included_lineno end unless lines.empty? reader.push_include(lines, path, target, incl_offset || 1, attributes) end end
Protected Instance Methods
@param target (see process
) @param reader (see process
) @return [Boolean] `true` if it's allowed to include the target,
`false` otherwise.
# File lib/asciidoctor/include_ext/include_processor.rb, line 84 def include_allowed?(target, reader) doc = reader.document return false if doc.safe >= ::Asciidoctor::SafeMode::SECURE return false if doc.attributes.fetch('max-include-depth', 64).to_i < 1 return false if target_uri?(target) && !doc.attributes.key?('allow-uri-read') true end
Finds and initializes a lines selector that can handle the specified include.
@param target (see process
) @param attributes (see process
) @return [#to_proc, nil] an instance of lines selector, or `nil` if not found.
# File lib/asciidoctor/include_ext/include_processor.rb, line 127 def lines_selector_for(target, attributes) if (klass = @selectors.find { |s| s.handles? target, attributes }) klass.new(target, attributes, logger: logger) end end
Reads the specified file as individual lines, filters them using the selector (if provided) and returns those lines in an array.
@param filename [String] path of the file to be read. @param selector [#to_proc, nil] predicate to filter lines that should be
included in the output. It must accept two arguments: line and the line number. If `nil` is given, all lines are passed.
@return [Array<String>] an array of read lines.
# File lib/asciidoctor/include_ext/include_processor.rb, line 114 def read_lines(filename, selector) if selector IO.foreach(filename).select.with_index(1, &selector) else open(filename, &:read) end end
@param target (see process
) @param reader (see process
) @return [String, nil] file path or URI of the target, or `nil` if not found.
# File lib/asciidoctor/include_ext/include_processor.rb, line 96 def resolve_target_path(target, reader) return target if target_uri? target # Include file is resolved relative to dir of the current include, # or base_dir if within original docfile. path = reader.document.normalize_system_path(target, reader.dir, nil, target_name: 'include file') path if ::File.file?(path) end
Replaces the include directive in ouput with a notice that it has not been resolved.
@param target (see process
) @param reader (see process
)
# File lib/asciidoctor/include_ext/include_processor.rb, line 138 def unresolved_include!(target, reader) reader.unshift_line("Unresolved directive in #{reader.path} - include::#{target}[]") end
Private Instance Methods
@param target (see process
) @return [Boolean] `true` if the target is an URI, `false` otherwise.
# File lib/asciidoctor/include_ext/include_processor.rb, line 146 def target_uri?(target) ::Asciidoctor::Helpers.uriish?(target) end