From 49ed78075a3a0038a2dde8f478434bf567be9154 Mon Sep 17 00:00:00 2001
From: Brett Walker <bwalker@gitlab.com>
Date: Wed, 27 Nov 2024 20:14:50 +0000
Subject: [PATCH] Only use url generation from gem

Method we used changed, so now build our own image
tag and use the gem's `gen_url` method.
---
 Gemfile                                       |  2 +-
 Gemfile.checksum                              |  2 +-
 Gemfile.lock                                  |  4 ++--
 Gemfile.next.checksum                         |  2 +-
 Gemfile.next.lock                             |  4 ++--
 app/models/application_setting.rb             |  4 ----
 lib/banzai/filter/plantuml_filter.rb          | 20 ++++++++++++++++---
 .../lib/banzai/filter/plantuml_filter_spec.rb | 17 ++++++++++++----
 spec/lib/gitlab/other_markup_spec.rb          |  2 +-
 spec/support/matchers/markdown_matchers.rb    |  2 +-
 10 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/Gemfile b/Gemfile
index bdf30c6993353..67b716bf6ed75 100644
--- a/Gemfile
+++ b/Gemfile
@@ -256,7 +256,7 @@ gem 'creole', '~> 0.5.0', feature_category: :markdown
 gem 'wikicloth', '0.8.1', feature_category: :markdown
 gem 'asciidoctor', '~> 2.0.18', feature_category: :markdown
 gem 'asciidoctor-include-ext', '~> 0.4.0', require: false, feature_category: :markdown
-gem 'asciidoctor-plantuml', '~> 0.0.16', feature_category: :markdown
+gem 'asciidoctor-plantuml', '~> 0.1.1', feature_category: :markdown
 gem 'asciidoctor-kroki', '~> 0.10.0', require: false, feature_category: :markdown
 gem 'rouge', '~> 4.4.0', feature_category: :shared
 gem 'truncato', '~> 0.7.12', feature_category: :team_planning
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 9b6d34d1c5fb4..f5422b22d2d41 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -26,7 +26,7 @@
 {"name":"asciidoctor","version":"2.0.23","platform":"ruby","checksum":"52208807f237dfa0ca29882f8b13d60b820496116ad191cf197ca56f2b7fddf3"},
 {"name":"asciidoctor-include-ext","version":"0.4.0","platform":"ruby","checksum":"406adb9d2fbfc25536609ca13b787ed704dc06a4e49d6709b83f3bad578f7878"},
 {"name":"asciidoctor-kroki","version":"0.10.0","platform":"ruby","checksum":"8e4225d88f120e2e7b5d3f5ddb67c5e69496d7344a16c57db5036ac900123062"},
-{"name":"asciidoctor-plantuml","version":"0.0.16","platform":"ruby","checksum":"407e47cd1186ded5ccc75f0c812e5524c26c571d542247c5132abb8f47bd1793"},
+{"name":"asciidoctor-plantuml","version":"0.1.1","platform":"ruby","checksum":"2bfa1a79349aa3fff611cdc54ade674e91423e38c20a21b24d8ca59006a0b0ae"},
 {"name":"ast","version":"2.4.2","platform":"ruby","checksum":"1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12"},
 {"name":"async","version":"2.12.1","platform":"ruby","checksum":"146fb3acf6d05ad40abb9ae659dd3b574067a3420fe7d6d5d6a3cf5413de3ea5"},
 {"name":"atlassian-jwt","version":"0.2.1","platform":"ruby","checksum":"2fd2d87418773f2e140c038cb22e049069708aff2bd0a423a7e1740574e97823"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 954dcdc8c00db..4e4bd4a2d1263 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -331,7 +331,7 @@ GEM
       asciidoctor (>= 1.5.6, < 3.0.0)
     asciidoctor-kroki (0.10.0)
       asciidoctor (~> 2.0)
-    asciidoctor-plantuml (0.0.16)
+    asciidoctor-plantuml (0.1.1)
       asciidoctor (>= 2.0.17, < 3.0.0)
     ast (2.4.2)
     async (2.12.1)
@@ -1980,7 +1980,7 @@ DEPENDENCIES
   asciidoctor (~> 2.0.18)
   asciidoctor-include-ext (~> 0.4.0)
   asciidoctor-kroki (~> 0.10.0)
-  asciidoctor-plantuml (~> 0.0.16)
+  asciidoctor-plantuml (~> 0.1.1)
   async (~> 2.12.1)
   atlassian-jwt (~> 0.2.1)
   attr_encrypted (~> 3.2.4)!
diff --git a/Gemfile.next.checksum b/Gemfile.next.checksum
index da5add729d22e..06c1c4ff8b917 100644
--- a/Gemfile.next.checksum
+++ b/Gemfile.next.checksum
@@ -26,7 +26,7 @@
 {"name":"asciidoctor","version":"2.0.23","platform":"ruby","checksum":"52208807f237dfa0ca29882f8b13d60b820496116ad191cf197ca56f2b7fddf3"},
 {"name":"asciidoctor-include-ext","version":"0.4.0","platform":"ruby","checksum":"406adb9d2fbfc25536609ca13b787ed704dc06a4e49d6709b83f3bad578f7878"},
 {"name":"asciidoctor-kroki","version":"0.10.0","platform":"ruby","checksum":"8e4225d88f120e2e7b5d3f5ddb67c5e69496d7344a16c57db5036ac900123062"},
-{"name":"asciidoctor-plantuml","version":"0.0.16","platform":"ruby","checksum":"407e47cd1186ded5ccc75f0c812e5524c26c571d542247c5132abb8f47bd1793"},
+{"name":"asciidoctor-plantuml","version":"0.1.1","platform":"ruby","checksum":"2bfa1a79349aa3fff611cdc54ade674e91423e38c20a21b24d8ca59006a0b0ae"},
 {"name":"ast","version":"2.4.2","platform":"ruby","checksum":"1e280232e6a33754cde542bc5ef85520b74db2aac73ec14acef453784447cc12"},
 {"name":"async","version":"2.12.1","platform":"ruby","checksum":"146fb3acf6d05ad40abb9ae659dd3b574067a3420fe7d6d5d6a3cf5413de3ea5"},
 {"name":"atlassian-jwt","version":"0.2.1","platform":"ruby","checksum":"2fd2d87418773f2e140c038cb22e049069708aff2bd0a423a7e1740574e97823"},
diff --git a/Gemfile.next.lock b/Gemfile.next.lock
index bd7ec9b03a11f..a3e685ad12810 100644
--- a/Gemfile.next.lock
+++ b/Gemfile.next.lock
@@ -340,7 +340,7 @@ GEM
       asciidoctor (>= 1.5.6, < 3.0.0)
     asciidoctor-kroki (0.10.0)
       asciidoctor (~> 2.0)
-    asciidoctor-plantuml (0.0.16)
+    asciidoctor-plantuml (0.1.1)
       asciidoctor (>= 2.0.17, < 3.0.0)
     ast (2.4.2)
     async (2.12.1)
@@ -2007,7 +2007,7 @@ DEPENDENCIES
   asciidoctor (~> 2.0.18)
   asciidoctor-include-ext (~> 0.4.0)
   asciidoctor-kroki (~> 0.10.0)
-  asciidoctor-plantuml (~> 0.0.16)
+  asciidoctor-plantuml (~> 0.1.1)
   async (~> 2.12.1)
   atlassian-jwt (~> 0.2.1)
   attr_encrypted (~> 3.2.4)!
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 03d0b7ad1c1af..11f27fd561898 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -885,10 +885,6 @@ def validate_kroki_url
     validate_url(parsed_kroki_url, :kroki_url, KROKI_URL_ERROR_MESSAGE)
   end
 
-  def kroki_url_absolute?
-    parsed_kroki_url&.absolute?
-  end
-
   def sourcegraph_url_is_com?
     !!(sourcegraph_url =~ %r{\Ahttps://(www\.)?sourcegraph\.com})
   end
diff --git a/lib/banzai/filter/plantuml_filter.rb b/lib/banzai/filter/plantuml_filter.rb
index 090bf08c6a47a..030443c0a3c99 100644
--- a/lib/banzai/filter/plantuml_filter.rb
+++ b/lib/banzai/filter/plantuml_filter.rb
@@ -9,18 +9,23 @@ module Filter
     #
     class PlantumlFilter < HTML::Pipeline::Filter
       prepend Concerns::PipelineTimingCheck
+      include ActionView::Helpers::TagHelper
+      include Gitlab::Utils::StrongMemoize
 
       def call
         return doc unless settings.plantuml_enabled? && doc.at_xpath(lang_tag)
+        return doc unless plantuml_url_valid?
 
         Gitlab::Plantuml.configure
 
         doc.xpath(lang_tag).each do |node|
-          img_tag = Nokogiri::HTML::DocumentFragment.parse(
-            Asciidoctor::PlantUml::Processor.plantuml_content(node.content, {})).css('img').first
+          next if node.content.blank?
 
-          next if img_tag.nil?
+          image_src = create_image_src('png', node.content)
+          img_tag = Nokogiri::HTML::DocumentFragment.parse(content_tag(:img, nil, src: image_src))
+          img_tag = img_tag.children.first
 
+          img_tag.add_class('plantuml')
           img_tag.set_attribute('data-diagram', 'plantuml')
           img_tag.set_attribute('data-diagram-src', "data:text/plain;base64,#{Base64.strict_encode64(node.content)}")
 
@@ -40,6 +45,15 @@ def lang_tag
       def settings
         Gitlab::CurrentSettings.current_application_settings
       end
+      strong_memoize_attr :settings
+
+      def create_image_src(format, text)
+        Asciidoctor::PlantUml::Processor.gen_url(text, format)
+      end
+
+      def plantuml_url_valid?
+        ::Gitlab::UrlSanitizer.valid_web?(settings.plantuml_url)
+      end
     end
   end
 end
diff --git a/spec/lib/banzai/filter/plantuml_filter_spec.rb b/spec/lib/banzai/filter/plantuml_filter_spec.rb
index bbbabd7a6bbc1..c1da963e51278 100644
--- a/spec/lib/banzai/filter/plantuml_filter_spec.rb
+++ b/spec/lib/banzai/filter/plantuml_filter_spec.rb
@@ -9,7 +9,7 @@
     stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
 
     input = '<pre data-canonical-lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
-    output = '<img class="plantuml" src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq" data-diagram="plantuml" data-diagram-src="data:text/plain;base64,Qm9iIC0+IFNhcmEgOiBIZWxsbw==">'
+    output = '<img src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq" class="plantuml" data-diagram="plantuml" data-diagram-src="data:text/plain;base64,Qm9iIC0+IFNhcmEgOiBIZWxsbw==">'
     doc = filter(input)
 
     expect(doc.to_s).to eq output
@@ -19,7 +19,7 @@
     stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
 
     input = '<pre><code data-canonical-lang="plantuml">Bob -> Sara : Hello</code></pre>'
-    output = '<img class="plantuml" src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq" data-diagram="plantuml" data-diagram-src="data:text/plain;base64,Qm9iIC0+IFNhcmEgOiBIZWxsbw==">'
+    output = '<img src="http://localhost:8080/png/U9npoazIqBLJ24uiIbImKl18pSd91m0rkGMq" class="plantuml" data-diagram="plantuml" data-diagram-src="data:text/plain;base64,Qm9iIC0+IFNhcmEgOiBIZWxsbw==">'
     doc = filter(input)
 
     expect(doc.to_s).to eq output
@@ -35,8 +35,17 @@
     expect(doc.to_s).to eq output
   end
 
-  it 'does not replace plantuml pre tag with img tag if url is invalid' do
-    stub_application_setting(plantuml_enabled: true, plantuml_url: "invalid")
+  it 'does not replace plantuml pre tag if there is no content' do
+    stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
+
+    input = '<pre><code data-canonical-lang="plantuml"></code></pre>'
+    doc = filter(input)
+
+    expect(doc.to_s).to eq input
+  end
+
+  it 'does not replace plantuml pre tag if the url is not valid' do
+    stub_application_setting(plantuml_enabled: true, plantuml_url: "invalid://localhost:8080")
 
     input = '<pre data-canonical-lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
     output = '<pre data-canonical-lang="plantuml"><code>Bob -&gt; Sara : Hello</code></pre>'
diff --git a/spec/lib/gitlab/other_markup_spec.rb b/spec/lib/gitlab/other_markup_spec.rb
index cb0d8dd1bf1a1..7f50e4f504b41 100644
--- a/spec/lib/gitlab/other_markup_spec.rb
+++ b/spec/lib/gitlab/other_markup_spec.rb
@@ -35,7 +35,7 @@
         RST
 
         output = <<~HTML
-          <img class="plantuml" src="https://plantuml.com/plantuml/png/U9npoazIqBLJSCp9J4wrKiX8pSd9vm9pGA9E-Kb0iKm0o4SAt000" data-diagram="plantuml" data-diagram-src="data:text/plain;base64,Qm9iIC0+IEFsaWNlOiBoZWxsbwpBbGljZSAtPiBCb2I6IGhp">
+          <img src="https://plantuml.com/plantuml/png/U9npoazIqBLJSCp9J4wrKiX8pSd9vm9pGA9E-Kb0iKm0o4SAt000" class="plantuml" data-diagram="plantuml" data-diagram-src="data:text/plain;base64,Qm9iIC0+IEFsaWNlOiBoZWxsbwpBbGljZSAtPiBCb2I6IGhp">
           <p>Caption with <strong>bold</strong> and <em>italic</em></p>
         HTML
 
diff --git a/spec/support/matchers/markdown_matchers.rb b/spec/support/matchers/markdown_matchers.rb
index c0ebcc5c4747a..4a205ae6bf617 100644
--- a/spec/support/matchers/markdown_matchers.rb
+++ b/spec/support/matchers/markdown_matchers.rb
@@ -299,7 +299,7 @@ def have_image(src)
     end
   end
 
-  # PLantumlFilter
+  # PlantumlFilter
   matcher :parse_plantuml do
     set_default_markdown_messages
 
-- 
GitLab