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
|
@@ -0,0 +1,772 @@
|
|
|
1
|
+
= PostSVG Validation Guide
|
|
2
|
+
:toc: left
|
|
3
|
+
:toclevels: 3
|
|
4
|
+
:sectnums:
|
|
5
|
+
|
|
6
|
+
== Introduction
|
|
7
|
+
|
|
8
|
+
PostSVG includes a comprehensive validation tool for PostScript and EPS files. The validator helps identify syntax errors, semantic issues, and structural problems before attempting conversion to SVG.
|
|
9
|
+
|
|
10
|
+
== Quick Start
|
|
11
|
+
|
|
12
|
+
=== Basic Usage
|
|
13
|
+
|
|
14
|
+
Validate a single file:
|
|
15
|
+
|
|
16
|
+
[source,shell]
|
|
17
|
+
----
|
|
18
|
+
postsvg check document.ps
|
|
19
|
+
----
|
|
20
|
+
|
|
21
|
+
Validate multiple files:
|
|
22
|
+
|
|
23
|
+
[source,shell]
|
|
24
|
+
----
|
|
25
|
+
postsvg check file1.ps file2.eps file3.ps
|
|
26
|
+
----
|
|
27
|
+
|
|
28
|
+
Validate all PostScript files in directory:
|
|
29
|
+
|
|
30
|
+
[source,shell]
|
|
31
|
+
----
|
|
32
|
+
postsvg check *.ps
|
|
33
|
+
----
|
|
34
|
+
|
|
35
|
+
== Validation Levels
|
|
36
|
+
|
|
37
|
+
PostSVG provides three validation levels, each building on the previous:
|
|
38
|
+
|
|
39
|
+
=== Syntax Level (Fast)
|
|
40
|
+
|
|
41
|
+
The syntax level performs basic structural checks without executing PostScript code.
|
|
42
|
+
|
|
43
|
+
*Checks performed:*
|
|
44
|
+
|
|
45
|
+
* Header format validation (PS vs EPS)
|
|
46
|
+
* BoundingBox validation for EPS files
|
|
47
|
+
* Delimiter balance (parentheses, brackets, braces)
|
|
48
|
+
* Basic tokenization
|
|
49
|
+
* EOF marker presence
|
|
50
|
+
|
|
51
|
+
*Usage:*
|
|
52
|
+
|
|
53
|
+
[source,shell]
|
|
54
|
+
----
|
|
55
|
+
postsvg check --level=syntax file.ps
|
|
56
|
+
----
|
|
57
|
+
|
|
58
|
+
*When to use:*
|
|
59
|
+
|
|
60
|
+
* Quick validation of many files
|
|
61
|
+
* Pre-processing check before batch conversion
|
|
62
|
+
* CI/CD pipeline early validation
|
|
63
|
+
* Syntax-only linting
|
|
64
|
+
|
|
65
|
+
=== Semantic Level (Default)
|
|
66
|
+
|
|
67
|
+
The semantic level adds PostScript operator analysis without full conversion.
|
|
68
|
+
|
|
69
|
+
*Checks performed:*
|
|
70
|
+
|
|
71
|
+
* All syntax checks
|
|
72
|
+
* Stack balance simulation
|
|
73
|
+
* Graphics state tracking (gsave/grestore pairs)
|
|
74
|
+
* Dictionary tracking (dict begin/end pairs)
|
|
75
|
+
* Operator coverage checking
|
|
76
|
+
|
|
77
|
+
*Usage:*
|
|
78
|
+
|
|
79
|
+
[source,shell]
|
|
80
|
+
----
|
|
81
|
+
postsvg check file.ps
|
|
82
|
+
postsvg check --level=semantic file.ps
|
|
83
|
+
----
|
|
84
|
+
|
|
85
|
+
*When to use:*
|
|
86
|
+
|
|
87
|
+
* Default validation for most use cases
|
|
88
|
+
* Detecting logical errors before conversion
|
|
89
|
+
* Ensuring PostScript semantic correctness
|
|
90
|
+
|
|
91
|
+
=== Full Level (Strict)
|
|
92
|
+
|
|
93
|
+
The full level performs complete conversion attempt for strictest validation.
|
|
94
|
+
|
|
95
|
+
*Checks performed:*
|
|
96
|
+
|
|
97
|
+
* All semantic checks
|
|
98
|
+
* Complete PostScript interpretation
|
|
99
|
+
* Full conversion to SVG
|
|
100
|
+
* All PostScript operator execution
|
|
101
|
+
|
|
102
|
+
*Usage:*
|
|
103
|
+
|
|
104
|
+
[source,shell]
|
|
105
|
+
----
|
|
106
|
+
postsvg check --level=full file.ps
|
|
107
|
+
----
|
|
108
|
+
|
|
109
|
+
*When to use:*
|
|
110
|
+
|
|
111
|
+
* Final validation before production
|
|
112
|
+
* Testing conversion compatibility
|
|
113
|
+
* Debugging complex PostScript files
|
|
114
|
+
|
|
115
|
+
== Output Formats
|
|
116
|
+
|
|
117
|
+
=== Text Format (Default)
|
|
118
|
+
|
|
119
|
+
Human-readable colorized output with visual indicators.
|
|
120
|
+
|
|
121
|
+
*Usage:*
|
|
122
|
+
|
|
123
|
+
[source,shell]
|
|
124
|
+
----
|
|
125
|
+
postsvg check file.ps
|
|
126
|
+
----
|
|
127
|
+
|
|
128
|
+
*Example output:*
|
|
129
|
+
|
|
130
|
+
[source,text]
|
|
131
|
+
----
|
|
132
|
+
✓ file.ps is valid
|
|
133
|
+
|
|
134
|
+
✗ broken.ps has errors:
|
|
135
|
+
ERROR: Unclosed string literal at line 5
|
|
136
|
+
ERROR: Stack underflow at line 10
|
|
137
|
+
WARNING: Unmatched gsave at line 15
|
|
138
|
+
----
|
|
139
|
+
|
|
140
|
+
*Options:*
|
|
141
|
+
|
|
142
|
+
* `--verbose`: Show warnings and info messages
|
|
143
|
+
* `--quiet`: Suppress valid file messages
|
|
144
|
+
* `--no-color`: Disable colored output
|
|
145
|
+
|
|
146
|
+
=== YAML Format
|
|
147
|
+
|
|
148
|
+
Structured output suitable for parsing and automation.
|
|
149
|
+
|
|
150
|
+
*Usage:*
|
|
151
|
+
|
|
152
|
+
[source,shell]
|
|
153
|
+
----
|
|
154
|
+
postsvg check --format=yaml file.ps
|
|
155
|
+
----
|
|
156
|
+
|
|
157
|
+
*Example output:*
|
|
158
|
+
|
|
159
|
+
[source,yaml]
|
|
160
|
+
----
|
|
161
|
+
file.ps:
|
|
162
|
+
valid: true
|
|
163
|
+
errors: []
|
|
164
|
+
warnings: []
|
|
165
|
+
info: []
|
|
166
|
+
|
|
167
|
+
broken.ps:
|
|
168
|
+
valid: false
|
|
169
|
+
errors:
|
|
170
|
+
- "Unclosed string literal at line 5"
|
|
171
|
+
- "Stack underflow at line 10"
|
|
172
|
+
warnings:
|
|
173
|
+
- "Unmatched gsave at line 15"
|
|
174
|
+
info: []
|
|
175
|
+
----
|
|
176
|
+
|
|
177
|
+
=== JSON Format
|
|
178
|
+
|
|
179
|
+
Machine-readable JSON output for integration with other tools.
|
|
180
|
+
|
|
181
|
+
*Usage:*
|
|
182
|
+
|
|
183
|
+
[source,shell]
|
|
184
|
+
----
|
|
185
|
+
postsvg check --format=json file.ps
|
|
186
|
+
----
|
|
187
|
+
|
|
188
|
+
*Example output:*
|
|
189
|
+
|
|
190
|
+
[source,json]
|
|
191
|
+
----
|
|
192
|
+
{
|
|
193
|
+
"file.ps": {
|
|
194
|
+
"valid": true,
|
|
195
|
+
"errors": [],
|
|
196
|
+
"warnings": [],
|
|
197
|
+
"info": []
|
|
198
|
+
},
|
|
199
|
+
"broken.ps": {
|
|
200
|
+
"valid": false,
|
|
201
|
+
"errors": [
|
|
202
|
+
"Unclosed string literal at line 5",
|
|
203
|
+
"Stack underflow at line 10"
|
|
204
|
+
],
|
|
205
|
+
"warnings": [
|
|
206
|
+
"Unmatched gsave at line 15"
|
|
207
|
+
],
|
|
208
|
+
"info": []
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
----
|
|
212
|
+
|
|
213
|
+
== Validation Options
|
|
214
|
+
|
|
215
|
+
=== Verbose Mode
|
|
216
|
+
|
|
217
|
+
Display all messages including warnings and informational messages.
|
|
218
|
+
|
|
219
|
+
[source,shell]
|
|
220
|
+
----
|
|
221
|
+
postsvg check --verbose file.ps
|
|
222
|
+
----
|
|
223
|
+
|
|
224
|
+
*Shows:*
|
|
225
|
+
|
|
226
|
+
* All errors
|
|
227
|
+
* All warnings
|
|
228
|
+
* All informational messages
|
|
229
|
+
* Operator coverage information
|
|
230
|
+
|
|
231
|
+
=== Quiet Mode
|
|
232
|
+
|
|
233
|
+
Suppress messages for valid files, only show errors.
|
|
234
|
+
|
|
235
|
+
[source,shell]
|
|
236
|
+
----
|
|
237
|
+
postsvg check --quiet *.ps
|
|
238
|
+
----
|
|
239
|
+
|
|
240
|
+
*Use cases:*
|
|
241
|
+
|
|
242
|
+
* Batch validation of many files
|
|
243
|
+
* Focus on problematic files only
|
|
244
|
+
* Cleaner CI/CD output
|
|
245
|
+
|
|
246
|
+
=== Fail-Fast Mode
|
|
247
|
+
|
|
248
|
+
Stop validation at the first error encountered.
|
|
249
|
+
|
|
250
|
+
[source,shell]
|
|
251
|
+
----
|
|
252
|
+
postsvg check --fail-fast file1.ps file2.ps file3.ps
|
|
253
|
+
----
|
|
254
|
+
|
|
255
|
+
*Behavior:*
|
|
256
|
+
|
|
257
|
+
* Processes files in order
|
|
258
|
+
* Stops immediately when error found
|
|
259
|
+
* Returns exit code 1
|
|
260
|
+
* Useful for rapid error detection
|
|
261
|
+
|
|
262
|
+
=== Color Control
|
|
263
|
+
|
|
264
|
+
Disable colored output for log files or non-terminal environments.
|
|
265
|
+
|
|
266
|
+
[source,shell]
|
|
267
|
+
----
|
|
268
|
+
postsvg check --no-color file.ps > validation.log
|
|
269
|
+
----
|
|
270
|
+
|
|
271
|
+
=== EPS Version Validation
|
|
272
|
+
|
|
273
|
+
Validate EPS version compliance for specific PostScript levels.
|
|
274
|
+
|
|
275
|
+
[source,shell]
|
|
276
|
+
----
|
|
277
|
+
postsvg check --eps-version=3.0 diagram.eps
|
|
278
|
+
----
|
|
279
|
+
|
|
280
|
+
*Supported versions:*
|
|
281
|
+
|
|
282
|
+
* 1.0 - Basic EPS
|
|
283
|
+
* 2.0 - Level 2 PostScript
|
|
284
|
+
* 3.0 - Level 3 PostScript
|
|
285
|
+
|
|
286
|
+
== Common Validation Errors
|
|
287
|
+
|
|
288
|
+
=== Delimiter Imbalance
|
|
289
|
+
|
|
290
|
+
*Error:* `Unclosed string literal`
|
|
291
|
+
|
|
292
|
+
*Cause:* Missing closing parenthesis in string.
|
|
293
|
+
|
|
294
|
+
*Example:*
|
|
295
|
+
|
|
296
|
+
[source,postscript]
|
|
297
|
+
----
|
|
298
|
+
(Hello World % Missing )
|
|
299
|
+
----
|
|
300
|
+
|
|
301
|
+
*Fix:*
|
|
302
|
+
|
|
303
|
+
[source,postscript]
|
|
304
|
+
----
|
|
305
|
+
(Hello World)
|
|
306
|
+
----
|
|
307
|
+
|
|
308
|
+
=== Stack Underflow
|
|
309
|
+
|
|
310
|
+
*Error:* `Stack underflow`
|
|
311
|
+
|
|
312
|
+
*Cause:* Operator requires more values than available on stack.
|
|
313
|
+
|
|
314
|
+
*Example:*
|
|
315
|
+
|
|
316
|
+
[source,postscript]
|
|
317
|
+
----
|
|
318
|
+
pop % Stack is empty
|
|
319
|
+
----
|
|
320
|
+
|
|
321
|
+
*Fix:*
|
|
322
|
+
|
|
323
|
+
[source,postscript]
|
|
324
|
+
----
|
|
325
|
+
5 pop % Push value before popping
|
|
326
|
+
----
|
|
327
|
+
|
|
328
|
+
=== Unmatched Graphics State
|
|
329
|
+
|
|
330
|
+
*Warning:* `Unmatched gsave/grestore`
|
|
331
|
+
|
|
332
|
+
*Cause:* Missing grestore for gsave operation.
|
|
333
|
+
|
|
334
|
+
*Example:*
|
|
335
|
+
|
|
336
|
+
[source,postscript]
|
|
337
|
+
----
|
|
338
|
+
gsave
|
|
339
|
+
1 0 0 setrgbcolor
|
|
340
|
+
100 100 moveto
|
|
341
|
+
% Missing grestore
|
|
342
|
+
----
|
|
343
|
+
|
|
344
|
+
*Fix:*
|
|
345
|
+
|
|
346
|
+
[source,postscript]
|
|
347
|
+
----
|
|
348
|
+
gsave
|
|
349
|
+
1 0 0 setrgbcolor
|
|
350
|
+
100 100 moveto
|
|
351
|
+
grestore
|
|
352
|
+
----
|
|
353
|
+
|
|
354
|
+
=== Missing BoundingBox
|
|
355
|
+
|
|
356
|
+
*Error:* `EPS file missing required BoundingBox comment`
|
|
357
|
+
|
|
358
|
+
*Cause:* EPS file lacks required `%%BoundingBox` header.
|
|
359
|
+
|
|
360
|
+
*Example:*
|
|
361
|
+
|
|
362
|
+
[source,postscript]
|
|
363
|
+
----
|
|
364
|
+
%!PS-Adobe-3.0 EPSF-3.0
|
|
365
|
+
% Missing %%BoundingBox
|
|
366
|
+
----
|
|
367
|
+
|
|
368
|
+
*Fix:*
|
|
369
|
+
|
|
370
|
+
[source,postscript]
|
|
371
|
+
----
|
|
372
|
+
%!PS-Adobe-3.0 EPSF-3.0
|
|
373
|
+
%%BoundingBox: 0 0 612 792
|
|
374
|
+
----
|
|
375
|
+
|
|
376
|
+
=== Dictionary Imbalance
|
|
377
|
+
|
|
378
|
+
*Warning:* `Unmatched dict begin/end`
|
|
379
|
+
|
|
380
|
+
*Cause:* Dictionary started but not ended, or vice versa.
|
|
381
|
+
|
|
382
|
+
*Example:*
|
|
383
|
+
|
|
384
|
+
[source,postscript]
|
|
385
|
+
----
|
|
386
|
+
10 dict begin
|
|
387
|
+
/key1 value1 def
|
|
388
|
+
% Missing end
|
|
389
|
+
----
|
|
390
|
+
|
|
391
|
+
*Fix:*
|
|
392
|
+
|
|
393
|
+
[source,postscript]
|
|
394
|
+
----
|
|
395
|
+
10 dict begin
|
|
396
|
+
/key1 value1 def
|
|
397
|
+
end
|
|
398
|
+
----
|
|
399
|
+
|
|
400
|
+
== Exit Codes
|
|
401
|
+
|
|
402
|
+
PostSVG validation returns standard exit codes for CI/CD integration:
|
|
403
|
+
|
|
404
|
+
* `0` - All files valid, no errors
|
|
405
|
+
* `1` - One or more files have errors
|
|
406
|
+
|
|
407
|
+
=== CI/CD Integration
|
|
408
|
+
|
|
409
|
+
==== GitHub Actions
|
|
410
|
+
|
|
411
|
+
[source,yaml]
|
|
412
|
+
----
|
|
413
|
+
name: Validate PostScript Files
|
|
414
|
+
on: [push, pull_request]
|
|
415
|
+
|
|
416
|
+
jobs:
|
|
417
|
+
validate:
|
|
418
|
+
runs-on: ubuntu-latest
|
|
419
|
+
steps:
|
|
420
|
+
- uses: actions/checkout@v3
|
|
421
|
+
- uses: ruby/setup-ruby@v1
|
|
422
|
+
with:
|
|
423
|
+
ruby-version: '3.2'
|
|
424
|
+
- run: gem install postsvg
|
|
425
|
+
- run: postsvg check --fail-fast --format=json *.ps
|
|
426
|
+
----
|
|
427
|
+
|
|
428
|
+
==== GitLab CI
|
|
429
|
+
|
|
430
|
+
[source,yaml]
|
|
431
|
+
----
|
|
432
|
+
validate:
|
|
433
|
+
image: ruby:3.2
|
|
434
|
+
script:
|
|
435
|
+
- gem install postsvg
|
|
436
|
+
- postsvg check --format=yaml --no-color *.ps
|
|
437
|
+
artifacts:
|
|
438
|
+
reports:
|
|
439
|
+
junit: validation-report.xml
|
|
440
|
+
----
|
|
441
|
+
|
|
442
|
+
==== Jenkins
|
|
443
|
+
|
|
444
|
+
[source,groovy]
|
|
445
|
+
----
|
|
446
|
+
stage('Validate PostScript') {
|
|
447
|
+
steps {
|
|
448
|
+
sh 'gem install postsvg'
|
|
449
|
+
sh 'postsvg check --fail-fast *.ps'
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
----
|
|
453
|
+
|
|
454
|
+
== Advanced Usage
|
|
455
|
+
|
|
456
|
+
=== Batch Processing
|
|
457
|
+
|
|
458
|
+
Validate all PostScript files in directory tree:
|
|
459
|
+
|
|
460
|
+
[source,shell]
|
|
461
|
+
----
|
|
462
|
+
find . -name "*.ps" -exec postsvg check --quiet {} \;
|
|
463
|
+
----
|
|
464
|
+
|
|
465
|
+
Generate validation report:
|
|
466
|
+
|
|
467
|
+
[source,shell]
|
|
468
|
+
----
|
|
469
|
+
postsvg check --format=json *.ps > validation-report.json
|
|
470
|
+
----
|
|
471
|
+
|
|
472
|
+
=== Pre-commit Hook
|
|
473
|
+
|
|
474
|
+
Add validation to Git pre-commit hook:
|
|
475
|
+
|
|
476
|
+
[source,shell]
|
|
477
|
+
----
|
|
478
|
+
#!/bin/sh
|
|
479
|
+
# .git/hooks/pre-commit
|
|
480
|
+
|
|
481
|
+
# Get list of PostScript files being committed
|
|
482
|
+
PS_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.ps$')
|
|
483
|
+
|
|
484
|
+
if [ -n "$PS_FILES" ]; then
|
|
485
|
+
echo "Validating PostScript files..."
|
|
486
|
+
for file in $PS_FILES; do
|
|
487
|
+
postsvg check --fail-fast "$file" || exit 1
|
|
488
|
+
done
|
|
489
|
+
fi
|
|
490
|
+
----
|
|
491
|
+
|
|
492
|
+
=== Automated Testing
|
|
493
|
+
|
|
494
|
+
Use validation in RSpec tests:
|
|
495
|
+
|
|
496
|
+
[source,ruby]
|
|
497
|
+
----
|
|
498
|
+
require 'postsvg'
|
|
499
|
+
|
|
500
|
+
RSpec.describe "PostScript Files" do
|
|
501
|
+
Dir.glob("spec/fixtures/**/*.ps").each do |file|
|
|
502
|
+
it "#{file} is valid" do
|
|
503
|
+
result = `postsvg check --format=json #{file}`
|
|
504
|
+
data = JSON.parse(result)
|
|
505
|
+
expect(data.dig(file, "valid")).to be true
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
----
|
|
510
|
+
|
|
511
|
+
== Best Practices
|
|
512
|
+
|
|
513
|
+
=== Development Workflow
|
|
514
|
+
|
|
515
|
+
. Use syntax level during development for quick feedback
|
|
516
|
+
. Use semantic level before committing changes
|
|
517
|
+
. Use full level before production deployment
|
|
518
|
+
|
|
519
|
+
=== File Organization
|
|
520
|
+
|
|
521
|
+
. Keep test fixtures in `spec/fixtures/validation/`
|
|
522
|
+
. Organize by valid/invalid categories
|
|
523
|
+
. Use descriptive filenames indicating error type
|
|
524
|
+
|
|
525
|
+
=== Documentation
|
|
526
|
+
|
|
527
|
+
. Document expected validation results in fixtures
|
|
528
|
+
. Include validation level requirements in README
|
|
529
|
+
. Add validation examples to user documentation
|
|
530
|
+
|
|
531
|
+
=== Performance
|
|
532
|
+
|
|
533
|
+
. Use syntax level for large batch operations
|
|
534
|
+
. Enable fail-fast for quick error detection
|
|
535
|
+
. Use quiet mode for cleaner output in automation
|
|
536
|
+
|
|
537
|
+
== Troubleshooting
|
|
538
|
+
|
|
539
|
+
=== Validator Returns False Positives
|
|
540
|
+
|
|
541
|
+
*Issue:* Valid PostScript reported as invalid.
|
|
542
|
+
|
|
543
|
+
*Solutions:*
|
|
544
|
+
|
|
545
|
+
. Check PostScript version compatibility
|
|
546
|
+
. Verify operator support in PostSVG
|
|
547
|
+
. Use `--verbose` to see detailed messages
|
|
548
|
+
. Test with `--level=syntax` to isolate issue
|
|
549
|
+
|
|
550
|
+
=== Validator Misses Errors
|
|
551
|
+
|
|
552
|
+
*Issue:* Invalid PostScript reported as valid.
|
|
553
|
+
|
|
554
|
+
*Solutions:*
|
|
555
|
+
|
|
556
|
+
. Use higher validation level (`--level=full`)
|
|
557
|
+
. Enable verbose mode to see warnings
|
|
558
|
+
. Check if error is semantic vs syntactic
|
|
559
|
+
. Report issue with sample file
|
|
560
|
+
|
|
561
|
+
=== Performance Issues
|
|
562
|
+
|
|
563
|
+
*Issue:* Validation is slow for large files.
|
|
564
|
+
|
|
565
|
+
*Solutions:*
|
|
566
|
+
|
|
567
|
+
. Use `--level=syntax` for initial checks
|
|
568
|
+
. Enable `--fail-fast` for quicker failure
|
|
569
|
+
. Process files in parallel using shell tools
|
|
570
|
+
. Consider file size and complexity
|
|
571
|
+
|
|
572
|
+
== API Usage
|
|
573
|
+
|
|
574
|
+
=== Ruby API
|
|
575
|
+
|
|
576
|
+
Use validation programmatically in Ruby:
|
|
577
|
+
|
|
578
|
+
[source,ruby]
|
|
579
|
+
----
|
|
580
|
+
require 'postsvg'
|
|
581
|
+
|
|
582
|
+
# Validate a file
|
|
583
|
+
service = Postsvg::ValidationService.new(
|
|
584
|
+
level: :semantic,
|
|
585
|
+
fail_fast: false,
|
|
586
|
+
verbose: false
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
result = service.validate_file('document.ps')
|
|
590
|
+
|
|
591
|
+
if result.valid?
|
|
592
|
+
puts "File is valid"
|
|
593
|
+
else
|
|
594
|
+
puts "Errors:"
|
|
595
|
+
result.error_messages.each { |msg| puts " #{msg}" }
|
|
596
|
+
end
|
|
597
|
+
----
|
|
598
|
+
|
|
599
|
+
=== Validation Result Object
|
|
600
|
+
|
|
601
|
+
[source,ruby]
|
|
602
|
+
----
|
|
603
|
+
# Access validation details
|
|
604
|
+
result.valid? # => true/false
|
|
605
|
+
result.error_count # => Integer
|
|
606
|
+
result.warning_count # => Integer
|
|
607
|
+
result.info_count # => Integer
|
|
608
|
+
|
|
609
|
+
result.error_messages # => Array of error strings
|
|
610
|
+
result.warning_messages # => Array of warning strings
|
|
611
|
+
result.info_messages # => Array of info strings
|
|
612
|
+
|
|
613
|
+
result.all_messages # => Hash with all messages by severity
|
|
614
|
+
----
|
|
615
|
+
|
|
616
|
+
=== Custom Reporters
|
|
617
|
+
|
|
618
|
+
Create custom reporter for specific output format:
|
|
619
|
+
|
|
620
|
+
[source,ruby]
|
|
621
|
+
----
|
|
622
|
+
class CustomReporter
|
|
623
|
+
def report(results)
|
|
624
|
+
# results is Hash of filename => ValidationResult
|
|
625
|
+
results.each do |file, result|
|
|
626
|
+
# Custom formatting logic
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
# Use custom reporter
|
|
632
|
+
reporter = CustomReporter.new
|
|
633
|
+
reporter.report(validation_results)
|
|
634
|
+
----
|
|
635
|
+
|
|
636
|
+
== Architecture
|
|
637
|
+
|
|
638
|
+
=== Component Diagram
|
|
639
|
+
|
|
640
|
+
[source]
|
|
641
|
+
----
|
|
642
|
+
┌─────────────────────────────────────────────────────────┐
|
|
643
|
+
│ CLI Command │
|
|
644
|
+
│ (check command) │
|
|
645
|
+
└───────────────────────┬─────────────────────────────────┘
|
|
646
|
+
│
|
|
647
|
+
▼
|
|
648
|
+
┌─────────────────────────────────────────────────────────┐
|
|
649
|
+
│ ValidationService │
|
|
650
|
+
│ • Orchestrates validation process │
|
|
651
|
+
│ • Manages validation levels │
|
|
652
|
+
│ • Implements fail-fast logic │
|
|
653
|
+
└───────────────────────┬─────────────────────────────────┘
|
|
654
|
+
│
|
|
655
|
+
┌───────────────┼───────────────┐
|
|
656
|
+
▼ ▼ ▼
|
|
657
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
658
|
+
│ Syntax │ │ Semantic │ │ Full │
|
|
659
|
+
│ Validator │ │ Validator │ │ Validator │
|
|
660
|
+
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
|
661
|
+
│ │ │
|
|
662
|
+
│ │ │
|
|
663
|
+
└───────────────┴───────────────┘
|
|
664
|
+
│
|
|
665
|
+
▼
|
|
666
|
+
┌──────────────────────┐
|
|
667
|
+
│ ValidationResult │
|
|
668
|
+
│ • Errors │
|
|
669
|
+
│ • Warnings │
|
|
670
|
+
│ • Info messages │
|
|
671
|
+
└──────────┬───────────┘
|
|
672
|
+
│
|
|
673
|
+
┌───────────────┼───────────────┐
|
|
674
|
+
▼ ▼ ▼
|
|
675
|
+
┌───────────┐ ┌──────────────┐ ┌──────────────┐
|
|
676
|
+
│ Text │ │ YAML │ │ JSON │
|
|
677
|
+
│ Reporter │ │ Reporter │ │ Reporter │
|
|
678
|
+
└───────────┘ └──────────────┘ └──────────────┘
|
|
679
|
+
----
|
|
680
|
+
|
|
681
|
+
=== Validator Classes
|
|
682
|
+
|
|
683
|
+
==== SyntaxValidator
|
|
684
|
+
|
|
685
|
+
Performs structural validation without PostScript execution:
|
|
686
|
+
|
|
687
|
+
* Header format checking
|
|
688
|
+
* BoundingBox validation
|
|
689
|
+
* Delimiter balance
|
|
690
|
+
* Token validity
|
|
691
|
+
|
|
692
|
+
==== SemanticValidator
|
|
693
|
+
|
|
694
|
+
Analyzes PostScript semantics:
|
|
695
|
+
|
|
696
|
+
* Stack simulation
|
|
697
|
+
* Graphics state tracking
|
|
698
|
+
* Dictionary tracking
|
|
699
|
+
* Operator coverage
|
|
700
|
+
|
|
701
|
+
==== Helper Classes
|
|
702
|
+
|
|
703
|
+
* *DelimiterChecker* - Validates balanced delimiters
|
|
704
|
+
* *StackSimulator* - Simulates PostScript stack
|
|
705
|
+
* *GraphicsStateTracker* - Tracks gsave/grestore
|
|
706
|
+
* *DictionaryTracker* - Tracks dict begin/end
|
|
707
|
+
|
|
708
|
+
== Reference
|
|
709
|
+
|
|
710
|
+
=== Command Line Options
|
|
711
|
+
|
|
712
|
+
[cols="2,3,2",options="header"]
|
|
713
|
+
|===
|
|
714
|
+
| Option | Description | Default
|
|
715
|
+
|
|
716
|
+
| `--level=LEVEL`
|
|
717
|
+
| Validation level (syntax/semantic/full)
|
|
718
|
+
| semantic
|
|
719
|
+
|
|
720
|
+
| `--format=FORMAT`
|
|
721
|
+
| Output format (text/yaml/json)
|
|
722
|
+
| text
|
|
723
|
+
|
|
724
|
+
| `--verbose`
|
|
725
|
+
| Show warnings and info messages
|
|
726
|
+
| false
|
|
727
|
+
|
|
728
|
+
| `--quiet`
|
|
729
|
+
| Suppress valid file messages
|
|
730
|
+
| false
|
|
731
|
+
|
|
732
|
+
| `--no-color`
|
|
733
|
+
| Disable colored output
|
|
734
|
+
| false
|
|
735
|
+
|
|
736
|
+
| `--fail-fast`
|
|
737
|
+
| Stop at first error
|
|
738
|
+
| false
|
|
739
|
+
|
|
740
|
+
| `--eps-version=VERSION`
|
|
741
|
+
| EPS version to validate (1.0/2.0/3.0)
|
|
742
|
+
| none
|
|
743
|
+
|===
|
|
744
|
+
|
|
745
|
+
=== Message Severities
|
|
746
|
+
|
|
747
|
+
[cols="2,3",options="header"]
|
|
748
|
+
|===
|
|
749
|
+
| Severity | Description
|
|
750
|
+
|
|
751
|
+
| ERROR
|
|
752
|
+
| Critical issues preventing conversion
|
|
753
|
+
|
|
754
|
+
| WARNING
|
|
755
|
+
| Potential problems that may affect output
|
|
756
|
+
|
|
757
|
+
| INFO
|
|
758
|
+
| Informational messages about file structure
|
|
759
|
+
|===
|
|
760
|
+
|
|
761
|
+
=== Supported File Types
|
|
762
|
+
|
|
763
|
+
* `.ps` - PostScript files
|
|
764
|
+
* `.eps` - Encapsulated PostScript files
|
|
765
|
+
* Any text file with PostScript content
|
|
766
|
+
|
|
767
|
+
== Further Reading
|
|
768
|
+
|
|
769
|
+
* link:../README.adoc[PostSVG README]
|
|
770
|
+
* link:ps2svg_compatibility.adoc[PS2SVG Compatibility Guide]
|
|
771
|
+
* link:postscript/index.adoc[PostScript Implementation Notes]
|
|
772
|
+
* link:optimization.adoc[Optimization Guide]
|