Class: Sevgi::Derender::Node

Inherits:
Object
  • Object
show all
Defined in:
lib/sevgi/derender/node.rb

Overview

Node in a derender tree produced from an SVG/XML node.

Constant Summary collapse

META_NAMESPACE =

Attribute namespace prefix used for Sevgi metadata.

"_:"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(node, pres = [], namespaces: nil, top: true) ⇒ void

Builds a derender node.

Parameters:

  • node (Nokogiri::XML::Node)

    source XML node

  • pres (Array<String>) (defaults to: [])

    preamble XML lines carried by the root node

  • namespaces (Hash{String => String}, nil) (defaults to: nil)

    namespace declarations to emit on this node; selected roots use their full inherited namespace scope, while ordinary children use only declarations from their own element

  • top (Boolean) (defaults to: true)

    true when this node is the root of the current conversion



43
44
45
46
47
48
49
# File 'lib/sevgi/derender/node.rb', line 43

def initialize(node, pres = [], namespaces: nil, top: true)
  @node = node
  @pres = pres
  @namespaces = namespaces
  @top = top
  @type = dispatch
end

Instance Attribute Details

#nodeNokogiri::XML::Node (readonly)

Returns the source XML node.

Returns:

  • (Nokogiri::XML::Node)


26
27
28
# File 'lib/sevgi/derender/node.rb', line 26

def node
  @node
end

#presArray<String> (readonly)

Returns preamble XML lines carried by the root node.

Returns:

  • (Array<String>)


30
31
32
# File 'lib/sevgi/derender/node.rb', line 30

def pres
  @pres
end

#typeSymbol (readonly)

Returns the dispatch type used by derender element strategies.

Returns:

  • (Symbol)


34
35
36
# File 'lib/sevgi/derender/node.rb', line 34

def type
  @type
end

Instance Method Details

#_Hash{String => String} Also known as: meta

Returns Sevgi metadata attributes without the metadata namespace prefix.

Returns:

  • (Hash{String => String})

    metadata attributes



56
57
58
59
60
61
62
# File 'lib/sevgi/derender/node.rb', line 56

def _
  @_ ||= attributes
    .slice(
      *attributes.keys.select { |key| key.start_with?(META_NAMESPACE) }
    )
    .transform_keys! { |key| key.delete_prefix(META_NAMESPACE) }
end

#attributesHash{String => String}

Returns source XML attributes keyed with namespace prefixes when present.

Returns:

  • (Hash{String => String})

    XML attributes



68
# File 'lib/sevgi/derender/node.rb', line 68

def attributes = @attributes ||= node.attribute_nodes.to_h { [attribute_key(it), it.value] }

#attributes!Hash{String => String}

Returns source XML attributes and namespace declarations emitted on this node.

Returns:

  • (Hash{String => String})

    XML attributes



72
# File 'lib/sevgi/derender/node.rb', line 72

def attributes! = {**attributes, **namespaces}

#childrenArray<Sevgi::Derender::Node>

Returns non-ignorable child derender nodes.

Returns:



76
# File 'lib/sevgi/derender/node.rb', line 76

def children = @children ||= node.children.map { self.class.new(it, top: false) }.reject { ignorable_child?(it) }

#contentString

Returns node text content.

xml:space="preserve" keeps content verbatim. Default-space text nodes are stripped for ordinary pretty-printed content; line-break indentation around mixed-content children is removed while inline boundary spaces and tabs are kept because they affect rendered SVG text.

Returns:

  • (String)


84
# File 'lib/sevgi/derender/node.rb', line 84

def content = @content ||= preserve_space? ? node.content : normalized_content

#derenderString

Note:

Foreign namespace elements use the explicit Element DSL path, and nested svg nodes remain elements.

Note:

Unsafe bare Ruby names are emitted through the explicit Element DSL word.

Converts this node into formatted Sevgi DSL Ruby source.

Returns:

  • (String)

    formatted Sevgi DSL source

Raises:

  • (Sevgi::PanicError)

    when generated Ruby source cannot be formatted



91
# File 'lib/sevgi/derender/node.rb', line 91

def derender = Ruby.format(decompile(pres).join("\n"))

#elementString

Returns the Sevgi DSL element name for this node.

Returns:

  • (String)


95
# File 'lib/sevgi/derender/node.rb', line 95

def element = name

#evaluate(element, include_current = true) ⇒ Sevgi::Graphics::Element, ...

Note:

Namespace declarations, qualified attributes, significant text, and nested svg nodes are preserved.

Evaluates this node under a graphics element.

Parameters:

  • element (Sevgi::Graphics::Element)

    target graphics element

  • include_current (Boolean) (defaults to: true)

    true to evaluate this node, false to evaluate only children

Returns:

  • (Sevgi::Graphics::Element, Array<Sevgi::Graphics::Element>, nil)

    included current element, included child elements when include_current is false, or nil when the node does not produce graphics output



103
104
105
106
107
# File 'lib/sevgi/derender/node.rb', line 103

def evaluate(element, include_current = true)
  return Evaluator.new(element).append(self) if include_current

  evaluate_children(element)
end

#evaluate_children(element) ⇒ Array<Sevgi::Graphics::Element>

Evaluates only this node's children under a graphics element.

Parameters:

  • element (Sevgi::Graphics::Element)

    target graphics element

Returns:

  • (Array<Sevgi::Graphics::Element>)

    included child elements



112
# File 'lib/sevgi/derender/node.rb', line 112

def evaluate_children(element) = children.map { it.evaluate(element) }.compact

#find(arg, by: "id") ⇒ Sevgi::Derender::Node?

Finds the first descendant whose attribute matches a value.

Parameters:

  • arg (String)

    attribute value to find

  • by (String) (defaults to: "id")

    attribute name used for lookup

Returns:



118
119
120
121
122
# File 'lib/sevgi/derender/node.rb', line 118

def find(arg, by: "id")
  return self if attributes[by] == arg

  children.lazy.map { it.find(arg, by:) }.find(&:itself)
end

#nameString

Returns the source XML qualified name, including its namespace prefix when present.

Returns:

  • (String)


126
# File 'lib/sevgi/derender/node.rb', line 126

def name = @name ||= [node.namespace&.prefix, node.name].compact.join(":")

#namespacesHash{String => String}

Returns source XML namespace declarations emitted on this node.

Returns:

  • (Hash{String => String})

    namespace declarations



130
# File 'lib/sevgi/derender/node.rb', line 130

def namespaces = (@namespaces ||= local_namespaces)

#root?Boolean

Reports whether this node is the SVG root strategy.

Returns:

  • (Boolean)


134
# File 'lib/sevgi/derender/node.rb', line 134

def root? = type == :Root