kramdown-rfc2629 1.7.11 → 1.7.13
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.
- checksums.yaml +4 -4
- data/README.md +5 -0
- data/bin/kramdown-rfc-lsr +269 -0
- data/kramdown-rfc2629.gemspec +3 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37a6e52b1686d310bf22c8c2530ce893e3ea30b74675b6cdd17143c141a51321
|
4
|
+
data.tar.gz: f9cedeb1b71146d4be4affd7ba343c1a2a497b607e82565b772445d7fc686c06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92fc3fc628cbcc21b0368f692f078206caa01fa8d5eb8f712777f369632f1d472efa20c0af96cd71a0e0e2752449d1efbeb2c354973fca4f740722545811b213
|
7
|
+
data.tar.gz: 924dc4cd075193b1cc9310ddee259290e5bd0026a5ccbb7ff2da65ea897ec3a6560e2fccbaee5122cacaa262ac9d4b692bfb14417359b6f39dfbdb8aaea7b340
|
data/README.md
CHANGED
@@ -12,6 +12,11 @@ Who would care? Anybody who is writing Internet-Drafts and RFCs in
|
|
12
12
|
the [IETF][] and prefers (or has co-authors who prefer) to do part of
|
13
13
|
their work in markdown.
|
14
14
|
|
15
|
+
kramdown-rfc is documented on this page, and also on
|
16
|
+
[the wiki][].
|
17
|
+
|
18
|
+
[the wiki]: https://github.com/cabo/kramdown-rfc/wiki
|
19
|
+
|
15
20
|
# Usage
|
16
21
|
|
17
22
|
Start by installing the kramdown-rfc gem (this automatically
|
@@ -0,0 +1,269 @@
|
|
1
|
+
#!/usr/bin/env ruby -KU
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# List Section References from a RFCXML document
|
5
|
+
#
|
6
|
+
# (PoC, in urgent need of refactoring)
|
7
|
+
# Requires xml2rfc and tidy commands in path
|
8
|
+
# Use without open-uri-cached is untested
|
9
|
+
|
10
|
+
require 'rexml/document'
|
11
|
+
require 'yaml'
|
12
|
+
require 'json'
|
13
|
+
require 'shellwords'
|
14
|
+
require 'fileutils'
|
15
|
+
begin
|
16
|
+
require 'open-uri/cached'
|
17
|
+
rescue LoadError
|
18
|
+
warn '*** please "gem install open-uri-cached" to enable caching'
|
19
|
+
require 'open-uri'
|
20
|
+
end
|
21
|
+
require_relative '../lib/kramdown-rfc/rexml-all-text.rb'
|
22
|
+
|
23
|
+
target = :shortname
|
24
|
+
require 'optparse'
|
25
|
+
begin
|
26
|
+
op = OptionParser.new do |opts|
|
27
|
+
opts.banner = "Usage: kramdown-rfc-lsr [options] xml-source"
|
28
|
+
opts.on("-u", "--url", "Source is URL") do |v|
|
29
|
+
target = :url
|
30
|
+
end
|
31
|
+
opts.on("-s", "--shortname", "Source is shortname (default)") do |v|
|
32
|
+
target = :shortname
|
33
|
+
end
|
34
|
+
opts.on("-f", "--file", "Source is filename") do |v|
|
35
|
+
target = :file
|
36
|
+
end
|
37
|
+
end
|
38
|
+
op.parse!
|
39
|
+
rescue Exception => e
|
40
|
+
warn e
|
41
|
+
exit 1
|
42
|
+
end
|
43
|
+
|
44
|
+
$exit_code = 0
|
45
|
+
|
46
|
+
if target != :file && ARGV.size != 1
|
47
|
+
puts op
|
48
|
+
exit 1
|
49
|
+
end
|
50
|
+
xmlsource = ARGV[0]
|
51
|
+
if target == :shortname
|
52
|
+
xmlsource = case xmlsource
|
53
|
+
when /^(?:rfc)?(\d+)$/i
|
54
|
+
"https://www.rfc-editor.org/rfc/rfc#{$1.to_i.to_s}.xml"
|
55
|
+
when /^(?:draft-|I-D.|)(.*-\d\d)$/
|
56
|
+
"https://www.ietf.org/archive/id/draft-#$1.xml"
|
57
|
+
# XXX find xml source for most recent version!
|
58
|
+
else
|
59
|
+
warn "*** Can't parse shortname #{xmlsource.inspect}"
|
60
|
+
puts op
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
target = :url
|
64
|
+
end
|
65
|
+
|
66
|
+
begin
|
67
|
+
xml = case target
|
68
|
+
when :file
|
69
|
+
ARGF.read
|
70
|
+
when :url
|
71
|
+
URI(xmlsource).open.read
|
72
|
+
else
|
73
|
+
fail
|
74
|
+
end
|
75
|
+
rescue Exception => e
|
76
|
+
warn "#{xmlsource.inspect}: #{e}"
|
77
|
+
exit 1
|
78
|
+
end
|
79
|
+
|
80
|
+
doc = REXML::Document.new(xml)
|
81
|
+
|
82
|
+
def series_info_to_URI(si)
|
83
|
+
case si[:name]
|
84
|
+
when "RFC"
|
85
|
+
"https://www.rfc-editor.org/rfc/rfc#{si[:value]}.xml"
|
86
|
+
when "Internet-Draft"
|
87
|
+
"https://www.ietf.org/archive/id/#{si[:value]}.xml"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def series_info_to_name(si)
|
93
|
+
case si[:name]
|
94
|
+
when "RFC"
|
95
|
+
"RFC#{si[:value]}"
|
96
|
+
when "Internet-Draft"
|
97
|
+
si[:value]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def section_number_to_pn_candidates(s)
|
102
|
+
if /^[0-9]/ =~ s
|
103
|
+
["section-#{s}"]
|
104
|
+
elsif /[.]/ =~ s
|
105
|
+
["section-#{s.downcase}", "section-appendix.#{s.downcase}"]
|
106
|
+
else
|
107
|
+
["section-appendix.#{s.downcase}"]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def section_number_to_htmlid(s)
|
112
|
+
if /^[0-9]/ =~ s
|
113
|
+
"section-#{s}"
|
114
|
+
else
|
115
|
+
"appendix-#{s.upcase}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
references = Hash[REXML::XPath.match(doc.root, "//reference").map {|r|
|
120
|
+
si = REXML::XPath.match(r, "seriesInfo").map {|s|
|
121
|
+
series_info_to_URI(s)}.compact.first
|
122
|
+
sn = REXML::XPath.match(r, "seriesInfo").map {|s|
|
123
|
+
series_info_to_name(s)}.compact.first
|
124
|
+
[r[:anchor], si ? [si, sn] : nil]
|
125
|
+
}] # XXX duplicates?
|
126
|
+
|
127
|
+
heading1 = "# #{xmlsource}"
|
128
|
+
title = REXML::XPath.first(doc.root, "//title")
|
129
|
+
heading1 << "\n(#{title.all_text})" if title
|
130
|
+
puts heading1
|
131
|
+
|
132
|
+
per_reference = Hash.new { |h, k| h[k] = Set[]}
|
133
|
+
|
134
|
+
REXML::XPath.each(doc.root, "//xref[@section]") do |x|
|
135
|
+
trg = x[:target]
|
136
|
+
if x[:relative]
|
137
|
+
puts "\n## #{x[:target]}#{x[:relative]}: #{x[:section]}"
|
138
|
+
else
|
139
|
+
# p x
|
140
|
+
per_reference[trg] << x[:section]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def error_out(s)
|
145
|
+
warn ""
|
146
|
+
warn s
|
147
|
+
warn ""
|
148
|
+
$exit_code = 1
|
149
|
+
end
|
150
|
+
|
151
|
+
def num_expand(s)
|
152
|
+
s.gsub(/\d+/) {|n| "%09d" % n.to_i}
|
153
|
+
end
|
154
|
+
|
155
|
+
require 'open3'
|
156
|
+
|
157
|
+
module OpenURI
|
158
|
+
class << self
|
159
|
+
def prepped(uri, *rest)
|
160
|
+
newuri = uri.to_s.sub(/\.xml$/, ".prepped.xml")
|
161
|
+
response = Cache.get(newuri) || (
|
162
|
+
unprepped = open_uri(uri, *rest).read
|
163
|
+
fn = [OpenURI::Cache.cache_path, uri.sub(/.*\//, '')].join('/')
|
164
|
+
File.open(fn, 'wb'){|f| f.write unprepped }
|
165
|
+
_prep_out, s = Open3.capture2("xml2rfc", "--prep", fn)
|
166
|
+
fail s.inspect unless s.success?
|
167
|
+
new_fn = fn.sub(/\.xml$/, ".prepped.xml")
|
168
|
+
Cache.set(newuri, File.open(new_fn))
|
169
|
+
)
|
170
|
+
response
|
171
|
+
end
|
172
|
+
def tidied(uri, *rest)
|
173
|
+
newuri = uri.to_s.sub(/\.html$/, ".tidied.html")
|
174
|
+
response = Cache.get(newuri) || (
|
175
|
+
unprepped = open_uri(uri, *rest).read
|
176
|
+
fn = [OpenURI::Cache.cache_path, uri.sub(/.*\//, '')].join('/')
|
177
|
+
File.open(fn, 'wb'){|f| f.write unprepped }
|
178
|
+
_prep_out, s = Open3.capture2("tidy", "-mq", "-asxml", "-f", "/dev/null", fn)
|
179
|
+
fail s.inspect unless s.exited?
|
180
|
+
Cache.set(newuri, File.open(fn))
|
181
|
+
)
|
182
|
+
response
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# go through section-referenced documents in sequence
|
188
|
+
per_reference.keys.sort_by {|x| num_expand(x)}.each do |trg|
|
189
|
+
uri, sname = references[trg]
|
190
|
+
add = +''
|
191
|
+
if sname != trg
|
192
|
+
add << " [#{sname}]"
|
193
|
+
end
|
194
|
+
begin
|
195
|
+
ref = URI(uri).open.read
|
196
|
+
refdoc = REXML::Document.new(ref)
|
197
|
+
if REXML::XPath.match(refdoc.root, "/rfc/front/abstract[@pn]").size == 0
|
198
|
+
ref = OpenURI.prepped(uri).read
|
199
|
+
refdoc = REXML::Document.new(ref)
|
200
|
+
add << " [+prep]"
|
201
|
+
end
|
202
|
+
add << " (#{REXML::XPath.match(refdoc.root, "//title").first.all_text})"
|
203
|
+
rescue OpenURI::HTTPError => e
|
204
|
+
begin
|
205
|
+
jsonuri = uri.sub(/\.xml$/, ".json")
|
206
|
+
refjson = URI(jsonuri).open.read
|
207
|
+
refdata = JSON.load(refjson)
|
208
|
+
add << " (#{refdata["title"].strip})"
|
209
|
+
rescue OpenURI::HTTPError => e
|
210
|
+
add << " [No XML or JSON]"
|
211
|
+
rescue Exception => e
|
212
|
+
warn "*** error getting #{jsonuri.inspect}: #{e}"
|
213
|
+
end
|
214
|
+
rescue Exception => e
|
215
|
+
warn "*** error getting #{uri.inspect}: #{e}"
|
216
|
+
end
|
217
|
+
puts "\n## #{trg}#{add}"
|
218
|
+
unless refdoc
|
219
|
+
begin
|
220
|
+
htmluri = uri.sub(/\.xml$/, ".html")
|
221
|
+
refhtml = OpenURI.tidied(htmluri).read
|
222
|
+
refhtmldoc = REXML::Document.new(refhtml)
|
223
|
+
rescue Exception => e
|
224
|
+
warn "*** error tidying up HTML for #{htmluri.inspect}: #{e}"
|
225
|
+
end
|
226
|
+
end
|
227
|
+
# go through individual section references in sequence
|
228
|
+
per_reference[trg].to_a.sort_by {|x| num_expand(x)}.each do |s|
|
229
|
+
add = +''
|
230
|
+
if refdoc # find section name in XML from anchor s
|
231
|
+
secpn = section_number_to_pn_candidates(s)
|
232
|
+
secs = secpn.flat_map{ |c|
|
233
|
+
REXML::XPath.match(refdoc.root, "//section[@pn=$pn]",
|
234
|
+
{}, {"pn" => c})}
|
235
|
+
what = "#{secpn.join(" or ")} in #{trg}"
|
236
|
+
add << " (#{case secs.size
|
237
|
+
when 0
|
238
|
+
error_out "*** cannot match #{what}"
|
239
|
+
"*** DOESN'T EXIST ***"
|
240
|
+
when 1
|
241
|
+
sec = secs.first
|
242
|
+
sec[:title] || sec.elements["name"].all_text
|
243
|
+
else
|
244
|
+
error_out "*** multiple matches for #{what}"
|
245
|
+
"*** MULTIPLE MATCHES ***"
|
246
|
+
end})"
|
247
|
+
elsif refhtmldoc # find section name in HTML from anchor s
|
248
|
+
secpn = section_number_to_htmlid(s)
|
249
|
+
secs = REXML::XPath.match(refhtmldoc.root,
|
250
|
+
"//xmlns:a[@id=$pn]/ancestor::xmlns:span",
|
251
|
+
{"xmlns" => "http://www.w3.org/1999/xhtml"},
|
252
|
+
{"pn" => secpn})
|
253
|
+
what = "#{secpn} in #{trg}"
|
254
|
+
add << " (#{case secs.size
|
255
|
+
when 0
|
256
|
+
error_out "*** cannot match #{what}"
|
257
|
+
"*** DOESN'T EXIST ***"
|
258
|
+
when 1
|
259
|
+
secs.first.text.sub(/^\.\s+/, '')
|
260
|
+
else
|
261
|
+
error_out "*** multiple matches for #{what}"
|
262
|
+
"*** MULTIPLE MATCHES ***"
|
263
|
+
end})"
|
264
|
+
end
|
265
|
+
puts "* #{/^[0-9]/ =~ s ? "Section" : "Appendix"} #{s}#{add}"
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
exit $exit_code
|
data/kramdown-rfc2629.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
2
2
|
s.name = 'kramdown-rfc2629'
|
3
|
-
s.version = '1.7.
|
3
|
+
s.version = '1.7.13'
|
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,11 +13,12 @@ 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 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)
|
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 bin/kramdown-rfc-lsr 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
20
|
'kramdown-rfc-extract-sourcecode',
|
21
|
+
'kramdown-rfc-lsr',
|
21
22
|
'kdrfc', 'kramdown-rfc-cache-i-d-bibxml',
|
22
23
|
'kramdown-rfc-cache-subseries-bibxml',
|
23
24
|
'kramdown-rfc-autolink-iref-cleanup',
|
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.7.
|
4
|
+
version: 1.7.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carsten Bormann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kramdown
|
@@ -147,6 +147,7 @@ executables:
|
|
147
147
|
- echars
|
148
148
|
- kramdown-rfc-extract-markdown
|
149
149
|
- kramdown-rfc-extract-sourcecode
|
150
|
+
- kramdown-rfc-lsr
|
150
151
|
- kdrfc
|
151
152
|
- kramdown-rfc-cache-i-d-bibxml
|
152
153
|
- kramdown-rfc-cache-subseries-bibxml
|
@@ -169,6 +170,7 @@ files:
|
|
169
170
|
- bin/kramdown-rfc-clean-svg-ids
|
170
171
|
- bin/kramdown-rfc-extract-markdown
|
171
172
|
- bin/kramdown-rfc-extract-sourcecode
|
173
|
+
- bin/kramdown-rfc-lsr
|
172
174
|
- bin/kramdown-rfc2629
|
173
175
|
- data/encoding-fallbacks.txt
|
174
176
|
- data/kramdown-rfc2629.erb
|
@@ -206,7 +208,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
206
208
|
- !ruby/object:Gem::Version
|
207
209
|
version: '0'
|
208
210
|
requirements: []
|
209
|
-
rubygems_version: 3.5.
|
211
|
+
rubygems_version: 3.5.9
|
210
212
|
signing_key:
|
211
213
|
specification_version: 4
|
212
214
|
summary: Kramdown extension for generating RFCXML (RFC 799x).
|