diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index b973bbc7..1652be86 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -5,7 +5,7 @@ Enhancements:: * Issue #423: Add support for loading JSyntrax via the `asciidoctor-diagram-jsyntrax` gem (@inponomarev) -* Issue #464: Replace usage of 'base64' gem with 'radix_encoding' to resolve Ruby 3.3+ compatibility issues +* Issue #464: Remove usage of 'base64' gem to resolve Ruby 3.3+ compatibility issues Bugfixes:: diff --git a/asciidoctor-diagram.gemspec b/asciidoctor-diagram.gemspec index 588f009d..d6df1315 100644 --- a/asciidoctor-diagram.gemspec +++ b/asciidoctor-diagram.gemspec @@ -34,6 +34,5 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'asciidoctor', '>= 1.5.7', '< 3.x' s.add_runtime_dependency 'asciidoctor-diagram-ditaamini', '~> 1.0' s.add_runtime_dependency 'asciidoctor-diagram-plantuml', '~> 1.2021' - s.add_runtime_dependency 'radix_encoding', '0.2.0' s.add_runtime_dependency 'rexml' end diff --git a/lib/asciidoctor-diagram/http/converter.rb b/lib/asciidoctor-diagram/http/converter.rb index 48a96e9b..3485b052 100644 --- a/lib/asciidoctor-diagram/http/converter.rb +++ b/lib/asciidoctor-diagram/http/converter.rb @@ -1,7 +1,7 @@ require_relative '../diagram_converter' +require_relative '../util/base64' require_relative '../util/platform' -require 'radix_encoding' require 'net/http' require 'uri' require 'zlib' @@ -12,18 +12,6 @@ module Diagram class HttpConverter DEFAULT_MAX_GET_SIZE = 1024 - PLANTUML_ENCODING = RadixEncoding::Encoding.new( - alphabet: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_", - radix: 64, - padding: "=" - ) - - BASE64_URL_SAFE = RadixEncoding::Encoding.new( - alphabet: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", - radix: 64, - padding: "=" - ) - include DiagramConverter def initialize(base_uri, type, converter) @@ -59,16 +47,20 @@ def convert(source, format, options) compressed = deflate.deflate(code, Zlib::FINISH) deflate.close - - - data = PLANTUML_ENCODING.encode(compressed) + data = Base64.urlsafe_encode(compressed) + # See https://plantuml.com/text-encoding + # PlantUML uses a different alphabet than the one from RFC 4648 + data.tr!( + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', + '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + ) path = uri.path.dup path << '/' unless path.end_with? '/' path << format.to_s when :kroki_io compressed = Zlib.deflate(code, Zlib::BEST_COMPRESSION) - data = BASE64_URL_SAFE.encode(compressed) + data = Base64.urlsafe_encode(compressed) path = uri.path.dup path << '/' unless path.end_with? '/' diff --git a/lib/asciidoctor-diagram/http/server.rb b/lib/asciidoctor-diagram/http/server.rb index 61ad19ac..b51f37c6 100644 --- a/lib/asciidoctor-diagram/http/server.rb +++ b/lib/asciidoctor-diagram/http/server.rb @@ -4,6 +4,7 @@ require_relative '../diagram_source' require_relative '../graphviz/converter' +require_relative '../util/base64' require_relative '../util/which' module Asciidoctor @@ -13,7 +14,7 @@ class Server < Sinatra::Base type = params['type'] accepts = lambda { |t| params['format'].downcase.to_sym == t } raw_source = params['source'] - decoded_source = Asciidoctor::Diagram::HttpConverter::BASE64_URL_SAFE.decode(raw_source) + decoded_source = Base64.urlsafe_decode(raw_source) decompressed_source = Zlib::Inflate.inflate(decoded_source) source = decompressed_source render_diagram(type, accepts, source, {}) diff --git a/lib/asciidoctor-diagram/util/base64.rb b/lib/asciidoctor-diagram/util/base64.rb new file mode 100644 index 00000000..20d52566 --- /dev/null +++ b/lib/asciidoctor-diagram/util/base64.rb @@ -0,0 +1,25 @@ +module Asciidoctor + module Diagram + module Base64 + def self.urlsafe_encode(bin, padding: true) + str = [bin].pack("m0") + str.chomp!("==") or str.chomp!("=") unless padding + str.tr!("+/", "-_") + str + end + + def self.urlsafe_decode(str) + # NOTE: RFC 4648 does say nothing about unpadded input, but says that + # "the excess pad characters MAY also be ignored", so it is inferred that + # unpadded input is also acceptable. + if !str.end_with?("=") && str.length % 4 != 0 + str = str.ljust((str.length + 3) & ~3, "=") + str.tr!("-_", "+/") + else + str = str.tr("-_", "+/") + end + str.unpack1("m0") + end + end + end +end \ No newline at end of file