postsvg 0.1.0 → 0.3.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 +105 -0
- data/CLAUDE.md +173 -0
- data/Gemfile +2 -3
- data/README.adoc +456 -179
- data/Rakefile +100 -0
- data/TODO.roadmap/00-architecture.md +139 -0
- data/TODO.roadmap/01-autoload-migration.md +39 -0
- data/TODO.roadmap/02-isolate-dormant-code.md +51 -0
- data/TODO.roadmap/03-domain-model.md +66 -0
- data/TODO.roadmap/04-lexer.md +40 -0
- data/TODO.roadmap/05-parser.md +43 -0
- data/TODO.roadmap/06-graphics-state.md +45 -0
- data/TODO.roadmap/07-matrix-and-color.md +37 -0
- data/TODO.roadmap/08-svg-builder.md +51 -0
- data/TODO.roadmap/09-renderer.md +52 -0
- data/TODO.roadmap/10-visitor.md +58 -0
- data/TODO.roadmap/11-operator-coverage.md +103 -0
- data/TODO.roadmap/12-svg-domain.md +62 -0
- data/TODO.roadmap/13-translation-handlers.md +69 -0
- data/TODO.roadmap/14-ps-serializer.md +49 -0
- data/TODO.roadmap/15-cli-and-public-api.md +47 -0
- data/TODO.roadmap/16-specs.md +84 -0
- data/TODO.roadmap/17-docs-sync.md +47 -0
- data/TODO.roadmap/18-performance-and-determinism.md +47 -0
- data/TODO.roadmap/19-error-model.md +45 -0
- data/TODO.roadmap/20-font-and-text.md +46 -0
- data/TODO.roadmap/21-images.md +45 -0
- data/TODO.roadmap/22-forms-and-resources.md +25 -0
- data/TODO.roadmap/23-level2-level3.md +52 -0
- data/TODO.roadmap/24-ci-and-release.md +42 -0
- data/TODO.roadmap/README.md +77 -0
- data/docs/.gitignore +29 -0
- data/docs/CHANGELOG.md +114 -0
- data/docs/COMPLETE_DOCUMENTATION_STATUS.md +376 -0
- data/docs/DEPLOYMENT.md +456 -0
- data/docs/DEPLOYMENT_INSTRUCTIONS.md +229 -0
- data/docs/DOCUMENTATION_PLAN.md +425 -0
- data/docs/FINAL_SUMMARY.md +657 -0
- data/docs/Gemfile +15 -0
- data/docs/README.md +327 -0
- data/docs/_config.yml +99 -0
- data/docs/advanced-topics.adoc +370 -0
- data/docs/api-reference/colors.adoc +705 -0
- data/docs/api-reference/converter.adoc +699 -0
- data/docs/api-reference/execution-context.adoc +1210 -0
- data/docs/api-reference/graphics-state.adoc +1070 -0
- data/docs/api-reference/interpreter.adoc +810 -0
- data/docs/api-reference/matrix.adoc +1179 -0
- data/docs/api-reference/path-builder.adoc +1284 -0
- data/docs/api-reference/postsvg-module.adoc +388 -0
- data/docs/api-reference/svg-generator.adoc +891 -0
- data/docs/api-reference/tokenizer.adoc +925 -0
- data/docs/api-reference.adoc +221 -0
- data/docs/architecture/command-registry.adoc +1191 -0
- data/docs/architecture/conversion-pipeline.adoc +746 -0
- data/docs/architecture/design-decisions.adoc +999 -0
- data/docs/architecture/generator-stage.adoc +1115 -0
- data/docs/architecture/graphics-state-model.adoc +1089 -0
- data/docs/architecture/interpreter-stage.adoc +1125 -0
- data/docs/architecture/parser-stage.adoc +1051 -0
- data/docs/architecture.adoc +354 -0
- data/docs/cli-reference/batch-command.adoc +616 -0
- data/docs/cli-reference/check-command.adoc +677 -0
- data/docs/cli-reference/cli-options.adoc +802 -0
- data/docs/cli-reference/convert-command.adoc +462 -0
- data/docs/cli-reference/version-command.adoc +296 -0
- data/docs/cli-reference.adoc +317 -0
- data/docs/concepts/conversion-pipeline.adoc +903 -0
- data/docs/concepts/coordinate-systems.adoc +836 -0
- data/docs/concepts/graphics-state.adoc +861 -0
- data/docs/concepts/path-operations.adoc +1076 -0
- data/docs/concepts/postscript-language.adoc +859 -0
- data/docs/concepts/svg-generation.adoc +937 -0
- data/docs/concepts.adoc +198 -0
- data/docs/contributing.adoc +443 -0
- data/docs/development.adoc +420 -0
- data/docs/faq.adoc +493 -0
- data/docs/getting-started/basic-usage.adoc +538 -0
- data/docs/getting-started/common-workflows.adoc +577 -0
- data/docs/getting-started/first-conversion.adoc +492 -0
- data/docs/getting-started/installation.adoc +534 -0
- data/docs/getting-started.adoc +94 -0
- data/docs/index.adoc +248 -0
- data/docs/optimization.adoc +196 -0
- data/docs/ps2svg_compatibility.adoc +149 -0
- data/docs/quick-reference.adoc +453 -0
- data/docs/sitemap.adoc +337 -0
- data/docs/troubleshooting.adoc +486 -0
- data/docs/validation.adoc +772 -0
- data/exe/postsvg +1 -0
- data/lib/postsvg/cli.rb +104 -57
- data/lib/postsvg/color.rb +132 -0
- data/lib/postsvg/errors.rb +68 -3
- data/lib/postsvg/format_number.rb +22 -0
- data/lib/postsvg/graphics_context.rb +80 -0
- data/lib/postsvg/graphics_stack.rb +43 -0
- data/lib/postsvg/model/literals/array.rb +41 -0
- data/lib/postsvg/model/literals/dictionary.rb +34 -0
- data/lib/postsvg/model/literals/hex.rb +37 -0
- data/lib/postsvg/model/literals/name.rb +40 -0
- data/lib/postsvg/model/literals/number.rb +36 -0
- data/lib/postsvg/model/literals/procedure.rb +41 -0
- data/lib/postsvg/model/literals/string.rb +30 -0
- data/lib/postsvg/model/literals.rb +19 -0
- data/lib/postsvg/model/operator.rb +58 -0
- data/lib/postsvg/model/operators/arithmetic.rb +264 -0
- data/lib/postsvg/model/operators/boolean.rb +182 -0
- data/lib/postsvg/model/operators/color.rb +74 -0
- data/lib/postsvg/model/operators/container.rb +186 -0
- data/lib/postsvg/model/operators/control_flow.rb +119 -0
- data/lib/postsvg/model/operators/device.rb +21 -0
- data/lib/postsvg/model/operators/dictionary.rb +118 -0
- data/lib/postsvg/model/operators/font.rb +121 -0
- data/lib/postsvg/model/operators/graphics_state.rb +84 -0
- data/lib/postsvg/model/operators/painting.rb +29 -0
- data/lib/postsvg/model/operators/path.rb +169 -0
- data/lib/postsvg/model/operators/stack.rb +72 -0
- data/lib/postsvg/model/operators/transformations.rb +103 -0
- data/lib/postsvg/model/operators.rb +89 -0
- data/lib/postsvg/model/program.rb +68 -0
- data/lib/postsvg/model/token.rb +43 -0
- data/lib/postsvg/model.rb +17 -0
- data/lib/postsvg/options.rb +29 -0
- data/lib/postsvg/renderer.rb +85 -0
- data/lib/postsvg/serializer.rb +325 -0
- data/lib/postsvg/source/ast_builder.rb +308 -0
- data/lib/postsvg/source/lexer.rb +322 -0
- data/lib/postsvg/source/operand_stack.rb +55 -0
- data/lib/postsvg/source.rb +21 -0
- data/lib/postsvg/svg/attribute_parser.rb +45 -0
- data/lib/postsvg/svg/clip_path_registry.rb +44 -0
- data/lib/postsvg/svg/document.rb +22 -0
- data/lib/postsvg/svg/element.rb +84 -0
- data/lib/postsvg/svg/elements/circle.rb +36 -0
- data/lib/postsvg/svg/elements/clip_path.rb +26 -0
- data/lib/postsvg/svg/elements/defs.rb +24 -0
- data/lib/postsvg/svg/elements/ellipse.rb +38 -0
- data/lib/postsvg/svg/elements/group.rb +37 -0
- data/lib/postsvg/svg/elements/image.rb +35 -0
- data/lib/postsvg/svg/elements/line.rb +36 -0
- data/lib/postsvg/svg/elements/path.rb +32 -0
- data/lib/postsvg/svg/elements/polygon.rb +12 -0
- data/lib/postsvg/svg/elements/polyline.rb +32 -0
- data/lib/postsvg/svg/elements/rect.rb +44 -0
- data/lib/postsvg/svg/elements/svg.rb +39 -0
- data/lib/postsvg/svg/elements/text.rb +42 -0
- data/lib/postsvg/svg/elements.rb +31 -0
- data/lib/postsvg/svg/paint.rb +34 -0
- data/lib/postsvg/svg/parser.rb +39 -0
- data/lib/postsvg/svg/path_data/command.rb +27 -0
- data/lib/postsvg/svg/path_data/parser.rb +82 -0
- data/lib/postsvg/svg/path_data.rb +17 -0
- data/lib/postsvg/svg/stroke.rb +31 -0
- data/lib/postsvg/svg/transform_list.rb +59 -0
- data/lib/postsvg/svg.rb +22 -0
- data/lib/postsvg/svg_builder.rb +249 -0
- data/lib/postsvg/translation/arc_converter.rb +86 -0
- data/lib/postsvg/translation/bounding_box.rb +59 -0
- data/lib/postsvg/translation/context.rb +34 -0
- data/lib/postsvg/translation/handler_registry.rb +38 -0
- data/lib/postsvg/translation/handlers/circle_handler.rb +28 -0
- data/lib/postsvg/translation/handlers/clip_path_handler.rb +13 -0
- data/lib/postsvg/translation/handlers/defs_handler.rb +15 -0
- data/lib/postsvg/translation/handlers/ellipse_handler.rb +31 -0
- data/lib/postsvg/translation/handlers/group_handler.rb +21 -0
- data/lib/postsvg/translation/handlers/image_handler.rb +20 -0
- data/lib/postsvg/translation/handlers/line_handler.rb +23 -0
- data/lib/postsvg/translation/handlers/open_handler.rb +18 -0
- data/lib/postsvg/translation/handlers/path_handler.rb +356 -0
- data/lib/postsvg/translation/handlers/polygon_handler.rb +33 -0
- data/lib/postsvg/translation/handlers/polyline_handler.rb +31 -0
- data/lib/postsvg/translation/handlers/rect_handler.rb +27 -0
- data/lib/postsvg/translation/handlers/shared.rb +110 -0
- data/lib/postsvg/translation/handlers/svg_handler.rb +25 -0
- data/lib/postsvg/translation/handlers/text_handler.rb +56 -0
- data/lib/postsvg/translation/handlers.rb +25 -0
- data/lib/postsvg/translation/ps_renderer.rb +105 -0
- data/lib/postsvg/translation/record_emitter.rb +35 -0
- data/lib/postsvg/translation.rb +17 -0
- data/lib/postsvg/version.rb +1 -1
- data/lib/postsvg/visitors/ps_visitor/arithmetic.rb +125 -0
- data/lib/postsvg/visitors/ps_visitor/boolean.rb +105 -0
- data/lib/postsvg/visitors/ps_visitor/color.rb +53 -0
- data/lib/postsvg/visitors/ps_visitor/common.rb +66 -0
- data/lib/postsvg/visitors/ps_visitor/container.rb +164 -0
- data/lib/postsvg/visitors/ps_visitor/control_flow.rb +110 -0
- data/lib/postsvg/visitors/ps_visitor/device.rb +20 -0
- data/lib/postsvg/visitors/ps_visitor/dictionary.rb +89 -0
- data/lib/postsvg/visitors/ps_visitor/font.rb +93 -0
- data/lib/postsvg/visitors/ps_visitor/graphics_state.rb +55 -0
- data/lib/postsvg/visitors/ps_visitor/painting.rb +90 -0
- data/lib/postsvg/visitors/ps_visitor/path.rb +112 -0
- data/lib/postsvg/visitors/ps_visitor/stack.rb +47 -0
- data/lib/postsvg/visitors/ps_visitor/transformations.rb +101 -0
- data/lib/postsvg/visitors/ps_visitor.rb +208 -0
- data/lib/postsvg/visitors.rb +9 -0
- data/lib/postsvg.rb +93 -59
- data/lychee.toml +86 -0
- metadata +216 -11
- data/postsvg.gemspec +0 -38
data/docs/concepts.adoc
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
= Core Concepts
|
|
2
|
+
:page-nav_order: 3
|
|
3
|
+
|
|
4
|
+
== Purpose
|
|
5
|
+
|
|
6
|
+
This section explains the fundamental concepts behind Postsvg's architecture and operation. Understanding these concepts will help you use Postsvg effectively and troubleshoot issues when they arise.
|
|
7
|
+
|
|
8
|
+
== References
|
|
9
|
+
|
|
10
|
+
* link:index.adoc[Documentation Home]
|
|
11
|
+
* link:architecture.adoc[Architecture Documentation]
|
|
12
|
+
* link:postscript.adoc[PostScript Language Reference]
|
|
13
|
+
* link:getting-started.adoc[Getting Started Guide]
|
|
14
|
+
|
|
15
|
+
== Concepts
|
|
16
|
+
|
|
17
|
+
**Conversion Pipeline**:: The three-stage process of tokenization, interpretation, and SVG generation that transforms PostScript into SVG.
|
|
18
|
+
|
|
19
|
+
**Graphics State**:: A data structure maintaining the current drawing parameters including colors, line width, transformations, and the current path.
|
|
20
|
+
|
|
21
|
+
**Operand Stack**:: A stack-based execution model where PostScript operators pop arguments from the stack and push results back.
|
|
22
|
+
|
|
23
|
+
**Coordinate Transformation**:: The mathematical transformation between PostScript's coordinate system and SVG's coordinate system.
|
|
24
|
+
|
|
25
|
+
**Path Construction**:: The process of building vector paths through moveto, lineto, curveto, and other path operators.
|
|
26
|
+
|
|
27
|
+
== Core Concepts Topics
|
|
28
|
+
|
|
29
|
+
link:concepts/postscript-language.adoc[**PostScript Language**]::
|
|
30
|
+
Overview of the PostScript language, its stack-based execution model, and how Postsvg interprets it.
|
|
31
|
+
|
|
32
|
+
link:concepts/conversion-pipeline.adoc[**Conversion Pipeline**]::
|
|
33
|
+
The three-stage architecture: tokenization/parsing, interpretation/execution, and SVG generation.
|
|
34
|
+
|
|
35
|
+
link:concepts/graphics-state.adoc[**Graphics State Management**]::
|
|
36
|
+
How Postsvg maintains and manipulates the graphics state throughout conversion.
|
|
37
|
+
|
|
38
|
+
link:concepts/coordinate-systems.adoc[**Coordinate Systems**]::
|
|
39
|
+
Understanding PostScript's bottom-left origin vs SVG's top-left origin, and how transformations work.
|
|
40
|
+
|
|
41
|
+
link:concepts/path-operations.adoc[**Path Operations**]::
|
|
42
|
+
How paths are constructed, manipulated, and rendered in the conversion process.
|
|
43
|
+
|
|
44
|
+
link:concepts/svg-generation.adoc[**SVG Generation**]::
|
|
45
|
+
The process of generating clean, standards-compliant SVG from interpreted PostScript commands.
|
|
46
|
+
|
|
47
|
+
== Conversion Pipeline Overview
|
|
48
|
+
|
|
49
|
+
.Three-Stage Conversion Architecture
|
|
50
|
+
[source]
|
|
51
|
+
----
|
|
52
|
+
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
|
|
53
|
+
│ PostScript │ │ Tokenizer & │ │ Interpreter │
|
|
54
|
+
│ Input File │─────>│ Parser │─────>│ & Execution │
|
|
55
|
+
│ (.ps/.eps) │ │ │ │ Context │
|
|
56
|
+
└─────────────────┘ └──────────────────┘ └────────┬────────┘
|
|
57
|
+
│
|
|
58
|
+
┌──────────────────┐ │
|
|
59
|
+
│ SVG Generator │<──────────────┘
|
|
60
|
+
│ │
|
|
61
|
+
└────────┬─────────┘
|
|
62
|
+
│
|
|
63
|
+
▼
|
|
64
|
+
┌──────────────────┐
|
|
65
|
+
│ SVG Output │
|
|
66
|
+
│ (.svg) │
|
|
67
|
+
└──────────────────┘
|
|
68
|
+
----
|
|
69
|
+
|
|
70
|
+
=== Stage 1: Tokenization and Parsing
|
|
71
|
+
|
|
72
|
+
The [`Tokenizer`](../lib/postsvg/tokenizer.rb:8) class reads the PostScript file and breaks it into tokens:
|
|
73
|
+
|
|
74
|
+
* Numbers (integers and floats)
|
|
75
|
+
* Operators (commands like `moveto`, `lineto`)
|
|
76
|
+
* Names (identifiers starting with `/`)
|
|
77
|
+
* Strings (enclosed in parentheses or angle brackets)
|
|
78
|
+
* Arrays (enclosed in square brackets)
|
|
79
|
+
* Procedures (executable arrays enclosed in curly braces)
|
|
80
|
+
|
|
81
|
+
=== Stage 2: Interpretation and Execution
|
|
82
|
+
|
|
83
|
+
The [`Interpreter`](../lib/postsvg/interpreter.rb:9) class executes PostScript commands using:
|
|
84
|
+
|
|
85
|
+
* **Operand Stack**: Stores values for operators
|
|
86
|
+
* **Dictionary Stack**: Manages variable definitions
|
|
87
|
+
* **Graphics State**: Tracks current drawing parameters
|
|
88
|
+
* **Execution Context**: Coordinates the execution environment
|
|
89
|
+
|
|
90
|
+
=== Stage 3: SVG Generation
|
|
91
|
+
|
|
92
|
+
The [`SvgGenerator`](../lib/postsvg/svg_generator.rb:7) class creates SVG output:
|
|
93
|
+
|
|
94
|
+
* Transforms coordinates from PostScript to SVG space
|
|
95
|
+
* Converts paths to SVG path data format
|
|
96
|
+
* Applies colors, line widths, and other styling
|
|
97
|
+
* Generates optimized, standards-compliant SVG markup
|
|
98
|
+
|
|
99
|
+
== Graphics State Model
|
|
100
|
+
|
|
101
|
+
The graphics state is a critical concept in both PostScript and Postsvg. It maintains all parameters that affect how graphics are rendered:
|
|
102
|
+
|
|
103
|
+
**Transformation Matrix**:: Current coordinate transformation (CTM)
|
|
104
|
+
**Current Path**:: Path being constructed
|
|
105
|
+
**Current Point**:: Last point touched by a path operator
|
|
106
|
+
**Color**:: Fill and stroke colors (RGB, grayscale, or CMYK)
|
|
107
|
+
**Line Attributes**:: Line width, cap style, join style, dash pattern
|
|
108
|
+
**Clipping Path**:: Region where drawing operations are visible
|
|
109
|
+
|
|
110
|
+
.Graphics State Stack
|
|
111
|
+
[source]
|
|
112
|
+
----
|
|
113
|
+
gsave → Save current state
|
|
114
|
+
(modify state)
|
|
115
|
+
gsave → Save modified state
|
|
116
|
+
(modify state further)
|
|
117
|
+
grestore → Restore to first modified state
|
|
118
|
+
grestore → Restore to original state
|
|
119
|
+
----
|
|
120
|
+
|
|
121
|
+
== PostScript Stack Model
|
|
122
|
+
|
|
123
|
+
PostScript uses a stack-based execution model:
|
|
124
|
+
|
|
125
|
+
[source,postscript]
|
|
126
|
+
----
|
|
127
|
+
10 20 moveto % Stack: empty (moveto consumed both values)
|
|
128
|
+
100 0 rlineto % Stack: empty (rlineto consumed both values)
|
|
129
|
+
0.5 setgray % Stack: empty (setgray consumed the value)
|
|
130
|
+
fill % Stack: empty (fill takes no arguments)
|
|
131
|
+
----
|
|
132
|
+
|
|
133
|
+
The stack operations are fundamental:
|
|
134
|
+
|
|
135
|
+
* `dup` - Duplicate top item
|
|
136
|
+
* `pop` - Remove top item
|
|
137
|
+
* `exch` - Exchange top two items
|
|
138
|
+
* `roll` - Rotate items on stack
|
|
139
|
+
|
|
140
|
+
== Coordinate System Transformation
|
|
141
|
+
|
|
142
|
+
PostScript uses a bottom-left origin with Y increasing upward, while SVG uses a top-left origin with Y increasing downward.
|
|
143
|
+
|
|
144
|
+
.Coordinate System Difference
|
|
145
|
+
[source]
|
|
146
|
+
----
|
|
147
|
+
PostScript (0,0 at bottom-left) SVG (0,0 at top-left)
|
|
148
|
+
|
|
149
|
+
100 ┌────────┐ ┌────────┐ 0
|
|
150
|
+
│ │ │ │
|
|
151
|
+
│ │ │ │
|
|
152
|
+
0 └────────┘ └────────┘ 100
|
|
153
|
+
0 100 0 100
|
|
154
|
+
----
|
|
155
|
+
|
|
156
|
+
Postsvg handles this transformation automatically by:
|
|
157
|
+
|
|
158
|
+
1. Flipping the Y-coordinate: `svg_y = height - ps_y`
|
|
159
|
+
2. Adjusting the viewBox to match the BoundingBox
|
|
160
|
+
3. Transforming all path coordinates appropriately
|
|
161
|
+
|
|
162
|
+
== Path Construction Process
|
|
163
|
+
|
|
164
|
+
Paths in PostScript are built incrementally:
|
|
165
|
+
|
|
166
|
+
[source,postscript]
|
|
167
|
+
----
|
|
168
|
+
newpath % Initialize empty path
|
|
169
|
+
10 10 moveto % Start new subpath at (10,10)
|
|
170
|
+
90 10 lineto % Add line to (90,10)
|
|
171
|
+
90 90 lineto % Add line to (90,90)
|
|
172
|
+
10 90 lineto % Add line to (10,90)
|
|
173
|
+
closepath % Close the subpath (back to 10,10)
|
|
174
|
+
fill % Fill the path with current color
|
|
175
|
+
----
|
|
176
|
+
|
|
177
|
+
This becomes an SVG path:
|
|
178
|
+
|
|
179
|
+
[source,xml]
|
|
180
|
+
----
|
|
181
|
+
<path d="M 10 90 L 90 90 L 90 10 L 10 10 Z" fill="#808080"/>
|
|
182
|
+
----
|
|
183
|
+
|
|
184
|
+
== Next Steps
|
|
185
|
+
|
|
186
|
+
After understanding these core concepts:
|
|
187
|
+
|
|
188
|
+
* Explore the link:architecture.adoc[Architecture Documentation] for implementation details
|
|
189
|
+
* Read the link:postscript.adoc[PostScript Language Reference] for operator details
|
|
190
|
+
* Review link:api-reference.adoc[API Reference] to use these concepts in code
|
|
191
|
+
* Check link:advanced-topics.adoc[Advanced Topics] for complex scenarios
|
|
192
|
+
|
|
193
|
+
== Bibliography
|
|
194
|
+
|
|
195
|
+
* Adobe Systems Incorporated. _PostScript Language Reference_, 3rd Edition
|
|
196
|
+
* link:https://www.w3.org/TR/SVG/paths.html[SVG Paths Specification]
|
|
197
|
+
* link:concepts/conversion-pipeline.adoc[Detailed Conversion Pipeline]
|
|
198
|
+
* link:concepts/graphics-state.adoc[Graphics State Management]
|
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
= Contributing Guide
|
|
2
|
+
:page-nav_order: 9
|
|
3
|
+
|
|
4
|
+
== Purpose
|
|
5
|
+
|
|
6
|
+
Thank you for your interest in contributing to Postsvg! This guide explains how to contribute code, documentation, bug reports, and feature requests.
|
|
7
|
+
|
|
8
|
+
== References
|
|
9
|
+
|
|
10
|
+
* link:index.adoc[Documentation Home]
|
|
11
|
+
* link:development.adoc[Development Guide]
|
|
12
|
+
* link:https://github.com/metanorma/postsvg[GitHub Repository]
|
|
13
|
+
* link:https://github.com/metanorma/postsvg/issues[Issue Tracker]
|
|
14
|
+
|
|
15
|
+
== Concepts
|
|
16
|
+
|
|
17
|
+
**Contribution Types**:: Code contributions, documentation improvements, bug reports, and feature requests.
|
|
18
|
+
|
|
19
|
+
**Code of Conduct**:: Expected behavior and community standards for all contributors.
|
|
20
|
+
|
|
21
|
+
**Pull Request Process**:: The workflow for submitting and reviewing code changes.
|
|
22
|
+
|
|
23
|
+
**Issue Reporting**:: How to report bugs and request features effectively.
|
|
24
|
+
|
|
25
|
+
== Ways to Contribute
|
|
26
|
+
|
|
27
|
+
=== Report Bugs
|
|
28
|
+
|
|
29
|
+
Found a bug? Please link:https://github.com/metanorma/postsvg/issues/new[create an issue] with:
|
|
30
|
+
|
|
31
|
+
* **Clear title** describing the problem
|
|
32
|
+
* **Steps to reproduce** the issue
|
|
33
|
+
* **Expected behavior** vs actual behavior
|
|
34
|
+
* **PostScript file** or minimal example (if applicable)
|
|
35
|
+
* **Error messages** and stack traces
|
|
36
|
+
* **Environment details** (Ruby version, OS, gem version)
|
|
37
|
+
|
|
38
|
+
.Bug report template
|
|
39
|
+
[example]
|
|
40
|
+
====
|
|
41
|
+
**Title:** Conversion fails on files with CMYK colors
|
|
42
|
+
|
|
43
|
+
**Description:**
|
|
44
|
+
PostScript files using `setcmykcolor` fail to convert with error "Unknown operator: setcmykcolor"
|
|
45
|
+
|
|
46
|
+
**Steps to Reproduce:**
|
|
47
|
+
1. Create PS file with CMYK color: `0.5 0.3 0.1 0.0 setcmykcolor`
|
|
48
|
+
2. Run: `postsvg convert test.ps output.svg`
|
|
49
|
+
3. Observe error
|
|
50
|
+
|
|
51
|
+
**Expected:** Should convert CMYK to RGB
|
|
52
|
+
**Actual:** Crashes with unknown operator error
|
|
53
|
+
|
|
54
|
+
**Environment:**
|
|
55
|
+
- postsvg 0.1.0
|
|
56
|
+
- Ruby 3.2.0
|
|
57
|
+
- macOS Sonoma 14.0
|
|
58
|
+
====
|
|
59
|
+
|
|
60
|
+
=== Request Features
|
|
61
|
+
|
|
62
|
+
Have an idea? link:https://github.com/metanorma/postsvg/issues/new[Create a feature request] with:
|
|
63
|
+
|
|
64
|
+
* **Use case** explaining why the feature is needed
|
|
65
|
+
* **Proposed solution** or implementation ideas
|
|
66
|
+
* **Alternatives considered**
|
|
67
|
+
* **Impact** on existing functionality
|
|
68
|
+
|
|
69
|
+
.Feature request template
|
|
70
|
+
[example]
|
|
71
|
+
====
|
|
72
|
+
**Title:** Add support for gradient fills
|
|
73
|
+
|
|
74
|
+
**Use Case:**
|
|
75
|
+
Many modern PostScript files use gradient fills (shfill, axial shading). Currently these are not supported.
|
|
76
|
+
|
|
77
|
+
**Proposed Solution:**
|
|
78
|
+
Implement `shfill` operator to convert PostScript gradients to SVG `<linearGradient>` and `<radialGradient>` elements.
|
|
79
|
+
|
|
80
|
+
**Alternatives:**
|
|
81
|
+
1. Rasterize gradient areas (loses vector quality)
|
|
82
|
+
2. Ignore gradients (loses visual accuracy)
|
|
83
|
+
3. Approximate with solid colors (loses aesthetic)
|
|
84
|
+
|
|
85
|
+
**Impact:**
|
|
86
|
+
New feature, no breaking changes. Would greatly improve visual accuracy for modern PS files.
|
|
87
|
+
====
|
|
88
|
+
|
|
89
|
+
=== Improve Documentation
|
|
90
|
+
|
|
91
|
+
Documentation improvements are always welcome:
|
|
92
|
+
|
|
93
|
+
* Fix typos and grammar
|
|
94
|
+
* Clarify confusing sections
|
|
95
|
+
* Add examples and use cases
|
|
96
|
+
* Improve code samples
|
|
97
|
+
* Add missing API documentation
|
|
98
|
+
|
|
99
|
+
Small fixes can be made directly via GitHub's web interface. Larger changes should follow the pull request process.
|
|
100
|
+
|
|
101
|
+
=== Contribute Code
|
|
102
|
+
|
|
103
|
+
Code contributions follow this process:
|
|
104
|
+
|
|
105
|
+
1. **Check existing issues** - Avoid duplicate work
|
|
106
|
+
2. **Discuss major changes** - Create an issue first for big changes
|
|
107
|
+
3. **Fork and branch** - Work in a feature branch
|
|
108
|
+
4. **Write tests** - All new code needs tests
|
|
109
|
+
5. **Follow style guide** - Run RuboCop
|
|
110
|
+
6. **Update documentation** - Document new features
|
|
111
|
+
7. **Submit pull request** - Request review
|
|
112
|
+
|
|
113
|
+
See link:development.adoc[Development Guide] for setup and workflow details.
|
|
114
|
+
|
|
115
|
+
== Pull Request Guidelines
|
|
116
|
+
|
|
117
|
+
=== Before Submitting
|
|
118
|
+
|
|
119
|
+
✅ **Do:**
|
|
120
|
+
* Run full test suite: `bundle exec rspec`
|
|
121
|
+
* Check code style: `bundle exec rubocop -A`
|
|
122
|
+
* Update documentation for new features
|
|
123
|
+
* Write clear commit messages
|
|
124
|
+
* Keep changes focused and atomic
|
|
125
|
+
* Add tests for new functionality
|
|
126
|
+
* Update CHANGELOG.md
|
|
127
|
+
|
|
128
|
+
❌ **Don't:**
|
|
129
|
+
* Mix unrelated changes in one PR
|
|
130
|
+
* Submit untested code
|
|
131
|
+
* Ignore RuboCop warnings
|
|
132
|
+
* Break existing tests
|
|
133
|
+
* Leave commented-out code
|
|
134
|
+
* Add dependencies without discussion
|
|
135
|
+
|
|
136
|
+
=== PR Description Template
|
|
137
|
+
|
|
138
|
+
[source,markdown]
|
|
139
|
+
----
|
|
140
|
+
## Description
|
|
141
|
+
Brief description of what this PR does.
|
|
142
|
+
|
|
143
|
+
## Motivation
|
|
144
|
+
Why is this change needed? What problem does it solve?
|
|
145
|
+
|
|
146
|
+
## Changes
|
|
147
|
+
- List of specific changes made
|
|
148
|
+
- Each as a separate bullet point
|
|
149
|
+
|
|
150
|
+
## Testing
|
|
151
|
+
How was this tested?
|
|
152
|
+
- [ ] Unit tests added/updated
|
|
153
|
+
- [ ] Integration tests pass
|
|
154
|
+
- [ ] Manual testing performed
|
|
155
|
+
|
|
156
|
+
## Related Issues
|
|
157
|
+
Closes #123
|
|
158
|
+
Relates to #456
|
|
159
|
+
|
|
160
|
+
## Checklist
|
|
161
|
+
- [ ] Tests pass locally
|
|
162
|
+
- [ ] RuboCop passes
|
|
163
|
+
- [ ] Documentation updated
|
|
164
|
+
- [ ] CHANGELOG.md updated
|
|
165
|
+
----
|
|
166
|
+
|
|
167
|
+
=== Code Review Process
|
|
168
|
+
|
|
169
|
+
1. **Automated checks** run on every PR
|
|
170
|
+
- CI tests must pass
|
|
171
|
+
- Code coverage maintained
|
|
172
|
+
- RuboCop checks pass
|
|
173
|
+
|
|
174
|
+
2. **Maintainer review**
|
|
175
|
+
- Code quality and style
|
|
176
|
+
- Test coverage
|
|
177
|
+
- Documentation completeness
|
|
178
|
+
- Architecture fit
|
|
179
|
+
|
|
180
|
+
3. **Feedback and iteration**
|
|
181
|
+
- Address review comments
|
|
182
|
+
- Update as needed
|
|
183
|
+
- Request re-review
|
|
184
|
+
|
|
185
|
+
4. **Merge**
|
|
186
|
+
- Squash and merge preferred
|
|
187
|
+
- Descriptive commit message
|
|
188
|
+
- PR automatically closed
|
|
189
|
+
|
|
190
|
+
== Code Style Guidelines
|
|
191
|
+
|
|
192
|
+
=== Ruby Style
|
|
193
|
+
|
|
194
|
+
Follow the link:https://rubystyle.guide/[Ruby Style Guide]:
|
|
195
|
+
|
|
196
|
+
[source,ruby]
|
|
197
|
+
----
|
|
198
|
+
# Good
|
|
199
|
+
def convert_file(input_path, output_path = nil)
|
|
200
|
+
ps_content = File.read(input_path)
|
|
201
|
+
svg_content = convert(ps_content)
|
|
202
|
+
File.write(output_path, svg_content) if output_path
|
|
203
|
+
svg_content
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Bad
|
|
207
|
+
def convertFile(inputPath, outputPath=nil)
|
|
208
|
+
ps_content=File.read(inputPath)
|
|
209
|
+
svg_content=convert(ps_content)
|
|
210
|
+
if outputPath
|
|
211
|
+
File.write(outputPath,svg_content)
|
|
212
|
+
end
|
|
213
|
+
return svg_content
|
|
214
|
+
end
|
|
215
|
+
----
|
|
216
|
+
|
|
217
|
+
=== Documentation Style
|
|
218
|
+
|
|
219
|
+
[source,ruby]
|
|
220
|
+
----
|
|
221
|
+
# Good
|
|
222
|
+
# Converts PostScript content to SVG format
|
|
223
|
+
#
|
|
224
|
+
# @param ps_content [String] PostScript content to convert
|
|
225
|
+
# @return [String] SVG markup
|
|
226
|
+
def convert(ps_content)
|
|
227
|
+
# ...
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Bad - no documentation
|
|
231
|
+
def convert(ps_content)
|
|
232
|
+
# ...
|
|
233
|
+
end
|
|
234
|
+
----
|
|
235
|
+
|
|
236
|
+
=== Test Style
|
|
237
|
+
|
|
238
|
+
[source,ruby]
|
|
239
|
+
----
|
|
240
|
+
# Good - descriptive and focused
|
|
241
|
+
RSpec.describe Postsvg::Converter do
|
|
242
|
+
describe '#convert' do
|
|
243
|
+
it 'converts simple rectangle to SVG' do
|
|
244
|
+
ps = "newpath 0 0 moveto 100 0 lineto stroke"
|
|
245
|
+
svg = subject.convert(ps)
|
|
246
|
+
expect(svg).to include('<path')
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Bad - unclear purpose
|
|
252
|
+
it 'works' do
|
|
253
|
+
result = subject.convert(input)
|
|
254
|
+
expect(result).to be_truthy
|
|
255
|
+
end
|
|
256
|
+
----
|
|
257
|
+
|
|
258
|
+
== Commit Message Guidelines
|
|
259
|
+
|
|
260
|
+
Use link:https://www.conventionalcommits.org/[Conventional Commits]:
|
|
261
|
+
|
|
262
|
+
[source]
|
|
263
|
+
----
|
|
264
|
+
<type>(<scope>): <subject>
|
|
265
|
+
|
|
266
|
+
[optional body]
|
|
267
|
+
|
|
268
|
+
[optional footer]
|
|
269
|
+
----
|
|
270
|
+
|
|
271
|
+
**Types:**
|
|
272
|
+
* `feat` - New feature
|
|
273
|
+
* `fix` - Bug fix
|
|
274
|
+
* `docs` - Documentation only
|
|
275
|
+
* `style` - Code style (formatting, semicolons)
|
|
276
|
+
* `refactor` - Code refactoring
|
|
277
|
+
* `test` - Adding or updating tests
|
|
278
|
+
* `chore` - Maintenance tasks
|
|
279
|
+
|
|
280
|
+
**Examples:**
|
|
281
|
+
|
|
282
|
+
[source]
|
|
283
|
+
----
|
|
284
|
+
feat(operators): add gradient fill support
|
|
285
|
+
|
|
286
|
+
Implements shfill operator for linear and radial gradients.
|
|
287
|
+
Converts PostScript shading to SVG gradient elements.
|
|
288
|
+
|
|
289
|
+
Closes #123
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
fix(converter): handle malformed BoundingBox
|
|
294
|
+
|
|
295
|
+
Previously crashed on malformed BoundingBox comments.
|
|
296
|
+
Now falls back to default dimensions with warning.
|
|
297
|
+
|
|
298
|
+
Fixes #456
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
docs(api): add examples for Matrix class
|
|
303
|
+
|
|
304
|
+
Added usage examples for all Matrix transformation methods.
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
test(interpreter): improve procedure parsing coverage
|
|
309
|
+
|
|
310
|
+
Added edge case tests for nested procedures and arrays.
|
|
311
|
+
----
|
|
312
|
+
|
|
313
|
+
## Testing Requirements
|
|
314
|
+
|
|
315
|
+
=== Required Tests
|
|
316
|
+
|
|
317
|
+
All code contributions must include tests:
|
|
318
|
+
|
|
319
|
+
**Unit Tests:**
|
|
320
|
+
[source,ruby]
|
|
321
|
+
----
|
|
322
|
+
# Test individual methods
|
|
323
|
+
RSpec.describe Postsvg::Matrix do
|
|
324
|
+
describe '#translate' do
|
|
325
|
+
it 'translates by given offsets' do
|
|
326
|
+
matrix = described_class.new
|
|
327
|
+
result = matrix.translate(10, 20)
|
|
328
|
+
|
|
329
|
+
expect(result.e).to eq(10)
|
|
330
|
+
expect(result.f).to eq(20)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
----
|
|
335
|
+
|
|
336
|
+
**Integration Tests:**
|
|
337
|
+
[source,ruby]
|
|
338
|
+
----
|
|
339
|
+
# Test full workflow
|
|
340
|
+
RSpec.describe 'PostScript conversion' do
|
|
341
|
+
it 'converts rectangle to SVG' do
|
|
342
|
+
ps_file = 'spec/fixtures/rectangle.ps'
|
|
343
|
+
svg = Postsvg.convert_file(ps_file)
|
|
344
|
+
|
|
345
|
+
expect(svg).to include('<?xml')
|
|
346
|
+
expect(svg).to include('<svg')
|
|
347
|
+
expect(svg).to include('<path')
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
----
|
|
351
|
+
|
|
352
|
+
=== Test Coverage
|
|
353
|
+
|
|
354
|
+
* Maintain >80% code coverage
|
|
355
|
+
* Cover edge cases and error conditions
|
|
356
|
+
* Test both success and failure paths
|
|
357
|
+
* Include integration tests for new features
|
|
358
|
+
|
|
359
|
+
== Documentation Requirements
|
|
360
|
+
|
|
361
|
+
=== Code Documentation
|
|
362
|
+
|
|
363
|
+
[source,ruby]
|
|
364
|
+
----
|
|
365
|
+
# Use YARD format for API documentation
|
|
366
|
+
##
|
|
367
|
+
# Converts PostScript content to SVG format.
|
|
368
|
+
#
|
|
369
|
+
# @param ps_content [String] PostScript or EPS content
|
|
370
|
+
# @return [String] SVG markup
|
|
371
|
+
# @raise [Postsvg::Error] if conversion fails
|
|
372
|
+
#
|
|
373
|
+
# @example Convert simple PostScript
|
|
374
|
+
# ps = "newpath 0 0 moveto 100 100 lineto stroke"
|
|
375
|
+
# svg = Postsvg.convert(ps)
|
|
376
|
+
#
|
|
377
|
+
def convert(ps_content)
|
|
378
|
+
# ...
|
|
379
|
+
end
|
|
380
|
+
----
|
|
381
|
+
|
|
382
|
+
=== User Documentation
|
|
383
|
+
|
|
384
|
+
When adding features:
|
|
385
|
+
|
|
386
|
+
1. Update relevant documentation files
|
|
387
|
+
2. Add examples showing usage
|
|
388
|
+
3. Document any new CLI options
|
|
389
|
+
4. Update CHANGELOG.md
|
|
390
|
+
5. Consider adding FAQ entries
|
|
391
|
+
|
|
392
|
+
== License
|
|
393
|
+
|
|
394
|
+
By contributing, you agree that your contributions will be licensed under the BSD 2-Clause License.
|
|
395
|
+
|
|
396
|
+
== Code of Conduct
|
|
397
|
+
|
|
398
|
+
### Our Standards
|
|
399
|
+
|
|
400
|
+
**Positive behaviors:**
|
|
401
|
+
* Being respectful and inclusive
|
|
402
|
+
* Accepting constructive criticism
|
|
403
|
+
* Focusing on what's best for the project
|
|
404
|
+
* Showing empathy towards others
|
|
405
|
+
|
|
406
|
+
**Unacceptable behaviors:**
|
|
407
|
+
* Harassment or discriminatory language
|
|
408
|
+
* Personal attacks or trolling
|
|
409
|
+
* Publishing private information
|
|
410
|
+
* Other unprofessional conduct
|
|
411
|
+
|
|
412
|
+
### Enforcement
|
|
413
|
+
|
|
414
|
+
Violations should be reported to project maintainers. All complaints will be reviewed and investigated promptly and fairly.
|
|
415
|
+
|
|
416
|
+
## Getting Help
|
|
417
|
+
|
|
418
|
+
**Questions about contributing?**
|
|
419
|
+
* Check link:development.adoc[Development Guide]
|
|
420
|
+
* Review link:architecture.adoc[Architecture Documentation]
|
|
421
|
+
* Ask in GitHub Discussions
|
|
422
|
+
* Comment on relevant issues
|
|
423
|
+
|
|
424
|
+
**Need help with your contribution?**
|
|
425
|
+
* Create a draft pull request early
|
|
426
|
+
* Ask for feedback in comments
|
|
427
|
+
* Tag maintainers for guidance
|
|
428
|
+
|
|
429
|
+
== Recognition
|
|
430
|
+
|
|
431
|
+
Contributors are recognized in:
|
|
432
|
+
* GitHub contributors list
|
|
433
|
+
* CHANGELOG.md for significant contributions
|
|
434
|
+
* Project documentation for major features
|
|
435
|
+
|
|
436
|
+
Thank you for making Postsvg better!
|
|
437
|
+
|
|
438
|
+
== Bibliography
|
|
439
|
+
|
|
440
|
+
* link:development.adoc[Development Guide]
|
|
441
|
+
* link:https://www.conventionalcommits.org/[Conventional Commits Specification]
|
|
442
|
+
* link:https://docs.github.com/en/pull-requests[GitHub Pull Request Documentation]
|
|
443
|
+
* link:https://rubystyle.guide/[Ruby Style Guide]
|