sevgi-appendix 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 +3 -3
- data/agents/skills/sevgi/SKILL.md +27 -23
- data/agents/skills/sevgi/references/derender.md +31 -18
- data/agents/skills/sevgi/references/drawing.md +4 -3
- data/agents/skills/sevgi/references/dsl.md +45 -15
- data/agents/skills/sevgi/references/inspection.md +5 -5
- data/agents/skills/sevgi/references/layout.md +49 -13
- data/agents/skills/sevgi/references/output.md +19 -11
- data/agents/skills/sevgi/references/ruby.md +32 -21
- data/agents/skills/sevgi/references/svg.md +6 -6
- data/agents/skills/sevgi/references/toolkit.md +16 -6
- data/lib/sevgi/appendix/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: de8ed7f67989c92a4f828b1308146b6ec91fbd1971e4643df4c644c784ef32a1
|
|
4
|
+
data.tar.gz: eb023302ed8980659744d2d07d8813d67ad7bb91eb7a24127b612c84fa39641f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0c3ace1e02a9533c6303049334356816cb2315d4583154e50525323aa1e482d340eedc17f2559e61e3832700ab0afe774b6ca704291dc3c9e3d6595b5b7e2dd5
|
|
7
|
+
data.tar.gz: 554d7b3471bfb370524197507d1cc1746c293e533cf93d91f9e158656215dc77ee76f2bbba407d6b49f1fc994cab5926a1a6ddb2c013fbcbd1d0056f9ca9f9f4
|
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
|
@@ -30,9 +30,9 @@ Locate the skill without guessing a Homebrew prefix or Cellar version:
|
|
|
30
30
|
sevgi --skill
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
The command prints one validated absolute path and nothing else. It fails
|
|
34
|
-
|
|
35
|
-
skill directory
|
|
33
|
+
The command prints one validated absolute path and nothing else. It fails when the `sevgi-appendix` version does not
|
|
34
|
+
match Sevgi. It also fails when `SKILL.md` is missing. Homebrew reports a stable path below its `opt` tree. An agent's
|
|
35
|
+
skill directory can safely link to it. Homebrew keeps that path current across upgrades.
|
|
36
36
|
|
|
37
37
|
Coding agents look for skills in different directories. Paste this prompt into the agent you want to configure:
|
|
38
38
|
|
|
@@ -15,38 +15,42 @@ visible intent.
|
|
|
15
15
|
renderer resolve it. Use Ruby or `Sevgi::Geometry` only for information the program genuinely must derive. Read
|
|
16
16
|
[drawing.md](references/drawing.md) before adding rendering-related arithmetic.
|
|
17
17
|
2. **Fix the cause, not the symptom.** Treat the visible result as the acceptance criterion. Trace a mismatch through
|
|
18
|
-
drawing geometry, viewport, transforms, styles, strokes, and renderer behavior
|
|
18
|
+
drawing geometry, viewport, transforms, styles, strokes, and renderer behavior. Fix the layer that owns the faulty
|
|
19
19
|
contract. Do not hide it with empty margins, oversized frames, clipping, non-uniform scaling, or a one-case offset.
|
|
20
20
|
3. **Stay native to Sevgi.** Use SVG elements through the Sevgi DSL and prefer Sevgi's existing Graphics, Geometry,
|
|
21
21
|
Sundries, and Function helpers where they fit. Do not generate raw SVG/XML, another graphics format, or an
|
|
22
22
|
intermediate string and then convert it into Sevgi. Use Derender only when existing SVG/XML is a genuine input
|
|
23
|
-
artifact.
|
|
23
|
+
artifact. Treat Ruby's dynamic evaluation APIs (`eval`, `*_eval`, and `*_exec`) as anti-patterns throughout every
|
|
24
|
+
Derender workflow. Use `Include` or `IncludeChildren` when the editor file remains authoritative, an `Evaluate*`
|
|
25
|
+
operation when the target must be explicit, or reviewed source integrated statically into the maintained DSL.
|
|
24
26
|
|
|
25
27
|
## Workflow
|
|
26
28
|
|
|
27
29
|
1. Determine the host and installed dependency surface: executable `.sevgi` script, full-toolkit Ruby library, or a
|
|
28
30
|
focused component. Read [dsl.md](references/dsl.md) for its grammar and facade boundaries.
|
|
29
|
-
2.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
operation.
|
|
42
|
-
8. Write the smallest clear Sevgi expression. Keep case-sensitive, normally lowercase-leading SVG element calls,
|
|
31
|
+
2. Before introducing an operation, make sure that the target version documents its name, signature, required profile, and component.
|
|
32
|
+
Read [toolkit.md](references/toolkit.md) for lookup paths or before replacing a Sevgi helper.
|
|
33
|
+
Do not infer an API from an English name or use `Element` to bypass an unknown operation.
|
|
34
|
+
3. Before changing a drawing, state the visible target and the properties that must remain unchanged.
|
|
35
|
+
Keep these acceptance criteria through verification. Equal canvas dimensions do not substitute for equal visible size.
|
|
36
|
+
4. Read only the references needed for the operation. Use [ruby.md](references/ruby.md) for helpers, callable modules,
|
|
37
|
+
document extensions, or DSL formatting. Before adding visual arithmetic, offsets, or scaling, read
|
|
38
|
+
[drawing.md](references/drawing.md). Use [svg.md](references/svg.md) to find a renderer-owned mechanism.
|
|
39
|
+
5. Read [layout.md](references/layout.md) for repetition, tiling, alignment, rulers, grids, `Draw`, or hatching.
|
|
40
|
+
6. For editor-authored SVG/XML, `igves` prints Sevgi source. `igsev` round-trips to normalized SVG. Both accept files or
|
|
41
|
+
standard input. Read [derender.md](references/derender.md). For PDF/PNG output, read [output.md](references/output.md).
|
|
42
|
+
7. Write the smallest clear Sevgi expression. Keep case-sensitive, normally lowercase-leading SVG element calls,
|
|
43
43
|
capitalized Sevgi operations, ordinary Ruby control flow, and SVG attributes visibly distinct. Do not mechanically
|
|
44
|
-
parenthesize statement-like DSL calls.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
44
|
+
parenthesize statement-like DSL calls. When braces would require those parentheses, use `do`/`end`.
|
|
45
|
+
8. Use the verification boundaries in [dsl.md](references/dsl.md). Report unavailable checks rather than claiming they passed.
|
|
46
|
+
9. For new or visually changed drawings, render and inspect the supported contexts affected by the change.
|
|
47
|
+
Compare the output against the original acceptance criteria. For size, alignment, clipping, density, or visual-regression
|
|
48
|
+
evidence, read [inspection.md](references/inspection.md) before choosing a measurement tool.
|
|
49
|
+
Do not require visual measurements for source-only changes with no effect on rendering.
|
|
50
|
+
10. Re-read the finished source for raw-XML detours, avoidable calculations, magic offsets, duplicated geometry or
|
|
51
|
+
paint passes, duplicated helpers, and stale artifacts. Emit each semantic shape once by default. Collapse repeated
|
|
52
|
+
draws when one SVG element can carry the required fill and stroke. Add another paint pass only when the visible
|
|
53
|
+
requirement or inspection proves that separate z-order is necessary; make each pass's role evident in the source.
|
|
50
54
|
|
|
51
55
|
## References
|
|
52
56
|
|
|
@@ -55,7 +59,7 @@ visible intent.
|
|
|
55
59
|
| Choose script/library syntax, profiles, SVG elements, or Sevgi DSL words | [dsl.md](references/dsl.md) |
|
|
56
60
|
| Choose a component and locate user, YARD, or checkout documentation | [toolkit.md](references/toolkit.md) |
|
|
57
61
|
| Structure `.sevgi` and library code as idiomatic Ruby | [ruby.md](references/ruby.md) |
|
|
58
|
-
| Apply the renderer/program ownership boundary
|
|
62
|
+
| Apply the renderer/program ownership boundary and diagnose visual mismatches | [drawing.md](references/drawing.md) |
|
|
59
63
|
| Measure SVG geometry, browser layout, or painted pixels | [inspection.md](references/inspection.md) |
|
|
60
64
|
| Find an SVG capability and its authoritative specification | [svg.md](references/svg.md) |
|
|
61
65
|
| Choose repetition, tiling, ruler, grid, Draw, pattern, or Hatch | [layout.md](references/layout.md) |
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
Some vector geometry is
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
output. This combines both workflows without pretending every path should originate in code.
|
|
5
|
+
Some vector geometry is easier to create in a visual editor. Examples include a Bezier-heavy logo, a traced
|
|
6
|
+
illustration, and a hand-adjusted path. Derender brings that SVG/XML into the Sevgi element model. Editor-authored
|
|
7
|
+
geometry can then participate in Ruby-driven composition, styling, layout, and output.
|
|
9
8
|
|
|
10
9
|
Do not use Derender as a detour for ordinary shapes or relationships that are clearer in the Sevgi DSL. Use it when
|
|
11
10
|
SVG/XML is a real input artifact.
|
|
@@ -21,16 +20,16 @@ SVG/XML is a real input artifact.
|
|
|
21
20
|
| Include a selected file node inside an SVG block | — | `Include` | included element or `nil` |
|
|
22
21
|
| Include only a selected file node's children inside a block | — | `IncludeChildren` | frozen child snapshot |
|
|
23
22
|
|
|
24
|
-
Use `DerenderFile` when generated Ruby
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
Use `DerenderFile` when generated Ruby becomes the maintained source. Use `Include`, `EvaluateFile`, or their children
|
|
24
|
+
variants when the editor file remains the geometry source. Use `DecompileFile` to inspect names, attributes,
|
|
25
|
+
namespaces, metadata, and children. Choose one maintained representation. Do not maintain editor SVG and generated
|
|
26
|
+
Sevgi in parallel.
|
|
28
27
|
|
|
29
28
|
Keep the editor file as the geometry source and compose a selected group in Sevgi:
|
|
30
29
|
|
|
31
30
|
```ruby
|
|
32
|
-
SVG
|
|
33
|
-
Include "brand.svg", "logo"
|
|
31
|
+
SVG do
|
|
32
|
+
Include "brand.svg", "logo"
|
|
34
33
|
end.Save "badge.svg"
|
|
35
34
|
```
|
|
36
35
|
|
|
@@ -45,36 +44,50 @@ drawing.Render
|
|
|
45
44
|
Generate Ruby for review and integration into the maintained source instead:
|
|
46
45
|
|
|
47
46
|
```ruby
|
|
48
|
-
source = SVG.DerenderFile "brand.svg", id: "logo"
|
|
47
|
+
source = SVG.DerenderFile "brand.svg", id: "logo"
|
|
49
48
|
puts source
|
|
50
49
|
```
|
|
51
50
|
|
|
52
51
|
At the command line, `igves` prints generated Sevgi source. Use `igsev` from the umbrella gem only when the intended
|
|
53
52
|
result is normalized SVG produced by a complete SVG-to-Sevgi-to-SVG round trip. Both commands accept repeatable
|
|
54
|
-
`--omit ATTRIBUTE` and read standard input when the file is omitted or
|
|
53
|
+
`--omit ATTRIBUTE` and read standard input when the file is omitted or `-`. `igsev` is a structural formatter, not a
|
|
55
54
|
byte-preserving XML rewrite.
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
Derender reads the XML encoding declaration or byte-order mark. Generated Ruby and rendered XML use UTF-8.
|
|
57
|
+
The declaration keeps its version and standalone flag, with any encoding field changed to UTF-8.
|
|
58
|
+
|
|
59
|
+
A selected subtree can produce a fragment rather than a standalone `.sevgi` script. Review the conversion. Then place
|
|
60
|
+
it inside the document or callable module that owns it. Do not rename an arbitrary fragment to `.sevgi`.
|
|
59
61
|
|
|
60
62
|
## Selection and Cleanup
|
|
61
63
|
|
|
64
|
+
Processing instructions retain their target, data, and order as inert XML markup. Custom entity references in the
|
|
65
|
+
selected subtree raise `Sevgi::ArgumentError` before target mutation. Predefined and numeric references remain valid.
|
|
66
|
+
Whole-document conversion rejects nodes after the root except whitespace. Explicit selection ignores unrelated siblings.
|
|
67
|
+
|
|
62
68
|
- Give reusable editor groups stable IDs and select one with `id:`. `Include` takes that ID as its second positional
|
|
63
69
|
argument.
|
|
70
|
+
- Selection preserves namespace scope, but does not copy ancestor transforms, inherited styles, or definitions outside the subtree.
|
|
71
|
+
Include the required context explicitly or select a self-contained ancestor.
|
|
72
|
+
- `IncludeChildren` and `EvaluateChildren*` omit the selected wrapper, including its transform and style attributes.
|
|
73
|
+
Use the whole-node form when the wrapper affects appearance.
|
|
64
74
|
- Inspect an SVG tree with `SVG.DecompileFile` (or component-level `Sevgi::Derender.decompile_file`) before falling back
|
|
65
75
|
to text search. Grep can mistake editor helpers, generated IDs, metadata, or unrelated layers for reusable artwork.
|
|
66
76
|
- Use `omit:` with one String/Symbol or an Array of exact, case-sensitive attribute names. Selection happens before
|
|
67
|
-
omission
|
|
77
|
+
omission. The omission applies throughout the selected subtree, not only to its root.
|
|
78
|
+
Removing IDs can break `href`, `url(#...)`, and CSS references. Keep referenced IDs or update their consumers together.
|
|
68
79
|
- Namespace declarations remain intact, and omitting the `style` attribute does not remove `style` elements. Omit
|
|
69
80
|
style, transform, or geometry attributes only when their behavior is intentionally replaced.
|
|
70
|
-
- Expect paths and other low-level editor geometry to remain low-level. Derender preserves the SVG tree
|
|
81
|
+
- Expect paths and other low-level editor geometry to remain low-level. Derender preserves the SVG tree. It cannot
|
|
71
82
|
reconstruct the loops, modules, or design operations that originally created it.
|
|
72
83
|
- Treat parsing and executing as separate trust boundaries. Derender parses XML as data and direct evaluation builds
|
|
73
|
-
graphics elements without executing generated Ruby.
|
|
84
|
+
graphics elements without executing generated Ruby. Do not pass generated source to Ruby's dynamic evaluation APIs
|
|
85
|
+
(`eval`, `*_eval`, or `*_exec`), even when the input is trusted. When generated Ruby becomes the maintained
|
|
86
|
+
representation, review it and integrate it statically into the owning source or callable module.
|
|
74
87
|
- After renaming or removing a selected id or source path, update its consumers, regenerate derived drawings, and check
|
|
75
88
|
for stale references.
|
|
76
89
|
|
|
77
|
-
Script mode uses bare names such as `DerenderFile
|
|
90
|
+
Script mode uses bare names such as `DerenderFile`. Library mode uses the `SVG.` facade. Component-only consumers use
|
|
78
91
|
the lowercase `Sevgi::Derender` methods and `_file` variants.
|
|
79
92
|
|
|
80
93
|
Read the [Derender guide](https://sevgi.roktas.dev/derender/) for the complete workflow and
|
|
@@ -22,7 +22,7 @@ and hatching. It is not a parallel rendering engine.
|
|
|
22
22
|
|
|
23
23
|
## Example: Preserve the Ownership Boundary
|
|
24
24
|
|
|
25
|
-
The Showcase Ruler illustrates the general rule
|
|
25
|
+
The Showcase Ruler illustrates the general rule. It does not introduce a text-specific recipe. The desired relationship
|
|
26
26
|
is “center each label on this tick,” while the rendered width of a label depends on font metrics known by the SVG
|
|
27
27
|
renderer.
|
|
28
28
|
|
|
@@ -63,8 +63,9 @@ Fix the first contract that is false. Do not make a frame larger to hide unequal
|
|
|
63
63
|
alignment, clip an overflow caused by wrong geometry, or use a special-case offset that only matches one label or
|
|
64
64
|
viewport.
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
desktop
|
|
66
|
+
Make sure that the result works in every rendering context that the artifact supports. Browser assets can require
|
|
67
|
+
representative desktop and mobile widths plus light and dark themes. Print output can require several page sizes and an
|
|
68
|
+
independent PDF renderer.
|
|
68
69
|
Equal SVG dimensions or DOM boxes do not prove equal visible size.
|
|
69
70
|
|
|
70
71
|
## Layout Changes
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
| Form | Meaning |
|
|
6
6
|
| --- | --- |
|
|
7
|
-
| `rect`, `circle`, `linearGradient`, `clipPath`, ... | Standard SVG elements created
|
|
7
|
+
| `rect`, `circle`, `linearGradient`, `clipPath`, ... | Standard SVG elements created by exact, case-sensitive names that normally start lowercase |
|
|
8
8
|
| `Translate`, `Tile`, `Call`, `Render`, ... | Sevgi operations, normally capitalized to stand apart from SVG elements |
|
|
9
|
-
| `css`, `layer`, `layer!`, `base` |
|
|
9
|
+
| `css`, `square`, `symbol!`, `layer`, `layer!`, `base` | Examples of deliberate lowercase Sevgi words. The DSL catalog owns the full list |
|
|
10
10
|
| `SVG(...)` | Build a document in both script and library code |
|
|
11
11
|
| `SVG.Canvas(...)` | Call a full-toolkit facade operation in library code |
|
|
12
|
+
| `SVG.Module { ... }` | Build an anonymous callable with public steps and private or protected helpers |
|
|
13
|
+
| `extend SVG::Module` | Apply the same callable contract to an existing or explicitly declared module |
|
|
12
14
|
| `SVG::Canvas` | Refer to a type or namespace |
|
|
13
15
|
| `Canvas(...)` | Call the promoted operation in an executable `.sevgi` script |
|
|
14
16
|
|
|
@@ -22,13 +24,20 @@ text "Ready", x: 12, y: 16, "text-anchor": "middle", "font-weight": "bold"
|
|
|
22
24
|
|
|
23
25
|
| Host | Load | Vocabulary |
|
|
24
26
|
| --- | --- | --- |
|
|
25
|
-
| Executable script | `
|
|
27
|
+
| Executable script | `sevgi file.sevgi` or an executable `.sevgi` shebang | bare promoted operations such as `Canvas`, `Paper`, and `Grid` |
|
|
26
28
|
| Full-toolkit library | `require "sevgi"` | `SVG(...)` plus facade operations such as `SVG.Canvas` and `SVG.Grid` |
|
|
27
|
-
| Focused graphics library | `require "sevgi/graphics"` | `Sevgi::Graphics.SVG` and lowercase component constructors
|
|
29
|
+
| Focused graphics library | `require "sevgi/graphics"` | `Sevgi::Graphics.SVG` and lowercase component constructors without the full `SVG` facade |
|
|
28
30
|
|
|
29
31
|
Follow the consumer's declared gems and existing dialect. Do not require the full toolkit merely to obtain facade
|
|
30
32
|
spelling, and do not use facade operations when only a focused component is installed.
|
|
31
33
|
|
|
34
|
+
When the project bundle owns the dependencies, use `bundle exec sevgi file.sevgi`.
|
|
35
|
+
The `#!/usr/bin/env -S ruby -S sevgi` shebang helps editors detect Ruby syntax.
|
|
36
|
+
The shorter `#!/usr/bin/env sevgi` also works, but some editors do not recognize it as Ruby.
|
|
37
|
+
|
|
38
|
+
`SVG(...)` is the default constructor in library code as well as scripts. If another method shadows that name, use
|
|
39
|
+
`Sevgi.SVG(...)`. The explicit receiver is supported but not required. `SVG.Canvas(...)` is a separate facade operation.
|
|
40
|
+
|
|
32
41
|
## Minimal Forms
|
|
33
42
|
|
|
34
43
|
Executable script:
|
|
@@ -38,7 +47,7 @@ Executable script:
|
|
|
38
47
|
|
|
39
48
|
canvas = Canvas width: 24, height: 24, unit: :px
|
|
40
49
|
|
|
41
|
-
SVG
|
|
50
|
+
SVG canvas do
|
|
42
51
|
circle cx: 12, cy: 12, r: 10, fill: "tomato"
|
|
43
52
|
end.Save "badge.svg"
|
|
44
53
|
```
|
|
@@ -49,7 +58,9 @@ Ruby library:
|
|
|
49
58
|
require "sevgi"
|
|
50
59
|
|
|
51
60
|
canvas = SVG.Canvas width: 24, height: 24, unit: :px
|
|
52
|
-
drawing = SVG
|
|
61
|
+
drawing = SVG canvas do
|
|
62
|
+
circle cx: 12, cy: 12, r: 10, fill: "tomato"
|
|
63
|
+
end
|
|
53
64
|
|
|
54
65
|
File.write "badge.svg", drawing.Render
|
|
55
66
|
```
|
|
@@ -60,32 +71,51 @@ Keep physical size and serialization dialect independent:
|
|
|
60
71
|
|
|
61
72
|
| Need | Use | Owns |
|
|
62
73
|
| --- | --- | --- |
|
|
63
|
-
| Register
|
|
74
|
+
| Register a named physical size | `SVG.Paper` / script `Paper` | width, height, and unit |
|
|
75
|
+
| Look up a registered physical size | `SVG::Paper.fetch` | the registered size value |
|
|
64
76
|
| Build one drawing surface | `SVG.Canvas` / script `Canvas` | size, margins, unit, name, and resulting `viewBox` |
|
|
65
77
|
| Define or select an SVG document profile | `SVG.Document` / script `Document` | root attributes and preambles |
|
|
66
78
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
79
|
+
Omitting the profile selects `:default`. A Canvas or Paper can be the first argument when the default profile is
|
|
80
|
+
suitable. Otherwise, the first argument selects a document profile and the optional second argument supplies the
|
|
81
|
+
canvas. Use an anonymous `Document` for one-off metadata. Use a named profile only for shared process-wide vocabulary.
|
|
82
|
+
Prefer non-bang registration. Use `Paper!` or `Document!` only for an intentional overwrite.
|
|
83
|
+
|
|
84
|
+
A canvas's `viewBox` starts at the negative left and top margins. Drawing coordinates remain relative to the inner
|
|
85
|
+
area. For example, `SVG.Canvas(width: 40, height: 20, unit: :px, margins: 2)` starts at `(-2, -2)`.
|
|
86
|
+
With `margins: -2`, it starts at `(2, 2)` instead. Negative margins enlarge the inner area, not the viewport.
|
|
70
87
|
|
|
71
88
|
## Task-to-Word Map
|
|
72
89
|
|
|
73
90
|
| Task | Start with |
|
|
74
91
|
| --- | --- |
|
|
75
|
-
| Create SVG structure | SVG element names
|
|
76
|
-
| Choose page dimensions and document metadata | `Paper`, `Canvas`, `Document
|
|
92
|
+
| Create SVG structure | SVG element names with blocks for nested containers |
|
|
93
|
+
| Choose page dimensions and document metadata | `Paper`, `Canvas`, and `Document` with separate responsibilities |
|
|
77
94
|
| Set reusable styles | `css`, classes, presentation attributes |
|
|
78
95
|
| Transform an element or group | `Translate`, `Rotate`, `Scale`, `Skew`, `Flip` |
|
|
79
|
-
| Center known inner and outer boxes | element `Align
|
|
96
|
+
| Center known inner and outer boxes | element `Align`, or `Sevgi::Geometry::Operation` for edge alignment or a Ruby result |
|
|
80
97
|
| Draw simple line/path wrappers | `LineTo`, `LineBy`, `HLineTo`, `HLineBy`, `VLineTo`, `VLineBy` |
|
|
81
98
|
| Reuse or repeat drawing | `defs`/`use`, `Tile`, `TileX`, `TileY`, `Duplicate` |
|
|
82
|
-
| Compose reusable drawing code | `SVG::Module`, `base`, `Call
|
|
99
|
+
| Compose reusable drawing code | `SVG.Module`, `SVG::Module`, `base`, `Call`, and profile-specific wrappers |
|
|
83
100
|
| Move existing element trees | `Append`, `Prepend`, `Adopt`, `AdoptFirst`, `Orphan` |
|
|
84
101
|
| Draw or hatch Geometry values | `Draw`, `Hatch` on `:inkscape` or an explicitly extended custom profile |
|
|
85
102
|
| Inspect or validate output | `Identifiers`, `Validate`, `Lint` |
|
|
86
|
-
| Produce output | `Render`, `Out`, `Save
|
|
103
|
+
| Produce output | `Render`, `Out`, `Save`, and optional `PDF` or `PNG` export |
|
|
87
104
|
| Import existing SVG/XML | `Include`, `Evaluate`, `Derender`, `Decompile` and their file variants |
|
|
88
105
|
|
|
106
|
+
## Verification Boundaries
|
|
107
|
+
|
|
108
|
+
| Check | Establishes | Does not establish |
|
|
109
|
+
| --- | --- | --- |
|
|
110
|
+
| `Validate` | SVG vocabulary and nesting compliance when Standard is available | Visual correctness; without Standard it returns `nil` and performs no validation |
|
|
111
|
+
| `Lint` | No duplicate visible IDs | Complete reference integrity or SVG standard compliance |
|
|
112
|
+
| `Render` | SVG serialization | Correct appearance in a browser or export engine |
|
|
113
|
+
| Visual inspection | Appearance in the inspected context | Correctness in untested contexts |
|
|
114
|
+
|
|
115
|
+
For a new or changed drawing, run `Lint` and, when Standard is available, `Validate` before accepting the output.
|
|
116
|
+
Report a missing Standard component as unavailable validation, not a successful check.
|
|
117
|
+
Inspect visually changed output against the user's acceptance criteria.
|
|
118
|
+
|
|
89
119
|
## Profiles
|
|
90
120
|
|
|
91
121
|
| Profile | Use |
|
|
@@ -16,7 +16,7 @@ State the question before selecting a tool:
|
|
|
16
16
|
| Where does it appear after layout and transforms? | Browser `getBoundingClientRect()` or an equivalent automation API | Viewport-relative CSS pixels |
|
|
17
17
|
| What is a path's renderer-computed length or point? | `getTotalLength()` or `getPointAtLength()` | SVG user units |
|
|
18
18
|
| Which pixels were actually painted? | A deterministic PNG or browser screenshot inspected as raster data | Raster pixels |
|
|
19
|
-
| Does the result have the intended balance or density? | Visual inspection at representative outputs | Perceptual
|
|
19
|
+
| Does the result have the intended balance or density? | Visual inspection at representative outputs | Perceptual because no single bounding box proves it |
|
|
20
20
|
|
|
21
21
|
Do not compare values from different spaces as if they shared units. Label every recorded measurement with:
|
|
22
22
|
|
|
@@ -46,7 +46,7 @@ and integration-context checks.
|
|
|
46
46
|
|
|
47
47
|
`getBBox()` applies geometry attributes but does not apply transforms on the element or its parents.
|
|
48
48
|
`getBoundingClientRect()` is an axis-aligned CSS-pixel rectangle after layout and transforms. Do not treat either value
|
|
49
|
-
as the exact painted-pixel boundary
|
|
49
|
+
as the exact painted-pixel boundary. Strokes, markers, clipping, filters, font rasterization, and antialiasing can require
|
|
50
50
|
raster evidence. With rotated or skewed content, transform all relevant corners instead of scaling a width and height.
|
|
51
51
|
|
|
52
52
|
## Raster Recipe
|
|
@@ -59,7 +59,7 @@ regression.
|
|
|
59
59
|
2. Inspect the image visually before reducing it to numbers. Confirm that the selected image contains the intended
|
|
60
60
|
context and that no crop already concealed the defect.
|
|
61
61
|
3. When ImageMagick or an equivalent tool is available, derive the occupied-pixel box from the alpha channel or a known
|
|
62
|
-
background. Record the transparency threshold or color tolerance
|
|
62
|
+
background. Record the transparency threshold or color tolerance. Antialiased edge pixels make that policy part of
|
|
63
63
|
the measurement.
|
|
64
64
|
4. Compare occupied bounds, edge margins, and clipping against the stated acceptance criterion. Pixel counts and boxes
|
|
65
65
|
do not measure perceived weight or balance by themselves.
|
|
@@ -74,9 +74,9 @@ renderer and apply the same fixed-context checks. Do not convert a raster observ
|
|
|
74
74
|
- Wrong SVG-user-unit geometry points to coordinates, repetition, transforms, or a Sevgi layout helper.
|
|
75
75
|
- Correct geometry but wrong CSS-pixel placement points to the viewport, host layout, responsive CSS, or transforms.
|
|
76
76
|
- Stable browser boxes but different raster bounds point to paint, clipping, filters, fonts, or renderer behavior.
|
|
77
|
-
- Equal boxes with visibly unequal results point to spacing, stroke weight, contrast, or density
|
|
77
|
+
- Equal boxes with visibly unequal results point to spacing, stroke weight, contrast, or density. Keep visual inspection
|
|
78
78
|
as the acceptance criterion.
|
|
79
79
|
|
|
80
80
|
Do not measure routine API or source-only changes merely because a browser or image tool is available. Stop when the
|
|
81
|
-
chosen evidence answers the original question
|
|
81
|
+
chosen evidence answers the original question. Extra metrics add confidence only when they test another relevant
|
|
82
82
|
contract.
|
|
@@ -8,19 +8,35 @@ Choose by the value the caller needs after the operation, not merely by the visi
|
|
|
8
8
|
| --- | --- | --- |
|
|
9
9
|
| Repeat one SVG subtree in the rendered document | `defs`/`use`, or DSL `Tile`, `TileX`, `TileY` | SVG references with generated positions |
|
|
10
10
|
| Copy and independently edit an existing subtree | `Duplicate`, `DuplicateX`, `DuplicateY` | Independent SVG element trees |
|
|
11
|
+
| Copy a subtree without attachment or ID changes | `dup` or `clone` | Independent subtree with IDs preserved |
|
|
11
12
|
| Inspect repeated cells or row/column bounds in Ruby | `Sevgi::Sundries::Tile` | Geometry values and boxes, no SVG elements |
|
|
12
13
|
|
|
14
|
+
The repetition APIs have different block contracts:
|
|
15
|
+
|
|
16
|
+
| API channel | Runs for | Use |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| `Tile`, `TileX`, `TileY` block | One template under `defs` | Draw the shared subtree, not each cell |
|
|
19
|
+
| Tile `proc:` | Each generated `use` element | Mutate that element through the callback argument. Row and column indices are zero-based |
|
|
20
|
+
| `Duplicate`, `DuplicateX`, `DuplicateY` block | Every copied element | Customize the yielded element, not a new drawing context |
|
|
21
|
+
|
|
22
|
+
`Duplicate` moves visible `id` attributes to non-rendering `-id` metadata before customization.
|
|
23
|
+
An existing `-id` takes precedence. When replacing IDs, update their references as well.
|
|
24
|
+
The copied subtree attaches to its target parent after customization. Do not depend on that attachment during the callback.
|
|
25
|
+
Ordinary `dup` and `clone` leave the copy detached.
|
|
26
|
+
Before attaching it beside the original, resolve duplicate IDs and their references.
|
|
27
|
+
Use the exact callback keywords from the selected method's YARD contract. The Tile variants differ.
|
|
28
|
+
|
|
13
29
|
## Intervals and Grids
|
|
14
30
|
|
|
15
31
|
| Need | Use |
|
|
16
32
|
| --- | --- |
|
|
17
|
-
| Fit whole major/minor intervals into a span and inspect their distances | `Sevgi::Sundries::Ruler` |
|
|
33
|
+
| Fit whole major/minor intervals into a span and inspect their distances | script `Ruler`, library `SVG.Ruler`, or component `Sevgi::Sundries::Ruler` |
|
|
18
34
|
| Require an even major-interval count | `Sevgi::Sundries::RulerEven` |
|
|
19
35
|
| Combine two fitted rulers and obtain lines, points, cells, or a fitted canvas | `SVG.Grid` or `Sevgi::Sundries::Grid` |
|
|
20
36
|
|
|
21
|
-
`Ruler`
|
|
22
|
-
when lines are required. In a Grid, `grid.x` returns horizontal lines and
|
|
23
|
-
line direction.
|
|
37
|
+
`Ruler` constructs a Ruby layout value without drawing SVG elements. `Grid` also returns a layout model.
|
|
38
|
+
`Draw` materializes its geometry as SVG when lines are required. In a Grid, `grid.x` returns horizontal lines and
|
|
39
|
+
`grid.y` vertical lines—the names describe line direction.
|
|
24
40
|
|
|
25
41
|
## Alignment
|
|
26
42
|
|
|
@@ -30,26 +46,46 @@ line direction.
|
|
|
30
46
|
| Align Geometry at center or an edge and return the value or offset | `Sevgi::Geometry::Operation.align` or `Sevgi::Geometry::Operation.alignment` |
|
|
31
47
|
| Align rendered text or other renderer-owned content | SVG anchoring, baseline, layout, or transform semantics |
|
|
32
48
|
|
|
33
|
-
Geometry alignment accepts `:center`, `:left`, `:right`, `:top`, and `:bottom
|
|
34
|
-
contract accepts only `:center`. Do not calculate font or painted-content bounds
|
|
35
|
-
when the program already owns meaningful box geometry.
|
|
49
|
+
Geometry alignment accepts `:center`, `:left`, `:right`, `:top`, and `:bottom`. The element DSL's narrower `Align`
|
|
50
|
+
contract accepts only `:center`. Do not calculate font or painted-content bounds only to feed either API. Use these
|
|
51
|
+
APIs when the program already owns meaningful box geometry.
|
|
52
|
+
|
|
53
|
+
`Align` includes both box origins. Width-and-height-only objects have origin `(0, 0)`.
|
|
54
|
+
An object with `position` must supply finite numeric `x` and `y` coordinates:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
inner = Sevgi::Geometry::Rect[8, 4, position: [2, 3]]
|
|
58
|
+
outer = Sevgi::Geometry::Rect[40, 20, position: [5, 5]]
|
|
59
|
+
drawing = SVG width: 50, height: 30 do
|
|
60
|
+
shape = rect x: 2, y: 3, width: 8, height: 4
|
|
61
|
+
shape.Align :center, inner:, outer:
|
|
62
|
+
end
|
|
63
|
+
drawing.Render # The rectangle receives translate(19 10).
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Curved Geometry
|
|
67
|
+
|
|
68
|
+
For an SVG path, use `ArcTo` or `ArcBy`. The renderer resolves their endpoint, radius, `large`, and `sweep` rules.
|
|
69
|
+
Use `Geometry::Circle`, `Geometry::Ellipse`, or `Geometry::Arc` when Ruby needs intersections, endpoints, or bounds.
|
|
70
|
+
An arc has a finite extent and no filled interior. Positive angles run clockwise in screen coordinates, where y
|
|
71
|
+
increases downward. See [Geometry](https://sevgi.roktas.dev/geometry/#arcs-and-ellipses) and the installed Geometry YARD.
|
|
36
72
|
|
|
37
73
|
## Drawing and Hatching
|
|
38
74
|
|
|
39
75
|
| Need | Use |
|
|
40
76
|
| --- | --- |
|
|
41
|
-
| A visual repeated fill whose individual strokes are irrelevant | SVG `pattern
|
|
77
|
+
| A visual repeated fill whose individual strokes are irrelevant | SVG `pattern` that the renderer repeats and clips |
|
|
42
78
|
| Explicit finite hatch segments that must remain separate geometry/SVG paths | Geometry sweep or `Hatch` |
|
|
43
79
|
| Existing Geometry values rendered as SVG elements | `Draw` |
|
|
44
80
|
|
|
45
81
|
`Hatch` computes finite segments and emits each as a separate SVG path. Use it for editable, inspectable, plotter-like,
|
|
46
|
-
or otherwise explicit line geometry
|
|
47
|
-
`:inkscape
|
|
48
|
-
|
|
82
|
+
or otherwise explicit line geometry. Do not use it only because a region needs stripes. `Draw` and `Hatch` are included
|
|
83
|
+
by `:inkscape`. Add the Hatch mixture to another profile only when that profile owns the capability. For a scoped
|
|
84
|
+
extension, subclass `SVG::Document::Base`, then call `SVG.Mixin :Hatch, profile`. Targeting `Base` itself changes
|
|
49
85
|
every descendant profile process-wide.
|
|
50
86
|
|
|
51
|
-
Read the [
|
|
52
|
-
[Geometry sweeps and hatching](https://sevgi.roktas.dev/geometry/#sweeps) for explicit hatch lines
|
|
87
|
+
Read the [Layout guide](https://sevgi.roktas.dev/layout/) for Ruler, Grid, and both Tile models. Read
|
|
88
|
+
[Geometry sweeps and hatching](https://sevgi.roktas.dev/geometry/#sweeps) for explicit hatch lines. Use the
|
|
53
89
|
[DSL Catalog](https://sevgi.roktas.dev/dsl/) for exact drawing words. Exact Ruby contracts live in
|
|
54
90
|
[`sevgi-sundries`](https://www.rubydoc.info/gems/sevgi-sundries) and
|
|
55
91
|
[`sevgi-graphics`](https://www.rubydoc.info/gems/sevgi-graphics).
|
|
@@ -11,9 +11,9 @@ Keep document construction and output policy separate. Choose the final operatio
|
|
|
11
11
|
| PNG file | `PNG` |
|
|
12
12
|
| Export an existing SVG String outside the document | `Sevgi::Sundries::Export.call` |
|
|
13
13
|
|
|
14
|
-
The `sevgi` command reads standard input when no file is given. Use `sevgi --as badge`
|
|
15
|
-
or `PNG`
|
|
16
|
-
basename, not a path
|
|
14
|
+
The `sevgi` command reads standard input when no file is given. Use `sevgi --as badge` to make an implicit `Save`, `PDF`,
|
|
15
|
+
or `PNG` derive `badge.svg`, `badge.pdf`, or `badge.png` instead of the default `output` basename. `NAME` is a
|
|
16
|
+
basename, not a path. Explicit destinations in the source remain authoritative.
|
|
17
17
|
|
|
18
18
|
## PDF
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@ For a document, use the convenience operation:
|
|
|
21
21
|
|
|
22
22
|
```ruby
|
|
23
23
|
canvas = SVG.Canvas width: 40, height: 40, unit: :px
|
|
24
|
-
drawing = SVG
|
|
24
|
+
drawing = SVG canvas do
|
|
25
25
|
circle cx: 20, cy: 20, r: 16, fill: "tomato"
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -32,30 +32,38 @@ For an application that owns the rendered SVG and output policy separately:
|
|
|
32
32
|
|
|
33
33
|
```ruby
|
|
34
34
|
canvas = SVG.Canvas width: 40, height: 40, unit: :px
|
|
35
|
-
svg = SVG
|
|
35
|
+
svg = SVG canvas do
|
|
36
|
+
circle cx: 20, cy: 20, r: 16, fill: "tomato"
|
|
37
|
+
end.Render
|
|
36
38
|
Sevgi::Sundries::Export.call(svg, "badge.pdf")
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
The output suffix selects PDF when `format:` is omitted. `width:` and `height:` are export dimensions
|
|
41
|
+
The output suffix selects PDF when `format:` is omitted. `width:` and `height:` are export dimensions. They do not
|
|
40
42
|
repair or replace the drawing's canvas, `viewBox`, or visible geometry. Fix those in the SVG document. Use `css:` only
|
|
41
43
|
for deliberate export-only styling, and use `dpi:` when the CSS-pixel-to-output conversion policy must differ.
|
|
42
44
|
|
|
43
|
-
|
|
45
|
+
Export CSS is a last-minute adjustment after document validation. It still obeys the CSS cascade.
|
|
46
|
+
Insertion requires well-formed SVG ending in an unprefixed `</svg>` plus optional XML whitespace.
|
|
47
|
+
Self-closing or prefixed roots and comments after the root are unsupported with `css:`. Without CSS, this restriction
|
|
48
|
+
does not apply. Sevgi escapes CSS as XML text but does not validate the stylesheet. Native `Export.call` runs its source
|
|
49
|
+
callback after insertion and before conversion. Inspect the final output for changed visibility, size, and clipping.
|
|
50
|
+
|
|
51
|
+
SVG output has no native graphics dependency. PDF and PNG export lazily require Cairo, RSVG, and HexaPDF. Report a
|
|
44
52
|
missing optional component rather than replacing the path with an unrequested external command or raster workaround.
|
|
45
53
|
|
|
46
54
|
## Verification
|
|
47
55
|
|
|
48
|
-
Inspect the produced artifact
|
|
56
|
+
Inspect the produced artifact. A successful write does not prove correct rendering. For a parameterized or multi-page
|
|
49
57
|
family, start with a representative output and then check other variants affected by the same rule.
|
|
50
58
|
|
|
51
59
|
For PDF output, validate document structure with `qpdf` when available, render representative pages through Poppler or
|
|
52
|
-
an equivalent independent renderer
|
|
53
|
-
|
|
60
|
+
an equivalent independent renderer. Inspect embedded fonts when fallback changes the result. Compare raster output
|
|
61
|
+
only as evidence. Fix discrepancies in the SVG source, export policy, or environment that owns them.
|
|
54
62
|
|
|
55
63
|
Treat rendered SVGs, PDFs, PNGs, and visual snapshots as derived evidence, not implementation sources. Fix the
|
|
56
64
|
maintained Sevgi or editor-owned SVG/XML source and regenerate. Update expected artifacts only for an intentional output
|
|
57
65
|
change, then review the visible diff before accepting it.
|
|
58
66
|
|
|
59
|
-
Read [
|
|
67
|
+
Read [Output](https://sevgi.roktas.dev/output/) for SVG, PDF, and PNG workflows, and
|
|
60
68
|
[`Sevgi::Sundries::Export`](https://www.rubydoc.info/gems/sevgi-sundries/Sevgi/Sundries/Export) for exact dimensions,
|
|
61
69
|
options, return paths, and errors.
|
|
@@ -4,28 +4,28 @@ A `.sevgi` file is executable Ruby evaluated with Sevgi's drawing vocabulary. It
|
|
|
4
4
|
configuration format. Apply ordinary Ruby design and readability rules unless the compact DSL form is clearer.
|
|
5
5
|
|
|
6
6
|
- Use local variables for local drawing state and constants for genuine module/script invariants.
|
|
7
|
-
- Use Arrays, Hashes, ranges, loops, Enumerables, methods, and modules directly
|
|
7
|
+
- Use Arrays, Hashes, ranges, loops, Enumerables, methods, and modules directly. Do not recreate them as a second DSL.
|
|
8
8
|
- Separate input data from drawing behavior when that makes either easier to read or test.
|
|
9
|
-
- Extract reusable drawing behavior into ordinary methods or `SVG::Module
|
|
9
|
+
- Extract reusable drawing behavior into ordinary methods or `SVG::Module`. Use `SVG::Modules` for an owned nested
|
|
10
10
|
module family.
|
|
11
11
|
- Prefer explicit arguments and return values over hidden global state, `eval`, monkey patches, or unnecessary
|
|
12
12
|
metaprogramming.
|
|
13
13
|
- Keep side effects at the output boundary: build a document, then `Render`, `Save`, `Out`, `PDF`, or `PNG` deliberately.
|
|
14
14
|
- Preserve the surrounding project's Ruby version, naming, error, test, and formatting conventions.
|
|
15
15
|
- Hand-format `.sevgi` source for DSL readability. Do not run a broad Ruby formatter or autocorrect over `.sevgi`
|
|
16
|
-
files when it
|
|
16
|
+
files when it flattens or obscures the drawing.
|
|
17
17
|
|
|
18
18
|
## Preserve the DSL Shape
|
|
19
19
|
|
|
20
|
-
Let drawing code read as a Sevgi program rather than mechanically parenthesized Ruby. Use braces for a one-line block
|
|
21
|
-
`do`/`end` for a multiline block
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
Let drawing code read as a Sevgi program rather than mechanically parenthesized Ruby. Use braces for a one-line block.
|
|
21
|
+
Use `do`/`end` for a multiline block. Omit optional parentheses from statement-like SVG elements and Sevgi operations.
|
|
22
|
+
If braces require parentheses around a statement-like call, use `do`/`end` instead. Keep parentheses only when Ruby
|
|
23
|
+
grammar still requires them.
|
|
24
24
|
|
|
25
25
|
Avoid:
|
|
26
26
|
|
|
27
27
|
```ruby
|
|
28
|
-
SVG(:
|
|
28
|
+
SVG(width: 16, height: 12) do
|
|
29
29
|
g({ id: "mark" }) do
|
|
30
30
|
rect({ x: 2, y: 2, width: 12, height: 8 })
|
|
31
31
|
circle({ cx: 8, cy: 6, r: 3 })
|
|
@@ -36,7 +36,7 @@ end.Save("mark.svg")
|
|
|
36
36
|
Prefer:
|
|
37
37
|
|
|
38
38
|
```ruby
|
|
39
|
-
SVG :
|
|
39
|
+
SVG width: 16, height: 12 do
|
|
40
40
|
g id: "mark" do
|
|
41
41
|
rect x: 2, y: 2, width: 12, height: 8
|
|
42
42
|
circle cx: 8, cy: 6, r: 3
|
|
@@ -44,36 +44,47 @@ SVG :minimal do
|
|
|
44
44
|
end.Save "mark.svg"
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
The first form is valid Ruby
|
|
47
|
+
The first form is valid Ruby. It hides the drawing vocabulary's visual rhythm.
|
|
48
|
+
|
|
49
|
+
## Choose Where Helpers Live
|
|
50
|
+
|
|
51
|
+
- Use `SVG.Module` for drawing code that works with different document profiles without adding methods to them.
|
|
52
|
+
Invoke it explicitly with `Call` or another callable wrapper. Every public instance method is a drawing step, so keep
|
|
53
|
+
non-step helpers private or protected. Those helpers run on the callable receiver rather than the SVG document.
|
|
54
|
+
- Subclass `SVG::Document::Base` when every document of a new type needs the same helper methods. The methods can
|
|
55
|
+
be called directly in the drawing block, and subclasses inherit them.
|
|
56
|
+
- Use `SVG.Mixin` to add methods to a document class after it has been defined or from another library. It changes the
|
|
57
|
+
target class and its subclasses. Targeting `SVG::Document::Base` changes every descendant profile process-wide.
|
|
48
58
|
|
|
49
59
|
## Callable Modules
|
|
50
60
|
|
|
51
|
-
|
|
52
|
-
give several steps descriptive names. Private methods
|
|
53
|
-
`require "sevgi/graphics"` consumer
|
|
54
|
-
|
|
61
|
+
Build an anonymous callable module with `SVG.Module`, or extend an existing Ruby module with `SVG::Module`. Its public
|
|
62
|
+
instance methods are drawing steps. Name the only step `call`, or give several steps descriptive names. Private methods
|
|
63
|
+
remain ordinary implementation helpers. A focused `require "sevgi/graphics"` consumer creates an ordinary `Module`
|
|
64
|
+
and extends it with `Sevgi::Graphics::Module`. Use `Sevgi::Graphics::Modules` for a named module family.
|
|
55
65
|
|
|
56
66
|
`base` registers argument-independent invariant SVG content that runs once per invocation before the public drawing
|
|
57
67
|
steps. It is not general initialization or an ordering hook.
|
|
58
68
|
|
|
59
69
|
```ruby
|
|
60
|
-
Badge = Module
|
|
61
|
-
extend SVG::Module
|
|
62
|
-
|
|
70
|
+
Badge = SVG.Module do
|
|
63
71
|
base { css ".badge" => { fill: "tomato" } }
|
|
64
72
|
def call(label:) = text label, class: "badge"
|
|
65
73
|
end
|
|
66
74
|
|
|
67
|
-
SVG
|
|
75
|
+
SVG :minimal do
|
|
76
|
+
Call Badge, label: "OK"
|
|
77
|
+
end.Render
|
|
68
78
|
```
|
|
69
79
|
|
|
70
80
|
`Call` draws directly. On an Inkscape profile, `Group`, `Layer`, and `Layer!` wrap the same invocation in a group,
|
|
71
|
-
normal layer, or insensitive layer
|
|
81
|
+
normal layer, or insensitive layer. `Symbols` expands the public steps into reusable symbols. Lowercase `layer` and
|
|
72
82
|
`layer!` instead open explicit layer blocks without invoking a module. Use `SVG::Modules` only when one namespace owns
|
|
73
83
|
a nested family of callable modules.
|
|
74
84
|
|
|
75
85
|
Ruby arithmetic is appropriate for domain data and values the program must know. It does not supersede the renderer
|
|
76
86
|
ownership rule in [drawing.md](drawing.md): idiomatic Ruby can still be the wrong layer for a rendering calculation.
|
|
77
87
|
|
|
78
|
-
Use
|
|
79
|
-
[
|
|
88
|
+
Use [Compose](https://sevgi.roktas.dev/compose/) for callable modules,
|
|
89
|
+
[Documents](https://sevgi.roktas.dev/documents/#document-types) for document classes and mixtures, and
|
|
90
|
+
[Usage](https://sevgi.roktas.dev/usage/) for script and library behavior.
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# SVG Routing
|
|
2
2
|
|
|
3
|
-
Use this page to identify the SVG mechanism
|
|
4
|
-
this index into a cookbook of one-off drawing tips.
|
|
3
|
+
Use this page to identify the SVG mechanism. Then make sure that MDN or the SVG specification documents its exact
|
|
4
|
+
behavior. Do not turn this index into a cookbook of one-off drawing tips.
|
|
5
5
|
|
|
6
6
|
| Rendering concept | Start with |
|
|
7
7
|
| --- | --- |
|
|
8
8
|
| Coordinate system and responsive scaling | `viewBox`, viewport dimensions, `preserveAspectRatio` |
|
|
9
|
-
| Relative placement of an element tree | `transform
|
|
9
|
+
| Relative placement of an element tree | `transform` with Sevgi's transform helpers when available |
|
|
10
10
|
| Reusable drawing definitions | `defs`, `symbol`, `use` |
|
|
11
11
|
| Repeated visual fill | `pattern` |
|
|
12
12
|
| Paint | presentation attributes or CSS, gradients, opacity |
|
|
13
|
-
| Visibility boundaries | `clipPath` for hard clipping
|
|
13
|
+
| Visibility boundaries | `clipPath` for hard clipping and `mask` for luminance/alpha compositing |
|
|
14
14
|
| Line decoration | `marker`, stroke width, line cap, line join, dash array |
|
|
15
15
|
| Renderer effects | `filter` and filter primitives |
|
|
16
|
-
| Text relationships | text positioning and anchoring attributes
|
|
16
|
+
| Text relationships | text positioning and anchoring attributes with font metrics left to the renderer |
|
|
17
17
|
|
|
18
18
|
Resolve questions in this order:
|
|
19
19
|
|
|
@@ -29,7 +29,7 @@ Authoritative references:
|
|
|
29
29
|
|
|
30
30
|
- [MDN SVG reference](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference)
|
|
31
31
|
- [W3C SVG 2 specification](https://www.w3.org/TR/SVG2/)
|
|
32
|
-
- [Sevgi
|
|
32
|
+
- [Sevgi Documents](https://sevgi.roktas.dev/documents/)
|
|
33
33
|
|
|
34
34
|
Do not invent an SVG name from memory when validation matters. Check MDN and let Sevgi Standard validate known element
|
|
35
35
|
names, attributes, content, and nesting.
|
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
| Need | Component / entry point | Boundary |
|
|
6
6
|
| --- | --- | --- |
|
|
7
|
-
| Build SVG documents and element trees | Graphics
|
|
7
|
+
| Build SVG documents and element trees | Graphics with `SVG(...)` and SVG element calls | Default starting point for every drawing |
|
|
8
8
|
| Choose paper size, canvas geometry, or root serialization metadata | `SVG.Paper`, `SVG.Canvas`, `SVG.Document` | Keep physical size, drawing surface, and document profile independent |
|
|
9
|
-
| Validate SVG vocabulary and nesting | Standard | Use validation
|
|
9
|
+
| Validate SVG vocabulary and nesting | Standard | Use validation instead of hand-maintained element/attribute allowlists |
|
|
10
10
|
| Calculate geometry SVG cannot supply | `Sevgi::Geometry` | Use for constructed values, intersections, sweeps, and algorithmic bounds—not renderer layout |
|
|
11
|
+
| Inspect circle, ellipse, or finite arc geometry | `Sevgi::Geometry::Circle`, `Ellipse`, `Arc` | See `layout.md` for the distinction from renderer-owned `ArcTo` and `ArcBy` |
|
|
11
12
|
| Fit rulers, grids, and reusable tile layouts | `Sevgi::Sundries`, `SVG.Grid` | Choose the exact model through `layout.md` |
|
|
12
|
-
| Reuse supported cross-component helpers | `Sevgi::F` |
|
|
13
|
+
| Reuse supported cross-component helpers | `Sevgi::F` | Use it before adding a project-local Sevgi helper. Do not treat it as a general utility library |
|
|
13
14
|
| Import or inspect existing SVG/XML | Derender facade methods | Choose the source/evaluation relationship through `derender.md` |
|
|
14
15
|
| Render SVG as PDF or PNG | Sundries export / document `PDF` and `PNG` | Choose the output boundary through `output.md` |
|
|
15
16
|
|
|
@@ -28,6 +29,14 @@ When a Sevgi checkout is available, prefer its canonical sources:
|
|
|
28
29
|
| Exact public contracts | the owning component's `lib/` YARD comments |
|
|
29
30
|
| Rendered local YARD | `.local/var/ruby/doc/api` after `bundle exec rake doc` |
|
|
30
31
|
|
|
32
|
+
## Installed Gems
|
|
33
|
+
|
|
34
|
+
Without a checkout, use the consumer's active bundle to locate the owning gem, for example `bundle show sevgi-graphics`.
|
|
35
|
+
Outside Bundler, use `gem which sevgi/graphics` to locate that component's entrypoint.
|
|
36
|
+
Read the adjacent `lib/` sources and YARD comments for the installed contract.
|
|
37
|
+
Use the same Ruby and dependency environment as the drawing.
|
|
38
|
+
Do not assume that the latest online API exists in the installed version.
|
|
39
|
+
|
|
31
40
|
## Lookup Order
|
|
32
41
|
|
|
33
42
|
1. Read the task-relevant user guide for semantics and workflow.
|
|
@@ -38,10 +47,11 @@ When a Sevgi checkout is available, prefer its canonical sources:
|
|
|
38
47
|
|
|
39
48
|
| Topic | User guide | YARD |
|
|
40
49
|
| --- | --- | --- |
|
|
41
|
-
| Script and library forms | [Getting Started](https://sevgi.roktas.dev/
|
|
42
|
-
| SVG documents and
|
|
50
|
+
| Script and library forms | [Getting Started](https://sevgi.roktas.dev/start/), [Usage](https://sevgi.roktas.dev/usage/) | [`sevgi`](https://www.rubydoc.info/gems/sevgi) |
|
|
51
|
+
| SVG documents and composition | [Documents](https://sevgi.roktas.dev/documents/), [Compose](https://sevgi.roktas.dev/compose/), [DSL Catalog](https://sevgi.roktas.dev/dsl/) | [`sevgi-graphics`](https://www.rubydoc.info/gems/sevgi-graphics) |
|
|
43
52
|
| Geometry | [Geometry](https://sevgi.roktas.dev/geometry/) | [`sevgi-geometry`](https://www.rubydoc.info/gems/sevgi-geometry) |
|
|
44
|
-
| Rulers, grids, tiles
|
|
53
|
+
| Rulers, grids, and tiles | [Layout](https://sevgi.roktas.dev/layout/) | [`sevgi-sundries`](https://www.rubydoc.info/gems/sevgi-sundries) |
|
|
54
|
+
| SVG, PDF, and PNG output | [Output](https://sevgi.roktas.dev/output/) | [`sevgi-graphics`](https://www.rubydoc.info/gems/sevgi-graphics), [`sevgi-sundries`](https://www.rubydoc.info/gems/sevgi-sundries) |
|
|
45
55
|
| Shared helpers | [Functions](https://sevgi.roktas.dev/functions/) | [`sevgi-function`](https://www.rubydoc.info/gems/sevgi-function) |
|
|
46
56
|
| SVG/XML import and round trip | [Derender](https://sevgi.roktas.dev/derender/) | [`sevgi-derender`](https://www.rubydoc.info/gems/sevgi-derender) |
|
|
47
57
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sevgi-appendix
|
|
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ş
|
|
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
98
98
|
- !ruby/object:Gem::Version
|
|
99
99
|
version: '0'
|
|
100
100
|
requirements: []
|
|
101
|
-
rubygems_version: 4.0.
|
|
101
|
+
rubygems_version: 4.0.20
|
|
102
102
|
specification_version: 4
|
|
103
103
|
summary: Development extras for the Sevgi SVG DSL.
|
|
104
104
|
test_files: []
|