New Upstream Release - ruby-asciidoctor-plantuml

Ready changes

Summary

Merged new upstream version: 0.1.1 (was: 0.0.16).

Resulting package

Built on 2023-01-11T04:52 (took 13m5s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-releases ruby-asciidoctor-plantuml

Lintian Result

Diff

diff --git a/asciidoctor-plantuml.gemspec b/asciidoctor-plantuml.gemspec
index c99a633..4dd1bad 100644
--- a/asciidoctor-plantuml.gemspec
+++ b/asciidoctor-plantuml.gemspec
@@ -2,26 +2,26 @@
 # This file has been automatically generated by gem2tgz #
 #########################################################
 # -*- encoding: utf-8 -*-
-# stub: asciidoctor-plantuml 0.0.16 ruby lib
+# stub: asciidoctor-plantuml 0.1.1 ruby lib
 
 Gem::Specification.new do |s|
   s.name = "asciidoctor-plantuml".freeze
-  s.version = "0.0.16"
+  s.version = "0.1.1"
 
   s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
   s.metadata = { "rubygems_mfa_required" => "true" } if s.respond_to? :metadata=
   s.require_paths = ["lib".freeze]
   s.authors = ["Horacio Sanson".freeze]
-  s.date = "2022-04-30"
+  s.date = "2022-05-01"
   s.description = "Asciidoctor PlantUML extension".freeze
   s.email = ["hsanson@gmail.com".freeze]
-  s.files = ["lib/asciidoctor-plantuml.rb".freeze, "lib/asciidoctor_plantuml/plantuml.rb".freeze, "lib/asciidoctor_plantuml/version.rb".freeze, "test/test_plantuml.rb".freeze]
+  s.files = ["lib/asciidoctor-plantuml.rb".freeze, "lib/asciidoctor_plantuml/plantuml.rb".freeze, "lib/asciidoctor_plantuml/version.rb".freeze, "test/fixtures/config.puml".freeze, "test/fixtures/test.puml".freeze, "test/test_plantuml.rb".freeze]
   s.homepage = "https://github.com/hsanson/asciidoctor-plantuml".freeze
   s.licenses = ["MIT".freeze]
   s.required_ruby_version = Gem::Requirement.new(">= 2.6".freeze)
-  s.rubygems_version = "3.3.15".freeze
+  s.rubygems_version = "3.2.5".freeze
   s.summary = "Asciidoctor support for PlantUML diagrams.".freeze
-  s.test_files = ["test/test_plantuml.rb".freeze]
+  s.test_files = ["test/fixtures/config.puml".freeze, "test/fixtures/test.puml".freeze, "test/test_plantuml.rb".freeze]
 
   if s.respond_to? :specification_version then
     s.specification_version = 4
diff --git a/debian/changelog b/debian/changelog
index 8e9fcbd..df4876f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+ruby-asciidoctor-plantuml (0.1.1-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Wed, 11 Jan 2023 04:40:11 -0000
+
 ruby-asciidoctor-plantuml (0.0.16-1) unstable; urgency=medium
 
   [ Balasankar C ]
diff --git a/lib/asciidoctor-plantuml.rb b/lib/asciidoctor-plantuml.rb
index 97e0a66..83bd652 100644
--- a/lib/asciidoctor-plantuml.rb
+++ b/lib/asciidoctor-plantuml.rb
@@ -6,4 +6,5 @@ require_relative 'asciidoctor_plantuml/plantuml'
 
 Asciidoctor::Extensions.register do
   block Asciidoctor::PlantUml::BlockProcessor, :plantuml
+  block_macro Asciidoctor::PlantUml::BlockMacroProcessor, :plantuml
 end
diff --git a/lib/asciidoctor_plantuml/plantuml.rb b/lib/asciidoctor_plantuml/plantuml.rb
index 9077e60..cf9f57d 100644
--- a/lib/asciidoctor_plantuml/plantuml.rb
+++ b/lib/asciidoctor_plantuml/plantuml.rb
@@ -78,23 +78,56 @@ module Asciidoctor
           txt_enabled? || png_enabled? || svg_enabled?
         end
 
-        def plantuml_content_format(code, format, attrs = {})
-          if %w[png svg txt].include?(format) &&
-             method("#{format}_enabled?").call
-            method("plantuml_#{format}_content").call(code, format, attrs)
+        def plantuml_content_format(parent, code, format, attrs = {})
+          content = code.read
+
+          # honor subs attributes
+          # e.g. replace asciidoc variables
+          subs = attrs['subs']
+          content = parent.apply_subs(content, parent.resolve_subs(subs)) if subs
+
+          # add @start... and @end... if missing
+          content = "@startuml\n#{content}\n@enduml" unless content =~ /^@start.*@end[a-z]*$/m
+
+          # insert global plantuml config after first line
+          config_path = parent.attr('plantuml-include', '', true)
+
+          unless config_path.empty?
+            begin
+              source_file = parent.document.normalize_system_path(config_path, nil, nil, recover: false)
+              content = insert_config_to_content(parent, source_file, content, attrs)
+            rescue StandardError => e
+              return plantuml_invalid_file(source_file, e.message, attrs)
+            rescue SecurityError => e
+              return plantuml_insecure_file(source_file, e.message, attrs)
+            end
+          end
+
+          if %w[png svg txt].include?(format) && method("#{format}_enabled?").call
+            method("plantuml_#{format}_content").call(content, format, attrs)
           else
             plantuml_invalid_content(format, attrs)
           end
         end
 
-        def plantuml_content(code, attrs = {})
+        def plantuml_content(parent, code, attrs = {})
           format = attrs['format'] || DEFAULT_FORMAT
 
           return plantuml_disabled_content(code, attrs) unless enabled?
 
           return plantuml_server_unavailable_content(server_url, attrs) unless valid_uri?(server_url)
 
-          plantuml_content_format(code, format, attrs)
+          plantuml_content_format(parent, code, format, attrs)
+        end
+
+        def plantuml_content_from_file(parent, target, attrs = {})
+          source_file = parent.document.normalize_system_path(target, nil, nil, recover: false)
+          content = ::File.open(source_file, mode: FILE_READ_MODE)
+          plantuml_content(parent, content, attrs)
+        rescue StandardError => e
+          plantuml_invalid_file(source_file, e.message, attrs)
+        rescue SecurityError => e
+          plantuml_insecure_file(source_file, e.message, attrs)
         end
 
         # Compression code used to generate PlantUML URLs. Taken directly from
@@ -113,8 +146,23 @@ module Asciidoctor
           join_paths(server_url, "#{format}/", result).to_s
         end
 
+        def create_plantuml_block(parent, content, attrs)
+          Asciidoctor::Block.new parent, :pass, {
+            content_model: :raw,
+            source: content,
+            subs: :default
+          }.merge(attrs)
+        end
+
         private
 
+        def insert_config_to_content(parent, config_path, content, attrs)
+          config = File.read(config_path, mode: FILE_READ_MODE)
+          subs = attrs['subs']
+          config = parent.apply_subs(config, parent.resolve_subs(subs)) if subs
+          return content.dup.insert(content.index("\n"), "\n#{config}") unless config.empty?
+        end
+
         def plantuml_txt_content(code, format, attrs = {})
           url = gen_url(code, format)
           URI(url).open do |f|
@@ -180,6 +228,16 @@ module Asciidoctor
           _plantuml_error_content(code, attrs)
         end
 
+        def plantuml_invalid_file(file, error, attrs = {})
+          error = "PlantUML Error: Could not parse \"#{file}\": #{error}"
+          _plantuml_error_content(error, attrs)
+        end
+
+        def plantuml_insecure_file(file, error, attrs = {})
+          error = "PlantUML Error: Could not read \"#{file}\": #{error}"
+          _plantuml_error_content(error, attrs)
+        end
+
         def _plantuml_error_content(error, attrs = {})
           content = '<div class="listingblock">'
           content += '<div class="content">'
@@ -263,25 +321,19 @@ module Asciidoctor
       content_model :simple
 
       def process(parent, target, attrs)
-        lines = target.lines
-
-        lines = ['@startuml'] + target.lines unless target.lines[0] =~ /@startuml/
-
-        lines += ['@enduml'] unless target.lines[-1] =~ /@enduml/
-
-        content = Processor.plantuml_content(lines.join("\n"), attrs)
-
-        create_plantuml_block(parent, content, attrs)
+        content = Processor.plantuml_content(parent, target, attrs)
+        Processor.create_plantuml_block(parent, content, attrs)
       end
+    end
 
-      private
+    # PlantUML BlockMacroProcessor
+    class BlockMacroProcessor < Asciidoctor::Extensions::BlockMacroProcessor
+      use_dsl
+      named :plantuml
 
-      def create_plantuml_block(parent, content, attrs)
-        Asciidoctor::Block.new parent, :pass,  {
-          content_model: :raw,
-          source: content,
-          subs: :default
-        }.merge(attrs)
+      def process(parent, target, attrs)
+        content = Processor.plantuml_content_from_file(parent, target, attrs)
+        Processor.create_plantuml_block(parent, content, attrs)
       end
     end
   end
diff --git a/lib/asciidoctor_plantuml/version.rb b/lib/asciidoctor_plantuml/version.rb
index ee35038..1ebf6db 100644
--- a/lib/asciidoctor_plantuml/version.rb
+++ b/lib/asciidoctor_plantuml/version.rb
@@ -2,6 +2,6 @@
 
 module Asciidoctor
   module PlantUML
-    VERSION = '0.0.16'
+    VERSION = '0.1.1'
   end
 end
diff --git a/test/fixtures/config.puml b/test/fixtures/config.puml
new file mode 100644
index 0000000..328674a
--- /dev/null
+++ b/test/fixtures/config.puml
@@ -0,0 +1,3 @@
+skinparam monochrome true
+skinparam backgroundColor transparent
+skinparam style strictuml
\ No newline at end of file
diff --git a/test/fixtures/test.puml b/test/fixtures/test.puml
new file mode 100644
index 0000000..91e5e6c
--- /dev/null
+++ b/test/fixtures/test.puml
@@ -0,0 +1,4 @@
+@startuml
+User -> (Start)
+User --> (Use the application) : Label
+@enduml
\ No newline at end of file
diff --git a/test/test_plantuml.rb b/test/test_plantuml.rb
index ea4dc9b..a91c6cf 100644
--- a/test/test_plantuml.rb
+++ b/test/test_plantuml.rb
@@ -184,10 +184,88 @@ DOC_SVG = <<~ENDOFSTRING
   ----
 ENDOFSTRING
 
+DOC_BLOCK_MACRO = <<~ENDOFSTRING
+  = Hello PlantUML!
+
+  .Title Of this
+  plantuml::test/fixtures/test.puml[]
+ENDOFSTRING
+
+DOC_BLOCK_MACRO_MISSING_FILE = <<~ENDOFSTRING
+  = Hello PlantUML!
+
+  .Title Of this
+  plantuml::test/fixtures/missing.puml[]
+ENDOFSTRING
+
+DOC_BLOCK_MACRO_INSECURE_FILE = <<~ENDOFSTRING
+  = Hello PlantUML!
+
+  .Title Of this
+  plantuml::/etc/passwd[]
+ENDOFSTRING
+
+DOC_SUBS_ATTRIBUTES = <<~ENDOFSTRING
+  = Hello PlantUML!
+  :text: Label
+
+  [plantuml, format="png", subs="attributes+"]
+  .Title Of this
+  ----
+  User -> (Start)
+  User --> (Use the application) : {text}
+  ----
+ENDOFSTRING
+
+DOC_CONFIG_INCLUDE = <<~ENDOFSTRING
+  = Hello PlantUML!
+  :plantuml-include: test/fixtures/config.puml
+
+  [plantuml, format="png"]
+  .Title Of this
+  ----
+  User -> (Start)
+  User --> (Use the application) : Label
+  ----
+ENDOFSTRING
+
+DOC_CONFIG_INCLUDE_MISSING_FILE = <<~ENDOFSTRING
+  = Hello PlantUML!
+  :plantuml-include: test/fixtures/missing.puml
+
+  [plantuml, format="png"]
+  .Title Of this
+  ----
+  User -> (Start)
+  User --> (Use the application) : Label
+  ----
+ENDOFSTRING
+
+DOC_CONFIG_INCLUDE_INSECURE_FILE = <<~ENDOFSTRING
+  = Hello PlantUML!
+  :plantuml-include: /etc/passwd
+
+  [plantuml, format="png"]
+  .Title Of this
+  ----
+  User -> (Start)
+  User --> (Use the application) : Label
+  ----
+ENDOFSTRING
+
+DOC_CONFIG_INCLUDE_MACRO_BLOCK = <<~ENDOFSTRING
+  = Hello PlantUML!
+  :plantuml-include: test/fixtures/config.puml
+
+  [plantuml, format="png"]
+  plantuml::test/fixtures/test.puml[]
+ENDOFSTRING
+
 class PlantUmlTest < Test::Unit::TestCase
   GENURL = 'http://localhost:8080/plantuml/png/U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
   GENURL2 = 'http://localhost:8080/plantuml/png/U9npA2v9B2efpStXYdRszmqmZ8NGHh4mleAkdGAAa15G22Pc7Clba9gN0jGE00W75Cm0'
   GENURL_ENCODING = 'http://localhost:8080/plantuml/png/~1U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
+  GENURL_CONFIG = 'http://localhost:8080/plantuml/png/~1U9nDZJ4Emp08HVUSWh4PUe4ELQIktQeUW3YeiMA31NZexKEg3bc-Fly1Vp97zLxBO5lcXeeLgh2aLQKIk7OwaHdJzb7fl3oaY0P6ja34Vjeo_nOArPn-dzz62jSxN5v7r_YVZo0S-4g0hPMSqBFm23Tuuanbc8YNEDy1SzOwlG00'
   SVGGENURL = 'http://localhost:8080/plantuml/svg/~1U9npA2v9B2efpStX2YrEBLBGjLFG20Q9Q4Bv804WIw4a8rKXiQ0W9pCviIGpFqzJmKh19p4fDOVB8JKl1QWT05kd5wq0'
 
   def setup
@@ -302,6 +380,94 @@ class PlantUmlTest < Test::Unit::TestCase
     assert_equal GENURL_ENCODING, element['src']
   end
 
+  def test_plantuml_block_macro_processor
+    html = ::Asciidoctor.convert(StringIO.new(DOC_BLOCK_MACRO), backend: 'html5')
+    page = Nokogiri::HTML(html)
+
+    elements = page.css('img.plantuml')
+
+    assert_equal elements.size, 1
+
+    element = elements.first
+
+    assert_equal GENURL, element['src']
+  end
+
+  def test_should_show_file_error
+    html = ::Asciidoctor.convert(StringIO.new(DOC_BLOCK_MACRO_MISSING_FILE), backend: 'html5', safe: :secure)
+    page = Nokogiri::HTML(html)
+
+    elements = page.css('pre.plantuml-error')
+    assert_equal elements.size, 1
+    assert_includes html, 'No such file or directory'
+  end
+
+  def test_should_show_insecure_error
+    html = ::Asciidoctor.convert(StringIO.new(DOC_BLOCK_MACRO_INSECURE_FILE), backend: 'html5', safe: :secure)
+    page = Nokogiri::HTML(html)
+
+    elements = page.css('pre.plantuml-error')
+    assert_equal elements.size, 1
+    assert_includes html, 'is outside of jail'
+  end
+
+  def test_plantuml_subs_attributes
+    html = ::Asciidoctor.convert(StringIO.new(DOC_SUBS_ATTRIBUTES), backend: 'html5')
+    page = Nokogiri::HTML(html)
+
+    elements = page.css('img.plantuml')
+
+    assert_equal elements.size, 1
+
+    element = elements.first
+
+    assert_equal GENURL_ENCODING, element['src']
+  end
+
+  def test_plantuml_config_include
+    html = ::Asciidoctor.convert(StringIO.new(DOC_CONFIG_INCLUDE), backend: 'html5', safe: :secure)
+    page = Nokogiri::HTML(html)
+
+    elements = page.css('img.plantuml')
+
+    assert_equal elements.size, 1
+
+    element = elements.first
+
+    assert_equal GENURL_CONFIG, element['src']
+  end
+
+  def test_plantuml_config_include_missing_file
+    html = ::Asciidoctor.convert(StringIO.new(DOC_CONFIG_INCLUDE_MISSING_FILE), backend: 'html5')
+    page = Nokogiri::HTML(html)
+
+    elements = page.css('pre.plantuml-error')
+    assert_equal elements.size, 1
+    assert_includes html, 'No such file or directory'
+  end
+
+  def test_plantuml_config_include_insecure_file
+    html = ::Asciidoctor.convert(StringIO.new(DOC_CONFIG_INCLUDE_INSECURE_FILE), backend: 'html5', safe: :secure)
+    page = Nokogiri::HTML(html)
+
+    elements = page.css('pre.plantuml-error')
+    assert_equal elements.size, 1
+    assert_includes html, 'is outside of jail'
+  end
+
+  def test_plantuml_config_include_macro_block
+    html = ::Asciidoctor.convert(StringIO.new(DOC_CONFIG_INCLUDE_MACRO_BLOCK), backend: 'html5', safe: :secure)
+    page = Nokogiri::HTML(html)
+
+    elements = page.css('img.plantuml')
+
+    assert_equal elements.size, 1
+
+    element = elements.first
+
+    assert_equal GENURL_CONFIG, element['src']
+  end
+
   def test_plantuml_id_attribute
     html = ::Asciidoctor.convert(StringIO.new(DOC_ID), backend: 'html5')
     page = Nokogiri::HTML(html)

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/share/rubygems-integration/all/specifications/asciidoctor-plantuml-0.1.1.gemspec

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/share/rubygems-integration/all/specifications/asciidoctor-plantuml-0.0.16.gemspec

No differences were encountered in the control files

More details

Full run details