kramdown-rfc2629 1.3.8 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0bf90a7fd57ee1492ceaf533983659336ca24c1334b79cd9be55661c4622d10f
4
- data.tar.gz: 940584f0bea9de4fb1e2e9b91a79bd8b4eb0192543f625d7c0cbfa9858402275
3
+ metadata.gz: fe573235c508ba9d089f72b578a53ea8507b53d82a539539228982a799e830a7
4
+ data.tar.gz: b7541fa31e84a9428f18541f2bef57b63984e1b3b9c193e4c28c82cdd3e2bcbb
5
5
  SHA512:
6
- metadata.gz: f444f161ab0611bc92bbdb2f790c13f1676b9e035368fbcd7869317e5f30b28dd3e59789e55c0c6e3f67f5f8d4d5fa3d2368b26e307ab44f2e846604670754ab
7
- data.tar.gz: dfcae66926b4a96424d0be1144d7ccf5c00a28b5153d2adf5897484b9f51826989bf14314909e7a3327ad9ac75b9b57f63270626890b7de3648ddbf2d63e2c5d
6
+ metadata.gz: 754f2d2d69f025e73037aaf86b6b315eb362251b3fd1c4f070adb4c7a380d9c05bef9445c863aa0e0e4c4877d5d0eb2f0e38b5b120a9a86642969b8b81673ccf
7
+ data.tar.gz: 53a5b1caa470513f06a4bf28618b35f45ae2632cda64edc3e64e2e894d91e780272da81c383d0967aa6e98553f39286f4daa8ddaf97c299397e30f7d0d423a1a
data/README.md CHANGED
@@ -281,6 +281,31 @@ special support in XML2RFC), and HTML syntax of course.
281
281
  A number of more esoteric features have recently been added.
282
282
  (The minimum required version for each full feature is indicated.)
283
283
 
284
+ (1.3.x)
285
+ Slowly improving support for SVG generating tools for XML2RFCv3 (i.e.,
286
+ with `-3` flag).
287
+ These tools must be installed and callable from the command line.
288
+
289
+ The basic idea is to mark an input code block with one of the following
290
+ labels (language types), yielding some plaintext form in the .TXT
291
+ output and a graphical form in the .HTML output. The plaintext is the
292
+ input in some cases (e.g., ASCII art, `mscgen`), or some plaintext
293
+ output generated by the tool (e.g., `plantuml-utxt`).
294
+
295
+ Currently supported labels as of 1.3.9:
296
+
297
+ * goat, ditaa: ASCII (plaintext) art to figure conversion
298
+ * mscgen: Message Sequence Charts
299
+ * plantuml: widely used multi-purpose diagram generator
300
+ * plantuml-utxt: Like plantuml, except that a plantuml-generated
301
+ plaintext form is used
302
+ * mermaid: Very experimental; the conversion to SVG is prone to
303
+ generate black-on-black text in this version
304
+
305
+ Note that this feature does not play well with the CI (continuous
306
+ integration) support in Martin Thomson's [I-D Template][], as that may
307
+ not have the tools installed in its docker instance.
308
+
284
309
  (1.2.9:)
285
310
  The YAML header now allows specifying [kramdown_options][].
286
311
 
data/bin/doilit CHANGED
@@ -39,11 +39,17 @@ ARGV.each do |doi|
39
39
  warn "*** Usage: doilit [-c] [-v] [-h=handle|-x=xmlhandle] doi..."
40
40
  exit 1
41
41
  end
42
- cite = JSON.parse(open("https://dx.doi.org/#{doi}", ACCEPT_CITE_JSON).read)
42
+ cite = JSON.parse(URI("https://dx.doi.org/#{doi}").open(ACCEPT_CITE_JSON).read)
43
43
  puts cite.to_yaml if $verbose
44
44
  lit = {}
45
45
  ser = lit["seriesinfo"] = {}
46
46
  lit["title"] = cite["title"]
47
+ if (st = cite["subtitle"]) && Array === st # defensive
48
+ st.delete('')
49
+ if st != []
50
+ lit["title"] << ": " << st.join("; ")
51
+ end
52
+ end
47
53
  if authors = cite["author"]
48
54
  lit["author"] = authors.map do |au|
49
55
  lau = {}
data/bin/kdrfc CHANGED
@@ -3,6 +3,9 @@ require 'uri'
3
3
  require 'net/http'
4
4
  require 'open3'
5
5
 
6
+ # try to get this from gemspec.
7
+ KDRFC_VERSION=Gem.loaded_specs["kramdown-rfc2629"].version rescue "unknown-version"
8
+
6
9
  def v3_flag?
7
10
  $options.v3 ? ["--v3"] : []
8
11
  end
@@ -46,16 +49,21 @@ def process_xml_locally(input, output, *flags)
46
49
  end
47
50
  end
48
51
 
52
+ XML2RFC_WEBSERVICE = ENV["KRAMDOWN_XML2RFC_WEBSERVICE"] ||
53
+ 'http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc-dev.cgi'
54
+
55
+
49
56
  def process_xml_remotely(input, output)
50
57
  warn "* converting remotely from xml #{input} to txt #{output}" if $options.verbose
51
- url = URI('http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi')
58
+ url = URI(XML2RFC_WEBSERVICE)
52
59
  req = Net::HTTP::Post.new(url)
53
- req.set_form([["modeAsFormat", "txt/#{"v3" if $options.v3}ascii"],
54
- ["type", "binary"],
55
- ["input", File.open(input),
56
- {filename: "input.xml",
57
- content_type: "text/plain"}]],
58
- 'multipart/form-data')
60
+ form = [["modeAsFormat", "txt/#{"v3" if $options.v3}ascii"],
61
+ ["type", "binary"],
62
+ ["input", File.open(input),
63
+ {filename: "input.xml",
64
+ content_type: "text/plain"}]]
65
+ diag = ["url/form: ", url, form].inspect
66
+ req.set_form(form, 'multipart/form-data')
59
67
  res = Net::HTTP::start(url.hostname, url.port,
60
68
  :use_ssl => url.scheme == 'https' ) {|http|
61
69
  http.request(req)
@@ -64,17 +72,21 @@ def process_xml_remotely(input, output)
64
72
  when Net::HTTPOK
65
73
  case res.content_type
66
74
  when 'application/octet-stream'
75
+ if res.body == ''
76
+ warn "*** HTTP response is empty with status #{res.code}, not written"
77
+ exit 1
78
+ end
67
79
  File.open(output, "w") do |fo|
68
80
  fo.print(res.body)
69
81
  end
70
82
  warn "* #{output} written" if $options.verbose
71
83
  else
72
- warn "*** HTTP response has unexpected content_type #{res.content_type} with status #{res.code}"
84
+ warn "*** HTTP response has unexpected content_type #{res.content_type} with status #{res.code}, #{diag}"
73
85
  warn res.body
74
86
  exit 1
75
87
  end
76
88
  else
77
- warn "*** HTTP response: #{res.code}"
89
+ warn "*** HTTP response: #{res.code}, #{diag}"
78
90
  exit 1
79
91
  end
80
92
  end
@@ -85,8 +97,18 @@ require 'ostruct'
85
97
  $options = OpenStruct.new
86
98
  $options.txt = true # default
87
99
  op = OptionParser.new do |opts|
88
- opts.banner = "Usage: kdrfc [options] file.md|file.mkd|file.xml"
89
-
100
+ opts.banner = <<BANNER
101
+ Usage: kdrfc [options] file.md|file.mkd|file.xml
102
+ Version: #{KDRFC_VERSION}
103
+ BANNER
104
+ opts.on("-V", "--version", "Show version and exit") do |v|
105
+ puts "kdrfc, from kramdown-rfc2629 #{KDRFC_VERSION}"
106
+ exit
107
+ end
108
+ opts.on("-H", "--help", "Show option summary and exit") do |v|
109
+ puts opts
110
+ exit
111
+ end
90
112
  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
91
113
  $options.verbose = v
92
114
  end
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby2.1
1
+ #!/usr/bin/env ruby
2
2
  # -*- coding: utf-8 -*-
3
3
  require 'kramdown-rfc2629'
4
4
  require 'kramdown-rfc/parameterset'
@@ -7,6 +7,9 @@ require 'yaml'
7
7
  require 'erb'
8
8
  require 'date'
9
9
 
10
+ # try to get this from gemspec.
11
+ KDRFC_VERSION=Gem.loaded_specs["kramdown-rfc2629"].version rescue "unknown-version"
12
+
10
13
  Encoding.default_external = "UTF-8" # wake up, smell the coffee
11
14
 
12
15
  def boilerplate(key)
@@ -287,8 +290,18 @@ require 'ostruct'
287
290
 
288
291
  $options = OpenStruct.new
289
292
  op = OptionParser.new do |opts|
290
- opts.banner = "Usage: kramdown-rfc2629 [options] file.md|file.mkd > file.xml"
291
-
293
+ opts.banner = <<BANNER
294
+ Usage: kramdown-rfc2629 [options] file.md|file.mkd > file.xml
295
+ Version: #{KDRFC_VERSION}
296
+ BANNER
297
+ opts.on("-V", "--version", "Show version and exit") do |v|
298
+ puts "kramdown-rfc2629 #{KDRFC_VERSION}"
299
+ exit
300
+ end
301
+ opts.on("-H", "--help", "Show option summary and exit") do |v|
302
+ puts opts
303
+ exit
304
+ end
292
305
  opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
293
306
  $options.verbose = v
294
307
  end
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'kramdown-rfc2629'
3
- s.version = '1.3.8'
3
+ s.version = '1.3.13'
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.}
@@ -9,7 +9,6 @@ spec = Gem::Specification.new do |s|
9
9
  s.files = Dir['lib/**/*.rb'] + %w(README.md LICENSE kramdown-rfc2629.gemspec bin/kdrfc bin/kramdown-rfc2629 bin/doilit bin/kramdown-rfc-extract-markdown data/kramdown-rfc2629.erb data/encoding-fallbacks.txt)
10
10
  s.require_path = 'lib'
11
11
  s.executables = ['kramdown-rfc2629', 'doilit', 'kramdown-rfc-extract-markdown', 'kdrfc']
12
- s.default_executable = 'kramdown-rfc2629'
13
12
  s.required_ruby_version = '>= 2.3.0'
14
13
  # s.requirements = 'wget'
15
14
  # s.has_rdoc = true
@@ -37,16 +37,27 @@ module Kramdown
37
37
  @span_parsers.unshift(:iref)
38
38
  end
39
39
 
40
- XREF_START = /\{\{(.*?)\}\}/u
40
+ XREF_START = /\{\{(?:(?:\{(.*?)\}(?:\{(.*?)\})?)|(.*?))((?:\}\})|\})/u
41
41
 
42
42
  # Introduce new {{target}} syntax for empty xrefs, which would
43
43
  # otherwise be an ugly ![!](target) or ![ ](target)
44
44
  # (I'd rather use [[target]], but that somehow clashes with links.)
45
45
  def parse_xref
46
46
  @src.pos += @src.matched_size
47
- href = @src[1]
48
- href = href.gsub(/\A[0-9]/) { "_#{$&}" } # can't start an IDREF with a number
49
- el = Element.new(:xref, nil, {'target' => href})
47
+ unless @src[4] == "}}"
48
+ warn "*** #{@src[0]}: unmatched braces #{@src[4].inspect}"
49
+ end
50
+ if contact_name = @src[1]
51
+ attr = {'fullname' => contact_name}
52
+ if ascii_name = @src[2]
53
+ attr["asciiFullname"] = ascii_name
54
+ end
55
+ el = Element.new(:contact, nil, attr)
56
+ else
57
+ href = @src[3]
58
+ href = href.gsub(/\A[0-9]/) { "_#{$&}" } # can't start an IDREF with a number
59
+ el = Element.new(:xref, nil, {'target' => href})
60
+ end
50
61
  @tree.children << el
51
62
  end
52
63
  define_parser(:xref, XREF_START, '{{')
@@ -150,10 +161,42 @@ module Kramdown
150
161
  generate_id(value).gsub(/-+/, '-')
151
162
  end
152
163
 
164
+ SVG_COLORS = Hash.new {|h, k| k}
165
+ <<COLORS.each_line {|l| k, v = l.chomp.split; SVG_COLORS[k] = v}
166
+ black #000000
167
+ silver #C0C0C0
168
+ gray #808080
169
+ white #FFFFFF
170
+ maroon #800000
171
+ red #FF0000
172
+ purple #800080
173
+ fuchsia #FF00FF
174
+ green #008000
175
+ lime #00FF00
176
+ olive #808000
177
+ yellow #FFFF00
178
+ navy #000080
179
+ blue #0000FF
180
+ teal #008080
181
+ aqua #00FFFF
182
+ COLORS
183
+
184
+ def svg_munch_id(id)
185
+ id.gsub(/[^-._A-Za-z0-9]/) {|x| "_%02X" % x.ord}
186
+ end
187
+
188
+ def self.hex_to_lin(h)
189
+ h.to_i(16)**2.22 # approximating sRGB gamma
190
+ end
191
+ define_method :hex_to_lin, &method(:hex_to_lin)
192
+
193
+ B_W_THRESHOLD = hex_to_lin("a4") # a little brighter than 1/2 0xFF -> white
194
+
153
195
  def svg_munch_color(c, fill)
196
+ c = SVG_COLORS[c]
154
197
  case c
155
198
  when /\A#(..)(..)(..)\z/
156
- if [$1, $2, $3].map {|x| x.to_i(16)}.sum >= 300 # arbitrary
199
+ if hex_to_lin($1)*0.2126 + hex_to_lin($2)*0.7152 + hex_to_lin($3)*0.0722 >= B_W_THRESHOLD
157
200
  'white'
158
201
  else
159
202
  'black'
@@ -172,9 +215,56 @@ module Kramdown
172
215
  REXML::XPath.each(d.root, "//*[@text-rendering]") { |x| x.attributes["text-rendering"] = nil } #; warn x.inspect }
173
216
  REXML::XPath.each(d.root, "//*[@stroke]") { |x| x.attributes["stroke"] = svg_munch_color(x.attributes["stroke"], false) }
174
217
  REXML::XPath.each(d.root, "//*[@fill]") { |x| x.attributes["fill"] = svg_munch_color(x.attributes["fill"], true) }
218
+ REXML::XPath.each(d.root, "//*[@id]") { |x| x.attributes["id"] = svg_munch_id(x.attributes["id"]) }
219
+ ## REXML::XPath.each(d.root, "//rect") { |x| x.attributes["style"] = "fill:none;stroke:black;stroke-width:1" unless x.attributes["style"] }
175
220
  d.to_s
176
221
  end
177
222
 
223
+ def memoize(meth, *args)
224
+ require 'digest'
225
+ Dir.mkdir(REFCACHEDIR) unless Dir.exists?(REFCACHEDIR)
226
+ kdrfc_version = Gem.loaded_specs["kramdown-rfc2629"].version.to_s.gsub('.', '_') rescue "UNKNOWN"
227
+ fn = "#{REFCACHEDIR}/kdrfc-#{kdrfc_version}-#{meth}-#{Digest::SHA256.hexdigest(Marshal.dump(args))[0...40]}.cache"
228
+ begin
229
+ out = Marshal.load(File.binread(fn))
230
+ rescue StandardError => e
231
+ # warn e.inspect
232
+ out = method(meth).call(*args)
233
+ File.binwrite(fn, Marshal.dump(out))
234
+ end
235
+ out
236
+ end
237
+
238
+ def svg_tool_process(t, result)
239
+ require 'tempfile'
240
+ file = Tempfile.new("kramdown-rfc")
241
+ file.write(result)
242
+ file.close
243
+ case t
244
+ when "goat"
245
+ result1, _s = Open3.capture2("goat #{file.path}", stdin_data: result);
246
+ when "ditaa" # XXX: This needs some form of option-setting
247
+ result1, _s = Open3.capture2("ditaa #{file.path} --svg -o -", stdin_data: result);
248
+ when "mscgen"
249
+ result1, _s = Open3.capture2("mscgen -T svg -i #{file.path} -o -", stdin_data: result);
250
+ when "mermaid"
251
+ result1, _s = Open3.capture2("mmdc -i #{file.path}", stdin_data: result); # -b transparent
252
+ outpath = file.path + ".svg"
253
+ result1 = File.read(outpath)
254
+ File.unlink(outpath)
255
+ when "plantuml", "plantuml-utxt"
256
+ plantuml = "@startuml\n#{result}\n@enduml"
257
+ result1, _s = Open3.capture2("plantuml -pipe -tsvg", stdin_data: plantuml);
258
+ result, _s = Open3.capture2("plantuml -pipe -tutxt", stdin_data: plantuml) if t == "plantuml-utxt"
259
+ end
260
+ # warn ["goat:", result1.inspect]
261
+ file.unlink
262
+ result1 = svg_clean(result1) unless t == "goat"
263
+ result1, _s = Open3.capture2("svgcheck -qa", stdin_data: result1);
264
+ # warn ["svgcheck:", result1.inspect]
265
+ [result, result1]
266
+ end
267
+
178
268
  def convert_codeblock(el, indent, opts)
179
269
  # el.attr['anchor'] ||= saner_generate_id(el.value) -- no longer in 1.0.6
180
270
  result = el.value
@@ -219,30 +309,8 @@ module Kramdown
219
309
  end
220
310
  end
221
311
  case t
222
- when "goat", "ditaa", "mscgen", "plantuml", "plantuml-utxt"
223
- require 'tempfile'
224
- file = Tempfile.new("kramdown-rfc")
225
- file.write(result)
226
- file.close
227
- case t
228
- when "goat"
229
- result1, _s = Open3.capture2("goat #{file.path}", stdin_data: result);
230
- when "ditaa" # XXX: This needs some form of option-setting
231
- result1, _s = Open3.capture2("ditaa #{file.path} --svg -o -", stdin_data: result);
232
- result1 = svg_clean(result1)
233
- when "mscgen"
234
- result1, _s = Open3.capture2("mscgen -T svg -i #{file.path} -o -", stdin_data: result);
235
- result1 = svg_clean(result1)
236
- when "plantuml", "plantuml-utxt"
237
- plantuml = "@startuml\n#{result}\n@enduml"
238
- result1, _s = Open3.capture2("plantuml -pipe -tsvg", stdin_data: plantuml);
239
- result1 = svg_clean(result1)
240
- result, _s = Open3.capture2("plantuml -pipe -tutxt", stdin_data: plantuml) if t == "plantuml-utxt"
241
- end
242
- # warn ["goat:", result1.inspect]
243
- file.unlink
244
- result1, _s = Open3.capture2("svgcheck -qa", stdin_data: result1);
245
- # warn ["svgcheck:", result1.inspect]
312
+ when "goat", "ditaa", "mscgen", "plantuml", "plantuml-utxt", "mermaid"
313
+ result, result1 = memoize(:svg_tool_process, t, result)
246
314
  "#{' '*indent}<figure#{el_html_attributes(el)}><artset><artwork #{html_attributes(artwork_attr.merge("type"=> "svg"))}>#{result1.sub(/.*?<svg/m, "<svg")}</artwork><artwork #{html_attributes(artwork_attr.merge("type"=> "ascii-art"))}><![CDATA[#{result}#{result =~ /\n\Z/ ? '' : "\n"}]]></artwork></artset></figure>\n"
247
315
  else
248
316
  "#{' '*indent}<figure#{el_html_attributes(el)}><artwork#{html_attributes(artwork_attr)}><![CDATA[#{result}#{result =~ /\n\Z/ ? '' : "\n"}]]></artwork></figure>\n"
@@ -467,6 +535,10 @@ module Kramdown
467
535
  end
468
536
  end
469
537
 
538
+ def convert_contact(el, indent, opts)
539
+ "<contact#{el_html_attributes(el)}/>"
540
+ end
541
+
470
542
  REFCACHEDIR = ENV["KRAMDOWN_REFCACHEDIR"] || ".refcache"
471
543
 
472
544
  # warn "*** REFCACHEDIR #{REFCACHEDIR}"
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.3.8
4
+ version: 1.3.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-31 00:00:00.000000000 Z
11
+ date: 2020-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: kramdown
@@ -67,7 +67,7 @@ homepage: http://github.com/cabo/kramdown-rfc2629
67
67
  licenses:
68
68
  - MIT
69
69
  metadata: {}
70
- post_install_message:
70
+ post_install_message:
71
71
  rdoc_options: []
72
72
  require_paths:
73
73
  - lib
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
83
  version: '0'
84
84
  requirements: []
85
85
  rubygems_version: 3.1.2
86
- signing_key:
86
+ signing_key:
87
87
  specification_version: 4
88
88
  summary: Kramdown extension for generating RFC 7749 XML.
89
89
  test_files: []