Class: Paru::PandocFilter::Node
- Inherits:
-
Object
- Object
- Paru::PandocFilter::Node
- Includes:
- Enumerable, ASTManipulation
- Defined in:
- lib/paru/filter/node.rb
Overview
Every node in a Pandoc AST is mapped to Node. Filters are all about manipulating Nodes.
Direct Known Subclasses
Block, Document, Inline, MetaBlocks, MetaInlines, MetaList, MetaMap, MetaValue, Value, Version
Instance Attribute Summary collapse
-
#parent ⇒ Node
The parent node, if any.
Class Method Summary collapse
-
.from_markdown(markdown_string) ⇒ Block|Div
Create a new node from a markdown string.
Instance Method Summary collapse
-
#append(child) ⇒ Object
(also: #<<)
included
from ASTManipulation
Append a child to the list with this node's children.
-
#ast_contents ⇒ Array
An AST representation of the contents of this node.
-
#ast_type ⇒ String
The AST type of this Node.
-
#can_act_as_both_block_and_inline? ⇒ Boolean
Can this node act both as a block and inline node? Some nodes are hybrids in this regard, like Math or Image.
-
#children ⇒ Array<Node>
Get this node's children,.
-
#children=(list) ⇒ Object
Set this node's children.
-
#delete(child) ⇒ Object
included
from ASTManipulation
Delete child from this node's children.
-
#each {|Node| ... } ⇒ Object
For each child of this Node, yield the child.
-
#each_depth_first(&block) {|Node| ... } ⇒ Object
included
from ASTManipulation
Walk the node tree starting at this node, depth first, and apply block to each node in the tree.
-
#find_index(child) ⇒ Number
included
from ASTManipulation
Find index of child.
-
#get(index) ⇒ Node
included
from ASTManipulation
Get the child node at index.
-
#get_replacement ⇒ Node
Get this node's replacemnt.
-
#has_been_replaced? ⇒ Boolean
Has this node been replaced by using the #markdown method? If so, return true.
-
#has_block? ⇒ Boolean
Does this node have Block contents?.
-
#has_children? ⇒ Boolean
Does this node have any children?.
-
#has_class?(name) ⇒ Boolean
If this node has attributes with classes, is name among them?.
-
#has_inline? ⇒ Boolean
Does this node have Inline contents?.
-
#has_parent? ⇒ Boolean
Does this node have a parent?.
-
#has_string? ⇒ Boolean
Does this node has a string value?.
-
#initialize(contents = [], inline_children = false) ⇒ Node
constructor
Create a new Node with contents.
-
#insert(index, child) ⇒ Object
included
from ASTManipulation
Insert child node among this node's children at position index.
-
#is_block? ⇒ Boolean
Is this node a Block level node?.
-
#is_inline? ⇒ Boolean
Is this an Inline level node?.
-
#is_leaf? ⇒ Boolean
Is this Node a leaf? See also #is_node?.
-
#is_node? ⇒ Boolean
Is this Node a Node or a leaf? See #is_leaf?.
-
#is_root? ⇒ Boolean
Is this a root node?.
-
#markdown ⇒ String
(also: #outer_markdown)
Get the markdown representation of this Node, including the Node itself.
-
#markdown=(markdown) ⇒ Object
(also: #outer_markdown=)
Set the markdown representation of this Node: replace this Node by the Node represented by the markdown string.
-
#prepend(child) ⇒ Object
included
from ASTManipulation
Prepend a child to the list with this node's children.
-
#remove_at(index) ⇒ Object
included
from ASTManipulation
Remove the child at position index from this node's children.
-
#replace(old_child, new_child) ⇒ Object
included
from ASTManipulation
Replace a child from this node's children with a new child.
-
#replace_at(index, new_child) ⇒ Object
included
from ASTManipulation
Replace the child at position index from this node's children with a new child.
-
#to_ast ⇒ Hash
Create an AST representation of this Node.
-
#to_s ⇒ String
A String representation of this Node.
-
#toMetadata ⇒ MetaInlines|MetaBlocks
Convert this Node to a metadata value.
-
#type ⇒ String
The pandoc type of this Node.
Constructor Details
#initialize(contents = [], inline_children = false) ⇒ Node
Create a new Node with contents. Also indicate if this node has inline children or block children.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/paru/filter/node.rb', line 115 def initialize(contents = [], inline_children = false) @children = [] @parent = nil if contents.is_a? Array contents.each do |elt| if PandocFilter.const_defined? elt["t"] child = PandocFilter.const_get(elt["t"]).new elt["c"] else if inline_children child = PandocFilter::Inline.new elt["c"] else child = PandocFilter::Plain.new elt["c"] end end child.parent = self @children.push child end end end |
Instance Attribute Details
#parent ⇒ Node
Returns the parent node, if any.
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 |
# File 'lib/paru/filter/node.rb', line 44 class Node include Enumerable include ASTManipulation attr_accessor :parent # Block level nodes require_relative './block_quote.rb' require_relative './block.rb' require_relative './bullet_list.rb' require_relative './code_block.rb' require_relative './definition_list_item.rb' require_relative './definition_list.rb' require_relative './div.rb' require_relative './empty_block.rb' require_relative './header.rb' require_relative './horizontal_rule.rb' require_relative './line_block.rb' require_relative './null.rb' require_relative './ordered_list.rb' require_relative './para.rb' require_relative './plain.rb' require_relative './raw_block.rb' require_relative './table.rb' require_relative './caption.rb' require_relative './table_head.rb' require_relative './table_foot.rb' require_relative './row.rb' require_relative './cell.rb' require_relative './figure.rb' # Inline level nodes require_relative './cite.rb' require_relative './code.rb' require_relative './emph.rb' require_relative './empty_inline.rb' require_relative './image.rb' require_relative './inline.rb' require_relative './line_break.rb' require_relative './link.rb' require_relative './math.rb' require_relative './note.rb' require_relative './quoted.rb' require_relative './raw_inline.rb' require_relative './small_caps.rb' require_relative './soft_break.rb' require_relative './space.rb' require_relative './span.rb' require_relative './strikeout.rb' require_relative './strong.rb' require_relative './str.rb' require_relative './subscript.rb' require_relative './superscript.rb' require_relative './short_caption.rb' require_relative './underline.rb' # Metadata level nodes require_relative './meta_blocks.rb' require_relative './meta_bool.rb' require_relative './meta_inlines.rb' require_relative './meta_list.rb' require_relative './meta_map.rb' require_relative './meta_string.rb' # Create a new Node with contents. Also indicate if this node has # inline children or block children. # # @param contents [Array<pandoc node in JSON> = []] the contents of # this node # @param inline_children [Boolean] does this node have # inline children (true) or block children (false). def initialize(contents = [], inline_children = false) @children = [] @parent = nil if contents.is_a? Array contents.each do |elt| if PandocFilter.const_defined? elt["t"] child = PandocFilter.const_get(elt["t"]).new elt["c"] else if inline_children child = PandocFilter::Inline.new elt["c"] else child = PandocFilter::Plain.new elt["c"] end end child.parent = self @children.push child end end end # Create a new node from a markdown string. This is always a block # level node. If more # than one new node is created, a {Div} is created as a parent for # the newly created block nodes.. # # @param markdown_string [String] the markdown string to convert # to a AST node # # @return [Block|Div] The {Block} node created by converting # markdown_string with pandoc; A {Div} node if this conversion # holds more than one {Block} node. def self.from_markdown(markdown_string) node = Node.new [] node.outer_markdown = markdown_string if node.children.size == 1 node = node.children.first else container = from_markdown "<div></div>" container.children = node.children node = container end return node end # For each child of this Node, yield the child # # @yield [Node] def each() @children.each do |child| yield child end end # Does this node have any children? # # @return [Boolean] True if this node has any children, false # otherwise. def has_children?() defined? @children and not @children.nil? and @children.size > 0 end # Get this node's children, # # @return [Array<Node>] this node's children as an Array. def children() if has_children? @children else [] end end # Set this node's children # # @param list [Array<Node>] a list with nodes def children=(list) @children = list end # Does this node have a parent? # # @return [Boolean] True if this node has a parent, false # otherwise. def has_parent?() not @parent.nil? end # Is this a root node? # # @return [Boolean] True if this node has a no parent, false # otherwise def is_root?() not has_parent? end # Is this Node a Node or a leaf? See #is_leaf? # # @return [Boolean] A node is a node if it is not a leaf. def is_node?() not is_leaf end # Is this Node a leaf? See also #is_node? # # @return [Boolean] A node is a leaf when it has no children # false otherwise def is_leaf?() not has_children? end # Does this node has a string value? # # @return [Boolean] true if this node has a string value, false # otherwise def has_string?() false end # Does this node have Inline contents? # # @return [Boolean] true if this node has Inline contents, false # otherwise def has_inline?() false end # Does this node have Block contents? # # @return [Boolean] true if this node has Block contents, false # otherwise def has_block?() false end # Is this node a Block level node? # # @return [Boolean] true if this node is a block level node, false # otherwise def is_block?() false end # Can this node act both as a block and inline node? Some nodes # are hybrids in this regard, like Math or Image # # @return [Boolean] def can_act_as_both_block_and_inline?() false end # Is this an Inline level node? # # @return [Boolean] true if this node is an inline level node, # false otherwise def is_inline?() false end # Convert this Node to a metadata value. If this Node # {is_inline?}, it is converted to {MetaInlines} if it is # {is_block?}, it is converted to {MetaBlocks}. # # @return [MetaInlines|MetaBlocks] def toMetadata() if is_inline? then MetaInlines.new to_ast, true elsif is_blocks? then MetaBlocks.new to_ast, false else # ? end end # If this node has attributes with classes, is name among them? # # @param name [String] the class name to search for # # @return [Boolean] true if this node has attributes with classes # and name is among them, false otherwise def has_class?(name) if not @attr.nil? @attr.has_class? name else false end end # A String representation of this Node # # @return [String] def to_s() self.class.name end # The pandoc type of this Node # # @return [String] def type() ast_type end # The AST type of this Node # # @return [String] def ast_type() self.class.name.split("::").last end # An AST representation of the contents of this node # # @return [Array] def ast_contents() if has_children? @children.map {|child| child.to_ast} else [] end end # Create an AST representation of this Node # # @return [Hash] def to_ast() { "t" => ast_type, "c" => ast_contents } end # Get the markdown representation of this Node, including the Node # itself. # # @return [String] the outer markdown representation of this Node def markdown() temp_doc = PandocFilter::Document.fragment [self] markdown = AST2MARKDOWN << temp_doc.to_JSON markdown end alias outer_markdown markdown # Set the markdown representation of this Node: replace this Node # by the Node represented by the markdown string. If an inline # node is being replaced and the replacement has more than one # paragraph, only the contents of the first paragraph is used # # @param markdown [String] the markdown string to replace this # Node # # @example Replacing all horizontal lines by a Plain node saying "hi" # Paru::Filter.run do # with "HorizontalLine" do |line| # line.markdown = "hi" # end # end # def markdown=(markdown) json = MARKDOWN2JSON << markdown temp_doc = PandocFilter::Document.from_JSON json if not has_parent? or is_root? @children = temp_doc.children else # replace current node by new nodes # There is a difference between inline and block nodes current_index = parent.find_index self # By default, pandoc creates a Block level node when # converting a string. However, if the original is a # inline level node, so should its replacement node(s) be. # Only using first block node (paragraph?) if is_inline? temp_doc = temp_doc.children.first if not temp_doc.children.all? {|node| node.is_inline?} raise Error.new "Cannot replace the inline level node represented by '#{self.markdown}' with markdown that converts to block level nodes: '#{markdown}'." end else replacement = temp_doc.children.first @replacement = replacement unless replacement.nil? or to_ast == replacement.to_ast end index = current_index temp_doc.each do |child| index += 1 parent.insert index, child end # Remove the original node parent.remove_at current_index end end alias outer_markdown= markdown= # Has this node been replaced by using the {markdown} method? If # so, return true. # # @return [Boolean] def has_been_replaced? not @replacement.nil? end # Get this node's replacemnt. Nil if it has not been replaced by # the {markdown} method # # @return [Node] This node's replacement or nil if there is none. def get_replacement @replacement end end |
Class Method Details
.from_markdown(markdown_string) ⇒ Block|Div
Create a new node from a markdown string. This is always a block level node. If more than one new node is created, a Div is created as a parent for the newly created block nodes..
148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/paru/filter/node.rb', line 148 def self.from_markdown(markdown_string) node = Node.new [] node.outer_markdown = markdown_string if node.children.size == 1 node = node.children.first else container = from_markdown "<div></div>" container.children = node.children node = container end return node end |
Instance Method Details
#append(child) ⇒ Object Also known as: << Originally defined in module ASTManipulation
Append a child to the list with this node's children.
#ast_contents ⇒ Array
An AST representation of the contents of this node
330 331 332 333 334 335 336 |
# File 'lib/paru/filter/node.rb', line 330 def ast_contents() if has_children? @children.map {|child| child.to_ast} else [] end end |
#ast_type ⇒ String
The AST type of this Node
323 324 325 |
# File 'lib/paru/filter/node.rb', line 323 def ast_type() self.class.name.split("::").last end |
#can_act_as_both_block_and_inline? ⇒ Boolean
Can this node act both as a block and inline node? Some nodes are hybrids in this regard, like Math or Image
265 266 267 |
# File 'lib/paru/filter/node.rb', line 265 def can_act_as_both_block_and_inline?() false end |
#children ⇒ Array<Node>
Get this node's children,
183 184 185 186 187 188 189 |
# File 'lib/paru/filter/node.rb', line 183 def children() if has_children? @children else [] end end |
#children=(list) ⇒ Object
Set this node's children
194 195 196 |
# File 'lib/paru/filter/node.rb', line 194 def children=(list) @children = list end |
#delete(child) ⇒ Object Originally defined in module ASTManipulation
Delete child from this node's children.
#each {|Node| ... } ⇒ Object
For each child of this Node, yield the child
166 167 168 169 170 |
# File 'lib/paru/filter/node.rb', line 166 def each() @children.each do |child| yield child end end |
#each_depth_first(&block) {|Node| ... } ⇒ Object Originally defined in module ASTManipulation
Walk the node tree starting at this node, depth first, and apply block to each node in the tree
#find_index(child) ⇒ Number Originally defined in module ASTManipulation
Find index of child
#get(index) ⇒ Node Originally defined in module ASTManipulation
Get the child node at index
#get_replacement ⇒ Node
Get this node's replacemnt. Nil if it has not been replaced by the #markdown method
427 428 429 |
# File 'lib/paru/filter/node.rb', line 427 def get_replacement @replacement end |
#has_been_replaced? ⇒ Boolean
Has this node been replaced by using the #markdown method? If so, return true.
419 420 421 |
# File 'lib/paru/filter/node.rb', line 419 def has_been_replaced? not @replacement.nil? end |
#has_block? ⇒ Boolean
Does this node have Block contents?
249 250 251 |
# File 'lib/paru/filter/node.rb', line 249 def has_block?() false end |
#has_children? ⇒ Boolean
Does this node have any children?
176 177 178 |
# File 'lib/paru/filter/node.rb', line 176 def has_children?() defined? @children and not @children.nil? and @children.size > 0 end |
#has_class?(name) ⇒ Boolean
If this node has attributes with classes, is name among them?
298 299 300 301 302 303 304 |
# File 'lib/paru/filter/node.rb', line 298 def has_class?(name) if not @attr.nil? @attr.has_class? name else false end end |
#has_inline? ⇒ Boolean
Does this node have Inline contents?
241 242 243 |
# File 'lib/paru/filter/node.rb', line 241 def has_inline?() false end |
#has_parent? ⇒ Boolean
Does this node have a parent?
202 203 204 |
# File 'lib/paru/filter/node.rb', line 202 def has_parent?() not @parent.nil? end |
#has_string? ⇒ Boolean
Does this node has a string value?
233 234 235 |
# File 'lib/paru/filter/node.rb', line 233 def has_string?() false end |
#insert(index, child) ⇒ Object Originally defined in module ASTManipulation
Insert child node among this node's children at position index.
#is_block? ⇒ Boolean
Is this node a Block level node?
257 258 259 |
# File 'lib/paru/filter/node.rb', line 257 def is_block?() false end |
#is_inline? ⇒ Boolean
Is this an Inline level node?
273 274 275 |
# File 'lib/paru/filter/node.rb', line 273 def is_inline?() false end |
#is_leaf? ⇒ Boolean
Is this Node a leaf? See also #is_node?
225 226 227 |
# File 'lib/paru/filter/node.rb', line 225 def is_leaf?() not has_children? end |
#is_node? ⇒ Boolean
Is this Node a Node or a leaf? See #is_leaf?
217 218 219 |
# File 'lib/paru/filter/node.rb', line 217 def is_node?() not is_leaf end |
#is_root? ⇒ Boolean
Is this a root node?
210 211 212 |
# File 'lib/paru/filter/node.rb', line 210 def is_root?() not has_parent? end |
#markdown ⇒ String Also known as: outer_markdown
Get the markdown representation of this Node, including the Node itself.
352 353 354 355 356 |
# File 'lib/paru/filter/node.rb', line 352 def markdown() temp_doc = PandocFilter::Document.fragment [self] markdown = AST2MARKDOWN << temp_doc.to_JSON markdown end |
#markdown=(markdown) ⇒ Object Also known as: outer_markdown=
Set the markdown representation of this Node: replace this Node by the Node represented by the markdown string. If an inline node is being replaced and the replacement has more than one paragraph, only the contents of the first paragraph is used
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 |
# File 'lib/paru/filter/node.rb', line 375 def markdown=(markdown) json = MARKDOWN2JSON << markdown temp_doc = PandocFilter::Document.from_JSON json if not has_parent? or is_root? @children = temp_doc.children else # replace current node by new nodes # There is a difference between inline and block nodes current_index = parent.find_index self # By default, pandoc creates a Block level node when # converting a string. However, if the original is a # inline level node, so should its replacement node(s) be. # Only using first block node (paragraph?) if is_inline? temp_doc = temp_doc.children.first if not temp_doc.children.all? {|node| node.is_inline?} raise Error.new "Cannot replace the inline level node represented by '#{self.markdown}' with markdown that converts to block level nodes: '#{markdown}'." end else replacement = temp_doc.children.first @replacement = replacement unless replacement.nil? or to_ast == replacement.to_ast end index = current_index temp_doc.each do |child| index += 1 parent.insert index, child end # Remove the original node parent.remove_at current_index end end |
#prepend(child) ⇒ Object Originally defined in module ASTManipulation
Prepend a child to the list with this node's children.
#remove_at(index) ⇒ Object Originally defined in module ASTManipulation
Remove the child at position index from this node's children
#replace(old_child, new_child) ⇒ Object Originally defined in module ASTManipulation
Replace a child from this node's children with a new child.
#replace_at(index, new_child) ⇒ Object Originally defined in module ASTManipulation
Replace the child at position index from this node's children with a new child.
#to_ast ⇒ Hash
Create an AST representation of this Node
341 342 343 344 345 346 |
# File 'lib/paru/filter/node.rb', line 341 def to_ast() { "t" => ast_type, "c" => ast_contents } end |
#to_s ⇒ String
A String representation of this Node
309 310 311 |
# File 'lib/paru/filter/node.rb', line 309 def to_s() self.class.name end |
#toMetadata ⇒ MetaInlines|MetaBlocks
Convert this Node to a metadata value. If this Node #is_inline?, it is converted to MetaInlines if it is #is_block?, it is converted to MetaBlocks.
282 283 284 285 286 287 288 289 290 |
# File 'lib/paru/filter/node.rb', line 282 def toMetadata() if is_inline? then MetaInlines.new to_ast, true elsif is_blocks? then MetaBlocks.new to_ast, false else # ? end end |
#type ⇒ String
The pandoc type of this Node
316 317 318 |
# File 'lib/paru/filter/node.rb', line 316 def type() ast_type end |