diff --git a/app/assets/javascripts/admin/addon/components/modal/watched-word-test.js b/app/assets/javascripts/admin/addon/components/modal/watched-word-test.js index bbf92e29cff..67474568c08 100644 --- a/app/assets/javascripts/admin/addon/components/modal/watched-word-test.js +++ b/app/assets/javascripts/admin/addon/components/modal/watched-word-test.js @@ -1,9 +1,5 @@ import Component from "@glimmer/component"; import { tracked } from "@glimmer/tracking"; -import { - createWatchedWordRegExp, - toWatchedWord, -} from "discourse-common/utils/watched-words"; export default class WatchedWordTest extends Component { @tracked value; @@ -31,7 +27,10 @@ export default class WatchedWordTest extends Component { if (this.isReplace || this.isLink) { const matches = []; this.args.model.watchedWord.words.forEach((word) => { - const regexp = createWatchedWordRegExp(word); + const regexp = new RegExp( + word.regexp, + word.case_sensitive ? "gu" : "gui" + ); let match; while ((match = regexp.exec(this.value)) !== null) { @@ -42,38 +41,44 @@ export default class WatchedWordTest extends Component { } }); return matches; - } else if (this.isTag) { - const matches = {}; + } + + if (this.isTag) { + const matches = new Map(); this.args.model.watchedWord.words.forEach((word) => { - const regexp = createWatchedWordRegExp(word); + const regexp = new RegExp( + word.regexp, + word.case_sensitive ? "gu" : "gui" + ); let match; while ((match = regexp.exec(this.value)) !== null) { - if (!matches[match[1]]) { - matches[match[1]] = new Set(); + if (!matches.has(match[1])) { + matches.set(match[1], new Set()); } - let tags = matches[match[1]]; - word.replacement.split(",").forEach((tag) => { - tags.add(tag); - }); + const tags = matches.get(match[1]); + word.replacement.split(",").forEach((tag) => tags.add(tag)); } }); - return Object.entries(matches).map((entry) => ({ - match: entry[0], - tags: Array.from(entry[1]), + return Array.from(matches, ([match, tagsSet]) => ({ + match, + tags: Array.from(tagsSet), })); - } else { - let matches = []; - this.args.model.watchedWord.compiledRegularExpression.forEach( - (regexp) => { - const wordRegexp = createWatchedWordRegExp(toWatchedWord(regexp)); - matches.push(...(this.value.match(wordRegexp) || [])); - } + } + + let matches = []; + this.args.model.watchedWord.compiledRegularExpression.forEach((entry) => { + const [regexp, options] = Object.entries(entry)[0]; + const wordRegexp = new RegExp( + regexp, + options.case_sensitive ? "gu" : "gui" ); - return matches; - } + matches.push(...(this.value.match(wordRegexp) || [])); + }); + + return matches; } } diff --git a/app/assets/javascripts/discourse-common/addon/utils/watched-words.js b/app/assets/javascripts/discourse-common/addon/utils/watched-words.js deleted file mode 100644 index 3641be2ad79..00000000000 --- a/app/assets/javascripts/discourse-common/addon/utils/watched-words.js +++ /dev/null @@ -1,9 +0,0 @@ -export function createWatchedWordRegExp(word) { - const caseFlag = word.case_sensitive ? "" : "i"; - return new RegExp(word.regexp, `${caseFlag}gu`); -} - -export function toWatchedWord(regexp) { - const [[regexpString, options]] = Object.entries(regexp); - return { ...options, regexp: regexpString }; -} diff --git a/app/assets/javascripts/discourse-markdown-it/src/features/emoji.js b/app/assets/javascripts/discourse-markdown-it/src/features/emoji.js index 0d59c83bf03..05ff41582c8 100644 --- a/app/assets/javascripts/discourse-markdown-it/src/features/emoji.js +++ b/app/assets/javascripts/discourse-markdown-it/src/features/emoji.js @@ -196,7 +196,7 @@ function applyEmoji( enableShortcuts, inlineEmoji, customEmojiTranslation, - watchedWordsReplacer, + watchedWordsReplace, emojiDenyList ) { let result = null; @@ -206,19 +206,16 @@ function applyEmoji( content = emojiUnicodeReplacer(content); } - if (watchedWordsReplacer) { - const watchedWordRegex = Object.keys(watchedWordsReplacer); - - watchedWordRegex.forEach((watchedWord) => { - if (content?.match(watchedWord)) { - const regex = new RegExp(watchedWord, "g"); + if (content && watchedWordsReplace) { + Object.entries(watchedWordsReplace).forEach(([regexpString, options]) => { + if (content.match(regexpString)) { + const regex = new RegExp(regexpString, "g"); const matches = content.match(regex); - const replacement = watchedWordsReplacer[watchedWord].replacement; matches.forEach(() => { const matchingRegex = regex.exec(content); if (matchingRegex) { - content = content.replace(matchingRegex[1], replacement); + content = content.replace(matchingRegex[1], options.replacement); } }); } @@ -226,9 +223,9 @@ function applyEmoji( } // prevent denied emoji and aliases from being rendered - if (emojiDenyList?.length > 0) { + if (content && emojiDenyList?.length > 0) { emojiDenyList.forEach((emoji) => { - if (content?.match(emoji)) { + if (content.match(emoji)) { const regex = new RegExp(`:${emoji}:`, "g"); content = content.replace(regex, ""); } 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 284174e562c..e9f52178bde 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 @@ -1,8 +1,3 @@ -import { - createWatchedWordRegExp, - toWatchedWord, -} from "discourse-common/utils/watched-words"; - const MAX_MATCHES = 100; function isLinkOpen(str) { @@ -59,11 +54,12 @@ export function setup(helper) { if (md.options.discourse.watchedWordsReplace) { Object.entries(md.options.discourse.watchedWordsReplace).forEach( ([regexpString, options]) => { - const word = toWatchedWord({ [regexpString]: options }); - matchers.push({ word: new RegExp(options.regexp, options.case_sensitive ? "" : "i"), - pattern: createWatchedWordRegExp(word), + pattern: new RegExp( + regexpString, + options.case_sensitive ? "gu" : "gui" + ), replacement: options.replacement, link: false, html: options.html, @@ -75,11 +71,12 @@ export function setup(helper) { if (md.options.discourse.watchedWordsLink) { Object.entries(md.options.discourse.watchedWordsLink).forEach( ([regexpString, options]) => { - const word = toWatchedWord({ [regexpString]: options }); - matchers.push({ word: new RegExp(options.regexp, options.case_sensitive ? "" : "i"), - pattern: createWatchedWordRegExp(word), + pattern: new RegExp( + regexpString, + options.case_sensitive ? "gu" : "gui" + ), replacement: options.replacement, link: true, }); diff --git a/app/assets/javascripts/pretty-text/addon/censored-words.js b/app/assets/javascripts/pretty-text/addon/censored-words.js index dc3b93b99d0..aa91c12d72e 100644 --- a/app/assets/javascripts/pretty-text/addon/censored-words.js +++ b/app/assets/javascripts/pretty-text/addon/censored-words.js @@ -1,13 +1,8 @@ -import { - createWatchedWordRegExp, - toWatchedWord, -} from "discourse-common/utils/watched-words"; - -export function censorFn(regexpList, replacementLetter) { +export function censorFn(regexpList, replacementLetter = "■") { if (regexpList?.length) { - replacementLetter = replacementLetter || "■"; - let censorRegexps = regexpList.map((regexp) => { - return createWatchedWordRegExp(toWatchedWord(regexp)); + const censorRegexps = regexpList.map((entry) => { + const [regexp, options] = Object.entries(entry)[0]; + return new RegExp(regexp, options.case_sensitive ? "gu" : "gui"); }); return function (text) { diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb index 9a86cf04ef6..f21706e1a87 100644 --- a/lib/pretty_text.rb +++ b/lib/pretty_text.rb @@ -91,7 +91,6 @@ module PrettyText discourse-common/addon/lib/deprecated discourse-common/addon/lib/escape discourse-common/addon/lib/avatar-utils - discourse-common/addon/utils/watched-words discourse/app/lib/to-markdown discourse/app/static/markdown-it/features ].each do |f|