metanorma-standoc 2.0.2 → 2.0.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/lib/metanorma/standoc/base.rb +73 -23
- data/lib/metanorma/standoc/basicdoc.rng +5 -3
- data/lib/metanorma/standoc/biblio.rng +5 -3
- data/lib/metanorma/standoc/blocks.rb +4 -4
- data/lib/metanorma/standoc/cleanup_amend.rb +33 -30
- data/lib/metanorma/standoc/cleanup_boilerplate.rb +29 -5
- data/lib/metanorma/standoc/cleanup_image.rb +117 -3
- data/lib/metanorma/standoc/cleanup_ref.rb +32 -3
- data/lib/metanorma/standoc/cleanup_ref_dl.rb +25 -16
- data/lib/metanorma/standoc/cleanup_section.rb +2 -2
- data/lib/metanorma/standoc/cleanup_terms_designations.rb +4 -2
- data/lib/metanorma/standoc/cleanup_text.rb +39 -17
- data/lib/metanorma/standoc/cleanup_xref.rb +82 -13
- data/lib/metanorma/standoc/converter.rb +2 -1
- data/lib/metanorma/standoc/inline.rb +21 -12
- data/lib/metanorma/standoc/isodoc.rng +73 -3
- data/lib/metanorma/standoc/macros.rb +14 -2
- data/lib/metanorma/standoc/macros_embed.rb +35 -14
- data/lib/metanorma/standoc/macros_note.rb +4 -3
- data/lib/metanorma/standoc/processor.rb +6 -1
- data/lib/metanorma/standoc/ref.rb +20 -16
- data/lib/metanorma/standoc/ref_utility.rb +8 -6
- data/lib/metanorma/standoc/render.rb +7 -3
- data/lib/metanorma/standoc/table.rb +8 -10
- data/lib/metanorma/standoc/term_lookup_cleanup.rb +16 -10
- data/lib/metanorma/standoc/terms.rb +10 -7
- data/lib/metanorma/standoc/utils.rb +3 -1
- data/lib/metanorma/standoc/validate.rb +81 -7
- data/lib/metanorma/standoc/version.rb +1 -1
- data/metanorma-standoc.gemspec +2 -2
- data/spec/assets/a2.adoc +4 -2
- data/spec/assets/a3.adoc +2 -2
- data/spec/assets/a3a.adoc +7 -0
- data/spec/metanorma/base_spec.rb +1 -1
- data/spec/metanorma/cleanup_blocks_spec.rb +136 -0
- data/spec/metanorma/cleanup_spec.rb +34 -23
- data/spec/metanorma/cleanup_terms_spec.rb +16 -4
- data/spec/metanorma/inline_spec.rb +31 -0
- data/spec/metanorma/isobib_cache_spec.rb +2 -2
- data/spec/metanorma/macros_plantuml_spec.rb +41 -42
- data/spec/metanorma/macros_spec.rb +267 -4
- data/spec/metanorma/processor_spec.rb +17 -13
- data/spec/metanorma/refs_spec.rb +632 -460
- data/spec/metanorma/section_spec.rb +1 -1
- data/spec/metanorma/validate_spec.rb +108 -0
- data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +48 -48
- data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +13 -13
- data/spec/vcr_cassettes/hide_refs.yml +100 -100
- data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
- data/spec/vcr_cassettes/isobib_get_123_1.yml +25 -25
- data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +35 -35
- data/spec/vcr_cassettes/isobib_get_123_2001.yml +11 -11
- data/spec/vcr_cassettes/isobib_get_124.yml +13 -13
- data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +18 -18
- data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +86 -66
- metadata +10 -9
@@ -2,7 +2,7 @@ module Metanorma
|
|
2
2
|
module Standoc
|
3
3
|
module Refs
|
4
4
|
def set_date_range(date, text)
|
5
|
-
matched = /^(?<from>[0-9]+)(
|
5
|
+
matched = /^(?<from>[0-9]+)(?:-+(?<to>[0-9]+))?$/.match text
|
6
6
|
return unless matched[:from]
|
7
7
|
|
8
8
|
if matched[:to]
|
@@ -75,7 +75,8 @@ module Metanorma
|
|
75
75
|
|
76
76
|
def analyse_ref_repo_path(ret)
|
77
77
|
return ret unless m =
|
78
|
-
/^(?<type>repo|path):\((?<key>[^,]+),?(?<id>.*)\)
|
78
|
+
/^(?<type>repo|path):\((?<key>[^,]+),?(?<id>.*)\)$/
|
79
|
+
.match(ret[:id])
|
79
80
|
|
80
81
|
id = m[:id].empty? ? m[:key].sub(%r{^[^/]+/}, "") : m[:id]
|
81
82
|
ret.merge(id: id, type: m[:type], key: m[:key], nofetch: true)
|
@@ -112,10 +113,11 @@ module Metanorma
|
|
112
113
|
{ id: match[:anchor], type: "standard" }
|
113
114
|
end
|
114
115
|
|
115
|
-
MALFORMED_REF =
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
MALFORMED_REF = <<~REF.freeze
|
117
|
+
no anchor on reference, markup may be malformed: see
|
118
|
+
https://www.metanorma.com/author/topics/document-format/bibliography/ ,
|
119
|
+
https://www.metanorma.com/author/iso/topics/markup/#bibliographies
|
120
|
+
REF
|
119
121
|
|
120
122
|
def ref_normalise(ref)
|
121
123
|
ref.gsub(/&amp;/, "&").gsub(%r{^<em>(.*)</em>}, "\\1")
|
@@ -25,6 +25,9 @@ module Metanorma
|
|
25
25
|
sectionsplit: node.attr("sectionsplit"),
|
26
26
|
baseassetpath: node.attr("base-asset-path"),
|
27
27
|
aligncrosselements: node.attr("align-cross-elements"),
|
28
|
+
tocfigures: @tocfigures,
|
29
|
+
toctables: @toctables,
|
30
|
+
tocrecommendations: @tocrecommendations,
|
28
31
|
}
|
29
32
|
end
|
30
33
|
|
@@ -61,12 +64,13 @@ module Metanorma
|
|
61
64
|
bare: node.attr("bare"),
|
62
65
|
baseassetpath: node.attr("base-asset-path"),
|
63
66
|
aligncrosselements: node.attr("align-cross-elements"),
|
67
|
+
tocfigures: @tocfigures,
|
68
|
+
toctables: @toctables,
|
69
|
+
tocrecommendations: @tocrecommendations,
|
64
70
|
}
|
65
71
|
|
66
72
|
if fonts_manifest = node.attr(FONTS_MANIFEST)
|
67
|
-
attrs[IsoDoc::XslfoPdfConvert::
|
68
|
-
IsoDoc::XslfoPdfConvert::MN2PDF_FONT_MANIFEST => fonts_manifest,
|
69
|
-
}
|
73
|
+
attrs[IsoDoc::XslfoPdfConvert::MN2PDF_FONT_MANIFEST] = fonts_manifest
|
70
74
|
end
|
71
75
|
|
72
76
|
attrs
|
@@ -19,9 +19,7 @@ module Metanorma
|
|
19
19
|
xml.table **attr_code(table_attrs(node)) do |xml_table|
|
20
20
|
colgroup(node, xml_table)
|
21
21
|
table_name(node, xml_table)
|
22
|
-
%i(head body foot).reject
|
23
|
-
node.rows[tblsec].empty?
|
24
|
-
end
|
22
|
+
%i(head body foot).reject { |tblsec| node.rows[tblsec].empty? }
|
25
23
|
table_head_body_and_foot node, xml_table
|
26
24
|
end
|
27
25
|
end
|
@@ -50,12 +48,12 @@ module Metanorma
|
|
50
48
|
end
|
51
49
|
end
|
52
50
|
|
53
|
-
def table_cell1(cell
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
51
|
+
def table_cell1(cell)
|
52
|
+
if cell.style == :asciidoc
|
53
|
+
cell.content
|
54
|
+
else
|
55
|
+
cell.text
|
56
|
+
end
|
59
57
|
end
|
60
58
|
|
61
59
|
def table_cell(node, xml_tr, tblsec)
|
@@ -65,7 +63,7 @@ module Metanorma
|
|
65
63
|
cell_tag = "td"
|
66
64
|
cell_tag = "th" if tblsec == :head || node.style == :header
|
67
65
|
xml_tr.send cell_tag, **attr_code(cell_attributes) do |thd|
|
68
|
-
table_cell1(node
|
66
|
+
thd << table_cell1(node)
|
69
67
|
end
|
70
68
|
end
|
71
69
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true.
|
2
2
|
require "metanorma/standoc/utils"
|
3
3
|
|
4
|
-
|
5
4
|
module Metanorma
|
6
5
|
module Standoc
|
7
6
|
# Intelligent term lookup xml modifier
|
@@ -58,7 +57,7 @@ module Metanorma
|
|
58
57
|
|
59
58
|
def set_termxref_tags_target
|
60
59
|
xmldoc.xpath("//termxref").each do |node|
|
61
|
-
target = normalize_ref_id(node
|
60
|
+
target = normalize_ref_id(node)
|
62
61
|
if termlookup[:term][target].nil? && termlookup[:symbol][target].nil?
|
63
62
|
remove_missing_ref(node, target)
|
64
63
|
next
|
@@ -78,7 +77,7 @@ module Metanorma
|
|
78
77
|
|
79
78
|
def remove_missing_ref_term(node, target)
|
80
79
|
log.add("AsciiDoc Input", node,
|
81
|
-
%(Error: Term reference
|
80
|
+
%(Error: Term reference to `#{target}` missing: \
|
82
81
|
"#{target}" is not defined in document))
|
83
82
|
node.name = "strong"
|
84
83
|
node&.at("../xrefrender")&.remove
|
@@ -110,15 +109,15 @@ module Metanorma
|
|
110
109
|
if type == "term" || ((!type || node.parent.name == "related") && t)
|
111
110
|
node["target"] = t
|
112
111
|
elsif type == "symbol" ||
|
113
|
-
|
112
|
+
((!type || node.parent.name == "related") && s)
|
114
113
|
node["target"] = s
|
115
114
|
end
|
116
115
|
end
|
117
116
|
|
118
117
|
def replace_automatic_generated_ids_terms
|
119
118
|
r = xmldoc.xpath("//term").each.with_object({}) do |n, res|
|
120
|
-
normalize_id_and_memorize(n, res, "./preferred//name",
|
121
|
-
|
119
|
+
normalize_id_and_memorize(n, res, "./preferred//name", "term")
|
120
|
+
normalize_id_and_memorize(n, res, "./admitted//name", "term")
|
122
121
|
end
|
123
122
|
s = xmldoc.xpath("//definitions//dt").each.with_object({}) do |n, res|
|
124
123
|
normalize_id_and_memorize(n, res, ".", "symbol")
|
@@ -127,11 +126,13 @@ module Metanorma
|
|
127
126
|
end
|
128
127
|
|
129
128
|
def pref_secondary2primary
|
129
|
+
term = ""
|
130
130
|
xmldoc.xpath("//term").each.with_object({}) do |n, res|
|
131
131
|
n.xpath("./preferred//name").each_with_index do |p, i|
|
132
132
|
i.zero? and term = p.text
|
133
133
|
i.positive? and res[p.text] = term
|
134
134
|
end
|
135
|
+
n.xpath("./admitted//name").each { |p| res[p.text] = term }
|
135
136
|
end
|
136
137
|
end
|
137
138
|
|
@@ -141,7 +142,7 @@ module Metanorma
|
|
141
142
|
end
|
142
143
|
|
143
144
|
def normalize_id_and_memorize_init(node, res_table, text_selector, prefix)
|
144
|
-
term_text = normalize_ref_id(node.at(text_selector)
|
145
|
+
term_text = normalize_ref_id(node.at(text_selector)) or return
|
145
146
|
unless AUTOMATIC_GENERATED_ID_REGEXP.match(node["id"]).nil? &&
|
146
147
|
!node["id"].nil?
|
147
148
|
id = unique_text_id(term_text, prefix)
|
@@ -155,12 +156,17 @@ module Metanorma
|
|
155
156
|
node.xpath(text_selector).each_with_index do |p, i|
|
156
157
|
next unless i.positive?
|
157
158
|
|
158
|
-
res_table[normalize_ref_id(p
|
159
|
+
res_table[normalize_ref_id(p)] = node["id"]
|
159
160
|
end
|
160
161
|
end
|
161
162
|
|
162
|
-
def normalize_ref_id(
|
163
|
-
|
163
|
+
def normalize_ref_id(term)
|
164
|
+
return nil if term.nil?
|
165
|
+
|
166
|
+
t = term.dup
|
167
|
+
t.xpath(".//index").map(&:remove)
|
168
|
+
Metanorma::Utils::to_ncname(t.text.strip.downcase
|
169
|
+
.gsub(/[[:space:]]+/, "-"))
|
164
170
|
end
|
165
171
|
|
166
172
|
def unique_text_id(text, prefix)
|
@@ -92,7 +92,7 @@ module Metanorma
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
-
def
|
95
|
+
def termsource_origin_attrs(_node, seen_xref)
|
96
96
|
{ case: seen_xref.children[0]["case"],
|
97
97
|
droploc: seen_xref.children[0]["droploc"],
|
98
98
|
bibitemid: seen_xref.children[0]["target"],
|
@@ -103,7 +103,7 @@ module Metanorma
|
|
103
103
|
if seen_xref.children[0].name == "concept"
|
104
104
|
xml_t.origin { |o| o << seen_xref.children[0].to_xml }
|
105
105
|
else
|
106
|
-
attrs =
|
106
|
+
attrs = termsource_origin_attrs(node, seen_xref)
|
107
107
|
attrs.delete(:text)
|
108
108
|
xml_t.origin **attr_code(attrs) do |o|
|
109
109
|
o << seen_xref.children[0].children.to_xml
|
@@ -135,13 +135,16 @@ module Metanorma
|
|
135
135
|
matched
|
136
136
|
end
|
137
137
|
|
138
|
+
def termsource_attrs(node, matched)
|
139
|
+
status = node.attr("status") ||
|
140
|
+
(matched[:text] ? "modified" : "identical")
|
141
|
+
{ status: status, type: node.attr("type") || "authoritative" }
|
142
|
+
end
|
143
|
+
|
138
144
|
def termsource(node)
|
139
|
-
matched = extract_termsource_refs(node.content, node)
|
145
|
+
matched = extract_termsource_refs(node.content, node) or return
|
140
146
|
noko do |xml|
|
141
|
-
|
142
|
-
(matched[:text] ? "modified" : "identical")
|
143
|
-
attrs = { status: status, type: node.attr("type") || "authoritative" }
|
144
|
-
xml.termsource **attrs do |xml_t|
|
147
|
+
xml.termsource **termsource_attrs(node, matched) do |xml_t|
|
145
148
|
seen_xref = Nokogiri::XML.fragment(matched[:xref])
|
146
149
|
add_term_source(node, xml_t, seen_xref, matched)
|
147
150
|
end
|
@@ -32,7 +32,9 @@ module Metanorma
|
|
32
32
|
doc = ::Nokogiri::XML.parse(NOKOHEAD)
|
33
33
|
fragment = doc.fragment("")
|
34
34
|
::Nokogiri::XML::Builder.with fragment, &block
|
35
|
-
fragment.to_xml(encoding: "US-ASCII", indent: 0
|
35
|
+
fragment.to_xml(encoding: "US-ASCII", indent: 0,
|
36
|
+
save_with: Nokogiri::XML::Node::SaveOptions::AS_XML)
|
37
|
+
.lines.map do |l|
|
36
38
|
l.gsub(/>\n$/, ">").gsub(/\s*\n$/m, " ").gsub("–", "\u0096")
|
37
39
|
.gsub("—", "\u0097").gsub("–", "\u0096")
|
38
40
|
.gsub("—", "\u0097")
|
@@ -49,9 +49,79 @@ module Metanorma
|
|
49
49
|
iev_validate(doc.root)
|
50
50
|
concept_validate(doc, "concept", "refterm")
|
51
51
|
concept_validate(doc, "related", "preferred//name")
|
52
|
+
table_validate(doc)
|
52
53
|
@fatalerror.empty? or clean_abort(@fatalerror.join("\n"), doc.to_xml)
|
53
54
|
end
|
54
55
|
|
56
|
+
def table_validate(doc)
|
57
|
+
doc.xpath("//table[colgroup]").each do |t|
|
58
|
+
maxrowcols_validate(t, t.xpath("./colgroup/col").size)
|
59
|
+
end
|
60
|
+
doc.xpath("//table[.//*[@colspan] | .//*[@rowspan]]").each do |t|
|
61
|
+
maxrowcols_validate(t, max_td_count(t))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def max_td_count(table)
|
66
|
+
max = 0
|
67
|
+
table.xpath(".//tr").each do |tr|
|
68
|
+
n = tr.xpath("./td | ./th").size
|
69
|
+
max < n and max = n
|
70
|
+
end
|
71
|
+
max
|
72
|
+
end
|
73
|
+
|
74
|
+
def maxrowcols_validate(table, maxcols)
|
75
|
+
cells2d = table.xpath(".//tr").each_with_object([]) { |_r, m| m << {} }
|
76
|
+
table.xpath(".//tr").each_with_index do |tr, r|
|
77
|
+
curr = 0
|
78
|
+
tr.xpath("./td | ./th").each do |td|
|
79
|
+
curr = maxcols_validate1(td, r, curr, cells2d, maxcols)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
maxrows_validate(table, cells2d)
|
83
|
+
end
|
84
|
+
|
85
|
+
# code doesn't actually do anything, since Asciidoctor refuses to generate
|
86
|
+
# table with inconsistent column count
|
87
|
+
def maxcols_validate1(tcell, row, curr, cells2d, maxcols)
|
88
|
+
rs = tcell&.attr("rowspan")&.to_i || 1
|
89
|
+
cs = tcell&.attr("colspan")&.to_i || 1
|
90
|
+
curr = table_tracker_update(cells2d, row, curr, rs, cs)
|
91
|
+
maxcols_check(curr + cs - 1, maxcols, tcell)
|
92
|
+
curr + cs
|
93
|
+
end
|
94
|
+
|
95
|
+
def table_tracker_update(cells2d, row, curr, rowspan, colspan)
|
96
|
+
cells2d[row] ||= {}
|
97
|
+
while cells2d[row][curr]
|
98
|
+
curr += 1
|
99
|
+
end
|
100
|
+
(row..(row + rowspan - 1)).each do |y2|
|
101
|
+
cells2d[y2] ||= {}
|
102
|
+
(curr..(curr + colspan - 1)).each { |x2| cells2d[y2][x2] = 1 }
|
103
|
+
end
|
104
|
+
curr
|
105
|
+
end
|
106
|
+
|
107
|
+
def maxrows_validate(table, cells2d)
|
108
|
+
if cells2d.any? { |x| x.size != cells2d.first.size }
|
109
|
+
@log.add("Table", table,
|
110
|
+
"Table rows in table are inconsistent: check rowspan")
|
111
|
+
@fatalerror << "Table rows in table are inconsistent: check rowspan"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# if maxcols or maxrows negative, do not check them
|
116
|
+
def maxcols_check(col, maxcols, tcell)
|
117
|
+
if maxcols.positive? && col > maxcols
|
118
|
+
@log.add("Table", tcell, "Table exceeds maximum number of columns "\
|
119
|
+
"defined (#{maxcols})")
|
120
|
+
@fatalerror << "Table exceeds maximum number of columns defined "\
|
121
|
+
"(#{maxcols})"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
55
125
|
def norm_ref_validate(doc)
|
56
126
|
found = false
|
57
127
|
doc.xpath("//references[@normative = 'true']/bibitem").each do |b|
|
@@ -71,10 +141,9 @@ module Metanorma
|
|
71
141
|
next if doc.at("//term[@id = '#{x['target']}']")
|
72
142
|
next if doc.at("//definitions//dt[@id = '#{x['target']}']")
|
73
143
|
|
74
|
-
ref = x&.at("../#{refterm}")&.text
|
75
144
|
@log.add("Anchors", x,
|
76
|
-
"#{tag.capitalize} #{
|
77
|
-
"#{x['target']}, which is not a term or symbol")
|
145
|
+
"#{tag.capitalize} #{x&.at("../#{refterm}")&.text} is "\
|
146
|
+
"pointing to #{x['target']}, which is not a term or symbol")
|
78
147
|
found = true
|
79
148
|
end
|
80
149
|
found and
|
@@ -120,20 +189,25 @@ module Metanorma
|
|
120
189
|
end
|
121
190
|
end
|
122
191
|
|
192
|
+
SVG_NS = "http://www.w3.org/2000/svg".freeze
|
193
|
+
|
194
|
+
WILDCARD_ATTRS =
|
195
|
+
"//*[@format] | //stem | //bibdata//description | "\
|
196
|
+
"//formattedref | //bibdata//note | //bibdata/abstract | "\
|
197
|
+
"//bibitem/abstract | //bibitem/note | //misc-container".freeze
|
198
|
+
|
123
199
|
# RelaxNG cannot cope well with wildcard attributes. So we strip
|
124
200
|
# any attributes from FormattedString instances (which can contain
|
125
201
|
# xs:any markup, and are signalled with @format) before validation.
|
126
202
|
def formattedstr_strip(doc)
|
127
|
-
doc.xpath("
|
128
|
-
"//formattedref | //bibdata//note | //bibdata/abstract | "\
|
129
|
-
"//bibitem/abstract | //bibitem/note | //misc-container")
|
130
|
-
.each do |n|
|
203
|
+
doc.xpath(WILDCARD_ATTRS, "m" => SVG_NS).each do |n|
|
131
204
|
n.elements.each do |e|
|
132
205
|
e.traverse do |e1|
|
133
206
|
e1.element? and e1.each { |k, _v| e1.delete(k) }
|
134
207
|
end
|
135
208
|
end
|
136
209
|
end
|
210
|
+
doc.xpath("//m:svg", "m" => SVG_NS).each { |n| n.replace("<svg/>") }
|
137
211
|
doc
|
138
212
|
end
|
139
213
|
|
data/metanorma-standoc.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_dependency "asciidoctor", "~> 2.0.0"
|
30
30
|
spec.add_dependency "iev", "~> 0.3.0"
|
31
31
|
spec.add_dependency "isodoc", "~> 2.0.0"
|
32
|
-
spec.add_dependency "metanorma-plugin-datastruct"
|
32
|
+
spec.add_dependency "metanorma-plugin-datastruct", "~> 0.2.0"
|
33
33
|
spec.add_dependency "metanorma-plugin-lutaml"
|
34
34
|
spec.add_dependency "ruby-jing"
|
35
35
|
# relaton-cli not just relaton, to avoid circular reference in metanorma
|
@@ -52,6 +52,6 @@ Gem::Specification.new do |spec|
|
|
52
52
|
spec.add_development_dependency "sassc", "2.4.0"
|
53
53
|
spec.add_development_dependency "simplecov", "~> 0.15"
|
54
54
|
spec.add_development_dependency "timecop", "~> 0.9"
|
55
|
-
spec.add_development_dependency "vcr", "~>
|
55
|
+
spec.add_development_dependency "vcr", "~> 6.1.0"
|
56
56
|
spec.add_development_dependency "webmock"
|
57
57
|
end
|
data/spec/assets/a2.adoc
CHANGED
data/spec/assets/a3.adoc
CHANGED
data/spec/metanorma/base_spec.rb
CHANGED
@@ -1051,7 +1051,7 @@ QU1FOiB0ZXN0Cgo=
|
|
1051
1051
|
.new(:standoc, header_footer: true)
|
1052
1052
|
.doc_extract_attributes(node)
|
1053
1053
|
|
1054
|
-
expect(options
|
1054
|
+
expect(options[:font_manifest])
|
1055
1055
|
.to eq(node[Metanorma::Standoc::Base::FONTS_MANIFEST])
|
1056
1056
|
end
|
1057
1057
|
|
@@ -1039,4 +1039,140 @@ RSpec.describe Metanorma::Standoc do
|
|
1039
1039
|
annotation_id = output.at("//xmlns:annotation/@id").text
|
1040
1040
|
expect(callout_id).to eq(annotation_id)
|
1041
1041
|
end
|
1042
|
+
it "deduplicates identifiers in inline SVGs" do
|
1043
|
+
input = <<~INPUT
|
1044
|
+
#{BLANK_HDR}
|
1045
|
+
<sections>
|
1046
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 256 256">
|
1047
|
+
<defs>
|
1048
|
+
<linearGradient id="gradient1">
|
1049
|
+
<stop class="stop1" offset="0%" xlink:href="#gradient1"/>
|
1050
|
+
<stop class="stop2" offset="100%"/>
|
1051
|
+
<style>url(#gradient1)</style>
|
1052
|
+
</linearGradient>
|
1053
|
+
</defs>
|
1054
|
+
<circle fill="url(#gradient1)" cx="128" cy="128" r="100" />
|
1055
|
+
</svg>
|
1056
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 256 256">
|
1057
|
+
<defs>
|
1058
|
+
<linearGradient id="gradient2">
|
1059
|
+
<stop class="stop1" offset="0%" xlink:href="#gradient2"/>
|
1060
|
+
<stop class="stop2" offset="100%"/>
|
1061
|
+
<style>url(#gradient2)</style>
|
1062
|
+
</linearGradient>
|
1063
|
+
</defs>
|
1064
|
+
<circle fill="url(#gradient2)" cx="128" cy="128" r="100" />
|
1065
|
+
</svg>
|
1066
|
+
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 256 256">
|
1067
|
+
<defs>
|
1068
|
+
<linearGradient id="gradient1">
|
1069
|
+
<stop class="stop1" offset="0%" xlink:href="#gradient1"/>
|
1070
|
+
<stop class="stop2" offset="100%"/>
|
1071
|
+
<style>url(#gradient1)</style>
|
1072
|
+
</linearGradient>
|
1073
|
+
</defs>
|
1074
|
+
<circle fill="url(#gradient1)" cx="128" cy="128" r="100" />
|
1075
|
+
</svg>
|
1076
|
+
</sections>
|
1077
|
+
</standard-document>
|
1078
|
+
INPUT
|
1079
|
+
output = <<~OUTPUT
|
1080
|
+
#{BLANK_HDR}
|
1081
|
+
<sections>
|
1082
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 256 256">
|
1083
|
+
<defs>
|
1084
|
+
<linearGradient id="gradient1_inject_0">
|
1085
|
+
<stop class="stop1" offset="0%" xlink:href="#gradient1_inject_0"/>
|
1086
|
+
<stop class="stop2" offset="100%"/>
|
1087
|
+
<style>url(#gradient1_inject_0)</style>
|
1088
|
+
</linearGradient>
|
1089
|
+
</defs>
|
1090
|
+
<circle fill="url(#gradient1_inject_0)" cx="128" cy="128" r="100"/>
|
1091
|
+
</svg>
|
1092
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 256 256">
|
1093
|
+
<defs>
|
1094
|
+
<linearGradient id="gradient2">
|
1095
|
+
<stop class="stop1" offset="0%" xlink:href="#gradient2"/>
|
1096
|
+
<stop class="stop2" offset="100%"/>
|
1097
|
+
<style>url(#gradient2)</style>
|
1098
|
+
</linearGradient>
|
1099
|
+
</defs>
|
1100
|
+
<circle fill="url(#gradient2)" cx="128" cy="128" r="100"/>
|
1101
|
+
</svg>
|
1102
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 256 256">
|
1103
|
+
<defs>
|
1104
|
+
<linearGradient id="gradient1_inject_2">
|
1105
|
+
<stop class="stop1" offset="0%" xlink:href="#gradient1_inject_2"/>
|
1106
|
+
<stop class="stop2" offset="100%"/>
|
1107
|
+
<style>url(#gradient1_inject_2)</style>
|
1108
|
+
</linearGradient>
|
1109
|
+
</defs>
|
1110
|
+
<circle fill="url(#gradient1_inject_2)" cx="128" cy="128" r="100"/>
|
1111
|
+
</svg>
|
1112
|
+
</sections>
|
1113
|
+
</standard-document>
|
1114
|
+
OUTPUT
|
1115
|
+
expect(Metanorma::Standoc::Converter.new(nil, *OPTIONS)
|
1116
|
+
.cleanup(Nokogiri::XML(input)).to_xml)
|
1117
|
+
.to be_equivalent_to xmlpp(output)
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
it "deduplicates identifiers in embedded SVGs" do
|
1121
|
+
input = <<~INPUT
|
1122
|
+
#{ASCIIDOC_BLANK_HDR.sub(/:data-uri-image: false/, ':data-uri-image: true')}
|
1123
|
+
|
1124
|
+
image::spec/fixtures/action_schemaexpg1.svg[]
|
1125
|
+
|
1126
|
+
image::spec/examples/rice_images/rice_image1.png[]
|
1127
|
+
|
1128
|
+
image::spec/fixtures/action_schemaexpg1.svg[]
|
1129
|
+
INPUT
|
1130
|
+
|
1131
|
+
output = <<~OUTPUT
|
1132
|
+
#{BLANK_HDR}
|
1133
|
+
<sections>
|
1134
|
+
<figure id='_'>
|
1135
|
+
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
|
1136
|
+
<style/>
|
1137
|
+
<image/>
|
1138
|
+
<a xlink:href='mn://action_schema'>
|
1139
|
+
<rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
|
1140
|
+
</a>
|
1141
|
+
<a xlink:href='mn://basic_attribute_schema'>
|
1142
|
+
<rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
|
1143
|
+
</a>
|
1144
|
+
<a xlink:href='mn://support_resource_schema'>
|
1145
|
+
<rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
|
1146
|
+
</a>
|
1147
|
+
</svg>
|
1148
|
+
</figure>
|
1149
|
+
<figure id='_'>
|
1150
|
+
<image/>
|
1151
|
+
</figure>
|
1152
|
+
<figure id='_'>
|
1153
|
+
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' version='1.1' id='Layer_1_inject_1' x='0px' y='0px' viewBox='0 0 595.28 841.89' style='enable-background:new 0 0 595.28 841.89;' xml:space='preserve'>
|
1154
|
+
<style/>
|
1155
|
+
<image/>
|
1156
|
+
<a xlink:href='mn://action_schema'>
|
1157
|
+
<rect x='123.28' y='273.93' class='st0' width='88.05' height='41.84'/>
|
1158
|
+
</a>
|
1159
|
+
<a xlink:href='mn://basic_attribute_schema'>
|
1160
|
+
<rect x='324.69' y='450.52' class='st0' width='132.62' height='40.75'/>
|
1161
|
+
</a>
|
1162
|
+
<a xlink:href='mn://support_resource_schema'>
|
1163
|
+
<rect x='324.69' y='528.36' class='st0' width='148.16' height='40.75'/>
|
1164
|
+
</a>
|
1165
|
+
</svg>
|
1166
|
+
</figure>
|
1167
|
+
</sections>
|
1168
|
+
</standard-document>
|
1169
|
+
OUTPUT
|
1170
|
+
xml = Nokogiri::XML(Asciidoctor.convert(input, *OPTIONS))
|
1171
|
+
xml.xpath("//*[local-name() = 'image']").each do |x|
|
1172
|
+
x.replace("<image/>")
|
1173
|
+
end
|
1174
|
+
expect(xmlpp(strip_guid(xml.to_xml)
|
1175
|
+
.gsub(%r{<style.*?</style>}m, "<style/>")))
|
1176
|
+
.to be_equivalent_to xmlpp(output)
|
1177
|
+
end
|
1042
1178
|
end
|