suma 0.5.8 → 0.5.10
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/.github/workflows/release-provenance.yml +5 -2
- data/.rubocop_todo.yml +27 -0
- data/CLAUDE.md +17 -5
- data/README.adoc +237 -11
- data/lib/suma/anchor_validator.rb +85 -0
- data/lib/suma/artifact_server.rb +102 -0
- data/lib/suma/cli/artifact_server_cli.rb +22 -0
- data/lib/suma/cli/build.rb +4 -0
- data/lib/suma/cli/core.rb +50 -4
- data/lib/suma/cli/export.rb +1 -1
- data/lib/suma/cli/extract_terms.rb +1 -1
- data/lib/suma/cli/generate_register.rb +1 -1
- data/lib/suma/cli/ingest_translations.rb +36 -0
- data/lib/suma/cli/package_gcr.rb +51 -0
- data/lib/suma/cli/validate.rb +16 -0
- data/lib/suma/cli.rb +4 -1
- data/lib/suma/closure_validator.rb +124 -20
- data/lib/suma/corpus_graph.rb +79 -16
- data/lib/suma/gcr_package.rb +230 -0
- data/lib/suma/link_validation_result.rb +8 -0
- data/lib/suma/link_validator.rb +0 -3
- data/lib/suma/output_canonicalizer.rb +107 -0
- data/lib/suma/processor.rb +94 -20
- data/lib/suma/provenance.rb +92 -12
- data/lib/suma/schema_collection.rb +1 -0
- data/lib/suma/schema_compiler.rb +79 -13
- data/lib/suma/schema_manifest_generator.rb +10 -3
- data/lib/suma/schema_profile.rb +12 -0
- data/lib/suma/schema_template/anchors.rb +154 -0
- data/lib/suma/schema_template/document.rb +2 -93
- data/lib/suma/schema_template/plain.rb +10 -6
- data/lib/suma/schema_template.rb +1 -0
- data/lib/suma/site_build.rb +153 -0
- data/lib/suma/staged_collection_builder.rb +11 -3
- data/lib/suma/translation_ingester.rb +169 -0
- data/lib/suma/urn_resolver.rb +51 -1
- data/lib/suma/version.rb +1 -1
- data/lib/suma.rb +7 -0
- metadata +13 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 01e0b1dd212172912b654cac481e0ce1eea1efee1275f45d4332c0a6bbb28e69
|
|
4
|
+
data.tar.gz: 54399e492be26b0a09595debdc61c256f566da28ed13ca002cae2a6eb0925b57
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fb0aebf85233af1df6162efb518605bd7ab01c7396e7af6012144fd05c74a135ba7d2833b7bb633fa45c755e067d6799569412df0b21458b33d2730a5081a3a
|
|
7
|
+
data.tar.gz: d9836497a01e7711aece5c76534ecfa4e7e0876bfd414aab783ada288b1906e07a3f3b6994d17085f294b79a827c16ecb61bab7cf305a823b9527933e5aa7f1c
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
name: release-provenance
|
|
2
2
|
|
|
3
3
|
on:
|
|
4
|
-
release
|
|
5
|
-
|
|
4
|
+
# Tag pushes reliably fan out (the release workflow pushes v* tags with a
|
|
5
|
+
# PAT); release-published events created by CI tokens may not.
|
|
6
|
+
push:
|
|
7
|
+
tags:
|
|
8
|
+
- "v*"
|
|
6
9
|
workflow_dispatch:
|
|
7
10
|
|
|
8
11
|
permissions:
|
data/.rubocop_todo.yml
CHANGED
|
@@ -116,9 +116,11 @@ Lint/UnusedMethodArgument:
|
|
|
116
116
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
117
117
|
Metrics/AbcSize:
|
|
118
118
|
Exclude:
|
|
119
|
+
- 'lib/suma/gcr_package.rb'
|
|
119
120
|
- 'bin/benchmark_corpus'
|
|
120
121
|
- 'lib/suma/worker_pool.rb'
|
|
121
122
|
- 'spec/suma/reproducibility_spec.rb'
|
|
123
|
+
- 'spec/suma/cli/build_integration_spec.rb'
|
|
122
124
|
- 'lib/suma/cli/resolve.rb'
|
|
123
125
|
- 'lib/suma/urn_resolver.rb'
|
|
124
126
|
- 'lib/suma/cli/check_svg_quality.rb'
|
|
@@ -155,6 +157,8 @@ Metrics/BlockLength:
|
|
|
155
157
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
156
158
|
Metrics/CyclomaticComplexity:
|
|
157
159
|
Exclude:
|
|
160
|
+
- 'lib/suma/gcr_package.rb'
|
|
161
|
+
- 'lib/suma/corpus_graph.rb'
|
|
158
162
|
- 'lib/suma/worker_pool.rb'
|
|
159
163
|
- 'lib/suma/urn_resolver.rb'
|
|
160
164
|
- 'lib/suma/cli/check_svg_quality.rb'
|
|
@@ -172,6 +176,8 @@ Metrics/CyclomaticComplexity:
|
|
|
172
176
|
# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
173
177
|
Metrics/MethodLength:
|
|
174
178
|
Exclude:
|
|
179
|
+
- 'lib/suma/artifact_server.rb'
|
|
180
|
+
- 'lib/suma/gcr_package.rb'
|
|
175
181
|
- 'bin/benchmark_corpus'
|
|
176
182
|
- 'lib/suma/cli/build.rb'
|
|
177
183
|
- 'lib/suma/worker_pool.rb'
|
|
@@ -204,6 +210,7 @@ Metrics/MethodLength:
|
|
|
204
210
|
# Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters.
|
|
205
211
|
Metrics/ParameterLists:
|
|
206
212
|
Exclude:
|
|
213
|
+
- 'lib/suma/gcr_package.rb'
|
|
207
214
|
- 'lib/suma/processor.rb'
|
|
208
215
|
- 'lib/suma/express_schema.rb'
|
|
209
216
|
- 'lib/suma/term_extractor.rb'
|
|
@@ -216,6 +223,7 @@ Metrics/ParameterLists:
|
|
|
216
223
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
217
224
|
Metrics/PerceivedComplexity:
|
|
218
225
|
Exclude:
|
|
226
|
+
- 'lib/suma/gcr_package.rb'
|
|
219
227
|
- 'lib/suma/worker_pool.rb'
|
|
220
228
|
- 'lib/suma/eengine/wrapper.rb'
|
|
221
229
|
- 'lib/suma/jsdai/figure_image.rb'
|
|
@@ -259,6 +267,16 @@ RSpec/ContextWording:
|
|
|
259
267
|
# Configuration parameters: Max, CountAsOne.
|
|
260
268
|
RSpec/ExampleLength:
|
|
261
269
|
Exclude:
|
|
270
|
+
- 'spec/suma/site_build_spec.rb'
|
|
271
|
+
- 'spec/suma/output_canonicalizer_spec.rb'
|
|
272
|
+
- 'spec/suma/anchor_validator_spec.rb'
|
|
273
|
+
- 'spec/suma/translation_ingester_spec.rb'
|
|
274
|
+
- 'spec/suma/ifc_profile_pipeline_spec.rb'
|
|
275
|
+
- 'spec/suma/schema_manifest_generator_spec.rb'
|
|
276
|
+
- 'spec/suma/schema_naming_spec.rb'
|
|
277
|
+
- 'spec/suma/cli/build_integration_spec.rb'
|
|
278
|
+
- 'spec/suma/artifact_server_spec.rb'
|
|
279
|
+
- 'spec/suma/gcr_package_spec.rb'
|
|
262
280
|
- 'spec/suma/schema_cache_spec.rb'
|
|
263
281
|
- 'spec/suma/worker_pool_spec.rb'
|
|
264
282
|
- 'spec/suma/schema_collection_rebuild_targets_spec.rb'
|
|
@@ -338,6 +356,11 @@ RSpec/MessageSpies:
|
|
|
338
356
|
# Configuration parameters: Max.
|
|
339
357
|
RSpec/MultipleExpectations:
|
|
340
358
|
Exclude:
|
|
359
|
+
- 'spec/suma/site_build_spec.rb'
|
|
360
|
+
- 'spec/suma/output_canonicalizer_spec.rb'
|
|
361
|
+
- 'spec/suma/cli/build_integration_spec.rb'
|
|
362
|
+
- 'spec/suma/artifact_server_spec.rb'
|
|
363
|
+
- 'spec/suma/gcr_package_spec.rb'
|
|
341
364
|
- 'spec/suma/schema_cache_spec.rb'
|
|
342
365
|
- 'spec/suma/worker_pool_spec.rb'
|
|
343
366
|
- 'spec/suma/reproducibility_spec.rb'
|
|
@@ -400,11 +423,13 @@ RSpec/NestedGroups:
|
|
|
400
423
|
RSpec/DescribeClass:
|
|
401
424
|
Exclude:
|
|
402
425
|
- 'spec/suma/reproducibility_spec.rb'
|
|
426
|
+
- 'spec/suma/ifc_profile_pipeline_spec.rb'
|
|
403
427
|
|
|
404
428
|
RSpec/SpecFilePathFormat:
|
|
405
429
|
Exclude:
|
|
406
430
|
- '**/spec/routing/**/*'
|
|
407
431
|
- 'spec/suma/cli/expressir_spec.rb'
|
|
432
|
+
- 'spec/suma/ifc_profile_pipeline_spec.rb'
|
|
408
433
|
|
|
409
434
|
# Offense count: 1
|
|
410
435
|
RSpec/StubbedMock:
|
|
@@ -415,6 +440,8 @@ RSpec/StubbedMock:
|
|
|
415
440
|
# Configuration parameters: Max.
|
|
416
441
|
RSpec/MultipleMemoizedHelpers:
|
|
417
442
|
Exclude:
|
|
443
|
+
- 'spec/suma/ifc_profile_pipeline_spec.rb'
|
|
444
|
+
- 'spec/suma/gcr_package_spec.rb'
|
|
418
445
|
- 'spec/suma/provenance_spec.rb'
|
|
419
446
|
- 'spec/suma/worker_pool_spec.rb'
|
|
420
447
|
- 'spec/suma/schema_cache_spec.rb'
|
data/CLAUDE.md
CHANGED
|
@@ -37,11 +37,15 @@ exe/suma reformat PATH # Reformat EXP files (us
|
|
|
37
37
|
exe/suma generate-schemas METANORMA_YAML SCHEMAS_YAML # Generate schema manifest from site manifest
|
|
38
38
|
exe/suma extract-terms SCHEMA_YAML GLOSSARIST_DIR -u URN # Extract EXPRESS entity concepts to Glossarist v3 format
|
|
39
39
|
exe/suma extract-terms ... --edition 3 --language-codes fra deu # Provenance + linked localizations
|
|
40
|
+
exe/suma ingest-translations CONCEPTS_DIR TRANSLATIONS_FILE [-o OUT] # Overlay translated localized-concept content onto extracted concepts
|
|
40
41
|
exe/suma resolve URN --manifest SCHEMAS_YAML --concepts DIR --register register.yaml -o OUT # Emit canonical JSON + HTML
|
|
41
42
|
exe/suma resolve --all --manifest SCHEMAS_YAML --concepts DIR --register register.yaml -o OUT # Emit every URN artifact
|
|
43
|
+
exe/suma package-gcr CONCEPTS_DIR --register register.yaml --shortname ID --version V --title T --description D -o OUT # Package concepts into a .gcr archive
|
|
44
|
+
exe/suma serve ARTIFACTS_DIR --port 2113 # Serve resolved URN artifacts with Accept negotiation
|
|
42
45
|
exe/suma generate-register SCHEMA_YAML OUT_DIR -u URN --id ID --ref REF # Generate hierarchical register.yaml from schema manifest
|
|
43
46
|
exe/suma validate links SCHEMAS_FILE DOCS_PATH # Validate EXPRESS cross-reference links
|
|
44
47
|
exe/suma validate closure SCHEMAS_MANIFEST [DOCUMENTS_PATH] # Referential closure: every reference resolves (exit 1 on violations)
|
|
48
|
+
exe/suma validate anchors SCHEMA_DOCS_PATH # Rendered docs: every xref and in-page link resolves (exit 1 on dead links)
|
|
45
49
|
```
|
|
46
50
|
|
|
47
51
|
## Schema profiles
|
|
@@ -51,8 +55,10 @@ identifiers and paths map to types (`ExpressSchema::Type`), how
|
|
|
51
55
|
identifiers become display names (`SchemaNaming`), and the ordered
|
|
52
56
|
register categories (`SchemaCategory`). Registered profiles: `iso10303`
|
|
53
57
|
(default; STEP conventions incl. `/applications/` → application
|
|
54
|
-
protocol)
|
|
55
|
-
|
|
58
|
+
protocol), `generic` (no STEP conventions), and `ifc` (buildingSMART
|
|
59
|
+
IFC editions: standalone classification, `IFC4`-style edition names via
|
|
60
|
+
`/\Aifc\d+(x\d+)*\z/`). The CLI takes `--profile` on `export`,
|
|
61
|
+
`extract-terms`, and `generate-register`.
|
|
56
62
|
|
|
57
63
|
## ISO 10303 AP publications
|
|
58
64
|
|
|
@@ -81,10 +87,12 @@ per-publication parent section.
|
|
|
81
87
|
- **`SchemaCategory`** — value object mapping `ExpressSchema::Type` to a register/export category (id, label, prefix, types, directory). Single source of truth for category identity across `SchemaExporter`, `SchemaNaming`, and `RegisterManifestGenerator`
|
|
82
88
|
- **`Urn`** — value object encapsulating ISO URN semantics (wildcard stripping, base/alias split, leaf composition for `for_schema`/`for_term`/`for_entity`)
|
|
83
89
|
- **`TermExtractor`** — extracts EXPRESS entity concepts from a schema manifest into Glossarist v3 YAML format. Generates definitions with URN cross-references, processes remarks into notes, and resolves EXPRESS xrefs to URN mentions. Assigns stable UUIDv5 identifiers
|
|
90
|
+
- **`TranslationIngester`** — T5 translation ingestion: overlays a YAML sequence of localized-concept entries (keyed by `concept_id` or localized UUID) onto extracted concepts through the Glossarist/lutaml-model framework. Entry fields win; omitted fields keep the source-language content; a new language is created with the same UUIDv5 convention as the linked localizations, and the persisted localization "id" is preserved (Glossarist parses it as `#id`, not `#uuid`)
|
|
84
91
|
- **`RegisterManifestGenerator`** (file: `lib/suma/register_manifest_generator.rb`) — generates a Glossarist v3 `register.yaml` with hierarchical sections from a schema manifest. Classifies schemas via `ExpressSchema::Type` (DRY), delegates naming to `SchemaNaming` (OCP), orders resources before modules. Uses the Section model's `children` field for hierarchy
|
|
85
92
|
- **`SchemaNaming`** — pure module that converts EXPRESS schema IDs to human-readable display names. Strips type suffixes (`_schema`/`_arm`/`_mim`/`_bom`), title-cases with acronym preservation (AIC, AEC, BREP, 2D, 3D…), lowercases function words, appends type labels (ARM/MIM)
|
|
86
|
-
- **`SchemaTemplate::Plain` / `SchemaTemplate::Document`** — pure renderers for the AsciiDoc body fed to Metanorma (no I/O, no schema knowledge). `
|
|
87
|
-
- **`
|
|
93
|
+
- **`SchemaTemplate::Plain` / `SchemaTemplate::Document`** — pure renderers for the AsciiDoc body fed to Metanorma (no I/O, no schema knowledge). Both render the schema through `formatted_hyperlinked_adoc` (live cross-references) under the shared `Anchors` block, which emits one `[[id]]` per linkable element — schema-qualified ids plus bare `entity.attribute` pairs, matching Expressir's two xref forms. `Plain` produces HTML+XML for top-level schemas; `Document` produces XML-only for schemas-only entries. `validate anchors` verifies zero dead links in rendered docs
|
|
94
|
+
- **`AnchorValidator`** — T4 dead-link gate: for every rendered `doc_*.adoc` + `doc_*.html`, each `<<target,...>>` xref must have an anchor in the HTML (unresolved xrefs are silently dropped by the renderer) and every in-page `href="#..."` must hit an id; cross-document xrefs are out of scope. `validate anchors SCHEMA_DOCS_PATH` exits 1 on violations
|
|
95
|
+
- **`SchemaCompiler`** — orchestrates one schema's compilation: writes adoc + config, invokes `Metanorma::Compile`. Templates are injected via the constructor (composition over inheritance). A render key over adoc, config, schema source, and `Provenance.render_toolchain` is stored in `.suma-render-key` beside the outputs; an unchanged key with the requested outputs present reuses them without invoking Metanorma
|
|
88
96
|
- **`SchemaCollection`** — orchestrates processing of all schemas from a config; selects `Plain` for top-level schemas and `Document` for schemas-only entries
|
|
89
97
|
- **`SchemaExporter`** — standalone export of schemas from manifest or `.exp` files to a directory, with optional ZIP
|
|
90
98
|
- **`CollectionManifest`** — pure data model (lutaml-model attributes + YAML mappings) for one node of a Metanorma collection manifest. No imperative methods
|
|
@@ -97,9 +105,13 @@ per-publication parent section.
|
|
|
97
105
|
- **`OwlProjection`** — S2 formal semantics: projects a parsed corpus into OWL/Turtle. Entities → `owl:Class`; `SUBTYPE OF` → `rdfs:subClassOf`; SELECT → `owl:unionOf`; enums → `owl:oneOf` named individuals; simple type aliases → `rdfs:Datatype`; explicit/derived/inverse attributes → object/datatype properties attached through named `owl:Restriction` nodes (cardinality from optionality and aggregate bounds); WHERE rules and DERIVE/INVERSE clauses → annotated (`rdfs:comment`) constraints. IRIs come from `Urn` (`<base>:tech:<schema>.<element>`), per-schema ontologies declare `owl:imports` for their `USE FROM`/`REFERENCE` targets, and the corpus ontology imports every schema. `#validate` checks materialization, property declarations, orphan classes, and superclass acyclicity. Output contains no blank nodes, so projections are deterministic and golden-comparable
|
|
98
106
|
- **`SchemaCache`** — content-addressed on-disk store for generated `.exp` output and parsed Expressir repositories. Keys compose source bytes with the Expressir version (plus Suma/Marshal versions for parsed entries), so a hit is equivalent to a fresh build. Enabled by `SUMA_SCHEMA_CACHE_DIR`; hit/miss counters expose parse reuse. **`NullCache`** is the disabled-mode null object
|
|
99
107
|
- **`BuildPlan`** — incremental-build decision: hashes every schema source, diffs against the persisted state, and expands changed schemas to their transitive dependents through `CorpusGraph`. State defaults to `plain_schemas/.suma-build-state.json`; `SchemaCollection#rebuild_targets` is the build-facing query
|
|
108
|
+
- **`SiteBuild`** — T3 site freshness: keys every source file under the site root (excluding generated trees, render copies, and the Relaton cache) plus the render toolchain, records the key and produced files in `_site/.suma-site-build.json`, and lets `Processor` skip the collection render when nothing changed. Generated per-document artifacts (`document*.xml*`, `*_index.html`, `*.err.html`, `*.log.txt`, temp files) are never treated as inputs
|
|
109
|
+
- **`OutputCanonicalizer`** — T3 determinism: Metanorma assigns random UUIDs to manifest nodes without identifiers and stamps rendered documents with a random 8-letter root type. This pass rewrites those to position-derived UUIDv5s and a fixed marker in the emitted manifest and root XML, while preserving UUIDs that occur in source YAML, so identical builds are byte-identical
|
|
100
110
|
- **`WorkerPool`** — bounded worker pool for independent per-schema work. Schema export runs in the pool (`build --jobs N`); Metanorma document compilation stays sequential and composes with `StagedCollectionBuilder`'s process isolation
|
|
101
111
|
- **`UrnResolver`** — S4 dereferenceable identity: resolves `tech:` schema/element URNs from a manifest, `term:` concept URNs from Glossarist documents, and the dataset URN from `register.yaml`; emits canonical JSON plus a static HTML document per URN at a path derived from the URN itself. Every URN the register emits resolves against the artifact set
|
|
102
|
-
- **`
|
|
112
|
+
- **`ArtifactServer`** — T2 development server for the resolved artifact tree (`serve DIRECTORY`): dependency-free TCP responder negotiating JSON vs HTML by the Accept header at URN-derived paths; production hosting maps the same paths statically
|
|
113
|
+
- **`GcrPackage`** — T2 packaging (`package-gcr`): bundles extracted concepts into a GCR archive for the Glossarist Vocabulary Browser — `metadata.yaml` (identity, statistics, schema_version), `register.yaml`, and `concepts/` in the browser's canonical flat format (`termid`, `term`, `{lang}` blocks). Standard variant only; `created_at` is injectable for byte-reproducible archives
|
|
114
|
+
- **`Provenance`** — S5 build provenance: sha256 of every input and output (files or directory trees) plus Ruby/Expressir/Suma toolchain versions, written as canonical JSON by `build --provenance FILE`. `Provenance.verify` recomputes the digests independently and reports unrecorded files under the recorded output roots (`_site`, `schema_docs`, `plain_schemas`); explicit exclusions cover build metadata such as the site state file and staged store. `build --sign minisign|sigstore` (with `--sign-key` where needed) optionally signs the manifest, and `bin/release_provenance` signs keylessly with cosign in the release workflow (`SUMA_PROVENANCE_SIGN`). `Provenance.render_toolchain` keys rendered-document reuse
|
|
103
115
|
- **`LinkValidator`** — validates EXPRESS cross-reference links against a `SchemaIndex`; returns `LinkValidationResult` structs for unresolved links
|
|
104
116
|
|
|
105
117
|
### CLI structure
|
data/README.adoc
CHANGED
|
@@ -14,12 +14,18 @@ to build the following artifacts:
|
|
|
14
14
|
|
|
15
15
|
== Features
|
|
16
16
|
|
|
17
|
-
* EXPRESS schema management for STEP
|
|
17
|
+
* EXPRESS schema management for STEP and other schema collections
|
|
18
18
|
* Document collection building and compilation
|
|
19
|
+
* Referential closure validation over the whole corpus
|
|
19
20
|
* EXPRESS links validation and extraction
|
|
20
21
|
* Schema listing file generation
|
|
22
|
+
* OWL/Turtle projection with structural validation
|
|
23
|
+
* Typed change manifests, changelogs, and dependency impact analysis
|
|
24
|
+
* Glossarist terminology and hierarchical registers with edition metadata
|
|
25
|
+
* Dereferenceable URN artifacts (canonical JSON + static HTML)
|
|
26
|
+
* Incremental, parallel, and cached corpus builds
|
|
27
|
+
* Reproducible outputs with verifiable, optionally signed provenance
|
|
21
28
|
* Integration with the Metanorma ecosystem
|
|
22
|
-
* Progress tracking for schema loading operations
|
|
23
29
|
|
|
24
30
|
== Installation
|
|
25
31
|
|
|
@@ -37,13 +43,19 @@ $ gem install suma
|
|
|
37
43
|
# Defaults to `suma help`
|
|
38
44
|
$ suma
|
|
39
45
|
Commands:
|
|
40
|
-
suma build METANORMA_SITE_MANIFEST # Build collection
|
|
41
|
-
suma
|
|
42
|
-
suma
|
|
43
|
-
suma
|
|
44
|
-
suma
|
|
45
|
-
suma
|
|
46
|
+
suma build METANORMA_SITE_MANIFEST # Build collection from site manifest
|
|
47
|
+
suma check_svg_quality [PATH] # Check SVG quality
|
|
48
|
+
suma compare TRIAL_SCHEMA REFERENCE_SCHEMA # Compare schemas; typed changes, impact
|
|
49
|
+
suma convert-jsdai XML_FILE IMAGE_FILE OUTPUT_DIR # Convert JSDAI XML and image files to SVG and EXP
|
|
50
|
+
suma export *FILES -o OUTPUT # Export EXPRESS schemas or project them to OWL
|
|
51
|
+
suma extract-terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH # Extract entity concepts to Glossarist v3
|
|
52
|
+
suma ingest-translations CONCEPTS_DIR TRANSLATIONS_FILE [-o OUT] # Overlay translated content onto extracted concepts
|
|
53
|
+
suma generate-register SCHEMA_MANIFEST_FILE OUTPUT_PATH # Generate hierarchical register.yaml
|
|
54
|
+
suma generate-schemas METANORMA_MANIFEST_FILE SCHEMA_MANIFEST_FILE # Generate a schema manifest from a site manifest
|
|
46
55
|
suma reformat EXPRESS_FILE_PATH # Reformat EXPRESS files
|
|
56
|
+
suma resolve [URN] --manifest=MANIFEST -o OUTPUT # Emit canonical JSON + HTML for URNs
|
|
57
|
+
suma package-gcr CONCEPTS_DIR --register=REGISTER -o OUTPUT # Package concepts into a .gcr archive
|
|
58
|
+
suma serve DIRECTORY # Serve resolved artifacts (Accept negotiation)
|
|
47
59
|
suma validate SUBCOMMAND ...ARGS # Validate express documents
|
|
48
60
|
----
|
|
49
61
|
|
|
@@ -65,10 +77,31 @@ Options:
|
|
|
65
77
|
|
|
66
78
|
`--[no-]compile`:: Compile or skip compilation of collection (default: true)
|
|
67
79
|
`--schemas-all-path=PATH`, `-s PATH`:: Generate file that contains all schemas in the collection
|
|
80
|
+
`--[no-]staged`:: Memory-bounded build: compile each member in its own process, then reinflate
|
|
81
|
+
`--[no-]incremental`:: Re-render only changed schemas and their transitive dependents
|
|
82
|
+
`--state-file=PATH`:: Incremental build state file (default: `plain_schemas/.suma-build-state.json`)
|
|
83
|
+
`--jobs=N`:: Concurrent schema export workers (document compilation stays sequential; default: 1)
|
|
84
|
+
`--provenance=PATH`:: Write a provenance manifest (sha256 of inputs/outputs + toolchain versions)
|
|
85
|
+
`--sign=METHOD`:: Sign the provenance manifest: `minisign` or `sigstore`
|
|
86
|
+
`--sign-key=PATH`:: Signing key; minisign requires it, sigstore signs keylessly when omitted
|
|
68
87
|
|
|
69
88
|
The generated `schemas-*.yaml` file name is derived from the input file name
|
|
70
89
|
with the word `metanorma` replaced with `schemas`.
|
|
71
90
|
|
|
91
|
+
Repeated builds reuse work and are reproducible: a schema document is rendered
|
|
92
|
+
again only when its adoc, schema config, schema source, or the rendering
|
|
93
|
+
toolchain changed, and the collection render is skipped entirely when no site
|
|
94
|
+
input changed (state: `_site/.suma-site-build.json`). Metanorma's random
|
|
95
|
+
manifest identifiers and per-document type markers are canonicalized, so two
|
|
96
|
+
identical builds produce byte-identical output. A provenance manifest covers
|
|
97
|
+
`schema_docs`, `plain_schemas`, and `_site`, and verification reports files
|
|
98
|
+
that appeared under those roots without being recorded (build metadata such as
|
|
99
|
+
the site state file is excluded explicitly).
|
|
100
|
+
|
|
101
|
+
Top-level schema documents render with live cross-reference links: every
|
|
102
|
+
`schema.entity` and `entity.attribute` reference Expressir emits becomes an
|
|
103
|
+
in-page link, and `suma validate anchors` verifies that no link is dead.
|
|
104
|
+
|
|
72
105
|
[example]
|
|
73
106
|
====
|
|
74
107
|
.To compile SRL subset test collection
|
|
@@ -141,6 +174,7 @@ $ suma validate SUBCOMMAND [options]
|
|
|
141
174
|
Subcommands:
|
|
142
175
|
|
|
143
176
|
`links`:: Validate EXPRESS links
|
|
177
|
+
`closure`:: Validate referential closure over the whole corpus
|
|
144
178
|
|
|
145
179
|
==== Links subcommand
|
|
146
180
|
|
|
@@ -176,6 +210,36 @@ This command:
|
|
|
176
210
|
* Writes validation results to the `OUTPUT_FILE`
|
|
177
211
|
* Provides progress bars to track schema loading and link validation
|
|
178
212
|
|
|
213
|
+
==== Closure subcommand
|
|
214
|
+
|
|
215
|
+
The `closure` subcommand extracts every EXPRESS-internal reference (attribute
|
|
216
|
+
domains, SELECT and aggregate branches, where-rule expressions, subtype
|
|
217
|
+
constraints, supertype/subtype lists, rule applies-to, and USE/REFERENCE
|
|
218
|
+
interfaces) and resolves it against the corpus graph. It exits non-zero when
|
|
219
|
+
any reference does not resolve, which makes it usable as a CI gate
|
|
220
|
+
(`rake closure` runs it on the fixture corpus).
|
|
221
|
+
|
|
222
|
+
[source,sh]
|
|
223
|
+
----
|
|
224
|
+
$ suma validate closure SCHEMAS_MANIFEST [DOCUMENTS_PATH] [--format terminal|json|yaml]
|
|
225
|
+
----
|
|
226
|
+
|
|
227
|
+
When `DOCUMENTS_PATH` is given, documentation-layer link failures are merged
|
|
228
|
+
into the same report.
|
|
229
|
+
|
|
230
|
+
==== Anchors subcommand
|
|
231
|
+
|
|
232
|
+
The `anchors` subcommand checks rendered schema documents for dead links:
|
|
233
|
+
every Expressir cross-reference (`<<schema.entity,...>>`,
|
|
234
|
+
`<<entity.attribute,...>>`) emitted in a compiled `doc_*.adoc` must have a
|
|
235
|
+
matching anchor in its rendered `doc_*.html`, and every in-page `href` must
|
|
236
|
+
point at an existing id. It exits non-zero on violations.
|
|
237
|
+
|
|
238
|
+
[source,sh]
|
|
239
|
+
----
|
|
240
|
+
$ suma validate anchors SCHEMA_DOCS_PATH
|
|
241
|
+
----
|
|
242
|
+
|
|
179
243
|
|
|
180
244
|
=== Generate schemas command
|
|
181
245
|
|
|
@@ -225,7 +289,7 @@ used for other EXPRESS schema collections that require term extraction for
|
|
|
225
289
|
glossary or dictionary applications.
|
|
226
290
|
|
|
227
291
|
The `suma extract-terms` command extracts terms from EXPRESS schemas and
|
|
228
|
-
generates a Glossarist
|
|
292
|
+
generates a Glossarist v3 dataset in the output directory. This command processes
|
|
229
293
|
various types of STEP schemas and creates standardized terminology datasets
|
|
230
294
|
suitable for glossary and dictionary applications.
|
|
231
295
|
|
|
@@ -239,12 +303,14 @@ Parameters:
|
|
|
239
303
|
`SCHEMA_MANIFEST_FILE`:: Path to the schema manifest file that lists all schemas
|
|
240
304
|
to process (e.g., "schemas-smrl-all.yml")
|
|
241
305
|
|
|
242
|
-
`GLOSSARIST_OUTPUT_PATH`:: Path to the output directory where the Glossarist
|
|
306
|
+
`GLOSSARIST_OUTPUT_PATH`:: Path to the output directory where the Glossarist v3
|
|
243
307
|
dataset will be generated
|
|
244
308
|
|
|
245
309
|
Options:
|
|
246
310
|
|
|
247
311
|
`--language_code`, `-l`:: Language code for the Glossarist dataset (default: "eng")
|
|
312
|
+
`--edition=N`:: Owning edition recorded on each concept
|
|
313
|
+
`--language-codes=a,b`:: Additional linked localization languages (the primary language is always included)
|
|
248
314
|
|
|
249
315
|
==== Supported schema types
|
|
250
316
|
|
|
@@ -275,7 +341,7 @@ information:
|
|
|
275
341
|
|
|
276
342
|
==== Output format
|
|
277
343
|
|
|
278
|
-
The command generates a Glossarist
|
|
344
|
+
The command generates a Glossarist v3 compliant dataset with:
|
|
279
345
|
|
|
280
346
|
* `concept/` directory containing concept definition files in YAML
|
|
281
347
|
* `localized_concept/` directory containing localized concept files in YAML
|
|
@@ -301,6 +367,37 @@ $ bundle exec suma extract-terms schemas-activity-modules.yml terms_output
|
|
|
301
367
|
----
|
|
302
368
|
====
|
|
303
369
|
|
|
370
|
+
=== Ingest translations command
|
|
371
|
+
|
|
372
|
+
The `suma ingest-translations` command overlays translated content onto
|
|
373
|
+
extracted concepts. A translations file is a YAML sequence of
|
|
374
|
+
localized-concept documents, each keyed by concept id (or localized
|
|
375
|
+
UUID) and carrying the fields to apply:
|
|
376
|
+
|
|
377
|
+
[source,yaml]
|
|
378
|
+
----
|
|
379
|
+
- concept_id: example_schema.part
|
|
380
|
+
data:
|
|
381
|
+
language_code: fra
|
|
382
|
+
terms:
|
|
383
|
+
- designation: pièce
|
|
384
|
+
type: expression
|
|
385
|
+
normative_status: preferred
|
|
386
|
+
definition:
|
|
387
|
+
- content: "Composant d'un assemblage."
|
|
388
|
+
----
|
|
389
|
+
|
|
390
|
+
Every field the entry provides replaces that localization's field; every
|
|
391
|
+
field it omits keeps the source-language content (a language absent from
|
|
392
|
+
the extracted concepts is created with the same stable UUID convention
|
|
393
|
+
the linked localizations use). Updated concepts are written in place, or
|
|
394
|
+
to `--output` when given.
|
|
395
|
+
|
|
396
|
+
[source,sh]
|
|
397
|
+
----
|
|
398
|
+
$ suma ingest-translations CONCEPTS_DIR TRANSLATIONS_FILE [-o OUTPUT_DIR]
|
|
399
|
+
----
|
|
400
|
+
|
|
304
401
|
|
|
305
402
|
=== Generate register command
|
|
306
403
|
|
|
@@ -326,6 +423,13 @@ Options:
|
|
|
326
423
|
The wildcard is stripped for the base URN and kept in `urnAliases`.
|
|
327
424
|
*Required*.
|
|
328
425
|
|
|
426
|
+
`--year=N`:: Edition year recorded on the register
|
|
427
|
+
|
|
428
|
+
`--supersedes=URN`:: URN/ref of the superseded edition
|
|
429
|
+
|
|
430
|
+
`--edition=N`:: Edition number, tagged as `edition:N`; every register also
|
|
431
|
+
carries a `dataset:<id>` tag so sibling editions can be grouped.
|
|
432
|
+
|
|
329
433
|
The URN is fully configurable — every component can be changed to match the
|
|
330
434
|
dataset being exported. The general structure is:
|
|
331
435
|
|
|
@@ -521,6 +625,11 @@ Options:
|
|
|
521
625
|
`--[no-]annotations`:: Include annotations (remarks/comments) in exported schemas (default: false)
|
|
522
626
|
|
|
523
627
|
`--[no-]zip`:: Create ZIP archive of exported schemas (default: false)
|
|
628
|
+
`--profile=PROFILE`:: Schema profile: `iso10303` (default) or `generic`
|
|
629
|
+
`--publication=SCHEMA_ID`:: Export an AP publication bundle: the lead schema plus its transitive USE-FROM/REFERENCE closure
|
|
630
|
+
`--format=FORMAT`:: Output format: `express` (default) or `owl`
|
|
631
|
+
`--[no-]corpus`:: OWL only: emit one corpus ontology importing every schema ontology
|
|
632
|
+
`--urn=URN`:: OWL only: base URN for IRIs, before the `:tech` component
|
|
524
633
|
|
|
525
634
|
==== Behavior
|
|
526
635
|
|
|
@@ -639,6 +748,105 @@ express-files/
|
|
|
639
748
|
----
|
|
640
749
|
|
|
641
750
|
|
|
751
|
+
=== Schema profiles and AP publications
|
|
752
|
+
|
|
753
|
+
Suma works with any schema collection. `Suma::SchemaProfile` declares how
|
|
754
|
+
schema identifiers and paths map to types, how identifiers become display
|
|
755
|
+
names, and the ordered register categories. Registered profiles:
|
|
756
|
+
|
|
757
|
+
`iso10303`:: Default; STEP conventions including `/applications/` classifying as an application protocol
|
|
758
|
+
`generic`:: No STEP conventions (one category for every schema)
|
|
759
|
+
`ifc`:: buildingSMART IFC editions: one standalone schema per edition (`ifc4`, `ifc4x3`, ...), edition names preserved uppercase (`IFC4`, `IFC4X3`), Ifc-prefixed declarations, one `Other Schemas` register category
|
|
760
|
+
|
|
761
|
+
An AP publication is a lead schema bundled with the module and resource
|
|
762
|
+
schemas it USEs. `--publication SCHEMA_ID` computes the transitive
|
|
763
|
+
USE-FROM/REFERENCE closure and writes the bundle flat under
|
|
764
|
+
`OUTPUT/<lead_id>/`. In the register, application protocols are grouped under
|
|
765
|
+
a per-publication parent section.
|
|
766
|
+
|
|
767
|
+
=== OWL projection
|
|
768
|
+
|
|
769
|
+
`suma export --format owl` projects a parsed corpus into OWL/Turtle:
|
|
770
|
+
|
|
771
|
+
* entities become `owl:Class`; `SUBTYPE OF` becomes `rdfs:subClassOf`
|
|
772
|
+
* SELECT types become `owl:unionOf`; enumerations become `owl:oneOf` named individuals
|
|
773
|
+
* simple type aliases become `rdfs:Datatype`
|
|
774
|
+
* explicit, derived, and inverse attributes become object/datatype properties attached through named `owl:Restriction` nodes, with cardinality from optionality and aggregate bounds
|
|
775
|
+
* WHERE, DERIVE, and INVERSE clauses are preserved as annotated constraints
|
|
776
|
+
|
|
777
|
+
IRIs derive from the corpus URN scheme (`<base>:tech:<schema>.<element>`).
|
|
778
|
+
Per-schema ontologies declare `owl:imports` for their USE-FROM/REFERENCE
|
|
779
|
+
targets, and `--corpus` adds a corpus ontology importing every schema. The
|
|
780
|
+
projection is validated before writing (materialization, property
|
|
781
|
+
declarations, orphan classes, dangling superclasses, superclass cycles), and
|
|
782
|
+
contains no blank nodes, so it is deterministic and golden-comparable.
|
|
783
|
+
|
|
784
|
+
[source,sh]
|
|
785
|
+
----
|
|
786
|
+
$ suma export --format owl --urn urn:iso:std:iso:10303:-2:ed-2:en \
|
|
787
|
+
-o OUTPUT schemas.yaml
|
|
788
|
+
$ suma export --format owl --corpus --urn urn:iso:std:iso:10303:-2:ed-2:en \
|
|
789
|
+
-o OUTPUT schemas.yaml
|
|
790
|
+
----
|
|
791
|
+
|
|
792
|
+
=== Package concepts for the Vocabulary Browser
|
|
793
|
+
|
|
794
|
+
The `package-gcr` command bundles extracted concepts into a GCR
|
|
795
|
+
(Glossarist Concept Repository) archive — the sealed distribution format
|
|
796
|
+
consumed by the Glossarist Vocabulary Browser:
|
|
797
|
+
|
|
798
|
+
[source,sh]
|
|
799
|
+
----
|
|
800
|
+
$ suma package-gcr CONCEPTS_DIR --register register.yaml \
|
|
801
|
+
--shortname my-dataset --version 1.0.0 \
|
|
802
|
+
--title "My Dataset" --description "Concepts from my corpus" \
|
|
803
|
+
-o OUT
|
|
804
|
+
----
|
|
805
|
+
|
|
806
|
+
The archive contains `metadata.yaml` (identity, statistics), the original
|
|
807
|
+
`register.yaml`, and `concepts/` in the browser's canonical flat format
|
|
808
|
+
(`termid`, `term`, one block per language). Both a versioned
|
|
809
|
+
(`{shortname}-{version}.gcr`) and an unversioned (`{shortname}.gcr`)
|
|
810
|
+
archive are written. Pass `--created-at` to pin the package timestamp for
|
|
811
|
+
byte-reproducible archives. Point the browser's `datasets.yml` at the
|
|
812
|
+
published archive (or at the concepts directory in development via
|
|
813
|
+
`localPath`).
|
|
814
|
+
|
|
815
|
+
=== Serve resolved artifacts
|
|
816
|
+
|
|
817
|
+
`suma serve` serves a `resolve --all` artifact tree at its URN-derived
|
|
818
|
+
paths, returning JSON or HTML according to the request's `Accept`
|
|
819
|
+
header:
|
|
820
|
+
|
|
821
|
+
[source,sh]
|
|
822
|
+
----
|
|
823
|
+
$ suma serve OUT --port 2113
|
|
824
|
+
$ curl -H "Accept: application/json" \
|
|
825
|
+
http://localhost:2113/urn/iso/std/iso/10303/-2/ed-2/en/tech/action_schema.action
|
|
826
|
+
----
|
|
827
|
+
|
|
828
|
+
Production hosting maps the same paths statically; no application server
|
|
829
|
+
is required.
|
|
830
|
+
|
|
831
|
+
=== Resolve URNs command
|
|
832
|
+
|
|
833
|
+
The `resolve` command turns URNs into static, dereferenceable artifacts: a
|
|
834
|
+
canonical JSON document (sorted keys) and an HTML page per URN, written under
|
|
835
|
+
a path derived from the URN itself. It resolves:
|
|
836
|
+
|
|
837
|
+
* `tech:` schema, declared-element, and attribute (OWL property) URNs from a schema manifest
|
|
838
|
+
* `term:` concept URNs from Glossarist concept documents
|
|
839
|
+
* the dataset URN from `register.yaml`
|
|
840
|
+
|
|
841
|
+
[source,sh]
|
|
842
|
+
----
|
|
843
|
+
$ suma resolve URN --manifest SCHEMAS_YAML [--concepts DIR] [--register register.yaml] -o OUT
|
|
844
|
+
$ suma resolve --all --manifest SCHEMAS_YAML [--concepts DIR] [--register register.yaml] -o OUT
|
|
845
|
+
----
|
|
846
|
+
|
|
847
|
+
`--all` also writes `index.html`, linking every artifact. No server is
|
|
848
|
+
required.
|
|
849
|
+
|
|
642
850
|
=== Compare schemas command
|
|
643
851
|
|
|
644
852
|
==== General
|
|
@@ -667,6 +875,10 @@ Options:
|
|
|
667
875
|
`--trial-stepmod=PATH`:: Override auto-detected trial repository root
|
|
668
876
|
`--reference-stepmod=PATH`:: Override auto-detected reference repository root
|
|
669
877
|
`--verbose`:: Enable verbose output
|
|
878
|
+
`--typed-output=PATH`:: Write a typed change manifest (lutaml-model records with classification)
|
|
879
|
+
`--[no-]changelog`:: Render a markdown changelog alongside the change manifest
|
|
880
|
+
`--[no-]impact`:: Report affected schemas and AP publications using the corpus graph
|
|
881
|
+
`--manifest=SCHEMAS_YAML`:: Schema manifest used for impact analysis
|
|
670
882
|
|
|
671
883
|
==== Typical workflow
|
|
672
884
|
|
|
@@ -1163,3 +1375,17 @@ Code-style rules enforced throughout `lib/suma/`:
|
|
|
1163
1375
|
== Copyright and license
|
|
1164
1376
|
|
|
1165
1377
|
Copyright Ribose. BSD 2-clause license.
|
|
1378
|
+
|
|
1379
|
+
== Development and benchmarks
|
|
1380
|
+
|
|
1381
|
+
The default gate is `rake` (specs, RuboCop, referential closure).
|
|
1382
|
+
|
|
1383
|
+
[source,sh]
|
|
1384
|
+
----
|
|
1385
|
+
$ rake benchmark
|
|
1386
|
+
----
|
|
1387
|
+
|
|
1388
|
+
`rake benchmark` builds a synthetic 1,000-schema corpus and asserts wall-time
|
|
1389
|
+
and peak-RSS budgets; the same benchmark runs nightly in CI. Schema export can
|
|
1390
|
+
run in parallel with `build --jobs N`, while Metanorma document compilation
|
|
1391
|
+
stays sequential and composes with staged process isolation.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Suma
|
|
4
|
+
# Validates that every cross-reference a rendered schema document emits
|
|
5
|
+
# resolves inside it. The Expressir hyperlinked source emits xref macros
|
|
6
|
+
# (`<<schema.entity,...>>`, `<<entity.attribute,...>>`); when a target is
|
|
7
|
+
# missing, the renderer silently drops the link, so the check is done on
|
|
8
|
+
# the source macros against the anchors present in the rendered HTML —
|
|
9
|
+
# plus the reverse check that every in-page href hits an existing id.
|
|
10
|
+
class AnchorValidator
|
|
11
|
+
XREF_PATTERN = /<<([^,>]+)(?:,[^>]*)?>>/
|
|
12
|
+
ID_PATTERN = /id="([^"]+)"/
|
|
13
|
+
FRAGMENT_PATTERN = /href="#([^"]+)"/
|
|
14
|
+
|
|
15
|
+
# @param directory [String] tree of compiled schema docs (doc_*.adoc
|
|
16
|
+
# with their rendered doc_*.html)
|
|
17
|
+
def initialize(directory)
|
|
18
|
+
@directory = directory
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [Array<LinkValidationResult>] dead links (empty = valid)
|
|
22
|
+
def validate
|
|
23
|
+
Dir.glob(File.join(@directory, "**", "doc_*.adoc"))
|
|
24
|
+
.flat_map { |adoc| validate_document(adoc) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def validate_document(adoc)
|
|
30
|
+
html = adoc.sub(/\.adoc\z/, ".html")
|
|
31
|
+
return [missing_html(adoc, html)] unless File.file?(html)
|
|
32
|
+
|
|
33
|
+
content = File.read(adoc)
|
|
34
|
+
ids, fragments = rendered_digests(html)
|
|
35
|
+
|
|
36
|
+
xref_violations(adoc, content, ids, fragments) +
|
|
37
|
+
fragment_violations(html, ids)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def rendered_digests(html)
|
|
41
|
+
rendered = File.read(html)
|
|
42
|
+
[rendered.scan(ID_PATTERN).flatten.uniq,
|
|
43
|
+
rendered.scan(FRAGMENT_PATTERN).flatten.uniq]
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def xref_violations(adoc, content, ids, fragments)
|
|
47
|
+
content.scan(XREF_PATTERN).flatten.uniq.filter_map do |target|
|
|
48
|
+
next if cross_document?(target) || resolved?(target, ids, fragments)
|
|
49
|
+
|
|
50
|
+
LinkValidationResult.new(
|
|
51
|
+
file: adoc, line: nil, link: target,
|
|
52
|
+
reason: "cross-reference has no anchor in the rendered document"
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def fragment_violations(html, ids)
|
|
58
|
+
File.read(html).scan(FRAGMENT_PATTERN).flatten.uniq.filter_map do |frag|
|
|
59
|
+
next if ids.include?(frag)
|
|
60
|
+
|
|
61
|
+
LinkValidationResult.new(
|
|
62
|
+
file: html, line: nil, link: "##{frag}",
|
|
63
|
+
reason: "in-page link points at no anchor in the document"
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Xrefs that cross documents (Asciidoctor `path.adoc#anchor` syntax)
|
|
69
|
+
# resolve against other pages and are out of scope here.
|
|
70
|
+
def cross_document?(target)
|
|
71
|
+
target.include?("/") || target.include?("#")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def resolved?(target, ids, fragments)
|
|
75
|
+
ids.include?(target) || fragments.include?(target)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def missing_html(adoc, html)
|
|
79
|
+
LinkValidationResult.new(
|
|
80
|
+
file: adoc, line: nil, link: html,
|
|
81
|
+
reason: "no rendered HTML next to the adoc source"
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|