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,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