metanorma 1.2.4 → 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf7d6f99cb5eec27df20786b79a6932eb9e339c49072f4183b5cf9cb2ff747a3
4
- data.tar.gz: '049577c6c56eb8092765b8e3679ac7f0c8362f9129e787e4e7b923f5b3b61734'
3
+ metadata.gz: 72a5ff12b5b2793f4d8b8ced7b5cdc747a7b59cb938300f1e288150787d82951
4
+ data.tar.gz: 2a8f1a0fda7ceed680324833c18ab595d9de381aab36f3a5848040743029dfc8
5
5
  SHA512:
6
- metadata.gz: 7de4db35db282e2ec0665d79533885c31fd8a1b46493177d47a48920ab685e20d2f5a74e473b11d0dfa54b357b8d4e0be15d2908885a770b4e3ec518dd427975
7
- data.tar.gz: 8ef45f441c0129920575751b10bf3d86b132395d020794d39e69429e099ba6bcde65f1d5930dca240ad07209e12eddada6926bf56ec54322674ef8f47e07cedc
6
+ metadata.gz: d8ad8063e83a0d51494cb9d69f552676b27ac2022c9d477af6e12902bc2a9c7ceddc07d51965c594ab3ddf92839da6071d8a407836774e26c676b2fd3c9d584d
7
+ data.tar.gz: 18b394b6fd082a3072d543b120656ee181a68ce4c1a4cf3f0551f53719e07a96ec1b2140d61fac86e328370464e024df38872a0d85bc0b95aee588bb3e844982
@@ -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,7 @@ name: rake
4
4
 
5
5
  on:
6
6
  push:
7
- branches: [ master, main ]
7
+ branches: [ master, main ]
8
8
  tags: [ v* ]
9
9
  pull_request:
10
10
 
@@ -16,38 +16,28 @@ jobs:
16
16
  strategy:
17
17
  fail-fast: false
18
18
  matrix:
19
- ruby: [ '2.6', '2.5', '2.4' ]
19
+ ruby: [ '2.7', '2.6', '2.5', '2.4' ]
20
20
  os: [ ubuntu-latest, windows-latest, macos-latest ]
21
21
  experimental: [ false ]
22
22
  include:
23
- - ruby: '2.7'
23
+ - ruby: '3.0'
24
24
  os: 'ubuntu-latest'
25
25
  experimental: true
26
- - ruby: '2.7'
26
+ - ruby: '3.0'
27
27
  os: 'windows-latest'
28
28
  experimental: true
29
- - ruby: '2.7'
29
+ - ruby: '3.0'
30
30
  os: 'macos-latest'
31
31
  experimental: true
32
32
  steps:
33
- - uses: actions/checkout@master
33
+ - uses: actions/checkout@v2
34
+ with:
35
+ submodules: true
34
36
 
35
37
  - uses: ruby/setup-ruby@v1
36
38
  with:
37
39
  ruby-version: ${{ matrix.ruby }}
38
-
39
- - if: matrix.os == 'macos-latest'
40
- run: brew install autoconf automake libtool
41
-
42
- - uses: actions/cache@v2
43
- with:
44
- path: vendor/bundle
45
- key: bundle-${{ matrix.os }}-${{ matrix.ruby }}-${{ hashFiles('**/*.gemspec') }}
46
- restore-keys: bundle-${{ matrix.os }}-${{ matrix.ruby }}
47
-
48
- - run: bundle config set path 'vendor/bundle'
49
-
50
- - run: bundle install --jobs 4 --retry 3
40
+ bundler-cache: true
51
41
 
52
42
  - run: bundle exec rake
53
43
 
@@ -55,11 +45,9 @@ jobs:
55
45
  needs: rake
56
46
  runs-on: ubuntu-latest
57
47
  steps:
58
- - name: Trigger tests passed event
59
- uses: Sibz/github-status-action@v1
48
+ - uses: peter-evans/repository-dispatch@v1
60
49
  with:
61
- authToken: ${{ secrets.GITHUB_TOKEN }}
62
- context: 'tests-passed-successfully'
63
- description: 'Tests passed successfully'
64
- state: 'success'
65
- sha: ${{ github.event.pull_request.head.sha || github.sha }}
50
+ token: ${{ secrets.METANORMA_CI_PAT_TOKEN || secrets.GITHUB_TOKEN }}
51
+ repository: ${{ github.repository }}
52
+ event-type: notify
53
+ client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'
data/.gitignore CHANGED
@@ -20,3 +20,5 @@
20
20
  Gemfile.lock
21
21
  relaton/
22
22
  .vscode/
23
+
24
+ .rubocop-https--*
data/.rubocop.yml CHANGED
@@ -1,6 +1,14 @@
1
1
  # This project follows the Ribose OSS style guide.
2
2
  # https://github.com/riboseinc/oss-guides
3
3
  # All project-specific additions and overrides should be specified in this file.
4
-
5
4
  inherit_from:
6
5
  - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
6
+
7
+ # local repo-specific modifications
8
+
9
+ AllCops:
10
+ DisplayCopNames: false
11
+ StyleGuideCopsOnly: false
12
+ TargetRubyVersion: 2.4
13
+ Rails:
14
+ Enabled: true
@@ -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,292 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "isodoc"
4
+ require "metanorma-utils"
5
+
6
+ module Metanorma
7
+ # XML collection renderer
8
+ class CollectionRenderer
9
+ # hash for each document in collection of document identifier to:
10
+ # document reference (fileref or id), type of document reference,
11
+ # and bibdata entry for that file
12
+ # @param path [String] path to collection
13
+ # @return [Hash{String=>Hash}]
14
+ def read_files(path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
15
+ files = {}
16
+ @xml.xpath(ns("//docref")).each do |d|
17
+ identifier = d.at(ns("./identifier")).text
18
+ files[identifier] = if d["fileref"]
19
+ { type: "fileref",
20
+ ref: File.join(path, d["fileref"]) }
21
+ else { type: "id", ref: d["id"] }
22
+ end
23
+ file, _filename = targetfile(files[identifier], true)
24
+ xml = Nokogiri::XML(file)
25
+ add_document_suffix(identifier, xml)
26
+ files[identifier][:anchors] = read_anchors(xml)
27
+ files[identifier][:bibdata] = xml.at(ns("//bibdata"))
28
+ end
29
+ files
30
+ end
31
+
32
+ def add_suffix_to_attributes(doc, suffix, tag_name, attribute_name)
33
+ doc.xpath(ns("//#{tag_name}[@#{attribute_name}]")).each do |elem|
34
+ elem.attributes[attribute_name].value =
35
+ "#{elem.attributes[attribute_name].value}_#{suffix}"
36
+ end
37
+ end
38
+
39
+ def add_document_suffix(identifier, doc)
40
+ document_suffix = Metanorma::Utils::to_ncname(identifier)
41
+ [%w[* id],
42
+ %w[* bibitemid],
43
+ %w[review from],
44
+ %w[review to],
45
+ %w[index to],
46
+ %w[xref target],
47
+ %w[callout target]]
48
+ .each do |(tag_name, attribute_name)|
49
+ add_suffix_to_attributes(doc, document_suffix, tag_name, attribute_name)
50
+ end
51
+ end
52
+
53
+ # map locality type and label (e.g. "clause" "1") to id = anchor for
54
+ # a document
55
+ def read_anchors(xml)
56
+ ret = {}
57
+ xrefs = @isodoc.xref_init(@lang, @script, @isodoc, @isodoc.i18n, {})
58
+ xrefs.parse xml
59
+ xrefs.get.each do |k, v|
60
+ ret[v[:type]] ||= {}
61
+ index = v[:container] || v[:label].nil? || v[:label].empty? ?
62
+ UUIDTools::UUID.random_create.to_s : v[:label]
63
+ # Note: will only key clauses, which have unambiguous reference label in locality.
64
+ # Notes, examples etc with containers are just plunked agaisnt UUIDs, so that their
65
+ # IDs can at least be registered to be tracked as existing.
66
+ ret[v[:type]][index] = k
67
+ end
68
+ ret
69
+ end
70
+
71
+ # return file contents + output filename for each file in the collection,
72
+ # given a docref entry
73
+ # @param data [Hash]
74
+ # @param read [Boolean]
75
+ # @return [Array<String, nil>]
76
+ def targetfile(data, read = false)
77
+ if data[:type] == "fileref" then ref_file data[:ref], read
78
+ else xml_file data[:id], read
79
+ end
80
+ end
81
+
82
+ # @param ref [String]
83
+ # @param read [Boolean]
84
+ # @return [Array<String, nil>]
85
+ def ref_file(ref, read)
86
+ file = File.read(ref, encoding: "utf-8") if read
87
+ filename = ref.sub(/\.xml$/, ".html")
88
+ [file, filename]
89
+ end
90
+
91
+ # @param id [String]
92
+ # @param read [Boolean]
93
+ # @return [Array<String, nil>]
94
+ def xml_file(id, read)
95
+ file = @xml.at(ns("//doc-container[@id = '#{id}']")).to_xml if read
96
+ filename = id + ".html"
97
+ [file, filename]
98
+ end
99
+
100
+ # @param bib [Nokogiri::XML::Element]
101
+ # @param identifier [String]
102
+ def update_bibitem(bib, identifier) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
103
+ docid = bib&.at(ns("./docidentifier"))&.text
104
+ unless @files[docid]
105
+ error = "[metanorma] Cannot find crossreference to document #{docid} in document #{identifier}."
106
+ @log.add("Cross-References", nil, error)
107
+ Util.log(error, :warning)
108
+ return
109
+ end
110
+ id = bib["id"]
111
+ newbib = bib.replace(@files[docid][:bibdata])
112
+ newbib.name = "bibitem"
113
+ newbib["id"] = id
114
+ newbib["hidden"] = "true"
115
+ newbib&.at(ns("./ext"))&.remove
116
+ _file, url = targetfile(@files[docid], false)
117
+ uri_node = Nokogiri::XML::Node.new "uri", newbib
118
+ uri_node[:type] = "citation"
119
+ uri_node.content = url
120
+ newbib.at(ns("./docidentifier")).previous = uri_node
121
+ end
122
+
123
+ # Resolves direct links to other files in collection (repo(current-metanorma-collection/x),
124
+ # and indirect links to other files in collection (bibitem[@type = 'internal'] pointing to a file anchor
125
+ # in another file in the collection)
126
+ # @param file [String] XML content
127
+ # @param identifier [String] docid
128
+ # @param internal_refs [Hash{String=>Hash{String=>String}] schema name to anchor to filename
129
+ # @return [String] XML content
130
+ def update_xrefs(file, identifier, internal_refs)
131
+ docxml = Nokogiri::XML(file)
132
+ update_indirect_refs_to_docs(docxml, internal_refs)
133
+ add_document_suffix(identifier, docxml)
134
+ update_direct_refs_to_docs(docxml, identifier)
135
+ svgmap_resolve(datauri_encode(docxml))
136
+ docxml.xpath(ns("//references[not(./bibitem[not(@hidden) or @hidden = 'false'])]")).each do |f|
137
+ f["hidden"] = "true"
138
+ end
139
+ docxml.to_xml
140
+ end
141
+
142
+ def datauri_encode(docxml)
143
+ docxml.xpath(ns("//image")).each { |i| i["src"] = Metanorma::Utils::datauri(i["src"]) }
144
+ docxml
145
+ end
146
+
147
+ def svgmap_resolve(docxml)
148
+ isodoc = IsoDoc::Convert.new({})
149
+ docxml.xpath(ns("//svgmap//eref")).each do |e|
150
+ href = isodoc.eref_target(e)
151
+ next if href == "#" + e["bibitemid"]
152
+ if href.match(/^#/)
153
+ next unless docxml.at("//*[@id = '#{href.sub(/^#/, '')}']")
154
+ end
155
+ e["target"] = href.strip
156
+ e.name = "link"
157
+ e&.elements&.remove
158
+ end
159
+ Metanorma::Utils::svgmap_rewrite(docxml, "")
160
+ end
161
+
162
+ # repo(current-metanorma-collection/ISO 17301-1:2016)
163
+ # replaced by bibdata of "ISO 17301-1:2016" in situ as bibitem.
164
+ # Any erefs to that bibitem id are replaced with relative URL
165
+ # Preferably with anchor, and is a job to realise dynamic lookup of localities.
166
+ def update_direct_refs_to_docs(docxml, identifier)
167
+ docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |b|
168
+ docid = b&.at(ns("./docidentifier[@type = 'repository']"))&.text
169
+ next unless docid && %r{^current-metanorma-collection/}.match(docid)
170
+ update_bibitem(b, identifier)
171
+ update_anchors(b, docxml, docid)
172
+ end
173
+ end
174
+
175
+ # Resolve erefs to a container of ids in another doc, to an anchor eref (direct link)
176
+ def update_indirect_refs_to_docs(docxml, internal_refs)
177
+ internal_refs.each do |schema, ids|
178
+ ids.each do |id, file|
179
+ update_indirect_refs_to_docs1(docxml, schema, id, file)
180
+ end
181
+ end
182
+ end
183
+
184
+ def update_indirect_refs_to_docs1(docxml, schema, id, file)
185
+ docxml.xpath(ns("//eref[@bibitemid = '#{schema}_#{id}']")).each do |e|
186
+ e["citeas"] = file
187
+ end
188
+ docid = docxml.at(ns("//bibitem[@id = '#{schema}_#{id}']/docidentifier[@type = 'repository']")) or return
189
+ docid.children = "current-metanorma-collection/#{file}"
190
+ docid.previous = "<docidentifier type='X'>#{file}</docidentifier>"
191
+ end
192
+
193
+ # update crossrefences to other documents, to include disambiguating document suffix on id
194
+ def update_anchors(bib, docxml, _id) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
195
+ docid = bib&.at(ns("./docidentifier"))&.text
196
+ docxml.xpath("//xmlns:eref[@citeas = '#{docid}']").each do |e|
197
+ if @files[docid]
198
+ update_anchor_loc(bib, e, docid)
199
+ else
200
+ e << "<strong>** Unresolved reference to document #{docid}, id #{e['bibitemid']}</strong>"
201
+ end
202
+ end
203
+ end
204
+
205
+ def update_anchor_loc(bib, e, docid)
206
+ loc = e.at(ns(".//locality[@type = 'anchor']")) or return update_anchor_create_loc(bib, e, docid)
207
+ document_suffix = Metanorma::Utils::to_ncname(docid)
208
+ ref = loc.at(ns("./referenceFrom")) || return
209
+ anchor = "#{ref.text}_#{document_suffix}"
210
+ return unless @files[docid][:anchors].inject([]) { |m, (_, x)| m+= x.values }.include?(anchor)
211
+ ref.content = anchor
212
+ end
213
+
214
+ # if there is a crossref to another document, with no anchor, retrieve the
215
+ # anchor given the locality, and insert it into the crossref
216
+ def update_anchor_create_loc(bib, e, docid)
217
+ ins = e.at(ns("./localityStack")) || return
218
+ type = ins&.at(ns("./locality/@type"))&.text
219
+ ref = ins&.at(ns("./locality/referenceFrom"))&.text
220
+ (anchor = @files[docid][:anchors][type][ref]) || return
221
+ ref_from = Nokogiri::XML::Node.new "referenceFrom", bib
222
+ ref_from.content = anchor.sub(/^_/, "")
223
+ locality = Nokogiri::XML::Node.new "locality", bib
224
+ locality[:type] = "anchor"
225
+ locality.add_child ref_from
226
+ ins << locality
227
+ end
228
+
229
+ # compile and output individual file in collection
230
+ def file_compile(f, filename, identifier)
231
+ # warn "metanorma compile -x html #{f.path}"
232
+ c = Compile.new
233
+ c.compile f.path, { format: :asciidoc, extension_keys: @format }.merge(@compile_options)
234
+ @files[identifier][:outputs] = {}
235
+ @format.each do |e|
236
+ ext = c.processor.output_formats[e]
237
+ fn = File.basename(filename).sub(/(?<=\.)[^\.]+$/, ext.to_s)
238
+ FileUtils.mv f.path.sub(/\.xml$/, ".#{ext}"), File.join(@outdir, fn)
239
+ @files[identifier][:outputs][e] = File.join(@outdir, fn)
240
+ end
241
+ end
242
+
243
+ # gather internal bibitem references
244
+ def gather_internal_refs
245
+ @files.each_with_object({}) do |(identifier, x), refs|
246
+ file, _ = targetfile(x, true)
247
+ Nokogiri::XML(file).xpath(ns("//bibitem[@type = 'internal']/docidentifier[@type = 'repository']")).each do |d|
248
+ a = d.text.split(%r{/}, 2)
249
+ a.size > 1 or next
250
+ refs[a[0]] ||= {}
251
+ refs[a[0]][a[1]] = true
252
+ end
253
+ end
254
+ end
255
+
256
+ # resolve file location for the target of each internal reference
257
+ def locate_internal_refs
258
+ refs = gather_internal_refs
259
+ @files.each do |identifier, x|
260
+ file, filename = targetfile(x, true)
261
+ docxml = Nokogiri::XML(file)
262
+ refs.each do |schema, ids|
263
+ ids.keys.each do |id|
264
+ n = docxml.at("//*[@id = '#{id}']") and n.at("./ancestor-or-self::*[@type = '#{schema}']") and
265
+ refs[schema][id] = identifier
266
+ end
267
+ end
268
+ end
269
+ refs.each do |schema, ids|
270
+ ids.each do |id, key|
271
+ key == true and refs[schema][id] = "Missing:#{schema}:#{id}"
272
+ end
273
+ end
274
+ refs
275
+ end
276
+
277
+ # process each file in the collection
278
+ # files are held in memory, and altered as postprocessing
279
+ def files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
280
+ internal_refs = locate_internal_refs
281
+ @files.each do |identifier, x|
282
+ file, filename = targetfile(x, true)
283
+ file = update_xrefs(file, identifier, internal_refs)
284
+ Tempfile.open(["collection", ".xml"], encoding: "utf-8") do |f|
285
+ f.write(file)
286
+ f.close
287
+ file_compile(f, filename, identifier)
288
+ end
289
+ end
290
+ end
291
+ end
292
+ 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
@@ -34,6 +35,7 @@ module Metanorma
34
35
  @coverpage = options[:coverpage]
35
36
  @format = options[:format]
36
37
  @compile_options = options[:compile] || {}
38
+ @log = options[:log]
37
39
 
38
40
  # list of files in the collection
39
41
  @files = read_files folder
@@ -114,68 +116,6 @@ module Metanorma
114
116
  IsoDoc::Convert.new({}).ns(xpath)
115
117
  end
116
118
 
117
- # hash for each document in collection of document identifier to:
118
- # document reference (fileref or id), type of document reference,
119
- # and bibdata entry for that file
120
- # @param path [String] path to collection
121
- # @return [Hash{String=>Hash}]
122
- def read_files(path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
123
- files = {}
124
- @xml.xpath(ns("//docref")).each do |d|
125
- identifier = d.at(ns("./identifier")).text
126
- files[identifier] = if d["fileref"]
127
- { type: "fileref",
128
- ref: File.join(path, d["fileref"]) }
129
- else { type: "id", ref: d["id"] }
130
- end
131
- file, _filename = targetfile(files[identifier], true)
132
- xml = Nokogiri::XML(file)
133
- add_document_suffix(identifier, xml)
134
- files[identifier][:anchors] = read_anchors(xml)
135
- files[identifier][:bibdata] = xml.at(ns("//bibdata"))
136
- end
137
- files
138
- end
139
-
140
- def add_suffix_to_attributes(doc, suffix, tag_name, attribute_name)
141
- doc.xpath(ns("//#{tag_name}[@#{attribute_name}]")).each do |elem|
142
- elem.attributes[attribute_name].value =
143
- "#{elem.attributes[attribute_name].value}_#{suffix}"
144
- end
145
- end
146
-
147
- def add_document_suffix(identifier, doc)
148
- document_suffix = Asciidoctor::Standoc::Cleanup.to_ncname(identifier)
149
- [%w[* id],
150
- %w[* bibitemid],
151
- %w[review from],
152
- %w[review to],
153
- %w[index to],
154
- %w[xref target],
155
- %w[callout target]]
156
- .each do |(tag_name, attribute_name)|
157
- add_suffix_to_attributes(doc, document_suffix, tag_name, attribute_name)
158
- end
159
- end
160
-
161
- # map locality type and label (e.g. "clause" "1") to id = anchor for
162
- # a document
163
- def read_anchors(xml)
164
- ret = {}
165
- xrefs = @isodoc.xref_init(@lang, @script, @isodoc, @isodoc.i18n, {})
166
- xrefs.parse xml
167
- xrefs.get.each do |k, v|
168
- ret[v[:type]] ||= {}
169
- index = v[:container] || v[:label].nil? || v[:label].empty? ?
170
- UUIDTools::UUID.random_create.to_s : v[:label]
171
- # Note: will only key clauses, which have unambiguous reference label in locality.
172
- # Notes, examples etc with containers are just plunked agaisnt UUIDs, so that their
173
- # IDs can at least be registered to be tracked as existing.
174
- ret[v[:type]][index] = k
175
- end
176
- ret
177
- end
178
-
179
119
  # populate liquid template of ARGV[1] with metadata extracted from
180
120
  # collection manifest
181
121
  def coverpage
@@ -235,132 +175,6 @@ module Metanorma
235
175
  end.doc.root.to_html
236
176
  end
237
177
 
238
- # return file contents + output filename for each file in the collection,
239
- # given a docref entry
240
- # @param data [Hash]
241
- # @param read [Boolean]
242
- # @return [Array<String, nil>]
243
- def targetfile(data, read = false)
244
- if data[:type] == "fileref" then ref_file data[:ref], read
245
- else xml_file data[:id], read
246
- end
247
- end
248
-
249
- # @param ref [String]
250
- # @param read [Boolean]
251
- # @return [Array<String, nil>]
252
- def ref_file(ref, read)
253
- file = File.read(ref, encoding: "utf-8") if read
254
- filename = ref.sub(/\.xml$/, ".html")
255
- [file, filename]
256
- end
257
-
258
- # @param id [String]
259
- # @param read [Boolean]
260
- # @return [Array<String, nil>]
261
- def xml_file(id, read)
262
- file = @xml.at(ns("//doc-container[@id = '#{id}']")).to_xml if read
263
- filename = id + ".html"
264
- [file, filename]
265
- end
266
-
267
- # @param bib [Nokogiri::XML::Element]
268
- # @param identifier [String]
269
- def update_bibitem(bib, identifier) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
270
- docid = bib&.at(ns("./docidentifier"))&.text
271
- unless @files[docid]
272
- warn "Cannot find crossreference to document #{docid} in document "\
273
- "#{identifier}!"
274
- abort
275
- end
276
- id = bib["id"]
277
- newbib = bib.replace(@files[docid][:bibdata])
278
- newbib.name = "bibitem"
279
- newbib["id"] = id
280
- newbib["hidden"] = "true"
281
- newbib&.at(ns("./ext"))&.remove
282
- _file, url = targetfile(@files[docid], false)
283
- uri_node = Nokogiri::XML::Node.new "uri", newbib
284
- uri_node[:type] = "citation"
285
- uri_node.content = url
286
- newbib.at(ns("./docidentifier")).previous = uri_node
287
- end
288
-
289
- # TODO: update crossreferences to other files in the selection
290
- # repo(current-metanorma-collection/ISO 17301-1:2016)
291
- # replaced by
292
- # bibdata of "ISO 17301-1:2016" in situ as bibitem
293
- # Any erefs to that bibitem id are replaced with relative URL
294
- # Preferably with anchor, and is a job to realise dynamic lookup of
295
- # localities
296
- # @param file [String] XML content
297
- # @param identifier [String] docid
298
- # @return [String] XML content
299
- def update_xrefs(file, identifier)
300
- docxml = Nokogiri::XML(file)
301
- add_document_suffix(identifier, docxml)
302
- docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |b|
303
- docid = b&.at(ns("./docidentifier[@type = 'repository']"))&.text
304
- next unless docid && %r{^current-metanorma-collection/}.match(docid)
305
- update_bibitem(b, identifier)
306
- update_anchors(b, docxml, docid)
307
- end
308
- docxml.xpath(ns("//references[not(./bibitem[not(@hidden) or @hidden = 'false'])]")).each do |f|
309
- f["hidden"] = "true"
310
- end
311
- docxml.to_xml
312
- end
313
-
314
- # if there is a crossref to another document, with no anchor, retrieve the
315
- # anchor given the locality, and insert it into the crossref
316
- def update_anchors(bib, docxml, _id) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
317
- docid = bib&.at(ns("./docidentifier"))&.text
318
- document_suffix = Asciidoctor::Standoc::Cleanup.to_ncname(docid)
319
- docxml.xpath("//xmlns:eref[@citeas = '#{docid}']").each do |e|
320
- if loc = e.at(ns(".//locality[@type = 'anchor']"))
321
- ref = loc.at(ns("./referenceFrom")) || next
322
- anchor = "#{ref.text}_#{document_suffix}"
323
- next unless @files[docid][:anchors].inject([]) { |m, (_, x)| m+= x.values }.include?(anchor)
324
- ref.content = anchor
325
- else
326
- ins = e.at(ns("./localityStack")) || next
327
- type = ins&.at(ns("./locality/@type"))&.text
328
- ref = ins&.at(ns("./locality/referenceFrom"))&.text
329
- (anchor = @files[docid][:anchors][type][ref]) || next
330
- ref_from = Nokogiri::XML::Node.new "referenceFrom", bib
331
- ref_from.content = anchor.sub(/^_/, "")
332
- locality = Nokogiri::XML::Node.new "locality", bib
333
- locality[:type] = "anchor"
334
- locality.add_child ref_from
335
- ins << locality
336
- end
337
- end
338
- end
339
-
340
- # process each file in the collection
341
- # files are held in memory, and altered as postprocessing
342
- def files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
343
- @files.each do |identifier, x|
344
- file, filename = targetfile(x, true)
345
- file = update_xrefs(file, identifier)
346
- Tempfile.open(["collection", ".xml"], encoding: "utf-8") do |f|
347
- f.write(file)
348
- f.close
349
- # warn "metanorma compile -x html #{f.path}"
350
- c = Compile.new
351
- options = { format: :asciidoc, extension_keys: @format }.merge @compile_options
352
- c.compile f.path, options
353
- @files[identifier][:outputs] = {}
354
- @format.each do |e|
355
- ext = c.processor.output_formats[e]
356
- fn = File.basename(filename).sub(/(?<=\.)[^\.]+$/, ext.to_s)
357
- FileUtils.mv f.path.sub(/\.xml$/, ".#{ext}"), File.join(@outdir, fn)
358
- @files[identifier][:outputs][e] = File.join(@outdir, fn)
359
- end
360
- end
361
- end
362
- end
363
-
364
178
  private
365
179
 
366
180
  # @param options [Hash]
@@ -370,7 +184,6 @@ module Metanorma
370
184
  raise ArgumentError, "Need to specify formats (xml,html,pdf,doc)"
371
185
  end
372
186
  return if !options[:format].include?(:html) || options[:coverpage]
373
-
374
187
  raise ArgumentError, "Need to specify a coverpage to render HTML"
375
188
  end
376
189
  end
@@ -1,6 +1,7 @@
1
1
  require "fileutils"
2
2
  require "nokogiri"
3
3
  require "htmlentities"
4
+ require "yaml"
4
5
 
5
6
  require "fontist"
6
7
  require "fontist/manifest/install"
@@ -251,6 +252,10 @@ module Metanorma
251
252
  isodoc_options[:datauriimage] = true if options[:datauriimage]
252
253
  file_extension = @processor.output_formats[ext]
253
254
  outfilename = f.sub(/\.[^.]+$/, ".#{file_extension}")
255
+ if ext == :pdf
256
+ font_locations = fontist_font_locations(options)
257
+ isodoc_options[:mn2pdf] = { font_manifest_file: font_locations.path } if font_locations
258
+ end
254
259
  if ext == :rxl
255
260
  options[:relaton] = outfilename
256
261
  relaton_export(isodoc, options)
@@ -264,62 +269,105 @@ module Metanorma
264
269
  puts e.backtrace.join("\n")
265
270
  end
266
271
  end
272
+ if ext == :pdf
273
+ # font_locations.unlink
274
+ end
267
275
  wrap_html(options, file_extension, outfilename)
268
276
  end
269
277
  end
270
278
 
271
279
  def install_fonts(options)
272
- if options[:"no-install-fonts"]
280
+ if options[:no_install_fonts]
273
281
  Util.log("[fontist] Skip font installation because" \
274
282
  " --no-install-fonts argument passed", :debug)
275
283
  return
276
284
  end
277
285
 
278
- if !@processor.respond_to?(:fonts_manifest) || @processor.fonts_manifest.nil?
286
+ if missing_fontist_manifest?
279
287
  Util.log("[fontist] Skip font installation because font_manifest is missing", :debug)
280
288
  return
281
289
  end
282
290
 
291
+ @updated_formulas_repo = false
292
+
283
293
  manifest = @processor.fonts_manifest
284
- agree_to_terms = options[:"agree-to-terms"] || false
285
- continue_without_fonts = options[:"continue-without-fonts"] || false
294
+ agree_to_terms = options[:agree_to_terms] || false
295
+ continue_without_fonts = options[:continue_without_fonts] || false
296
+ no_progress = options[:no_progress] || false
286
297
 
287
- install_fonts_safe(manifest, agree_to_terms, continue_without_fonts)
298
+ install_fonts_safe(manifest, agree_to_terms, continue_without_fonts, no_progress)
288
299
  end
289
300
 
290
301
  private
291
302
 
292
- def install_fonts_safe(manifest, agree, continue)
293
- fontist_install(manifest, agree)
303
+ def install_fonts_safe(manifest, agree, continue, no_progress)
304
+ fontist_install(manifest, agree, no_progress)
294
305
  rescue Fontist::Errors::LicensingError
295
306
  if continue
296
- Util.log("[fontist] Processing will continue without fonts installed", :debug)
307
+ Util.log(
308
+ "[fontist] Processing will continue without fonts installed",
309
+ :debug
310
+ )
297
311
  else
298
312
  Util.log("[fontist] Aborting without proper fonts installed," \
299
313
  " make sure that you have set option --agree-to-terms", :fatal)
300
314
  end
301
315
  rescue Fontist::Errors::FontError => e
316
+ log_level = continue ? :warning : :fatal
302
317
  Util.log("[fontist] '#{e.font}' font is not supported. " \
303
- "Please report this issue at github.com/metanorma/metanorma-#{@processor.short}/issues" \
304
- " to report this issue.", :info)
318
+ "Please report this issue at github.com/metanorma/metanorma-"\
319
+ "#{@processor.short}/issues to report this issue.", log_level)
305
320
  rescue Fontist::Errors::FormulaIndexNotFoundError
321
+ if @updated_formulas_repo
322
+ Util.log(
323
+ "[fontist] Bug: formula index not found after 'fontist update'",
324
+ :fatal
325
+ )
326
+ end
306
327
  Util.log("[fontist] Missing formula index. Fetching it...", :debug)
307
328
  Fontist::Formula.update_formulas_repo
308
- fontist_install(manifest, agree)
329
+ @updated_formulas_repo = true
330
+ install_fonts_safe(manifest, agree, continue, no_progress)
309
331
  end
310
332
 
311
- def fontist_install(manifest, agree)
333
+ def fontist_install(manifest, agree, no_progress)
312
334
  Fontist::Manifest::Install.from_hash(
313
335
  manifest,
314
- confirmation: agree ? "yes" : "no"
336
+ confirmation: agree ? "yes" : "no",
337
+ no_progress: no_progress
315
338
  )
316
339
  end
317
340
 
341
+ def fontist_font_locations(options)
342
+ return nil if missing_fontist_manifest? || options[:no_install_fonts]
343
+
344
+ dump_fontist_manifest_locations(@processor.fonts_manifest)
345
+ rescue Fontist::Errors::FormulaIndexNotFoundError
346
+ raise unless options[:continue_without_fonts]
347
+
348
+ nil
349
+ end
350
+
351
+ def dump_fontist_manifest_locations(manifest)
352
+ location_manifest = Fontist::Manifest::Locations.from_hash(
353
+ manifest
354
+ )
355
+ location_manifest_file = Tempfile.new(["fontist_locations", ".yml"])
356
+ location_manifest_file.write location_manifest.to_yaml
357
+ location_manifest_file.flush
358
+
359
+ location_manifest_file
360
+ end
361
+
362
+ def missing_fontist_manifest?
363
+ !@processor.respond_to?(:fonts_manifest) || @processor.fonts_manifest.nil?
364
+ end
365
+
318
366
  # @param options [Hash]
319
367
  # @return [String]
320
368
  def change_output_dir(options)
321
- if options[:"output-dir"]
322
- File.join options[:"output-dir"], File.basename(options[:filename])
369
+ if options[:output_dir]
370
+ File.join options[:output_dir], File.basename(options[:filename])
323
371
  else options[:filename]
324
372
  end
325
373
  end
@@ -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)
@@ -70,11 +70,13 @@ module Metanorma
70
70
  /\n:title-font: (?<titlefont>[^\n]+)\n/ =~ headerextract
71
71
  /\n:i18nyaml: (?<i18nyaml>[^\n]+)\n/ =~ headerextract
72
72
  /\n:htmlstylesheet: (?<htmlstylesheet>[^\n]+)\n/ =~ headerextract
73
+ /\n:htmlstylesheet-override: (?<htmlstylesheet_override>[^\n]+)\n/ =~ headerextract
73
74
  /\n:htmlcoverpage: (?<htmlcoverpage>[^\n]+)\n/ =~ headerextract
74
75
  /\n:htmlintropage: (?<htmlintropage>[^\n]+)\n/ =~ headerextract
75
76
  /\n:scripts: (?<scripts>[^\n]+)\n/ =~ headerextract
76
77
  /\n:scripts-pdf: (?<scripts_pdf>[^\n]+)\n/ =~ headerextract
77
78
  /\n:wordstylesheet: (?<wordstylesheet>[^\n]+)\n/ =~ headerextract
79
+ /\n:wordstylesheet-override: (?<wordstylesheet_override>[^\n]+)\n/ =~ headerextract
78
80
  /\n:standardstylesheet: (?<standardstylesheet>[^\n]+)\n/ =~ headerextract
79
81
  /\n:header: (?<header>[^\n]+)\n/ =~ headerextract
80
82
  /\n:wordcoverpage: (?<wordcoverpage>[^\n]+)\n/ =~ headerextract
@@ -102,11 +104,13 @@ module Metanorma
102
104
  titlefont: defined?(titlefont) ? titlefont : nil,
103
105
  i18nyaml: defined?(i18nyaml) ? i18nyaml : nil,
104
106
  htmlstylesheet: defined?(htmlstylesheet) ? htmlstylesheet : nil,
107
+ htmlstylesheet_override: defined?(htmlstylesheet_override) ? htmlstylesheet_override : nil,
105
108
  htmlcoverpage: defined?(htmlcoverpage) ? htmlcoverpage : nil,
106
109
  htmlintropage: defined?(htmlintropage) ? htmlintropage : nil,
107
110
  scripts: defined?(scripts) ? scripts : nil,
108
111
  scripts_pdf: defined?(scripts_pdf) ? scripts_pdf : nil,
109
112
  wordstylesheet: defined?(wordstylesheet) ? wordstylesheet : nil,
113
+ wordstylesheet_override: defined?(wordstylesheet_override) ? wordstylesheet_override : nil,
110
114
  standardstylesheet: defined?(standardstylesheet) ? standardstylesheet : nil,
111
115
  header: defined?(header) ? header : nil,
112
116
  wordcoverpage: defined?(wordcoverpage) ? wordcoverpage : nil,
@@ -1,3 +1,3 @@
1
1
  module Metanorma
2
- VERSION = "1.2.4"
2
+ VERSION = "1.2.8"
3
3
  end
data/metanorma.gemspec CHANGED
@@ -27,19 +27,20 @@ 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
+ spec.add_runtime_dependency 'metanorma-utils', "~> 1.1.0"
30
31
  spec.add_runtime_dependency 'pry'
31
32
  spec.add_runtime_dependency 'fontist', '~> 1.8'
32
33
 
33
- # get relaton-cli to avoic circular reference with metanorma-standoc
34
+ # get relaton-cli to avoid circular reference with metanorma-standoc
34
35
  #spec.add_dependency "relaton-cli"
35
- #spec.add_dependency "metanorma-standoc", "~> 1.5.3"
36
+ #spec.add_dependency "metanorma-standoc"
36
37
 
37
- spec.add_development_dependency "rake", "~> 12.0"
38
+ spec.add_development_dependency "rake", "~> 13.0"
38
39
  spec.add_development_dependency "rspec", "~> 3.0"
39
40
  spec.add_development_dependency "byebug", "~> 10.0"
40
41
  spec.add_development_dependency "rspec-command", "~> 1.0"
41
42
  spec.add_development_dependency "equivalent-xml", "~> 0.6"
42
- spec.add_development_dependency "metanorma-iso", "~> 1.6.0"
43
+ spec.add_development_dependency "metanorma-iso", "~> 1.7.0"
43
44
  spec.add_development_dependency "sassc", "~> 2.4.0"
44
- #spec.add_development_dependency "isodoc", "~> 1.2.1"
45
+ spec.add_development_dependency "rubocop", "~> 1.5.2"
45
46
  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.4
4
+ version: 1.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-14 00:00:00.000000000 Z
11
+ date: 2021-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -66,6 +66,20 @@ 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.1.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.1.0
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: pry
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -100,14 +114,14 @@ dependencies:
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: '12.0'
117
+ version: '13.0'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: '12.0'
124
+ version: '13.0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: rspec
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -170,14 +184,14 @@ dependencies:
170
184
  requirements:
171
185
  - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: 1.6.0
187
+ version: 1.7.0
174
188
  type: :development
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
- version: 1.6.0
194
+ version: 1.7.0
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: sassc
183
197
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +206,20 @@ dependencies:
192
206
  - - "~>"
193
207
  - !ruby/object:Gem::Version
194
208
  version: 2.4.0
209
+ - !ruby/object:Gem::Dependency
210
+ name: rubocop
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: 1.5.2
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - "~>"
221
+ - !ruby/object:Gem::Version
222
+ version: 1.5.2
195
223
  description: Library to process any Metanorma standard.
196
224
  email:
197
225
  - open.source@ribose.com
@@ -224,6 +252,7 @@ files:
224
252
  - lib/metanorma/asciidoctor_extensions.rb
225
253
  - lib/metanorma/asciidoctor_extensions/glob_include_processor.rb
226
254
  - lib/metanorma/collection.rb
255
+ - lib/metanorma/collection_fileprocess.rb
227
256
  - lib/metanorma/collection_manifest.rb
228
257
  - lib/metanorma/collection_renderer.rb
229
258
  - lib/metanorma/compile.rb
@@ -261,7 +290,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
261
290
  - !ruby/object:Gem::Version
262
291
  version: '0'
263
292
  requirements: []
264
- rubygems_version: 3.0.3
293
+ rubygems_version: 3.1.4
265
294
  signing_key:
266
295
  specification_version: 4
267
296
  summary: Metanorma is the standard of standards; the metanorma gem allows you to create