FIX: Do not truncate encoded slugs

FIX: Do not truncate encoded slugs

Trying to truncate encoded slugs will mean that we have to keep the URL valid, which can be tricky as you have to be aware of multibyte characters.

Since we already have upper bounds for the title, the slug won’t grow for more than title*6 in the worst case. The slug column in the topic table can store that just fine.

Added a test to ensure that a generated slug is a valid URL too, so we don’t introduce regressions in the future.

diff --git a/lib/slug.rb b/lib/slug.rb
index 8436f74ebc..f50492bddf 100644
--- a/lib/slug.rb
+++ b/lib/slug.rb
@@ -9,6 +9,10 @@ module Slug
   def self.for(string, default = 'topic', max_length = MAX_LENGTH)
     string = string.gsub(/:([\w\-+]+(?::t\d)?):/, '') if string.present? # strip emoji strings
 
+    if SiteSetting.slug_generation_method == 'encoded'
+      max_length = 9999 # do not truncate encoded slugs
+    end
+
     slug =
       case (SiteSetting.slug_generation_method || :ascii).to_sym
       when :ascii then self.ascii_generator(string)
diff --git a/spec/components/slug_spec.rb b/spec/components/slug_spec.rb
index dba8bcb6f5..699d3e0c6b 100644
--- a/spec/components/slug_spec.rb
+++ b/spec/components/slug_spec.rb
@@ -81,6 +81,11 @@ describe Slug do
       it "kills the trailing dash" do
         expect(Slug.for("2- -this!~-_|,we-#-=^-")).to eq('2-this-we')
       end
+
+      it "returns a slug that can be used in a valid URL" do
+        slug = Slug.for("Γνωμη για αγορα μπουζουκιου μεσω ιντερνετ και εκτίμηση")
+        expect { URI.parse("http://example.com/#{slug}") }.not_to raise_error
+      end
     end
 
     context 'none generator' do

GitHub sha: 2304dcf9

I think highest possible multiplier is at least 12:

CGI.escape('😂')
=> "%F0%9F%98%82"
2 Likes

This commit has been mentioned on Discourse Meta. There might be relevant details there:

Last I checked we limit for at most 1 emoji in a title, so I think most chars will fit in two or three. Anyway the column can hold it.

1 Like