suma 0.2.6 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +10 -1
- data/.rubocop_todo.yml +170 -13
- data/CLAUDE.md +37 -11
- data/Gemfile +3 -3
- data/README.adoc +57 -1
- data/exe/suma +1 -1
- data/lib/suma/cli/build.rb +0 -5
- data/lib/suma/cli/check_svg_quality.rb +0 -6
- data/lib/suma/cli/compare.rb +0 -1
- data/lib/suma/cli/convert_jsdai.rb +0 -2
- data/lib/suma/cli/core.rb +119 -0
- data/lib/suma/cli/export.rb +0 -3
- data/lib/suma/cli/extract_terms.rb +5 -8
- data/lib/suma/cli/generate_register.rb +34 -0
- data/lib/suma/cli/generate_schemas.rb +0 -2
- data/lib/suma/cli/reformat.rb +0 -1
- data/lib/suma/cli/validate.rb +0 -2
- data/lib/suma/cli/validate_links.rb +0 -2
- data/lib/suma/cli.rb +12 -141
- data/lib/suma/collection_config.rb +0 -2
- data/lib/suma/collection_manifest.rb +7 -110
- data/lib/suma/eengine/wrapper.rb +0 -1
- data/lib/suma/eengine.rb +8 -0
- data/lib/suma/express_schema.rb +0 -1
- data/lib/suma/jsdai/figure.rb +0 -3
- data/lib/suma/jsdai.rb +5 -2
- data/lib/suma/link_validator.rb +15 -7
- data/lib/suma/manifest_traverser.rb +92 -0
- data/lib/suma/processor.rb +5 -8
- data/lib/suma/register_manifest_generator.rb +163 -0
- data/lib/suma/schema_category.rb +83 -0
- data/lib/suma/schema_collection.rb +29 -33
- data/lib/suma/schema_comparer.rb +4 -3
- data/lib/suma/schema_compiler.rb +86 -0
- data/lib/suma/schema_discovery.rb +75 -0
- data/lib/suma/schema_exporter.rb +2 -18
- data/lib/suma/schema_manifest_generator.rb +14 -6
- data/lib/suma/schema_naming.rb +111 -0
- data/lib/suma/schema_template/document.rb +141 -0
- data/lib/suma/schema_template/plain.rb +46 -0
- data/lib/suma/schema_template.rb +19 -0
- data/lib/suma/svg_quality/batch_report.rb +0 -2
- data/lib/suma/svg_quality/formatters.rb +12 -0
- data/lib/suma/svg_quality.rb +3 -1
- data/lib/suma/term_extractor.rb +119 -46
- data/lib/suma/urn.rb +61 -0
- data/lib/suma/version.rb +1 -1
- data/lib/suma.rb +31 -3
- data/suma.gemspec +1 -1
- metadata +24 -6
- data/lib/suma/schema_attachment.rb +0 -103
- data/lib/suma/schema_document.rb +0 -118
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "thor"
|
|
4
|
-
require_relative "../thor_ext"
|
|
5
|
-
require_relative "../term_extractor"
|
|
6
4
|
|
|
7
5
|
module Suma
|
|
8
6
|
module Cli
|
|
9
7
|
class ExtractTerms < Thor
|
|
10
8
|
desc "extract_terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH",
|
|
11
9
|
"Extract terms from SCHEMA_MANIFEST_FILE into " \
|
|
12
|
-
"Glossarist
|
|
10
|
+
"Glossarist v3 format"
|
|
13
11
|
option :language_code, type: :string, default: "eng", aliases: "-l",
|
|
14
12
|
desc: "Language code for the Glossarist"
|
|
13
|
+
option :urn, type: :string, required: true, aliases: "-u",
|
|
14
|
+
desc: "URN for the dataset source " \
|
|
15
|
+
"(used for section references)"
|
|
15
16
|
|
|
16
17
|
def extract_terms(schema_manifest_file, output_path)
|
|
17
|
-
unless File.exist?(File.expand_path(schema_manifest_file))
|
|
18
|
-
raise Errno::ENOENT, "Specified SCHEMA_MANIFEST_FILE " \
|
|
19
|
-
"`#{schema_manifest_file}` not found."
|
|
20
|
-
end
|
|
21
|
-
|
|
22
18
|
TermExtractor.new(
|
|
23
19
|
schema_manifest_file,
|
|
24
20
|
output_path,
|
|
25
21
|
language_code: options[:language_code],
|
|
22
|
+
urn: options[:urn],
|
|
26
23
|
).call
|
|
27
24
|
end
|
|
28
25
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "thor"
|
|
4
|
+
|
|
5
|
+
module Suma
|
|
6
|
+
module Cli
|
|
7
|
+
class GenerateRegister < Thor
|
|
8
|
+
desc "generate_register SCHEMA_MANIFEST_FILE OUTPUT_PATH",
|
|
9
|
+
"Generate a Glossarist register.yaml with hierarchical sections"
|
|
10
|
+
option :language_code, type: :string, default: "eng", aliases: "-l",
|
|
11
|
+
desc: "Language code for section names"
|
|
12
|
+
option :urn, type: :string, required: true, aliases: "-u",
|
|
13
|
+
desc: "URN prefix for the dataset"
|
|
14
|
+
option :id, type: :string, required: true,
|
|
15
|
+
desc: "Dataset identifier (e.g. iso10303-2-express)"
|
|
16
|
+
option :ref, type: :string, required: true,
|
|
17
|
+
desc: "Human-readable reference label"
|
|
18
|
+
option :owner, type: :string, default: Suma::RegisterManifestGenerator::DEFAULT_OWNER,
|
|
19
|
+
desc: "Owner of the dataset (e.g. 'ISO/TC 184/SC 4')"
|
|
20
|
+
|
|
21
|
+
def generate_register(schema_manifest_file, output_path)
|
|
22
|
+
RegisterManifestGenerator.new(
|
|
23
|
+
schema_manifest_file,
|
|
24
|
+
output_path,
|
|
25
|
+
urn: options[:urn],
|
|
26
|
+
id: options[:id],
|
|
27
|
+
ref: options[:ref],
|
|
28
|
+
language_code: options[:language_code],
|
|
29
|
+
owner: options[:owner],
|
|
30
|
+
).generate
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
data/lib/suma/cli/reformat.rb
CHANGED
data/lib/suma/cli/validate.rb
CHANGED
|
@@ -9,8 +9,6 @@ module Suma
|
|
|
9
9
|
desc "links SCHEMAS_FILE DOCUMENTS_PATH [OUTPUT_FILE]",
|
|
10
10
|
"Extract and validate express links without creating intermediate file"
|
|
11
11
|
def links(*args)
|
|
12
|
-
require_relative "validate_links"
|
|
13
|
-
|
|
14
12
|
# Forward the command to ValidateLinks
|
|
15
13
|
links = Cli::ValidateLinks.new
|
|
16
14
|
links.extract_and_validate(*args)
|
data/lib/suma/cli.rb
CHANGED
|
@@ -1,147 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "thor"
|
|
4
|
-
require_relative "thor_ext"
|
|
5
|
-
require_relative "cli/validate"
|
|
6
|
-
require_relative "cli/check_svg_quality"
|
|
7
|
-
require "expressir"
|
|
8
|
-
require "expressir/cli"
|
|
9
|
-
|
|
10
3
|
module Suma
|
|
11
4
|
module Cli
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
require_relative "cli/build"
|
|
25
|
-
Cli::Build.start
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
desc "generate-schemas METANORMA_MANIFEST_FILE SCHEMA_MANIFEST_FILE",
|
|
29
|
-
"Generate EXPRESS schema manifest file from Metanorma site manifest"
|
|
30
|
-
option :exclude_paths, type: :string, default: nil, aliases: "-e",
|
|
31
|
-
desc: "Exclude schemas paths by pattern " \
|
|
32
|
-
"(e.g. `*_lf.exp`)"
|
|
33
|
-
def generate_schemas(_metanorma_manifest_file, _schema_manifest_file)
|
|
34
|
-
require_relative "cli/generate_schemas"
|
|
35
|
-
Cli::GenerateSchemas.start
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
desc "reformat EXPRESS_FILE_PATH",
|
|
39
|
-
"Reformat EXPRESS files"
|
|
40
|
-
option :recursive, type: :boolean, default: false, aliases: "-r",
|
|
41
|
-
desc: "Reformat EXPRESS files under the specified " \
|
|
42
|
-
"path recursively"
|
|
43
|
-
def reformat(_express_file_path)
|
|
44
|
-
require_relative "cli/reformat"
|
|
45
|
-
Cli::Reformat.start
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
desc "extract-terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH",
|
|
49
|
-
"Extract terms from SCHEMA_MANIFEST_FILE into " \
|
|
50
|
-
"Glossarist v2 format"
|
|
51
|
-
option :language_code, type: :string, default: "eng", aliases: "-l",
|
|
52
|
-
desc: "Language code for the Glossarist"
|
|
53
|
-
def extract_terms(_schema_manifest_file, _glossarist_output_path)
|
|
54
|
-
require_relative "cli/extract_terms"
|
|
55
|
-
Cli::ExtractTerms.start
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
desc "convert-jsdai XML_FILE IMAGE_FILE OUTPUT_DIR",
|
|
59
|
-
"Convert JSDAI XML and image files to SVG and EXP files"
|
|
60
|
-
def convert_jsdai(_xml_file, _image_file, _output_dir)
|
|
61
|
-
require_relative "cli/convert_jsdai"
|
|
62
|
-
Cli::ConvertJsdai.start
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
desc "export *FILES",
|
|
66
|
-
"Export EXPRESS schemas from manifest files or " \
|
|
67
|
-
"standalone EXPRESS files"
|
|
68
|
-
option :output, type: :string, aliases: "-o", required: true,
|
|
69
|
-
desc: "Output directory path"
|
|
70
|
-
option :annotations, type: :boolean, default: false,
|
|
71
|
-
desc: "Include annotations (remarks/comments)"
|
|
72
|
-
option :zip, type: :boolean, default: false,
|
|
73
|
-
desc: "Create ZIP archive of exported schemas"
|
|
74
|
-
def export(*_files)
|
|
75
|
-
require_relative "cli/export"
|
|
76
|
-
Cli::Export.start
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
desc "compare TRIAL_SCHEMA REFERENCE_SCHEMA",
|
|
80
|
-
"Compare EXPRESS schemas using eengine and generate Change YAML"
|
|
81
|
-
option :output, type: :string, aliases: "-o",
|
|
82
|
-
desc: "Output Change YAML file path"
|
|
83
|
-
option :version, type: :string, aliases: "-v", required: true,
|
|
84
|
-
desc: "Version number for this change version"
|
|
85
|
-
option :mode, type: :string, default: "resource",
|
|
86
|
-
desc: "Schema comparison mode (resource/module)"
|
|
87
|
-
option :trial_stepmod, type: :string,
|
|
88
|
-
desc: "Override auto-detected trial repo root"
|
|
89
|
-
option :reference_stepmod, type: :string,
|
|
90
|
-
desc: "Override auto-detected reference repo root"
|
|
91
|
-
option :verbose, type: :boolean, default: false,
|
|
92
|
-
desc: "Enable verbose output"
|
|
93
|
-
def compare(_trial_schema, _reference_schema)
|
|
94
|
-
require_relative "cli/compare"
|
|
95
|
-
Cli::Compare.start
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
desc "validate SUBCOMMAND ...ARGS", "Validate express documents"
|
|
99
|
-
subcommand "validate", Cli::Validate
|
|
100
|
-
|
|
101
|
-
desc "check_svg_quality [PATH]",
|
|
102
|
-
"Check SVG quality and sort by severity (critical files first)"
|
|
103
|
-
option :pattern, type: :string, default: Cli::CheckSvgQuality::DEFAULT_PATTERN,
|
|
104
|
-
desc: "Glob pattern for finding SVG files"
|
|
105
|
-
option :profile, type: :string,
|
|
106
|
-
default: Cli::CheckSvgQuality::DEFAULT_PROFILE,
|
|
107
|
-
desc: "Validation profile to use (metanorma, svg_1_2_rfc, etc.)"
|
|
108
|
-
option :format, type: :string, default: "terminal",
|
|
109
|
-
desc: "Output format: terminal, yaml, json"
|
|
110
|
-
option :output, type: :string, aliases: "-o",
|
|
111
|
-
desc: "Output file path"
|
|
112
|
-
option :min_errors, type: :numeric,
|
|
113
|
-
desc: "Minimum error count threshold"
|
|
114
|
-
option :limit, type: :numeric, default: nil,
|
|
115
|
-
desc: "Maximum number of files to show (default: unlimited)"
|
|
116
|
-
option :sort, type: :string, default: "errors",
|
|
117
|
-
desc: "Sort by: errors (most errors first) or quality (lowest scores first)"
|
|
118
|
-
option :progress, type: :boolean, default: false,
|
|
119
|
-
desc: "Show progress during processing"
|
|
120
|
-
option :summary_only, type: :boolean, default: false,
|
|
121
|
-
desc: "Show only summary"
|
|
122
|
-
def check_svg_quality(path = Cli::CheckSvgQuality::DATA_PATH)
|
|
123
|
-
require_relative "cli/check_svg_quality"
|
|
124
|
-
|
|
125
|
-
analyzer = Cli::CheckSvgQuality.new(
|
|
126
|
-
pattern: options[:pattern],
|
|
127
|
-
profile: options[:profile],
|
|
128
|
-
format: options[:format],
|
|
129
|
-
output: options[:output],
|
|
130
|
-
min_errors: options[:min_errors],
|
|
131
|
-
summary_only: options[:summary_only],
|
|
132
|
-
progress: options[:progress],
|
|
133
|
-
limit: options[:limit],
|
|
134
|
-
sort: options[:sort],
|
|
135
|
-
)
|
|
136
|
-
analyzer.run(path)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
desc "expressir SUBCOMMAND ...ARGS", "Expressir commands"
|
|
140
|
-
subcommand "expressir", Expressir::Cli
|
|
141
|
-
|
|
142
|
-
def self.exit_on_failure?
|
|
143
|
-
true
|
|
144
|
-
end
|
|
145
|
-
end
|
|
5
|
+
autoload :Core, "suma/cli/core"
|
|
6
|
+
autoload :Build, "suma/cli/build"
|
|
7
|
+
autoload :CheckSvgQuality, "suma/cli/check_svg_quality"
|
|
8
|
+
autoload :Compare, "suma/cli/compare"
|
|
9
|
+
autoload :ConvertJsdai, "suma/cli/convert_jsdai"
|
|
10
|
+
autoload :Export, "suma/cli/export"
|
|
11
|
+
autoload :ExtractTerms, "suma/cli/extract_terms"
|
|
12
|
+
autoload :GenerateRegister, "suma/cli/generate_register"
|
|
13
|
+
autoload :GenerateSchemas, "suma/cli/generate_schemas"
|
|
14
|
+
autoload :Reformat, "suma/cli/reformat"
|
|
15
|
+
autoload :Validate, "suma/cli/validate"
|
|
16
|
+
autoload :ValidateLinks, "suma/cli/validate_links"
|
|
146
17
|
end
|
|
147
18
|
end
|
|
@@ -4,6 +4,13 @@ require "metanorma"
|
|
|
4
4
|
require "expressir"
|
|
5
5
|
|
|
6
6
|
module Suma
|
|
7
|
+
# Pure data model for one node of a Metanorma collection manifest.
|
|
8
|
+
#
|
|
9
|
+
# CollectionManifest extends the Metanorma config manifest to add the
|
|
10
|
+
# `schemas_only` flag and an `entry` sub-collection. It owns only state:
|
|
11
|
+
# attributes, YAML mappings, and the `schema_config` slot populated by
|
|
12
|
+
# SchemaDiscovery. Tree-walking logic lives in ManifestTraverser; schema
|
|
13
|
+
# I/O lives in SchemaDiscovery.
|
|
7
14
|
class CollectionManifest < Metanorma::Collection::Config::Manifest
|
|
8
15
|
attribute :schemas_only, Lutaml::Model::Type::Boolean
|
|
9
16
|
attribute :entry, CollectionManifest, collection: true,
|
|
@@ -32,115 +39,5 @@ module Suma
|
|
|
32
39
|
def docref_from_yaml(model, value)
|
|
33
40
|
model.entry = CollectionManifest.from_yaml(value.to_yaml)
|
|
34
41
|
end
|
|
35
|
-
|
|
36
|
-
# Recursively exports schema configuration by traversing collection manifests.
|
|
37
|
-
#
|
|
38
|
-
# This method builds an EXPRESS Schema Manifest (Expressir::SchemaManifest) by:
|
|
39
|
-
# 1. Starting with an empty or existing Expressir::SchemaManifest
|
|
40
|
-
# 2. Recursively traversing child entries to collect schemas
|
|
41
|
-
# 3. Using Expressir::SchemaManifest#concat to combine manifests
|
|
42
|
-
#
|
|
43
|
-
# The actual schema manifest operations (creation, concatenation, serialization)
|
|
44
|
-
# are handled by Expressir's SchemaManifest class, keeping the logic DRY.
|
|
45
|
-
#
|
|
46
|
-
# @param path [String] Base path for resolving relative schema paths
|
|
47
|
-
# @return [Expressir::SchemaManifest] Combined schema manifest
|
|
48
|
-
def export_schema_config(path)
|
|
49
|
-
export_config = @schema_config || Expressir::SchemaManifest.new
|
|
50
|
-
return export_config unless entry
|
|
51
|
-
|
|
52
|
-
entry.each do |x|
|
|
53
|
-
child_config = x.export_schema_config(path)
|
|
54
|
-
# Use Expressir's concat method to combine schema manifests
|
|
55
|
-
export_config.concat(child_config) if child_config
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
export_config
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def lookup_schemas_only
|
|
62
|
-
results = entry.select(&:schemas_only)
|
|
63
|
-
results << self if schemas_only
|
|
64
|
-
results
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def process_entry(schema_output_path)
|
|
68
|
-
return [self] unless entry
|
|
69
|
-
|
|
70
|
-
ret = entry.each_with_object([]) do |e, m|
|
|
71
|
-
add = e.expand_schemas_only(schema_output_path)
|
|
72
|
-
m.concat(add)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
self.entry = ret
|
|
76
|
-
[self]
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def expand_schemas_only(schema_output_path)
|
|
80
|
-
return process_entry(schema_output_path) unless file
|
|
81
|
-
|
|
82
|
-
update_schema_config
|
|
83
|
-
|
|
84
|
-
return process_entry(schema_output_path) unless schemas_only
|
|
85
|
-
|
|
86
|
-
# If we are going to keep the schemas-only file and compile it, we can't
|
|
87
|
-
# have it showing up in output.
|
|
88
|
-
self.index = false
|
|
89
|
-
|
|
90
|
-
[self, added_collection_manifest(schema_output_path)]
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def remove_schemas_only_sources
|
|
94
|
-
ret = entry.each_with_object([]) do |e, m|
|
|
95
|
-
e.schemas_only or m << e
|
|
96
|
-
end
|
|
97
|
-
self.entry = ret
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def entries(schema_output_path)
|
|
101
|
-
@schema_config.schemas.map do |schema|
|
|
102
|
-
fname = [File.basename(schema.path, ".exp"), ".xml"].join
|
|
103
|
-
|
|
104
|
-
CollectionManifest.new(
|
|
105
|
-
identifier: schema.id,
|
|
106
|
-
title: schema.id,
|
|
107
|
-
file: File.join(schema_output_path, schema.id, "doc_#{fname}"),
|
|
108
|
-
# schema_source: schema.path
|
|
109
|
-
)
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def added_collection_manifest(schema_output_path)
|
|
114
|
-
doc = CollectionConfig.from_file(file)
|
|
115
|
-
doc_id = doc.bibdata.id
|
|
116
|
-
|
|
117
|
-
# we need to separate this file from the following new entries
|
|
118
|
-
added = CollectionManifest.new(
|
|
119
|
-
title: "Collection",
|
|
120
|
-
type: "collection",
|
|
121
|
-
identifier: "#{identifier}_",
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
added.entry = [
|
|
125
|
-
CollectionManifest.new(
|
|
126
|
-
title: doc_id,
|
|
127
|
-
type: "document",
|
|
128
|
-
entry: entries(schema_output_path),
|
|
129
|
-
),
|
|
130
|
-
]
|
|
131
|
-
|
|
132
|
-
added
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def update_schema_config
|
|
136
|
-
# If there is collection.yml, this is a document collection, we process
|
|
137
|
-
# schemas.yaml.
|
|
138
|
-
if File.basename(file) == "collection.yml"
|
|
139
|
-
schemas_yaml_path = File.join(File.dirname(file), "schemas.yaml")
|
|
140
|
-
if schemas_yaml_path && File.exist?(schemas_yaml_path)
|
|
141
|
-
@schema_config = Expressir::SchemaManifest.from_file(schemas_yaml_path)
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
42
|
end
|
|
146
43
|
end
|
data/lib/suma/eengine/wrapper.rb
CHANGED
data/lib/suma/eengine.rb
ADDED
data/lib/suma/express_schema.rb
CHANGED
data/lib/suma/jsdai/figure.rb
CHANGED
data/lib/suma/jsdai.rb
CHANGED
data/lib/suma/link_validator.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "schema_index"
|
|
4
3
|
require "expressir"
|
|
5
4
|
|
|
6
5
|
module Suma
|
|
7
|
-
LinkValidationResult = Struct.new(:file, :line, :link, :reason,
|
|
6
|
+
LinkValidationResult = Struct.new(:file, :line, :link, :reason,
|
|
7
|
+
keyword_init: true)
|
|
8
8
|
|
|
9
9
|
class LinkValidator
|
|
10
10
|
def initialize(index)
|
|
@@ -93,18 +93,22 @@ module Suma
|
|
|
93
93
|
|
|
94
94
|
return unless parts.size > 2
|
|
95
95
|
|
|
96
|
-
error = validate_deep_path(schema, element, parts[2..], file, line_idx,
|
|
96
|
+
error = validate_deep_path(schema, element, parts[2..], file, line_idx,
|
|
97
|
+
link)
|
|
97
98
|
unresolved << error if error
|
|
98
99
|
end
|
|
99
100
|
|
|
100
|
-
def validate_deep_path(schema, element, path_parts, file, line_idx,
|
|
101
|
+
def validate_deep_path(schema, element, path_parts, file, line_idx,
|
|
102
|
+
full_link)
|
|
101
103
|
current = element
|
|
102
104
|
current_path = "#{schema.id}.#{element.id}"
|
|
103
105
|
|
|
104
106
|
path_parts.each do |part|
|
|
105
107
|
case current
|
|
106
108
|
when Expressir::Model::Declarations::Entity
|
|
107
|
-
attribute = current.attributes&.find
|
|
109
|
+
attribute = current.attributes&.find do |a|
|
|
110
|
+
a.id.downcase == part.downcase
|
|
111
|
+
end
|
|
108
112
|
|
|
109
113
|
unless attribute
|
|
110
114
|
return LinkValidationResult.new(
|
|
@@ -122,7 +126,9 @@ module Suma
|
|
|
122
126
|
underlying = current.underlying_type
|
|
123
127
|
|
|
124
128
|
if underlying.is_a?(Expressir::Model::DataTypes::Enumeration)
|
|
125
|
-
enum_value = underlying.items.find
|
|
129
|
+
enum_value = underlying.items.find do |e|
|
|
130
|
+
e.id.downcase == part.downcase
|
|
131
|
+
end
|
|
126
132
|
|
|
127
133
|
unless enum_value
|
|
128
134
|
return LinkValidationResult.new(
|
|
@@ -193,7 +199,9 @@ module Suma
|
|
|
193
199
|
schema.procedures,
|
|
194
200
|
schema.subtype_constraints,
|
|
195
201
|
].each do |collection|
|
|
196
|
-
element = collection&.find
|
|
202
|
+
element = collection&.find do |e|
|
|
203
|
+
e.id.downcase == element_name.downcase
|
|
204
|
+
end
|
|
197
205
|
return element if element
|
|
198
206
|
end
|
|
199
207
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "expressir"
|
|
4
|
+
|
|
5
|
+
module Suma
|
|
6
|
+
# Tree-walking service over a CollectionManifest.
|
|
7
|
+
#
|
|
8
|
+
# ManifestTraverser owns all imperative operations that walk or mutate a
|
|
9
|
+
# manifest tree: finding schemas-only entries, expanding them into
|
|
10
|
+
# compiled-doc sub-trees, exporting a unified Expressir::SchemaManifest,
|
|
11
|
+
# and removing schemas-only sources after compilation.
|
|
12
|
+
#
|
|
13
|
+
# Each method takes the manifest passed at construction as its root;
|
|
14
|
+
# recursion instantiates a new traverser per child node so the surface
|
|
15
|
+
# stays instance-based and the data model (CollectionManifest) stays pure.
|
|
16
|
+
#
|
|
17
|
+
# Schema-config loading and doc-entry construction are delegated to
|
|
18
|
+
# SchemaDiscovery so this class owns traversal, not schema I/O.
|
|
19
|
+
class ManifestTraverser
|
|
20
|
+
attr_reader :manifest
|
|
21
|
+
|
|
22
|
+
def initialize(manifest)
|
|
23
|
+
@manifest = manifest
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Returns every entry (anywhere in the tree) whose `schemas_only` flag
|
|
27
|
+
# is truthy, plus +manifest+ itself if it is schemas-only.
|
|
28
|
+
def find_schemas_only
|
|
29
|
+
results = (manifest.entry || []).select(&:schemas_only)
|
|
30
|
+
results << manifest if manifest.schemas_only
|
|
31
|
+
results
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Recursively concatenate every nested schema_config into a single
|
|
35
|
+
# Expressir::SchemaManifest. The manifest's own schema_config (if set)
|
|
36
|
+
# seeds the result; otherwise an empty SchemaManifest is returned.
|
|
37
|
+
def export_schema_config(path)
|
|
38
|
+
export_config = manifest.schema_config || Expressir::SchemaManifest.new
|
|
39
|
+
return export_config unless manifest.entry
|
|
40
|
+
|
|
41
|
+
manifest.entry.each do |child|
|
|
42
|
+
child_config = self.class.new(child).export_schema_config(path)
|
|
43
|
+
export_config.concat(child_config) if child_config
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
export_config
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Expand schemas-only entries into compiled-doc sub-trees. If the
|
|
50
|
+
# manifest has no file, walks children via process_entry. Otherwise
|
|
51
|
+
# loads the schema_config (SchemaDiscovery), and if this entry is
|
|
52
|
+
# schemas-only, hides it from the output index and appends a new
|
|
53
|
+
# sub-collection that hosts the compiled docs.
|
|
54
|
+
def expand_schemas_only(schema_output_path)
|
|
55
|
+
return process_entry(schema_output_path) unless manifest.file
|
|
56
|
+
|
|
57
|
+
SchemaDiscovery.new(manifest).load_config
|
|
58
|
+
|
|
59
|
+
return process_entry(schema_output_path) unless manifest.schemas_only
|
|
60
|
+
|
|
61
|
+
manifest.index = false
|
|
62
|
+
|
|
63
|
+
added = SchemaDiscovery.new(manifest).build_added_manifest(schema_output_path)
|
|
64
|
+
[manifest, added]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Drop every direct child whose `schemas_only` is truthy. Called after
|
|
68
|
+
# compilation so the schemas-only manifest file no longer shows up in
|
|
69
|
+
# the rendered collection.
|
|
70
|
+
def remove_schemas_only_sources
|
|
71
|
+
return unless manifest.entry
|
|
72
|
+
|
|
73
|
+
kept = manifest.entry.reject(&:schemas_only)
|
|
74
|
+
manifest.entry = kept
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
# Walk each child via expand_schemas_only, flattening the results back
|
|
80
|
+
# into manifest.entry.
|
|
81
|
+
def process_entry(schema_output_path)
|
|
82
|
+
return [manifest] unless manifest.entry
|
|
83
|
+
|
|
84
|
+
flattened = manifest.entry.each_with_object([]) do |child, acc|
|
|
85
|
+
acc.concat(self.class.new(child).expand_schemas_only(schema_output_path))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
manifest.entry = flattened
|
|
89
|
+
[manifest]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
data/lib/suma/processor.rb
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "schema_collection"
|
|
4
|
-
require_relative "utils"
|
|
5
|
-
require_relative "collection_config"
|
|
6
|
-
require_relative "site_config"
|
|
7
3
|
require "metanorma"
|
|
8
4
|
|
|
9
5
|
module Suma
|
|
@@ -41,11 +37,12 @@ module Suma
|
|
|
41
37
|
collection_config_path = site_config.metanorma.source.files.first
|
|
42
38
|
collection_config = Suma::CollectionConfig.from_file(collection_config_path)
|
|
43
39
|
collection_config.path = collection_config_path
|
|
44
|
-
collection_config.manifest.expand_schemas_only("schema_docs")
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
traverser = ManifestTraverser.new(collection_config.manifest)
|
|
42
|
+
traverser.expand_schemas_only("schema_docs")
|
|
48
43
|
|
|
44
|
+
exported_schema_config = traverser.export_schema_config(schemas_all_path)
|
|
45
|
+
exported_schema_config.path = schemas_all_path
|
|
49
46
|
exported_schema_config.to_file
|
|
50
47
|
|
|
51
48
|
collection_config
|
|
@@ -72,7 +69,7 @@ module Suma
|
|
|
72
69
|
|
|
73
70
|
def build_collection(collection_config, output_directory)
|
|
74
71
|
new_collection_config_path = "collection-output.yaml"
|
|
75
|
-
collection_config.manifest.remove_schemas_only_sources
|
|
72
|
+
ManifestTraverser.new(collection_config.manifest).remove_schemas_only_sources
|
|
76
73
|
collection_config.to_file(new_collection_config_path)
|
|
77
74
|
|
|
78
75
|
collection = Metanorma::Collection.parse(new_collection_config_path)
|