Class: Asciidoctor::AbstractNode
- Inherits:
-
Object
- Object
- Asciidoctor::AbstractNode
- Includes:
- Logging, Substitutors
- Defined in:
- lib/asciidoctor/abstract_node.rb
Overview
all content segments in an AsciiDoc document.
Direct Known Subclasses
Constant Summary
Constants included from Substitutors
Substitutors::CAN, Substitutors::CGI, Substitutors::DEL, Substitutors::ESC_R_SB, Substitutors::HighlightedPassSlotRx, Substitutors::PASS_END, Substitutors::PASS_START, Substitutors::PLUS, Substitutors::PassSlotRx, Substitutors::QuotedTextSniffRx, Substitutors::RS, Substitutors::R_SB, Substitutors::SUB_GROUPS, Substitutors::SUB_HINTS, Substitutors::SUB_OPTIONS, Substitutors::SpecialCharsRx, Substitutors::SpecialCharsTr
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
Get the Hash of attributes for this node.
-
#context ⇒ Object
readonly
Get the Symbol context for this node.
-
#document ⇒ Object
readonly
Get the Asciidoctor::Document to which this node belongs.
-
#id ⇒ Object
Get/Set the String id of this node.
-
#node_name ⇒ Object
readonly
Get the String name of this node.
-
#parent ⇒ Object
Get the AbstractBlock parent element of this node.
Instance Method Summary collapse
-
#add_role(name) ⇒ Boolean
Adds the given role directly to this node.
-
#attr(name, default_value = nil, fallback_name = nil) ⇒ Object
Get the value of the specified attribute.
-
#attr?(name, expected_value = nil, fallback_name = nil) ⇒ Boolean
Check if the specified attribute is defined using the same logic as #attr, optionally performing a comparison with the expected value if specified.
-
#block? ⇒ Boolean
Returns whether this AbstractNode is an instance of Block.
-
#converter ⇒ Object
Get the Asciidoctor::Converter instance being used to convert the current Asciidoctor::Document.
-
#enabled_options ⇒ Set
Retrieve the Set of option names that are enabled on this node.
-
#generate_data_uri(target_image, asset_dir_key = nil) ⇒ A
Generate a data URI that can be used to embed an image in the output document.
-
#generate_data_uri_from_uri(image_uri, cache_uri = false) ⇒ A
Read the image data from the specified URI and generate a data URI.
-
#has_role?(name) ⇒ Boolean
Checks if the specified role is present in the list of roles for this node.
-
#icon_uri(name) ⇒ A
Construct a reference or data URI to an icon image for the specified icon name.
-
#image_uri(target_image, asset_dir_key = 'imagesdir') ⇒ A
Construct a URI reference or data URI to the target image.
-
#initialize(parent, context, opts = {}) ⇒ AbstractNode
constructor
A new instance of AbstractNode.
-
#inline? ⇒ Boolean
Returns whether this AbstractNode is an instance of Inline.
-
#is_uri?(str) ⇒ Boolean
deprecated
Deprecated.
Do not use this in new code, and replace it when updating old code.
-
#media_uri(target, asset_dir_key = 'imagesdir') ⇒ A
Construct a URI reference to the target media.
-
#normalize_asset_path(asset_ref, asset_name = 'path', autocorrect = true) ⇒ Object
Normalize the asset file or directory to a concrete and rinsed path.
-
#normalize_system_path(target, start = nil, jail = nil, opts = {}) ⇒ String
Resolve and normalize a secure path from the target and start paths using the PathResolver.
-
#normalize_web_path(target, start = nil, preserve_uri_target = true) ⇒ String
Normalize the web path using the PathResolver.
-
#option?(name) ⇒ Boolean
A convenience method to check if the specified option attribute is enabled on the current node.
-
#read_asset(path, opts = {}) ⇒ String
Read the contents of the file at the specified path.
-
#read_contents(target, opts = {}) ⇒ Object
Resolve the URI or system path to the specified target, then read and return its contents.
-
#reftext ⇒ Object
A convenience method that returns the value of the reftext attribute with substitutions applied.
-
#reftext? ⇒ Boolean
A convenience method that checks if the reftext attribute is defined.
-
#remove_attr(name) ⇒ String
Remove the attribute from the current node.
-
#remove_role(name) ⇒ Boolean
Removes the given role directly from this node.
-
#role ⇒ String
Retrieves the space-separated String role for this node.
-
#role?(expected_value = nil) ⇒ Boolean
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.
-
#roles ⇒ Array
Retrieves the String role names for this node as an Array.
-
#set_attr(name, value = '', overwrite = true) ⇒ Boolean
Assign the value to the attribute name for the current node.
-
#set_option(name) ⇒ Object
Set the specified option on this node.
-
#update_attributes(new_attributes) ⇒ Hash
Update the attributes of this node with the new values in the attributes argument.
Methods included from Substitutors
#apply_header_subs, #apply_normal_subs, #apply_reftext_subs, #apply_subs, #expand_subs, #extract_passthroughs, #highlight_source, #resolve_block_subs, #resolve_lines_to_highlight, #resolve_pass_subs, #resolve_subs, #restore_passthroughs, #sub_attributes, #sub_callouts, #sub_macros, #sub_post_replacements, #sub_quotes, #sub_replacements, #sub_source, #sub_specialchars
Methods included from Logging
#logger, #message_with_context
Constructor Details
#initialize(parent, context, opts = {}) ⇒ AbstractNode
Returns a new instance of AbstractNode.
27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/asciidoctor/abstract_node.rb', line 27 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 |
Instance Attribute Details
#attributes ⇒ Object (readonly)
Get the Hash of attributes for this node
10 11 12 |
# File 'lib/asciidoctor/abstract_node.rb', line 10 def attributes @attributes end |
#context ⇒ Object (readonly)
Get the Symbol context for this node
13 14 15 |
# File 'lib/asciidoctor/abstract_node.rb', line 13 def context @context end |
#document ⇒ Object (readonly)
Get the Asciidoctor::Document to which this node belongs
16 17 18 |
# File 'lib/asciidoctor/abstract_node.rb', line 16 def document @document end |
#id ⇒ Object
Get/Set the String id of this node
19 20 21 |
# File 'lib/asciidoctor/abstract_node.rb', line 19 def id @id end |
#node_name ⇒ Object (readonly)
Get the String name of this node
22 23 24 |
# File 'lib/asciidoctor/abstract_node.rb', line 22 def node_name @node_name end |
#parent ⇒ Object
Get the AbstractBlock parent element of this node
25 26 27 |
# File 'lib/asciidoctor/abstract_node.rb', line 25 def parent @parent end |
Instance Method Details
#add_role(name) ⇒ Boolean
Adds the given role directly to this node.
222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/asciidoctor/abstract_node.rb', line 222 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 |
#attr(name, default_value = nil, fallback_name = nil) ⇒ Object
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).
86 87 88 |
# File 'lib/asciidoctor/abstract_node.rb', line 86 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 |
#attr?(name, expected_value = nil, fallback_name = nil) ⇒ Boolean
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.
105 106 107 108 109 110 111 |
# File 'lib/asciidoctor/abstract_node.rb', line 105 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 |
#block? ⇒ Boolean
Returns whether this Asciidoctor::AbstractNode is an instance of Block
43 44 45 46 47 |
# File 'lib/asciidoctor/abstract_node.rb', line 43 def block? # :nocov: raise ::NotImplementedError # :nocov: end |
#converter ⇒ Object
Get the Asciidoctor::Converter instance being used to convert the current Asciidoctor::Document.
60 61 62 |
# File 'lib/asciidoctor/abstract_node.rb', line 60 def converter @document.converter end |
#enabled_options ⇒ Set
Retrieve the Set of option names that are enabled on this node
167 168 169 |
# File 'lib/asciidoctor/abstract_node.rb', line 167 def ::Set.new.tap {|accum| @attributes.each_key {|k| accum << (k.slice 0, k.length - 7) if k.to_s.end_with? '-option' } } end |
#generate_data_uri(target_image, asset_dir_key = nil) ⇒ A
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.
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'lib/asciidoctor/abstract_node.rb', line 355 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 |
#generate_data_uri_from_uri(image_uri, cache_uri = false) ⇒ A
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.
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
# File 'lib/asciidoctor/abstract_node.rb', line 391 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 |
#has_role?(name) ⇒ Boolean
Checks if the specified role is present in the list of roles for this node.
214 215 216 217 |
# File 'lib/asciidoctor/abstract_node.rb', line 214 def has_role? name # NOTE center + include? is faster than split + include? (val = @attributes['role']) ? (%( #{val} ).include? %( #{name} )) : false end |
#icon_uri(name) ⇒ A
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.
281 282 283 284 285 286 287 288 289 290 |
# File 'lib/asciidoctor/abstract_node.rb', line 281 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 |
#image_uri(target_image, asset_dir_key = 'imagesdir') ⇒ A
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.
311 312 313 314 315 316 317 318 319 320 321 322 323 |
# 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 = 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 |
#inline? ⇒ Boolean
Returns whether this Asciidoctor::AbstractNode is an instance of Inline
52 53 54 55 56 |
# File 'lib/asciidoctor/abstract_node.rb', line 52 def inline? # :nocov: raise ::NotImplementedError # :nocov: end |
#is_uri?(str) ⇒ Boolean
Do not use this in new code, and replace it when updating old code.
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
552 553 554 |
# File 'lib/asciidoctor/abstract_node.rb', line 552 def is_uri? str Helpers.uriish? str end |
#media_uri(target, asset_dir_key = 'imagesdir') ⇒ A
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).
339 340 341 |
# File 'lib/asciidoctor/abstract_node.rb', line 339 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) ⇒ Object
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.
419 420 421 |
# File 'lib/asciidoctor/abstract_node.rb', line 419 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 = {}) ⇒ String
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).
448 449 450 451 452 453 454 455 456 457 458 459 460 |
# File 'lib/asciidoctor/abstract_node.rb', line 448 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 unless start jail = doc.base_dir unless jail end doc.path_resolver.system_path target, start, jail, opts end |
#normalize_web_path(target, start = nil, preserve_uri_target = true) ⇒ String
Normalize the web path using the PathResolver.
See PathResolver#web_path for details about path resolution and encoding.
471 472 473 474 475 476 477 |
# File 'lib/asciidoctor/abstract_node.rb', line 471 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 |
#option?(name) ⇒ Boolean
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.
148 149 150 |
# File 'lib/asciidoctor/abstract_node.rb', line 148 def option? name @attributes[%(#{name}-option)] ? true : false end |
#read_asset(path, opts = {}) ⇒ String
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.
492 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/asciidoctor/abstract_node.rb', line 492 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 |
#read_contents(target, opts = {}) ⇒ Object
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.
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 |
# File 'lib/asciidoctor/abstract_node.rb', line 520 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] (Helpers.prepare_source_string ::OpenURI.open_uri(target, URI_READ_MODE) {|f| f.read }).join LF else ::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 return end else logger.warn %(cannot retrieve contents of #{opts[:label] || 'asset'} at URI: #{target} (allow-uri-read attribute not enabled)) if opts.fetch :warn_on_failure, true return end else target = normalize_system_path target, opts[:start], nil, target_name: (opts[:label] || 'asset') read_asset target, normalize: opts[:normalize], warn_on_failure: (opts.fetch :warn_on_failure, true), label: opts[:label] end end |
#reftext ⇒ Object
A convenience method that returns the value of the reftext attribute with substitutions applied.
254 255 256 |
# File 'lib/asciidoctor/abstract_node.rb', line 254 def reftext (val = @attributes['reftext']) ? (apply_reftext_subs val) : nil end |
#reftext? ⇒ Boolean
A convenience method that checks if the reftext attribute is defined.
259 260 261 |
# File 'lib/asciidoctor/abstract_node.rb', line 259 def reftext? @attributes.key? 'reftext' end |
#remove_attr(name) ⇒ String
Remove the attribute from the current node.
135 136 137 |
# File 'lib/asciidoctor/abstract_node.rb', line 135 def remove_attr name @attributes.delete name end |
#remove_role(name) ⇒ Boolean
Removes the given role directly from this node.
240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/asciidoctor/abstract_node.rb', line 240 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 |
#role ⇒ String
Retrieves the space-separated String role for this node.
187 188 189 |
# File 'lib/asciidoctor/abstract_node.rb', line 187 def role @attributes['role'] end |
#role?(expected_value = nil) ⇒ Boolean
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.
205 206 207 |
# File 'lib/asciidoctor/abstract_node.rb', line 205 def role? expected_value = nil expected_value ? expected_value == @attributes['role'] : (@attributes.key? 'role') end |
#roles ⇒ Array
Retrieves the String role names for this node as an Array.
194 195 196 |
# File 'lib/asciidoctor/abstract_node.rb', line 194 def roles (val = @attributes['role']) ? val.split : [] end |
#set_attr(name, value = '', overwrite = true) ⇒ Boolean
Assign the value to the attribute name for the current node.
121 122 123 124 125 126 127 128 |
# File 'lib/asciidoctor/abstract_node.rb', line 121 def set_attr name, value = '', overwrite = true if overwrite == false && (@attributes.key? name) false else @attributes[name] = value true end end |
#set_option(name) ⇒ Object
Set the specified option on this node.
This method sets the specified option on this node by setting the <name>-option attribute.
159 160 161 162 |
# File 'lib/asciidoctor/abstract_node.rb', line 159 def set_option name @attributes[%(#{name}-option)] = '' nil end |
#update_attributes(new_attributes) ⇒ Hash
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.
180 181 182 |
# File 'lib/asciidoctor/abstract_node.rb', line 180 def update_attributes new_attributes @attributes.update new_attributes end |