kramdown-rfc2629 1.6.31 → 1.6.33

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78da707841d2475396ae7578307bf10ab16440755d79591078490738b9dd89ed
4
- data.tar.gz: dc0143966fdc29ebe27e1cb07c28e4541b27038fac6d5a783d3dc2368e50d657
3
+ metadata.gz: d4c663bed0e8e2dc848a9e532ba201b9e9a26b4090368c0d83f8c518275df710
4
+ data.tar.gz: a2ac5d0be0615b41ecd65964ca7dfd61e3163fbb3aa612994fa5ac05ae1504ca
5
5
  SHA512:
6
- metadata.gz: 71abd171f1fce10fd52d5ba1d1cbedcd7c982090acf5d120c23be6702528a2eb5e09da2da9a6fc2d161eba5fc0980f5850eced87c403b7d21971e52588f849b8
7
- data.tar.gz: ea9ffd32a3189c778f3e74ead8ea43e8bc3961e9886a3b2055377da32f4ec36148eeee56c120fa627c3739cb41c9ab037d48f1300801ce3a6e61d96564003cb6
6
+ metadata.gz: 90ef1269825ef2b9484fc358cf92fa7ffa1ce255ea6e0b520cf99e98ed9f463551bf060d9af84de1ef87f0bd2e8a12442c4b9dc866858e1ed18bf23d4084829a
7
+ data.tar.gz: 840c014bc4efcabb1491e81126f577541bb237b0fa92a06fdaa293556eed480997829a357728da96caadc480347d32ddfb3be76a8e7027c986c775adff9babc7
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby -KU
2
+ require 'rexml/document' # for SVG and bibxml acrobatics
3
+ require 'yaml'
4
+ require 'shellwords'
5
+ require 'fileutils'
6
+ require_relative '../lib/kramdown-rfc/rfc8792'
7
+
8
+ def clean(s)
9
+ s.gsub!(/\//, ":")
10
+ s.gsub!(/[^:\w]/, "_") # handles leading dot, too -- s.gsub!(/\A([.]+)/) {"_" * $1.size } otherwise
11
+ s
12
+ end
13
+
14
+ target = nil
15
+ dir = nil
16
+ unfold = true
17
+ targets = [:list, :files, :zip, :yaml]
18
+ require 'optparse'
19
+ begin
20
+ op = OptionParser.new do |opts|
21
+ opts.banner = "Usage: kramdown-rfc-extract-sourcecode [options] document.xml"
22
+ opts.on("-tFMT", "--to=FMT", targets, "Target format #{targets.map(&:to_s)}") do |v|
23
+ target = v
24
+ end
25
+ opts.on("-dDIR", "--dir=DIR", "Target directory (default: sourcecode)") do |v|
26
+ dir = v
27
+ end
28
+ opts.on("-f", "--[no-]unfold", "RFC8972-unfold (default: yes)") do |v|
29
+ unfold = v
30
+ end
31
+ end
32
+ op.parse!
33
+ rescue Exception => e
34
+ warn e
35
+ exit 1
36
+ end
37
+ if dir
38
+ target ||= :files
39
+ unless [:files, :zip].include? target
40
+ warn "** Unused argument --dir=#{dir}"
41
+ end
42
+ end
43
+ dir ||= "sourcecode"
44
+
45
+ target ||= :list
46
+
47
+ gensym = "unnamed-000"
48
+ taken = Hash.new { |h, k| h[k] = Hash.new }
49
+ warned = Hash.new { |h, k| h[k] = Hash.new }
50
+ d = REXML::Document.new(ARGF)
51
+ REXML::XPath.each(d.root, "//sourcecode|//artwork") do |x|
52
+ if ty = x[:type]
53
+ ty = clean(ty)
54
+ name = x[:name] || gensym.succ!
55
+ name = clean(name)
56
+ if taken[ty][name]
57
+ unless warned[ty][name]
58
+ warn "Concatenating to #{ty}/#{name}."
59
+ warned[ty][name] = true
60
+ end
61
+ else
62
+ taken[ty][name] = ''
63
+ end
64
+ taken[ty][name] << handle_artwork_sourcecode(x.text, unfold)
65
+ end
66
+ end
67
+
68
+ def make_directory_from(dir, taken)
69
+ if File.exist?(dir)
70
+ bak = "#{dir}.bak"
71
+ begin
72
+ FileUtils.mv(dir, bak)
73
+ rescue Errno::EEXIST
74
+ bak.succ!
75
+ retry
76
+ end
77
+ end
78
+ FileUtils.mkdir_p(dir)
79
+ taken.each { |dir1, v|
80
+ FileUtils.mkdir_p("#{dir}/#{dir1}")
81
+ v.each { |fn, value|
82
+ IO.write("#{dir}/#{dir1}/#{fn}", value)
83
+ }
84
+ }
85
+ end
86
+
87
+ case target
88
+ when :yaml
89
+ puts taken.to_yaml
90
+ when :list
91
+ puts Hash[
92
+ taken.map {|k, v|
93
+ [k, v.keys]
94
+ }
95
+ ].to_yaml
96
+ when :files
97
+ make_directory_from(dir, taken)
98
+ when :zip
99
+ make_directory_from(dir, taken)
100
+ zip = "#{dir}.zip"
101
+ if File.exist?(zip)
102
+ bak = "#{zip}.bak"
103
+ begin
104
+ FileUtils.mv(zip, bak)
105
+ rescue Errno::EEXIST # This doesn't actually happen. XXX
106
+ bak.succ!
107
+ retry
108
+ end
109
+ end
110
+ cmd = ["zip", "-mr", zip, dir].shelljoin
111
+ warn cmd
112
+ system(cmd)
113
+ end
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'kramdown-rfc2629'
3
- s.version = '1.6.31'
3
+ s.version = '1.6.33'
4
4
  s.summary = "Kramdown extension for generating RFCXML (RFC 799x)."
5
5
  s.description = %{An RFCXML (RFC 799x) generating backend for Thomas Leitner's
6
6
  "kramdown" markdown parser. Mostly useful for RFC writers.}
@@ -13,10 +13,11 @@ spec = Gem::Specification.new do |s|
13
13
  s.add_dependency('unicode-scripts', '~> 1.0')
14
14
  s.add_dependency('net-http-persistent', '~> 4.0')
15
15
  s.add_dependency('differ', '~>0.1')
16
- s.files = Dir['lib/**/*.rb'] + %w(README.md LICENSE kramdown-rfc2629.gemspec bin/kdrfc bin/kramdown-rfc bin/kramdown-rfc2629 bin/doilit bin/echars bin/kramdown-rfc-extract-markdown data/kramdown-rfc2629.erb data/encoding-fallbacks.txt data/math.json bin/kramdown-rfc-cache-subseries-bibxml bin/kramdown-rfc-autolink-iref-cleanup bin/de-gfm bin/kramdown-rfc-clean-svg-ids)
16
+ s.files = Dir['lib/**/*.rb'] + %w(README.md LICENSE kramdown-rfc2629.gemspec bin/kdrfc bin/kramdown-rfc bin/kramdown-rfc2629 bin/doilit bin/echars bin/kramdown-rfc-extract-markdown bin/kramdown-rfc-extract-sourcecode data/kramdown-rfc2629.erb data/encoding-fallbacks.txt data/math.json bin/kramdown-rfc-cache-subseries-bibxml bin/kramdown-rfc-autolink-iref-cleanup bin/de-gfm bin/kramdown-rfc-clean-svg-ids)
17
17
  s.require_path = 'lib'
18
18
  s.executables = ['kramdown-rfc', 'kramdown-rfc2629', 'doilit', 'echars',
19
19
  'kramdown-rfc-extract-markdown',
20
+ 'kramdown-rfc-extract-sourcecode',
20
21
  'kdrfc', 'kramdown-rfc-cache-i-d-bibxml',
21
22
  'kramdown-rfc-cache-subseries-bibxml',
22
23
  'kramdown-rfc-autolink-iref-cleanup',
@@ -13,13 +13,6 @@ KDRFC_VERSION=Gem.loaded_specs["kramdown-rfc2629"].version rescue "unknown-versi
13
13
 
14
14
  Encoding.default_external = "UTF-8" # wake up, smell the coffee
15
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
16
  def add_quote(s)
24
17
  l = s.lines
25
18
  l.map {|li| "> #{li}"}.join
@@ -141,8 +134,8 @@ def do_the_tls_dance
141
134
  end
142
135
  end
143
136
 
144
- RE_NL = /(?:\n|\r|\r\n)/
145
- RE_SECTION = /---(?: +(\w+)(-?))?\s*#{RE_NL}(.*?#{RE_NL})(?=---(?:\s+\w+-?)?\s*#{RE_NL}|\Z)/m
137
+ RE_NL = /(?:\r\n|\n|\r)/
138
+ RE_SECTION = /---(?: +(\w+)(-?))? *#{RE_NL}(.*?#{RE_NL})(?=---(?:\s+\w+-?)?\s*#{RE_NL}|\Z)/m
146
139
 
147
140
  NMDTAGS = ["{:/nomarkdown}\n\n", "\n\n{::nomarkdown}\n"]
148
141
 
@@ -240,6 +233,12 @@ def xml_from_sections(input)
240
233
 
241
234
  sections = input.scan(RE_SECTION)
242
235
  # resulting in an array; each section is [section-label, nomarkdown-flag, section-text]
236
+ line = 1 # skip "---"
237
+ sections.each do |section|
238
+ section << line
239
+ line += 1 + section[2].lines.count
240
+ end
241
+ # warn "#{line-1} lines"
243
242
 
244
243
  # the first section is a YAML with front matter parameters (don't put a label here)
245
244
  # We put back the "---" plus gratuitous blank lines to hack the line number in errors
@@ -278,7 +277,7 @@ def xml_from_sections(input)
278
277
  # all the other sections are put in a Hash, possibly concatenated from parts there
279
278
  sechash = Hash.new{ |h,k| h[k] = ""}
280
279
  snames = [] # a stack of section names
281
- sections.each do |sname, nmdflag, text|
280
+ sections.each do |sname, nmdflag, text, line|
282
281
  # warn [:SNAME, sname, nmdflag, text[0..10]].inspect
283
282
  nmdin, nmdout = {
284
283
  "-" => ["", ""], # stay in nomarkdown
@@ -289,7 +288,7 @@ def xml_from_sections(input)
289
288
  else
290
289
  snames.pop # just "---" -> pop label (previous now current)
291
290
  end
292
- sechash[snames.last] << "#{nmdin}#{text}#{nmdout}"
291
+ sechash[snames.last] << "#{nmdin}<?line #{line}?>\n#{text}#{nmdout}"
293
292
  end
294
293
 
295
294
  ref_replacements = { }
@@ -540,7 +539,9 @@ if input[-1] != "\n"
540
539
  end
541
540
  process_includes(input) unless ENV["KRAMDOWN_SAFE"]
542
541
  input.gsub!(/^\{::boilerplate\s+(.*?)\}/) {
543
- boilerplate($1)
542
+ bp = boilerplate($1)
543
+ delta = bp.lines.count
544
+ bp + "<?line -#{delta+1}?>\n"
544
545
  }
545
546
  if input =~ /[\t]/
546
547
  warn "*** Input contains HT (\"tab\") characters. Undefined behavior will ensue."
@@ -1,4 +1,45 @@
1
+
2
+ # Note that this doesn't attempt to handle HT characters
3
+ def remove_indentation(s)
4
+ l = s.lines
5
+ indent = l.grep(/\S/).map {|l| l[/^\s*/].size}.min
6
+ l.map {|li| li.sub(/^ {0,#{indent}}/, "")}.join
7
+ end
8
+
9
+ def trim_empty_lines_around(s) # this deletes the trailing newline, which may need to be reconstructed
10
+ s.sub(/\A(\r?\n)*/, '').sub(/(\r?\n)*\z/, '')
11
+ end
12
+
13
+ def fix_unterminated_line(s)
14
+ s.sub(/[^\n]\z/) { "#$&\n" } # XXX
15
+ end
16
+
17
+ def handle_artwork_sourcecode(s, unfold = true)
18
+ s = trim_empty_lines_around(s)
19
+ s = unfold8792(s) if unfold
20
+ fix_unterminated_line(s)
21
+ end
22
+
1
23
  FOLD_MSG = "NOTE: '\\' line wrapping per RFC 8792".freeze
24
+ UNFOLD_RE = /\A.*#{FOLD_MSG.sub("\\", "(\\\\\\\\\\\\\\\\?)")}.*\n\r?\n/
25
+
26
+ def unfold8792(s)
27
+ if s =~ UNFOLD_RE
28
+ indicator = $1
29
+ s = $'
30
+ sub = case indicator
31
+ when "\\"
32
+ s.gsub!(/\\\n[ \t]*/, '')
33
+ when "\\\\"
34
+ s.gsub!(/\\\n[ \t]*\\/, '')
35
+ else
36
+ fail "indicator" # Cannot happen
37
+ end
38
+ warn "** encountered RFC 8792 header without folded lines" unless sub
39
+ end
40
+ s
41
+ end
42
+
2
43
  MIN_FOLD_COLUMNS = FOLD_MSG.size
3
44
  FOLD_COLUMNS = 69
4
45
  RE_IDENT = /\A[A-Za-z0-9_]\z/
@@ -23,6 +23,7 @@ require 'json' # for math
23
23
  require 'rexml/document' # for SVG and bibxml acrobatics
24
24
 
25
25
  require 'kramdown-rfc/doi' # for fetching information for a DOI
26
+ require 'kramdown-rfc/rfc8792'
26
27
 
27
28
  class Object
28
29
  def deep_clone
@@ -315,15 +316,21 @@ module Kramdown
315
316
  def initialize(*doc)
316
317
  super
317
318
  @sec_level = 1
319
+ @location_delta = 100000 # until reset
320
+ @location_correction = 0 # pre-scanning corrections
318
321
  @in_dt = 0
319
322
  @footnote_names_in_use = {}
320
323
  end
321
324
 
325
+ def correct_location(location)
326
+ location + @location_delta + @location_correction
327
+ end
328
+
322
329
  def convert(el, indent = -INDENTATION, opts = {})
323
330
  if el.children[-1].type == :raw
324
331
  raw = convert1(el.children.pop, indent, opts)
325
332
  end
326
- "#{convert1(el, indent, opts)}#{end_sections(1, indent)}#{raw}"
333
+ "#{convert1(el, indent, opts)}#{end_sections(1, indent, el.options[:location])}#{raw}"
327
334
  end
328
335
 
329
336
  def convert1(el, indent, opts = {})
@@ -658,34 +665,80 @@ COLORS
658
665
  if anchor = el.attr['anchor']
659
666
  "##{anchor}"
660
667
  elsif lineno = el.options[:location]
661
- "approx. line #{lineno}" # XXX
668
+ "#{correct_location(lineno)}"
662
669
  else
663
670
  "UNKNOWN"
664
671
  end
672
+ preprocs = el.attr.delete("pre")
673
+ checks = el.attr.delete("check")
674
+ postprocs = el.attr.delete("post")
665
675
  case t
666
676
  when "json"
677
+ checks ||= "json"
678
+ when /\A(.*)-from-yaml\z/
679
+ t = $1
680
+ preprocs ||= "yaml2json"
681
+ end
682
+ preprocs = (preprocs || '').split("-")
683
+ checks = (checks || '').split("-")
684
+ postprocs = (postprocs || '').split("-")
685
+ result = sourcecode_checkproc(preprocs, checks, postprocs, loc_str, result)
686
+ "#{' '*indent}<figure#{el_html_attributes(el)}><#{gi}#{html_attributes(artwork_attr)}><![CDATA[#{result}#{result =~ /\n\Z/ ? '' : "\n"}]]></#{gi}></figure>\n"
687
+ end
688
+ end
689
+ end
690
+
691
+ def sourcecode_proc(proc, loc_str, result)
692
+ case proc
693
+ when "dedent"
694
+ result = remove_indentation(result)
695
+ when /\Afold(\d*)(left(\d*))?(dry)?\z/
696
+ fold = [$1.to_i, # col 0 for ''
697
+ ($3.to_i if $2), # left 0 for '', nil if no "left"
698
+ $4] # dry
699
+ result = fix_unterminated_line(fold8792_1(trim_empty_lines_around(result), *fold)) # XXX
700
+ when "yaml2json"
701
+ begin
702
+ y = YAML.safe_load(result, aliases: true, filename: loc_str)
703
+ result = JSON.pretty_generate(y)
704
+ rescue => e
705
+ warn "*** #{loc_str}: YAML isn't: #{e.message}\n"
706
+ end
707
+ else
708
+ warn "*** #{loc_str}: unknown proc '#{proc}'"
709
+ end
710
+ result
711
+ end
712
+
713
+ def sourcecode_checkproc(preprocs, checks, postprocs, loc_str, result)
714
+ preprocs.each do |proc|
715
+ result = sourcecode_proc(proc, loc_str, result)
716
+ end if preprocs
717
+ check_input = result
718
+ checks.each do |check|
719
+ case check
720
+ when "skipheader"
721
+ check_input = handle_artwork_sourcecode(check_input).sub(/.*?\n\n/m, '')
722
+ when "json"
723
+ # check for 8792; undo if needed:
724
+ begin
725
+ JSON.load(handle_artwork_sourcecode(check_input))
726
+ rescue => e
727
+ err1 = "*** #{loc_str}: JSON isn't: #{JSON.dump(e.message[0..40])}\n"
667
728
  begin
668
- JSON.load(result)
669
- rescue => e
670
- err1 = "*** #{loc_str}: JSON isn't: #{e.message[0..40]}\n"
671
- begin
672
- JSON.load("{" << result << "}")
673
- rescue => e
674
- warn err1 << "*** not even with braces added around: #{e.message[0..40]}"
675
- end
676
- end
677
- when "json-from-yaml"
678
- begin
679
- y = YAML.safe_load(result, aliases: true, filename: loc_str)
680
- result = JSON.pretty_generate(y)
681
- t = "json" # XXX, this could be another format!
729
+ JSON.load("{" << check_input << "}")
682
730
  rescue => e
683
- warn "*** YAML isn't: #{e.message}\n"
731
+ warn err1 << "*** not even with braces added around: #{JSON.dump(e.message[0..40])}"
684
732
  end
685
733
  end
686
- "#{' '*indent}<figure#{el_html_attributes(el)}><#{gi}#{html_attributes(artwork_attr)}><![CDATA[#{result}#{result =~ /\n\Z/ ? '' : "\n"}]]></#{gi}></figure>\n"
734
+ else
735
+ warn "*** #{loc_str}: unknown check '#{check}'"
687
736
  end
688
- end
737
+ end if checks
738
+ postprocs.each do |proc|
739
+ result = sourcecode_proc(proc, loc_str, result)
740
+ end if postprocs
741
+ result
689
742
  end
690
743
 
691
744
  def mk_artwork(artwork_attr, typ, content)
@@ -707,7 +760,7 @@ COLORS
707
760
  end
708
761
  end
709
762
 
710
- def end_sections(to_level, indent)
763
+ def end_sections(to_level, indent, location)
711
764
  if indent < 0
712
765
  indent = 0
713
766
  end
@@ -716,7 +769,7 @@ COLORS
716
769
  @sec_level = to_level
717
770
  "#{' '*indent}</section>\n" * delta
718
771
  else
719
- $stderr.puts "Incorrect section nesting: Need to start with 1"
772
+ $stderr.puts "** #{correct_location(location)}: Bad section nesting: start heading level at 1 and increment by 1"
720
773
  end
721
774
  end
722
775
 
@@ -768,7 +821,7 @@ COLORS
768
821
  clean, irefs = clean_pcdata(inner_a(el, indent, opts))
769
822
  el.attr['title'] = clean
770
823
  end
771
- "#{end_sections(el.options[:level], indent)}#{' '*indent}<section#{@sec_level += 1; el_html_attributes(el)}>#{irefs}\n"
824
+ "#{end_sections(el.options[:level], indent, el.options[:location])}#{' '*indent}<section#{@sec_level += 1; el_html_attributes(el)}>#{irefs}\n"
772
825
  end
773
826
 
774
827
  def convert_hr(el, indent, opts) # misuse for page break
@@ -885,6 +938,15 @@ COLORS
885
938
  end
886
939
 
887
940
  def convert_xml_comment(el, indent, opts)
941
+ if el.value =~ /\A<\?line (([-+]?)[0-9]+)\?>\z/
942
+ lineno = $1.to_i
943
+ case $2
944
+ when '' # absolute
945
+ @location_delta = lineno - el.options[:location]
946
+ when '+', '-' # correction (pre-scanning!)
947
+ @location_correction += lineno
948
+ end
949
+ end
888
950
  if el.options[:category] == :block && !el.options[:parent_is_raw]
889
951
  ' '*indent + el.value + "\n"
890
952
  else
@@ -1277,7 +1339,7 @@ COLORS
1277
1339
  end
1278
1340
 
1279
1341
  def convert_raw(el, indent, opts)
1280
- end_sections(1, indent) +
1342
+ end_sections(1, indent, el.options[:location]) +
1281
1343
  el.value + (el.options[:category] == :block ? "\n" : '')
1282
1344
  end
1283
1345
 
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.6.31
4
+ version: 1.6.33
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-20 00:00:00.000000000 Z
11
+ date: 2023-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kramdown
@@ -146,6 +146,7 @@ executables:
146
146
  - doilit
147
147
  - echars
148
148
  - kramdown-rfc-extract-markdown
149
+ - kramdown-rfc-extract-sourcecode
149
150
  - kdrfc
150
151
  - kramdown-rfc-cache-i-d-bibxml
151
152
  - kramdown-rfc-cache-subseries-bibxml
@@ -167,6 +168,7 @@ files:
167
168
  - bin/kramdown-rfc-cache-subseries-bibxml
168
169
  - bin/kramdown-rfc-clean-svg-ids
169
170
  - bin/kramdown-rfc-extract-markdown
171
+ - bin/kramdown-rfc-extract-sourcecode
170
172
  - bin/kramdown-rfc2629
171
173
  - data/encoding-fallbacks.txt
172
174
  - data/kramdown-rfc2629.erb