about summary refs log tree commit diff
path: root/app/models/tag.rb
diff options
context:
space:
mode:
authorPartho Ghosh <partho.ghosh24@gmail.com>2023-01-03 17:12:48 -0800
committerGitHub <noreply@github.com>2023-01-04 02:12:48 +0100
commit115ab2869b2742f0cc68116a8c03359d220fd608 (patch)
treef4fd39d5f3dbb6b9c3bb44a72395c1cb0febdf9c /app/models/tag.rb
parent546e301bcdbe54a1df6d54303cda4d7f11beb6cc (diff)
Fix ・ detection in hashtag regex to construct hashtag correctly (#22888)
* Fix ・ detection in hashtag regex to construct hashtag correctly

* Fixed rubocop liniting issues

* More rubocop linting fix
Diffstat (limited to 'app/models/tag.rb')
-rw-r--r--app/models/tag.rb22
1 files changed, 17 insertions, 5 deletions
diff --git a/app/models/tag.rb b/app/models/tag.rb
index b66f85423..47a05d00a 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -26,8 +26,12 @@ class Tag < ApplicationRecord
   has_many :featured_tags, dependent: :destroy, inverse_of: :tag
   has_many :followers, through: :passive_relationships, source: :account
 
-  HASHTAG_SEPARATORS = "_\u00B7\u200c"
-  HASHTAG_NAME_PAT = "([[:word:]_][[:word:]#{HASHTAG_SEPARATORS}]*[[:alpha:]#{HASHTAG_SEPARATORS}][[:word:]#{HASHTAG_SEPARATORS}]*[[:word:]_])|([[:word:]_]*[[:alpha:]][[:word:]_]*)"
+  HASHTAG_SEPARATORS = "_\u00B7\u30FB\u200c"
+  HASHTAG_FIRST_SEQUENCE_CHUNK_ONE = "[[:word:]_][[:word:]#{HASHTAG_SEPARATORS}]*[[:alpha:]#{HASHTAG_SEPARATORS}]"
+  HASHTAG_FIRST_SEQUENCE_CHUNK_TWO = "[[:word:]#{HASHTAG_SEPARATORS}]*[[:word:]_]"
+  HASHTAG_FIRST_SEQUENCE = "(#{HASHTAG_FIRST_SEQUENCE_CHUNK_ONE}#{HASHTAG_FIRST_SEQUENCE_CHUNK_TWO})"
+  HASTAG_LAST_SEQUENCE = '([[:word:]_]*[[:alpha:]][[:word:]_]*)'
+  HASHTAG_NAME_PAT = "#{HASHTAG_FIRST_SEQUENCE}|#{HASTAG_LAST_SEQUENCE}"
 
   HASHTAG_RE = /(?:^|[^\/\)\w])#(#{HASHTAG_NAME_PAT})/i
   HASHTAG_NAME_RE = /\A(#{HASHTAG_NAME_PAT})\z/i
@@ -45,7 +49,11 @@ class Tag < ApplicationRecord
   scope :listable, -> { where(listable: [true, nil]) }
   scope :trendable, -> { Setting.trendable_by_default ? where(trendable: [true, nil]) : where(trendable: true) }
   scope :not_trendable, -> { where(trendable: false) }
-  scope :recently_used, ->(account) { joins(:statuses).where(statuses: { id: account.statuses.select(:id).limit(1000) }).group(:id).order(Arel.sql('count(*) desc')) }
+  scope :recently_used, ->(account) {
+                          joins(:statuses)
+                            .where(statuses: { id: account.statuses.select(:id).limit(1000) })
+                            .group(:id).order(Arel.sql('count(*) desc'))
+                        }
   scope :matches_name, ->(term) { where(arel_table[:name].lower.matches(arel_table.lower("#{sanitize_sql_like(Tag.normalize(term))}%"), nil, true)) } # Search with case-sensitive to use B-tree index
 
   update_index('tags', :self)
@@ -105,7 +113,8 @@ class Tag < ApplicationRecord
       names = Array(name_or_names).map { |str| [normalize(str), str] }.uniq(&:first)
 
       names.map do |(normalized_name, display_name)|
-        tag = matching_name(normalized_name).first || create(name: normalized_name, display_name: display_name.gsub(HASHTAG_INVALID_CHARS_RE, ''))
+        tag = matching_name(normalized_name).first || create(name: normalized_name,
+                                                             display_name: display_name.gsub(HASHTAG_INVALID_CHARS_RE, ''))
 
         yield tag if block_given?
 
@@ -154,6 +163,9 @@ class Tag < ApplicationRecord
   end
 
   def validate_display_name_change
-    errors.add(:display_name, I18n.t('tags.does_not_match_previous_name')) unless HashtagNormalizer.new.normalize(display_name).casecmp(name.mb_chars).zero?
+    unless HashtagNormalizer.new.normalize(display_name).casecmp(name.mb_chars).zero?
+      errors.add(:display_name,
+                 I18n.t('tags.does_not_match_previous_name'))
+    end
   end
 end