diff --git a/app/assets/javascripts/admin/addon/templates/components/admin-watched-word.hbs b/app/assets/javascripts/admin/addon/templates/components/admin-watched-word.hbs index 058329145c1..cc034965108 100644 --- a/app/assets/javascripts/admin/addon/templates/components/admin-watched-word.hbs +++ b/app/assets/javascripts/admin/addon/templates/components/admin-watched-word.hbs @@ -1 +1 @@ -{{d-icon "times"}} {{word.word}} {{#if word.replacement}}→ {{word.replacement}}{{/if}} +{{d-icon "times"}} {{word.word}} {{#if word.replacement}}→ {{word.replacement}}{{/if}} diff --git a/app/assets/javascripts/discourse/tests/unit/lib/pretty-text-test.js b/app/assets/javascripts/discourse/tests/unit/lib/pretty-text-test.js index 3d6d500ec97..f413ffea754 100644 --- a/app/assets/javascripts/discourse/tests/unit/lib/pretty-text-test.js +++ b/app/assets/javascripts/discourse/tests/unit/lib/pretty-text-test.js @@ -1672,4 +1672,27 @@ var bar = 'bar'; assert.cookedOptions("(r) (R)", enabledTypographer, "
(r) (R)
"); assert.cookedOptions("(p) (P)", enabledTypographer, "(p) (P)
"); }); + + test("watched words replace", function (assert) { + const opts = { + watchedWordsReplacements: { fun: "times" }, + }; + + assert.cookedOptions("test fun", opts, "test times
"); + }); + + test("watched words replace with bad regex", function (assert) { + const maxMatches = 100; // same limit as MD watched-words-replace plugin + const opts = { + siteSettings: { watched_words_regular_expressions: true }, + watchedWordsReplacements: { "\\bu?\\b": "you" }, + }; + + assert.cookedOptions( + "one", + opts, + `${"you".repeat(maxMatches)}one
`, + "does not loop infinitely" + ); + }); }); diff --git a/app/assets/javascripts/pretty-text/engines/discourse-markdown/watched-words-replace.js b/app/assets/javascripts/pretty-text/engines/discourse-markdown/watched-words-replace.js index f006efb37f3..7c358d13cf2 100644 --- a/app/assets/javascripts/pretty-text/engines/discourse-markdown/watched-words-replace.js +++ b/app/assets/javascripts/pretty-text/engines/discourse-markdown/watched-words-replace.js @@ -10,9 +10,17 @@ function findAllMatches(text, matchers, useRegExp) { const matches = []; if (useRegExp) { + const maxMatches = 100; + let index = 0; + matchers.forEach((matcher) => { let match; - while ((match = matcher.pattern.exec(text)) !== null) { + while ( + (match = matcher.pattern.exec(text)) !== null && + index < maxMatches + ) { + index++; + matches.push({ index: match.index, text: match[0], diff --git a/app/assets/stylesheets/common/admin/staff_logs.scss b/app/assets/stylesheets/common/admin/staff_logs.scss index 9d70972ec52..4c9c9958470 100644 --- a/app/assets/stylesheets/common/admin/staff_logs.scss +++ b/app/assets/stylesheets/common/admin/staff_logs.scss @@ -330,6 +330,10 @@ table.screened-ip-addresses { width: 250px; margin-bottom: 1em; vertical-align: top; + .replacement { + white-space: pre; + background-color: var(--tertiary-low); + } } .watched-words-uploader {