2
0
Fork 0
mirror of https://github.com/discourse/discourse.git synced 2026-03-04 01:15:08 +08:00
discourse/app/serializers/watched_word_serializer.rb
Régis Hanol d01d060a8b
FIX: unify watched word boundary regex across Ruby and JS engines (#37965)
The CJK fix (d7a53ada16) introduced separate boundary patterns for Ruby
and JS engines in `match_word_regexp`. The Ruby engine used `[:word:]`
(which includes digits), while the JS engine used `\P{L}` (non-Letter).
Since digits are not letters, the JS pattern treated them as valid word
boundaries — causing "123Test" to match as "3Test" and standalone number
watched words like "123" to match inside "abc123".

Replace both engine-specific patterns with a single unified pattern
using Unicode property classes (`\p{L}`, `\p{M}`, `\p{N}`, `\p{Pc}`)
that work identically in Ruby and JavaScript. This treats letters,
marks, numbers, and connector punctuation as word characters in boundary
checks, which fixes the number-matching bug for JS consumers while
preserving the existing correct behavior on the Ruby side.

Since `match_word_regexp` no longer branches on engine, remove the
now-dead `engine:` parameter from all 5 method signatures that threaded
it through (`match_word_regexp`, `word_to_regexp`, `regexps_for_action`,
`compiled_regexps_for_action`, `serialized_regexps_for_action`) and all
call sites passing `engine: :js` (serializers, pretty_text).

https://meta.discourse.org/t/396110
https://meta.discourse.org/t/396109

Follow-up to d7a53ada16 (#37844)
2026-02-23 16:30:10 +01:00

28 lines
566 B
Ruby

# frozen_string_literal: true
class WatchedWordSerializer < ApplicationSerializer
attributes :id,
:word,
:regexp,
:replacement,
:action,
:case_sensitive,
:watched_word_group_id,
:html
def regexp
WordWatcher.word_to_regexp(word)
end
def action
WatchedWord.actions[object.action]
end
def include_replacement?
WatchedWord.has_replacement?(action)
end
def include_html?
object.action == WatchedWord.actions[:replace] && object.html
end
end