metanorma 1.3.0 → 1.3.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 +4 -4
- data/.github/workflows/rake.yml +2 -12
- data/.hound.yml +3 -1
- data/.rubocop.yml +4 -8
- data/Rakefile +1 -1
- data/lib/metanorma/asciidoctor_extensions/glob_include_processor.rb +4 -6
- data/lib/metanorma/collection.rb +36 -17
- data/lib/metanorma/collection_fileparse.rb +45 -34
- data/lib/metanorma/collection_fileprocess.rb +50 -31
- data/lib/metanorma/collection_manifest.rb +26 -12
- data/lib/metanorma/collection_renderer.rb +33 -12
- data/lib/metanorma/compile.rb +20 -11
- data/lib/metanorma/compile_validate.rb +34 -28
- data/lib/metanorma/config.rb +1 -1
- data/lib/metanorma/document.rb +22 -10
- data/lib/metanorma/input.rb +0 -1
- data/lib/metanorma/input/asciidoc.rb +27 -30
- data/lib/metanorma/output.rb +0 -2
- data/lib/metanorma/output/utils.rb +2 -1
- data/lib/metanorma/util.rb +28 -0
- data/lib/metanorma/version.rb +1 -1
- data/metanorma.gemspec +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4ccf8d6a09fd9345faa44ae7201b4f7ee8816a6f36245c26b2482abd3f7afa9
|
4
|
+
data.tar.gz: 7997e0bea6b752e07f7db96f19b6d136b7a9740c046a0850022b477a2223a85b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 162c6e5e79ff9f7f4f41b17444c68ec23168ee593173b72c251c8623f9a16916f6ae557bc581f39d220c2c6d68d6350c2e4f4de7c000a87e90f39bed7e825609
|
7
|
+
data.tar.gz: a92a8a6ddd41e404cb6a1e00e0a0aaa2ecd645723486769b8656bb09e10f9e595a9df81231713224f6f9781d17c1c6943135d978b5865d0c02842b5e0ccbb84c
|
data/.github/workflows/rake.yml
CHANGED
@@ -16,19 +16,9 @@ jobs:
|
|
16
16
|
strategy:
|
17
17
|
fail-fast: false
|
18
18
|
matrix:
|
19
|
-
ruby: [ '2.7', '2.6', '2.5', '2.4' ]
|
19
|
+
ruby: [ '3.0', '2.7', '2.6', '2.5', '2.4' ]
|
20
20
|
os: [ ubuntu-latest, windows-latest, macos-latest ]
|
21
21
|
experimental: [ false ]
|
22
|
-
include:
|
23
|
-
- ruby: '3.0'
|
24
|
-
os: 'ubuntu-latest'
|
25
|
-
experimental: true
|
26
|
-
- ruby: '3.0'
|
27
|
-
os: 'windows-latest'
|
28
|
-
experimental: true
|
29
|
-
- ruby: '3.0'
|
30
|
-
os: 'macos-latest'
|
31
|
-
experimental: true
|
32
22
|
steps:
|
33
23
|
- uses: actions/checkout@v2
|
34
24
|
with:
|
@@ -49,5 +39,5 @@ jobs:
|
|
49
39
|
with:
|
50
40
|
token: ${{ secrets.METANORMA_CI_PAT_TOKEN || secrets.GITHUB_TOKEN }}
|
51
41
|
repository: ${{ github.repository }}
|
52
|
-
event-type:
|
42
|
+
event-type: tests-passed
|
53
43
|
client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}"}'
|
data/.hound.yml
CHANGED
data/.rubocop.yml
CHANGED
@@ -1,14 +1,10 @@
|
|
1
|
-
#
|
2
|
-
# https://github.com/
|
3
|
-
# All project-specific additions and overrides should be specified in this file.
|
1
|
+
# Auto-generated by Cimas: Do not edit it manually!
|
2
|
+
# See https://github.com/metanorma/cimas
|
4
3
|
inherit_from:
|
5
4
|
- https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
|
6
5
|
|
7
6
|
# local repo-specific modifications
|
7
|
+
# ...
|
8
8
|
|
9
9
|
AllCops:
|
10
|
-
|
11
|
-
StyleGuideCopsOnly: false
|
12
|
-
TargetRubyVersion: 2.4
|
13
|
-
Rails:
|
14
|
-
Enabled: true
|
10
|
+
TargetRubyVersion: 2.5
|
data/Rakefile
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
module Metanorma::AsciidoctorExtensions
|
2
|
-
|
3
2
|
class GlobIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
|
4
|
-
def process
|
3
|
+
def process(_doc, reader, target_glob, attributes)
|
5
4
|
Dir[File.join reader.dir, target_glob].sort.reverse_each do |target|
|
6
5
|
content = IO.readlines target
|
7
|
-
content.unshift
|
6
|
+
content.unshift "" unless attributes["adjoin-option"]
|
8
7
|
reader.push_include content, target, target, 1, attributes
|
9
8
|
end
|
10
9
|
reader
|
11
10
|
end
|
12
11
|
|
13
|
-
def handles?
|
14
|
-
target.include?
|
12
|
+
def handles?(target)
|
13
|
+
target.include? "*"
|
15
14
|
end
|
16
15
|
end
|
17
|
-
|
18
16
|
end
|
19
17
|
|
20
18
|
Asciidoctor::Extensions.register do
|
data/lib/metanorma/collection.rb
CHANGED
@@ -4,6 +4,7 @@ require "relaton"
|
|
4
4
|
require "relaton/cli"
|
5
5
|
require "metanorma/collection_manifest"
|
6
6
|
require "metanorma-utils"
|
7
|
+
require_relative "util"
|
7
8
|
|
8
9
|
module Metanorma
|
9
10
|
# Metanorma collection of documents
|
@@ -18,6 +19,8 @@ module Metanorma
|
|
18
19
|
# @return [Hash<String, Metanorma::Document>]
|
19
20
|
attr_accessor :documents
|
20
21
|
|
22
|
+
attr_accessor :disambig
|
23
|
+
|
21
24
|
# @param file [String] path to source file
|
22
25
|
# @param directives [Array<String>] documents-inline to inject the XML into
|
23
26
|
# the collection manifest; documents-external to keeps them outside
|
@@ -41,25 +44,32 @@ module Metanorma
|
|
41
44
|
@prefatory = args[:prefatory]
|
42
45
|
@final = args[:final]
|
43
46
|
@log = Metanorma::Utils::Log.new
|
47
|
+
@disambig = Util::DisambigFiles.new
|
44
48
|
end
|
45
49
|
|
46
50
|
# rubocop:enable Metrics/AbcSize,Metrics/MethodLength
|
47
|
-
|
48
|
-
|
49
|
-
|
51
|
+
def clean_exit
|
52
|
+
@log.write(File.join(File.dirname(@file),
|
53
|
+
"#{File.basename(@file, '.*')}.err"))
|
54
|
+
end
|
50
55
|
|
51
56
|
# @return [String] XML
|
52
57
|
def to_xml
|
53
|
-
Nokogiri::XML::Builder.new do |xml|
|
58
|
+
b = Nokogiri::XML::Builder.new do |xml|
|
54
59
|
xml.send("metanorma-collection",
|
55
60
|
"xmlns" => "http://metanorma.org") do |mc|
|
56
|
-
mc
|
57
|
-
@manifest.to_xml mc
|
58
|
-
content_to_xml "prefatory", mc
|
59
|
-
doccontainer mc
|
60
|
-
content_to_xml "final", mc
|
61
|
+
collection_body(mc)
|
61
62
|
end
|
62
|
-
end
|
63
|
+
end
|
64
|
+
b.to_xml
|
65
|
+
end
|
66
|
+
|
67
|
+
def collection_body(coll)
|
68
|
+
coll << @bibdata.to_xml(bibdata: true, date_format: :full)
|
69
|
+
@manifest.to_xml coll
|
70
|
+
content_to_xml "prefatory", coll
|
71
|
+
doccontainer coll
|
72
|
+
content_to_xml "final", coll
|
63
73
|
end
|
64
74
|
|
65
75
|
def render(opts)
|
@@ -110,7 +120,7 @@ module Metanorma
|
|
110
120
|
# @parma mnf [Metanorma::CollectionManifest]
|
111
121
|
# @return [Hash{String=>Metanorma::Document}]
|
112
122
|
def docs_from_xml(xml, mnf)
|
113
|
-
xml.xpath("//xmlns:doc-container
|
123
|
+
xml.xpath("//xmlns:doc-container//xmlns:bibdata")
|
114
124
|
.each_with_object({}) do |b, m|
|
115
125
|
bd = Relaton::Cli.parse_xml b
|
116
126
|
docref = mnf.docref_by_id bd.docidentifier.first.id
|
@@ -127,7 +137,7 @@ module Metanorma
|
|
127
137
|
<<~CONT
|
128
138
|
|
129
139
|
== #{xml.at('title')&.text}
|
130
|
-
|
140
|
+
#{xml.at('p')&.text}
|
131
141
|
CONT
|
132
142
|
end
|
133
143
|
end
|
@@ -152,8 +162,8 @@ module Metanorma
|
|
152
162
|
return unless (cnt = send(elm))
|
153
163
|
|
154
164
|
require "metanorma-#{doctype}"
|
155
|
-
out = sections(dummy_header + cnt)
|
156
|
-
builder.send(elm
|
165
|
+
out = sections(dummy_header + cnt.strip)
|
166
|
+
builder.send("#{elm}-content") { |b| b << out }
|
157
167
|
end
|
158
168
|
|
159
169
|
# @param cnt [String] prefatory/final content
|
@@ -168,9 +178,18 @@ module Metanorma
|
|
168
178
|
return unless Array(@directives).include? "documents-inline"
|
169
179
|
|
170
180
|
documents.each_with_index do |(_, d), i|
|
171
|
-
|
172
|
-
|
173
|
-
|
181
|
+
doccontainer1(builder, d, i)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def doccontainer1(builder, doc, idx)
|
186
|
+
id = format("doc%<index>09d", index: idx)
|
187
|
+
builder.send("doc-container", id: id) do |b|
|
188
|
+
if doc.attachment
|
189
|
+
doc.bibitem and b << doc.bibitem.root.to_xml
|
190
|
+
b.attachment Metanorma::Utils::datauri(doc.file)
|
191
|
+
else doc.to_xml b
|
192
|
+
end
|
174
193
|
end
|
175
194
|
end
|
176
195
|
|
@@ -8,16 +8,18 @@ module Metanorma
|
|
8
8
|
# UUIDs, so that their IDs can at least be registered to be tracked
|
9
9
|
# as existing.
|
10
10
|
def read_anchors(xml)
|
11
|
-
ret = {}
|
12
11
|
xrefs = @isodoc.xref_init(@lang, @script, @isodoc, @isodoc.i18n, {})
|
13
12
|
xrefs.parse xml
|
14
|
-
xrefs.get.
|
13
|
+
xrefs.get.each_with_object({}) do |(k, v), ret|
|
14
|
+
v[:type] ||= "clause"
|
15
15
|
ret[v[:type]] ||= {}
|
16
|
-
index = v[:container] || v[:label].nil? || v[:label].empty?
|
17
|
-
|
16
|
+
index = if v[:container] || v[:label].nil? || v[:label].empty?
|
17
|
+
UUIDTools::UUID.random_create.to_s
|
18
|
+
else v[:label]
|
19
|
+
end
|
18
20
|
ret[v[:type]][index] = k
|
21
|
+
ret[v[:type]][v[:value]] = k if v[:value]
|
19
22
|
end
|
20
|
-
ret
|
21
23
|
end
|
22
24
|
|
23
25
|
# @param id [String]
|
@@ -32,7 +34,7 @@ module Metanorma
|
|
32
34
|
# @param bib [Nokogiri::XML::Element]
|
33
35
|
# @param identifier [String]
|
34
36
|
def update_bibitem(bib, identifier) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
35
|
-
docid = bib&.at(ns("./docidentifier"))&.
|
37
|
+
docid = bib&.at(ns("./docidentifier"))&.children&.to_xml
|
36
38
|
unless @files[docid]
|
37
39
|
error = "[metanorma] Cannot find crossreference to document #{docid} "\
|
38
40
|
"in document #{identifier}."
|
@@ -41,12 +43,14 @@ module Metanorma
|
|
41
43
|
return
|
42
44
|
end
|
43
45
|
id = bib["id"]
|
44
|
-
newbib =
|
46
|
+
newbib = @files[docid][:bibdata].dup
|
45
47
|
newbib.name = "bibitem"
|
46
48
|
newbib["id"] = id
|
47
49
|
newbib["hidden"] = "true"
|
48
|
-
newbib&.at(
|
49
|
-
|
50
|
+
newbib&.at("./*[local-name() = 'ext']")&.remove
|
51
|
+
bib.replace(newbib)
|
52
|
+
_file, url = targetfile(@files[docid], relative: true, read: false,
|
53
|
+
doc: !@files[docid][:attachment])
|
50
54
|
uri_node = Nokogiri::XML::Node.new "uri", newbib
|
51
55
|
uri_node[:type] = "citation"
|
52
56
|
uri_node.content = url
|
@@ -68,7 +72,8 @@ module Metanorma
|
|
68
72
|
add_document_suffix(identifier, docxml)
|
69
73
|
update_direct_refs_to_docs(docxml, identifier)
|
70
74
|
svgmap_resolve(datauri_encode(docxml))
|
71
|
-
docxml.xpath(ns("//references[not(./bibitem[not(@hidden) or
|
75
|
+
docxml.xpath(ns("//references[bibitem][not(./bibitem[not(@hidden) or "\
|
76
|
+
"@hidden = 'false'])]")).each do |f|
|
72
77
|
f["hidden"] = "true"
|
73
78
|
end
|
74
79
|
docxml.to_xml
|
@@ -85,11 +90,9 @@ module Metanorma
|
|
85
90
|
isodoc = IsoDoc::Convert.new({})
|
86
91
|
docxml.xpath(ns("//svgmap//eref")).each do |e|
|
87
92
|
href = isodoc.eref_target(e)
|
88
|
-
next if href == "##{e['bibitemid']}"
|
93
|
+
next if href == "##{e['bibitemid']}" ||
|
94
|
+
href =~ /^#/ && !docxml.at("//*[@id = '#{href.sub(/^#/, '')}']")
|
89
95
|
|
90
|
-
if href.match(/^#/)
|
91
|
-
next unless docxml.at("//*[@id = '#{href.sub(/^#/, '')}']")
|
92
|
-
end
|
93
96
|
e["target"] = href.strip
|
94
97
|
e.name = "link"
|
95
98
|
e&.elements&.remove
|
@@ -106,6 +109,7 @@ module Metanorma
|
|
106
109
|
docxml.xpath(ns("//bibitem[not(ancestor::bibitem)]")).each do |b|
|
107
110
|
docid = b&.at(ns("./docidentifier[@type = 'repository']"))&.text
|
108
111
|
next unless docid && %r{^current-metanorma-collection/}.match(docid)
|
112
|
+
|
109
113
|
update_bibitem(b, identifier)
|
110
114
|
update_anchors(b, docxml, docid)
|
111
115
|
end
|
@@ -131,14 +135,16 @@ module Metanorma
|
|
131
135
|
docid.previous = "<docidentifier type='X'>#{file}</docidentifier>"
|
132
136
|
end
|
133
137
|
|
134
|
-
# update crossrefences to other documents, to include
|
138
|
+
# update crossrefences to other documents, to include
|
139
|
+
# disambiguating document suffix on id
|
135
140
|
def update_anchors(bib, docxml, _id) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
136
|
-
docid = bib&.at(ns("./docidentifier"))&.
|
141
|
+
docid = bib&.at(ns("./docidentifier"))&.children.to_xml
|
137
142
|
docxml.xpath("//xmlns:eref[@citeas = '#{docid}']").each do |e|
|
138
143
|
if @files[docid]
|
139
144
|
update_anchor_loc(bib, e, docid)
|
140
145
|
else
|
141
|
-
e << "<strong>** Unresolved reference to document #{docid},
|
146
|
+
e << "<strong>** Unresolved reference to document #{docid}, "\
|
147
|
+
"id #{e['bibitemid']}</strong>"
|
142
148
|
end
|
143
149
|
end
|
144
150
|
end
|
@@ -150,18 +156,20 @@ module Metanorma
|
|
150
156
|
ref = loc.at(ns("./referenceFrom")) || return
|
151
157
|
anchor = "#{ref.text}_#{document_suffix}"
|
152
158
|
return unless @files[docid][:anchors].inject([]) do |m, (_, x)|
|
153
|
-
m+= x.values
|
159
|
+
m += x.values
|
154
160
|
end.include?(anchor)
|
161
|
+
|
155
162
|
ref.content = anchor
|
156
163
|
end
|
157
164
|
|
158
165
|
# if there is a crossref to another document, with no anchor, retrieve the
|
159
166
|
# anchor given the locality, and insert it into the crossref
|
160
|
-
def update_anchor_create_loc(bib,
|
161
|
-
ins =
|
167
|
+
def update_anchor_create_loc(bib, eref, docid)
|
168
|
+
ins = eref.at(ns("./localityStack")) or return
|
162
169
|
type = ins&.at(ns("./locality/@type"))&.text
|
170
|
+
type = "clause" if type == "annex"
|
163
171
|
ref = ins&.at(ns("./locality/referenceFrom"))&.text
|
164
|
-
|
172
|
+
anchor = @files[docid][:anchors].dig(type, ref) or return
|
165
173
|
ref_from = Nokogiri::XML::Node.new "referenceFrom", bib
|
166
174
|
ref_from.content = anchor.sub(/^_/, "")
|
167
175
|
locality = Nokogiri::XML::Node.new "locality", bib
|
@@ -174,7 +182,8 @@ module Metanorma
|
|
174
182
|
def gather_internal_refs
|
175
183
|
@files.each_with_object({}) do |(_, x), refs|
|
176
184
|
next if x[:attachment]
|
177
|
-
|
185
|
+
|
186
|
+
file, = targetfile(x, read: true)
|
178
187
|
Nokogiri::XML(file)
|
179
188
|
.xpath(ns("//bibitem[@type = 'internal']/"\
|
180
189
|
"docidentifier[@type = 'repository']")).each do |d|
|
@@ -189,18 +198,8 @@ module Metanorma
|
|
189
198
|
# resolve file location for the target of each internal reference
|
190
199
|
def locate_internal_refs
|
191
200
|
refs = gather_internal_refs
|
192
|
-
@files.each do |identifier
|
193
|
-
|
194
|
-
|
195
|
-
file, _filename = targetfile(x, true)
|
196
|
-
docxml = Nokogiri::XML(file)
|
197
|
-
refs.each do |schema, ids|
|
198
|
-
ids.each_key do |id|
|
199
|
-
n = docxml.at("//*[@id = '#{id}']") and
|
200
|
-
n.at("./ancestor-or-self::*[@type = '#{schema}']") and
|
201
|
-
refs[schema][id] = identifier
|
202
|
-
end
|
203
|
-
end
|
201
|
+
@files.keys.reject { |k| @files[k][:attachment] }.each do |identifier|
|
202
|
+
locate_internal_refs1(refs, identifier, @files[identifier])
|
204
203
|
end
|
205
204
|
refs.each do |schema, ids|
|
206
205
|
ids.each do |id, key|
|
@@ -209,5 +208,17 @@ module Metanorma
|
|
209
208
|
end
|
210
209
|
refs
|
211
210
|
end
|
211
|
+
|
212
|
+
def locate_internal_refs1(refs, identifier, filedesc)
|
213
|
+
file, _filename = targetfile(filedesc, read: true)
|
214
|
+
docxml = Nokogiri::XML(file)
|
215
|
+
refs.each do |schema, ids|
|
216
|
+
ids.each_key do |id|
|
217
|
+
n = docxml.at("//*[@id = '#{id}']") and
|
218
|
+
n.at("./ancestor-or-self::*[@type = '#{schema}']") and
|
219
|
+
refs[schema][id] = identifier
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
212
223
|
end
|
213
224
|
end
|
@@ -15,27 +15,35 @@ module Metanorma
|
|
15
15
|
def read_files(path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
16
16
|
files = {}
|
17
17
|
@xml.xpath(ns("//docref")).each do |d|
|
18
|
-
identifier = d.at(ns("./identifier")).
|
19
|
-
files[identifier] = file_entry(d, path)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
identifier = d.at(ns("./identifier")).children.to_xml
|
19
|
+
files[identifier] = file_entry(d, identifier, path)
|
20
|
+
if files[identifier][:attachment]
|
21
|
+
files[identifier][:bibdata] = Metanorma::Document
|
22
|
+
.attachment_bibitem(identifier).root
|
23
|
+
else
|
24
|
+
file, _filename = targetfile(files[identifier], read: true)
|
25
|
+
xml = Nokogiri::XML(file)
|
26
|
+
add_document_suffix(identifier, xml)
|
27
|
+
files[identifier][:anchors] = read_anchors(xml)
|
28
|
+
files[identifier][:bibdata] = xml.at(ns("//bibdata"))
|
29
|
+
end
|
27
30
|
end
|
28
31
|
files
|
29
32
|
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
# rel_path is the source file address, determined relative to the YAML.
|
35
|
+
# out_path is the destination file address, with any references outside
|
36
|
+
# the working directory (../../...) truncated
|
37
|
+
def file_entry(ref, identifier, _path)
|
38
|
+
out = ref["attachment"] ? ref["fileref"] : File.basename(ref["fileref"])
|
39
|
+
ret = if ref["fileref"]
|
40
|
+
{ type: "fileref", ref: @documents[identifier].file,
|
41
|
+
rel_path: ref["fileref"],
|
42
|
+
out_path: out }
|
35
43
|
else
|
36
|
-
{ type: "id", ref:
|
44
|
+
{ type: "id", ref: ref["id"] }
|
37
45
|
end
|
38
|
-
ret[:attachment] =
|
46
|
+
ret[:attachment] = ref["attachment"] if ref["attachment"]
|
39
47
|
ret
|
40
48
|
end
|
41
49
|
|
@@ -58,12 +66,20 @@ module Metanorma
|
|
58
66
|
|
59
67
|
# return file contents + output filename for each file in the collection,
|
60
68
|
# given a docref entry
|
61
|
-
# @param data [Hash]
|
62
|
-
# @param read [Boolean]
|
69
|
+
# @param data [Hash] docref entry
|
70
|
+
# @param read [Boolean] read the file in and return it
|
71
|
+
# @param doc [Boolean] I am a Metanorma document,
|
72
|
+
# so my URL should end with html or pdf or whatever
|
73
|
+
# @param relative [Boolean] Return output path,
|
74
|
+
# formed relative to YAML file, not input path, relative to calling function
|
63
75
|
# @return [Array<String, nil>]
|
64
|
-
def targetfile(data,
|
65
|
-
|
66
|
-
|
76
|
+
def targetfile(data, options)
|
77
|
+
options = { read: false, doc: true, relative: false }.merge(options)
|
78
|
+
path = options[:relative] ? data[:rel_path] : data[:ref]
|
79
|
+
if data[:type] == "fileref"
|
80
|
+
ref_file path, data[:out_path], options[:read], options[:doc]
|
81
|
+
else
|
82
|
+
xml_file data[:id], options[:read]
|
67
83
|
end
|
68
84
|
end
|
69
85
|
|
@@ -71,43 +87,46 @@ module Metanorma
|
|
71
87
|
# @param read [Boolean]
|
72
88
|
# @param doc [Boolean]
|
73
89
|
# @return [Array<String, nil>]
|
74
|
-
def ref_file(ref, read, doc)
|
90
|
+
def ref_file(ref, out, read, doc)
|
75
91
|
file = File.read(ref, encoding: "utf-8") if read
|
76
|
-
filename =
|
92
|
+
filename = out.dup
|
77
93
|
filename.sub!(/\.xml$/, ".html") if doc
|
78
94
|
[file, filename]
|
79
95
|
end
|
80
96
|
|
81
97
|
# compile and output individual file in collection
|
82
|
-
def file_compile(
|
98
|
+
def file_compile(file, filename, identifier)
|
83
99
|
# warn "metanorma compile -x html #{f.path}"
|
100
|
+
Array(@directives).include?("presentation-xml") and
|
101
|
+
@compile_options.merge!(passthrough_presentation_xml: true)
|
84
102
|
c = Compile.new
|
85
|
-
c.compile
|
86
|
-
|
103
|
+
c.compile file.path, { format: :asciidoc,
|
104
|
+
extension_keys: @format }.merge(@compile_options)
|
87
105
|
@files[identifier][:outputs] = {}
|
88
106
|
@format.each do |e|
|
89
107
|
ext = c.processor.output_formats[e]
|
90
108
|
fn = File.basename(filename).sub(/(?<=\.)[^\.]+$/, ext.to_s)
|
91
|
-
FileUtils.
|
109
|
+
FileUtils.cp file.path.sub(/\.xml$/, ".#{ext}"), File.join(@outdir, fn)
|
92
110
|
@files[identifier][:outputs][e] = File.join(@outdir, fn)
|
93
111
|
end
|
94
112
|
end
|
95
113
|
|
96
114
|
def copy_file_to_dest(fileref)
|
97
|
-
|
98
|
-
dest = File.join(@outdir, fileref[:rel_path])
|
115
|
+
dest = File.join(@outdir, fileref[:out_path])
|
99
116
|
FileUtils.mkdir_p(File.dirname(dest))
|
100
|
-
FileUtils.cp
|
117
|
+
FileUtils.cp fileref[:ref], dest
|
101
118
|
end
|
102
119
|
|
103
120
|
# process each file in the collection
|
104
121
|
# files are held in memory, and altered as postprocessing
|
105
122
|
def files # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
106
123
|
internal_refs = locate_internal_refs
|
107
|
-
@files.
|
124
|
+
@files.each_with_index do |(identifier, x), i|
|
125
|
+
i.positive? && Array(@directives).include?("bare-after-first") and
|
126
|
+
@compile_options.merge!(bare: true)
|
108
127
|
if x[:attachment] then copy_file_to_dest(x)
|
109
128
|
else
|
110
|
-
file, filename = targetfile(x, true)
|
129
|
+
file, filename = targetfile(x, read: true)
|
111
130
|
file = update_xrefs(file, identifier, internal_refs)
|
112
131
|
Tempfile.open(["collection", ".xml"], encoding: "utf-8") do |f|
|
113
132
|
f.write(file)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require_relative "util"
|
2
3
|
|
3
4
|
module Metanorma
|
4
5
|
# Metanorma collection's manifest
|
@@ -15,6 +16,7 @@ module Metanorma
|
|
15
16
|
@title = title
|
16
17
|
@docref = docref
|
17
18
|
@manifest = manifest
|
19
|
+
@disambig = Util::DisambigFiles.new
|
18
20
|
end
|
19
21
|
|
20
22
|
class << self
|
@@ -43,8 +45,8 @@ module Metanorma
|
|
43
45
|
# @return [Hash{String=>String}]
|
44
46
|
def parse_docref(mnf)
|
45
47
|
mnf.xpath("xmlns:docref").map do |dr|
|
46
|
-
h = { "identifier" => dr.at("identifier").
|
47
|
-
|
48
|
+
h = { "identifier" => dr.at("identifier").children.to_xml }
|
49
|
+
dr[:fileref] and h["fileref"] = dr[:fileref]
|
48
50
|
h["attachment"] = dr[:attachment] if dr[:attachment]
|
49
51
|
h
|
50
52
|
end
|
@@ -63,12 +65,13 @@ module Metanorma
|
|
63
65
|
docs = @docref.each_with_object({}) do |dr, m|
|
64
66
|
next m unless dr["fileref"]
|
65
67
|
|
66
|
-
m[dr["identifier"]] = Document.parse_file(
|
68
|
+
m[dr["identifier"]] = Document.parse_file(
|
69
|
+
File.join(dir, dr["fileref"]),
|
70
|
+
dr["attachment"], dr["identifier"]
|
71
|
+
)
|
67
72
|
m
|
68
73
|
end
|
69
|
-
@manifest.reduce(docs)
|
70
|
-
mem.merge mnf.documents(dir)
|
71
|
-
end
|
74
|
+
@manifest.reduce(docs) { |mem, mnf| mem.merge mnf.documents(dir) }
|
72
75
|
end
|
73
76
|
|
74
77
|
# @param builder [Nokogiri::XML::Builder]
|
@@ -99,14 +102,25 @@ module Metanorma
|
|
99
102
|
|
100
103
|
# @param builder [Nokogiri::XML::Builder]
|
101
104
|
def docref_to_xml(builder)
|
105
|
+
@disambig = Util::DisambigFiles.new
|
102
106
|
@docref.each do |dr|
|
103
|
-
drf = builder.docref
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
107
|
+
drf = builder.docref do |b|
|
108
|
+
b.identifier do |i|
|
109
|
+
i << dr["identifier"]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
docref_to_xml_attrs(drf, dr)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def docref_to_xml_attrs(elem, docref)
|
117
|
+
elem[:fileref] = @disambig.source2dest_filename(docref["fileref"])
|
118
|
+
elem[:attachment] = docref["attachment"] if docref["attachment"]
|
119
|
+
if collection.directives.include?("documents-inline")
|
120
|
+
id = collection.documents.find_index do |k, _|
|
121
|
+
k == docref["identifier"]
|
109
122
|
end
|
123
|
+
elem[:id] = format("doc%<index>09d", index: id)
|
110
124
|
end
|
111
125
|
end
|
112
126
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "isodoc"
|
4
4
|
require_relative "collection_fileprocess"
|
5
5
|
require_relative "fontist_utils"
|
6
|
+
require_relative "util"
|
6
7
|
|
7
8
|
module Metanorma
|
8
9
|
# XML collection renderer
|
@@ -21,9 +22,9 @@ module Metanorma
|
|
21
22
|
# the collection, and that the flavour gem can sensibly process it. We may
|
22
23
|
# need to enhance metadata in the flavour gems isodoc/metadata.rb with
|
23
24
|
# collection metadata
|
24
|
-
def initialize(
|
25
|
+
def initialize(collection, folder, options = {}) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
25
26
|
check_options options
|
26
|
-
@xml = Nokogiri::XML
|
27
|
+
@xml = Nokogiri::XML collection.to_xml # @xml is the collection manifest
|
27
28
|
@lang = @xml&.at(ns("//bibdata/language"))&.text || "en"
|
28
29
|
@script = @xml&.at(ns("//bibdata/script"))&.text || "Latn"
|
29
30
|
@doctype = doctype
|
@@ -37,9 +38,13 @@ module Metanorma
|
|
37
38
|
@format = options[:format]
|
38
39
|
@compile_options = options[:compile] || {}
|
39
40
|
@log = options[:log]
|
41
|
+
@documents = collection.documents
|
42
|
+
@directives = collection.directives
|
43
|
+
@disambig = Util::DisambigFiles.new
|
40
44
|
|
41
45
|
# list of files in the collection
|
42
46
|
@files = read_files folder
|
47
|
+
isodoc_populate(@isodoc)
|
43
48
|
FileUtils.rm_rf @outdir
|
44
49
|
FileUtils.mkdir_p @outdir
|
45
50
|
end
|
@@ -51,7 +56,7 @@ module Metanorma
|
|
51
56
|
# @option options [Strong] :ourput_folder output directory
|
52
57
|
def self.render(col, options = {})
|
53
58
|
folder = File.dirname col.file
|
54
|
-
cr = new(col
|
59
|
+
cr = new(col, folder, options)
|
55
60
|
cr.files
|
56
61
|
cr.concatenate(col, options)
|
57
62
|
cr.coverpage if options[:format]&.include?(:html)
|
@@ -61,11 +66,13 @@ module Metanorma
|
|
61
66
|
options[:format] << :presentation if options[:format].include?(:pdf)
|
62
67
|
options[:format].uniq.each do |e|
|
63
68
|
next unless %i(presentation xml).include?(e)
|
69
|
+
|
64
70
|
ext = e == :presentation ? "presentation.xml" : e.to_s
|
65
71
|
out = col.clone
|
66
72
|
out.directives << "documents-inline"
|
67
73
|
out.documents.keys.each do |id|
|
68
74
|
next if @files[id][:attachment]
|
75
|
+
|
69
76
|
filename = @files[id][:outputs][e]
|
70
77
|
out.documents[id] = Metanorma::Document.raw_file(filename)
|
71
78
|
end
|
@@ -100,15 +107,21 @@ module Metanorma
|
|
100
107
|
end
|
101
108
|
|
102
109
|
# The isodoc class for the metanorma flavour we are using
|
103
|
-
def isodoc
|
110
|
+
def isodoc
|
104
111
|
x = Asciidoctor.load nil, backend: @doctype.to_sym
|
105
112
|
isodoc = x.converter.html_converter(Dummy.new)
|
106
113
|
isodoc.i18n_init(@lang, @script) # read in internationalisation
|
114
|
+
isodoc.metadata_init(@lang, @script, isodoc.i18n)
|
115
|
+
isodoc.info(@xml, nil)
|
116
|
+
isodoc
|
117
|
+
end
|
118
|
+
|
119
|
+
def isodoc_populate(isodoc)
|
107
120
|
# create the @meta class of isodoc, with "navigation" set to the index bar
|
108
121
|
# extracted from the manifest
|
109
122
|
nav = indexfile(@xml.at(ns("//manifest")))
|
110
123
|
i18n = isodoc.i18n
|
111
|
-
i18n.set(
|
124
|
+
i18n.set("navigation", nav)
|
112
125
|
isodoc.metadata_init(@lang, @script, i18n)
|
113
126
|
# populate the @meta class of isodoc with the various metadata fields
|
114
127
|
# native to the flavour; used to populate Liquid
|
@@ -135,6 +148,8 @@ module Metanorma
|
|
135
148
|
# populate liquid template of ARGV[1] with metadata extracted from
|
136
149
|
# collection manifest
|
137
150
|
def coverpage
|
151
|
+
return unless @coverpage
|
152
|
+
|
138
153
|
File.open(File.join(@outdir, "index.html"), "w:UTF-8") do |f|
|
139
154
|
f.write @isodoc.populate_template(File.read(@coverpage))
|
140
155
|
end
|
@@ -163,11 +178,19 @@ module Metanorma
|
|
163
178
|
# @param builder [Nokogiri::XML::Builder]
|
164
179
|
def docrefs(elm, builder)
|
165
180
|
elm.xpath(ns("./docref")).each do |d|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
181
|
+
ident = d.at(ns("./identifier")).children.to_xml
|
182
|
+
builder.li do |li|
|
183
|
+
li.a **{ href: index_link(d, ident) } do |a|
|
184
|
+
a << ident
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def index_link(docref, ident)
|
191
|
+
if docref["fileref"]
|
192
|
+
@files[ident][:out_path].sub(/\.xml$/, ".html")
|
193
|
+
else "#{docref['id']}.html"
|
171
194
|
end
|
172
195
|
end
|
173
196
|
|
@@ -199,8 +222,6 @@ module Metanorma
|
|
199
222
|
unless options[:format].is_a?(Array) && (FORMATS & options[:format]).any?
|
200
223
|
raise ArgumentError, "Need to specify formats (xml,html,pdf,doc)"
|
201
224
|
end
|
202
|
-
return if !options[:format].include?(:html) || options[:coverpage]
|
203
|
-
raise ArgumentError, "Need to specify a coverpage to render HTML"
|
204
225
|
end
|
205
226
|
end
|
206
227
|
end
|
data/lib/metanorma/compile.rb
CHANGED
@@ -20,7 +20,7 @@ module Metanorma
|
|
20
20
|
def compile(filename, options = {})
|
21
21
|
require_libraries(options)
|
22
22
|
options = options_extract(filename, options)
|
23
|
-
|
23
|
+
validate_options(options)
|
24
24
|
@processor = @registry.find_processor(options[:type].to_sym)
|
25
25
|
extensions = get_extensions(options) or return nil
|
26
26
|
(file, isodoc = process_input(filename, options)) or return nil
|
@@ -74,7 +74,9 @@ module Metanorma
|
|
74
74
|
memo
|
75
75
|
end
|
76
76
|
end
|
77
|
-
if !extensions.include?(:presentation)
|
77
|
+
if !extensions.include?(:presentation) && extensions.any? do |e|
|
78
|
+
@processor.use_presentation_xml(e)
|
79
|
+
end
|
78
80
|
extensions << :presentation
|
79
81
|
end
|
80
82
|
extensions
|
@@ -88,7 +90,7 @@ module Metanorma
|
|
88
90
|
options[:asciimath] and
|
89
91
|
file.sub!(/^(=[^\n]+\n)/, "\\1:mn-keep-asciimath:\n")
|
90
92
|
dir = File.dirname(filename)
|
91
|
-
dir !=
|
93
|
+
dir != "." and
|
92
94
|
file.gsub!(/^include::/, "include::#{dir}/")
|
93
95
|
[file, @processor.input_to_isodoc(file, filename, options)]
|
94
96
|
when ".xml"
|
@@ -108,15 +110,17 @@ module Metanorma
|
|
108
110
|
|
109
111
|
def relaton_export(isodoc, options)
|
110
112
|
return unless options[:relaton]
|
113
|
+
|
111
114
|
xml = Nokogiri::XML(isodoc)
|
112
115
|
bibdata = xml.at("//bibdata") || xml.at("//xmlns:bibdata")
|
113
|
-
#docid = bibdata&.at("./xmlns:docidentifier")&.text || options[:filename]
|
114
|
-
#outname = docid.sub(/^\s+/, "").sub(/\s+$/, "").gsub(/\s+/, "-") + ".xml"
|
116
|
+
# docid = bibdata&.at("./xmlns:docidentifier")&.text || options[:filename]
|
117
|
+
# outname = docid.sub(/^\s+/, "").sub(/\s+$/, "").gsub(/\s+/, "-") + ".xml"
|
115
118
|
File.open(options[:relaton], "w:UTF-8") { |f| f.write bibdata.to_xml }
|
116
119
|
end
|
117
120
|
|
118
121
|
def clean_sourcecode(xml)
|
119
|
-
xml.xpath(".//callout | .//annotation | .//xmlns:callout |
|
122
|
+
xml.xpath(".//callout | .//annotation | .//xmlns:callout | "\
|
123
|
+
".//xmlns:annotation").each do |x|
|
120
124
|
x.remove
|
121
125
|
end
|
122
126
|
xml.xpath(".//br | .//xmlns:br").each { |x| x.replace("\n") }
|
@@ -125,6 +129,7 @@ module Metanorma
|
|
125
129
|
|
126
130
|
def extract(isodoc, dirname, extract_types)
|
127
131
|
return unless dirname
|
132
|
+
|
128
133
|
if extract_types.nil? || extract_types.empty?
|
129
134
|
extract_types = [:sourcecode, :image, :requirement]
|
130
135
|
end
|
@@ -207,6 +212,7 @@ module Metanorma
|
|
207
212
|
isodoc_options = @processor.extract_options(file)
|
208
213
|
isodoc_options[:datauriimage] = true if options[:datauriimage]
|
209
214
|
isodoc_options[:sourcefilename] = options[:filename]
|
215
|
+
isodoc_options[:bare] = options[:bare]
|
210
216
|
file_extension = @processor.output_formats[ext]
|
211
217
|
outfilename = f.sub(/\.[^.]+$/, ".#{file_extension}")
|
212
218
|
if ext == :pdf
|
@@ -217,19 +223,22 @@ module Metanorma
|
|
217
223
|
if ext == :rxl
|
218
224
|
options[:relaton] = outfilename
|
219
225
|
relaton_export(isodoc, options)
|
226
|
+
elsif options[:passthrough_presentation_xml] && ext == :presentation
|
227
|
+
FileUtils.cp f, presentationxml_name
|
220
228
|
else
|
221
229
|
begin
|
222
230
|
@processor.use_presentation_xml(ext) ?
|
223
231
|
@processor.output(nil, presentationxml_name, outfilename, ext, isodoc_options) :
|
224
232
|
@processor.output(isodoc, xml_name, outfilename, ext, isodoc_options)
|
225
233
|
rescue StandardError => e
|
226
|
-
|
227
|
-
|
234
|
+
if e.message.include? "Fatal:"
|
235
|
+
@errors << e.message
|
236
|
+
else
|
237
|
+
puts e.message
|
238
|
+
puts e.backtrace.join("\n")
|
239
|
+
end
|
228
240
|
end
|
229
241
|
end
|
230
|
-
if ext == :pdf
|
231
|
-
# font_locations.unlink
|
232
|
-
end
|
233
242
|
wrap_html(options, file_extension, outfilename)
|
234
243
|
end
|
235
244
|
end
|
@@ -1,45 +1,51 @@
|
|
1
1
|
module Metanorma
|
2
2
|
class Compile
|
3
|
+
def validate_options(options)
|
4
|
+
validate_type(options)
|
5
|
+
validate_format(options)
|
6
|
+
end
|
7
|
+
|
3
8
|
def validate_type(options)
|
4
9
|
unless options[:type]
|
5
10
|
Util.log("[metanorma] Error: Please specify a standard type: "\
|
6
|
-
"#{@registry.supported_backends}.", :
|
7
|
-
return nil
|
11
|
+
"#{@registry.supported_backends}.", :fatal)
|
8
12
|
end
|
9
13
|
stdtype = options[:type].to_sym
|
10
|
-
|
14
|
+
load_flavor(stdtype)
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate_format(options)
|
18
|
+
unless options[:format] == :asciidoc
|
19
|
+
Util.log("[metanorma] Error: Only source file format currently "\
|
20
|
+
"supported is 'asciidoc'.", :fatal)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def load_flavor(stdtype)
|
27
|
+
flavor = "metanorma-#{stdtype}"
|
11
28
|
unless @registry.supported_backends.include? stdtype
|
12
|
-
Util.log("[metanorma] Info: Loading `#{
|
29
|
+
Util.log("[metanorma] Info: Loading `#{flavor}` gem "\
|
13
30
|
"for standard type `#{stdtype}`.", :info)
|
14
31
|
end
|
15
|
-
|
16
|
-
require "metanorma-#{stdtype}"
|
17
|
-
Util.log("[metanorma] Info: gem `#{metanorma_flavor}` loaded.", :info)
|
18
|
-
rescue Gem::ConflictError
|
19
|
-
Util.log("[metanorma] Error: Couldn't resolve dependencies for "\
|
20
|
-
"`metanorma-#{stdtype}`, Please add it to your Gemfile "\
|
21
|
-
"and run bundle install first", :error)
|
22
|
-
return false
|
23
|
-
rescue LoadError
|
24
|
-
Util.log("[metanorma] Error: loading gem `#{metanorma_flavor}` "\
|
25
|
-
"failed. Exiting.", :error)
|
26
|
-
return false
|
27
|
-
end
|
32
|
+
require_flavor(flavor, stdtype)
|
28
33
|
unless @registry.supported_backends.include? stdtype
|
29
|
-
Util.log("[metanorma] Error: The `#{
|
30
|
-
"still doesn't support `#{stdtype}`. Exiting.", :
|
31
|
-
return false
|
34
|
+
Util.log("[metanorma] Error: The `#{flavor}` gem "\
|
35
|
+
"still doesn't support `#{stdtype}`. Exiting.", :fatal)
|
32
36
|
end
|
33
|
-
true
|
34
37
|
end
|
35
38
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
def require_flavor(flavor, stdtype)
|
40
|
+
require flavor
|
41
|
+
Util.log("[metanorma] Info: gem `#{flavor}` loaded.", :info)
|
42
|
+
rescue Gem::ConflictError
|
43
|
+
Util.log("[metanorma] Error: Couldn't resolve dependencies for "\
|
44
|
+
"`metanorma-#{stdtype}`, Please add it to your Gemfile "\
|
45
|
+
"and run bundle install first", :fatal)
|
46
|
+
rescue LoadError
|
47
|
+
Util.log("[metanorma] Error: loading gem `#{flavor}` "\
|
48
|
+
"failed. Exiting.", :fatal)
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
data/lib/metanorma/config.rb
CHANGED
data/lib/metanorma/document.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Metanorma
|
2
2
|
class Document
|
3
3
|
# @return [Strin]
|
4
|
-
attr_reader :file, :attachment
|
4
|
+
attr_reader :file, :attachment, :bibitem
|
5
5
|
|
6
6
|
# @param bibitem [RelatonBib::BibliographicItem]
|
7
7
|
def initialize(bibitem, file, options = {})
|
@@ -14,9 +14,12 @@ module Metanorma
|
|
14
14
|
class << self
|
15
15
|
# @param file [String] file path
|
16
16
|
# @param attachment [Bool] is an attachment
|
17
|
+
# @param identifier [String] is the identifier assigned the file
|
18
|
+
# in the collection file
|
17
19
|
# @return [Metanorma::Document]
|
18
|
-
def parse_file(file, attachment)
|
19
|
-
new
|
20
|
+
def parse_file(file, attachment, identifier = nil)
|
21
|
+
new(bibitem(file, attachment, identifier), file,
|
22
|
+
{ attachment: attachment })
|
20
23
|
end
|
21
24
|
|
22
25
|
# #param xml [Nokogiri::XML::Document, Nokogiri::XML::Element]
|
@@ -31,6 +34,12 @@ module Metanorma
|
|
31
34
|
new(doc, filename, raw: true)
|
32
35
|
end
|
33
36
|
|
37
|
+
def attachment_bibitem(identifier)
|
38
|
+
Nokogiri::XML(
|
39
|
+
"<bibdata><docidentifier>#{identifier}</docidentifier></bibdata>",
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
34
43
|
private
|
35
44
|
|
36
45
|
# #param xml [Nokogiri::XML::Document, Nokogiri::XML::Element]
|
@@ -51,13 +60,16 @@ module Metanorma
|
|
51
60
|
# @param file [String]
|
52
61
|
# @return [RelatonBib::BibliographicItem,
|
53
62
|
# RelatonIso::IsoBibliographicItem]
|
54
|
-
def bibitem(file)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
63
|
+
def bibitem(file, attachment, identifier)
|
64
|
+
if attachment then attachment_bibitem(identifier)
|
65
|
+
else
|
66
|
+
case format(file)
|
67
|
+
when :xml
|
68
|
+
from_xml Nokogiri::XML(File.read(file, encoding: "UTF-8"))
|
69
|
+
when :yaml
|
70
|
+
yaml = File.read(file, encoding: "UTF-8")
|
71
|
+
Relaton::Cli::YAMLConvertor.convert_single_file(yaml)
|
72
|
+
end
|
61
73
|
end
|
62
74
|
end
|
63
75
|
end
|
data/lib/metanorma/input.rb
CHANGED
@@ -2,20 +2,14 @@ require "nokogiri"
|
|
2
2
|
|
3
3
|
module Metanorma
|
4
4
|
module Input
|
5
|
-
|
6
5
|
class Asciidoc < Base
|
7
|
-
|
8
6
|
def process(file, filename, type, options = {})
|
9
7
|
require "asciidoctor"
|
10
8
|
out_opts = {
|
11
|
-
to_file: false,
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
attributes: [
|
16
|
-
"nodoc", "stem", "xrefstyle=short", "docfile=#{filename}",
|
17
|
-
"output_dir=#{options[:output_dir]}"
|
18
|
-
]
|
9
|
+
to_file: false, safe: :safe, backend: type, header_footer: true,
|
10
|
+
attributes: ["nodoc", "stem", "xrefstyle=short",
|
11
|
+
"docfile=#{filename}",
|
12
|
+
"output_dir=#{options[:output_dir]}"]
|
19
13
|
}
|
20
14
|
unless asciidoctor_validate(file, filename, out_opts)
|
21
15
|
warn "Cannot continue compiling Asciidoctor document"
|
@@ -27,11 +21,12 @@ module Metanorma
|
|
27
21
|
def asciidoctor_validate(file, filename, options)
|
28
22
|
err = nil
|
29
23
|
begin
|
30
|
-
previous_stderr
|
24
|
+
previous_stderr = $stderr
|
25
|
+
$stderr = StringIO.new
|
31
26
|
::Asciidoctor.load(file, options)
|
32
|
-
%r{(\n|^)asciidoctor: ERROR: ['"]?#{Regexp.escape(filename ||
|
33
|
-
"<empty>")}['"]?: line \d+: include file not found: }
|
34
|
-
|
27
|
+
%r{(\n|^)asciidoctor: ERROR: ['"]?#{Regexp.escape(filename ||
|
28
|
+
"<empty>")}['"]?: line \d+: include file not found: }
|
29
|
+
.match($stderr.string) and err = $stderr.string
|
35
30
|
ensure
|
36
31
|
$stderr = previous_stderr
|
37
32
|
end
|
@@ -45,8 +40,9 @@ module Metanorma
|
|
45
40
|
/\n:mn-output-extensions: (?<extensions>[^\n]+)\n/ =~ headerextract
|
46
41
|
/\n:mn-relaton-output-file: (?<relaton>[^\n]+)\n/ =~ headerextract
|
47
42
|
/\n(?<asciimath>:mn-keep-asciimath:[^\n]*)\n/ =~ headerextract
|
48
|
-
asciimath = defined?(asciimath)
|
49
|
-
|
43
|
+
asciimath = if defined?(asciimath)
|
44
|
+
(!asciimath.nil? && asciimath != ":mn-keep-asciimath: false")
|
45
|
+
end
|
50
46
|
asciimath = nil if asciimath == false
|
51
47
|
{
|
52
48
|
type: defined?(type) ? type : nil,
|
@@ -60,38 +56,39 @@ module Metanorma
|
|
60
56
|
attr&.sub(/^#{name}:\s*$/, "#{name}: true")&.sub(/^#{name}:\s+/, "")
|
61
57
|
end
|
62
58
|
|
59
|
+
ADOC_OPTIONS = %w(htmlstylesheet htmlcoverpage htmlintropage scripts
|
60
|
+
scripts-override scripts-pdf wordstylesheet bare i18nyaml
|
61
|
+
standardstylesheet header wordcoverpage wordintropage
|
62
|
+
ulstyle olstyle htmlstylesheet-override
|
63
|
+
htmltoclevels doctoclevels sectionsplit
|
64
|
+
body-font header-font monospace-font title-font
|
65
|
+
wordstylesheet-override).freeze
|
66
|
+
|
63
67
|
def extract_options(file)
|
64
68
|
header = file.sub(/\n\n.*$/m, "\n")
|
65
|
-
ret =
|
66
|
-
scripts-pdf wordstylesheet
|
67
|
-
standardstylesheet header wordcoverpage wordintropage i18nyaml
|
68
|
-
ulstyle olstyle htmlstylesheet-override
|
69
|
-
htmltoclevels doctoclevels sectionsplit
|
70
|
-
body-font header-font monospace-font title-font
|
71
|
-
wordstylesheet-override).each_with_object({}) do |w, acc|
|
69
|
+
ret = ADOC_OPTIONS.each_with_object({}) do |w, acc|
|
72
70
|
m = /\n:#{w}: ([^\n]+)\n/.match(header) or next
|
73
71
|
acc[w.gsub(/-/, "").sub(/override$/, "_override")
|
74
72
|
.sub(/pdf$/, "_pdf").to_sym] = m[1]
|
75
73
|
end
|
76
74
|
/\n:data-uri-image: (?<datauriimage>[^\n]+)\n/ =~ header
|
77
|
-
/\n:(?<
|
75
|
+
/\n:(?<hier_assets>hierarchical-assets:[^\n]*)\n/ =~ header
|
78
76
|
/\n:(?<use_xinclude>use-xinclude:[^\n]*)\n/ =~ header
|
79
77
|
/\n:(?<break_up>break-up-urls-in-tables:[^\n]*)\n/ =~ header
|
80
78
|
|
81
|
-
defined?(
|
82
|
-
|
79
|
+
defined?(hier_assets) and
|
80
|
+
hier_assets = empty_attr(hier_assets, "hierarchical-assets")
|
83
81
|
defined?(use_xinclude) and
|
84
82
|
use_xinclude = empty_attr(use_xinclude, "use-xinclude")
|
85
83
|
defined?(break_up) and
|
86
84
|
break_up = empty_attr(break_up, "break-up-urls-in-tables")
|
87
|
-
ret.merge(
|
85
|
+
ret.merge(
|
88
86
|
datauriimage: defined?(datauriimage) ? datauriimage != "false" : nil,
|
89
|
-
hierarchical_assets: defined?(
|
87
|
+
hierarchical_assets: defined?(hier_assets) ? hier_assets : nil,
|
90
88
|
use_xinclude: defined?(use_xinclude) ? use_xinclude : nil,
|
91
89
|
break_up_urls_in_tables: defined?(break_up) ? break_up : nil,
|
92
|
-
|
90
|
+
).reject { |_, val| val.nil? }
|
93
91
|
end
|
94
|
-
|
95
92
|
end
|
96
93
|
end
|
97
94
|
end
|
data/lib/metanorma/output.rb
CHANGED
@@ -7,7 +7,8 @@ module Metanorma
|
|
7
7
|
def file_path(url_path)
|
8
8
|
file_url = url_path
|
9
9
|
file_url = "file://#{url_path}" if Pathname.new(file_url).absolute?
|
10
|
-
|
10
|
+
%r{^file://}.match?(file_url) or
|
11
|
+
file_url = "file://#{Dir.pwd}/#{url_path}"
|
11
12
|
file_url
|
12
13
|
end
|
13
14
|
end
|
data/lib/metanorma/util.rb
CHANGED
@@ -11,5 +11,33 @@ module Metanorma
|
|
11
11
|
exit(1)
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
class DisambigFiles
|
16
|
+
def initialize
|
17
|
+
@seen_filenames = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def source2dest_filename(name, disambig = true)
|
21
|
+
n = name.sub(%r{^(\./)?(\.\./)+}, "")
|
22
|
+
dir = File.dirname(n)
|
23
|
+
base = File.basename(n)
|
24
|
+
if disambig && @seen_filenames.include?(base)
|
25
|
+
base = disambiguate_filename(base)
|
26
|
+
end
|
27
|
+
@seen_filenames << base
|
28
|
+
dir == "." ? base : File.join(dir, base)
|
29
|
+
end
|
30
|
+
|
31
|
+
def disambiguate_filename(base)
|
32
|
+
m = /^(?<start>.+\.)(?!0)(?<num>\d+)\.(?<suff>[^.]*)$/.match(base) ||
|
33
|
+
/^(?<start>.+\.)(?<suff>[^.]*)/.match(base) ||
|
34
|
+
/^(?<start>.+)$/.match(base)
|
35
|
+
i = m.names.include?("num") ? m["num"].to_i + 1 : 1
|
36
|
+
while @seen_filenames.include? base = "#{m['start']}#{i}.#{m['suff']}"
|
37
|
+
i += 1
|
38
|
+
end
|
39
|
+
base
|
40
|
+
end
|
41
|
+
end
|
14
42
|
end
|
15
43
|
end
|
data/lib/metanorma/version.rb
CHANGED
data/metanorma.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.bindir = "bin"
|
21
21
|
# spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
22
|
spec.require_paths = ["lib"]
|
23
|
-
spec.required_ruby_version = ">= 2.
|
23
|
+
spec.required_ruby_version = ">= 2.5.0"
|
24
24
|
|
25
25
|
spec.add_runtime_dependency "asciidoctor"
|
26
26
|
spec.add_runtime_dependency "fontist", "~> 1.8"
|
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.3.
|
4
|
+
version: 1.3.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: 2021-
|
11
|
+
date: 2021-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -286,7 +286,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
286
286
|
requirements:
|
287
287
|
- - ">="
|
288
288
|
- !ruby/object:Gem::Version
|
289
|
-
version: 2.
|
289
|
+
version: 2.5.0
|
290
290
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
291
291
|
requirements:
|
292
292
|
- - ">="
|