metanorma-ietf 1.0.0

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.
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,120 @@
1
+ module Asciidoctor
2
+ module Rfc::Common
3
+ module Front
4
+ def title(node, xml)
5
+ title_attributes = {
6
+ abbrev: node.attr("abbrev"),
7
+ }
8
+ xml.title **attr_code(title_attributes) do |t|
9
+ t << node.doctitle
10
+ end
11
+ end
12
+
13
+ # Syntax:
14
+ # = Title
15
+ # Author;Author_2;Author_3
16
+ # :fullname
17
+ # :lastname
18
+ # :organization
19
+ # :email
20
+ # :fullname_2
21
+ # :lastname_2
22
+ # :organization_2
23
+ # :email_2
24
+ # :fullname_3
25
+ # :lastname_3
26
+ # :organization_3
27
+ # :email_3
28
+ # @note recurse: author, author_2, author_3...
29
+ def author(node, xml)
30
+ author1(node, "", xml)
31
+ i = 2
32
+ loop do
33
+ suffix = "_#{i}"
34
+ author = node.attr("author#{suffix}")
35
+ fullname = node.attr("fullname#{suffix}")
36
+ break unless [author, fullname].any?
37
+ author1(node, suffix, xml)
38
+ i += 1
39
+ end
40
+ end
41
+
42
+ # Syntax:
43
+ # = Title
44
+ # Author (contains author firstname lastname middlename authorinitials email: Firstname Middlename Lastname <Email>)
45
+ # :fullname
46
+ # :lastname
47
+ # :forename_initials (excludes surname, unlike Asciidoc "initials" attribute)
48
+ # :organization
49
+ # :email
50
+ # :role
51
+ # :fax
52
+ # :uri
53
+ # :phone
54
+ # :postalLine (mutually exclusive with street city etc) (lines broken up by "\ ")
55
+ # :street
56
+ # :city
57
+ # :region
58
+ # :country
59
+ # :code
60
+ def author1(node, suffix, xml)
61
+ role = node.attr("role#{suffix}")
62
+ role = nil if role == "author"
63
+ author_attributes = {
64
+ fullname: node.attr("author#{suffix}") || node.attr("fullname#{suffix}"),
65
+ surname: node.attr("lastname#{suffix}"),
66
+ initials: node.attr("forename_initials#{suffix}"),
67
+ role: role,
68
+ }
69
+
70
+ xml.author **attr_code(author_attributes) do |xml_sub|
71
+ organization node, suffix, xml_sub
72
+ address node, suffix, xml_sub
73
+ end
74
+ end
75
+
76
+ def date1(revdate, xml)
77
+ revdate.gsub!(/T.*$/, "")
78
+ if revdate.length == 4 && revdate =~ /^\d\d\d\d$/
79
+ date_attributes = {
80
+ year: revdate,
81
+ }
82
+ elsif revdate =~ /^\d\d\d\d-?\d\d$/
83
+ matched = /^(?<year>\d\d\d\d)-(?<month>\d\d)$/.match revdate
84
+ date_attributes = {
85
+ month: Date::MONTHNAMES[(matched[:month]).to_i],
86
+ year: matched[:year],
87
+ }
88
+ else
89
+ d = Date.iso8601 revdate
90
+ date_attributes = {
91
+ day: d.day.to_s.gsub(/^0/, ""),
92
+ month: Date::MONTHNAMES[d.month],
93
+ year: d.year,
94
+ }
95
+ end
96
+ xml.date **attr_code(date_attributes)
97
+ end
98
+
99
+ # Syntax:
100
+ # = Title
101
+ # Author
102
+ # :revdate or :date
103
+ def date(node, xml)
104
+ revdate = node.attr("revdate") || node.attr("date")
105
+ if revdate.nil?
106
+ revdate = DateTime.now.iso8601
107
+ warn %(asciidoctor: WARNING (#{current_location(node)}): revdate attribute missing from header, provided current date)
108
+ end
109
+ unless revdate.nil?
110
+ begin
111
+ date1(revdate, xml)
112
+ rescue ArgumentError # invalid date
113
+ warn %(asciidoctor: WARNING (#{current_location(node)}): invalid date in header, provided current date)
114
+ date1(DateTime.now.iso8601, xml)
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,379 @@
1
+ require "pp"
2
+ # coding: utf-8
3
+ module Asciidoctor
4
+ module Rfc::V2
5
+ module Base
6
+ # Syntax:
7
+ # =Title
8
+ # Author
9
+ # :status
10
+ # :consensus
11
+ # :name
12
+ # :number
13
+ #
14
+ # :ipr
15
+ # :obsoletes
16
+ # :updates
17
+ # :submissionType
18
+ # :indexInclude
19
+ # :ipr-extract
20
+ # :sort-refs
21
+ # :sym-refs
22
+ # :toc-include
23
+ #
24
+ # ABSTRACT
25
+ #
26
+ # NOTEs
27
+ #
28
+ # ==first title
29
+ # CONTENT
30
+ #
31
+ # [bibliography] # start of back matter
32
+ # == Bibliography
33
+ #
34
+ # [appendix] # start of back matter if not already started
35
+ # == Appendix
36
+ def document(node)
37
+ $seen_back_matter = false
38
+ $smart_quotes = (node.attr("smart-quotes") != "false")
39
+ $inline_definition_lists = (node.attr("inline-definition-lists") == "true")
40
+
41
+ result = []
42
+ result << '<?xml version="1.0" encoding="UTF-8"?>'
43
+
44
+ is_rfc = node.attr("doctype") == "rfc"
45
+
46
+ consensus_value = {
47
+ "false" => "no",
48
+ "true" => "yes",
49
+ }[node.attr("consensus")] || node.attr("consensus")
50
+
51
+ category = node.attr("status")
52
+ category = "info" if category == "informational"
53
+ category = "std" if category == "standard"
54
+ category = "exp" if category == "experimental"
55
+
56
+ rfc_attributes = {
57
+ ipr: node.attr("ipr"),
58
+ obsoletes: node.attr("obsoletes"),
59
+ updates: node.attr("updates"),
60
+ category: category,
61
+ consensus: consensus_value,
62
+ submissionType: node.attr("submission-type") || "IETF",
63
+ iprExtract: node.attr("ipr-extract"),
64
+ docName: (node.attr("name") unless is_rfc),
65
+ number: (node.attr("name") if is_rfc),
66
+ seriesNo: node.attr("series-no"),
67
+ "xml:lang": node.attr("xml-lang"),
68
+ }
69
+
70
+ rfc_open = noko { |xml| xml.rfc **attr_code(rfc_attributes) }.join.gsub(/\/>$/, ">")
71
+ result << rfc_open
72
+
73
+ result << noko { |xml| front node, xml }
74
+ result.last.last.gsub! /<\/front>$/, "" # FIXME: this is a hack!
75
+ result << "</front><middle1>"
76
+
77
+ result << node.content if node.blocks?
78
+ result << ($seen_back_matter ? "</back>" : "</middle>")
79
+ result << "</rfc>"
80
+
81
+ # <middle> needs to move after preamble
82
+ result = result.flatten
83
+ result = if result.any? { |e| e =~ /<\/front><middle>/ } && result.any? { |e| e =~ /<\/front><middle1>/ }
84
+ result.reject { |e| e =~ /<\/front><middle1>/ }
85
+ else
86
+ result.map { |e| e =~ /<\/front><middle1>/ ? "</front><middle>" : e }
87
+ end
88
+
89
+ ret = result * "\n"
90
+ ret = cleanup(ret)
91
+ ret1 = Nokogiri::XML(ret)
92
+ # Validate::validate(ret1)
93
+ ret1 = set_pis(node, ret1)
94
+ ret1 = insert_biblio(node, ret1) unless node.attr("biblio-dir").nil? || node.attr("biblio-dir").empty?
95
+ Validate::validate(ret1)
96
+ ret1 = resolve_references(node, ret1)
97
+ # Validate::validate(ret1)
98
+ ret1.to_xml
99
+ end
100
+
101
+ def resolve_references(node, doc)
102
+ extract_entities(node, doc).each do |entity|
103
+ Nokogiri::XML::EntityDecl::new(entity[:entity], doc,
104
+ Nokogiri::XML::EntityDecl::EXTERNAL_GENERAL_PARSED,
105
+ nil, entity[:url], nil)
106
+ entity[:node].replace(Nokogiri::XML::EntityReference.new(doc, entity[:entity]))
107
+ end
108
+ doc
109
+ end
110
+
111
+ def inline_break(node)
112
+ noko do |xml|
113
+ xml << node.text
114
+ xml.vspace
115
+ end.join
116
+ end
117
+
118
+ def inline_quoted(node)
119
+ noko do |xml|
120
+ case node.type
121
+ when :emphasis
122
+ xml.spanx node.text, style: "emph"
123
+ when :strong
124
+ xml.spanx node.text, style: "strong"
125
+ when :monospaced
126
+ xml.spanx node.text, style: "verb"
127
+ when :double
128
+ xml << ($smart_quotes ? "“#{node.text}”" : "\"#{node.text}\"")
129
+ when :single
130
+ xml << ($smart_quotes ? "‘#{node.text}’" : "'#{node.text}'")
131
+ when :superscript
132
+ xml << "^#{node.text}^"
133
+ when :subscript
134
+ xml << "_#{node.text}_"
135
+ else
136
+ # [bcp14]#MUST NOT#
137
+ if node.role == "bcp14"
138
+ xml.spanx node.text.upcase, style: "strong"
139
+ elsif node.role == "comment"
140
+ xml.comment " " + node.text + " "
141
+ else
142
+ xml << node.text
143
+ end
144
+ end
145
+ end.join
146
+ end
147
+
148
+ # Syntax:
149
+ # [[id]]
150
+ # Text
151
+ def paragraph(node)
152
+ if node.role == "comment"
153
+ return noko do |xml|
154
+ xml.comment " " + [flatten_rawtext(node)].flatten.join("\n") + " "
155
+ end.join("\n")
156
+ end
157
+
158
+ t_attributes = {
159
+ anchor: node.id,
160
+ }
161
+
162
+ noko do |xml|
163
+ xml.t **attr_code(t_attributes) do |xml_t|
164
+ xml_t << node.content
165
+ end
166
+ end.join("\n")
167
+ end
168
+
169
+ def verse(node)
170
+ result = []
171
+
172
+ t_attributes = {
173
+ anchor: node.id,
174
+ }
175
+
176
+ result << noko do |xml|
177
+ xml.t **attr_code(t_attributes) do |xml_t|
178
+ xml_t << node.content.gsub("\n\n", "<vspace blankLines=\"1\"/>").gsub("\n", "<vspace/>\n")
179
+ end
180
+ end
181
+
182
+ result
183
+ end
184
+
185
+ # Syntax:
186
+ # [[id]]
187
+ # == title
188
+ # Content
189
+ #
190
+ # [bibliography]
191
+ # == References
192
+ #
193
+ # [bibliography]
194
+ # === Normative|Informative References
195
+ # ++++
196
+ # RFC XML references
197
+ # ++++
198
+ def section(node)
199
+ result = []
200
+ if node.attr("style") == "bibliography" ||
201
+ node.parent.context == :section && node.parent.attr("style") == "bibliography"
202
+ $xreftext = {}
203
+ $processing_reflist = true
204
+
205
+ references_attributes = {
206
+ title: node.title,
207
+ }
208
+ if node.blocks.empty?
209
+ result << noko { |xml| xml.references **references_attributes }
210
+ end
211
+ node.blocks.each do |block|
212
+ if block.context == :section
213
+ result << node.content
214
+ elsif block.context == :pass
215
+ # NOTE: references are assumed to be found in a single passthrough
216
+ # block containing <reference> tags.
217
+
218
+ result << noko do |xml|
219
+ xml.references **references_attributes do |xml_references|
220
+ # NOTE: we're allowing the user to do more or less whathever
221
+ # in the passthrough since the xpath below just fishes out ALL
222
+ # <reference>s in an unrooted fragment, regardless of structure.
223
+ Nokogiri::XML::DocumentFragment.
224
+ parse(block.content).xpath(".//reference").
225
+ each { |reference| xml_references << reference.to_xml }
226
+ end
227
+ end
228
+ end
229
+ end
230
+
231
+ result = result.unshift("</middle><back>") unless $seen_back_matter
232
+ $processing_reflist = false
233
+ $seen_back_matter = true
234
+ else
235
+ if node.attr("style") == "appendix"
236
+ result << "</middle><back>" unless $seen_back_matter
237
+ $seen_back_matter = true
238
+ end
239
+
240
+ section_attributes = {
241
+ anchor: node.id,
242
+ title: node.title.gsub(/<[^>]+>/, ""),
243
+ }
244
+
245
+ result << noko do |xml|
246
+ xml.section **attr_code(section_attributes) do |xml_section|
247
+ xml_section << node.content
248
+ end
249
+ end
250
+ end
251
+
252
+ result
253
+ end
254
+
255
+ # Syntax:
256
+ # [[id]]
257
+ # .Name
258
+ # [link=xxx,align=left|center|right,alt=alt_text,type]
259
+ # image::filename[alt_text,width,height]
260
+ # @note ignoring width, height attributes
261
+ def image(node)
262
+ uri = node.image_uri node.attr("target")
263
+ artwork_attributes = {
264
+ align: node.attr("align"),
265
+ alt: node.alt,
266
+ height: node.attr("height"),
267
+ name: node.title,
268
+ src: uri,
269
+ type: node.attr("type"),
270
+ width: node.attr("width"),
271
+ }
272
+
273
+ noko do |xml|
274
+ if node.parent.context != :example
275
+ figure_attributes = {
276
+ anchor: node.id,
277
+ }
278
+ xml.figure **attr_code(figure_attributes) do |xml_figure|
279
+ xml_figure.artwork **attr_code(artwork_attributes)
280
+ end
281
+ else
282
+ xml.artwork **attr_code(artwork_attributes)
283
+ end
284
+ end
285
+ end
286
+
287
+ # clean up XML
288
+ def cleanup(doc)
289
+ xmldoc = Nokogiri::XML(doc) do |config|
290
+ config.noent
291
+ end
292
+
293
+ # any crefs that are direct children of section should become children of the preceding
294
+ # paragraph, if it exists; otherwise, they need to be wrapped in a paragraph
295
+ crefs = xmldoc.xpath("//cref")
296
+ crefs.each do |cref|
297
+ if cref.parent.name == "section"
298
+ prev = cref.previous_element
299
+ if !prev.nil? && prev.name == "t"
300
+ cref.parent = prev
301
+ else
302
+ t = Nokogiri::XML::Element.new("t", xmldoc)
303
+ cref.before(t)
304
+ cref.parent = t
305
+ end
306
+ end
307
+ end
308
+ # any instances of spanx must be stripped of any internal tags
309
+ spanxs = xmldoc.xpath("//spanx[descendant::*]")
310
+ while !spanxs.empty?
311
+ spanx = spanxs[0]
312
+ spanx_text = ""
313
+ spanx.traverse do |node|
314
+ spanx_text = spanx_text + node.text.gsub(/<[^>]+>/, "") if node.text?
315
+ end
316
+ spanx.children = spanx_text
317
+ spanxs = xmldoc.xpath("//spanx[descendant::*]")
318
+ end
319
+
320
+ xmldoc.root = merge_vspace(xmldoc.root)
321
+ xmldoc = smart_quote_cleanup(xmldoc) unless $smart_quotes
322
+ xmldoc.to_xml(encoding: "US-ASCII")
323
+ end
324
+
325
+ def merge_vspace(node)
326
+ nodes = []
327
+ newnodes = []
328
+ node.children.each do |element|
329
+ nodes << element
330
+ end
331
+
332
+ counter = 0
333
+ while counter < nodes.size
334
+ if nodes[counter].name == "vspace"
335
+ blankLines = 0
336
+ while counter < nodes.size && nodes[counter].name == "vspace"
337
+ blankLines += 1
338
+ if nodes[counter][:blankLines].nil?
339
+ blankLines += nodes[counter][:blankLines].to_i
340
+ end
341
+ if counter + 1 < nodes.size && nodes[counter + 1].text? && nodes[counter + 1].text =~ /\A[\n ]+\Z/m
342
+ counter += 1
343
+ end
344
+ counter += 1
345
+ end
346
+ counter -= 1 if counter == nodes.size
347
+ newnodes << noko do |xml|
348
+ xml.vspace **attr_code(blankLines: (blankLines - 1))
349
+ end.join
350
+ else
351
+ newnodes << merge_vspace(nodes[counter])
352
+ counter += 1
353
+ end
354
+ end
355
+ node.children.remove
356
+ newnodes.each do |item|
357
+ node.add_child(item)
358
+ end
359
+ node
360
+ end
361
+
362
+ # replace any <t>text</t> instances with <vspace blankLines="1"/>text
363
+ def para_to_vspace(doc)
364
+ xmldoc = Nokogiri::XML("<fragment>#{doc}</fragment>")
365
+ paras = xmldoc.xpath("/fragment/t")
366
+ paras.each do |para|
367
+ # we do not insert vspace if the para contains a list: space will go there anyway
368
+ unless para.element_children.size == 1 && para.element_children[0].name == "list"
369
+ vspace = Nokogiri::XML::Element.new("vspace", xmldoc.document)
370
+ vspace["blankLines"] = "1"
371
+ para.before(vspace)
372
+ end
373
+ para.replace(para.children)
374
+ end
375
+ xmldoc.root.children.to_xml(encoding: "US-ASCII")
376
+ end
377
+ end
378
+ end
379
+ end