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