metanorma-ietf 1.0.10 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/macos.yml +3 -2
- data/.github/workflows/ubuntu.yml +3 -2
- data/.github/workflows/windows.yml +4 -3
- data/README.adoc +9 -0
- data/lib/asciidoctor/ietf/basicdoc.rng +1045 -0
- data/lib/asciidoctor/ietf/biblio.rng +1142 -0
- data/lib/asciidoctor/ietf/blocks.rb +76 -0
- data/lib/asciidoctor/ietf/converter.rb +211 -0
- data/lib/asciidoctor/ietf/front.rb +143 -0
- data/lib/asciidoctor/ietf/ietf.rng +882 -0
- data/lib/asciidoctor/ietf/isodoc.rng +514 -0
- data/lib/asciidoctor/ietf/isostandard.rng +860 -0
- data/lib/asciidoctor/ietf/reqt.rng +171 -0
- data/lib/asciidoctor/ietf/validate.rb +84 -0
- data/lib/isodoc/ietf/blocks.rb +215 -0
- data/lib/isodoc/ietf/cleanup.rb +220 -0
- data/lib/isodoc/ietf/footnotes.rb +70 -0
- data/lib/isodoc/ietf/front.rb +232 -0
- data/lib/isodoc/ietf/inline.rb +136 -0
- data/lib/isodoc/ietf/metadata.rb +62 -0
- data/lib/isodoc/ietf/references.rb +129 -0
- data/lib/isodoc/ietf/reqt.rb +74 -0
- data/lib/isodoc/ietf/rfc_convert.rb +60 -0
- data/lib/isodoc/ietf/section.rb +162 -0
- data/lib/isodoc/ietf/table.rb +43 -0
- data/lib/isodoc/ietf/terms.rb +65 -0
- data/lib/metanorma-ietf.rb +2 -1
- data/lib/metanorma/ietf/processor.rb +16 -37
- data/lib/metanorma/ietf/version.rb +1 -1
- data/metanorma-ietf.gemspec +3 -3
- metadata +36 -36
- data/Gemfile.lock +0 -327
- data/lib/asciidoctor/rfc.rb +0 -8
- data/lib/asciidoctor/rfc/common/base.rb +0 -544
- data/lib/asciidoctor/rfc/common/front.rb +0 -120
- data/lib/asciidoctor/rfc/common/validate.rb +0 -31
- data/lib/asciidoctor/rfc/v2/base.rb +0 -380
- data/lib/asciidoctor/rfc/v2/blocks.rb +0 -299
- data/lib/asciidoctor/rfc/v2/converter.rb +0 -60
- data/lib/asciidoctor/rfc/v2/front.rb +0 -69
- data/lib/asciidoctor/rfc/v2/inline_anchor.rb +0 -111
- data/lib/asciidoctor/rfc/v2/lists.rb +0 -135
- data/lib/asciidoctor/rfc/v2/table.rb +0 -116
- data/lib/asciidoctor/rfc/v2/validate.rng +0 -716
- data/lib/asciidoctor/rfc/v3/base.rb +0 -330
- data/lib/asciidoctor/rfc/v3/blocks.rb +0 -246
- data/lib/asciidoctor/rfc/v3/converter.rb +0 -62
- data/lib/asciidoctor/rfc/v3/front.rb +0 -122
- data/lib/asciidoctor/rfc/v3/inline_anchor.rb +0 -89
- data/lib/asciidoctor/rfc/v3/lists.rb +0 -176
- data/lib/asciidoctor/rfc/v3/svg.rng +0 -9081
- data/lib/asciidoctor/rfc/v3/table.rb +0 -65
- data/lib/asciidoctor/rfc/v3/validate.rng +0 -2143
@@ -0,0 +1,220 @@
|
|
1
|
+
module IsoDoc::Ietf
|
2
|
+
class RfcConvert < ::IsoDoc::Convert
|
3
|
+
def cleanup(docxml)
|
4
|
+
image_cleanup(docxml)
|
5
|
+
figure_cleanup(docxml)
|
6
|
+
table_cleanup(docxml)
|
7
|
+
footnote_cleanup(docxml)
|
8
|
+
sourcecode_cleanup(docxml)
|
9
|
+
annotation_cleanup(docxml)
|
10
|
+
deflist_cleanup(docxml)
|
11
|
+
bookmark_cleanup(docxml)
|
12
|
+
aside_cleanup(docxml)
|
13
|
+
docxml
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO: insert <u>
|
17
|
+
|
18
|
+
def table_footnote_cleanup(docxml)
|
19
|
+
docxml.xpath("//table[descendant::fn]").each do |t|
|
20
|
+
t.xpath(".//fn").each do |a|
|
21
|
+
t << "<aside>#{a.remove.children}</aside>"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def figure_footnote_cleanup(docxml)
|
27
|
+
docxml.xpath("//figure[descendant::fn]").each do |t|
|
28
|
+
t.xpath(".//fn").each do |a|
|
29
|
+
t << "<aside>#{a.remove.children}</aside>"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def table_cleanup(docxml)
|
35
|
+
table_footnote_cleanup(docxml)
|
36
|
+
end
|
37
|
+
|
38
|
+
def figure_cleanup(docxml)
|
39
|
+
figure_postamble(docxml)
|
40
|
+
figure_wrap_artwork(docxml)
|
41
|
+
figure_unnest(docxml)
|
42
|
+
figure_footnote_cleanup(docxml)
|
43
|
+
end
|
44
|
+
|
45
|
+
def figure_wrap_artwork(docxml)
|
46
|
+
docxml.xpath("//artwork[not(parent::figure)] | "\
|
47
|
+
"//sourcecode[not(parent::figure)]").each do |a|
|
48
|
+
a.wrap("<figure></figure>")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def figure_unnest(docxml)
|
53
|
+
docxml.xpath("//figure[descendant::figure]").each do |f|
|
54
|
+
insert = f
|
55
|
+
f.xpath(".//figure").each do |a|
|
56
|
+
insert.next = a.remove
|
57
|
+
insert = insert.next_element
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def figure_postamble(docxml)
|
63
|
+
make_postamble(docxml)
|
64
|
+
move_postamble(docxml)
|
65
|
+
move_preamble(docxml)
|
66
|
+
end
|
67
|
+
|
68
|
+
def make_postamble(docxml)
|
69
|
+
docxml.xpath("//figure").each do |f|
|
70
|
+
a = f&.at("./artwork | ./sourcecode") || next
|
71
|
+
name = f&.at("./name")&.remove
|
72
|
+
b = a&.xpath("./preceding-sibling::*")&.remove
|
73
|
+
c = a&.xpath("./following-sibling::*")&.remove
|
74
|
+
a = a.remove
|
75
|
+
name and f << name
|
76
|
+
b.empty? or f << "<preamble>#{b.to_xml}</preamble>"
|
77
|
+
a and f << a
|
78
|
+
c.empty? or f << "<postamble>#{c.to_xml}</postamble>"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def move_postamble(docxml)
|
83
|
+
docxml.xpath("//postamble").each do |p|
|
84
|
+
insert = p.parent
|
85
|
+
p.remove.elements.each do |e|
|
86
|
+
insert.next = e
|
87
|
+
insert = insert.next_element
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def move_preamble(docxml)
|
93
|
+
docxml.xpath("//preamble").each do |p|
|
94
|
+
insert = p.parent
|
95
|
+
p.remove.elements.each do |e|
|
96
|
+
insert.previous = e
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def footnote_cleanup(docxml)
|
102
|
+
fn = footnote_refs_cleanup(docxml)
|
103
|
+
endnotes = make_endnotes(docxml)
|
104
|
+
docxml.xpath("//section[descendant::fn] | "\
|
105
|
+
"//abstract[descendant::fn]").each do |s|
|
106
|
+
s.xpath(".//fn").each do |f|
|
107
|
+
ref = f.at(".//ref") and ref.replace("[#{fn[ref.text]}] ")
|
108
|
+
endnotes << f.remove.children
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def footnote_refs_cleanup(docxml)
|
114
|
+
i = 0
|
115
|
+
fn = {}
|
116
|
+
docxml.xpath("//fnref").each do |f|
|
117
|
+
unless fn[f.text]
|
118
|
+
i = i + 1
|
119
|
+
fn[f.text] = i.to_s
|
120
|
+
end
|
121
|
+
f.replace(" [#{fn[f.text]}]")
|
122
|
+
end
|
123
|
+
fn
|
124
|
+
end
|
125
|
+
|
126
|
+
def make_endnotes(docxml)
|
127
|
+
return unless docxml.at("//fn")
|
128
|
+
endnotes = docxml.at("//back") or
|
129
|
+
docxml << "<back/>" and endnotes = docxml.at("//back")
|
130
|
+
endnotes << "<section><name>Endnotes</name></section>"
|
131
|
+
endnotes = docxml.at("//back/section[last()]")
|
132
|
+
end
|
133
|
+
|
134
|
+
def image_cleanup(docxml)
|
135
|
+
docxml.xpath("//t[descendant::artwork]").each do |t|
|
136
|
+
insert = t
|
137
|
+
t.xpath(".//artwork").each_with_index do |a, i|
|
138
|
+
insert.next = a.dup
|
139
|
+
insert = insert.next
|
140
|
+
a.replace("[IMAGE #{i+1}]")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# for markup in pseudocode
|
146
|
+
def sourcecode_cleanup(docxml)
|
147
|
+
docxml.xpath("//sourcecode").each do |s|
|
148
|
+
s.children = s.children.to_xml.gsub(%r{<br/>\n}, "\n").
|
149
|
+
gsub(%r{\s+(<t[ >])}, "\\1").gsub(%r{</t>\s+}, "</t>")
|
150
|
+
sourcecode_remove_markup(s)
|
151
|
+
s.children = "<![CDATA[#{s.children.to_xml.sub(/\A\n+/, "")}]]>"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def sourcecode_remove_markup(s)
|
156
|
+
s.traverse do |n|
|
157
|
+
next if n.text?
|
158
|
+
next if %w(name callout annotation note sourcecode).include? n.name
|
159
|
+
if n.name == "br" then n.replace("\n")
|
160
|
+
elsif n.name == "t" then n.replace("\n\n#{n.children}")
|
161
|
+
else
|
162
|
+
n.replace(n.children)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def annotation_cleanup(docxml)
|
168
|
+
docxml.xpath("//reference").each do |r|
|
169
|
+
next unless r&.next_element&.name == "aside"
|
170
|
+
aside = r.next_element
|
171
|
+
aside.name = "annotation"
|
172
|
+
aside.traverse do |n|
|
173
|
+
n.name == "t" and n.replace(n.children)
|
174
|
+
end
|
175
|
+
r << aside
|
176
|
+
end
|
177
|
+
docxml.xpath("//references/aside").each { |r| r.remove }
|
178
|
+
end
|
179
|
+
|
180
|
+
def deflist_cleanup(docxml)
|
181
|
+
dt_cleanup(docxml)
|
182
|
+
dd_cleanup(docxml)
|
183
|
+
end
|
184
|
+
|
185
|
+
def dt_cleanup(docxml)
|
186
|
+
docxml.xpath("//dt").each do |d|
|
187
|
+
d&.first_element_child&.name == "bookmark" and
|
188
|
+
d["anchor"] ||= d.first_element_child["anchor"]
|
189
|
+
d.xpath(".//t").each do |t|
|
190
|
+
d["anchor"] ||= t["anchor"]
|
191
|
+
t.replace(t.children)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def dd_cleanup(docxml)
|
197
|
+
docxml.xpath("//dd").each do |d|
|
198
|
+
d&.first_element_child&.name == "bookmark" and
|
199
|
+
d["anchor"] ||= d.first_element_child["anchor"]
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def bookmark_cleanup(docxml)
|
204
|
+
docxml.xpath("//bookmark").each do |b|
|
205
|
+
b.remove
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def aside_cleanup(docxml)
|
210
|
+
docxml.xpath("//t[descendant::aside] | //table[descendant::aside] | "\
|
211
|
+
"//figure[descendant::aside]").each do |p|
|
212
|
+
insert = p
|
213
|
+
p.xpath(".//aside").each do |a|
|
214
|
+
insert.next = a.remove
|
215
|
+
insert = insert.next_element
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module IsoDoc::Ietf
|
2
|
+
class RfcConvert < ::IsoDoc::Convert
|
3
|
+
def footnote_parse(node, out)
|
4
|
+
return table_footnote_parse(node, out) if @in_table || @in_figure
|
5
|
+
fn = node["reference"]
|
6
|
+
out.fnref fn
|
7
|
+
make_local_footnote(node, fn, out)
|
8
|
+
end
|
9
|
+
|
10
|
+
def make_local_footnote(node, fn, out)
|
11
|
+
return if @seen_footnote.include?(fn)
|
12
|
+
@in_footnote = true
|
13
|
+
out << make_generic_footnote_text(node, fn)
|
14
|
+
@in_footnote = false
|
15
|
+
@seen_footnote << fn
|
16
|
+
end
|
17
|
+
|
18
|
+
def make_generic_footnote_text(node, fnref)
|
19
|
+
first = node.first_element_child
|
20
|
+
noko do |xml|
|
21
|
+
xml.fn do |div|
|
22
|
+
xml.t **attr_code(anchor: first ? first["id"] : nil) do |div|
|
23
|
+
div.ref fnref
|
24
|
+
first.name == "p" and first.children.each { |n| parse(n, div) }
|
25
|
+
end
|
26
|
+
first.name == "p" and
|
27
|
+
node.elements.drop(1).each { |n| parse(n, xml) } or
|
28
|
+
node.children.each { |n| parse(n, xml) }
|
29
|
+
end
|
30
|
+
end.join
|
31
|
+
end
|
32
|
+
|
33
|
+
def table_footnote_parse(node, out)
|
34
|
+
fn = node["reference"]
|
35
|
+
tid = get_table_ancestor_id(node)
|
36
|
+
make_table_footnote_link(out, tid + fn, fn)
|
37
|
+
# do not output footnote text if we have already seen it for this table
|
38
|
+
return if @seen_footnote.include?(tid + fn)
|
39
|
+
@in_footnote = true
|
40
|
+
out.fn do |a|
|
41
|
+
a << make_table_footnote_text(node, tid + fn, fn)
|
42
|
+
end
|
43
|
+
@in_footnote = false
|
44
|
+
@seen_footnote << (tid + fn)
|
45
|
+
end
|
46
|
+
|
47
|
+
def make_table_footnote_link(out, fnid, fnref)
|
48
|
+
out << " [#{fnref}]"
|
49
|
+
end
|
50
|
+
|
51
|
+
def make_table_footnote_text(node, fnid, fnref)
|
52
|
+
first = node.first_element_child
|
53
|
+
noko do |xml|
|
54
|
+
xml.t **attr_code(anchor: first ? first["id"] : nil) do |div|
|
55
|
+
div << "[#{fnref}] "
|
56
|
+
first.name == "p" and first.children.each { |n| parse(n, div) }
|
57
|
+
end
|
58
|
+
first.name == "p" and
|
59
|
+
node.elements.drop(1).each { |n| parse(n, xml) } or
|
60
|
+
node.children.each { |n| parse(n, xml) }
|
61
|
+
end.join
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_table_ancestor_id(node)
|
65
|
+
table = node.ancestors("table") || node.ancestors("figure")
|
66
|
+
return UUIDTools::UUID.random_create.to_s if table.empty?
|
67
|
+
table.last["id"]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
require "sterile"
|
2
|
+
|
3
|
+
module IsoDoc::Ietf
|
4
|
+
class RfcConvert < ::IsoDoc::Convert
|
5
|
+
def make_front(out, isoxml)
|
6
|
+
info(isoxml, out)
|
7
|
+
out.front do |front|
|
8
|
+
title isoxml, front
|
9
|
+
seriesinfo isoxml, front
|
10
|
+
author isoxml, front
|
11
|
+
date isoxml, front
|
12
|
+
area isoxml, front
|
13
|
+
workgroup isoxml, front
|
14
|
+
keyword isoxml, front
|
15
|
+
abstract isoxml, front
|
16
|
+
note isoxml, front
|
17
|
+
boilerplate isoxml, front
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def info(isoxml, out)
|
22
|
+
@meta.keywords isoxml, out
|
23
|
+
@meta.areas isoxml, out
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def title(isoxml, front)
|
28
|
+
title = @meta.get[:doctitle] or return
|
29
|
+
front.title title, **attr_code(abbrev: @meta.get[:docabbrev],
|
30
|
+
ascii: @meta.get[:docascii] ||
|
31
|
+
title.transliterate)
|
32
|
+
end
|
33
|
+
|
34
|
+
def seriesinfo(isoxml, front)
|
35
|
+
rfc_seriesinfo(isoxml, front) if @meta.get[:doctype] == "Rfc"
|
36
|
+
id_seriesinfo(isoxml, front) if @meta.get[:doctype] == "Internet Draft"
|
37
|
+
end
|
38
|
+
|
39
|
+
def seriesinfo_attr(isoxml)
|
40
|
+
attr_code(value: @meta.get[:docnumber] || "",
|
41
|
+
asciiValue: @meta.get[:docnumber]&.transliterate,
|
42
|
+
status: @meta.get[:stage],
|
43
|
+
stream: isoxml&.at(ns("//bibdata/series[@type = 'stream']/"\
|
44
|
+
"title"))&.text)
|
45
|
+
end
|
46
|
+
|
47
|
+
def rfc_seriesinfo(isoxml, front)
|
48
|
+
front.seriesInfo **seriesinfo_attr(isoxml).merge({name: "RFC",
|
49
|
+
asciiName: "RFC"})
|
50
|
+
i = isoxml&.at(ns("//bibdata/series[@type = 'intended']")) and
|
51
|
+
front.seriesInfo nil,
|
52
|
+
**attr_code(name: "", status: i&.at(ns("./title"))&.text,
|
53
|
+
value: i&.at(ns("./number"))&.text || "")
|
54
|
+
end
|
55
|
+
|
56
|
+
def id_seriesinfo(isoxml, front)
|
57
|
+
front.seriesInfo nil,
|
58
|
+
**seriesinfo_attr(isoxml).merge({name: "Internet-Draft",
|
59
|
+
asciiName: "Internet-Draft"})
|
60
|
+
i = isoxml&.at(ns("//bibdata/series[@type = 'intended']/title"))&.text and
|
61
|
+
front.seriesInfo **attr_code(name: "", value: "", status: i)
|
62
|
+
end
|
63
|
+
|
64
|
+
def author(isoxml, front)
|
65
|
+
isoxml.xpath(("//xmlns:bibdata/xmlns:contributor[xmlns:role/@type = "\
|
66
|
+
"'author' or xmlns:role/@type = 'editor']")).each do |c|
|
67
|
+
role = c.at(ns("./role/@type")).text == "editor" ? "editor" : nil
|
68
|
+
c.at("./organization") and org_author(c, role, front) or
|
69
|
+
person_author(c, role, front)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def person_author_attrs(c, role)
|
74
|
+
return {} if c.nil?
|
75
|
+
full = c&.at(ns("./completename"))&.text
|
76
|
+
init = c&.at(ns("./initial"))&.text ||
|
77
|
+
c&.xpath(ns("./forename")).map { |n| n.text[0] }.join(".")
|
78
|
+
init = nil if init.empty?
|
79
|
+
ret = attr_code(role: role, fullname: full, initials: init,
|
80
|
+
surname: c&.at(ns("./surname"))&.text)
|
81
|
+
pers_author_attrs1(ret, full, init, c)
|
82
|
+
end
|
83
|
+
|
84
|
+
def pers_author_attrs1(ret, full, init, c)
|
85
|
+
full and ret.merge!(attr_code(
|
86
|
+
asciiFullname: full&.transliterate,
|
87
|
+
asciiInitials: init&.transliterate,
|
88
|
+
asciiSurname: c&.at(ns("./surname"))&.text&.transliterate))
|
89
|
+
ret
|
90
|
+
end
|
91
|
+
|
92
|
+
def person_author(c, role, front)
|
93
|
+
front.author **person_author_attrs(c.at(ns("./person/name")), role) do |a|
|
94
|
+
org = c.at(ns("./person/affiliation/organization")) and
|
95
|
+
organization(org, a, c.document.at(ns("//showOnFrontPage")))
|
96
|
+
address(c.xpath(ns(".//address")),
|
97
|
+
c.at(ns(".//phone[not(@type = 'fax')]")),
|
98
|
+
c.at(ns(".//phone[@type = 'fax']")),
|
99
|
+
c.xpath(ns(".//email")), c.xpath(ns(".//uri")), a)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def org_author(c, role, front)
|
104
|
+
front.author **attr_code(role: role) do |a|
|
105
|
+
organization(c.at(ns("./organization")), a,
|
106
|
+
c.document.at(ns("//showOnFrontPage")))
|
107
|
+
address(c.at(ns(".//address")),
|
108
|
+
c.at(ns(".//phone[not(@type = 'fax')]")),
|
109
|
+
c.at(ns(".//phone[@type = 'fax']")),
|
110
|
+
c.at(ns(".//email")), c.at(ns(".//uri")), a)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def organization(org, out, show)
|
115
|
+
name = org.at(ns("./name"))&.text
|
116
|
+
out.organization name, **attr_code(
|
117
|
+
showOnFrontPage: show&.text, ascii: name&.transliterate,
|
118
|
+
asciiAbbrev: org&.at(ns("./abbreviation"))&.transliterate,
|
119
|
+
abbrev: org.at(ns("./abbreviation")))
|
120
|
+
end
|
121
|
+
|
122
|
+
def address(addr, phone, fax, email, uri, out)
|
123
|
+
return unless addr || phone || fax || email || uri
|
124
|
+
out.address do |a|
|
125
|
+
addr and postal(addr, a)
|
126
|
+
phone and a.phone phone.text
|
127
|
+
fax and a.facsimile fax.text
|
128
|
+
email and email(email, a)
|
129
|
+
uri and a.uri uri.text
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def postal(addr, out)
|
134
|
+
if line = addr.at(ns("./formattedAddress"))
|
135
|
+
line.text.split(/\n/).each do |l|
|
136
|
+
out.postalLine l, **attr_code(ascii: l.transliterate)
|
137
|
+
end
|
138
|
+
else
|
139
|
+
out.postal do |p|
|
140
|
+
postal_detailed(addr, p)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def postal_detailed(addr, out)
|
146
|
+
addr.xpath(ns("./street")).each do |s|
|
147
|
+
out.street s.text, **attr_code(ascii: s.text.transliterate)
|
148
|
+
end
|
149
|
+
s = addr.at(ns("./city")) and
|
150
|
+
out.city s.text, **attr_code(ascii: s.text.transliterate)
|
151
|
+
s = addr.at(ns("./state")) and
|
152
|
+
out.region s.text, **attr_code(ascii: s.text.transliterate)
|
153
|
+
s = addr.at(ns("./country")) and
|
154
|
+
out.country s.text, **attr_code(ascii: s.text.transliterate)
|
155
|
+
s = addr.at(ns("./postcode")) and
|
156
|
+
out.code s.text, **attr_code(ascii: s.text.transliterate)
|
157
|
+
end
|
158
|
+
|
159
|
+
def email(email, out)
|
160
|
+
ascii = email.text.transliterate
|
161
|
+
out.email email.text,
|
162
|
+
**attr_code(ascii: ascii == email.text ? nil : ascii )
|
163
|
+
end
|
164
|
+
|
165
|
+
def date(isoxml, front)
|
166
|
+
date = @meta.get[:publisheddate] || @meta.get[:circulateddate] || return
|
167
|
+
date.gsub!(/T.*$/, "")
|
168
|
+
attr = date_attr(date) || return
|
169
|
+
front.date **attr_code(attr)
|
170
|
+
end
|
171
|
+
|
172
|
+
def date_attr(date)
|
173
|
+
return nil if date.nil?
|
174
|
+
if date.length == 4 && date =~ /^\d\d\d\d$/ then { year: date }
|
175
|
+
elsif date =~ /^\d\d\d\d-?\d\d$/
|
176
|
+
m = /^(?<year>\d\d\d\d)-(?<month>\d\d)$/.match date
|
177
|
+
{ month: Date::MONTHNAMES[(m[:month]).to_i], year: m[:year] }
|
178
|
+
else
|
179
|
+
begin
|
180
|
+
d = Date.iso8601 date
|
181
|
+
{ day: d.day.to_s.gsub(/^0/, ""), year: d.year,
|
182
|
+
month: Date::MONTHNAMES[d.month] }
|
183
|
+
rescue
|
184
|
+
nil
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def area(isoxml, front)
|
190
|
+
@meta.get[:areas].each do |w|
|
191
|
+
front.area w
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def workgroup(isoxml, front)
|
196
|
+
@meta.get[:wg].each do |w|
|
197
|
+
front.workgroup w
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def keyword(isoxml, front)
|
202
|
+
@meta.get[:keywords].each do |kw|
|
203
|
+
front.keyword kw
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def abstract(isoxml, front)
|
208
|
+
a = isoxml.at(ns("//preface/abstract | //preface/foreword")) || return
|
209
|
+
front.abstract **attr_code(anchor: a["id"]) do |abs|
|
210
|
+
a.children.reject { |c1| %w(title note).include? c1.name }.each do |c1|
|
211
|
+
parse(c1, abs)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def note(isoxml, front)
|
217
|
+
a = isoxml.at(ns("//preface/abstract/note | //preface/foreword/note")) or
|
218
|
+
return
|
219
|
+
front.note **attr_code(removeInRFC: a["removeInRFC"]) do |n|
|
220
|
+
title = a.at(ns("./name")) and n.name do |t|
|
221
|
+
title.children.each { |tt| parse(tt, t) }
|
222
|
+
end
|
223
|
+
a.children.reject { |c1| c1.name == "name" }.each do |c1|
|
224
|
+
parse(c1, n)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def boilerplate(isoxml, front)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|