suma 0.4.0 → 0.5.1
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 -3
- data/.github/workflows/release.yml +1 -5
- data/.rubocop.yml +16 -12
- data/.rubocop_todo.yml +149 -178
- data/Gemfile +5 -1
- data/lib/suma/cli/build.rb +5 -0
- data/lib/suma/cli/core.rb +32 -4
- data/lib/suma/eengine_converter.rb +9 -8
- data/lib/suma/link_validator/step.rb +149 -0
- data/lib/suma/link_validator.rb +20 -97
- data/lib/suma/note_processor.rb +270 -0
- data/lib/suma/processor.rb +19 -3
- data/lib/suma/schema_comparer.rb +1 -1
- data/lib/suma/staged_collection_builder.rb +188 -0
- data/lib/suma/term_extractor.rb +9 -195
- data/lib/suma/version.rb +1 -1
- data/lib/suma.rb +2 -0
- metadata +6 -6
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "metanorma"
|
|
4
|
+
require "yaml"
|
|
5
|
+
require "fileutils"
|
|
6
|
+
|
|
7
|
+
module Suma
|
|
8
|
+
# Memory-bounded, resumable staged collection build (metanorma/suma#94).
|
|
9
|
+
#
|
|
10
|
+
# A normal collection build renders every member document in one OS process, so
|
|
11
|
+
# peak memory accumulates across the whole collection and a large collection
|
|
12
|
+
# (e.g. the STEP SRL) OOMs. This builder instead:
|
|
13
|
+
#
|
|
14
|
+
# 1. compiles each member in its OWN fresh OS process, preserving that
|
|
15
|
+
# member's unresolved cross-document references as stubs and writing the
|
|
16
|
+
# stub-bearing Semantic XML + anchors to a durable content-addressed store
|
|
17
|
+
# (the metanorma engine's +preserve_unresolved:+ / +artifact_store_dir:+
|
|
18
|
+
# render options, metanorma/metanorma#576);
|
|
19
|
+
# 2. runs those per-member processes SEQUENTIALLY (never in parallel --
|
|
20
|
+
# parallelism reintroduces the cross-linking / sectionsplit races that are
|
|
21
|
+
# deliberately avoided); each process exits and the OS reclaims its memory
|
|
22
|
+
# before the next, so peak memory is bounded by a single member; then
|
|
23
|
+
# 3. REINFLATES: a final pass assembles a manifest of the stored stubs and
|
|
24
|
+
# resolves them into real cross-document links (+reinflate:+), producing
|
|
25
|
+
# the same output an all-present build would.
|
|
26
|
+
#
|
|
27
|
+
# The empirical case (metanorma/metanorma#576): on the real SRL a single-process
|
|
28
|
+
# build peaks ~4.1 GB and OOMs; each member compiled in isolation peaks ~1 GB,
|
|
29
|
+
# so process isolation is a ~4x peak reduction that converts the OOM into a
|
|
30
|
+
# bounded footprint.
|
|
31
|
+
#
|
|
32
|
+
# This is opt-in; +Suma::Processor+ uses the normal single-process build unless
|
|
33
|
+
# staging is requested.
|
|
34
|
+
class StagedCollectionBuilder
|
|
35
|
+
STORE_DIRNAME = ".metanorma-collection-cache"
|
|
36
|
+
|
|
37
|
+
# +collection_config_path+ is the emitted collection manifest (the same
|
|
38
|
+
# +collection-output.yaml+ the normal build renders). Member filerefs are
|
|
39
|
+
# relative to its directory, so all per-member manifests are written there.
|
|
40
|
+
def initialize(collection_config_path:, output_directory:, coverpage: nil,
|
|
41
|
+
store_dir: nil, formats: %i[xml html])
|
|
42
|
+
@config_path = collection_config_path
|
|
43
|
+
@config_dir = File.dirname(File.expand_path(collection_config_path))
|
|
44
|
+
@output_directory = output_directory
|
|
45
|
+
@coverpage = coverpage
|
|
46
|
+
@store_dir = store_dir || File.join(output_directory, STORE_DIRNAME)
|
|
47
|
+
@formats = formats
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def build
|
|
51
|
+
FileUtils.mkdir_p(@output_directory)
|
|
52
|
+
FileUtils.mkdir_p(@store_dir)
|
|
53
|
+
members = collection_members
|
|
54
|
+
Utils.log "[staged] #{members.size} members; one process per member, " \
|
|
55
|
+
"sequential; store: #{@store_dir}"
|
|
56
|
+
members.each_with_index { |member, i| stage_member(member, i) }
|
|
57
|
+
reinflate(members)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def manifest
|
|
63
|
+
@manifest ||= YAML.load_file(@config_path)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Every document member of the manifest tree, in order: any node carrying a
|
|
67
|
+
# file reference (+fileref+ or legacy +file+) that is not an attachment.
|
|
68
|
+
def collection_members
|
|
69
|
+
members = []
|
|
70
|
+
walk_members(manifest["manifest"]) { |member| members << member }
|
|
71
|
+
members
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def walk_members(node, &block)
|
|
75
|
+
case node
|
|
76
|
+
when Array then node.each { |child| walk_members(child, &block) }
|
|
77
|
+
when Hash then walk_member_hash(node, &block)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def walk_member_hash(node, &block)
|
|
82
|
+
ref = node["fileref"] || node["file"]
|
|
83
|
+
ref && !truthy?(node["attachment"]) and
|
|
84
|
+
yield({ "fileref" => ref, "identifier" => node["identifier"],
|
|
85
|
+
"sectionsplit" => node["sectionsplit"] }.compact)
|
|
86
|
+
node.each_value { |value| walk_members(value, &block) }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Stage one member in its own process: a single-member manifest rendered with
|
|
90
|
+
# preserve + store. Written beside the collection config so relative filerefs
|
|
91
|
+
# resolve; removed afterwards.
|
|
92
|
+
def stage_member(member, idx)
|
|
93
|
+
one_path = File.join(@config_dir, "._suma_staged_#{idx}.yml")
|
|
94
|
+
File.write(one_path, single_member_manifest(member).to_yaml)
|
|
95
|
+
out = File.join(@output_directory, "._staged_out_#{idx}")
|
|
96
|
+
run_render(
|
|
97
|
+
manifest_path: one_path,
|
|
98
|
+
opts: { format: [:xml], output_folder: out,
|
|
99
|
+
preserve_unresolved: true, artifact_store_dir: @store_dir,
|
|
100
|
+
compile: { install_fonts: false } },
|
|
101
|
+
)
|
|
102
|
+
ensure
|
|
103
|
+
FileUtils.rm_f(one_path)
|
|
104
|
+
FileUtils.rm_rf(File.join(@output_directory, "._staged_out_#{idx}"))
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Assemble a manifest of the stored stubs and reinflate them into the site.
|
|
108
|
+
def reinflate(members)
|
|
109
|
+
reinf_dir = File.join(@output_directory, "_staged_reinflate")
|
|
110
|
+
FileUtils.mkdir_p(reinf_dir)
|
|
111
|
+
docrefs = stored_docrefs(members, reinf_dir)
|
|
112
|
+
reinf_path = File.join(reinf_dir, "reinflate.yml")
|
|
113
|
+
File.write(reinf_path,
|
|
114
|
+
base_manifest.merge("manifest" => collection_manifest(docrefs)).to_yaml)
|
|
115
|
+
Utils.log "[staged] reinflating #{docrefs.size} stored members -> " \
|
|
116
|
+
"#{@output_directory}"
|
|
117
|
+
run_render(
|
|
118
|
+
manifest_path: reinf_path,
|
|
119
|
+
opts: { format: @formats, output_folder: @output_directory,
|
|
120
|
+
reinflate: true, coverpage: @coverpage,
|
|
121
|
+
compile: { install_fonts: false } }.compact,
|
|
122
|
+
)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Copy each member's stored stub into +dir+ and return docref entries pointing
|
|
126
|
+
# at the copies, keyed by real docid (as the store keys them).
|
|
127
|
+
def stored_docrefs(members, dir)
|
|
128
|
+
members.map.with_index do |member, i|
|
|
129
|
+
stored = stored_semantic(member["identifier"]) or
|
|
130
|
+
raise "[staged] no stored artefact for #{member['identifier'].inspect}"
|
|
131
|
+
name = "member_#{i}.xml"
|
|
132
|
+
FileUtils.cp(stored, File.join(dir, name))
|
|
133
|
+
dr = { "fileref" => name, "identifier" => member["identifier"] }
|
|
134
|
+
dr["sectionsplit"] = true if truthy?(member["sectionsplit"])
|
|
135
|
+
dr
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# A minimal single-member manifest reusing the collection's directives and
|
|
140
|
+
# bibdata, so the isolated render carries the right collection identity.
|
|
141
|
+
def single_member_manifest(member)
|
|
142
|
+
base_manifest.merge("manifest" => collection_manifest([member]))
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def collection_manifest(docrefs)
|
|
146
|
+
{ "level" => "collection", "title" => "Collection",
|
|
147
|
+
"manifest" => [{ "level" => "subcollection", "title" => "Members",
|
|
148
|
+
"docref" => docrefs }] }
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def base_manifest
|
|
152
|
+
{ "directives" => manifest["directives"] || ["documents-inline"],
|
|
153
|
+
"bibdata" => manifest["bibdata"] }.compact
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def stored_semantic(identifier)
|
|
157
|
+
Dir[File.join(@store_dir, "#{slug(identifier)}.*.semantic.xml")]
|
|
158
|
+
.max_by { |f| File.mtime(f) }
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Mirrors the store's filename slug (metanorma ArtifactStore#slug).
|
|
162
|
+
def slug(identifier)
|
|
163
|
+
identifier.to_s.gsub(/[^A-Za-z0-9._-]+/, "-")
|
|
164
|
+
.gsub(/-{2,}/, "-").gsub(/\A-|-\z/, "")
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Render a manifest in a FRESH child process so its memory is reclaimed on
|
|
168
|
+
# exit. Under +bundle exec+, the child inherits the bundle. Raises on failure.
|
|
169
|
+
def run_render(manifest_path:, opts:)
|
|
170
|
+
script = <<~RUBY
|
|
171
|
+
require "metanorma"
|
|
172
|
+
opts = Marshal.load(STDIN.read)
|
|
173
|
+
Metanorma::Collection.parse(#{manifest_path.inspect}).render(opts)
|
|
174
|
+
RUBY
|
|
175
|
+
IO.popen([RbConfig.ruby, "-e", script], "wb") do |io|
|
|
176
|
+
io.write(Marshal.dump(opts))
|
|
177
|
+
io.close_write
|
|
178
|
+
end
|
|
179
|
+
return if $?.success?
|
|
180
|
+
|
|
181
|
+
raise "[staged] render subprocess failed for #{manifest_path}"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def truthy?(val)
|
|
185
|
+
[true, "true"].include?(val)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
data/lib/suma/term_extractor.rb
CHANGED
|
@@ -6,15 +6,6 @@ require "glossarist"
|
|
|
6
6
|
|
|
7
7
|
module Suma
|
|
8
8
|
class TermExtractor
|
|
9
|
-
REDUNDANT_NOTE_REGEX =
|
|
10
|
-
%r{
|
|
11
|
-
^An? # Starts with "A" or "An"
|
|
12
|
-
\s.*?\sis\sa\stype\sof # Text followed by "is a type of"
|
|
13
|
-
(\sa|\san)? # Optional " a" or " an"
|
|
14
|
-
\s\{\{[^\}]*\}\} # Text in double curly braces
|
|
15
|
-
\s*?\.?$ # Optional whitespace and period at the end
|
|
16
|
-
}x
|
|
17
|
-
|
|
18
9
|
def initialize(schema_manifest_file, output_path, urn:,
|
|
19
10
|
language_code: "eng")
|
|
20
11
|
@schema_manifest_file = File.expand_path(schema_manifest_file)
|
|
@@ -140,7 +131,11 @@ module Suma
|
|
|
140
131
|
data.domain = schema_domain
|
|
141
132
|
data.sources = [source_ref] if source_ref
|
|
142
133
|
|
|
143
|
-
notes =
|
|
134
|
+
notes = NoteProcessor.call(
|
|
135
|
+
entity.remarks,
|
|
136
|
+
definitions: data.definition,
|
|
137
|
+
xref_to_mention: method(:xref_to_mention),
|
|
138
|
+
)
|
|
144
139
|
data.notes = notes if notes && !notes.empty?
|
|
145
140
|
data.examples = []
|
|
146
141
|
end
|
|
@@ -166,6 +161,10 @@ module Suma
|
|
|
166
161
|
"{{#{urn},#{display}}}"
|
|
167
162
|
end
|
|
168
163
|
|
|
164
|
+
def xref_to_mention(full_ref, display)
|
|
165
|
+
urn_mention(express_entity_urn(full_ref), display)
|
|
166
|
+
end
|
|
167
|
+
|
|
169
168
|
def get_section_ref(schema)
|
|
170
169
|
return nil unless @urn
|
|
171
170
|
|
|
@@ -219,183 +218,6 @@ module Suma
|
|
|
219
218
|
[Glossarist::V3::DetailedDefinition.new(content: definition)]
|
|
220
219
|
end
|
|
221
220
|
|
|
222
|
-
def get_entity_notes(entity, schema_domain, definitions)
|
|
223
|
-
notes = []
|
|
224
|
-
|
|
225
|
-
if entity.remarks && !entity.remarks.empty?
|
|
226
|
-
trimmed_def = trim_definition(entity.remarks)
|
|
227
|
-
if trimmed_def && !trimmed_def.empty?
|
|
228
|
-
notes << Glossarist::V3::DetailedDefinition.new(
|
|
229
|
-
content: convert_express_xref(trimmed_def, schema_domain),
|
|
230
|
-
)
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
notes = only_keep_first_sentence(notes)
|
|
235
|
-
notes = remove_see_content(notes)
|
|
236
|
-
notes = remove_redundant_note(notes)
|
|
237
|
-
notes = remove_invalid_references(notes)
|
|
238
|
-
compare_with_definitions(notes, definitions)
|
|
239
|
-
end
|
|
240
|
-
|
|
241
|
-
def only_keep_first_sentence(notes)
|
|
242
|
-
notes.each do |note|
|
|
243
|
-
if note&.content && should_preserve_complete_structure?(note.content)
|
|
244
|
-
next
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
if note&.content
|
|
248
|
-
new_content = note.content
|
|
249
|
-
.split(".\n").first.strip
|
|
250
|
-
.split(". ").first.strip
|
|
251
|
-
note.content = new_content.end_with?(".") ? new_content : "#{new_content}."
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
def should_preserve_complete_structure?(content)
|
|
257
|
-
return false if content.nil? || content.empty?
|
|
258
|
-
|
|
259
|
-
lines = content.split("\n")
|
|
260
|
-
first_paragraph = lines.first&.strip
|
|
261
|
-
|
|
262
|
-
if first_paragraph&.end_with?(":") && lines.length > 1
|
|
263
|
-
if first_paragraph.count(".").positive?
|
|
264
|
-
return false
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
remaining_content = lines[1..].join("\n")
|
|
268
|
-
return starts_with_list?(remaining_content.strip)
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
false
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
def compare_with_definitions(notes, definitions)
|
|
275
|
-
if notes&.first&.content == definitions&.first&.content
|
|
276
|
-
return []
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
notes
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
def remove_invalid_references(notes)
|
|
283
|
-
notes.reject do |note|
|
|
284
|
-
note.content.include?("image::") ||
|
|
285
|
-
note.content.match?(/<<(.*?){1,999}>>/)
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
def remove_redundant_note(notes)
|
|
290
|
-
notes.reject do |note|
|
|
291
|
-
note.content.match?(REDUNDANT_NOTE_REGEX) &&
|
|
292
|
-
!note.content.include?("\n")
|
|
293
|
-
end
|
|
294
|
-
end
|
|
295
|
-
|
|
296
|
-
def remove_see_content(notes)
|
|
297
|
-
notes.each do |note|
|
|
298
|
-
note.content = note.content.gsub(/\s+\(see(.*?){1,999}\)/, "")
|
|
299
|
-
end
|
|
300
|
-
end
|
|
301
|
-
|
|
302
|
-
def starts_with_list?(content)
|
|
303
|
-
return false if content.nil? || content.empty?
|
|
304
|
-
|
|
305
|
-
content.match?(/^\s*[*\-+]\s+/) || content.match?(/^\s*\d+\.\s+/)
|
|
306
|
-
end
|
|
307
|
-
|
|
308
|
-
def trim_definition(definition)
|
|
309
|
-
return nil if definition.nil? || definition.empty?
|
|
310
|
-
|
|
311
|
-
definition_str = definition.is_a?(Array) ? definition.join("\n\n") : definition.to_s
|
|
312
|
-
|
|
313
|
-
return nil if definition_str.empty?
|
|
314
|
-
|
|
315
|
-
paragraphs = definition_str.split("\n\n")
|
|
316
|
-
first_paragraph = paragraphs.first
|
|
317
|
-
|
|
318
|
-
combined = if paragraphs.length == 1
|
|
319
|
-
apply_first_sentence_logic(first_paragraph)
|
|
320
|
-
elsif first_paragraph.end_with?(":") && paragraphs.length > 1 && starts_with_list?(paragraphs[1])
|
|
321
|
-
complete_list = extract_complete_list(paragraphs, 1)
|
|
322
|
-
"#{first_paragraph}\n\n#{complete_list}"
|
|
323
|
-
else
|
|
324
|
-
apply_first_sentence_logic(first_paragraph)
|
|
325
|
-
end
|
|
326
|
-
|
|
327
|
-
combined = "#{combined}\n"
|
|
328
|
-
combined.gsub!(/\n\/\/.*?\n/, "\n")
|
|
329
|
-
combined.strip!
|
|
330
|
-
|
|
331
|
-
express_reference_to_mention(combined)
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
def apply_first_sentence_logic(paragraph)
|
|
335
|
-
new_content = paragraph
|
|
336
|
-
.split(".\n").first.strip
|
|
337
|
-
.split(". ").first.strip
|
|
338
|
-
|
|
339
|
-
new_content.end_with?(".") ? new_content : "#{new_content}."
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
def extract_complete_list(paragraphs, start_index)
|
|
343
|
-
return paragraphs[start_index] if start_index >= paragraphs.length
|
|
344
|
-
|
|
345
|
-
combined = paragraphs[start_index].dup
|
|
346
|
-
current_index = start_index + 1
|
|
347
|
-
in_continuation_block = combined.include?("--") && !combined.match?(/--.*--/m)
|
|
348
|
-
|
|
349
|
-
while current_index < paragraphs.length
|
|
350
|
-
next_para = paragraphs[current_index]
|
|
351
|
-
|
|
352
|
-
if next_para.match?(/^--\s*$/) || next_para.end_with?("--")
|
|
353
|
-
in_continuation_block = !in_continuation_block
|
|
354
|
-
combined += "\n\n#{next_para}"
|
|
355
|
-
current_index += 1
|
|
356
|
-
next
|
|
357
|
-
end
|
|
358
|
-
|
|
359
|
-
if in_continuation_block
|
|
360
|
-
combined += "\n\n#{next_para}"
|
|
361
|
-
current_index += 1
|
|
362
|
-
next
|
|
363
|
-
end
|
|
364
|
-
|
|
365
|
-
if starts_with_list?(next_para) || is_list_continuation?(next_para)
|
|
366
|
-
combined += "\n\n#{next_para}"
|
|
367
|
-
current_index += 1
|
|
368
|
-
in_continuation_block = true if next_para.include?("--") && !next_para.match?(/--.*--/m)
|
|
369
|
-
else
|
|
370
|
-
break
|
|
371
|
-
end
|
|
372
|
-
end
|
|
373
|
-
|
|
374
|
-
combined
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
def is_list_continuation?(content)
|
|
378
|
-
return false if content.nil? || content.empty?
|
|
379
|
-
|
|
380
|
-
content.match?(/^\+\s*$/) ||
|
|
381
|
-
content.match?(/^--\s*$/) ||
|
|
382
|
-
content.match?(/^\s{2,}/) ||
|
|
383
|
-
content.start_with?("which", "where", "that")
|
|
384
|
-
end
|
|
385
|
-
|
|
386
|
-
def express_reference_to_mention(description)
|
|
387
|
-
description
|
|
388
|
-
.gsub(/<<express:([\w.]+)>>/) do |_match|
|
|
389
|
-
full_ref = Regexp.last_match[1]
|
|
390
|
-
entity_id = full_ref.split(".").last
|
|
391
|
-
urn_mention(express_entity_urn(full_ref), entity_id)
|
|
392
|
-
end.gsub(/<<express:([\w.]+),([\w. ][\w. ]*)>>/) do |_match|
|
|
393
|
-
full_ref = Regexp.last_match[1]
|
|
394
|
-
display = Regexp.last_match(2)
|
|
395
|
-
urn_mention(express_entity_urn(full_ref), display)
|
|
396
|
-
end
|
|
397
|
-
end
|
|
398
|
-
|
|
399
221
|
def entity_name_to_text(entity_id)
|
|
400
222
|
entity_id.downcase.gsub("_", " ")
|
|
401
223
|
end
|
|
@@ -425,13 +247,5 @@ module Suma
|
|
|
425
247
|
"#{entity_name_to_text(entity.id)} #{entity_ref}"
|
|
426
248
|
end
|
|
427
249
|
end
|
|
428
|
-
|
|
429
|
-
def convert_express_xref(content, _schema_domain)
|
|
430
|
-
content.gsub(/<<express:([\w.]+),([\w. ][\w. ]*)>>/) do
|
|
431
|
-
full_ref = Regexp.last_match(1)
|
|
432
|
-
display = Regexp.last_match(2)
|
|
433
|
-
urn_mention(express_entity_urn(full_ref), display)
|
|
434
|
-
end
|
|
435
|
-
end
|
|
436
250
|
end
|
|
437
251
|
end
|
data/lib/suma/version.rb
CHANGED
data/lib/suma.rb
CHANGED
|
@@ -16,6 +16,7 @@ module Suma
|
|
|
16
16
|
autoload :LinkValidation, "suma/link_validation"
|
|
17
17
|
autoload :LinkValidator, "suma/link_validator"
|
|
18
18
|
autoload :ManifestTraverser, "suma/manifest_traverser"
|
|
19
|
+
autoload :NoteProcessor, "suma/note_processor"
|
|
19
20
|
autoload :RegisterManifestGenerator, "suma/register_manifest_generator"
|
|
20
21
|
autoload :SchemaCategory, "suma/schema_category"
|
|
21
22
|
autoload :SchemaCollection, "suma/schema_collection"
|
|
@@ -28,6 +29,7 @@ module Suma
|
|
|
28
29
|
autoload :SchemaNaming, "suma/schema_naming"
|
|
29
30
|
autoload :SchemaTemplate, "suma/schema_template"
|
|
30
31
|
autoload :SiteConfig, "suma/site_config"
|
|
32
|
+
autoload :StagedCollectionBuilder, "suma/staged_collection_builder"
|
|
31
33
|
autoload :SvgQuality, "suma/svg_quality"
|
|
32
34
|
autoload :TermClassification, "suma/term_classification"
|
|
33
35
|
autoload :TermExtractor, "suma/term_extractor"
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: suma
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: expressir
|
|
@@ -214,7 +213,9 @@ files:
|
|
|
214
213
|
- lib/suma/jsdai/figure_xml.rb
|
|
215
214
|
- lib/suma/link_validation.rb
|
|
216
215
|
- lib/suma/link_validator.rb
|
|
216
|
+
- lib/suma/link_validator/step.rb
|
|
217
217
|
- lib/suma/manifest_traverser.rb
|
|
218
|
+
- lib/suma/note_processor.rb
|
|
218
219
|
- lib/suma/processor.rb
|
|
219
220
|
- lib/suma/register_manifest_generator.rb
|
|
220
221
|
- lib/suma/schema_category.rb
|
|
@@ -230,6 +231,7 @@ files:
|
|
|
230
231
|
- lib/suma/schema_template/document.rb
|
|
231
232
|
- lib/suma/schema_template/plain.rb
|
|
232
233
|
- lib/suma/site_config.rb
|
|
234
|
+
- lib/suma/staged_collection_builder.rb
|
|
233
235
|
- lib/suma/svg_quality.rb
|
|
234
236
|
- lib/suma/svg_quality/batch_report.rb
|
|
235
237
|
- lib/suma/svg_quality/formatters.rb
|
|
@@ -251,7 +253,6 @@ licenses:
|
|
|
251
253
|
- BSD-2-Clause
|
|
252
254
|
metadata:
|
|
253
255
|
rubygems_mfa_required: 'true'
|
|
254
|
-
post_install_message:
|
|
255
256
|
rdoc_options: []
|
|
256
257
|
require_paths:
|
|
257
258
|
- lib
|
|
@@ -266,8 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
266
267
|
- !ruby/object:Gem::Version
|
|
267
268
|
version: '0'
|
|
268
269
|
requirements: []
|
|
269
|
-
rubygems_version:
|
|
270
|
-
signing_key:
|
|
270
|
+
rubygems_version: 4.0.10
|
|
271
271
|
specification_version: 4
|
|
272
272
|
summary: Utility for SUMA (STEP Unified Model-Based Standards Architecture)
|
|
273
273
|
test_files: []
|