diff --git a/components/utils/index.js b/components/utils/index.js index 5340474e..d3266356 100644 --- a/components/utils/index.js +++ b/components/utils/index.js @@ -687,6 +687,8 @@ export const updateLinks = (input) => { const EMPTY_QUILL_PARAGRAPHS_REGEX = /]*>\s*(?:| |\s)*\s*<\/p>/gi; + const VIDEO_EMBED_REGEX = /<(iframe|video)\b[^>]*>[\s\S]*?<\/\1\s*>/gi; + const URL_REGEX = /\b(https?:\/\/[^\s<]+)/gi; const stripTrailingUrlPunctuation = (url) => { @@ -732,7 +734,9 @@ export const updateLinks = (input) => { const processHtmlString = (htmlString) => { if (typeof htmlString !== "string" || !htmlString) return htmlString; - let html = htmlString.replace(EMPTY_QUILL_PARAGRAPHS_REGEX, ""); + let html = htmlString + .replace(VIDEO_EMBED_REGEX, "") + .replace(EMPTY_QUILL_PARAGRAPHS_REGEX, ""); const anchorPlaceholders = []; html = html.replace(/]*>[\s\S]*?<\/a>/gi, (match) => { diff --git a/tests/phase22/client-utils-behaviour.test.cjs b/tests/phase22/client-utils-behaviour.test.cjs index 310c58fc..217957de 100644 --- a/tests/phase22/client-utils-behaviour.test.cjs +++ b/tests/phase22/client-utils-behaviour.test.cjs @@ -219,6 +219,83 @@ test("clients/fileRouteBuilder builds query with optional encoding and suffix he ); }); +const loadUpdateLinks = () => { + const filePath = path.join(rootDir, "components", "utils", "index.js"); + const source = fs.readFileSync(filePath, "utf8"); + + const start = source.indexOf("export const updateLinks ="); + const end = source.indexOf("\nexport const whichRepType", start); + + assert.ok(start >= 0, "updateLinks export not found"); + assert.ok(end > start, "updateLinks boundary not found"); + + const implementation = source + .slice(start, end) + .replace("export const updateLinks =", "const updateLinks ="); + + const context = { module: { exports: {} } }; + + vm.runInNewContext( + `${implementation}\nmodule.exports = updateLinks;`, + context, + { filename: filePath } + ); + + return context.module.exports; +}; + +test("updateLinks removes Quill video iframe", () => { + const updateLinks = loadUpdateLinks(); + + const input = + '

Before

After

'; + + assert.strictEqual(updateLinks(input), "

Before

After

"); +}); + +test("updateLinks removes HTML video elements", () => { + const updateLinks = loadUpdateLinks(); + + const input = + '

Before

After

'; + + assert.strictEqual(updateLinks(input), "

Before

After

"); +}); + +test("updateLinks converts plain URLs", () => { + const updateLinks = loadUpdateLinks(); + + assert.strictEqual( + updateLinks("

Visit https://example.com.

"), + '

Visit https://example.com.

' + ); +}); + +test("updateLinks preserves existing anchors", () => { + const updateLinks = loadUpdateLinks(); + + const input = '

Existing link

'; + + assert.strictEqual(updateLinks(input), input); +}); + +test("updateLinks preserves standard rich-text formatting", () => { + const updateLinks = loadUpdateLinks(); + + const input = "

Bold and italic

"; + + assert.strictEqual(updateLinks(input), input); +}); + +test("updateLinks removes empty Quill paragraphs", () => { + const updateLinks = loadUpdateLinks(); + + assert.strictEqual( + updateLinks("

Content


 

"), + "

Content

" + ); +}); + const run = async () => { let passed = 0;