metanorma-ietf 1.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 +7 -0
  2. data/.gitignore +18 -0
  3. data/.hound.yml +3 -0
  4. data/.oss-guides.rubocop.yml +1077 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.ribose.yml +65 -0
  7. data/.rubocop.tb.yml +650 -0
  8. data/.rubocop.yml +15 -0
  9. data/.travis.yml +23 -0
  10. data/CODE_OF_CONDUCT.md +74 -0
  11. data/Gemfile +4 -0
  12. data/Guardfile +22 -0
  13. data/LICENSE +25 -0
  14. data/README.adoc +1660 -0
  15. data/Rakefile +6 -0
  16. data/bin/asciidoctor-rfc2 +14 -0
  17. data/bin/asciidoctor-rfc3 +14 -0
  18. data/bin/console +14 -0
  19. data/bin/rspec +17 -0
  20. data/bin/setup +8 -0
  21. data/docs/installation.md +21 -0
  22. data/docs/navigation.md +10 -0
  23. data/docs/overview.md +5 -0
  24. data/lib/asciidoctor/rfc.rb +8 -0
  25. data/lib/asciidoctor/rfc/common/base.rb +531 -0
  26. data/lib/asciidoctor/rfc/common/front.rb +120 -0
  27. data/lib/asciidoctor/rfc/v2/base.rb +379 -0
  28. data/lib/asciidoctor/rfc/v2/blocks.rb +261 -0
  29. data/lib/asciidoctor/rfc/v2/converter.rb +60 -0
  30. data/lib/asciidoctor/rfc/v2/front.rb +69 -0
  31. data/lib/asciidoctor/rfc/v2/inline_anchor.rb +111 -0
  32. data/lib/asciidoctor/rfc/v2/lists.rb +135 -0
  33. data/lib/asciidoctor/rfc/v2/table.rb +114 -0
  34. data/lib/asciidoctor/rfc/v2/validate.rb +32 -0
  35. data/lib/asciidoctor/rfc/v2/validate2.rng +716 -0
  36. data/lib/asciidoctor/rfc/v3/base.rb +329 -0
  37. data/lib/asciidoctor/rfc/v3/blocks.rb +246 -0
  38. data/lib/asciidoctor/rfc/v3/converter.rb +62 -0
  39. data/lib/asciidoctor/rfc/v3/front.rb +122 -0
  40. data/lib/asciidoctor/rfc/v3/inline_anchor.rb +89 -0
  41. data/lib/asciidoctor/rfc/v3/lists.rb +176 -0
  42. data/lib/asciidoctor/rfc/v3/svg.rng +9081 -0
  43. data/lib/asciidoctor/rfc/v3/table.rb +65 -0
  44. data/lib/asciidoctor/rfc/v3/validate.rb +34 -0
  45. data/lib/asciidoctor/rfc/v3/validate.rng +2143 -0
  46. data/lib/metanorma-ietf.rb +7 -0
  47. data/lib/metanorma/ietf.rb +8 -0
  48. data/lib/metanorma/ietf/processor.rb +89 -0
  49. data/lib/metanorma/ietf/version.rb +5 -0
  50. data/metanorma-ietf.gemspec +51 -0
  51. data/rfc2629-other.ent +61 -0
  52. data/rfc2629-xhtml.ent +165 -0
  53. data/rfc2629.dtd +312 -0
  54. metadata +289 -0
@@ -0,0 +1,62 @@
1
+ require "asciidoctor"
2
+
3
+ require_relative "../common/base"
4
+ require_relative "../common/front"
5
+ require_relative "base"
6
+ require_relative "blocks"
7
+ require_relative "front"
8
+ require_relative "inline_anchor"
9
+ require_relative "lists"
10
+ require_relative "table"
11
+ require_relative "validate"
12
+
13
+ module Asciidoctor
14
+ module Rfc::V3
15
+ # A {Converter} implementation that generates RFC XML output, a format used to
16
+ # format RFC proposals (https://tools.ietf.org/html/rfc7991)
17
+ #
18
+ # Features drawn from https://github.com/miekg/mmark/wiki/Syntax and
19
+ # https://github.com/riboseinc/rfc2md
20
+ class Converter
21
+ include ::Asciidoctor::Converter
22
+ include ::Asciidoctor::Writer
23
+
24
+ include ::Asciidoctor::Rfc::Common::Base
25
+ include ::Asciidoctor::Rfc::Common::Front
26
+ include ::Asciidoctor::Rfc::V3::Base
27
+ include ::Asciidoctor::Rfc::V3::Blocks
28
+ include ::Asciidoctor::Rfc::V3::Front
29
+ include ::Asciidoctor::Rfc::V3::InlineAnchor
30
+ include ::Asciidoctor::Rfc::V3::Lists
31
+ include ::Asciidoctor::Rfc::V3::Table
32
+ include ::Asciidoctor::Rfc::V3::Validate
33
+
34
+ register_for "rfc3"
35
+
36
+ $seen_back_matter = false
37
+ $xreftext = {}
38
+
39
+ def initialize(backend, opts)
40
+ super
41
+ # enable when Asciidoctor 1.5.7 is released
42
+ Asciidoctor::Compliance.natural_xrefs = false
43
+ # basebackend 'html'
44
+ outfilesuffix ".xml"
45
+ end
46
+
47
+ # alias_method :pass, :content
48
+ alias_method :embedded, :content
49
+ alias_method :audio, :skip
50
+ alias_method :colist, :skip
51
+ alias_method :page_break, :skip
52
+ alias_method :thematic_break, :skip
53
+ alias_method :video, :skip
54
+ alias_method :inline_button, :skip
55
+ alias_method :inline_kbd, :skip
56
+ alias_method :inline_menu, :skip
57
+ alias_method :inline_image, :skip
58
+
59
+ alias_method :inline_callout, :content
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,122 @@
1
+ module Asciidoctor
2
+ module Rfc::V3
3
+ module Front
4
+ # Syntax:
5
+ # = Title
6
+ # Author
7
+ # :METADATA
8
+ def front(node, xml)
9
+ xml.front do |xml_front|
10
+ title node, xml_front
11
+ series_info node, xml_front
12
+ author node, xml_front
13
+ date node, xml_front
14
+ area node, xml_front
15
+ workgroup node, xml_front
16
+ keyword node, xml_front
17
+ end
18
+ end
19
+
20
+ def series_info(node, xml)
21
+ docname = node.attr("name")
22
+ return if docname.nil? || docname&.empty?
23
+ is_rfc = docname =~ /^rfc-?/i || node.attr("doctype") == "rfc"
24
+
25
+ if is_rfc
26
+ name = docname.gsub(/^rfc-?/i, "")
27
+ nameattr = "RFC"
28
+ else
29
+ name = docname
30
+ nameattr = "Internet-Draft"
31
+ end
32
+ value = name.gsub(/\.[^\/]+$/, "")
33
+
34
+ seriesInfo_attributes = {
35
+ name: nameattr,
36
+ status: node.attr("status"),
37
+ stream: node.attr("submission-type") || "IETF",
38
+ value: value,
39
+ }
40
+ xml.seriesInfo **attr_code(seriesInfo_attributes)
41
+
42
+ intendedstatus = node.attr("intended-series")
43
+ if !is_rfc && !intendedstatus.nil?
44
+ unless intendedstatus =~ /^(standard|full-standard|bcp|fyi|informational|experimental|historic)$/
45
+ warn %(asciidoctor: WARNING (#{current_location(node)}): disallowed value for intended-series in document header: #{intendedstatus})
46
+ end
47
+ seriesInfo_attributes = {
48
+ name: "",
49
+ status: intendedstatus,
50
+ value: value,
51
+ }
52
+ xml.seriesInfo **attr_code(seriesInfo_attributes)
53
+ end
54
+
55
+ rfcstatus = intendedstatus
56
+ if is_rfc && !rfcstatus.nil?
57
+ m = /^(\S+) (\d+)$/.match rfcstatus
58
+ if m.nil?
59
+ rfcstatus = "exp" if rfcstatus == "experimental"
60
+ rfcstatus = "info" if rfcstatus == "informational"
61
+ warn %(asciidoctor: WARNING (#{current_location(node)}): disallowed value for intended-series in document header with no series number: #{rfcstatus}) unless rfcstatus =~ /^(info|exp|historic)$/
62
+ else
63
+ rfcstatus = m[1]
64
+ value = m[2]
65
+ warn %(asciidoctor: WARNING (#{current_location(node)}): disallowed value for intended-series in document header with series number: #{rfcstatus}) unless rfcstatus =~ /^(standard|full-standard|bcp)$/
66
+ end
67
+ seriesInfo_attributes = {
68
+ name: "",
69
+ status: rfcstatus,
70
+ value: value,
71
+ }
72
+ xml.seriesInfo **attr_code(seriesInfo_attributes)
73
+ end
74
+ end
75
+
76
+ def organization(node, suffix, xml)
77
+ organization = node.attr("organization#{suffix}")
78
+ xml.organization { |org| org << organization } unless organization.nil?
79
+ end
80
+
81
+ def address(node, suffix, xml)
82
+ email = node.attr("email#{suffix}")
83
+ facsimile = node.attr("fax#{suffix}")
84
+ phone = node.attr("phone#{suffix}")
85
+ postalline = node.attr("postal-line#{suffix}")
86
+ street = node.attr("street#{suffix}")
87
+ uri = node.attr("uri#{suffix}")
88
+ if [email, facsimile, phone, postalline, street, uri].any?
89
+ xml.address do |xml_address|
90
+ address1 node, suffix, xml_address if [postalline, street].any?
91
+ xml_address.phone { |p| p << phone } unless phone.nil?
92
+ xml_address.facsimile { |f| f << facsimile } unless facsimile.nil?
93
+ xml_address.email { |e| e << email } unless email.nil?
94
+ xml_address.uri { |u| u << uri } unless uri.nil?
95
+ end
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def address1(node, suffix, xml_address)
102
+ postalline = node.attr("postal-line#{suffix}")
103
+ street = node.attr("street#{suffix}")
104
+ xml_address.postal do |xml_postal|
105
+ if postalline.nil?
106
+ city = node.attr("city#{suffix}")
107
+ code = node.attr("code#{suffix}")
108
+ country = node.attr("country#{suffix}")
109
+ region = node.attr("region#{suffix}")
110
+ street&.split("\\ ")&.each { |st| xml_postal.street { |s| s << st } }
111
+ xml_postal.city { |c| c << city } unless city.nil?
112
+ xml_postal.region { |r| r << region } unless region.nil?
113
+ xml_postal.code { |c| c << code } unless code.nil?
114
+ xml_postal.country { |c| c << country } unless country.nil?
115
+ else
116
+ postalline&.split("\\ ")&.each { |pl| xml_postal.postalLine { |p| p << pl } }
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,89 @@
1
+ module Asciidoctor
2
+ module Rfc::V3
3
+ module InlineAnchor
4
+ def inline_anchor(node)
5
+ case node.type
6
+ when :xref
7
+ inline_anchor_xref node
8
+ when :link
9
+ inline_anchor_link node
10
+ when :bibref
11
+ inline_anchor_bibref node
12
+ when :ref
13
+ inline_anchor_ref node
14
+ else
15
+ warn %(asciidoctor: WARNING (#{current_location(node)}): unknown anchor type: #{node.type.inspect})
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def inline_anchor_xref(node)
22
+ text = node.text
23
+ if text =~ /^\S+ (of|comma|parens|bare)\b/
24
+ # <<crossreference#fragment,section (of|comma|parens|bare): text>> = relref
25
+ matched = /(?<section>\S+)\s+(?<format>[a-z]+)(: )?(?<text>.*)$/.match node.text
26
+
27
+ relref_contents = matched[:text]
28
+
29
+ relref_attributes = {
30
+ relative: node.attributes["path"].nil? ? nil : node.attributes["fragment"],
31
+ section: matched[:section],
32
+ displayFormat: matched[:format],
33
+ # fragment inserts file suffix, e.g. rfc2911#fragment becomes rfc2911.xml#fragment
34
+ target: node.target.gsub(/^#/, "").gsub(/(.)(\.xml)?#.*$/, "\\1"),
35
+ }
36
+
37
+ noko do |xml|
38
+ xml.relref relref_contents, **attr_code(relref_attributes)
39
+ end.join
40
+ else
41
+ xref_contents = node.text
42
+ matched = /^format=(?<format>counter|title|none|default)(?<text>:\s*.*)?$/.match xref_contents
43
+ xref_contents = if matched.nil?
44
+ xref_contents
45
+ else
46
+ matched[:text].nil? ? "" : matched[:text].gsub(/^:\s*/, "")
47
+ end
48
+
49
+ warn %(asciidoctor: WARNING (#{current_location(node)}): fragments not supported on crossreferences in v3 without relref: #{node.target} #{node.text}) if node.target =~ /.#/
50
+ xref_attributes = {
51
+ format: matched&.[](:format),
52
+ target: node.target.gsub(/^#/, "").gsub(/(.)(\.xml)?#.*$/, "\\1"),
53
+ }
54
+
55
+ noko do |xml|
56
+ xml.xref xref_contents, **attr_code(xref_attributes)
57
+ end.join
58
+ end
59
+ end
60
+
61
+ def inline_anchor_link(node)
62
+ eref_contents = node.target == node.text ? nil : node.text
63
+ eref_attributes = {
64
+ target: node.target,
65
+ }
66
+
67
+ noko do |xml|
68
+ xml.eref eref_contents, **attr_code(eref_attributes)
69
+ end.join
70
+ end
71
+
72
+ def inline_anchor_bibref(node)
73
+ unless node.xreftext.nil?
74
+ x = node.xreftext.gsub(/^\[(.+)\]$/, "\\1")
75
+ if node.id != x
76
+ $xreftext[node.id] = x
77
+ end
78
+ end
79
+ # NOTE technically node.text should be node.reftext, but subs have already been applied to text
80
+ # %(<bibanchor="#{node.id}">) # will convert to anchor attribute upstream
81
+ nil
82
+ end
83
+
84
+ def inline_anchor_ref(node)
85
+ warn %(asciidoctor: WARNING (#{current_location(node)}): anchor "#{node.id}" is not in a place where XML RFC will recognise it as an anchor attribute)
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,176 @@
1
+ module Asciidoctor
2
+ module Rfc::V3
3
+ module Lists
4
+ # Syntax:
5
+ # * [[[ref1]]] A
6
+ # * [[[ref2]]] B
7
+ # * [[[ref3]]] (Referencegroup: no content)
8
+ # * [[[ref4]]] C
9
+ # * [[[ref4]]] D
10
+ # @note ulist repurposed as reference list
11
+ # def reflist(node)
12
+ # result = []
13
+ # if node.context == :ulist
14
+ # node.items.each do |item|
15
+ # # we expect the biblio anchor to be right at the start of the reference
16
+ # if item.blocks?
17
+ # # we expect any list to be embedded, and only one level of embedding
18
+ # # we expect no content in the referencegroup line other than the bibliographic anchor
19
+ # result << "<referencegroup>#{item.text}".gsub(/<referencegroup>\s*\[?<bibanchor="([^"]+)">\]?.*$/, "<referencegroup anchor=\"\\1\">")
20
+ # item.blocks.each { |b| result << reflist(b) }
21
+ # result << "</referencegroup>"
22
+ # else
23
+ # # quoteTitle = get_header_attribute item, "quoteTitle"
24
+ # # target = get_header_attribute item, "target"
25
+ # # annotation = get_header_attribute item, "annotation"
26
+ # # FIXME: [[[x]]] within embedded list is processed as [<bibref>]
27
+ # result << "<reference>#{item.text}</refcontent></reference>".gsub(/<reference>\s*\[?<bibanchor="([^"]+)">\]?\s*/, "<reference anchor=\"\\1\"><refcontent>")
28
+ # end
29
+ # end
30
+ # elsif node.context == :pass
31
+ # # we expect raw xml
32
+ # node.lines.each do |item|
33
+ # # undo XML substitution
34
+ # ref = item.gsub(/\&lt;/, "<").gsub(/\&gt;/, ">")
35
+ # result << ref
36
+ # end
37
+ # else
38
+ # warn %(asciidoctor: WARNING: references are not a ulist or raw XML: #{node.context})
39
+ # end
40
+ # result
41
+ # end
42
+
43
+ # Syntax:
44
+ # [[id]]
45
+ # [empty=true,spacing=compact|normal] (optional)
46
+ # * A
47
+ # * B
48
+ def ulist(node)
49
+ result = []
50
+
51
+ result << noko do |xml|
52
+ ul_attributes = {
53
+ anchor: node.id,
54
+ empty: node.attr("empty"),
55
+ spacing: node.attr("spacing"),
56
+ }
57
+
58
+ xml.ul **attr_code(ul_attributes) do |xml_ul|
59
+ node.items.each do |item|
60
+ li_attributes = {
61
+ anchor: item.id,
62
+ }
63
+
64
+ xml_ul.li **attr_code(li_attributes) do |xml_li|
65
+ if item.blocks?
66
+ xml_li.t do |t|
67
+ t << item.text
68
+ end
69
+ xml_li << item.content
70
+ else
71
+ xml_li << item.text
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ result
79
+ end
80
+
81
+ OLIST_TYPES = Hash.new("1").merge(
82
+ arabic: "1",
83
+ # decimal: "1", # not supported
84
+ loweralpha: "a",
85
+ # lowergreek: "lower-greek", # not supported
86
+ lowerroman: "i",
87
+ upperalpha: "A",
88
+ upperroman: "I",
89
+ ).freeze
90
+
91
+ # Syntax:
92
+ # [[id]]
93
+ # [start=n,group=n,spacing=normal|compact] (optional)
94
+ # . A
95
+ # . B
96
+ def olist(node)
97
+ result = []
98
+
99
+ result << noko do |xml|
100
+ type = OLIST_TYPES[node.style.to_sym]
101
+ type = node.attr("format") unless node.attr("format").nil?
102
+ ol_attributes = {
103
+ anchor: node.id,
104
+ start: node.attr("start"),
105
+ group: node.attr("group"),
106
+ type: type,
107
+ spacing: ("compact" if node.style == "compact") || node.attr("spacing"),
108
+ }
109
+
110
+ xml.ol **attr_code(ol_attributes) do |xml_ol|
111
+ node.items.each do |item|
112
+ li_attributes = {
113
+ anchor: item.id,
114
+ }
115
+ xml_ol.li **attr_code(li_attributes) do |xml_li|
116
+ if item.blocks?
117
+ xml_li.t do |t|
118
+ t << item.text
119
+ end
120
+ xml_li << item.content
121
+ else
122
+ xml_li << item.text
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ result
129
+ end
130
+
131
+ # Syntax:
132
+ # [[id]]
133
+ # [horizontal,compact] (optional)
134
+ # A:: B
135
+ # C:: D
136
+ def dlist(node)
137
+ result = []
138
+
139
+ result << noko do |xml|
140
+ dl_attributes = {
141
+ anchor: node.id,
142
+ hanging: ("true" if node.style == "horizontal"),
143
+ spacing: ("compact" if node.style == "compact"),
144
+ }
145
+
146
+ xml.dl **attr_code(dl_attributes) do |xml_dl|
147
+ node.items.each do |terms, dd|
148
+ terms.each_with_index do |dt, idx|
149
+ xml_dl.dt { |xml_dt| xml_dt << dt.text }
150
+ if idx < terms.size - 1
151
+ xml_dl.dd
152
+ end
153
+ end
154
+
155
+ if dd.nil?
156
+ xml_dl.dd
157
+ else
158
+ xml_dl.dd do |xml_dd|
159
+ if dd.blocks?
160
+ if dd.text?
161
+ xml_dd.t { |t| t << dd.text }
162
+ end
163
+ xml_dd << dd.content
164
+ else
165
+ xml_dd << dd.text
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
172
+ result
173
+ end
174
+ end
175
+ end
176
+ end