metanorma 2.0.0 → 2.5.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/.envrc +1 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +23 -2
- data/Gemfile +17 -0
- data/Gemfile.devel +10 -0
- data/README.adoc +1 -1
- data/lib/metanorma/collection/artifact_store.rb +142 -0
- data/lib/metanorma/collection/collection.rb +160 -122
- data/lib/metanorma/collection/config/bibdata.rb +3 -3
- data/lib/metanorma/collection/config/compile_options.rb +4 -5
- data/lib/metanorma/collection/config/config.rb +81 -83
- data/lib/metanorma/collection/config/converters.rb +92 -8
- data/lib/metanorma/collection/config/directive.rb +9 -3
- data/lib/metanorma/collection/config/doc_container.rb +28 -0
- data/lib/metanorma/collection/config/manifest.rb +59 -29
- data/lib/metanorma/collection/config/namespaces.rb +12 -0
- data/lib/metanorma/collection/document/document.rb +56 -15
- data/lib/metanorma/collection/filelookup/filelookup.rb +185 -77
- data/lib/metanorma/collection/filelookup/filelookup_sectionsplit.rb +99 -27
- data/lib/metanorma/collection/filelookup/utils.rb +52 -0
- data/lib/metanorma/collection/helpers.rb +82 -0
- data/lib/metanorma/collection/log.rb +24 -0
- data/lib/metanorma/collection/manifest/manifest.rb +45 -14
- data/lib/metanorma/collection/multilingual/multilingual.rb +660 -0
- data/lib/metanorma/collection/renderer/filelocation.rb +166 -0
- data/lib/metanorma/collection/renderer/fileparse.rb +135 -115
- data/lib/metanorma/collection/renderer/fileprocess.rb +185 -37
- data/lib/metanorma/collection/renderer/navigation.rb +21 -7
- data/lib/metanorma/collection/renderer/render_word.rb +15 -10
- data/lib/metanorma/collection/renderer/renderer.rb +236 -32
- data/lib/metanorma/collection/renderer/svg.rb +107 -0
- data/lib/metanorma/collection/renderer/utils.rb +110 -39
- data/lib/metanorma/collection/sectionsplit/collection.rb +110 -0
- data/lib/metanorma/collection/sectionsplit/sectionsplit.rb +198 -115
- data/lib/metanorma/collection/util/disambig_files.rb +4 -5
- data/lib/metanorma/collection/util/util.rb +155 -18
- data/lib/metanorma/collection/xrefprocess/xrefprocess.rb +47 -33
- data/lib/metanorma/compile/assets/icc-boilerplate.adoc +41 -0
- data/lib/metanorma/compile/compile.rb +181 -156
- data/lib/metanorma/compile/compile_options.rb +186 -79
- data/lib/metanorma/compile/extract.rb +75 -58
- data/lib/metanorma/compile/flavor.rb +28 -0
- data/lib/metanorma/compile/output_filename.rb +75 -0
- data/lib/metanorma/compile/output_filename_config.rb +27 -0
- data/lib/metanorma/compile/relaton_drop.rb +56 -0
- data/lib/metanorma/compile/render.rb +226 -0
- data/lib/metanorma/compile/validator.rb +26 -0
- data/lib/metanorma/compile/writeable.rb +12 -0
- data/lib/metanorma/util/fontist_helper.rb +35 -19
- data/lib/metanorma/version.rb +1 -1
- data/lib/metanorma.rb +1 -7
- data/metanorma.gemspec +15 -21
- data/plans/collection-rendering-architecture-review.md +516 -0
- metadata +65 -113
- data/.hound.yml +0 -5
- data/lib/metanorma/asciidoctor_extensions/glob_include_processor.rb +0 -22
- data/lib/metanorma/asciidoctor_extensions.rb +0 -1
- data/lib/metanorma/compile/compile_validate.rb +0 -68
- data/lib/metanorma/config/config.rb +0 -23
- data/lib/metanorma/input/asciidoc.rb +0 -107
- data/lib/metanorma/input/base.rb +0 -9
- data/lib/metanorma/input.rb +0 -7
- data/lib/metanorma/processor/processor.rb +0 -54
- data/lib/metanorma/processor.rb +0 -6
- data/lib/metanorma/registry/registry.rb +0 -63
- data/lib/metanorma/shale_monkeypatch.rb +0 -15
- data/lib/metanorma/util/util.rb +0 -45
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Metanorma
|
|
4
|
+
class Collection
|
|
5
|
+
class Renderer
|
|
6
|
+
def file_compile_formats(filename, identifier, opts)
|
|
7
|
+
f = @files.get(identifier, :outputs)
|
|
8
|
+
format = opts[:extension_keys]
|
|
9
|
+
concatenate_presentation?({ format: }) and format << :presentation
|
|
10
|
+
format.each do |e|
|
|
11
|
+
e == :pdf and output_filename = opts[:pdffile]
|
|
12
|
+
file_compile_format(filename, identifier, e, f, output_filename)
|
|
13
|
+
end
|
|
14
|
+
@files.set(identifier, :outputs, f)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Generate output filename with correct extension
|
|
18
|
+
def output_filename_with_extension(fname, format)
|
|
19
|
+
ext = @compile.processor.output_formats[format]
|
|
20
|
+
fname_base = File.basename(fname)
|
|
21
|
+
# ONLY replace .xml or .html extensions, NEVER remove section numbers
|
|
22
|
+
if /\.(xml|html)$/.match?(fname_base)
|
|
23
|
+
fname_base.sub(/\.(xml|html)$/, ".#{ext}")
|
|
24
|
+
else
|
|
25
|
+
"#{fname_base}.#{ext}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Move file to new output filename if specified. A member that
|
|
30
|
+
# failed to render has nothing to move: keep the original name
|
|
31
|
+
# registered so output verification reports it as missing, rather
|
|
32
|
+
# than crashing the whole collection on the mv (#586).
|
|
33
|
+
def handle_new_output_filename(output_fname, new_output_fname)
|
|
34
|
+
return output_fname unless new_output_fname
|
|
35
|
+
|
|
36
|
+
src = File.join(@outdir, output_fname)
|
|
37
|
+
File.exist?(src) or return output_fname
|
|
38
|
+
FileUtils.mv(src, File.join(@outdir, new_output_fname))
|
|
39
|
+
new_output_fname
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Apply custom filename pattern with substitutions
|
|
43
|
+
def apply_custom_filename_pattern(ident, custom_fname, output_fname,
|
|
44
|
+
format)
|
|
45
|
+
idx = @files.get(ident, :idx)
|
|
46
|
+
original_file = @files.get(ident, :ref)
|
|
47
|
+
basename = File.basename(original_file, ".*")
|
|
48
|
+
basename_legacy = File.basename(original_file)
|
|
49
|
+
custom_fname = @files.substitute_filename_pattern(
|
|
50
|
+
custom_fname, document_num: idx,
|
|
51
|
+
basename: basename, basename_legacy: basename_legacy
|
|
52
|
+
)
|
|
53
|
+
if File.dirname(custom_fname) == "."
|
|
54
|
+
output_fname
|
|
55
|
+
else
|
|
56
|
+
preserve_output_dir_structure(custom_fname, output_fname,
|
|
57
|
+
format, explicit_custom: true)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Apply directory preservation for files with directory structure
|
|
62
|
+
def apply_directory_preservation(fname, output_fname, format)
|
|
63
|
+
fname_dir = File.dirname(fname)
|
|
64
|
+
output_fname = File.join(fname_dir, output_fname)
|
|
65
|
+
preserve_output_dir_structure(fname, output_fname, format)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Compile single format for a file and update outputs hash
|
|
69
|
+
def file_compile_format(fname, ident, format, outputs, new_output_fname)
|
|
70
|
+
ext = @compile.processor.output_formats[format]
|
|
71
|
+
output_fname = output_filename_with_extension(fname, format)
|
|
72
|
+
output_fname = handle_new_output_filename(output_fname,
|
|
73
|
+
new_output_fname)
|
|
74
|
+
if !new_output_fname && (custom = @files.preserve_directory_structure?(ident))
|
|
75
|
+
output_fname = apply_custom_filename_pattern(ident, custom,
|
|
76
|
+
output_fname, format)
|
|
77
|
+
elsif !new_output_fname && File.dirname(fname) != "."
|
|
78
|
+
output_fname = apply_directory_preservation(fname, output_fname,
|
|
79
|
+
format)
|
|
80
|
+
end
|
|
81
|
+
should_skip = /html$/.match?(ext) && @files.get(ident, :sectionsplit)
|
|
82
|
+
should_skip or outputs[format] = File.join(@outdir, output_fname)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Determine if file should be moved to subdirectory
|
|
86
|
+
def should_move_to_subdirectory?(ext, output_basename, explicit_custom)
|
|
87
|
+
if explicit_custom
|
|
88
|
+
# For explicit output-filename: move html, doc, pdf, presentation.xml
|
|
89
|
+
ext.end_with?("html") || ext == "doc" || ext == "pdf" ||
|
|
90
|
+
output_basename.end_with?(".presentation.xml")
|
|
91
|
+
else
|
|
92
|
+
# Default: only HTML and presentation files
|
|
93
|
+
ext.end_with?("html") ||
|
|
94
|
+
output_basename.end_with?(".html", ".presentation.xml")
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Move file from root to subdirectory
|
|
99
|
+
def move_file_to_subdirectory(fname_dir, output_basename)
|
|
100
|
+
output_with_dir = File.join(fname_dir, output_basename)
|
|
101
|
+
output_dest = File.join(@outdir, output_with_dir)
|
|
102
|
+
output_src = File.join(@outdir, output_basename)
|
|
103
|
+
return nil unless File.exist?(output_src) && output_src != output_dest
|
|
104
|
+
|
|
105
|
+
FileUtils.mkdir_p(File.dirname(output_dest))
|
|
106
|
+
FileUtils.mv(output_src, output_dest)
|
|
107
|
+
output_with_dir
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Handle case where destination already exists
|
|
111
|
+
def handle_existing_destination(output_with_dir, output_src)
|
|
112
|
+
output_dest = File.join(@outdir, output_with_dir)
|
|
113
|
+
return nil unless File.exist?(output_dest)
|
|
114
|
+
return output_with_dir unless File.exist?(output_src)
|
|
115
|
+
|
|
116
|
+
FileUtils.rm_f(output_src)
|
|
117
|
+
err_src = output_src.sub(/\.html$/, ".err.html")
|
|
118
|
+
FileUtils.rm_f(err_src) if File.exist?(err_src)
|
|
119
|
+
output_with_dir
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Generate custom basename with extension
|
|
123
|
+
def custom_basename_with_extension(fname, output_basename)
|
|
124
|
+
custom_basename = File.basename(fname, ".*")
|
|
125
|
+
ext = File.extname(output_basename)
|
|
126
|
+
"#{custom_basename}#{ext}"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Preserve directory structure from input filename in output
|
|
130
|
+
def preserve_output_dir_structure(fname, output_fname, format = nil,
|
|
131
|
+
explicit_custom: false)
|
|
132
|
+
fname_dir = File.dirname(fname)
|
|
133
|
+
return output_fname if fname_dir == "."
|
|
134
|
+
|
|
135
|
+
output_basename = File.basename(output_fname)
|
|
136
|
+
ext = format ? @compile.processor.output_formats[format].to_s : ""
|
|
137
|
+
should_move = should_move_to_subdirectory?(ext, output_basename,
|
|
138
|
+
explicit_custom)
|
|
139
|
+
if should_move
|
|
140
|
+
result = move_file_to_subdirectory(fname_dir, output_basename)
|
|
141
|
+
return result if result
|
|
142
|
+
|
|
143
|
+
handle_existing_destination(File.join(fname_dir, output_basename),
|
|
144
|
+
File.join(@outdir,
|
|
145
|
+
output_basename)) || output_fname
|
|
146
|
+
elsif explicit_custom
|
|
147
|
+
custom_basename_with_extension(fname, output_basename)
|
|
148
|
+
else
|
|
149
|
+
output_basename
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def copy_file_to_dest(identifier)
|
|
154
|
+
out = Pathname.new(@files.get(identifier, :out_path)).cleanpath
|
|
155
|
+
out.absolute? and
|
|
156
|
+
out = out.relative_path_from(File.expand_path(FileUtils.pwd))
|
|
157
|
+
dest = File.join(@outdir,
|
|
158
|
+
@disambig.source2dest_filename(out.to_s,
|
|
159
|
+
preserve_dirs: true))
|
|
160
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
|
161
|
+
source = @files.get(identifier, :ref)
|
|
162
|
+
source != dest and FileUtils.cp_r source, dest, remove_destination: true
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
@@ -4,7 +4,7 @@ module Metanorma
|
|
|
4
4
|
# Resolves references to other files in the collection. Three routines:
|
|
5
5
|
# 1. Eref to a document that has been split into multiple documents
|
|
6
6
|
# (sectionsplit) are resolved to direct eref to the split document
|
|
7
|
-
# 2. Indirect erefs to a file anchor in an
|
|
7
|
+
# 2. Indirect erefs to a file anchor in an unknown file in the collection
|
|
8
8
|
# (bibitem[@type = 'internal'] ) are resolved to direct eref to the
|
|
9
9
|
# containing document
|
|
10
10
|
# 3. Direct erefs to other files in collection
|
|
@@ -14,21 +14,46 @@ module Metanorma
|
|
|
14
14
|
# @param internal_refs [Hash{String=>Hash{String=>String}] schema name to
|
|
15
15
|
# anchor to filename
|
|
16
16
|
# @return [String] XML content
|
|
17
|
+
# Each pass below mutates the SAME Nokogiri tree in place; the inline
|
|
18
|
+
# comments state the post-condition each pass guarantees on exit. The
|
|
19
|
+
# contract between passes is "the tree is now in state X" -- there is no
|
|
20
|
+
# intermediate typed representation, so the ordering is load-bearing.
|
|
21
|
+
# `sso` truthy (sectionsplit_output) => `xml` is Presentation XML and the
|
|
22
|
+
# semantic-only passes are skipped; otherwise `xml` is Semantic XML.
|
|
23
|
+
# See the pipeline map in the collection architecture review plan.
|
|
17
24
|
def update_xrefs(file, docid, internal_refs)
|
|
18
25
|
xml, sso = update_xrefs_prep(file, docid)
|
|
19
|
-
|
|
26
|
+
# post: repository docidentifiers supplied on bibitems naming a
|
|
27
|
+
# collection file; `sso` resolved (Presentation vs Semantic).
|
|
28
|
+
@nested || sso || @reinflate or
|
|
20
29
|
Metanorma::Collection::XrefProcess::xref_process(xml, xml, nil, docid,
|
|
21
|
-
@isodoc)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
@isodoc, sso)
|
|
31
|
+
# post (semantic only): intra-doc xref/eref turned into internal erefs;
|
|
32
|
+
# repo bibitems copied; indirect bibliography inserted.
|
|
33
|
+
@ncnames = {}
|
|
34
|
+
@nested or update_indirect_refs_to_docs(xml, docid, internal_refs, sso)
|
|
35
|
+
# post: bibitem[@type='internal'] anchors resolved to the containing
|
|
36
|
+
# collection document.
|
|
37
|
+
@reinflate or @files.add_document_suffix(docid, xml)
|
|
38
|
+
# post: every @id/@anchor namespaced with this doc's NCName suffix, so
|
|
39
|
+
# concatenated documents do not collide.
|
|
40
|
+
@nested or update_sectionsplit_refs_to_docs(xml, docid, internal_refs,
|
|
41
|
+
sso)
|
|
42
|
+
# post: erefs targeting a sectionsplit document point at the specific
|
|
43
|
+
# split section file that holds the anchor.
|
|
44
|
+
update_direct_refs_to_docs(xml, docid, sso)
|
|
45
|
+
# post: repo(current-metanorma-collection/x) bibitems replaced in situ
|
|
46
|
+
# with resolved bibdata + citation URI; their erefs become hyperlinks.
|
|
47
|
+
::Metanorma::Collection::Util::hide_refs(xml)
|
|
48
|
+
# post: references containers with only hidden bibitems flagged hidden.
|
|
49
|
+
sso and eref2link(xml, sso)
|
|
50
|
+
@nested || @reinflate or svgmap_resolve(xml, docid, sso)
|
|
29
51
|
xml.to_xml
|
|
30
52
|
end
|
|
31
53
|
|
|
54
|
+
## sso (sectionsplit_output) truthy => Presentation XML, else Semantic.
|
|
55
|
+
## This is the single discriminator that decides which grammar `xml`
|
|
56
|
+
## carries and therefore which passes in update_xrefs run.
|
|
32
57
|
def update_xrefs_prep(file, docid)
|
|
33
58
|
docxml = file.is_a?(String) ? Nokogiri::XML(file, &:huge) : file
|
|
34
59
|
supply_repo_ids(docxml)
|
|
@@ -36,8 +61,9 @@ module Metanorma
|
|
|
36
61
|
[docxml, sso]
|
|
37
62
|
end
|
|
38
63
|
|
|
39
|
-
def update_sectionsplit_refs_to_docs(docxml, internal_refs
|
|
40
|
-
|
|
64
|
+
def update_sectionsplit_refs_to_docs(docxml, docid, internal_refs,
|
|
65
|
+
presxml)
|
|
66
|
+
Util::gather_citeases(docxml, presxml).each do |k, v|
|
|
41
67
|
(@files.get(k) && @files.get(k, :sectionsplit)) or next
|
|
42
68
|
opts = { key: @files.get(k, :indirect_key),
|
|
43
69
|
source_suffix: docxml.root["document_suffix"],
|
|
@@ -45,13 +71,15 @@ module Metanorma
|
|
|
45
71
|
refs = v.each_with_object({}) do |eref, m|
|
|
46
72
|
update_sectionsplit_eref_to_doc(eref, internal_refs, m, opts)
|
|
47
73
|
end
|
|
48
|
-
add_hidden_bibliography(docxml, refs)
|
|
74
|
+
add_hidden_bibliography(docxml, refs, docid)
|
|
49
75
|
end
|
|
50
76
|
end
|
|
51
77
|
|
|
78
|
+
ANCHOR_XPATH = "xmlns:locality[@type = 'anchor']/xmlns:referenceFrom"
|
|
79
|
+
.freeze
|
|
80
|
+
|
|
52
81
|
def update_sectionsplit_eref_to_doc(eref, internal_refs, doclist, opts)
|
|
53
|
-
a = eref.at(
|
|
54
|
-
"referenceFrom")) or return
|
|
82
|
+
a = eref.at("./xmlns:localityStack/#{ANCHOR_XPATH}") or return
|
|
55
83
|
doc = internal_refs[opts[:key]]["#{a.text}_#{opts[:target_suffix]}"]
|
|
56
84
|
bibitemid = Metanorma::Utils::to_ncname("#{doc}_#{opts[:source_suffix]}")
|
|
57
85
|
eref["bibitemid"] = bibitemid
|
|
@@ -59,21 +87,9 @@ module Metanorma
|
|
|
59
87
|
doclist
|
|
60
88
|
end
|
|
61
89
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
ins.at(ns("./referenced[@hidden = 'true']")) or
|
|
66
|
-
ins.add_child("<references hidden='true' normative='false'/>").first
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def eref2link(docxml)
|
|
70
|
-
isodoc = IsoDoc::PresentationXMLConvert.new({})
|
|
71
|
-
isodoc.bibitem_lookup(docxml)
|
|
72
|
-
isodoc.eref2link(docxml)
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
BIBITEM_NOT_REPO_XPATH = "//bibitem[not(ancestor::bibitem)]" \
|
|
76
|
-
"[not(./docidentifier[@type = 'repository'])]".freeze
|
|
90
|
+
BIBITEM_NOT_REPO_XPATH = <<~XPATH.strip
|
|
91
|
+
//bibitem[not(ancestor::bibitem)][not(ancestor::bibdata)][not(./docidentifier[@type = 'repository'])]
|
|
92
|
+
XPATH
|
|
77
93
|
|
|
78
94
|
def supply_repo_ids(doc)
|
|
79
95
|
doc.xpath(ns(BIBITEM_NOT_REPO_XPATH)).each do |b|
|
|
@@ -86,47 +102,39 @@ module Metanorma
|
|
|
86
102
|
end
|
|
87
103
|
end
|
|
88
104
|
|
|
89
|
-
def svgmap_resolve(docxml, docid)
|
|
90
|
-
ids = @files.get(docid, :ids)
|
|
91
|
-
dir = File.join(@dirname, File.dirname(@files.get(docid, :rel_path)))
|
|
92
|
-
docxml = datauri_encode(docxml, dir)
|
|
93
|
-
isodoc = IsoDoc::PresentationXMLConvert.new({})
|
|
94
|
-
isodoc.bibitem_lookup(docxml)
|
|
95
|
-
docxml.xpath(ns("//svgmap//eref")).each do |e|
|
|
96
|
-
svgmap_resolve1(e, isodoc, docxml, ids)
|
|
97
|
-
end
|
|
98
|
-
Vectory::SvgMapping.new(docxml, "").call
|
|
99
|
-
docxml.xpath(ns("//svgmap")).each { |s| isodoc.svgmap_extract(s) }
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def svgmap_resolve1(eref, isodoc, _docxml, ids)
|
|
103
|
-
href = isodoc.eref_target(eref) or return
|
|
104
|
-
href == "##{eref['bibitemid']}" ||
|
|
105
|
-
(href =~ /^#/ && !ids[href.sub(/^#/, "")]) and return
|
|
106
|
-
eref["target"] = href.strip
|
|
107
|
-
eref.name = "link"
|
|
108
|
-
eref.elements&.remove
|
|
109
|
-
end
|
|
110
|
-
|
|
111
105
|
# repo(current-metanorma-collection/ISO 17301-1:2016)
|
|
112
106
|
# replaced by bibdata of "ISO 17301-1:2016" in situ as bibitem.
|
|
113
107
|
# Any erefs to that bibitem id are replaced with relative URL
|
|
114
108
|
# Preferably with anchor, and is a job to realise dynamic lookup
|
|
115
109
|
# of localities.
|
|
116
|
-
def update_direct_refs_to_docs(
|
|
117
|
-
erefs, erefs1 =
|
|
118
|
-
|
|
110
|
+
def update_direct_refs_to_docs(xml, identifier, presxml)
|
|
111
|
+
erefs, erefs_no_anchor, anchors, erefs1 =
|
|
112
|
+
update_direct_refs_to_docs_prep(xml, presxml)
|
|
113
|
+
x = xml.xpath(ns("//bibitem")) - xml.xpath(ns("//bibdata//bibitem"))
|
|
114
|
+
x.each do |b|
|
|
119
115
|
docid = b.at(ns("./docidentifier[@type = 'repository']")) or next
|
|
120
116
|
strip_unresolved_repo_erefs(identifier, docid, erefs1, b) or next
|
|
121
117
|
update_bibitem(b, identifier)
|
|
122
118
|
docid = docid_to_citeas(b) or next
|
|
123
|
-
erefs[docid] and
|
|
119
|
+
erefs[docid] and
|
|
120
|
+
update_anchors(b, docid, erefs[docid], erefs_no_anchor[docid],
|
|
121
|
+
anchors[docid])
|
|
124
122
|
end
|
|
125
123
|
end
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
125
|
+
# Hash(docid) of arrays
|
|
126
|
+
def update_direct_refs_to_docs_prep(docxml, presxml)
|
|
127
|
+
erefs = Util::gather_citeases(docxml, presxml)
|
|
128
|
+
no_anchor = erefs.keys.each_with_object({}) { |k, m| m[k] = [] }
|
|
129
|
+
anchors = erefs.keys.each_with_object({}) { |k, m| m[k] = [] }
|
|
130
|
+
erefs.each do |k, v|
|
|
131
|
+
v.each do |e|
|
|
132
|
+
if loc = e.at(".//#{ANCHOR_XPATH}") then anchors[k] << loc
|
|
133
|
+
else no_anchor[k] << e
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
[erefs, no_anchor, anchors, Util::gather_bibitemids(docxml, presxml)]
|
|
130
138
|
end
|
|
131
139
|
|
|
132
140
|
# strip erefs if they are repository erefs, but do not point to a document
|
|
@@ -135,8 +143,13 @@ module Metanorma
|
|
|
135
143
|
# Do not do this if this is a sectionsplit collection or a nested manifest.
|
|
136
144
|
# Return false if bibitem is not to be further processed
|
|
137
145
|
def strip_unresolved_repo_erefs(_document_id, bib_docid, erefs, bibitem)
|
|
138
|
-
%r{^current-metanorma-collection/(?!Missing:)}.match?(bib_docid.text)
|
|
146
|
+
if %r{^current-metanorma-collection/(?!Missing:)}.match?(bib_docid.text)
|
|
147
|
+
# Isolated build: keep the cross-document ref as a stub (its bibitemid
|
|
148
|
+
# and repository docidentifier intact) for a later reinflation pass to
|
|
149
|
+
# relink, rather than resolving it now against an absent target.
|
|
150
|
+
@preserve_unresolved and return false
|
|
139
151
|
return true
|
|
152
|
+
end
|
|
140
153
|
@nested and return false
|
|
141
154
|
erefs[bibitem["id"]]&.each { |x| x.parent and strip_eref(x) }
|
|
142
155
|
false
|
|
@@ -144,90 +157,98 @@ module Metanorma
|
|
|
144
157
|
|
|
145
158
|
# Resolve erefs to a container of ids in another doc,
|
|
146
159
|
# to an anchor eref (direct link)
|
|
147
|
-
def update_indirect_refs_to_docs(docxml,
|
|
148
|
-
|
|
160
|
+
def update_indirect_refs_to_docs(docxml, _docid, internal_refs, presxml)
|
|
161
|
+
bib, erefs, doc_suffix, doc_type, f = update_indirect_refs_prep(docxml,
|
|
162
|
+
presxml)
|
|
149
163
|
internal_refs.each do |schema, ids|
|
|
164
|
+
add_suffix = doc_suffix && doc_type && doc_type != schema
|
|
150
165
|
ids.each do |id, file|
|
|
151
|
-
|
|
152
|
-
|
|
166
|
+
f[file] ||= { url: @files.url?(file),
|
|
167
|
+
parentid: @files.get(file) && @files.get(file,
|
|
168
|
+
:parentid) }
|
|
169
|
+
k = indirect_ref_key(schema, id, doc_suffix, add_suffix)
|
|
170
|
+
update_indirect_refs_to_docs1(f[file], k, file, bib, erefs)
|
|
153
171
|
end
|
|
154
172
|
end
|
|
155
173
|
end
|
|
156
174
|
|
|
157
|
-
def
|
|
175
|
+
def update_indirect_refs_prep(docxml, presxml)
|
|
158
176
|
@updated_anchors = {}
|
|
159
|
-
|
|
177
|
+
@indirect_keys = {}
|
|
178
|
+
[Util::gather_bibitems(docxml), Util::gather_bibitemids(docxml, presxml),
|
|
179
|
+
docxml.root["document_suffix"], docxml.root["type"], {}]
|
|
160
180
|
end
|
|
161
181
|
|
|
162
|
-
def indirect_ref_key(schema, id,
|
|
182
|
+
def indirect_ref_key(schema, id, doc_suffix, add_suffix)
|
|
163
183
|
/^#{schema}_/.match?(id) and return id
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
184
|
+
x = @indirect_keys.dig(schema, id) and return x
|
|
185
|
+
@indirect_keys[schema] ||= {}
|
|
186
|
+
@indirect_keys[schema][id] = if add_suffix
|
|
187
|
+
"#{schema}_#{id}_#{doc_suffix}"
|
|
188
|
+
else
|
|
189
|
+
"#{schema}_#{id}"
|
|
190
|
+
end
|
|
169
191
|
end
|
|
170
192
|
|
|
171
|
-
def update_indirect_refs_to_docs1(
|
|
193
|
+
def update_indirect_refs_to_docs1(filec, key, file, bibitems, erefs)
|
|
172
194
|
erefs[key]&.each do |e|
|
|
173
195
|
e["citeas"] = file
|
|
174
|
-
update_indirect_refs_to_docs_anchor(e, file
|
|
196
|
+
update_indirect_refs_to_docs_anchor(e, file, filec[:url],
|
|
197
|
+
filec[:parentid])
|
|
175
198
|
end
|
|
176
199
|
update_indirect_refs_to_docs_docid(bibitems[key], file)
|
|
177
200
|
end
|
|
178
201
|
|
|
179
|
-
def update_indirect_refs_to_docs_anchor(eref, file)
|
|
180
|
-
a = eref.at(
|
|
181
|
-
|
|
182
|
-
@files.get(file) && p = @files.get(file, :parentid) and
|
|
183
|
-
suffix = "#{p}_#{suffix}"
|
|
202
|
+
def update_indirect_refs_to_docs_anchor(eref, file, url, parentid)
|
|
203
|
+
a = eref.at(".//#{ANCHOR_XPATH}") or return
|
|
204
|
+
parentid and file = "#{parentid}_#{file}"
|
|
184
205
|
existing = a.text
|
|
185
|
-
anchor = existing
|
|
186
|
-
|
|
187
|
-
|
|
206
|
+
anchor = if url then existing
|
|
207
|
+
else
|
|
208
|
+
@indirect_keys[existing] ||= {}
|
|
209
|
+
@indirect_keys[existing][file] ||= Metanorma::Utils::to_ncname("#{existing}_#{file}")
|
|
210
|
+
end
|
|
188
211
|
@updated_anchors[existing] or a.children = anchor
|
|
189
212
|
@updated_anchors[anchor] = true
|
|
190
213
|
end
|
|
191
214
|
|
|
192
|
-
def update_indirect_refs_to_docs_docid(
|
|
193
|
-
docid =
|
|
194
|
-
return
|
|
215
|
+
def update_indirect_refs_to_docs_docid(bib, file)
|
|
216
|
+
docid = bib&.at(ns("./docidentifier[@type = 'repository']")) or return
|
|
195
217
|
docid.children = "current-metanorma-collection/#{file}"
|
|
196
218
|
docid.previous =
|
|
197
219
|
"<docidentifier type='metanorma-collection'>#{file}</docidentifier>"
|
|
198
220
|
end
|
|
199
221
|
|
|
200
|
-
#
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
222
|
+
# bottleneck
|
|
223
|
+
def update_anchors(bib, docid, erefs, erefs_no_anchor, erefs_anchors)
|
|
224
|
+
@files.get(docid) or error_anchor(erefs, docid)
|
|
225
|
+
has_anchors, url, ncn_docid = update_anchors_prep(docid)
|
|
226
|
+
erefs_no_anchor.each do |e|
|
|
227
|
+
update_anchor_create_loc(bib, e, docid)
|
|
228
|
+
end
|
|
229
|
+
!url && has_anchors or return
|
|
230
|
+
erefs_anchors.each do |e|
|
|
231
|
+
update_anchors1(docid, ncn_docid, e)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def update_anchors1(docid, ncn_docid, anchor)
|
|
236
|
+
@concat_anchors[anchor.text] ||= "#{ncn_docid}_#{anchor.text}"
|
|
237
|
+
if @files.get(docid).dig(:anchors_lookup, @concat_anchors[anchor.text])
|
|
238
|
+
anchor.content = @concat_anchors[anchor.text]
|
|
212
239
|
end
|
|
213
240
|
end
|
|
214
241
|
|
|
215
|
-
def
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
anchor = suffix_anchor(ref, docid)
|
|
220
|
-
a = @files.get(docid, :anchors) or return
|
|
221
|
-
a.inject([]) { |m, (_, x)| m + x.values }
|
|
222
|
-
.include?(anchor) or return
|
|
223
|
-
ref.content = anchor
|
|
242
|
+
def update_anchors_prep(docid)
|
|
243
|
+
@concat_anchors = {}
|
|
244
|
+
[@files.get(docid)&.key?(:anchors_lookup), @files.url?(docid),
|
|
245
|
+
Metanorma::Utils::to_ncname(docid)]
|
|
224
246
|
end
|
|
225
247
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
@
|
|
230
|
-
anchor
|
|
248
|
+
# encode both prefix and suffix to NCName
|
|
249
|
+
def suffix_anchor_indirect(prefix, suffix)
|
|
250
|
+
k = "#{prefix}_#{suffix}"
|
|
251
|
+
@ncnames[k] ||= Metanorma::Utils::to_ncname(k)
|
|
231
252
|
end
|
|
232
253
|
|
|
233
254
|
# if there is a crossref to another document, with no anchor, retrieve the
|
|
@@ -237,10 +258,9 @@ module Metanorma
|
|
|
237
258
|
type = ins.at(ns("./locality/@type"))&.text
|
|
238
259
|
type = "clause" if type == "annex"
|
|
239
260
|
ref = ins.at(ns("./locality/referenceFrom"))&.text
|
|
240
|
-
|
|
241
|
-
ins << "<locality type='anchor'><referenceFrom>#{
|
|
242
|
-
|
|
243
|
-
"</referenceFrom></locality>"
|
|
261
|
+
a = @files.get(docid, :anchors).dig(type, ref) or return
|
|
262
|
+
ins << "<locality type='anchor'><referenceFrom>#{a}" \
|
|
263
|
+
"</referenceFrom></locality>"
|
|
244
264
|
end
|
|
245
265
|
end
|
|
246
266
|
end
|