From 30c21cb8a3f6c8c64e14c327c10dec2ae3f17b24 Mon Sep 17 00:00:00 2001 From: Daniel Dada Date: Mon, 16 Jun 2025 16:33:47 +0300 Subject: [PATCH] init --- _locales/en/messages.json | 68 +++++++++++++ _locales/ru/messages.json | 68 +++++++++++++ background.js | 0 content.js | 53 ++++++++++ icons/icon128.png | Bin 0 -> 14997 bytes icons/icon16.png | Bin 0 -> 449 bytes icons/icon32.png | Bin 0 -> 1408 bytes icons/icon48.png | Bin 0 -> 3020 bytes manifest.json | 26 +++++ popup/popup.css | 77 +++++++++++++++ popup/popup.html | 51 ++++++++++ popup/popup.js | 197 ++++++++++++++++++++++++++++++++++++++ storage.js | 8 ++ utils.js | 0 14 files changed, 548 insertions(+) create mode 100644 _locales/en/messages.json create mode 100644 _locales/ru/messages.json create mode 100644 background.js create mode 100644 content.js create mode 100644 icons/icon128.png create mode 100644 icons/icon16.png create mode 100644 icons/icon32.png create mode 100644 icons/icon48.png create mode 100644 manifest.json create mode 100644 popup/popup.css create mode 100644 popup/popup.html create mode 100644 popup/popup.js create mode 100644 storage.js create mode 100644 utils.js diff --git a/_locales/en/messages.json b/_locales/en/messages.json new file mode 100644 index 0000000..82fbe69 --- /dev/null +++ b/_locales/en/messages.json @@ -0,0 +1,68 @@ +{ + "extension_name": { + "message": "Goose Highlighter" + }, + "select_list": { + "message": "Select List:" + }, + "new_list": { + "message": "+ New List" + }, + "delete_list": { + "message": "Delete List" + }, + "list_name": { + "message": "List Name:" + }, + "background": { + "message": "Background:" + }, + "foreground": { + "message": "Foreground:" + }, + "enable_highlight": { + "message": "Enable Highlight" + }, + "paste_hint": { + "message": "Paste words here" + }, + "apply_paste": { + "message": "Add Words" + }, + "select_all": { + "message": "Select All" + }, + "delete_selected": { + "message": "Delete Selected" + }, + "disable_selected": { + "message": "Disable Selected" + }, + "enable_selected": { + "message": "Enable Selected" + }, + "import_list": { + "message": "Import JSON" + }, + "export_list": { + "message": "Export JSON" + }, + "default_list_name": { + "message": "Default List" + }, + "new_list_name": { + "message": "New List" + }, + "word_active_label": { + "message": "active" + }, + "invalid_json_error": { + "message": "Invalid JSON file" + }, + "confirm_delete_list": { + "message": "Are you sure you want to delete this list?" + }, + "confirm_delete_words": { + "message": "Are you sure you want to delete the selected words?" + } +} \ No newline at end of file diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json new file mode 100644 index 0000000..1524286 --- /dev/null +++ b/_locales/ru/messages.json @@ -0,0 +1,68 @@ +{ + "extension_name": { + "message": "Goose Highlighter" + }, + "select_list": { + "message": "Выберите список:" + }, + "new_list": { + "message": "+ Новый список" + }, + "delete_list": { + "message": "Удалить список" + }, + "list_name": { + "message": "Имя списка:" + }, + "background": { + "message": "Фон:" + }, + "foreground": { + "message": "Текст:" + }, + "enable_highlight": { + "message": "Включить выделение" + }, + "paste_hint": { + "message": "Вставьте список слов здесь" + }, + "apply_paste": { + "message": "Добавить слова" + }, + "select_all": { + "message": "Выбрать все" + }, + "delete_selected": { + "message": "Удалить выбранное" + }, + "disable_selected": { + "message": "Отключить выбранное" + }, + "enable_selected": { + "message": "Включить выбранное" + }, + "import_list": { + "message": "Импорт JSON" + }, + "export_list": { + "message": "Экспорт JSON" + }, + "default_list_name": { + "message": "Список по умолчанию" + }, + "new_list_name": { + "message": "Новый список" + }, + "word_active_label": { + "message": "активно" + }, + "invalid_json_error": { + "message": "Неверный JSON файл" + }, + "confirm_delete_list": { + "message": "Вы уверены, что хотите удалить этот список?" + }, + "confirm_delete_words": { + "message": "Вы уверены, что хотите удалить выбранные слова?" + } +} \ No newline at end of file diff --git a/background.js b/background.js new file mode 100644 index 0000000..e69de29 diff --git a/content.js b/content.js new file mode 100644 index 0000000..9760e16 --- /dev/null +++ b/content.js @@ -0,0 +1,53 @@ +function escapeRegex(s) { + return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +function highlightWords(lists) { + const textNodes = []; + const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, { + acceptNode: node => { + if (node.parentNode && ['SCRIPT', 'STYLE', 'NOSCRIPT', 'IFRAME'].includes(node.parentNode.nodeName)) return NodeFilter.FILTER_REJECT; + if (!node.nodeValue.trim()) return NodeFilter.FILTER_SKIP; + return NodeFilter.FILTER_ACCEPT; + } + }); + + while (walker.nextNode()) textNodes.push(walker.currentNode); + + const activeWords = []; + + for (const list of lists) { + if (!list.active) continue; + for (const word of list.words) { + if (!word.active) continue; + activeWords.push({ + text: word.wordStr, + background: word.background || list.background, + foreground: word.foreground || list.foreground + }); + } + } + + if (activeWords.length === 0) return; + + 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'); + + for (const node of textNodes) { + if (!pattern.test(node.nodeValue)) continue; + + const span = document.createElement('span'); + span.innerHTML = node.nodeValue.replace(pattern, match => { + const word = wordMap.get(match.toLowerCase()) || { background: '#ffff00', foreground: '#000000' }; + return `${match}`; + }); + + node.parentNode.replaceChild(span, node); + } +} + +chrome.storage.local.get("lists", ({ lists }) => { + if (Array.isArray(lists)) highlightWords(lists); +}); diff --git a/icons/icon128.png b/icons/icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..37a67235c8c3a3baf0837f7b376d0b31dad4fcbb GIT binary patch literal 14997 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 literal 0 HcmV?d00001 diff --git a/icons/icon16.png b/icons/icon16.png new file mode 100644 index 0000000000000000000000000000000000000000..c18953b9d67238925f3839860e74b85658651fc2 GIT binary patch literal 449 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 O0000"], + "js": ["content.js"], + "run_at": "document_idle" + } + ], + "icons": { + "48": "icons/icon48.png", + "128": "icons/icon128.png" + } +} diff --git a/popup/popup.css b/popup/popup.css new file mode 100644 index 0000000..6a1d2d7 --- /dev/null +++ b/popup/popup.css @@ -0,0 +1,77 @@ +body { + font-family: Arial, sans-serif; + width: 360px; + margin: 0; + padding: 0; + background: #f9f9f9; + color: #333; +} + +.container { + padding: 10px; +} + +h1 { + font-size: 1.4em; + margin-bottom: 10px; +} + +.section { + margin-bottom: 12px; +} + +input[type="text"], +textarea, +select { + width: 100%; + box-sizing: border-box; + margin-top: 4px; + margin-bottom: 8px; + padding: 6px; + border-radius: 4px; + border: 1px solid #ccc; +} + +textarea { + height: 60px; + resize: vertical; +} + +button { + margin: 4px 2px; + padding: 6px 10px; + font-size: 0.9em; + border: none; + border-radius: 4px; + background-color: #007bff; + color: white; + cursor: pointer; +} + +button:hover { + background-color: #0056b3; +} + +#wordList > div { + display: flex; + align-items: center; + margin-bottom: 6px; + gap: 4px; +} + +#wordList input[type="text"] { + flex: 2; +} + +#wordList input[type="color"] { + width: 30px; + height: 30px; + padding: 0; + border: none; +} + +label { + display: inline-flex; + align-items: center; + gap: 6px; +} \ No newline at end of file diff --git a/popup/popup.html b/popup/popup.html new file mode 100644 index 0000000..377cf75 --- /dev/null +++ b/popup/popup.html @@ -0,0 +1,51 @@ + + + + + + <span data-i18n="extension_name"></span> + + + +
+

Goose Highlighter

+ +
+ + + + +
+ +
+ + + + +
+ +
+ + +
+ +
+ + + + +
+ +
+ +
+ + + +
+
+ + + + + \ No newline at end of file diff --git a/popup/popup.js b/popup/popup.js new file mode 100644 index 0000000..9c520bc --- /dev/null +++ b/popup/popup.js @@ -0,0 +1,197 @@ +const listSelect = document.getElementById("listSelect"); +const listName = document.getElementById("listName"); +const listBg = document.getElementById("listBg"); +const listFg = document.getElementById("listFg"); +const listActive = document.getElementById("listActive"); +const bulkPaste = document.getElementById("bulkPaste"); +const wordList = document.getElementById("wordList"); +const importInput = document.getElementById("importInput"); + +let lists = []; +let currentListIndex = 0; + +async function save() { + await chrome.storage.local.set({ lists }); + renderLists(); + renderWords(); +} + +async function load() { + const res = await chrome.storage.local.get("lists"); + lists = res.lists || []; + if (!lists.length) { + lists.push({ + id: Date.now(), + name: chrome.i18n.getMessage("default_list_name"), + background: "#ffff00", + foreground: "#000000", + active: true, + words: [] + }); + } + renderLists(); + renderWords(); +} + +function renderLists() { + listSelect.innerHTML = lists.map((list, index) => ``).join(""); + listSelect.value = currentListIndex; + updateListForm(); +} + +function updateListForm() { + const list = lists[currentListIndex]; + listName.value = list.name; + listBg.value = list.background; + listFg.value = list.foreground; + listActive.checked = list.active; +} + +function renderWords() { + const list = lists[currentListIndex]; + wordList.innerHTML = list.words.map((w, i) => ` +
+ + + + + +
+ `).join(""); +} + +listSelect.onchange = () => { + currentListIndex = +listSelect.value; + renderWords(); + updateListForm(); +}; + +document.getElementById("newListBtn").onclick = () => { + lists.push({ + id: Date.now(), + name: chrome.i18n.getMessage("new_list_name"), + background: "#ffff00", + foreground: "#000000", + active: true, + words: [] + }); + currentListIndex = lists.length - 1; + save(); +}; + +document.getElementById("deleteListBtn").onclick = () => { + if (confirm(chrome.i18n.getMessage("confirm_delete_list"))) { + lists.splice(currentListIndex, 1); + currentListIndex = Math.max(0, currentListIndex - 1); + save(); + } +}; + +listName.oninput = () => { lists[currentListIndex].name = listName.value; save(); }; +listBg.oninput = () => { lists[currentListIndex].background = listBg.value; save(); }; +listFg.oninput = () => { lists[currentListIndex].foreground = listFg.value; save(); }; +listActive.onchange = () => { lists[currentListIndex].active = listActive.checked; save(); }; + +document.getElementById("addWordsBtn").onclick = () => { + const words = bulkPaste.value.split(/\n+/).map(w => w.trim()).filter(Boolean); + const list = lists[currentListIndex]; + for (const w of words) list.words.push({ wordStr: w, background: "", foreground: "", active: true }); + bulkPaste.value = ""; + save(); +}; + +document.getElementById("selectAllBtn").onclick = () => { + wordList.querySelectorAll("input[type=checkbox]").forEach(cb => cb.checked = true); +}; + +document.getElementById("deleteSelectedBtn").onclick = () => { + if (confirm(chrome.i18n.getMessage("confirm_delete_words"))) { + const list = lists[currentListIndex]; + const toDelete = [...wordList.querySelectorAll("input[type=checkbox]:checked")].map(cb => +cb.dataset.index); + lists[currentListIndex].words = list.words.filter((_, i) => !toDelete.includes(i)); + save(); + } +}; + +document.getElementById("disableSelectedBtn").onclick = () => { + const list = lists[currentListIndex]; + wordList.querySelectorAll("input[type=checkbox]:checked").forEach(cb => list.words[+cb.dataset.index].active = false); + save(); +}; + +document.getElementById("enableSelectedBtn").onclick = () => { + const list = lists[currentListIndex]; + wordList.querySelectorAll("input[type=checkbox]:checked").forEach(cb => list.words[+cb.dataset.index].active = true); + save(); +}; + +wordList.addEventListener("input", e => { + const index = e.target.dataset.wordEdit ?? e.target.dataset.bgEdit ?? e.target.dataset.fgEdit; + if (e.target.dataset.wordEdit != null) lists[currentListIndex].words[index].wordStr = e.target.value; + if (e.target.dataset.bgEdit != null) lists[currentListIndex].words[index].background = e.target.value; + if (e.target.dataset.fgEdit != null) lists[currentListIndex].words[index].foreground = e.target.value; + save(); +}); + +wordList.addEventListener("change", e => { + if (e.target.dataset.activeEdit != null) { + lists[currentListIndex].words[e.target.dataset.activeEdit].active = e.target.checked; + save(); + } +}); + + +const exportBtn = document.getElementById("exportBtn"); +exportBtn.onclick = () => { + const blob = new Blob([JSON.stringify(lists, null, 2)], { type: "application/json" }); + const url = URL.createObjectURL(blob); + const a = document.createElement("a"); + a.href = url; + a.download = "highlight-lists.json"; + a.click(); + URL.revokeObjectURL(url); +}; + +const importBtn = document.getElementById("importBtn"); +importBtn.onclick = () => importInput.click(); + +importInput.onchange = e => { + const file = e.target.files[0]; + if (!file) return; + const reader = new FileReader(); + reader.onload = e => { + try { + const data = JSON.parse(e.target.result); + if (Array.isArray(data)) { + lists = data; + currentListIndex = 0; + save(); + } + } catch (err) { + alert(chrome.i18n.getMessage("invalid_json_error")); + } + }; + reader.readAsText(file); +}; + +// Localize the page +function localizePage() { + // Localize all elements with a data-i18n attribute + const elements = document.querySelectorAll('[data-i18n]'); + elements.forEach(element => { + const message = element.dataset.i18n; + const localizedText = chrome.i18n.getMessage(message); + if (localizedText) { + if (element.tagName === 'INPUT' && element.hasAttribute('placeholder')) { + element.placeholder = localizedText; + } else { + element.textContent = localizedText; + } + } + }); +} + +// Call this function when the page loads +document.addEventListener('DOMContentLoaded', localizePage); + +load(); \ No newline at end of file diff --git a/storage.js b/storage.js new file mode 100644 index 0000000..88f33f7 --- /dev/null +++ b/storage.js @@ -0,0 +1,8 @@ +export async function getLists() { + const { lists } = await chrome.storage.local.get("lists"); + return lists || []; +} + +export async function saveLists(lists) { + await chrome.storage.local.set({ lists }); +} diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..e69de29