From 074f5abc3c1f40ada2b135bf45f7c5a6eaec498d Mon Sep 17 00:00:00 2001 From: Mathis Rouget <147822571+MathisRouget@users.noreply.github.com> Date: Tue, 9 Dec 2025 15:49:25 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(frontend)=20use=20regex=20patterns?= =?UTF-8?q?=20to=20detect=20forgotten=20attachments=20(#442)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently the attachments-detection-map contains regex patterns but those ones were treat as raw strings. We now parse patterns to detect regex string (starts and ends with `/`). --- .../i18n/attachments-detection-map.json | 32 +++++++++---------- .../src/features/utils/mail-helper.test.tsx | 17 ++++++++++ .../src/features/utils/mail-helper.tsx | 18 ++++++++--- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/frontend/src/features/i18n/attachments-detection-map.json b/src/frontend/src/features/i18n/attachments-detection-map.json index bd90b966..59b60f09 100644 --- a/src/frontend/src/features/i18n/attachments-detection-map.json +++ b/src/frontend/src/features/i18n/attachments-detection-map.json @@ -38,12 +38,12 @@ "enc." ], "patterns": [ - "please (see|find) (the )?attached", - "you will find (the )?attached", - "attached (is|are|you’ll find)", - "find (the )?attached file", - "enclosed (you will find|please find)?", - "I (forgot|didn’t) (to )?(attach|include)" + "/please (see|find) (the )?attached/", + "/you will find (the )?attached/", + "/attached (is|are|you['']ll find)/", + "/find (the )?attached file/", + "/enclosed (you will find|please find)?/", + "/I (forgot|didn['']t) (to )?(attach|include)/" ] }, "fr": { @@ -85,10 +85,10 @@ "annexe" ], "patterns": [ - "vous trouverez (ci-joint|en pièce jointe)", - "je (vous )?(joins|envoie) (le|la|les)? (fichier|document|pièce jointe)", - "en pièce jointe(,)? (vous trouverez|je vous ai mis)", - "j['']?ai oublié (de )?(joindre|mettre en pièce jointe)" + "/vous trouverez (ci-joint|en pièce jointe)/", + "/je (vous )?(joins|envoie) (le|la|les)? (fichier|document|pièce jointe)/", + "/en pièce jointe(,)? (vous trouverez|je vous ai mis)/", + "/j['']?ai oublié (de )?(joindre|mettre en pièce jointe)/" ] }, "nl": { @@ -127,11 +127,11 @@ "bgv." ], "patterns": [ - "(zie|vind(t)?) (je |u )?bijgevoegd", - "bijgevoegd (is|zijn|vindt u|vind je)", - "in de bijlage (vindt u|vind je)", - "ik (ben|was) vergeten (bij te voegen|toe te voegen)", - "(hierbij|anbij) (stuur|zend) ik( je| u)?( het| de)?( bestand| document)?" + "/(zie|vind(t)?) (je |u )?bijgevoegd/", + "/bijgevoegd (is|zijn|vindt u|vind je)/", + "/in de bijlage (vindt u|vind je)/", + "/ik (ben|was) vergeten (bij te voegen|toe te voegen)/", + "/(hierbij|anbij) (stuur|zend) ik( je| u)?( het| de)?( bestand| document)?/" ] } -} \ No newline at end of file +} diff --git a/src/frontend/src/features/utils/mail-helper.test.tsx b/src/frontend/src/features/utils/mail-helper.test.tsx index a6114d9f..736c06db 100644 --- a/src/frontend/src/features/utils/mail-helper.test.tsx +++ b/src/frontend/src/features/utils/mail-helper.test.tsx @@ -1,4 +1,5 @@ import MailHelper, { SUPPORTED_IMAP_DOMAINS, ATTACHMENT_SEPARATORS } from './mail-helper'; +import DetectionMap from '@/features/i18n/attachments-detection-map.json'; describe('MailHelper', () => { describe('markdownToHtml', () => { @@ -221,6 +222,12 @@ describe('MailHelper', () => { it('should handle empty safely', () => { expect(MailHelper.areAttachmentsMentionedInDraft('')).toBe(false); }); + + it('should use regex patterns if present', () => { + const draftText = 'I didn\'t include the document.'; + const result = MailHelper.areAttachmentsMentionedInDraft(draftText); + expect(result).toBe(true); + }); }); describe('MailHelper.attachDriveAttachmentsToDraft', () => { @@ -748,4 +755,14 @@ describe('MailHelper', () => { ]); }); }); + + describe('DetectionMap', () => { + it('should not have invalid regex patterns', () => { + // A test guard to ensure that the detection map does not contain malformed regex patterns + const regexPatterns = MailHelper.getAttachmentKeywords(DetectionMap).filter((pattern) => pattern.startsWith('/') && pattern.endsWith('/')); + for (const pattern of regexPatterns) { + expect(() => new RegExp(pattern.slice(1, -1), 'i')).not.toThrowError(); + } + }); + }); }); diff --git a/src/frontend/src/features/utils/mail-helper.tsx b/src/frontend/src/features/utils/mail-helper.tsx index 1143db1b..358805f1 100644 --- a/src/frontend/src/features/utils/mail-helper.tsx +++ b/src/frontend/src/features/utils/mail-helper.tsx @@ -118,10 +118,20 @@ class MailHelper { /** * Check if any attachment keyword is mentioned in the draft text. */ - static areAttachmentsMentionedInDraft(draftText: string): boolean { - const keyWordsAttachments = MailHelper.getAttachmentKeywords(DetectionMap); - const messageEditorDraft = draftText?.toLowerCase() || ""; - return keyWordsAttachments.some((keyword) => messageEditorDraft.includes(keyword)); + static areAttachmentsMentionedInDraft(draftText: string = ''): boolean { + const patterns = MailHelper.getAttachmentKeywords(DetectionMap); + return patterns.some((pattern) => { + const isRegex = pattern.startsWith('/') && pattern.endsWith('/'); + if (isRegex) { + try { + return new RegExp(pattern.slice(1, -1), 'i').test(draftText); + } catch (e) { + console.error('Invalid regex pattern', pattern, e); + return false; + } + } + return draftText.toLowerCase().includes(pattern); + }); } /**