Class: MDOM::Node
- Inherits:
-
Object
- Object
- MDOM::Node
- Defined in:
- lib/mdom/node.rb
Overview
Base class for every node in the Markdown tree.
A node carries a type (a Symbol), an ordered list of children, and
optional attributes (a Hash). The parent of a node is maintained
automatically whenever a child is appended or removed.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#attributes ⇒ Object
readonly
Returns the value of attribute attributes.
-
#children ⇒ Object
readonly
Returns the value of attribute children.
-
#parent ⇒ Object
Returns the value of attribute parent.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
Instance Method Summary collapse
-
#[](*types) ⇒ Object
Query by one or more types (Symbol or array of Symbols).
-
#ancestors ⇒ Object
The chain of ancestors, closest first.
-
#append(child) ⇒ Object
(also: #<<)
Append
childto the end of this node's children. - #children? ⇒ Boolean
-
#depth ⇒ Object
Depth in the tree: 0 at the root, 1 for its direct children, etc.
-
#each_child(&block) ⇒ Object
(also: #each)
Yield each child in order.
- #empty? ⇒ Boolean
-
#find(type = nil, &block) ⇒ Object
The first matching descendant (or self);
typemay be a Symbol or a callable, or a block may be supplied. -
#find_all(type = nil) ⇒ Object
Yield each descendant (including self) whose type matches
type, or all nodes when no type is given. -
#initialize(type, attributes: {}, children: []) ⇒ Node
constructor
-- construction -------------------------------------------------------.
-
#insert_after(node) ⇒ Object
Insert
nodeas the sibling immediately after this node. -
#insert_before(node) ⇒ Object
Insert
nodeas the sibling immediately before this node. -
#inspect ⇒ Object
A human-readable tree rendering of this node and its descendants.
-
#plain_text ⇒ Object
Concatenate the literal string content of this subtree.
-
#pretty_print(level = 0) ⇒ Object
Render this node plus its subtree as an indented, printable tree.
-
#remove ⇒ Object
Remove this node from its current parent, if any.
-
#replace(node) ⇒ Object
Replace this node in its parent with
node. -
#root ⇒ Object
The topmost ancestor (a node whose parent is nil).
-
#text? ⇒ Boolean
-- misc ---------------------------------------------------------------.
-
#to_markdown ⇒ Object
(also: #markdown)
Serialize this node (and its subtree) back to Markdown.
-
#to_s ⇒ Object
A compact, single-line summary of this node (its own type/attributes only, without recursing into children).
-
#walk(&block) ⇒ Object
Depth-first (preorder) traversal that yields this node then its descendants, depth-first.
Constructor Details
#initialize(type, attributes: {}, children: []) ⇒ Node
-- construction -------------------------------------------------------
15 16 17 18 19 20 21 |
# File 'lib/mdom/node.rb', line 15 def initialize(type, attributes: {}, children: []) @type = type @attributes = attributes @children = [] @parent = nil children.each { |child| append(child) } end |
Instance Attribute Details
#attributes ⇒ Object (readonly)
Returns the value of attribute attributes.
10 11 12 |
# File 'lib/mdom/node.rb', line 10 def attributes @attributes end |
#children ⇒ Object (readonly)
Returns the value of attribute children.
10 11 12 |
# File 'lib/mdom/node.rb', line 10 def children @children end |
#parent ⇒ Object
Returns the value of attribute parent.
11 12 13 |
# File 'lib/mdom/node.rb', line 11 def parent @parent end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
10 11 12 |
# File 'lib/mdom/node.rb', line 10 def type @type end |
Instance Method Details
#[](*types) ⇒ Object
Query by one or more types (Symbol or array of Symbols). Returns an array of matching nodes (including self if it matches) in document order.
129 130 131 132 |
# File 'lib/mdom/node.rb', line 129 def [](*types) types = types.flatten find_all.select { |n| types.include?(n.type) } end |
#ancestors ⇒ Object
The chain of ancestors, closest first. Returns [] for a root node.
74 75 76 77 78 79 80 81 82 |
# File 'lib/mdom/node.rb', line 74 def ancestors list = [] node = @parent while node list << node node = node.parent end list end |
#append(child) ⇒ Object Also known as: <<
Append child to the end of this node's children. Reparents child
away from any previous parent. Returns self so it can be chained.
27 28 29 30 31 32 33 34 |
# File 'lib/mdom/node.rb', line 27 def append(child) return self if child.nil? child.remove if child.parent child.parent = self @children << child self end |
#children? ⇒ Boolean
46 47 48 |
# File 'lib/mdom/node.rb', line 46 def children? !@children.empty? end |
#depth ⇒ Object
Depth in the tree: 0 at the root, 1 for its direct children, etc.
67 68 69 70 71 |
# File 'lib/mdom/node.rb', line 67 def depth return 0 if @parent.nil? @parent.depth + 1 end |
#each_child(&block) ⇒ Object Also known as: each
Yield each child in order. Returns an Enumerator when no block is given.
38 39 40 41 42 43 |
# File 'lib/mdom/node.rb', line 38 def each_child(&block) return enum_for(:each_child) unless block @children.each(&block) self end |
#empty? ⇒ Boolean
194 195 196 |
# File 'lib/mdom/node.rb', line 194 def empty? @children.empty? end |
#find(type = nil, &block) ⇒ Object
The first matching descendant (or self); type may be a Symbol or a
callable, or a block may be supplied.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/mdom/node.rb', line 112 def find(type = nil, &block) predicate = if block block elsif type.is_a?(Symbol) ->(n) { n.type == type } elsif type.respond_to?(:call) type else nil end walk { |node| return node if predicate && predicate.call(node) } nil end |
#find_all(type = nil) ⇒ Object
Yield each descendant (including self) whose type matches type, or all
nodes when no type is given. With a block given, also yields when the
block returns truthy.
99 100 101 102 103 104 105 106 107 108 |
# File 'lib/mdom/node.rb', line 99 def find_all(type = nil) results = [] walk do |node| next unless type.nil? || node.type == type next if block_given? && !yield(node) results << node end results end |
#insert_after(node) ⇒ Object
Insert node as the sibling immediately after this node.
149 150 151 152 153 154 155 156 157 158 |
# File 'lib/mdom/node.rb', line 149 def insert_after(node) parent = @parent raise "cannot insert after a root node" if parent.nil? node.remove if node.parent idx = parent.children.index(self) parent.children.insert(idx + 1, node) node.parent = parent self end |
#insert_before(node) ⇒ Object
Insert node as the sibling immediately before this node.
137 138 139 140 141 142 143 144 145 146 |
# File 'lib/mdom/node.rb', line 137 def insert_before(node) parent = @parent raise "cannot insert before a root node" if parent.nil? node.remove if node.parent idx = parent.children.index(self) parent.children.insert(idx, node) node.parent = parent self end |
#inspect ⇒ Object
A human-readable tree rendering of this node and its descendants.
205 206 207 |
# File 'lib/mdom/node.rb', line 205 def inspect pretty_print end |
#plain_text ⇒ Object
Concatenate the literal string content of this subtree. Leaves that carry
text expose it via to_s (Text, Code); container nodes recurse.
181 182 183 184 185 186 |
# File 'lib/mdom/node.rb', line 181 def plain_text return "\n" if @type == :softbreak || @type == :hardbreak return to_s.to_s if @children.empty? @children.map(&:plain_text).join end |
#pretty_print(level = 0) ⇒ Object
Render this node plus its subtree as an indented, printable tree.
210 211 212 213 214 |
# File 'lib/mdom/node.rb', line 210 def pretty_print(level = 0) indent = " " * level children = @children.empty? ? "" : "\n" + @children.map { |c| c.pretty_print(level + 1) }.join("\n") "#{indent}#<#{short_class}#{detail}>#{children}" end |
#remove ⇒ Object
Remove this node from its current parent, if any. Returns self.
51 52 53 54 55 |
# File 'lib/mdom/node.rb', line 51 def remove @parent&.children&.delete(self) @parent = nil self end |
#replace(node) ⇒ Object
Replace this node in its parent with node. Returns node.
161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/mdom/node.rb', line 161 def replace(node) parent = @parent raise "cannot replace a root node" if parent.nil? node.remove if node.parent idx = parent.children.index(self) parent.children[idx] = node node.parent = parent @parent = nil node end |
#root ⇒ Object
The topmost ancestor (a node whose parent is nil).
60 61 62 63 64 |
# File 'lib/mdom/node.rb', line 60 def root node = self node = node.parent while node.parent node end |
#text? ⇒ Boolean
-- misc ---------------------------------------------------------------
175 176 177 |
# File 'lib/mdom/node.rb', line 175 def text? @type == :text end |
#to_markdown ⇒ Object Also known as: markdown
Serialize this node (and its subtree) back to Markdown.
189 190 191 |
# File 'lib/mdom/node.rb', line 189 def to_markdown MDOM::Serializer.serialize(self) end |
#to_s ⇒ Object
A compact, single-line summary of this node (its own type/attributes only, without recursing into children).
200 201 202 |
# File 'lib/mdom/node.rb', line 200 def to_s "#<#{short_class}#{detail}>" end |
#walk(&block) ⇒ Object
Depth-first (preorder) traversal that yields this node then its descendants, depth-first. Returns an Enumerator when no block is given.
88 89 90 91 92 93 94 |
# File 'lib/mdom/node.rb', line 88 def walk(&block) return enum_for(:walk) unless block block.call(self) @children.each { |child| child.walk(&block) } self end |