stepmod-utils 0.6.10.pre.alpha.1 → 0.6.10
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.yml +1 -1
- data/README.adoc +67 -0
- data/exe/stepmod-convert-bibliography +97 -0
- data/lib/stepmod/utils/bibliography_converter.rb +294 -0
- data/lib/stepmod/utils/cleaner.rb +23 -3
- data/lib/stepmod/utils/converters/a.rb +14 -0
- data/lib/stepmod/utils/converters/em_express_description.rb +29 -0
- data/lib/stepmod/utils/converters/figure.rb +3 -2
- data/lib/stepmod/utils/converters/strong.rb +29 -7
- data/lib/stepmod/utils/express_bibdata.rb +3 -1
- data/lib/stepmod/utils/stepmod_file_annotator.rb +15 -13
- data/lib/stepmod/utils/terms_extractor.rb +2 -2
- data/lib/stepmod/utils/version.rb +1 -1
- data/stepmod-utils.gemspec +3 -2
- metadata +26 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9af636493e609c32af652ba4c7ba9c27bcf544b2b050f166d046d320cc951c3e
|
|
4
|
+
data.tar.gz: 721483a250021b902ccb6f9c13848ac9b2eb9679ca419c3a4c041badffc10533
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 572cb2422c959eb5dee160ecac7e35d32c3533ab8368aa60a9051a2a834c6a41297809539154caa63e08884b0cca17e7c4bb19c7ae28be5843d938e12ad02910
|
|
7
|
+
data.tar.gz: 87ca83a2d9413b9de293bc2857d749ad3ef437b61cc7aba90e2f1ec0760d2053746684ff1aa6393f5afb3c2c2b33000aa387187b523b81b671016e819b625050
|
data/.rubocop.yml
CHANGED
data/README.adoc
CHANGED
|
@@ -30,6 +30,10 @@ Or include it in your gemspec.
|
|
|
30
30
|
This command uses Expressir to validate all EXPRESS schemas listed in the
|
|
31
31
|
`{stepmod}/repository_index.xml` file.
|
|
32
32
|
|
|
33
|
+
Validation parses each file separately so that a broken schema is reported
|
|
34
|
+
without preventing validation of the remaining files. It does not build the
|
|
35
|
+
shared repository used for concept extraction.
|
|
36
|
+
|
|
33
37
|
There is a `SHOULD_REWRITE` constant that can be switched in the code which
|
|
34
38
|
allows overwriting of the EXPRESS schemas into a pretty-printed format.
|
|
35
39
|
|
|
@@ -68,6 +72,10 @@ SCHEMA: data/resources/geometric_model_schema/geometric_model_schema.exp
|
|
|
68
72
|
This command takes the STEPmod directory and parses its XML to synthesize
|
|
69
73
|
with the target EXPRESS schemas to migrate into Annotated EXPRESS schemas.
|
|
70
74
|
|
|
75
|
+
Annotation parses each input file to determine its schema name before combining
|
|
76
|
+
it with the XML descriptions. It does not resolve references across schemas;
|
|
77
|
+
repository-wide parsing happens when extracting concepts from the annotated files.
|
|
78
|
+
|
|
71
79
|
Given the following schemas:
|
|
72
80
|
|
|
73
81
|
* Simple EXPRESS schema: `{stepmod-root-dir}/data/resources/action_schema/action_schema.exp`
|
|
@@ -119,6 +127,15 @@ $ bundle exec stepmod-annotate-all --stepmod-dir iso-10303-stepmod-wg12 --output
|
|
|
119
127
|
|
|
120
128
|
=== ISO 10303-2 concepts extraction
|
|
121
129
|
|
|
130
|
+
Concept extraction passes the complete selected set of annotated EXPRESS files to
|
|
131
|
+
`Expressir::Express::Parser.from_files` once, producing a shared repository for
|
|
132
|
+
cross-schema references as requested in
|
|
133
|
+
https://github.com/metanorma/stepmod-utils/issues/136[issue #136]. The set contains
|
|
134
|
+
existing ARM and MIM files for published, non-withdrawn modules and existing
|
|
135
|
+
schemas for published, non-withdrawn resources listed in `repository_index.xml`.
|
|
136
|
+
ISO 13584 schemas are excluded. BOMs and application protocols do not contribute
|
|
137
|
+
Clause 3 terms and are excluded from concept extraction.
|
|
138
|
+
|
|
122
139
|
[source,sh]
|
|
123
140
|
----
|
|
124
141
|
$ bundle exec stepmod-extract-concepts \
|
|
@@ -256,6 +273,56 @@ End!
|
|
|
256
273
|
[stepmod-utils] ******************************
|
|
257
274
|
----
|
|
258
275
|
|
|
276
|
+
=== Converting the STEPmod bibliography to a Relaton collection
|
|
277
|
+
|
|
278
|
+
STEPmod keeps the shared references for `normref.inc` and `bibitem.inc` in
|
|
279
|
+
`data/basic/normrefs.xml` and `data/basic/bibliography.xml`. This command
|
|
280
|
+
converts both lists into one Relaton collection, so that Metanorma can cite any
|
|
281
|
+
entry by its id.
|
|
282
|
+
|
|
283
|
+
[source,sh]
|
|
284
|
+
----
|
|
285
|
+
# from a STEPmod checkout
|
|
286
|
+
$ stepmod-convert-bibliography -s {stepmod-directory} -o stepmod-bibliography.xml
|
|
287
|
+
|
|
288
|
+
# or from the two files directly (either one can be left out)
|
|
289
|
+
$ stepmod-convert-bibliography --normrefs normrefs.xml \
|
|
290
|
+
--bibliography bibliography.xml -o stepmod-bibliography.xml
|
|
291
|
+
----
|
|
292
|
+
|
|
293
|
+
Without `-o`, the collection is written to standard output. `-t` sets the
|
|
294
|
+
collection title.
|
|
295
|
+
|
|
296
|
+
The output is a `<relaton-collection>` with one `<relation type="partOf">` per
|
|
297
|
+
entry, each holding a Relaton `<bibitem>`:
|
|
298
|
+
|
|
299
|
+
* The item id is the STEPmod id with the prefix `normref_` or `bibitem_` (for
|
|
300
|
+
example `bibitem_ref8824-1`), the anchor form that the migrated ISO 10303
|
|
301
|
+
documents use. The raw STEPmod id is kept as a `docidentifier` of type
|
|
302
|
+
`STEPmod-id`.
|
|
303
|
+
* The primary `docidentifier` is `orgname` + `stdnumber` for a normref (for
|
|
304
|
+
example `ISO 31-0`), the `stdnumber` for a bibliography entry, and
|
|
305
|
+
`report-type` + `number` for a technical report.
|
|
306
|
+
* `bibitem` and `normref` become `standard`, `bibitem.techreport` becomes
|
|
307
|
+
`techreport`, and `bibitem.book` becomes `book`.
|
|
308
|
+
* `<term>` children of a normref are not bibliographic data and are skipped.
|
|
309
|
+
* A duplicate id in one list is skipped with a warning. An unknown named
|
|
310
|
+
entity is kept as text with a warning.
|
|
311
|
+
|
|
312
|
+
From Ruby:
|
|
313
|
+
|
|
314
|
+
[source,ruby]
|
|
315
|
+
----
|
|
316
|
+
require "stepmod/utils/bibliography_converter"
|
|
317
|
+
|
|
318
|
+
converter = Stepmod::Utils::BibliographyConverter.new(
|
|
319
|
+
normrefs: "data/basic/normrefs.xml",
|
|
320
|
+
bibliography: "data/basic/bibliography.xml",
|
|
321
|
+
)
|
|
322
|
+
converter.items # => Array<Relaton::Bib::ItemData>
|
|
323
|
+
converter.to_xml # => relaton-collection XML
|
|
324
|
+
----
|
|
325
|
+
|
|
259
326
|
== Conversion of STEPmod descriptions.xml into adoc
|
|
260
327
|
|
|
261
328
|
[source,sh]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# resolve bin path, ignoring symlinks
|
|
4
|
+
require "pathname"
|
|
5
|
+
bin_file = Pathname.new(__FILE__).realpath
|
|
6
|
+
|
|
7
|
+
# add self to libpath
|
|
8
|
+
$:.unshift File.expand_path("../../lib", bin_file)
|
|
9
|
+
|
|
10
|
+
require "bundler/setup"
|
|
11
|
+
require "optparse"
|
|
12
|
+
require "stepmod/utils/bibliography_converter"
|
|
13
|
+
|
|
14
|
+
def log(message)
|
|
15
|
+
warn "[stepmod-utils] #{message}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
options = {}
|
|
19
|
+
parser = OptionParser.new do |opts|
|
|
20
|
+
opts.banner = "Usage: #{$0} [options]\n\n" \
|
|
21
|
+
"Convert STEPmod normrefs.xml and bibliography.xml into " \
|
|
22
|
+
"one Relaton collection."
|
|
23
|
+
|
|
24
|
+
opts.on("-s", "--stepmod DIR",
|
|
25
|
+
"STEPmod root; reads data/basic/normrefs.xml and " \
|
|
26
|
+
"data/basic/bibliography.xml") do |dir|
|
|
27
|
+
options[:stepmod] = dir
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
opts.on("--normrefs PATH", "Path to normrefs.xml") do |path|
|
|
31
|
+
options[:normrefs] = path
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
opts.on("--bibliography PATH", "Path to bibliography.xml") do |path|
|
|
35
|
+
options[:bibliography] = path
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opts.on("-o", "--output PATH",
|
|
39
|
+
"Output collection XML (default: standard output)") do |path|
|
|
40
|
+
options[:output] = path
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
opts.on("-t", "--title TITLE", "Title of the collection") do |title|
|
|
44
|
+
options[:title] = title
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
|
48
|
+
puts opts
|
|
49
|
+
exit
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
begin
|
|
53
|
+
parser.parse!
|
|
54
|
+
rescue OptionParser::ParseError => e
|
|
55
|
+
warn e.message
|
|
56
|
+
warn parser
|
|
57
|
+
exit 1
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
unless ARGV.empty?
|
|
61
|
+
warn "Unexpected argument: #{ARGV.join(' ')}"
|
|
62
|
+
warn parser
|
|
63
|
+
exit 1
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
if options[:stepmod]
|
|
67
|
+
basic = File.join(options[:stepmod], "data", "basic")
|
|
68
|
+
options[:normrefs] ||= File.join(basic, "normrefs.xml")
|
|
69
|
+
options[:bibliography] ||= File.join(basic, "bibliography.xml")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
inputs = options.values_at(:normrefs, :bibliography).compact
|
|
73
|
+
if inputs.empty?
|
|
74
|
+
warn "Give --stepmod DIR, or --normrefs PATH and/or --bibliography PATH."
|
|
75
|
+
warn parser
|
|
76
|
+
exit 1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
missing = inputs.reject { |path| File.file?(path) }
|
|
80
|
+
unless missing.empty?
|
|
81
|
+
warn "File not found: #{missing.join(', ')}"
|
|
82
|
+
exit 1
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
converter = Stepmod::Utils::BibliographyConverter.new(
|
|
86
|
+
normrefs: options[:normrefs],
|
|
87
|
+
bibliography: options[:bibliography],
|
|
88
|
+
title: options[:title],
|
|
89
|
+
)
|
|
90
|
+
xml = converter.to_xml
|
|
91
|
+
|
|
92
|
+
if options[:output]
|
|
93
|
+
File.write(options[:output], xml, encoding: "UTF-8")
|
|
94
|
+
log "#{converter.items.size} items written to #{options[:output]}"
|
|
95
|
+
else
|
|
96
|
+
$stdout.write(xml)
|
|
97
|
+
end
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
require "date"
|
|
2
|
+
require "nokogiri"
|
|
3
|
+
require "relaton/bib"
|
|
4
|
+
|
|
5
|
+
module Stepmod
|
|
6
|
+
module Utils
|
|
7
|
+
# Converts the STEPmod shared reference lists, data/basic/normrefs.xml
|
|
8
|
+
# and data/basic/bibliography.xml, into one Relaton collection, so that
|
|
9
|
+
# Metanorma can cite any entry by its id.
|
|
10
|
+
#
|
|
11
|
+
# Each entry becomes a Relaton::Bib::ItemData. Its id is the STEPmod id
|
|
12
|
+
# with the list prefix the migrated documents use ("normref_",
|
|
13
|
+
# "bibitem_"), and the raw STEPmod id is kept as a docidentifier of type
|
|
14
|
+
# "STEPmod-id".
|
|
15
|
+
class BibliographyConverter
|
|
16
|
+
COLLECTION_NS = "https://open.ribose.com/relaton-xml".freeze
|
|
17
|
+
DEFAULT_TITLE = "STEPmod bibliography".freeze
|
|
18
|
+
AUTHOR = "ISO/TC 184/SC 4".freeze
|
|
19
|
+
|
|
20
|
+
XML_ENTITIES = %w[amp lt gt quot apos].freeze
|
|
21
|
+
DASHES = /\A[\s—–-]+|[\s—–-]+\z/
|
|
22
|
+
ITEM_TYPES = {
|
|
23
|
+
"normref" => "standard",
|
|
24
|
+
"bibitem" => "standard",
|
|
25
|
+
"bibitem.techreport" => "techreport",
|
|
26
|
+
"bibitem.book" => "book",
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
Bib = Relaton::Bib
|
|
30
|
+
|
|
31
|
+
attr_reader :title
|
|
32
|
+
|
|
33
|
+
# @param normrefs [String, nil] path to normrefs.xml
|
|
34
|
+
# @param bibliography [String, nil] path to bibliography.xml
|
|
35
|
+
# @param title [String, nil] title of the collection
|
|
36
|
+
def initialize(normrefs: nil, bibliography: nil, title: nil)
|
|
37
|
+
@normrefs = normrefs
|
|
38
|
+
@bibliography = bibliography
|
|
39
|
+
@title = title || DEFAULT_TITLE
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [Array<Relaton::Bib::ItemData>]
|
|
43
|
+
def items
|
|
44
|
+
@items ||= read_list(@normrefs, "normref", "//normref") +
|
|
45
|
+
read_list(@bibliography, "bibitem",
|
|
46
|
+
"//bibitem | //bibitem.techreport | //bibitem.book")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [String] a relaton-collection XML document
|
|
50
|
+
def to_xml
|
|
51
|
+
doc = Nokogiri::XML::Document.new
|
|
52
|
+
doc.encoding = "UTF-8"
|
|
53
|
+
root = doc.add_child(doc.create_element("relaton-collection",
|
|
54
|
+
xmlns: COLLECTION_NS))
|
|
55
|
+
root.add_child(doc.create_element("title", title))
|
|
56
|
+
root.add_child(author_node(doc))
|
|
57
|
+
items.each do |item|
|
|
58
|
+
relation = root.add_child(doc.create_element("relation",
|
|
59
|
+
type: "partOf"))
|
|
60
|
+
relation.add_child(Nokogiri::XML(item.to_xml, &:noblanks).root)
|
|
61
|
+
end
|
|
62
|
+
doc.to_xml
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def author_node(doc)
|
|
68
|
+
contributor = doc.create_element("contributor")
|
|
69
|
+
contributor.add_child(doc.create_element("role", type: "author"))
|
|
70
|
+
org = contributor.add_child(doc.create_element("organization"))
|
|
71
|
+
org.add_child(doc.create_element("name", AUTHOR))
|
|
72
|
+
contributor
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def read_list(path, prefix, xpath)
|
|
76
|
+
return [] unless path
|
|
77
|
+
|
|
78
|
+
seen = {}
|
|
79
|
+
parse(path).xpath(xpath).filter_map do |node|
|
|
80
|
+
raw_id = node["id"]
|
|
81
|
+
id = "#{prefix}_#{sanitize_id(raw_id)}"
|
|
82
|
+
if seen[id]
|
|
83
|
+
log(path, "duplicate id #{raw_id.inspect} skipped")
|
|
84
|
+
next
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
seen[id] = true
|
|
88
|
+
build_item(node, id, raw_id)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def log(path, message)
|
|
93
|
+
warn "[stepmod-utils] #{path}: #{message}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# The DTD that declares the HTML entities is not available, so resolve
|
|
97
|
+
# them before the parse.
|
|
98
|
+
# An unknown entity would be dropped silently by the parser, so it is
|
|
99
|
+
# reported and kept as text.
|
|
100
|
+
def parse(path)
|
|
101
|
+
xml = File.read(path, encoding: "UTF-8")
|
|
102
|
+
xml = xml.gsub(/&([a-zA-Z][a-zA-Z0-9]*);/) do |match|
|
|
103
|
+
name = Regexp.last_match(1)
|
|
104
|
+
next match if XML_ENTITIES.include?(name)
|
|
105
|
+
|
|
106
|
+
resolve_entity(name) || unknown_entity(path, match)
|
|
107
|
+
end
|
|
108
|
+
Nokogiri::XML(xml, &:nonet)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def resolve_entity(name)
|
|
112
|
+
codepoint = entity_lookup[name]
|
|
113
|
+
[codepoint].pack("U") if codepoint
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def unknown_entity(path, match)
|
|
117
|
+
log(path, "unknown entity #{match} kept as text")
|
|
118
|
+
"&#{match[1..]}"
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def entity_lookup
|
|
122
|
+
@entity_lookup ||= Nokogiri::HTML4::EntityLookup.new
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def sanitize_id(raw_id)
|
|
126
|
+
raw_id.to_s.gsub(/[^\w.-]+/, "_")
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def build_item(node, id, raw_id)
|
|
130
|
+
ref = node.at("./stdref") || node
|
|
131
|
+
Bib::ItemData.new(
|
|
132
|
+
id: id,
|
|
133
|
+
type: ITEM_TYPES[node.name],
|
|
134
|
+
docidentifier: docidentifiers(node, ref, raw_id),
|
|
135
|
+
title: titles(node, ref),
|
|
136
|
+
date: dates(ref),
|
|
137
|
+
contributor: contributors(node, ref),
|
|
138
|
+
place: places(node),
|
|
139
|
+
source: sources(node),
|
|
140
|
+
note: notes(node),
|
|
141
|
+
)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def docidentifiers(node, ref, raw_id)
|
|
145
|
+
primary = primary_identifier(node, ref)
|
|
146
|
+
stepmod_id = Bib::Docidentifier.new(content: raw_id,
|
|
147
|
+
type: "STEPmod-id")
|
|
148
|
+
primary ? [primary, stepmod_id] : [stepmod_id]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# A normref stdnumber is the bare number ("31-0"). A bibliography
|
|
152
|
+
# stdnumber is already the full identifier ("ISO 286-1", "RFC 3986").
|
|
153
|
+
def primary_identifier(node, ref)
|
|
154
|
+
orgname = text(ref, "orgname")
|
|
155
|
+
number = text(ref, "stdnumber")
|
|
156
|
+
if number
|
|
157
|
+
content = node.name == "normref" ? prefixed(orgname, number) : number
|
|
158
|
+
type = docid_type(orgname)
|
|
159
|
+
elsif (number = text(node, "number"))
|
|
160
|
+
content = prefixed(text(node, "report-type"), number)
|
|
161
|
+
type = "STEPmod"
|
|
162
|
+
end
|
|
163
|
+
return unless content
|
|
164
|
+
|
|
165
|
+
Bib::Docidentifier.new(content: content, type: type, primary: true)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def prefixed(prefix, value)
|
|
169
|
+
return value if prefix.nil? || value.start_with?(prefix)
|
|
170
|
+
|
|
171
|
+
"#{prefix} #{value}"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def docid_type(orgname)
|
|
175
|
+
case orgname
|
|
176
|
+
when /\AISO/ then "ISO"
|
|
177
|
+
when /\AIEC/ then "IEC"
|
|
178
|
+
else "STEPmod"
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# A normref subtitle continues the title ("— Part 1: ..."). A
|
|
183
|
+
# bibliography subtitle is free text, so it becomes a note instead.
|
|
184
|
+
def titles(node, ref)
|
|
185
|
+
main = strip_dashes(text(ref, "stdtitle"))
|
|
186
|
+
return [] unless main
|
|
187
|
+
|
|
188
|
+
subtitle = node.name == "normref" && strip_dashes(text(ref, "subtitle"))
|
|
189
|
+
return [title_of(main, "main")] unless subtitle
|
|
190
|
+
|
|
191
|
+
result = [title_of(join_title(main, subtitle), "main"),
|
|
192
|
+
title_of(main, "title-main")]
|
|
193
|
+
part = subtitle.start_with?("Part")
|
|
194
|
+
result << title_of(subtitle, "title-part") if part
|
|
195
|
+
result
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Some subtitles continue the sentence (", corrected and reprinted
|
|
199
|
+
# in 1995", "(OMG-UML VER 1.3)"); the others are title components.
|
|
200
|
+
def join_title(main, subtitle)
|
|
201
|
+
case subtitle
|
|
202
|
+
when /\A[,;.]/ then "#{main}#{subtitle}"
|
|
203
|
+
when /\A\(/ then "#{main} #{subtitle}"
|
|
204
|
+
else "#{main} — #{subtitle}"
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def title_of(content, type)
|
|
209
|
+
Bib::Title.new(content: content, type: type, language: "en",
|
|
210
|
+
script: "Latn")
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def strip_dashes(value)
|
|
214
|
+
stripped = value&.gsub(DASHES, "")
|
|
215
|
+
stripped unless stripped.nil? || stripped.empty?
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def notes(node)
|
|
219
|
+
return [] if node.name == "normref"
|
|
220
|
+
|
|
221
|
+
subtitle = text(node, "subtitle")
|
|
222
|
+
subtitle ? [Bib::Note.new(content: subtitle)] : []
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
# STEPmod dates are "YYYY", "YYYY-MM-DD", or free text such as
|
|
226
|
+
# "January 1992". Free text is kept as the date text. A value without
|
|
227
|
+
# a year ("—", "-", "CHECK DATE") means "undated" and is dropped, and
|
|
228
|
+
# so is a future date ("To be published in 2018").
|
|
229
|
+
def dates(ref)
|
|
230
|
+
value = text(ref, "pubdate")
|
|
231
|
+
return [] unless value
|
|
232
|
+
|
|
233
|
+
if value.match?(/\A\d{4}(-\d{2}){0,2}\z/)
|
|
234
|
+
return [Bib::Date.new(type: "published", at: value)]
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
year = value[/\b(\d{4})\b/, 1]
|
|
238
|
+
return [] if year.nil? || value.match?(/to be published/i)
|
|
239
|
+
|
|
240
|
+
[Bib::Date.new(type: "published", at: year, text: value)]
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def contributors(node, ref)
|
|
244
|
+
authors = texts(node, "primary-responsibility").map do |name|
|
|
245
|
+
Bib::Contributor.new(role: [role("author")], person: person(name))
|
|
246
|
+
end
|
|
247
|
+
publishers = %w[orgname institution publisher].flat_map do |tag|
|
|
248
|
+
texts(tag == "orgname" ? ref : node, tag)
|
|
249
|
+
end
|
|
250
|
+
authors + publishers.uniq.map do |name|
|
|
251
|
+
Bib::Contributor.new(role: [role("publisher")],
|
|
252
|
+
organization: organization(name))
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def role(type)
|
|
257
|
+
Bib::Contributor::Role.new(type: type)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def person(name)
|
|
261
|
+
Bib::Person.new(
|
|
262
|
+
name: Bib::FullName.new(
|
|
263
|
+
completename: Bib::LocalizedString.new(content: name),
|
|
264
|
+
),
|
|
265
|
+
)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def organization(name)
|
|
269
|
+
Bib::Organization.new(
|
|
270
|
+
name: [Bib::TypedLocalizedString.new(content: name)],
|
|
271
|
+
)
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def places(node)
|
|
275
|
+
texts(node, "place").map { |p| Bib::Place.new(formatted_place: p) }
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def sources(node)
|
|
279
|
+
texts(node, "ulink").map { |u| Bib::Uri.new(type: "src", content: u) }
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def text(node, tag)
|
|
283
|
+
texts(node, tag).first
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def texts(node, tag)
|
|
287
|
+
node.xpath("./#{tag}").filter_map do |el|
|
|
288
|
+
value = el.text.gsub(/\s+/, " ").strip
|
|
289
|
+
value unless value.empty?
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
end
|
|
@@ -12,7 +12,8 @@ module Stepmod
|
|
|
12
12
|
# Find non-asterisk content that is enclosed by two or
|
|
13
13
|
# more asterisks. Ensure that only one whitespace occurs
|
|
14
14
|
# in the border area.
|
|
15
|
-
# Same for underscores and brackets.
|
|
15
|
+
# Same for underscores and brackets. A missing border is added, except
|
|
16
|
+
# next to a word character: unconstrained markup may sit inside a word.
|
|
16
17
|
def clean_tag_borders(string)
|
|
17
18
|
patterns = {
|
|
18
19
|
/\s?\*{2,}.*?\*{2,}\s?/ => "**",
|
|
@@ -23,8 +24,7 @@ module Stepmod
|
|
|
23
24
|
result = string.dup
|
|
24
25
|
patterns.each do |pattern, value|
|
|
25
26
|
result = result.gsub(pattern) do |match|
|
|
26
|
-
|
|
27
|
-
default_border: Coradoc::Input::Html.config.tag_border) do
|
|
27
|
+
border_tags(match, Regexp.last_match) do
|
|
28
28
|
match.strip.sub(" #{value}", value).sub("#{value} ", value)
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -37,6 +37,26 @@ module Stepmod
|
|
|
37
37
|
end
|
|
38
38
|
result
|
|
39
39
|
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# Like preserve_border_whitespaces, but a border is only invented where
|
|
44
|
+
# the neighbouring character is not part of a word.
|
|
45
|
+
def border_tags(match, matched)
|
|
46
|
+
return match if /\A\s*\Z/.match?(match)
|
|
47
|
+
|
|
48
|
+
invent = !/[\[(\])]/.match?(match)
|
|
49
|
+
start = match[/\A\s*/]
|
|
50
|
+
finish = match[/\s*\Z/]
|
|
51
|
+
start = border(matched.pre_match[-1]) if start.empty? && invent
|
|
52
|
+
finish = border(matched.post_match[0]) if finish.empty? && invent
|
|
53
|
+
|
|
54
|
+
start + yield + finish
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def border(neighbour)
|
|
58
|
+
neighbour&.match?(/\w/) ? "" : Coradoc::Input::Html.config.tag_border
|
|
59
|
+
end
|
|
40
60
|
end
|
|
41
61
|
end
|
|
42
62
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "figure"
|
|
4
|
+
|
|
3
5
|
module Stepmod
|
|
4
6
|
module Utils
|
|
5
7
|
module Converters
|
|
@@ -18,6 +20,7 @@ module Stepmod
|
|
|
18
20
|
"[[#{id}]]"
|
|
19
21
|
elsif href.to_s.start_with?("#")
|
|
20
22
|
href = href.sub(/^#/, "").gsub(/\s/, "").gsub(/__+/, "_")
|
|
23
|
+
href = figure_anchor(href, state) || href
|
|
21
24
|
if name.empty? || number_with_optional_prefix?(name)
|
|
22
25
|
"<<#{href}>>"
|
|
23
26
|
else
|
|
@@ -36,6 +39,17 @@ module Stepmod
|
|
|
36
39
|
|
|
37
40
|
private
|
|
38
41
|
|
|
42
|
+
# A reference to a figure must use the id the figure is given by
|
|
43
|
+
# Figure.pattern, or the link does not resolve.
|
|
44
|
+
def figure_anchor(href, state)
|
|
45
|
+
return unless state[:schema_and_entity] || state[:schema_name]
|
|
46
|
+
|
|
47
|
+
figure_id = href[/\Afigure[_-](.+)\z/, 1]
|
|
48
|
+
figure_id = href if figure_id.nil? &&
|
|
49
|
+
Array(state[:figure_ids]).include?(href)
|
|
50
|
+
Figure.pattern(state, figure_id) if figure_id
|
|
51
|
+
end
|
|
52
|
+
|
|
39
53
|
def number_with_optional_prefix?(name)
|
|
40
54
|
/.*?\s*\(?\d+\)?/.match(name)
|
|
41
55
|
end
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "strong"
|
|
4
|
+
|
|
3
5
|
module Stepmod
|
|
4
6
|
module Utils
|
|
5
7
|
module Converters
|
|
6
8
|
class Em < Stepmod::Utils::Converters::Base
|
|
9
|
+
BOLD_TAGS = %w[b strong].freeze
|
|
10
|
+
|
|
7
11
|
def convert(node, state = {})
|
|
8
12
|
italic_converted(node, state)
|
|
9
13
|
end
|
|
@@ -15,6 +19,11 @@ module Stepmod
|
|
|
15
19
|
private
|
|
16
20
|
|
|
17
21
|
def italic_converted(node, state)
|
|
22
|
+
bold = sole_bold_child(node)
|
|
23
|
+
if bold && !state[:already_italic]
|
|
24
|
+
return bold_italic(node, bold, state)
|
|
25
|
+
end
|
|
26
|
+
|
|
18
27
|
cloned_node = node.clone
|
|
19
28
|
equations = extract_equations(cloned_node)
|
|
20
29
|
content = treat_children(cloned_node,
|
|
@@ -34,6 +43,26 @@ module Stepmod
|
|
|
34
43
|
[content, equation_content].compact.join("")
|
|
35
44
|
end
|
|
36
45
|
|
|
46
|
+
# <i><b>x</b></i> is written bold outside, italic inside: `*_x_*`.
|
|
47
|
+
def bold_italic(node, bold, state)
|
|
48
|
+
content = treat_children(bold, state.merge(already_italic: true))
|
|
49
|
+
return content if content.strip.empty?
|
|
50
|
+
|
|
51
|
+
lead = content[/^\s*/]
|
|
52
|
+
trail = content[/\s*$/]
|
|
53
|
+
Strong.new.mark_up(node, "#{lead}_#{content.strip}_#{trail}", state)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def sole_bold_child(node)
|
|
57
|
+
return unless node.element_children.one?
|
|
58
|
+
return if node.children.any? { |c| c.text? && !c.text.strip.empty? }
|
|
59
|
+
|
|
60
|
+
bold = node.element_children.first
|
|
61
|
+
return unless BOLD_TAGS.include?(bold.name)
|
|
62
|
+
|
|
63
|
+
bold unless bold.element_children.any? { |c| c.name == "eqn" }
|
|
64
|
+
end
|
|
65
|
+
|
|
37
66
|
def extract_equations(node)
|
|
38
67
|
equations = []
|
|
39
68
|
|
|
@@ -7,11 +7,12 @@ module Stepmod
|
|
|
7
7
|
module Converters
|
|
8
8
|
class Figure < Coradoc::Input::Html::Converters::Figure
|
|
9
9
|
def self.pattern(state, id)
|
|
10
|
-
|
|
10
|
+
schema_and_entity = state[:schema_and_entity] || state[:schema_name]
|
|
11
|
+
if schema_and_entity.nil?
|
|
11
12
|
raise StandardError.new("[figure]: no state given, #{id}")
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
schema =
|
|
15
|
+
schema = schema_and_entity.split(".").first
|
|
15
16
|
"figure-#{schema}-#{id}"
|
|
16
17
|
end
|
|
17
18
|
|
|
@@ -10,8 +10,36 @@ module Stepmod
|
|
|
10
10
|
bold_converted(node, state)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
# Wraps already converted +content+ in AsciiDoc bold markup, as
|
|
14
|
+
# +node+ (a <b>, or an element standing in for one) would.
|
|
15
|
+
def mark_up(node, content, state)
|
|
16
|
+
return content if content.strip.empty? || state[:already_strong] ||
|
|
17
|
+
state[:equation]
|
|
18
|
+
|
|
19
|
+
strong_tag = unconstrained?(node, content, state) ? "**" : "*"
|
|
20
|
+
leading = content[0, content.length - content.lstrip.length]
|
|
21
|
+
trailing = content[content.rstrip.length..]
|
|
22
|
+
handle_express_escape_seq(
|
|
23
|
+
node,
|
|
24
|
+
"#{leading}#{strong_tag}#{content.strip}#{strong_tag}#{trailing}",
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
13
28
|
private
|
|
14
29
|
|
|
30
|
+
# Constrained bold (`*x*`) is not recognised inside a word, so
|
|
31
|
+
# unconstrained markup is needed whenever a word character touches it.
|
|
32
|
+
def unconstrained?(node, content, state)
|
|
33
|
+
return true if state[:non_flanking_whitesapce]
|
|
34
|
+
|
|
35
|
+
(content.match?(/\A\S/) && word_sibling?(node.previous, /\w\z/)) ||
|
|
36
|
+
(content.match?(/\S\z/) && word_sibling?(node.next, /\A\w/))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def word_sibling?(sibling, pattern)
|
|
40
|
+
sibling&.text? && sibling.text.match?(pattern)
|
|
41
|
+
end
|
|
42
|
+
|
|
15
43
|
def bold_converted(node, state)
|
|
16
44
|
cloned_node = node.clone
|
|
17
45
|
equations = extract_equations(cloned_node)
|
|
@@ -23,14 +51,8 @@ module Stepmod
|
|
|
23
51
|
|
|
24
52
|
content = if state[:equation] && state[:convert_bold_and_italics]
|
|
25
53
|
"bb(#{content.strip})"
|
|
26
|
-
elsif content.strip.empty? || state[:already_strong] || state[:equation]
|
|
27
|
-
content
|
|
28
54
|
else
|
|
29
|
-
|
|
30
|
-
handle_express_escape_seq(
|
|
31
|
-
node,
|
|
32
|
-
"#{content[/^\s*/]}#{strong_tag}#{content.strip}#{strong_tag}#{content[/\s*$/]}",
|
|
33
|
-
)
|
|
55
|
+
mark_up(node, content, state)
|
|
34
56
|
end
|
|
35
57
|
|
|
36
58
|
[content, equation_content].compact.join("")
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require "pubid"
|
|
2
|
+
|
|
1
3
|
module Stepmod
|
|
2
4
|
module Utils
|
|
3
5
|
class ExpressBibdata
|
|
@@ -22,7 +24,7 @@ module Stepmod
|
|
|
22
24
|
@pubid = Pubid::Iso::Identifier.parse(published_info)
|
|
23
25
|
|
|
24
26
|
@part = pubid.part&.to_i
|
|
25
|
-
@version = pubid.edition&.to_i
|
|
27
|
+
@version = pubid.edition&.number&.to_i
|
|
26
28
|
@pub_year = pubid.year&.to_i
|
|
27
29
|
elsif !schema.version.nil?
|
|
28
30
|
@part = schema.version.items.find { |i| i.name == "part" }.value&.to_i
|
|
@@ -87,7 +87,7 @@ module Stepmod
|
|
|
87
87
|
# TODO there are schemas with only arm, mim, mim_lf:
|
|
88
88
|
# schemas/modules/limited_length_or_area_indicator_assignment/mim_lf.exp
|
|
89
89
|
part = @identifier.part
|
|
90
|
-
edition = @identifier.edition
|
|
90
|
+
edition = @identifier.edition&.number
|
|
91
91
|
schema_or_object = (schema_type == :module) ? "schema" : "object"
|
|
92
92
|
|
|
93
93
|
"\nSCHEMA #{@schema_name} '{ " \
|
|
@@ -246,6 +246,11 @@ processed_images_cache)
|
|
|
246
246
|
examples = description.xpath("example")
|
|
247
247
|
figures = description.xpath("figure")
|
|
248
248
|
tables = description.xpath("table")
|
|
249
|
+
state = {
|
|
250
|
+
schema_and_entity: description["linkend"],
|
|
251
|
+
descriptions_file: descriptions_file,
|
|
252
|
+
figure_ids: figures.map { |f| f["id"] || f["number"] },
|
|
253
|
+
}
|
|
249
254
|
|
|
250
255
|
converted_description = <<~DESCRIPTION
|
|
251
256
|
|
|
@@ -253,6 +258,7 @@ processed_images_cache)
|
|
|
253
258
|
wrapper,
|
|
254
259
|
no_notes_examples: true,
|
|
255
260
|
descriptions_file: descriptions_file,
|
|
261
|
+
figure_ids: state[:figure_ids],
|
|
256
262
|
)}
|
|
257
263
|
DESCRIPTION
|
|
258
264
|
|
|
@@ -263,7 +269,7 @@ processed_images_cache)
|
|
|
263
269
|
converted_figures = figures.map do |figure|
|
|
264
270
|
Stepmod::Utils::Converters::ExpressFigure
|
|
265
271
|
.new
|
|
266
|
-
.convert(figure,
|
|
272
|
+
.convert(figure, state)
|
|
267
273
|
end.join
|
|
268
274
|
|
|
269
275
|
converted_tables = tables.map do |table|
|
|
@@ -275,13 +281,13 @@ processed_images_cache)
|
|
|
275
281
|
converted_notes = notes.map do |note|
|
|
276
282
|
Stepmod::Utils::Converters::ExpressNote
|
|
277
283
|
.new
|
|
278
|
-
.convert(note,
|
|
284
|
+
.convert(note, state)
|
|
279
285
|
end.join
|
|
280
286
|
|
|
281
287
|
converted_examples = examples.map do |example|
|
|
282
288
|
Stepmod::Utils::Converters::ExpressExample
|
|
283
289
|
.new
|
|
284
|
-
.convert(example,
|
|
290
|
+
.convert(example, state)
|
|
285
291
|
end.join
|
|
286
292
|
|
|
287
293
|
[
|
|
@@ -402,16 +408,12 @@ processed_images_cache)
|
|
|
402
408
|
year = "" if year == "tbd"
|
|
403
409
|
edition = bib.attributes["version"].value
|
|
404
410
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
pubid.part = part if part && !part.empty?
|
|
411
|
-
pubid.year = year.split("-").first if year && !year.empty?
|
|
412
|
-
pubid.edition = edition if edition && !edition.empty?
|
|
411
|
+
attrs = { number: 10303 }
|
|
412
|
+
attrs[:part] = part if part && !part.empty?
|
|
413
|
+
attrs[:date] = { year: year.split("-").first } if year && !year.empty?
|
|
414
|
+
attrs[:edition] = { number: edition } if edition && !edition.empty?
|
|
413
415
|
|
|
414
|
-
|
|
416
|
+
Pubid::Iso::Identifier.new(**attrs)
|
|
415
417
|
end
|
|
416
418
|
|
|
417
419
|
def resource_bib_data(bib, schema_and_entity)
|
|
@@ -541,12 +541,12 @@ document:)
|
|
|
541
541
|
raise Error.new("[stepmod-utils] encountered unsupported schema_type")
|
|
542
542
|
end
|
|
543
543
|
|
|
544
|
-
if entity.subtype_of.empty?
|
|
544
|
+
if entity.subtype_of.to_a.empty?
|
|
545
545
|
"#{entity_type} " \
|
|
546
546
|
"that represents the " \
|
|
547
547
|
"#{entity_name_to_text(entity.id)} {{entity}}"
|
|
548
548
|
else
|
|
549
|
-
entity_subtypes = entity.subtype_of.map do |e|
|
|
549
|
+
entity_subtypes = entity.subtype_of.to_a.map do |e|
|
|
550
550
|
"{{#{e.id}}}"
|
|
551
551
|
end
|
|
552
552
|
|
data/stepmod-utils.gemspec
CHANGED
|
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
|
18
18
|
spec.require_paths = ["lib"]
|
|
19
19
|
spec.files = `git ls-files`.split("\n")
|
|
20
20
|
spec.test_files = `git ls-files -- {spec}/*`.split("\n")
|
|
21
|
-
spec.required_ruby_version = Gem::Requirement.new(">= 3.
|
|
21
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.3.0")
|
|
22
22
|
|
|
23
23
|
# Specify which files should be added to the gem when it is released.
|
|
24
24
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
@@ -42,7 +42,8 @@ Gem::Specification.new do |spec|
|
|
|
42
42
|
spec.add_dependency "ptools"
|
|
43
43
|
# The pubid monogem ships Pubid::Iso itself; the separate pubid-iso
|
|
44
44
|
# gem is superseded and its lib/pubid/iso.rb shadows the monogem's.
|
|
45
|
-
spec.add_dependency "pubid", "~> 2.0
|
|
45
|
+
spec.add_dependency "pubid", "~> 2.0"
|
|
46
|
+
spec.add_dependency "relaton", "~> 3.0"
|
|
46
47
|
spec.add_dependency "shale"
|
|
47
48
|
spec.add_dependency "thor", ">= 0.20"
|
|
48
49
|
spec.add_dependency "unitsml"
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stepmod-utils
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.10
|
|
4
|
+
version: 0.6.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-11-06 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: concurrent-ruby
|
|
@@ -141,14 +142,28 @@ dependencies:
|
|
|
141
142
|
requirements:
|
|
142
143
|
- - "~>"
|
|
143
144
|
- !ruby/object:Gem::Version
|
|
144
|
-
version: 2.0
|
|
145
|
+
version: '2.0'
|
|
146
|
+
type: :runtime
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - "~>"
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '2.0'
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: relaton
|
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - "~>"
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: '3.0'
|
|
145
160
|
type: :runtime
|
|
146
161
|
prerelease: false
|
|
147
162
|
version_requirements: !ruby/object:Gem::Requirement
|
|
148
163
|
requirements:
|
|
149
164
|
- - "~>"
|
|
150
165
|
- !ruby/object:Gem::Version
|
|
151
|
-
version:
|
|
166
|
+
version: '3.0'
|
|
152
167
|
- !ruby/object:Gem::Dependency
|
|
153
168
|
name: shale
|
|
154
169
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -198,6 +213,7 @@ email:
|
|
|
198
213
|
- open.source@ribose.com
|
|
199
214
|
executables:
|
|
200
215
|
- stepmod-annotate-all
|
|
216
|
+
- stepmod-convert-bibliography
|
|
201
217
|
- stepmod-convert-express-description
|
|
202
218
|
- stepmod-convert-express-resource
|
|
203
219
|
- stepmod-extract-changes
|
|
@@ -221,6 +237,7 @@ files:
|
|
|
221
237
|
- bin/console
|
|
222
238
|
- bin/setup
|
|
223
239
|
- exe/stepmod-annotate-all
|
|
240
|
+
- exe/stepmod-convert-bibliography
|
|
224
241
|
- exe/stepmod-convert-express-description
|
|
225
242
|
- exe/stepmod-convert-express-resource
|
|
226
243
|
- exe/stepmod-extract-changes
|
|
@@ -229,6 +246,7 @@ files:
|
|
|
229
246
|
- exe/stepmod-validate-express
|
|
230
247
|
- lib/stepmod/utils.rb
|
|
231
248
|
- lib/stepmod/utils/bibdata.rb
|
|
249
|
+
- lib/stepmod/utils/bibliography_converter.rb
|
|
232
250
|
- lib/stepmod/utils/change.rb
|
|
233
251
|
- lib/stepmod/utils/change_collection.rb
|
|
234
252
|
- lib/stepmod/utils/change_edition.rb
|
|
@@ -346,6 +364,7 @@ homepage: https://github.com/metanorma/stepmod-utils
|
|
|
346
364
|
licenses:
|
|
347
365
|
- BSD-2-Clause
|
|
348
366
|
metadata: {}
|
|
367
|
+
post_install_message:
|
|
349
368
|
rdoc_options: []
|
|
350
369
|
require_paths:
|
|
351
370
|
- lib
|
|
@@ -353,14 +372,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
353
372
|
requirements:
|
|
354
373
|
- - ">="
|
|
355
374
|
- !ruby/object:Gem::Version
|
|
356
|
-
version: 3.
|
|
375
|
+
version: 3.3.0
|
|
357
376
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
358
377
|
requirements:
|
|
359
378
|
- - ">="
|
|
360
379
|
- !ruby/object:Gem::Version
|
|
361
380
|
version: '0'
|
|
362
381
|
requirements: []
|
|
363
|
-
rubygems_version: 3.
|
|
382
|
+
rubygems_version: 3.5.22
|
|
383
|
+
signing_key:
|
|
364
384
|
specification_version: 4
|
|
365
385
|
summary: Stepmod-utils is a toolkit that works on STEPmod data.
|
|
366
386
|
test_files: []
|