From 759307f9834a2bbb23e963e2042b7d41d5cfda44 Mon Sep 17 00:00:00 2001 From: Daniel Dada Date: Fri, 27 Jun 2025 00:43:31 +0300 Subject: [PATCH] feat: added matching flags --- _locales/de/messages.json | 5 ++++- _locales/en/messages.json | 9 +++++++++ _locales/es/messages.json | 9 +++++++++ _locales/fr/messages.json | 9 +++++++++ _locales/hi/messages.json | 9 +++++++++ _locales/it/messages.json | 9 +++++++++ _locales/ja/messages.json | 9 +++++++++ _locales/ko/messages.json | 9 +++++++++ _locales/nl/messages.json | 9 +++++++++ _locales/pl/messages.json | 9 +++++++++ _locales/pt_BR/messages.json | 5 ++++- _locales/ru/messages.json | 9 +++++++++ _locales/tr/messages.json | 9 +++++++++ _locales/zh_CN/messages.json | 11 ++++++++++- main.js | 19 ++++++++++++++++--- popup/popup.css | 13 +++++++++++++ popup/popup.html | 18 +++++++++++++----- popup/popup.js | 32 +++++++++++++++++++++++++++++--- 18 files changed, 188 insertions(+), 14 deletions(-) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 7a70208..fea45c1 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -91,5 +91,8 @@ }, "search_placeholder": { "message": "Suchen..." -} +}, + "options": { "message": "Optionen" }, + "match_case": { "message": "Groß-/Kleinschreibung beachten" }, + "match_whole": { "message": "Ganzes Wort übereinstimmen" } } \ No newline at end of file diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 7c2f11f..dbbdd91 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "Search..." + }, + "options": { + "message": "Options" + }, + "match_case": { + "message": "Match Case" + }, + "match_whole": { + "message": "Match Whole Word" } } \ No newline at end of file diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 8eed28a..f618259 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "Buscar..." + }, + "options": { + "message": "Opciones" + }, + "match_case": { + "message": "Coincidir mayúsculas/minúsculas" + }, + "match_whole": { + "message": "Coincidir palabra completa" } } \ No newline at end of file diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 93ef3bf..7c70fe4 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "Rechercher..." + }, + "options": { + "message": "Options" + }, + "match_case": { + "message": "Respecter la casse" + }, + "match_whole": { + "message": "Mot entier seulement" } } \ No newline at end of file diff --git a/_locales/hi/messages.json b/_locales/hi/messages.json index 0fc8646..0c14435 100644 --- a/_locales/hi/messages.json +++ b/_locales/hi/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "खोजें..." + }, + "options": { + "message": "विकल्प" + }, + "match_case": { + "message": "केस मिलाएं" + }, + "match_whole": { + "message": "पूरा शब्द मिलाएं" } } \ No newline at end of file diff --git a/_locales/it/messages.json b/_locales/it/messages.json index 9a467b0..a832aac 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "Cerca..." + }, + "options": { + "message": "Opzioni" + }, + "match_case": { + "message": "Maiuscole/minuscole" + }, + "match_whole": { + "message": "Solo parola intera" } } \ No newline at end of file diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index 205fcee..b93a981 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "検索..." + }, + "options": { + "message": "オプション" + }, + "match_case": { + "message": "大文字と小文字を区別" + }, + "match_whole": { + "message": "完全一致" } } \ No newline at end of file diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index 2a12a44..50ebccd 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "검색..." + }, + "options": { + "message": "옵션" + }, + "match_case": { + "message": "대소문자 구분" + }, + "match_whole": { + "message": "전체 단어 일치" } } \ No newline at end of file diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json index 901ae74..8cf63a9 100644 --- a/_locales/nl/messages.json +++ b/_locales/nl/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "Zoeken..." + }, + "options": { + "message": "Opties" + }, + "match_case": { + "message": "Hoofdlettergevoelig" + }, + "match_whole": { + "message": "Alleen volledig woord" } } \ No newline at end of file diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json index 353fc65..804f134 100644 --- a/_locales/pl/messages.json +++ b/_locales/pl/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "Szukaj..." + }, + "options": { + "message": "Opcje" + }, + "match_case": { + "message": "Uwzględnij wielkość liter" + }, + "match_whole": { + "message": "Tylko całe słowo" } } \ No newline at end of file diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json index be27005..02bb2df 100644 --- a/_locales/pt_BR/messages.json +++ b/_locales/pt_BR/messages.json @@ -91,5 +91,8 @@ }, "search_placeholder": { "message": "Pesquisar..." -} +}, + "options": { "message": "Opções" }, + "match_case": { "message": "Diferenciar maiúsculas/minúsculas" }, + "match_whole": { "message": "Palavra inteira" } } \ No newline at end of file diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index 6700373..94505ea 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "Поиск..." + }, + "options": { + "message": "Опции" + }, + "match_case": { + "message": "С учетом регистра" + }, + "match_whole": { + "message": "Слово целиком" } } \ No newline at end of file diff --git a/_locales/tr/messages.json b/_locales/tr/messages.json index 9f61e54..9be70a1 100644 --- a/_locales/tr/messages.json +++ b/_locales/tr/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "Ara..." + }, + "options": { + "message": "Seçenekler" + }, + "match_case": { + "message": "Büyük/küçük harf duyarlı" + }, + "match_whole": { + "message": "Tüm kelimeyle eşleş" } } \ No newline at end of file diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index 86d7153..80005c1 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -91,5 +91,14 @@ }, "search_placeholder": { "message": "搜索..." -} + }, + "options": { + "message": "选项" + }, + "match_case": { + "message": "区分大小写" + }, + "match_whole": { + "message": "全词匹配" + } } \ No newline at end of file diff --git a/main.js b/main.js index 74e37f0..0f19d35 100644 --- a/main.js +++ b/main.js @@ -1,5 +1,7 @@ let currentLists = []; let isGlobalHighlightEnabled = true; +let matchCase = false; +let matchWhole = false; function escapeRegex(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); @@ -62,7 +64,12 @@ function processNodes() { const wordMap = new Map(); for (const word of activeWords) wordMap.set(word.text.toLowerCase(), word); - const pattern = new RegExp(`(${Array.from(wordMap.keys()).map(escapeRegex).join('|')})`, 'gi'); + let flags = matchCase ? 'g' : 'gi'; + let wordsPattern = Array.from(wordMap.keys()).map(escapeRegex).join('|'); + if (matchWhole) { + wordsPattern = `\\b(?:${wordsPattern})\\b`; + } + const pattern = new RegExp(`(${wordsPattern})`, flags); for (const node of textNodes) { if (!pattern.test(node.nodeValue)) continue; @@ -102,12 +109,14 @@ function debounce(func, wait) { } // Initial highlight on load -chrome.storage.local.get(["lists", "globalHighlightEnabled"], ({ lists, globalHighlightEnabled }) => { +chrome.storage.local.get(["lists", "globalHighlightEnabled", "matchCaseEnabled", "matchWholeEnabled"], ({ lists, globalHighlightEnabled, matchCaseEnabled, matchWholeEnabled }) => { if (Array.isArray(lists)) setListsAndUpdate(lists); if (globalHighlightEnabled !== undefined) { isGlobalHighlightEnabled = globalHighlightEnabled; } - processNodes(); // Initial processing + matchCase = !!matchCaseEnabled; + matchWhole = !!matchWholeEnabled; + processNodes(); }); // Listen for updates from the popup and re-apply highlights @@ -119,6 +128,10 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { } else if (message.type === "GLOBAL_TOGGLE_UPDATED") { isGlobalHighlightEnabled = message.enabled; processNodes(); + } else if (message.type === "MATCH_OPTIONS_UPDATED") { + matchCase = !!message.matchCase; + matchWhole = !!message.matchWhole; + processNodes(); } }); diff --git a/popup/popup.css b/popup/popup.css index 6e389d1..a0e4b15 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -257,6 +257,19 @@ button.danger:hover { flex-wrap: wrap; } +.button-row label { + display: flex; + align-items: center; + gap: 6px; + cursor: pointer; + font-size: 1em; +} + +.button-row input[type="checkbox"] { + margin: 0; + vertical-align: middle; +} + .color-row { display: flex; gap: 24px; diff --git a/popup/popup.html b/popup/popup.html index 54a8279..15ec0aa 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -77,19 +77,27 @@ - +
-
- - - +

Options

+
+ +
+
+
+ + + +
+
+ diff --git a/popup/popup.js b/popup/popup.js index 8c8ad1f..76932ca 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -6,12 +6,16 @@ const listActive = document.getElementById("listActive"); const bulkPaste = document.getElementById("bulkPaste"); const wordList = document.getElementById("wordList"); const importInput = document.getElementById("importInput"); +const matchCase = document.getElementById("matchCase"); +const matchWhole = document.getElementById("matchWhole"); let lists = []; let currentListIndex = 0; let saveTimeout; let selectedCheckboxes = new Set(); let globalHighlightEnabled = true; let wordSearchQuery = ""; +let matchCaseEnabled = false; +let matchWholeEnabled = false; function escapeHtml(str) { return str.replace(/[&<>"']/g, function (m) { @@ -35,7 +39,9 @@ async function debouncedSave() { async function save() { await chrome.storage.local.set({ lists: lists, - globalHighlightEnabled: globalHighlightEnabled + globalHighlightEnabled: globalHighlightEnabled, + matchCaseEnabled, + matchWholeEnabled }); renderLists(); renderWords(); @@ -48,6 +54,11 @@ async function save() { type: "GLOBAL_TOGGLE_UPDATED", enabled: globalHighlightEnabled }); + chrome.tabs.sendMessage(tab.id, { + type: "MATCH_OPTIONS_UPDATED", + matchCase: matchCaseEnabled, + matchWhole: matchWholeEnabled + }); } } }); @@ -70,10 +81,16 @@ async function updateGlobalToggleState() { async function load() { const res = await chrome.storage.local.get({ lists: [], - globalHighlightEnabled: true + globalHighlightEnabled: true, + matchCaseEnabled: false, + matchWholeEnabled: false }); lists = res.lists; - globalHighlightEnabled = res.globalHighlightEnabled !== false; // Default to true if undefined + globalHighlightEnabled = res.globalHighlightEnabled !== false; + matchCaseEnabled = !!res.matchCaseEnabled; + matchWholeEnabled = !!res.matchWholeEnabled; + matchCase.checked = matchCaseEnabled; + matchWhole.checked = matchWholeEnabled; if (!lists.length) { lists.push({ @@ -429,5 +446,14 @@ document.addEventListener('DOMContentLoaded', () => { renderWords(); }); + matchCase.addEventListener('change', () => { + matchCaseEnabled = matchCase.checked; + save(); + }); + matchWhole.addEventListener('change', () => { + matchWholeEnabled = matchWhole.checked; + save(); + }); + load(); });