svg_conform 0.1.4 → 0.1.5
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/.rubocop_todo.yml +182 -21
- data/README.adoc +391 -989
- data/config/profiles/metanorma.yml +5 -0
- data/docs/api_reference.adoc +1355 -0
- data/docs/cli_guide.adoc +846 -0
- data/docs/reference_manifest.adoc +370 -0
- data/docs/requirements.adoc +68 -1
- data/examples/document_input_demo.rb +102 -0
- data/lib/svg_conform/document.rb +40 -1
- data/lib/svg_conform/profile.rb +15 -9
- data/lib/svg_conform/references/base_reference.rb +130 -0
- data/lib/svg_conform/references/id_definition.rb +38 -0
- data/lib/svg_conform/references/reference_classifier.rb +45 -0
- data/lib/svg_conform/references/reference_manifest.rb +129 -0
- data/lib/svg_conform/references.rb +11 -0
- data/lib/svg_conform/remediations/namespace_attribute_remediation.rb +34 -43
- data/lib/svg_conform/requirements/id_collection_requirement.rb +38 -0
- data/lib/svg_conform/requirements/id_reference_requirement.rb +11 -0
- data/lib/svg_conform/requirements/invalid_id_references_requirement.rb +3 -0
- data/lib/svg_conform/requirements/link_validation_requirement.rb +114 -31
- data/lib/svg_conform/requirements/no_external_css_requirement.rb +5 -2
- data/lib/svg_conform/requirements.rb +11 -9
- data/lib/svg_conform/sax_validation_handler.rb +16 -1
- data/lib/svg_conform/validation_context.rb +67 -1
- data/lib/svg_conform/validation_result.rb +43 -2
- data/lib/svg_conform/validator.rb +56 -16
- data/lib/svg_conform/version.rb +1 -1
- data/lib/svg_conform.rb +11 -2
- data/spec/svg_conform/commands/svgcheck_compare_command_spec.rb +1 -0
- data/spec/svg_conform/commands/svgcheck_compatibility_command_spec.rb +1 -0
- data/spec/svg_conform/commands/svgcheck_generate_command_spec.rb +1 -0
- data/spec/svg_conform/references/integration_spec.rb +206 -0
- data/spec/svg_conform/references/reference_classifier_spec.rb +142 -0
- data/spec/svg_conform/references/reference_manifest_spec.rb +307 -0
- data/spec/svg_conform/requirements/id_reference_state_spec.rb +93 -0
- data/spec/svg_conform/validator_input_types_spec.rb +172 -0
- metadata +17 -2
data/README.adoc
CHANGED
|
@@ -25,6 +25,7 @@ SvgConform is distributed as a Ruby gem.
|
|
|
25
25
|
|
|
26
26
|
* **Profile-based validation**: Validate SVG files against predefined or custom profiles
|
|
27
27
|
* **Remediation**: Automatically fix common SVG conformance issues
|
|
28
|
+
* **Reference manifest**: Complete tracking of IDs and references for consumer-level validation
|
|
28
29
|
* **Extensible architecture**: Easy to add new rules and profiles
|
|
29
30
|
* **Command-line interface**: Validate and fix files from the command line
|
|
30
31
|
* **Ruby API**: Integrate validation into Ruby applications
|
|
@@ -230,1227 +231,628 @@ if !result.valid? && profile.remediation_count > 0
|
|
|
230
231
|
end
|
|
231
232
|
----
|
|
232
233
|
|
|
234
|
+
==== Accepting multiple input types
|
|
233
235
|
|
|
236
|
+
The validator accepts multiple input types and always uses SAX validation for memory-safe processing:
|
|
234
237
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
=== Architecture
|
|
238
|
-
|
|
239
|
-
The SvgConform architecture is built around a modular design that separates
|
|
240
|
-
concerns and allows for easy extension.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
[source]
|
|
244
|
-
----
|
|
245
|
-
╭────────────────────────────────────────────────────────────────╮
|
|
246
|
-
│ SvgConform │
|
|
247
|
-
├────────────────────────────────────────────────────────────────┤
|
|
248
|
-
│ │
|
|
249
|
-
│ ╭─────────────╮ ╭─────────────╮ ╭─────────────╮ │
|
|
250
|
-
│ │ CLI │ │ Ruby API │ │ Profiles │ │
|
|
251
|
-
│ │ │ │ │ │ Registry │ │
|
|
252
|
-
│ ╰─────┬───────╯ ╰──────┬──────╯ ╰─────┬───────╯ │
|
|
253
|
-
│ │ │ │ │
|
|
254
|
-
│ └───────────────────┼─────────────────┘ │
|
|
255
|
-
│ │ │
|
|
256
|
-
│ ╭─────────────────────────▼─────────────────────────╮ │
|
|
257
|
-
│ │ Validator │ │
|
|
258
|
-
│ │ ╭─────────────╮ ╭─────────────╮ ╭─────────────╮ │ │
|
|
259
|
-
│ │ │ Document │ │ Validation │ │ Remediation │ │ │
|
|
260
|
-
│ │ │ Parser │ │ Engine │ │ Engine │ │ │
|
|
261
|
-
│ │ ╰─────────────╯ ╰─────────────╯ ╰─────────────╯ │ │
|
|
262
|
-
│ ╰─────────────────────────┬─────────────────────────╯ │
|
|
263
|
-
│ │ │
|
|
264
|
-
│ ╭─────────────────────────▼─────────────────────────╮ │
|
|
265
|
-
│ │ Profile System │ │
|
|
266
|
-
│ │ │ │
|
|
267
|
-
│ │ ╭─────────────╮ ╭─────────────╮ ╭─────────────╮ │ │
|
|
268
|
-
│ │ │ SVG 1.2 RFC │ │ Metanorma │ │ Future │ │ │
|
|
269
|
-
│ │ │ Profile │ │ SVG Profile │ │ Profiles │ │ │
|
|
270
|
-
│ │ │ │ │ │ │ │ │ │
|
|
271
|
-
│ │ │ • svgcheck │ │ • ID links │ │ • Custom │ │ │
|
|
272
|
-
│ │ │ compatible │ │ • No ext. │ │ rules │ │ │
|
|
273
|
-
│ │ │ • Grayscale │ │ fonts │ │ • Org │ │ │
|
|
274
|
-
│ │ │ • RFC 7996 │ │ • Font def. │ │ standards │ │ │
|
|
275
|
-
│ │ ╰─────────────╯ ╰─────────────╯ ╰─────────────╯ │ │
|
|
276
|
-
│ ╰─────────────────────────┬─────────────────────────╯ │
|
|
277
|
-
│ │ │
|
|
278
|
-
│ ╭─────────────────────────▼─────────────────────────╮ │
|
|
279
|
-
│ │ Requirements & Remediations Engine │ │
|
|
280
|
-
│ │ ╭─────────────╮ ╭─────────────╮ ╭─────────────╮ │ │
|
|
281
|
-
│ │ │Requirements │ │Remediations │ │ Validation │ │ │
|
|
282
|
-
│ │ │ System │ │ System │ │ Results │ │ │
|
|
283
|
-
│ │ ╰─────────────╯ ╰─────────────╯ ╰─────────────╯ │ │
|
|
284
|
-
│ ╰─────────────────────────┬─────────────────────────╯ │
|
|
285
|
-
│ │ │
|
|
286
|
-
│ ╭─────────────────────────▼─────────────────────────╮ │
|
|
287
|
-
│ │ svgcheck Compatibility │ │
|
|
288
|
-
│ │ ╭─────────────╮ ╭─────────────╮ ╭─────────────╮ │ │
|
|
289
|
-
│ │ │ svgcheck │ │ YAML │ │ Report │ │ │
|
|
290
|
-
│ │ │ Parser │ │ Mapping │ │ Comparator │ │ │
|
|
291
|
-
│ │ ╰─────────────╯ ╰─────────────╯ ╰─────────────╯ │ │
|
|
292
|
-
│ ╰─────────────────────────┬─────────────────────────╯ │
|
|
293
|
-
│ │ │
|
|
294
|
-
│ ╭─────────────────────────▼─────────────────────────╮ │
|
|
295
|
-
│ │ Moxml │ │
|
|
296
|
-
│ │ (XML Processing) │ │
|
|
297
|
-
│ ╰───────────────────────────────────────────────────╯ │
|
|
298
|
-
│ │
|
|
299
|
-
╰────────────────────────────────────────────────────────────────╯
|
|
300
|
-
----
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
=== Profiles
|
|
304
|
-
|
|
305
|
-
SvgConform includes predefined profiles that can be used out-of-the-box.
|
|
306
|
-
Each profile is designed for different use cases and compliance standards.
|
|
307
|
-
|
|
308
|
-
.Predefined SVG profiles included in SvgConform
|
|
309
|
-
[cols="2,3,3,2", options="header"]
|
|
310
|
-
|===
|
|
311
|
-
|Profile |Use Case |Key Features |Documentation
|
|
312
|
-
|
|
313
|
-
|`base`
|
|
314
|
-
|Foundation profile
|
|
315
|
-
|Basic validation, namespace checks, starting point for custom profiles.
|
|
316
|
-
|link:docs/profiles.adoc#base-profile[Details]
|
|
317
|
-
|
|
318
|
-
|`metanorma`
|
|
319
|
-
|Metanorma SVG profile
|
|
320
|
-
|Standard SVG for Metanorma documents. Valid HREFs and ID linking. No external
|
|
321
|
-
fonts, images and CSS. No non-SVG elements or attributes.
|
|
322
|
-
|link:docs/profiles.adoc#no-external-css-profile[Details]
|
|
323
|
-
|
|
324
|
-
|`svg_1_2_rfc`
|
|
325
|
-
|IETF RFC SVG 1.2 profile
|
|
326
|
-
|RFC 7996/6949 compliant. Black/white color only, limited elements, generic
|
|
327
|
-
fonts. Fully compatible with `svgcheck` outcomes.
|
|
328
|
-
|link:docs/profiles.adoc#svg-1-2-rfc-profile[Details]
|
|
329
|
-
|
|
330
|
-
|`svg_1_2_rfc_with_rdf`
|
|
331
|
-
|IETF RFC SVG 1.2 profile with RDF metadata
|
|
332
|
-
|Same as `svg_1_2_rfc`, but allows RDF/Dublin Core metadata from design tools.
|
|
333
|
-
Supported by `svgcheck`.
|
|
334
|
-
|link:docs/profiles.adoc#svg-1-2-rfc-with-rdf-profile[Details]
|
|
335
|
-
|
|
336
|
-
|`no_external_css`
|
|
337
|
-
|Self-contained SVG
|
|
338
|
-
|No external references, security-focused, offline usage.
|
|
339
|
-
|link:docs/profiles.adoc#no-external-css-profile[Details]
|
|
340
|
-
|
|
341
|
-
|`lucid_fix`
|
|
342
|
-
|Lucid cleanup
|
|
343
|
-
|Remove Lucid-specific metadata, clean standard SVG output
|
|
344
|
-
|link:docs/profiles.adoc#lucid-fix-profile[Details]
|
|
345
|
-
|===
|
|
346
|
-
|
|
347
|
-
For complete profile documentation, including inheritance, customization, RDF
|
|
348
|
-
metadata support, and selection guides, see
|
|
349
|
-
link:docs/profiles.adoc[SVG Profiles Documentation].
|
|
350
|
-
|
|
351
|
-
For detailed information about configuring RDF metadata support in profiles, see
|
|
352
|
-
link:docs/rdf_metadata_support.adoc[RDF Metadata Support Documentation].
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
=== Requirements
|
|
357
|
-
|
|
358
|
-
SvgConform includes different requirement checkers that validate various aspects
|
|
359
|
-
of SVG documents.
|
|
360
|
-
|
|
361
|
-
There are two main categories of requirements:
|
|
362
|
-
|
|
363
|
-
* structural requirements: requirements set towards the XML structure and syntax of SVG documents
|
|
364
|
-
* logical requirements: requirements set towards content and stylistic aspects of SVG documents
|
|
365
|
-
|
|
366
|
-
.SvgConform supported requirement classes
|
|
367
|
-
[cols="2,2,3", options="header"]
|
|
368
|
-
|===
|
|
369
|
-
|Type |Requirement |Description
|
|
370
|
-
|
|
371
|
-
|Structural
|
|
372
|
-
|link:docs/requirements.adoc#namespace-requirement[`NamespaceRequirement`]
|
|
373
|
-
|Ensures proper SVG namespace declarations
|
|
374
|
-
|
|
375
|
-
|Structural
|
|
376
|
-
|link:docs/requirements.adoc#namespace-attributes-requirement[`NamespaceAttributesRequirement`]
|
|
377
|
-
|Validates namespace attributes are from allowed namespaces
|
|
378
|
-
|
|
379
|
-
|Structural
|
|
380
|
-
|link:docs/requirements.adoc#allowed-elements-requirement[`AllowedElementsRequirement`]
|
|
381
|
-
|Restricts which SVG elements are permitted
|
|
382
|
-
|
|
383
|
-
|Structural
|
|
384
|
-
|link:docs/requirements.adoc#viewbox-required-requirement[`ViewboxRequiredRequirement`]
|
|
385
|
-
|Requires viewBox attributes on root elements
|
|
386
|
-
|
|
387
|
-
|Logical
|
|
388
|
-
|link:docs/requirements.adoc#color-restrictions-requirement[`ColorRestrictionsRequirement`]
|
|
389
|
-
|Enforces color usage restrictions (e.g., grayscale only)
|
|
390
|
-
|
|
391
|
-
|Logical
|
|
392
|
-
|link:docs/requirements.adoc#font-family-requirement[`FontFamilyRequirement`]
|
|
393
|
-
|Controls font family usage and validates font specifications
|
|
394
|
-
|
|
395
|
-
|Logical
|
|
396
|
-
|link:docs/requirements.adoc#no-external-css-requirement[`NoExternalCssRequirement`]
|
|
397
|
-
|Prevents external CSS references to ensure self-contained documents
|
|
398
|
-
|
|
399
|
-
|Logical
|
|
400
|
-
|link:docs/requirements.adoc#no-external-fonts-requirement[`NoExternalFontsRequirement`]
|
|
401
|
-
|Validates that no external font references are present
|
|
402
|
-
|
|
403
|
-
|Logical
|
|
404
|
-
|link:docs/requirements.adoc#no-external-images-requirement[`NoExternalImagesRequirement`]
|
|
405
|
-
|Validates that no external image references are present
|
|
406
|
-
|
|
407
|
-
|Logical
|
|
408
|
-
|link:docs/requirements.adoc#forbidden-content-requirement[`ForbiddenContentRequirement`]
|
|
409
|
-
|Prevents inclusion of forbidden elements and attributes
|
|
410
|
-
|
|
411
|
-
|Logical
|
|
412
|
-
|link:docs/requirements.adoc#id-reference-requirement[`IdReferenceRequirement`]
|
|
413
|
-
|Validates that ID references point to existing elements
|
|
414
|
-
|
|
415
|
-
|Logical
|
|
416
|
-
|link:docs/requirements.adoc#invalid-id-references-requirement[`InvalidIdReferencesRequirement`]
|
|
417
|
-
|Detects and validates broken ID references in SVG documents
|
|
418
|
-
|
|
419
|
-
|Logical
|
|
420
|
-
|link:docs/requirements.adoc#link-validation-requirement[`LinkValidationRequirement`]
|
|
421
|
-
|Validates that links use only ASCII characters (IETF requirement)
|
|
422
|
-
|
|
423
|
-
|Logical
|
|
424
|
-
|link:docs/requirements.adoc#style-requirement[`StyleRequirement`]
|
|
425
|
-
|Comprehensive CSS style validation including syntax and properties
|
|
426
|
-
|
|
427
|
-
|Logical
|
|
428
|
-
|link:docs/requirements.adoc#style-promotion-requirement[`StylePromotionRequirement`]
|
|
429
|
-
|Detects style properties that should be promoted to SVG attributes
|
|
430
|
-
|===
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
=== Remediations
|
|
435
|
-
|
|
436
|
-
Remediations are automatic fixing actions that can resolve requirement failures.
|
|
437
|
-
Each remediation targets one or more specific requirements.
|
|
438
|
-
|
|
439
|
-
SvgConform includes different remediation actions that can automatically fix
|
|
440
|
-
SVG documents to resolve requirement violations.
|
|
441
|
-
|
|
442
|
-
.SvgConform supported remediation classes
|
|
443
|
-
[cols="2,2,3,2", options="header"]
|
|
444
|
-
|===
|
|
445
|
-
|Type |Remediation |Description |Targets
|
|
446
|
-
|
|
447
|
-
|Content Conversion
|
|
448
|
-
|link:docs/remediation.adoc#color-remediation[`ColorRemediation`]
|
|
449
|
-
|Converts invalid colors to allowed alternatives using threshold-based conversion
|
|
450
|
-
|link:docs/requirements.adoc#color-restrictions-requirement[`ColorRestrictionsRequirement`]
|
|
451
|
-
|
|
452
|
-
|Content Conversion
|
|
453
|
-
|link:docs/remediation.adoc#font-remediation[`FontRemediation`]
|
|
454
|
-
|Maps font families to generic alternatives (serif, sans-serif, monospace)
|
|
455
|
-
|link:docs/requirements.adoc#font-family-requirement[`FontFamilyRequirement`]
|
|
456
|
-
|
|
457
|
-
|Content Conversion
|
|
458
|
-
|link:docs/remediation.adoc#font-embedding-remediation[`FontEmbeddingRemediation`]
|
|
459
|
-
|Converts external font references to embedded data URIs
|
|
460
|
-
|link:docs/requirements.adoc#no-external-fonts-requirement[`NoExternalFontsRequirement`]
|
|
461
|
-
|
|
462
|
-
|Content Conversion
|
|
463
|
-
|link:docs/remediation.adoc#image-embedding-remediation[`ImageEmbeddingRemediation`]
|
|
464
|
-
|Converts external image references to embedded data URIs
|
|
465
|
-
|link:docs/requirements.adoc#no-external-images-requirement[`NoExternalImagesRequirement`]
|
|
466
|
-
|
|
467
|
-
|Element/Attribute Removal
|
|
468
|
-
|link:docs/remediation.adoc#namespace-remediation[`NamespaceRemediation`]
|
|
469
|
-
|Removes invalid namespace elements and cleans up namespace declarations
|
|
470
|
-
|link:docs/requirements.adoc#namespace-requirement[`NamespaceRequirement`]
|
|
471
|
-
|
|
472
|
-
|Element/Attribute Removal
|
|
473
|
-
|link:docs/remediation.adoc#namespace-attribute-remediation[`NamespaceAttributeRemediation`]
|
|
474
|
-
|Removes attributes from disallowed namespaces
|
|
475
|
-
|link:docs/requirements.adoc#namespace-attributes-requirement[`NamespaceAttributesRequirement`]
|
|
476
|
-
|
|
477
|
-
|Element/Attribute Removal
|
|
478
|
-
|link:docs/remediation.adoc#no-external-css-remediation[`NoExternalCssRemediation`]
|
|
479
|
-
|Removes external CSS references including @import and external stylesheets
|
|
480
|
-
|link:docs/requirements.adoc#no-external-css-requirement[`NoExternalCssRequirement`]
|
|
481
|
-
|
|
482
|
-
|Addition
|
|
483
|
-
|link:docs/remediation.adoc#viewbox-remediation[`ViewboxRemediation`]
|
|
484
|
-
|Adds missing viewBox attributes to root SVG elements
|
|
485
|
-
|link:docs/requirements.adoc#viewbox-required-requirement[`ViewboxRequiredRequirement`]
|
|
486
|
-
|
|
487
|
-
|Style Processing
|
|
488
|
-
|link:docs/remediation.adoc#style-promotion-remediation[`StylePromotionRemediation`]
|
|
489
|
-
|Promotes CSS style properties to equivalent SVG attributes
|
|
490
|
-
|link:docs/requirements.adoc#style-promotion-requirement[`StylePromotionRequirement`]
|
|
491
|
-
|
|
492
|
-
|Reference Fixing
|
|
493
|
-
|link:docs/remediation.adoc#invalid-id-references-remediation[`InvalidIdReferencesRemediation`]
|
|
494
|
-
|Fixes or removes broken ID references and invalid href attributes
|
|
495
|
-
|link:docs/requirements.adoc#id-reference-requirement[`IdReferenceRequirement`], `InvalidIdReferencesRequirement`
|
|
496
|
-
|===
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
=== Requirement and remediation mapping
|
|
500
|
-
|
|
501
|
-
Remediations are mapped to requirements using the `targets` configuration in
|
|
502
|
-
profile YAML files.
|
|
503
|
-
|
|
504
|
-
[source,yaml]
|
|
505
|
-
----
|
|
506
|
-
remediations:
|
|
507
|
-
- id: "fix_invalid_colors"
|
|
508
|
-
type: "ColorRemediationAction"
|
|
509
|
-
description: "Convert invalid colors to black or white"
|
|
510
|
-
targets: ["color_restrictions"] # Maps to ColorRestrictionsRequirement
|
|
238
|
+
[source,ruby]
|
|
511
239
|
----
|
|
240
|
+
validator = SvgConform::Validator.new
|
|
512
241
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
* **Targeted fixes**: Remediations only run when their target requirements fail
|
|
516
|
-
* **Flexible configuration**: Multiple remediations can target the same requirement
|
|
517
|
-
* **Conditional application**: Remediations can be enabled/disabled per profile
|
|
518
|
-
|
|
519
|
-
|
|
242
|
+
# String input: Direct SAX parsing
|
|
243
|
+
result = validator.validate(svg_string, profile: :metanorma)
|
|
520
244
|
|
|
521
|
-
|
|
245
|
+
# Moxml documents/elements: Serialize once, then SAX validate
|
|
246
|
+
moxml_doc = Moxml.new.parse(svg_string)
|
|
247
|
+
result = validator.validate(moxml_doc, profile: :metanorma)
|
|
522
248
|
|
|
523
|
-
|
|
524
|
-
|
|
249
|
+
moxml_element = moxml_doc.root
|
|
250
|
+
result = validator.validate(moxml_element, profile: :metanorma)
|
|
525
251
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
. If fixing is enabled, the Validator uses the RemediationEngine to apply Remediations.
|
|
530
|
-
. The fixed Document is returned along with the validation results in the ConformanceReport.
|
|
252
|
+
# Nokogiri documents/elements: Serialize once, then SAX validate
|
|
253
|
+
nokogiri_doc = Nokogiri::XML(svg_string)
|
|
254
|
+
result = validator.validate(nokogiri_doc, profile: :metanorma)
|
|
531
255
|
|
|
532
|
-
|
|
256
|
+
nokogiri_element = nokogiri_doc.root # Common in metanorma integration
|
|
257
|
+
result = validator.validate(nokogiri_element, profile: :metanorma)
|
|
533
258
|
----
|
|
534
|
-
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
535
|
-
│ SVG File │───▶│ Document │───▶│ Validator │
|
|
536
|
-
│ │ │ Parser │ │ │
|
|
537
|
-
└─────────────┘ └─────────────┘ └─────┬───────┘
|
|
538
|
-
│
|
|
539
|
-
┌─────────────┐ │
|
|
540
|
-
│ Profile │◀─────────┘
|
|
541
|
-
└─────┬───────┘
|
|
542
|
-
│
|
|
543
|
-
┌─────▼───────┐
|
|
544
|
-
│ Rules │
|
|
545
|
-
└─────┬───────┘
|
|
546
|
-
│
|
|
547
|
-
┌─────▼───────┐ ┌─────────────┐
|
|
548
|
-
│Requirements │───▶│ Validation │
|
|
549
|
-
│ │ │ Result │
|
|
550
|
-
└─────────────┘ └─────┬───────┘
|
|
551
|
-
│
|
|
552
|
-
┌─────────────┐ │
|
|
553
|
-
│Remediations │◀─────────┘
|
|
554
|
-
└─────┬───────┘
|
|
555
|
-
│
|
|
556
|
-
┌───────▼────────┐
|
|
557
|
-
│ Fixed Document │
|
|
558
|
-
└────────────────┘
|
|
559
|
-
----
|
|
560
|
-
|
|
561
|
-
=== Classes
|
|
562
259
|
|
|
563
|
-
|
|
260
|
+
**Why SAX validation for all inputs?**
|
|
564
261
|
|
|
565
|
-
|
|
566
|
-
library, and provides SVG-specific functionality through the Document class.
|
|
262
|
+
SAX (Simple API for XML) parsing is memory-safe and can handle arbitrarily large SVG files without hanging. DOM-based validation loads the entire tree into memory, which can cause performance issues or crashes with large files.
|
|
567
263
|
|
|
568
|
-
|
|
264
|
+
**Benefits of accepting DOM objects**:
|
|
569
265
|
|
|
570
|
-
|
|
571
|
-
validation process with loading profiles, applying rules, and collecting results.
|
|
266
|
+
When integrating with tools like Metanorma where SVG elements are already parsed:
|
|
572
267
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
loaded dynamically at runtime.
|
|
578
|
-
|
|
579
|
-
Notice that there are requirement violations that cannot be automatically
|
|
580
|
-
remediated. For example, if an SVG uses a forbidden element, the remediation may
|
|
581
|
-
simply remove it, which could lead to loss of important content.
|
|
268
|
+
[source,ruby]
|
|
269
|
+
----
|
|
270
|
+
# ❌ Old way: User manually serializes
|
|
271
|
+
result = validator.validate(svg_element.to_xml, profile: :metanorma)
|
|
582
272
|
|
|
273
|
+
# ✅ New way: Library handles serialization internally
|
|
274
|
+
result = validator.validate(svg_element, profile: :metanorma)
|
|
275
|
+
----
|
|
583
276
|
|
|
584
|
-
|
|
277
|
+
Benefits:
|
|
278
|
+
- **Cleaner API**: No need to call `.to_xml` explicitly
|
|
279
|
+
- **Type flexibility**: Works with Nokogiri, Moxml, or strings
|
|
280
|
+
- **Safe for large files**: Always uses memory-efficient SAX parsing
|
|
281
|
+
- **Backward compatible**: String input still works as before
|
|
585
282
|
|
|
586
|
-
An SvgConform requirement is a specific validation check that determines if an SVG
|
|
587
|
-
document meets certain criteria. Requirements are implemented as classes that inherit
|
|
588
|
-
from `SvgConform::Requirements::BaseRequirement`.
|
|
589
283
|
|
|
590
|
-
|
|
591
|
-
XML tree traversal and validation logic.
|
|
284
|
+
=== Reference manifest
|
|
592
285
|
|
|
593
|
-
|
|
594
|
-
its behavior.
|
|
286
|
+
SvgConform provides comprehensive ID and reference tracking through its reference manifest system:
|
|
595
287
|
|
|
596
|
-
|
|
597
|
-
|
|
288
|
+
[source,ruby]
|
|
289
|
+
----
|
|
290
|
+
result = validator.validate(svg_content, profile: :metanorma)
|
|
598
291
|
|
|
599
|
-
|
|
292
|
+
# Access the reference manifest
|
|
293
|
+
manifest = result.reference_manifest
|
|
600
294
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
295
|
+
# Get all defined IDs
|
|
296
|
+
manifest.available_ids.each do |id_def|
|
|
297
|
+
puts "ID: #{id_def.id_value} at line #{id_def.line_number}"
|
|
298
|
+
end
|
|
604
299
|
|
|
605
|
-
|
|
606
|
-
|
|
300
|
+
# Check for unresolved internal references
|
|
301
|
+
if result.has_unresolved_references?
|
|
302
|
+
result.unresolved_internal_references.each do |ref|
|
|
303
|
+
puts "Unresolved reference: #{ref.value} at line #{ref.line_number}"
|
|
304
|
+
end
|
|
305
|
+
end
|
|
607
306
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
307
|
+
# Check for external references
|
|
308
|
+
if result.has_external_references?
|
|
309
|
+
result.external_references.each do |ref|
|
|
310
|
+
puts "External reference: #{ref.value}"
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
----
|
|
611
314
|
|
|
315
|
+
See link:docs/reference_manifest.adoc[Reference Manifest Documentation] for complete details.
|
|
612
316
|
|
|
613
317
|
|
|
614
318
|
[[command_line_interface]]
|
|
615
319
|
== Command line interface
|
|
616
320
|
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
The `svg_conform` command provides a comprehensive CLI for validation and fixing.
|
|
321
|
+
The `svg_conform` command-line tool provides validation and remediation capabilities for SVG files.
|
|
620
322
|
|
|
323
|
+
=== Basic commands
|
|
621
324
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
The `profiles` command lists all available SVG profiles included in SvgConform.
|
|
625
|
-
|
|
626
|
-
Syntax:
|
|
325
|
+
==== List available profiles
|
|
627
326
|
|
|
628
327
|
[source,bash]
|
|
629
328
|
----
|
|
630
|
-
svg_conform profiles
|
|
631
|
-
|
|
632
|
-
Options:
|
|
633
|
-
-v, --verbose Show detailed profile information
|
|
329
|
+
$ svg_conform profiles
|
|
634
330
|
----
|
|
635
331
|
|
|
636
|
-
|
|
637
|
-
|
|
332
|
+
Show detailed information about profiles:
|
|
333
|
+
|
|
638
334
|
[source,bash]
|
|
639
335
|
----
|
|
640
|
-
|
|
641
|
-
$ svg_conform profiles
|
|
642
|
-
|
|
643
|
-
Available SVG Profiles
|
|
644
|
-
========================================
|
|
645
|
-
|
|
646
|
-
╭──────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
|
|
647
|
-
│ Profile │ Description │
|
|
648
|
-
├──────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
|
|
649
|
-
│ base │ Base SVG validation profile with common requirements │
|
|
650
|
-
│ lucid_fix │ Lucid SVG Fix Profile - Removes invalid use element references and namespace attributes from Lucid-generated SVGs │
|
|
651
|
-
│ metanorma │ Metanorma SVG Profile - SVG requirements for Metanorma technical documents with embedded resources │
|
|
652
|
-
│ no_external_css │ Security-focused profile that disallows external CSS references │
|
|
653
|
-
│ svg_1_2_rfc │ SVG 1.2 RFC Profile (RFC 7996) - Black and white diagrams for technical documents │
|
|
654
|
-
│ svg_1_2_rfc_with_rdf │ SVG 1.2 RFC Profile with RDF metadata support - Allows RDF/Dublin Core metadata in SVG files │
|
|
655
|
-
╰──────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
|
|
336
|
+
$ svg_conform profiles --verbose
|
|
656
337
|
----
|
|
657
|
-
====
|
|
658
|
-
|
|
659
338
|
|
|
660
|
-
|
|
661
|
-
=== `svg_conform check`
|
|
662
|
-
|
|
663
|
-
The `check` command validates SVG files against a specified profile and optionally
|
|
664
|
-
applies automatic remediations. It supports single files, multiple files via shell
|
|
665
|
-
glob expansion, and directory scanning.
|
|
666
|
-
|
|
667
|
-
Syntax:
|
|
339
|
+
==== Validate a single SVG file
|
|
668
340
|
|
|
669
341
|
[source,bash]
|
|
670
342
|
----
|
|
671
|
-
svg_conform check
|
|
672
|
-
|
|
343
|
+
$ svg_conform check file.svg --profile=metanorma
|
|
344
|
+
----
|
|
673
345
|
|
|
674
|
-
|
|
675
|
-
-p, --profile PROFILE Profile to validate against
|
|
346
|
+
Options:
|
|
676
347
|
|
|
677
|
-
|
|
678
|
-
|
|
348
|
+
* `--profile=PROFILE` or `-p`: Profile to validate against (default: `svg_1_2_rfc`)
|
|
349
|
+
* `--format=FORMAT`: Output format: `table` (default), `json`, or `yaml`
|
|
350
|
+
* `--output=FILE` or `-o`: Save report to file
|
|
679
351
|
|
|
680
|
-
|
|
681
|
-
-f, --fix Enable automatic remediation
|
|
682
|
-
--output-dir DIR Output directory for remediated files (required for multi-file)
|
|
683
|
-
--in-place Replace original files (requires --force)
|
|
684
|
-
--force Confirm destructive operations
|
|
685
|
-
--fix-output FILE Output file for single file mode (default: FILE.fixed.svg)
|
|
352
|
+
Example with JSON output:
|
|
686
353
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
--report-format FORMAT Batch report format: json, yaml
|
|
691
|
-
--report-output FILE Save detailed batch report to file
|
|
692
|
-
--manifest FILE Manifest file path (default: manifest.json with --fix)
|
|
693
|
-
-q, --quiet Suppress per-file output, show summary only
|
|
694
|
-
-v, --verbose Show detailed progress
|
|
354
|
+
[source,bash]
|
|
355
|
+
----
|
|
356
|
+
$ svg_conform check file.svg -p metanorma --format=json --output=report.json
|
|
695
357
|
----
|
|
696
358
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
**Single File Mode:**
|
|
359
|
+
==== Fix a single SVG file
|
|
700
360
|
|
|
701
|
-
|
|
361
|
+
Apply automatic remediations to fix conformance issues:
|
|
702
362
|
|
|
703
363
|
[source,bash]
|
|
704
364
|
----
|
|
705
|
-
|
|
706
|
-
svg_conform check file.svg -p metanorma
|
|
707
|
-
|
|
708
|
-
# With remediation
|
|
709
|
-
svg_conform check file.svg -p metanorma -f --fix-output fixed.svg
|
|
710
|
-
|
|
711
|
-
# Output YAML report
|
|
712
|
-
svg_conform check file.svg -p metanorma --format yaml -o report.yaml
|
|
365
|
+
$ svg_conform check file.svg --profile=metanorma --fix
|
|
713
366
|
----
|
|
714
367
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
Validates multiple files specified via shell glob patterns. The shell expands
|
|
718
|
-
patterns like `*.svg` before passing to the command.
|
|
368
|
+
Specify custom output file:
|
|
719
369
|
|
|
720
370
|
[source,bash]
|
|
721
371
|
----
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
# Validate with pattern matching
|
|
726
|
-
svg_conform check images/*/*.svg -p metanorma
|
|
372
|
+
$ svg_conform check file.svg -p metanorma -f --fix-output=fixed.svg
|
|
373
|
+
----
|
|
727
374
|
|
|
728
|
-
|
|
729
|
-
svg_conform check *.svg -p metanorma -f --output-dir fixed/
|
|
375
|
+
Options:
|
|
730
376
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
----
|
|
377
|
+
* `--fix` or `-f`: Enable automatic remediation
|
|
378
|
+
* `--fix-output=FILE`: Output file for remediated SVG (default: `FILE.fixed.svg`)
|
|
734
379
|
|
|
735
|
-
|
|
380
|
+
==== Process multiple files
|
|
736
381
|
|
|
737
|
-
|
|
382
|
+
Process multiple SVG files at once:
|
|
738
383
|
|
|
739
384
|
[source,bash]
|
|
740
385
|
----
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
# Scan and remediate to new directory
|
|
745
|
-
svg_conform check -d images/ -p metanorma -f --output-dir fixed/
|
|
746
|
-
|
|
747
|
-
# Replace files in place (requires confirmation)
|
|
748
|
-
svg_conform check -d images/ -p metanorma -f --in-place --force
|
|
386
|
+
$ svg_conform check file1.svg file2.svg file3.svg --profile=metanorma
|
|
387
|
+
----
|
|
749
388
|
|
|
750
|
-
|
|
751
|
-
svg_conform check -d images/ -p metanorma -f --output-dir fixed/ --quiet \
|
|
752
|
-
--report-format json --report-output report.json
|
|
389
|
+
With remediation, an output directory is required:
|
|
753
390
|
|
|
754
|
-
|
|
755
|
-
|
|
391
|
+
[source,bash]
|
|
392
|
+
----
|
|
393
|
+
$ svg_conform check *.svg -p metanorma --fix --output-dir=fixed/
|
|
756
394
|
----
|
|
757
395
|
|
|
758
|
-
|
|
396
|
+
==== Process a directory
|
|
759
397
|
|
|
760
|
-
|
|
398
|
+
Recursively process all SVG files in a directory:
|
|
761
399
|
|
|
762
|
-
[source]
|
|
400
|
+
[source,bash]
|
|
763
401
|
----
|
|
764
|
-
|
|
765
|
-
Directory: /path/to/images
|
|
766
|
-
Profile: metanorma
|
|
767
|
-
Files processed: 56
|
|
768
|
-
Valid before: 0
|
|
769
|
-
Remediated: 56
|
|
770
|
-
Valid after: 56
|
|
771
|
-
Failed: 0
|
|
772
|
-
Success rate: 100.0%
|
|
773
|
-
Manifest written to manifest.json
|
|
402
|
+
$ svg_conform check --directory=images/ --profile=metanorma
|
|
774
403
|
----
|
|
775
404
|
|
|
776
|
-
|
|
777
|
-
YAML format using lutaml-model serialization:
|
|
405
|
+
With remediation:
|
|
778
406
|
|
|
779
|
-
[source,
|
|
407
|
+
[source,bash]
|
|
780
408
|
----
|
|
781
|
-
|
|
782
|
-
"directory": "/path/to/images",
|
|
783
|
-
"profile": "metanorma",
|
|
784
|
-
"timestamp": "2025-10-12T15:36:25+08:00",
|
|
785
|
-
"total_files": 56,
|
|
786
|
-
"valid_before": 0,
|
|
787
|
-
"valid_after": 56,
|
|
788
|
-
"remediated": 56,
|
|
789
|
-
"failed": 0,
|
|
790
|
-
"success_rate": 100.0,
|
|
791
|
-
"files": [
|
|
792
|
-
{
|
|
793
|
-
"filename": "diagram.svg",
|
|
794
|
-
"original_path": "/path/to/images/diagram.svg",
|
|
795
|
-
"valid_before": false,
|
|
796
|
-
"valid_after": true,
|
|
797
|
-
"errors_before": 3,
|
|
798
|
-
"errors_after": 0,
|
|
799
|
-
"remediated_path": "/path/to/fixed/diagram.svg",
|
|
800
|
-
"status": "remediated"
|
|
801
|
-
}
|
|
802
|
-
],
|
|
803
|
-
"manifest": {
|
|
804
|
-
"/path/to/images/diagram.svg": "/path/to/fixed/diagram.svg"
|
|
805
|
-
}
|
|
806
|
-
}
|
|
409
|
+
$ svg_conform check -d images/ -p metanorma --fix --output-dir=fixed/
|
|
807
410
|
----
|
|
808
411
|
|
|
809
|
-
|
|
412
|
+
Replace files in-place (use with caution):
|
|
810
413
|
|
|
811
|
-
|
|
812
|
-
explicitly specified with `--manifest`). The manifest maps original file paths
|
|
813
|
-
to their remediated counterparts:
|
|
814
|
-
|
|
815
|
-
[source,json]
|
|
414
|
+
[source,bash]
|
|
816
415
|
----
|
|
817
|
-
|
|
818
|
-
"timestamp": "2025-10-12T15:00:00+08:00",
|
|
819
|
-
"profile": "metanorma",
|
|
820
|
-
"mappings": {
|
|
821
|
-
"/original/path/file1.svg": "/fixed/path/file1.svg",
|
|
822
|
-
"/original/path/file2.svg": "/fixed/path/file2.svg"
|
|
823
|
-
}
|
|
824
|
-
}
|
|
416
|
+
$ svg_conform check -d images/ -p metanorma --fix --in-place --force
|
|
825
417
|
----
|
|
826
418
|
|
|
419
|
+
==== Batch processing options
|
|
827
420
|
|
|
828
|
-
|
|
421
|
+
Additional options for batch processing:
|
|
829
422
|
|
|
830
|
-
|
|
423
|
+
* `--quiet` or `-q`: Suppress per-file output, show summary only
|
|
424
|
+
* `--verbose` or `-v`: Show detailed progress
|
|
425
|
+
* `--report-format=FORMAT`: Generate detailed report in `json` or `yaml`
|
|
426
|
+
* `--report-output=FILE`: Save detailed batch report to file
|
|
427
|
+
* `--manifest=FILE`: Generate manifest mapping original to remediated files (default: `manifest.json`)
|
|
831
428
|
|
|
832
|
-
|
|
429
|
+
Example with detailed reporting:
|
|
833
430
|
|
|
834
431
|
[source,bash]
|
|
835
432
|
----
|
|
836
|
-
svg_conform
|
|
433
|
+
$ svg_conform check -d images/ -p metanorma -f --output-dir=fixed/ \
|
|
434
|
+
--report-format=json --report-output=batch-report.json \
|
|
435
|
+
--manifest=file-mapping.json
|
|
837
436
|
----
|
|
838
437
|
|
|
839
|
-
|
|
438
|
+
==== Display version
|
|
439
|
+
|
|
840
440
|
[source,bash]
|
|
841
441
|
----
|
|
842
442
|
$ svg_conform version
|
|
843
|
-
SvgConform 0.1.0
|
|
844
443
|
----
|
|
845
444
|
|
|
445
|
+
=== Exit codes
|
|
846
446
|
|
|
447
|
+
* `0`: All files valid or successfully remediated
|
|
448
|
+
* `1`: Validation failures or errors occurred
|
|
847
449
|
|
|
848
|
-
|
|
849
|
-
== Ruby API
|
|
450
|
+
=== Common workflows
|
|
850
451
|
|
|
851
|
-
|
|
452
|
+
==== Quality control workflow
|
|
852
453
|
|
|
853
|
-
|
|
454
|
+
Check all SVG files before deployment:
|
|
455
|
+
|
|
456
|
+
[source,bash]
|
|
457
|
+
----
|
|
458
|
+
$ svg_conform check -d assets/images/ -p metanorma --quiet
|
|
854
459
|
----
|
|
855
|
-
require 'svg_conform'
|
|
856
460
|
|
|
857
|
-
|
|
858
|
-
result = SvgConform.validate_file('diagram.svg', profile: :svg_1_2_rfc)
|
|
461
|
+
==== Batch remediation workflow
|
|
859
462
|
|
|
860
|
-
|
|
861
|
-
puts "Valid: #{result.valid?}"
|
|
862
|
-
puts "Errors: #{result.errors.count}"
|
|
863
|
-
puts "Warnings: #{result.warnings.count}"
|
|
463
|
+
Fix all non-conforming files:
|
|
864
464
|
|
|
865
|
-
|
|
866
|
-
result.errors.each do |error|
|
|
867
|
-
puts "#{error.rule.id}: #{error.message}"
|
|
868
|
-
puts " Element: #{error.element}" if error.element
|
|
869
|
-
puts " Location: #{error.location}" if error.location
|
|
870
|
-
end
|
|
465
|
+
[source,bash]
|
|
871
466
|
----
|
|
467
|
+
# 1. Validate and identify issues
|
|
468
|
+
$ svg_conform check -d images/ -p metanorma --report-format=json \
|
|
469
|
+
--report-output=pre-fix-report.json
|
|
872
470
|
|
|
873
|
-
|
|
471
|
+
# 2. Apply fixes
|
|
472
|
+
$ svg_conform check -d images/ -p metanorma --fix --output-dir=fixed/ \
|
|
473
|
+
--manifest=manifest.json
|
|
874
474
|
|
|
875
|
-
|
|
475
|
+
# 3. Verify fixes
|
|
476
|
+
$ svg_conform check -d fixed/ -p metanorma --report-format=json \
|
|
477
|
+
--report-output=post-fix-report.json
|
|
876
478
|
----
|
|
877
|
-
# Create validator instance
|
|
878
|
-
validator = SvgConform::Validator.new
|
|
879
479
|
|
|
880
|
-
|
|
881
|
-
result = validator.validate_file('diagram.svg',
|
|
882
|
-
profile: :svg_1_2_rfc,
|
|
883
|
-
fix: true,
|
|
884
|
-
strict: false
|
|
885
|
-
)
|
|
480
|
+
==== Integration with CI/CD
|
|
886
481
|
|
|
887
|
-
|
|
888
|
-
if result.fixed?
|
|
889
|
-
fixed_svg = result.fixed_document.to_xml
|
|
890
|
-
File.write('diagram_fixed.svg', fixed_svg)
|
|
891
|
-
end
|
|
482
|
+
Validate SVGs in continuous integration:
|
|
892
483
|
|
|
893
|
-
|
|
894
|
-
profile_info = validator.profile_info(:svg_1_2_rfc)
|
|
895
|
-
puts "Profile: #{profile_info[:name]}"
|
|
896
|
-
puts "Description: #{profile_info[:description]}"
|
|
897
|
-
puts "Rules: #{profile_info[:rules].map { |r| r[:id] }.join(', ')}"
|
|
484
|
+
[source,bash]
|
|
898
485
|
----
|
|
486
|
+
$ svg_conform check -d docs/images/ -p metanorma --quiet
|
|
899
487
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
[source,ruby]
|
|
488
|
+
# Exit code 0 = pass, 1 = fail
|
|
903
489
|
----
|
|
904
|
-
# Parse SVG content
|
|
905
|
-
document = SvgConform::Document.from_content(svg_string)
|
|
906
490
|
|
|
907
|
-
|
|
908
|
-
root = document.root
|
|
909
|
-
puts "Root element: #{root.name}"
|
|
910
|
-
puts "Namespace: #{root.namespace}"
|
|
491
|
+
=== Complete reference
|
|
911
492
|
|
|
912
|
-
|
|
913
|
-
circles = document.find_elements('circle')
|
|
914
|
-
texts = document.find_elements('text')
|
|
493
|
+
See link:docs/cli_guide.adoc[CLI Guide] for comprehensive documentation including:
|
|
915
494
|
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
495
|
+
* All available profiles and their requirements
|
|
496
|
+
* Detailed option descriptions
|
|
497
|
+
* Advanced usage patterns
|
|
498
|
+
* Troubleshooting common issues
|
|
499
|
+
* Integration examples
|
|
920
500
|
|
|
921
|
-
# Get modified XML
|
|
922
|
-
modified_svg = fixer.to_xml
|
|
923
|
-
----
|
|
924
501
|
|
|
502
|
+
[[ruby_api_reference]]
|
|
503
|
+
== Ruby API reference
|
|
925
504
|
|
|
926
|
-
|
|
505
|
+
The SvgConform Ruby API provides programmatic access to SVG validation and remediation.
|
|
927
506
|
|
|
928
|
-
===
|
|
507
|
+
=== Basic validation
|
|
929
508
|
|
|
930
|
-
|
|
509
|
+
==== Using the validator
|
|
931
510
|
|
|
932
|
-
[source,
|
|
511
|
+
[source,ruby]
|
|
933
512
|
----
|
|
934
|
-
|
|
935
|
-
name: "Custom Profile"
|
|
936
|
-
description: "Custom SVG profile for specific requirements"
|
|
937
|
-
extends: "base" # Optional: inherit from another profile
|
|
513
|
+
require 'svg_conform'
|
|
938
514
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
type: "namespace_rule"
|
|
942
|
-
config:
|
|
943
|
-
required_namespace: "http://www.w3.org/2000/svg"
|
|
515
|
+
validator = SvgConform::Validator.new
|
|
516
|
+
result = validator.validate(svg_content, profile: :metanorma)
|
|
944
517
|
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
allowed_elements:
|
|
949
|
-
- "svg"
|
|
950
|
-
- "g"
|
|
951
|
-
- "rect"
|
|
952
|
-
- "circle"
|
|
953
|
-
- "path"
|
|
954
|
-
- "text"
|
|
518
|
+
puts "Valid: #{result.valid?}"
|
|
519
|
+
puts "Errors: #{result.errors.count}"
|
|
520
|
+
puts "Warnings: #{result.warnings.count}"
|
|
955
521
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
- "black"
|
|
962
|
-
- "white"
|
|
963
|
-
- "gray"
|
|
522
|
+
# Access error details
|
|
523
|
+
result.errors.each do |error|
|
|
524
|
+
puts "#{error.requirement_id}: #{error.message}"
|
|
525
|
+
puts " Location: #{error.element}" if error.element
|
|
526
|
+
end
|
|
964
527
|
----
|
|
965
528
|
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
TODO.
|
|
969
|
-
|
|
970
|
-
=== Remediation configuration
|
|
971
|
-
|
|
972
|
-
TODO.
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
== Extending SvgConform
|
|
529
|
+
==== Loading profiles
|
|
976
530
|
|
|
977
|
-
|
|
531
|
+
Load a profile by name:
|
|
978
532
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
533
|
+
[source,ruby]
|
|
534
|
+
----
|
|
535
|
+
profile = SvgConform::Profiles.get(:svg_1_2_rfc)
|
|
982
536
|
----
|
|
983
|
-
# config/profiles/my_organization.yml
|
|
984
|
-
profile:
|
|
985
|
-
name: "My Organization SVG Profile"
|
|
986
|
-
description: "SVG profile for internal use"
|
|
987
|
-
import: "base" # Optional: inherit from another profile
|
|
988
|
-
|
|
989
|
-
requirements:
|
|
990
|
-
- id: "namespace"
|
|
991
|
-
type: "NamespaceRequirement"
|
|
992
|
-
description: "Ensure proper SVG namespace"
|
|
993
537
|
|
|
994
|
-
|
|
995
|
-
type: "CustomRequirement"
|
|
996
|
-
description: "Validate custom elements"
|
|
997
|
-
config:
|
|
998
|
-
custom_option: "organization_value"
|
|
538
|
+
Available built-in profiles:
|
|
999
539
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
540
|
+
* `:base` - Minimal SVG validation
|
|
541
|
+
* `:svg_1_2_rfc` - RFC 7996 compliance (IETF XMLRFC documents)
|
|
542
|
+
* `:svg_1_2_rfc_with_rdf` - RFC 7996 with RDF metadata support
|
|
543
|
+
* `:metanorma` - Metanorma document requirements
|
|
544
|
+
* `:lucid` - Lucid profile
|
|
545
|
+
* `:no_external_css` - Disallow external CSS
|
|
1003
546
|
|
|
1004
|
-
|
|
1005
|
-
- id: "fix_namespace"
|
|
1006
|
-
type: "NamespaceRemediationAction"
|
|
1007
|
-
description: "Add missing SVG namespace"
|
|
1008
|
-
targets: ["namespace"]
|
|
547
|
+
Load a custom profile from file:
|
|
1009
548
|
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
targets: ["custom_requirement"]
|
|
1014
|
-
config:
|
|
1015
|
-
default_value: "organization_default"
|
|
549
|
+
[source,ruby]
|
|
550
|
+
----
|
|
551
|
+
profile = SvgConform::Profile.load_from_file('path/to/profile.yml')
|
|
1016
552
|
----
|
|
1017
553
|
|
|
1018
|
-
|
|
554
|
+
==== Validating with profiles
|
|
1019
555
|
|
|
1020
556
|
[source,ruby]
|
|
1021
557
|
----
|
|
1022
|
-
|
|
1023
|
-
profile = SvgConform::Profile.load_from_file('config/profiles/my_organization.yml')
|
|
558
|
+
profile = SvgConform::Profiles.get(:metanorma)
|
|
1024
559
|
document = SvgConform::Document.new(svg_content)
|
|
1025
560
|
result = profile.validate(document)
|
|
1026
561
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
puts "
|
|
562
|
+
if result.valid?
|
|
563
|
+
puts "SVG is valid!"
|
|
564
|
+
else
|
|
565
|
+
puts "Found #{result.errors.count} errors"
|
|
1031
566
|
end
|
|
1032
567
|
----
|
|
1033
568
|
|
|
1034
|
-
|
|
1035
|
-
== External compliance
|
|
1036
|
-
|
|
1037
|
-
=== General
|
|
569
|
+
=== Applying remediations
|
|
1038
570
|
|
|
1039
|
-
|
|
1040
|
-
and comparison with external SVG validation tools.
|
|
571
|
+
==== Basic remediation
|
|
1041
572
|
|
|
1042
|
-
|
|
1043
|
-
assessment of compatibility with external SVG validation tools. This supports
|
|
1044
|
-
migration workflows and quality assurance processes.
|
|
1045
|
-
|
|
1046
|
-
=== svgcheck
|
|
1047
|
-
|
|
1048
|
-
IETF provides the `svgcheck` tool, a Python-based SVG validator and fixer
|
|
1049
|
-
that checks SVG files against the SVG 1.2 RFC profile defined in RFC 7996.
|
|
1050
|
-
|
|
1051
|
-
SvgConform supports validation compatibility testing against the IETF Python
|
|
1052
|
-
svgcheck tool for SVG 1.2 RFC validation.
|
|
1053
|
-
|
|
1054
|
-
SvgConform includes a compatibility analysis feature that compares its
|
|
1055
|
-
validation results with those of `svgcheck`, helping users identify any
|
|
1056
|
-
discrepancies or issues.
|
|
1057
|
-
|
|
1058
|
-
IMPORTANT: As of version 2025-10-12, SvgConform's SVG 1.2 RFC profile provides a
|
|
1059
|
-
100% match in check and repair modes of svgcheck for all test files, except for
|
|
1060
|
-
the `full-tiny.svg` file, which svgcheck marks as invalid and fails to repair.
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
=== svgcheck testing workflow
|
|
1064
|
-
|
|
1065
|
-
The external compliance testing workflow involves generating reference outputs
|
|
1066
|
-
from external tools and comparing validation results:
|
|
1067
|
-
|
|
1068
|
-
[source,bash]
|
|
573
|
+
[source,ruby]
|
|
1069
574
|
----
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
# 2. Generate comparison reports
|
|
1074
|
-
svg_conform svgcheck compatibility --output comparison_report.json
|
|
1075
|
-
----
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
=== svgcheck compatibility architecture
|
|
1079
|
-
|
|
1080
|
-
SvgConform provides compatibility with the IETF Python svgcheck tool through a
|
|
1081
|
-
sophisticated mapping and comparison system that enables validation against the
|
|
1082
|
-
SVG 1.2 RFC profile.
|
|
1083
|
-
|
|
1084
|
-
.Architecture of svgcheck compatibility checks
|
|
1085
|
-
[source]
|
|
1086
|
-
----
|
|
1087
|
-
╭────────────────────────────────────────────────────────────────╮
|
|
1088
|
-
│ svgcheck Compatibility System │
|
|
1089
|
-
│ (SvgConform ↔ svgcheck Python tool) │
|
|
1090
|
-
├────────────────────────────────────────────────────────────────┤
|
|
1091
|
-
│ │
|
|
1092
|
-
│ ╭─────────────╮ ╭─────────────────────────────────────╮ │
|
|
1093
|
-
│ │ svgcheck │ │ YAML Mapping │ │
|
|
1094
|
-
│ │ Raw Errors │───▶│ config/svgcheck_mapping.yml │ │
|
|
1095
|
-
│ │ (Python) │ │ │ │
|
|
1096
|
-
│ ╰─────────────╯ │ • Pattern matching with regex │ │
|
|
1097
|
-
│ │ • Requirement categorization │ │
|
|
1098
|
-
│ │ • Semantic meaning extraction │ │
|
|
1099
|
-
│ │ • Unmapped error detection │ │
|
|
1100
|
-
│ ╰─────────────┬───────────────────────╯ │
|
|
1101
|
-
│ │ │
|
|
1102
|
-
│ ╭────────────────────────────────▼────────────────────────╮ │
|
|
1103
|
-
│ │ SvgcheckParser │ │
|
|
1104
|
-
│ │ │ │
|
|
1105
|
-
│ │ • Applies YAML mapping during parsing │ │
|
|
1106
|
-
│ │ • Categorizes errors by requirement │ │
|
|
1107
|
-
│ │ • Marks unmapped errors for RED display │ │
|
|
1108
|
-
│ │ • Creates properly structured ConformanceReport │ │
|
|
1109
|
-
│ ╰─────────────────────────┬───────────────────────────────╯ │
|
|
1110
|
-
│ │ │
|
|
1111
|
-
│ ▼ │
|
|
1112
|
-
│ ╭─────────────────────────────────────────────────────────╮ │
|
|
1113
|
-
│ │ Parallel Processing │ │
|
|
1114
|
-
│ │ │ │
|
|
1115
|
-
│ │ ╭─────────────────────╮ ╭─────────────────────────╮ │ │
|
|
1116
|
-
│ │ │ SvgConform │ │ svgcheck │ │ │
|
|
1117
|
-
│ │ │ Validation │ │ ConformanceReport │ │ │
|
|
1118
|
-
│ │ │ │ │ (mapped) │ │ │
|
|
1119
|
-
│ │ │ • Native Ruby │ │ • Parsed from YAML │ │ │
|
|
1120
|
-
│ │ │ • Direct profile │ │ • Requirement-mapped │ │ │
|
|
1121
|
-
│ │ │ • ConformanceReport │ │ • Compatible structure │ │ │
|
|
1122
|
-
│ │ ╰─────────────────────╯ ╰─────────────────────────╯ │ │
|
|
1123
|
-
│ ╰─────────────┬───────────────────────┬───────────────────╯ │
|
|
1124
|
-
│ │ │ │
|
|
1125
|
-
│ └───────────┬───────────┘ │
|
|
1126
|
-
│ │ │
|
|
1127
|
-
│ ╭─────────────────────────▼─────────────────────────╮ │
|
|
1128
|
-
│ │ ReportComparator │ │
|
|
1129
|
-
│ │ │ │
|
|
1130
|
-
│ │ • Direct ConformanceReport comparison │ │
|
|
1131
|
-
│ │ • Unified requirement-based display │ │
|
|
1132
|
-
│ │ • Side-by-side error mapping │ │
|
|
1133
|
-
│ │ • 🚨 RED highlighting for unmapped errors │ │
|
|
1134
|
-
│ │ • Compatibility metrics and analysis │ │
|
|
1135
|
-
│ ╰───────────────────────────────────────────────────╯ │
|
|
1136
|
-
│ │
|
|
1137
|
-
╰────────────────────────────────────────────────────────────────╯
|
|
1138
|
-
----
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
=== svgcheck compatibility commands
|
|
1142
|
-
|
|
1143
|
-
==== General
|
|
1144
|
-
|
|
1145
|
-
In order to run the compatibility commands, you need to have the `svgcheck` tool
|
|
1146
|
-
installed and accessible in your PATH.
|
|
1147
|
-
|
|
1148
|
-
NOTE: The `svgcheck` tool can be installed via `pip install svgcheck`.
|
|
1149
|
-
|
|
1150
|
-
The commands in this section provide functionality to generate svgcheck outputs
|
|
1151
|
-
for test files and perform compatibility analysis between SvgConform and svgcheck
|
|
1152
|
-
results.
|
|
1153
|
-
|
|
1154
|
-
The test files from svgcheck are included in the SvgConform repository under
|
|
1155
|
-
`spec/fixtures/svgcheck` to ensure consistent testing.
|
|
1156
|
-
|
|
1157
|
-
The mapping configuration file `config/svgcheck_mapping.yml` defines how
|
|
1158
|
-
svgcheck error messages are interpreted and mapped to SvgConform requirements.
|
|
1159
|
-
|
|
1160
|
-
The data flow steps for compatibility analysis is as follows:
|
|
1161
|
-
|
|
1162
|
-
. svgcheck outputs are generated for test files using the `svgcheck generate` command.
|
|
1163
|
-
|
|
1164
|
-
. For each test file, svgcheck outputs are generated in both check-only and
|
|
1165
|
-
repair modes through the `svgcheck generate` command, and are then parsed by the
|
|
1166
|
-
`Svgcheck::Parser` class into the `ReportGenerator` class.
|
|
1167
|
-
|
|
1168
|
-
. SvgConform validates the same test files using the SVG 1.2 RFC profile, which provides
|
|
1169
|
-
a `ConformanceReport` object.
|
|
1170
|
-
|
|
1171
|
-
. The `ReportComparator` class compares the `ConformanceReport` from SvgConform
|
|
1172
|
-
with the svgcheck `ReportGenerator` results. The `ReportComparator` handles
|
|
1173
|
-
both check-only and repair mode outputs, and maps svgcheck messages to SvgConform
|
|
1174
|
-
requirements and remediations outcomes.
|
|
1175
|
-
|
|
1176
|
-
. A detailed comparison report is generated, highlighting matches and discrepancies.
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
==== `svg_conform svgcheck compatibility`
|
|
1181
|
-
|
|
1182
|
-
The `svgcheck compatibility` command performs a comprehensive compatibility analysis
|
|
1183
|
-
between SvgConform validation results and the IETF `svgcheck` tool output.
|
|
575
|
+
profile = SvgConform::Profiles.get(:metanorma)
|
|
576
|
+
document = SvgConform::Document.from_file('input.svg')
|
|
1184
577
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
svg_conform svgcheck compatibility [OPTIONS] [FILE]
|
|
578
|
+
# Apply all remediations defined in the profile
|
|
579
|
+
changes = profile.apply_remediations(document)
|
|
1188
580
|
|
|
1189
|
-
|
|
1190
|
-
-p, --profile PROFILE Profile to use (default: svg_1_2_rfc)
|
|
1191
|
-
-f, --file FILE Analyze specific file instead of all test files
|
|
1192
|
-
-o, --output FILE Output clean report to file (no color codes)
|
|
1193
|
-
-v, --verbose Verbose output
|
|
1194
|
-
----
|
|
581
|
+
puts "Applied #{changes.length} remediations"
|
|
1195
582
|
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
[source,bash]
|
|
583
|
+
# Save the remediated SVG
|
|
584
|
+
File.write('output.svg', document.to_xml)
|
|
1199
585
|
----
|
|
1200
|
-
# Run comprehensive compatibility analysis
|
|
1201
|
-
svg_conform svgcheck compatibility
|
|
1202
586
|
|
|
1203
|
-
|
|
1204
|
-
svg_conform svgcheck compatibility --file example.svg
|
|
587
|
+
==== Using the remediation runner
|
|
1205
588
|
|
|
1206
|
-
|
|
1207
|
-
svg_conform svgcheck compatibility --output compatibility-report.md
|
|
589
|
+
For more control over the remediation process:
|
|
1208
590
|
|
|
1209
|
-
|
|
1210
|
-
svg_conform svgcheck compatibility --file example.svg --output analysis.md
|
|
591
|
+
[source,ruby]
|
|
1211
592
|
----
|
|
1212
|
-
|
|
593
|
+
profile = SvgConform::Profiles.get(:metanorma)
|
|
594
|
+
runner = SvgConform::RemediationRunner.new(profile: profile)
|
|
1213
595
|
|
|
596
|
+
# Run remediation on a file
|
|
597
|
+
result = runner.run_remediation_file('input.svg')
|
|
1214
598
|
|
|
1215
|
-
|
|
599
|
+
if result.success?
|
|
600
|
+
File.write('output.svg', result.remediated_content)
|
|
601
|
+
puts "Fixed #{result.issues_fixed} issues"
|
|
602
|
+
puts "Final validation: #{result.final_validation.valid?}"
|
|
603
|
+
else
|
|
604
|
+
puts "Remediation failed: #{result.error.message}"
|
|
605
|
+
end
|
|
606
|
+
----
|
|
1216
607
|
|
|
1217
|
-
|
|
1218
|
-
facilitate compatibility analysis.
|
|
608
|
+
==== Checking available remediations
|
|
1219
609
|
|
|
1220
|
-
|
|
1221
|
-
|
|
610
|
+
[source,ruby]
|
|
611
|
+
----
|
|
612
|
+
profile = SvgConform::Profiles.get(:metanorma)
|
|
1222
613
|
|
|
614
|
+
puts "Profile has #{profile.remediation_count} remediations available"
|
|
1223
615
|
|
|
1224
|
-
|
|
616
|
+
profile.remediations.each do |remediation|
|
|
617
|
+
puts "- #{remediation.class.name}"
|
|
618
|
+
end
|
|
1225
619
|
----
|
|
1226
|
-
Usage:
|
|
1227
|
-
svg_conform svgcheck generate SVGCHECK_REPO_PATH
|
|
1228
|
-
|
|
1229
|
-
Options:
|
|
1230
|
-
-m, [--mode=MODE] # Generation mode: check, repair, or both
|
|
1231
|
-
# Default: both
|
|
1232
|
-
# Possible values: check, repair, both
|
|
1233
|
-
[--svgcheck-exec=SVGCHECK_EXEC] # Path to svgcheck executable
|
|
1234
|
-
[--fixtures-path=FIXTURES_PATH] # Output directory (default: spec/fixtures/svgcheck)
|
|
1235
|
-
-f, [--single-file=SINGLE_FILE] # Process single file only
|
|
1236
|
-
[--force] # Overwrite existing outputs
|
|
1237
|
-
# Default: false
|
|
1238
|
-
-v, [--verbose], [--no-verbose], [--skip-verbose] # Verbose output
|
|
1239
|
-
# Default: false
|
|
1240
620
|
|
|
1241
|
-
|
|
1242
|
-
Generate svgcheck outputs for test files by running svgcheck on them.
|
|
621
|
+
=== Working with documents
|
|
1243
622
|
|
|
1244
|
-
|
|
623
|
+
==== Creating documents
|
|
1245
624
|
|
|
1246
|
-
|
|
1247
|
-
outputs in separate subdirectories.
|
|
625
|
+
From a string:
|
|
1248
626
|
|
|
1249
|
-
|
|
1250
|
-
|
|
627
|
+
[source,ruby]
|
|
628
|
+
----
|
|
629
|
+
document = SvgConform::Document.new(svg_string)
|
|
1251
630
|
----
|
|
1252
631
|
|
|
1253
|
-
|
|
1254
|
-
enabling comprehensive compatibility testing and analysis. By default, it
|
|
1255
|
-
generates both check and repair outputs in separate subdirectories.
|
|
1256
|
-
|
|
1257
|
-
The command creates a structured output directory with separate subdirectories
|
|
1258
|
-
for different svgcheck modes:
|
|
632
|
+
From a file:
|
|
1259
633
|
|
|
1260
|
-
[source]
|
|
634
|
+
[source,ruby]
|
|
1261
635
|
----
|
|
1262
|
-
|
|
1263
|
-
├── check/ # Check-only outputs (validation without remediation)
|
|
1264
|
-
│ ├── file1.svg.out # Validation messages from svgcheck
|
|
1265
|
-
│ ├── file1.svg.err # Error messages from svgcheck
|
|
1266
|
-
│ └── file1.svg.code # Exit status from svgcheck
|
|
1267
|
-
└── repair/ # Repair outputs (validation + remediation)
|
|
1268
|
-
├── file1.svg.out # Validation messages from svgcheck
|
|
1269
|
-
├── file1.svg.err # Error messages from svgcheck
|
|
1270
|
-
├── file1.svg.code # Exit status from svgcheck
|
|
1271
|
-
└── file1.svg.file # Remediated SVG content
|
|
636
|
+
document = SvgConform::Document.from_file('path/to/file.svg')
|
|
1272
637
|
----
|
|
1273
638
|
|
|
1274
|
-
|
|
1275
|
-
which is defined in `svgcheck_generate.rb`:
|
|
1276
|
-
|
|
1277
|
-
* svgcheck `full-tiny.xml` is renamed to `full-tiny.svg`
|
|
1278
|
-
* svgcheck `rfc-svg.xml` is renamed to `rfc-svg.svg`
|
|
1279
|
-
|
|
1280
|
-
The generated outputs are used by the `compatibility` command to perform
|
|
1281
|
-
detailed comparisons between SvgConform and svgcheck validation results. The
|
|
1282
|
-
structured directory layout enables:
|
|
1283
|
-
|
|
1284
|
-
- **Targeted analysis**: Compare check-only vs repair mode behaviors
|
|
1285
|
-
- **Comprehensive testing**: Validate against both validation and remediation workflows
|
|
1286
|
-
- **Regression testing**: Track changes in svgcheck behavior over time
|
|
1287
|
-
- **Profile development**: Use svgcheck outputs as reference for profile refinement
|
|
639
|
+
From a DOM node (Nokogiri or Moxml):
|
|
1288
640
|
|
|
641
|
+
[source,ruby]
|
|
642
|
+
----
|
|
643
|
+
nokogiri_element = Nokogiri::XML(svg_string).root
|
|
644
|
+
document = SvgConform::Document.from_node(nokogiri_element)
|
|
645
|
+
----
|
|
1289
646
|
|
|
1290
|
-
|
|
647
|
+
==== Document operations
|
|
1291
648
|
|
|
1292
|
-
|
|
649
|
+
[source,ruby]
|
|
650
|
+
----
|
|
651
|
+
# Access the underlying DOM
|
|
652
|
+
root = document.root
|
|
653
|
+
elements = document.find_all('//svg:rect')
|
|
1293
654
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
- Generates `.out`, `.err`, and `.code` files
|
|
1297
|
-
- No remediated content is produced
|
|
655
|
+
# Check for specific elements
|
|
656
|
+
has_viewbox = document.root.attribute?('viewBox')
|
|
1298
657
|
|
|
1299
|
-
|
|
658
|
+
# Modify the document
|
|
659
|
+
document.root.set_attribute('width', '500')
|
|
1300
660
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
- The `.file` contains the remediated SVG content
|
|
661
|
+
# Serialize to XML
|
|
662
|
+
xml_string = document.to_xml
|
|
663
|
+
----
|
|
1305
664
|
|
|
1306
|
-
|
|
665
|
+
=== Reference manifest
|
|
1307
666
|
|
|
1308
|
-
|
|
1309
|
-
- Generates complete output sets in both subdirectories
|
|
1310
|
-
- Provides comprehensive data for compatibility analysis
|
|
667
|
+
==== Accessing the manifest
|
|
1311
668
|
|
|
1312
|
-
[source,
|
|
669
|
+
[source,ruby]
|
|
1313
670
|
----
|
|
1314
|
-
|
|
1315
|
-
|
|
671
|
+
result = validator.validate(svg_content, profile: :metanorma)
|
|
672
|
+
manifest = result.reference_manifest
|
|
1316
673
|
|
|
1317
|
-
#
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
svg_conform svgcheck generate /path/to/svgcheck-reference --single-file example.svg --verbose
|
|
674
|
+
# Get all defined IDs
|
|
675
|
+
manifest.available_ids.each do |id_def|
|
|
676
|
+
puts "ID: #{id_def.id_value}"
|
|
677
|
+
puts " Element: #{id_def.element_name}"
|
|
678
|
+
puts " Line: #{id_def.line_number}"
|
|
679
|
+
end
|
|
680
|
+
----
|
|
1325
681
|
|
|
1326
|
-
|
|
1327
|
-
svg_conform svgcheck generate /path/to/svgcheck-reference --force
|
|
682
|
+
==== Checking references
|
|
1328
683
|
|
|
1329
|
-
|
|
1330
|
-
svg_conform svgcheck generate /path/to/svgcheck-reference --fixtures-path /path/to/custom/output
|
|
684
|
+
[source,ruby]
|
|
1331
685
|
----
|
|
686
|
+
# Check for unresolved internal references
|
|
687
|
+
if result.has_unresolved_references?
|
|
688
|
+
puts "Unresolved references found:"
|
|
689
|
+
result.unresolved_internal_references.each do |ref|
|
|
690
|
+
puts " #{ref.value} at line #{ref.line_number}"
|
|
691
|
+
end
|
|
692
|
+
end
|
|
1332
693
|
|
|
694
|
+
# Check for external references
|
|
695
|
+
if result.has_external_references?
|
|
696
|
+
puts "External references:"
|
|
697
|
+
result.external_references.each do |ref|
|
|
698
|
+
puts " #{ref.value} (#{ref.reference_type})"
|
|
699
|
+
end
|
|
700
|
+
end
|
|
701
|
+
----
|
|
1333
702
|
|
|
703
|
+
==== Reference types
|
|
1334
704
|
|
|
1335
|
-
|
|
705
|
+
The manifest classifies references by type:
|
|
1336
706
|
|
|
1337
|
-
|
|
1338
|
-
|
|
707
|
+
[source,ruby]
|
|
708
|
+
----
|
|
709
|
+
manifest.internal_references.each do |ref|
|
|
710
|
+
case ref.reference_type
|
|
711
|
+
when 'url'
|
|
712
|
+
puts "URL reference: #{ref.value}"
|
|
713
|
+
when 'fragment'
|
|
714
|
+
puts "Fragment reference: #{ref.value}"
|
|
715
|
+
when 'fill'
|
|
716
|
+
puts "Fill attribute: #{ref.value}"
|
|
717
|
+
when 'href'
|
|
718
|
+
puts "Href attribute: #{ref.value}"
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
----
|
|
1339
722
|
|
|
1340
|
-
|
|
1341
|
-
to the IETF svgcheck tool.
|
|
723
|
+
=== Advanced usage
|
|
1342
724
|
|
|
1343
|
-
|
|
725
|
+
==== Custom validation context
|
|
1344
726
|
|
|
1345
|
-
[source,
|
|
727
|
+
[source,ruby]
|
|
1346
728
|
----
|
|
1347
|
-
|
|
729
|
+
context = SvgConform::ValidationContext.new(
|
|
730
|
+
document: document,
|
|
731
|
+
profile: profile
|
|
732
|
+
)
|
|
1348
733
|
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
734
|
+
# Run specific requirements
|
|
735
|
+
requirement = SvgConform::Requirements::ViewboxRequiredRequirement.new
|
|
736
|
+
errors = requirement.check(context)
|
|
1352
737
|
----
|
|
1353
738
|
|
|
1354
|
-
|
|
1355
|
-
====
|
|
1356
|
-
[source,bash]
|
|
1357
|
-
----
|
|
1358
|
-
# Compare with auto-detected svgcheck report
|
|
1359
|
-
$ svg_conform svgcheck compare diagram.svg -p svg_1_2_rfc
|
|
739
|
+
==== Batch processing
|
|
1360
740
|
|
|
1361
|
-
|
|
1362
|
-
$ svg_conform svgcheck compare diagram.svg --svgcheck-report diagram.svg.svgcheck.yaml
|
|
741
|
+
[source,ruby]
|
|
1363
742
|
----
|
|
1364
|
-
|
|
1365
|
-
|
|
743
|
+
validator = SvgConform::Validator.new
|
|
744
|
+
results = {}
|
|
1366
745
|
|
|
746
|
+
Dir.glob('images/**/*.svg').each do |file|
|
|
747
|
+
result = validator.validate_file(file, profile: :metanorma)
|
|
748
|
+
results[file] = result
|
|
749
|
+
end
|
|
1367
750
|
|
|
1368
|
-
|
|
751
|
+
# Summary
|
|
752
|
+
valid_count = results.count { |_, r| r.valid? }
|
|
753
|
+
puts "#{valid_count}/#{results.size} files are valid"
|
|
754
|
+
----
|
|
1369
755
|
|
|
1370
|
-
|
|
756
|
+
==== Report generation
|
|
1371
757
|
|
|
1372
|
-
|
|
1373
|
-
|
|
758
|
+
[source,ruby]
|
|
759
|
+
----
|
|
760
|
+
# Create a conformance report
|
|
761
|
+
report = SvgConform::ConformanceReport.from_svg_conform_result(
|
|
762
|
+
"file.svg",
|
|
763
|
+
result,
|
|
764
|
+
profile: :metanorma
|
|
765
|
+
)
|
|
1374
766
|
|
|
1375
|
-
|
|
767
|
+
# Export as JSON
|
|
768
|
+
json_output = report.to_json
|
|
769
|
+
File.write('report.json', json_output)
|
|
1376
770
|
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
771
|
+
# Export as YAML
|
|
772
|
+
yaml_output = report.to_yaml
|
|
773
|
+
File.write('report.yaml', yaml_output)
|
|
774
|
+
----
|
|
1380
775
|
|
|
1381
|
-
|
|
776
|
+
=== API classes
|
|
1382
777
|
|
|
1383
|
-
|
|
1384
|
-
* 4.57 MB file: >60s → 1.37s (40x faster)
|
|
1385
|
-
* 3.44 MB file: >60s → 0.29s (200x faster)
|
|
778
|
+
==== Core classes
|
|
1386
779
|
|
|
1387
|
-
|
|
780
|
+
* `SvgConform::Validator` - Main validation interface
|
|
781
|
+
* `SvgConform::Profile` - Profile definition and management
|
|
782
|
+
* `SvgConform::Document` - SVG document wrapper
|
|
783
|
+
* `SvgConform::ValidationResult` - Validation result container
|
|
784
|
+
* `SvgConform::RemediationRunner` - Remediation execution
|
|
1388
785
|
|
|
1389
|
-
|
|
1390
|
-
in memory. This provides:
|
|
786
|
+
==== Requirement classes
|
|
1391
787
|
|
|
1392
|
-
|
|
1393
|
-
* Constant memory: No full DOM tree in memory
|
|
1394
|
-
* Predictable performance: O(n) complexity guaranteed
|
|
1395
|
-
* No object identity issues: Path-based node identification
|
|
788
|
+
Located in `SvgConform::Requirements`:
|
|
1396
789
|
|
|
1397
|
-
|
|
790
|
+
* `AllowedElementsRequirement` - Element whitelist validation
|
|
791
|
+
* `ColorRestrictionsRequirement` - Color format restrictions
|
|
792
|
+
* `FontFamilyRequirement` - Font family restrictions
|
|
793
|
+
* `ForbiddenContentRequirement` - Forbidden element/attribute check
|
|
794
|
+
* `IdReferenceRequirement` - ID reference validation
|
|
795
|
+
* `InvalidIdReferencesRequirement` - Invalid reference detection
|
|
796
|
+
* `LinkValidationRequirement` - Link validation
|
|
797
|
+
* `NamespaceRequirement` - Namespace validation
|
|
798
|
+
* `NamespaceAttributesRequirement` - Namespace attribute check
|
|
799
|
+
* `NoExternalCssRequirement` - External CSS prohibition
|
|
800
|
+
* `NoExternalFontsRequirement` - External font prohibition
|
|
801
|
+
* `NoExternalImagesRequirement` - External image prohibition
|
|
802
|
+
* `StylePromotionRequirement` - Presentation attribute check
|
|
803
|
+
* `StyleRequirement` - Style attribute validation
|
|
804
|
+
* `ViewboxRequiredRequirement` - ViewBox requirement
|
|
1398
805
|
|
|
1399
|
-
|
|
1400
|
-
automatically used when remediation is requested (`fix: true`).
|
|
806
|
+
==== Remediation classes
|
|
1401
807
|
|
|
1402
|
-
|
|
1403
|
-
----
|
|
1404
|
-
# Default: SAX mode (best performance)
|
|
1405
|
-
validator = SvgConform::Validator.new
|
|
1406
|
-
result = validator.validate_file('large.svg', profile: :metanorma)
|
|
808
|
+
Located in `SvgConform::Remediations`:
|
|
1407
809
|
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
810
|
+
* `ColorRemediation` - Fix color format issues
|
|
811
|
+
* `FontRemediation` - Fix font family issues
|
|
812
|
+
* `FontEmbeddingRemediation` - Embed external fonts
|
|
813
|
+
* `ImageEmbeddingRemediation` - Embed external images
|
|
814
|
+
* `InvalidIdReferencesRemediation` - Fix invalid references
|
|
815
|
+
* `NamespaceRemediation` - Fix namespace issues
|
|
816
|
+
* `NamespaceAttributeRemediation` - Remove namespace attributes
|
|
817
|
+
* `NoExternalCssRemediation` - Convert external CSS
|
|
818
|
+
* `StylePromotionRemediation` - Promote presentation attributes
|
|
819
|
+
* `ViewboxRemediation` - Add missing ViewBox
|
|
1413
820
|
|
|
1414
|
-
|
|
821
|
+
=== Complete reference
|
|
1415
822
|
|
|
1416
|
-
|
|
1417
|
-
(94.7% parity). The one exception is `full-tiny.svg`, a comprehensive test file
|
|
1418
|
-
with known architectural differences.
|
|
823
|
+
See link:docs/api_reference.adoc[API Reference] for comprehensive documentation including:
|
|
1419
824
|
|
|
825
|
+
* Complete class hierarchy
|
|
826
|
+
* Detailed method signatures
|
|
827
|
+
* Parameter descriptions
|
|
828
|
+
* Return value specifications
|
|
829
|
+
* Integration patterns
|
|
830
|
+
* Advanced examples
|
|
1420
831
|
|
|
1421
832
|
|
|
1422
|
-
|
|
833
|
+
[[external_compliance]]
|
|
834
|
+
== External compliance
|
|
1423
835
|
|
|
1424
|
-
|
|
836
|
+
SvgConform provides compatibility with existing SVG validation tools:
|
|
1425
837
|
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
bundle exec rspec
|
|
1429
|
-
----
|
|
838
|
+
* **SVGCheck**: 100% error report matching with Python svgcheck tool
|
|
839
|
+
* Profile compatibility modes for different validation tools
|
|
1430
840
|
|
|
1431
|
-
|
|
841
|
+
See link:docs/compatibility.adoc[Compatibility Documentation] for details.
|
|
1432
842
|
|
|
1433
|
-
[source,bash]
|
|
1434
|
-
----
|
|
1435
|
-
# Unit tests
|
|
1436
|
-
bundle exec rspec spec/unit/
|
|
1437
843
|
|
|
1438
|
-
|
|
1439
|
-
bundle exec rspec spec/integration/
|
|
844
|
+
== Development
|
|
1440
845
|
|
|
1441
|
-
|
|
1442
|
-
bundle exec rspec spec/svgcheck_compatibility_spec.rb
|
|
1443
|
-
----
|
|
846
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
|
1444
847
|
|
|
848
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
1445
849
|
|
|
1446
|
-
== Changelog
|
|
1447
850
|
|
|
1448
|
-
|
|
851
|
+
== Contributing
|
|
1449
852
|
|
|
853
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/metanorma/svg_conform.
|
|
1450
854
|
|
|
1451
|
-
== Copyright and license
|
|
1452
855
|
|
|
1453
|
-
|
|
856
|
+
== License
|
|
1454
857
|
|
|
1455
|
-
|
|
1456
|
-
license.
|
|
858
|
+
The gem is available as open source under the terms of the BSD 2-Clause License.
|