2013-02-05 14:16:51 -05:00
|
|
|
# encoding: utf-8
|
2019-05-02 18:17:27 -04:00
|
|
|
# frozen_string_literal: true
|
2013-02-05 14:16:51 -05:00
|
|
|
|
|
|
|
module Slug
|
2016-10-12 15:44:26 -04:00
|
|
|
CHAR_FILTER_REGEXP = /[:\/\?#\[\]@!\$&'\(\)\*\+,;=_\.~%\\`^\s|\{\}"<>]+/ # :/?#[]@!$&'()*+,;=_.~%\`^|{}"<>
|
2017-10-03 06:52:24 -04:00
|
|
|
MAX_LENGTH = 255
|
2016-10-12 15:44:26 -04:00
|
|
|
|
2021-01-12 10:28:33 -05:00
|
|
|
def self.for(string, default = "topic", max_length = MAX_LENGTH, method: nil)
|
2018-04-17 14:44:43 -04:00
|
|
|
string = string.gsub(/:([\w\-+]+(?::t\d)?):/, "") if string.present? # strip emoji strings
|
2021-01-12 10:28:33 -05:00
|
|
|
method = (method || SiteSetting.slug_generation_method || :ascii).to_sym
|
|
|
|
max_length = 9999 if method == :encoded # do not truncate encoded slugs
|
2019-10-17 12:38:31 -04:00
|
|
|
|
2015-05-05 18:50:54 -04:00
|
|
|
slug =
|
2021-01-12 10:28:33 -05:00
|
|
|
case method
|
2015-04-13 10:50:41 -04:00
|
|
|
when :ascii
|
|
|
|
self.ascii_generator(string)
|
|
|
|
when :encoded
|
|
|
|
self.encoded_generator(string)
|
|
|
|
when :none
|
|
|
|
self.none_generator(string)
|
|
|
|
end
|
2021-01-12 10:28:33 -05:00
|
|
|
|
2017-10-03 06:52:24 -04:00
|
|
|
slug = self.prettify_slug(slug, max_length: max_length)
|
2019-12-16 19:34:20 -05:00
|
|
|
(slug.blank? || slug_is_only_numbers?(slug)) ? default : slug
|
2015-04-13 10:50:41 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2019-12-16 19:34:20 -05:00
|
|
|
def self.slug_is_only_numbers?(slug)
|
|
|
|
(slug =~ /[^\d]/).blank?
|
|
|
|
end
|
|
|
|
|
2017-10-26 23:02:12 -04:00
|
|
|
def self.prettify_slug(slug, max_length:)
|
2019-12-03 20:22:29 -05:00
|
|
|
# Reject slugs that only contain numbers, because they would be indistinguishable from id's.
|
2019-12-16 19:34:20 -05:00
|
|
|
slug = (slug_is_only_numbers?(slug) ? "" : slug)
|
2019-12-03 20:22:29 -05:00
|
|
|
|
2017-10-26 23:02:12 -04:00
|
|
|
slug
|
|
|
|
.tr("_", "-")
|
|
|
|
.truncate(max_length, omission: "")
|
|
|
|
.squeeze("-") # squeeze continuous dashes to prettify slug
|
|
|
|
.gsub(/\A-+|-+\z/, "") # remove possible trailing and preceding dashes
|
2017-10-03 06:52:24 -04:00
|
|
|
end
|
|
|
|
|
2015-04-13 10:50:41 -04:00
|
|
|
def self.ascii_generator(string)
|
2019-04-29 12:29:45 -04:00
|
|
|
I18n.with_locale(SiteSetting.default_locale) { string.tr("'", "").parameterize }
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|
|
|
|
|
2017-10-03 06:52:24 -04:00
|
|
|
def self.encoded_generator(string, downcase: true)
|
2015-05-04 07:48:37 -04:00
|
|
|
# This generator will sanitize almost all special characters,
|
|
|
|
# including reserved characters from RFC3986.
|
|
|
|
# See also URI::REGEXP::PATTERN.
|
2017-10-26 23:02:12 -04:00
|
|
|
string = string.strip.gsub(/\s+/, "-").gsub(CHAR_FILTER_REGEXP, "")
|
|
|
|
|
2019-10-11 11:38:16 -04:00
|
|
|
string = string.downcase if downcase
|
|
|
|
|
|
|
|
CGI.escape(string)
|
2015-04-13 10:50:41 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.none_generator(string)
|
2023-01-09 07:10:19 -05:00
|
|
|
""
|
2015-04-13 10:50:41 -04:00
|
|
|
end
|
2013-02-05 14:16:51 -05:00
|
|
|
end
|