suma 0.2.5 → 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/.github/workflows/rake.yml +3 -0
- data/.github/workflows/release.yml +5 -1
- data/.gitignore +10 -1
- data/.rubocop_todo.yml +237 -28
- data/CLAUDE.md +102 -0
- data/Gemfile +3 -1
- data/README.adoc +188 -1
- data/exe/suma +1 -1
- data/lib/suma/cli/build.rb +2 -8
- data/lib/suma/cli/check_svg_quality.rb +172 -0
- data/lib/suma/cli/compare.rb +6 -158
- data/lib/suma/cli/convert_jsdai.rb +0 -2
- data/lib/suma/cli/core.rb +119 -0
- data/lib/suma/cli/export.rb +1 -10
- data/lib/suma/cli/extract_terms.rb +10 -654
- data/lib/suma/cli/generate_register.rb +34 -0
- data/lib/suma/cli/generate_schemas.rb +8 -124
- data/lib/suma/cli/reformat.rb +0 -1
- data/lib/suma/cli/validate.rb +0 -2
- data/lib/suma/cli/validate_links.rb +14 -291
- data/lib/suma/cli.rb +12 -102
- data/lib/suma/collection_config.rb +0 -2
- data/lib/suma/collection_manifest.rb +7 -111
- data/lib/suma/eengine/wrapper.rb +0 -1
- data/lib/suma/eengine.rb +8 -0
- data/lib/suma/express_schema.rb +43 -31
- data/lib/suma/jsdai/figure.rb +0 -3
- data/lib/suma/jsdai/figure_xml.rb +12 -9
- data/lib/suma/jsdai.rb +5 -8
- data/lib/suma/link_validator.rb +211 -0
- data/lib/suma/manifest_traverser.rb +92 -0
- data/lib/suma/processor.rb +76 -105
- data/lib/suma/register_manifest_generator.rb +163 -0
- data/lib/suma/schema_category.rb +83 -0
- data/lib/suma/schema_collection.rb +28 -63
- data/lib/suma/schema_comparer.rb +117 -0
- data/lib/suma/schema_compiler.rb +86 -0
- data/lib/suma/schema_discovery.rb +75 -0
- data/lib/suma/schema_exporter.rb +7 -35
- data/lib/suma/schema_index.rb +53 -0
- data/lib/suma/schema_manifest_generator.rb +113 -0
- 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 +78 -0
- data/lib/suma/svg_quality/formatters/json_formatter.rb +30 -0
- data/lib/suma/svg_quality/formatters/terminal_formatter.rb +168 -0
- data/lib/suma/svg_quality/formatters/yaml_formatter.rb +32 -0
- data/lib/suma/svg_quality/formatters.rb +12 -0
- data/lib/suma/svg_quality/report.rb +52 -0
- data/lib/suma/svg_quality.rb +30 -0
- data/lib/suma/term_extractor.rb +466 -0
- data/lib/suma/urn.rb +61 -0
- data/lib/suma/utils.rb +10 -2
- data/lib/suma/version.rb +1 -1
- data/lib/suma.rb +34 -5
- data/suma.gemspec +3 -2
- metadata +53 -9
- data/lib/suma/export_standalone_schema.rb +0 -14
- data/lib/suma/schema_attachment.rb +0 -130
- data/lib/suma/schema_document.rb +0 -132
|
@@ -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,114 +1,85 @@
|
|
|
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
|
|
10
6
|
class Processor
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
metanorma_collection.render(collection_opts)
|
|
89
|
-
|
|
90
|
-
# TODO: Temporarily disable removal of XML files
|
|
91
|
-
Dir.glob(File.join(Dir.getwd, output_directory,
|
|
92
|
-
"*.xml")).each do |file|
|
|
93
|
-
puts "NOT DELETING ANY FILE #{file.inspect}"
|
|
94
|
-
# File.delete(file)
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def build_collection(collection_config, output_directory)
|
|
99
|
-
new_collection_config_path = "collection-output.yaml"
|
|
100
|
-
collection_config.manifest.remove_schemas_only_sources
|
|
101
|
-
collection_config.to_file(new_collection_config_path)
|
|
102
|
-
|
|
103
|
-
collection = Metanorma::Collection.parse(new_collection_config_path)
|
|
104
|
-
|
|
105
|
-
collection_opts = {
|
|
106
|
-
output_folder: output_directory,
|
|
107
|
-
compile: { install_fonts: false },
|
|
108
|
-
coverpage: collection_config.coverpage || "cover.html",
|
|
109
|
-
}
|
|
110
|
-
[collection, collection_opts]
|
|
111
|
-
end
|
|
7
|
+
attr_reader :metanorma_yaml_path, :output_directory, :schemas_all_path,
|
|
8
|
+
:compile_flag
|
|
9
|
+
|
|
10
|
+
def initialize(metanorma_yaml_path:, schemas_all_path:, compile: true,
|
|
11
|
+
output_directory: "_site")
|
|
12
|
+
@metanorma_yaml_path = metanorma_yaml_path
|
|
13
|
+
@schemas_all_path = schemas_all_path
|
|
14
|
+
@compile_flag = compile
|
|
15
|
+
@output_directory = output_directory
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def run
|
|
19
|
+
Utils.log "Current directory: #{Dir.getwd}, writing #{schemas_all_path}..."
|
|
20
|
+
|
|
21
|
+
collection_config = export_schema_config
|
|
22
|
+
|
|
23
|
+
return nil unless @compile_flag
|
|
24
|
+
|
|
25
|
+
Utils.log "Compiling schema collection..."
|
|
26
|
+
compile_schema(schemas_all_path, collection_config)
|
|
27
|
+
|
|
28
|
+
Utils.log "Compiling complete collection..."
|
|
29
|
+
compile_collection(collection_config, output_directory)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def export_schema_config
|
|
35
|
+
site_config = Suma::SiteConfig::Config.from_file(metanorma_yaml_path)
|
|
36
|
+
|
|
37
|
+
collection_config_path = site_config.metanorma.source.files.first
|
|
38
|
+
collection_config = Suma::CollectionConfig.from_file(collection_config_path)
|
|
39
|
+
collection_config.path = collection_config_path
|
|
40
|
+
|
|
41
|
+
traverser = ManifestTraverser.new(collection_config.manifest)
|
|
42
|
+
traverser.expand_schemas_only("schema_docs")
|
|
43
|
+
|
|
44
|
+
exported_schema_config = traverser.export_schema_config(schemas_all_path)
|
|
45
|
+
exported_schema_config.path = schemas_all_path
|
|
46
|
+
exported_schema_config.to_file
|
|
47
|
+
|
|
48
|
+
collection_config
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def compile_schema(schemas_all_path, collection_config)
|
|
52
|
+
col = Suma::SchemaCollection.new(
|
|
53
|
+
config_yaml: schemas_all_path,
|
|
54
|
+
manifest: collection_config.manifest,
|
|
55
|
+
output_path_docs: "schema_docs",
|
|
56
|
+
output_path_schemas: "plain_schemas",
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
col.compile
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def compile_collection(collection_config, output_directory)
|
|
63
|
+
metanorma_collection, collection_opts = build_collection(
|
|
64
|
+
collection_config, output_directory
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
metanorma_collection.render(collection_opts)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def build_collection(collection_config, output_directory)
|
|
71
|
+
new_collection_config_path = "collection-output.yaml"
|
|
72
|
+
ManifestTraverser.new(collection_config.manifest).remove_schemas_only_sources
|
|
73
|
+
collection_config.to_file(new_collection_config_path)
|
|
74
|
+
|
|
75
|
+
collection = Metanorma::Collection.parse(new_collection_config_path)
|
|
76
|
+
|
|
77
|
+
collection_opts = {
|
|
78
|
+
output_folder: output_directory,
|
|
79
|
+
compile: { install_fonts: false },
|
|
80
|
+
coverpage: collection_config.coverpage || "cover.html",
|
|
81
|
+
}
|
|
82
|
+
[collection, collection_opts]
|
|
112
83
|
end
|
|
113
84
|
end
|
|
114
85
|
end
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "yaml"
|
|
4
|
+
require "pathname"
|
|
5
|
+
require "expressir"
|
|
6
|
+
require "glossarist"
|
|
7
|
+
|
|
8
|
+
module Suma
|
|
9
|
+
# Generates a Glossarist v3 register.yaml from an EXPRESS schema manifest.
|
|
10
|
+
#
|
|
11
|
+
# The schema manifest (schemas-smrl-part-2.yml) is the single source of
|
|
12
|
+
# truth for schema identities and paths. This class reads it, classifies
|
|
13
|
+
# each schema by type (resource/module), and emits a register.yaml with
|
|
14
|
+
# hierarchical sections and human-readable names.
|
|
15
|
+
#
|
|
16
|
+
# Architecture:
|
|
17
|
+
# - Classification: delegates to ExpressSchema::Type (DRY)
|
|
18
|
+
# - Naming: delegates to SchemaNaming (OCP — extend naming without
|
|
19
|
+
# touching this class)
|
|
20
|
+
# - Sections: built from Glossarist::Section models (model-driven)
|
|
21
|
+
# - URN semantics: delegates to Suma::Urn (OCP)
|
|
22
|
+
#
|
|
23
|
+
# @example
|
|
24
|
+
# generator = RegisterManifestGenerator.new(
|
|
25
|
+
# "schemas-smrl-part-2.yml",
|
|
26
|
+
# urn: "urn:iso:std:iso:10303:-2:ed-2:en:tech:*",
|
|
27
|
+
# id: "iso10303-2-express",
|
|
28
|
+
# ref: "ISO 10303-2 EXPRESS Concepts",
|
|
29
|
+
# )
|
|
30
|
+
# generator.generate # writes register.yaml
|
|
31
|
+
class RegisterManifestGenerator
|
|
32
|
+
DEFAULT_OWNER = "ISO/TC 184/SC 4"
|
|
33
|
+
DEFAULT_STATUS = "current"
|
|
34
|
+
DEFAULT_ORDERING = "systematic"
|
|
35
|
+
DEFAULT_SCHEMA_TYPE = "glossarist"
|
|
36
|
+
DEFAULT_SCHEMA_VERSION = "3"
|
|
37
|
+
|
|
38
|
+
# @param schema_manifest_file [String] path to schemas-smrl-part-2.yml
|
|
39
|
+
# @param output_path [String] directory to write register.yaml
|
|
40
|
+
# @param urn [String] base URN for the dataset
|
|
41
|
+
# @param id [String] dataset identifier
|
|
42
|
+
# @param ref [String] human-readable reference label
|
|
43
|
+
# @param language_code [String] language for section names
|
|
44
|
+
# @param owner [String] dataset owner organisation
|
|
45
|
+
def initialize(schema_manifest_file, output_path, urn:, id:, ref:,
|
|
46
|
+
language_code: "eng", owner: DEFAULT_OWNER)
|
|
47
|
+
@schema_manifest_file = File.expand_path(schema_manifest_file)
|
|
48
|
+
@output_path = output_path
|
|
49
|
+
@urn = Suma::Urn.new(urn)
|
|
50
|
+
@id = id
|
|
51
|
+
@ref = ref
|
|
52
|
+
@language_code = language_code
|
|
53
|
+
@owner = owner
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Generate and write register.yaml.
|
|
57
|
+
#
|
|
58
|
+
# @return [Glossarist::DatasetRegister] the generated register
|
|
59
|
+
def generate
|
|
60
|
+
validate_inputs
|
|
61
|
+
schemas = load_schemas
|
|
62
|
+
register = build_register(schemas)
|
|
63
|
+
|
|
64
|
+
FileUtils.mkdir_p(@output_path)
|
|
65
|
+
output_file = File.join(@output_path, "register.yaml")
|
|
66
|
+
File.write(output_file, register.to_yaml)
|
|
67
|
+
Utils.log "Generated register.yaml: #{output_file}"
|
|
68
|
+
Utils.log " #{schemas.length} schemas in #{register.sections.length} categories"
|
|
69
|
+
|
|
70
|
+
register
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
# Verify that the manifest path exists, is a regular file, and contains
|
|
76
|
+
# at least one schema entry. Called from {#generate} so both the CLI
|
|
77
|
+
# shell and direct construction get the same validation behavior.
|
|
78
|
+
#
|
|
79
|
+
# @raise [Errno::ENOENT] when the manifest path is missing or not a file
|
|
80
|
+
# @raise [ArgumentError] when the manifest is empty
|
|
81
|
+
def validate_inputs
|
|
82
|
+
unless File.exist?(@schema_manifest_file)
|
|
83
|
+
raise Errno::ENOENT, "Specified SCHEMA_MANIFEST_FILE " \
|
|
84
|
+
"`#{@schema_manifest_file}` not found."
|
|
85
|
+
end
|
|
86
|
+
unless File.file?(@schema_manifest_file)
|
|
87
|
+
raise Errno::ENOENT, "Specified SCHEMA_MANIFEST_FILE " \
|
|
88
|
+
"`#{@schema_manifest_file}` is not a file."
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Load all schemas from the manifest file as SchemaManifestEntry models.
|
|
93
|
+
#
|
|
94
|
+
# @return [Array<Expressir::SchemaManifestEntry>]
|
|
95
|
+
def load_schemas
|
|
96
|
+
manifest = Expressir::SchemaManifest.from_file(@schema_manifest_file)
|
|
97
|
+
schemas = manifest.schemas.sort_by { |s| s.id.downcase }
|
|
98
|
+
if schemas.empty?
|
|
99
|
+
raise ArgumentError, "No schemas found in manifest " \
|
|
100
|
+
"`#{@schema_manifest_file}`."
|
|
101
|
+
end
|
|
102
|
+
schemas
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Build a fully-populated DatasetRegister model.
|
|
106
|
+
#
|
|
107
|
+
# @param schemas [Array<Expressir::SchemaManifestEntry>]
|
|
108
|
+
# @return [Glossarist::DatasetRegister]
|
|
109
|
+
def build_register(schemas)
|
|
110
|
+
Glossarist::DatasetRegister.new(
|
|
111
|
+
schema_type: DEFAULT_SCHEMA_TYPE,
|
|
112
|
+
schema_version: DEFAULT_SCHEMA_VERSION,
|
|
113
|
+
id: @id,
|
|
114
|
+
ref: @ref,
|
|
115
|
+
urn: @urn.to_s,
|
|
116
|
+
urn_aliases: @urn.aliases,
|
|
117
|
+
status: DEFAULT_STATUS,
|
|
118
|
+
owner: @owner,
|
|
119
|
+
languages: [@language_code],
|
|
120
|
+
ordering: DEFAULT_ORDERING,
|
|
121
|
+
sections: build_sections(schemas),
|
|
122
|
+
)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Build a list of top-level sections, one per category, in
|
|
126
|
+
# SchemaCategory::ALL declaration order. Categories with no
|
|
127
|
+
# schemas are omitted.
|
|
128
|
+
#
|
|
129
|
+
# @param schemas [Array<Expressir::SchemaManifestEntry>]
|
|
130
|
+
# @return [Array<Glossarist::Section>]
|
|
131
|
+
def build_sections(schemas)
|
|
132
|
+
groups = schemas.group_by do |s|
|
|
133
|
+
SchemaCategory.for_schema(id: s.id, path: s.path)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
SchemaCategory::ALL.filter_map do |category|
|
|
137
|
+
children = groups[category] || []
|
|
138
|
+
next if children.empty?
|
|
139
|
+
|
|
140
|
+
Glossarist::Section.new(
|
|
141
|
+
id: category.id,
|
|
142
|
+
names: { @language_code => category.label },
|
|
143
|
+
children: children.map { |s| build_section(s) },
|
|
144
|
+
)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Build a single leaf section from a schema descriptor.
|
|
149
|
+
#
|
|
150
|
+
# @param schema [Expressir::SchemaManifestEntry]
|
|
151
|
+
# @return [Glossarist::Section]
|
|
152
|
+
def build_section(schema)
|
|
153
|
+
Glossarist::Section.new(
|
|
154
|
+
id: schema.id,
|
|
155
|
+
names: {
|
|
156
|
+
@language_code => SchemaNaming.prefixed_name(
|
|
157
|
+
schema.id, path: schema.path
|
|
158
|
+
),
|
|
159
|
+
},
|
|
160
|
+
)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Suma
|
|
4
|
+
# Value object mapping an ExpressSchema::Type to its register/export category.
|
|
5
|
+
#
|
|
6
|
+
# Single source of truth for category identity across the codebase:
|
|
7
|
+
# directory layout (SchemaExporter), display prefix (SchemaNaming), and
|
|
8
|
+
# register.yaml sections (RegisterManifestGenerator) all derive from this.
|
|
9
|
+
#
|
|
10
|
+
# Each category carries: +id+ (slug used in register.yaml section id and
|
|
11
|
+
# export subdirectory), +label+ (human-readable section heading),
|
|
12
|
+
# +prefix+ (prefix used when forming display names, e.g. "Resource: ..."),
|
|
13
|
+
# +types+ (Array of ExpressSchema::Type symbols that belong to it),
|
|
14
|
+
# and +directory+ (subdirectory name; "." for the root output path).
|
|
15
|
+
class SchemaCategory
|
|
16
|
+
attr_reader :id, :label, :prefix, :types, :directory
|
|
17
|
+
|
|
18
|
+
def initialize(id:, label:, prefix:, types:, directory:)
|
|
19
|
+
@id = id
|
|
20
|
+
@label = label
|
|
21
|
+
@prefix = prefix
|
|
22
|
+
@types = types
|
|
23
|
+
@directory = directory
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def member?(type)
|
|
27
|
+
types.include?(type)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
RESOURCES = new(
|
|
31
|
+
id: "resources",
|
|
32
|
+
label: "Resources",
|
|
33
|
+
prefix: "Resource",
|
|
34
|
+
types: [ExpressSchema::Type::RESOURCE].freeze,
|
|
35
|
+
directory: "resources",
|
|
36
|
+
)
|
|
37
|
+
MODULES = new(
|
|
38
|
+
id: "modules",
|
|
39
|
+
label: "Application Modules",
|
|
40
|
+
prefix: "Module",
|
|
41
|
+
types: [ExpressSchema::Type::MODULE_ARM, ExpressSchema::Type::MODULE_MIM].freeze,
|
|
42
|
+
directory: "modules",
|
|
43
|
+
)
|
|
44
|
+
BUSINESS_OBJECT_MODELS = new(
|
|
45
|
+
id: "business_object_models",
|
|
46
|
+
label: "Business Object Models",
|
|
47
|
+
prefix: "Business Object Model",
|
|
48
|
+
types: [ExpressSchema::Type::BUSINESS_OBJECT_MODEL].freeze,
|
|
49
|
+
directory: "business_object_models",
|
|
50
|
+
)
|
|
51
|
+
CORE_MODEL = new(
|
|
52
|
+
id: "core_model",
|
|
53
|
+
label: "Core Model",
|
|
54
|
+
prefix: "Core Model",
|
|
55
|
+
types: [ExpressSchema::Type::CORE_MODEL].freeze,
|
|
56
|
+
directory: "core_model",
|
|
57
|
+
)
|
|
58
|
+
OTHER = new(
|
|
59
|
+
id: "other",
|
|
60
|
+
label: "Other Schemas",
|
|
61
|
+
prefix: "Schema",
|
|
62
|
+
types: [ExpressSchema::Type::STANDALONE].freeze,
|
|
63
|
+
directory: ".",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
ALL = [
|
|
67
|
+
RESOURCES,
|
|
68
|
+
MODULES,
|
|
69
|
+
BUSINESS_OBJECT_MODELS,
|
|
70
|
+
CORE_MODEL,
|
|
71
|
+
OTHER,
|
|
72
|
+
].freeze
|
|
73
|
+
|
|
74
|
+
def self.for_type(type)
|
|
75
|
+
ALL.find { |category| category.member?(type) } || OTHER
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.for_schema(id:, path:)
|
|
79
|
+
type = ExpressSchema::Type.classify(id: id, path: path)
|
|
80
|
+
for_type(type)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "express_schema"
|
|
4
|
-
require_relative "schema_attachment"
|
|
5
|
-
require_relative "schema_document"
|
|
6
|
-
require_relative "schema_exporter"
|
|
7
3
|
require "expressir"
|
|
8
|
-
require_relative "utils"
|
|
9
4
|
|
|
10
5
|
module Suma
|
|
11
6
|
class SchemaCollection
|
|
@@ -30,46 +25,20 @@ module Suma
|
|
|
30
25
|
@schema_name_to_docs[schema_name]
|
|
31
26
|
end
|
|
32
27
|
|
|
33
|
-
def process_schemas(schemas, klass)
|
|
34
|
-
schemas.each do |config_schema|
|
|
35
|
-
process_schema(config_schema, klass)
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def process_schema(config_schema, klass)
|
|
40
|
-
s = ExpressSchema.new(
|
|
41
|
-
id: config_schema.id, path: config_schema.path.to_s,
|
|
42
|
-
output_path: @output_path_schemas.to_s
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
doc = klass.new(
|
|
46
|
-
schema: s, output_path: @output_path_docs.join(s.id),
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
@docs[s.id] = doc
|
|
50
|
-
@schemas[s.id] = s
|
|
51
|
-
@schema_name_to_docs[s.id] = doc
|
|
52
|
-
end
|
|
53
|
-
|
|
54
28
|
def finalize
|
|
55
|
-
|
|
56
|
-
process_schemas(@config.schemas, SchemaAttachment)
|
|
29
|
+
process_schemas(@config.schemas, SchemaTemplate::Plain)
|
|
57
30
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
manifest_entry.each do |entry|
|
|
31
|
+
schemas_only_entries = ManifestTraverser.new(@manifest).find_schemas_only
|
|
32
|
+
schemas_only_entries.each do |entry|
|
|
61
33
|
next unless entry.schema_config
|
|
62
34
|
|
|
63
|
-
|
|
64
|
-
process_schemas(entry.schema_config.schemas, SchemaDocument)
|
|
35
|
+
process_schemas(entry.schema_config.schemas, SchemaTemplate::Document)
|
|
65
36
|
end
|
|
66
37
|
end
|
|
67
38
|
|
|
68
|
-
# rubocop:disable Metrics/MethodLength
|
|
69
39
|
def compile
|
|
70
40
|
finalize
|
|
71
41
|
|
|
72
|
-
# Use SchemaExporter for schema export
|
|
73
42
|
exporter = SchemaExporter.new(
|
|
74
43
|
schemas: @config.schemas,
|
|
75
44
|
output_path: @output_path_schemas,
|
|
@@ -77,36 +46,32 @@ module Suma
|
|
|
77
46
|
)
|
|
78
47
|
exporter.export
|
|
79
48
|
|
|
80
|
-
docs.each_pair do |_schema_id,
|
|
81
|
-
|
|
49
|
+
docs.each_pair do |_schema_id, compiler|
|
|
50
|
+
compiler.compile
|
|
82
51
|
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def process_schemas(schemas, template_class)
|
|
57
|
+
schemas.each { |s| process_schema(s, template_class) }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def process_schema(config_schema, template_class)
|
|
61
|
+
express = ExpressSchema.new(
|
|
62
|
+
id: config_schema.id, path: config_schema.path.to_s,
|
|
63
|
+
output_path: @output_path_schemas.to_s
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
compiler = SchemaCompiler.new(
|
|
67
|
+
schema: express,
|
|
68
|
+
output_path: @output_path_docs.join(express.id),
|
|
69
|
+
template: template_class.new(express.id),
|
|
70
|
+
)
|
|
83
71
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# loop do
|
|
88
|
-
# Ractor.yield(Ractor.receive)
|
|
89
|
-
# end
|
|
90
|
-
# end
|
|
91
|
-
# workers = (1..4).map do |i|
|
|
92
|
-
# Ractor.new(pool, name: "r#{i}") do |p|
|
|
93
|
-
# loop do
|
|
94
|
-
# input = p.take
|
|
95
|
-
# Utils.log"compiling in ractor for #{input.filename_adoc}"
|
|
96
|
-
# output_value = input.compile
|
|
97
|
-
# Ractor.yield(output_value)
|
|
98
|
-
# end
|
|
99
|
-
# end
|
|
100
|
-
# end
|
|
101
|
-
# docs.each do |doc|
|
|
102
|
-
# pool.send(doc)
|
|
103
|
-
# end
|
|
104
|
-
# results = []
|
|
105
|
-
# docs.size.times do
|
|
106
|
-
# results << Ractor.select(*workers)
|
|
107
|
-
# end
|
|
108
|
-
# pp results
|
|
72
|
+
@docs[express.id] = compiler
|
|
73
|
+
@schemas[express.id] = express
|
|
74
|
+
@schema_name_to_docs[express.id] = compiler
|
|
109
75
|
end
|
|
110
|
-
# rubocop:enable Metrics/MethodLength
|
|
111
76
|
end
|
|
112
77
|
end
|