metanorma 1.6.1 → 1.6.3
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/lib/metanorma/collection.rb +15 -27
- data/lib/metanorma/collection_fileparse.rb +80 -125
- data/lib/metanorma/collection_fileprocess.rb +14 -190
- data/lib/metanorma/collection_manifest.rb +1 -3
- data/lib/metanorma/collection_render_utils.rb +111 -0
- data/lib/metanorma/collection_renderer.rb +17 -107
- data/lib/metanorma/compile.rb +15 -0
- data/lib/metanorma/compile_options.rb +16 -12
- data/lib/metanorma/document.rb +1 -1
- data/lib/metanorma/files_lookup.rb +51 -44
- data/lib/metanorma/input/asciidoc.rb +3 -2
- data/lib/metanorma/sectionsplit.rb +101 -156
- data/lib/metanorma/sectionsplit_links.rb +116 -0
- data/lib/metanorma/util.rb +31 -0
- data/lib/metanorma/version.rb +1 -1
- data/metanorma.gemspec +1 -1
- metadata +6 -4
@@ -5,6 +5,8 @@ require "metanorma-utils"
|
|
5
5
|
module Metanorma
|
6
6
|
# XML collection renderer
|
7
7
|
class FileLookup
|
8
|
+
attr_accessor :files_to_delete, :parent
|
9
|
+
|
8
10
|
# hash for each document in collection of document identifier to:
|
9
11
|
# document reference (fileref or id), type of document reference,
|
10
12
|
# and bibdata entry for that file
|
@@ -18,12 +20,12 @@ module Metanorma
|
|
18
20
|
@path = path
|
19
21
|
@compile = parent.compile
|
20
22
|
@documents = parent.documents
|
23
|
+
@files_to_delete = []
|
21
24
|
read_files
|
22
25
|
end
|
23
26
|
|
24
27
|
def read_files
|
25
28
|
@xml.xpath(ns("//docref")).each { |d| read_file(d) }
|
26
|
-
add_section_split
|
27
29
|
end
|
28
30
|
|
29
31
|
def read_file(docref)
|
@@ -41,9 +43,10 @@ module Metanorma
|
|
41
43
|
.attachment_bibitem(identifier).root
|
42
44
|
else
|
43
45
|
file, _filename = targetfile(entry, read: true)
|
44
|
-
xml = Nokogiri::XML(file)
|
46
|
+
xml = Nokogiri::XML(file, &:huge)
|
45
47
|
add_document_suffix(identifier, xml)
|
46
48
|
entry[:anchors] = read_anchors(xml)
|
49
|
+
entry[:ids] = read_ids(xml)
|
47
50
|
entry[:bibdata] = xml.at(ns("//bibdata"))
|
48
51
|
end
|
49
52
|
end
|
@@ -56,66 +59,61 @@ module Metanorma
|
|
56
59
|
end
|
57
60
|
|
58
61
|
def add_section_split
|
59
|
-
#require "debug"; binding.b
|
60
62
|
ret = @files.keys.each_with_object({}) do |k, m|
|
61
63
|
if @files[k][:sectionsplit] == "true" && !@files[k]["attachment"]
|
62
|
-
s, manifest = sectionsplit(@files[k][:ref])
|
63
|
-
s.each_with_index
|
64
|
-
add_section_split_instance(f1, m, k, i)
|
65
|
-
end
|
64
|
+
s, manifest = sectionsplit(@files[k][:ref], k)
|
65
|
+
s.each_with_index { |f1, i| add_section_split_instance(f1, m, k, i) }
|
66
66
|
m["#{k}:index.html"] = add_section_split_cover(manifest, k)
|
67
|
+
@files_to_delete << m["#{k}:index.html"][:ref]
|
67
68
|
end
|
68
69
|
m[k] = @files[k]
|
69
|
-
#require "debug"; binding.b
|
70
70
|
end
|
71
71
|
@files = ret
|
72
72
|
end
|
73
73
|
|
74
74
|
def add_section_split_cover(manifest, ident)
|
75
|
-
cover = section_split_cover(manifest,
|
75
|
+
cover = @sectionsplit.section_split_cover(manifest,
|
76
|
+
@parent.dir_name_cleanse(ident))
|
76
77
|
@files[ident][:out_path] = cover
|
77
78
|
{ attachment: true, index: false, out_path: cover,
|
78
79
|
ref: File.join(File.dirname(manifest.file), cover) }
|
79
80
|
end
|
80
81
|
|
81
|
-
def section_split_cover(col, ident)
|
82
|
-
dir = File.dirname(col.file)
|
83
|
-
@compile.collection_setup(nil, dir)
|
84
|
-
#require "debug";binding.b
|
85
|
-
CollectionRenderer.new(col, dir,
|
86
|
-
output_folder: "#{ident}_collection",
|
87
|
-
format: %i(html),
|
88
|
-
coverpage: File.join(dir, "cover.html")).coverpage
|
89
|
-
FileUtils.mv "#{ident}_collection/index.html",
|
90
|
-
File.join(dir, "#{ident}_index.html")
|
91
|
-
FileUtils.rm_rf "#{ident}_collection"
|
92
|
-
"#{ident}_index.html"
|
93
|
-
end
|
94
|
-
|
95
82
|
def add_section_split_instance(file, manifest, key, idx)
|
96
|
-
presfile =
|
97
|
-
|
98
|
-
newkey = key("#{key.strip} #{file[:title]}")
|
83
|
+
presfile, newkey, xml =
|
84
|
+
add_section_split_instance_prep(file, key)
|
99
85
|
manifest[newkey] =
|
100
86
|
{ parentid: key, presentationxml: true, type: "fileref",
|
101
87
|
rel_path: file[:url], out_path: File.basename(file[:url]),
|
102
|
-
anchors: read_anchors(
|
88
|
+
anchors: read_anchors(xml), ids: read_ids(xml),
|
89
|
+
sectionsplit_output: true,
|
103
90
|
bibdata: @files[key][:bibdata], ref: presfile }
|
91
|
+
@files_to_delete << file[:url]
|
104
92
|
manifest[newkey][:bare] = true unless idx.zero?
|
105
93
|
end
|
106
94
|
|
107
|
-
def
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
95
|
+
def add_section_split_instance_prep(file, key)
|
96
|
+
presfile = File.join(File.dirname(@files[key][:ref]),
|
97
|
+
File.basename(file[:url]))
|
98
|
+
newkey = key("#{key.strip} #{file[:title]}")
|
99
|
+
xml = Nokogiri::XML(File.read(presfile), &:huge)
|
100
|
+
[presfile, newkey, xml]
|
101
|
+
end
|
102
|
+
|
103
|
+
def sectionsplit(file, ident)
|
104
|
+
@sectionsplit =
|
105
|
+
Sectionsplit.new(input: file, base: File.basename(file), dir: File.dirname(file),
|
106
|
+
output: file, compile_options: @parent.compile_options,
|
107
|
+
fileslookup: self, ident: ident, isodoc: @isodoc)
|
108
|
+
coll = @sectionsplit.sectionsplit.sort_by { |f| f[:order] }
|
109
|
+
# s = @compile.sectionsplit(file, File.basename(file), File.dirname(file),
|
110
|
+
# @parent.compile_options, self, ident)
|
111
|
+
# .sort_by { |f| f[:order] }
|
112
|
+
# xml = Nokogiri::XML(File.read(file, encoding: "UTF-8")) { |x| x.huge }
|
113
|
+
xml = Nokogiri::XML(File.read(file, encoding: "UTF-8"), &:huge)
|
114
|
+
[coll, @sectionsplit
|
115
|
+
.collection_manifest(File.basename(file), coll, xml, nil,
|
116
|
+
File.dirname(file))]
|
119
117
|
end
|
120
118
|
|
121
119
|
# rel_path is the source file address, determined relative to the YAML.
|
@@ -220,8 +218,19 @@ module Metanorma
|
|
220
218
|
ret[val[:type]][val[:value]] = key if val[:value]
|
221
219
|
end
|
222
220
|
|
221
|
+
# Also parse all ids in doc (including ones which won't be xref targets)
|
222
|
+
def read_ids(xml)
|
223
|
+
ret = {}
|
224
|
+
xml.traverse do |x|
|
225
|
+
x.text? and next
|
226
|
+
/^semantic__/.match?(x.name) and next
|
227
|
+
x["id"] and ret[x["id"]] = true
|
228
|
+
end
|
229
|
+
ret
|
230
|
+
end
|
231
|
+
|
223
232
|
def key(ident)
|
224
|
-
@c.decode(ident).gsub(/(\
|
233
|
+
@c.decode(ident).gsub(/(\p{Zs})+/, " ").sub(/^metanorma-collection /, "")
|
225
234
|
end
|
226
235
|
|
227
236
|
def keys
|
@@ -229,10 +238,8 @@ module Metanorma
|
|
229
238
|
end
|
230
239
|
|
231
240
|
def get(ident, attr = nil)
|
232
|
-
if attr
|
233
|
-
|
234
|
-
else
|
235
|
-
@files[key(ident)]
|
241
|
+
if attr then @files[key(ident)][attr]
|
242
|
+
else @files[key(ident)]
|
236
243
|
end
|
237
244
|
end
|
238
245
|
|
@@ -69,7 +69,8 @@ module Metanorma
|
|
69
69
|
pdf-allow-print pdf-allow-print-hq pdf-allow-fill-in-forms
|
70
70
|
fonts font-license-agreement pdf-allow-access-content
|
71
71
|
pdf-encrypt-metadata iso-word-template document-scheme
|
72
|
-
localize-number iso-word-bg-strip-color modspec-identifier-base)
|
72
|
+
localize-number iso-word-bg-strip-color modspec-identifier-base)
|
73
|
+
.freeze
|
73
74
|
|
74
75
|
EMPTY_ADOC_OPTIONS_DEFAULT_TRUE =
|
75
76
|
%w(data-uri-image suppress-asciimath-dup use-xinclude
|
@@ -80,7 +81,7 @@ module Metanorma
|
|
80
81
|
toc-tables toc-recommendations).freeze
|
81
82
|
|
82
83
|
def attr_name_normalise(name)
|
83
|
-
name.gsub(
|
84
|
+
name.gsub("-", "").sub(/override$/, "_override").sub(/pdf$/, "_pdf")
|
84
85
|
.to_sym
|
85
86
|
end
|
86
87
|
|
@@ -1,31 +1,35 @@
|
|
1
1
|
require "yaml"
|
2
|
+
require_relative "util"
|
3
|
+
require_relative "sectionsplit_links"
|
2
4
|
|
3
5
|
module Metanorma
|
4
|
-
class
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@
|
14
|
-
|
15
|
-
|
6
|
+
class Sectionsplit
|
7
|
+
attr_accessor :filecache
|
8
|
+
|
9
|
+
def initialize(opts)
|
10
|
+
@input_filename = opts[:input]
|
11
|
+
@base = opts[:base]
|
12
|
+
@output_filename = opts[:output]
|
13
|
+
@xml = opts[:xml]
|
14
|
+
@dir = opts[:dir]
|
15
|
+
@compile_opts = opts[:compile_opts] || {}
|
16
|
+
@fileslookup = opts[:fileslookup]
|
17
|
+
@ident = opts[:ident]
|
18
|
+
@isodoc = opts[:isodoc]
|
16
19
|
end
|
17
20
|
|
18
21
|
def ns(xpath)
|
19
22
|
@isodoc.ns(xpath)
|
20
23
|
end
|
21
24
|
|
22
|
-
def build_collection
|
23
|
-
base
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
def build_collection
|
26
|
+
collection_setup(@base, @dir)
|
27
|
+
files = sectionsplit #(@input_filename, @base, @dir, @compile_opts)
|
28
|
+
input_xml = Nokogiri::XML(File.read(@input_filename,
|
29
|
+
encoding: "UTF-8"), &:huge)
|
30
|
+
collection_manifest(@base, files, input_xml, @xml, @dir).render(
|
31
|
+
{ format: %i(html), output_folder: "#{@output_filename}_collection",
|
32
|
+
coverpage: File.join(@dir, "cover.html") }.merge(@compile_opts),
|
29
33
|
)
|
30
34
|
end
|
31
35
|
|
@@ -46,13 +50,11 @@ module Metanorma
|
|
46
50
|
|
47
51
|
def coll_cover
|
48
52
|
<<~COVER
|
49
|
-
<html><head
|
50
|
-
<body>
|
53
|
+
<html><head/><body>
|
51
54
|
<h1>{{ doctitle }}</h1>
|
52
55
|
<h2>{{ docnumber }}</h2>
|
53
56
|
<nav>{{ navigation }}</nav>
|
54
|
-
</body>
|
55
|
-
</html>
|
57
|
+
</body></html>
|
56
58
|
COVER
|
57
59
|
end
|
58
60
|
|
@@ -62,161 +64,91 @@ module Metanorma
|
|
62
64
|
["//bibliography/*[not(@hidden = 'true')]", "bibliography"],
|
63
65
|
["//indexsect", nil], ["//colophon", nil]].freeze
|
64
66
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
# Input XML is Semantic
|
68
|
+
# def sectionsplit(filename, basename, dir, compile_options, fileslookup = nil, ident = nil)
|
69
|
+
def sectionsplit
|
70
|
+
xml = sectionsplit_prep(File.read(@input_filename), @base, @dir)
|
71
|
+
@key = xref_preprocess(xml, @fileslookup, @ident)
|
69
72
|
SPLITSECTIONS.each_with_object([]) do |n, ret|
|
70
|
-
xml.xpath(ns(n[0])).each do |s|
|
71
|
-
ret << sectionfile(xml,
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def emptydoc(xml)
|
77
|
-
out = xml.dup
|
78
|
-
out.xpath(
|
79
|
-
ns("//preface | //sections | //annex | //bibliography/clause | " \
|
80
|
-
"//bibliography/references[not(@hidden = 'true')] | //indexsect" \
|
81
|
-
"//colophon"),
|
82
|
-
).each(&:remove)
|
83
|
-
out
|
84
|
-
end
|
85
|
-
|
86
|
-
def sectionfile(fulldoc, xml, file, chunk, parentnode)
|
87
|
-
fname = create_sectionfile(fulldoc, xml.dup, file, chunk, parentnode)
|
88
|
-
{ order: chunk["displayorder"].to_i, url: fname,
|
89
|
-
title: titlerender(chunk) }
|
90
|
-
end
|
91
|
-
|
92
|
-
def create_sectionfile(xml, out, file, chunk, parentnode)
|
93
|
-
ins = out.at(ns("//misccontainer")) || out.at(ns("//bibdata"))
|
94
|
-
if parentnode
|
95
|
-
ins.next = "<#{parentnode}/>"
|
96
|
-
ins.next.add_child(chunk.dup)
|
97
|
-
else ins.next = chunk.dup
|
98
|
-
end
|
99
|
-
xref_process(out, xml, @key)
|
100
|
-
outname = "#{file}.xml"
|
101
|
-
File.open(File.join(@splitdir, outname), "w:UTF-8") { |f| f.write(out) }
|
102
|
-
outname
|
103
|
-
end
|
104
|
-
|
105
|
-
def xref_preprocess(xml)
|
106
|
-
svg_preprocess(xml)
|
107
|
-
key = (0...8).map { rand(65..90).chr }.join # random string
|
108
|
-
xml.root["type"] = key # to force recognition of internal refs
|
109
|
-
key
|
110
|
-
end
|
111
|
-
|
112
|
-
def xref_process(section, xml, key)
|
113
|
-
refs = eref_to_internal_eref(section, xml, key)
|
114
|
-
refs += xref_to_internal_eref(section, key)
|
115
|
-
ins = new_hidden_ref(section)
|
116
|
-
copied_refs = copy_repo_items_biblio(ins, section, xml)
|
117
|
-
insert_indirect_biblio(ins, refs - copied_refs, key)
|
118
|
-
end
|
119
|
-
|
120
|
-
def svg_preprocess(xml)
|
121
|
-
xml.xpath("//m:svg", "m" => "http://www.w3.org/2000/svg").each do |s|
|
122
|
-
m = svgmap_wrap(s)
|
123
|
-
s.xpath(".//m:a", "m" => "http://www.w3.org/2000/svg").each do |a|
|
124
|
-
next unless /^#/.match? a["href"]
|
125
|
-
|
126
|
-
a["href"] = a["href"].sub(/^#/, "")
|
127
|
-
m << "<target href='#{a['href']}'>" \
|
128
|
-
"<xref target='#{a['href']}'/></target>"
|
73
|
+
conflate_floatingtitles(xml.xpath(ns(n[0]))).each do |s|
|
74
|
+
ret << sectionfile(xml, emptydoc(xml), "#{@base}.#{ret.size}", s, n[1])
|
129
75
|
end
|
130
76
|
end
|
131
77
|
end
|
132
78
|
|
133
|
-
def
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
svg.at("./ancestor::xmlns:svgmap")
|
138
|
-
end
|
139
|
-
|
140
|
-
def make_anchor(anchor)
|
141
|
-
"<localityStack><locality type='anchor'><referenceFrom>" \
|
142
|
-
"#{anchor}</referenceFrom></locality></localityStack>"
|
79
|
+
def block?(node)
|
80
|
+
%w(p table formula admonition ol ul dl figure quote sourcecode example
|
81
|
+
pre note pagebrreak hr bookmark requirement recommendation permission
|
82
|
+
svgmap inputform toc passthrough review imagemap).include?(node.name)
|
143
83
|
end
|
144
84
|
|
145
|
-
def
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
m[x
|
150
|
-
x.delete("target")
|
151
|
-
x["type"] = key
|
152
|
-
x.name = "eref"
|
153
|
-
end.keys
|
154
|
-
end
|
155
|
-
|
156
|
-
def eref_to_internal_eref(section, xml, key)
|
157
|
-
eref_to_internal_eref_select(section, xml).each_with_object([]) do |x, m|
|
158
|
-
url = xml.at(ns("//bibitem[@id = '#{x}']/uri[@type = 'citation']"))
|
159
|
-
section.xpath("//*[@bibitemid = '#{x}']").each do |e|
|
160
|
-
id = eref_to_internal_eref1(e, key, url)
|
161
|
-
id and m << id
|
85
|
+
def conflate_floatingtitles(nodes)
|
86
|
+
holdover = false
|
87
|
+
nodes.each_with_object([]) do |x, m|
|
88
|
+
if holdover then m.last << x
|
89
|
+
else m << [x]
|
162
90
|
end
|
91
|
+
holdover = block?(x)
|
163
92
|
end
|
164
93
|
end
|
165
94
|
|
166
|
-
def
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
end
|
95
|
+
def sectionsplit_prep(file, filename, dir)
|
96
|
+
@splitdir = dir
|
97
|
+
xml1filename, type = sectionsplit_preprocess_semxml(file, filename)
|
98
|
+
Compile.new.compile(
|
99
|
+
xml1filename,
|
100
|
+
{ format: :asciidoc, extension_keys: [:presentation], type: type }
|
101
|
+
.merge(@compile_opts),
|
102
|
+
)
|
103
|
+
Nokogiri::XML(File.read(xml1filename.sub(/\.xml$/, ".presentation.xml"),
|
104
|
+
encoding: "utf-8"), &:huge)
|
177
105
|
end
|
178
106
|
|
179
|
-
def
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
107
|
+
def sectionsplit_preprocess_semxml(file, filename)
|
108
|
+
xml = Nokogiri::XML(file, &:huge)
|
109
|
+
type = xml.root.name.sub("-standard", "").to_sym
|
110
|
+
@fileslookup&.parent&.update_xrefs(xml, @ident, {})
|
111
|
+
xml1 = Tempfile.open([filename, ".xml"], encoding: "utf-8") do |f|
|
112
|
+
f.write(@isodoc.to_xml(svg_preprocess(xml)))
|
113
|
+
f
|
185
114
|
end
|
115
|
+
@filecache ||= []
|
116
|
+
@filecache << xml1
|
117
|
+
[xml1.path, type]
|
186
118
|
end
|
187
119
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
120
|
+
def emptydoc(xml)
|
121
|
+
out = xml.dup
|
122
|
+
out.xpath(
|
123
|
+
ns("//preface | //sections | //annex | //bibliography/clause | " \
|
124
|
+
"//bibliography/references[not(@hidden = 'true')] | //indexsect | " \
|
125
|
+
"//colophon"),
|
126
|
+
).each(&:remove)
|
127
|
+
out
|
193
128
|
end
|
194
129
|
|
195
|
-
def
|
196
|
-
xml.
|
197
|
-
|
198
|
-
|
199
|
-
ins << b.dup
|
200
|
-
m << b["id"]
|
201
|
-
end
|
130
|
+
def sectionfile(fulldoc, xml, file, chunks, parentnode)
|
131
|
+
fname = create_sectionfile(fulldoc, xml.dup, file, chunks, parentnode)
|
132
|
+
{ order: chunks.last["displayorder"].to_i, url: fname,
|
133
|
+
title: titlerender(chunks.last) }
|
202
134
|
end
|
203
135
|
|
204
|
-
def
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
136
|
+
def create_sectionfile(xml, out, file, chunks, parentnode)
|
137
|
+
ins = out.at(ns("//metanorma-extension")) || out.at(ns("//bibdata"))
|
138
|
+
sectionfile_insert(ins, chunks, parentnode)
|
139
|
+
xref_process(out, xml, @key)
|
140
|
+
outname = "#{file}.xml"
|
141
|
+
File.open(File.join(@splitdir, outname), "w:UTF-8") do |f|
|
142
|
+
f.write(out)
|
211
143
|
end
|
144
|
+
outname
|
212
145
|
end
|
213
146
|
|
214
|
-
def
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
else
|
219
|
-
hash
|
147
|
+
def sectionfile_insert(ins, chunks, parentnode)
|
148
|
+
if parentnode
|
149
|
+
ins.next = "<#{parentnode}/>"
|
150
|
+
chunks.each { |c| ins.next.add_child(c.dup) }
|
151
|
+
else chunks.each { |c| ins.next = c.dup }
|
220
152
|
end
|
221
153
|
end
|
222
154
|
|
@@ -249,7 +181,20 @@ module Metanorma
|
|
249
181
|
end
|
250
182
|
},
|
251
183
|
}
|
252
|
-
recursive_string_keys(ret).to_yaml
|
184
|
+
Util::recursive_string_keys(ret).to_yaml
|
185
|
+
end
|
186
|
+
|
187
|
+
def section_split_cover(col, ident)
|
188
|
+
dir = File.dirname(col.file)
|
189
|
+
collection_setup(nil, dir)
|
190
|
+
CollectionRenderer.new(col, dir,
|
191
|
+
output_folder: "#{ident}_collection",
|
192
|
+
format: %i(html),
|
193
|
+
coverpage: File.join(dir, "cover.html")).coverpage
|
194
|
+
FileUtils.mv "#{ident}_collection/index.html",
|
195
|
+
File.join(dir, "#{ident}_index.html")
|
196
|
+
FileUtils.rm_rf "#{ident}_collection"
|
197
|
+
"#{ident}_index.html"
|
253
198
|
end
|
254
199
|
end
|
255
200
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Metanorma
|
2
|
+
class Sectionsplit
|
3
|
+
def xref_preprocess(xml, fileslookup, identifier)
|
4
|
+
key = (0...8).map { rand(65..90).chr }.join # random string
|
5
|
+
xml.root["type"] = key # to force recognition of internal refs
|
6
|
+
key
|
7
|
+
end
|
8
|
+
|
9
|
+
def xref_process(section, xml, key)
|
10
|
+
refs = eref_to_internal_eref(section, xml, key)
|
11
|
+
refs += xref_to_internal_eref(section, key)
|
12
|
+
ins = new_hidden_ref(section)
|
13
|
+
copied_refs = copy_repo_items_biblio(ins, section, xml)
|
14
|
+
insert_indirect_biblio(ins, refs - copied_refs, key)
|
15
|
+
end
|
16
|
+
|
17
|
+
def svg_preprocess(xml)
|
18
|
+
xml.xpath("//m:svg", "m" => "http://www.w3.org/2000/svg").each do |s|
|
19
|
+
m = svgmap_wrap(s)
|
20
|
+
s.xpath(".//m:a", "m" => "http://www.w3.org/2000/svg").each do |a|
|
21
|
+
next unless /^#/.match? a["href"]
|
22
|
+
|
23
|
+
a["href"] = a["href"].sub(/^#/, "")
|
24
|
+
m << "<target href='#{a['href']}'>" \
|
25
|
+
"<xref target='#{a['href']}'/></target>"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
xml
|
29
|
+
end
|
30
|
+
|
31
|
+
def svgmap_wrap(svg)
|
32
|
+
ret = svg.at("./ancestor::xmlns:svgmap") and return ret
|
33
|
+
ret = svg.at("./ancestor::xmlns:figure")
|
34
|
+
ret.wrap("<svgmap/>")
|
35
|
+
svg.at("./ancestor::xmlns:svgmap")
|
36
|
+
end
|
37
|
+
|
38
|
+
def make_anchor(anchor)
|
39
|
+
"<localityStack><locality type='anchor'><referenceFrom>" \
|
40
|
+
"#{anchor}</referenceFrom></locality></localityStack>"
|
41
|
+
end
|
42
|
+
|
43
|
+
def xref_to_internal_eref(xml, key)
|
44
|
+
xml.xpath(ns("//xref")).each_with_object({}) do |x, m|
|
45
|
+
x["bibitemid"] = "#{key}_#{x['target']}"
|
46
|
+
x << make_anchor(x["target"])
|
47
|
+
m[x["bibitemid"]] = true
|
48
|
+
x.delete("target")
|
49
|
+
x["type"] = key
|
50
|
+
x.name = "eref"
|
51
|
+
end.keys
|
52
|
+
end
|
53
|
+
|
54
|
+
def eref_to_internal_eref(section, xml, key)
|
55
|
+
bibitems = Util::gather_bibitems(xml)
|
56
|
+
bibitemids = Util::gather_bibitemids(section)
|
57
|
+
eref_to_internal_eref_select(section, xml, bibitems)
|
58
|
+
.each_with_object([]) do |x, m|
|
59
|
+
url = bibitems[x]&.at(ns("./uri[@type = 'citation']"))
|
60
|
+
bibitemids[x]&.each do |e|
|
61
|
+
id = eref_to_internal_eref1(e, key, url)
|
62
|
+
id and m << id
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def eref_to_internal_eref1(elem, key, url)
|
68
|
+
if url
|
69
|
+
elem.name = "link"
|
70
|
+
elem["target"] = url
|
71
|
+
nil
|
72
|
+
else
|
73
|
+
elem["bibitemid"] = "#{key}_#{elem['bibitemid']}"
|
74
|
+
elem << make_anchor(elem["bibitemid"])
|
75
|
+
elem["type"] = key
|
76
|
+
elem["bibitemid"]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def eref_to_internal_eref_select(section, _xml, bibitems)
|
81
|
+
refs = Util::gather_bibitemids(section).keys
|
82
|
+
refs.uniq.reject do |x|
|
83
|
+
b = bibitems[x] and (b["type"] == "internal" ||
|
84
|
+
b.at(ns("./docidentifier/@type = 'repository']")))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# from standoc
|
89
|
+
def new_hidden_ref(xmldoc)
|
90
|
+
ins = xmldoc.at("bibliography") or
|
91
|
+
xmldoc.root << "<bibliography/>" and ins = xmldoc.at("bibliography")
|
92
|
+
ins.add_child("<references hidden='true' normative='false'/>").first
|
93
|
+
end
|
94
|
+
|
95
|
+
def copy_repo_items_biblio(ins, section, xml)
|
96
|
+
bibitems = Util::gather_bibitems(section)
|
97
|
+
xml.xpath(ns("//references/bibitem[docidentifier/@type = 'repository']"))
|
98
|
+
.each_with_object([]) do |b, m|
|
99
|
+
bibitems[b["id"]] or next
|
100
|
+
# section.at("//*[@bibitemid = '#{b['id']}']") or next
|
101
|
+
ins << b.dup
|
102
|
+
m << b["id"]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def insert_indirect_biblio(ins, refs, prefix)
|
107
|
+
refs.each do |x|
|
108
|
+
ins << <<~BIBENTRY
|
109
|
+
<bibitem id="#{x}" type="internal">
|
110
|
+
<docidentifier type="repository">#{x.sub(/^#{prefix}_/, "#{prefix}/")}</docidentifier>
|
111
|
+
</bibitem>
|
112
|
+
BIBENTRY
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/lib/metanorma/util.rb
CHANGED
@@ -29,6 +29,37 @@ module Metanorma
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
def self.recursive_string_keys(hash)
|
33
|
+
case hash
|
34
|
+
when Hash then hash.map { |k, v| [k.to_s, recursive_string_keys(v)] }.to_h
|
35
|
+
when Enumerable then hash.map { |v| recursive_string_keys(v) }
|
36
|
+
else
|
37
|
+
hash
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.gather_bibitems(xml)
|
42
|
+
xml.xpath("//xmlns:bibitem[@id]").each_with_object({}) do |b, m|
|
43
|
+
m[b["id"]] = b
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.gather_bibitemids(xml)
|
48
|
+
xml.xpath("//*[@bibitemid]").each_with_object({}) do |e, m|
|
49
|
+
/^semantic__/.match?(e.name) and next
|
50
|
+
m[e["bibitemid"]] ||= []
|
51
|
+
m[e["bibitemid"]] << e
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.gather_citeases(xml)
|
56
|
+
xml.xpath("//*[@citeas]").each_with_object({}) do |e, m|
|
57
|
+
/^semantic__/.match?(e.name) and next
|
58
|
+
m[e["citeas"]] ||= []
|
59
|
+
m[e["citeas"]] << e
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
32
63
|
class DisambigFiles
|
33
64
|
def initialize
|
34
65
|
@seen_filenames = []
|
data/lib/metanorma/version.rb
CHANGED