kramdown-rfc2629 1.5.26 → 1.6.3

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.
@@ -0,0 +1,577 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'kramdown-rfc2629'
4
+ require 'kramdown-rfc/parameterset'
5
+ require 'kramdown-rfc/refxml'
6
+ require 'kramdown-rfc/rfc8792'
7
+ require 'yaml'
8
+ require 'kramdown-rfc/erb'
9
+ require 'date'
10
+
11
+ # try to get this from gemspec.
12
+ KDRFC_VERSION=Gem.loaded_specs["kramdown-rfc2629"].version rescue "unknown-version"
13
+
14
+ Encoding.default_external = "UTF-8" # wake up, smell the coffee
15
+
16
+ # Note that this doesn't attempt to handle HT characters
17
+ def remove_indentation(s)
18
+ l = s.lines
19
+ indent = l.grep(/\S/).map {|l| l[/^\s*/].size}.min
20
+ l.map {|li| li.sub(/^ {0,#{indent}}/, "")}.join
21
+ end
22
+
23
+ def add_quote(s)
24
+ l = s.lines
25
+ l.map {|li| "> #{li}"}.join
26
+ end
27
+
28
+ def process_chunk(s, nested, dedent, fold, quote)
29
+ process_includes(s) if nested
30
+ s = remove_indentation(s) if dedent
31
+ s = fold8792_1(s, *fold) if fold
32
+ s = add_quote(s) if quote
33
+ s
34
+ end
35
+
36
+ def process_includes(input)
37
+ input.gsub!(/^\{::include((?:-[a-z0-9]+)*)\s+(.*?)\}/) {
38
+ include_flags = $1
39
+ fn = [$2]
40
+ chunks = false
41
+ nested = false
42
+ dedent = false
43
+ fold = false
44
+ quote = false
45
+ include_flags.split("-") do |flag|
46
+ case flag
47
+ when ""
48
+ when "nested"
49
+ nested = true
50
+ when "quote"
51
+ quote = true
52
+ when "dedent"
53
+ dedent = true
54
+ when /\Afold(\d*)(left(\d*))?(dry)?\z/
55
+ fold = [$1.to_i, # col 0 for ''
56
+ ($3.to_i if $2), # left 0 for '', nil if no "left"
57
+ $4] # dry
58
+ when "all", "last"
59
+ fn = fn.flat_map{|n| Dir[n]}
60
+ fn = [fn.last] if flag == "last"
61
+ chunks = fn.map{ |f|
62
+ ret = process_chunk(File.read(f), nested, dedent, fold, quote)
63
+ nested = false; dedent = false; fold = false; quote = false
64
+ ret
65
+ }
66
+ else
67
+ warn "** unknown include flag #{flag}"
68
+ end
69
+ end
70
+ chunks = fn.map{|f| File.read(f)} unless chunks # no all/last
71
+ chunks = chunks.map {|ch| process_chunk(ch, nested, dedent, fold, quote)}
72
+ chunks.join.chomp
73
+ }
74
+ end
75
+
76
+
77
+ def boilerplate(key)
78
+ case key.downcase
79
+ when /\Abcp14(info)?(\+)?(-tagged)?\z/i
80
+ ret = ''
81
+ if $1
82
+ ret << <<RFC8174ise
83
+ Although this document is not an IETF Standards Track publication, it
84
+ adopts the conventions for normative language to provide clarity of
85
+ instructions to the implementer.
86
+ RFC8174ise
87
+ end
88
+ ret << <<RFC8174
89
+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
90
+ NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED",
91
+ "MAY", and "OPTIONAL" in this document are to be interpreted as
92
+ described in BCP 14 {{!RFC2119}} {{!RFC8174}} when, and only when, they
93
+ appear in all capitals, as shown here.
94
+ RFC8174
95
+ if $2
96
+ ret << <<PLUS
97
+ These words may also appear in this document in
98
+ lower case as plain English words, absent their normative meanings.
99
+ PLUS
100
+ end
101
+ if $3
102
+ ($options.v3_used ||= []) << "** need --v3 to tag bcp14"
103
+ ret << <<TAGGED
104
+
105
+ *[MUST]: <bcp14>
106
+ *[MUST NOT]: <bcp14>
107
+ *[REQUIRED]: <bcp14>
108
+ *[SHALL]: <bcp14>
109
+ *[SHALL NOT]: <bcp14>
110
+ *[SHOULD]: <bcp14>
111
+ *[SHOULD NOT]: <bcp14>
112
+ *[RECOMMENDED]: <bcp14>
113
+ *[NOT RECOMMENDED]: <bcp14>
114
+ *[MAY]: <bcp14>
115
+ *[OPTIONAL]: <bcp14>
116
+ TAGGED
117
+ end
118
+ ret
119
+ else
120
+ warn "** Unknwon boilerplate key: #{key}"
121
+ "{::boilerplate #{key}}"
122
+ end
123
+ end
124
+
125
+ def do_the_tls_dance
126
+ begin
127
+ require 'openssl'
128
+ File.open(OpenSSL::X509::DEFAULT_CERT_FILE) do end
129
+ # This guards against having an unreadable cert file (yes, that appears to happen a lot).
130
+ rescue
131
+ if Dir[File.join(OpenSSL::X509::DEFAULT_CERT_DIR, "*.pem")].empty?
132
+ # This guards against having no certs at all, not against missing the right one for IETF.
133
+ # Oh well.
134
+ warn "** Configuration problem with OpenSSL certificate store."
135
+ warn "** You may want to examine #{OpenSSL::X509::DEFAULT_CERT_FILE}"
136
+ warn "** and #{OpenSSL::X509::DEFAULT_CERT_DIR}."
137
+ warn "** Activating suboptimal workaround."
138
+ warn "** Occasionally run `certified-update` to maintain that workaround."
139
+ require 'certified'
140
+ end
141
+ end
142
+ end
143
+
144
+ RE_NL = /(?:\n|\r|\r\n)/
145
+ RE_SECTION = /---(?: +(\w+)(-?))?\s*#{RE_NL}(.*?#{RE_NL})(?=---(?:\s+\w+-?)?\s*#{RE_NL}|\Z)/m
146
+
147
+ NMDTAGS = ["{:/nomarkdown}\n\n", "\n\n{::nomarkdown}\n"]
148
+
149
+ NORMINFORM = { "!" => :normative, "?" => :informative }
150
+
151
+ def yaml_load(input, *args)
152
+ if YAML.respond_to?(:safe_load)
153
+ begin
154
+ YAML.safe_load(input, *args)
155
+ rescue ArgumentError
156
+ YAML.safe_load(input, permitted_classes: args[0], permitted_symbols: args[1], aliases: args[2])
157
+ end
158
+ else
159
+ YAML.load(input)
160
+ end
161
+ end
162
+
163
+ def process_kramdown_options(coding_override = nil,
164
+ smart_quotes = nil, typographic_symbols = nil,
165
+ header_kramdown_options = nil)
166
+
167
+ ascii_target = coding_override && coding_override =~ /ascii/
168
+ suppress_typography = ascii_target || $options.v3
169
+ entity_output = ascii_target ? :numeric : :as_char;
170
+
171
+ options = {input: 'RFC2629Kramdown', entity_output: entity_output, link_defs: {}}
172
+
173
+ if smart_quotes.nil? && suppress_typography
174
+ smart_quotes = false
175
+ end
176
+ if smart_quotes == false
177
+ smart_quotes = ["'".ord, "'".ord, '"'.ord, '"'.ord]
178
+ end
179
+ case smart_quotes
180
+ when Array
181
+ options[:smart_quotes] = smart_quotes
182
+ when nil, true
183
+ # nothin
184
+ else
185
+ warn "*** Can't deal with smart_quotes value #{smart_quotes.inspect}"
186
+ end
187
+
188
+ if typographic_symbols.nil? && suppress_typography
189
+ typographic_symbols = false
190
+ end
191
+ if typographic_symbols == false
192
+ typographic_symbols = Hash[::Kramdown::Parser::Kramdown::TYPOGRAPHIC_SYMS.map { |k, v|
193
+ if Symbol === v
194
+ [v.intern, k]
195
+ end
196
+ }.compact]
197
+ end
198
+ # warn [:TYPOGRAPHIC_SYMBOLS, typographic_symbols].to_yaml
199
+ case typographic_symbols
200
+ when Hash
201
+ options[:typographic_symbols] = typographic_symbols
202
+ when nil, true
203
+ # nothin
204
+ else
205
+ warn "*** Can't deal with typographic_symbols value #{typographic_symbols.inspect}"
206
+ end
207
+
208
+ if header_kramdown_options
209
+ options.merge! header_kramdown_options
210
+ end
211
+
212
+ $global_markdown_options = options # For nested calls in bibref annotation processing and xref text
213
+
214
+ options
215
+ end
216
+
217
+ XREF_SECTIONS_RE = ::Kramdown::Parser::RFC2629Kramdown::SECTIONS_RE
218
+ XSR_PREFIX = "#{XREF_SECTIONS_RE} of "
219
+ XSR_SUFFIX = ", (#{XREF_SECTIONS_RE})| \\((#{XREF_SECTIONS_RE})\\)"
220
+ XREF_TXT = ::Kramdown::Parser::RFC2629Kramdown::XREF_TXT
221
+ XREF_TXT_SUFFIX = " \\(#{XREF_TXT}\\)"
222
+
223
+ def spacify_re(s)
224
+ s.gsub(' ', '[\u00A0\s]+')
225
+ end
226
+
227
+ def xml_from_sections(input)
228
+
229
+ unless ENV["KRAMDOWN_NO_SOURCE"]
230
+ require 'kramdown-rfc/gzip-clone'
231
+ require 'base64'
232
+ compressed_input = Gzip.compress(input)
233
+ $source = Base64.encode64(compressed_input)
234
+ end
235
+
236
+ sections = input.scan(RE_SECTION)
237
+ # resulting in an array; each section is [section-label, nomarkdown-flag, section-text]
238
+
239
+ # the first section is a YAML with front matter parameters (don't put a label here)
240
+ # We put back the "---" plus gratuitous blank lines to hack the line number in errors
241
+ yaml_in = input[/---\s*/] << sections.shift[2]
242
+ ps = KramdownRFC::ParameterSet.new(yaml_load(yaml_in, [Date], [], true))
243
+
244
+ if v = ps[:v]
245
+ warn "*** unsupported RFCXML version #{v}" if v != 3
246
+ if $options.v2
247
+ warn "*** command line --v2 wins over document's 'v: #{v}'"
248
+ else
249
+ $options.v3 = true
250
+ $options.v = 3
251
+ ps.default!(:stand_alone, true)
252
+ ps.default!(:ipr, "trust200902")
253
+ ps.default!(:pi, {"toc" => true, "sortrefs" => true, "symrefs" => true})
254
+ end
255
+ end
256
+
257
+ coding_override = ps.has(:coding)
258
+ smart_quotes = ps[:smart_quotes]
259
+ typographic_symbols = ps[:typographic_symbols]
260
+ header_kramdown_options = ps[:kramdown_options]
261
+
262
+ kramdown_options = process_kramdown_options(coding_override,
263
+ smart_quotes, typographic_symbols,
264
+ header_kramdown_options)
265
+
266
+ # all the other sections are put in a Hash, possibly concatenated from parts there
267
+ sechash = Hash.new{ |h,k| h[k] = ""}
268
+ snames = [] # a stack of section names
269
+ sections.each do |sname, nmdflag, text|
270
+ # warn [:SNAME, sname, nmdflag, text[0..10]].inspect
271
+ nmdin, nmdout = {
272
+ "-" => ["", ""], # stay in nomarkdown
273
+ "" => NMDTAGS, # pop out temporarily
274
+ }[nmdflag || ""]
275
+ if sname
276
+ snames << sname # "--- label" -> push label (now current)
277
+ else
278
+ snames.pop # just "---" -> pop label (previous now current)
279
+ end
280
+ sechash[snames.last] << "#{nmdin}#{text}#{nmdout}"
281
+ end
282
+
283
+ ref_replacements = { }
284
+ anchor_to_bibref = { }
285
+
286
+ displayref = {}
287
+
288
+ [:ref, :normative, :informative].each do |sn|
289
+ if refs = ps.has(sn)
290
+ warn "*** bad section #{sn}: #{refs.inspect}" unless refs.respond_to? :each
291
+ refs.each do |k, v|
292
+ if v.respond_to? :to_str
293
+ if bibtagsys(v) # enable "foo: RFC4711" as a custom anchor definition
294
+ anchor_to_bibref[k] = v.to_str
295
+ end
296
+ ref_replacements[v.to_str] = k
297
+ end
298
+ if Hash === v
299
+ if aliasname = v.delete("-")
300
+ ref_replacements[aliasname] = k
301
+ end
302
+ if bibref = v.delete("=")
303
+ anchor_to_bibref[k] = bibref
304
+ end
305
+ if dr = v.delete("display")
306
+ displayref[k] = dr
307
+ end
308
+ end
309
+ end
310
+ end
311
+ end
312
+ open_refs = ps[:ref] || { } # consumed
313
+
314
+ norm_ref = { }
315
+
316
+ # convenience replacement of {{-coap}} with {{I-D.ietf-core-coap}}
317
+ # collect normative/informative tagging {{!RFC2119}} {{?RFC4711}}
318
+ sechash.each do |k, v|
319
+ next if k == "fluff"
320
+ v.gsub!(/{{(#{
321
+ spacify_re(XSR_PREFIX)
322
+ })?(?:([?!])(-)?|(-))([\w._\-]+)(?:=([\w.\/_\-]+))?(#{
323
+ XREF_TXT_SUFFIX
324
+ })?(#{
325
+ spacify_re(XSR_SUFFIX)
326
+ })?}}/) do |match|
327
+ xsr_prefix = $1
328
+ norminform = $2
329
+ replacing = $3 || $4
330
+ word = $5
331
+ bibref = $6
332
+ xrt_suffix = $7
333
+ xsr_suffix = $8
334
+ if replacing
335
+ if new = ref_replacements[word]
336
+ word = new
337
+ else
338
+ warn "*** no alias replacement for {{-#{word}}}"
339
+ word = "-#{word}"
340
+ end
341
+ end # now, word is the anchor
342
+ if bibref
343
+ if old = anchor_to_bibref[word]
344
+ if bibref != old
345
+ warn "*** conflicting definitions for xref #{word}: #{old} != #{bibref}"
346
+ end
347
+ else
348
+ anchor_to_bibref[word] = bibref
349
+ end
350
+ end
351
+
352
+ # things can be normative in one place and informative in another -> normative
353
+ # collect norm/inform above and assign it by priority here
354
+ if norminform
355
+ norm_ref[word] ||= norminform == '!' # one normative ref is enough
356
+ end
357
+ "{{#{xsr_prefix}#{word}#{xrt_suffix}#{xsr_suffix}}}"
358
+ end
359
+ end
360
+
361
+ [:normative, :informative].each do |k|
362
+ ps.rest[k.to_s] ||= { }
363
+ end
364
+
365
+ norm_ref.each do |k, v|
366
+ # could check bibtagsys here: needed if open_refs is nil or string
367
+ target = ps.has(v ? :normative : :informative)
368
+ warn "*** overwriting #{k}" if target.has_key?(k)
369
+ target[k] = open_refs[k] # add reference to normative/informative
370
+ end
371
+ # note that unused items from ref are considered OK, therefore no check for that here
372
+
373
+ # also should allow norm/inform check of other references
374
+ # {{?coap}} vs. {{!coap}} vs. {{-coap}} (undecided)
375
+ # or {{?-coap}} vs. {{!-coap}} vs. {{-coap}} (undecided)
376
+ # could require all references to be decided by a global flag
377
+ overlap = [:normative, :informative].map { |s| (ps.has(s) || { }).keys }.reduce(:&)
378
+ unless overlap.empty?
379
+ warn "*** #{overlap.join(', ')}: both normative and informative"
380
+ end
381
+
382
+ stand_alone = ps[:stand_alone]
383
+
384
+ [:normative, :informative].each do |sn|
385
+ if refs = ps[sn]
386
+ refs.each do |k, v|
387
+ href = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(k)
388
+ kramdown_options[:link_defs][k] = ["##{href}", nil] # allow [RFC2119] in addition to {{RFC2119}}
389
+
390
+ bibref = anchor_to_bibref[k] || k
391
+ bts, url = bibtagsys(bibref, k, stand_alone)
392
+ if bts && (!v || v == {} || v.respond_to?(:to_str))
393
+ if stand_alone
394
+ a = %{{: anchor="#{k}"}}
395
+ sechash[sn.to_s] << %{\n#{NMDTAGS[0]}\n![:include:](#{bts})#{a}\n#{NMDTAGS[1]}\n}
396
+ else
397
+ bts.gsub!('/', '_')
398
+ (ps.rest["bibxml"] ||= []) << [bts, url]
399
+ sechash[sn.to_s] << %{&#{bts};\n} # ???
400
+ end
401
+ else
402
+ unless v && Hash === v
403
+ warn "*** don't know how to expand ref #{k}"
404
+ next
405
+ end
406
+ if bts && !v.delete("override")
407
+ warn "*** warning: explicit settings completely override canned bibxml in reference #{k}"
408
+ end
409
+ sechash[sn.to_s] << KramdownRFC::ref_to_xml(href, v)
410
+ end
411
+ end
412
+ end
413
+ end
414
+
415
+ erbfilename = File.expand_path '../../../data/kramdown-rfc2629.erb', __FILE__
416
+ erbfile = File.read(erbfilename, coding: "UTF-8")
417
+ erb = ERB.trim_new(erbfile, '-')
418
+ # remove redundant nomarkdown pop outs/pop ins as they confuse kramdown
419
+ input = erb.result(binding).gsub(%r"{::nomarkdown}\s*{:/nomarkdown}"m, "")
420
+ ps.warn_if_leftovers
421
+ sechash.delete("fluff") # fluff is a "commented out" section
422
+ if !sechash.empty? # any sections unused by the ERb file?
423
+ warn "*** sections left #{sechash.keys.inspect}!"
424
+ end
425
+
426
+ [input, kramdown_options, coding_override]
427
+ end
428
+
429
+ XML_RESOURCE_ORG_PREFIX = Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_PREFIX
430
+
431
+ # return XML entity name, url, rewrite_anchor flag
432
+ def bibtagsys(bib, anchor=nil, stand_alone=true)
433
+ if bib =~ /\Arfc(\d+)/i
434
+ rfc4d = "%04d" % $1.to_i
435
+ [bib.upcase,
436
+ "#{XML_RESOURCE_ORG_PREFIX}/bibxml/reference.RFC.#{rfc4d}.xml"]
437
+ elsif $options.v3 && bib =~ /\A(bcp|std)(\d+)/i
438
+ n4d = "%04d" % $2.to_i
439
+ [bib.upcase,
440
+ "#{XML_RESOURCE_ORG_PREFIX}/bibxml-rfcsubseries-new/reference.#{$1.upcase}.#{n4d}.xml"]
441
+ elsif bib =~ /\A([-A-Z0-9]+)\./ &&
442
+ (xro = Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_MAP[$1])
443
+ dir, _ttl, rewrite_anchor = xro
444
+ bib1 = ::Kramdown::Parser::RFC2629Kramdown.idref_cleanup(bib)
445
+ if anchor && bib1 != anchor
446
+ if rewrite_anchor
447
+ a = %{?anchor=#{anchor}}
448
+ else
449
+ if !stand_alone
450
+ warn "*** selecting a custom anchor '#{anchor}' for '#{bib1}' requires stand_alone mode"
451
+ warn " the output will need manual editing to correct this"
452
+ end
453
+ end
454
+ end
455
+ [bib1,
456
+ "#{XML_RESOURCE_ORG_PREFIX}/#{dir}/reference.#{bib}.xml#{a}"]
457
+ end
458
+ end
459
+
460
+ def read_encodings
461
+ encfilename = File.expand_path '../../../data/encoding-fallbacks.txt', __FILE__
462
+ encfile = File.read(encfilename, coding: "UTF-8")
463
+ Hash[encfile.lines.map{|l|
464
+ l.chomp!;
465
+ x, s = l.split(" ", 2)
466
+ [x.hex.chr(Encoding::UTF_8), s || " "]}]
467
+ end
468
+
469
+ FALLBACK = read_encodings
470
+
471
+ def expand_tabs(s, tab_stops = 8)
472
+ s.gsub(/([^\t\n]*)\t/) do
473
+ $1 + " " * (tab_stops - ($1.size % tab_stops))
474
+ end
475
+ end
476
+
477
+
478
+ require 'optparse'
479
+ require 'ostruct'
480
+
481
+ $options ||= OpenStruct.new
482
+ op = OptionParser.new do |opts|
483
+ opts.banner = <<BANNER
484
+ Usage: kramdown-rfc2629 [options] file.md|file.mkd > file.xml
485
+ Version: #{KDRFC_VERSION}
486
+ BANNER
487
+ opts.on("-V", "--version", "Show version and exit") do |v|
488
+ puts "kramdown-rfc2629 #{KDRFC_VERSION}"
489
+ exit
490
+ end
491
+ opts.on("-H", "--help", "Show option summary and exit") do |v|
492
+ puts opts
493
+ exit
494
+ end
495
+ opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
496
+ $options.verbose = v
497
+ end
498
+ opts.on("-3", "--[no-]v3", "Use RFCXML v3 processing rules") do |v|
499
+ $options.v3 = v
500
+ end
501
+ opts.on("-2", "--[no-]v2", "Use RFCXML v2 processing rules") do |v|
502
+ $options.v2 = v
503
+ end
504
+ end
505
+ op.parse!
506
+
507
+ if $options.v2 && $options.v3
508
+ warn "*** can't have v2 and eat v3 cake"
509
+ $options.v2 = false
510
+ end
511
+
512
+ if $options.v3.nil? && !$options.v2
513
+ if Time.now.to_i >= 1645567342 # Time.parse("2022-02-22T22:02:22Z").to_i
514
+ $options.v3 = true # new default from the above date
515
+ end
516
+ end
517
+
518
+ warn "*** v2 #{$options.v2.inspect} v3 #{$options.v3.inspect}" if $options.verbose
519
+
520
+ input = ARGF.read
521
+ if input[0] == "\uFEFF"
522
+ warn "*** There is a leading byte order mark. Ignored."
523
+ input[0..0] = ''
524
+ end
525
+ if input[-1] != "\n"
526
+ # warn "*** added missing newline at end"
527
+ input << "\n" # fix #26
528
+ end
529
+ process_includes(input) unless ENV["KRAMDOWN_SAFE"]
530
+ input.gsub!(/^\{::boilerplate\s+(.*?)\}/) {
531
+ boilerplate($1)
532
+ }
533
+ if input =~ /[\t]/
534
+ warn "*** Input contains HT (\"tab\") characters. Undefined behavior will ensue."
535
+ input = expand_tabs(input)
536
+ end
537
+
538
+ if input =~ /\A---/ # this is a sectionized file
539
+ do_the_tls_dance unless ENV["KRAMDOWN_DONT_VERIFY_HTTPS"]
540
+ input, options, coding_override = xml_from_sections(input)
541
+ else
542
+ options = process_kramdown_options # all default
543
+ end
544
+ if input =~ /\A<\?xml/ # if this is a whole XML file, protect it
545
+ input = "{::nomarkdown}\n#{input}\n{:/nomarkdown}\n"
546
+ end
547
+
548
+ if $options.v3_used && !$options.v3
549
+ warn $options.v3_used
550
+ $options.v3_used = nil
551
+ $options.v3 = true
552
+ end
553
+
554
+ if coding_override
555
+ input = input.encode(Encoding.find(coding_override), fallback: FALLBACK)
556
+ end
557
+
558
+ # 1.4.17: because of UTF-8 bibxml files, kramdown always needs to see UTF-8 (!)
559
+ if input.encoding != Encoding::UTF_8
560
+ input = input.encode(Encoding::UTF_8)
561
+ end
562
+
563
+ # warn "options: #{options.inspect}"
564
+ doc = Kramdown::Document.new(input, options)
565
+ $stderr.puts doc.warnings.to_yaml unless doc.warnings.empty?
566
+ output = doc.to_rfc2629
567
+
568
+ if $options.v3_used && !$options.v3
569
+ warn $options.v3_used
570
+ $options.v3 = true
571
+ end
572
+
573
+ if coding_override
574
+ output = output.encode(Encoding.find(coding_override), fallback: FALLBACK)
575
+ end
576
+
577
+ puts output
@@ -18,7 +18,8 @@ class KDRFC
18
18
  KDRFC_PREPEND = [ENV["KDRFC_PREPEND"]].compact
19
19
 
20
20
  def v3_flag?
21
- @options.v3 ? ["--v3"] : []
21
+ [*(@options.v3 ? ["--v3"] : []),
22
+ *(@options.v2 ? ["--v2"] : [])]
22
23
  end
23
24
 
24
25
  def process_mkd(input, output)
@@ -79,6 +80,7 @@ MODE_AS_FORMAT = {
79
80
  }
80
81
  }
81
82
 
83
+ # XXX move to author-tools@ietf.org API
82
84
  def process_xml_remotely(input, output, *flags)
83
85
  warn "* converting remotely from xml #{input} to txt #{output}" if @options.verbose
84
86
  format = flags[0] || "--text"
@@ -14,7 +14,15 @@ module KramdownRFC
14
14
  @f.delete(pn.to_s)
15
15
  end
16
16
  def []=(pn, val)
17
- @f[pn] = val
17
+ @f[pn.to_s] = val
18
+ end
19
+ def default(pn, &block)
20
+ @f.fetch(pn.to_s, &block)
21
+ end
22
+ def default!(pn, value)
23
+ default(pn) {
24
+ @f[pn.to_s] = value
25
+ }
18
26
  end
19
27
  def has(pn)
20
28
  @f[pn.to_s]
@@ -808,7 +808,7 @@ COLORS
808
808
  out ="#{' '*indent}<dd><t/></dd>\n" # you can't make this one up
809
809
  end
810
810
  opts[:haddt] = true
811
- out << "#{' '*indent}<dt#{el_html_attributes(el)}>\n#{inner(el, indent, opts)}#{' '*indent}</dt>\n"
811
+ out << "#{' '*indent}<dt#{el_html_attributes(el)}>#{inner(el, indent, opts)}</dt>\n"
812
812
  else
813
813
  close = "#{' '*indent}</t>\n" * @in_dt
814
814
  @in_dt = 1
@@ -914,6 +914,17 @@ COLORS
914
914
  gi = el.attr.delete('gi')
915
915
  res = inner(el, indent, opts)
916
916
  target = el.attr['target']
917
+ if target[0..1] == "{{"
918
+ # XXX ignoring all attributes and content
919
+ s = ::Kramdown::Converter::Rfc2629::process_markdown(target)
920
+ # if res != '' && s[-2..-1] == '/>'
921
+ # if s =~ /\A<([-A-Za-z0-9_.]+) /
922
+ # gi ||= $1
923
+ # end
924
+ # s[-2..-1] = ">#{res}</#{gi}>"
925
+ # end
926
+ return s
927
+ end
917
928
  if target[0] == "#" # handle [](#foo) as xref as in RFC 7328
918
929
  el.attr['target'] = target = target[1..-1]
919
930
  if target.downcase == res.downcase
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kramdown-rfc2629
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.26
4
+ version: 1.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-09 00:00:00.000000000 Z
11
+ date: 2022-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kramdown
@@ -67,10 +67,11 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.0'
69
69
  description: |-
70
- An RFC7749 (XML2RFC) generating backend for Thomas Leitner's
70
+ An RFCXML (RFC 799x) generating backend for Thomas Leitner's
71
71
  "kramdown" markdown parser. Mostly useful for RFC writers.
72
72
  email: cabo@tzi.org
73
73
  executables:
74
+ - kramdown-rfc
74
75
  - kramdown-rfc2629
75
76
  - doilit
76
77
  - kramdown-rfc-extract-markdown
@@ -86,6 +87,7 @@ files:
86
87
  - bin/de-gfm
87
88
  - bin/doilit
88
89
  - bin/kdrfc
90
+ - bin/kramdown-rfc
89
91
  - bin/kramdown-rfc-cache-i-d-bibxml
90
92
  - bin/kramdown-rfc-cache-subseries-bibxml
91
93
  - bin/kramdown-rfc-extract-markdown
@@ -94,6 +96,7 @@ files:
94
96
  - data/kramdown-rfc2629.erb
95
97
  - data/math.json
96
98
  - kramdown-rfc2629.gemspec
99
+ - lib/kramdown-rfc/command.rb
97
100
  - lib/kramdown-rfc/erb.rb
98
101
  - lib/kramdown-rfc/gzip-clone.rb
99
102
  - lib/kramdown-rfc/kdrfc-processor.rb
@@ -120,8 +123,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
123
  - !ruby/object:Gem::Version
121
124
  version: '0'
122
125
  requirements: []
123
- rubygems_version: 3.3.3
126
+ rubygems_version: 3.3.7
124
127
  signing_key:
125
128
  specification_version: 4
126
- summary: Kramdown extension for generating RFC 7749 XML.
129
+ summary: Kramdown extension for generating RFCXML (RFC 799x).
127
130
  test_files: []