metanorma-release 0.2.24 → 0.2.25
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/.rubocop_todo.yml +21 -319
- data/README.adoc +306 -91
- data/lib/metanorma/release/aggregation_pipeline.rb +65 -40
- data/lib/metanorma/release/asset_processor.rb +0 -2
- data/lib/metanorma/release/cache_store.rb +1 -0
- data/lib/metanorma/release/change_detector.rb +3 -2
- data/lib/metanorma/release/cli.rb +26 -2
- data/lib/metanorma/release/commands/aggregate.rb +0 -16
- data/lib/metanorma/release/commands/package.rb +9 -17
- data/lib/metanorma/release/commands/release_command.rb +19 -14
- data/lib/metanorma/release/config.rb +16 -7
- data/lib/metanorma/release/dependency_validation.rb +19 -0
- data/lib/metanorma/release/document_flattener.rb +173 -0
- data/lib/metanorma/release/index.rb +1 -1
- data/lib/metanorma/release/interfaces.rb +12 -0
- data/lib/metanorma/release/platform/github/manifest_reader.rb +3 -1
- data/lib/metanorma/release/platform/github/release_fetcher.rb +4 -10
- data/lib/metanorma/release/platform/github/topic_discoverer.rb +1 -1
- data/lib/metanorma/release/platform/github.rb +0 -4
- data/lib/metanorma/release/platform/local/fetcher.rb +5 -17
- data/lib/metanorma/release/platform/null/manifest_reader.rb +15 -0
- data/lib/metanorma/release/platform/null/publisher.rb +1 -1
- data/lib/metanorma/release/platform/null.rb +2 -0
- data/lib/metanorma/release/platform/static_discoverer.rb +19 -0
- data/lib/metanorma/release/platform.rb +1 -0
- data/lib/metanorma/release/platform_factory.rb +6 -21
- data/lib/metanorma/release/publication.rb +23 -161
- data/lib/metanorma/release/publication_serializer.rb +59 -0
- data/lib/metanorma/release/release_pipeline.rb +7 -15
- data/lib/metanorma/release/rxl_extractor.rb +106 -0
- data/lib/metanorma/release/site.rb +4 -164
- data/lib/metanorma/release/slug_strategy.rb +30 -15
- data/lib/metanorma/release/version.rb +1 -1
- data/lib/metanorma/release.rb +36 -19
- metadata +8 -2
|
@@ -13,7 +13,7 @@ module Metanorma
|
|
|
13
13
|
@index = index
|
|
14
14
|
@output_dir = output_dir
|
|
15
15
|
@data_dir = data_dir
|
|
16
|
-
@
|
|
16
|
+
@flattener = DocumentFlattener.new(display_categories: display_categories)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def write!
|
|
@@ -50,12 +50,13 @@ module Metanorma
|
|
|
50
50
|
index.publications.map do |pub|
|
|
51
51
|
enrich_publication(pub)
|
|
52
52
|
rescue StandardError => e
|
|
53
|
-
warn "
|
|
53
|
+
Metanorma::Release.logger.warn "Skip #{pub.identifier}: #{e.message}"
|
|
54
54
|
pub.to_h
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def enrich_publication(pub)
|
|
59
|
+
require "relaton/bib"
|
|
59
60
|
rxl_file = pub.files.find { |f| f.format == "rxl" }
|
|
60
61
|
return pub.to_h unless rxl_file
|
|
61
62
|
|
|
@@ -78,171 +79,10 @@ module Metanorma
|
|
|
78
79
|
|
|
79
80
|
def write_data_file(documents)
|
|
80
81
|
FileUtils.mkdir_p(@data_dir)
|
|
81
|
-
items = documents.compact.map { |doc|
|
|
82
|
+
items = documents.compact.map { |doc| @flattener.flatten(doc) }
|
|
82
83
|
File.write(File.join(@data_dir, "documents.json"),
|
|
83
84
|
JSON.pretty_generate({ "items" => items }))
|
|
84
85
|
end
|
|
85
|
-
|
|
86
|
-
def flatten_for_site(doc)
|
|
87
|
-
bib = doc["bibliographic"] || {}
|
|
88
|
-
doctype = extract_doctype(bib) || doc.fetch("doctype", "")
|
|
89
|
-
formats = doc["formats"] || []
|
|
90
|
-
base = {
|
|
91
|
-
"slug" => doc["id"],
|
|
92
|
-
"id" => resolve_doc_id(bib, doc),
|
|
93
|
-
"title" => doc["title"].to_s,
|
|
94
|
-
"abstract" => extract_abstract(bib),
|
|
95
|
-
"stage" => (doc["stage"] || "published").to_s.downcase,
|
|
96
|
-
"doctype" => doctype,
|
|
97
|
-
"edition" => doc["edition"],
|
|
98
|
-
"date" => extract_date(doc),
|
|
99
|
-
"channels" => doc["channels"] || [],
|
|
100
|
-
"formats" => formats,
|
|
101
|
-
"files" => doc["files"] || [],
|
|
102
|
-
"bibliographic" => bib,
|
|
103
|
-
}
|
|
104
|
-
add_format_flags(base, formats)
|
|
105
|
-
add_display_category(base, doctype)
|
|
106
|
-
add_contributors(base, bib)
|
|
107
|
-
base
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def add_format_flags(hash, formats)
|
|
111
|
-
hash["has_html"] = formats.include?("html")
|
|
112
|
-
hash["has_pdf"] = formats.include?("pdf")
|
|
113
|
-
hash["has_xml"] = formats.include?("xml")
|
|
114
|
-
hash["has_rxl"] = formats.include?("rxl")
|
|
115
|
-
|
|
116
|
-
files = hash["files"]
|
|
117
|
-
html_file = files.find { |f| f["format"] == "html" }
|
|
118
|
-
hash["html_path"] = html_file["path"] if html_file
|
|
119
|
-
pdf_file = files.find { |f| f["format"] == "pdf" }
|
|
120
|
-
hash["pdf_path"] = pdf_file["path"] if pdf_file
|
|
121
|
-
xml_file = files.find { |f| f["format"] == "xml" }
|
|
122
|
-
hash["xml_path"] = xml_file["path"] if xml_file
|
|
123
|
-
rxl_file = files.find { |f| f["format"] == "rxl" }
|
|
124
|
-
hash["rxl_path"] = rxl_file["path"] if rxl_file
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def add_display_category(hash, doctype)
|
|
128
|
-
cat = resolve_display_category(doctype)
|
|
129
|
-
hash["stage_css"] = hash["stage"].gsub(/\s+/, "-")
|
|
130
|
-
hash["doctype_class"] = "type-#{doctype.downcase}"
|
|
131
|
-
hash["display_category"] = cat&.fetch("name", nil)
|
|
132
|
-
hash["display_category_slug"] = cat&.fetch("slug", nil)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def resolve_doc_id(bib, doc)
|
|
136
|
-
extract_primary_id(bib) || doc["identifier"] || doc["id"]
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def extract_primary_id(bib)
|
|
140
|
-
ids = bib["docidentifier"]
|
|
141
|
-
return nil unless ids&.any?
|
|
142
|
-
|
|
143
|
-
primary = ids.find { |di| di["primary"] == true } || ids.first
|
|
144
|
-
primary["content"]
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
def extract_doctype(bib)
|
|
148
|
-
bib.dig("ext", "doctype", "content")
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def extract_abstract(bib)
|
|
152
|
-
abstracts = bib["abstract"]
|
|
153
|
-
return nil unless abstracts&.any?
|
|
154
|
-
|
|
155
|
-
abstracts.first["content"]
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def extract_date(doc)
|
|
159
|
-
bib_date = extract_bib_date(doc["bibliographic"])
|
|
160
|
-
return bib_date if bib_date
|
|
161
|
-
|
|
162
|
-
release_date = doc.dig("source", "releaseDate")
|
|
163
|
-
return nil unless release_date
|
|
164
|
-
|
|
165
|
-
release_date.to_s.split(/[T ]/).first
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def extract_bib_date(bib)
|
|
169
|
-
return nil unless bib
|
|
170
|
-
|
|
171
|
-
dates = bib["date"]
|
|
172
|
-
return nil if dates.nil? || dates.empty?
|
|
173
|
-
|
|
174
|
-
published = dates.find { |d| d["type"] == "published" }
|
|
175
|
-
entry = published || dates.first
|
|
176
|
-
at = entry["at"]
|
|
177
|
-
at ? at.to_s.split(/[T ]/).first : nil
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def resolve_display_category(doctype)
|
|
181
|
-
return nil if doctype.nil? || doctype.empty?
|
|
182
|
-
|
|
183
|
-
@display_categories.each do |cat|
|
|
184
|
-
doctypes = cat["doctypes"] || []
|
|
185
|
-
return { "name" => cat["name"], "slug" => cat["slug"] } if doctypes.include?(doctype)
|
|
186
|
-
end
|
|
187
|
-
nil
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
def add_contributors(hash, bib)
|
|
191
|
-
contribs = bib["contributor"] || []
|
|
192
|
-
persons, committees = partition_contributors(contribs)
|
|
193
|
-
hash["authors"] = persons
|
|
194
|
-
hash["committee"] = committees.first
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def partition_contributors(contribs)
|
|
198
|
-
persons = contribs.filter_map { |c| parse_person(c) }
|
|
199
|
-
committees = contribs.filter_map { |c| parse_committee(c) }
|
|
200
|
-
[persons, committees]
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
def parse_person(contrib)
|
|
204
|
-
return nil unless contrib["person"]
|
|
205
|
-
|
|
206
|
-
name = extract_person_name(contrib["person"])
|
|
207
|
-
return nil unless name
|
|
208
|
-
|
|
209
|
-
role = (contrib["role"] || []).first&.fetch("type", nil)
|
|
210
|
-
{ "name" => name, "role" => role }
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
def parse_committee(contrib)
|
|
214
|
-
return nil unless contrib["organization"]
|
|
215
|
-
|
|
216
|
-
extract_org_subdivision(contrib["organization"])
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
def extract_person_name(person)
|
|
220
|
-
n = person["name"] || {}
|
|
221
|
-
complete = n["completename"]
|
|
222
|
-
return complete["content"] if complete.is_a?(Hash) && complete["content"]
|
|
223
|
-
return complete if complete.is_a?(String)
|
|
224
|
-
|
|
225
|
-
surname = n["surname"]
|
|
226
|
-
given = n["given"]
|
|
227
|
-
given_str = given.is_a?(Hash) ? given["content"].to_s : given.to_s
|
|
228
|
-
parts = [given_str, surname].compact
|
|
229
|
-
parts.empty? ? nil : parts.join(" ")
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def extract_org_subdivision(org)
|
|
233
|
-
subs = org["subdivision"]
|
|
234
|
-
return nil unless subs&.any?
|
|
235
|
-
|
|
236
|
-
sd = subs.first
|
|
237
|
-
sd_name = sd["name"]
|
|
238
|
-
if sd_name.is_a?(Array)
|
|
239
|
-
sd_name.first&.dig("content")
|
|
240
|
-
elsif sd_name.is_a?(Hash)
|
|
241
|
-
sd_name["content"]
|
|
242
|
-
else
|
|
243
|
-
sd_name.to_s
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
86
|
end
|
|
247
87
|
end
|
|
248
88
|
end
|
|
@@ -11,6 +11,21 @@ module Metanorma
|
|
|
11
11
|
raise NotImplementedError,
|
|
12
12
|
"#{self.class} must implement #compute_asset_name"
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
def self.slug_from_identifier(identifier)
|
|
16
|
+
identifier.to_s.strip
|
|
17
|
+
.gsub(/\s+/, "-")
|
|
18
|
+
.gsub(/:+/, "-")
|
|
19
|
+
.downcase
|
|
20
|
+
.gsub(/--+/, "-")
|
|
21
|
+
.gsub(/[-.]+$/, "")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.publisher_from_identifier(identifier)
|
|
25
|
+
return nil if identifier.nil? || identifier.strip.empty?
|
|
26
|
+
|
|
27
|
+
identifier.strip.split(/[\s-]/).first&.downcase
|
|
28
|
+
end
|
|
14
29
|
end
|
|
15
30
|
|
|
16
31
|
class EditionSlug
|
|
@@ -18,18 +33,12 @@ module Metanorma
|
|
|
18
33
|
|
|
19
34
|
def compute_tag(publication)
|
|
20
35
|
tag = "#{publication.slug}/ed#{publication.edition}"
|
|
21
|
-
{ tag: tag, pre_release: draft?
|
|
36
|
+
{ tag: tag, pre_release: publication.draft? }
|
|
22
37
|
end
|
|
23
38
|
|
|
24
39
|
def compute_asset_name(publication)
|
|
25
40
|
"#{publication.slug}-ed#{publication.edition}.zip"
|
|
26
41
|
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def draft?(publication)
|
|
31
|
-
%w[20 30 40 50].include?(publication.stage.to_s)
|
|
32
|
-
end
|
|
33
42
|
end
|
|
34
43
|
|
|
35
44
|
class VersionSlug
|
|
@@ -37,18 +46,12 @@ module Metanorma
|
|
|
37
46
|
|
|
38
47
|
def compute_tag(publication)
|
|
39
48
|
tag = "#{publication.slug}/v#{publication.edition}"
|
|
40
|
-
{ tag: tag, pre_release: draft?
|
|
49
|
+
{ tag: tag, pre_release: publication.draft? }
|
|
41
50
|
end
|
|
42
51
|
|
|
43
52
|
def compute_asset_name(publication)
|
|
44
53
|
"#{publication.slug}-v#{publication.edition}.zip"
|
|
45
54
|
end
|
|
46
|
-
|
|
47
|
-
private
|
|
48
|
-
|
|
49
|
-
def draft?(publication)
|
|
50
|
-
%w[20 30 40 50].include?(publication.stage.to_s)
|
|
51
|
-
end
|
|
52
55
|
end
|
|
53
56
|
|
|
54
57
|
class InternetDraftSlug
|
|
@@ -129,6 +132,18 @@ module Metanorma
|
|
|
129
132
|
@strategies.fetch(publisher.to_s, @default)
|
|
130
133
|
end
|
|
131
134
|
|
|
135
|
+
def with_default(strategy)
|
|
136
|
+
registry = new
|
|
137
|
+
@strategies.each { |pub, s| registry.register(pub, s) }
|
|
138
|
+
registry.set_default(strategy)
|
|
139
|
+
registry
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def set_default(strategy)
|
|
143
|
+
@default = strategy
|
|
144
|
+
self
|
|
145
|
+
end
|
|
146
|
+
|
|
132
147
|
def self.from_config(config)
|
|
133
148
|
registry = new
|
|
134
149
|
config.slug_strategies.each do |publisher, strategy_name|
|
|
@@ -136,7 +151,7 @@ module Metanorma
|
|
|
136
151
|
registry.register(publisher, strategy) if strategy
|
|
137
152
|
end
|
|
138
153
|
default = build_strategy(config.slug_default_strategy) || EditionSlug.new
|
|
139
|
-
registry.
|
|
154
|
+
registry.set_default(default)
|
|
140
155
|
registry
|
|
141
156
|
end
|
|
142
157
|
|
data/lib/metanorma/release.rb
CHANGED
|
@@ -4,18 +4,32 @@ module Metanorma
|
|
|
4
4
|
module Release
|
|
5
5
|
require_relative "release/version"
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
autoload :Index, "metanorma/release/index"
|
|
12
|
-
autoload :Site, "metanorma/release/site"
|
|
13
|
-
autoload :Channel, "metanorma/release/channel"
|
|
14
|
-
autoload :Config, "metanorma/release/config"
|
|
15
|
-
autoload :DocumentEntry, "metanorma/release/config"
|
|
16
|
-
autoload :ChannelResolver, "metanorma/release/config"
|
|
17
|
-
autoload :ContentHash, "metanorma/release/content_hash"
|
|
7
|
+
require "logger"
|
|
8
|
+
|
|
9
|
+
class << self
|
|
10
|
+
attr_writer :logger
|
|
18
11
|
|
|
12
|
+
def logger
|
|
13
|
+
@logger ||= Logger.new($stderr, level: Logger::WARN)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Domain models
|
|
18
|
+
autoload :Publication, "metanorma/release/publication"
|
|
19
|
+
autoload :PublicationFile, "metanorma/release/publication"
|
|
20
|
+
autoload :PublicationSource, "metanorma/release/publication"
|
|
21
|
+
autoload :PublicationSerializer, "metanorma/release/publication_serializer"
|
|
22
|
+
autoload :RxlExtractor, "metanorma/release/rxl_extractor"
|
|
23
|
+
autoload :Index, "metanorma/release/index"
|
|
24
|
+
autoload :Site, "metanorma/release/site"
|
|
25
|
+
autoload :Channel, "metanorma/release/channel"
|
|
26
|
+
autoload :Config, "metanorma/release/config"
|
|
27
|
+
autoload :ConfigLoader, "metanorma/release/config"
|
|
28
|
+
autoload :DocumentEntry, "metanorma/release/config"
|
|
29
|
+
autoload :ChannelResolver, "metanorma/release/config"
|
|
30
|
+
autoload :ContentHash, "metanorma/release/content_hash"
|
|
31
|
+
autoload :DependencyValidation, "metanorma/release/dependency_validation"
|
|
32
|
+
autoload :DocumentFlattener, "metanorma/release/document_flattener"
|
|
19
33
|
# Strategies
|
|
20
34
|
autoload :SlugStrategy, "metanorma/release/slug_strategy"
|
|
21
35
|
autoload :EditionSlug, "metanorma/release/slug_strategy"
|
|
@@ -25,14 +39,17 @@ module Metanorma
|
|
|
25
39
|
autoload :DraftSuffixSlug, "metanorma/release/slug_strategy"
|
|
26
40
|
autoload :SlugRegistry, "metanorma/release/slug_strategy"
|
|
27
41
|
|
|
28
|
-
# Interfaces
|
|
29
|
-
autoload :
|
|
30
|
-
autoload :
|
|
31
|
-
autoload :
|
|
32
|
-
autoload :
|
|
33
|
-
autoload :
|
|
34
|
-
autoload :
|
|
35
|
-
autoload :
|
|
42
|
+
# Interfaces & shared types
|
|
43
|
+
autoload :Extractor, "metanorma/release/interfaces"
|
|
44
|
+
autoload :Release, "metanorma/release/interfaces"
|
|
45
|
+
autoload :Asset, "metanorma/release/interfaces"
|
|
46
|
+
autoload :Filter, "metanorma/release/interfaces"
|
|
47
|
+
autoload :ChangeDetector, "metanorma/release/interfaces"
|
|
48
|
+
autoload :Packager, "metanorma/release/interfaces"
|
|
49
|
+
autoload :Publisher, "metanorma/release/interfaces"
|
|
50
|
+
autoload :RepoDiscoverer, "metanorma/release/interfaces"
|
|
51
|
+
autoload :ReleaseFetcher, "metanorma/release/interfaces"
|
|
52
|
+
autoload :ManifestReader, "metanorma/release/interfaces"
|
|
36
53
|
|
|
37
54
|
# Pipeline components
|
|
38
55
|
autoload :RepoRef, "metanorma/release/repo_ref"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: metanorma-release
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.25
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: relaton-bib
|
|
@@ -104,6 +104,8 @@ files:
|
|
|
104
104
|
- lib/metanorma/release/config.rb
|
|
105
105
|
- lib/metanorma/release/content_hash.rb
|
|
106
106
|
- lib/metanorma/release/delta_state.rb
|
|
107
|
+
- lib/metanorma/release/dependency_validation.rb
|
|
108
|
+
- lib/metanorma/release/document_flattener.rb
|
|
107
109
|
- lib/metanorma/release/file_routing.rb
|
|
108
110
|
- lib/metanorma/release/index.rb
|
|
109
111
|
- lib/metanorma/release/interfaces.rb
|
|
@@ -118,11 +120,15 @@ files:
|
|
|
118
120
|
- lib/metanorma/release/platform/local/fetcher.rb
|
|
119
121
|
- lib/metanorma/release/platform/local/publisher.rb
|
|
120
122
|
- lib/metanorma/release/platform/null.rb
|
|
123
|
+
- lib/metanorma/release/platform/null/manifest_reader.rb
|
|
121
124
|
- lib/metanorma/release/platform/null/publisher.rb
|
|
125
|
+
- lib/metanorma/release/platform/static_discoverer.rb
|
|
122
126
|
- lib/metanorma/release/platform_factory.rb
|
|
123
127
|
- lib/metanorma/release/publication.rb
|
|
128
|
+
- lib/metanorma/release/publication_serializer.rb
|
|
124
129
|
- lib/metanorma/release/release_pipeline.rb
|
|
125
130
|
- lib/metanorma/release/repo_ref.rb
|
|
131
|
+
- lib/metanorma/release/rxl_extractor.rb
|
|
126
132
|
- lib/metanorma/release/site.rb
|
|
127
133
|
- lib/metanorma/release/slug_strategy.rb
|
|
128
134
|
- lib/metanorma/release/version.rb
|