metanorma-ietf 2.2.10 → 2.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,5 @@
1
+ require "open-uri"
2
+
1
3
  module Asciidoctor
2
4
  module Ietf
3
5
  class Converter < ::Asciidoctor::Standoc::Converter
@@ -10,15 +12,18 @@ module Asciidoctor
10
12
  def image_validate(doc)
11
13
  doc.xpath("//image").each do |i|
12
14
  next if i["mimetype"] == "image/svg+xml"
15
+
13
16
  @log.add("MIME", i, "image #{i['src'][0, 40]} is not SVG!")
14
17
  end
15
18
  end
16
19
 
17
20
  def workgroup_validate(doc)
18
21
  return if @workgroups.empty?
22
+
19
23
  doc.xpath("//bibdata/ext/editorialgroup/workgroup").each do |wg|
20
24
  wg_norm = wg.text.sub(/ (Working|Research) Group$/, "")
21
25
  next if @workgroups.include?(wg_norm)
26
+
22
27
  @log.add("Document Attributes", nil, "IETF: unrecognised working group #{wg.text}")
23
28
  end
24
29
  end
@@ -29,25 +34,29 @@ module Asciidoctor
29
34
  File.join(File.dirname(__FILE__), "ietf.rng"))
30
35
  end
31
36
 
37
+ def wgcache_name
38
+ "#{Dir.home}/.metanorma-ietf-workgroup-cache.json"
39
+ end
40
+
32
41
  def open_wg_cache(node)
33
- wgcache_name = "#{Dir.home}/.metanorma-ietf-workgroup-cache.json"
34
- node.attr("flush-caches") == "true" and FileUtils.rm wgcache_name, :force => true
42
+ node.attr("flush-caches") == "true" and
43
+ FileUtils.rm wgcache_name, force: true
35
44
  wg = []
36
45
  if Pathname.new(wgcache_name).file?
37
46
  begin
38
47
  File.open(wgcache_name, "r") { |f| wg = JSON.parse(f.read) }
39
48
  rescue Exception => e
40
- STDERR.puts "Cache #{wgcache_name} is invalid, drop it"
49
+ warn "Cache #{wgcache_name} is invalid, drop it"
41
50
  end
42
51
  end
43
52
  [wg, wgcache_name]
44
53
  end
45
54
 
46
- def cache_workgroup_ietf(wg, b)
47
- STDERR.puts "Reading workgroups from https://tools.ietf.org/wg/..."
48
- Kernel.open("https://tools.ietf.org/wg/") do |f|
49
- f.each_line do |line|
50
- line.scan(%r{<td width="50%" style='padding: 0 1ex'>([^<]+)</td>}) do |w|
55
+ def cache_workgroup_ietf(wg, _b)
56
+ warn "Reading workgroups from https://tools.ietf.org/wg/..."
57
+ URI.open("https://tools.ietf.org/wg/") do |f|
58
+ f.each_line do |l|
59
+ l.scan(%r{<td width="50%" style='padding: 0 1ex'>([^<]+)</td>}) do |w|
51
60
  wg << w[0].gsub(/\s+$/, "").gsub(/ Working Group$/, "")
52
61
  end
53
62
  end
@@ -55,11 +64,11 @@ module Asciidoctor
55
64
  wg
56
65
  end
57
66
 
58
- def cache_workgroup_irtf(wg, b)
59
- STDERR.puts "Reading workgroups from https://irtf.org/groups..."
60
- Kernel.open("https://irtf.org/groups", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE) do |f|
61
- f.each_line do |line|
62
- line.scan(%r{<a title="([^"]+) Research Group"[^>]+>([^<]+)<}) do |w|
67
+ def cache_workgroup_irtf(wg, _b)
68
+ warn "Reading workgroups from https://irtf.org/groups..."
69
+ URI.open("https://irtf.org/groups", ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE) do |f|
70
+ f.each_line do |l|
71
+ l.scan(%r{<a title="([^"]+) Research Group"[^>]+>([^<]+)<}) do |w|
63
72
  wg << w[0].gsub(/\s+$/, "")
64
73
  wg << w[1].gsub(/\s+$/, "") # abbrev
65
74
  end
@@ -43,7 +43,7 @@ module IsoDoc::Ietf
43
43
  end
44
44
 
45
45
  def ol_attrs(node)
46
- { anchor: node["id"],
46
+ { anchor: node["id"],
47
47
  spacing: node["spacing"],
48
48
  type: ol_style(node["type"]),
49
49
  group: node["group"],
@@ -73,7 +73,9 @@ module IsoDoc::Ietf
73
73
 
74
74
  def note_label(node)
75
75
  n = @xrefs.get[node["id"]]
76
- return l10n("#{@i18n.note}: ") if n.nil? || n[:label].nil? || n[:label].empty?
76
+ return l10n("#{@i18n.note}: ") if n.nil? || n[:label].nil? ||
77
+ n[:label].empty?
78
+
77
79
  l10n("#{@i18n.note} #{n[:label]}: ")
78
80
  end
79
81
 
@@ -98,7 +100,7 @@ module IsoDoc::Ietf
98
100
  def example_label(node, div, name)
99
101
  n = @xrefs.get[node["id"]]
100
102
  div.t **attr_code(anchor: node["id"], keepWithNext: "true") do |p|
101
- lbl = (n.nil? || n[:label].nil? || n[:label].empty?) ? @i18n.example :
103
+ lbl = n.nil? || n[:label].nil? || n[:label].empty? ? @i18n.example :
102
104
  l10n("#{@i18n.example} #{n[:label]}")
103
105
  p << lbl
104
106
  name and !lbl.nil? and p << ": "
@@ -107,15 +109,11 @@ module IsoDoc::Ietf
107
109
  end
108
110
 
109
111
  def sourcecode_parse(node, out)
110
- out.figure **attr_code(anchor: node["id"]) do |div|
111
- name = node&.at(ns("./name"))&.remove and div.name do |n|
112
- name.children.each { |nn| parse(nn, n) }
113
- end
114
- div.sourcecode **attr_code(type: node["lang"], name: node["filename"],
115
- markers: node["markers"],
116
- src: node["src"]) do |s|
117
- node.children.each { |x| parse(x, s) unless x.name == "name" }
118
- end
112
+ out.sourcecode **attr_code(
113
+ anchor: node["id"], type: node["lang"], name: node["filename"],
114
+ markers: node["markers"], src: node["src"]
115
+ ) do |s|
116
+ node.children.each { |x| parse(x, s) unless x.name == "name" }
119
117
  end
120
118
  end
121
119
 
@@ -139,6 +137,7 @@ module IsoDoc::Ietf
139
137
 
140
138
  def formula_where(dl, out)
141
139
  return unless dl
140
+
142
141
  out.t { |p| p << @i18n.where }
143
142
  parse(dl, out)
144
143
  end
@@ -146,7 +145,7 @@ module IsoDoc::Ietf
146
145
  def formula_parse1(node, out)
147
146
  out.t **attr_code(anchor: node["id"]) do |p|
148
147
  parse(node.at(ns("./stem")), p)
149
- lbl = @xrefs.anchor(node['id'], :label, false)
148
+ lbl = @xrefs.anchor(node["id"], :label, false)
150
149
  lbl.nil? or
151
150
  p << " (#{lbl})"
152
151
  end
@@ -157,6 +156,7 @@ module IsoDoc::Ietf
157
156
  formula_where(node.at(ns("./dl")), out)
158
157
  node.children.each do |n|
159
158
  next if %w(stem dl).include? n.name
159
+
160
160
  parse(n, out)
161
161
  end
162
162
  end
@@ -176,7 +176,7 @@ module IsoDoc::Ietf
176
176
  end
177
177
 
178
178
  def admonition_name_parse(_node, div, name)
179
- div.t **{keepWithNext: "true" } do |p|
179
+ div.t **{ keepWithNext: "true" } do |p|
180
180
  name.children.each { |n| parse(n, p) }
181
181
  end
182
182
  end
@@ -200,8 +200,9 @@ module IsoDoc::Ietf
200
200
  end
201
201
  end
202
202
 
203
- def figure_name_parse(node, div, name)
203
+ def figure_name_parse(_node, div, name)
204
204
  return if name.nil?
205
+
205
206
  div.name do |n|
206
207
  name.children.each { |n| parse(n, div) }
207
208
  end
@@ -214,6 +215,7 @@ module IsoDoc::Ietf
214
215
  def figure_parse(node, out)
215
216
  return pseudocode_parse(node, out) if node["class"] == "pseudocode" ||
216
217
  node["type"] == "pseudocode"
218
+
217
219
  @in_figure = true
218
220
  out.figure **attr_code(anchor: node["id"]) do |div|
219
221
  figure_name_parse(node, div, node.at(ns("./name")))
@@ -15,14 +15,14 @@ module IsoDoc::Ietf
15
15
  end
16
16
 
17
17
  # TODO: insert <u>
18
-
18
+
19
19
  def front_cleanup(xmldoc)
20
- xmldoc.xpath("//title").each { |s| s.children = s.text }
21
- xmldoc.xpath("//reference/front[not(author)]").each do |f|
22
- insert = f.at("./seriesInfo[last()]") || f.at("./title")
23
- insert.next = "<author surname='Unknown'/>"
24
- end
20
+ xmldoc.xpath("//title").each { |s| s.children = s.text }
21
+ xmldoc.xpath("//reference/front[not(author)]").each do |f|
22
+ insert = f.at("./seriesInfo[last()]") || f.at("./title")
23
+ insert.next = "<author surname='Unknown'/>"
25
24
  end
25
+ end
26
26
 
27
27
  def table_footnote_cleanup(docxml)
28
28
  docxml.xpath("//table[descendant::fn]").each do |t|
@@ -48,15 +48,28 @@ module IsoDoc::Ietf
48
48
  figure_postamble(docxml)
49
49
  figure_unnest(docxml)
50
50
  figure_footnote_cleanup(docxml)
51
+ figure_data_uri(docxml)
52
+ end
53
+
54
+ def figure_data_uri(docxml)
55
+ docxml.xpath("//artwork").each do |a|
56
+ next unless %r{^data:image/svg\+xml;base64}.match?(a["src"])
57
+
58
+ f = Metanorma::Utils::save_dataimage(a["src"])
59
+ a.delete("src")
60
+ a.children = File.read(f).sub(%r{<\?.+\?>}, "")
61
+ end
51
62
  end
52
63
 
53
64
  def figure_unnest(docxml)
54
65
  docxml.xpath("//figure[descendant::figure]").each do |f|
55
66
  insert = f
56
67
  f.xpath(".//figure").each do |a|
68
+ title = f.at("./name") and a.children.first.previous = title.remove
57
69
  insert.next = a.remove
58
70
  insert = insert.next_element
59
71
  end
72
+ f.remove
60
73
  end
61
74
  end
62
75
 
@@ -126,10 +139,12 @@ module IsoDoc::Ietf
126
139
 
127
140
  def make_endnotes(docxml)
128
141
  return unless docxml.at("//fn")
129
- endnotes = docxml.at("//back") or
130
- docxml << "<back/>" and endnotes = docxml.at("//back")
142
+
143
+ unless endnotes = docxml.at("//back")
144
+ docxml << "<back/>" and endnotes = docxml.at("//back")
145
+ end
131
146
  endnotes << "<section><name>Endnotes</name></section>"
132
- endnotes = docxml.at("//back/section[last()]")
147
+ docxml.at("//back/section[last()]")
133
148
  end
134
149
 
135
150
  def image_cleanup(docxml)
@@ -138,7 +153,7 @@ module IsoDoc::Ietf
138
153
  t.xpath(".//artwork").each_with_index do |a, i|
139
154
  insert.next = a.dup
140
155
  insert = insert.next
141
- a.replace("[IMAGE #{i+1}]")
156
+ a.replace("[IMAGE #{i + 1}]")
142
157
  end
143
158
  end
144
159
  end
@@ -146,20 +161,22 @@ module IsoDoc::Ietf
146
161
  # for markup in pseudocode
147
162
  def sourcecode_cleanup(docxml)
148
163
  docxml.xpath("//sourcecode").each do |s|
149
- s.children = s.children.to_xml.gsub(%r{<br/>\n}, "\n").
150
- gsub(%r{\s+(<t[ >])}, "\\1").gsub(%r{</t>\s+}, "</t>")
164
+ s.children = s.children.to_xml.gsub(%r{<br/>\n}, "\n")
165
+ .gsub(%r{\s+(<t[ >])}, "\\1").gsub(%r{</t>\s+}, "</t>")
151
166
  sourcecode_remove_markup(s)
152
- text = HTMLEntities.new.decode(s.children.to_xml.sub(/\A\n+/, ""))
153
- s.children = "<![CDATA[#{text}]]>"
167
+ s.children = "<![CDATA[#{HTMLEntities.new.decode(s
168
+ .children.to_xml.sub(/\A\n+/, ''))}]]>"
154
169
  end
155
170
  end
156
171
 
157
- def sourcecode_remove_markup(s)
158
- s.traverse do |n|
172
+ def sourcecode_remove_markup(node)
173
+ node.traverse do |n|
159
174
  next if n.text?
160
175
  next if %w(name callout annotation note sourcecode).include? n.name
161
- if n.name == "br" then n.replace("\n")
162
- elsif n.name == "t" then n.replace("\n\n#{n.children}")
176
+
177
+ case n.name
178
+ when "br" then n.replace("\n")
179
+ when "t" then n.replace("\n\n#{n.children}")
163
180
  else
164
181
  n.replace(n.children)
165
182
  end
@@ -169,6 +186,7 @@ module IsoDoc::Ietf
169
186
  def annotation_cleanup(docxml)
170
187
  docxml.xpath("//reference").each do |r|
171
188
  next unless r&.next_element&.name == "aside"
189
+
172
190
  aside = r.next_element
173
191
  aside.name = "annotation"
174
192
  aside.traverse do |n|
@@ -176,7 +194,7 @@ module IsoDoc::Ietf
176
194
  end
177
195
  r << aside
178
196
  end
179
- docxml.xpath("//references/aside").each { |r| r.remove }
197
+ docxml.xpath("//references/aside").each(&:remove)
180
198
  end
181
199
 
182
200
  def deflist_cleanup(docxml)
@@ -203,9 +221,7 @@ module IsoDoc::Ietf
203
221
  end
204
222
 
205
223
  def bookmark_cleanup(docxml)
206
- docxml.xpath("//bookmark").each do |b|
207
- b.remove
208
- end
224
+ docxml.xpath("//bookmark").each(&:remove)
209
225
  end
210
226
 
211
227
  def aside_cleanup(docxml)
@@ -25,10 +25,11 @@ module IsoDoc::Ietf
25
25
 
26
26
  def output_if_translit(text)
27
27
  return nil if text.nil?
28
+
28
29
  text.transliterate != text ? text.transliterate : nil
29
30
  end
30
31
 
31
- def title(isoxml, front)
32
+ def title(_isoxml, front)
32
33
  title = @meta.get[:doctitle] or return
33
34
  front.title title, **attr_code(abbrev: @meta.get[:docabbrev],
34
35
  ascii: (@meta.get[:docascii] ||
@@ -49,18 +50,20 @@ module IsoDoc::Ietf
49
50
  end
50
51
 
51
52
  def rfc_seriesinfo(isoxml, front)
52
- front.seriesInfo **seriesinfo_attr(isoxml).merge({name: "RFC",
53
- asciiName: "RFC"})
53
+ front.seriesInfo **seriesinfo_attr(isoxml).merge({ name: "RFC",
54
+ asciiName: "RFC" })
54
55
  i = isoxml&.at(ns("//bibdata/series[@type = 'intended']")) and
55
56
  front.seriesInfo nil,
56
- **attr_code(name: "", status: i&.at(ns("./title"))&.text,
57
- value: i&.at(ns("./number"))&.text || "")
57
+ **attr_code(name: "",
58
+ status: i&.at(ns("./title"))&.text,
59
+ value: i&.at(ns("./number"))&.text || "")
58
60
  end
59
61
 
60
62
  def id_seriesinfo(isoxml, front)
61
63
  front.seriesInfo nil,
62
- **seriesinfo_attr(isoxml).merge({name: "Internet-Draft",
63
- asciiName: "Internet-Draft"})
64
+ **seriesinfo_attr(isoxml)
65
+ .merge({ name: "Internet-Draft",
66
+ asciiName: "Internet-Draft" })
64
67
  i = isoxml&.at(ns("//bibdata/series[@type = 'intended']/title"))&.text and
65
68
  front.seriesInfo **attr_code(name: "", value: "", status: i)
66
69
  end
@@ -74,44 +77,49 @@ module IsoDoc::Ietf
74
77
  end
75
78
  end
76
79
 
77
- def person_author_attrs(c, role)
78
- return {} if c.nil?
79
- full = c&.at(ns("./completename"))&.text
80
- init = c&.at(ns("./initial"))&.text ||
81
- c&.xpath(ns("./forename")).map { |n| n.text[0] }.join(".")
80
+ def person_author_attrs(contrib, role)
81
+ return {} if contrib.nil?
82
+
83
+ full = contrib&.at(ns("./completename"))&.text
84
+ init = contrib&.at(ns("./initial"))&.text ||
85
+ contrib&.xpath(ns("./forename"))&.map { |n| n.text[0] }&.join(".")
82
86
  init = nil if init.empty?
83
87
  ret = attr_code(role: role, fullname: full, initials: init,
84
- surname: c&.at(ns("./surname"))&.text)
85
- pers_author_attrs1(ret, full, init, c)
86
- end
87
-
88
- def pers_author_attrs1(ret, full, init, c)
89
- full and ret.merge!(attr_code(
90
- asciiFullname: output_if_translit(full),
91
- asciiInitials: output_if_translit(init),
92
- asciiSurname: output_if_translit(c&.at(ns("./surname")))))
88
+ surname: contrib&.at(ns("./surname"))&.text)
89
+ pers_author_attrs1(ret, full, init, contrib)
90
+ end
91
+
92
+ def pers_author_attrs1(ret, full, init, contrib)
93
+ full and ret.merge!(
94
+ attr_code(
95
+ asciiFullname: output_if_translit(full),
96
+ asciiInitials: output_if_translit(init),
97
+ asciiSurname: output_if_translit(contrib&.at(ns("./surname"))),
98
+ ),
99
+ )
93
100
  ret
94
101
  end
95
102
 
96
- def person_author(c, role, front)
97
- front.author **person_author_attrs(c.at(ns("./person/name")), role) do |a|
98
- org = c.at(ns("./person/affiliation/organization")) and
99
- organization(org, a, c.document.at(ns("//showOnFrontPage")))
100
- address(c.xpath(ns(".//address")),
101
- c.at(ns(".//phone[not(@type = 'fax')]")),
102
- c.at(ns(".//phone[@type = 'fax']")),
103
- c.xpath(ns(".//email")), c.xpath(ns(".//uri")), a)
103
+ def person_author(contrib, role, front)
104
+ attrs = person_author_attrs(contrib.at(ns("./person/name")), role)
105
+ front.author **attrs do |a|
106
+ org = contrib.at(ns("./person/affiliation/organization")) and
107
+ organization(org, a, contrib.document.at(ns("//showOnFrontPage")))
108
+ address(contrib.xpath(ns(".//address")),
109
+ contrib.at(ns(".//phone[not(@type = 'fax')]")),
110
+ contrib.at(ns(".//phone[@type = 'fax']")),
111
+ contrib.xpath(ns(".//email")), contrib.xpath(ns(".//uri")), a)
104
112
  end
105
113
  end
106
114
 
107
- def org_author(c, role, front)
115
+ def org_author(contrib, role, front)
108
116
  front.author **attr_code(role: role) do |a|
109
- organization(c.at(ns("./organization")), a,
110
- c.document.at(ns("//showOnFrontPage")))
111
- address(c.at(ns(".//address")),
112
- c.at(ns(".//phone[not(@type = 'fax')]")),
113
- c.at(ns(".//phone[@type = 'fax']")),
114
- c.at(ns(".//email")), c.at(ns(".//uri")), a)
117
+ organization(contrib.at(ns("./organization")), a,
118
+ contrib.document.at(ns("//showOnFrontPage")))
119
+ address(contrib.at(ns(".//address")),
120
+ contrib.at(ns(".//phone[not(@type = 'fax')]")),
121
+ contrib.at(ns(".//phone[@type = 'fax']")),
122
+ contrib.at(ns(".//email")), contrib.at(ns(".//uri")), a)
115
123
  end
116
124
  end
117
125
 
@@ -120,11 +128,13 @@ module IsoDoc::Ietf
120
128
  out.organization name, **attr_code(
121
129
  showOnFrontPage: show&.text, ascii: output_if_translit(name),
122
130
  asciiAbbrev: output_if_translit(org.at(ns("./abbreviation"))),
123
- abbrev: org.at(ns("./abbreviation")))
131
+ abbrev: org.at(ns("./abbreviation"))
132
+ )
124
133
  end
125
134
 
126
135
  def address(addr, phone, fax, email, uri, out)
127
136
  return unless addr || phone || fax || email || uri
137
+
128
138
  out.address do |a|
129
139
  addr and postal(addr, a)
130
140
  phone and a.phone phone.text
@@ -137,6 +147,7 @@ module IsoDoc::Ietf
137
147
  def postal(addr, out)
138
148
  out.postal do |p|
139
149
  if line = addr.at(ns("./formattedAddress"))
150
+ line.xpath(ns(".//br")).each { |br| br.replace("\n") }
140
151
  line.text.split(/\n/).each do |l|
141
152
  p.postalLine l, **attr_code(ascii: l.transliterate)
142
153
  end
@@ -163,10 +174,10 @@ module IsoDoc::Ietf
163
174
  def email(email, out)
164
175
  ascii = email.text.transliterate
165
176
  out.email email.text,
166
- **attr_code(ascii: ascii == email.text ? nil : ascii )
177
+ **attr_code(ascii: ascii == email.text ? nil : ascii)
167
178
  end
168
179
 
169
- def date(isoxml, front)
180
+ def date(_isoxml, front)
170
181
  date = @meta.get[:publisheddate] || @meta.get[:circulateddate] || return
171
182
  date = date.gsub(/T.*$/, "")
172
183
  attr = date_attr(date) || return
@@ -175,8 +186,9 @@ module IsoDoc::Ietf
175
186
 
176
187
  def date_attr(date)
177
188
  return nil if date.nil?
189
+
178
190
  if date.length == 4 && date =~ /^\d\d\d\d$/ then { year: date }
179
- elsif date =~ /^\d\d\d\d-?\d\d$/
191
+ elsif /^\d\d\d\d-?\d\d$/.match?(date)
180
192
  m = /^(?<year>\d\d\d\d)-(?<month>\d\d)$/.match date
181
193
  { month: Date::MONTHNAMES[(m[:month]).to_i], year: m[:year] }
182
194
  else
@@ -184,25 +196,25 @@ module IsoDoc::Ietf
184
196
  d = Date.iso8601 date
185
197
  { day: d.day.to_s.gsub(/^0/, ""), year: d.year,
186
198
  month: Date::MONTHNAMES[d.month] }
187
- rescue
199
+ rescue StandardError
188
200
  nil
189
201
  end
190
202
  end
191
203
  end
192
204
 
193
- def area(isoxml, front)
205
+ def area(_isoxml, front)
194
206
  @meta.get[:areas].each do |w|
195
207
  front.area w
196
208
  end
197
209
  end
198
210
 
199
- def workgroup(isoxml, front)
211
+ def workgroup(_isoxml, front)
200
212
  @meta.get[:wg].each do |w|
201
213
  front.workgroup w
202
214
  end
203
215
  end
204
216
 
205
- def keyword(isoxml, front)
217
+ def keyword(_isoxml, front)
206
218
  @meta.get[:keywords].each do |kw|
207
219
  front.keyword kw
208
220
  end
@@ -230,7 +242,6 @@ module IsoDoc::Ietf
230
242
  end
231
243
  end
232
244
 
233
- def boilerplate(isoxml, front)
234
- end
245
+ def boilerplate(isoxml, front); end
235
246
  end
236
247
  end