Module: Metanorma::Standoc::Refs

Included in:
Converter
Defined in:
lib/metanorma/standoc/ref.rb,
lib/metanorma/standoc/ref_queue.rb,
lib/metanorma/standoc/ref_utility.rb

Constant Summary collapse

ISO_REF =
%r{^<ref\sid="(?<anchor>[^"]+)">
\[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9-]+|IEV)
(?::(?<year>[0-9][0-9-]+))?\]</ref>,?\s*(?<text>.*)$}xm.freeze
ISO_REF_NO_YEAR =
%r{^<ref\sid="(?<anchor>[^"]+)">
      \[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9-]+):
      (?:--|&\#821[12];)\]</ref>,?\s*
        (?:<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>)?,?\s?(?<text>.*)$}xm
.freeze
ISO_REF_ALL_PARTS =
%r{^<ref\sid="(?<anchor>[^"]+)">
      \[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9]+)
      (?::(?<year>--|&\#821[12];|[0-9][0-9-]+))?\s
      \(all\sparts\)\]</ref>,?\s*
(?:<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>,?\s?)?(?<text>.*)$}xm.freeze
NON_ISO_REF =
%r{^<ref\sid="(?<anchor>[^"]+)">
      \[(?<usrlbl>\([^)]+\))?(?<code>.+?)\]</ref>,?\s*(?<text>.*)$}xm
.freeze
NON_ISO_REF1 =
%r{^<ref\sid="(?<anchor>[^"]+)">
      (?<usrlbl>\([^)]+\))?(?<code>.+?)</ref>,?\s*(?<text>.*)$}xm
.freeze
JOINT_REFS =
%i(merge dual).freeze
MALFORMED_REF =
<<~REF.freeze
  no anchor on reference, markup may be malformed: see
  https://www.metanorma.com/author/topics/document-format/bibliography/ ,
  https://www.metanorma.com/author/iso/topics/markup/#bibliographies
REF

Instance Method Summary collapse

Instance Method Details

#analyse_ref_code(code) ⇒ Object



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

def analyse_ref_code(code)
  ret = { id: code }
  code.nil? || code.empty? and return ret
  analyse_ref_code_csv(ret) ||
    analyse_ref_code_nested(ret)
end

#analyse_ref_code_csv(ret) ⇒ Object



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

def analyse_ref_code_csv(ret)
  ret[:id].include?("=") or return nil
  line = CSV.parse_line(ret[:id], liberal_parsing: true) or return nil
  a = analyse_ref_code_csv_breakup(line)
  analyse_ref_code_csv_map(a)
rescue StandardError
  nil
end

#analyse_ref_code_csv_breakup(line) ⇒ Object



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

def analyse_ref_code_csv_breakup(line)
  line.each_with_object({}) do |x, m|
    kv = x.split("=", 2)
    kv.size == 1 and kv = ["code", kv.first]
    m[kv[0].to_sym] = kv[1].delete_prefix('"').delete_suffix('"')
      .delete_prefix("'").delete_suffix("'")
  end
end

#analyse_ref_code_csv_map(source) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/metanorma/standoc/ref_utility.rb', line 137

def analyse_ref_code_csv_map(source)
  source.each_with_object({}) do |(k, v), ret|
    case k
    when :dropid, :hidden, :nofetch
      ret[k] = v == "true"
    when :repo, :path
      ret[:type] = k.to_s
      ret[:key] = v
      ret[:nofetch] = true
      source[:code] or
        ret[:id] = v.sub(%r{^[^/]+/}, "")
    when :"local-file"
      ret[:localfile] = v
    when :number
      if source[:code] then ret[:usrlabel] = "(#{v})"
      else ret[:numeric] = true
      end
    when :usrlabel
      ret[:usrlabel] = "(#{v})"
    when :code then ret[:id] = v
    end
  end
end

#analyse_ref_code_nested(ret) ⇒ Object

ref id = (usrlbl)codeyear code = [? number ]? | ident | nofetch(code) | hidden(code) | dropid(code) | # (repo|path):(key,code) | local-file(source,? key) | merge(code, code) | dual(code, code)



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

def analyse_ref_code_nested(ret)
  analyse_ref_dual(
    analyse_ref_numeric(
      analyse_ref_repo_path(
        analyse_ref_dropid(
          analyse_ref_hidden(
            analyse_ref_nofetch(analyse_ref_localfile(ret)),
          ),
        ),
      ),
    ),
  )
end

#analyse_ref_dropid(ret) ⇒ Object



85
86
87
88
# File 'lib/metanorma/standoc/ref_utility.rb', line 85

def analyse_ref_dropid(ret)
  m = /^dropid\((?<id>.+)\)$/.match(ret[:id]) or return ret
  ret.merge(id: m[:id], dropid: true)
end

#analyse_ref_dual(ret) ⇒ Object



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

def analyse_ref_dual(ret)
  m = /^(?<type>merge|dual)\((?<keys>.+)\)$/.match(ret[:id]) or
    return ret
  line = CSV.parse_line(m[:keys], liberal_parsing: true) or return ret
  line.size > 1 or return ret
  ret[:id] = line.first
  ret[m[:type].to_sym] = line[1..-1].map(&:strip)
  ret
end

#analyse_ref_hidden(ret) ⇒ Object



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

def analyse_ref_hidden(ret)
  m = /^hidden\((?<id>.+)\)$/.match(ret[:id]) or return ret
  ret.merge(id: m[:id], hidden: true)
end

#analyse_ref_localfile(ret) ⇒ Object



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

def analyse_ref_localfile(ret)
  m = /^local-file\((?:(?<source>[^,]+),\s*)?(?<id>.+)\)$/.match(ret[:id])
  m or return ret
  ret.merge(id: m[:id], localfile: (m[:source] || "default"))
end

#analyse_ref_nofetch(ret) ⇒ Object



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

def analyse_ref_nofetch(ret)
  m = /^nofetch\((?<id>.+)\)$/.match(ret[:id]) or return ret
  ret.merge(id: m[:id], nofetch: true)
end

#analyse_ref_numeric(ret) ⇒ Object



97
98
99
100
# File 'lib/metanorma/standoc/ref_utility.rb', line 97

def analyse_ref_numeric(ret)
  /^\d+$/.match?(ret[:id]) or return ret
  ret.merge(numeric: true)
end

#analyse_ref_repo_path(ret) ⇒ Object



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

def analyse_ref_repo_path(ret)
  m = /^(?<type>repo|path):\((?<key>[^,]+),?(?<id>.*)\)$/
    .match(ret[:id]) or return ret
  id = m[:id].empty? ? m[:key].sub(%r{^[^/]+/}, "") : m[:id]
  ret.merge(id: id, type: m[:type], key: m[:key], nofetch: true)
end

#conditional_date(bib, match, noyr) ⇒ Object



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

def conditional_date(bib, match, noyr)
  if match.names.include?("year") && !match[:year].nil?
    bib.date(type: "published") do |d|
      (noyr and d.on "--") or set_date_range(d, norm_year(match[:year]))
    end
  end
end

#docid(bib, code) ⇒ Object



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

def docid(bib, code)
  type, code1 = if /^\[\d+\]$|^\([^)]+\).*$/.match?(code)
                  ["metanorma", mn_code(code)]
                else
                  @bibdb&.docid_type(code) || [nil, code]
                end
  code1.sub!(/^nofetch\((.+)\)$/, "\\1")
  bib.docidentifier **attr_code(type: type) do |d|
    d << code1
  end
end

#docnumber(bib, code) ⇒ Object



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

def docnumber(bib, code)
  code or return
  bib.docnumber do |d|
    d << @c.decode(code).sub(/^[^\d]*/, "")
  end
end

#docrelation_insert(base) ⇒ Object



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

def docrelation_insert(base)
  %w(relation copyright status abstract locale language note version
     edition contributor date docnumber docidentifier).each do |v|
    r = base.at("//#{v}[last()]") and return r
  end
end

#dual_entries(base, add) ⇒ Object



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

def dual_entries(base, add)
  ins = docrelation_insert(base)
  ins.next = "<relation type='hasReproduction'>#{to_xml(add)}</relation>"
end

#fetch_ref(xml, code, year, **opts) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/metanorma/standoc/ref_queue.rb', line 132

def fetch_ref(xml, code, year, **opts)
  return nil if opts[:no_year]

  code = code.sub(/^\([^)]+\)/, "")
  hit = fetch_ref1(code, year, opts) or return nil
  xml.parent.add_child(smart_render_xml(hit, code, opts))
  xml
rescue RelatonBib::RequestError
  @log.add("Bibliography", nil, "Could not retrieve #{code}: " \
                                "no access to online site", severity: 1)
  nil
end

#fetch_ref1(code, year, opts) ⇒ Object



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

def fetch_ref1(code, year, opts)
  code = supply_ref_prefix(code)
  if opts[:localfile]
    @local_bibdb.get(code, opts[:localfile])
  else @bibdb&.fetch(code, year, opts)
  end
end

#fetch_ref_async(ref, idx, res) ⇒ Object



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

def fetch_ref_async(ref, idx, res)
  ref[:code] &&= supply_ref_prefix(ref[:code])
  if unfetchable_ref_code?(ref)
    res << [ref, idx, nil]
    idx += 1
  elsif ref[:localfile]
    res << [ref, idx, @local_bibdb.get(ref[:code], ref[:localfile])]
    idx += 1
  else idx = fetch_ref_async1(ref, idx, res)
  end
  idx
end

#fetch_ref_async1(ref, idx, res) ⇒ Object



176
177
178
179
180
181
# File 'lib/metanorma/standoc/ref_queue.rb', line 176

def fetch_ref_async1(ref, idx, res)
  @bibdb.fetch_async(ref[:code], ref[:year], ref) do |doc|
    res << [ref, idx, doc]
  end
  fetch_ref_async_dual(ref, idx, idx + 1, res)
end

#fetch_ref_async_dual(ref, orig, idx, res) ⇒ Object



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

def fetch_ref_async_dual(ref, orig, idx, res)
  JOINT_REFS.each do |m|
    ref.dig(:analyse_code, m)&.each_with_index do |code, i|
      @bibdb.fetch_async(code, nil, ref.merge(ord: idx)) do |doc|
        res << [ref.merge("#{m}_into": orig, merge_order: i, ord: idx),
                idx, doc]
      end
      idx += 1
    end
  end
  idx
end

#global_ievcache_nameObject



120
121
122
# File 'lib/metanorma/standoc/ref_queue.rb', line 120

def global_ievcache_name
  "#{Dir.home}/.iev/cache"
end

#id_and_year(id, year) ⇒ Object



16
17
18
# File 'lib/metanorma/standoc/ref_utility.rb', line 16

def id_and_year(id, year)
  year ? "#{id}:#{year}" : id
end

#init_bib_caches(node) ⇒ Object



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

def init_bib_caches(node)
  return if @no_isobib

  global = !@no_isobib_cache && !node.attr("local-cache-only")
  local = node.attr("local-cache") || node.attr("local-cache-only")
  local = nil if @no_isobib_cache
  @bibdb = Relaton::Db.init_bib_caches(
    local_cache: local,
    flush_caches: node.attr("flush-caches"),
    global_cache: global,
  )
end

#init_iev_caches(node) ⇒ Object



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

def init_iev_caches(node)
  unless @no_isobib_cache || @no_isobib
    node.attr("local-cache-only") or
      @iev_globalname = global_ievcache_name
    @iev_localname = local_ievcache_name(node.attr("local-cache") ||
                                         node.attr("local-cache-only"))
    if node.attr("flush-caches")
      FileUtils.rm_f @iev_globalname unless @iev_globalname.nil?
      FileUtils.rm_f @iev_localname unless @iev_localname.nil?
    end
  end
  # @iev = Iev::Db.new(globalname, localname) unless @no_isobib
end

#iso_publisher(bib, code) ⇒ Object



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

def iso_publisher(bib, code)
  code.sub(/ .*$/, "").split("/").each do |abbrev|
    bib.contributor do |c|
      c.role type: "publisher"
      c.organization do |org|
        organization(org, abbrev, nil, true)
      end
    end
  end
end

#isorefmatches2_1(xml, match, code) ⇒ Object



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

def isorefmatches2_1(xml, match, code)
  xml.bibitem **attr_code(ref_attributes(match)) do |t|
    isorefrender1(t, match, code, "--")
    t.date type: "published" do |d|
      d.on "--"
    end
    iso_publisher(t, match[:code])
    unless match[:fn].nil?
      t.note(**plaintxt.merge(type: "Unpublished-Status")) do |p|
        p << (match[:fn]).to_s
      end
    end
  end
end

#isorefmatches2code(match, _item) ⇒ Object



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

def isorefmatches2code(match, _item)
  code = analyse_ref_code(match[:code])
  { code: match[:code], no_year: true, lang: @lang || :all,
    note: match[:fn], year: nil, match: match, analyse_code: code,
    title: match[:text], usrlbl: match[:usrlbl] || code[:usrlabel] }
end

#isorefmatches2out(item, xml) ⇒ Object



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

def isorefmatches2out(item, xml)
  if item[:doc] then use_retrieved_relaton(item, xml)
  else isorefmatches2_1(xml, item[:ref][:match],
                        item[:ref][:analyse_code])
  end
end

#isorefmatches3_1(xml, match, code, year, _hasyr, _ref) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/metanorma/standoc/ref.rb', line 97

def isorefmatches3_1(xml, match, code, year, _hasyr, _ref)
  xml.bibitem(**attr_code(ref_attributes(match))) do |t|
    isorefrender1(t, match, code, year, " (all parts)")
    conditional_date(t, match, year == "--")
    iso_publisher(t, match[:code])
    if match.names.include?("fn") && match[:fn]
      t.note(**plaintxt.merge(type: "Unpublished-Status")) do |p|
        p << (match[:fn]).to_s
      end
    end
    t.extent type: "part" do |e|
      e.referenceFrom "all"
    end
  end
end

#isorefmatches3code(match, _item) ⇒ Object



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

def isorefmatches3code(match, _item)
  code = analyse_ref_code(match[:code])
  yr = norm_year(match[:year])
  hasyr = !yr.nil? && yr != "--"
  { code: match[:code], match: match, yr: yr, hasyr: hasyr,
    year: hasyr ? yr : nil, lang: @lang || :all,
    all_parts: true, no_year: yr == "--",
    title: match[:text], usrlbl: match[:usrlbl] || code[:usrlabel] }
end

#isorefmatches3out(item, xml) ⇒ Object



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

def isorefmatches3out(item, xml)
  if item[:doc] then use_retrieved_relaton(item, xml)
  else isorefmatches3_1(
    xml, item[:ref][:match], item[:ref][:analyse_code],
    item[:ref][:yr], item[:ref][:hasyr], item[:doc]
  )
  end
end

#isorefmatchescode(match, _item) ⇒ Object



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

def isorefmatchescode(match, _item)
  code = analyse_ref_code(match[:code])
  yr = norm_year(match[:year])
  { code: match[:code], year: yr, match: match,
    title: match[:text], usrlbl: match[:usrlbl] || code[:usrlabel],
    analyse_code: code, lang: @lang || :all }
end

#isorefmatchesout(item, xml) ⇒ Object



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

def isorefmatchesout(item, xml)
  if item[:doc] then use_retrieved_relaton(item, xml)
  else
    xml.bibitem **attr_code(ref_attributes(item[:ref][:match])) do |t|
      isorefrender1(t, item[:ref][:match], item[:ref][:analyse_code],
                    item[:ref][:year])
      item[:ref][:year] and t.date type: "published" do |d|
        set_date_range(d, item[:ref][:year])
      end
      iso_publisher(t, item[:ref][:match][:code])
    end
  end
end

#isorefrender1(bib, match, code, year, allp = "") ⇒ Object



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

def isorefrender1(bib, match, code, year, allp = "")
  bib.title(**plaintxt) { |i| i << ref_normalise(match[:text]) }
  #refitem_render_formattedref(bib, match[:text])
  docid(bib, match[:usrlbl]) if match[:usrlbl]
  docid(bib, code[:usrlabel]) if code && code[:usrlabel]
  docid(bib, id_and_year(match[:code], year) + allp)
  docnumber(bib, match[:code])
end

#joint_entries(out, joint_prep) ⇒ Object



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

def joint_entries(out, joint_prep)
  joint_prep.each do |k, v|
    v[:merge]&.each do |i|
      merge_entries(out[k], out[i]) and out[i] = nil
    end
    v[:dual]&.each do |i|
      dual_entries(out[k], out[i]) and out[i] = nil
    end
  end
  out
end

#joint_entries_prep(out) ⇒ Object



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

def joint_entries_prep(out)
  out.each_with_object({}) do |r, m|
    JOINT_REFS.each do |v|
      if i = r&.dig(:ref, "#{v}_into".to_sym)
        m[i] ||= { "#{v}": [] }
        m[i][v][r[:ref][:merge_order]] = r[:ref][:ord]
      end
    end
  end
end

#local_ievcache_name(cachename) ⇒ Object



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

def local_ievcache_name(cachename)
  return nil if cachename.nil?

  cachename += "_iev" unless cachename.empty?
  cachename = "iev" if cachename.empty?
  "#{cachename}/cache"
end

#merge_docids(base, add) ⇒ Object



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

def merge_docids(base, add)
  ins = base.at("//docidentifier[last()]")
  [ins, add].each do |v|
    v.at("//docidentifier[@primary = 'true']") or
      v.at("//docidentifier")["primary"] = true
  end
  add.xpath("//docidentifier").reverse.each do |p|
    ins.next = p
  end
end

#merge_entries(base, add) ⇒ Object

append publishers docids of add to base



64
65
66
67
68
# File 'lib/metanorma/standoc/ref_queue.rb', line 64

def merge_entries(base, add)
  merge_publishers(base, add)
  merge_docids(base, add)
  merge_urls(base, add)
end

#merge_publishers(base, add) ⇒ Object



70
71
72
73
74
75
# File 'lib/metanorma/standoc/ref_queue.rb', line 70

def merge_publishers(base, add)
  ins = base.at("//contributor[last()]") || base.children[-1]
  add.xpath("//contributor[role/@type = 'publisher']").reverse.each do |p|
    ins.next = p
  end
end

#merge_urls(base, add) ⇒ Object



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

def merge_urls(base, add)
  ins = base.at("./uri[last()]") || base.at("./title[last()]")
  add.xpath("./uri").reverse.each do |p|
    ins.next = p
  end
end

#mn_code(code) ⇒ Object



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

def mn_code(code)
  code.sub(/^\(/, "[").sub(/\).*$/, "]")
    .sub(/^dropid\((.+)\)$/, "\\1")
    .sub(/^hidden\((.+)\)$/, "\\1")
    .sub(/^nofetch\((.+)\)$/, "\\1")
    .sub(/^local-file\((.+)\)$/, "\\1")
end

#no_year_generic_ref(code) ⇒ Object

if no year is supplied, interpret as no_year reference



180
181
182
# File 'lib/metanorma/standoc/ref_utility.rb', line 180

def no_year_generic_ref(code)
  /^(BSI|BS)\b/.match?(code)
end

#norm_year(year) ⇒ Object



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

def norm_year(year)
  /^&\#821[12];$/.match(year) and return "--"
  /^\d\d\d\d-\d\d\d\d$/.match(year) and return year
  year&.sub(/(?<=[0-9])-.*$/, "")
end

#plaintxtObject



184
185
186
# File 'lib/metanorma/standoc/ref_utility.rb', line 184

def plaintxt
  { format: "text/plain" }
end

#ref_attributes(match) ⇒ Object



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

def ref_attributes(match)
  code = analyse_ref_code(match[:code])

  { id: match[:anchor], type: "standard",
    suppress_identifier: code[:dropid] || nil }
end

#ref_normalise(ref) ⇒ Object



201
202
203
# File 'lib/metanorma/standoc/ref_utility.rb', line 201

def ref_normalise(ref)
  ref.gsub("&amp;amp;", "&amp;").gsub(%r{^<em>(.*)</em>}, "\\1")
end

#ref_normalise_no_format(ref) ⇒ Object



205
206
207
208
# File 'lib/metanorma/standoc/ref_utility.rb', line 205

def ref_normalise_no_format(ref)
  ref.gsub("&amp;amp;", "&amp;")
    .gsub(">\n", "> \n")
end

#reference(node) ⇒ Object



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

def reference(node)
  refs = node.items.each_with_object([]) do |b, m|
    m << reference1code(b.text, node)
  end
  reference_populate(reference_normalise(refs))
end

#reference1_matches(item) ⇒ Object



209
210
211
212
213
214
# File 'lib/metanorma/standoc/ref.rb', line 209

def reference1_matches(item)
  matched = ISO_REF.match item
  matched2 = ISO_REF_NO_YEAR.match item
  matched3 = ISO_REF_ALL_PARTS.match item
  [matched, matched2, matched3]
end

#reference1code(item, node) ⇒ Object



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

def reference1code(item, node)
  matched, matched2, matched3 = reference1_matches(item)
  if matched3.nil? && matched2.nil? && matched.nil?
    refitemcode(item, node).merge(process: 0)
  elsif !matched.nil? then isorefmatchescode(matched,
                                             item).merge(process: 1)
  elsif !matched2.nil? then isorefmatches2code(matched2,
                                               item).merge(process: 2)
  elsif !matched3.nil? then isorefmatches3code(matched3,
                                               item).merge(process: 3)
  end
end

#reference1out(item, xml) ⇒ Object



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

def reference1out(item, xml)
  item[:ref][:analyse_code] ||= analyse_ref_code(item[:ref][:code])
  case item[:ref][:process]
  when 0 then refitemout(item, xml)
  when 1 then isorefmatchesout(item, xml)
  when 2 then isorefmatches2out(item, xml)
  when 3 then isorefmatches3out(item, xml)
  end
end

#reference_normalise(refs) ⇒ Object



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

def reference_normalise(refs)
  refs.each do |r|
    r[:code] = @c.decode(r[:code])
      .gsub("\u2009\u2014\u2009", " -- ").strip
  end
end

#reference_populate(refs) ⇒ Object



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

def reference_populate(refs)
  ret = reference_queue(*references_fetch(refs))
  joint_prep = joint_entries_prep(ret)
  out = references2xml(ret)
  joint_entries(out, joint_prep).compact.map { |x| to_xml(x) }.join
end

#reference_queue(results, size) ⇒ Object



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

def reference_queue(results, size)
  (1..size).each.with_object([]) do |_, m|
    ref, i, doc = results.pop
    m[i.to_i] = { ref: ref }
    if doc.is_a?(RelatonBib::RequestError)
      @log.add("Bibliography", nil, "Could not retrieve #{ref[:code]}: " \
                                    "no access to online site", severity: 1)
    else m[i.to_i][:doc] = doc end
  end
end

#references2xml(ret) ⇒ Object



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

def references2xml(ret)
  out = ret.map do |b|
    b.nil? ? nil : noko { |xml| reference1out(b, xml) }.join
  end
  out.map { |x| x.nil? ? nil : Nokogiri::XML(x).root }
end

#references_fetch(refs) ⇒ Object



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

def references_fetch(refs)
  i = 0
  ret = refs.each_with_object(Queue.new) do |ref, res|
    i = fetch_ref_async(ref.merge(ord: i), i, res)
  end
  [ret, i]
end

#refitem1code(_item, match) ⇒ Object



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

def refitem1code(_item, match)
  code = analyse_ref_code(match[:code])
  ((code[:id] && code[:numeric]) || code[:nofetch]) and
    return { code: nil, match: match, analyse_code: code,
             hidden: code[:hidden] }
  { code: code[:id], analyse_code: code, localfile: code[:localfile],
    year: (m = refitem1yr(code[:id])) ? m[:year] : nil,
    title: match[:text], match: match, hidden: code[:hidden],
    usrlbl: match[:usrlbl] || code[:usrlabel], lang: @lang || :all }
end

#refitem1yr(code) ⇒ Object



168
169
170
171
172
173
# File 'lib/metanorma/standoc/ref.rb', line 168

def refitem1yr(code)
  yr_match = /[:-](?<year>(?:19|20)[0-9][0-9])$/.match(code)
  /[:-](?:19|20)[0-9][0-9].*?[:-](?:19|20)[0-9][0-9]$/.match(code) and
    yr_match = nil
  yr_match
end

#refitem_render(xml, match, code) ⇒ Object



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

def refitem_render(xml, match, code)
  xml.bibitem **attr_code(
    id: match[:anchor], suppress_identifier: code[:dropid],
    hidden: code[:hidden]
  ) do |t|
    refitem_render_formattedref(t, match[:text])
    yr_match = refitem1yr(code[:id])
    refitem_render1(match, code, t)
    /^\d+$|^\(.+\)$/.match?(code[:id]) or
      docnumber(t, code[:id]&.sub(/[:-](19|20)[0-9][0-9]$/, ""))
    conditional_date(t, yr_match || match, false)
  end
end

#refitem_render1(match, code, bib) ⇒ Object



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

def refitem_render1(match, code, bib)
  if code[:type] == "path"
    bib.uri code[:key].sub(/\.[a-zA-Z0-9]+$/, ""), type: "URI"
    bib.uri code[:key].sub(/\.[a-zA-Z0-9]+$/, ""), type: "citation"
  end
  # code[:id].sub!(/[:-](19|20)[0-9][0-9]$/, "")
  docid(bib, match[:usrlbl]) if match[:usrlbl]
  docid(bib, code[:usrlabel]) if code[:usrlabel]
  code[:id] and
    docid(bib, /^\d+$/.match?(code[:id]) ? "[#{code[:id]}]" : code[:id])
  code[:type] == "repo" and
    bib.docidentifier code[:key], type: "repository"
end

#refitem_render_formattedref(bibitem, title) ⇒ Object



141
142
143
144
145
146
# File 'lib/metanorma/standoc/ref.rb', line 141

def refitem_render_formattedref(bibitem, title)
  (title.nil? || title.empty?) and title = @i18n.no_information_available
  bibitem.formattedref format: "application/x-isodoc+xml" do |i|
    i << ref_normalise_no_format(title)
  end
end

#refitemcode(item, node) ⇒ Object

TODO: alternative where only title is available



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

def refitemcode(item, node)
  m = NON_ISO_REF.match(item) and return refitem1code(item, m).compact
  m = NON_ISO_REF1.match(item) and return refitem1code(item, m).compact
  @log.add("AsciiDoc Input", node, "#{MALFORMED_REF}: #{item}",
           severity: 1)
  {}
end

#refitemout(item, xml) ⇒ Object



175
176
177
178
179
180
# File 'lib/metanorma/standoc/ref.rb', line 175

def refitemout(item, xml)
  item[:ref][:match].nil? and return nil
  item[:doc] or return refitem_render(xml, item[:ref][:match],
                                      item[:ref][:analyse_code])
  use_retrieved_relaton(item, xml)
end

#set_date_range(date, text) ⇒ Object



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

def set_date_range(date, text)
  matched = /^(?<from>[0-9]+)(?:-+(?<to>[0-9]+))?$/.match text
  return unless matched[:from]

  if matched[:to]
    date.from matched[:from]
    date.to matched[:to]
  else
    date.on matched[:from]
  end
end

#skip_docidObject



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

def skip_docid
  <<~XPATH.strip.freeze
    @type = 'DOI' or @type = 'doi' or @type = 'ISSN' or @type = 'issn' or @type = 'ISBN' or @type = 'isbn' or starts-with(@type, 'ISSN.') or starts-with(@type, 'ISBN.') or starts-with(@type, 'issn.') or starts-with(@type, 'isbn.')
  XPATH
end

#smart_render_xml(xml, code, opts) ⇒ Object



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

def smart_render_xml(xml, code, opts)
  xml.respond_to? :to_xml or return nil
  xml = Nokogiri::XML(xml.to_xml(lang: opts[:lang]))
  emend_biblio(xml, code, opts[:title], opts[:usrlbl])
  xml.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
  xml.traverse do |n|
    n.text? and n.replace(Metanorma::Utils::smartformat(n.text))
  end
  xml.to_xml.sub(/<\?[^>]+>/, "")
end

#supply_ref_prefix(ret) ⇒ Object



145
146
147
# File 'lib/metanorma/standoc/ref_queue.rb', line 145

def supply_ref_prefix(ret)
  ret
end

#unfetchable_ref_code?(ref) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
160
161
# File 'lib/metanorma/standoc/ref_queue.rb', line 157

def unfetchable_ref_code?(ref)
  ref[:code].nil? || ref[:code].empty? || ref[:no_year] ||
    /^\(.+\)$/.match?(ref[:code]) ||
    (@bibdb.nil? && !ref[:localfile])
end

#use_my_anchor(ref, id, opt) ⇒ Object



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

def use_my_anchor(ref, id, opt)
  ref.parent.elements.last["id"] = id
  opt[:hidden] and ref.parent.elements.last["hidden"] = opt[:hidden]
  opt[:dropid] and
    ref.parent.elements.last["suppress_identifier"] = opt[:dropid]
  ref
end

#use_retrieved_relaton(item, xml) ⇒ Object



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

def use_retrieved_relaton(item, xml)
  xml.parent.add_child(smart_render_xml(item[:doc], item[:ref][:code],
                                        item[:ref]))
  use_my_anchor(xml, item[:ref][:match][:anchor],
                hidden: item.dig(:ref, :analyse_code, :hidden),
                dropid: item.dig(:ref, :analyse_code, :dropid))
end