class StringDoc::Node
String-based XML node.
@api private
Constants
- FORM_INPUTS
- REGEX_TAGS
- SELF_CLOSING
- VALUELESS
Attributes
@api private
@api private
@api private
@api private
@api private
@api private
@api private
@api private
Public Class Methods
Returns true if tag
is a form input.
# File lib/string_doc/node.rb, line 24 def form_input?(tag) FORM_INPUTS.include?(tag) end
# File lib/string_doc/node.rb, line 48 def initialize(tag_open_start = "", attributes = Attributes.new, tag_open_end = "", children = StringDoc.empty, tag_close = "", parent: nil, significance: [], labels: {}) @tag_open_start, @attributes, @tag_open_end, @children, @tag_close = tag_open_start, attributes, tag_open_end, children, tag_close @parent, @labels, @significance = parent, labels, significance @transforms = { high: [], default: [], low: [] } @pipeline = nil @finalized_labels = {} end
Returns true if tag
is self-closing.
# File lib/string_doc/node.rb, line 18 def self_closing?(tag) SELF_CLOSING.include?(tag) end
Returns true if tag
does not contain a value.
# File lib/string_doc/node.rb, line 30 def without_value?(tag) VALUELESS.include?(tag) end
Public Instance Methods
# File lib/string_doc/node.rb, line 314 def ==(other) other.is_a?(Node) && @tag_open_start == other.tag_open_start && @attributes == other.attributes && @tag_open_end == other.tag_open_end && @children == other.children && @tag_close == other.tag_close end
Inserts node
after self
.
# File lib/string_doc/node.rb, line 220 def after(node) @parent.insert_after(node, self) end
Appends node
as a child.
# File lib/string_doc/node.rb, line 232 def append(node) children.append(node) end
Appends html
as a child.
# File lib/string_doc/node.rb, line 238 def append_html(html) children.append_html(html) end
Inserts node
before self
.
# File lib/string_doc/node.rb, line 226 def before(node) @parent.insert_before(node, self) end
Removes all children.
# File lib/string_doc/node.rb, line 214 def clear children.clear end
Close self with tag
and a child.
@api private
# File lib/string_doc/node.rb, line 121 def close(tag, child) tap do @children = StringDoc.from_nodes(child) @tag_open_end = tag ? ">" : "" @tag_close = (tag && !self.class.self_closing?(tag)) ? "</#{tag}>" : "" end end
Delete the label with name
.
# File lib/string_doc/node.rb, line 277 def delete_label(name) @labels.delete(name.to_sym) end
# File lib/string_doc/node.rb, line 323 def each(descend: false) return enum_for(:each, descend: descend) unless block_given? yield self end
# File lib/string_doc/node.rb, line 328 def each_significant_node(type, descend: false, &block) return enum_for(:each_significant_node, type, descend: descend) unless block_given? if @children.is_a?(StringDoc) @children.each_significant_node(type, descend: descend, &block) end end
# File lib/string_doc/node.rb, line 344 def each_significant_node_with_name(type, name, descend: false, &block) return enum_for(:each_significant_node_with_name, type, name, descend: descend) unless block_given? if @children.is_a?(StringDoc) @children.each_significant_node_with_name(type, name, descend: descend, &block) end end
# File lib/string_doc/node.rb, line 336 def each_significant_node_without_descending_into_type(type, descend: false, &block) return enum_for(:each_significant_node_without_descending_into_type, type, descend: descend) unless block_given? if @children.is_a?(StringDoc) @children.each_significant_node_without_descending_into_type(type, descend: descend, &block) end end
@api private
# File lib/string_doc/node.rb, line 114 def empty? to_s.strip.empty? end
# File lib/string_doc/node.rb, line 93 def finalize_labels(keep: []) @finalized_labels = @labels @labels = keep.each_with_object({}) { |key, hash| hash[key] = @finalized_labels.delete(key).deep_dup } if children.is_a?(StringDoc) children.finalize_labels(keep: keep) end end
# File lib/string_doc/node.rb, line 352 def find_first_significant_node(type, descend: false) if @children.is_a?(StringDoc) @children.find_first_significant_node(type, descend: descend) else nil end end
# File lib/string_doc/node.rb, line 360 def find_significant_nodes(type, descend: false) if @children.is_a?(StringDoc) @children.find_significant_nodes(type, descend: descend) else [] end end
# File lib/string_doc/node.rb, line 368 def find_significant_nodes_with_name(type, name, descend: false) if @children.is_a?(StringDoc) @children.find_significant_nodes_with_name(type, name, descend: descend) else [] end end
# File lib/string_doc/node.rb, line 108 def freeze(*) pipeline super end
Returns the html contained within self.
# File lib/string_doc/node.rb, line 190 def html children.to_s end
Replaces self's inner html, without making it available for further manipulation.
# File lib/string_doc/node.rb, line 196 def html=(html) @children = html.to_s end
@api private
# File lib/string_doc/node.rb, line 57 def initialize_copy(_) super @labels = @labels.deep_dup @finalized_labels = @finalized_labels.deep_dup @attributes = @attributes.dup @children = @children.dup @significance = @significance.dup @transforms = @transforms.each_with_object({}) { |(key, value), hash| hash[key] = value.dup } @pipeline = nil end
Returns the value for label with name
.
# File lib/string_doc/node.rb, line 250 def label(name) name = name.to_sym if @labels.key?(name) @labels[name.to_sym] else @finalized_labels[name.to_sym] end end
Returns true if label exists with name
.
# File lib/string_doc/node.rb, line 261 def labeled?(name) @labels.key?(name.to_sym) || @finalized_labels.key?(name.to_sym) end
# File lib/string_doc/node.rb, line 104 def labels @labels.merge(@finalized_labels) end
# File lib/string_doc/node.rb, line 129 def next_transform pipeline.shift end
Prepends node
as a child.
# File lib/string_doc/node.rb, line 244 def prepend(node) children.prepend(node) end
Removes the node.
# File lib/string_doc/node.rb, line 166 def remove(label = true, descend = true) if label set_label(:removed, true) end @parent.remove_node(self) if descend && children.is_a?(StringDoc) children.each do |child| child.remove(label, descend) end end end
# File lib/string_doc/node.rb, line 271 def removed? labeled?(:removed) end
# File lib/string_doc/node.rb, line 281 def render(output = String.new, context: nil) if transforms_itself? __transform(output, context: context) else output << tag_open_start attributes.each_string do |attribute_string| output << attribute_string end output << tag_open_end case children when StringDoc children.render(output, context: context) else output << children.to_s end output << tag_close end output end
Replaces the current node.
# File lib/string_doc/node.rb, line 160 def replace(replacement) @parent.replace_node(self, replacement) end
Replaces self's children.
# File lib/string_doc/node.rb, line 202 def replace_children(children) @children.replace(children) end
Sets the label with name
and value
.
# File lib/string_doc/node.rb, line 267 def set_label(name, value) @labels[name.to_sym] = value end
# File lib/string_doc/node.rb, line 154 def significance?(*types) (@significance & types).any? end
# File lib/string_doc/node.rb, line 146 def significant?(type = nil) if type @significance.include?(type.to_sym) else @significance.any? end end
@api private
# File lib/string_doc/node.rb, line 74 def soft_copy instance = self.class.allocate instance.instance_variable_set(:@tag_open_start, @tag_open_start) instance.instance_variable_set(:@tag_open_end, @tag_open_end) instance.instance_variable_set(:@tag_close, @tag_close) instance.instance_variable_set(:@parent, @parent) instance.instance_variable_set(:@significance, @significance) instance.instance_variable_set(:@transforms, @transforms) instance.instance_variable_set(:@finalized_labels, @finalized_labels) instance.instance_variable_set(:@attributes, @attributes.dup) instance.instance_variable_set(:@children, @children.is_a?(StringDoc) ? @children.soft_copy : @children.dup) instance.instance_variable_set(:@labels, @labels.deep_dup) instance.instance_variable_set(:@pipeline, @pipeline.dup) instance end
Returns the node's tagname.
# File lib/string_doc/node.rb, line 208 def tagname @tag_open_start.gsub(/[^a-zA-Z0-9]/, "") end
Returns the text of this node and all children, joined together.
# File lib/string_doc/node.rb, line 184 def text html.gsub(REGEX_TAGS, "") end
Returns the node as an xml string, without transforming.
# File lib/string_doc/node.rb, line 310 def to_s string_nodes.flatten.map(&:to_s).join end
# File lib/string_doc/node.rb, line 133 def transform(priority: :default, &block) @transforms[priority] << block @pipeline = nil end
# File lib/string_doc/node.rb, line 138 def transforms? transforms_itself? || @children.transforms? end
# File lib/string_doc/node.rb, line 142 def transforms_itself? pipeline.any? end
Private Instance Methods
# File lib/string_doc/node.rb, line 382 def __transform(string, context:) node = if frozen? soft_copy else self end current = node while transform = node.next_transform return_value = transform.call(node, context, string) case return_value when NilClass return when StringDoc return_value.render(string, context: context); return when Node, MetaNode if return_value.removed? return else current = return_value end else string << return_value.to_s; return end end current.render(string, context: context) end
# File lib/string_doc/node.rb, line 378 def pipeline @pipeline ||= @transforms.values.flatten end
# File lib/string_doc/node.rb, line 412 def string_nodes [@tag_open_start, @attributes, @tag_open_end, @children, @tag_close] end