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 common to all content segments in an AsciiDoc document.
Attributes
Public: Get the Hash
of attributes for this node
Public: Get the Symbol context for this node
Public: Get the Asciidoctor::Document
to which this node belongs
Public: Get/Set the String
id of this node
Public: Get the String
name of this node
Public: Get the AbstractBlock
parent element of this node
Public Class Methods
# File lib/asciidoctor/abstract_node.rb, line 28 def initialize parent, context, opts = {} # document is a special case, should refer to itself if context == :document @document = self elsif parent @document = (@parent = parent).document end @node_name = (@context = context).to_s # NOTE the value of the :attributes option may be nil on an Inline node @attributes = (attrs = opts[:attributes]) ? attrs.merge : {} @passthroughs = [] end
Public Instance Methods
Public: Adds the given role directly to this node.
Returns a [Boolean] indicating whether the role was added.
# File lib/asciidoctor/abstract_node.rb, line 232 def add_role name if (val = @attributes['role']) # NOTE center + include? is faster than split + include? if %( #{val} ).include? %( #{name} ) false else @attributes['role'] = %(#{val} #{name}) true end else @attributes['role'] = name true end end
Public: Get the value of the specified attribute. If the attribute is not found on this node, fallback_name is set, and this node is not the Document
node, get the value of the specified attribute from the Document
node.
Look for the specified attribute in the attributes on this node and return the value of the attribute, if found. Otherwise, if fallback_name is set (default: same as name) and this node is not the Document
node, look for that attribute on the Document
node and return its value, if found. Otherwise, return the default value (default: nil).
name - The String
or Symbol name of the attribute to resolve. default_value - The Object
value to return if the attribute is not found (default: nil). fallback_name - The String
or Symbol of the attribute to resolve on the Document
if the attribute is not found on
this node (default: same as name).
Returns the [Object] value (typically a String
) of the attribute or default_value if the attribute is not found.
# File lib/asciidoctor/abstract_node.rb, line 87 def attr name, default_value = nil, fallback_name = nil @attributes[name.to_s] || (fallback_name && @parent && @document.attributes[(fallback_name == true ? name : fallback_name).to_s] || default_value) end
Public: Check if the specified attribute is defined using the same logic as {#attr}, optionally performing a comparison with the expected value if specified.
Look for the specified attribute in the attributes on this node. If not found, fallback_name is specified (default: same as name), and this node is not the Document
node, look for that attribute on the Document
node. In either case, if the attribute is found, and the comparison value is truthy, return whether the two values match. Otherwise, return whether the attribute was found.
name - The String
or Symbol name of the attribute to resolve. expected_value - The expected Object
value of the attribute (default: nil). fallback_name - The String
or Symbol of the attribute to resolve on the Document
if the attribute is not found on
this node (default: same as name).
Returns a [Boolean] indicating whether the attribute exists and, if a truthy comparison value is specified, whether the value of the attribute matches the comparison value.
# File lib/asciidoctor/abstract_node.rb, line 106 def attr? name, expected_value = nil, fallback_name = nil if expected_value expected_value == (@attributes[name.to_s] || (fallback_name && @parent ? @document.attributes[(fallback_name == true ? name : fallback_name).to_s] : nil)) else (@attributes.key? name.to_s) || (fallback_name && @parent ? (@document.attributes.key? (fallback_name == true ? name : fallback_name).to_s) : false) end end
Public: Returns whether this {AbstractNode} is an instance of {Block}
Returns [Boolean]
# File lib/asciidoctor/abstract_node.rb, line 44 def block? # :nocov: raise ::NotImplementedError # :nocov: end
Public: Get the Asciidoctor::Converter
instance being used to convert the current Asciidoctor::Document
.
# File lib/asciidoctor/abstract_node.rb, line 61 def converter @document.converter end
Public: Retrieve the Set of option names that are enabled on this node
Returns a [Set] of option names
# File lib/asciidoctor/abstract_node.rb, line 168 def enabled_options ::Set.new.tap {|accum| @attributes.each_key {|k| accum << (k.slice 0, k.length - 7) if k.to_s.end_with? '-option' } } end
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 365 def generate_data_uri(target_image, asset_dir_key = nil) if (ext = Helpers.extname target_image, nil) mimetype = ext == '.svg' ? 'image/svg+xml' : %(image/#{ext.slice 1, ext.length}) else mimetype = 'application/octet-stream' end 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 if ::File.readable? image_path # NOTE base64 is autoloaded by reference to ::Base64 %(data:#{mimetype};base64,#{::Base64.strict_encode64 ::File.binread image_path}) else logger.warn %(image to embed not found or not readable: #{image_path}) %(data:#{mimetype};base64,) # uncomment to return 1 pixel white dot instead #'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' end end
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 401 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, bindata = ::OpenURI.open_uri(image_uri, URI_READ_MODE) {|f| [f.content_type, f.read] } # NOTE base64 is autoloaded by reference to ::Base64 %(data:#{mimetype};base64,#{::Base64.strict_encode64 bindata}) rescue logger.warn %(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
Public: Checks if the specified role is present in the list of roles for this node.
name - The String
name of the role to find.
Returns a [Boolean] indicating whether this node has the specified role.
# File lib/asciidoctor/abstract_node.rb, line 215 def has_role? name # NOTE center + include? is faster than split + include? (val = @attributes['role']) ? (%( #{val} ).include? %( #{name} )) : false end
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 291 def icon_uri name if attr? 'icon' icon = attr 'icon' # QUESTION should we be adding the extension if the icon is an absolute URI? icon = %(#{icon}.#{@document.attr 'icontype', 'png'}) unless Helpers.extname? icon else icon = %(#{name}.#{@document.attr 'icontype', 'png'}) end image_uri icon, 'iconsdir' end
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 321 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 = Helpers.encode_spaces_in_uri 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)) (doc.attr? 'allow-uri-read') ? (generate_data_uri_from_uri target_image, (doc.attr? 'cache-uri')) : target_image 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
Public: Returns whether this {AbstractNode} is an instance of {Inline}
Returns [Boolean]
# File lib/asciidoctor/abstract_node.rb, line 53 def inline? # :nocov: raise ::NotImplementedError # :nocov: end
Deprecated: Check whether the specified String
is a URI by matching it against the Asciidoctor::UriSniffRx regex.
In use by Asciidoctor
PDF
@deprecated Use Helpers.uriish?
instead
# File lib/asciidoctor/abstract_node.rb, line 563 def is_uri? str Helpers.uriish? str end
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 349 def media_uri(target, asset_dir_key = 'imagesdir') normalize_web_path target, (asset_dir_key ? @document.attr(asset_dir_key) : nil) end
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 429 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
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 automatically 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 458 def normalize_system_path target, start = nil, jail = nil, opts = {} if (doc = @document).safe < SafeMode::SAFE if start start = ::File.join doc.base_dir, start unless doc.path_resolver.root? start else start = doc.base_dir end else start ||= doc.base_dir jail ||= doc.base_dir end doc.path_resolver.system_path target, start, jail, opts end
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 481 def normalize_web_path(target, start = nil, preserve_uri_target = true) if preserve_uri_target && (Helpers.uriish? target) Helpers.encode_spaces_in_uri target else @document.path_resolver.web_path target, start end end
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 149 def option? name @attributes[%(#{name}-option)] ? true : false end
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 502 def read_asset path, opts = {} # remap opts for backwards compatibility opts = { warn_on_failure: (opts != false) } unless ::Hash === opts if ::File.readable? path # QUESTION should we chomp content if normalize is false? opts[:normalize] ? ((Helpers.prepare_source_string ::File.read path, mode: FILE_READ_MODE).join LF) : (::File.read path, mode: FILE_READ_MODE) elsif opts[:warn_on_failure] logger.warn %(#{(attr 'docfile') || '<stdin>'}: #{opts[:label] || 'file'} does not exist or cannot be read: #{path}) nil end end
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) * :warn_if_empty a Boolean that indicates whether a warning is issued if contents of target is empty (default: false)
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 531 def read_contents target, opts = {} doc = @document if (Helpers.uriish? target) || ((start = opts[:start]) && (Helpers.uriish? start) && (target = doc.path_resolver.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 if opts[:normalize] contents = (Helpers.prepare_source_string ::OpenURI.open_uri(target, URI_READ_MODE) {|f| f.read }).join LF else contents = ::OpenURI.open_uri(target, URI_READ_MODE) {|f| f.read } end rescue logger.warn %(could not retrieve contents of #{opts[:label] || 'asset'} at URI: #{target}) if opts.fetch :warn_on_failure, true end elsif opts.fetch :warn_on_failure, true logger.warn %(cannot retrieve contents of #{opts[:label] || 'asset'} at URI: #{target} (allow-uri-read attribute not enabled)) end else target = normalize_system_path target, opts[:start], nil, target_name: (opts[:label] || 'asset') contents = read_asset target, normalize: opts[:normalize], warn_on_failure: (opts.fetch :warn_on_failure, true), label: opts[:label] end logger.warn %(contents of #{opts[:label] || 'asset'} is empty: #{target}) if contents && opts[:warn_if_empty] && contents.empty? contents end
Public: A convenience method that returns the value of the reftext attribute with substitutions applied.
# File lib/asciidoctor/abstract_node.rb, line 264 def reftext (val = @attributes['reftext']) ? (apply_reftext_subs val) : nil end
Public: A convenience method that checks if the reftext attribute is defined.
# File lib/asciidoctor/abstract_node.rb, line 269 def reftext? @attributes.key? 'reftext' end
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 136 def remove_attr name @attributes.delete name end
Public: Removes the given role directly from this node.
Returns a [Boolean] indicating whether the role was removed.
# File lib/asciidoctor/abstract_node.rb, line 250 def remove_role name if (val = @attributes['role']) && ((val = val.split).delete name) if val.empty? @attributes.delete 'role' else @attributes['role'] = val.join ' ' end true else false end end
Public: Retrieves the space-separated String
role for this node.
Returns the role as a space-separated [String].
# File lib/asciidoctor/abstract_node.rb, line 188 def role @attributes['role'] end
Public: Sets the value of the role attribute on this node.
names - A single role name, a space-separated String
of role names, or an Array
of role names
Returns the specified String
role name or Array
of role names
# File lib/asciidoctor/abstract_node.rb, line 225 def role= names @attributes['role'] = (::Array === names) ? (names.join ' ') : names end
Public: Checks if the role attribute is set on this node and, if an expected value is given, whether the space-separated role matches that value.
expected_value - The expected String
value of the role (optional, default: nil)
Returns a [Boolean] indicating whether the role attribute is set on this node and, if an expected value is given, whether the space-separated role matches that value.
# File lib/asciidoctor/abstract_node.rb, line 206 def role? expected_value = nil expected_value ? expected_value == @attributes['role'] : (@attributes.key? 'role') end
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 122 def set_attr name, value = '', overwrite = true if overwrite == false && (@attributes.key? name) false else @attributes[name] = value true end end
Public: Set the specified option on this node.
This method sets the specified option on this node by setting the <name>-option attribute.
name - the String
name of the option
Returns nothing
# File lib/asciidoctor/abstract_node.rb, line 160 def set_option name @attributes[%(#{name}-option)] = '' nil end
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 overwritten.
new_attributes - A Hash
of additional attributes to assign to this node.
Returns the updated attributes [Hash] on this node.
# File lib/asciidoctor/abstract_node.rb, line 181 def update_attributes new_attributes @attributes.update new_attributes end