class Asciidoctor::AbstractNode - asciidoctor-1.5.6.2 Documentation

# class Asciidoctor::AbstractNode

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.

### Attributes

attributes[R]

Public: Get the Hash of attributes for this node

context[R]

Public: Get the Symbol context for this node

document[R]

Public: Get the Asciidoctor::Document to which this node belongs

id[RW]

Public: Get/Set the id of this node

node_name[R]

Public: Get the String name of this node

parent[R]

Public: Get the element which is the parent of this node

### Public Class Methods

new(parent, context, opts = {}) click to toggle source

    # File lib/asciidoctor/abstract_node.rb, line 27
    def initialize parent, context, opts = {}
      if context == :document
        # document is a special case, should refer to itself
        @document, @parent = self, nil
      else
        if parent
          @document, @parent = parent.document, parent
        else
          @document = @parent = nil
        end
      end
      @node_name = (@context = context).to_s
      # QUESTION are we correct in duplicating the attributes (seems to be just as fast)
      @attributes = (opts.key? :attributes) ? opts[:attributes].dup : {}
      @passthroughs = {}
    end

### Public Instance Methods

add_role(name) click to toggle source

Public: A convenience method that adds the given role directly to this node

Returns a Boolean indicating whether the role was added.

    # File lib/asciidoctor/abstract_node.rb, line 220
    def add_role(name)
      if (val = @attributes['role']).nil_or_empty?
        @attributes['role'] = name
        true
      # NOTE center + include? is faster than split + include?
      elsif %Q( #{val} ).include?(%Q( #{name} ))
        false
      else
        @attributes['role'] = %Q(#{val} #{name})
        true
      end
    end

attr(name, default_val = nil, inherit = true) click to toggle source

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 String or Symbol name of the attribute to lookup default_val - the Object value to return if the attribute is not found (default: nil) inherit - a Boolean indicating whether to check for the attribute on the

    AsciiDoctor::Document if not found on this node (default: false)

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

    # File lib/asciidoctor/abstract_node.rb, line 93
    def attr name, default_val = nil, inherit = true
      name = name.to_s
      # NOTE if @parent is set, it means @document is also set
      @attributes[name] || (inherit && @parent ? @document.attributes[name] || default_val : default_val)
    end

attr?(name, expect_val = nil, inherit = true) click to toggle source

Public: Check if the attribute is defined, optionally performing a comparison of its value if expected is not nil

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 (not nil), return whether the two values match. Otherwise, return whether the attribute was found.

name - the String or Symbol name of the attribute to lookup expect_val - the expected Object value of the attribute (default: nil) inherit - a Boolean indicating whether to check for the attribute on the

    AsciiDoctor::Document if not found on this node (default: false)

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

    # File lib/asciidoctor/abstract_node.rb, line 116
    def attr? name, expect_val = nil, inherit = true
      name = name.to_s
      # NOTE if @parent is set, it means @document is also set
      if expect_val.nil?
        (@attributes.key? name) || (inherit && @parent && (@document.attributes.key? name))
      else
        expect_val == (@attributes[name] || (inherit && @parent ? @document.attributes[name] : nil))
      end
    end

block?() click to toggle source

Public: Returns whether this {AbstractNode} is an instance of {Block}

Returns [Boolean]

    # File lib/asciidoctor/abstract_node.rb, line 63
    def block?
      # :nocov:
      raise ::NotImplementedError
      # :nocov:
    end

converter() click to toggle source

Public: Get the Asciidoctor::Converter instance being used to convert the current Asciidoctor::Document.

    # File lib/asciidoctor/abstract_node.rb, line 56
    def converter
      @document.converter
    end

generate_data_uri(target_image, asset_dir_key = nil) click to toggle source

Public: Generate a data URI that can be used to embed an image in the output document

First, and foremost, the target image path is cleaned if the document safe mode level is set to at least SafeMode::SAFE (a condition which is true by default) to prevent access to ancestor paths in the filesystem. The image data is then read and converted to Base64. Finally, a data URI is built which can be used in an image tag.

target_image - A String path to the target image 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

    # File lib/asciidoctor/abstract_node.rb, line 359
    def generate_data_uri(target_image, asset_dir_key = nil)
      ext = ::File.extname target_image
      # QUESTION what if ext is empty?
      mimetype = (ext == '.svg' ? 'image/svg+xml' : %Q(image/#{ext[1..-1]}))
      if asset_dir_key
        image_path = normalize_system_path(target_image, @document.attr(asset_dir_key), nil, :target_name => 'image')
      else
        image_path = normalize_system_path(target_image)
      end

      unless ::File.readable? image_path
        warn %Q(asciidoctor: WARNING: image to embed not found or not readable: #{image_path})
        return %Q(data:#{mimetype};base64,)
        # uncomment to return 1 pixel white dot instead
        #return 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
      end

      # NOTE base64 is autoloaded by reference to ::Base64
      %Q(data:#{mimetype};base64,#{::Base64.encode64(::IO.binread image_path).delete LF})
    end

generate_data_uri_from_uri(image_uri, cache_uri = false) click to toggle source

Public: Read the image data from the specified URI and generate a data URI

The image data is read from the URI and converted to Base64. A data URI is constructed from the content_type header and Base64 data and returned, which can then be used in an image tag.

#image_uri - The URI from which to read the image data. Can be http://, https:// or ftp:// cache_uri - A Boolean to control caching. When true, the open-uri-cached library

    is used to cache the image for subsequent reads. (default: false)

Returns A data URI string built from Base64 encoded data read from the URI and the mime type specified in the Content Type header.

    # File lib/asciidoctor/abstract_node.rb, line 392
    def generate_data_uri_from_uri image_uri, cache_uri = false
      if cache_uri
        # caching requires the open-uri-cached gem to be installed
        # processing will be automatically aborted if these libraries can't be opened
        Helpers.require_library 'open-uri/cached', 'open-uri-cached'
      elsif !::RUBY_ENGINE_OPAL
        # autoload open-uri
        ::OpenURI
      end

      begin
        mimetype = nil
        bindata = open(image_uri, 'rb') {|fd|
          mimetype = fd.content_type
          fd.read
        }
        # NOTE base64 is autoloaded by reference to ::Base64
        %Q(data:#{mimetype};base64,#{::Base64.encode64(bindata).delete LF})
      rescue
        warn %Q(asciidoctor: WARNING: could not retrieve image data from URI: #{image_uri})
        image_uri
        # uncomment to return empty data (however, mimetype needs to be resolved)
        #%(data:#{mimetype}:base64,)
        # uncomment to return 1 pixel white dot instead
        #'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
      end
    end

has_role?(name) click to toggle source

Public: A convenience method that checks if the specified role is present in the list of roles on this node

    # File lib/asciidoctor/abstract_node.rb, line 212
    def has_role?(name)
      # NOTE center + include? is faster than split + include?
      (val = @attributes['role'] || @document.attributes['role']).nil_or_empty? ? false : %Q( #{val} ).include?(%Q( #{name} ))
    end

icon_uri(name) click to toggle source

Public: Construct a reference or data URI to an icon image for the specified icon name.

If the 'icon' attribute is set on this block, the name is ignored and the value of this attribute is used as the target image path. Otherwise, construct a target image path by concatenating the value of the 'iconsdir' attribute, the icon name and the value of the 'icontype' attribute (defaulting to 'png').

The target image path is then passed through the image_uri() method. If the 'data-uri' attribute is set on the document, the image will be safely converted to a data URI.

The return value of this method can be safely used in an image tag.

name - The String name of the icon

Returns A String reference or data URI for an icon image

    # File lib/asciidoctor/abstract_node.rb, line 279
    def icon_uri name
      if attr? 'icon'
        # QUESTION should we add extension if resolved value is an absolute URI?
        if ::File.extname(uri = (image_uri attr('icon'), 'iconsdir')).empty?
          %Q(#{uri}.#{@document.attr 'icontype', 'png'})
        else
          uri
        end
      else
        image_uri %Q(#{name}.#{@document.attr 'icontype', 'png'}), 'iconsdir'
      end
    end

image_uri(target_image, asset_dir_key = 'imagesdir') click to toggle source

Public: Construct a URI 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 by reading it from the same directory. If neither of these conditions are satisfied, a relative path (i.e., URL) will be returned.

The return value of this method can be safely used in an image tag.

target_image - A String path to the target image 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

    # File lib/asciidoctor/abstract_node.rb, line 311
    def image_uri(target_image, asset_dir_key = 'imagesdir')
      if (doc = @document).safe < SafeMode::SECURE && (doc.attr? 'data-uri')
        if ((Helpers.uriish? target_image) && (target_image = uri_encode_spaces target_image)) ||
            (asset_dir_key && (images_base = doc.attr asset_dir_key) && (Helpers.uriish? images_base) &&
            (target_image = normalize_web_path target_image, images_base, false))
          if doc.attr? 'allow-uri-read'
            generate_data_uri_from_uri target_image, (doc.attr? 'cache-uri')
          else
            target_image
          end
        else
          generate_data_uri target_image, asset_dir_key
        end
      else
        normalize_web_path target_image, (asset_dir_key ? (doc.attr asset_dir_key) : nil)
      end
    end

inline?() click to toggle source

Public: Returns whether this {AbstractNode} is an instance of {Inline}

Returns [Boolean]

    # File lib/asciidoctor/abstract_node.rb, line 72
    def inline?
      # :nocov:
      raise ::NotImplementedError
      # :nocov:
    end

is_uri?(str) click to toggle source

Public: Check whether the specified String is a URI by matching it against the Asciidoctor::UriSniffRx regex.

@deprecated Use Asciidoctor::Helpers.uriish? instead

    # File lib/asciidoctor/abstract_node.rb, line 567
    def is_uri? str
      Helpers.uriish? str
    end

media_uri(target, asset_dir_key = 'imagesdir') click to toggle source

Public: Construct a URI reference to the target media.

If the target media is a URI reference, then leave it untouched.

The target media is resolved relative to the directory retrieved from the specified attribute key, if provided.

The return value can be safely used in a media tag (img, audio, video).

target - A String reference to the target media asset_dir_key - The String attribute key used to lookup the directory where

    the media is located (default: 'imagesdir')

Returns A String reference for the target media

    # File lib/asciidoctor/abstract_node.rb, line 343
    def media_uri(target, asset_dir_key = 'imagesdir')
      normalize_web_path target, (asset_dir_key ? @document.attr(asset_dir_key) : nil)
    end

normalize_asset_path(asset_ref, asset_name = 'path', autocorrect = true) click to toggle source

Public: Normalize the asset file or directory to a concrete and rinsed path

Delegates to #normalize_system_path, with the start path set to the value of the base_dir instance variable on the Document object.

    # File lib/asciidoctor/abstract_node.rb, line 424
    def normalize_asset_path(asset_ref, asset_name = 'path', autocorrect = true)
      normalize_system_path(asset_ref, @document.base_dir, nil,
          :target_name => asset_name, :recover => autocorrect)
    end

normalize_system_path(target, start = nil, jail = nil, opts = {}) click to toggle source

Public: Resolve and normalize a secure path from the target and start paths using the PathResolver.

See {PathResolver#system_path} for details.

The most important functionality in this method is to prevent resolving a path outside of the jail (which defaults to the directory of the source file, stored in the base_dir instance variable on Document) if the document safe level is set to SafeMode::SAFE or greater (a condition which is true by default).

target - the String target path start - the String start (i.e., parent) path jail - the String jail path to confine the resolved path opts - an optional Hash of options to control processing (default: {}):

    * :recover is used to control whether the processor should auto-recover
        when an illegal path is encountered
    * :target_name is used in messages to refer to the path being resolved

raises a SecurityError if a jail is specified and the resolved path is outside the jail.

Returns the [String] path resolved from the start and target paths, with any parent references resolved and self references removed. If a jail is provided, this path will be guaranteed to be contained within the jail.

    # File lib/asciidoctor/abstract_node.rb, line 454
    def normalize_system_path target, start = nil, jail = nil, opts = {}
      path_resolver = (@path_resolver ||= PathResolver.new)
      if (doc = @document).safe < SafeMode::SAFE
        if start
          start = ::File.join doc.base_dir, start unless path_resolver.root? start
        else
          start = doc.base_dir
        end
      else
        start = doc.base_dir unless start
        jail = doc.base_dir unless jail
      end
      path_resolver.system_path target, start, jail, opts
    end

normalize_web_path(target, start = nil, preserve_uri_target = true) click to toggle source

Public: Normalize the web path using the PathResolver.

See {PathResolver#web_path} for details about path resolution and encoding.

target - the String target path start - the String start (i.e, parent) path (optional, default: nil) preserve_uri_target - a Boolean indicating whether target should be preserved if contains a URI (default: true)

Returns the resolved [String] path

    # File lib/asciidoctor/abstract_node.rb, line 478
    def normalize_web_path(target, start = nil, preserve_uri_target = true)
      if preserve_uri_target && (Helpers.uriish? target)
        uri_encode_spaces target
      else
        (@path_resolver ||= PathResolver.new).web_path target, start
      end
    end

option?(name) click to toggle source

Public: A convenience method to check if the specified option attribute is enabled on the current node.

Check if the option is enabled. This method simply checks to see if the %name%-option attribute is defined on the current node.

name - the String or Symbol name of the option

return a Boolean indicating whether the option has been specified

    # File lib/asciidoctor/abstract_node.rb, line 161
    def option?(name)
      @attributes.key? %Q(#{name}-option)
    end

parent=(parent) click to toggle source

Public: Associate this Block with a new parent Block

parent - The Block to set as the parent of this Block

Returns nothing

    # File lib/asciidoctor/abstract_node.rb, line 49
    def parent=(parent)
      @parent, @document = parent, parent.document
      nil
    end

read_asset(path, opts = {}) click to toggle source

Public: Read the contents of the file at the specified path. This method assumes that the path is safe to read. It checks that the file is readable before attempting to read it.

path - the String path from which to read the contents opts - a Hash of options to control processing (default: {})

    * :warn_on_failure a Boolean that controls whether a warning
      is issued if the file cannot be read (default: false)
    * :normalize a Boolean that controls whether the lines
      are normalized and coerced to UTF-8 (default: false)

Returns the [String] content of the file at the specified path, or nil if the file does not exist.

    # File lib/asciidoctor/abstract_node.rb, line 499
    def read_asset path, opts = {}
      # remap opts for backwards compatibility
      opts = { :warn_on_failure => (opts != false) } unless ::Hash === opts
      if ::File.readable? path
        if opts[:normalize]
          Helpers.normalize_lines_from_string(::IO.read path) * LF
        else
          # QUESTION should we chomp or rstrip content?
          ::IO.read path
        end
      elsif opts[:warn_on_failure]
        warn %Q(asciidoctor: WARNING: #{(attr 'docfile') || '<stdin>'}: #{opts[:label] || 'file'} does not exist or cannot be read: #{path})
      end
    end

read_contents(target, opts = {}) click to toggle source

Public: Resolve the URI or system path to the specified target, then read and return its contents

The URI or system path of the target is first resolved. If the resolved path is a URI, read the contents from the URI if the allow-uri-read attribute is set, enabling caching if the cache-uri attribute is also set. If the resolved path is not a URI, read the contents of the file from the file system. If the normalize option is set, the data will be normalized.

target - The URI or local path from which to read the data. opts - a Hash of options to control processing (default: {})

    * :label the String label of the target to use in warning messages (default: 'asset')
    * :normalize a Boolean that indicates whether the data should be normalized (default: false)
    * :start the String relative base path to use when resolving the target (default: nil)
    * :warn_on_failure a Boolean that indicates whether warnings are issued if the target cannot be read (default: true)

Returns the contents of the resolved target or nil if the resolved target cannot be read – TODO refactor other methods in this class to use this method were possible (repurposing if necessary)

    # File lib/asciidoctor/abstract_node.rb, line 530
    def read_contents target, opts = {}
      doc = @document
      if (Helpers.uriish? target) || ((start = opts[:start]) && (Helpers.uriish? start) &&
          (target = (@path_resolver ||= PathResolver.new).web_path target, start))
        if doc.attr? 'allow-uri-read'
          Helpers.require_library 'open-uri/cached', 'open-uri-cached' if doc.attr? 'cache-uri'
          begin
            data = ::OpenURI.open_uri(target) {|fd| fd.read }
            data = (Helpers.normalize_lines_from_string data) * LF if opts[:normalize]
          rescue
            warn %Q(asciidoctor: WARNING: could not retrieve contents of #{opts[:label] || 'asset'} at URI: #{target}) if opts.fetch :warn_on_failure, true
            data = nil
          end
        else
          warn %Q(asciidoctor: WARNING: cannot retrieve contents of #{opts[:label] || 'asset'} at URI: #{target} (allow-uri-read attribute not enabled)) if opts.fetch :warn_on_failure, true
          data = nil
        end
      else
        target = normalize_system_path target, opts[:start], nil, :target_name => (opts[:label] || 'asset')
        data = read_asset target, :normalize => opts[:normalize], :warn_on_failure => (opts.fetch :warn_on_failure, true), :label => opts[:label]
      end
      data
    end

reftext() click to toggle source

Public: A convenience method that returns the value of the reftext attribute with substitutions applied.

    # File lib/asciidoctor/abstract_node.rb, line 252
    def reftext
      (val = @attributes['reftext']) ? (apply_reftext_subs val) : nil
    end

reftext?() click to toggle source

Public: A convenience method that checks if the reftext attribute is defined.

    # File lib/asciidoctor/abstract_node.rb, line 257
    def reftext?
      @attributes.key? 'reftext'
    end

remove_attr(name) click to toggle source

Public: Remove the attribute from the current node.

name - The String attribute name to remove

Returns the previous [String] value, or nil if the attribute was not present.

    # File lib/asciidoctor/abstract_node.rb, line 148
    def remove_attr name
      @attributes.delete name
    end

remove_role(name) click to toggle source

Public: A convenience method that removes the given role directly from this node

Returns a Boolean indicating whether the role was removed.

    # File lib/asciidoctor/abstract_node.rb, line 236
    def remove_role(name)
      if (val = @attributes['role']).nil_or_empty?
        false
      elsif (val = val.split).delete name
        if val.empty?
          @attributes.delete('role')
        else
          @attributes['role'] = val * ' '
        end
        true
      else
        false
      end
    end

role() click to toggle source

Public: A convenience method that returns the value of the role attribute

    # File lib/asciidoctor/abstract_node.rb, line 190
    def role
      @attributes['role'] || @document.attributes['role']
    end

role?(expect_val = nil) click to toggle source

Public: A convenience method that checks if the role attribute is specified

    # File lib/asciidoctor/abstract_node.rb, line 202
    def role? expect_val = nil
      if expect_val
        expect_val == (@attributes['role'] || @document.attributes['role'])
      else
        @attributes.key?('role') || @document.attributes.key?('role')
      end
    end

roles() click to toggle source

Public: A convenience method that returns the role names as an Array

Returns the role names as an Array or an empty Array if the role attribute is absent.

    # File lib/asciidoctor/abstract_node.rb, line 197
    def roles
      (val = @attributes['role'] || @document.attributes['role']).nil_or_empty? ? [] : val.split
    end

set_attr(name, value = '', overwrite = true) click to toggle source

Public: Assign the value to the attribute name for the current node.

name - The String attribute name to assign value - The Object value to assign to the attribute (default: '') overwrite - A Boolean indicating whether to assign the attribute

    if currently present in the attributes Hash (default: true)

Returns a [Boolean] indicating whether the assignment was performed

    # File lib/asciidoctor/abstract_node.rb, line 134
    def set_attr name, value = '', overwrite = true
      if overwrite == false && (@attributes.key? name)
        false
      else
        @attributes[name] = value
        true
      end
    end

set_option(name) click to toggle source

TODO document me

    # File lib/asciidoctor/abstract_node.rb, line 166
    def set_option(name)
      if @attributes.key? 'options'
        @attributes['options'] = %Q(#{@attributes['options']},#{name})
      else
        @attributes['options'] = name
      end
      @attributes[%Q(#{name}-option)] = ''
    end

update_attributes(attributes) click to toggle source

Public: Update the attributes of this node with the new values in the attributes argument.

If an attribute already exists with the same key, it's value will be overridden.

attributes - A Hash of attributes to assign to this node.

Returns nothing

    # File lib/asciidoctor/abstract_node.rb, line 184
    def update_attributes(attributes)
      @attributes.update(attributes)
      nil
    end

uri_encode_spaces(str) click to toggle source

Internal: URI encode spaces in a String

str - the String to encode

Returns the String with all spaces replaced with %20.

    # File lib/asciidoctor/abstract_node.rb, line 559
    def uri_encode_spaces str
      (str.include? ' ') ? (str.gsub ' ', '%20') : str
    end