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