Module: Metanorma::Standoc::Xref

Includes:
Regex
Included in:
Cleanup
Defined in:
lib/metanorma/cleanup/xref.rb,
lib/metanorma/cleanup/xref_localities.rb

Constant Summary

Constants included from Regex

Regex::CONN_REGEX_STR, Regex::ISO_REF, Regex::ISO_REF_ALL_PARTS, Regex::ISO_REF_NO_YEAR, Regex::LOCALITIES, Regex::LOCALITY_REGEX_STR, Regex::LOCALITY_REGEX_STR_TRIPLEDASH, Regex::LOCALITY_REGEX_VALUE_ONLY_STR, Regex::NON_ISO_REF, Regex::NON_ISO_REF1, Regex::NUMERIC_REGEX, Regex::TERM_REFERENCE_RE, Regex::TERM_REFERENCE_RE_STR

Instance Method Summary collapse

Methods included from Regex

#to_regex

Instance Method Details

#add_locality(stack, match) ⇒ Object



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

def add_locality(stack, match)
  add_locality_attributes(stack, match)
  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_locality_attributes(stack, match) ⇒ Object



63
64
65
66
67
68
# File 'lib/metanorma/cleanup/xref_localities.rb', line 63

def add_locality_attributes(stack, match)
  stack.children.empty? && match[:conn] or return
  stack["connective"] = match[:conn]
  match[:custom] and stack["custom-connective"] =
                       match[:custom].sub(/^:/, "")
end

#anchor_alias(xmldoc) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/metanorma/cleanup/xref.rb', line 67

def anchor_alias(xmldoc)
  t = xmldoc.at("//metanorma-extension/table[@anchor = " \
                "'_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



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

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

#eref_default_style(xmldoc) ⇒ Object



179
180
181
182
183
# File 'lib/metanorma/cleanup/xref.rb', line 179

def eref_default_style(xmldoc)
  @erefstyle or return
  xmldoc.xpath("//eref[not(@style)]")
    .each { |e| e["style"] = @erefstyle }
end

#eref_stack(xmldoc) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/metanorma/cleanup/xref.rb', line 54

def eref_stack(xmldoc)
  xmldoc.xpath("//eref/display-text[eref]").each do |e|
    e.replace(e.children)
  end
  xmldoc.xpath("//eref[eref]").each do |e|
    e.name = "erefstack"
    e.delete("bibitemid")
    e.delete("citeas")
    e.xpath("./eref").each { |e1| e1["type"] = e["type"] }
    e.delete("type")
  end
end

#eref_style_normalise(elem) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/metanorma/cleanup/xref.rb', line 27

def eref_style_normalise(elem)
  eref_style_normalise_prep(elem) or return
  s = elem["style"].gsub("-", "_")
  if @isodoc.bibrenderer.citetemplate.template_raw.key?(s.to_sym)
    elem["style"] = s
  elsif s != "short"
    @log.add("STANDOC_60", elem, params: [elem["style"]])
  end
end

#eref_style_normalise_prep(elem) ⇒ Object



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

def eref_style_normalise_prep(elem)
  !elem["style"] && @erefstyle and
    elem["style"] = @erefstyle
  elem["style"] or return
  @anchors.dig(elem["target"], :id, elem["style"]) and return
  # else style is not docidentifier, so it's relaton-render style
  true
end

#extract_localities(elem) ⇒ Object



8
9
10
11
12
13
14
15
16
17
# File 'lib/metanorma/cleanup/xref_localities.rb', line 8

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

#extract_localities1(elem, text) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
# File 'lib/metanorma/cleanup/xref_localities.rb', line 27

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)
  xref_display_text(elem, text)
end

#extract_localities_update_text(match) ⇒ Object

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



46
47
48
49
50
51
52
# File 'lib/metanorma/cleanup/xref_localities.rb', line 46

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

#fill_in_eref_connectives(elem) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/metanorma/cleanup/xref_localities.rb', line 70

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"] = "and"
    n && n.name == "localityStack" && n["connective"] == "to" and
      l["connective"] = "from"
  end
end

#locality_label(match) ⇒ Object



80
81
82
83
# File 'lib/metanorma/cleanup/xref_localities.rb', line 80

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



20
21
22
23
24
25
# File 'lib/metanorma/cleanup/xref_localities.rb', line 20

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

#origin_cleanup(xmldoc) ⇒ Object



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

def origin_cleanup(xmldoc)
  origin_default_style(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("STANDOC_32", x, params: [x["bibitemid"]])
    extract_localities(x)
  end
end

#origin_default_style(xmldoc) ⇒ Object



173
174
175
176
177
# File 'lib/metanorma/cleanup/xref.rb', line 173

def origin_default_style(xmldoc)
  @originstyle or return
  xmldoc.xpath("//origin[not(@style)]")
    .each { |e| e["style"] = @originstyle }
end

#quotesource_cleanup(xmldoc) ⇒ Object



155
156
157
158
159
# File 'lib/metanorma/cleanup/xref.rb', line 155

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

#tq(text) ⇒ Object



4
5
6
# File 'lib/metanorma/cleanup/xref_localities.rb', line 4

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

#xref_alias(elem) ⇒ Object



143
144
145
146
147
148
# File 'lib/metanorma/cleanup/xref.rb', line 143

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

#xref_cleanup(xmldoc) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/metanorma/cleanup/xref.rb', line 46

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



118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/metanorma/cleanup/xref.rb', line 118

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"] then xref_to_eref(x, "eref")
    elsif @anchor_alias[x["target"]] then xref_alias(x)
    else
      x.delete("type")
      xref_default_style(x)
    end
  end
end

#xref_compound_cleanup(xmldoc) ⇒ Object



88
89
90
91
92
93
94
95
96
# File 'lib/metanorma/cleanup/xref.rb', line 88

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

#xref_compound_cleanup1(xref, locations) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/metanorma/cleanup/xref.rb', line 98

def xref_compound_cleanup1(xref, locations)
  xref.children.empty? and xref.children = "<sentinel/>"
  xref_parse_compound_locations(locations, xref).reverse_each do |y|
    y[:custom] and c = " custom-connective='#{y[:custom]}'"
    xref.add_first_child "<xref target='#{y[:ref]}' connective='#{y[:conn]}'#{c}/>"
  end
  xref&.at("./sentinel")&.remove
end

#xref_compound_wrapup(xmldoc) ⇒ Object



107
108
109
110
111
112
113
114
115
116
# File 'lib/metanorma/cleanup/xref.rb', line 107

def xref_compound_wrapup(xmldoc)
  xmldoc.xpath("//xref//xref").each do |x|
    x.name = "location"
  end
  xmldoc.xpath("//xref[not(./display-text)]").each do |x|
    c = x.xpath("./*[not(self::locality or self::localityStack or self::location)] | ./text()")
    c.empty? and next
    xref_display_text(x, c.remove)
  end
end

#xref_default_style(elem) ⇒ Object



150
151
152
153
# File 'lib/metanorma/cleanup/xref.rb', line 150

def xref_default_style(elem)
  elem["defaultstyle"] and elem["style"] ||= elem["defaultstyle"]
  elem.delete("defaultstyle")
end

#xref_display_text(elem, text) ⇒ Object



39
40
41
42
43
# File 'lib/metanorma/cleanup/xref_localities.rb', line 39

def xref_display_text(elem, text)
  d = elem.add_child("<display-text></display-text>").first
  d.add_child(text) if text
  d
end

#xref_parse_compound_locations(locations, xref) ⇒ Object



85
86
87
88
89
90
91
92
93
94
# File 'lib/metanorma/cleanup/xref_localities.rb', line 85

def xref_parse_compound_locations(locations, xref)
  l = locations.map { |y| y.split("!", 2) }.map do |y|
    if y.size == 1 then { ref: y[0] }
    else
      conn = y[0].split(":", 2)
      { ref: y[1], conn: conn[0], custom: conn[1] }.compact
    end
  end
  xref_parse_compound_locations_fill_in(l, xref)
end

#xref_parse_compound_locations_fill_in(locations, xref) ⇒ Object



96
97
98
99
100
101
102
103
104
# File 'lib/metanorma/cleanup/xref_localities.rb', line 96

def xref_parse_compound_locations_fill_in(locations, xref)
  locations.map.with_index do |y, i|
    y[:conn] or
      y[:conn] = (locations.dig(i + 1, :conn) == "to" ? "from" : "and")
    %w(and from to or).include?(y[:conn]) or
      @log.add("STANDOC_31", xref, params: [y[:conn]])
    y
  end
end

#xref_to_eref(elem, name) ⇒ Object



6
7
8
9
10
11
12
13
14
# File 'lib/metanorma/cleanup/xref.rb', line 6

def xref_to_eref(elem, name)
  elem.name = name
  elem["bibitemid"] = elem["target"]
  xref_to_eref1(elem)
  eref_style_normalise(elem)
  elem.delete("target")
  elem.delete("defaultstyle") # xrefstyle default
  extract_localities(elem)
end

#xref_to_eref1(elem) ⇒ Object



16
17
18
19
20
21
22
23
24
25
# File 'lib/metanorma/cleanup/xref.rb', line 16

def xref_to_eref1(elem)
  if ref = @anchors&.dig(elem["target"], :xref)
    t = @anchors.dig(elem["target"], :id, elem["style"]) and ref = t
    elem["citeas"] = @c.decode(ref)
  else
    elem["citeas"] = ""
    @internal_eref_namespaces.include?(elem["type"]) or
      @log.add("STANDOC_30", elem, params: [elem["target"]])
  end
end

#xref_to_internal_eref(elem) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/metanorma/cleanup/xref.rb', line 131

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..].join}",#{elem.children&.text}}
    elem["type"] = a[0]
    @internal_eref_namespaces << a[0]
    xref_to_eref(elem, "eref")
  end
end