Module: Sevgi::Derender

Defined in:
lib/sevgi/derender.rb,
lib/sevgi/derender/node.rb,
lib/sevgi/derender/version.rb,
lib/sevgi/derender/document.rb,
lib/sevgi/derender/elements.rb,
lib/sevgi/derender/internal.rb,
lib/sevgi/derender/evaluator.rb,
lib/sevgi/derender/attributes.rb,
lib/sevgi/derender/elements/any.rb,
lib/sevgi/derender/elements/css.rb,
lib/sevgi/derender/elements/junk.rb,
lib/sevgi/derender/elements/root.rb,
lib/sevgi/derender/elements/text.rb

Overview

Brings editor-authored SVG/XML into programmatic Sevgi workflows.

Vector geometry such as a Bezier-heavy logo or hand-adjusted illustration may be better authored in a visual editor than reconstructed as Ruby. Derender preserves that SVG/XML tree as inspectable data, formatted Sevgi DSL source, or graphics elements under an existing document. This lets editor-authored geometry participate in programmatic composition, styling, layout, and output. Use it when SVG/XML is a real input artifact, not as an intermediate authoring format for ordinary Sevgi drawing code.

Generated source uses bare DSL calls only for recognized element names that cannot dispatch to an existing Ruby or Sevgi method. Other XML names use the explicit Element DSL word so executing generated source preserves the XML tree without invoking same-named Ruby methods.

Evaluation APIs treat SVG/XML as data: they build graphics element trees directly and do not execute generated Ruby source. Malformed, rootless, or unmatched input is rejected with ArgumentError.

Namespace dispatch treats qualified and foreign elements as ordinary XML nodes. Their element identity, namespace declarations, qualified attributes, significant text, and nested svg elements survive source generation and direct evaluation. CSS specialization applies only to unqualified style elements in no namespace or the default SVG namespace; the document-root strategy additionally requires an unqualified svg at the root of the conversion. Simple CSS rules use the readable css({...}) DSL form. At-rules, duplicate declarations, and other CSS that cannot be represented losslessly as a Hash remain owned raw style content.

Attribute omission uses exact, case-sensitive names across the selected subtree. ID selection happens first; namespace declarations remain intact, and omitting the style attribute does not omit style elements.

Examples:

Inspect, select, and convert an immutable result

result = Sevgi::Derender.decompile('<svg><rect id="mark" width="10"/></svg>')
mark = result.find("mark")
mark.attributes #=> {"id"=>"mark", "width"=>"10"}
mark.derender   #=> "rect id: \"mark\", width: 10\n"

Preserve an at-rule as raw style content

Sevgi::Derender.derender("<style>@media print { rect { fill: black; } }</style>")
#=> "style Sevgi::Graphics::Content.cdata(\"@media print { rect { fill: black; } }\")\n"

Select a node while omitting editor-only attributes

source = '<svg><g id="mark" style="fill: red"><rect/></g></svg>'
Sevgi::Derender.derender(source, id: "mark", omit: %i[id style])
#=> "g do\n  rect\nend\n"

See Also:

Defined Under Namespace

Classes: Node

Constant Summary collapse

VERSION =

Current version of the Sevgi derender gem.

"0.98.2"

Class Method Summary collapse

Class Method Details

.decompile(content, id: nil, omit: nil) ⇒ Sevgi::Derender::Node

Converts SVG/XML content into an immutable derender result.

Examples:

Inspect a selected immutable node

root = Sevgi::Derender.decompile('<svg><g id="mark"><rect width="4"/></g></svg>')
mark = root.find("mark")
mark.name                  #=> "g"
mark.children.first.name  #=> "rect"
mark.attributes["id"]     #=> "mark"

Parameters:

  • content (String)

    SVG/XML source content

  • id (String, Symbol, nil) (defaults to: nil)

    optional SVG id selecting a node inside the source

  • omit (String, Symbol, Array<String, Symbol>, nil) (defaults to: nil)

    exact attribute name or names omitted from the selected subtree after id selection

Returns:

Raises:

  • (Sevgi::ArgumentError)

    when content is malformed or rootless, or when the id is absent

See Also:



70
# File 'lib/sevgi/derender.rb', line 70

def self.decompile(content, id: nil, omit: nil) = Document.new(content).decompile(id, omit:)

.decompile_file(file, id: nil, omit: nil) ⇒ Sevgi::Derender::Node

Converts an SVG/XML file into an immutable derender result.

Parameters:

  • file (String)

    path to the source SVG/XML file

  • id (String, Symbol, nil) (defaults to: nil)

    optional SVG id selecting a node inside the source

  • omit (String, Symbol, Array<String, Symbol>, nil) (defaults to: nil)

    exact attribute name or names omitted from the selected subtree after id selection

Returns:

Raises:

  • (Sevgi::ArgumentError)

    when the file cannot be found, file content is malformed or rootless, or the id is absent

  • (SystemCallError)

    when the file cannot be read

See Also:



83
# File 'lib/sevgi/derender.rb', line 83

def self.decompile_file(file, id: nil, omit: nil) = Document.load_file(file).decompile(id, omit:)

.derender(content, id: nil, omit: nil) ⇒ String

Note:

Namespace-aware dispatch preserves ordinary foreign/qualified nodes and nested SVG elements.

Note:

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

Converts SVG/XML content into Sevgi DSL Ruby source.

Examples:

Select first, then omit attributes from generated source

xml = '<svg><g id="mark" style="fill: red"><rect id="part"/></g></svg>'
Sevgi::Derender.derender(xml, id: :mark, omit: [:id, "style"])
#=> "g do\n  rect\nend\n"

Parameters:

  • content (String)

    SVG/XML source content

  • id (String, Symbol, nil) (defaults to: nil)

    optional SVG id selecting a node inside the source

  • omit (String, Symbol, Array<String, Symbol>, nil) (defaults to: nil)

    exact attribute name or names omitted from the selected subtree after id selection

Returns:

  • (String)

    formatted Sevgi DSL source

Raises:

  • (Sevgi::ArgumentError)

    when content is malformed or rootless, or when the id is absent

  • (Sevgi::PanicError)

    when generated Ruby source cannot be formatted

See Also:



101
# File 'lib/sevgi/derender.rb', line 101

def self.derender(content, id: nil, omit: nil) = Document.new(content).decompile(id, omit:).derender

.derender_file(file, id: nil, omit: nil) ⇒ String

Note:

Namespace-aware dispatch preserves ordinary foreign/qualified nodes and nested SVG elements.

Note:

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

Converts an SVG/XML file into Sevgi DSL Ruby source.

Parameters:

  • file (String)

    path to the source SVG/XML file

  • id (String, Symbol, nil) (defaults to: nil)

    optional SVG id selecting a node inside the source

  • omit (String, Symbol, Array<String, Symbol>, nil) (defaults to: nil)

    exact attribute name or names omitted from the selected subtree after id selection

Returns:

  • (String)

    formatted Sevgi DSL source

Raises:

  • (Sevgi::ArgumentError)

    when the file cannot be found, file content is malformed or rootless, or the id is absent

  • (Sevgi::PanicError)

    when generated Ruby source cannot be formatted

  • (SystemCallError)

    when the file cannot be read

See Also:



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

def self.derender_file(file, id: nil, omit: nil) = Document.load_file(file).decompile(id, omit:).derender

.evaluate(content, element, id: nil, omit: nil) ⇒ Sevgi::Graphics::Element?

Note:

Namespace-aware dispatch preserves ordinary foreign/qualified nodes and nested SVG elements.

Evaluates SVG/XML content under a graphics element, including the selected node.

Examples:

Include the selected node under an existing element

drawing = Sevgi::Graphics.SVG(:minimal)
included = Sevgi::Derender.evaluate('<circle id="mark" r="4"/>', drawing)
included.name   #=> :circle
included[:id]   #=> "mark"

Parameters:

  • content (String)

    SVG/XML source content

  • element (Sevgi::Graphics::Element)

    target graphics element

  • id (String, Symbol, nil) (defaults to: nil)

    optional SVG id selecting a node inside the source

  • omit (String, Symbol, Array<String, Symbol>, nil) (defaults to: nil)

    exact attribute name or names omitted from the selected subtree after id selection

Returns:

  • (Sevgi::Graphics::Element, nil)

    included selected/root graphics element, or nil when the selected node produces no graphics output

Raises:

  • (Sevgi::ArgumentError)

    when content is malformed or rootless, or when the id is absent

See Also:



136
137
138
# File 'lib/sevgi/derender.rb', line 136

def self.evaluate(content, element, id: nil, omit: nil)
  Document.new(content).decompile(id, omit:).evaluate(element)
end

.evaluate_children(content, element, id: nil, omit: nil) ⇒ Array<Sevgi::Graphics::Element>

Note:

Namespace-aware dispatch preserves ordinary foreign/qualified nodes and nested SVG elements.

Evaluates only the selected node's children under a graphics element.

Examples:

Include only children and retain an immutable result snapshot

drawing = Sevgi::Graphics.SVG(:minimal)
children = Sevgi::Derender.evaluate_children('<g><rect/><circle/></g>', drawing)
children.map(&:name) #=> [:rect, :circle]
children.frozen?     #=> true

Parameters:

  • content (String)

    SVG/XML source content

  • element (Sevgi::Graphics::Element)

    target graphics element

  • id (String, Symbol, nil) (defaults to: nil)

    optional SVG id selecting a node inside the source

  • omit (String, Symbol, Array<String, Symbol>, nil) (defaults to: nil)

    exact attribute name or names omitted from the selected subtree after id selection

Returns:

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

    immutable included-child snapshot

Raises:

  • (Sevgi::ArgumentError)

    when content is malformed or rootless, or when the id is absent

See Also:



156
157
158
# File 'lib/sevgi/derender.rb', line 156

def self.evaluate_children(content, element, id: nil, omit: nil)
  Document.new(content).decompile(id, omit:).evaluate_children(element)
end

.evaluate_children_file(file, element, id: nil, omit: nil) ⇒ Array<Sevgi::Graphics::Element>

Note:

Namespace-aware dispatch preserves ordinary foreign/qualified nodes and nested SVG elements.

Evaluates only the selected node's children from an SVG/XML file under a graphics element.

Parameters:

  • file (String)

    path to the source SVG/XML file

  • element (Sevgi::Graphics::Element)

    target graphics element

  • id (String, Symbol, nil) (defaults to: nil)

    optional SVG id selecting a node inside the source

  • omit (String, Symbol, Array<String, Symbol>, nil) (defaults to: nil)

    exact attribute name or names omitted from the selected subtree after id selection

Returns:

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

    immutable included-child snapshot

Raises:

  • (Sevgi::ArgumentError)

    when the file cannot be found, file content is malformed or rootless, or the id is absent

  • (SystemCallError)

    when the file cannot be read

See Also:



191
192
193
# File 'lib/sevgi/derender.rb', line 191

def self.evaluate_children_file(file, element, id: nil, omit: nil)
  Document.load_file(file).decompile(id, omit:).evaluate_children(element)
end

.evaluate_file(file, element, id: nil, omit: nil) ⇒ Sevgi::Graphics::Element?

Note:

Namespace-aware dispatch preserves ordinary foreign/qualified nodes and nested SVG elements.

Evaluates an SVG/XML file under a graphics element, including the selected node.

Parameters:

  • file (String)

    path to the source SVG/XML file

  • element (Sevgi::Graphics::Element)

    target graphics element

  • id (String, Symbol, nil) (defaults to: nil)

    optional SVG id selecting a node inside the source

  • omit (String, Symbol, Array<String, Symbol>, nil) (defaults to: nil)

    exact attribute name or names omitted from the selected subtree after id selection

Returns:

  • (Sevgi::Graphics::Element, nil)

    included selected/root graphics element, or nil when the selected node produces no graphics output

Raises:

  • (Sevgi::ArgumentError)

    when the file cannot be found, file content is malformed or rootless, or the id is absent

  • (SystemCallError)

    when the file cannot be read

See Also:



174
175
176
# File 'lib/sevgi/derender.rb', line 174

def self.evaluate_file(file, element, id: nil, omit: nil)
  Document.load_file(file).decompile(id, omit:).evaluate(element)
end