suma 0.1.13 → 0.1.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fcc000e30cb69dd5ab1d326cbcf06ca4fe2c2855a7368f2a0387a369c15721c
4
- data.tar.gz: 3873c8355f19b4ccb2f8b8d3530eeac2ad81e65e880e44b97765413377ff71a1
3
+ metadata.gz: d52aaad6ea81bb43e193cdf0c8e190dfe02f71791e218314a401ae3bea254cd3
4
+ data.tar.gz: a573936a7eabfad21a4768e6c32869ecc286a2980feeaf8350720b674c604f34
5
5
  SHA512:
6
- metadata.gz: 0a18e25ee8e47d39028d0bd9bd5dd9c2f602bf540f77b3729f402bf22c86cedc5f7b037c5901886c109d869aa64d1eb82ca70c4960ba73cc2e655bd73867f80a
7
- data.tar.gz: 0b29d4b9a641de7a7056785057379e9c26a4709cec7597aa2ee2135f22cc14b52dfd66c78b5ad3204848d775b7e3b3e0537ca34c21defb29155e8dd2a20d8342
6
+ metadata.gz: d7278d60481858a6507bf97f738df21f0168c60c6453f9de4479545c589450f63c148923be20b31a8bb88e50344adbf8521cfe12a826dbff3103e492782727f3
7
+ data.tar.gz: b37f9d1f0676607011f6f2059f0b639a563273930eb7961ee52866c04b30df14a7b88076752f4bf2ff4cfd4911a402b547b1c486c42cd9cc381d4e631bc6aac4
data/README.adoc CHANGED
@@ -37,10 +37,12 @@ $ gem install suma
37
37
  # Defaults to `suma help`
38
38
  $ suma
39
39
  Commands:
40
- suma build METANORMA_SITE_MANIFEST # Build collection specified in site manifest (`metanorma*.yml`)
41
- suma reformat EXPRESS_FILE_PATH # Reformat EXPRESS files
42
- suma validate SUBCOMMAND ...ARGS # Validate express documents
43
- suma help [COMMAND] # Describe available commands or one specific command
40
+ suma build METANORMA_SITE_MANIFEST # Build collection specified in site manifest (`metanorma*.yml`)
41
+ suma reformat EXPRESS_FILE_PATH # Reformat EXPRESS files
42
+ suma validate SUBCOMMAND ...ARGS # Validate express documents
43
+ suma generate_schemas METANORMA_MANIFEST_FILE SCHEMA_MANIFEST_FILE # Generate schemas manifest file from Metanorma manifest YAML file
44
+ suma extract_terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH # Extract terms from schema manifest file
45
+ suma help [COMMAND] # Describe available commands or one specific command
44
46
  ----
45
47
 
46
48
  === Build command
@@ -287,6 +289,85 @@ Replacement: AsciiMath: xx
287
289
  ----
288
290
 
289
291
 
292
+ === Generate schemas command
293
+
294
+ The `suma generate_schemas` command generates a schema manifest file containing
295
+ all schemas defined in the Metanorma manifest file.
296
+
297
+ [source,sh]
298
+ ----
299
+ $ suma generate_schemas METANORMA_MANIFEST_FILE SCHEMA_MANIFEST_FILE [options]
300
+ ----
301
+
302
+ Parameters:
303
+
304
+ `METANORMA_MANIFEST_FILE`:: Path to the Metanorma manifest file
305
+ (e.g.: "metanorma-smrl-all.yml")
306
+
307
+ Options:
308
+
309
+ `--exclude_path`, `-e`:: Exclude schemas by pattern (e.g. `*_lf.exp`)
310
+
311
+ [example]
312
+ ====
313
+ .To generate schemas manifest file from Metanorma manifest file
314
+ [source,sh]
315
+ ----
316
+ $ bundle exec suma generate_schemas metanorma-smrl-all.yml schemas-smrl-all.yml
317
+ # => generates schemas-smrl-all.yml
318
+ ----
319
+
320
+ .To generate schemas manifest file from Metanorma manifest file and exclude schemas with names like `*_lf.exp`
321
+ [source,sh]
322
+ ----
323
+ $ bundle exec suma generate_schemas metanorma-smrl-all.yml schemas-smrl-all.yml -e *_lf.exp
324
+ # => generates schemas-smrl-all.yml without schemas with names like *_lf.exp
325
+ ----
326
+ ====
327
+
328
+ All documents need to have a `schemas.yaml` in their document root that lists
329
+ out which schemas the document includes.
330
+
331
+
332
+ === Extract terms command
333
+
334
+ The `suma extract_terms` command extracts terms from SCHEMA_MANIFEST_FILE and
335
+ generates Glossarist v2 dataset in the output directory.
336
+
337
+ [source,sh]
338
+ ----
339
+ $ suma extract_terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH [options]
340
+ ----
341
+
342
+ Parameters:
343
+
344
+ `SCHEMA_MANIFEST_FILE`:: Path to SCHEMA_MANIFEST_FILE
345
+
346
+ `GLOSSARIST_OUTPUT_PATH`:: Path to the output directory for the Glossarist v2
347
+ dataset
348
+
349
+ Options:
350
+
351
+ `language_code`:: Language code for the Glossarist (default: "eng")
352
+
353
+ [example]
354
+ ====
355
+ .To extract terms from SCHEMA_MANIFEST_FILE
356
+ [source,sh]
357
+ ----
358
+ $ bundle exec suma extract_terms path/to/schemas-smrl-all.yml glossarist_output
359
+ # => generates glossarist_output/concept/foo.yaml and glossarist_output/localized_concept/bar.yaml
360
+ ----
361
+
362
+ .To extract terms from SCHEMA_MANIFEST_FILE with language code "fra"
363
+ [source,sh]
364
+ ----
365
+ $ bundle exec suma extract_terms path/to/schemas-smrl-all.yml glossarist_output -l fra
366
+ # => generates glossarist_output/concept/foo.yaml and glossarist_output/localized_concept/bar.yaml
367
+ ----
368
+ ====
369
+
370
+
290
371
  == Usage: Ruby
291
372
 
292
373
  === General
@@ -0,0 +1,286 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "thor"
4
+ require_relative "../thor_ext"
5
+ require "fileutils"
6
+ require "expressir"
7
+ require "yaml"
8
+ require "securerandom"
9
+ require "glossarist"
10
+
11
+ module Suma
12
+ module Cli
13
+ # ExtractTerms command using Expressir to extract terms into the
14
+ # Glossarist v2 format
15
+ class ExtractTerms < Thor
16
+ desc "extract_terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH",
17
+ "Extract terms from SCHEMA_MANIFEST_FILE into " \
18
+ "Glossarist v2 format"
19
+ option :language_code, type: :string, default: "eng", aliases: "-l",
20
+ desc: "Language code for the Glossarist"
21
+
22
+ YAML_FILE_EXTENSIONS = [".yaml", ".yml"].freeze
23
+
24
+ def extract_terms(schema_manifest_file, output_path) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
25
+ language_code = options[:language_code]
26
+ schema_manifest_file = File.expand_path(schema_manifest_file)
27
+
28
+ if File.file?(schema_manifest_file)
29
+ unless File.exist?(schema_manifest_file)
30
+ raise Errno::ENOENT, "Specified SCHEMA_MANIFEST_FILE " \
31
+ "`#{schema_manifest_file}` not found."
32
+ end
33
+
34
+ if !YAML_FILE_EXTENSIONS.include?(File.extname(schema_manifest_file))
35
+ raise ArgumentError, "Specified SCHEMA_MANIFEST_FILE " \
36
+ "`#{schema_manifest_file}` " \
37
+ "is not a YAML file."
38
+ end
39
+ end
40
+
41
+ run(schema_manifest_file, output_path, language_code)
42
+ end
43
+
44
+ private
45
+
46
+ def run(schema_manifest_file, output_path, language_code = "eng")
47
+ exp_files = get_exp_files(schema_manifest_file)
48
+
49
+ exp_files.map do |exp_file|
50
+ extract(exp_file, output_path, language_code)
51
+ end
52
+ end
53
+
54
+ def get_exp_files(schema_manifest_file)
55
+ data = YAML.safe_load(
56
+ File.read(schema_manifest_file, encoding: "UTF-8"),
57
+ permitted_classes: [Date, Time, Symbol],
58
+ permitted_symbols: [],
59
+ aliases: true,
60
+ )
61
+
62
+ paths = data["schemas"].values.filter_map { |v| v["path"] }
63
+
64
+ if paths.empty?
65
+ raise Errno::ENOENT, "No EXPRESS files found in " \
66
+ "`#{schema_manifest_file}`."
67
+ end
68
+
69
+ # resolve paths relative to the directory of the schema manifest file
70
+ paths.map do |path|
71
+ File.expand_path(path, File.dirname(schema_manifest_file))
72
+ end
73
+ end
74
+
75
+ def extract(exp_file, output_path, language_code) # rubocop:disable Metrics/AbcSize
76
+ puts "Processing EXPRESS file: #{exp_file}"
77
+ repo = Expressir::Express::Parser.from_file(exp_file)
78
+ schema = get_default_schema(repo)
79
+
80
+ collection = build_managed_concept_collection(
81
+ schema, language_code
82
+ )
83
+
84
+ output_data(collection, output_path, exp_file)
85
+ end
86
+
87
+ def output_data(collection, output_path, exp_file)
88
+ unless File.exist?(output_path)
89
+ FileUtils.mkdir_p(File.expand_path(output_path))
90
+ end
91
+
92
+ puts "Saving collection to files in: #{File.expand_path(output_path)}"
93
+ collection.save_to_files(File.expand_path(output_path))
94
+
95
+ puts "Processing EXPRESS file: #{exp_file}...Done."
96
+ collection
97
+ end
98
+
99
+ def build_managed_concept_collection(schema, language_code) # rubocop:disable Metrics/AbcSize
100
+ managed_concept_data = Glossarist::ManagedConceptData.new
101
+ managed_concept_data.id = get_identifier(schema)
102
+
103
+ localized_concept_id = SecureRandom.uuid
104
+ localized_concept = build_localized_concept(
105
+ schema, language_code, localized_concept_id
106
+ )
107
+
108
+ managed_concept_data
109
+ .localizations[localized_concept.language_code] = localized_concept
110
+
111
+ managed_concept_data.localized_concepts = {
112
+ localized_concept.language_code => localized_concept_id,
113
+ }
114
+
115
+ managed_concept = Glossarist::ManagedConcept.new
116
+ managed_concept.uuid = SecureRandom.uuid
117
+ managed_concept.data = managed_concept_data
118
+
119
+ collection = Glossarist::ManagedConceptCollection.new
120
+ collection.store(managed_concept)
121
+ collection
122
+ end
123
+
124
+ def build_localized_concept(schema, language_code, localized_concept_id) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity
125
+ schema_domain = get_domain(schema)
126
+
127
+ localized_concept_data = Glossarist::ConceptData.new
128
+ localized_concept_data.terms = get_terms(schema) || []
129
+ localized_concept_data.definition = get_definitions(schema) || []
130
+ localized_concept_data.notes = get_notes(schema, schema_domain) || []
131
+ localized_concept_data.examples = get_examples(schema,
132
+ schema_domain) || []
133
+ localized_concept_data.language_code = language_code
134
+ localized_concept_data.domain = schema_domain
135
+ localized_concept_data.sources = get_source_ref(schema) || []
136
+
137
+ localized_concept = Glossarist::LocalizedConcept.new
138
+ localized_concept.data = localized_concept_data
139
+
140
+ localized_concept.uuid = localized_concept_id
141
+ localized_concept
142
+ end
143
+
144
+ def get_default_schema(repo)
145
+ repo.schemas.first
146
+ end
147
+
148
+ def get_identifier(schema)
149
+ remark_item = schema.remark_items.find do |s|
150
+ s.id == "__identifier"
151
+ end
152
+ remark_item.remarks.first || SecureRandom.uuid
153
+ end
154
+
155
+ def get_title(schema)
156
+ remark_item = schema.remark_items.find do |s|
157
+ s.id == "__title"
158
+ end
159
+ remark_item.remarks.first
160
+ end
161
+
162
+ def get_source_ref(schema)
163
+ remark_item = schema.remark_items.find do |s|
164
+ s.id == "__published_in"
165
+ end
166
+ ref = remark_item&.remarks&.first
167
+
168
+ if ref
169
+ Glossarist::ConceptSource.new(
170
+ type: "authoritative",
171
+ origin: Glossarist::Citation.new(ref: ref),
172
+ )
173
+ end
174
+ end
175
+
176
+ def get_domain(schema)
177
+ prefix = module?(schema) ? "application module" : "resource"
178
+ "#{prefix}: #{schema.id}"
179
+ end
180
+
181
+ def module?(schema)
182
+ remark_item = schema.remark_items.find do |s|
183
+ s.id == "__schema_file"
184
+ end
185
+
186
+ File.basename(remark_item.remarks.first, ".*") == "module"
187
+ end
188
+
189
+ def arm?(schema_id)
190
+ schema_id.end_with?("_arm")
191
+ end
192
+
193
+ def get_terms(schema)
194
+ schema_title = get_title(schema)
195
+ if schema_title
196
+ [
197
+ Glossarist::Designation::Base.new(
198
+ designation: schema_title,
199
+ type: "expression",
200
+ normative_status: "preferred",
201
+ ),
202
+ ]
203
+ end
204
+ end
205
+
206
+ def get_schema_type(schema)
207
+ return "resource" if !module?(schema)
208
+
209
+ return "arm" if arm?(schema.id)
210
+
211
+ "min"
212
+ end
213
+
214
+ def get_definitions(schema)
215
+ type = get_schema_type(schema)
216
+ subtype = get_subtype_of(schema)
217
+
218
+ represent_str = "that represents the #{get_title(schema)} {{entity}}"
219
+ if subtype
220
+ represent_str = "that is a type of #{subtype} #{represent_str}"
221
+ end
222
+
223
+ definition = case type
224
+ when "arm"
225
+ "{{application object}} #{represent_str}"
226
+ else
227
+ "{{entity data type}} #{represent_str}"
228
+ end
229
+ [Glossarist::DetailedDefinition.new(content: definition)]
230
+ end
231
+
232
+ def get_subtype_of(schema)
233
+ schema.entities.first&.subtype_of&.first&.id # rubocop:disable Style/SafeNavigationChainLength
234
+ end
235
+
236
+ # get entities remarks and remark items with id `__note` as notes
237
+ def get_notes(schema, schema_domain) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize
238
+ notes = schema.entities&.map do |entity|
239
+ [
240
+ entity.remarks,
241
+ entity.remark_items&.select do |ri|
242
+ ri.id == "__note"
243
+ end&.map(&:remarks),
244
+ ]
245
+ end&.flatten&.compact
246
+
247
+ notes&.map do |note|
248
+ Glossarist::DetailedDefinition.new(
249
+ content: convert_express_xref(note, schema_domain),
250
+ )
251
+ end
252
+ end
253
+
254
+ # get entities remark items with id `__example` as examples
255
+ def get_examples(schema, schema_domain) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize
256
+ examples = schema.entities&.map do |entity|
257
+ entity.remark_items&.select do |ri|
258
+ ri.id == "__example"
259
+ end&.map(&:remarks)
260
+ end&.flatten&.compact
261
+
262
+ examples&.map do |example|
263
+ Glossarist::DetailedDefinition.new(
264
+ content: convert_express_xref(example, schema_domain),
265
+ )
266
+ end
267
+ end
268
+
269
+ def convert_express_xref(content, schema_domain)
270
+ content.gsub(/<<express:(.*),(.*)>>/) do
271
+ "{{<#{schema_domain}>" \
272
+ "#{Regexp.last_match(1).split('.').last},#{Regexp.last_match(2)}}}"
273
+ end
274
+ end
275
+
276
+ def get_concept_filename(concept)
277
+ identifier = concept["data"]["identifier"]
278
+ "#{sanitize_string(identifier)}.yaml"
279
+ end
280
+
281
+ def sanitize_string(str)
282
+ str.gsub(" ", "_").gsub("/", "_").gsub(":", "_")
283
+ end
284
+ end
285
+ end
286
+ end
@@ -0,0 +1,141 @@
1
+ require "thor"
2
+ require_relative "../thor_ext"
3
+ require "fileutils"
4
+ require "yaml"
5
+ require "pathname"
6
+
7
+ module Suma
8
+ module Cli
9
+ # GenerateSchemas command to generate Schemas YAML by Metanorma YAML
10
+ class GenerateSchemas < Thor
11
+ desc "generate_schemas METANORMA_MANIFEST_FILE SCHEMA_MANIFEST_FILE",
12
+ "Generate EXPRESS schema manifest file from Metanorma site manifest"
13
+ option :exclude_paths, type: :string, default: nil, aliases: "-e",
14
+ desc: "Exclude schemas paths by pattern " \
15
+ "(e.g. `*_lf.exp`)"
16
+
17
+ YAML_FILE_EXTENSIONS = [".yaml", ".yml"].freeze
18
+
19
+ def generate_schemas(metanorma_manifest_file, schema_manifest_file) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
20
+ metanorma_manifest_file = File.expand_path(metanorma_manifest_file)
21
+
22
+ unless File.exist?(metanorma_manifest_file)
23
+ raise Errno::ENOENT, "Specified file `#{metanorma_manifest_file}` " \
24
+ "not found."
25
+ end
26
+
27
+ unless File.file?(metanorma_manifest_file)
28
+ raise ArgumentError, "Specified path `#{metanorma_manifest_file}` " \
29
+ "is not a file."
30
+ end
31
+
32
+ [metanorma_manifest_file, schema_manifest_file].each do |file|
33
+ if !YAML_FILE_EXTENSIONS.include?(File.extname(file))
34
+ raise ArgumentError, "Specified file `#{file}` is not a YAML file."
35
+ end
36
+ end
37
+
38
+ run(
39
+ metanorma_manifest_file, schema_manifest_file,
40
+ exclude_paths: options[:exclude_paths]
41
+ )
42
+ end
43
+
44
+ private
45
+
46
+ def run(metanorma_manifest_file, schema_manifest_file, exclude_paths: nil)
47
+ metanorma_data = load_yaml(metanorma_manifest_file)
48
+ collection_files = metanorma_data["metanorma"]["source"]["files"]
49
+ manifest_files = load_manifest_files(collection_files)
50
+ all_schemas = load_project_schemas(manifest_files, exclude_paths,
51
+ schema_manifest_file)
52
+ all_schemas["schemas"] = all_schemas["schemas"].sort.to_h
53
+ output_data(all_schemas, schema_manifest_file)
54
+ end
55
+
56
+ def output_data(all_schemas, path)
57
+ puts "Writing the Schemas YAML file to #{File.expand_path(path)}..."
58
+ # debug use only
59
+ # puts all_schemas.to_yaml
60
+ File.write(File.expand_path(path), all_schemas.to_yaml)
61
+ puts "Writing the Schemas YAML file to #{File.expand_path(path)}...Done"
62
+ end
63
+
64
+ def load_yaml(file_path)
65
+ YAML.safe_load(
66
+ File.read(file_path, encoding: "UTF-8"),
67
+ permitted_classes: [Date, Time, Symbol],
68
+ permitted_symbols: [],
69
+ aliases: true,
70
+ )
71
+ end
72
+
73
+ def load_manifest_files(collection_files)
74
+ manifest_files = collection_files.map do |c|
75
+ collection_data = load_yaml(c)
76
+ collection_data["manifest"]["docref"].map { |docref| docref["file"] }
77
+ end
78
+ manifest_files.flatten
79
+ end
80
+
81
+ def load_project_schemas( # rubocop:disable Metrics/AbcSize
82
+ manifest_files, exclude_paths, schema_manifest_file
83
+ )
84
+ all_schemas = { "schemas" => {} }
85
+
86
+ manifest_files.each do |file|
87
+ # load schemas.yaml from the location of the collection.yml file
88
+ schemas_file_path = File.expand_path(
89
+ file.gsub("collection.yml", "schemas.yaml"),
90
+ )
91
+ unless File.exist?(schemas_file_path)
92
+ puts "Schemas file not found: #{schemas_file_path}"
93
+ next
94
+ end
95
+
96
+ schemas_data = load_yaml(schemas_file_path)
97
+
98
+ if schemas_data["schemas"]
99
+ schemas_data["schemas"] = fix_path(
100
+ schemas_data,
101
+ schemas_file_path,
102
+ schema_manifest_file,
103
+ )
104
+ all_schemas["schemas"].merge!(schemas_data["schemas"])
105
+ end
106
+
107
+ if exclude_paths
108
+ all_schemas["schemas"].delete_if do |_key, value|
109
+ value["path"].match?(
110
+ Regexp.new(exclude_paths.gsub("*", "(.*){1,999}")),
111
+ )
112
+ end
113
+ end
114
+ end
115
+
116
+ all_schemas
117
+ end
118
+
119
+ def fix_path(schemas_data, schemas_file_path, schema_manifest_file) # rubocop:disable Metrics/AbcSize
120
+ schema_manifest_path = File.expand_path(schema_manifest_file, Dir.pwd)
121
+
122
+ schemas_data["schemas"].each do |key, value|
123
+ # resolve the path in the schema file by the path in the schemas.yaml
124
+ path_in_schema = File.expand_path(
125
+ value["path"],
126
+ File.dirname(schemas_file_path),
127
+ )
128
+
129
+ # calculate the relative path from the schema manifest file
130
+ fixed_path = Pathname.new(path_in_schema).relative_path_from(
131
+ Pathname.new(File.dirname(schema_manifest_path)),
132
+ )
133
+
134
+ { key => value.merge!("path" => fixed_path.to_s) }
135
+ end
136
+
137
+ schemas_data["schemas"]
138
+ end
139
+ end
140
+ end
141
+ end
data/lib/suma/cli.rb CHANGED
@@ -23,6 +23,16 @@ module Suma
23
23
  Cli::Build.start
24
24
  end
25
25
 
26
+ desc "generate_schemas METANORMA_MANIFEST_FILE SCHEMA_MANIFEST_FILE",
27
+ "Generate EXPRESS schema manifest file from Metanorma site manifest"
28
+ option :exclude_paths, type: :string, default: nil, aliases: "-e",
29
+ desc: "Exclude schemas paths by pattern " \
30
+ "(e.g. `*_lf.exp`)"
31
+ def generate_schemas(_metanorma_manifest_file, _schema_manifest_file)
32
+ require_relative "cli/generate_schemas"
33
+ Cli::GenerateSchemas.start
34
+ end
35
+
26
36
  desc "reformat EXPRESS_FILE_PATH",
27
37
  "Reformat EXPRESS files"
28
38
  option :recursive, type: :boolean, default: false, aliases: "-r",
@@ -33,6 +43,16 @@ module Suma
33
43
  Cli::Reformat.start
34
44
  end
35
45
 
46
+ desc "extract_terms SCHEMA_MANIFEST_FILE GLOSSARIST_OUTPUT_PATH",
47
+ "Extract terms from SCHEMA_MANIFEST_FILE into " \
48
+ "Glossarist v2 format"
49
+ option :language_code, type: :string, default: "eng", aliases: "-l",
50
+ desc: "Language code for the Glossarist"
51
+ def extract_terms(_schema_manifest_file, _glossarist_output_path)
52
+ require_relative "cli/extract_terms"
53
+ Cli::ExtractTerms.start
54
+ end
55
+
36
56
  desc "validate SUBCOMMAND ...ARGS", "Validate express documents"
37
57
  subcommand "validate", Cli::Validate
38
58
 
data/lib/suma/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Suma
4
- VERSION = "0.1.13"
4
+ VERSION = "0.1.14"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: suma
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-05-24 00:00:00.000000000 Z
11
+ date: 2025-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: expressir
@@ -134,6 +134,8 @@ files:
134
134
  - lib/suma.rb
135
135
  - lib/suma/cli.rb
136
136
  - lib/suma/cli/build.rb
137
+ - lib/suma/cli/extract_terms.rb
138
+ - lib/suma/cli/generate_schemas.rb
137
139
  - lib/suma/cli/reformat.rb
138
140
  - lib/suma/cli/validate.rb
139
141
  - lib/suma/cli/validate_ascii.rb