metanorma 1.2.0 → 1.2.5

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: 189106fda9c97a62268cdf23a26f7b10f9784cff4d9cdf590563c0f9e71aaea5
4
- data.tar.gz: feec6fdbfbcdb931b3ca3ce782d9ba35248481902e66ca515b94f60346217dfe
3
+ metadata.gz: 66652dc0d52d85abe7e08d5804364bcc320760e292e91594ea135051d02ee92a
4
+ data.tar.gz: ab9bd75163ac8b107d2833bd5719d8742ad5b2d73c438361d40da77871efb36f
5
5
  SHA512:
6
- metadata.gz: e6843c3813d6d378a320ccdec21e85174889a0634396a0e1e15eeaf82192bf80414a8e698a7818cfebc575a3925e46007c6a006964179979682e51ea49a173b5
7
- data.tar.gz: 972d7e156885833eab9f91e142dd427dea72093d0a7eee665b5229e6e1dbd41bed117c8e72a09d6be9b6f2360c11eec3fa70eb0eb84807f5656bc08b496f56fc
6
+ metadata.gz: '038472b6e12dbcd3caca90a5538489e531d208a7168630f987fd3a12f7590ef5e4a2bb63cbcaabd5555dcbfa9ebaccf4894fd344df4e185a2a9954049166142c'
7
+ data.tar.gz: 135896ec6863c3a75cd0779957e439ebf964358bf0415ad44e74af3d0f8f729a777793d84bf23149a0309e4e70d15e5c1587eaae27f0b3744ab8c26344488a83
@@ -3,16 +3,16 @@
3
3
  name: notify
4
4
 
5
5
  on:
6
- push:
7
- branches: [ master ]
8
- tags:
9
- - '*'
6
+ repository_dispatch:
7
+ types: [ notify ]
10
8
 
11
9
  jobs:
12
10
  notify:
13
11
  name: Notify dependent repos
14
12
  runs-on: ubuntu-latest
15
13
  steps:
14
+ - uses: actions/checkout@v2
15
+
16
16
  - name: Trigger repositories
17
17
  env:
18
18
  GH_USERNAME: metanorma-ci
@@ -21,7 +21,7 @@ jobs:
21
21
  curl -LO --retry 3 https://raw.githubusercontent.com/metanorma/metanorma-build-scripts/master/trigger-gh-actions.sh
22
22
  [[ -f ".github/workflows/dependent_repos.env" ]] && source .github/workflows/dependent_repos.env
23
23
  CLIENT_PAYLOAD=$(cat <<EOF
24
- "{ "ref": "${GITHUB_REF}", "repo": "${GITHUB_REPOSITORY}" }"
24
+ "{ "ref": "${{ github.event.client_payload.ref }}", "repo": "${GITHUB_REPOSITORY}" }"
25
25
  EOF
26
26
  )
27
27
  for repo in $TEMPLATE_REPOS" $SAMPLES_REPOS"
@@ -30,7 +30,7 @@ jobs:
30
30
  done
31
31
 
32
32
  - name: Trigger release repositories
33
- if: github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')
33
+ if: github.event.client_payload.ref == 'refs/heads/master' || startsWith(github.event.client_payload.ref, 'refs/tags/v')
34
34
  env:
35
35
  GH_USERNAME: metanorma-ci
36
36
  GH_ACCESS_TOKEN: ${{ secrets.METANORMA_CI_PAT_TOKEN }}
@@ -38,7 +38,7 @@ jobs:
38
38
  curl -LO --retry 3 https://raw.githubusercontent.com/metanorma/metanorma-build-scripts/master/trigger-gh-actions.sh
39
39
  [[ -f ".github/workflows/dependent_repos.env" ]] && source .github/workflows/dependent_repos.env
40
40
  CLIENT_PAYLOAD=$(cat <<EOF
41
- "{ "ref": "${GITHUB_REF}", "repo": "${GITHUB_REPOSITORY}" }"
41
+ "{ "ref": "${{ github.event.client_payload.ref }}", "repo": "${GITHUB_REPOSITORY}" }"
42
42
  EOF
43
43
  )
44
44
  for repo in $DEPENDENT_REPOS
@@ -4,7 +4,8 @@ name: rake
4
4
 
5
5
  on:
6
6
  push:
7
- branches: [ master ]
7
+ branches: [ master, main ]
8
+ tags: [ v* ]
8
9
  pull_request:
9
10
 
10
11
  jobs:
@@ -31,14 +32,29 @@ jobs:
31
32
  steps:
32
33
  - uses: actions/checkout@master
33
34
 
34
- - name: Use Ruby
35
- uses: ruby/setup-ruby@v1
35
+ - uses: ruby/setup-ruby@v1
36
36
  with:
37
37
  ruby-version: ${{ matrix.ruby }}
38
- bundler-cache: true
39
38
 
40
- - name: Update gems
41
- run: bundle install --jobs 4 --retry 3
39
+ - uses: actions/cache@v2
40
+ with:
41
+ path: vendor/bundle
42
+ key: bundle-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
43
+ restore-keys: bundle-${{ matrix.os }}-${{ matrix.ruby }}
44
+
45
+ - run: bundle config set path 'vendor/bundle'
46
+
47
+ - run: bundle install --jobs 4 --retry 3
42
48
 
43
- - name: Run specs
44
- run: bundle exec rake
49
+ - run: bundle exec rake
50
+
51
+ tests-passed:
52
+ needs: rake
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - uses: peter-evans/repository-dispatch@v1
56
+ with:
57
+ token: ${{ secrets.GITHUB_TOKEN }}
58
+ repository: ${{ github.repository }}
59
+ event-type: notify
60
+ client-payload: '{"ref": "${{ github.ref }}"}'
@@ -1,9 +1,7 @@
1
1
  = Metanorma: the standard for standards
2
2
 
3
3
  image:https://img.shields.io/gem/v/metanorma.svg["Gem Version", link="https://rubygems.org/gems/metanorma"]
4
- image:https://github.com/metanorma/metanorma/workflows/ubuntu/badge.svg["Ubuntu Build Status", link="https://github.com/metanorma/metanorma/actions?query=workflow%3Aubuntu"]
5
- image:https://github.com/metanorma/metanorma/workflows/macos/badge.svg["OSX Build Status", link="https://github.com/metanorma/metanorma/actions?query=workflow%3Amacos"]
6
- image:https://github.com/metanorma/metanorma/workflows/windows/badge.svg["Windows Build Status", link="https://github.com/metanorma/metanorma/actions?query=workflow%3Awindows"]
4
+ image:https://github.com/metanorma/metanorma/workflows/rake/badge.svg["Build Status", link="https://github.com/metanorma/metanorma/actions?workflow=rake"]
7
5
  image:https://codeclimate.com/github/metanorma/metanorma/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/metanorma/metanorma"]
8
6
  image:https://img.shields.io/github/issues-pr-raw/metanorma/metanorma.svg["Pull Requests", link="https://github.com/metanorma/metanorma/pulls"]
9
7
  image:https://img.shields.io/github/commits-since/metanorma/metanorma/latest.svg["Commits since latest",link="https://github.com/metanorma/metanorma/releases"]
@@ -3,6 +3,7 @@
3
3
  require "relaton"
4
4
  require "relaton/cli"
5
5
  require "metanorma/collection_manifest"
6
+ require "metanorma-utils"
6
7
 
7
8
  module Metanorma
8
9
  # Metanorma collection of documents
@@ -39,8 +40,13 @@ module Metanorma
39
40
  @documents.merge! @manifest.documents(File.dirname(@file))
40
41
  @prefatory = args[:prefatory]
41
42
  @final = args[:final]
43
+ @log = Metanorma::Utils::Log.new
42
44
  end
45
+
43
46
  # rubocop:enable Metrics/AbcSize,Metrics/MethodLength
47
+ def clean_exit
48
+ @log.write(File.join(File.dirname(@file), File.basename(@file, ".*") + ".err"))
49
+ end
44
50
 
45
51
  # @return [String] XML
46
52
  def to_xml
@@ -57,7 +63,8 @@ module Metanorma
57
63
  end
58
64
 
59
65
  def render(opts)
60
- CollectionRenderer.render self, opts
66
+ CollectionRenderer.render self, opts.merge(log: @log)
67
+ clean_exit
61
68
  end
62
69
 
63
70
  class << self
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "isodoc"
4
+
5
+ module Metanorma
6
+ # XML collection renderer
7
+ class CollectionRenderer
8
+ # hash for each document in collection of document identifier to:
9
+ # document reference (fileref or id), type of document reference,
10
+ # and bibdata entry for that file
11
+ # @param path [String] path to collection
12
+ # @return [Hash{String=>Hash}]
13
+ def read_files(path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
14
+ files = {}
15
+ @xml.xpath(ns("//docref")).each do |d|
16
+ identifier = d.at(ns("./identifier")).text
17
+ files[identifier] = if d["fileref"]
18
+ { type: "fileref",
19
+ ref: File.join(path, d["fileref"]) }
20
+ else { type: "id", ref: d["id"] }
21
+ end
22
+ file, _filename = targetfile(files[identifier], true)
23
+ xml = Nokogiri::XML(file)
24
+ add_document_suffix(identifier, xml)
25
+ files[identifier][:anchors] = read_anchors(xml)
26
+ files[identifier][:bibdata] = xml.at(ns("//bibdata"))
27
+ end
28
+ files
29
+ end
30
+
31
+ def add_suffix_to_attributes(doc, suffix, tag_name, attribute_name)
32
+ doc.xpath(ns("//#{tag_name}[@#{attribute_name}]")).each do |elem|
33
+ elem.attributes[attribute_name].value =
34
+ "#{elem.attributes[attribute_name].value}_#{suffix}"
35
+ end
36
+ end
37
+
38
+ def add_document_suffix(identifier, doc)
39
+ document_suffix = Metanorma::Utils::to_ncname(identifier)
40
+ [%w[* id],
41
+ %w[* bibitemid],
42
+ %w[review from],
43
+ %w[review to],
44
+ %w[index to],
45
+ %w[xref target],
46
+ %w[callout target]]
47
+ .each do |(tag_name, attribute_name)|
48
+ add_suffix_to_attributes(doc, document_suffix, tag_name, attribute_name)
49
+ end
50
+ end
51
+
52
+ # map locality type and label (e.g. "clause" "1") to id = anchor for
53
+ # a document
54
+ def read_anchors(xml)
55
+ ret = {}
56
+ xrefs = @isodoc.xref_init(@lang, @script, @isodoc, @isodoc.i18n, {})
57
+ xrefs.parse xml
58
+ xrefs.get.each do |k, v|
59
+ ret[v[:type]] ||= {}
60
+ index = v[:container] || v[:label].nil? || v[:label].empty? ?
61
+ UUIDTools::UUID.random_create.to_s : v[:label]
62
+ # Note: will only key clauses, which have unambiguous reference label in locality.
63
+ # Notes, examples etc with containers are just plunked agaisnt UUIDs, so that their
64
+ # IDs can at least be registered to be tracked as existing.
65
+ ret[v[:type]][index] = k
66
+ end
67
+ ret
68
+ end
69
+
70
+ # return file contents + output filename for each file in the collection,
71
+ # given a docref entry
72
+ # @param data [Hash]
73
+ # @param read [Boolean]
74
+ # @return [Array<String, nil>]
75
+ def targetfile(data, read = false)
76
+ if data[:type] == "fileref" then ref_file data[:ref], read
77
+ else xml_file data[:id], read
78
+ end
79
+ end
80
+
81
+ # @param ref [String]
82
+ # @param read [Boolean]
83
+ # @return [Array<String, nil>]
84
+ def ref_file(ref, read)
85
+ file = File.read(ref, encoding: "utf-8") if read
86
+ filename = ref.sub(/\.xml$/, ".html")
87
+ [file, filename]
88
+ end
89
+
90
+ # @param id [String]
91
+ # @param read [Boolean]
92
+ # @return [Array<String, nil>]
93
+ def xml_file(id, read)
94
+ file = @xml.at(ns("//doc-container[@id = '#{id}']")).to_xml if read
95
+ filename = id + ".html"
96
+ [file, filename]
97
+ end
98
+
99
+ # @param bib [Nokogiri::XML::Element]
100
+ # @param identifier [String]
101
+ def update_bibitem(bib, identifier) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
102
+ docid = bib&.at(ns("./docidentifier"))&.text
103
+ unless @files[docid]
104
+ error = "[metanorma] Cannot find crossreference to document #{docid} in document #{identifier}."
105
+ @log.add("Cross-References", nil, error)
106
+ Util.log(error, :warning)
107
+ return
108
+ end
109
+ id = bib["id"]
110
+ newbib = bib.replace(@files[docid][:bibdata])
111
+ newbib.name = "bibitem"
112
+ newbib["id"] = id
113
+ newbib["hidden"] = "true"
114
+ newbib&.at(ns("./ext"))&.remove
115
+ _file, url = targetfile(@files[docid], false)
116
+ uri_node = Nokogiri::XML::Node.new "uri", newbib
117
+ uri_node[:type] = "citation"
118
+ uri_node.content = url
119
+ newbib.at(ns("./docidentifier")).previous = uri_node
120
+ end
121
+
122
+ # Resolves direct links to other files in collection (repo(current-metanorma-collection/x),
123
+ # and indirect links to other files in collection (bibitem[@type = 'internal'] pointing to a file anchor
124
+ # in another file in the collection)
125
+ # @param file [String] XML content
126
+ # @param identifier [String] docid
127
+ # @param internal_refs [Hash{String=>Hash{String=>String}] schema name to anchor to filename
128
+ # @return [String] XML content
129
+ def update_xrefs(file, identifier, internal_refs)
130
+ docxml = Nokogiri::XML(file)
131
+ update_indirect_refs_to_docs(docxml, internal_refs)
132
+ add_document_suffix(identifier, docxml)
133
+ update_direct_refs_to_docs(docxml, identifier)
134
+ docxml.xpath(ns("//references[not(./bibitem[not(@hidden) or @hidden = 'false'])]")).each do |f|
135
+ f["hidden"] = "true"
136
+ end
137
+ docxml.to_xml
138
+ end
139
+
140
+ # repo(current-metanorma-collection/ISO 17301-1:2016)
141
+ # replaced by bibdata of "ISO 17301-1:2016" in situ as bibitem.
142
+ # Any erefs to that bibitem id are replaced with relative URL
143
+ # Preferably with anchor, and is a job to realise dynamic lookup of localities.
144
+ def update_direct_refs_to_docs(docxml, identifier)
145
+ docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |b|
146
+ docid = b&.at(ns("./docidentifier[@type = 'repository']"))&.text
147
+ next unless docid && %r{^current-metanorma-collection/}.match(docid)
148
+ update_bibitem(b, identifier)
149
+ update_anchors(b, docxml, docid)
150
+ end
151
+ end
152
+
153
+ # Resolve erefs to a container of ids in another doc, to an anchor eref (direct link)
154
+ def update_indirect_refs_to_docs(docxml, internal_refs)
155
+ internal_refs.each do |schema, ids|
156
+ ids.each do |id, file|
157
+ update_indirect_refs_to_docs1(docxml, schema, id, file)
158
+ end
159
+ end
160
+ end
161
+
162
+ def update_indirect_refs_to_docs1(docxml, schema, id, file)
163
+ docxml.xpath(ns("//eref[@bibitemid = '#{schema}_#{id}']")).each do |e|
164
+ e["citeas"] = file
165
+ end
166
+ docid = docxml.at(ns("//bibitem[@id = '#{schema}_#{id}']/docidentifier[@type = 'repository']")) or return
167
+ docid.children = "current-metanorma-collection/#{file}"
168
+ docid.previous = "<docidentifier type='X'>#{file}</docidentifier>"
169
+ end
170
+
171
+ # update crossrefences to other documents, to include disambiguating document suffix on id
172
+ def update_anchors(bib, docxml, _id) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
173
+ docid = bib&.at(ns("./docidentifier"))&.text
174
+ docxml.xpath("//xmlns:eref[@citeas = '#{docid}']").each do |e|
175
+ if @files[docid]
176
+ update_anchor_loc(bib, e, docid)
177
+ else
178
+ e << "<strong>** Unresolved reference to document #{docid}, id #{e['bibitemid']}</strong>"
179
+ end
180
+ end
181
+ end
182
+
183
+ def update_anchor_loc(bib, e, docid)
184
+ loc = e.at(ns(".//locality[@type = 'anchor']")) or return update_anchor_create_loc(bib, e, docid)
185
+ document_suffix = Metanorma::Utils::to_ncname(docid)
186
+ ref = loc.at(ns("./referenceFrom")) || return
187
+ anchor = "#{ref.text}_#{document_suffix}"
188
+ return unless @files[docid][:anchors].inject([]) { |m, (_, x)| m+= x.values }.include?(anchor)
189
+ ref.content = anchor
190
+ end
191
+
192
+ # if there is a crossref to another document, with no anchor, retrieve the
193
+ # anchor given the locality, and insert it into the crossref
194
+ def update_anchor_create_loc(bib, e, docid)
195
+ ins = e.at(ns("./localityStack")) || return
196
+ type = ins&.at(ns("./locality/@type"))&.text
197
+ ref = ins&.at(ns("./locality/referenceFrom"))&.text
198
+ (anchor = @files[docid][:anchors][type][ref]) || return
199
+ ref_from = Nokogiri::XML::Node.new "referenceFrom", bib
200
+ ref_from.content = anchor.sub(/^_/, "")
201
+ locality = Nokogiri::XML::Node.new "locality", bib
202
+ locality[:type] = "anchor"
203
+ locality.add_child ref_from
204
+ ins << locality
205
+ end
206
+
207
+ # compile and output individual file in collection
208
+ def file_compile(f, filename, identifier)
209
+ # warn "metanorma compile -x html #{f.path}"
210
+ c = Compile.new
211
+ c.compile f.path, { format: :asciidoc, extension_keys: @format }.merge(@compile_options)
212
+ @files[identifier][:outputs] = {}
213
+ @format.each do |e|
214
+ ext = c.processor.output_formats[e]
215
+ fn = File.basename(filename).sub(/(?<=\.)[^\.]+$/, ext.to_s)
216
+ FileUtils.mv f.path.sub(/\.xml$/, ".#{ext}"), File.join(@outdir, fn)
217
+ @files[identifier][:outputs][e] = File.join(@outdir, fn)
218
+ end
219
+ end
220
+
221
+ # gather internal bibitem references
222
+ def gather_internal_refs
223
+ @files.each_with_object({}) do |(identifier, x), refs|
224
+ file, _ = targetfile(x, true)
225
+ Nokogiri::XML(file).xpath(ns("//bibitem[@type = 'internal']/docidentifier[@type = 'repository']")).each do |d|
226
+ a = d.text.split(%r{/}, 2)
227
+ a.size > 1 or next
228
+ refs[a[0]] ||= {}
229
+ refs[a[0]][a[1]] = true
230
+ end
231
+ end
232
+ end
233
+
234
+ # resolve file location for the target of each internal reference
235
+ def locate_internal_refs
236
+ refs = gather_internal_refs
237
+ @files.each do |identifier, x|
238
+ file, filename = targetfile(x, true)
239
+ docxml = Nokogiri::XML(file)
240
+ refs.each do |schema, ids|
241
+ ids.keys.each do |id|
242
+ docxml.at(ns("//*[@id = '#{id}'][@type = '#{schema}']")) and
243
+ refs[schema][id] = identifier
244
+ end
245
+ end
246
+ end
247
+ refs.each do |schema, ids|
248
+ ids.each do |id, key|
249
+ key == true and refs[schema][id] = "Missing:#{schema}:#{id}"
250
+ end
251
+ end
252
+ refs
253
+ end
254
+
255
+ # process each file in the collection
256
+ # files are held in memory, and altered as postprocessing
257
+ def files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
258
+ internal_refs = locate_internal_refs
259
+ @files.each do |identifier, x|
260
+ file, filename = targetfile(x, true)
261
+ file = update_xrefs(file, identifier, internal_refs)
262
+ Tempfile.open(["collection", ".xml"], encoding: "utf-8") do |f|
263
+ f.write(file)
264
+ f.close
265
+ file_compile(f, filename, identifier)
266
+ end
267
+ end
268
+ end
269
+ end
270
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "isodoc"
4
+ require_relative "./collection_fileprocess"
4
5
 
5
6
  module Metanorma
6
7
  # XML collection renderer
@@ -33,6 +34,8 @@ module Metanorma
33
34
  @outdir = options[:output_folder]
34
35
  @coverpage = options[:coverpage]
35
36
  @format = options[:format]
37
+ @compile_options = options[:compile] || {}
38
+ @log = options[:log]
36
39
 
37
40
  # list of files in the collection
38
41
  @files = read_files folder
@@ -113,42 +116,6 @@ module Metanorma
113
116
  IsoDoc::Convert.new({}).ns(xpath)
114
117
  end
115
118
 
116
- # hash for each document in collection of document identifier to:
117
- # document reference (fileref or id), type of document reference,
118
- # and bibdata entry for that file
119
- # @param path [String] path to collection
120
- # @return [Hash{String=>Hash}]
121
- def read_files(path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
122
- files = {}
123
- @xml.xpath(ns("//docref")).each do |d|
124
- identifier = d.at(ns("./identifier")).text
125
- files[identifier] = if d["fileref"]
126
- { type: "fileref",
127
- ref: File.join(path, d["fileref"]) }
128
- else { type: "id", ref: d["id"] }
129
- end
130
- file, _filename = targetfile(files[identifier], true)
131
- xml = Nokogiri::XML(file)
132
- files[identifier][:anchors] = read_anchors(xml)
133
- files[identifier][:bibdata] = xml.at(ns("//bibdata"))
134
- end
135
- files
136
- end
137
-
138
- # map locality type and label (e.g. "clause" "1") to id = anchor for
139
- # a document
140
- def read_anchors(xml)
141
- ret = {}
142
- xrefs = @isodoc.xref_init(@lang, @script, @isodoc, @isodoc.i18n, {})
143
- xrefs.parse xml
144
- xrefs.get.each do |k, v|
145
- v[:label] && v[:type] || next
146
- ret[v[:type]] ||= {}
147
- ret[v[:type]][v[:label]] = k
148
- end
149
- ret
150
- end
151
-
152
119
  # populate liquid template of ARGV[1] with metadata extracted from
153
120
  # collection manifest
154
121
  def coverpage
@@ -208,120 +175,6 @@ module Metanorma
208
175
  end.doc.root.to_html
209
176
  end
210
177
 
211
- # return file contents + output filename for each file in the collection,
212
- # given a docref entry
213
- # @param data [Hash]
214
- # @param read [Boolean]
215
- # @return [Array<String, nil>]
216
- def targetfile(data, read = false)
217
- if data[:type] == "fileref" then ref_file data[:ref], read
218
- else xml_file data[:id], read
219
- end
220
- end
221
-
222
- # @param ref [String]
223
- # @param read [Boolean]
224
- # @return [Array<String, nil>]
225
- def ref_file(ref, read)
226
- file = File.read(ref, encoding: "utf-8") if read
227
- filename = ref.sub(/\.xml$/, ".html")
228
- [file, filename]
229
- end
230
-
231
- # @param id [String]
232
- # @param read [Boolean]
233
- # @return [Array<String, nil>]
234
- def xml_file(id, read)
235
- file = @xml.at(ns("//doc-container[@id = '#{id}']")).to_xml if read
236
- filename = id + ".html"
237
- [file, filename]
238
- end
239
-
240
- # @param bib [Nokogiri::XML::Element]
241
- # @param identifier [String]
242
- def update_bibitem(bib, identifier) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
243
- docid = bib&.at(ns("./docidentifier"))&.text
244
- unless @files[docid]
245
- warn "Cannot find crossreference to document #{docid} in document "\
246
- "#{identifier}!"
247
- abort
248
- end
249
- id = bib["id"]
250
- newbib = bib.replace(@files[docid][:bibdata])
251
- newbib.name = "bibitem"
252
- newbib["id"] = id
253
- newbib&.at(ns("./ext"))&.remove
254
- _file, url = targetfile(@files[docid], false)
255
- uri_node = Nokogiri::XML::Node.new "uri", newbib
256
- uri_node[:type] = "citation"
257
- uri_node.content = url
258
- newbib.at(ns("./docidentifier")).previous = uri_node
259
- end
260
-
261
- # TODO: update crossreferences to other files in the selection
262
- # repo(current-metanorma-collection/ISO 17301-1:2016)
263
- # replaced by
264
- # bibdata of "ISO 17301-1:2016" in situ as bibitem
265
- # Any erefs to that bibitem id are replaced with relative URL
266
- # Preferably with anchor, and is a job to realise dynamic lookup of
267
- # localities
268
- # @param file [String] XML content
269
- # @param identifier [String] docid
270
- # @return [String] XML content
271
- def update_xrefs(file, identifier)
272
- docxml = Nokogiri::XML(file)
273
- docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |b|
274
- docid = b&.at(ns("./docidentifier[@type = 'repository']"))&.text
275
- next unless docid && %r{^current-metanorma-collection/}.match(docid)
276
-
277
- update_bibitem(b, identifier)
278
- update_anchors(b, docxml, docid)
279
- end
280
- docxml.to_xml
281
- end
282
-
283
- # if there is a crossref to another document, with no anchor, retrieve the
284
- # anchor given the locality, and insert it into the crossref
285
- def update_anchors(bib, docxml, _id) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
286
- docid = bib&.at(ns("./docidentifier"))&.text
287
- docxml.xpath("//xmlns:eref[@citeas = '#{docid}']").each do |e|
288
- e.at(ns(".//locality[@type = 'anchor']")).nil? || next
289
- ins = e.at(ns("./localityStack")) || next
290
- type = ins&.at(ns("./locality/@type"))&.text
291
- ref = ins&.at(ns("./locality/referenceFrom"))&.text
292
- (anchor = @files[docid][:anchors][type][ref]) || next
293
- ref_from = Nokogiri::XML::Node.new "referenceFrom", bib
294
- ref_from.content = anchor.sub(/^_/, "")
295
- locality = Nokogiri::XML::Node.new "locality", bib
296
- locality[:type] = "anchor"
297
- locality.add_child ref_from
298
- ins << locality
299
- end
300
- end
301
-
302
- # process each file in the collection
303
- # files are held in memory, and altered as postprocessing
304
- def files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
305
- @files.each do |identifier, x|
306
- file, filename = targetfile(x, true)
307
- file = update_xrefs(file, identifier)
308
- Tempfile.open(["collection", ".xml"], encoding: "utf-8") do |f|
309
- f.write(file)
310
- f.close
311
- # warn "metanorma compile -x html #{f.path}"
312
- c = Compile.new
313
- c.compile f.path, format: :asciidoc, extension_keys: @format
314
- @files[identifier][:outputs] = {}
315
- @format.each do |e|
316
- ext = c.processor.output_formats[e]
317
- fn = File.basename(filename).sub(/(?<=\.)[^\.]+$/, ext.to_s)
318
- FileUtils.mv f.path.sub(/\.xml$/, ".#{ext}"), File.join(@outdir, fn)
319
- @files[identifier][:outputs][e] = File.join(@outdir, fn)
320
- end
321
- end
322
- end
323
- end
324
-
325
178
  private
326
179
 
327
180
  # @param options [Hash]
@@ -331,7 +184,6 @@ module Metanorma
331
184
  raise ArgumentError, "Need to specify formats (xml,html,pdf,doc)"
332
185
  end
333
186
  return if !options[:format].include?(:html) || options[:coverpage]
334
-
335
187
  raise ArgumentError, "Need to specify a coverpage to render HTML"
336
188
  end
337
189
  end
@@ -2,6 +2,9 @@ require "fileutils"
2
2
  require "nokogiri"
3
3
  require "htmlentities"
4
4
 
5
+ require "fontist"
6
+ require "fontist/manifest/install"
7
+
5
8
  module Metanorma
6
9
  class Compile
7
10
  # @return [Array<String>]
@@ -21,6 +24,7 @@ module Metanorma
21
24
  (file, isodoc = process_input(filename, options)) or return nil
22
25
  relaton_export(isodoc, options)
23
26
  extract(isodoc, options[:extract], options[:extract_type])
27
+ install_fonts(options)
24
28
  process_extensions(extensions, file, isodoc, options)
25
29
  end
26
30
 
@@ -63,21 +67,32 @@ module Metanorma
63
67
  Util.log("[metanorma] Error: Please specify a standard type: #{@registry.supported_backends}.", :error)
64
68
  return nil
65
69
  end
70
+
66
71
  stdtype = options[:type].to_sym
72
+ metanorma_flavor = "metanorma-#{stdtype}"
73
+
67
74
  unless @registry.supported_backends.include? stdtype
68
- Util.log("[metanorma] Info: Loading `metanorma-#{stdtype}` gem for standard type `#{stdtype}`.", :info)
75
+ Util.log("[metanorma] Info: Loading `#{metanorma_flavor}` gem for standard type `#{stdtype}`.", :info)
69
76
  end
77
+
70
78
  begin
71
79
  require "metanorma-#{stdtype}"
72
- Util.log("[metanorma] Info: gem `metanorma-#{stdtype}` loaded.", :info)
80
+ Util.log("[metanorma] Info: gem `#{metanorma_flavor}` loaded.", :info)
81
+
82
+ rescue Gem::ConflictError
83
+ Util.log("[metanorma] Error: Couldn't resolve dependencies for `metanorma-#{stdtype}`, Please add it to your Gemfile and run bundle install first", :error)
84
+ return false
85
+
73
86
  rescue LoadError
74
- Util.log("[metanorma] Error: loading gem `metanorma-#{stdtype}` failed. Exiting.", :error)
87
+ Util.log("[metanorma] Error: loading gem `#{metanorma_flavor}` failed. Exiting.", :error)
75
88
  return false
76
89
  end
90
+
77
91
  unless @registry.supported_backends.include? stdtype
78
- Util.log("[metanorma] Error: The `metanorma-#{stdtype}` gem still doesn't support `#{stdtype}`. Exiting.", :error)
92
+ Util.log("[metanorma] Error: The `#{metanorma_flavor}` gem still doesn't support `#{stdtype}`. Exiting.", :error)
79
93
  return false
80
94
  end
95
+
81
96
  true
82
97
  end
83
98
 
@@ -246,19 +261,70 @@ module Metanorma
246
261
  @processor.output(isodoc, xml_name, outfilename, ext, isodoc_options)
247
262
  rescue StandardError => e
248
263
  puts e.message
264
+ puts e.backtrace.join("\n")
249
265
  end
250
266
  end
251
267
  wrap_html(options, file_extension, outfilename)
252
268
  end
253
269
  end
254
270
 
271
+ def install_fonts(options)
272
+ if options[:no_install_fonts]
273
+ Util.log("[fontist] Skip font installation because" \
274
+ " --no-install-fonts argument passed", :debug)
275
+ return
276
+ end
277
+
278
+ if !@processor.respond_to?(:fonts_manifest) || @processor.fonts_manifest.nil?
279
+ Util.log("[fontist] Skip font installation because font_manifest is missing", :debug)
280
+ return
281
+ end
282
+
283
+ @updated_formulas_repo = false
284
+
285
+ manifest = @processor.fonts_manifest
286
+ agree_to_terms = options[:agree_to_terms] || false
287
+ continue_without_fonts = options[:continue_without_fonts] || false
288
+
289
+ install_fonts_safe(manifest, agree_to_terms, continue_without_fonts)
290
+ end
291
+
255
292
  private
256
293
 
294
+ def install_fonts_safe(manifest, agree, continue)
295
+ fontist_install(manifest, agree)
296
+ rescue Fontist::Errors::LicensingError
297
+ if continue
298
+ Util.log("[fontist] Processing will continue without fonts installed", :debug)
299
+ else
300
+ Util.log("[fontist] Aborting without proper fonts installed," \
301
+ " make sure that you have set option --agree-to-terms", :fatal)
302
+ end
303
+ rescue Fontist::Errors::FontError => e
304
+ log_level = continue ? :warning : :fatal
305
+ Util.log("[fontist] '#{e.font}' font is not supported. " \
306
+ "Please report this issue at github.com/metanorma/metanorma-#{@processor.short}/issues" \
307
+ " to report this issue.", log_level)
308
+ rescue Fontist::Errors::FormulaIndexNotFoundError
309
+ Util.log("[fontist] Bug: formula index not found after 'fontist update'", :fatal) if @updated_formulas_repo
310
+ Util.log("[fontist] Missing formula index. Fetching it...", :debug)
311
+ Fontist::Formula.update_formulas_repo
312
+ @updated_formulas_repo = true
313
+ install_fonts_safe(manifest, agree, continue)
314
+ end
315
+
316
+ def fontist_install(manifest, agree)
317
+ Fontist::Manifest::Install.from_hash(
318
+ manifest,
319
+ confirmation: agree ? "yes" : "no"
320
+ )
321
+ end
322
+
257
323
  # @param options [Hash]
258
324
  # @return [String]
259
325
  def change_output_dir(options)
260
- if options[:"output-dir"]
261
- File.join options[:"output-dir"], File.basename(options[:filename])
326
+ if options[:output_dir]
327
+ File.join options[:output_dir], File.basename(options[:filename])
262
328
  else options[:filename]
263
329
  end
264
330
  end
@@ -15,7 +15,7 @@ module Metanorma
15
15
  attr_accessor :logs
16
16
 
17
17
  def initialize
18
- @logs ||= [:warning, :error]
18
+ @logs ||= [:warning, :error, :fatal]
19
19
  end
20
20
  end
21
21
 
@@ -14,7 +14,7 @@ module Metanorma
14
14
  header_footer: true,
15
15
  attributes: [
16
16
  "nodoc", "stem", "xrefstyle=short", "docfile=#{filename}",
17
- "output_dir=#{options[:"output-dir"]}"
17
+ "output_dir=#{options[:output_dir]}"
18
18
  ]
19
19
  }
20
20
  unless asciidoctor_validate(file, filename, out_opts)
@@ -6,6 +6,10 @@ module Metanorma
6
6
  if log_types.include?(type.to_s)
7
7
  puts(message)
8
8
  end
9
+
10
+ if type == :fatal
11
+ exit(1)
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -1,3 +1,3 @@
1
1
  module Metanorma
2
- VERSION = "1.2.0"
2
+ VERSION = "1.2.5"
3
3
  end
@@ -27,16 +27,19 @@ Gem::Specification.new do |spec|
27
27
  spec.add_runtime_dependency 'htmlentities'
28
28
  spec.add_runtime_dependency 'nokogiri'
29
29
  spec.add_runtime_dependency 'mn2pdf', "~> 1"
30
- # get relaton-cli to avoic circular reference with metanorma-standoc
30
+ spec.add_runtime_dependency 'metanorma-utils', "~> 1"
31
+ spec.add_runtime_dependency 'pry'
32
+ spec.add_runtime_dependency 'fontist', '~> 1.8'
33
+
34
+ # get relaton-cli to avoid circular reference with metanorma-standoc
31
35
  #spec.add_dependency "relaton-cli"
32
- #spec.add_dependency "metanorma-standoc", "~> 1.5.3"
36
+ #spec.add_dependency "metanorma-standoc"
33
37
 
34
38
  spec.add_development_dependency "rake", "~> 12.0"
35
39
  spec.add_development_dependency "rspec", "~> 3.0"
36
40
  spec.add_development_dependency "byebug", "~> 10.0"
37
41
  spec.add_development_dependency "rspec-command", "~> 1.0"
38
42
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
39
- spec.add_development_dependency "metanorma-iso", "~> 1.5.8"
43
+ spec.add_development_dependency "metanorma-iso", "~> 1.7.0"
40
44
  spec.add_development_dependency "sassc", "~> 2.4.0"
41
- #spec.add_development_dependency "isodoc", "~> 1.2.1"
42
45
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-25 00:00:00.000000000 Z
11
+ date: 2021-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -66,6 +66,48 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: metanorma-utils
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: fontist
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.8'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.8'
69
111
  - !ruby/object:Gem::Dependency
70
112
  name: rake
71
113
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +184,14 @@ dependencies:
142
184
  requirements:
143
185
  - - "~>"
144
186
  - !ruby/object:Gem::Version
145
- version: 1.5.8
187
+ version: 1.7.0
146
188
  type: :development
147
189
  prerelease: false
148
190
  version_requirements: !ruby/object:Gem::Requirement
149
191
  requirements:
150
192
  - - "~>"
151
193
  - !ruby/object:Gem::Version
152
- version: 1.5.8
194
+ version: 1.7.0
153
195
  - !ruby/object:Gem::Dependency
154
196
  name: sassc
155
197
  requirement: !ruby/object:Gem::Requirement
@@ -196,6 +238,7 @@ files:
196
238
  - lib/metanorma/asciidoctor_extensions.rb
197
239
  - lib/metanorma/asciidoctor_extensions/glob_include_processor.rb
198
240
  - lib/metanorma/collection.rb
241
+ - lib/metanorma/collection_fileprocess.rb
199
242
  - lib/metanorma/collection_manifest.rb
200
243
  - lib/metanorma/collection_renderer.rb
201
244
  - lib/metanorma/compile.rb