diff --git a/app/assets/javascripts/discourse-common/addon/utils/watched-words.js b/app/assets/javascripts/discourse-common/addon/utils/watched-words.js index 8ff622ce550..3641be2ad79 100644 --- a/app/assets/javascripts/discourse-common/addon/utils/watched-words.js +++ b/app/assets/javascripts/discourse-common/addon/utils/watched-words.js @@ -5,5 +5,5 @@ export function createWatchedWordRegExp(word) { export function toWatchedWord(regexp) { const [[regexpString, options]] = Object.entries(regexp); - return { regexp: regexpString, ...options }; + return { ...options, regexp: regexpString }; } diff --git a/app/assets/javascripts/discourse-markdown-it/src/features/watched-words.js b/app/assets/javascripts/discourse-markdown-it/src/features/watched-words.js index 5e0fc48a1b2..00f9d91fe1b 100644 --- a/app/assets/javascripts/discourse-markdown-it/src/features/watched-words.js +++ b/app/assets/javascripts/discourse-markdown-it/src/features/watched-words.js @@ -61,7 +61,7 @@ export function setup(helper) { const word = toWatchedWord({ [regexpString]: options }); matchers.push({ - word: new RegExp(options.word, options.case_sensitive ? "" : "i"), + word: new RegExp(options.regexp, options.case_sensitive ? "" : "i"), pattern: createWatchedWordRegExp(word), replacement: options.replacement, link: false, @@ -76,7 +76,7 @@ export function setup(helper) { const word = toWatchedWord({ [regexpString]: options }); matchers.push({ - word: new RegExp(options.word, options.case_sensitive ? "" : "i"), + word: new RegExp(options.regexp, options.case_sensitive ? "" : "i"), pattern: createWatchedWordRegExp(word), replacement: options.replacement, link: true, diff --git a/app/services/word_watcher.rb b/app/services/word_watcher.rb index 442c7fca29c..4b5760de8a3 100644 --- a/app/services/word_watcher.rb +++ b/app/services/word_watcher.rb @@ -32,7 +32,12 @@ class WordWatcher .limit(WatchedWord::MAX_WORDS_PER_ACTION) .order(:id) .pluck(:word, :replacement, :case_sensitive) - .to_h { |w, r, c| [w, { word: w, replacement: r, case_sensitive: c }.compact] } + .to_h do |w, r, c| + [ + word_to_regexp(w, match_word: false), + { word: w, replacement: r, case_sensitive: c }.compact, + ] + end end def self.words_for_action_exist?(action) @@ -50,8 +55,8 @@ class WordWatcher end def self.regexps_for_action(action, engine: :ruby) - cached_words_for_action(action)&.to_h do |word, attrs| - [word_to_regexp(word, engine: engine), attrs] + cached_words_for_action(action)&.to_h do |_, attrs| + [word_to_regexp(attrs[:word], engine: engine), attrs] end end diff --git a/lib/topic_creator.rb b/lib/topic_creator.rb index 3a685b1d452..c184486de53 100644 --- a/lib/topic_creator.rb +++ b/lib/topic_creator.rb @@ -191,8 +191,8 @@ class TopicCreator if watched_words.present? word_watcher = WordWatcher.new("#{@opts[:title]} #{@opts[:raw]}") word_watcher_tags = topic.tags.map(&:name) - watched_words.each do |word, opts| - if word_watcher.word_matches?(word, case_sensitive: opts[:case_sensitive]) + watched_words.each do |_, opts| + if word_watcher.word_matches?(opts[:word], case_sensitive: opts[:case_sensitive]) word_watcher_tags += opts[:replacement].split(",") end end diff --git a/spec/lib/pretty_text_spec.rb b/spec/lib/pretty_text_spec.rb index 19def8b7df0..5997d439051 100644 --- a/spec/lib/pretty_text_spec.rb +++ b/spec/lib/pretty_text_spec.rb @@ -1981,6 +1981,19 @@ HTML HTML end + it "replaces words with wildcards" do + Fabricate( + :watched_word, + action: WatchedWord.actions[:replace], + word: "*dolor*", + replacement: "something else", + ) + + expect(PrettyText.cook("Lorem ipsum xdolorx sit amet")).to match_html(<<~HTML) +

Lorem ipsum something else sit amet

+ HTML + end + it "replaces words with links" do Fabricate( :watched_word,