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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +3 -2
  3. data/.github/workflows/ubuntu.yml +3 -2
  4. data/.github/workflows/windows.yml +4 -3
  5. data/README.adoc +9 -0
  6. data/lib/asciidoctor/ietf/basicdoc.rng +1045 -0
  7. data/lib/asciidoctor/ietf/biblio.rng +1142 -0
  8. data/lib/asciidoctor/ietf/blocks.rb +76 -0
  9. data/lib/asciidoctor/ietf/converter.rb +211 -0
  10. data/lib/asciidoctor/ietf/front.rb +143 -0
  11. data/lib/asciidoctor/ietf/ietf.rng +882 -0
  12. data/lib/asciidoctor/ietf/isodoc.rng +514 -0
  13. data/lib/asciidoctor/ietf/isostandard.rng +860 -0
  14. data/lib/asciidoctor/ietf/reqt.rng +171 -0
  15. data/lib/asciidoctor/ietf/validate.rb +84 -0
  16. data/lib/isodoc/ietf/blocks.rb +215 -0
  17. data/lib/isodoc/ietf/cleanup.rb +220 -0
  18. data/lib/isodoc/ietf/footnotes.rb +70 -0
  19. data/lib/isodoc/ietf/front.rb +232 -0
  20. data/lib/isodoc/ietf/inline.rb +136 -0
  21. data/lib/isodoc/ietf/metadata.rb +62 -0
  22. data/lib/isodoc/ietf/references.rb +129 -0
  23. data/lib/isodoc/ietf/reqt.rb +74 -0
  24. data/lib/isodoc/ietf/rfc_convert.rb +60 -0
  25. data/lib/isodoc/ietf/section.rb +162 -0
  26. data/lib/isodoc/ietf/table.rb +43 -0
  27. data/lib/isodoc/ietf/terms.rb +65 -0
  28. data/lib/metanorma-ietf.rb +2 -1
  29. data/lib/metanorma/ietf/processor.rb +16 -37
  30. data/lib/metanorma/ietf/version.rb +1 -1
  31. data/metanorma-ietf.gemspec +3 -3
  32. metadata +36 -36
  33. data/Gemfile.lock +0 -327
  34. data/lib/asciidoctor/rfc.rb +0 -8
  35. data/lib/asciidoctor/rfc/common/base.rb +0 -544
  36. data/lib/asciidoctor/rfc/common/front.rb +0 -120
  37. data/lib/asciidoctor/rfc/common/validate.rb +0 -31
  38. data/lib/asciidoctor/rfc/v2/base.rb +0 -380
  39. data/lib/asciidoctor/rfc/v2/blocks.rb +0 -299
  40. data/lib/asciidoctor/rfc/v2/converter.rb +0 -60
  41. data/lib/asciidoctor/rfc/v2/front.rb +0 -69
  42. data/lib/asciidoctor/rfc/v2/inline_anchor.rb +0 -111
  43. data/lib/asciidoctor/rfc/v2/lists.rb +0 -135
  44. data/lib/asciidoctor/rfc/v2/table.rb +0 -116
  45. data/lib/asciidoctor/rfc/v2/validate.rng +0 -716
  46. data/lib/asciidoctor/rfc/v3/base.rb +0 -330
  47. data/lib/asciidoctor/rfc/v3/blocks.rb +0 -246
  48. data/lib/asciidoctor/rfc/v3/converter.rb +0 -62
  49. data/lib/asciidoctor/rfc/v3/front.rb +0 -122
  50. data/lib/asciidoctor/rfc/v3/inline_anchor.rb +0 -89
  51. data/lib/asciidoctor/rfc/v3/lists.rb +0 -176
  52. data/lib/asciidoctor/rfc/v3/svg.rng +0 -9081
  53. data/lib/asciidoctor/rfc/v3/table.rb +0 -65
  54. data/lib/asciidoctor/rfc/v3/validate.rng +0 -2143
@@ -0,0 +1,136 @@
1
+ require "mathml2asciimath"
2
+
3
+ module IsoDoc::Ietf
4
+ class RfcConvert < ::IsoDoc::Convert
5
+ def em_parse(node, out)
6
+ out.em do |e|
7
+ node.children.each { |n| parse(n, e) }
8
+ end
9
+ end
10
+
11
+ def sup_parse(node, out)
12
+ out.sup do |e|
13
+ node.children.each { |n| parse(n, e) }
14
+ end
15
+ end
16
+
17
+ def sub_parse(node, out)
18
+ out.sub do |e|
19
+ node.children.each { |n| parse(n, e) }
20
+ end
21
+ end
22
+
23
+ def tt_parse(node, out)
24
+ out.tt do |e|
25
+ node.children.each { |n| parse(n, e) }
26
+ end
27
+ end
28
+
29
+ def strong_parse(node, out)
30
+ out.strong do |e|
31
+ node.children.each { |n| parse(n, e) }
32
+ end
33
+ end
34
+
35
+ def bcp14_parse(node, out)
36
+ out.bcp14 do |e|
37
+ node.children.each { |n| parse(n, e) }
38
+ end
39
+ end
40
+
41
+ def strike_parse(node, out)
42
+ node.children.each { |n| parse(n, out) }
43
+ end
44
+
45
+ def smallcap_parse(node, out)
46
+ node.children.each { |n| parse(n, out) }
47
+ end
48
+
49
+ def keyword_parse(node, out)
50
+ node.children.each { |n| parse(n, out) }
51
+ end
52
+
53
+ def text_parse(node, out)
54
+ return if node.nil? || node.text.nil?
55
+ text = node.to_s
56
+ out << text
57
+ end
58
+
59
+ def stem_parse(node, out)
60
+ stem = case node["type"]
61
+ when "MathML" then MathML2AsciiMath.m2a(node.children.to_xml)
62
+ else
63
+ HTMLEntities.new.encode(node.text)
64
+ end
65
+ out << "#{@openmathdelim} #{stem} #{@closemathdelim}"
66
+ end
67
+
68
+ def page_break(_out)
69
+ end
70
+
71
+ def br_parse(node, out)
72
+ if @sourcecode
73
+ out.br
74
+ end
75
+ end
76
+
77
+ def hr_parse(node, out)
78
+ end
79
+
80
+ def link_parse(node, out)
81
+ out.eref **attr_code(target: node["target"]) do |l|
82
+ node.children.each { |n| parse(n, l) }
83
+ end
84
+ end
85
+
86
+ def image_parse(node, out, caption)
87
+ attrs = { src: node["src"], title: node["title"],
88
+ align: node["align"], name: node["filename"],
89
+ anchor: node["id"], type: "svg",
90
+ alt: node["alt"] }
91
+ out.artwork **attr_code(attrs)
92
+ image_title_parse(out, caption)
93
+ end
94
+
95
+ def image_title_parse(out, caption)
96
+ unless caption.nil?
97
+ out.t **{ align: "center", keepWithPrevious: "true" } do |p|
98
+ p << caption.to_s
99
+ end
100
+ end
101
+ end
102
+
103
+ def xref_parse(node, out)
104
+ out.xref **attr_code(target: node["target"], format: node["format"],
105
+ relative: node["relative"]) do |l|
106
+ l << get_linkend(node)
107
+ end
108
+ end
109
+
110
+ def eref_parse(node, out)
111
+ linkend = node.children.select { |c| c.name != "locality" }
112
+ section = eref_clause(node.xpath(ns("./locality")), nil) || ""
113
+ out.relref **attr_code(target: node["bibitemid"], section: section,
114
+ displayFormat: node["displayFormat"]) do |l|
115
+ linkend.each { |n| parse(n, l) }
116
+ end
117
+ end
118
+
119
+ def eref_clause(refs, target)
120
+ refs.each do |l|
121
+ next unless %w(clause section).include? l["type"]
122
+ return l&.at(ns("./referenceFrom"))&.text
123
+ end
124
+ return nil
125
+ end
126
+
127
+ def index_parse(node, out)
128
+ out.iref nil, **attr_code(item: node["primary"],
129
+ subitem: node["secondary"])
130
+ end
131
+
132
+ def bookmark_parse(node, out)
133
+ out.bookmark nil, **attr_code(anchor: node["id"])
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,62 @@
1
+ require "isodoc"
2
+
3
+ module IsoDoc
4
+ module Ietf
5
+ class Metadata < IsoDoc::Metadata
6
+ TITLE_RFC = "//bibdata//title[@type='main' and @language='en']".freeze
7
+
8
+ def title(isoxml, _out)
9
+ t = isoxml.at(ns(TITLE_RFC)) and
10
+ set(:doctitle, t.text)
11
+ t = isoxml.at(ns(TITLE_RFC.sub(/main/, "abbrev"))) and
12
+ set(:docabbrev, t.text)
13
+ t = isoxml.at(ns(TITLE_RFC.sub(/main/, "ascii"))) and
14
+ set(:docascii, t.text)
15
+ end
16
+
17
+ def relaton_relations
18
+ %w(included-in described-by derived-from equivalent)
19
+ # = item describedby convertedfrom alternate
20
+ end
21
+
22
+ def keywords(isoxml, _out)
23
+ ret = []
24
+ isoxml.xpath(ns("//bibdata/keyword")).each do |kw|
25
+ ret << kw.text
26
+ end
27
+ set(:keywords, ret)
28
+ end
29
+
30
+ def areas(isoxml, _out)
31
+ ret = []
32
+ isoxml.xpath(ns("//bibdata/ext/area")).each do |kw|
33
+ ret << kw.text
34
+ end
35
+ set(:areas, ret)
36
+ end
37
+
38
+ def docid(isoxml, _out)
39
+ dn = isoxml.at(ns("//bibdata/docnumber"))
40
+ set(:docnumber, dn&.text&.sub(/^rfc-/, "")&.sub(/\.[a-z0-9]+$/i, ""))
41
+ end
42
+
43
+ def author(xml, _out)
44
+ super
45
+ wg(xml)
46
+ end
47
+
48
+ def wg(xml)
49
+ workgroups = []
50
+ xml.xpath(ns("//bibdata/ext/editorialgroup/workgroup")).each do |wg|
51
+ workgroups << wg.text
52
+ end
53
+ set(:wg, workgroups)
54
+ end
55
+
56
+ def doctype(isoxml, _out)
57
+ super
58
+ set(:doctype, "Rfc") if get[:doctype].nil?
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,129 @@
1
+ module IsoDoc::Ietf
2
+ class RfcConvert < ::IsoDoc::Convert
3
+ # TODO displayreference will be implemented as combination of autofetch and user-provided citations
4
+
5
+ def bibliography(isoxml, out)
6
+ isoxml.xpath(ns("//references")).each do |f|
7
+ out.references **attr_code(anchor: f["id"]) do |div|
8
+ title = f.at(ns("./title")) and div.name do |name|
9
+ title.children.each { |n| parse(n, name) }
10
+ end
11
+ f.elements.reject do |e|
12
+ %w(reference title bibitem note).include? e.name
13
+ end.each { |e| parse(e, div) }
14
+ biblio_list(f, div, true)
15
+ end
16
+ end
17
+ end
18
+
19
+ def biblio_list(f, div, biblio)
20
+ i = 0
21
+ f.xpath(ns("./bibitem | ./note")).each do |b|
22
+ next if implicit_reference(b)
23
+ i += 1 if b.name == "bibitem"
24
+ if b.name == "note" then note_parse(b, div)
25
+ elsif(is_ietf(b)) then ietf_bibitem_entry(div, b, i)
26
+ else
27
+ nonstd_bibitem(div, b, i, biblio)
28
+ end
29
+ end
30
+ end
31
+
32
+ def nonstd_bibitem(list, b, ordinal, bibliography)
33
+ uris = b.xpath(ns("./uri"))
34
+ list.reference **attr_code(target: uris.empty? ? nil : uris[0]&.text,
35
+ anchor: b["id"]) do |r|
36
+ r.front do |f|
37
+ relaton_to_title(b, f)
38
+ relaton_to_author(b, f)
39
+ relaton_to_date(b, f)
40
+ relaton_to_keyword(b, f)
41
+ relaton_to_abstract(b, f)
42
+ end
43
+ uris[1..-1]&.each do |u|
44
+ r.format nil, **attr_code(target: u.text, type: u["type"])
45
+ end
46
+ end
47
+ end
48
+
49
+ def relaton_to_title(b, f)
50
+ id = bibitem_ref_code(b)
51
+ identifier = render_identifier(id)
52
+ title = b&.at(ns("./title")) || b&.at(ns("./formattedref")) or return
53
+ f.title do |t|
54
+ t << "#{identifier}, "
55
+ title.children.each { |n| parse(n, t) }
56
+ end
57
+ end
58
+
59
+ def relaton_to_author(b, f)
60
+ auths = b.xpath(ns("./contributor[xmlns:role/@type = 'author' or "\
61
+ "xmlns:role/@type = 'editor']"))
62
+ auths.empty? and auths = b.xpath(ns("./contributor[xmlns:role/@type = "\
63
+ "'publisher']"))
64
+ auths.each do |a|
65
+ role = a.at(ns("./role[@type = 'editor']")) ? "editor" : nil
66
+ p = a&.at(ns("./person/name")) and
67
+ relaton_person_to_author(p, role, f) or
68
+ relaton_org_to_author(a&.at(ns("./organization")), role, f)
69
+ end
70
+ end
71
+
72
+ def relaton_person_to_author(p, role, f)
73
+ fullname = p&.at(ns("./completename"))&.text
74
+ surname = p&.at(ns("./surname"))&.text
75
+ initials = p&.xpath(ns("./initial"))&.map { |i| i.text }&.join(" ") ||
76
+ p&.xpath(ns("./forename"))&.map { |i| i.text[0] }&.join(" ")
77
+ initials = nil if initials.empty?
78
+ f.author nil,
79
+ **attr_code(fullname: fullname, asciiFullname: fullname&.transliterate,
80
+ role: role, surname: surname, initials: initials,
81
+ asciiSurname: fullname ? surname&.transliterate : nil,
82
+ asciiInitials: fullname ? initials&.transliterate : nil)
83
+ end
84
+
85
+ def relaton_org_to_author(o, role, f)
86
+ name = o&.at(ns("./name"))&.text
87
+ abbrev = o&.at(ns("./abbreviation"))&.text
88
+ f.author do |a|
89
+ f.organization name, **attr_code(ascii: name&.transliterate,
90
+ abbrev: abbrev)
91
+ end
92
+ end
93
+
94
+ def relaton_to_date(b, f)
95
+ date = b.at(ns("./date[@type = 'published']")) ||
96
+ b.at(ns("./date[@type = 'issued']")) ||
97
+ b.at(ns("./date[@type = 'circulated']"))
98
+ return unless date
99
+ attr = date_attr(date&.at(ns("./on | ./from"))&.text) || return
100
+ f.date **attr_code(attr)
101
+ end
102
+
103
+ def relaton_to_keyword(b, f)
104
+ b.xpath(ns("./keyword")).each do |k|
105
+ f.keyword do |keyword|
106
+ k.children.each { |n| parse(n, keyword) }
107
+ end
108
+ end
109
+ end
110
+
111
+ def relaton_to_abstract(b, f)
112
+ b.xpath(ns("./abstract")).each do |k|
113
+ f.abstract do |abstract|
114
+ k.children.each { |n| parse(n, abstract) }
115
+ end
116
+ end
117
+ end
118
+
119
+ def ietf_bibitem_entry(div, b, i)
120
+ url = b&.at(ns("./uri[@type = 'xml']"))&.text
121
+ div << "<xi:include href='#{url}'/>"
122
+ end
123
+
124
+ def is_ietf(b)
125
+ url = b.at(ns("./uri[@type = 'xml']")) or return false
126
+ /xml2rfc\.tools\.ietf\.org/.match(url)
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,74 @@
1
+ module IsoDoc::Ietf
2
+ class RfcConvert < ::IsoDoc::Convert
3
+ def recommendation_name(node, out, type)
4
+ label, title, lbl = recommendation_labels(node)
5
+ out.t **{ keepWithNext: "true" } do |b|
6
+ b << (lbl.nil? ? l10n("#{type}:") : l10n("#{type} #{lbl}:"))
7
+ end
8
+ if label || title
9
+ out.t **{ keepWithNext: "true" } do |b|
10
+ label and label.children.each { |n| parse(n,b) }
11
+ b << "#{clausedelim} " if label && title
12
+ title and title.children.each { |n| parse(n,b) }
13
+ end
14
+ end
15
+ end
16
+
17
+ def recommendation_attributes(node, out)
18
+ ret = recommendation_attributes1(node)
19
+ return if ret.empty?
20
+ out.ul do |p|
21
+ ret.each do |l|
22
+ p.li do |i|
23
+ i.em { |e| i << l }
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ def recommendation_parse(node, out)
30
+ recommendation_name(node, out, @recommendation_lbl)
31
+ recommendation_attributes(node, out)
32
+ node.children.each do |n|
33
+ parse(n, out) unless %w(label title).include? n.name
34
+ end
35
+ end
36
+
37
+ def requirement_parse(node, out)
38
+ recommendation_name(node, out, @requirement_lbl)
39
+ recommendation_attributes(node, out)
40
+ node.children.each do |n|
41
+ parse(n, out) unless %w(label title).include? n.name
42
+ end
43
+ end
44
+
45
+ def permission_parse(node, out)
46
+ recommendation_name(node, out, @permission_lbl)
47
+ recommendation_attributes(node, out)
48
+ node.children.each do |n|
49
+ parse(n, out) unless %w(label title).include? n.name
50
+ end
51
+ end
52
+
53
+ def inline?(node)
54
+ return true if node.first_element_child.nil?
55
+ %w(em link eref xref strong tt sup sub strike keyword smallcap
56
+ br hr bookmark pagebreak stem origin term preferred admitted
57
+ deprecates domain termsource modification).include? node.first_element_child.name
58
+ end
59
+
60
+ def requirement_component_parse(node, out)
61
+ return if node["exclude"] == "true"
62
+ out1 = out
63
+ if inline?(node)
64
+ out.t do |p|
65
+ p << "INHERIT: " if node.name == "inherit"
66
+ node.children.each { |n| parse(n, p) }
67
+ end
68
+ else
69
+ node.children.each { |n| parse(n, out) }
70
+ end
71
+ end
72
+ end
73
+ end
74
+
@@ -0,0 +1,60 @@
1
+ require_relative "./terms"
2
+ require_relative "./blocks"
3
+ require_relative "./metadata"
4
+ require_relative "./front"
5
+ require_relative "./table"
6
+ require_relative "./inline"
7
+ require_relative "./reqt"
8
+ require_relative "./cleanup"
9
+ require_relative "./footnotes"
10
+ require_relative "./references"
11
+ require_relative "./section"
12
+
13
+ module IsoDoc::Ietf
14
+ class RfcConvert < ::IsoDoc::Convert
15
+ def convert1(docxml, filename, dir)
16
+ anchor_names docxml
17
+ info docxml, nil
18
+ xml = noko do |xml|
19
+ xml.rfc **attr_code(rfc_attributes(docxml)) do |html|
20
+ make_link(html, docxml)
21
+ make_front(html, docxml)
22
+ make_middle(html, docxml)
23
+ make_back(html, docxml)
24
+ end
25
+ end.join("\n").sub(/<!DOCTYPE[^>]+>\n/, "")
26
+ set_pis(docxml, Nokogiri::XML(xml))
27
+ end
28
+
29
+ def metadata_init(lang, script, labels)
30
+ @meta = Metadata.new(lang, script, labels)
31
+ end
32
+
33
+ def extract_delims(text)
34
+ @openmathdelim = "$$"
35
+ @closemathdelim = "$$"
36
+ while %r{#{Regexp.escape(@openmathdelim)}}m.match(text) ||
37
+ %r{#{Regexp.escape(@closemathdelim)}}m.match(text)
38
+ @openmathdelim += "$"
39
+ @closemathdelim += "$"
40
+ end
41
+ [@openmathdelim, @closemathdelim]
42
+ end
43
+
44
+ def error_parse(node, out)
45
+ case node.name
46
+ when "bcp14" then bcp14_parse(node, out)
47
+ else
48
+ text = node.to_xml.gsub(/</, "&lt;").gsub(/>/, "&gt;")
49
+ out.t { |p| p << text }
50
+ end
51
+ end
52
+
53
+ def postprocess(result, filename, dir)
54
+ result = from_xhtml(cleanup(to_xhtml(result))).sub(/<!DOCTYPE[^>]+>\n/, "").
55
+ sub(/(<rfc[^<]+? )lang="[^"]+"/, "\\1")
56
+ File.open("#{filename}.rfc.xml", "w:UTF-8") { |f| f.write(result) }
57
+ @files_to_delete.each { |f| FileUtils.rm_rf f }
58
+ end
59
+ end
60
+ end