Module: Metanorma::Standoc::Cleanup

Included in:
Converter
Defined in:
lib/metanorma/standoc/cleanup.rb,
lib/metanorma/standoc/cleanup_ref.rb,
lib/metanorma/standoc/cleanup_toc.rb,
lib/metanorma/standoc/cleanup_reqt.rb,
lib/metanorma/standoc/cleanup_text.rb,
lib/metanorma/standoc/cleanup_xref.rb,
lib/metanorma/standoc/cleanup_amend.rb,
lib/metanorma/standoc/cleanup_block.rb,
lib/metanorma/standoc/cleanup_image.rb,
lib/metanorma/standoc/cleanup_maths.rb,
lib/metanorma/standoc/cleanup_table.rb,
lib/metanorma/standoc/cleanup_terms.rb,
lib/metanorma/standoc/cleanup_inline.rb,
lib/metanorma/standoc/merge_bibitems.rb,
lib/metanorma/standoc/cleanup_bibdata.rb,
lib/metanorma/standoc/cleanup_bibitem.rb,
lib/metanorma/standoc/cleanup_section.rb,
lib/metanorma/standoc/cleanup_symbols.rb,
lib/metanorma/standoc/cleanup_asciibib.rb,
lib/metanorma/standoc/spans_to_bibitem.rb,
lib/metanorma/standoc/cleanup_footnotes.rb,
lib/metanorma/standoc/cleanup_boilerplate.rb,
lib/metanorma/standoc/cleanup_section_names.rb,
lib/metanorma/standoc/cleanup_terms_designations.rb,
lib/metanorma/standoc/spans_to_bibitem_preprocessing.rb

Defined Under Namespace

Classes: MergeBibitems, SpansToBibitem

Constant Summary collapse

TEXT_ELEMS =
%w{status language script version author name callout phone email
street city state country postcode identifier referenceFrom surname
referenceTo docidentifier docnumber prefix initial addition forename
title draft secretariat title-main title-intro title-part
verbal-definition non-verbal-representation}.freeze
IGNORE_QUOTES_ELEMENTS =
%w(pre tt sourcecode stem asciimath figure bibdata passthrough
identifier presentation-metadata semantic-metadata).freeze
IGNORE_TEXT_ELEMENTS =
%w(index fn).freeze
CONN_REGEX_STR =

extending localities to cover ISO referencing

"(?<conn>and|or|from|to)!".freeze
LOCALITIES =
"section|clause|part|paragraph|chapter|page|line|" \
"table|annex|figure|example|note|formula|list|time|anchor|" \
"locality:[^ \\t\\n\\r:,;=]+".freeze
LOCALITY_REGEX_STR =
<<~REGEXP.freeze
  ^((#{CONN_REGEX_STR})?
      (?<locality>#{LOCALITIES})(\\s+|=)
         (?<ref>[^"][^ \\t\\n,:;-]*|"[^"]+")
           (-(?<to>[^"][^ \\t\\n,:;-]*|"[^"]"))?|
    (?<locality2>whole|title|locality:[^ \\t\\n\\r:,;=]+))(?<punct>[,:;]?)\\s*
   (?<text>.*)$
REGEXP
LOCALITY_REGEX_VALUE_ONLY_STR =
<<~REGEXP.freeze
  ^(?<conn0>(#{CONN_REGEX_STR}))
    (?!whole|title|locality:)
    (?<value>[^=,;:\\t\\n\\r]+)
    (?<punct>[,;\\t\\n\\r]|$)
REGEXP
LOCALITY_REGEX_STR_TRIPLEDASH =
<<~REGEXP.freeze
  ^(?<locality>(#{CONN_REGEX_STR})?
      (#{LOCALITIES})(\\s+|=))
         (?<ref>[^"][^ \\t\\n,:;-]*
           -[^ \\t\\n,:;"-]+
           -[^ \\t\\n,:;"]+)
    (?<text>[,:;]?\\s*
   .*)$
REGEXP
ELEMS_ALLOW_NOTES =
%w[p formula ul ol dl figure].freeze
IRI_TAG_PROPERTIES_MAP =
{
  clipPath: ["clip-path"],
  "color-profile": nil,
  cursor: nil,
  filter: nil,
  linearGradient: ["fill", "stroke"],
  marker: ["marker", "marker-end", "marker-mid", "marker-start"],
  mask: nil,
  pattern: ["fill", "stroke"],
  radialGradient: ["fill", "stroke"],
}.freeze
SVG_NS =
"http://www.w3.org/2000/svg".freeze
MATHML_NS =
"http://www.w3.org/1998/Math/MathML".freeze
UNITSML_NS =
"https://schema.unitsml.org/unitsml/1.0".freeze
MATHVARIANT_OVERRIDE =
{
  bold: { normal: "bold", italic: "bold-italic", fraktur: "bold-fraktur",
          script: "bold-script", "sans-serif": "bold-sans-serif",
          "sans-serif-italic": "sans-serif-bold-italic" },
  italic: { normal: "italic", bod: "bold-italic",
            "sans-serif": "sans-serif-italic",
            "bold-sans-serif": "sans-serif-bold-italic" },
  "bold-italic": { normal: "bold-italic", bold: "bold-italic",
                   italic: "bold-italic",
                   "sans-serif": "sans-serif-bold-italic",
                   "bold-sans-serif": "sans-serif-bold-italic",
                   "sans-serif-italic": "sans-serif-bold-italic" },
  fraktur: { normal: "fraktur", bold: "bold-fraktur" },
  "bold-fraktur": { normal: "bold-fraktur", fraktur: "bold-fraktur" },
  script: { normal: "script", bold: "bold-script" },
  "bold-script": { normal: "script", script: "bold-script" },
  "sans-serif": { normal: "sans-serif", bold: "bold-sans-serif",
                  italic: "sans-serif-italic",
                  "bold-italic": "sans-serif-bold-italic" },
  "bold-sans-serif": { normal: "bold-sans-serif", bold: "bold-sans-serif",
                       "sans-serif": "bold-sans-serif",
                       italic: "sans-serif-bold-italic",
                       "bold-italic": "sans-serif-bold-italic",
                       "sans-serif-italic": "sans-serif-bold-italic" },
  "sans-serif-italic": { normal: "sans-serif-italic",
                         italic: "sans-serif-italic",
                         "sans-serif": "sans-serif-italic",
                         bold: "sans-serif-bold-italic",
                         "bold-italic": "sans-serif-bold-italic",
                         "sans-serif-bold": "sans-serif-bold-italic" },
  "sans-serif-bold-italic": { normal: "sans-serif-bold-italic",
                              italic: "sans-serif-bold-italic",
                              "sans-serif": "sans-serif-bold-italic",
                              "sans-serif-italic": "sans-serif-bold-italic",
                              bold: "sans-serif-bold-italic",
                              "bold-italic": "sans-serif-bold-italic",
                              "sans-serif-bold": "sans-serif-bold-italic" },
}.freeze
TERMDEF_BLOCKS =
"./p | ./ol | ./dl[not(@metadata = 'true')] | ./ul | ./figure | " \
"./formula | ./table".freeze
IDREF =
"//*/@id | //review/@from | //review/@to | " \
"//callout/@target | //citation/@bibitemid | " \
"//eref/@bibitemid".freeze
FIGURE_FN_XPATH =
"//figure/following-sibling::*[1][self::p and *[1][self::fn]]".freeze
TERM_CLAUSE =
"//sections/terms | " \
"//sections/clause[descendant::terms]".freeze
NORM_REF =
"//bibliography/references[@normative = 'true'][not(@hidden)] | " \
"//bibliography/clause[.//references[@normative = 'true']]".freeze
NO_SYMABBR =
"[.//definitions[not(@type)]]".freeze
SYMABBR =
"[.//definitions[@type = 'symbols']]" \
"[.//definitions[@type = 'abbreviated_terms']]".freeze
SYMnoABBR =
"[.//definitions[@type = 'symbols']]" \
"[not(.//definitions[@type = 'abbreviated_terms'])]".freeze
ABBRnoSYM =
"[.//definitions[@type = 'abbreviated_terms']]" \
"[not(.//definitions[@type = 'symbols'])]".freeze
SECTION_CONTAINERS =
%w(foreword introduction acknowledgements abstract
clause clause references terms definitions annex
appendix).freeze
DESIGNATOR =
%w(preferred admitted deprecates related).freeze

Instance Method Summary collapse

Instance Method Details

#add_locality(stack, match) ⇒ Object



84
85
86
87
88
89
90
91
92
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 84

def add_locality(stack, match)
  stack.children.empty? && match[:conn] and
    stack["connective"] = match[:conn]
  ref =
    match[:ref] ? "<referenceFrom>#{tq match[:ref]}</referenceFrom>" : ""
  refto = match[:to] ? "<referenceTo>#{tq match[:to]}</referenceTo>" : ""
  stack.add_child("<locality type='#{locality_label(match)}'>#{ref}" \
                  "#{refto}</locality>")
end

#add_misc_container(xmldoc) ⇒ Object



105
106
107
108
109
110
111
112
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 105

def add_misc_container(xmldoc)
  unless ins = xmldoc.at("//metanorma-extension")
    a = xmldoc.xpath("//termdocsource")&.last || xmldoc.at("//bibdata")
    a.next = "<metanorma-extension/>"
    ins = xmldoc.at("//metanorma-extension")
  end
  ins
end

#add_to_hash(bib, key, val) ⇒ Object



72
73
74
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 72

def add_to_hash(bib, key, val)
  Metanorma::Utils::set_nested_value(bib, key.split("."), val)
end

#align_callouts_to_annotations(xmldoc) ⇒ Object



120
121
122
123
124
125
126
127
# File 'lib/metanorma/standoc/cleanup_block.rb', line 120

def align_callouts_to_annotations(xmldoc)
  xmldoc.xpath("//sourcecode").each do |x|
    callouts = x.elements.select { |e| e.name == "callout" }
    annotations = x.elements.select { |e| e.name == "annotation" }
    callouts.size == annotations.size and
      link_callouts_to_annotations(callouts, annotations)
  end
end

#alternate_termdefinitions(xmldoc) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 56

def alternate_termdefinitions(xmldoc)
  xmldoc.xpath("//term").each do |t|
    t.xpath("./definition").each do |d|
      d1 = d.next_element or next
      if (v = d.at("./verbal-definition")) &&
          !d.at("./non-verbal-representation") &&
          !d1.at("./verbal-definition") &&
          nv = d1.at("./non-verbal-representation")
        v.next = nv.remove
        d1.remove
      end
    end
  end
end

#amend_attrs(yaml) ⇒ Object



190
191
192
193
194
195
196
197
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 190

def amend_attrs(yaml)
  ret = ""
  yaml["change"] ||= "modify"
  %w(change path path_end title).each do |x|
    a = yaml[x] and ret += " #{x}='#{a}'"
  end
  ret = "<amend#{ret}>"
end

#amend_classification(yaml) ⇒ Object



224
225
226
227
228
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 224

def amend_classification(yaml)
  a = yaml["classification"] or return ""
  a.is_a?(Array) or a = [a]
  a.map { |x| amend_classification1(x) }.join("\n")
end

#amend_classification1(yaml) ⇒ Object



230
231
232
233
234
235
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 230

def amend_classification1(yaml)
  yaml.is_a?(Hash) or yaml = { "tag" => "default", "value" => yaml }
  <<~OUT
    <classification><tag>#{yaml['tag']}</tag><value>#{yaml['value']}</value></classification>
  OUT
end

#amend_description(yaml) ⇒ Object



218
219
220
221
222
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 218

def amend_description(yaml)
  a = yaml["description"] or return ""
  out = adoc2xml(a, backend.to_sym)
  "<description>#{out.children.to_xml}</description>"
end

#amend_hash2mn(yaml) ⇒ Object



184
185
186
187
188
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 184

def amend_hash2mn(yaml)
  yaml.nil? and return ""
  yaml.is_a?(Hash) and yaml = [yaml]
  yaml.map { |x| amend_hash2mn1(x) }.join("\n")
end

#amend_hash2mn1(yaml) ⇒ Object



199
200
201
202
203
204
205
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 199

def amend_hash2mn1(yaml)
  ret = amend_attrs(yaml)
  ret += amend_description(yaml)
  ret += amend_location(yaml)
  ret += amend_classification(yaml)
  "#{ret}</amend>"
end

#amend_location(yaml) ⇒ Object



207
208
209
210
211
212
213
214
215
216
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 207

def amend_location(yaml)
  a = yaml["location"] or return ""
  a.is_a?(Array) or a = [a]
  ret = a.map do |x|
    elem = Nokogiri::XML("<location>#{x}</location>").root
    extract_localities(elem)
    elem.children.to_xml
  end.join("\n")
  "<location>#{ret}</location>"
end

#anchor_alias(xmldoc) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 151

def anchor_alias(xmldoc)
  t = xmldoc.at("//metanorma-extension/table[@id = " \
                "'_misccontainer_anchor_aliases']") or return
  key = ""
  t.xpath("./tbody/tr").each do |tr|
    tr.xpath("./td | ./th").each_with_index do |td, i|
      if i.zero? then key = td.text
      else anchor_alias1(key, td)
      end
    end
  end
end

#anchor_alias1(key, elem) ⇒ Object



164
165
166
167
168
169
170
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 164

def anchor_alias1(key, elem)
  id = elem.text.strip
  id.empty? and elem.at("./link") and
    id = elem.at("./link/@target")&.text
  (key && !id.empty?) or return
  @anchor_alias[id] = key
end

#anchor_cleanup(elem) ⇒ Object



138
139
140
141
142
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 138

def anchor_cleanup(elem)
  anchor_cleanup1(elem)
  xreftarget_cleanup(elem)
  contenthash_id_cleanup(elem)
end

#anchor_cleanup1(elem) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 144

def anchor_cleanup1(elem)
  elem.xpath(IDREF).each do |s|
    if (ret = Metanorma::Utils::to_ncname(s.value)) != (orig = s.value)
      s.value = ret
      output = s.parent.dup
      output.children.remove
      @log.add("Anchors", s.parent,
               "normalised identifier in #{output} from #{orig}")
    end
  end
end

#asciimath2mathml(xml) ⇒ Object



10
11
12
13
14
15
16
17
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 10

def asciimath2mathml(xml)
  xpath = xml.xpath("//stem[@type = 'AsciiMath']")
  xpath.each_with_index do |x, i|
    progress_conv(i, 500, xpath.size, 1000, "AsciiMath")
    asciimath2mathml_indiv(x)
  end
  asciimath2mathml_wrap(xml)
end

#asciimath2mathml_err(text, expr) ⇒ Object



30
31
32
33
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 30

def asciimath2mathml_err(text, expr)
  err = "Malformed MathML: #{expr}\n#{text}"
  @log.add("Maths", nil, err, severity: 0)
end

#asciimath2mathml_indiv(elem) ⇒ Object



19
20
21
22
23
24
25
26
27
28
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 19

def asciimath2mathml_indiv(elem)
  elem["type"] = "MathML"
  expr = @c.decode(elem.text)
  ret = Plurimath::Math.parse(expr, "asciimath")
    .to_mathml(display_style: elem["block"])
  ret += "<asciimath>#{@c.encode(@c.decode(expr), :basic)}</asciimath>"
  elem.children = ret
rescue StandardError => e
  asciimath2mathml_err(elem.to_xml, e)
end

#asciimath2mathml_wrap(xml) ⇒ Object



35
36
37
38
39
40
41
42
43
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 35

def asciimath2mathml_wrap(xml)
  xml.xpath("//*[local-name() = 'math'][@display]").each do |y|
    y.delete("display")
  end
  # x.xpath("//stem").each do |y|
  # y.next_element&.name == "asciimath" and y << y.next_element
  # end
  xml
end

#asciimath2unitsml_optionsObject



135
136
137
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 135

def asciimath2unitsml_options
  { multiplier: :space }
end

#asciimath_cleanup(xml) ⇒ Object



6
7
8
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 6

def asciimath_cleanup(xml)
  !@keepasciimath and asciimath2mathml(xml)
end

#auto_name_definitions(xml) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 77

def auto_name_definitions(xml)
  xml.xpath("//definitions[@type = 'symbols']").size > 1 and return false
  xml.xpath("//definitions[@type = 'abbreviated_terms']").size > 1 and
    return false
  xml.xpath("//definitions[not(@type)]").size > 1 and return false
  true
end

#auto_name_terms(xml) ⇒ Object

do not auto-name terms sections if there are terms subclauses not covered by the auto titles, or if more than one title is covered by an auto title



102
103
104
105
106
107
108
109
110
111
112
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 102

def auto_name_terms(xml)
  n = xml.at("//terms | //clause[.//terms]")
  out = terms_subclauses(n)
    .each_with_object({ term: 0, sna: 0, ans: 0, sa: 0, nsa: 0,
                        tsna: 0, tans: 0, tsa: 0, tnsa: 0,
                        termdef: 0, other: 0 }) do |x, m|
    terms_subclause_type_tally(x, m, n)
  end
  out.delete(:parent)
  !out.values.detect { |x| x > 1 } && out[:other].zero?
end

#bib_relation_insert_pt(xmldoc) ⇒ Object



153
154
155
156
157
158
159
160
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 153

def bib_relation_insert_pt(xmldoc)
  ins = nil
  %w(relation copyright status abstract script language note version
     edition contributor).each do |x|
    ins = xmldoc.at("//bibdata/#{x}[last()]") and break
  end
  ins
end

#bibabstract_location(xml) ⇒ Object



60
61
62
63
64
65
66
67
68
69
# File 'lib/metanorma/standoc/cleanup_section.rb', line 60

def bibabstract_location(xml)
  xml.at("//bibdata/script") || xml.at("//bibdata/language") ||
    xml.at("//bibdata/contributor[not(following-sibling::contributor)]") ||
    xml.at("//bibdata/date[not(following-sibling::date)]") ||
    xml.at("//docnumber") ||
    xml.at("//bibdata/docidentifier" \
           "[not(following-sibling::docidentifier)]") ||
    xml.at("//bibdata/uri[not(following-sibling::uri)]") ||
    xml.at("//bibdata/title[not(following-sibling::title)]")
end

#bibdata_anchor_cleanup(xmldoc) ⇒ Object



12
13
14
15
16
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 12

def bibdata_anchor_cleanup(xmldoc)
  xmldoc.xpath("//bibdata//bibitem | //bibdata//note").each do |b|
    b.delete("id")
  end
end

#bibdata_cleanup(xmldoc) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 4

def bibdata_cleanup(xmldoc)
  bibdata_anchor_cleanup(xmldoc)
  bibdata_docidentifier_cleanup(xmldoc)
  bibdata_embed_hdr_cleanup(xmldoc) # feeds bibdata_embed_id_cleanup
  bibdata_embed_id_cleanup(xmldoc)
  biblio_indirect_erefs(xmldoc, @internal_eref_namespaces&.uniq)
end

#bibdata_docidentifier_cleanup(xmldoc) ⇒ Object



18
19
20
21
22
23
24
25
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 18

def bibdata_docidentifier_cleanup(xmldoc)
  ins = xmldoc.at("//bibdata/docidentifier")
  xmldoc.xpath("//bibdata/docidentifier").each_with_index do |b, i|
    i.zero? and next
    ins.next = b.remove
    ins = ins.next
  end
end

#bibdata_embed_hdr_cleanup(xmldoc) ⇒ Object



83
84
85
86
87
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 83

def bibdata_embed_hdr_cleanup(xmldoc)
  (@embed_hdr.nil? || @embed_hdr.empty?) and return
  xmldoc.at("//bibdata") << "<relation type='derivedFrom'>" \
                            "#{hdr2bibitem(@embed_hdr.first)}</relation>"
end

#bibdata_embed_id_cleanup(xmldoc) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 113

def bibdata_embed_id_cleanup(xmldoc)
  @embed_id.nil? and return
  bibdata = xmldoc.at("//bibdata")
  @embed_id.each do |d|
    bibdata = bibdata.at("./relation[@type = 'derivedFrom']/bibitem")
    ident = bibdata.at("./docidentifier[@primary = 'true']") ||
      bibdata.at("./docidentifier")
    xmldoc.xpath("//xref[@target = '#{d}'][normalize-space(text()) = '']")
      .each { |x| x << ident.text }
  end
end

#bibitem_cleanup(xmldoc) ⇒ Object



136
137
138
139
140
141
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 136

def bibitem_cleanup(xmldoc)
  bibitem_nested_id(xmldoc)
  ref_dl_cleanup(xmldoc)
  formattedref_spans(xmldoc)
  fetch_local_bibitem(xmldoc)
end

#bibitem_nested_id(xmldoc) ⇒ Object



130
131
132
133
134
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 130

def bibitem_nested_id(xmldoc)
  xmldoc.xpath("//bibitem//bibitem").each do |b|
    b.delete("id")
  end
end

#biblio_annex(xmldoc) ⇒ Object



94
95
96
97
98
99
100
101
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 94

def biblio_annex(xmldoc)
  xmldoc.xpath("//annex[references/references]").each do |t|
    t.xpath("./clause | ./references | ./terms").size == 1 or next
    r = t.at("./references")
    r.xpath("./references").each { |b| b["normative"] = r["normative"] }
    r.replace(r.elements)
  end
end

#biblio_cleanup(xmldoc) ⇒ Object



65
66
67
68
69
70
71
72
73
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 65

def biblio_cleanup(xmldoc)
  biblio_reorder(xmldoc)
  biblio_annex(xmldoc)
  biblio_nested(xmldoc)
  biblio_renumber(xmldoc)
  biblio_linkonly(xmldoc)
  biblio_hidden_inherit(xmldoc)
  biblio_no_ext(xmldoc)
end

#biblio_hidden_inherit(xmldoc) ⇒ Object



46
47
48
49
50
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 46

def biblio_hidden_inherit(xmldoc)
  xmldoc.xpath("//references[@hidden = 'true']").each do |r|
    r.xpath("./bibitem").each { |b| b["hidden"] = true }
  end
end

#biblio_indirect_erefs(xmldoc, prefixes) ⇒ Object



74
75
76
77
78
79
80
81
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 74

def biblio_indirect_erefs(xmldoc, prefixes)
  prefixes&.each do |prefix|
    refs = gather_indirect_erefs(xmldoc, prefix)
    refs = resolve_local_indirect_erefs(xmldoc, refs, prefix)
    refs.empty? and next
    insert_indirect_biblio(xmldoc, refs, prefix)
  end
end

#biblio_linkonly(xmldoc) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 75

def biblio_linkonly(xmldoc)
  xmldoc.at("//xref[@hidden]") or return
  ins = xmldoc.at("//bibliography")
    .add_child("<references hidden='true' normative='true'/>").first
  refs = xmldoc.xpath("//xref[@hidden]").each_with_object([]) do |x, m|
    @refids << x["target"]
    m << { id: x["target"], ref: x["hidden"] }
    x.delete("hidden")
  end
  ins << insert_hidden_bibitems(refs)
end

#biblio_nested(xmldoc) ⇒ Object



103
104
105
106
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 103

def biblio_nested(xmldoc)
  biblio_nested_initial_items(xmldoc)
  biblio_nested_sections(xmldoc)
end

#biblio_nested_initial_items(xmldoc) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 108

def biblio_nested_initial_items(xmldoc)
  xmldoc.xpath("//references[references][bibitem]").each do |t|
    r = t.at("./references")
    ref = t.at("./bibitem")
      .before("<references unnumbered='true'></references>").previous
    (ref.xpath("./following-sibling::*") &
     r.xpath("./preceding-sibling::*")).each do |x|
      ref << x
    end
  end
end

#biblio_nested_sections(xmldoc) ⇒ Object



120
121
122
123
124
125
126
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 120

def biblio_nested_sections(xmldoc)
  xmldoc.xpath("//references[references]").each do |t|
    t.name = "clause"
    t.xpath("./references").each { |r| r["normative"] = t["normative"] }
    t.delete("normative")
  end
end

#biblio_no_ext(xmldoc) ⇒ Object



52
53
54
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 52

def biblio_no_ext(xmldoc)
  xmldoc.xpath("//bibitem/ext").each(&:remove)
end

#biblio_renumber(xmldoc) ⇒ Object

default presuppose that all citations in biblio numbered consecutively, but that standards codes are preserved as is: only numeric references are renumbered



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 36

def biblio_renumber(xmldoc)
  i = 0
  xmldoc.xpath("//references[not(@normative = 'true')]" \
               "[not(@hidden = 'true')]").each do |r|
    r.xpath("./bibitem[not(@hidden = 'true')]").each do |b|
      i += 1
      docid = b.at("./docidentifier[@type = 'metanorma']") or next
      /^\[\d+\]$/.match?(docid.text) or next
      docid.children = "[#{i}]"
    end
  end
end

#biblio_reorder(xmldoc) ⇒ Object



10
11
12
13
14
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 10

def biblio_reorder(xmldoc)
  xmldoc.xpath("//references[@normative = 'false']").each do |r|
    biblio_reorder1(r)
  end
end

#biblio_reorder1(refs) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 16

def biblio_reorder1(refs)
  fold_notes_into_biblio(refs)
  bib = sort_biblio(refs.xpath("./bibitem"))
  insert = refs.at("./bibitem")&.previous_element
  refs.xpath("./bibitem").each(&:remove)
  bib.reverse.each do |b|
    (insert and insert.next = b.to_xml) or
      refs.children.first.add_previous_sibling b.to_xml
  end
  extract_notes_from_biblio(refs)
  refs.xpath("./references").each { |r| biblio_reorder1(r) }
end

#block?(elem) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
69
70
71
72
73
# File 'lib/metanorma/standoc/cleanup_text.rb', line 66

def block?(elem)
  %w(title name variant-title clause figure annex example introduction
     foreword acknowledgements note li th td dt dd p quote label
     abstract preferred admitted related deprecates field-of-application
     usage-info expression pronunciation grammar-value domain
     definition termnote termexample modification description
     newcontent floating-title tab).include? elem.name
end

#block_index_cleanup(xmldoc) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/metanorma/standoc/cleanup_block.rb', line 179

def block_index_cleanup(xmldoc)
  xmldoc.xpath("//quote | //td | //th | //formula | //li | //dt | " \
               "//dd | //example | //note | //figure | //sourcecode | " \
               "//admonition | //termnote | //termexample | //form  | " \
               "//requirement | //recommendation | //permission | " \
               "//imagemap | //svgmap").each do |b|
    b.xpath("./p[indexterm]").each do |p|
      indexterm_para?(p) or next
      p.replace(p.children)
    end
  end
end

#blocksource_cleanup(xmldoc) ⇒ Object



226
227
228
229
230
231
# File 'lib/metanorma/standoc/cleanup_block.rb', line 226

def blocksource_cleanup(xmldoc)
  xmldoc.xpath("//figure//termsource | //table//termsource").each do |s|
    s.name = "source"
    s.delete("type")
  end
end

#boilerplate(xml, conv) ⇒ Object



139
140
141
142
143
144
145
146
147
148
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 139

def boilerplate(xml, conv)
  # prevent infinite recursion of asciidoc boilerplate processing
  xml.at("//metanorma-extension/semantic-metadata/" \
         "headless[text() = 'true']") and return nil
  file = boilerplate_file(xml)
  @boilerplateauthority and
    file2 = File.join(@localdir, @boilerplateauthority)
  resolve_boilerplate_files(process_boilerplate_file(file, conv),
                            process_boilerplate_file(file2, conv))
end

#boilerplate_cleanup(xmldoc) ⇒ Object



118
119
120
121
122
123
124
125
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 118

def boilerplate_cleanup(xmldoc)
  isodoc = boilerplate_isodoc(xmldoc)
  termdef_boilerplate_cleanup(xmldoc)
  termdef_boilerplate_insert(xmldoc, isodoc)
  unwrap_boilerplate_clauses(xmldoc, self.class::TERM_CLAUSE)
  f = xmldoc.at(self.class::NORM_REF) and norm_ref_preface(f)
  initial_boilerplate(xmldoc, isodoc)
end

#boilerplate_file(_xmldoc) ⇒ Object



135
136
137
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 135

def boilerplate_file(_xmldoc)
  File.join(@libdir, "boilerplate.xml")
end

#boilerplate_file_convert(file) ⇒ Object

If Asciidoctor, convert top clauses to tags and wrap in <boilerplate>



186
187
188
189
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 186

def boilerplate_file_convert(file)
  ret = Nokogiri::XML(file).root and return ret
  boilerplate_file_restructure(file)
end

#boilerplate_file_restructure(file) ⇒ Object

If Asciidoctor, convert top clauses to tags and wrap in <boilerplate>



192
193
194
195
196
197
198
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 192

def boilerplate_file_restructure(file)
  ret = adoc2xml(file, backend.to_sym)
  boilerplate_xml_cleanup(ret)
  ret.name = "boilerplate"
  boilerplate_top_elements(ret)
  ret
end

#boilerplate_isodoc(xmldoc) ⇒ Object



63
64
65
66
67
68
69
70
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 63

def boilerplate_isodoc(xmldoc)
  x = xmldoc.dup
  x.root.add_namespace(nil, self.class::XML_NAMESPACE)
  xml = Nokogiri::XML(x.to_xml)
  @isodoc ||= isodoc(@lang, @script, @locale)
  @isodoc.info(xml, nil)
  @isodoc
end

#boilerplate_read(file) ⇒ Object



178
179
180
181
182
183
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 178

def boilerplate_read(file)
  ret = File.read(file, encoding: "UTF-8")
  /\.adoc$/.match?(file) and
    ret.gsub!(/(?<!\{)(\{\{[^{}]+\}\})(?!\})/, "pass:[\\1]")
  ret
end

#boilerplate_top_elements(xml) ⇒ Object



214
215
216
217
218
219
220
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 214

def boilerplate_top_elements(xml)
  xml.elements.each do |e|
    (t = e.at("./title") and /-statement$/.match?(t.text)) or next
    e.name = t.remove.text
    e.keys.each { |a| e.delete(a) } # rubocop:disable Style/HashEachMethods
  end
end

#boilerplate_xml_cleanup(xml) ⇒ Object

remove Metanorma namespace, so generated doc containing boilerplate can be queried consistently _d+ anchor is assigned to titleless clauses, will clash with main doc instances of same



204
205
206
207
208
209
210
211
212
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 204

def boilerplate_xml_cleanup(xml)
  ns = xml.namespace.href
  xml.traverse do |n|
    n.element? or next
    n.namespace.href == ns and n.namespace = nil
    /^_\d+$/.match?(n["id"]) and
      n["id"] = "_#{UUIDTools::UUID.random_create}"
  end
end

#bookmark_cleanup(xmldoc) ⇒ Object



26
27
28
29
30
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 26

def bookmark_cleanup(xmldoc)
  redundant_bookmark_cleanup(xmldoc)
  li_bookmark_cleanup(xmldoc)
  dt_bookmark_cleanup(xmldoc)
end

#bookmark_to_id(elem, bookmark) ⇒ Object



43
44
45
46
47
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 43

def bookmark_to_id(elem, bookmark)
  parent = bookmark.parent
  elem["id"] = bookmark.remove["id"]
  strip_initial_space(parent)
end

#bpart_cleanup(xmldoc) ⇒ Object

allows us to deal with doc relation localities, temporarily stashed to “bpart”



129
130
131
132
133
134
# File 'lib/metanorma/standoc/cleanup.rb', line 129

def bpart_cleanup(xmldoc)
  xmldoc.xpath("//relation/bpart").each do |x|
    extract_localities(x)
    x.replace(x.children)
  end
end

#callout_cleanup(xmldoc) ⇒ Object



137
138
139
140
# File 'lib/metanorma/standoc/cleanup_block.rb', line 137

def callout_cleanup(xmldoc)
  merge_annotations_into_sourcecode(xmldoc)
  align_callouts_to_annotations(xmldoc)
end

#change_clauses(docxml) ⇒ Object



4
5
6
7
8
# File 'lib/metanorma/standoc/cleanup_amend.rb', line 4

def change_clauses(docxml)
  docxml.xpath("//clause[@change]").each do |c|
    create_amend(c)
  end
end

#clausebefore_cleanup(xmldoc) ⇒ Object



178
179
180
181
# File 'lib/metanorma/standoc/cleanup_section.rb', line 178

def clausebefore_cleanup(xmldoc)
  sections_clausebefore_cleanup(xmldoc)
  preface_clausebefore_cleanup(xmldoc)
end

#clean_abstract(dupabstract) ⇒ Object



52
53
54
55
56
57
58
# File 'lib/metanorma/standoc/cleanup_section.rb', line 52

def clean_abstract(dupabstract)
  dupabstract.traverse { |n| n.remove_attribute("id") }
  dupabstract.remove_attribute("language")
  dupabstract.remove_attribute("script")
  dupabstract.at("./title")&.remove
  dupabstract
end

#cleanup(xmldoc) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/metanorma/standoc/cleanup.rb', line 27

def cleanup(xmldoc)
  @doctype = xmldoc.at("//bibdata/ext/doctype")&.text
  element_name_cleanup(xmldoc)
  passthrough_cleanup(xmldoc)
  unnumbered_blocks_cleanup(xmldoc)
  termdocsource_cleanup(xmldoc) # feeds: metadata_cleanup
  (xmldoc) # feeds: boilerplate_cleanup
  sections_cleanup(xmldoc) # feeds: obligations_cleanup, toc_cleanup,
  # floatingtitle_cleanup
  obligations_cleanup(xmldoc)
  para_index_cleanup(xmldoc)
  block_index_cleanup(xmldoc)
  table_cleanup(xmldoc) # feeds: blocksource_cleanup
  formula_cleanup(xmldoc)
  form_cleanup(xmldoc)
  sourcecode_cleanup(xmldoc) # feeds: callout_cleanup
  figure_cleanup(xmldoc)
  blocksource_cleanup(xmldoc)
  requirement_cleanup(xmldoc) # feeds: xref_cleanup
  element_name_cleanup(xmldoc)
  ref_cleanup(xmldoc) # feeds: bibitem_cleanup
  note_cleanup(xmldoc)
  clausebefore_cleanup(xmldoc) # feeeds: floatingtitle_cleanup
  floatingtitle_cleanup(xmldoc)
  bibitem_cleanup(xmldoc) # feeds: normref_cleanup, biblio_cleanup,
  # reference_names, bpart_cleanup
  normref_cleanup(xmldoc)
  biblio_cleanup(xmldoc)
  reference_names(xmldoc)
  asciimath_cleanup(xmldoc) # feeds: mathml_cleanup, termdef_cleanup,
  # symbols_cleanup
  symbols_cleanup(xmldoc) # feeds: termdef_cleanup
  xref_cleanup(xmldoc) # feeds: concept_cleanup, origin_cleanup
  concept_cleanup(xmldoc) # feeds: related_cleanup, termdef_cleanup
  related_cleanup(xmldoc) # feeds: termdef_cleanup
  origin_cleanup(xmldoc) # feeds: termdef_cleanup
  bookmark_cleanup(xmldoc)
  termdef_cleanup(xmldoc) # feeds: relaton_iev_cleanup, term_index_cleanup
  relaton_iev_cleanup(xmldoc)
  element_name_cleanup(xmldoc)
  term_index_cleanup(xmldoc)
  bpart_cleanup(xmldoc)
  quotesource_cleanup(xmldoc)
  callout_cleanup(xmldoc)
  footnote_cleanup(xmldoc)
  ol_cleanup(xmldoc)
  mathml_cleanup(xmldoc)
  script_cleanup(xmldoc)
  docidentifier_cleanup(xmldoc) # feeds: bibdata_cleanup
  ext_contributor_cleanup(xmldoc) # feeds: bibdata_cleanup
  ext_dochistory_cleanup(xmldoc) # feeds: bibdata_cleanup
  bibdata_cleanup(xmldoc)
  svgmap_cleanup(xmldoc) # feeds: img_cleanup
  boilerplate_cleanup(xmldoc)
  toc_cleanup(xmldoc)
  smartquotes_cleanup(xmldoc)
  variant_cleanup(xmldoc)
  para_cleanup(xmldoc)
  empty_element_cleanup(xmldoc)
  img_cleanup(xmldoc)
  anchor_cleanup(xmldoc)
  link_cleanup(xmldoc)
  xmldoc
end

#concept_cleanup(xmldoc) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 72

def concept_cleanup(xmldoc)
  xmldoc.xpath("//concept[not(termxref)]").each do |x|
    term = x.at("./refterm")
    term&.remove if term&.text&.empty?
    concept_cleanup1(x)
  end
end

#concept_cleanup1(elem) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 80

def concept_cleanup1(elem)
  elem.children.remove if elem&.children&.text&.strip&.empty?
  key_extract_locality(elem)
  if elem["key"].include?(":") then concept_termbase_cleanup(elem)
  elsif refid? elem["key"] then concept_eref_cleanup(elem)
  else concept_xref_cleanup(elem)
  end
  elem.delete("key")
end

#concept_eref_cleanup(elem) ⇒ Object



117
118
119
120
121
122
123
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 117

def concept_eref_cleanup(elem)
  t = elem.at("./xrefrender")&.remove&.children&.to_xml
  l = elem.at("./locality")&.remove&.children&.to_xml
  elem.add_child "<eref bibitemid='#{elem['key']}'>#{l}</eref>"
  extract_localities(elem.elements[-1])
  elem.elements[-1].add_child(t) if t
end

#concept_termbase_cleanup(elem) ⇒ Object



105
106
107
108
109
110
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 105

def concept_termbase_cleanup(elem)
  t = elem&.at("./xrefrender")&.remove&.children
  termbase, key = elem["key"].split(":", 2)
  elem.add_child(%(<termref base="#{termbase}" target="#{key}">) +
                 "#{t&.to_xml}</termref>")
end

#concept_xref_cleanup(elem) ⇒ Object



112
113
114
115
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 112

def concept_xref_cleanup(elem)
  t = elem&.at("./xrefrender")&.remove&.children
  elem.add_child(%(<xref target="#{elem['key']}">#{t&.to_xml}</xref>))
end

#contenthash(elem) ⇒ Object



196
197
198
199
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 196

def contenthash(elem)
  Digest::MD5.hexdigest("#{elem.path}////#{elem.text}")
    .sub(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, "_\\1-\\2-\\3-\\4-\\5")
end

#contenthash_id_cleanup(doc) ⇒ Object



173
174
175
176
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 173

def contenthash_id_cleanup(doc)
  ids = contenthash_id_make(doc)
  contenthash_id_update_refs(doc, ids)
end

#contenthash_id_make(doc) ⇒ Object



178
179
180
181
182
183
184
185
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 178

def contenthash_id_make(doc)
  doc.xpath("//*[@id]").each_with_object({}) do |x, m|
    next unless guid?(x["id"])

    m[x["id"]] = contenthash(x)
    x["id"] = m[x["id"]]
  end
end

#contenthash_id_update_refs(doc, ids) ⇒ Object



187
188
189
190
191
192
193
194
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 187

def contenthash_id_update_refs(doc, ids)
  [%w(review from), %w(review to), %w(callout target), %w(eref bibitemid),
   %w(citation bibitemid), %w(xref target), %w(xref to)].each do |a|
    doc.xpath("//#{a[0]}").each do |x|
      ids[x[a[1]]] and x[a[1]] = ids[x[a[1]]]
    end
  end
end

#create_amend(clause) ⇒ Object



10
11
12
13
14
15
16
17
# File 'lib/metanorma/standoc/cleanup_amend.rb', line 10

def create_amend(clause)
  a = clause.add_child("<amend id='_#{UUIDTools::UUID.random_create}'/>")
    .first
  clause.elements.each do |e|
    e.parent = a unless %w(amend title).include? e.name
  end
  create_amend1(clause, a)
end

#create_amend1(clause, amend) ⇒ Object



19
20
21
22
23
24
25
26
27
# File 'lib/metanorma/standoc/cleanup_amend.rb', line 19

def create_amend1(clause, amend)
  create_amend2(clause, amend)
  d = amend.at("./description")
  autonum = d.xpath(".//autonumber").map(&:remove)
  d.xpath(".//p[normalize-space(.)='']").each(&:remove)
  move_attrs_to_amend(clause, amend)
  autonum.each { |a| amend << a }
  amend
end

#create_amend2(_clause, amend) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/metanorma/standoc/cleanup_amend.rb', line 29

def create_amend2(_clause, amend)
  q = amend.at("./quote") and q.name = "newcontent"
  if q.nil?
    amend.children = "<description>#{amend.children.to_xml}</description>"
    return
  end
  pre = q.xpath("./preceding-sibling::*")&.remove
  post = q.xpath("./following-sibling::*")&.remove
  pre.empty? or amend << "<description>#{pre.to_xml}</description>"
  amend << q.remove
  post.empty? or amend << "<description>#{post.to_xml}</description>"
end

#dd_bib_extract(dtd) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 59

def dd_bib_extract(dtd)
  return nil if dtd.children.empty?

  dtd.at("./dl") and return dl_bib_extract(dtd)
  elems = dtd.remove.elements
  return p_unwrap(dtd) unless elems.size == 1 &&
    %w(ol ul).include?(elems[0].name)

  elems[0].xpath("./li").each_with_object([]) do |li, ret|
    ret << p_unwrap(li)
  end
end

#dl1_table_cleanup(xmldoc) ⇒ Object



4
5
6
7
8
9
# File 'lib/metanorma/standoc/cleanup_table.rb', line 4

def dl1_table_cleanup(xmldoc)
  q = "//table/following-sibling::*[1][self::dl]"
  xmldoc.xpath(q).each do |s|
    s["key"] == "true" and s.previous_element << s.remove
  end
end

#dl2_table_cleanup(xmldoc) ⇒ Object

move Key dl after table footer



12
13
14
15
16
17
18
19
20
21
# File 'lib/metanorma/standoc/cleanup_table.rb', line 12

def dl2_table_cleanup(xmldoc)
  q = "//table/following-sibling::*[1][self::p]"
  xmldoc.xpath(q).each do |s|
    if s.text =~ /^\s*key[^a-z]*$/i && s&.next_element&.name == "dl"
      s.next_element["key"] = "true"
      s.previous_element << s.next_element.remove
      s.remove
    end
  end
end

#dl_bib_extract(clause, nested = false) ⇒ Object

definition list, with at most one level of unordered lists



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 77

def dl_bib_extract(clause, nested = false)
  dl = clause.at("./dl") or return
  key = ""
  bib = dl.xpath("./dt | ./dd").each_with_object({}) do |dtd, m|
    (dtd.name == "dt" and key = dtd.text.sub(/:+$/, "")) and next
    add_to_hash(m, key, dd_bib_extract(dtd))
  end
  clause.xpath("./clause").each do |c1|
    key = c1&.at("./title")&.text&.downcase&.strip
    next unless %w(contributor relation series).include? key

    add_to_hash(bib, key, dl_bib_extract(c1, true))
  end
  dl_bib_extract_title(bib, clause, nested)
end

#dl_bib_extract_title(bib, clause, nested) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 93

def dl_bib_extract_title(bib, clause, nested)
  (!nested && clause.at("./title")) or return bib
  title = clause.at("./title").remove.children.to_xml
  bib["title"] = [bib["title"]] if bib["title"].is_a?(Hash) ||
    bib["title"].is_a?(String)
  bib["title"] ||= []
  bib["title"] << title if !title.empty?
  bib
end

#dl_to_designation(dlist) ⇒ Object



116
117
118
119
120
121
122
123
124
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 116

def dl_to_designation(dlist)
  prev = dlist.previous_element
  unless %w(preferred admitted deprecates related).include? prev&.name
    @log.add("AsciiDoc Input", dlist, "Metadata definition list does " \
                                      "not follow a term designation")
    return nil
  end
  prev
end

#docidentifier_cleanup(xmldoc) ⇒ Object



99
# File 'lib/metanorma/standoc/cleanup.rb', line 99

def docidentifier_cleanup(xmldoc); end

#dt_bookmark_cleanup(xmldoc) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 59

def dt_bookmark_cleanup(xmldoc)
  xmldoc.xpath("//dt[descendant::bookmark]").each do |x|
    if x.at("./*[1][local-name() = 'p']/" \
            "*[1][local-name() = 'bookmark']") &&
        empty_text_before_first_element(x.elements[0])
      bookmark_to_id(x, x.elements[0].elements[0])
    elsif x.at("./*[1][local-name() = 'bookmark']") &&
        empty_text_before_first_element(x)
      bookmark_to_id(x, x.elements[0])
    end
  end
end

#dumb2smart_quotes(xmldoc) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/metanorma/standoc/cleanup_text.rb', line 79

def dumb2smart_quotes(xmldoc)
  prev = ""
  xmldoc.traverse do |x|
    block?(x) and prev = ""
    empty_tag_with_text_content?(x) and prev = "dummy"
    x.text? or next

    ancestors = x.path.gsub(/\[\d+\]/, "").split(%r{/})[1..-2]
    ancestors.intersection(IGNORE_QUOTES_ELEMENTS).empty? or next
    dumb2smart_quotes1(x, prev)
    prev = x.text
  end
end

#dumb2smart_quotes1(curr, prev) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/metanorma/standoc/cleanup_text.rb', line 93

def dumb2smart_quotes1(curr, prev)
  /[-'"(<>]|\.\.|\dx/.match?(curr.text) or return

  /\A["']/.match?(curr.text) && prev.match?(/\S\Z/) and
    curr.content = curr.text.sub(/\A"/, "").sub(/\A'/, "")
  curr.replace(Metanorma::Utils::smartformat(curr.text))
end

#dumbquote_cleanup(xmldoc) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/metanorma/standoc/cleanup_text.rb', line 101

def dumbquote_cleanup(xmldoc)
  xmldoc.traverse do |n|
    next unless n.text? && /\u2019/.match?(n.text)

    n.replace(@c.encode(
                @c.decode(n.text)
      .gsub(/(?<=\p{Alnum})\u2019(?=\p{Alpha})/, "'"),
                :basic, :hexadecimal
              ))
  end
end

#element_name_cleanup(xmldoc) ⇒ Object



123
124
125
# File 'lib/metanorma/standoc/cleanup.rb', line 123

def element_name_cleanup(xmldoc)
  xmldoc.traverse { |n| n.name = n.name.gsub("_", "-") }
end

#embed_recurse(bibitem, node) ⇒ Object



107
108
109
110
111
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 107

def embed_recurse(bibitem, node)
  node[:child].map { |x| hdr2bibitem(x) }.each do |x|
    bibitem << "<relation type='derivedFrom'>#{x}</relation>"
  end
end

#empty_element_cleanup(xmldoc) ⇒ Object



115
116
117
118
119
120
121
# File 'lib/metanorma/standoc/cleanup.rb', line 115

def empty_element_cleanup(xmldoc)
  xmldoc.xpath("//#{TEXT_ELEMS.join(' | //')}").each do |x|
    next if x.name == "name" && x.parent.name == "expression"

    x.remove if x.children.empty?
  end
end

#empty_tag_with_text_content?(elem) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/metanorma/standoc/cleanup_text.rb', line 75

def empty_tag_with_text_content?(elem)
  %w(eref xref termref link).include? elem.name
end

#empty_text_before_first_element(elem) ⇒ Object



8
9
10
11
12
13
14
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 8

def empty_text_before_first_element(elem)
  elem.children.each do |c|
    return false if c.text? && /\S/.match(c.text)
    return true if c.element?
  end
  true
end

#endofpreface_clausebefore(xmldoc, ins) ⇒ Object

only move clausebefore notes at the very end of preface



206
207
208
209
210
211
212
213
# File 'lib/metanorma/standoc/cleanup_section.rb', line 206

def endofpreface_clausebefore(xmldoc, ins)
  xmldoc.xpath("//preface//*[@beforeclauses = 'true']").reverse.each do |x|
    textafternote = xmldoc.xpath("//preface//*") & x.xpath("./following::*")
    textafternote.text.strip.empty? or break
    x.delete("beforeclauses")
    ins.previous = x.remove
  end
end

#eref_stack(xmldoc) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 139

def eref_stack(xmldoc)
  xmldoc.xpath("//eref[eref]").each do |e|
    e.name = "erefstack"
    e.delete("bibitemid")
    e.delete("citeas")
    e.xpath("./eref").each do |e1|
      e1["type"] = e["type"]
    end
    e.delete("type")
  end
end

#ext_contributor_cleanup(xmldoc) ⇒ Object



125
126
127
128
129
130
131
132
133
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 125

def ext_contributor_cleanup(xmldoc)
  t = xmldoc.xpath("//metanorma-extension/clause/title").detect do |x|
    x.text.strip.casecmp("contributor metadata").zero?
  end or return
  a = t.at("../sourcecode") or return
  ins = xmldoc.at("//bibdata/contributor[last()]")
  yaml = YAML.safe_load(a.text, permitted_classes: [Date])
  ext_contributors_process(yaml, ins)
end

#ext_contributors_process(yaml, ins) ⇒ Object



143
144
145
146
147
148
149
150
151
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 143

def ext_contributors_process(yaml, ins)
  yaml.is_a?(Hash) && !yaml["contributor"] and yaml = [yaml]
  yaml.is_a?(Array) and yaml = { "contributor" => yaml }
  r = yaml2relaton(yaml)
  Nokogiri::XML(r).xpath("//contributor").reverse
    .each do |c|
    ins.next = c
  end
end

#ext_dochistory_cleanup(xmldoc) ⇒ Object



162
163
164
165
166
167
168
169
170
171
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 162

def ext_dochistory_cleanup(xmldoc)
  t = xmldoc.xpath("//metanorma-extension/clause/title").detect do |x|
    x.text.strip.casecmp("document history").zero?
  end or return
  a = t.at("../sourcecode") or return
  ins = bib_relation_insert_pt(xmldoc) or return
  docid = xmldoc.at("//bibdata/docidentifier")
  yaml = YAML.safe_load(a.text, permitted_classes: [Date])
  ext_dochistory_process(yaml, ins, docid)
end

#ext_dochistory_process(yaml, ins, docid) ⇒ Object



173
174
175
176
177
178
179
180
181
182
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 173

def ext_dochistory_process(yaml, ins, docid)
  yaml.is_a?(Hash) and yaml = [yaml]
  yaml.reverse.each do |y|
    type = y["relation.type"] || "updatedBy"
    docid and
      y["docid"] ||= [{ "type" => docid["type"], "id" => docid.text }]
    r = yaml2relaton(y, amend_hash2mn(y["amend"]))
    ins.next = "<relation type='#{type}'>#{r}</relation>"
  end
end

#external_terms_boilerplate(sources) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 4

def external_terms_boilerplate(sources)
  @i18n.l10n(
    @i18n.external_terms_boilerplate.gsub(/%(?=\p{P}|\p{Z}|$)/,
                                          sources || "???"),
    @lang, @script, @locale
  )
end

#extract_from_p(tag, bib, key) ⇒ Object



42
43
44
45
46
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 42

def extract_from_p(tag, bib, key)
  return unless bib[tag]

  "<#{key}>#{bib[tag].at('p').children}</#{key}>"
end

#extract_localities(elem) ⇒ Object



35
36
37
38
39
40
41
42
43
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 35

def extract_localities(elem)
  elem.children.empty? and return
  f = elem.children.first
  f.text? or return
  head = f.remove.text
  tail = elem.children.remove
  extract_localities1(elem, head)
  tail and elem << tail
end

#extract_localities1(elem, text) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 63

def extract_localities1(elem, text)
  re = to_regex(LOCALITY_REGEX_STR)
  b = elem.add_child("<localityStack/>").first if re.match text
  while (m = re.match locality_normalise(text))
    add_locality(b, m)
    text = extract_localities_update_text(m)
    b = elem.add_child("<localityStack/>").first if m[:punct] == ";"
  end
  fill_in_eref_connectives(elem)
  elem.add_child(text) if text
end

#extract_localities_update_text(match) ⇒ Object

clause=3;and!5 => clause=3;and!clause=5



76
77
78
79
80
81
82
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 76

def extract_localities_update_text(match)
  ret = match[:text]
  re = to_regex(LOCALITY_REGEX_VALUE_ONLY_STR)
  re.match?(ret) && match[:punct] == ";" and
    ret.sub!(%r{^(#{CONN_REGEX_STR})}o, "\\1#{match[:locality]}=")
  ret
end

#extract_notes_from_biblio(refs) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 37

def extract_notes_from_biblio(refs)
  refs.xpath("./bibitem").each do |r|
    r.xpath("./note[@appended]").reverse.each do |n|
      n.delete("appended")
      r.next = n
    end
  end
end

#extract_symbols_list(dlist) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/metanorma/standoc/cleanup_symbols.rb', line 19

def extract_symbols_list(dlist)
  dl_out = []
  dlist.xpath("./dt | ./dd").each do |dtd|
    if dtd.name == "dt"
      dl_out << { dt: dtd.remove, key: symbol_key(dtd) }
    else
      dl_out.last[:dd] = dtd.remove
    end
  end
  dl_out
end

#fetch_local_bibitem(xmldoc) ⇒ Object

if citation uri points to local file, get bibitem from it



120
121
122
123
124
125
126
127
128
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 120

def fetch_local_bibitem(xmldoc)
  xmldoc.xpath("//bibitem[formattedref][uri[@type = 'citation']]")
    .each do |b|
    uri = b&.at("./uri[@type = 'citation']")&.text
    bibitem = read_local_bibitem(uri) or next
    bibitem["id"] = b["id"]
    b.replace(bibitem)
  end
end

#fetch_termbase(_termbase, _id) ⇒ Object



95
96
97
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 95

def fetch_termbase(_termbase, _id)
  ""
end

#figure_cleanup(xmldoc) ⇒ Object



87
88
89
90
91
92
93
# File 'lib/metanorma/standoc/cleanup_block.rb', line 87

def figure_cleanup(xmldoc)
  figure_footnote_cleanup(xmldoc)
  subfigure_cleanup(xmldoc)
  figure_dl_cleanup1(xmldoc)
  figure_dl_cleanup2(xmldoc)
  single_subfigure_cleanup(xmldoc)
end

#figure_dl_cleanup1(xmldoc) ⇒ Object



48
49
50
51
52
53
54
# File 'lib/metanorma/standoc/cleanup_block.rb', line 48

def figure_dl_cleanup1(xmldoc)
  q = "//figure/following-sibling::*[self::dl]"
  q1 = "//figure/figure/following-sibling::*[self::dl]"
  (xmldoc.xpath(q) - xmldoc.xpath(q1)).each do |s|
    s["key"] == "true" and s.previous_element << s.remove
  end
end

#figure_dl_cleanup2(xmldoc) ⇒ Object

include key definition list inside figure



57
58
59
60
61
62
63
64
65
66
# File 'lib/metanorma/standoc/cleanup_block.rb', line 57

def figure_dl_cleanup2(xmldoc)
  q = "//figure/following-sibling::*[self::p]"
  xmldoc.xpath(q).each do |s|
    if s.text =~ /^\s*key[^a-z]*$/i && s&.next_element&.name == "dl"
      s.next_element["key"] = "true"
      s.previous_element << s.next_element.remove
      s.remove
    end
  end
end

#figure_footnote_cleanup(xmldoc) ⇒ Object

include footnotes inside figure if they are the only content of the paras following



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 21

def figure_footnote_cleanup(xmldoc)
  nomatches = false
  until nomatches
    nomatches = true
    xmldoc.xpath(FIGURE_FN_XPATH).each do |s|
      next if s.children.map do |c|
                c.text? && /[[:alpha:]]/.match(c.text)
              end.any?

      s.previous_element << s.first_element_child.remove
      s.remove
      nomatches = false
    end
  end
end

#fill_in_eref_connectives(elem) ⇒ Object



94
95
96
97
98
99
100
101
102
103
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 94

def fill_in_eref_connectives(elem)
  elem.xpath("./localityStack").size < 2 and return
  elem.xpath("./localityStack[not(@connective)]").each do |l|
    n = l.next_element
    l["connective"] = if n && n.name == "localityStack" &&
        n["connective"] == "to"
                        "from"
                      else "and" end
  end
end

#floating_title_preface2sections(xmldoc) ⇒ Object



241
242
243
244
245
246
247
# File 'lib/metanorma/standoc/cleanup_section.rb', line 241

def floating_title_preface2sections(xmldoc)
  t = xmldoc.at("//preface/floating-title") or return
  s = xmldoc.at("//sections")
  unless t.next_element
    s.children.first.previous = t.remove
  end
end

#floatingtitle_cleanup(xmldoc) ⇒ Object



223
224
225
226
# File 'lib/metanorma/standoc/cleanup_section.rb', line 223

def floatingtitle_cleanup(xmldoc)
  pop_floating_title(xmldoc) # done again, after endofpreface_clausebefore
  floating_title_preface2sections(xmldoc)
end

#fold_notes_into_biblio(refs) ⇒ Object



28
29
30
31
32
33
34
35
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 28

def fold_notes_into_biblio(refs)
  refs.xpath("./bibitem").each do |r|
    while r&.next_element&.name == "note"
      r.next_element["appended"] = true
      r << r.next_element.remove
    end
  end
end

#footnote_block_cleanup(xmldoc) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 96

def footnote_block_cleanup(xmldoc)
  ids = xmldoc.xpath("//footnoteblock").each_with_object([]) do |f, m|
    f.name = "fn"
    m << f.text
    if id = xmldoc.at("//*[@id = '#{f.text}']")
      f.children = id.dup.children
    else footnote_block_error(f)
    end
  end
  footnote_block_remove(xmldoc, ids)
end

#footnote_block_error(fnote) ⇒ Object



115
116
117
118
119
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 115

def footnote_block_error(fnote)
  @log.add("Crossreferences", fnote,
           "Could not resolve footnoteblock:[#{fnote.text}]", severity: 1)
  fnote.children = "[ERROR]"
end

#footnote_block_remove(xmldoc, ids) ⇒ Object



108
109
110
111
112
113
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 108

def footnote_block_remove(xmldoc, ids)
  ids.each do |id|
    n = xmldoc.at("//*[@id = '#{id}']") and
      n.remove
  end
end

#footnote_cleanup(xmldoc) ⇒ Object



121
122
123
124
125
126
127
128
129
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 121

def footnote_cleanup(xmldoc)
  footnote_block_cleanup(xmldoc)
  title_footnote_move(xmldoc)
  table_footnote_renumber(xmldoc)
  other_footnote_renumber(xmldoc)
  xmldoc.xpath("//fn").each do |fn|
    fn.delete("table")
  end
end

#footnote_content(fnote) ⇒ Object



8
9
10
11
12
13
14
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 8

def footnote_content(fnote)
  c = if fnote.children.respond_to?(:to_xml)
        fnote.children.to_xml
      else fn.children
      end
  c.gsub(/ id="[^"]+"/, "")
end

#form_cleanup(xmldoc) ⇒ Object



171
172
173
174
175
176
177
# File 'lib/metanorma/standoc/cleanup_block.rb', line 171

def form_cleanup(xmldoc)
  xmldoc.xpath("//select").each do |s|
    while s.next_element&.name == "option"
      s << s.next_element
    end
  end
end

#format_ref(ref, type) ⇒ Object



56
57
58
59
60
61
62
63
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 56

def format_ref(ref, type)
  ret = Nokogiri::XML.fragment(ref)
  ret.traverse { |x| x.remove if x.name == "fn" }
  ref = to_xml(ret)
  type != "metanorma" and return @isodoc.docid_prefix(type, ref)
  /^\d+$/.match(ref) && !/^\[.*\]$/.match(ref) and return "[#{ref}]"
  ref
end

#formattedref_spans(xmldoc) ⇒ Object



4
5
6
7
8
9
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 4

def formattedref_spans(xmldoc)
  xmldoc.xpath("//bibitem[formattedref//span]").each do |b|
    ret = new_bibitem_from_formattedref_spans(b)
    merge_bibitem_from_formattedref_spans(b, ret)
  end
end

#formula_cleanup(formula) ⇒ Object

include where definition list inside stem block



25
26
27
28
# File 'lib/metanorma/standoc/cleanup_block.rb', line 25

def formula_cleanup(formula)
  formula_cleanup_where1(formula)
  formula_cleanup_where2(formula)
end

#formula_cleanup_where1(formula) ⇒ Object



30
31
32
33
34
35
# File 'lib/metanorma/standoc/cleanup_block.rb', line 30

def formula_cleanup_where1(formula)
  q = "//formula/following-sibling::*[1][self::dl]"
  formula.xpath(q).each do |s|
    s["key"] == "true" and s.previous_element << s.remove
  end
end

#formula_cleanup_where2(formula) ⇒ Object



37
38
39
40
41
42
43
44
45
46
# File 'lib/metanorma/standoc/cleanup_block.rb', line 37

def formula_cleanup_where2(formula)
  q = "//formula/following-sibling::*[1][self::p]"
  formula.xpath(q).each do |s|
    if s.text =~ /^\s*where[^a-z]*$/i && s&.next_element&.name == "dl"
      s.next_element["key"] = "true"
      s.previous_element << s.next_element.remove
      s.remove
    end
  end
end

#gather_indirect_erefs(xmldoc, prefix) ⇒ Object



27
28
29
30
31
32
33
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 27

def gather_indirect_erefs(xmldoc, prefix)
  xmldoc.xpath("//eref[@type = '#{prefix}']")
    .each_with_object({}) do |e, m|
    e.delete("type")
    m[e["bibitemid"]] = true
  end.keys
end

#gather_unitsml(unitsml, xmldoc, tag) ⇒ Object



124
125
126
127
128
129
130
131
132
133
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 124

def gather_unitsml(unitsml, xmldoc, tag)
  tags = xmldoc.xpath(".//m:#{tag}", "m" => UNITSML_NS)
    .each_with_object({}) do |x, m|
    m[x["xml:id"]] = x.remove
  end
  return if tags.empty?

  set = unitsml.add_child("<#{tag}Set/>").first
  tags.each_value { |v| set << v }
end

#generate_termdefinitions(xmldoc) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 33

def generate_termdefinitions(xmldoc)
  xmldoc.xpath("//term[not(definition)]").each do |d|
    first_child = d.at(TERMDEF_BLOCKS) || next
    t = Nokogiri::XML::Element.new("definition", xmldoc)
    first_child.replace(t)
    t << first_child.remove
    d.xpath(TERMDEF_BLOCKS).each do |n|
      t << n.remove
    end
  end
end

#get_or_make_title(node) ⇒ Object



4
5
6
7
8
9
10
11
12
13
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 4

def get_or_make_title(node)
  unless node.at("./title")
    if node.children.empty?
      node << "<title/>"
    else
      node.children.first.previous = "<title/>"
    end
  end
  node.at("./title")
end

#guid?(str) ⇒ Boolean

Returns:

  • (Boolean)


13
14
15
16
# File 'lib/metanorma/standoc/cleanup_image.rb', line 13

def guid?(str)
  /^_[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
    .match(str)
end

#hdr2bibitem(hdr) ⇒ Object



89
90
91
92
93
94
95
96
97
98
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 89

def hdr2bibitem(hdr)
  xml = Asciidoctor
    .convert(hdr[:text], backend: hdr2bibitem_type(hdr),
                         header_footer: true)
  b = Nokogiri::XML(xml).at("//xmlns:bibdata")
  b.name = "bibitem"
  b.delete("type")
  embed_recurse(b, hdr)
  b.to_xml
end

#hdr2bibitem_type(hdr) ⇒ Object



100
101
102
103
104
105
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 100

def hdr2bibitem_type(hdr)
  m = /:mn-document-class: (\S+)/.match(hdr[:text])
  if m then m[1].to_sym
  else Processor.new.asciidoctor_backend
  end
end

#header_rows_cleanup(xmldoc) ⇒ Object



33
34
35
36
37
38
39
40
41
42
# File 'lib/metanorma/standoc/cleanup_table.rb', line 33

def header_rows_cleanup(xmldoc)
  xmldoc.xpath("//table[@headerrows]").each do |s|
    thead = insert_thead(s)
    (thead.xpath("./tr").size...s["headerrows"].to_i).each do
      s.at("./tbody/tr").parent = thead
    end
    thead.xpath(".//td").each { |n| n.name = "th" }
    s.delete("headerrows")
  end
end

#idtype2cit(ref) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 76

def idtype2cit(ref)
  ref.xpath("./docidentifier/@type").each_with_object({}) do |t, m|
    m[t.text] and next
    docid = select_docid(ref, t.text) or next
    m[t.text] = format_ref(docid.children.to_xml, docid["type"])
  end
end

#ignoretext?(elem) ⇒ Boolean

Returns:

  • (Boolean)


62
63
64
# File 'lib/metanorma/standoc/cleanup_text.rb', line 62

def ignoretext?(elem)
  IGNORE_TEXT_ELEMENTS.include? elem.name
end

#img_cleanup(xmldoc) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/metanorma/standoc/cleanup_image.rb', line 62

def img_cleanup(xmldoc)
  if @datauriimage
    xmldoc.xpath("//image").each do |i|
      # do not datauri encode SVG, we need to deduplicate its IDs
      unless read_in_if_svg(i, @localdir)
        i["src"] = Vectory::Utils::datauri(i["src"], @localdir)
      end
    end
  end
  svg_cleanup(xmldoc)
  xmldoc
end

#include_indexterm?(elem) ⇒ Boolean

Returns:

  • (Boolean)


198
199
200
201
# File 'lib/metanorma/standoc/cleanup_block.rb', line 198

def include_indexterm?(elem)
  elem.nil? and return false
  !%w(image literal sourcecode).include?(elem.name)
end

#index_cleanup1(term, fieldofappl) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 137

def index_cleanup1(term, fieldofappl)
  return unless term

  idx = term.children.dup
  fieldofappl.empty? or idx << ", &#x3c;#{fieldofappl}&#x3e;"
  term << "<index><primary>#{idx.to_xml}</primary></index>"
end

#indexterm_para?(para) ⇒ Boolean

Returns:

  • (Boolean)


192
193
194
195
196
# File 'lib/metanorma/standoc/cleanup_block.rb', line 192

def indexterm_para?(para)
  p = para.dup
  p.xpath("./index").each(&:remove)
  p.text.strip.empty?
end

#indirect_eref_to_xref(eref, ident) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 48

def indirect_eref_to_xref(eref, ident)
  loc = eref.at("./localityStack[locality[@type = 'anchor']]") ||
    eref.at("./locality[@type = 'anchor']")
  loc = loc&.remove&.text || ident
  eref.name = "xref"
  eref.delete("bibitemid")
  eref.delete("citeas")
  eref["target"] = loc
  eref.document.at("//*[@id = '#{loc}']") and return
  eref.children = %(** Missing target #{loc})
  eref["target"] = ident
end

#initial_boilerplate(xml, isodoc) ⇒ Object



127
128
129
130
131
132
133
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 127

def initial_boilerplate(xml, isodoc)
  xml.at("//boilerplate") and return
  preface = xml.at("//preface | //sections | //annex | //references") or
    return
  b = boilerplate(xml, isodoc) or return
  preface.previous = b
end

#inject_id(xmldoc, path) ⇒ Object



18
19
20
21
22
# File 'lib/metanorma/standoc/cleanup_block.rb', line 18

def inject_id(xmldoc, path)
  xmldoc.xpath(path).each do |x|
    x["id"] ||= Metanorma::Utils::anchor_or_uuid
  end
end

#insert_before(xmldoc, xpath) ⇒ Object



215
216
217
218
219
220
221
# File 'lib/metanorma/standoc/cleanup_section.rb', line 215

def insert_before(xmldoc, xpath)
  unless ins = xmldoc.at(xpath).children.first
    xmldoc.at(xpath) << " "
    ins = xmldoc.at(xpath).children.first
  end
  ins
end

#insert_hidden_bibitems(bib) ⇒ Object



87
88
89
90
91
92
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 87

def insert_hidden_bibitems(bib)
  refs = bib.each_with_object([]) do |b, m|
    m << reference1code(%(<ref id="#{b[:id]}">[#{b[:ref]}]</ref>), nil)
  end
  reference_populate(refs)
end

#insert_indirect_biblio(xmldoc, refs, prefix) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 35

def insert_indirect_biblio(xmldoc, refs, prefix)
  i = xmldoc.at("bibliography") or
    xmldoc.root << "<bibliography/>" and i = xmldoc.at("bibliography")
  i = i.add_child("<references hidden='true' normative='false'/>").first
  refs.each do |x|
    i << <<~BIB
      <bibitem id="#{x}" type="internal">
      <docidentifier type="repository">#{x.sub(/^#{prefix}_/, "#{prefix}/")}</docidentifier>
      </bibitem>
    BIB
  end
end

#insert_thead(table) ⇒ Object



23
24
25
26
27
28
29
30
31
# File 'lib/metanorma/standoc/cleanup_table.rb', line 23

def insert_thead(table)
  thead = table.at("./thead")
  thead.nil? or return thead
  if tname = table.at("./name")
    thead = tname.add_next_sibling("<thead/>").first
    return thead
  end
  table.children.first.add_previous_sibling("<thead/>").first
end

#internal_external_terms_boilerplate(sources) ⇒ Object



12
13
14
15
16
17
18
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 12

def internal_external_terms_boilerplate(sources)
  @i18n.l10n(
    @i18n.internal_external_terms_boilerplate.gsub(/%(?=\p{P}|\p{Z}|$)/,
                                                   sources || "??"),
    @lang, @script
  )
end

#key_extract_locality(elem) ⇒ Object



99
100
101
102
103
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 99

def key_extract_locality(elem)
  elem["key"].include?(",") or return
  elem.add_child("<locality>#{elem['key'].sub(/^[^,]+,/, '')}</locality>")
  elem["key"] = elem["key"].sub(/,.*$/, "")
end

#li_bookmark_cleanup(xmldoc) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 49

def li_bookmark_cleanup(xmldoc)
  xmldoc.xpath("//li[descendant::bookmark]").each do |x|
    if x.at("./*[1][local-name() = 'p']/" \
            "*[1][local-name() = 'bookmark']") &&
        empty_text_before_first_element(x.elements[0])
      bookmark_to_id(x, x.elements[0].elements[0])
    end
  end
end


113
114
115
116
117
118
# File 'lib/metanorma/standoc/cleanup_block.rb', line 113

def link_callouts_to_annotations(callouts, annotations)
  callouts.each_with_index do |c, i|
    c["target"] = "_#{UUIDTools::UUID.random_create}"
    annotations[i]["id"] = c["target"]
  end
end


211
212
213
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 211

def link_cleanup(xmldoc)
  uri_cleanup(xmldoc)
end

#locality_label(match) ⇒ Object



105
106
107
108
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 105

def locality_label(match)
  loc = match[:locality] || match[:locality2]
  /^locality:/.match?(loc) ? loc : loc&.downcase
end

#locality_normalise(text) ⇒ Object

treat n-n-n locality as “n-n-n”, do not parse as a range



56
57
58
59
60
61
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 56

def locality_normalise(text)
  re = to_regex(LOCALITY_REGEX_STR_TRIPLEDASH)
  m = re.match(text) and
    text = %(#{m[:locality]}"#{m[:ref]}"#{m[:text]})
  text
end

#make_abstract(xml, sect) ⇒ Object



41
42
43
44
45
46
47
48
49
50
# File 'lib/metanorma/standoc/cleanup_section.rb', line 41

def make_abstract(xml, sect)
  if xml.at("//abstract[not(ancestor::bibitem)]")
    preface = sect.at("//preface") ||
      sect.add_previous_sibling("<preface/>").first
    abstract = xml.at("//abstract[not(ancestor::bibitem)]").remove
    preface.prepend_child abstract.remove
    bibabstract = bibabstract_location(xml)
    bibabstract.next = clean_abstract(abstract.dup)
  end
end

#make_annexes(xml) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
# File 'lib/metanorma/standoc/cleanup_section.rb', line 97

def make_annexes(xml)
  xml.xpath("//*[@annex]").each do |y|
    y.delete("annex")
    y.name == "annex" || !y.ancestors("annex").empty? and next
    y.wrap("<annex/>")
    y.parent["id"] = "_#{UUIDTools::UUID.random_create}"
    y.parent["obligation"] = y["obligation"]
    y.parent["language"] = y["language"]
    y.parent["script"] = y["script"]
  end
end

#make_bibliography(xml, sect) ⇒ Object



71
72
73
74
75
76
77
78
# File 'lib/metanorma/standoc/cleanup_section.rb', line 71

def make_bibliography(xml, sect)
  if xml.at("//sections/references | //xref[@hidden]")
    biblio = sect.add_next_sibling("<bibliography/>").first
    xml.xpath("//sections/references").each do |r|
      biblio.add_child r.remove
    end
  end
end

#make_colophon(xml) ⇒ Object



32
33
34
35
36
37
38
39
# File 'lib/metanorma/standoc/cleanup_section.rb', line 32

def make_colophon(xml)
  xml.at("//clause[@colophon]") or return
  colophon = xml.root.add_child("<colophon/>").first
  xml.xpath("//*[@colophon]").each do |c|
    c.delete("colophon")
    colophon.add_child c.remove
  end
end

#make_indexsect(xml, sect) ⇒ Object



80
81
82
83
84
# File 'lib/metanorma/standoc/cleanup_section.rb', line 80

def make_indexsect(xml, sect)
  xml.xpath("//sections/indexsect").reverse_each do |r|
    sect.next = r.remove
  end
end

#make_preface(xml, sect) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
# File 'lib/metanorma/standoc/cleanup_section.rb', line 9

def make_preface(xml, sect)
  if xml.at("//foreword | //introduction | //acknowledgements | " \
            "//*[@preface]")
    preface = sect.add_previous_sibling("<preface/>").first
    f = xml.at("//foreword") and to_preface(preface, f)
    f = xml.at("//introduction") and to_preface(preface, f)
    move_clauses_into_preface(xml, preface)
    f = xml.at("//acknowledgements") and to_preface(preface, f)
  end
  make_abstract(xml, sect)
end

#mathml_cleanup(xmldoc) ⇒ Object



194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 194

def mathml_cleanup(xmldoc)
  unitsml = Asciimath2UnitsML::Conv.new(asciimath2unitsml_options)
  xmldoc.xpath("//stem[@type = 'MathML']").each do |x|
    xml_unescape_mathml(x)
    mathml_namespace(x)
    mathml_preserve_space(x)
    unitsml.MathML2UnitsML(x)
    mathml_mathvariant(x)
    mathml_italicise(x)
  end
  mathml_unitsML(xmldoc)
end

#mathml_italicise(xml) ⇒ Object

presuppose multichar mi upright, singlechar mi MathML default italic



81
82
83
84
85
86
87
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 81

def mathml_italicise(xml)
  xml.xpath(".//m:mi[not(ancestor::*[@mathvariant])]",
            "m" => MATHML_NS).each do |i|
    char = @c.decode(i.text)
    i["mathvariant"] = "normal" if mi_italicise?(char)
  end
end

#mathml_mathvariant(math) ⇒ Object



185
186
187
188
189
190
191
192
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 185

def mathml_mathvariant(math)
  math.xpath(".//*[@mathvariant]").each do |outer|
    outer.xpath(".//*[@mathvariant]").each do |inner|
      inner["mathvariant"] =
        mathvariant_override(inner["mathvariant"], outer["mathvariant"])
    end
  end
end

#mathml_mi_italicsObject



75
76
77
78
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 75

def mathml_mi_italics
  { uppergreek: true, upperroman: true,
    lowergreek: true, lowerroman: true }
end

#mathml_namespace(stem) ⇒ Object



69
70
71
72
73
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 69

def mathml_namespace(stem)
  stem.xpath("./*[local-name() = 'math']").each do |x|
    x.default_namespace = MATHML_NS
  end
end

#mathml_preserve_space(math) ⇒ Object



62
63
64
65
66
67
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 62

def mathml_preserve_space(math)
  math.xpath(".//m:mtext", "m" => MATHML_NS).each do |x|
    x.children = x.children.to_xml
      .gsub(/^\s/, "&#xA0;").gsub(/\s$/, "&#xA0;")
  end
end

#mathml_unitsML(xmldoc) ⇒ Object



114
115
116
117
118
119
120
121
122
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 114

def mathml_unitsML(xmldoc)
  return unless xmldoc.at(".//m:*", "m" => UNITSML_NS)

  misc = add_misc_container(xmldoc)
  unitsml = misc.add_child("<UnitsML xmlns='#{UNITSML_NS}'/>").first
  %w(Unit CountedItem Quantity Dimension Prefix).each do |t|
    gather_unitsml(unitsml, xmldoc, t)
  end
end

#mathvariant_override(inner, outer) ⇒ Object



178
179
180
181
182
183
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 178

def mathvariant_override(inner, outer)
  o = outer.to_sym
  i = inner.to_sym
  MATHVARIANT_OVERRIDE[o] or return inner
  MATHVARIANT_OVERRIDE[o][i] || inner
end

#maxlevel(xml) ⇒ Object



109
110
111
112
113
114
115
# File 'lib/metanorma/standoc/cleanup_section.rb', line 109

def maxlevel(xml)
  max = 5
  xml.xpath("//clause[@level]").each do |c|
    max = c["level"].to_i if max < c["level"].to_i
  end
  max
end

#merge_annotations_into_sourcecode(xmldoc) ⇒ Object



129
130
131
132
133
134
135
# File 'lib/metanorma/standoc/cleanup_block.rb', line 129

def merge_annotations_into_sourcecode(xmldoc)
  xmldoc.xpath("//sourcecode").each do |x|
    while x.next_element&.name == "annotation"
      x.next_element.parent = x
    end
  end
end

#merge_bibitem_from_formattedref_spans(bib, new) ⇒ Object



19
20
21
22
23
24
25
26
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 19

def merge_bibitem_from_formattedref_spans(bib, new)
  new["type"] and bib["type"] = new["type"]
  if bib.at("./title") # there already is a fetched record here: merge
    bib.children = MergeBibitems
      .new(bib.to_xml, new.to_xml).merge.to_noko.children
  else bib << new.children.to_xml
  end
end

#merge_boilerplate_files(built_in, user_add) ⇒ Object



162
163
164
165
166
167
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 162

def merge_boilerplate_files(built_in, user_add)
  %w(copyright license legal feedback).each do |w|
    resolve_boilerplate_statement(built_in, user_add, w)
  end
  to_xml(built_in)
end

#metadata_cleanup(xmldoc) ⇒ Object



171
172
173
174
175
# File 'lib/metanorma/standoc/cleanup.rb', line 171

def (xmldoc)
  (@metadata_attrs.nil? || @metadata_attrs.empty?) and return
  ins = add_misc_container(xmldoc)
  ins << @metadata_attrs
end

#mi_italicise?(char) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 89

def mi_italicise?(char)
  return false if char.length > 1

  case char
  when /\p{Greek}/
    (/\p{Lower}/.match(char) && !mathml_mi_italics[:lowergreek]) ||
      (/\p{Upper}/.match(char) && !mathml_mi_italics[:uppergreek])
  when /\p{Latin}/
    (/\p{Lower}/.match(char) && !mathml_mi_italics[:lowerroman]) ||
      (/\p{Upper}/.match(char) && !mathml_mi_italics[:upperroman])
  else false
  end
end

#misccontainer_cleanup(xml) ⇒ Object



137
138
139
140
141
# File 'lib/metanorma/standoc/cleanup_section.rb', line 137

def misccontainer_cleanup(xml)
  m = xml.at("//misc-container-clause") or return
  ins = add_misc_container(xml)
  ins << m.remove.children
end

#move_attrs_to_amend(clause, amend) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/metanorma/standoc/cleanup_amend.rb', line 42

def move_attrs_to_amend(clause, amend)
  %w(change path path_end title).each do |e|
    next unless clause[e]

    amend[e] = clause[e]
    clause.delete(e)
  end
  return unless amend["locality"]

  loc = amend.children.add_previous_sibling("<location/>")
  extract_localities1(loc, amend["locality"])
  loc1 = loc.at("./localityStack") and loc.replace(loc1.elements)
  amend.delete("locality")
end

#move_clauses_into_preface(xml, preface) ⇒ Object



21
22
23
24
25
# File 'lib/metanorma/standoc/cleanup_section.rb', line 21

def move_clauses_into_preface(xml, preface)
  xml.xpath("//*[@preface]").each do |c|
    to_preface(preface, c)
  end
end

#new_bibitem_from_formattedref_spans(bib) ⇒ Object



11
12
13
14
15
16
17
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 11

def new_bibitem_from_formattedref_spans(bib)
  ret = SpansToBibitem.new(bib).convert
  ret.err.each do |e|
    @log.add("Bibliography", bib, e[:msg], severity: e[:fatal] ? 0 : 1)
  end
  ret.out
end

#norm_ref_preface(ref) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 44

def norm_ref_preface(ref)
  if ref.at("./note[@type = 'boilerplate']")
    unwrap_boilerplate_clauses(ref, ".")
  else
    refs = ref.elements.select do |e|
      %w(references bibitem).include? e.name
    end
    pref = refs.empty? ? @i18n.norm_empty_pref : @i18n.norm_with_refs_pref
    ref.at("./title").next = "<p>#{pref}</p>"
  end
end

#normref_cleanup(xmldoc) ⇒ Object



57
58
59
60
61
62
63
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 57

def normref_cleanup(xmldoc)
  r = xmldoc.at(self.class::NORM_REF) || return
  preface = ((r.xpath("./title/following-sibling::*") & # intersection
              r.xpath("./bibitem[1]/preceding-sibling::*")) -
  r.xpath("./note[@type = 'boilerplate']/descendant-or-self::*"))
  preface.each(&:remove)
end

#note_cleanup(xmldoc) ⇒ Object

if a note is at the end of a section, it is left alone if a note is followed by a non-note block, it is moved inside its preceding block if it is not delimited (so there was no way of making that block include the note)



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/metanorma/standoc/cleanup_block.rb', line 101

def note_cleanup(xmldoc)
  xmldoc.xpath("//note").each do |n|
    n["keep-separate"] == "true" || !n.ancestors("table").empty? and next
    prev = n.previous_element || next
    n.parent = prev if ELEMS_ALLOW_NOTES.include? prev.name
  end
  xmldoc.xpath("//note[@keep-separate] | " \
               "//termnote[@keep-separate]").each do |n|
    n.delete("keep-separate")
  end
end

#notes_table_cleanup(xmldoc) ⇒ Object

move notes into table



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/metanorma/standoc/cleanup_table.rb', line 66

def notes_table_cleanup(xmldoc)
  nomatches = false
  until nomatches
    nomatches = true
    xmldoc.xpath("//table/following-sibling::*[1]" \
                 "[self::note[not(@keep-separate = 'true')]]").each do |n|
      n.delete("keep-separate")
      n.previous_element << n.remove
      nomatches = false
    end
  end
end

#obligations_cleanup(xml) ⇒ Object



149
150
151
152
153
# File 'lib/metanorma/standoc/cleanup_section.rb', line 149

def obligations_cleanup(xml)
  obligations_cleanup_info(xml)
  obligations_cleanup_norm(xml)
  obligations_cleanup_inherit(xml)
end

#obligations_cleanup_info(xml) ⇒ Object



155
156
157
158
159
160
# File 'lib/metanorma/standoc/cleanup_section.rb', line 155

def obligations_cleanup_info(xml)
  xml.xpath("//foreword | //introduction | //acknowledgements | " \
            "//references | //preface//clause").each do |r|
    r["obligation"] = "informative"
  end
end

#obligations_cleanup_inherit(xml) ⇒ Object



169
170
171
172
173
174
175
176
# File 'lib/metanorma/standoc/cleanup_section.rb', line 169

def obligations_cleanup_inherit(xml)
  xml.xpath("//annex | //clause[not(ancestor::boilerplate)]").each do |r|
    r["obligation"] = "normative" unless r["obligation"]
  end
  xml.xpath(Utils::SUBCLAUSE_XPATH).each do |r|
    o = r.at("./ancestor::*/@obligation")&.text and r["obligation"] = o
  end
end

#obligations_cleanup_norm(xml) ⇒ Object



162
163
164
165
166
167
# File 'lib/metanorma/standoc/cleanup_section.rb', line 162

def obligations_cleanup_norm(xml)
  s = xml.at("//clause[@type = 'scope']") and
    s["obligation"] = "normative"
  xml.xpath("//terms").each { |r| r["obligation"] = "normative" }
  xml.xpath("//definitions").each { |r| r["obligation"] = "normative" }
end

#ol_cleanup(doc) ⇒ Object



218
219
220
221
222
223
224
# File 'lib/metanorma/standoc/cleanup_block.rb', line 218

def ol_cleanup(doc)
  doc.xpath("//ol[@explicit-type]").each do |x|
    x.delete("explicit-type")
    @log.add("Style", x,
             "Style override set for ordered list")
  end
end

#origin_cleanup(xmldoc) ⇒ Object



241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 241

def origin_cleanup(xmldoc)
  xmldoc.xpath("//origin/concept[termref]").each do |x|
    x.replace(x.at("./termref"))
  end
  xmldoc.xpath("//origin").each do |x|
    x["citeas"] = @anchors&.dig(x["bibitemid"], :xref) or
      @log.add("Crossreferences", x,
               "#{x['bibitemid']} does not have a corresponding anchor " \
               "ID in the bibliography!")
    extract_localities(x)
  end
end

#other_footnote_renumber(xmldoc) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 78

def other_footnote_renumber(xmldoc)
  seen = {}
  i = 0
  xmldoc.xpath("//fn").each do |fn|
    i, seen = other_footnote_renumber1(fn, i, seen)
  end
end

#other_footnote_renumber1(fnote, idx, seen) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 64

def other_footnote_renumber1(fnote, idx, seen)
  return [idx, seen] if fnote["table"]

  content = footnote_content(fnote)
  if seen[content] then outnum = seen[content]
  else
    idx += 1
    outnum = idx
    seen[content] = outnum
  end
  fnote["reference"] = outnum.to_s
  [idx, seen]
end

#p_unwrap(para) ⇒ Object

if the content is a single paragraph, replace it with its children single links replaced with uri



50
51
52
53
54
55
56
57
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 50

def p_unwrap(para)
  elems = para.elements
  if elems.size == 1 && elems[0].name == "p"
    link_unwrap(elems[0]).children.to_xml.strip
  else
    para.to_xml.strip
  end
end

#para_cleanup(xmldoc) ⇒ Object



7
8
9
10
11
12
13
14
15
16
# File 'lib/metanorma/standoc/cleanup_block.rb', line 7

def para_cleanup(xmldoc)
  ["//p[not(ancestor::bibdata)]", "//ol[not(ancestor::bibdata)]",
   "//ul[not(ancestor::bibdata)]", "//quote[not(ancestor::bibdata)]",
   "//dl[not(ancestor::bibdata)]",
   "//note[not(ancestor::bibitem or " \
   "ancestor::table or ancestor::bibdata)]"].each do |w|
    inject_id(xmldoc, w)
  end
  xmldoc.xpath("//p[not(text()) and not(node())]").each(&:remove)
end

#para_index_cleanup(xmldoc) ⇒ Object



203
204
205
206
207
208
# File 'lib/metanorma/standoc/cleanup_block.rb', line 203

def para_index_cleanup(xmldoc)
  xmldoc.xpath("//p[index]").select { |p| indexterm_para?(p) }
    .each do |p|
      para_index_cleanup1(p, p.previous_element, p.next_element)
    end
end

#para_index_cleanup1(para, prev, foll) ⇒ Object



210
211
212
213
214
215
216
# File 'lib/metanorma/standoc/cleanup_block.rb', line 210

def para_index_cleanup1(para, prev, foll)
  if include_indexterm?(prev)
    prev << para.remove.children
  elsif include_indexterm?(foll) && !foll.children.empty?
    foll.children.first.previous = para.remove.children
  end
end

#passthrough_cleanup(doc) ⇒ Object



201
202
203
204
205
206
207
208
209
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 201

def passthrough_cleanup(doc)
  doc.xpath("//passthrough-inline").each do |p|
    p.name = "passthrough"
    p.children = select_odd_chars(p.children.to_xml)
  end
  doc.xpath("//identifier").each do |p|
    p.children = select_odd_chars(p.children.to_xml)
  end
end

#pop_floating_title(xmldoc) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/metanorma/standoc/cleanup_section.rb', line 228

def pop_floating_title(xmldoc)
  loop do
    found = false
    xmldoc.xpath("//floating-title").each do |t|
      t.next_element.nil? or next
      %w(sections annex preface).include? t.parent.name and next
      t.parent.next = t
      found = true
    end
    break unless found
  end
end

#preface_clausebefore_cleanup(xmldoc) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
# File 'lib/metanorma/standoc/cleanup_section.rb', line 183

def preface_clausebefore_cleanup(xmldoc)
  xmldoc.at("//preface") or return
  ins = insert_before(xmldoc, "//preface")
  xmldoc.xpath("//preface//*[@beforeclauses = 'true']").each do |x|
    x.delete("beforeclauses")
    ins.previous = x.remove
  end
  xmldoc.xpath("//*[@coverpage = 'true']").each do |x|
    ins.previous = x.remove
  end
end

#process_boilerplate_file(filename, conv) ⇒ Object



150
151
152
153
154
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 150

def process_boilerplate_file(filename, conv)
  (!filename.nil? and File.exist?(filename)) or return
  b = conv.populate_template(boilerplate_read(filename), nil)
  boilerplate_file_convert(b)
end

#progress_conv(idx, step, total, threshold, msg) ⇒ Object



45
46
47
48
49
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 45

def progress_conv(idx, step, total, threshold, msg)
  return unless (idx % step).zero? && total > threshold && idx.positive?

  warn "#{msg} #{idx} of #{total}"
end

#quotesource_cleanup(xmldoc) ⇒ Object



235
236
237
238
239
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 235

def quotesource_cleanup(xmldoc)
  xmldoc.xpath("//quote/source | //terms/source").each do |x|
    xref_to_eref(x, "source")
  end
end

#read_in_if_svg(img, localdir) ⇒ Object



80
81
82
83
84
85
86
87
88
89
# File 'lib/metanorma/standoc/cleanup_image.rb', line 80

def read_in_if_svg(img, localdir)
  img["src"] or return false
  path = Vectory::Utils.svgmap_rewrite0_path(img["src"], localdir)
  File.file?(path) or return false
  types = MIME::Types.type_for(path) or return false
  types.first == "image/svg+xml" or return false
  svg = File.read(path, encoding: "utf-8") or return false
  img.children = (Nokogiri::XML(svg).root)
  true
end

#read_local_bibitem(uri) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 99

def read_local_bibitem(uri)
  xml = read_local_bibitem_file(uri) or return nil
  ret = xml.at("//*[local-name() = 'bibdata']") or return nil
  ret = Nokogiri::XML(ret.to_xml
    .sub(%r{(<bibdata[^>]*?) xmlns=("[^"]+"|'[^']+')}, "\\1")).root
  ret.name = "bibitem"
  ins = ret.at("./*[local-name() = 'docidentifier']") or return nil
  ins.previous = %{<uri type="citation">#{uri}</uri>}
  ret&.at("./*[local-name() = 'ext']")&.remove
  ret
end

#read_local_bibitem_file(uri) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 111

def read_local_bibitem_file(uri)
  %r{^https?://}.match?(uri) and return nil
  file = "#{@localdir}#{uri}.rxl"
  File.file?(file) or file = "#{@localdir}#{uri}.xml"
  File.file?(file) or return nil
  Nokogiri::XML(File.read(file, encoding: "utf-8"))
end

#redundant_bookmark_cleanup(xmldoc) ⇒ Object



32
33
34
35
36
37
38
39
40
41
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 32

def redundant_bookmark_cleanup(xmldoc)
  xmldoc.xpath("//bookmark").each do |b|
    p = b
    while !p.xml? && p = p.parent
      p["id"] == b["id"] or next
      b.remove
      break
    end
  end
end

#ref_cleanup(xmldoc) ⇒ Object

move ref before p



50
51
52
53
54
55
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 50

def ref_cleanup(xmldoc)
  xmldoc.xpath("//p/ref").each do |r|
    parent = r.parent
    parent.previous = r.remove
  end
end

#ref_dl_cleanup(xmldoc) ⇒ Object



7
8
9
10
11
12
13
14
15
16
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 7

def ref_dl_cleanup(xmldoc)
  xmldoc.xpath("//clause[@bibitem = 'true']").each do |c|
    bib = dl_bib_extract(c) or next
    validate_ref_dl(bib, c)
    bibitemxml = RelatonBib::BibliographicItem.from_hash(bib).to_xml or next
    bibitem = Nokogiri::XML(bibitemxml)
    bibitem.root["id"] = c["id"] if c["id"] && !/^_/.match(c["id"])
    c.replace(bibitem.root)
  end
end

#reference_names(xmldoc) ⇒ Object



65
66
67
68
69
70
71
72
73
74
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 65

def reference_names(xmldoc)
  xmldoc.xpath("//bibitem[not(ancestor::bibitem)]").each do |ref|
    @anchors[ref["id"]] =
      if docid = select_docid(ref)
        reference = format_ref(docid.children.to_xml, docid["type"])
        { xref: reference, id: idtype2cit(ref) }
      else { xref: ref["id"], id: { "" => ref["id"] } }
      end
  end
end

#related2pref(elem) ⇒ Object



177
178
179
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 177

def related2pref(elem)
  elem&.name == "related" ? elem.at("./preferred") : elem
end


90
91
92
93
94
95
96
97
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 90

def related_cleanup(xmldoc)
  xmldoc.xpath("//related[not(termxref)]").each do |x|
    term = x.at("./refterm")
    term.replace("<preferred>#{term_expr(term.children.to_xml)}" \
                 "</preferred>")
    concept_cleanup1(x)
  end
end

#relaton_iev_cleanup(xmldoc) ⇒ Object



92
93
94
95
96
97
# File 'lib/metanorma/standoc/cleanup.rb', line 92

def relaton_iev_cleanup(xmldoc)
  _, err = RelatonIev::iev_cleanup(xmldoc, @bibdb)
  err.each do |e|
    @log.add("Bibliography", nil, e, severity: 0)
  end
end

#replace_title(doc, xpath, text, first = false) ⇒ Object



15
16
17
18
19
20
21
22
23
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 15

def replace_title(doc, xpath, text, first = false)
  text or return
  doc.xpath(xpath).each_with_index do |node, i|
    first && !i.zero? and next
    node["keeptitle"] == "true" and next
    title = get_or_make_title(node)
    set_title_with_footnotes(title, text)
  end
end

#requirement_cleanup(xmldoc) ⇒ Object



4
5
6
7
8
# File 'lib/metanorma/standoc/cleanup_reqt.rb', line 4

def requirement_cleanup(xmldoc)
  @reqt_models ||=
    requirements_processor.new({ default: @default_requirement_model })
  @reqt_models.requirement_cleanup(xmldoc)
end

#resolve_boilerplate_files(built_in, user_add) ⇒ Object



156
157
158
159
160
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 156

def resolve_boilerplate_files(built_in, user_add)
  built_in || user_add or return
  built_in && user_add or return to_xml(built_in || user_add)
  merge_boilerplate_files(built_in, user_add)
end

#resolve_boilerplate_statement(built_in, user_add, statement) ⇒ Object



169
170
171
172
173
174
175
176
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 169

def resolve_boilerplate_statement(built_in, user_add, statement)
  b = user_add.at("./#{statement}-statement") or return
  if a = built_in.at("./#{statement}-statement")
    b.text.strip.empty? and a.remove or a.replace(b)
  else
    built_in << b
  end
end

#resolve_local_indirect_erefs(xmldoc, refs, prefix) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 61

def resolve_local_indirect_erefs(xmldoc, refs, prefix)
  refs.each_with_object([]) do |r, m|
    id = r.sub(/^#{prefix}_/, "")
    n = xmldoc.at("//*[@id = '#{id}']")
    if n&.at("./ancestor-or-self::*[@type = '#{prefix}']")
      xmldoc.xpath("//eref[@bibitemid = '#{r}']").each do |e|
        indirect_eref_to_xref(e, id)
      end
    else m << r
    end
  end
end

#safe_noko(text, doc) ⇒ Object



152
153
154
155
156
157
# File 'lib/metanorma/standoc/cleanup_block.rb', line 152

def safe_noko(text, doc)
  Nokogiri::XML::Text.new(text, doc).to_xml(
    encoding: "US-ASCII",
    save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION,
  )
end

#script_cleanup(xmldoc) ⇒ Object

it seems Nokogiri::XML is treating the content of <script> as cdata, because of its use in HTML. Bad nokogiri. Undoing that, since we use script as a normal tag



111
112
113
# File 'lib/metanorma/standoc/cleanup.rb', line 111

def script_cleanup(xmldoc)
  xmldoc.xpath("//script").each { |x| x.content = x.to_str }
end

#section_names_definitions(xml) ⇒ Object



67
68
69
70
71
72
73
74
75
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 67

def section_names_definitions(xml)
  auto_name_definitions(xml) or return
  replace_title(xml, "//definitions[@type = 'symbols']",
                @i18n&.symbols)
  replace_title(xml, "//definitions[@type = 'abbreviated_terms']",
                @i18n&.abbrev)
  replace_title(xml, "//definitions[not(@type)]",
                @i18n&.symbolsabbrev)
end

#section_names_refs_cleanup(xml) ⇒ Object



47
48
49
50
51
52
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 47

def section_names_refs_cleanup(xml)
  replace_title(xml, "//bibliography/references[@normative = 'true']",
                @i18n&.normref, true)
  replace_title(xml, "//bibliography/references[@normative = 'false']",
                @i18n&.bibliography, true)
end

#section_names_terms1_cleanup(xml) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 85

def section_names_terms1_cleanup(xml)
  auto_name_terms(xml) or return
  replace_title(xml, "//terms#{SYMnoABBR} | //clause[.//terms]#{SYMnoABBR}",
                @i18n&.termsdefsymbols, true)
  replace_title(xml, "//terms#{ABBRnoSYM} | //clause[.//terms]#{ABBRnoSYM}",
                @i18n&.termsdefabbrev, true)
  replace_title(xml, "//terms#{SYMABBR} | //clause[.//terms]#{SYMABBR}",
                @i18n&.termsdefsymbolsabbrev, true)
  replace_title(xml, "//terms#{NO_SYMABBR} | //clause[.//terms]#{NO_SYMABBR}",
                @i18n&.termsdefsymbolsabbrev, true)
  replace_title(xml, "//terms[not(.//definitions)] | //clause[.//terms][not(.//definitions)]",
                @i18n&.termsdef, true)
end

#section_names_terms_cleanup(xml) ⇒ Object



62
63
64
65
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 62

def section_names_terms_cleanup(xml)
  section_names_definitions(xml)
  section_names_terms1_cleanup(xml)
end

#sections_clausebefore_cleanup(xmldoc) ⇒ Object



195
196
197
198
199
200
201
202
203
# File 'lib/metanorma/standoc/cleanup_section.rb', line 195

def sections_clausebefore_cleanup(xmldoc)
  xmldoc.at("//sections") or return
  ins = insert_before(xmldoc, "//sections")
  xmldoc.xpath("//sections//*[@beforeclauses = 'true']").reverse.each do |x|
    x.delete("beforeclauses")
    ins.previous = x.remove
  end
  endofpreface_clausebefore(xmldoc, ins)
end

#sections_cleanup(xml) ⇒ Object



128
129
130
131
132
133
134
135
# File 'lib/metanorma/standoc/cleanup_section.rb', line 128

def sections_cleanup(xml)
  misccontainer_cleanup(xml)
  sections_order_cleanup(xml)
  sections_level_cleanup(xml)
  sections_names_cleanup(xml)
  sections_variant_title_cleanup(xml)
  change_clauses(xml)
end

#sections_level_cleanup(xml) ⇒ Object



117
118
119
120
121
122
123
124
125
126
# File 'lib/metanorma/standoc/cleanup_section.rb', line 117

def sections_level_cleanup(xml)
  m = maxlevel(xml)
  m < 6 and return
  m.downto(6).each do |l|
    xml.xpath("//clause[@level = '#{l}']").each do |c|
      c.delete("level")
      c.previous_element << c.remove
    end
  end
end

#sections_names_cleanup(xml) ⇒ Object



32
33
34
35
36
37
38
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 32

def sections_names_cleanup(xml)
  replace_title(xml, "//clause[@type = 'scope']", @i18n&.scope)
  sections_names_pref_cleanup(xml)
  section_names_refs_cleanup(xml)
  section_names_terms_cleanup(xml)
  xml.xpath("//*[@keeptitle]").each { |s| s.delete("keeptitle") }
end

#sections_names_pref_cleanup(xml) ⇒ Object



40
41
42
43
44
45
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 40

def sections_names_pref_cleanup(xml)
  replace_title(xml, "//preface//abstract", @i18n&.abstract)
  replace_title(xml, "//foreword", @i18n&.foreword)
  replace_title(xml, "//introduction", @i18n&.introduction)
  replace_title(xml, "//acknowledgements", @i18n&.acknowledgements)
end

#sections_order_cleanup(xml) ⇒ Object



86
87
88
89
90
91
92
93
94
95
# File 'lib/metanorma/standoc/cleanup_section.rb', line 86

def sections_order_cleanup(xml)
  s = xml.at("//sections")
  pop_floating_title(xml)
  make_preface(xml, s)
  make_annexes(xml)
  make_indexsect(xml, s)
  make_bibliography(xml, s)
  make_colophon(xml)
  xml.xpath("//sections/annex").reverse_each { |r| s.next = r.remove }
end

#sections_variant_title_cleanup(xml) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 151

def sections_variant_title_cleanup(xml)
  path = SECTION_CONTAINERS.map { |x| "./ancestor::#{x}" }.join(" | ")
  xml.xpath("//p[@variant_title]").each do |p|
    p.name = "variant-title"
    p.delete("id")
    p.delete("variant_title")
    p.xpath("(#{path})[last()]").each do |sect|
      (ins = sect.at("./title") and ins.next = p) or
        sect.children.first.previous = p
    end
  end
end

#select_docid(ref, type = nil) ⇒ Object



84
85
86
87
88
89
90
91
92
93
# File 'lib/metanorma/standoc/cleanup_bibitem.rb', line 84

def select_docid(ref, type = nil)
  type and t = "[@type = '#{type}']"
  ref.at("./docidentifier[@type = 'metanorma']#{t}") ||
    ref.at("./docidentifier[@primary = 'true'][@language = '#{@lang}']#{t}") ||
    ref.at("./docidentifier[@primary = 'true'][not(@language)]#{t}") ||
    ref.at("./docidentifier[@primary = 'true']#{t}") ||
    ref.at("./docidentifier[not(@type = 'DOI')][@language = '#{@lang}']#{t}") ||
    ref.at("./docidentifier[not(@type = 'DOI')][not(@language)]#{t}") ||
    ref.at("./docidentifier[not(@type = 'DOI')]#{t}")
end

#set_title_with_footnotes(title, text) ⇒ Object



25
26
27
28
29
30
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 25

def set_title_with_footnotes(title, text)
  fn = title.xpath("./fn | ./bookmark | ./index")
  fn.each(&:remove)
  title.children = text
  fn.each { |n| title << n }
end

#single_clause_annex(xml) ⇒ Object



143
144
145
146
147
# File 'lib/metanorma/standoc/cleanup_section.rb', line 143

def single_clause_annex(xml)
  xml.xpath("//annex").each do |a|
    single_clause_annex1(a)
  end
end

#single_subfigure_cleanup(xmldoc) ⇒ Object



79
80
81
82
83
84
85
# File 'lib/metanorma/standoc/cleanup_block.rb', line 79

def single_subfigure_cleanup(xmldoc)
  xmldoc.xpath("//figure[figure]").each do |e|
    s = e.xpath("./figure")
    s.size == 1 or next
    s[0].replace(s[0].children)
  end
end

#smartquotes_cleanup(xmldoc) ⇒ Object



14
15
16
17
18
19
# File 'lib/metanorma/standoc/cleanup_text.rb', line 14

def smartquotes_cleanup(xmldoc)
  xmldoc.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
  if @smartquotes then smartquotes_cleanup1(xmldoc)
  else dumbquote_cleanup(xmldoc)
  end
end

#smartquotes_cleanup1(xmldoc) ⇒ Object



21
22
23
24
# File 'lib/metanorma/standoc/cleanup_text.rb', line 21

def smartquotes_cleanup1(xmldoc)
  uninterrupt_quotes_around_xml(xmldoc)
  dumb2smart_quotes(xmldoc)
end

#sort_biblio(bib) ⇒ Object



29
30
31
# File 'lib/metanorma/standoc/cleanup_ref.rb', line 29

def sort_biblio(bib)
  bib
end

#sourcecode_cleanup(xmldoc) ⇒ Object



142
143
144
145
146
147
148
149
150
# File 'lib/metanorma/standoc/cleanup_block.rb', line 142

def sourcecode_cleanup(xmldoc)
  xmldoc.xpath("//sourcecode").each do |x|
    x.traverse do |n|
      n.text? or next
      /#{Regexp.escape(@sourcecode_markup_start)}/.match?(n.text) or next
      n.replace(sourcecode_markup(n))
    end
  end
end

#sourcecode_markup(node) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
# File 'lib/metanorma/standoc/cleanup_block.rb', line 159

def sourcecode_markup(node)
  node.text.split(/(#{Regexp.escape(@sourcecode_markup_start)}|
                    #{Regexp.escape(@sourcecode_markup_end)})/x)
    .each_slice(4).map.with_object([]) do |a, acc|
    acc << safe_noko(a[0], node.document)
    a.size == 4 or next
    acc << Asciidoctor.convert(
      a[2], doctype: :inline, backend: (self&.backend&.to_sym || :standoc)
    )
  end.join
end

#sources_table_cleanup(xmldoc) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/metanorma/standoc/cleanup_table.rb', line 52

def sources_table_cleanup(xmldoc)
  nomatches = false
  until nomatches
    nomatches = true
    xmldoc.xpath("//table/following-sibling::*[1]" \
                 "[self::termsource]").each do |n|
      n.previous_element << n.remove
      nomatches = false
      # will be renamed source from termsource later
    end
  end
end

#split_termdefinitions(xmldoc) ⇒ Object



45
46
47
48
49
50
51
52
53
54
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 45

def split_termdefinitions(xmldoc)
  xmldoc.xpath("//definition").each do |d|
    if d.at("./p | ./ol | ./dl | ./ul")
      d.children = "<verbal-definition>#{d.children}</verbal-definition>"
    else
      d.children = "<non-verbal-representation>" \
                   "#{d.children}</non-verbal-representation>"
    end
  end
end

#strip_initial_space(elem) ⇒ Object



16
17
18
19
20
21
22
23
24
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 16

def strip_initial_space(elem)
  a = elem.children[0]
  a.text? or return
  if /\S/.match?(a.text)
    a.content = a.text.lstrip
  else
    a.remove
  end
end

#subfigure_cleanup(xmldoc) ⇒ Object

examples containing only figures become subfigures of figures



69
70
71
72
73
74
75
76
77
# File 'lib/metanorma/standoc/cleanup_block.rb', line 69

def subfigure_cleanup(xmldoc)
  xmldoc.xpath("//example[figure]").each do |e|
    e.elements.reject do |m|
      %w(name figure index note).include?(m.name) ||
        (m.name == "dl" && m["key"] == "true")
    end.empty? or next
    e.name = "figure"
  end
end

#svg_attrupdate(elem, iri_properties, idx, ids) ⇒ Object



185
186
187
188
189
190
# File 'lib/metanorma/standoc/cleanup_image.rb', line 185

def svg_attrupdate(elem, iri_properties, idx, ids)
  iri_properties.each do |p|
    elem[p] or next
    elem[p] = svg_update_url(elem[p], idx, ids)
  end
end

#svg_classupdate(xmldoc) ⇒ Object



91
92
93
94
95
96
# File 'lib/metanorma/standoc/cleanup_image.rb', line 91

def svg_classupdate(xmldoc)
  xmldoc.xpath("//m:svg[m:style]", "m" => SVG_NS)
    .each_with_index do |s, i|
    svg_classupdate1(s, s.at("./m:style", "m" => SVG_NS), i)
  end
end

#svg_classupdate1(svg, style, idx) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/metanorma/standoc/cleanup_image.rb', line 98

def svg_classupdate1(svg, style, idx)
  tree = Crass.parse(style.text)
  tree.each { |n| svg_suffix_css_style(n, idx) }
  style.children = Crass::Parser.stringify(tree)
  svg.xpath(".//*[@class]").each do |n|
    n["class"] = n["class"].split(/\s+/)
      .map { |x| "#{x}_inject_#{idx}" }.join(" ")
  end
end

#svg_cleanup(xmldoc) ⇒ Object



75
76
77
78
# File 'lib/metanorma/standoc/cleanup_image.rb', line 75

def svg_cleanup(xmldoc)
  svg_uniqueids(xmldoc)
  svg_classupdate(xmldoc)
end

#svg_idupdate(elem, idx, ids) ⇒ Object



201
202
203
204
205
# File 'lib/metanorma/standoc/cleanup_image.rb', line 201

def svg_idupdate(elem, idx, ids)
  elem["id"] or return
  ids[elem["id"]] or return
  elem["id"] += "_inject_#{idx}"
end

#svg_iri_properties(id_elems) ⇒ Object



140
141
142
143
144
145
146
147
148
149
# File 'lib/metanorma/standoc/cleanup_image.rb', line 140

def svg_iri_properties(id_elems)
  iri_tag_names = id_elems.each_with_object([]) do |e, m|
    IRI_TAG_PROPERTIES_MAP.key?(e.name.to_sym) and m << e.name
  end.uniq
  iri_properties = iri_tag_names.each_with_object([]) do |t, m|
    (IRI_TAG_PROPERTIES_MAP[t.to_sym] || [t]).each { |t1| m = m << t1 }
  end.uniq
  iri_properties.empty? and return []
  iri_properties << "style"
end

#svg_linkupdate(elem, idx, ids) ⇒ Object



192
193
194
195
196
197
198
199
# File 'lib/metanorma/standoc/cleanup_image.rb', line 192

def svg_linkupdate(elem, idx, ids)
  %w(xlink:href href).each do |ref|
    iri = elem[ref]&.strip
    /^#/.match?(iri) or next
    ids[iri.sub(/^#/, "")] or next
    elem[ref] += "_inject_#{idx}"
  end
end

#svg_styleupdate(elem, idx, ids) ⇒ Object



181
182
183
# File 'lib/metanorma/standoc/cleanup_image.rb', line 181

def svg_styleupdate(elem, idx, ids)
  elem.children = svg_update_url(elem.text, idx, ids)
end

#svg_suffix_css_style(node, idx) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/metanorma/standoc/cleanup_image.rb', line 108

def svg_suffix_css_style(node, idx)
  node[:node] == :style_rule && /\./.match?(node[:selector][:value]) or
    return
  v = node[:selector][:value]
    .gsub(/([^.\s]*\.\S+)/, "\\1_inject_#{idx}")
  node[:selector] = Crass.parse("#{v} {}").first[:selector]
end

#svg_uniqueids(xmldoc) ⇒ Object



130
131
132
133
134
135
136
137
138
# File 'lib/metanorma/standoc/cleanup_image.rb', line 130

def svg_uniqueids(xmldoc)
  # only keep non-unique identifiers
  ids = xmldoc.xpath("//m:svg//*/@id | //svg/@id", "m" => SVG_NS)
    .map(&:text).group_by(&:itself).transform_values(&:count)
    .delete_if { |_, v| v < 2 }
  xmldoc.xpath("//m:svg", "m" => SVG_NS).each_with_index do |s, i|
    ids = svg_uniqueids1(s, i, ids)
  end
end

#svg_uniqueids1(svg, idx, ids) ⇒ Object



151
152
153
154
155
156
157
158
# File 'lib/metanorma/standoc/cleanup_image.rb', line 151

def svg_uniqueids1(svg, idx, ids)
  id_elems = svg.xpath(".//*[@id] | ./@id/..")
  iri_properties = svg_iri_properties(id_elems)
  svg_uniqueids2(svg, iri_properties, idx, ids)
  new_ids = id_elems.map { |x| x["id"] }
    .map { |x| x + (ids[x] ? "_inject_#{idx}" : "") }
  ids.merge(new_ids.each.map { |value| [value, true] }.to_h)
end

#svg_uniqueids2(svg, iri_properties, idx, ids) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/metanorma/standoc/cleanup_image.rb', line 160

def svg_uniqueids2(svg, iri_properties, idx, ids)
  svg.traverse do |e|
    e.element? or next
    if e.name == "style"
      svg_styleupdate(e, idx, ids)
    elsif !e.attributes.empty?
      svg_attrupdate(e, iri_properties, idx, ids)
    end
    svg_linkupdate(e, idx, ids)
    svg_idupdate(e, idx, ids)
  end
end

#svg_update_url(text, idx, ids) ⇒ Object



173
174
175
176
177
178
179
# File 'lib/metanorma/standoc/cleanup_image.rb', line 173

def svg_update_url(text, idx, ids)
  text.gsub(/url\("?#([a-zA-Z][\w:.-]*)"?\)/) do |x|
    if ids[$1] then "url(##{$1}_inject_#{idx})"
    else x
    end
  end
end

#svgmap_cleanup(xmldoc) ⇒ Object



7
8
9
10
11
# File 'lib/metanorma/standoc/cleanup_image.rb', line 7

def svgmap_cleanup(xmldoc)
  svgmap_moveattrs(xmldoc)
  svgmap_populate(xmldoc)
  Vectory::SvgMapping.new(xmldoc, @localdir).call
end

#svgmap_moveattrs(xmldoc) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/metanorma/standoc/cleanup_image.rb', line 18

def svgmap_moveattrs(xmldoc)
  xmldoc.xpath("//svgmap").each do |s|
    f = s.at(".//figure") or next
    (t = s.at("./name")) && !f.at("./name") and
      f.children.first.previous = t.remove
    if s["id"] && guid?(f["id"])
      f["id"] = s["id"]
      s.delete("id")
    end
    svgmap_moveattrs1(s, f)
  end
end

#svgmap_moveattrs1(svgmap, figure) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/metanorma/standoc/cleanup_image.rb', line 31

def svgmap_moveattrs1(svgmap, figure)
  %w(unnumbered number subsequence keep-with-next
     keep-lines-together tag multilingual-rendering).each do |a|
    figure[a] || !svgmap[a] and next
    figure[a] = svgmap[a]
    svgmap.delete(a)
  end
end

#svgmap_populate(xmldoc) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/metanorma/standoc/cleanup_image.rb', line 40

def svgmap_populate(xmldoc)
  xmldoc.xpath("//svgmap").each do |s|
    s1 = s.dup
    s.children.remove
    f = s1.at(".//figure") and s << f
    s1.xpath(".//li").each do |li|
      t = li.at(".//eref | .//link | .//xref") or next
      href = t.xpath("./following-sibling::node()")
      href.empty? or
        s << %[<target href="#{svgmap_target(href)}">#{t.to_xml}</target>]
    end
  end
end

#svgmap_target(nodeset) ⇒ Object



54
55
56
57
58
59
60
# File 'lib/metanorma/standoc/cleanup_image.rb', line 54

def svgmap_target(nodeset)
  nodeset.each do |n|
    n.name == "link" or next
    n.children = n["target"]
  end
  nodeset.text.sub(/^[,; ]/, "").strip
end

#symbol_key(sym) ⇒ Object

Indices sort after letter but before any following letter (x, x_m, x_1, xa); we use colon to force that sort order. Numbers sort after letters; we use thorn to force that sort order. Capitals sort before their corresponding lowercase.



10
11
12
13
14
15
16
17
# File 'lib/metanorma/standoc/cleanup_symbols.rb', line 10

def symbol_key(sym)
  @c.decode(asciimath_key(sym).text)
    .gsub(/[\[\]{}<>()]/, "").gsub(/\s/m, "")
    .gsub(/[[:punct:]]|[_^]/, ":\\0").gsub("`", "")
    .gsub(/[0-9]+/, "þ\\0")
    .tr("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",
        "ABCFEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
end

#symbols_cleanup(docxml) ⇒ Object



31
32
33
34
35
36
37
38
# File 'lib/metanorma/standoc/cleanup_symbols.rb', line 31

def symbols_cleanup(docxml)
  docxml.xpath("//definitions/dl").each do |dl|
    dl_out = extract_symbols_list(dl)
    dl_out.sort! { |a, b| a[:key] <=> b[:key] || a[:dt] <=> b[:dt] }
    dl.children = dl_out.map { |d| d[:dt].to_s + d[:dd].to_s }.join("\n")
  end
  docxml
end

#table_cleanup(xmldoc) ⇒ Object



44
45
46
47
48
49
50
# File 'lib/metanorma/standoc/cleanup_table.rb', line 44

def table_cleanup(xmldoc)
  dl1_table_cleanup(xmldoc)
  dl2_table_cleanup(xmldoc)
  sources_table_cleanup(xmldoc)
  notes_table_cleanup(xmldoc)
  header_rows_cleanup(xmldoc)
end

#table_footnote_number(outnum) ⇒ Object



50
51
52
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 50

def table_footnote_number(outnum)
  (outnum - 1 + "a".ord).chr
end

#table_footnote_renumber(xmldoc) ⇒ Object



54
55
56
57
58
59
60
61
62
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 54

def table_footnote_renumber(xmldoc)
  xmldoc.xpath("//table | //figure").each do |t|
    seen = {}
    i = 0
    t.xpath(".//fn[not(ancestor::name)]").each do |fn|
      i, seen = table_footnote_renumber1(fn, i, seen)
    end
  end
end

#table_footnote_renumber1(fnote, idx, seen) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 37

def table_footnote_renumber1(fnote, idx, seen)
  content = footnote_content(fnote)
  if seen[content] then outnum = seen[content]
  else
    idx += 1
    outnum = idx
    seen[content] = outnum
  end
  fnote["reference"] = table_footnote_number(outnum)
  fnote["table"] = true
  [idx, seen]
end

#term_children_cleanup(xmldoc) ⇒ Object



76
77
78
79
80
81
82
83
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 76

def term_children_cleanup(xmldoc)
  xmldoc.xpath("//terms[terms][not(term)]").each { |t| t.name = "clause" }
  xmldoc.xpath("//term").each do |t|
    %w(termnote termexample termsource term).each do |w|
      t.xpath("./#{w}").each { |n| t << n.remove }
    end
  end
end

#term_defs_boilerplate(div, source, term, _preface, isodoc) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 20

def term_defs_boilerplate(div, source, term, _preface, isodoc)
  a = @i18n.term_def_boilerplate and div.next = a
  source.each do |s|
    @anchors[s["bibitemid"]] or
      @log.add("Crossreferences", nil,
               "term source #{s['bibitemid']} not referenced", severity: 1)
  end
  a = if source.empty? && term.nil? then @i18n.no_terms_boilerplate
      else term_defs_boilerplate_cont(source, term, isodoc)
      end
  a and div.next = a
end

#term_defs_boilerplate_cont(src, term, isodoc) ⇒ Object



33
34
35
36
37
38
39
40
41
42
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 33

def term_defs_boilerplate_cont(src, term, isodoc)
  sources = isodoc.sentence_join(src.map do |s|
    %{<eref bibitemid="#{s['bibitemid']}"/>}
  end)
  if src.empty? then @i18n.internal_terms_boilerplate
  elsif term.nil? then external_terms_boilerplate(sources)
  else
    internal_external_terms_boilerplate(sources)
  end
end

#term_designation_redundant(xmldoc) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 181

def term_designation_redundant(xmldoc)
  xmldoc.xpath("//term").each do |t|
    DESIGNATOR.each do |n|
      t.xpath("./#{n}/expression/name").each_with_object([]) do |d, m|
        if m.include?(d.text)
          @log.add("Terms", t, "Removed duplicate designation #{d.text}")
          d.parent.parent.remove
        end
        m << d.text
      end
    end
  end
end

#term_designation_reorder(xmldoc) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 165

def term_designation_reorder(xmldoc)
  xmldoc.xpath("//term").each do |t|
    des = DESIGNATOR.each_with_object([]) do |tag, m|
      t.xpath("./#{tag}").each { |x| m << x.remove }
    end.reverse
    t << " "
    des.each do |x|
      t.children.first.previous = x
    end
  end
end

#term_dl_to_designation_category(prev, category) ⇒ Object



101
102
103
104
105
106
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 101

def term_dl_to_designation_category(prev, category)
  cat = prev.at(".//expression/grammar/#{category}")
  cat&.text&.include?(",") and
    cat.replace(cat.text.split(/,\s*/)
      .map { |x| "<#{category}>#{x}</#{category}>" }.join)
end

#term_dl_to_designation_metadata(prev, dlist) ⇒ Object



45
46
47
48
49
50
51
52
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 45

def (prev, dlist)
  %w(absent geographic-area).each do |a|
    dl_to_attrs(prev, dlist, a)
  end
  %w(field-of-application usage-info).reverse.each do |a|
    dl_to_elems(prev.at("./expression"), prev, dlist, a)
  end
end

#term_dl_to_expression_grammar(prev, dlist) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 88

def term_dl_to_expression_grammar(prev, dlist)
  prev.at(".//expression") or return
  prev.at(".//expression") << "<grammar><sentinel/></grammar>"
  %w(gender number isPreposition isParticiple isAdjective isAdverb isNoun
     grammar-value).reverse.each do |a|
    dl_to_elems(prev.at(".//expression/grammar/*"), prev.elements.last,
                dlist, a)
  end
  term_dl_to_designation_category(prev, "gender")
  term_dl_to_designation_category(prev, "number")
  prev.at(".//expression/grammar/sentinel").remove
end

#term_dl_to_expression_metadata(prev, dlist) ⇒ Object



63
64
65
66
67
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 63

def (prev, dlist)
  (prev, dlist)
  (prev, dlist)
  term_to_letter_symbol(prev, dlist)
end

#term_dl_to_expression_name_metadata(prev, dlist) ⇒ Object



80
81
82
83
84
85
86
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 80

def (prev, dlist)
  %w(abbreviation-type pronunciation).reverse.each do |a|
    dl_to_elems(prev.at("./expression/name"), prev, dlist, a)
  end
  g = dlist.at("./dt[text()='grammar']/following::dd//dl") and
    term_dl_to_expression_grammar(prev, g)
end

#term_dl_to_expression_root_metadata(prev, dlist) ⇒ Object



69
70
71
72
73
74
75
76
77
78
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 69

def (prev, dlist)
  %w(isInternational).each do |a|
    p = prev.at("./expression | ./letter-symbol | ./graphical-symbol")
    dl_to_attrs(p, dlist, a)
  end
  %w(language script type).each do |a|
    p = prev.at("./expression") or next
    dl_to_attrs(p, dlist, a)
  end
end

#term_dl_to_metadata(xmldoc) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 23

def (xmldoc)
  xmldoc.xpath("//term[dl[@metadata = 'true']]").each do |t|
    t.xpath("./dl[@metadata = 'true']").each do |dl|
      prev = related2pref(dl_to_designation(dl)) or next
      (prev, dl)
      (prev, dl)
      (prev, dl)
      dl.remove
    end
  end
end

#term_dl_to_term_metadata(prev, dlist) ⇒ Object



35
36
37
38
39
40
41
42
43
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 35

def (prev, dlist)
  return unless prev.name == "preferred" &&
    prev.at("./preceding-sibling::preferred").nil?

  ins = term_element_insert_point(prev)
  %w(domain subject).each do |a|
    ins = dl_to_elems(ins, prev.parent, dlist, a)
  end
end

#term_element_insert_point(prev) ⇒ Object



54
55
56
57
58
59
60
61
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 54

def term_element_insert_point(prev)
  ins = prev
  while %w(preferred admitted deprecates related domain dl)
      .include? ins&.next_element&.name
    ins = ins.next_element
  end
  ins
end

#term_index_cleanup(xmldoc) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 124

def term_index_cleanup(xmldoc)
  return unless @index_terms

  xmldoc.xpath("//preferred").each do |p|
    index_cleanup1(p.at("./expression/name | ./letter-symbol/name"),
                   p.xpath("./field-of-application | ./usage-info")
      &.map(&:text)&.join(", "))
  end
  xmldoc.xpath("//definitions/dl/dt").each do |p|
    index_cleanup1(p, "")
  end
end

#term_nonverbal_designations(xmldoc) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 126

def term_nonverbal_designations(xmldoc)
  xmldoc.xpath("//term/preferred | //term/admitted | //term/deprecates")
    .each do |d|
    d.text.strip.empty? or next
    n = d.next_element
    if %w(formula figure).include?(n&.name)
      term_nonverbal_designations1(d, n)
    else d.at("./expression/name") or
      d.children = term_expr("")
    end
  end
end

#term_nonverbal_designations1(desgn, elem) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 139

def term_nonverbal_designations1(desgn, elem)
  desgn = related2pref(desgn)
  if elem.name == "figure"
    elem.at("./name").remove
    desgn.children =
      "<graphical-symbol>#{elem.remove.to_xml}</graphical-symbol>"
  else
    desgn.children = term_expr(elem.at("./stem").to_xml)
    elem.remove
  end
end

#term_termsource_to_designation(xmldoc) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 153

def term_termsource_to_designation(xmldoc)
  xmldoc.xpath("//term/termsource").each do |t|
    p = t.previous_element
    while %w(domain subject).include? p&.name
      p = p.previous_element
    end
    DESIGNATOR.include?(p&.name) or
      next
    related2pref(p) << t.remove
  end
end

#term_to_letter_symbol(prev, dlist) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 108

def term_to_letter_symbol(prev, dlist)
  ls = dlist.at("./dt[text()='letter-symbol']/following::dd/p")&.text
  !ls || ls == "false" and return
  e = prev.at(".//expression")
  e.name = "letter-symbol"
  ls != "true" and e["type"] = ls
end

#termdef_boilerplate_cleanup(xmldoc) ⇒ Object



72
73
74
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 72

def termdef_boilerplate_cleanup(xmldoc)
  # termdef_remove_initial_paras(xmldoc)
end

#termdef_boilerplate_insert(xmldoc, isodoc, once = false) ⇒ Object



90
91
92
93
94
95
96
97
98
99
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 90

def termdef_boilerplate_insert(xmldoc, isodoc, once = false)
  if once
    f = termdef_boilerplate_insert_location(xmldoc) and
      termdef_boilerplate_insert1(f, xmldoc, isodoc)
  else
    xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
      termdef_boilerplate_insert1(f, xmldoc, isodoc)
    end
  end
end

#termdef_boilerplate_insert1(sect, xmldoc, isodoc) ⇒ Object



110
111
112
113
114
115
116
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 110

def termdef_boilerplate_insert1(sect, xmldoc, isodoc)
  sect.at("./clause[@type = 'boilerplate'] | " \
          "./note[@type = 'boilerplate']") and return
  term_defs_boilerplate(sect.at("./title"),
                        xmldoc.xpath(".//termdocsource"),
                        sect.at(".//term"), sect.at(".//p"), isodoc)
end

#termdef_boilerplate_insert_location(xmldoc) ⇒ Object



101
102
103
104
105
106
107
108
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 101

def termdef_boilerplate_insert_location(xmldoc)
  f = xmldoc.at(self.class::TERM_CLAUSE)
  root = xmldoc.at("//sections/terms | //sections/clause[.//terms]")
  !f || !root and return f || root
  f.at("./following::terms") and return root
  f.at("./preceding-sibling::clause") and return root
  f
end

#termdef_cleanup(xmldoc) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 107

def termdef_cleanup(xmldoc)
  termdef_unnest_cleanup(xmldoc)
  termlookup_cleanup(xmldoc)
  term_nonverbal_designations(xmldoc)
  (xmldoc)
  term_termsource_to_designation(xmldoc)
  term_designation_reorder(xmldoc)
  term_designation_redundant(xmldoc)
  termdef_from_termbase(xmldoc)
  termdomain_cleanup(xmldoc)
  termdef_stem_cleanup(xmldoc)
  termdefinition_cleanup(xmldoc)
  termdomain1_cleanup(xmldoc)
  termnote_example_cleanup(xmldoc)
  term_children_cleanup(xmldoc)
end

#termdef_from_termbase(xmldoc) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 85

def termdef_from_termbase(xmldoc)
  xmldoc.xpath("//term").each do |x|
    if (c = x.at("./origin/termref")) && !x.at("./definition")
      x.at("./origin").previous = fetch_termbase(c["base"], c.text)
    end
  end
end

#termdef_remove_initial_paras(xmldoc) ⇒ Object



76
77
78
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 76

def termdef_remove_initial_paras(xmldoc)
  xmldoc.xpath("//terms/p | //terms/ul").each(&:remove)
end

#termdef_stem_cleanup(xmldoc) ⇒ Object



4
5
6
7
8
9
10
11
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 4

def termdef_stem_cleanup(xmldoc)
  xmldoc.xpath("//term//expression/name[stem]").each do |n|
    test = n.dup
    test.at("./stem").remove
    test.text.strip.empty? or next
    n.parent.name = "letter-symbol"
  end
end

#termdef_unnest_cleanup(xmldoc) ⇒ Object

release termdef tags from surrounding paras



14
15
16
17
18
19
20
21
# File 'lib/metanorma/standoc/cleanup_terms_designations.rb', line 14

def termdef_unnest_cleanup(xmldoc)
  desgn = "//p/admitted | //p/deprecates | //p/preferred | //p//related"
  nodes = xmldoc.xpath(desgn)
  while !nodes.empty?
    nodes[0].parent.replace(nodes[0].parent.children)
    nodes = xmldoc.xpath(desgn)
  end
end

#termdefinition_cleanup(xmldoc) ⇒ Object



23
24
25
26
27
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 23

def termdefinition_cleanup(xmldoc)
  generate_termdefinitions(xmldoc)
  split_termdefinitions(xmldoc)
  alternate_termdefinitions(xmldoc)
end

#termdocsource_cleanup(xmldoc) ⇒ Object



71
72
73
74
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 71

def termdocsource_cleanup(xmldoc)
  f = xmldoc.at("//preface | //sections")
  xmldoc.xpath("//termdocsource").each { |s| f.previous = s.remove }
end

#termdomain1_cleanup(xmldoc) ⇒ Object



16
17
18
19
20
21
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 16

def termdomain1_cleanup(xmldoc)
  xmldoc.xpath("//term").each do |t|
    d = t.xpath("./domain | ./subject").last or next
    defn = d.at("../definition") and defn.previous = d.remove
  end
end

#termdomain_cleanup(xmldoc) ⇒ Object



7
8
9
10
11
12
13
14
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 7

def termdomain_cleanup(xmldoc)
  xmldoc.xpath("//p/domain").each do |a|
    parent = a.parent
    prev = parent.previous
    prev.next = a.remove
    parent.text.strip.empty? and parent.remove
  end
end

#termlookup_cleanup(xmldoc) ⇒ Object



103
104
105
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 103

def termlookup_cleanup(xmldoc)
  Metanorma::Standoc::TermLookupCleanup.new(xmldoc, @log).call
end

#termnote_example_cleanup(xmldoc) ⇒ Object



93
94
95
96
97
98
99
100
101
# File 'lib/metanorma/standoc/cleanup_terms.rb', line 93

def termnote_example_cleanup(xmldoc)
  %w(note example).each do |w|
    xmldoc.xpath("//term#{w}[not(ancestor::term)]").each do |x|
      if x["keepasterm"] then x.delete("keepasterm")
      else x.name = w
      end
    end
  end
end

#terms_subclause_type_tally(node, m, parent) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 123

def terms_subclause_type_tally(node, m, parent)
  sym = if (node.at(".//term") && !node.at(".//definitions")) ||
      (node.name == "terms" && !node.at(".//term"))
          unless m[:parent] == :term # don't count Term > Term twice
            :term
          end
        elsif node.at(".//term") && node.at("./self::*#{SYMnoABBR}") then :tsna
        elsif node.at(".//term") && node.at("./self::*#{ABBRnoSYM}") then :tans
        elsif node.at(".//term") && node.at("./self::*#{SYMABBR}") then :tsa
        elsif node.at(".//term") && node.at("./self::*#{NO_SYMABBR}") then :tnsa
        elsif node.at("./self::*#{SYMnoABBR}") then :sna
        elsif node.at("./self::*#{ABBRnoSYM}") then :ans
        elsif node.at("./self::*#{SYMABBR}") then :sa
        elsif node.at("./self::*#{NO_SYMABBR}") then :nsa
        elsif node.name == "definitions" # ignore
        elsif node == parent && node.at(".//term") &&
            node.at(".//definitions")
          :termdef
        else :other
        end
  node == parent and m[:parent] = sym
  sym and m[sym] += 1
end

#terms_subclauses(node) ⇒ Object



114
115
116
117
118
119
120
121
# File 'lib/metanorma/standoc/cleanup_section_names.rb', line 114

def terms_subclauses(node)
  legal = %w(terms definitions clause)
  [node, node&.elements].compact.flatten
    .select do |x|
      legal.include?(x.name) &&
        !(x.name == "clause" && x["type"] == "boilerplate")
    end
end

#textcleanup(result) ⇒ Object



4
5
6
7
8
9
10
11
12
# File 'lib/metanorma/standoc/cleanup_text.rb', line 4

def textcleanup(result)
  text = result.flatten.map { |l| l.sub(/\s*\Z/, "") } * "\n"
  text = text.gsub(/\s+<fn /, "<fn ")
  %w(passthrough passthrough-inline).each do |v|
    text.gsub!(%r{<#{v}\s+formats="metanorma">([^<]*)
              </#{v}>}mx) { @c.decode($1) }
  end
  text
end

#title_footnote_move(xmldoc) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/metanorma/standoc/cleanup_footnotes.rb', line 86

def title_footnote_move(xmldoc)
  ins = xmldoc.at("//bibdata/language")
  xmldoc.xpath("//bibdata/title//fn").each do |f|
    f.name = "note"
    f["type"] = "title-footnote"
    f.delete("reference")
    ins.previous = f.remove
  end
end

#to_preface(preface, clause) ⇒ Object



27
28
29
30
# File 'lib/metanorma/standoc/cleanup_section.rb', line 27

def to_preface(preface, clause)
  clause.delete("preface")
  preface.add_child clause.remove
end

#to_regex(str) ⇒ Object



20
21
22
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 20

def to_regex(str)
  Regexp.new(str.gsub(/\s/, ""), Regexp::IGNORECASE | Regexp::MULTILINE)
end

#to_xreftarget(str) ⇒ Object



125
126
127
128
129
130
131
132
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 125

def to_xreftarget(str)
  return Metanorma::Utils::to_ncname(str) unless /^[^#]+#.+$/.match?(str)

  /^(?<pref>[^#]+)#(?<suff>.+)$/ =~ str
  pref = pref.gsub(%r([#{Metanorma::Utils::NAMECHAR}])o, "_")
  suff = suff.gsub(%r([#{Metanorma::Utils::NAMECHAR}])o, "_")
  "#{pref}##{suff}"
end

#toc_cleanup(xmldoc) ⇒ Object



4
5
6
7
8
9
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 4

def toc_cleanup(xmldoc)
  toc_cleanup_para(xmldoc)
  xmldoc.xpath("//toc").each { |t| toc_cleanup1(t, xmldoc) }
  toc_cleanup_clause(xmldoc)
  (xmldoc)
end

#toc_cleanup1(toc, xmldoc) ⇒ Object



43
44
45
46
47
48
49
50
51
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 43

def toc_cleanup1(toc, xmldoc)
  depth = 1
  ret = ""
  toc_index(toc, xmldoc).each do |x|
    ret = toc_cleanup1_entry(x, depth, ret)
    depth = x[:depth]
  end
  toc.children = "<ul>#{ret}</ul>"
end

#toc_cleanup1_entry(entry, depth, ret) ⇒ Object



53
54
55
56
57
58
59
60
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 53

def toc_cleanup1_entry(entry, depth, ret)
  if depth > entry[:depth]
    ret += "</ul></li>" * (depth - entry[:depth])
  elsif depth < entry[:depth]
    ret += "<li><ul>" * (entry[:depth] - depth)
  end
  ret + "<li><xref target='#{entry[:target]}'>#{entry[:text]}</xref></li>"
end

#toc_cleanup_clause(xmldoc) ⇒ Object



62
63
64
65
66
67
68
69
70
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 62

def toc_cleanup_clause(xmldoc)
  xmldoc
    .xpath("//clause[@type = 'toc'] | //annex[@type = 'toc']").each do |c|
    c.xpath(".//ul[not(ancestor::ul)]").each do |ul|
      toc_cleanup_clause_entry(xmldoc, ul)
      ul.replace("<toc>#{ul.to_xml}</toc>")
    end
  end
end

#toc_cleanup_clause_entry(xmldoc, list) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 72

def toc_cleanup_clause_entry(xmldoc, list)
  list.xpath(".//xref[not(text())]").each do |x|
    c1 = xmldoc.at("//*[@id = '#{x['target']}']")
    t = c1.at("./variant-title[@type = 'toc']") || c1.at("./title")
    x << t.dup.children
  end
end

#toc_cleanup_para(xmldoc) ⇒ Object



11
12
13
14
15
16
17
18
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 11

def toc_cleanup_para(xmldoc)
  xmldoc.xpath("//p[toc]").each do |x|
    x.xpath("./toc").reverse.each do |t|
      x.next = t
    end
    x.remove if x.text.strip.empty?
  end
end

#toc_index(toc, xmldoc) ⇒ Object



20
21
22
23
24
25
26
27
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 20

def toc_index(toc, xmldoc)
  depths = toc_index_depths(toc)
  depths.keys.each_with_object([]) do |key, arr|
    xmldoc.xpath(key).each do |x|
      arr << toc_index1(key, x, depths)
    end
  end.sort_by { |a| a[:line] }
end

#toc_index1(key, entry, depths) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 29

def toc_index1(key, entry, depths)
  t = entry.at("./following-sibling::variant-title[@type = 'toc']") and
    entry = t
  { text: entry.children.to_xml, depth: depths[key].to_i,
    target: entry.xpath("(./ancestor-or-self::*/@id)[last()]")[0].text,
    line: entry.line }
end

#toc_index_depths(toc) ⇒ Object



37
38
39
40
41
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 37

def toc_index_depths(toc)
  toc.xpath("./toc-xpath").each_with_object({}) do |x, m|
    m[x.text] = x["depth"]
  end
end

#toc_metadata(xmldoc) ⇒ Object



80
81
82
83
84
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 80

def (xmldoc)
  @htmltoclevels || @doctoclevels || @pdftoclevels || @toclevels or return
  ins = add_misc_container(xmldoc)
  toc_metadata1(ins)
end

#toc_metadata1(ins) ⇒ Object



86
87
88
89
90
91
92
93
94
# File 'lib/metanorma/standoc/cleanup_toc.rb', line 86

def toc_metadata1(ins)
  [[@toclevels, "TOC Heading Levels"],
   [@htmltoclevels, "HTML TOC Heading Levels"],
   [@doctoclevels, "DOC TOC Heading Levels"],
   [@pdftoclevels, "PDF TOC Heading Levels"]].each do |n|
    n[0] and ins << "<presentation-metadata><name>#{n[1]}</name>" \
                    "<value>#{n[0]}</value></presentation-metadata>"
  end
end

#tq(text) ⇒ Object



31
32
33
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 31

def tq(text)
  text.sub(/^"/, "").sub(/"$/, "")
end

#uninterrupt_quotes_around_xml(xmldoc) ⇒ Object

“abc<tag/>”, def => “abc”,<tag/> def



27
28
29
30
31
32
33
34
# File 'lib/metanorma/standoc/cleanup_text.rb', line 27

def uninterrupt_quotes_around_xml(xmldoc)
  xmldoc.traverse do |n|
    next unless n.text? && n&.previous&.element?
    next if uninterrupt_quotes_around_xml_skip(n)

    uninterrupt_quotes_around_xml1(n.previous)
  end
end

#uninterrupt_quotes_around_xml1(elem) ⇒ Object



49
50
51
52
53
54
55
56
57
# File 'lib/metanorma/standoc/cleanup_text.rb', line 49

def uninterrupt_quotes_around_xml1(elem)
  prev = elem.at(".//preceding::text()[1]") or return
  /\S\Z/.match?(prev.text) or return
  foll = elem.at(".//following::text()[1]")
  m = /\A(["'][[:punct:]]*)(\s|\Z)/
    .match(@c.decode(foll&.text)) or return
  foll.content = foll.text.sub(/\A(["'][[:punct:]]*)/, "")
  prev.content = "#{prev.text}#{m[1]}"
end

#uninterrupt_quotes_around_xml_skip(elem) ⇒ Object



40
41
42
43
44
45
46
47
# File 'lib/metanorma/standoc/cleanup_text.rb', line 40

def uninterrupt_quotes_around_xml_skip(elem)
  !(/\A['"]/.match?(elem.text) &&
    elem.previous.path.gsub(/\[\d+\]/, "").split(%r{/})[1..-2]
    .intersection(IGNORE_QUOTES_ELEMENTS).empty? &&
    ((elem.previous.text.strip.empty? &&
      !empty_tag_with_text_content?(elem.previous)) ||
     ignoretext?(elem.previous)))
end

#unnumbered_blocks_cleanup(xmldoc) ⇒ Object



233
234
235
236
237
238
239
240
# File 'lib/metanorma/standoc/cleanup_block.rb', line 233

def unnumbered_blocks_cleanup(xmldoc)
  @blockunnumbered&.each do |b|
    xmldoc.xpath("//#{b}").each do |e|
      /^[^_]/.match?(e["id"]) and e["unnumbered"] = "false"
      e["unnumbered"] ||= "true"
    end
  end
end

#unwrap_boilerplate_clauses(xmldoc, xpath) ⇒ Object



80
81
82
83
84
85
86
87
88
# File 'lib/metanorma/standoc/cleanup_boilerplate.rb', line 80

def unwrap_boilerplate_clauses(xmldoc, xpath)
  xmldoc.xpath(xpath).each do |f|
    f.xpath(".//clause[@type = 'boilerplate'] | " \
            ".//note[@type = 'boilerplate']").each do |c|
      c.at("./title")&.remove
      c.replace(c.children)
    end
  end
end

#uri_cleanup(xmldoc) ⇒ Object



215
216
217
218
219
220
221
222
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 215

def uri_cleanup(xmldoc)
  xmldoc.xpath("//link[@target]").each do |l|
    l["target"] = Addressable::URI.parse(l["target"]).to_s
  rescue Addressable::URI::InvalidURIError
    err = "Malformed URI: #{l['target']}"
    @log.add("Anchors", l, err, severity: 0)
  end
end

#uri_component_encode(comp) ⇒ Object



224
225
226
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 224

def uri_component_encode(comp)
  CGI.escape(comp).gsub("+", "%20")
end

#validate_ref_dl(bib, clause) ⇒ Object

do not accept implicit id



19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 19

def validate_ref_dl(bib, clause)
  id = bib["id"]
  id ||= clause["id"] unless /^_/.match?(clause["id"])
  unless id
    @log.add("Anchors", clause,
             "The following reference is missing an anchor:\n" \
             "#{clause.to_xml}", severity: 1)
    return
  end
  @refids << id
  validate_ref_dl1(bib, id, clause)
end

#validate_ref_dl1(bib, id, clause) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/metanorma/standoc/cleanup_asciibib.rb', line 32

def validate_ref_dl1(bib, id, clause)
  bib["title"] or
    @log.add("Bibliography", clause, "Reference #{id} is missing a title",
             severity: 1)
  bib["docid"] or
    @log.add("Bibliography", clause,
             "Reference #{id} is missing a document identifier (docid)",
             severity: 1)
end

#variant_cleanup(xmldoc) ⇒ Object



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/metanorma/standoc/cleanup.rb', line 136

def variant_cleanup(xmldoc)
  variant_space_cleanup(xmldoc)
  xmldoc.xpath("//*[variant]").each do |c|
    next unless c.children.any? do |n|
      n.name != "variant" && (!n.text? || !n.text.gsub(/\s/, "").empty?)
    end

    variant_cleanup1(c)
  end
  xmldoc.xpath("//variantwrap").each { |n| n.name = "variant" }
end

#variant_cleanup1(elem) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
# File 'lib/metanorma/standoc/cleanup.rb', line 148

def variant_cleanup1(elem)
  elem.xpath("./variant").each do |n|
    if n.at_xpath("preceding-sibling::node()" \
                  "[not(self::text()[not(normalize-space())])][1]" \
                  "[self::variantwrap]")
      n.previous_element << n
    else
      n.replace("<variantwrap/>").first << n
    end
  end
end

#variant_space_cleanup(xmldoc) ⇒ Object



160
161
162
163
164
165
166
167
168
169
# File 'lib/metanorma/standoc/cleanup.rb', line 160

def variant_space_cleanup(xmldoc)
  xmldoc.xpath("//*[variant]").each do |c|
    next if c.next.nil? || c.next.next.nil?

    if c.next.text? && c.next.next.name == "variant"
      c.next.text.gsub(/\s/, "").empty? and
        c.next.remove
    end
  end
end

#xml_unescape_mathml(xml) ⇒ Object



51
52
53
54
55
56
57
58
# File 'lib/metanorma/standoc/cleanup_maths.rb', line 51

def xml_unescape_mathml(xml)
  return if xml.children.any?(&:element?)

  math = xml.text.gsub("&lt;", "<").gsub("&gt;", ">")
    .gsub("&quot;", '"').gsub("&apos;", "'").gsub("&amp;", "&")
    .gsub(/<[^: \r\n\t\/]+:/, "<").gsub(/<\/[^ \r\n\t:]+:/, "</")
  xml.children = math
end

#xref_alias(elem) ⇒ Object



229
230
231
232
233
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 229

def xref_alias(elem)
  elem["style"] == "id" && elem.text.strip.empty? and
    elem << elem["target"]
  elem["target"] = @anchor_alias[elem["target"]]
end

#xref_cleanup(xmldoc) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 131

def xref_cleanup(xmldoc)
  anchor_alias(xmldoc)
  xref_compound_cleanup(xmldoc)
  xref_cleanup1(xmldoc)
  xref_compound_wrapup(xmldoc)
  eref_stack(xmldoc)
end

#xref_cleanup1(xmldoc) ⇒ Object



205
206
207
208
209
210
211
212
213
214
215
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 205

def xref_cleanup1(xmldoc)
  xmldoc.xpath("//xref").each do |x|
    %r{:(?!//)}.match?(x["target"]) and xref_to_internal_eref(x)
    x.name == "xref" or next
    if refid? x["target"]
      xref_to_eref(x, "eref")
    elsif @anchor_alias[x["target"]] then xref_alias(x)
    else x.delete("type")
    end
  end
end

#xref_compound_cleanup(xmldoc) ⇒ Object



172
173
174
175
176
177
178
179
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 172

def xref_compound_cleanup(xmldoc)
  xmldoc.xpath("//xref").each do |x|
    x["target"].include?(";") or next
    locations = x["target"].split(";")
    x["target"] = locations.first.sub(/^[^!]*!/, "")
    xref_compound_cleanup1(x, locations)
  end
end

#xref_compound_cleanup1(xref, locations) ⇒ Object



181
182
183
184
185
186
187
188
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 181

def xref_compound_cleanup1(xref, locations)
  xref.children.empty? and xref.children = "<sentinel/>"
  xref_parse_compound_locations(locations).reverse.each do |y|
    xref.children.first.previous =
      "<xref target='#{y[1]}' connective='#{y[0]}'/>"
  end
  xref&.at("./sentinel")&.remove
end

#xref_compound_wrapup(xmldoc) ⇒ Object



199
200
201
202
203
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 199

def xref_compound_wrapup(xmldoc)
  xmldoc.xpath("//xref//xref").each do |x|
    x.name = "location"
  end
end

#xref_parse_compound_locations(locations) ⇒ Object



190
191
192
193
194
195
196
197
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 190

def xref_parse_compound_locations(locations)
  l = locations.map { |y| y.split("!", 2) }
  l.map.with_index do |y, i|
    y.size == 1 and
      y.unshift(l.dig(i + 1, 0) == "to" ? "from" : "and")
    y
  end
end

#xref_to_eref(elem, name) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 110

def xref_to_eref(elem, name)
  elem.name = name
  elem["bibitemid"] = elem["target"]
  if ref = @anchors&.dig(elem["target"], :xref)
    t = @anchors.dig(elem["target"], :id, elem["style"]) and
      ref = t
    elem["citeas"] = @c.decode(ref)
  else xref_to_eref1(elem)
  end
  elem.delete("target")
  extract_localities(elem)
end

#xref_to_eref1(elem) ⇒ Object



123
124
125
126
127
128
129
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 123

def xref_to_eref1(elem)
  elem["citeas"] = ""
  @internal_eref_namespaces.include?(elem["type"]) or
    @log.add("Crossreferences", elem,
             "#{elem['target']} does not have a corresponding " \
             "anchor ID in the bibliography!")
end

#xref_to_internal_eref(elem) ⇒ Object



217
218
219
220
221
222
223
224
225
226
227
# File 'lib/metanorma/standoc/cleanup_xref.rb', line 217

def xref_to_internal_eref(elem)
  a = elem["target"].split(":", 3)
  unless a.size < 2 || a[0].empty? || a[1].empty?
    elem["target"] = "#{a[0]}_#{a[1]}"
    a.size > 2 and
      elem.children = %{anchor="#{a[2..-1].join}",#{elem.children&.text}}
    elem["type"] = a[0]
    @internal_eref_namespaces << a[0]
    xref_to_eref(elem, "eref")
  end
end

#xreftarget_cleanup(elem) ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
# File 'lib/metanorma/standoc/cleanup_inline.rb', line 156

def xreftarget_cleanup(elem)
  elem.xpath("//xref/@target").each do |s|
    if (ret = to_xreftarget(s.value)) != (orig = s.value)
      s.value = ret
      output = s.parent.dup
      output.children.remove
      @log.add("Anchors", s.parent,
               "normalised identifier in #{output} from #{orig}")
    end
  end
end

#yaml2relaton(yaml, amend = nil) ⇒ Object



135
136
137
138
139
140
141
# File 'lib/metanorma/standoc/cleanup_bibdata.rb', line 135

def yaml2relaton(yaml, amend = nil)
  r = RelatonBib.parse_yaml(yaml.to_yaml, [Date], symbolize_names: true)
  h = RelatonBib::HashConverter.hash_to_bib(r)
  b = RelatonBib::BibliographicItem.new(**h).to_xml
  amend and b.sub!("</bibitem>", "#{amend}</bibitem>")
  b
end