Skip to content

Commit 515337c

Browse files
authored
Add ASCII slug for topic function (#2)
Uses AnyAscii for Ascii generation
1 parent 3804253 commit 515337c

3 files changed

Lines changed: 91 additions & 0 deletions

File tree

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
require 'any_ascii'
4+
5+
module ::DiscourseModifications
6+
class TopicSlug
7+
8+
# Converts a topic title into a slug, removing any emoji strings and normalizing the text.
9+
# This is primarily adds the unicode normalization step to the existing slug generation process
10+
# for ASCII encoding.
11+
def self.slug_for_topic(topic, slug, title)
12+
return slug unless (SiteSetting.slug_generation_method || :ascii).to_sym == :ascii
13+
14+
string = title.gsub(/:([\w\-+]+(?::t\d)?):/, "")
15+
string = AnyAscii.transliterate(string)
16+
string = Slug.ascii_generator(string)
17+
string = Slug.prettify_slug(string, max_length: Slug::MAX_LENGTH)
18+
19+
string.blank? || Slug.slug_is_only_numbers?(string) ? "topic-#{topic.id}" : string
20+
end
21+
end
22+
end

plugin.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
# url: TODO
99
# required_version: 2.7.0
1010

11+
gem 'any_ascii', '0.3.2'
12+
1113
enabled_site_setting :discourse_modifications_enabled
1214

1315
module ::DiscourseModifications
@@ -18,4 +20,9 @@ module ::DiscourseModifications
1820

1921
after_initialize do
2022
# Code which should run after Rails has finished booting
23+
24+
# Note: if this file gets too large, consider moving code into separate files in the lib directory
25+
# and applying a Initializer pattern to load them.
26+
27+
Topic.slug_computed_callbacks << ::DiscourseModifications::TopicSlug.method(:slug_for_topic)
2128
end
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.configure { |c| c.filter_run_when_matching :focus }
4+
5+
RSpec.describe DiscourseModifications::TopicSlug do
6+
let(:topic) { Fabricate(:topic, id: 42) }
7+
8+
describe ".slug_for_topic" do
9+
before do
10+
# Default to ascii slug generation
11+
allow(SiteSetting).to receive(:slug_generation_method).and_return("ascii")
12+
end
13+
14+
it "removes emoji codes from the title" do
15+
title = "Hello :smile: World"
16+
slug = "hello-world"
17+
expect(described_class.slug_for_topic(topic, slug, title)).to eq("hello-world")
18+
end
19+
20+
it "unicode normalizes the title" do
21+
title = "Café"
22+
slug = "cafe"
23+
expect(described_class.slug_for_topic(topic, slug, title)).to eq("cafe")
24+
end
25+
26+
it "returns the original slug if slug_generation_method is not ascii" do
27+
allow(SiteSetting).to receive(:slug_generation_method).and_return("encoded")
28+
expect(described_class.slug_for_topic(topic, "original-slug", "Some Title")).to eq("original-slug")
29+
end
30+
31+
it "returns a fallback slug if the result is blank" do
32+
title = ":smile:"
33+
slug = ""
34+
expect(described_class.slug_for_topic(topic, slug, title)).to eq("topic-42")
35+
end
36+
37+
it "returns a fallback slug if the result is only numbers" do
38+
title = "123456"
39+
slug = "123456"
40+
expect(described_class.slug_for_topic(topic, slug, title)).to eq("topic-42")
41+
end
42+
43+
it "truncates the slug to the max length" do
44+
long_title = "a" * (Slug::MAX_LENGTH + 10)
45+
slug = "a" * (Slug::MAX_LENGTH + 10)
46+
result = described_class.slug_for_topic(topic, slug, long_title)
47+
expect(result.length).to eq(Slug::MAX_LENGTH)
48+
end
49+
50+
it "handles titles with multiple emoji codes" do
51+
title = "Hello :smile: World :rocket:"
52+
slug = "hello-world"
53+
expect(described_class.slug_for_topic(topic, slug, title)).to eq("hello-world")
54+
end
55+
56+
it "handles titles with emoji codes with t modifier" do
57+
title = "Hello :wave:t2: World"
58+
slug = "hello-world"
59+
expect(described_class.slug_for_topic(topic, slug, title)).to eq("hello-world")
60+
end
61+
end
62+
end

0 commit comments

Comments
 (0)