metanorma-standoc 2.0.3 → 2.0.5.1

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metanorma/standoc/base.rb +73 -23
  3. data/lib/metanorma/standoc/blocks.rb +1 -1
  4. data/lib/metanorma/standoc/blocks_notes.rb +2 -2
  5. data/lib/metanorma/standoc/cleanup_amend.rb +33 -30
  6. data/lib/metanorma/standoc/cleanup_boilerplate.rb +29 -5
  7. data/lib/metanorma/standoc/cleanup_ref.rb +31 -2
  8. data/lib/metanorma/standoc/cleanup_ref_dl.rb +25 -16
  9. data/lib/metanorma/standoc/cleanup_section.rb +1 -1
  10. data/lib/metanorma/standoc/cleanup_terms_designations.rb +4 -2
  11. data/lib/metanorma/standoc/cleanup_text.rb +39 -17
  12. data/lib/metanorma/standoc/cleanup_xref.rb +70 -8
  13. data/lib/metanorma/standoc/converter.rb +2 -1
  14. data/lib/metanorma/standoc/inline.rb +21 -12
  15. data/lib/metanorma/standoc/isodoc.rng +63 -3
  16. data/lib/metanorma/standoc/macros.rb +14 -2
  17. data/lib/metanorma/standoc/macros_embed.rb +35 -14
  18. data/lib/metanorma/standoc/macros_note.rb +4 -3
  19. data/lib/metanorma/standoc/processor.rb +6 -1
  20. data/lib/metanorma/standoc/ref.rb +14 -15
  21. data/lib/metanorma/standoc/ref_utility.rb +6 -5
  22. data/lib/metanorma/standoc/render.rb +7 -3
  23. data/lib/metanorma/standoc/table.rb +8 -10
  24. data/lib/metanorma/standoc/term_lookup_cleanup.rb +10 -6
  25. data/lib/metanorma/standoc/utils.rb +3 -1
  26. data/lib/metanorma/standoc/validate.rb +79 -10
  27. data/lib/metanorma/standoc/version.rb +1 -1
  28. data/metanorma-standoc.gemspec +2 -2
  29. data/spec/assets/a2.adoc +4 -2
  30. data/spec/assets/a3.adoc +2 -2
  31. data/spec/assets/a3a.adoc +7 -0
  32. data/spec/metanorma/base_spec.rb +1 -1
  33. data/spec/metanorma/cleanup_spec.rb +31 -20
  34. data/spec/metanorma/cleanup_terms_spec.rb +16 -4
  35. data/spec/metanorma/inline_spec.rb +31 -0
  36. data/spec/metanorma/macros_plantuml_spec.rb +41 -42
  37. data/spec/metanorma/macros_spec.rb +206 -4
  38. data/spec/metanorma/processor_spec.rb +17 -13
  39. data/spec/metanorma/refs_spec.rb +129 -2
  40. data/spec/metanorma/validate_spec.rb +108 -0
  41. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +45 -45
  42. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +10 -10
  43. data/spec/vcr_cassettes/hide_refs.yml +39 -39
  44. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  45. data/spec/vcr_cassettes/isobib_get_123_1.yml +23 -23
  46. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +28 -28
  47. data/spec/vcr_cassettes/isobib_get_123_2001.yml +11 -11
  48. data/spec/vcr_cassettes/isobib_get_124.yml +12 -12
  49. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +18 -18
  50. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +75 -65
  51. metadata +10 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc4b55c7be36492191bd86bc19646a520c76e94bd2e2af9f96cf0d80d25fb05e
4
- data.tar.gz: 533fc5380552ab239528a559ee41a47c246203e17cb33df64cb5cdef5df21f34
3
+ metadata.gz: cfc9dd3ae0dd167d4c3b92c4b051619cde74ae602a66c9b34e363af1498682a0
4
+ data.tar.gz: 1cde7c4c003cdf59c2ef85e0ec1fc3247095716b6fc4f99b121c638f0744aaf9
5
5
  SHA512:
6
- metadata.gz: adc2d0b10dd30e5f59060b20574701dc6049b25a9d25eff06557ac51ca66645f62b553517690380009460f01fe135d26e83ab653b81c7746209e8f55221c3703
7
- data.tar.gz: 8bc78cf1ab42e80d93c8a22f0028e44e7ba735914fa43c2dcdd5eb53cb57b3a3ee52ea1677cae5033dbc738f8b444bc0dc2e5021ff08a443d991535c84c373b2
6
+ metadata.gz: af0f552acb3f93c8c2e1f1bff1ca60fadff61a5242e08bf0de29df086906a14025a1f6b2d2fb23a6e97afdd086fb60c9b812a91359056e6195a42a6d1d305630
7
+ data.tar.gz: cfad71e3de0a31950aee00c477a50449b97eb436ea6261584b73c616d7d24d30ab380ff7504b0357bd5e234752639a7705a43dca46f9f15983114ea50eaf2210
@@ -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: "UTF-8", 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
@@ -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
@@ -36,7 +36,7 @@ module Metanorma
36
36
  xml.review **sidebar_attrs(node) do |r|
37
37
  wrap_in_para(node, r)
38
38
  end
39
- end
39
+ end.join("\n")
40
40
  end
41
41
 
42
42
  def todo_attrs(node)
@@ -53,7 +53,7 @@ module Metanorma
53
53
  xml.review **todo_attrs(node) do |r|
54
54
  wrap_in_para(node, r)
55
55
  end
56
- end
56
+ end.join("\n")
57
57
  end
58
58
 
59
59
  def termnote(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
@@ -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,7 +144,6 @@ 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
149
  reference = format_ref(docid.children.to_xml, docid["type"])
@@ -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
@@ -182,10 +182,12 @@ module Metanorma
182
182
 
183
183
  def term_designation_reorder(xmldoc)
184
184
  xmldoc.xpath("//term").each do |t|
185
- %w(preferred admitted deprecates related)
185
+ des = %w(preferred admitted deprecates related)
186
186
  .each_with_object([]) do |tag, m|
187
187
  t.xpath("./#{tag}").each { |x| m << x.remove }
188
- end.reverse.each do |x|
188
+ end.reverse
189
+ t << " "
190
+ des.each do |x|
189
191
  t.children.first.previous = x
190
192
  end
191
193
  end
@@ -9,12 +9,6 @@ module Metanorma
9
9
  </passthrough>}mx) { HTMLEntities.new.decode($1) }
10
10
  end
11
11
 
12
- IGNORE_DUMBQUOTES =
13
- "//pre | //pre//* | //tt | //tt//* | "\
14
- "//sourcecode | //sourcecode//* | //bibdata//* | //stem | "\
15
- "//stem//* | //figure[@class = 'pseudocode'] | "\
16
- "//figure[@class = 'pseudocode']//*".freeze
17
-
18
12
  def smartquotes_cleanup(xmldoc)
19
13
  xmldoc.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
20
14
  if @smartquotes then smartquotes_cleanup1(xmldoc)
@@ -31,14 +25,21 @@ module Metanorma
31
25
  def uninterrupt_quotes_around_xml(xmldoc)
32
26
  xmldoc.traverse do |n|
33
27
  next unless n.text? && n&.previous&.element?
34
- next unless /^['"]/.match?(n.text)
35
- next unless n.previous.ancestors("pre, tt, sourcecode, stem, figure")
36
- .empty?
28
+ next if uninterrupt_quotes_around_xml_skip(n)
37
29
 
38
30
  uninterrupt_quotes_around_xml1(n.previous)
39
31
  end
40
32
  end
41
33
 
34
+ def uninterrupt_quotes_around_xml_skip(elem)
35
+ !(/^['"]/.match?(elem.text) &&
36
+ elem.previous.ancestors("pre, tt, sourcecode, stem, figure, bibdata")
37
+ .empty? &&
38
+ ((elem.previous.text.strip.empty? &&
39
+ !empty_tag_with_text_content?(elem.previous)) ||
40
+ elem.previous.name == "index"))
41
+ end
42
+
42
43
  def uninterrupt_quotes_around_xml1(elem)
43
44
  prev = elem.at(".//preceding::text()[1]") or return
44
45
  /\S$/.match?(prev.text) or return
@@ -49,19 +50,40 @@ module Metanorma
49
50
  prev.content = "#{prev.text}#{m[1]}"
50
51
  end
51
52
 
52
- def dumb2smart_quotes(xmldoc)
53
- (xmldoc.xpath("//*[child::text()]") - xmldoc.xpath(IGNORE_DUMBQUOTES))
54
- .each do |x|
55
- x.children.each do |n|
56
- next unless n.text?
53
+ def block?(elem)
54
+ %w(title name variant-title clause figure annex example introduction
55
+ foreword acknowledgements note li th td dt dd p quote label
56
+ abstract preferred admitted related deprecates field-of-application
57
+ usage-info expression pronunciation grammar-value domain
58
+ definition termnote termexample modification description
59
+ newcontent floating-title).include? elem.name
60
+ end
57
61
 
58
- /[-'"(<>]|\.\.|\dx/.match(n) or next
62
+ def empty_tag_with_text_content?(elem)
63
+ %w(eref xref termref link).include? elem.name
64
+ end
59
65
 
60
- n.replace(Metanorma::Utils::smartformat(n.text))
61
- end
66
+ def dumb2smart_quotes(xmldoc)
67
+ prev = ""
68
+ xmldoc.traverse do |x|
69
+ block?(x) and prev = ""
70
+ empty_tag_with_text_content?(x) and prev = "dummy"
71
+ next unless x.text?
72
+
73
+ x.ancestors("pre, tt, sourcecode, stem, figure, bibdata").empty? and
74
+ dumb2smart_quotes1(x, prev)
75
+ prev = x.text if x.ancestors("index").empty?
62
76
  end
63
77
  end
64
78
 
79
+ def dumb2smart_quotes1(curr, prev)
80
+ /[-'"(<>]|\.\.|\dx/.match?(curr.text) or return
81
+
82
+ /^["']/.match?(curr.text) && prev.match?(/\S$/) and
83
+ curr.content = curr.text.sub(/^"/, "”").sub(/"’"/, "‘")
84
+ curr.replace(Metanorma::Utils::smartformat(curr.text))
85
+ end
86
+
65
87
  def dumbquote_cleanup(xmldoc)
66
88
  xmldoc.traverse do |n|
67
89
  next unless n.text?