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 = []) ⇒ 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



19
20
21
22
23
# File 'lib/sevgi/derender/node.rb', line 19

def initialize(node, pres = [])
  @node = node
  @pres = pres
  @type = dispatch
end

Instance Attribute Details

#nodeNokogiri::XML::Node (readonly)

Returns source XML node.

Returns:

  • (Nokogiri::XML::Node)

    source XML node



13
14
15
# File 'lib/sevgi/derender/node.rb', line 13

def node
  @node
end

#presArray<String> (readonly)

Returns preamble XML lines carried by the root node.

Returns:

  • (Array<String>)

    preamble XML lines carried by the root node



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

attr_reader :node, :pres, :type

#typeObject (readonly)

Returns the value of attribute type.



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

attr_reader :node, :pres, :type

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



30
31
32
33
34
35
36
# File 'lib/sevgi/derender/node.rb', line 30

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



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/sevgi/derender/node.rb', line 42

def attributes
  @attributes ||= node.attribute_nodes.to_h do |attr|
    name, value = attr.name, attr.value

    if attr.respond_to?(:namespace) && (namespace = attr.namespace) && (prefix = namespace.prefix)
      "#{prefix}:#{name}"
    else
      name
    end => key

    [key, value]
  end
end

#attributes!Hash{String => String}

Returns source XML attributes.

Returns:

  • (Hash{String => String})

    XML attributes



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

def attributes! = attributes

#childrenArray<Sevgi::Derender::Node>

Returns non-ignorable child derender nodes.

Returns:



62
63
64
65
66
67
# File 'lib/sevgi/derender/node.rb', line 62

def children
  @children ||= node
    .children
    .map { |child| self.class.new(child) }
    .reject { |child| ignorable_child?(child) }
end

#contentString

Returns node text content, preserving or stripping whitespace according to xml:space.

Returns:

  • (String)


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

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

#derenderString

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



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

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

#elementString

Returns the Sevgi DSL element name for this node.

Returns:

  • (String)


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

def element = name

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

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)

    target graphics element

Raises:

  • (Sevgi::PanicError)

    when generated Ruby source cannot be formatted



87
88
89
90
91
# File 'lib/sevgi/derender/node.rb', line 87

def evaluate(element, include_current = true)
  return element.instance_eval(derender) if include_current

  children.each { element.instance_eval(it.derender) }
end

#evaluate!(element) ⇒ Sevgi::Graphics::Element

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

Parameters:

  • element (Sevgi::Graphics::Element)

    target graphics element

Returns:

  • (Sevgi::Graphics::Element)

    target graphics element

Raises:

  • (Sevgi::PanicError)

    when generated Ruby source cannot be formatted



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

def evaluate!(element) = evaluate(element, false)

#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:



103
104
105
106
107
108
109
110
111
112
113
# File 'lib/sevgi/derender/node.rb', line 103

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

  children&.each do |child|
    found = child.find(arg, by:)

    return found if found
  end

  nil
end

#nameString

Returns the source XML node name.

Returns:

  • (String)


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

def name = @name ||= node.name

#namespacesHash{String => String}

Returns source XML namespaces.

Returns:

  • (Hash{String => String})

    namespace declarations



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

def namespaces = (@namespaces ||= node.namespaces.to_h { |namespace, uri| [namespace, uri] })

#root?Boolean

Reports whether this node is the SVG root strategy.

Returns:

  • (Boolean)


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

def root? = type == :Root