Module: Asciidoctor::ISO::Lists

Included in:
Converter
Defined in:
lib/asciidoctor/iso/ref.rb,
lib/asciidoctor/iso/lists.rb

Constant Summary collapse

ISO_REF =
%r{^<ref\sid="(?<anchor>[^"]+)">
\[(?<code>(ISO|IEC)[^0-9]*\s[0-9-]+|IEV)
(:(?<year>[0-9][0-9-]+))?\]</ref>,?\s
(?<text>.*)$}xm
ISO_REF_NO_YEAR =
%r{^<ref\sid="(?<anchor>[^"]+)">
\[(?<code>(ISO|IEC)[^0-9]*\s[0-9-]+):--\]</ref>,?\s?
<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>,?\s?(?<text>.*)$}xm
ISO_REF_ALL_PARTS =
%r{^<ref\sid="(?<anchor>[^"]+)">
\[(?<code>(ISO|IEC)[^0-9]*\s[0-9]+)(:(?<year>[0-9][0-9-]+))?\s
\(all\sparts\)\]</ref>,?\s
(?<text>.*)$}xm
NON_ISO_REF =
%r{^<ref\sid="(?<anchor>[^"]+)">
\[(?<code>[^\]]+)\]</ref>,?\s
(?<text>.*)$}xm

Instance Method Summary collapse

Instance Method Details

#bibliocache_name(global) ⇒ Object



299
300
301
302
# File 'lib/asciidoctor/iso/ref.rb', line 299

def bibliocache_name(global)
  global ?  "#{Dir.home}/.relaton-bib.json" :
    "#{@filename}.relaton.json"
end

#colist(node) ⇒ Object



77
78
79
80
81
82
83
84
85
# File 'lib/asciidoctor/iso/lists.rb', line 77

def colist(node)
  noko do |xml|
    node.items.each_with_index do |item, i|
      xml.annotation **attr_code(id: i + 1) do |xml_li|
        xml_li.p { |p| p << item.text }
      end
    end
  end.join("\n")
end

#dd(dd, xml_dl) ⇒ Object



55
56
57
58
59
60
61
62
63
64
# File 'lib/asciidoctor/iso/lists.rb', line 55

def dd(dd, xml_dl)
  if dd.nil?
    xml_dl.dd
    return
  end
  xml_dl.dd do |xml_dd|
    xml_dd.p { |t| t << dd.text } if dd.text?
    xml_dd << dd.content if dd.blocks?
  end
end

#dlist(node) ⇒ Object



66
67
68
69
70
71
72
73
74
75
# File 'lib/asciidoctor/iso/lists.rb', line 66

def dlist(node)
  noko do |xml|
    xml.dl **id_attr(node) do |xml_dl|
      node.items.each do |terms, dd|
        dt(terms, xml_dl)
        dd(dd, xml_dl)
      end
    end
  end.join("\n")
end

#dt(terms, xml_dl) ⇒ Object



46
47
48
49
50
51
52
53
# File 'lib/asciidoctor/iso/lists.rb', line 46

def dt(terms, xml_dl)
  terms.each_with_index do |dt, idx|
    xml_dl.dt { |xml_dt| xml_dt << dt.text }
    if idx < terms.size - 1
      xml_dl.dd
    end
  end
end

#fetch_pages(s, n) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/asciidoctor/iso/ref.rb', line 101

def fetch_pages(s, n)
  workers = WorkersPool.new n
  workers.worker { |w| { i: w[:i], hit: w[:hit].fetch } }
  s.each_with_index { |hit, i| workers << { i: i, hit: hit } }
  workers.end
  workers.result.sort { |x, y| x[:i] <=> y[:i] }.map { |x| x[:hit] }
end

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



214
215
216
217
218
219
220
221
# File 'lib/asciidoctor/iso/ref.rb', line 214

def fetch_ref(xml, code, year, **opts)
  hit = fetch_ref1(code, year, opts)
  return nil if hit.nil?
  xml.parent.add_child(hit)
  xml
rescue Algolia::AlgoliaProtocolError
  nil # Render reference without an Internet connection.
end

#fetch_ref1(code, year, opts) ⇒ Object



204
205
206
207
208
209
210
211
212
# File 'lib/asciidoctor/iso/ref.rb', line 204

def fetch_ref1(code, year, opts)
  id = iso_id(code, year, opts[:all_parts])
  return nil if @bibliodb.nil? # signals we will not be using isobib
  @bibliodb[id] = isobib_get(code, year, opts) unless @bibliodb[id]
  @local_bibliodb[id] = @bibliodb[id] if !@local_bibliodb.nil? &&
    !@local_bibliodb[id]
  return @local_bibliodb[id] unless @local_bibliodb.nil?
  @bibliodb[id]
end

#fetch_ref_err(code, year, missed_years) ⇒ Object

— ISOBIB



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/asciidoctor/iso/ref.rb', line 84

def fetch_ref_err(code, year, missed_years)
  id = year ? "#{code}:#{year}" : code
  warn "WARNING: no match found on the ISO website for #{id}. "\
    "The code must be exactly like it is on the website."
  warn "(There was no match for #{year}, though there were matches "\
    "found for #{missed_years.join(', ')}.)" unless missed_years.empty?
  if /\d-\d/.match? code
    warn "The provided document part may not exist, or the document "\
      "may no longer be published in parts."
  else
    warn "If you wanted to cite all document parts for the reference, "\
      "use \"#{code} (all parts)\".\nIf the document is not a standard, "\
      "use its document type abbreviation (TS, TR, PAS, Guide)."
  end
  nil
end

#ievObject



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/asciidoctor/iso/ref.rb', line 121

def iev
  Nokogiri::XML.fragment(<<~"END")
    <bibitem type="international-standard" id="IEV">
  <title format="text/plain" language="en" script="Latn">Electropedia: 
  The World's Online Electrotechnical Vocabulary</title>
  <source type="src">http://www.electropedia.org</source>
  <docidentifier>IEV</docidentifier>
  <date type="published"> <on>#{Date.today.year}</on> </date>
  <contributor>
    <role type="publisher"/>
    <organization>
<name>International Electrotechnical Commission</name>
<abbreviation>IEC</abbreviation>
<uri>www.iec.ch</uri>
    </organization>
  </contributor>
  <language>en</language> <language>fr</language>
  <script>Latn</script>
  <copyright>
    <from>#{Date.today.year}</from>
    <owner>
<organization>
<name>International Electrotechnical Commission</name>
<abbreviation>IEC</abbreviation>
<uri>www.iec.ch</uri>
</organization>
    </owner>
  </copyright>
  <relation type="updates">
    <bibitem>
<formattedref>IEC 60050</formattedref>
    </bibitem>
  </relation>
</bibitem>
  END
end

#iso_id(code, year, all_parts) ⇒ Object

— ISOBIB



197
198
199
200
201
202
# File 'lib/asciidoctor/iso/ref.rb', line 197

def iso_id(code, year, all_parts)
  ret = code
  ret += ":#{year}" if year
  ret += " (all parts)" if all_parts
  ret
end

#iso_publisher(t, code) ⇒ Object



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

def iso_publisher(t, code)
  code.sub(/ .*$/, "").split(/\//).each do |abbrev|
    t.contributor do |c|
      c.role **{ type: "publisher" }
      c.organization do |org|
        organization(org, abbrev)
      end
    end
  end
end

#isobib_get(code, year, opts) ⇒ Object



186
187
188
189
190
191
192
193
# File 'lib/asciidoctor/iso/ref.rb', line 186

def isobib_get(code, year, opts)
  code += "-1" if opts[:all_parts]
  ret = isobib_get1(code, year, opts)
  return nil if ret.nil?
  ret.to_most_recent_reference if !year
  ret.to_all_parts if opts[:all_parts]
  ret.to_xml
end

#isobib_get1(code, year, opts) ⇒ Object



178
179
180
181
182
183
184
# File 'lib/asciidoctor/iso/ref.rb', line 178

def isobib_get1(code, year, opts)
  return iev if code.casecmp? "IEV"
  result = isobib_search_filter(code) or return nil
  ret = isobib_results_filter(result, year)
  return ret[:ret] if ret[:ret]
  fetch_ref_err(code, year, ret[:years])
end

#isobib_results_filter(result, year) ⇒ Object

Sort through the results from Isobib, fetching them three at a time, and return the first result that matches the code, matches the year (if provided), and which # has a title (amendments do not). Only expects the first page of results to be populated. Does not match corrigenda etc (e.g. ISO 3166-1:2006/Cor 1:2007) If no match, returns any years which caused mismatch, for error reporting



164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/asciidoctor/iso/ref.rb', line 164

def isobib_results_filter(result, year)
  missed_years = []
  result.each_slice(3) do |s| # ISO website only allows 3 connections
    fetch_pages(s, 3).each_with_index do |r, i|
      return { ret: r } if !year
      r.dates.select { |d| d.type == "published" }.each do |d|
        return { ret: r } if year.to_i == d.on.year
        missed_years << d.on.year
      end
    end
  end
  { years: missed_years }
end

#isobib_search_filter(code) ⇒ Object



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/asciidoctor/iso/ref.rb', line 109

def isobib_search_filter(code)
docidrx = %r{^(ISO|IEC)[^0-9]*\s[0-9-]+}
corrigrx = %r{^(ISO|IEC)[^0-9]*\s[0-9-]+:[0-9]+/}
  warn "fetching #{code}..."
  result = Isobib::IsoBibliography.search(code)
  result.first.select do |i| 
    i.hit["title"] &&
    i.hit["title"].match(docidrx).to_s == code &&
      !corrigrx.match?(i.hit["title"])
  end 
end

#isorefmatches(xml, m) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/asciidoctor/iso/ref.rb', line 42

def isorefmatches(xml, m)
  ref = fetch_ref xml, m[:code], m[:year]
  return use_my_anchor(ref, m[:anchor]) if ref
  xml.bibitem **attr_code(ref_attributes(m)) do |t|
    t.title(**plaintxt) { |i| i << ref_normalise(m[:text]) }
    t.docidentifier m[:code]
    m[:year] and t.date **{ type: "published" } do |d|
      set_date_range(d, m[:year])
    end
    iso_publisher(t, m[:code])
  end
end

#isorefmatches2(xml, m) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/asciidoctor/iso/ref.rb', line 55

def isorefmatches2(xml, m)
  ref = fetch_ref xml, m[:code], nil, no_year: true, note: m[:fn]
  return use_my_anchor(ref, m[:anchor]) if ref
  xml.bibitem **attr_code(ref_attributes(m)) do |t|
    t.title(**plaintxt) { |i| i << ref_normalise(m[:text]) }
    t.docidentifier m[:code]
    t.date **{ type: "published" } do |d|
      d.on "--"
    end
    iso_publisher(t, m[:code])
    t.note(**plaintxt) { |p| p << "ISO DATE: #{m[:fn]}" }
  end
end

#isorefmatches3(xml, m) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/asciidoctor/iso/ref.rb', line 69

def isorefmatches3(xml, m)
  ref = fetch_ref xml, m[:code], m[:year], all_parts: true
  return use_my_anchor(ref, m[:anchor]) if ref
  xml.bibitem(**attr_code(ref_attributes(m))) do |t|
    t.title(**plaintxt) { |i| i << ref_normalise(m[:text]) }
    t.docidentifier "#{m[:code]}"
    if m.named_captures.has_key?("year")
      t.date(**{ type: "published" }) { |d| set_date_range(d, m[:year]) }
    end
    iso_publisher(t, m[:code])
    t.allParts "true"
  end
end

#li(xml_ul, item) ⇒ Object



7
8
9
10
11
12
13
14
15
16
# File 'lib/asciidoctor/iso/lists.rb', line 7

def li(xml_ul, item)
  xml_ul.li do |xml_li|
    if item.blocks?
      xml_li.p(**id_attr(item)) { |t| t << item.text }
      xml_li << item.content
    else
      xml_li.p(**id_attr(item)) { |p| p << item.text }
    end
  end
end

#olist(node) ⇒ Object



37
38
39
40
41
42
43
44
# File 'lib/asciidoctor/iso/lists.rb', line 37

def olist(node)
  noko do |xml|
    xml.ol **attr_code(id: Utils::anchor_or_uuid(node),
                       type: olist_style(node.style)) do |xml_ol|
      node.items.each { |item| li(xml_ol, item) }
    end
  end.join("\n")
end

#olist_style(style) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/asciidoctor/iso/lists.rb', line 29

def olist_style(style)
  return "alphabet" if style == "loweralpha"
  return "roman" if style == "lowerroman"
  return "roman_upper" if style == "upperroman"
  return "alphabet_upper" if style == "upperalpha"
  style
end

#open_cache_biblio(node, global) ⇒ Object

if returns nil, then biblio caching is disabled, and so is use of isobib



305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/asciidoctor/iso/ref.rb', line 305

def open_cache_biblio(node, global)
  # return nil # disabling for now
  return nil if node.attr("no-isobib")
  return {} if @no_isobib_cache
  filename = bibliocache_name(global)
  system("rm -f #{filename}") if node.attr("flush-caches")
  biblio = {}
  if Pathname.new(filename).file?
    File.open(filename, "r") do |f|
      biblio = JSON.parse(f.read)
    end
  end
  biblio
end

#plaintxtObject



18
19
20
# File 'lib/asciidoctor/iso/ref.rb', line 18

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

#ref_attributes(m) ⇒ Object



22
23
24
# File 'lib/asciidoctor/iso/ref.rb', line 22

def ref_attributes(m)
  { id: m[:anchor], type: "standard" }
end

#ref_normalise(ref) ⇒ Object



237
238
239
240
241
242
# File 'lib/asciidoctor/iso/ref.rb', line 237

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

#ref_normalise_no_format(ref) ⇒ Object



244
245
246
247
248
# File 'lib/asciidoctor/iso/ref.rb', line 244

def ref_normalise_no_format(ref)
  ref.
    # gsub(/&#8201;&#8212;&#8201;/, " -- ").
    gsub(/&amp;amp;/, "&amp;")
end

#reference(node) ⇒ Object



291
292
293
294
295
296
297
# File 'lib/asciidoctor/iso/ref.rb', line 291

def reference(node)
  noko do |xml|
    node.items.each do |item|
      reference1(node, item.text, xml)
    end
  end.join("\n")
end

#reference1(node, item, xml) ⇒ Object

Parameters:

  • node (Asciidoctor::List)
  • item (String)
  • xml (Nokogiri::XML::Builder)


280
281
282
283
284
285
286
287
288
289
# File 'lib/asciidoctor/iso/ref.rb', line 280

def reference1(node, item, xml)
  matched, matched2, matched3 = reference1_matches(item)
  if matched3.nil? && matched2.nil? && matched.nil?
    refitem(xml, item, node)
    # elsif fetch_ref(matched3 || matched2 || matched, xml)
  elsif !matched.nil? then isorefmatches(xml, matched)
  elsif !matched2.nil? then isorefmatches2(xml, matched2)
  elsif !matched3.nil? then isorefmatches3(xml, matched3)
  end
end

#reference1_matches(item) ⇒ Array<MatchData>

Parameters:

  • item (String)

Returns:

  • (Array<MatchData>)


270
271
272
273
274
275
# File 'lib/asciidoctor/iso/ref.rb', line 270

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

#refitem(xml, item, node) ⇒ Object

TODO: alternative where only title is available



224
225
226
227
228
229
230
231
232
233
234
235
# File 'lib/asciidoctor/iso/ref.rb', line 224

def refitem(xml, item, node)
  unless m = NON_ISO_REF.match(item)
    Utils::warning(node, "no anchor on reference", item)
    return
  end
  xml.bibitem **attr_code(id: m[:anchor]) do |t|
    t.formattedref **{ format: "application/x-isodoc+xml" } do |i|
      i << ref_normalise_no_format(m[:text])
    end
    t.docidentifier(/^\d+$/.match?(m[:code]) ? "[#{m[:code]}]" : m[:code])
  end
end

#save_cache_biblio(biblio, global) ⇒ Object



320
321
322
323
324
325
326
# File 'lib/asciidoctor/iso/ref.rb', line 320

def save_cache_biblio(biblio, global)
  return if biblio.nil? || @no_isobib_cache
  filename = bibliocache_name(global)
  File.open(filename, "w") do |b|
    b << biblio.to_json
  end
end

#set_date_range(date, text) ⇒ Object



26
27
28
29
30
31
32
33
34
35
# File 'lib/asciidoctor/iso/ref.rb', line 26

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

#ulist(node) ⇒ Object



18
19
20
21
22
23
24
25
26
27
# File 'lib/asciidoctor/iso/lists.rb', line 18

def ulist(node)
  return reference(node) if in_norm_ref? || in_biblio?
  noko do |xml|
    xml.ul **id_attr(node) do |xml_ul|
      node.items.each do |item|
        li(xml_ul, item)
      end
    end
  end.join("\n")
end

#use_my_anchor(ref, id) ⇒ Object



37
38
39
40
# File 'lib/asciidoctor/iso/ref.rb', line 37

def use_my_anchor(ref, id)
  ref.parent.children.last["id"] = id
  ref
end