metanorma-standoc 2.0.2 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metanorma/standoc/base.rb +73 -23
  3. data/lib/metanorma/standoc/basicdoc.rng +5 -3
  4. data/lib/metanorma/standoc/biblio.rng +5 -3
  5. data/lib/metanorma/standoc/blocks.rb +4 -4
  6. data/lib/metanorma/standoc/cleanup_amend.rb +33 -30
  7. data/lib/metanorma/standoc/cleanup_boilerplate.rb +29 -5
  8. data/lib/metanorma/standoc/cleanup_image.rb +117 -3
  9. data/lib/metanorma/standoc/cleanup_ref.rb +32 -3
  10. data/lib/metanorma/standoc/cleanup_ref_dl.rb +25 -16
  11. data/lib/metanorma/standoc/cleanup_section.rb +2 -2
  12. data/lib/metanorma/standoc/cleanup_terms_designations.rb +4 -2
  13. data/lib/metanorma/standoc/cleanup_text.rb +39 -17
  14. data/lib/metanorma/standoc/cleanup_xref.rb +82 -13
  15. data/lib/metanorma/standoc/converter.rb +2 -1
  16. data/lib/metanorma/standoc/inline.rb +21 -12
  17. data/lib/metanorma/standoc/isodoc.rng +73 -3
  18. data/lib/metanorma/standoc/macros.rb +14 -2
  19. data/lib/metanorma/standoc/macros_embed.rb +35 -14
  20. data/lib/metanorma/standoc/macros_note.rb +4 -3
  21. data/lib/metanorma/standoc/processor.rb +6 -1
  22. data/lib/metanorma/standoc/ref.rb +20 -16
  23. data/lib/metanorma/standoc/ref_utility.rb +8 -6
  24. data/lib/metanorma/standoc/render.rb +7 -3
  25. data/lib/metanorma/standoc/table.rb +8 -10
  26. data/lib/metanorma/standoc/term_lookup_cleanup.rb +16 -10
  27. data/lib/metanorma/standoc/terms.rb +10 -7
  28. data/lib/metanorma/standoc/utils.rb +3 -1
  29. data/lib/metanorma/standoc/validate.rb +81 -7
  30. data/lib/metanorma/standoc/version.rb +1 -1
  31. data/metanorma-standoc.gemspec +2 -2
  32. data/spec/assets/a2.adoc +4 -2
  33. data/spec/assets/a3.adoc +2 -2
  34. data/spec/assets/a3a.adoc +7 -0
  35. data/spec/metanorma/base_spec.rb +1 -1
  36. data/spec/metanorma/cleanup_blocks_spec.rb +136 -0
  37. data/spec/metanorma/cleanup_spec.rb +34 -23
  38. data/spec/metanorma/cleanup_terms_spec.rb +16 -4
  39. data/spec/metanorma/inline_spec.rb +31 -0
  40. data/spec/metanorma/isobib_cache_spec.rb +2 -2
  41. data/spec/metanorma/macros_plantuml_spec.rb +41 -42
  42. data/spec/metanorma/macros_spec.rb +267 -4
  43. data/spec/metanorma/processor_spec.rb +17 -13
  44. data/spec/metanorma/refs_spec.rb +632 -460
  45. data/spec/metanorma/section_spec.rb +1 -1
  46. data/spec/metanorma/validate_spec.rb +108 -0
  47. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +48 -48
  48. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +13 -13
  49. data/spec/vcr_cassettes/hide_refs.yml +100 -100
  50. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  51. data/spec/vcr_cassettes/isobib_get_123_1.yml +25 -25
  52. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +35 -35
  53. data/spec/vcr_cassettes/isobib_get_123_2001.yml +11 -11
  54. data/spec/vcr_cassettes/isobib_get_124.yml +13 -13
  55. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +18 -18
  56. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +86 -66
  57. metadata +10 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9031c28646f9cd9a481ad67911f2f0f7e5bd058368f80888a788753e5f63fa3
4
- data.tar.gz: 25b16459f351f266f19b2f00d70b5bf7f6f5c95325a0d61d43fbe5f3fa518802
3
+ metadata.gz: 219579e1dcc116cb03bfddaa5d11819180d7e5b8b306f499335a39a61c2e8075
4
+ data.tar.gz: 7d8c958d3ae1e834d5e8a93c8ee3c8ebb4040e4dcee899f1bc66c87e538cdad7
5
5
  SHA512:
6
- metadata.gz: 885e62405f3198482ffd7e152b25bef8ab09fc227a8107984297e8fa15b64552b2e745f4ce5e1d60dd37df6dc5cf5c505fb9acfeedd1bdc4ef77954e01218893
7
- data.tar.gz: 69cac251a0696b46dd25f37fb23828780e1945e57464e829c91ab5d88ac481311d130c4ff0e670ee89d56fd998eff4ea48e3c5a0c4b24c514021431fb785d852
6
+ metadata.gz: a4925a6bbee7f29186d5a98cd90a51c647b4443b383f5b09e714554c1bc12da5f88c7c7143236077d96ea3685f2885c4057f245c687a5404d9f6c77489ea8063
7
+ data.tar.gz: 3644084092782115188b9240f0e8dc68e4ef4b2bb663e5e4270214ab861018ec3a3c4bfd082fbb49f9134af62e714acb309fa774d7ebeaac85a4b20444ef5ef9
@@ -26,17 +26,54 @@ module Metanorma
26
26
  end
27
27
 
28
28
  def init(node)
29
+ init_vars
30
+ init_misc(node)
31
+ init_processing(node)
32
+ init_toc(node)
33
+ init_output(node)
34
+ init_i18n(node)
35
+ init_biblio(node)
36
+ @metadata_attrs = metadata_attrs(node)
37
+ end
38
+
39
+ def init_vars
29
40
  @fn_number ||= 0
30
- @draft = false
31
41
  @refids = Set.new
32
42
  @anchors = {}
33
43
  @internal_eref_namespaces = []
44
+ @seen_headers = []
45
+ @embed_hdr = []
46
+ end
47
+
48
+ def init_misc(node)
34
49
  @draft = node.attributes.has_key?("draft")
50
+ @index_terms = node.attr("index-terms")
51
+ @boilerplateauthority = node.attr("boilerplate-authority")
52
+ @embed_hdr = node.attr("embed_hdr")
53
+ end
54
+
55
+ def init_processing(node)
35
56
  @novalid = node.attr("novalid")
36
57
  @smartquotes = node.attr("smartquotes") != "false"
37
58
  @keepasciimath = node.attr("mn-keep-asciimath") &&
38
59
  node.attr("mn-keep-asciimath") != "false"
60
+ @sourcecode_markup_start = node.attr("sourcecode-markup-start") || "{{{"
61
+ @sourcecode_markup_end = node.attr("sourcecode-markup-end") || "}}}"
62
+ @datauriimage = node.attr("data-uri-image") != "false"
63
+ end
64
+
65
+ def init_toc(node)
66
+ @htmltoclevels = node.attr("htmltoclevels")
67
+ @doctoclevels = node.attr("doctoclevels")
68
+ @toclevels = node.attr("toclevels")
69
+ @tocfigures = node.attr("toc-figures")
70
+ @toctables = node.attr("toc-tables")
71
+ @tocrecommendations = node.attr("toc-recommendations")
72
+ end
73
+
74
+ def init_output(node)
39
75
  @fontheader = default_fonts(node)
76
+ @log = Metanorma::Utils::Log.new
40
77
  @files_to_delete = []
41
78
  @filename = if node.attr("docfile")
42
79
  File.basename(node.attr("docfile"))&.gsub(/\.adoc$/, "")
@@ -44,35 +81,26 @@ module Metanorma
44
81
  end
45
82
  @localdir = Metanorma::Utils::localdir(node)
46
83
  @output_dir = outputdir node
47
- @no_isobib_cache = node.attr("no-isobib-cache")
48
- @no_isobib = node.attr("no-isobib")
49
- @index_terms = node.attr("index-terms")
50
- @sourcecode_markup_start = node.attr("sourcecode-markup-start") || "{{{"
51
- @sourcecode_markup_end = node.attr("sourcecode-markup-end") || "}}}"
52
- @bibdb = nil
53
- @seen_headers = []
54
- @datauriimage = node.attr("data-uri-image") != "false"
55
- @boilerplateauthority = node.attr("boilerplate-authority")
56
- @sourcecode_markup_start = node.attr("sourcecode-markup-start") || "{{{"
57
- @sourcecode_markup_end = node.attr("sourcecode-markup-end") || "}}}"
58
- @log = Metanorma::Utils::Log.new
59
- init_bib_caches(node)
60
- init_iev_caches(node)
84
+ end
85
+
86
+ def init_i18n(node)
61
87
  @lang = (node.attr("language") || "en")
62
88
  @script = (node.attr("script") ||
63
89
  Metanorma::Utils.default_script(node.attr("language")))
64
90
  @isodoc = isodoc(@lang, @script, node.attr("i18nyaml"))
65
91
  @i18n = @isodoc.i18n
66
- @htmltoclevels = node.attr("htmltoclevels")
67
- @doctoclevels = node.attr("doctoclevels")
68
- @toclevels = node.attr("toclevels")
69
- @metadata_attrs = metadata_attrs(node)
92
+ end
93
+
94
+ def init_biblio(node)
95
+ @no_isobib_cache = node.attr("no-isobib-cache")
96
+ @no_isobib = node.attr("no-isobib")
97
+ @bibdb = nil
98
+ init_bib_caches(node)
99
+ init_iev_caches(node)
70
100
  end
71
101
 
72
102
  def document(node)
73
- init(node)
74
- ret = makexml(node).to_xml(encoding: "US-ASCII", indent: 2)
75
- outputs(node, ret) unless node.attr("nodoc") || !node.attr("docfile")
103
+ ret = document1(node)
76
104
  clean_exit
77
105
  ret
78
106
  rescue StandardError => e
@@ -81,6 +109,28 @@ module Metanorma
81
109
  raise e
82
110
  end
83
111
 
112
+ def document1(node)
113
+ init(node)
114
+ ret = makexml(node)
115
+ .to_xml(encoding: "UTF-8", indent: 2,
116
+ save_with: Nokogiri::XML::Node::SaveOptions::AS_XML)
117
+ outputs(node, ret) unless node.attr("nodoc") || !node.attr("docfile")
118
+ ret
119
+ end
120
+
121
+ def insert_xml_cr(doc)
122
+ doc
123
+ .gsub(%r{(</(clause|table|figure|p|bibitem|ul|ol|dl|dt|dd|li|example|
124
+ sourcecode|formula|quote|references|annex|appendix|title|
125
+ name|note|thead|tbody|tfoot|th|td|form|requirement|
126
+ recommendation|permission|imagemap|svgmap|preferred|
127
+ admitted|related|deprecates|letter-symbol|domain|
128
+ graphical-symbol|expression|abbreviation-type|subject|
129
+ pronunciation|grammar|term|terms|termnote|termexample|
130
+ termsource|origin|termref|modification)>)}x, "\\1\n")
131
+ .gsub(%r{(<(title|name))}x, "\n\\1")
132
+ end
133
+
84
134
  def version
85
135
  flavour = self.class.name.sub(/::Converter$/, "").sub(/^.+::/, "")
86
136
  Metanorma.versioned(Metanorma, flavour)[-1]::VERSION
@@ -110,7 +160,7 @@ module Metanorma
110
160
 
111
161
  def makexml(node)
112
162
  result = makexml1(node)
113
- ret1 = cleanup(Nokogiri::XML(result))
163
+ ret1 = cleanup(Nokogiri::XML(insert_xml_cr(result)))
114
164
  ret1.root.add_namespace(nil, xml_namespace)
115
165
  validate(ret1) unless @novalid
116
166
  ret1
@@ -173,9 +173,11 @@
173
173
  <data type="dateTime"/>
174
174
  </attribute>
175
175
  </optional>
176
- <attribute name="from">
177
- <data type="IDREF"/>
178
- </attribute>
176
+ <optional>
177
+ <attribute name="from">
178
+ <data type="IDREF"/>
179
+ </attribute>
180
+ </optional>
179
181
  <optional>
180
182
  <attribute name="to">
181
183
  <data type="IDREF"/>
@@ -209,9 +209,6 @@
209
209
  <zeroOrMore>
210
210
  <ref name="contact"/>
211
211
  </zeroOrMore>
212
- <zeroOrMore>
213
- <ref name="uri"/>
214
- </zeroOrMore>
215
212
  </element>
216
213
  </define>
217
214
  <define name="fullname">
@@ -828,6 +825,11 @@
828
825
  <optional>
829
826
  <attribute name="scope"/>
830
827
  </optional>
828
+ <optional>
829
+ <attribute name="primary">
830
+ <data type="boolean"/>
831
+ </attribute>
832
+ </optional>
831
833
  <text/>
832
834
  </element>
833
835
  </define>
@@ -174,11 +174,11 @@ module Metanorma
174
174
  def paragraph(node)
175
175
  return termsource(node) if node.role == "source"
176
176
 
177
- noko do |xml|
177
+ ret = noko do |xml|
178
178
  xml.p **para_attrs(node) do |xml_t|
179
179
  xml_t << node.content
180
180
  end
181
- end.join("\n")
181
+ end.join
182
182
  end
183
183
 
184
184
  def quote_attrs(node)
@@ -188,7 +188,7 @@ module Metanorma
188
188
 
189
189
  def quote_attribution(node, out)
190
190
  if node.attr("citetitle")
191
- m = /^(?<cite>[^,]+)(,(?<text>.*$))?$/m.match node.attr("citetitle")
191
+ m = /^(?<cite>[^,]+)(?:,(?<text>.*$))?$/m.match node.attr("citetitle")
192
192
  out.source **attr_code(target: m[:cite], type: "inline") do |s|
193
193
  s << m[:text]
194
194
  end
@@ -203,7 +203,7 @@ module Metanorma
203
203
  quote_attribution(node, q)
204
204
  wrap_in_para(node, q)
205
205
  end
206
- end.join("\n")
206
+ end.join
207
207
  end
208
208
 
209
209
  def listing_attrs(node)
@@ -1,53 +1,56 @@
1
1
  module Metanorma
2
2
  module Standoc
3
3
  module Cleanup
4
- def change_clauses(x)
5
- x.xpath("//clause[@change]").each do |c|
6
- a = create_amend(c)
4
+ def change_clauses(docxml)
5
+ docxml.xpath("//clause[@change]").each do |c|
6
+ create_amend(c)
7
7
  end
8
8
  end
9
9
 
10
- def create_amend(c)
11
- a = c.add_child("<amend id='_#{UUIDTools::UUID.random_create}'/>").first
12
- c.elements.each do |e|
10
+ def create_amend(clause)
11
+ a = clause.add_child("<amend id='_#{UUIDTools::UUID.random_create}'/>")
12
+ .first
13
+ clause.elements.each do |e|
13
14
  e.parent = a unless %w(amend title).include? e.name
14
15
  end
15
- create_amend1(c, a)
16
+ create_amend1(clause, a)
16
17
  end
17
18
 
18
- def create_amend1(c, a)
19
- create_amend2(c, a)
20
- d = a.at("./description")
19
+ def create_amend1(clause, amend)
20
+ create_amend2(clause, amend)
21
+ d = amend.at("./description")
21
22
  d.xpath(".//autonumber").each { |e| d.previous = e }
22
- d.xpath(".//p[normalize-space(.)='']").each { |e| e.remove }
23
- move_attrs_to_amend(c, a)
24
- a
23
+ d.xpath(".//p[normalize-space(.)='']").each(&:remove)
24
+ move_attrs_to_amend(clause, amend)
25
+ amend
25
26
  end
26
27
 
27
- def create_amend2(c, a)
28
- q = a.at("./quote") and q.name = "newcontent"
28
+ def create_amend2(_clause, amend)
29
+ q = amend.at("./quote") and q.name = "newcontent"
29
30
  if q.nil?
30
- a.children = "<description>#{a.children.to_xml}</description>"
31
- else
32
- pre = q&.xpath("./preceding-sibling::*")&.remove
33
- post = q&.xpath("./following-sibling::*")&.remove
34
- pre.empty? or a << "<description>#{pre.to_xml}</description>"
35
- a << q.remove
36
- post.empty? or a << "<description>#{post.to_xml}</description>"
31
+ amend.children = "<description>#{amend.children.to_xml}</description>"
32
+ return
37
33
  end
34
+ pre = q&.xpath("./preceding-sibling::*")&.remove
35
+ post = q&.xpath("./following-sibling::*")&.remove
36
+ pre.empty? or amend << "<description>#{pre.to_xml}</description>"
37
+ amend << q.remove
38
+ post.empty? or amend << "<description>#{post.to_xml}</description>"
38
39
  end
39
40
 
40
- def move_attrs_to_amend(c, a)
41
+ def move_attrs_to_amend(clause, amend)
41
42
  %w(change path path_end title).each do |e|
42
- next unless c[e]
43
- a[e] = c[e]
44
- c.delete(e)
43
+ next unless clause[e]
44
+
45
+ amend[e] = clause[e]
46
+ clause.delete(e)
45
47
  end
46
- return unless a["locality"]
47
- loc = a.children.add_previous_sibling("<location/>")
48
- extract_localities1(loc, a["locality"])
48
+ return unless amend["locality"]
49
+
50
+ loc = amend.children.add_previous_sibling("<location/>")
51
+ extract_localities1(loc, amend["locality"])
49
52
  loc1 = loc.at("./localityStack") and loc.replace(loc1.elements)
50
- a.delete("locality")
53
+ amend.delete("locality")
51
54
  end
52
55
  end
53
56
  end
@@ -56,9 +56,9 @@ module Metanorma
56
56
  TERM_CLAUSE = "//sections/terms | "\
57
57
  "//sections/clause[descendant::terms]".freeze
58
58
 
59
- NORM_REF = "//bibliography/references[@normative = 'true'] | "\
60
- "//bibliography/clause[.//references[@normative = 'true']]"
61
- .freeze
59
+ NORM_REF =
60
+ "//bibliography/references[@normative = 'true'][not(@hidden)] | "\
61
+ "//bibliography/clause[.//references[@normative = 'true']]".freeze
62
62
 
63
63
  def boilerplate_isodoc(xmldoc)
64
64
  x = xmldoc.dup
@@ -133,6 +133,7 @@ module Metanorma
133
133
  def bibdata_cleanup(xmldoc)
134
134
  bibdata_anchor_cleanup(xmldoc)
135
135
  bibdata_docidentifier_cleanup(xmldoc)
136
+ bibdata_embed_hdr_cleanup(xmldoc)
136
137
  biblio_indirect_erefs(xmldoc, @internal_eref_namespaces&.uniq)
137
138
  end
138
139
 
@@ -190,8 +191,8 @@ module Metanorma
190
191
  def resolve_local_indirect_erefs(xmldoc, refs, prefix)
191
192
  refs.each_with_object([]) do |r, m|
192
193
  id = r.sub(/^#{prefix}_/, "")
193
- if n = xmldoc.at("//*[@id = '#{id}']") and
194
- n.at("./ancestor-or-self::*[@type = '#{prefix}']")
194
+ n = xmldoc.at("//*[@id = '#{id}']")
195
+ if n&.at("./ancestor-or-self::*[@type = '#{prefix}']")
195
196
  xmldoc.xpath("//eref[@bibitemid = '#{r}']").each do |e|
196
197
  indirect_eref_to_xref(e, id)
197
198
  end
@@ -208,6 +209,29 @@ module Metanorma
208
209
  insert_indirect_biblio(xmldoc, refs, prefix)
209
210
  end
210
211
  end
212
+
213
+ def bibdata_embed_hdr_cleanup(xmldoc)
214
+ return if @embed_hdr.nil? || @embed_hdr.empty?
215
+
216
+ embed_recurse(xmldoc.at("//bibdata"), @embed_hdr.first)
217
+ end
218
+
219
+ def hdr2bibitem(hdr)
220
+ xml = Asciidoctor
221
+ .convert(hdr[:text], backend: Processor.new.asciidoctor_backend,
222
+ header_footer: true)
223
+ b = Nokogiri::XML(xml).at("//xmlns:bibdata")
224
+ b.name = "bibitem"
225
+ b.delete("type")
226
+ embed_recurse(b, hdr)
227
+ b.to_xml
228
+ end
229
+
230
+ def embed_recurse(bibitem, node)
231
+ node[:child].map { |x| hdr2bibitem(x) }.each do |x|
232
+ bibitem << "<relation type='derivedFrom'>#{x}</relation>"
233
+ end
234
+ end
211
235
  end
212
236
  end
213
237
  end
@@ -2,6 +2,7 @@ module Metanorma
2
2
  module Standoc
3
3
  module Cleanup
4
4
  def svgmap_cleanup(xmldoc)
5
+ svg_uniqueids(xmldoc)
5
6
  svgmap_moveattrs(xmldoc)
6
7
  svgmap_populate(xmldoc)
7
8
  Metanorma::Utils::svgmap_rewrite(xmldoc, @localdir)
@@ -59,12 +60,125 @@ module Metanorma
59
60
  end
60
61
 
61
62
  def img_cleanup(xmldoc)
62
- return xmldoc unless @datauriimage
63
+ if @datauriimage
64
+ xmldoc.xpath("//image").each do |i|
65
+ # do not datauri encode SVG, we need to deduplicate its IDs
66
+ unless read_in_if_svg(i, @localdir)
67
+ i["src"] = Metanorma::Utils::datauri(i["src"], @localdir)
68
+ end
69
+ end
70
+ end
71
+ svg_uniqueids(xmldoc)
72
+ xmldoc
73
+ end
74
+
75
+ def read_in_if_svg(img, localdir)
76
+ return false unless img["src"]
77
+
78
+ path = Metanorma::Utils::svgmap_rewrite0_path(img["src"], localdir)
79
+ File.file?(path) or return false
80
+ types = MIME::Types.type_for(path) or return false
81
+ types.first == "image/svg+xml" or return false
82
+ svg = File.read(path, encoding: "utf-8") or return false
83
+ img.replace(Nokogiri::XML(svg).root.to_xml)
84
+ true
85
+ end
86
+
87
+ IRI_TAG_PROPERTIES_MAP = {
88
+ clipPath: ["clip-path"],
89
+ "color-profile": nil,
90
+ cursor: nil,
91
+ filter: nil,
92
+ linearGradient: ["fill", "stroke"],
93
+ marker: ["marker", "marker-end", "marker-mid", "marker-start"],
94
+ mask: nil,
95
+ pattern: ["fill", "stroke"],
96
+ radialGradient: ["fill", "stroke"],
97
+ }.freeze
98
+
99
+ SVG_NS = "http://www.w3.org/2000/svg".freeze
100
+
101
+ def svg_uniqueids(xmldoc)
102
+ # only keep non-unique identifiers
103
+ ids = xmldoc.xpath("//m:svg//*/@id | //svg/@id", "m" => SVG_NS)
104
+ .map(&:text).group_by(&:itself).transform_values(&:count)
105
+ .delete_if { |_, v| v < 2 }
106
+ xmldoc.xpath("//m:svg", "m" => SVG_NS).each_with_index do |s, i|
107
+ ids = svg_uniqueids1(s, i, ids)
108
+ end
109
+ end
110
+
111
+ def svg_iri_properties(id_elems)
112
+ iri_tag_names = id_elems.each_with_object([]) do |e, m|
113
+ IRI_TAG_PROPERTIES_MAP.key?(e.name.to_sym) and m = m << e.name
114
+ end.uniq
115
+ iri_properties = iri_tag_names.each_with_object([]) do |t, m|
116
+ (IRI_TAG_PROPERTIES_MAP[t.to_sym] || [t]).each { |t1| m = m << t1 }
117
+ end.uniq
118
+ return [] if iri_properties.empty?
119
+
120
+ iri_properties << "style"
121
+ end
63
122
 
64
- xmldoc.xpath("//image").each do |i|
65
- i["src"] = Metanorma::Utils::datauri(i["src"], @localdir)
123
+ def svg_uniqueids1(svg, idx, ids)
124
+ id_elems = svg.xpath(".//*[@id] | ./@id/..")
125
+ iri_properties = svg_iri_properties(id_elems)
126
+ svg_uniqueids2(svg, iri_properties, idx, ids)
127
+ new_ids = id_elems.map { |x| x["id"] }
128
+ .map { |x| x + (ids[x] ? "_inject_#{idx}" : "") }
129
+ ids.merge(new_ids.each.map { |value| [value, true] }.to_h)
130
+ end
131
+
132
+ def svg_uniqueids2(svg, iri_properties, idx, ids)
133
+ svg.traverse do |e|
134
+ next unless e.element?
135
+
136
+ if e.name == "style"
137
+ svg_styleupdate(e, idx, ids)
138
+ elsif !e.attributes.empty?
139
+ svg_attrupdate(e, iri_properties, idx, ids)
140
+ end
141
+ svg_linkupdate(e, idx, ids)
142
+ svg_idupdate(e, idx, ids)
66
143
  end
67
144
  end
145
+
146
+ def svg_update_url(text, idx, ids)
147
+ text.gsub(/url\("?#([a-zA-Z][\w:.-]*)"?\)/) do |x|
148
+ if ids[$1] then "url(##{$1}_inject_#{idx})"
149
+ else x
150
+ end
151
+ end
152
+ end
153
+
154
+ def svg_styleupdate(elem, idx, ids)
155
+ elem.children = svg_update_url(elem.text, idx, ids)
156
+ end
157
+
158
+ def svg_attrupdate(elem, iri_properties, idx, ids)
159
+ iri_properties.each do |p|
160
+ next unless elem[p]
161
+
162
+ elem[p] = svg_update_url(elem[p], idx, ids)
163
+ end
164
+ end
165
+
166
+ def svg_linkupdate(elem, idx, ids)
167
+ %w(xlink:href href).each do |ref|
168
+ iri = elem[ref]&.strip
169
+ next unless /^#/.match?(iri)
170
+ next unless ids[iri.sub(/^#/, "")]
171
+
172
+ elem[ref] += "_inject_#{idx}"
173
+ end
174
+ end
175
+
176
+ def svg_idupdate(elem, idx, ids)
177
+ return unless elem["id"]
178
+ return unless ids[elem["id"]]
179
+
180
+ elem["id"] += "_inject_#{idx}"
181
+ end
68
182
  end
69
183
  end
70
184
  end
@@ -16,7 +16,7 @@ module Metanorma
16
16
  insert = refs&.at("./bibitem")&.previous_element
17
17
  refs.xpath("./bibitem").each(&:remove)
18
18
  bib.reverse.each do |b|
19
- insert and insert.next = b.to_xml or
19
+ (insert and insert.next = b.to_xml) or
20
20
  refs.children.first.add_previous_sibling b.to_xml
21
21
  end
22
22
  extract_notes_from_biblio(refs)
@@ -84,9 +84,39 @@ module Metanorma
84
84
  biblio_reorder(xmldoc)
85
85
  biblio_nested(xmldoc)
86
86
  biblio_renumber(xmldoc)
87
+ biblio_linkonly(xmldoc)
88
+ biblio_hidden_inherit(xmldoc)
87
89
  biblio_no_ext(xmldoc)
88
90
  end
89
91
 
92
+ def biblio_hidden_inherit(xmldoc)
93
+ xmldoc.xpath("//references[@hidden = 'true']").each do |r|
94
+ r.xpath("./bibitem").each do |b|
95
+ b["hidden"] = true
96
+ end
97
+ end
98
+ end
99
+
100
+ def biblio_linkonly(xmldoc)
101
+ return unless xmldoc.at("//xref[@hidden]")
102
+
103
+ ins = xmldoc.at("//bibliography")
104
+ .add_child("<references hidden='true' normative='true'/>").first
105
+ refs = xmldoc.xpath("//xref[@hidden]").each_with_object([]) do |x, m|
106
+ @refids << x["target"]
107
+ m << { id: x["target"], ref: x["hidden"] }
108
+ x.delete("hidden")
109
+ end
110
+ ins << insert_hidden_bibitems(refs)
111
+ end
112
+
113
+ def insert_hidden_bibitems(bib)
114
+ refs = bib.each_with_object([]) do |b, m|
115
+ m << reference1code(%(<ref id="#{b[:id]}">[#{b[:ref]}]</ref>), nil)
116
+ end
117
+ reference_populate(refs)
118
+ end
119
+
90
120
  def biblio_no_ext(xmldoc)
91
121
  xmldoc.xpath("//bibitem/ext").each(&:remove)
92
122
  end
@@ -114,10 +144,9 @@ module Metanorma
114
144
 
115
145
  def reference_names(xmldoc)
116
146
  xmldoc.xpath("//bibitem[not(ancestor::bibitem)]").each do |ref|
117
- # isopub = ref.at(ISO_PUBLISHER_XPATH)
118
147
  docid = ref.at("./docidentifier[@type = 'metanorma']") ||
119
148
  ref.at("./docidentifier[not(@type = 'DOI')]") or next
120
- reference = format_ref(docid.text, docid["type"])
149
+ reference = format_ref(docid.children.to_xml, docid["type"])
121
150
  @anchors[ref["id"]] = { xref: reference }
122
151
  end
123
152
  end
@@ -15,19 +15,25 @@ module Metanorma
15
15
  end
16
16
  end
17
17
 
18
- def validate_ref_dl(bib, c)
18
+ # do not accept implicit id
19
+ def validate_ref_dl(bib, clause)
19
20
  id = bib["id"]
20
- id ||= c["id"] unless /^_/.match?(c["id"]) # do not accept implicit id
21
+ id ||= clause["id"] unless /^_/.match?(clause["id"])
21
22
  unless id
22
- @log.add("Anchors", c,
23
- "The following reference is missing an anchor:\n" + c.to_xml)
23
+ @log.add("Anchors", clause,
24
+ "The following reference is missing an anchor:\n"\
25
+ "#{clause.to_xml}")
24
26
  return
25
27
  end
26
28
  @refids << id
29
+ validate_ref_dl1(bib, id, clause)
30
+ end
31
+
32
+ def validate_ref_dl1(bib, id, clause)
27
33
  bib["title"] or
28
- @log.add("Bibliography", c, "Reference #{id} is missing a title")
34
+ @log.add("Bibliography", clause, "Reference #{id} is missing a title")
29
35
  bib["docid"] or
30
- @log.add("Bibliography", c,
36
+ @log.add("Bibliography", clause,
31
37
  "Reference #{id} is missing a document identifier (docid)")
32
38
  end
33
39
 
@@ -76,27 +82,30 @@ module Metanorma
76
82
  end
77
83
 
78
84
  # definition list, with at most one level of unordered lists
79
- def dl_bib_extract(c, nested = false)
80
- dl = c.at("./dl") or return
85
+ def dl_bib_extract(clause, nested = false)
86
+ dl = clause.at("./dl") or return
81
87
  bib = {}
82
88
  key = ""
83
89
  dl.xpath("./dt | ./dd").each do |dtd|
84
90
  (dtd.name == "dt" and key = dtd.text.sub(/:+$/, "")) or
85
91
  add_to_hash(bib, key, dd_bib_extract(dtd))
86
92
  end
87
- c.xpath("./clause").each do |c1|
93
+ clause.xpath("./clause").each do |c1|
88
94
  key = c1&.at("./title")&.text&.downcase&.strip
89
95
  next unless %w(contributor relation series).include? key
90
96
 
91
97
  add_to_hash(bib, key, dl_bib_extract(c1, true))
92
98
  end
93
- if !nested && c.at("./title")
94
- title = c.at("./title").remove.children.to_xml
95
- bib["title"] = [bib["title"]] if bib["title"].is_a? Hash
96
- bib["title"] = [bib["title"]] if bib["title"].is_a? String
97
- bib["title"] = [] unless bib["title"]
98
- bib["title"] << title if !title.empty?
99
- end
99
+ dl_bib_extract_title(bib, clause, nested)
100
+ end
101
+
102
+ def dl_bib_extract_title(bib, clause, nested)
103
+ (!nested && clause.at("./title")) or return bib
104
+ title = clause.at("./title").remove.children.to_xml
105
+ bib["title"] = [bib["title"]] if bib["title"].is_a?(Hash) ||
106
+ bib["title"].is_a?(String)
107
+ bib["title"] = [] unless bib["title"]
108
+ bib["title"] << title if !title.empty?
100
109
  bib
101
110
  end
102
111
  end
@@ -54,7 +54,7 @@ module Metanorma
54
54
  end
55
55
 
56
56
  def make_bibliography(xml, sect)
57
- if xml.at("//sections/references")
57
+ if xml.at("//sections/references | //xref[@hidden]")
58
58
  biblio = sect.add_next_sibling("<bibliography/>").first
59
59
  xml.xpath("//sections/references").each do |r|
60
60
  biblio.add_child r.remove
@@ -193,7 +193,7 @@ module Metanorma
193
193
  next unless t.next_element.nil?
194
194
  next if %w(sections annex preface).include? t.parent.name
195
195
 
196
- t.parent.parent << t
196
+ t.parent.next = t
197
197
  found = true
198
198
  end
199
199
  break unless found