kramdown-rfc2629 1.0.42 → 1.1.0

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
  SHA1:
3
- metadata.gz: 75ac2b119d2630278f0db1cb169ca40a25dc8f55
4
- data.tar.gz: 013e491c8bcd6bb1d0b694919dd87813b958df2f
3
+ metadata.gz: eccebf9e2835616858b24412132d8ef16799526f
4
+ data.tar.gz: ca13164f41dc311f2ef333c21dfa11489057bf07
5
5
  SHA512:
6
- metadata.gz: 8f229ee5ceeed8ae1d926ffbe72fefa90a7d37902aad0b78220db53653e5d95ad4721c79a4a7a22edd87608746dbf7a2428175b1ab2d21744081e67dd313fbbd
7
- data.tar.gz: b8bfa1df8e6d4679992bae4297940a789bca034553d55e52f2fcec07f6c25f06d6bb117e737ef8b4128064562714c70f4980f67e7f276377809262a28a78e483
6
+ metadata.gz: b6aec8582e3b6a5ca6e3ebd32eacde950f89246a1595eaa8fd13dd9fe8d1d7fe7e04affe118751d2a6781910b051419cf9d9fdb3e0e1491f21191a1de50772d5
7
+ data.tar.gz: 034c56c7f6baa6aaac94fd94ad43dc7240dd12fe39e67b09e5b3ca43127c75759d9d6f5bf4e2c2c9bc454fd92104a4c50a2cc3e38544e8a8cc9acbdc313c0989
data/README.md CHANGED
@@ -14,7 +14,8 @@ their work in markdown.
14
14
  # Usage
15
15
 
16
16
  Start by installing the kramdown-rfc2629 gem (this automatically
17
- installs kramdown version 1.6.x as well):
17
+ installs appropriate versions of referenced gems such as kramdown as
18
+ well):
18
19
 
19
20
  gem install kramdown-rfc2629
20
21
 
@@ -33,6 +34,10 @@ To use kramdown-rfc2629, you'll need a Ruby 1.9 or 2.x, and maybe
33
34
  kramdown-rfc2629 mydraft.mkd >mydraft.xml
34
35
  xml2rfc mydraft.xml
35
36
 
37
+ (The most popular file name extension that IETF people have for
38
+ markdown is .md -- for those who tend to think about GNU machine
39
+ descriptions here, any extension such as .mkd will do, too.)
40
+
36
41
  # Examples
37
42
 
38
43
  For historical interest
@@ -149,8 +154,36 @@ and then just write `{{RFC2119}}` or `{{RFC1925}}`. (Yes, there is a
149
154
  colon in the YAML, because this is a hash that could provide other
150
155
  information.)
151
156
 
152
- If your references are not in the [XML2RFC][] databases, you need to
153
- spell it out like this:
157
+ Since version 1.1, references imported from the [XML2RFC][] databases
158
+ can be supplied with a replacement label (anchor name). E.g., RFC 793
159
+ could be referenced as `{{!TCP=RFC0793}}, further references then just
160
+ can say `{{TCP}}`; both will get `[TCP]` as the label. In the
161
+ YAML, the same replacement can be expressed as in the first example:
162
+
163
+ normative:
164
+ TCP: RFC0793
165
+ informative:
166
+ SST: DOI.10.1145/1282427.1282421
167
+
168
+ Notes about this feature:
169
+
170
+ * At the time of writing, the DOI and IANA repositories are
171
+ slightly unstable.
172
+ * Thank you, Martin Thomson, for supplying an implementation and
173
+ insisting this be done.
174
+ * While this feature is now available, you are not forced to use it
175
+ for everything: readers of documents often benefit from not having
176
+ to look up references, so continuing to use the draft names and RFC
177
+ numbers as labels may be the preferrable style in many cases.
178
+ * As a final caveat, renaming anchors does not work in the
179
+ `stand_alone: no` mode (except for IANA and DOI), as there is no
180
+ such mechanism in XML entity referencing; exporting to XML while
181
+ maintaining live references then may require some manual editing to
182
+ get rid of the custom anchors.
183
+
184
+ If your references are not in the [XML2RFC][] databases and do not
185
+ have a DOI (that also happens to have correct data) either, you need
186
+ to spell it out like in the examples below:
154
187
 
155
188
  informative:
156
189
  RFC1925:
data/bin/kramdown-rfc2629 CHANGED
@@ -52,18 +52,25 @@ def xml_from_sections(input)
52
52
  end
53
53
 
54
54
  ref_replacements = { }
55
+ anchor_to_bibref = { }
55
56
 
56
57
  [:ref, :normative, :informative].each do |sn|
57
58
  if refs = ps.has(sn)
58
59
  warn "*** bad section #{sn}: #{refs.inspect}" unless refs.respond_to? :each
59
60
  refs.each do |k, v|
60
61
  if v.respond_to? :to_str
62
+ if bibtagsys(v) # enable "foo: RFC4711" as a custom anchor definition
63
+ anchor_to_bibref[k] = v.to_str
64
+ end
61
65
  ref_replacements[v.to_str] = k
62
66
  end
63
- if v.respond_to? :[]
67
+ if Hash === v
64
68
  if aliasname = v.delete("-")
65
69
  ref_replacements[aliasname] = k
66
70
  end
71
+ if bibref = v.delete("=")
72
+ anchor_to_bibref[k] = bibref
73
+ end
67
74
  end
68
75
  end
69
76
  end
@@ -76,18 +83,29 @@ def xml_from_sections(input)
76
83
  # collect normative/informative tagging {{!RFC2119}} {{?RFC4711}}
77
84
  sechash.each do |k, v|
78
85
  next if k == "fluff"
79
- v.gsub!(/{{(?:([?!])(-)?|(-))([\w.\-]+)}}/) do |match|
86
+ v.gsub!(/{{(?:([?!])(-)?|(-))([\w._\-]+)(?:=([\w.\/_\-]+))?}}/) do |match|
80
87
  norminform = $1
81
88
  replacing = $2 || $3
82
89
  word = $4
90
+ bibref = $5
83
91
  if replacing
84
92
  if new = ref_replacements[word]
85
93
  word = new
86
94
  else
87
- warn "*** no alias replacement for {{-#{word}}}"
95
+ warn "*** no alias replacement for {{-#{word}}}"
88
96
  word = "-#{word}"
89
97
  end
98
+ end # now, word is the anchor
99
+ if bibref
100
+ if old = anchor_to_bibref[word]
101
+ if bibref != old
102
+ warn "*** conflicting definitions for xref #{anchor}: #{old} != #{bibref}"
103
+ end
104
+ else
105
+ anchor_to_bibref[word] = bibref
106
+ end
90
107
  end
108
+
91
109
  # things can be normative in one place and informative in another -> normative
92
110
  # collect norm/inform above and assign it by priority here
93
111
  if norminform
@@ -126,19 +144,24 @@ def xml_from_sections(input)
126
144
  refs.each do |k, v|
127
145
  href = k.gsub(/\A[0-9]/) { "_#{$&}" } # can't start an IDREF with a number
128
146
  link_defs[k] = ["##{href}", nil] # allow [RFC2119] in addition to {{RFC2119}}
129
- if bts = bibtagsys(k)
130
- if v
147
+
148
+ bibref = anchor_to_bibref[k] || k
149
+ bts, url = bibtagsys(bibref, k, stand_alone)
150
+ if bts
151
+ if v && v != {}
131
152
  warn "*** redundant in #{k}: #{v.inspect}" unless v.respond_to? :to_str
132
153
  end
133
154
  if stand_alone
134
- sechash[sn.to_s] << %{\n#{NMDTAGS[0]}\n![:include:](#{bts[0]})\n#{NMDTAGS[1]}\n}
155
+ a = %{{: anchor="#{k}"}}
156
+ sechash[sn.to_s] << %{\n#{NMDTAGS[0]}\n![:include:](#{bts})#{a}\n#{NMDTAGS[1]}\n}
135
157
  else
136
- (ps.rest["bibxml"] ||= []) << k
137
- sechash[sn.to_s] << %{&#{bts[0]};\n}
158
+ bts.gsub!('/', '_')
159
+ (ps.rest["bibxml"] ||= []) << [bts, url]
160
+ sechash[sn.to_s] << %{&#{bts};\n} # ???
138
161
  end
139
162
  else
140
163
  unless v && Hash === v
141
- warn "*** don't know how to expand ref #{k}"
164
+ warn "*** don't know how to expand ref #{k}"
142
165
  next
143
166
  end
144
167
  sechash[sn.to_s] << KramdownRFC::ref_to_xml(k, v)
@@ -163,23 +186,34 @@ end
163
186
 
164
187
  XML_RESOURCE_ORG_PREFIX = Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_PREFIX
165
188
 
166
- def bibtagsys(bib)
189
+ # return XML entity name, url, rewrite_anchor flag
190
+ def bibtagsys(bib, anchor=nil, stand_alone=true)
167
191
  if bib =~ /\Arfc(\d+)/i
168
192
  rfc4d = "%04d" % $1.to_i
169
193
  [bib.upcase,
170
194
  "#{XML_RESOURCE_ORG_PREFIX}/bibxml/reference.RFC.#{rfc4d}.xml"]
171
195
  elsif bib =~ /\A([-A-Z0-9]+)\./ &&
172
- dir = Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_MAP[$1]
196
+ (dir, _ttl, rewrite_anchor = Kramdown::Converter::Rfc2629::XML_RESOURCE_ORG_MAP[$1])
173
197
  bib1 = bib.gsub(/\A[0-9]/) { "_#{$&}" } # can't start an ID with a number
198
+ if anchor && bib1 != anchor
199
+ if rewrite_anchor
200
+ a = %{?anchor=#{anchor}}
201
+ else
202
+ if !stand_alone
203
+ warn "*** selecting a custom anchor '#{anchor}' for '#{bib1}' requires stand_alone mode"
204
+ warn " the output will need manual editing to correct this"
205
+ end
206
+ end
207
+ end
174
208
  [bib1,
175
- "#{XML_RESOURCE_ORG_PREFIX}/#{dir}/reference.#{bib}.xml"]
209
+ "#{XML_RESOURCE_ORG_PREFIX}/#{dir}/reference.#{bib}.xml#{a}"]
176
210
  end
177
211
  end
178
212
 
179
213
  def read_encodings
180
214
  encfilename = File.expand_path '../../data/encoding-fallbacks.txt', __FILE__
181
215
  encfile = File.read(encfilename, coding: "UTF-8")
182
- Hash[encfile.lines.map{|l|
216
+ Hash[encfile.lines.map{|l|
183
217
  l.chomp!;
184
218
  x, s = l.split(" ", 2)
185
219
  [x.hex.chr(Encoding::UTF_8), s || " "]}]
@@ -4,8 +4,7 @@
4
4
  Gem.loaded_specs["kramdown-rfc2629"].version rescue nil %> -->
5
5
 
6
6
  <!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
7
- <% ps.arr("bibxml") do |bib|
8
- tag, sys = bibtagsys(bib) -%>
7
+ <% ps.arr("bibxml") do |tag, sys| -%>
9
8
  <!ENTITY <%= tag %> SYSTEM "<%= sys %>">
10
9
  <% end -%>
11
10
  <% ps.arr("entity", false) do |en, ev| -%>
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'kramdown-rfc2629'
3
- s.version = '1.0.42'
3
+ s.version = '1.1.0'
4
4
  s.summary = "Kramdown extension for generating RFC 7749 XML."
5
5
  s.description = %{An RFC7749 (XML2RFC) generating backend for Thomas Leitner's
6
6
  "kramdown" markdown parser. Mostly useful for RFC writers.}
@@ -1,9 +1,15 @@
1
1
  module KramdownRFC
2
2
 
3
+ extend Kramdown::Utils::Html
4
+
5
+ def self.escattr(str)
6
+ escape_html(str.to_s, :attribute)
7
+ end
8
+
3
9
  def self.ref_to_xml(k, v)
4
10
  vps = KramdownRFC::ParameterSet.new(v)
5
11
  erb = ERB.new <<-REFERB, nil, '-'
6
- <reference anchor="<%= k %>" <%= vps.attr("target") %>>
12
+ <reference anchor="<%= escattr(k) %>" <%= vps.attr("target") %>>
7
13
  <front>
8
14
  <%= vps.ele("title") -%>
9
15
 
@@ -18,10 +24,10 @@ module KramdownRFC
18
24
  <date <%= dateattrs(vps[:date]) %>/>
19
25
  </front>
20
26
  <% vps.arr("seriesinfo", false) do |k, v| -%>
21
- <seriesInfo name="<%=k%>" value="<%=v%>"/>
27
+ <seriesInfo name="<%=escattr(k)%>" value="<%=escattr(v)%>"/>
22
28
  <% end -%>
23
29
  <% vps.arr("format", false) do |k, v| -%>
24
- <format type="<%=k%>" target="<%=v%>"/>
30
+ <format type="<%=escattr(k)%>" target="<%=escattr(v)%>"/>
25
31
  <% end -%>
26
32
  <%= vps.ele("annotation=ann") -%>
27
33
  </reference>
@@ -412,9 +412,10 @@ module Kramdown
412
412
  KRAMDOWN_OFFLINE = ENV["KRAMDOWN_OFFLINE"]
413
413
  KRAMDOWN_REFCACHE_REFETCH = ENV["KRAMDOWN_REFCACHE_REFETCH"]
414
414
 
415
- def get_and_cache_resource(url, tvalid = 7200, tn = Time.now)
415
+ # this is now slightly dangerous as multiple urls could map to the same cachefile
416
+ def get_and_cache_resource(url, cachefile, tvalid = 7200, tn = Time.now)
417
+ fn = "#{REFCACHEDIR}/#{cachefile}"
416
418
  Dir.mkdir(REFCACHEDIR) unless Dir.exists?(REFCACHEDIR)
417
- fn = "#{REFCACHEDIR}/#{File.basename(url)}"
418
419
  f = File.stat(fn) rescue nil unless KRAMDOWN_REFCACHE_REFETCH
419
420
  if !KRAMDOWN_OFFLINE && (!f || tn - f.ctime >= tvalid)
420
421
  if f
@@ -457,7 +458,11 @@ module Kramdown
457
458
  end
458
459
  end
459
460
  end
460
- File.read(fn) # this blows up if no cache available after fetch attempt
461
+ begin
462
+ File.read(fn) # this blows up if no cache available after fetch attempt
463
+ rescue Errno::ENOENT => e
464
+ warn "*** #{e} for ${fn}"
465
+ end
461
466
  end
462
467
 
463
468
  XML_RESOURCE_ORG_MAP = {
@@ -475,8 +480,8 @@ module Kramdown
475
480
  "NIST" => "bibxml2",
476
481
  "OASIS" => "bibxml2",
477
482
  "PKCS" => "bibxml2",
478
- "DOI" => ["bibxml7", 86400], # 24 h cache at source anyway
479
- "IANA" => ["bibxml8", 86400], # ditto
483
+ "DOI" => ["bibxml7", 86400, true], # 24 h cache at source anyway
484
+ "IANA" => ["bibxml8", 86400, true], # ditto
480
485
  }
481
486
 
482
487
  # XML_RESOURCE_ORG_HOST = ENV["XML_RESOURCE_ORG_HOST"] || "xml.resource.org"
@@ -490,23 +495,36 @@ module Kramdown
490
495
  if a = el.attr
491
496
  alt = a.delete('alt').strip
492
497
  alt = '' if alt == '!' # work around re-wrap uglyness
493
- if anchor = a.delete('src')
494
- a['target'] = anchor
498
+ if src = a.delete('src')
499
+ a['target'] = src
495
500
  end
496
501
  end
497
502
  if alt == ":include:" # Really bad misuse of tag...
503
+ anchor = el.attr.delete('anchor') || (
504
+ # not yet
505
+ warn "*** missing anchor for '#{src}'"
506
+ src
507
+ )
508
+ anchor.sub!(/\A[0-9]/) { "_#{$&}" } # can't start an ID with a number
509
+ anchor.gsub!('/', '_') # should take out all illegals
498
510
  to_insert = ""
499
- anchor.scan(/(W3C|3GPP|[A-Z-]+)[.]?([A-Za-z0-9.-]+)/) do |t, n|
511
+ src.scan(/(W3C|3GPP|[A-Z-]+)[.]?([A-Za-z_0-9.\/\+-]+)/) do |t, n|
500
512
  fn = "reference.#{t}.#{n}.xml"
501
513
  sub, ttl = XML_RESOURCE_ORG_MAP[t]
502
514
  ttl ||= KRAMDOWN_REFCACHETTL # everything but RFCs might change a lot
503
515
  puts "Huh: ${fn}" unless sub
504
516
  url = "#{XML_RESOURCE_ORG_PREFIX}/#{sub}/#{fn}"
505
- to_insert = get_and_cache_resource(url, ttl)
517
+ to_insert = get_and_cache_resource(url, fn.gsub('/', '_'), ttl)
506
518
  to_insert.scrub! rescue nil # only do this for Ruby >= 2.1
519
+ # this may be a bit controversial: Don't break the build if reference is broken
520
+ if KRAMDOWN_OFFLINE
521
+ to_insert ||= "<reference anchor='#{anchor}'> <front> <title>*** BROKEN REFERENCE ***</title> <author> <organization/> </author> <date/> </front> </reference>"
522
+ else
523
+ exit 66 unless to_insert # EX_NOINPUT
524
+ end
507
525
  end
508
- to_insert.gsub(/<\?xml version=["']1.0["'] encoding=["']UTF-8["']\?>/, '').
509
- gsub(/(anchor=["'])([0-9])/) { "#{$1}_#{$2}"} # can't start an ID with a number
526
+ to_insert.sub(/<\?xml version=["']1.0["'] encoding=["']UTF-8["']\?>/, '')
527
+ .sub(/\banchor=(?:"[^"]+"|'[^']+')/, "anchor=\"#{anchor}\"")
510
528
  else
511
529
  "<xref#{el_html_attributes(el)}>#{alt}</xref>"
512
530
  end
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.0.42
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-15 00:00:00.000000000 Z
11
+ date: 2017-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kramdown