lib/asciidoctor/abstract_node.rb in asciidoctor-0.1.0 vs lib/asciidoctor/abstract_node.rb in asciidoctor-0.1.1

- old
+ new

@@ -1,11 +1,12 @@ +module Asciidoctor # Public: An abstract base class that provides state and methods for managing a # node of AsciiDoc content. The state and methods on this class are comment to # all content segments in an AsciiDoc document. -class Asciidoctor::AbstractNode +class AbstractNode - include Asciidoctor::Substituters + include Substituters # Public: Get the element which is the parent of this node attr_reader :parent # Public: Get the Asciidoctor::Document to which this node belongs @@ -22,34 +23,76 @@ def initialize(parent, context) @parent = (context != :document ? parent : nil) if !parent.nil? - @document = parent.is_a?(Asciidoctor::Document) ? parent : parent.document + @document = parent.is_a?(Document) ? parent : parent.document else @document = nil end @context = context @attributes = {} @passthroughs = [] end + # Public: Get the value of the specified attribute + # + # Get the value for the specified attribute. First look in the attributes on + # this node and return the value of the attribute if found. Otherwise, if + # this node is a child of the Document node, look in the attributes of the + # Document node and return the value of the attribute if found. Otherwise, + # return the default value, which defaults to nil. + # + # name - the name of the attribute to lookup as a String or Symbol + # default - the value to return if the attribute is not found (default: nil) + # + # return the value of the attribute or the default value if the attribute + # is not found in the attributes of this node or the document node def attr(name, default = nil) + name = name.to_s if name.is_a?(Symbol) if self == @document - default.nil? ? @attributes[name.to_s] : @attributes.fetch(name.to_s, default) + default.nil? ? @attributes[name] : @attributes.fetch(name, default) else - default.nil? ? @attributes.fetch(name.to_s, @document.attr(name)) : - @attributes.fetch(name.to_s, @document.attr(name, default)) + default.nil? ? @attributes.fetch(name, @document.attr(name)) : + @attributes.fetch(name, @document.attr(name, default)) end end - def attr?(name) - if self == @document - @attributes.has_key? name.to_s + # Public: Check if the attribute is defined, optionally performing a + # comparison of its value + # + # Check if the attribute is defined. First look in the attributes on this + # node. If not found, and this node is a child of the Document node, look in + # the attributes of the Document node. If the attribute is found and a + # comparison value is specified, return whether the two values match. + # Otherwise, return whether the attribute was found. + # + # name - the name of the attribute to lookup as a String or Symbol + # expect - the expected value of the attribute (default: nil) + # + # return a Boolean indicating whether the attribute exists and, if a + # comparison value is specified, whether the value of the attribute matches + # the comparison value + def attr?(name, expect = nil) + name = name.to_s if name.is_a?(Symbol) + if expect.nil? + if @attributes.has_key? name + true + elsif self != @document + @document.attributes.has_key? name + else + false + end else - @attributes.has_key?(name.to_s) || @document.attr?(name) + if @attributes.has_key? name + @attributes[name] == expect + elsif self != @document && @document.attributes.has_key?(name) + @document.attributes[name] == expect + else + false + end end end # Public: Get the execution context of this object (via Kernel#binding). # @@ -117,10 +160,12 @@ end end # Public: Construct a reference or data URI to the target image. # + # If the target image is a URI reference, then leave it untouched. + # # The target image is resolved relative to the directory retrieved from the # specified attribute key, if provided. # # If the 'data-uri' attribute is set on the document, and the safe mode level # is less than SafeMode::SECURE, the image will be safely converted to a data URI @@ -133,11 +178,13 @@ # asset_dir_key - The String attribute key used to lookup the directory where # the image is located (default: 'imagesdir') # # Returns A String reference or data URI for the target image def image_uri(target_image, asset_dir_key = 'imagesdir') - if @document.safe < Asciidoctor::SafeMode::SECURE && @document.attr?('data-uri') + if target_image.include?(':') && target_image.match(Asciidoctor::REGEXP[:uri_sniff]) + target_image + elsif @document.safe < Asciidoctor::SafeMode::SECURE && @document.attr?('data-uri') generate_data_uri(target_image, asset_dir_key) elsif asset_dir_key && attr?(asset_dir_key) File.join(@document.attr(asset_dir_key), target_image) else target_image @@ -155,11 +202,11 @@ # asset_dir_key - The String attribute key used to lookup the directory where # the image is located (default: nil) # # Returns A String data URI containing the content of the target image def generate_data_uri(target_image, asset_dir_key = nil) - Asciidoctor.require_library 'base64' + Helpers.require_library 'base64' mimetype = 'image/' + File.extname(target_image)[1..-1] if asset_dir_key image_path = File.join(normalize_asset_path(@document.attr(asset_dir_key, '.'), asset_dir_key), target_image) else @@ -223,26 +270,26 @@ # TODO this method is missing a coordinate; it should be able to resolve # both the directory reference and the path to an asset in it; callers # of this method are still doing a File.join to finish the task def normalize_asset_path(asset_ref, asset_name = 'path', autocorrect = true) # TODO we may use pathname enough to make it a top-level require - Asciidoctor.require_library 'pathname' + Helpers.require_library 'pathname' input_path = @document.base_dir asset_path = Pathname.new(asset_ref) if asset_path.relative? asset_path = File.expand_path(File.join(input_path, asset_ref)) else asset_path = asset_path.cleanpath.to_s end - if @document.safe >= Asciidoctor::SafeMode::SAFE + if @document.safe >= SafeMode::SAFE relative_asset_path = Pathname.new(asset_path).relative_path_from(Pathname.new(input_path)).to_s if relative_asset_path.start_with?('..') if autocorrect - puts 'asciidoctor: WARNING: ' + asset_name + ' has illegal reference to ancestor of base directory' + puts "asciidoctor: WARNING: #{asset_name} has illegal reference to ancestor of base directory" else raise SecurityError, "#{asset_name} has reference to path outside of base directory, disallowed in safe mode: #{asset_path}" end relative_asset_path.sub!(/^(?:\.\.\/)*/, '') # just to be absolutely sure ;) @@ -254,6 +301,7 @@ end asset_path end +end end