sevgi-derender 0.98.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +96 -2
- data/README.md +16 -3
- data/lib/sevgi/binaries/igves.rb +3 -3
- data/lib/sevgi/derender/attributes.rb +0 -1
- data/lib/sevgi/derender/document.rb +33 -16
- data/lib/sevgi/derender/elements/any.rb +10 -10
- data/lib/sevgi/derender/elements/comment.rb +18 -0
- data/lib/sevgi/derender/elements/css.rb +8 -7
- data/lib/sevgi/derender/elements/instruction.rb +17 -0
- data/lib/sevgi/derender/elements/root.rb +16 -9
- data/lib/sevgi/derender/elements/text.rb +11 -0
- data/lib/sevgi/derender/elements.rb +2 -1
- data/lib/sevgi/derender/evaluator.rb +25 -17
- data/lib/sevgi/derender/internal.rb +1 -6
- data/lib/sevgi/derender/node.rb +52 -23
- data/lib/sevgi/derender/version.rb +1 -1
- data/lib/sevgi/derender.rb +16 -7
- metadata +8 -7
- data/lib/sevgi/derender/elements/junk.rb +0 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e02ddd4869fac0f3ab35c12f53bcdd9e23bdc936d8753a17ff56b651c8a07882
|
|
4
|
+
data.tar.gz: aeff138c2ced508eca978c9eccd2e547c808e2be7d4d7bac859a57700e118892
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dee05c8a84e8872ce946aa18f3f10071c0b07bea43170cc3a59f03ef9b434383e184478c84fe43270bf9524af3b135ee827bbe55868a64b62099af8dc34f37a1
|
|
7
|
+
data.tar.gz: db4b7b23ca99f153f40ff0ec6bc2cdd126c399a466b93c3d92f028669a672de39e9dc783f093f1bb68fa1b738b7809fc6693651c19e251700248e9601afdb581
|
data/CHANGELOG.md
CHANGED
|
@@ -3,7 +3,101 @@
|
|
|
3
3
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## 1.0.0 - 2026-09-16
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Added Hatch and Orb Showcase examples and displayed both arc lengths in the Arc example.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Matched documentation page widths to the homepage Showcase.
|
|
15
|
+
- Aligned Derender user guidance with UTF-8 normalization and safe subtree selection rules.
|
|
16
|
+
- Clarified the packaged skill's script invocation, subtree copying, and Derender selection and encoding rules.
|
|
17
|
+
- Allowed Canvas and Paper values as the first `SVG` argument when using the default document profile.
|
|
18
|
+
- Made element `dup` and `clone` own independent subtrees while retaining IDs and Ruby copy semantics.
|
|
19
|
+
- Made Segment equality compare length and direction; ordering still compares length only.
|
|
20
|
+
- Limited Tile cell, row, and column queries to the requested geometry and accelerated XML character validation.
|
|
21
|
+
- Simplified the first-run guide and aligned library constructor examples.
|
|
22
|
+
- Updated the packaged skill for canvas origins, alignment, Paper lookup, curved geometry, and export constraints.
|
|
23
|
+
- Revised DSL catalog examples and packaged Sevgi skill guidance to use statement-style calls and show inspection results.
|
|
24
|
+
- Refined Showcase example tabs, made Ruby and XML views fill their panels, and hid executable preambles from Ruby views.
|
|
25
|
+
- Documented non-rendering element data and clarified the related DSL catalog examples.
|
|
26
|
+
- Refined Showcase heading spacing, page-title colors, and DSL catalog cards across light and dark themes.
|
|
27
|
+
- Removed an obsolete ruler example and unused site code.
|
|
28
|
+
- Kept the Squared and Copperplate guidesheet examples together at the end of the Showcase.
|
|
29
|
+
- Updated the packaged skill to avoid duplicate semantic shapes and unnecessary paint passes.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- Kept horizontal scrollbars visible in Showcase example code panels.
|
|
34
|
+
- Read Derender input in its declared XML encoding and normalized generated source, XML declarations, and markup to UTF-8.
|
|
35
|
+
- Preserved open-path endpoints and derived edges independently of display precision.
|
|
36
|
+
- Kept near-axis and near-parallel line equations and intersections independent of angle and slope rounding.
|
|
37
|
+
- Corrected the Showcase social image dimensions.
|
|
38
|
+
- Added SVG namespaces to standalone drawing examples and regenerated their outputs.
|
|
39
|
+
- Made failed Sevgi Rake tasks stop dependent tasks and captured required-library failures in executor results.
|
|
40
|
+
- Removed executor signal-handler replacement so the host and shell retain SIGINT ownership.
|
|
41
|
+
- Escaped late export CSS as XML text and inserted it only at a supported final root closing tag.
|
|
42
|
+
- Preserved Derender processing instructions and rejected custom entity references and unsupported trailing document nodes before inclusion.
|
|
43
|
+
- Included both box origins in `Align`, unified Tile index validation, and isolated custom numeric attribute snapshots.
|
|
44
|
+
- Prevented avoidable overflow and underflow in point distances.
|
|
45
|
+
- Corrected browser source-panel expectations and added executable documentation, YARD, and packaged-skill checks.
|
|
46
|
+
- Rendered inline code in DSL catalog summaries and kept linked task themes visible below the sticky header.
|
|
47
|
+
- Restored Showcase tab icons with embedded Font Awesome SVGs.
|
|
48
|
+
|
|
49
|
+
## 0.100.0 - 2026-09-09
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- Added `ArcTo` and `ArcBy` for SVG-native elliptical arc paths.
|
|
54
|
+
- Added Geometry `Arc`, `Ellipse`, and `Circle` with bounds, length, predicates, affine transformations, and
|
|
55
|
+
linear/quadratic intersections. Closed ellipses and circles support sweeps and hatching.
|
|
56
|
+
- Added Geometry `Point.midpoint`, `Element#closed?`, lined `vertices`, open-path traversal, and `Rect#center`.
|
|
57
|
+
- Added Geometry aggregate bounding boxes through `Operation.box`, point collinearity through `Point.collinear?`, and
|
|
58
|
+
polygon `simple?`, `convex?`, and `concave?` predicates.
|
|
59
|
+
- Added Protractor and Arc examples and documented the drawing and calculation APIs.
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- Removed redundant parent scans while duplicating element subtrees.
|
|
64
|
+
- Reused source bounds across Tile cells to reduce repeated calculations and object allocations.
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- Preserved Showcase card HTML through Markdown rendering so all examples and their tabs remain visible.
|
|
69
|
+
- Preserved XML declarations, pre-root comments, CDATA sections, inline comments, and namespace-only leaves in
|
|
70
|
+
Derender output and evaluation.
|
|
71
|
+
- Limited PDF stamp recoloring to replaced text and carried graphics state across a page's content streams.
|
|
72
|
+
- Corrected decimal interval fitting and made Grid point queries honor the active numeric precision.
|
|
73
|
+
- Prevented implicit shell interpretation of single executable arguments in `F.sh` and `F.sh!`, including paths with spaces or shell metacharacters.
|
|
74
|
+
- Preserved inherited namespaces on detached Derender nodes in generated source and direct evaluation, including imports through `EvaluateChildren` and `IncludeChildren`.
|
|
75
|
+
- Prevented sweep and Hatch lines from crossing the exterior between two tangent vertices of a concave polygon.
|
|
76
|
+
- Aligned Tile cells with their declared bounds for circles, rotated shapes, and polygons whose first vertex differs from their bounding-box origin.
|
|
77
|
+
- Limited `Load` chains to 128 active sources with `Executor::LoadDepthError`, preserving cycle detection and nested load diagnostics.
|
|
78
|
+
- Rejected nil and false aggregate-box inputs with the documented geometry error.
|
|
79
|
+
- Restored precision-aware rejection of zero-length Triangle sides.
|
|
80
|
+
- Made point-set collinearity independent of input order and removed eager polygon edge-pair storage.
|
|
81
|
+
- Applied the collinearity tolerance to every three-point subset, removing coordinate-axis-dependent baseline selection.
|
|
82
|
+
|
|
83
|
+
## 0.99.0 - 2026-08-09
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
|
|
87
|
+
- Added `SVG.Module` for building anonymous callable drawing modules with their contract installed before definition.
|
|
88
|
+
- Added responsive Mermaid diagrams for the Derender round trip and SVG validation lifecycle.
|
|
89
|
+
|
|
90
|
+
### Changed
|
|
91
|
+
|
|
92
|
+
- Reorganized the documentation around getting started, usage, composition, documents, layout, output, and examples.
|
|
93
|
+
- Documented how the `igves` and `igsev` command names reflect their conversion directions.
|
|
94
|
+
- Normalized DSL catalog provider labels to lowercase and simplified polyfill-backed editor entries to `inkscape`.
|
|
95
|
+
|
|
96
|
+
### Fixed
|
|
97
|
+
|
|
98
|
+
- Allowed A5-on-A4 pdfcpu conversion to replace an existing output file.
|
|
99
|
+
- Pre-rendered Mermaid diagrams as inline SVG instead of parsing them in site visitors' browsers.
|
|
100
|
+
- Removed duplicate provider and context labels from DSL catalog entries.
|
|
7
101
|
|
|
8
102
|
## 0.98.2 - 2026-07-25
|
|
9
103
|
|
|
@@ -212,7 +306,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
212
306
|
|
|
213
307
|
### Changed
|
|
214
308
|
|
|
215
|
-
- Added the
|
|
309
|
+
- Added the checkerboard example to the documentation showcase flow.
|
|
216
310
|
- Consolidated Victor Book attribution for adapted showcase examples into a single documentation note.
|
|
217
311
|
|
|
218
312
|
### Fixed
|
data/README.md
CHANGED
|
@@ -18,12 +18,25 @@ require "sevgi/derender"
|
|
|
18
18
|
|
|
19
19
|
```ruby
|
|
20
20
|
source = "<svg><rect width=\"3\" height=\"5\"/></svg>"
|
|
21
|
-
Sevgi::Derender.derender(source)
|
|
21
|
+
puts Sevgi::Derender.derender(source)
|
|
22
|
+
# SVG do
|
|
23
|
+
# rect width: 3, height: 5
|
|
24
|
+
# end
|
|
22
25
|
|
|
23
26
|
source = '<svg><rect id="mark" style="fill: red" width="3"/></svg>'
|
|
24
|
-
Sevgi::Derender.derender(source, omit: %i[id style])
|
|
27
|
+
puts Sevgi::Derender.derender(source, omit: %i[id style])
|
|
28
|
+
# SVG do
|
|
29
|
+
# rect width: 3
|
|
30
|
+
# end
|
|
25
31
|
```
|
|
26
32
|
|
|
33
|
+
Use `decompile` to inspect an immutable parsed node. Use `evaluate` to add a selected node directly to an existing
|
|
34
|
+
Sevgi document. Generated source is ordinary Ruby. Review it and integrate it statically instead of evaluating it
|
|
35
|
+
dynamically.
|
|
36
|
+
|
|
37
|
+
Derender reads the XML encoding declaration or byte-order mark. Generated Ruby and rendered XML use UTF-8.
|
|
38
|
+
The XML declaration keeps its version and standalone flag, with any encoding field changed to UTF-8.
|
|
39
|
+
|
|
27
40
|
## Executable
|
|
28
41
|
|
|
29
42
|
```sh
|
|
@@ -49,7 +62,7 @@ Requires Ruby 3.4.0 or newer. CI verifies the current Ruby 3.4 release and the d
|
|
|
49
62
|
|
|
50
63
|
## Native prerequisites
|
|
51
64
|
|
|
52
|
-
This gem needs no native libraries of its own. Nokogiri
|
|
65
|
+
This gem needs no native libraries of its own. Nokogiri can use platform packages on some Ruby platforms.
|
|
53
66
|
|
|
54
67
|
## Links
|
|
55
68
|
|
data/lib/sevgi/binaries/igves.rb
CHANGED
|
@@ -88,10 +88,10 @@ module Sevgi
|
|
|
88
88
|
rescue ::StandardError => e
|
|
89
89
|
raise if raw_error?(options)
|
|
90
90
|
|
|
91
|
-
die(e
|
|
91
|
+
die(e)
|
|
92
92
|
end
|
|
93
93
|
|
|
94
|
-
def die(error
|
|
94
|
+
def die(error)
|
|
95
95
|
warn(error.message)
|
|
96
96
|
warn("")
|
|
97
97
|
backtrace(error).each { warn(" #{it}") }
|
|
@@ -142,7 +142,7 @@ module Sevgi
|
|
|
142
142
|
rescue ::StandardError => e
|
|
143
143
|
raise if raw_error?(options)
|
|
144
144
|
|
|
145
|
-
die(e
|
|
145
|
+
die(e)
|
|
146
146
|
end
|
|
147
147
|
|
|
148
148
|
def raw_error?(options)
|
|
@@ -20,7 +20,7 @@ module Sevgi
|
|
|
20
20
|
|
|
21
21
|
ArgumentError.("File not found: #{path}") unless ::File.exist?(entry)
|
|
22
22
|
|
|
23
|
-
content = ::File.
|
|
23
|
+
content = ::File.binread(entry)
|
|
24
24
|
new(content)
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -30,7 +30,7 @@ module Sevgi
|
|
|
30
30
|
# @raise [Sevgi::ArgumentError] when content is not well-formed XML
|
|
31
31
|
# @raise [Sevgi::ArgumentError] when content has no root element
|
|
32
32
|
def self.parse(content)
|
|
33
|
-
Nokogiri::XML(content.to_s.
|
|
33
|
+
Nokogiri::XML(content.to_s.b.sub(/\A[ \t\r\n]+/, ""), &:strict).tap do |doc|
|
|
34
34
|
ArgumentError.("XML document has no root element") unless doc.root
|
|
35
35
|
end
|
|
36
36
|
|
|
@@ -38,20 +38,26 @@ module Sevgi
|
|
|
38
38
|
raise ArgumentError, "Malformed XML: #{e.message.lines.first.strip}", cause: e
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
# Extracts the XML declaration
|
|
41
|
+
# Extracts the XML declaration and aligns its encoding with UTF-8 output.
|
|
42
42
|
# @param content [String] SVG/XML source content
|
|
43
|
+
# @param encoding [String, nil] source encoding reported by the XML parser
|
|
43
44
|
# @return [String, nil] XML declaration line, if present
|
|
44
|
-
def self.declaration(content)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
content
|
|
45
|
+
def self.declaration(content, encoding: nil)
|
|
46
|
+
content = content.to_s.b
|
|
47
|
+
encoding ||= content.start_with?("\xFF\xFE".b, "\xFE\xFF".b) ? "UTF-16" : "UTF-8"
|
|
48
|
+
content = content.encode("UTF-8", encoding).delete_prefix("\uFEFF").lstrip
|
|
49
|
+
declaration = content[/\A<\?xml[ \t\r\n].*?\?>/m]
|
|
50
|
+
|
|
51
|
+
declaration&.sub(/encoding\s*=\s*(["']).*?\1/, "encoding=\"UTF-8\"")
|
|
52
|
+
rescue EncodingError, ::ArgumentError => e
|
|
53
|
+
raise ArgumentError, "Invalid XML encoding: #{e.message}", cause: e
|
|
48
54
|
end
|
|
49
55
|
|
|
50
56
|
# Returns the parsed XML document.
|
|
51
57
|
# @return [Nokogiri::XML::Document]
|
|
52
58
|
attr_reader :doc
|
|
53
59
|
|
|
54
|
-
# Returns the
|
|
60
|
+
# Returns the XML declaration with its encoding field normalized to UTF-8, when present.
|
|
55
61
|
# @return [String, nil]
|
|
56
62
|
attr_reader :decl
|
|
57
63
|
|
|
@@ -62,7 +68,8 @@ module Sevgi
|
|
|
62
68
|
# @raise [Sevgi::ArgumentError] when content has no root element
|
|
63
69
|
def initialize(content)
|
|
64
70
|
@doc = self.class.parse(content)
|
|
65
|
-
@decl = self.class.declaration(content)
|
|
71
|
+
@decl = self.class.declaration(content, encoding: doc.encoding)
|
|
72
|
+
@doc.encoding = "UTF-8"
|
|
66
73
|
end
|
|
67
74
|
|
|
68
75
|
# Converts the root or selected node into a derender node.
|
|
@@ -72,22 +79,19 @@ module Sevgi
|
|
|
72
79
|
# @raise [Sevgi::ArgumentError] when the document has no root element or the id is absent
|
|
73
80
|
def decompile(id = nil, omit: nil)
|
|
74
81
|
if id
|
|
75
|
-
|
|
76
|
-
ArgumentError.("No such element with id '#{id}' in document")
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
found.first
|
|
82
|
+
doc.at_xpath("//*[@id=#{xpath_literal(id)}]") || ArgumentError.("No such element with id '#{id}' in document")
|
|
80
83
|
else
|
|
81
84
|
doc.root
|
|
82
85
|
end => element
|
|
83
86
|
|
|
84
87
|
ArgumentError.("XML document has no root element") unless element
|
|
88
|
+
validate_selection(element, whole: !id)
|
|
85
89
|
|
|
86
90
|
Node.send(:new, element, pres, namespaces: namespace_scope(element), omit: omissions(omit))
|
|
87
91
|
end
|
|
88
92
|
|
|
89
|
-
# Returns XML declaration and pre-root nodes
|
|
90
|
-
#
|
|
93
|
+
# Returns the XML declaration and pre-root nodes as UTF-8 for root decompilation.
|
|
94
|
+
# The result omits the declaration when the source did not provide one.
|
|
91
95
|
# @return [Array<String>] preamble XML lines
|
|
92
96
|
def pres
|
|
93
97
|
@pres ||= [].tap do |lines|
|
|
@@ -99,6 +103,19 @@ module Sevgi
|
|
|
99
103
|
|
|
100
104
|
private
|
|
101
105
|
|
|
106
|
+
def validate_selection(element, whole:)
|
|
107
|
+
if whole && doc.root.next_sibling
|
|
108
|
+
ArgumentError.("XML nodes after the root element are not supported")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
element.traverse do |node|
|
|
112
|
+
references = [node, *node.attribute_nodes.flat_map { it.children.to_a }]
|
|
113
|
+
if references.any? { it.type == Nokogiri::XML::Node::ENTITY_REF_NODE }
|
|
114
|
+
ArgumentError.("Custom XML entity references are not supported")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
102
119
|
def namespace_scope(element)
|
|
103
120
|
element == doc.root ? local_namespaces(element) : element.namespaces
|
|
104
121
|
end
|
|
@@ -8,21 +8,19 @@ module Sevgi
|
|
|
8
8
|
module Any
|
|
9
9
|
# Converts this node into unformatted Sevgi DSL lines.
|
|
10
10
|
# @return [Array<String>] unformatted Ruby source lines
|
|
11
|
-
def decompile(
|
|
11
|
+
def decompile(*, namespaces: self.namespaces())
|
|
12
12
|
if children.any?
|
|
13
|
-
|
|
13
|
+
text_leaf? ? Array(leaf(Ruby.literal(content), namespaces:)) : tree(namespaces)
|
|
14
14
|
else
|
|
15
|
-
Array(leaf(
|
|
15
|
+
Array(leaf(namespaces:))
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
private
|
|
20
20
|
|
|
21
|
-
def leaf(
|
|
22
|
-
attributes = all_attributes
|
|
23
|
-
args
|
|
24
|
-
args << Ruby.literal(content) if has_content
|
|
25
|
-
args << Attributes.decompile(attributes) if has_attributes && attributes.any?
|
|
21
|
+
def leaf(*args, namespaces:)
|
|
22
|
+
attributes = all_attributes(namespaces)
|
|
23
|
+
args << Attributes.decompile(attributes) if attributes.any?
|
|
26
24
|
|
|
27
25
|
return explicit_leaf(args) unless bare?
|
|
28
26
|
|
|
@@ -37,9 +35,11 @@ module Sevgi
|
|
|
37
35
|
args.empty? ? "#{call})" : "#{call}, #{args.join(", ")})"
|
|
38
36
|
end
|
|
39
37
|
|
|
40
|
-
def tree
|
|
38
|
+
def tree(namespaces)
|
|
39
|
+
opening = inline_content? ? leaf(Ruby.literal(""), namespaces:) : leaf(namespaces:)
|
|
40
|
+
|
|
41
41
|
[
|
|
42
|
-
"#{
|
|
42
|
+
"#{opening} do",
|
|
43
43
|
*children.map { it.send(:decompile) }.flatten,
|
|
44
44
|
"end"
|
|
45
45
|
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sevgi
|
|
4
|
+
module Derender
|
|
5
|
+
module Elements
|
|
6
|
+
# Element strategy for XML comments.
|
|
7
|
+
# @api private
|
|
8
|
+
module Comment
|
|
9
|
+
# Converts a comment into a floating DSL node.
|
|
10
|
+
# @return [Array<String>] unformatted Ruby source lines
|
|
11
|
+
def decompile(*)
|
|
12
|
+
markup = "<!--#{content}-->"
|
|
13
|
+
["_ Sevgi::Graphics::Content.verbatim(#{Ruby.literal(markup)})"]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -8,21 +8,21 @@ module Sevgi
|
|
|
8
8
|
module CSS
|
|
9
9
|
# Converts a style node into unformatted Sevgi DSL lines.
|
|
10
10
|
# @return [Array<String>] unformatted Ruby source lines
|
|
11
|
-
def decompile(
|
|
12
|
-
return raw_style unless (lines = css_lines)
|
|
11
|
+
def decompile(*, namespaces: self.namespaces())
|
|
12
|
+
return raw_style(namespaces) unless (lines = css_lines)
|
|
13
13
|
|
|
14
14
|
[
|
|
15
15
|
"css({",
|
|
16
16
|
*lines,
|
|
17
|
-
"}, #{css_attributes})",
|
|
17
|
+
"}, #{css_attributes(namespaces)})",
|
|
18
18
|
""
|
|
19
19
|
]
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
private
|
|
23
23
|
|
|
24
|
-
def css_attributes
|
|
25
|
-
attributes = all_attributes
|
|
24
|
+
def css_attributes(namespaces)
|
|
25
|
+
attributes = all_attributes(namespaces)
|
|
26
26
|
source = Attributes.decompile(attributes)
|
|
27
27
|
|
|
28
28
|
attributes.key?("type") ? source : [source, "type: nil"].reject(&:empty?).join(", ")
|
|
@@ -42,9 +42,10 @@ module Sevgi
|
|
|
42
42
|
.flatten
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
def raw_style
|
|
45
|
+
def raw_style(namespaces)
|
|
46
46
|
arguments = ["Sevgi::Graphics::Content.cdata(#{Ruby.literal(node.content)})"]
|
|
47
|
-
|
|
47
|
+
attributes = all_attributes(namespaces)
|
|
48
|
+
arguments << Attributes.decompile(attributes) if attributes.any?
|
|
48
49
|
|
|
49
50
|
["style #{arguments.join(", ")}", ""]
|
|
50
51
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sevgi
|
|
4
|
+
module Derender
|
|
5
|
+
module Elements
|
|
6
|
+
# Preserves XML processing instructions as inert markup.
|
|
7
|
+
# @api private
|
|
8
|
+
module Instruction
|
|
9
|
+
# Converts a processing instruction into a floating DSL node.
|
|
10
|
+
# @return [Array<String>] unformatted Ruby source lines
|
|
11
|
+
def decompile(*)
|
|
12
|
+
["_ Sevgi::Graphics::Content.verbatim(#{Ruby.literal(content)})"]
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -11,20 +11,27 @@ module Sevgi
|
|
|
11
11
|
# Converts the SVG root into unformatted Sevgi DSL lines.
|
|
12
12
|
# @param pres [Array<String>] preamble XML lines
|
|
13
13
|
# @return [Array<String>] unformatted Ruby source lines
|
|
14
|
-
def decompile(pres = [])
|
|
14
|
+
def decompile(pres = [], **)
|
|
15
15
|
lines = super
|
|
16
16
|
return lines unless pres&.any?
|
|
17
17
|
|
|
18
|
-
lines.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
lines[0] = document_call(lines.first)
|
|
19
|
+
|
|
20
|
+
lines.unshift(preamble_lines(pres))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def document_call(line)
|
|
24
|
+
return line.sub("SVG", "SVG document") if ["SVG", "SVG do"].include?(line)
|
|
25
|
+
|
|
26
|
+
line.sub(/\ASVG /, "SVG document, ")
|
|
26
27
|
end
|
|
27
28
|
|
|
29
|
+
def preamble_lines(pres)
|
|
30
|
+
["document = SVG.Document preambles: [", *pres.map { "#{Ruby.literal(it)}," }, "]", ""]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private :document_call, :preamble_lines
|
|
34
|
+
|
|
28
35
|
# Returns the root DSL word.
|
|
29
36
|
# @return [String]
|
|
30
37
|
def element = "SVG"
|
|
@@ -10,6 +10,17 @@ module Sevgi
|
|
|
10
10
|
# @return [Array<String>] unformatted Ruby source lines
|
|
11
11
|
def decompile(*) = ["_ #{Ruby.literal(content)}"]
|
|
12
12
|
end
|
|
13
|
+
|
|
14
|
+
# Element strategy for CDATA sections.
|
|
15
|
+
# @api private
|
|
16
|
+
module CData
|
|
17
|
+
# Converts CDATA into a floating content node.
|
|
18
|
+
# @return [Array<String>] unformatted Ruby source lines
|
|
19
|
+
def decompile(*)
|
|
20
|
+
markup = "<![CDATA[#{Graphics.const_get(:XML).cdata(content)}]]>"
|
|
21
|
+
["_ Sevgi::Graphics::Content.verbatim(#{Ruby.literal(markup)})"]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
13
24
|
end
|
|
14
25
|
end
|
|
15
26
|
end
|
|
@@ -10,7 +10,8 @@ module Sevgi
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
require_relative "elements/any"
|
|
13
|
+
require_relative "elements/comment"
|
|
14
|
+
require_relative "elements/instruction"
|
|
13
15
|
require_relative "elements/css"
|
|
14
|
-
require_relative "elements/junk"
|
|
15
16
|
require_relative "elements/root"
|
|
16
17
|
require_relative "elements/text"
|
|
@@ -12,42 +12,48 @@ module Sevgi
|
|
|
12
12
|
|
|
13
13
|
# Appends a derender node to the target parent.
|
|
14
14
|
# @param node [Sevgi::Derender::Node] derender node
|
|
15
|
+
# @param namespaces [Hash{String => String}] namespace declarations for the appended node
|
|
15
16
|
# @return [Sevgi::Graphics::Element, nil] included element, or nil when the node does not produce graphics output
|
|
16
|
-
def append(node)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
def append(node, namespaces: node.namespaces)
|
|
18
|
+
type = node.send(:type)
|
|
19
|
+
return append_css(node, namespaces) if type == :CSS
|
|
20
|
+
return build(:_, node.content) if type == :Text
|
|
21
|
+
return append_cdata(node) if type == :CData
|
|
22
|
+
return build(:_, Graphics::Content.verbatim("<!--#{node.content}-->")) if type == :Comment
|
|
23
|
+
return build(:_, Graphics::Content.verbatim(node.content)) if type == :Instruction
|
|
24
|
+
|
|
25
|
+
append_element(node, namespaces)
|
|
25
26
|
end
|
|
26
27
|
|
|
27
28
|
private
|
|
28
29
|
|
|
29
30
|
attr_reader :parent
|
|
30
31
|
|
|
31
|
-
def
|
|
32
|
+
def append_cdata(node)
|
|
33
|
+
body = Graphics.const_get(:XML).cdata(node.content)
|
|
34
|
+
build(:_, Graphics::Content.verbatim("<![CDATA[#{body}]]>"))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def append_css(node, namespaces)
|
|
32
38
|
content = if (hash = Css.rules(node.content))
|
|
33
39
|
Graphics::Content.css(hash)
|
|
34
40
|
else
|
|
35
41
|
Graphics::Content.cdata(node.content)
|
|
36
42
|
end
|
|
37
43
|
|
|
38
|
-
build(:style, content, **node.send(:all_attributes))
|
|
44
|
+
build(:style, content, **node.send(:all_attributes, namespaces))
|
|
39
45
|
end
|
|
40
46
|
|
|
41
|
-
def append_element(node)
|
|
47
|
+
def append_element(node, namespaces)
|
|
42
48
|
contents = contents(node)
|
|
43
49
|
|
|
44
|
-
build(node.name, *contents, **attributes(node)).tap do |element|
|
|
45
|
-
node.children.each { self.class.new(element).append(it) }
|
|
50
|
+
build(node.name, *contents, **attributes(node, namespaces)).tap do |element|
|
|
51
|
+
node.children.each { self.class.new(element).append(it) } unless node.send(:text_leaf?)
|
|
46
52
|
end
|
|
47
53
|
end
|
|
48
54
|
|
|
49
|
-
def attributes(node)
|
|
50
|
-
attributes = node.send(:all_attributes)
|
|
55
|
+
def attributes(node, namespaces)
|
|
56
|
+
attributes = node.send(:all_attributes, namespaces)
|
|
51
57
|
return attributes unless (style = attributes["style"])
|
|
52
58
|
return attributes unless (declarations = Css.declarations(style))
|
|
53
59
|
|
|
@@ -55,7 +61,9 @@ module Sevgi
|
|
|
55
61
|
end
|
|
56
62
|
|
|
57
63
|
def contents(node)
|
|
58
|
-
node.
|
|
64
|
+
return [node.content] if node.send(:text_leaf?)
|
|
65
|
+
|
|
66
|
+
node.send(:inline_content?) ? [""] : []
|
|
59
67
|
end
|
|
60
68
|
|
|
61
69
|
def build(name, *contents, **attributes)
|
|
@@ -51,16 +51,11 @@ module Sevgi
|
|
|
51
51
|
nil
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
# Converts a CSS key into a Ruby hash key.
|
|
55
|
-
# @param arg [String] CSS key
|
|
56
|
-
# @return [String] Ruby hash key source
|
|
57
|
-
def to_key(arg) = arg
|
|
58
|
-
|
|
59
54
|
# Converts a CSS key/value pair into Ruby hash source.
|
|
60
55
|
# @param key [String] CSS declaration key
|
|
61
56
|
# @param value [String] CSS declaration value
|
|
62
57
|
# @return [String] Ruby hash pair source
|
|
63
|
-
def to_key_value(key, value) = "#{Ruby.literal(
|
|
58
|
+
def to_key_value(key, value) = "#{Ruby.literal(key)}: #{to_value(value)}"
|
|
64
59
|
|
|
65
60
|
# Converts a CSS value into Ruby source.
|
|
66
61
|
# @param arg [String] CSS value
|
data/lib/sevgi/derender/node.rb
CHANGED
|
@@ -25,11 +25,20 @@ module Sevgi
|
|
|
25
25
|
# Captures owned Node state during construction.
|
|
26
26
|
# @api private
|
|
27
27
|
module Capture
|
|
28
|
+
NODE_TYPES = {
|
|
29
|
+
Nokogiri::XML::Node::TEXT_NODE => :Text,
|
|
30
|
+
Nokogiri::XML::Node::CDATA_SECTION_NODE => :CData,
|
|
31
|
+
Nokogiri::XML::Node::COMMENT_NODE => :Comment,
|
|
32
|
+
Nokogiri::XML::Node::PI_NODE => :Instruction
|
|
33
|
+
}.freeze
|
|
34
|
+
private_constant :NODE_TYPES
|
|
35
|
+
|
|
28
36
|
private
|
|
29
37
|
|
|
30
38
|
def capture_context(pres, namespaces)
|
|
31
39
|
@pres = pres.map { it.to_s.dup.freeze }.freeze
|
|
32
40
|
@namespaces = snapshot(namespaces || local_namespaces)
|
|
41
|
+
@scope = snapshot(node.namespaces)
|
|
33
42
|
@type = dispatch
|
|
34
43
|
singleton_class.send(:private, :decompile)
|
|
35
44
|
end
|
|
@@ -53,10 +62,17 @@ module Sevgi
|
|
|
53
62
|
end
|
|
54
63
|
|
|
55
64
|
def capture_identity
|
|
56
|
-
@content =
|
|
65
|
+
@content = captured_content.dup.freeze
|
|
66
|
+
|
|
57
67
|
@name = [node.namespace&.prefix, node.name].compact.join(":").freeze
|
|
58
68
|
end
|
|
59
69
|
|
|
70
|
+
def captured_content
|
|
71
|
+
return node.to_xml if node.processing_instruction?
|
|
72
|
+
|
|
73
|
+
literal_content? || preserve_space? ? node.content : normalized_content
|
|
74
|
+
end
|
|
75
|
+
|
|
60
76
|
def metadata(key, value)
|
|
61
77
|
[key.delete_prefix(META_NAMESPACE), value] if key.start_with?(META_NAMESPACE)
|
|
62
78
|
end
|
|
@@ -74,7 +90,7 @@ module Sevgi
|
|
|
74
90
|
|
|
75
91
|
# Immutable conversion result for one SVG/XML node.
|
|
76
92
|
#
|
|
77
|
-
# Attributes, namespaces, content, and descendants are owned snapshots
|
|
93
|
+
# Attributes, namespaces, content, and descendants are owned snapshots. Parser objects and dispatch strategies
|
|
78
94
|
# remain internal to Derender. Attributes omitted during decompilation are absent throughout the captured subtree.
|
|
79
95
|
class Node
|
|
80
96
|
include Capture
|
|
@@ -90,7 +106,8 @@ module Sevgi
|
|
|
90
106
|
attr_reader :children
|
|
91
107
|
|
|
92
108
|
# Returns immutable normalized text content. `xml:space="preserve"` and single-line mixed text retain their exact
|
|
93
|
-
# text. Other text trims surrounding whitespace
|
|
109
|
+
# text. Other text trims surrounding whitespace. Multiline mixed text removes only its outer indentation lines.
|
|
110
|
+
# For a processing instruction, content is its complete XML markup, including the target and data.
|
|
94
111
|
# @return [String] frozen owned text snapshot
|
|
95
112
|
attr_reader :content
|
|
96
113
|
|
|
@@ -98,8 +115,9 @@ module Sevgi
|
|
|
98
115
|
# @return [String] owned element name
|
|
99
116
|
attr_reader :name
|
|
100
117
|
|
|
101
|
-
# Returns immutable namespace declarations emitted for this node. A conversion root owns its local declarations
|
|
102
|
-
#
|
|
118
|
+
# Returns immutable namespace declarations emitted for this node. A conversion root owns its local declarations.
|
|
119
|
+
# A separately selected node owns all declarations in scope. Descendant snapshots own their local declarations.
|
|
120
|
+
# Independent source conversion and evaluation also emit the inherited declarations captured for that node.
|
|
103
121
|
# @return [Hash{String => String}] frozen owned namespace snapshot
|
|
104
122
|
attr_reader :namespaces
|
|
105
123
|
|
|
@@ -128,20 +146,22 @@ module Sevgi
|
|
|
128
146
|
|
|
129
147
|
alias meta _
|
|
130
148
|
|
|
131
|
-
# Converts this node into formatted Sevgi DSL Ruby source.
|
|
149
|
+
# Converts this node into formatted Sevgi DSL Ruby source. The returned String is ordinary Ruby source. Review and
|
|
150
|
+
# integrate it statically rather than using Ruby's raw dynamic evaluation methods.
|
|
132
151
|
# @return [String] formatted Sevgi DSL source
|
|
133
152
|
# @raise [Sevgi::PanicError] when generated Ruby source cannot be formatted
|
|
134
153
|
# @note Foreign namespace elements use the explicit `Element` DSL path, and nested `svg` nodes remain elements.
|
|
135
154
|
# @note Unsafe bare Ruby names are emitted through the explicit `Element` DSL word.
|
|
136
|
-
def derender = Ruby.format(decompile(@pres).join("\n"))
|
|
155
|
+
def derender = Ruby.format(decompile(@pres, namespaces: @scope).join("\n"))
|
|
137
156
|
|
|
138
157
|
# Evaluates this node under a graphics element.
|
|
139
158
|
# @param element [Sevgi::Graphics::Element] target graphics element
|
|
140
159
|
# @return [Sevgi::Graphics::Element, nil] included current element, or nil when it produces no graphics output
|
|
141
160
|
# @note Namespace declarations, qualified attributes, significant text, and nested `svg` nodes are preserved.
|
|
142
|
-
def evaluate(element) = Evaluator.new(element).append(self)
|
|
161
|
+
def evaluate(element) = Evaluator.new(element).append(self, namespaces: @scope)
|
|
143
162
|
|
|
144
163
|
# Evaluates only this node's children under a graphics element.
|
|
164
|
+
# Each imported element retains its namespace scope without changing the target parent's declarations.
|
|
145
165
|
# @param element [Sevgi::Graphics::Element] target graphics element
|
|
146
166
|
# @return [Array<Sevgi::Graphics::Element>] immutable included-child snapshot
|
|
147
167
|
def evaluate_children(element) = children.filter_map { it.evaluate(element) }.freeze
|
|
@@ -165,36 +185,34 @@ module Sevgi
|
|
|
165
185
|
|
|
166
186
|
attr_reader :node, :type
|
|
167
187
|
|
|
168
|
-
def all_attributes = {**attributes, **namespaces}.freeze
|
|
188
|
+
def all_attributes(namespaces = self.namespaces()) = {**attributes, **namespaces}.freeze
|
|
169
189
|
|
|
170
190
|
def attribute_key(attribute) = [attribute.namespace&.prefix, attribute.name].compact.join(":")
|
|
171
191
|
|
|
172
192
|
def dispatch
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
:Text
|
|
176
|
-
when node.comment?
|
|
177
|
-
:Junk
|
|
178
|
-
when Namespace.svg?(node, "style")
|
|
193
|
+
type = NODE_TYPES[node.type]
|
|
194
|
+
type ||= if Namespace.svg?(node, "style") && node.children.all? { it.text? || it.cdata? }
|
|
179
195
|
:CSS
|
|
180
|
-
|
|
196
|
+
elsif @top && Namespace.svg?(node, "svg")
|
|
181
197
|
:Root
|
|
182
198
|
else
|
|
183
199
|
:Any
|
|
184
200
|
end
|
|
185
|
-
|
|
201
|
+
|
|
202
|
+
type.tap { extend(Elements.const_get(it)) }
|
|
186
203
|
end
|
|
187
204
|
|
|
188
205
|
def element = name
|
|
189
206
|
|
|
190
207
|
def ignorable_child?(child)
|
|
191
|
-
child.send(:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
!child.send(:inline_text?))
|
|
208
|
+
child.send(:text?) &&
|
|
209
|
+
child.content.strip.empty? &&
|
|
210
|
+
!child.send(:preserve_space?) &&
|
|
211
|
+
!child.send(:inline_text?)
|
|
196
212
|
end
|
|
197
213
|
|
|
214
|
+
def literal_content? = node.cdata? || node.comment?
|
|
215
|
+
|
|
198
216
|
def preserve_space?
|
|
199
217
|
each_node do |current|
|
|
200
218
|
case xml_space(current)
|
|
@@ -210,6 +228,12 @@ module Sevgi
|
|
|
210
228
|
|
|
211
229
|
def inline_text? = mixed_text? && !node.content.match?(/[\r\n]/)
|
|
212
230
|
|
|
231
|
+
def inline_content?
|
|
232
|
+
return false unless children.any? { it.send(:text?) || it.send(:type) == :CData }
|
|
233
|
+
|
|
234
|
+
preserve_space? || node.children.none? { it.text? && it.content.match?(/[\r\n]/) }
|
|
235
|
+
end
|
|
236
|
+
|
|
213
237
|
def normalized_content
|
|
214
238
|
return node.content if mixed_text? && inline_text?
|
|
215
239
|
return node.content.strip unless mixed_text?
|
|
@@ -217,7 +241,10 @@ module Sevgi
|
|
|
217
241
|
node.content.sub(/\A[ \t]*\r?\n[ \t]*/, "").sub(/[ \t]*\r?\n[ \t]*\z/, "")
|
|
218
242
|
end
|
|
219
243
|
|
|
220
|
-
def mixed_text?
|
|
244
|
+
def mixed_text?
|
|
245
|
+
node.text? &&
|
|
246
|
+
node.parent&.children&.any? { it.element? || it.cdata? || it.comment? || it.processing_instruction? }
|
|
247
|
+
end
|
|
221
248
|
|
|
222
249
|
def local_namespaces
|
|
223
250
|
return {} unless node.respond_to?(:namespace_definitions)
|
|
@@ -238,6 +265,8 @@ module Sevgi
|
|
|
238
265
|
|
|
239
266
|
def text? = node.text?
|
|
240
267
|
|
|
268
|
+
def text_leaf? = children.one? && children.first.send(:text?)
|
|
269
|
+
|
|
241
270
|
def xml_space(current)
|
|
242
271
|
return unless current.respond_to?(:attribute_nodes)
|
|
243
272
|
|
data/lib/sevgi/derender.rb
CHANGED
|
@@ -13,8 +13,8 @@ require_relative "derender/version"
|
|
|
13
13
|
module Sevgi
|
|
14
14
|
# Brings editor-authored SVG/XML into programmatic Sevgi workflows.
|
|
15
15
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
16
|
+
# Some vector geometry is easier to create in a visual editor than to reconstruct as Ruby. Examples include a
|
|
17
|
+
# Bezier-heavy logo and a hand-adjusted illustration. Derender preserves that SVG/XML tree as inspectable data,
|
|
18
18
|
# or graphics elements under an existing document. This lets editor-authored geometry participate in programmatic
|
|
19
19
|
# composition, styling, layout, and output. Use it when SVG/XML is a real input artifact, not as an intermediate
|
|
20
20
|
# authoring format for ordinary Sevgi drawing code.
|
|
@@ -24,16 +24,23 @@ module Sevgi
|
|
|
24
24
|
# tree without invoking same-named Ruby methods.
|
|
25
25
|
#
|
|
26
26
|
# Evaluation APIs treat SVG/XML as data: they build graphics element trees directly and do not execute generated Ruby
|
|
27
|
-
# source.
|
|
27
|
+
# source. The String returned by source-generation APIs is ordinary Ruby source. Review and integrate it statically
|
|
28
|
+
# rather than passing it to Ruby's raw dynamic evaluation methods. Malformed, rootless, or unmatched input is rejected
|
|
29
|
+
# with {Sevgi::ArgumentError}.
|
|
30
|
+
# Processing instructions retain their target, data, and order as inert XML markup. Custom entity references in the
|
|
31
|
+
# selected subtree are rejected before inclusion changes a target. Predefined and numeric references remain valid.
|
|
32
|
+
# Whole-document conversion rejects nodes after the root. Explicit id selection ignores unrelated document siblings.
|
|
33
|
+
# Input uses the XML encoding declaration or byte-order mark. Generated source and rendered XML use UTF-8.
|
|
34
|
+
# The XML declaration retains its version and standalone flag, with any encoding field changed to UTF-8.
|
|
28
35
|
#
|
|
29
36
|
# Namespace dispatch treats qualified and foreign elements as ordinary XML nodes. Their element identity, namespace
|
|
30
37
|
# declarations, qualified attributes, significant text, and nested `svg` elements survive source generation and direct
|
|
31
38
|
# evaluation. CSS specialization applies only to unqualified `style` elements in no namespace or the default SVG
|
|
32
|
-
# namespace
|
|
39
|
+
# namespace. The document-root strategy also requires an unqualified `svg` at the root of the conversion.
|
|
33
40
|
# Simple CSS rules use the readable `css({...})` DSL form. At-rules, duplicate declarations, and other CSS that cannot
|
|
34
41
|
# be represented losslessly as a Hash remain owned raw style content.
|
|
35
42
|
#
|
|
36
|
-
# Attribute omission uses exact, case-sensitive names across the selected subtree. ID selection happens first
|
|
43
|
+
# Attribute omission uses exact, case-sensitive names across the selected subtree. ID selection happens first.
|
|
37
44
|
# namespace declarations remain intact, and omitting the `style` attribute does not omit `style` elements.
|
|
38
45
|
#
|
|
39
46
|
# @example Inspect, select, and convert an immutable result
|
|
@@ -82,7 +89,8 @@ module Sevgi
|
|
|
82
89
|
# @see Sevgi.DecompileFile
|
|
83
90
|
def self.decompile_file(file, id: nil, omit: nil) = Document.load_file(file).decompile(id, omit:)
|
|
84
91
|
|
|
85
|
-
# Converts SVG/XML content into Sevgi DSL Ruby source.
|
|
92
|
+
# Converts SVG/XML content into Sevgi DSL Ruby source. The returned String is ordinary Ruby source. Review and
|
|
93
|
+
# integrate it statically rather than using Ruby's raw dynamic evaluation methods.
|
|
86
94
|
# @param content [String] SVG/XML source content
|
|
87
95
|
# @param id [String, Symbol, nil] optional SVG id selecting a node inside the source
|
|
88
96
|
# @param omit [String, Symbol, Array<String, Symbol>, nil] exact attribute name or names omitted from the selected
|
|
@@ -100,7 +108,8 @@ module Sevgi
|
|
|
100
108
|
# @see Sevgi.Derender
|
|
101
109
|
def self.derender(content, id: nil, omit: nil) = Document.new(content).decompile(id, omit:).derender
|
|
102
110
|
|
|
103
|
-
# Converts an SVG/XML file into Sevgi DSL Ruby source.
|
|
111
|
+
# Converts an SVG/XML file into Sevgi DSL Ruby source. The returned String is ordinary Ruby source. Review and
|
|
112
|
+
# integrate it statically rather than using Ruby's raw dynamic evaluation methods.
|
|
104
113
|
# @param file [String] path to the source SVG/XML file
|
|
105
114
|
# @param id [String, Symbol, nil] optional SVG id selecting a node inside the source
|
|
106
115
|
# @param omit [String, Symbol, Array<String, Symbol>, nil] exact attribute name or names omitted from the selected
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sevgi-derender
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Recai Oktaş
|
|
@@ -15,28 +15,28 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 1.0.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 1.0.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: sevgi-graphics
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - '='
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: 0.
|
|
32
|
+
version: 1.0.0
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - '='
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: 0.
|
|
39
|
+
version: 1.0.0
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
41
|
name: css_parser
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -96,8 +96,9 @@ files:
|
|
|
96
96
|
- lib/sevgi/derender/document.rb
|
|
97
97
|
- lib/sevgi/derender/elements.rb
|
|
98
98
|
- lib/sevgi/derender/elements/any.rb
|
|
99
|
+
- lib/sevgi/derender/elements/comment.rb
|
|
99
100
|
- lib/sevgi/derender/elements/css.rb
|
|
100
|
-
- lib/sevgi/derender/elements/
|
|
101
|
+
- lib/sevgi/derender/elements/instruction.rb
|
|
101
102
|
- lib/sevgi/derender/elements/root.rb
|
|
102
103
|
- lib/sevgi/derender/elements/text.rb
|
|
103
104
|
- lib/sevgi/derender/evaluator.rb
|
|
@@ -126,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
126
127
|
- !ruby/object:Gem::Version
|
|
127
128
|
version: '0'
|
|
128
129
|
requirements: []
|
|
129
|
-
rubygems_version: 4.0.
|
|
130
|
+
rubygems_version: 4.0.20
|
|
130
131
|
specification_version: 4
|
|
131
132
|
summary: SVG-to-Sevgi source conversion.
|
|
132
133
|
test_files: []
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Sevgi
|
|
4
|
-
module Derender
|
|
5
|
-
module Elements
|
|
6
|
-
# Element strategy for comments and ignored XML nodes.
|
|
7
|
-
# @api private
|
|
8
|
-
module Junk
|
|
9
|
-
# Drops ignored nodes from generated source.
|
|
10
|
-
# @return [Array<String>] empty source lines
|
|
11
|
-
def decompile(*) = []
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|