Class: Sevgi::Derender::Document
- Inherits:
-
Object
- Object
- Sevgi::Derender::Document
- Defined in:
- lib/sevgi/derender/document.rb
Overview
Parsed SVG/XML document wrapper used by the derender pipeline.
Instance Attribute Summary collapse
-
#decl ⇒ String?
readonly
Returns the source XML declaration when present.
-
#doc ⇒ Nokogiri::XML::Document
readonly
Returns the parsed XML document.
Class Method Summary collapse
-
.declaration(content) ⇒ String?
Extracts the XML declaration from SVG/XML content.
-
.load_file(path) ⇒ Sevgi::Derender::Document
Loads and parses an SVG/XML file.
-
.parse(content) ⇒ Nokogiri::XML::Document
Parses SVG/XML content in strict XML mode.
Instance Method Summary collapse
-
#decompile(id = nil) ⇒ Sevgi::Derender::Node
Converts the root or selected node into a derender node.
-
#initialize(content) ⇒ void
constructor
Builds a parsed document wrapper from SVG/XML content.
-
#pres ⇒ Array<String>
Returns XML declaration and pre-root nodes preserved for root decompilation.
Constructor Details
#initialize(content) ⇒ void
Builds a parsed document wrapper from SVG/XML content.
62 63 64 65 |
# File 'lib/sevgi/derender/document.rb', line 62 def initialize(content) @doc = self.class.parse(content) @decl = self.class.declaration(content) end |
Instance Attribute Details
#decl ⇒ String? (readonly)
Returns the source XML declaration when present.
55 56 57 |
# File 'lib/sevgi/derender/document.rb', line 55 def decl @decl end |
#doc ⇒ Nokogiri::XML::Document (readonly)
Returns the parsed XML document.
51 52 53 |
# File 'lib/sevgi/derender/document.rb', line 51 def doc @doc end |
Class Method Details
.declaration(content) ⇒ String?
Extracts the XML declaration from SVG/XML content.
43 44 45 46 47 |
# File 'lib/sevgi/derender/document.rb', line 43 def self.declaration(content) return unless (content = content.to_s.lstrip).start_with?("<?xml ") content[/\A<\?xml\b.*?\?>/m] end |
.load_file(path) ⇒ Sevgi::Derender::Document
Loads and parses an SVG/XML file.
Each call reads the current file content and returns an isolated parsed document. Caller mutation of one loaded document does not affect later loads of the same path.
17 18 19 20 21 22 23 24 |
# File 'lib/sevgi/derender/document.rb', line 17 def self.load_file(path) entry = ::File.(F.qualify(path, "svg")) ArgumentError.("File not found: #{path}") unless ::File.exist?(entry) content = ::File.read(entry) new(content) end |
.parse(content) ⇒ Nokogiri::XML::Document
Parses SVG/XML content in strict XML mode.
31 32 33 34 35 36 37 38 |
# File 'lib/sevgi/derender/document.rb', line 31 def self.parse(content) Nokogiri::XML(content.to_s.lstrip, &:strict).tap do |doc| ArgumentError.("XML document has no root element") unless doc.root end rescue Nokogiri::XML::SyntaxError => e raise ArgumentError, "Malformed XML: #{e..lines.first.strip}", cause: e end |
Instance Method Details
#decompile(id = nil) ⇒ Sevgi::Derender::Node
Converts the root or selected node into a derender node.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/sevgi/derender/document.rb', line 71 def decompile(id = nil) if id if (found = doc.xpath("//*[@id=#{xpath_literal(id)}]") || []).empty? ArgumentError.("No such element with id '#{id}' in document") end found.first else doc.root end => element ArgumentError.("XML document has no root element") unless element Node.new(element, pres, namespaces: namespace_scope(element)) end |
#pres ⇒ Array<String>
Returns XML declaration and pre-root nodes preserved for root decompilation. The result contains only String lines and omits the declaration when the source did not provide one.
90 91 92 93 94 95 96 |
# File 'lib/sevgi/derender/document.rb', line 90 def pres @pres ||= [].tap do |lines| lines.append(*doc.children.take_while { |node| node != doc.root }.map(&:to_xml)) lines.unshift(decl) if decl && lines.first != decl lines.compact! end end |