metanorma-ietf 2.2.9 → 2.3.3

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|
@@ -46,25 +46,19 @@ module IsoDoc::Ietf
46
46
 
47
47
  def figure_cleanup(docxml)
48
48
  figure_postamble(docxml)
49
- figure_wrap_artwork(docxml)
50
49
  figure_unnest(docxml)
51
50
  figure_footnote_cleanup(docxml)
52
51
  end
53
52
 
54
- def figure_wrap_artwork(docxml)
55
- docxml.xpath("//artwork[not(parent::figure)] | "\
56
- "//sourcecode[not(parent::figure)]").each do |a|
57
- a.wrap("<figure></figure>")
58
- end
59
- end
60
-
61
53
  def figure_unnest(docxml)
62
54
  docxml.xpath("//figure[descendant::figure]").each do |f|
63
55
  insert = f
64
56
  f.xpath(".//figure").each do |a|
57
+ title = f.at("./name") and a.children.first.previous = title.remove
65
58
  insert.next = a.remove
66
59
  insert = insert.next_element
67
60
  end
61
+ f.remove
68
62
  end
69
63
  end
70
64
 
@@ -134,8 +128,10 @@ module IsoDoc::Ietf
134
128
 
135
129
  def make_endnotes(docxml)
136
130
  return unless docxml.at("//fn")
137
- endnotes = docxml.at("//back") or
138
- docxml << "<back/>" and endnotes = docxml.at("//back")
131
+
132
+ unless endnotes = docxml.at("//back")
133
+ docxml << "<back/>" and endnotes = docxml.at("//back")
134
+ end
139
135
  endnotes << "<section><name>Endnotes</name></section>"
140
136
  endnotes = docxml.at("//back/section[last()]")
141
137
  end
@@ -146,7 +142,7 @@ module IsoDoc::Ietf
146
142
  t.xpath(".//artwork").each_with_index do |a, i|
147
143
  insert.next = a.dup
148
144
  insert = insert.next
149
- a.replace("[IMAGE #{i+1}]")
145
+ a.replace("[IMAGE #{i + 1}]")
150
146
  end
151
147
  end
152
148
  end
@@ -154,8 +150,8 @@ module IsoDoc::Ietf
154
150
  # for markup in pseudocode
155
151
  def sourcecode_cleanup(docxml)
156
152
  docxml.xpath("//sourcecode").each do |s|
157
- s.children = s.children.to_xml.gsub(%r{<br/>\n}, "\n").
158
- gsub(%r{\s+(<t[ >])}, "\\1").gsub(%r{</t>\s+}, "</t>")
153
+ s.children = s.children.to_xml.gsub(%r{<br/>\n}, "\n")
154
+ .gsub(%r{\s+(<t[ >])}, "\\1").gsub(%r{</t>\s+}, "</t>")
159
155
  sourcecode_remove_markup(s)
160
156
  text = HTMLEntities.new.decode(s.children.to_xml.sub(/\A\n+/, ""))
161
157
  s.children = "<![CDATA[#{text}]]>"
@@ -166,8 +162,10 @@ module IsoDoc::Ietf
166
162
  s.traverse do |n|
167
163
  next if n.text?
168
164
  next if %w(name callout annotation note sourcecode).include? n.name
169
- if n.name == "br" then n.replace("\n")
170
- elsif n.name == "t" then n.replace("\n\n#{n.children}")
165
+
166
+ case n.name
167
+ when "br" then n.replace("\n")
168
+ when "t" then n.replace("\n\n#{n.children}")
171
169
  else
172
170
  n.replace(n.children)
173
171
  end
@@ -177,6 +175,7 @@ module IsoDoc::Ietf
177
175
  def annotation_cleanup(docxml)
178
176
  docxml.xpath("//reference").each do |r|
179
177
  next unless r&.next_element&.name == "aside"
178
+
180
179
  aside = r.next_element
181
180
  aside.name = "annotation"
182
181
  aside.traverse do |n|
@@ -184,7 +183,7 @@ module IsoDoc::Ietf
184
183
  end
185
184
  r << aside
186
185
  end
187
- docxml.xpath("//references/aside").each { |r| r.remove }
186
+ docxml.xpath("//references/aside").each(&:remove)
188
187
  end
189
188
 
190
189
  def deflist_cleanup(docxml)
@@ -211,9 +210,7 @@ module IsoDoc::Ietf
211
210
  end
212
211
 
213
212
  def bookmark_cleanup(docxml)
214
- docxml.xpath("//bookmark").each do |b|
215
- b.remove
216
- end
213
+ docxml.xpath("//bookmark").each(&:remove)
217
214
  end
218
215
 
219
216
  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