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.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +105 -0
  3. data/CLAUDE.md +173 -0
  4. data/Gemfile +2 -3
  5. data/README.adoc +456 -179
  6. data/Rakefile +100 -0
  7. data/TODO.roadmap/00-architecture.md +139 -0
  8. data/TODO.roadmap/01-autoload-migration.md +39 -0
  9. data/TODO.roadmap/02-isolate-dormant-code.md +51 -0
  10. data/TODO.roadmap/03-domain-model.md +66 -0
  11. data/TODO.roadmap/04-lexer.md +40 -0
  12. data/TODO.roadmap/05-parser.md +43 -0
  13. data/TODO.roadmap/06-graphics-state.md +45 -0
  14. data/TODO.roadmap/07-matrix-and-color.md +37 -0
  15. data/TODO.roadmap/08-svg-builder.md +51 -0
  16. data/TODO.roadmap/09-renderer.md +52 -0
  17. data/TODO.roadmap/10-visitor.md +58 -0
  18. data/TODO.roadmap/11-operator-coverage.md +103 -0
  19. data/TODO.roadmap/12-svg-domain.md +62 -0
  20. data/TODO.roadmap/13-translation-handlers.md +69 -0
  21. data/TODO.roadmap/14-ps-serializer.md +49 -0
  22. data/TODO.roadmap/15-cli-and-public-api.md +47 -0
  23. data/TODO.roadmap/16-specs.md +84 -0
  24. data/TODO.roadmap/17-docs-sync.md +47 -0
  25. data/TODO.roadmap/18-performance-and-determinism.md +47 -0
  26. data/TODO.roadmap/19-error-model.md +45 -0
  27. data/TODO.roadmap/20-font-and-text.md +46 -0
  28. data/TODO.roadmap/21-images.md +45 -0
  29. data/TODO.roadmap/22-forms-and-resources.md +25 -0
  30. data/TODO.roadmap/23-level2-level3.md +52 -0
  31. data/TODO.roadmap/24-ci-and-release.md +42 -0
  32. data/TODO.roadmap/README.md +77 -0
  33. data/docs/.gitignore +29 -0
  34. data/docs/CHANGELOG.md +114 -0
  35. data/docs/COMPLETE_DOCUMENTATION_STATUS.md +376 -0
  36. data/docs/DEPLOYMENT.md +456 -0
  37. data/docs/DEPLOYMENT_INSTRUCTIONS.md +229 -0
  38. data/docs/DOCUMENTATION_PLAN.md +425 -0
  39. data/docs/FINAL_SUMMARY.md +657 -0
  40. data/docs/Gemfile +15 -0
  41. data/docs/README.md +327 -0
  42. data/docs/_config.yml +99 -0
  43. data/docs/advanced-topics.adoc +370 -0
  44. data/docs/api-reference/colors.adoc +705 -0
  45. data/docs/api-reference/converter.adoc +699 -0
  46. data/docs/api-reference/execution-context.adoc +1210 -0
  47. data/docs/api-reference/graphics-state.adoc +1070 -0
  48. data/docs/api-reference/interpreter.adoc +810 -0
  49. data/docs/api-reference/matrix.adoc +1179 -0
  50. data/docs/api-reference/path-builder.adoc +1284 -0
  51. data/docs/api-reference/postsvg-module.adoc +388 -0
  52. data/docs/api-reference/svg-generator.adoc +891 -0
  53. data/docs/api-reference/tokenizer.adoc +925 -0
  54. data/docs/api-reference.adoc +221 -0
  55. data/docs/architecture/command-registry.adoc +1191 -0
  56. data/docs/architecture/conversion-pipeline.adoc +746 -0
  57. data/docs/architecture/design-decisions.adoc +999 -0
  58. data/docs/architecture/generator-stage.adoc +1115 -0
  59. data/docs/architecture/graphics-state-model.adoc +1089 -0
  60. data/docs/architecture/interpreter-stage.adoc +1125 -0
  61. data/docs/architecture/parser-stage.adoc +1051 -0
  62. data/docs/architecture.adoc +354 -0
  63. data/docs/cli-reference/batch-command.adoc +616 -0
  64. data/docs/cli-reference/check-command.adoc +677 -0
  65. data/docs/cli-reference/cli-options.adoc +802 -0
  66. data/docs/cli-reference/convert-command.adoc +462 -0
  67. data/docs/cli-reference/version-command.adoc +296 -0
  68. data/docs/cli-reference.adoc +317 -0
  69. data/docs/concepts/conversion-pipeline.adoc +903 -0
  70. data/docs/concepts/coordinate-systems.adoc +836 -0
  71. data/docs/concepts/graphics-state.adoc +861 -0
  72. data/docs/concepts/path-operations.adoc +1076 -0
  73. data/docs/concepts/postscript-language.adoc +859 -0
  74. data/docs/concepts/svg-generation.adoc +937 -0
  75. data/docs/concepts.adoc +198 -0
  76. data/docs/contributing.adoc +443 -0
  77. data/docs/development.adoc +420 -0
  78. data/docs/faq.adoc +493 -0
  79. data/docs/getting-started/basic-usage.adoc +538 -0
  80. data/docs/getting-started/common-workflows.adoc +577 -0
  81. data/docs/getting-started/first-conversion.adoc +492 -0
  82. data/docs/getting-started/installation.adoc +534 -0
  83. data/docs/getting-started.adoc +94 -0
  84. data/docs/index.adoc +248 -0
  85. data/docs/optimization.adoc +196 -0
  86. data/docs/ps2svg_compatibility.adoc +149 -0
  87. data/docs/quick-reference.adoc +453 -0
  88. data/docs/sitemap.adoc +337 -0
  89. data/docs/troubleshooting.adoc +486 -0
  90. data/docs/validation.adoc +772 -0
  91. data/exe/postsvg +1 -0
  92. data/lib/postsvg/cli.rb +104 -57
  93. data/lib/postsvg/color.rb +132 -0
  94. data/lib/postsvg/errors.rb +68 -3
  95. data/lib/postsvg/format_number.rb +22 -0
  96. data/lib/postsvg/graphics_context.rb +80 -0
  97. data/lib/postsvg/graphics_stack.rb +43 -0
  98. data/lib/postsvg/model/literals/array.rb +41 -0
  99. data/lib/postsvg/model/literals/dictionary.rb +34 -0
  100. data/lib/postsvg/model/literals/hex.rb +37 -0
  101. data/lib/postsvg/model/literals/name.rb +40 -0
  102. data/lib/postsvg/model/literals/number.rb +36 -0
  103. data/lib/postsvg/model/literals/procedure.rb +41 -0
  104. data/lib/postsvg/model/literals/string.rb +30 -0
  105. data/lib/postsvg/model/literals.rb +19 -0
  106. data/lib/postsvg/model/operator.rb +58 -0
  107. data/lib/postsvg/model/operators/arithmetic.rb +264 -0
  108. data/lib/postsvg/model/operators/boolean.rb +182 -0
  109. data/lib/postsvg/model/operators/color.rb +74 -0
  110. data/lib/postsvg/model/operators/container.rb +186 -0
  111. data/lib/postsvg/model/operators/control_flow.rb +119 -0
  112. data/lib/postsvg/model/operators/device.rb +21 -0
  113. data/lib/postsvg/model/operators/dictionary.rb +118 -0
  114. data/lib/postsvg/model/operators/font.rb +121 -0
  115. data/lib/postsvg/model/operators/graphics_state.rb +84 -0
  116. data/lib/postsvg/model/operators/painting.rb +29 -0
  117. data/lib/postsvg/model/operators/path.rb +169 -0
  118. data/lib/postsvg/model/operators/stack.rb +72 -0
  119. data/lib/postsvg/model/operators/transformations.rb +103 -0
  120. data/lib/postsvg/model/operators.rb +89 -0
  121. data/lib/postsvg/model/program.rb +68 -0
  122. data/lib/postsvg/model/token.rb +43 -0
  123. data/lib/postsvg/model.rb +17 -0
  124. data/lib/postsvg/options.rb +29 -0
  125. data/lib/postsvg/renderer.rb +85 -0
  126. data/lib/postsvg/serializer.rb +325 -0
  127. data/lib/postsvg/source/ast_builder.rb +308 -0
  128. data/lib/postsvg/source/lexer.rb +322 -0
  129. data/lib/postsvg/source/operand_stack.rb +55 -0
  130. data/lib/postsvg/source.rb +21 -0
  131. data/lib/postsvg/svg/attribute_parser.rb +45 -0
  132. data/lib/postsvg/svg/clip_path_registry.rb +44 -0
  133. data/lib/postsvg/svg/document.rb +22 -0
  134. data/lib/postsvg/svg/element.rb +84 -0
  135. data/lib/postsvg/svg/elements/circle.rb +36 -0
  136. data/lib/postsvg/svg/elements/clip_path.rb +26 -0
  137. data/lib/postsvg/svg/elements/defs.rb +24 -0
  138. data/lib/postsvg/svg/elements/ellipse.rb +38 -0
  139. data/lib/postsvg/svg/elements/group.rb +37 -0
  140. data/lib/postsvg/svg/elements/image.rb +35 -0
  141. data/lib/postsvg/svg/elements/line.rb +36 -0
  142. data/lib/postsvg/svg/elements/path.rb +32 -0
  143. data/lib/postsvg/svg/elements/polygon.rb +12 -0
  144. data/lib/postsvg/svg/elements/polyline.rb +32 -0
  145. data/lib/postsvg/svg/elements/rect.rb +44 -0
  146. data/lib/postsvg/svg/elements/svg.rb +39 -0
  147. data/lib/postsvg/svg/elements/text.rb +42 -0
  148. data/lib/postsvg/svg/elements.rb +31 -0
  149. data/lib/postsvg/svg/paint.rb +34 -0
  150. data/lib/postsvg/svg/parser.rb +39 -0
  151. data/lib/postsvg/svg/path_data/command.rb +27 -0
  152. data/lib/postsvg/svg/path_data/parser.rb +82 -0
  153. data/lib/postsvg/svg/path_data.rb +17 -0
  154. data/lib/postsvg/svg/stroke.rb +31 -0
  155. data/lib/postsvg/svg/transform_list.rb +59 -0
  156. data/lib/postsvg/svg.rb +22 -0
  157. data/lib/postsvg/svg_builder.rb +249 -0
  158. data/lib/postsvg/translation/arc_converter.rb +86 -0
  159. data/lib/postsvg/translation/bounding_box.rb +59 -0
  160. data/lib/postsvg/translation/context.rb +34 -0
  161. data/lib/postsvg/translation/handler_registry.rb +38 -0
  162. data/lib/postsvg/translation/handlers/circle_handler.rb +28 -0
  163. data/lib/postsvg/translation/handlers/clip_path_handler.rb +13 -0
  164. data/lib/postsvg/translation/handlers/defs_handler.rb +15 -0
  165. data/lib/postsvg/translation/handlers/ellipse_handler.rb +31 -0
  166. data/lib/postsvg/translation/handlers/group_handler.rb +21 -0
  167. data/lib/postsvg/translation/handlers/image_handler.rb +20 -0
  168. data/lib/postsvg/translation/handlers/line_handler.rb +23 -0
  169. data/lib/postsvg/translation/handlers/open_handler.rb +18 -0
  170. data/lib/postsvg/translation/handlers/path_handler.rb +356 -0
  171. data/lib/postsvg/translation/handlers/polygon_handler.rb +33 -0
  172. data/lib/postsvg/translation/handlers/polyline_handler.rb +31 -0
  173. data/lib/postsvg/translation/handlers/rect_handler.rb +27 -0
  174. data/lib/postsvg/translation/handlers/shared.rb +110 -0
  175. data/lib/postsvg/translation/handlers/svg_handler.rb +25 -0
  176. data/lib/postsvg/translation/handlers/text_handler.rb +56 -0
  177. data/lib/postsvg/translation/handlers.rb +25 -0
  178. data/lib/postsvg/translation/ps_renderer.rb +105 -0
  179. data/lib/postsvg/translation/record_emitter.rb +35 -0
  180. data/lib/postsvg/translation.rb +17 -0
  181. data/lib/postsvg/version.rb +1 -1
  182. data/lib/postsvg/visitors/ps_visitor/arithmetic.rb +125 -0
  183. data/lib/postsvg/visitors/ps_visitor/boolean.rb +105 -0
  184. data/lib/postsvg/visitors/ps_visitor/color.rb +53 -0
  185. data/lib/postsvg/visitors/ps_visitor/common.rb +66 -0
  186. data/lib/postsvg/visitors/ps_visitor/container.rb +164 -0
  187. data/lib/postsvg/visitors/ps_visitor/control_flow.rb +110 -0
  188. data/lib/postsvg/visitors/ps_visitor/device.rb +20 -0
  189. data/lib/postsvg/visitors/ps_visitor/dictionary.rb +89 -0
  190. data/lib/postsvg/visitors/ps_visitor/font.rb +93 -0
  191. data/lib/postsvg/visitors/ps_visitor/graphics_state.rb +55 -0
  192. data/lib/postsvg/visitors/ps_visitor/painting.rb +90 -0
  193. data/lib/postsvg/visitors/ps_visitor/path.rb +112 -0
  194. data/lib/postsvg/visitors/ps_visitor/stack.rb +47 -0
  195. data/lib/postsvg/visitors/ps_visitor/transformations.rb +101 -0
  196. data/lib/postsvg/visitors/ps_visitor.rb +208 -0
  197. data/lib/postsvg/visitors.rb +9 -0
  198. data/lib/postsvg.rb +93 -59
  199. data/lychee.toml +86 -0
  200. metadata +216 -11
  201. data/postsvg.gemspec +0 -38
@@ -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]