metanorma-standoc 1.9.0 → 1.10.0
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 +3 -13
- data/.hound.yml +3 -1
- data/.rubocop.yml +4 -8
- data/lib/asciidoctor/standoc/base.rb +31 -35
- data/lib/asciidoctor/standoc/biblio.rng +1 -0
- data/lib/asciidoctor/standoc/blocks.rb +25 -9
- data/lib/asciidoctor/standoc/blocks_notes.rb +41 -24
- data/lib/asciidoctor/standoc/cleanup.rb +59 -84
- data/lib/asciidoctor/standoc/cleanup_block.rb +63 -85
- data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +28 -15
- data/lib/asciidoctor/standoc/cleanup_footnotes.rb +1 -0
- data/lib/asciidoctor/standoc/cleanup_image.rb +71 -0
- data/lib/asciidoctor/standoc/cleanup_inline.rb +117 -77
- data/lib/asciidoctor/standoc/cleanup_maths.rb +36 -27
- data/lib/asciidoctor/standoc/cleanup_ref.rb +31 -15
- data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +1 -1
- data/lib/asciidoctor/standoc/cleanup_reqt.rb +47 -0
- data/lib/asciidoctor/standoc/cleanup_section.rb +77 -135
- data/lib/asciidoctor/standoc/cleanup_section_names.rb +75 -0
- data/lib/asciidoctor/standoc/cleanup_terms.rb +19 -18
- data/lib/asciidoctor/standoc/converter.rb +7 -2
- data/lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb +67 -66
- data/lib/asciidoctor/standoc/front.rb +35 -18
- data/lib/asciidoctor/standoc/front_contributor.rb +70 -45
- data/lib/asciidoctor/standoc/inline.rb +45 -34
- data/lib/asciidoctor/standoc/isodoc.rng +209 -4
- data/lib/asciidoctor/standoc/lists.rb +4 -2
- data/lib/asciidoctor/standoc/macros.rb +11 -11
- data/lib/asciidoctor/standoc/macros_form.rb +63 -0
- data/lib/asciidoctor/standoc/macros_plantuml.rb +19 -21
- data/lib/asciidoctor/standoc/macros_terms.rb +33 -23
- data/lib/asciidoctor/standoc/ref.rb +87 -112
- data/lib/asciidoctor/standoc/ref_date_id.rb +62 -0
- data/lib/asciidoctor/standoc/ref_sect.rb +20 -17
- data/lib/asciidoctor/standoc/section.rb +3 -1
- data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +40 -27
- data/lib/asciidoctor/standoc/terms.rb +25 -18
- data/lib/asciidoctor/standoc/utils.rb +35 -9
- data/lib/asciidoctor/standoc/validate.rb +48 -33
- data/lib/metanorma-standoc.rb +0 -1
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +4 -4
- data/spec/asciidoctor/base_spec.rb +701 -508
- data/spec/asciidoctor/blocks_spec.rb +831 -738
- data/spec/asciidoctor/cleanup_sections_spec.rb +51 -14
- data/spec/asciidoctor/cleanup_spec.rb +889 -682
- data/spec/asciidoctor/inline_spec.rb +62 -14
- data/spec/asciidoctor/isobib_cache_spec.rb +404 -358
- data/spec/asciidoctor/lists_spec.rb +149 -137
- data/spec/asciidoctor/macros_plantuml_spec.rb +8 -8
- data/spec/asciidoctor/macros_spec.rb +923 -503
- data/spec/asciidoctor/macros_yaml2text_spec.rb +1 -1
- data/spec/asciidoctor/refs_dl_spec.rb +4 -4
- data/spec/asciidoctor/refs_spec.rb +1528 -1533
- data/spec/asciidoctor/section_spec.rb +405 -299
- data/spec/asciidoctor/table_spec.rb +6 -6
- data/spec/asciidoctor/validate_spec.rb +342 -304
- data/spec/spec_helper.rb +13 -9
- data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +54 -54
- data/spec/vcr_cassettes/isobib_get_123.yml +13 -13
- data/spec/vcr_cassettes/isobib_get_123_1.yml +25 -25
- data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +37 -37
- data/spec/vcr_cassettes/isobib_get_123_2001.yml +12 -12
- data/spec/vcr_cassettes/isobib_get_124.yml +13 -13
- data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
- data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
- metadata +16 -15
- data/lib/liquid/custom_blocks/key_iterator.rb +0 -21
- data/lib/liquid/custom_blocks/with_json_nested_context.rb +0 -18
- data/lib/liquid/custom_blocks/with_yaml_nested_context.rb +0 -19
- data/lib/liquid/custom_filters/values.rb +0 -7
@@ -37,14 +37,15 @@ module Asciidoctor
|
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
40
|
-
def insert_thead(
|
41
|
-
thead =
|
40
|
+
def insert_thead(table)
|
41
|
+
thead = table.at("./thead")
|
42
42
|
return thead unless thead.nil?
|
43
|
-
|
43
|
+
|
44
|
+
if tname = table.at("./name")
|
44
45
|
thead = tname.add_next_sibling("<thead/>").first
|
45
46
|
return thead
|
46
47
|
end
|
47
|
-
|
48
|
+
table.children.first.add_previous_sibling("<thead/>").first
|
48
49
|
end
|
49
50
|
|
50
51
|
def header_rows_cleanup(xmldoc)
|
@@ -80,21 +81,21 @@ module Asciidoctor
|
|
80
81
|
end
|
81
82
|
|
82
83
|
# include where definition list inside stem block
|
83
|
-
def formula_cleanup(
|
84
|
-
formula_cleanup_where1(
|
85
|
-
formula_cleanup_where2(
|
84
|
+
def formula_cleanup(formula)
|
85
|
+
formula_cleanup_where1(formula)
|
86
|
+
formula_cleanup_where2(formula)
|
86
87
|
end
|
87
88
|
|
88
|
-
def formula_cleanup_where1(
|
89
|
+
def formula_cleanup_where1(formula)
|
89
90
|
q = "//formula/following-sibling::*[1][self::dl]"
|
90
|
-
|
91
|
+
formula.xpath(q).each do |s|
|
91
92
|
s["key"] == "true" and s.previous_element << s.remove
|
92
93
|
end
|
93
94
|
end
|
94
95
|
|
95
|
-
def formula_cleanup_where2(
|
96
|
+
def formula_cleanup_where2(formula)
|
96
97
|
q = "//formula/following-sibling::*[1][self::p]"
|
97
|
-
|
98
|
+
formula.xpath(q).each do |s|
|
98
99
|
if s.text =~ /^\s*where[^a-z]*$/i && s&.next_element&.name == "dl"
|
99
100
|
s.next_element["key"] = "true"
|
100
101
|
s.previous_element << s.next_element.remove
|
@@ -125,9 +126,10 @@ module Asciidoctor
|
|
125
126
|
# examples containing only figures become subfigures of figures
|
126
127
|
def subfigure_cleanup(xmldoc)
|
127
128
|
xmldoc.xpath("//example[figure]").each do |e|
|
128
|
-
next unless e.elements.map
|
129
|
+
next unless e.elements.map(&:name).reject do |m|
|
129
130
|
%w(name figure).include? m
|
130
131
|
end.empty?
|
132
|
+
|
131
133
|
e.name = "figure"
|
132
134
|
end
|
133
135
|
end
|
@@ -142,7 +144,7 @@ module Asciidoctor
|
|
142
144
|
ELEMS_ALLOW_NOTES = %w[p formula ul ol dl figure].freeze
|
143
145
|
|
144
146
|
# if a note is at the end of a section, it is left alone
|
145
|
-
# if a note is followed by a non-note block,
|
147
|
+
# if a note is followed by a non-note block,
|
146
148
|
# it is moved inside its preceding block if it is not delimited
|
147
149
|
# (so there was no way of making that block include the note)
|
148
150
|
def note_cleanup(xmldoc)
|
@@ -150,6 +152,7 @@ module Asciidoctor
|
|
150
152
|
xmldoc.xpath(q).each do |n|
|
151
153
|
next if n["keep-separate"] == "true"
|
152
154
|
next unless n.ancestors("table").empty?
|
155
|
+
|
153
156
|
prev = n.previous_element || next
|
154
157
|
n.parent = prev if ELEMS_ALLOW_NOTES.include? prev.name
|
155
158
|
end
|
@@ -159,100 +162,75 @@ module Asciidoctor
|
|
159
162
|
end
|
160
163
|
end
|
161
164
|
|
162
|
-
def
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
def requirement_inherit(x)
|
168
|
-
x.xpath("//requirement | //recommendation | //permission").each do |r|
|
169
|
-
ins = r.at("./classification") ||
|
170
|
-
r.at("./description | ./measurementtarget | ./specification | "\
|
171
|
-
"./verification | ./import | ./description | ./requirement | "\
|
172
|
-
"./recommendation | ./permission")
|
173
|
-
r.xpath("./*//inherit").each { |i| ins.previous = i }
|
165
|
+
def link_callouts_to_annotations(callouts, annotations)
|
166
|
+
callouts.each_with_index do |c, i|
|
167
|
+
c["target"] = "_#{UUIDTools::UUID.random_create}"
|
168
|
+
annotations[i]["id"] = c["target"]
|
174
169
|
end
|
175
170
|
end
|
176
171
|
|
177
|
-
def
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
e.before(t)
|
184
|
-
t.children = e.remove
|
185
|
-
end
|
186
|
-
end
|
187
|
-
requirement_cleanup1(r)
|
172
|
+
def align_callouts_to_annotations(xmldoc)
|
173
|
+
xmldoc.xpath("//sourcecode").each do |x|
|
174
|
+
callouts = x.elements.select { |e| e.name == "callout" }
|
175
|
+
annotations = x.elements.select { |e| e.name == "annotation" }
|
176
|
+
callouts.size == annotations.size and
|
177
|
+
link_callouts_to_annotations(callouts, annotations)
|
188
178
|
end
|
189
179
|
end
|
190
180
|
|
191
|
-
def
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
end
|
197
|
-
r.xpath("./description[normalize-space(.)='']").each do |d|
|
198
|
-
d.replace("\n")
|
181
|
+
def merge_annotations_into_sourcecode(xmldoc)
|
182
|
+
xmldoc.xpath("//sourcecode").each do |x|
|
183
|
+
while x&.next_element&.name == "annotation"
|
184
|
+
x.next_element.parent = x
|
185
|
+
end
|
199
186
|
end
|
200
187
|
end
|
201
188
|
|
202
|
-
def
|
203
|
-
|
204
|
-
|
205
|
-
Metanorma::Utils::svgmap_rewrite(xmldoc, @localdir)
|
189
|
+
def callout_cleanup(xmldoc)
|
190
|
+
merge_annotations_into_sourcecode(xmldoc)
|
191
|
+
align_callouts_to_annotations(xmldoc)
|
206
192
|
end
|
207
193
|
|
208
|
-
def
|
209
|
-
|
210
|
-
|
211
|
-
|
194
|
+
def sourcecode_cleanup(xmldoc)
|
195
|
+
xmldoc.xpath("//sourcecode").each do |x|
|
196
|
+
x.traverse do |n|
|
197
|
+
next unless n.text?
|
198
|
+
next unless /#{Regexp.escape(@sourcecode_markup_start)}/
|
199
|
+
.match?(n.text)
|
212
200
|
|
213
|
-
|
214
|
-
xmldoc.xpath("//svgmap").each do |s|
|
215
|
-
f = s.at(".//figure") or next
|
216
|
-
if t = s.at("./name") and !f.at("./name")
|
217
|
-
f.children.first.previous = t.remove
|
201
|
+
n.replace(sourcecode_markup(n))
|
218
202
|
end
|
219
|
-
if s["id"] && guid?(f["id"])
|
220
|
-
f["id"] = s["id"]
|
221
|
-
s.delete("id")
|
222
|
-
end
|
223
|
-
svgmap_moveattrs1(s, f)
|
224
203
|
end
|
225
204
|
end
|
226
205
|
|
227
|
-
def
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
s.delete(a)
|
233
|
-
end
|
206
|
+
def safe_noko(text, doc)
|
207
|
+
Nokogiri::XML::Text.new(text, doc).to_xml(
|
208
|
+
encoding: "US-ASCII",
|
209
|
+
save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
|
210
|
+
)
|
234
211
|
end
|
235
212
|
|
236
|
-
def
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
213
|
+
def sourcecode_markup(node)
|
214
|
+
acc = []
|
215
|
+
node.text.split(/(#{Regexp.escape(@sourcecode_markup_start)}|
|
216
|
+
#{Regexp.escape(@sourcecode_markup_end)})/x)
|
217
|
+
.each_slice(4).map do |a|
|
218
|
+
acc << safe_noko(a[0], node.document)
|
219
|
+
next unless a.size == 4
|
220
|
+
|
221
|
+
acc << Asciidoctor.convert(
|
222
|
+
a[2], doctype: :inline, backend: (self&.backend&.to_sym || :standoc)
|
223
|
+
)
|
247
224
|
end
|
225
|
+
acc.join
|
248
226
|
end
|
249
227
|
|
250
|
-
def
|
251
|
-
|
252
|
-
|
253
|
-
|
228
|
+
def form_cleanup(xmldoc)
|
229
|
+
xmldoc.xpath("//select").each do |s|
|
230
|
+
while s&.next_element&.name == "option"
|
231
|
+
s << s.next_element
|
232
|
+
end
|
254
233
|
end
|
255
|
-
nodeset.text.sub(/^[,; ]/, "").strip
|
256
234
|
end
|
257
235
|
end
|
258
236
|
end
|
@@ -38,17 +38,23 @@ module Asciidoctor
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
def norm_ref_preface(
|
42
|
-
|
43
|
-
|
41
|
+
def norm_ref_preface(ref)
|
42
|
+
if ref.at("./note[@type = 'boilerplate']")
|
43
|
+
unwrap_boilerplate_clauses(ref, ".")
|
44
|
+
else
|
45
|
+
refs = ref.elements.select do |e|
|
46
|
+
%w(references bibitem).include? e.name
|
47
|
+
end
|
48
|
+
pref = refs.empty? ? @i18n.norm_empty_pref : @i18n.norm_with_refs_pref
|
49
|
+
ref.at("./title").next = "<p>#{pref}</p>"
|
44
50
|
end
|
45
|
-
f.at("./title").next =
|
46
|
-
"<p>#{(refs.empty? ? @i18n.norm_empty_pref : @i18n.norm_with_refs_pref)}</p>"
|
47
51
|
end
|
48
52
|
|
49
|
-
TERM_CLAUSE = "//sections/terms |
|
53
|
+
TERM_CLAUSE = "//sections/terms | "\
|
54
|
+
"//sections/clause[descendant::terms]".freeze
|
50
55
|
|
51
|
-
NORM_REF = "//bibliography/references[@normative = 'true']"
|
56
|
+
NORM_REF = "//bibliography/references[@normative = 'true'] | "\
|
57
|
+
"//bibliography/clause[.//references[@normative = 'true']]".freeze
|
52
58
|
|
53
59
|
def boilerplate_isodoc(xmldoc)
|
54
60
|
x = xmldoc.dup
|
@@ -67,25 +73,32 @@ module Asciidoctor
|
|
67
73
|
xmldoc.xpath("//terms/p | //terms/ul").each(&:remove)
|
68
74
|
end
|
69
75
|
|
70
|
-
def
|
71
|
-
xmldoc.xpath(
|
72
|
-
f.xpath(".//clause[@type = 'boilerplate']
|
76
|
+
def unwrap_boilerplate_clauses(xmldoc, xpath)
|
77
|
+
xmldoc.xpath(xpath).each do |f|
|
78
|
+
f.xpath(".//clause[@type = 'boilerplate'] | "\
|
79
|
+
".//note[@type = 'boilerplate']").each do |c|
|
73
80
|
c&.at("./title")&.remove
|
74
81
|
c.replace(c.children)
|
75
82
|
end
|
76
83
|
end
|
77
84
|
end
|
78
85
|
|
79
|
-
def
|
80
|
-
isodoc = boilerplate_isodoc(xmldoc)
|
81
|
-
termdef_boilerplate_cleanup(xmldoc)
|
86
|
+
def termdef_boilerplate_insert(xmldoc, isodoc, once = false)
|
82
87
|
xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
|
83
88
|
next if f.at("./clause[@type = 'boilerplate']")
|
84
89
|
|
85
|
-
term_defs_boilerplate(f.at("./title"),
|
90
|
+
term_defs_boilerplate(f.at("./title"),
|
91
|
+
xmldoc.xpath(".//termdocsource"),
|
86
92
|
f.at(".//term"), f.at(".//p"), isodoc)
|
93
|
+
break if once
|
87
94
|
end
|
88
|
-
|
95
|
+
end
|
96
|
+
|
97
|
+
def boilerplate_cleanup(xmldoc)
|
98
|
+
isodoc = boilerplate_isodoc(xmldoc)
|
99
|
+
termdef_boilerplate_cleanup(xmldoc)
|
100
|
+
termdef_boilerplate_insert(xmldoc, isodoc)
|
101
|
+
unwrap_boilerplate_clauses(xmldoc, self.class::TERM_CLAUSE)
|
89
102
|
f = xmldoc.at(self.class::NORM_REF) and norm_ref_preface(f)
|
90
103
|
initial_boilerplate(xmldoc, isodoc)
|
91
104
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Asciidoctor
|
2
|
+
module Standoc
|
3
|
+
module Cleanup
|
4
|
+
def svgmap_cleanup(xmldoc)
|
5
|
+
svgmap_moveattrs(xmldoc)
|
6
|
+
svgmap_populate(xmldoc)
|
7
|
+
Metanorma::Utils::svgmap_rewrite(xmldoc, @localdir)
|
8
|
+
end
|
9
|
+
|
10
|
+
def guid?(str)
|
11
|
+
/^_[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
|
12
|
+
.match(str)
|
13
|
+
end
|
14
|
+
|
15
|
+
def svgmap_moveattrs(xmldoc)
|
16
|
+
xmldoc.xpath("//svgmap").each do |s|
|
17
|
+
f = s.at(".//figure") or next
|
18
|
+
if (t = s.at("./name")) && !f.at("./name")
|
19
|
+
f.children.first.previous = t.remove
|
20
|
+
end
|
21
|
+
if s["id"] && guid?(f["id"])
|
22
|
+
f["id"] = s["id"]
|
23
|
+
s.delete("id")
|
24
|
+
end
|
25
|
+
svgmap_moveattrs1(s, f)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def svgmap_moveattrs1(s, f)
|
30
|
+
%w(unnumbered number subsequence keep-with-next
|
31
|
+
keep-lines-together).each do |a|
|
32
|
+
next if f[a] || !s[a]
|
33
|
+
|
34
|
+
f[a] = s[a]
|
35
|
+
s.delete(a)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def svgmap_populate(xmldoc)
|
40
|
+
xmldoc.xpath("//svgmap").each do |s|
|
41
|
+
s1 = s.dup
|
42
|
+
s.children.remove
|
43
|
+
f = s1.at(".//figure") and s << f
|
44
|
+
s1.xpath(".//li").each do |li|
|
45
|
+
t = li&.at(".//eref | .//link | .//xref") or next
|
46
|
+
href = t.xpath("./following-sibling::node()")
|
47
|
+
href.empty? or
|
48
|
+
s << %[<target href="#{svgmap_target(href)}">#{t.to_xml}</target>]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def svgmap_target(nodeset)
|
54
|
+
nodeset.each do |n|
|
55
|
+
next unless n.name == "link"
|
56
|
+
|
57
|
+
n.children = n["target"]
|
58
|
+
end
|
59
|
+
nodeset.text.sub(/^[,; ]/, "").strip
|
60
|
+
end
|
61
|
+
|
62
|
+
def img_cleanup(xmldoc)
|
63
|
+
return xmldoc unless @datauriimage
|
64
|
+
|
65
|
+
xmldoc.xpath("//image").each do |i|
|
66
|
+
i["src"] = Metanorma::Utils::datauri(i["src"], @localdir)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -3,32 +3,54 @@ require "metanorma-utils"
|
|
3
3
|
module Asciidoctor
|
4
4
|
module Standoc
|
5
5
|
module Cleanup
|
6
|
-
def empty_text_before_first_element(
|
7
|
-
|
8
|
-
return false if c.text?
|
6
|
+
def empty_text_before_first_element(elem)
|
7
|
+
elem.children.each do |c|
|
8
|
+
return false if c.text? && /\S/.match(c.text)
|
9
9
|
return true if c.element?
|
10
10
|
end
|
11
11
|
true
|
12
12
|
end
|
13
13
|
|
14
|
-
def strip_initial_space(
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
def strip_initial_space(elem)
|
15
|
+
return unless elem.children[0].text?
|
16
|
+
|
17
|
+
if /\S/.match?(elem.children[0].text)
|
18
|
+
elem.children[0].content = elem.children[0].text.gsub(/^ /, "")
|
19
|
+
else
|
20
|
+
elem.children[0].remove
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
def bookmark_cleanup(xmldoc)
|
25
|
+
li_bookmark_cleanup(xmldoc)
|
26
|
+
dt_bookmark_cleanup(xmldoc)
|
27
|
+
end
|
28
|
+
|
29
|
+
def bookmark_to_id(elem, bookmark)
|
30
|
+
parent = bookmark.parent
|
31
|
+
elem["id"] = bookmark.remove["id"]
|
32
|
+
strip_initial_space(parent)
|
33
|
+
end
|
34
|
+
|
35
|
+
def li_bookmark_cleanup(xmldoc)
|
25
36
|
xmldoc.xpath("//li[descendant::bookmark]").each do |x|
|
26
|
-
if x
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
37
|
+
if x.at("./*[1][local-name() = 'p']/"\
|
38
|
+
"*[1][local-name() = 'bookmark']") &&
|
39
|
+
empty_text_before_first_element(x.elements[0])
|
40
|
+
bookmark_to_id(x, x.elements[0].elements[0])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def dt_bookmark_cleanup(xmldoc)
|
46
|
+
xmldoc.xpath("//dt[descendant::bookmark]").each do |x|
|
47
|
+
if x.at("./*[1][local-name() = 'p']/"\
|
48
|
+
"*[1][local-name() = 'bookmark']") &&
|
49
|
+
empty_text_before_first_element(x.elements[0])
|
50
|
+
bookmark_to_id(x, x.elements[0].elements[0])
|
51
|
+
elsif x.at("./*[1][local-name() = 'bookmark']") &&
|
52
|
+
empty_text_before_first_element(x)
|
53
|
+
bookmark_to_id(x, x.elements[0])
|
32
54
|
end
|
33
55
|
end
|
34
56
|
end
|
@@ -46,65 +68,67 @@ module Asciidoctor
|
|
46
68
|
LOCALITY_RE = Regexp.new(LOCALITY_REGEX_STR.gsub(/\s/, ""),
|
47
69
|
Regexp::IGNORECASE | Regexp::MULTILINE)
|
48
70
|
|
49
|
-
def tq(
|
50
|
-
|
71
|
+
def tq(text)
|
72
|
+
text.sub(/^"/, "").sub(/"$/, "")
|
51
73
|
end
|
52
74
|
|
53
|
-
def extract_localities(
|
54
|
-
f =
|
75
|
+
def extract_localities(elem)
|
76
|
+
f = elem&.children&.first or return
|
55
77
|
f.text? or return
|
56
78
|
head = f.remove.text
|
57
|
-
tail =
|
58
|
-
extract_localities1(
|
59
|
-
tail and
|
79
|
+
tail = elem&.children&.remove
|
80
|
+
extract_localities1(elem, head)
|
81
|
+
tail and elem << tail
|
60
82
|
end
|
61
83
|
|
62
|
-
def extract_localities1(
|
63
|
-
b =
|
84
|
+
def extract_localities1(elem, text)
|
85
|
+
b = elem.add_child("<localityStack/>").first if LOCALITY_RE.match text
|
64
86
|
while (m = LOCALITY_RE.match text)
|
65
87
|
ref = m[:ref] ? "<referenceFrom>#{tq m[:ref]}</referenceFrom>" : ""
|
66
88
|
refto = m[:to] ? "<referenceTo>#{tq m[:to]}</referenceTo>" : ""
|
67
89
|
loc = m[:locality]&.downcase || m[:locality2]&.downcase
|
68
90
|
b.add_child("<locality type='#{loc}'>#{ref}#{refto}</locality>")
|
69
91
|
text = m[:text]
|
70
|
-
b =
|
92
|
+
b = elem.add_child("<localityStack/>").first if m[:punct] == ";"
|
71
93
|
end
|
72
|
-
|
94
|
+
elem.add_child(text) if text
|
73
95
|
end
|
74
96
|
|
75
|
-
def xref_to_eref(
|
76
|
-
|
77
|
-
unless
|
78
|
-
@internal_eref_namespaces.include?(
|
79
|
-
|
80
|
-
|
97
|
+
def xref_to_eref(elem)
|
98
|
+
elem["bibitemid"] = elem["target"]
|
99
|
+
unless elem["citeas"] = @anchors&.dig(elem["target"], :xref)
|
100
|
+
@internal_eref_namespaces.include?(elem["type"]) or
|
101
|
+
@log.add("Crossreferences", elem,
|
102
|
+
"#{elem['target']} does not have a corresponding "\
|
103
|
+
"anchor ID in the bibliography!")
|
81
104
|
end
|
82
|
-
|
83
|
-
extract_localities(
|
105
|
+
elem.delete("target")
|
106
|
+
extract_localities(elem) unless elem.children.empty?
|
84
107
|
end
|
85
108
|
|
86
109
|
def xref_cleanup(xmldoc)
|
87
110
|
xmldoc.xpath("//xref").each do |x|
|
88
111
|
/:/.match(x["target"]) and xref_to_internal_eref(x)
|
89
112
|
next unless x.name == "xref"
|
113
|
+
|
90
114
|
if refid? x["target"]
|
91
115
|
x.name = "eref"
|
92
116
|
xref_to_eref(x)
|
93
|
-
else
|
94
|
-
x.delete("type")
|
117
|
+
else x.delete("type")
|
95
118
|
end
|
96
119
|
end
|
97
120
|
end
|
98
121
|
|
99
|
-
def xref_to_internal_eref(
|
100
|
-
a =
|
101
|
-
unless
|
102
|
-
|
103
|
-
a.size > 2 and
|
104
|
-
|
122
|
+
def xref_to_internal_eref(elem)
|
123
|
+
a = elem["target"].split(":", 3)
|
124
|
+
unless a.size < 2 || a[0].empty? || a[1].empty?
|
125
|
+
elem["target"] = "#{a[0]}_#{a[1]}"
|
126
|
+
a.size > 2 and
|
127
|
+
elem.children = %{anchor="#{a[2..-1].join}",#{elem&.children&.text}}
|
128
|
+
elem["type"] = a[0]
|
105
129
|
@internal_eref_namespaces << a[0]
|
106
|
-
|
107
|
-
xref_to_eref(
|
130
|
+
elem.name = "eref"
|
131
|
+
xref_to_eref(elem)
|
108
132
|
end
|
109
133
|
end
|
110
134
|
|
@@ -116,10 +140,11 @@ module Asciidoctor
|
|
116
140
|
|
117
141
|
def origin_cleanup(xmldoc)
|
118
142
|
xmldoc.xpath("//origin/concept[termref]").each do |x|
|
119
|
-
x.
|
143
|
+
t = x.at("./termref")
|
144
|
+
x.replace(t)
|
120
145
|
end
|
121
146
|
xmldoc.xpath("//origin").each do |x|
|
122
|
-
x["citeas"] = @anchors&.dig(x["bibitemid"], :xref)
|
147
|
+
x["citeas"] = @anchors&.dig(x["bibitemid"], :xref) or
|
123
148
|
@log.add("Crossreferences", x,
|
124
149
|
"#{x['bibitemid']} does not have a corresponding anchor "\
|
125
150
|
"ID in the bibliography!")
|
@@ -128,68 +153,83 @@ module Asciidoctor
|
|
128
153
|
end
|
129
154
|
|
130
155
|
def concept_cleanup(xmldoc)
|
131
|
-
xmldoc.xpath("//concept").each do |x|
|
132
|
-
x.
|
133
|
-
if
|
156
|
+
xmldoc.xpath("//concept[not(termxref)]").each do |x|
|
157
|
+
term = x.at("./refterm")
|
158
|
+
term&.remove if term&.text&.empty?
|
159
|
+
x.children.remove if x&.children&.text&.strip&.empty?
|
160
|
+
key_extract_locality(x)
|
161
|
+
if /:/.match?(x["key"]) then concept_termbase_cleanup(x)
|
134
162
|
elsif refid? x["key"] then concept_eref_cleanup(x)
|
135
|
-
else
|
136
|
-
concept_xref_cleanup(x)
|
163
|
+
else concept_xref_cleanup(x)
|
137
164
|
end
|
138
165
|
x.delete("key")
|
139
166
|
end
|
140
167
|
end
|
141
168
|
|
142
|
-
def
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
169
|
+
def key_extract_locality(elem)
|
170
|
+
return unless /,/.match?(elem["key"])
|
171
|
+
|
172
|
+
elem.add_child("<locality>#{elem['key'].sub(/^[^,]+,/, '')}</locality>")
|
173
|
+
elem["key"] = elem["key"].sub(/,.*$/, "")
|
174
|
+
end
|
175
|
+
|
176
|
+
def concept_termbase_cleanup(elem)
|
177
|
+
t = elem&.at("./xrefrender")&.remove&.children
|
178
|
+
termbase, key = elem["key"].split(/:/, 2)
|
179
|
+
elem.add_child(%(<termref base="#{termbase}" target="#{key}">) +
|
180
|
+
"#{t&.to_xml}</termref>")
|
147
181
|
end
|
148
182
|
|
149
|
-
def concept_xref_cleanup(
|
150
|
-
|
151
|
-
|
183
|
+
def concept_xref_cleanup(elem)
|
184
|
+
t = elem&.at("./xrefrender")&.remove&.children
|
185
|
+
elem.add_child(%(<xref target="#{elem['key']}">#{t&.to_xml}</xref>))
|
152
186
|
end
|
153
187
|
|
154
|
-
def concept_eref_cleanup(
|
155
|
-
|
156
|
-
|
188
|
+
def concept_eref_cleanup(elem)
|
189
|
+
t = elem&.at("./xrefrender")&.remove&.children&.to_xml
|
190
|
+
l = elem&.at("./locality")&.remove&.children&.to_xml
|
191
|
+
elem.add_child "<eref bibitemid='#{elem['key']}'>#{l}</eref>"
|
192
|
+
extract_localities(elem.elements[-1])
|
193
|
+
elem.elements[-1].add_child(t) if t
|
157
194
|
end
|
158
195
|
|
159
|
-
def to_xreftarget(
|
160
|
-
return Metanorma::Utils::to_ncname(
|
161
|
-
|
162
|
-
pref
|
163
|
-
|
196
|
+
def to_xreftarget(str)
|
197
|
+
return Metanorma::Utils::to_ncname(str) unless /^[^#]+#.+$/.match?(str)
|
198
|
+
|
199
|
+
/^(?<pref>[^#]+)#(?<suff>.+)$/ =~ str
|
200
|
+
pref = pref.gsub(%r([#{Metanorma::Utils::NAMECHAR}])o, "_")
|
201
|
+
suff = suff.gsub(%r([#{Metanorma::Utils::NAMECHAR}])o, "_")
|
164
202
|
"#{pref}##{suff}"
|
165
203
|
end
|
166
204
|
|
167
205
|
IDREF = "//*/@id | //review/@from | //review/@to | "\
|
168
206
|
"//callout/@target | //citation/@bibitemid | //eref/@bibitemid".freeze
|
169
207
|
|
170
|
-
def anchor_cleanup(
|
171
|
-
anchor_cleanup1(
|
172
|
-
xreftarget_cleanup(
|
208
|
+
def anchor_cleanup(elem)
|
209
|
+
anchor_cleanup1(elem)
|
210
|
+
xreftarget_cleanup(elem)
|
173
211
|
end
|
174
212
|
|
175
|
-
def anchor_cleanup1(
|
176
|
-
|
213
|
+
def anchor_cleanup1(elem)
|
214
|
+
elem.xpath(IDREF).each do |s|
|
177
215
|
if (ret = Metanorma::Utils::to_ncname(s.value)) != (orig = s.value)
|
178
216
|
s.value = ret
|
179
217
|
output = s.parent.dup
|
180
218
|
output.children.remove
|
181
|
-
@log.add("Anchors", s.parent,
|
219
|
+
@log.add("Anchors", s.parent,
|
220
|
+
"normalised identifier in #{output} from #{orig}")
|
182
221
|
end
|
183
222
|
end
|
184
223
|
end
|
185
224
|
|
186
|
-
def xreftarget_cleanup(
|
187
|
-
|
225
|
+
def xreftarget_cleanup(elem)
|
226
|
+
elem.xpath("//xref/@target").each do |s|
|
188
227
|
if (ret = to_xreftarget(s.value)) != (orig = s.value)
|
189
228
|
s.value = ret
|
190
229
|
output = s.parent.dup
|
191
230
|
output.children.remove
|
192
|
-
@log.add("Anchors", s.parent,
|
231
|
+
@log.add("Anchors", s.parent,
|
232
|
+
"normalised identifier in #{output} from #{orig}")
|
193
233
|
end
|
194
234
|
end
|
195
235
|
end
|