diff --git a/README.md b/README.md index b286708..7146916 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Goose Highlighter is a browser extension that allows you to highlight words on a - **Custom Colors:** Set background and foreground for each list or individual word. - **Bulk Add:** Paste multiple words at once. - **Enable/Disable:** Toggle highlighting globally, per list, or per word. +- **Page Navigation:** View all highlights on the current page and jump to any occurrence with a single click. - **Site Exceptions:** Add specific websites to an exceptions list to disable highlighting there. - **Import/Export:** Backup or share your highlight lists and exceptions as JSON files. diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 9e9b318..c2ce82c 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -151,5 +151,26 @@ }, "text_color_title": { "message": "Textfarbe" + }, + "tab_page_highlights": { + "message": "Auf Seite" + }, + "highlights_on_page": { + "message": "Hervorhebungen auf dieser Seite" + }, + "total_highlights": { + "message": "Gesamt" + }, + "refresh": { + "message": "Aktualisieren" + }, + "no_highlights_on_page": { + "message": "Keine Hervorhebungen auf dieser Seite gefunden" + }, + "previous": { + "message": "Vorherige" + }, + "next": { + "message": "Nächste" } } \ No newline at end of file diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 514a866..0d6c0c8 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "Text color" + }, + "tab_page_highlights": { + "message": "On Page" + }, + "highlights_on_page": { + "message": "Highlights on This Page" + }, + "total_highlights": { + "message": "Total" + }, + "refresh": { + "message": "Refresh" + }, + "no_highlights_on_page": { + "message": "No highlights found on this page" + }, + "previous": { + "message": "Previous" + }, + "next": { + "message": "Next" } } \ No newline at end of file diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 8f16b83..f473ca7 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "Color de texto" + }, + "tab_page_highlights": { + "message": "En página" + }, + "highlights_on_page": { + "message": "Resaltados en esta página" + }, + "total_highlights": { + "message": "Total" + }, + "refresh": { + "message": "Actualizar" + }, + "no_highlights_on_page": { + "message": "No se encontraron resaltados en esta página" + }, + "previous": { + "message": "Anterior" + }, + "next": { + "message": "Siguiente" } } \ No newline at end of file diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 1c0995c..1fac6e8 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "Couleur du texte" + }, + "tab_page_highlights": { + "message": "Sur la page" + }, + "highlights_on_page": { + "message": "Surlignages sur cette page" + }, + "total_highlights": { + "message": "Total" + }, + "refresh": { + "message": "Actualiser" + }, + "no_highlights_on_page": { + "message": "Aucun surlignage trouvé sur cette page" + }, + "previous": { + "message": "Précédent" + }, + "next": { + "message": "Suivant" } } \ No newline at end of file diff --git a/_locales/hi/messages.json b/_locales/hi/messages.json index edbfd11..b0337b5 100644 --- a/_locales/hi/messages.json +++ b/_locales/hi/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "पाठ रंग" + }, + "tab_page_highlights": { + "message": "पृष्ठ पर" + }, + "highlights_on_page": { + "message": "इस पृष्ठ पर हाइलाइट" + }, + "total_highlights": { + "message": "कुल" + }, + "refresh": { + "message": "रीफ्रेश करें" + }, + "no_highlights_on_page": { + "message": "इस पृष्ठ पर कोई हाइलाइट नहीं मिला" + }, + "previous": { + "message": "पिछला" + }, + "next": { + "message": "अगला" } } \ No newline at end of file diff --git a/_locales/it/messages.json b/_locales/it/messages.json index 716da1f..a9fd1cd 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "Colore del testo" + }, + "tab_page_highlights": { + "message": "Sulla pagina" + }, + "highlights_on_page": { + "message": "Evidenziazioni su questa pagina" + }, + "total_highlights": { + "message": "Totale" + }, + "refresh": { + "message": "Aggiorna" + }, + "no_highlights_on_page": { + "message": "Nessuna evidenziazione trovata su questa pagina" + }, + "previous": { + "message": "Precedente" + }, + "next": { + "message": "Successivo" } } \ No newline at end of file diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index 8ed70be..9fe838b 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "文字色" + }, + "tab_page_highlights": { + "message": "ページ上" + }, + "highlights_on_page": { + "message": "このページのハイライト" + }, + "total_highlights": { + "message": "合計" + }, + "refresh": { + "message": "更新" + }, + "no_highlights_on_page": { + "message": "このページにハイライトが見つかりません" + }, + "previous": { + "message": "前へ" + }, + "next": { + "message": "次へ" } } \ No newline at end of file diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index ddcdba2..38c058d 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "글자색" + }, + "tab_page_highlights": { + "message": "페이지에서" + }, + "highlights_on_page": { + "message": "이 페이지의 하이라이트" + }, + "total_highlights": { + "message": "전체" + }, + "refresh": { + "message": "새로고침" + }, + "no_highlights_on_page": { + "message": "이 페이지에서 하이라이트를 찾을 수 없습니다" + }, + "previous": { + "message": "이전" + }, + "next": { + "message": "다음" } } \ No newline at end of file diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json index df7c9b8..3f3768d 100644 --- a/_locales/nl/messages.json +++ b/_locales/nl/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "Tekstkleur" + }, + "tab_page_highlights": { + "message": "Op pagina" + }, + "highlights_on_page": { + "message": "Markeringen op deze pagina" + }, + "total_highlights": { + "message": "Totaal" + }, + "refresh": { + "message": "Vernieuwen" + }, + "no_highlights_on_page": { + "message": "Geen markeringen gevonden op deze pagina" + }, + "previous": { + "message": "Vorige" + }, + "next": { + "message": "Volgende" } } \ No newline at end of file diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json index 3dba18d..3b3da2f 100644 --- a/_locales/pl/messages.json +++ b/_locales/pl/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "Kolor tekstu" + }, + "tab_page_highlights": { + "message": "Na stronie" + }, + "highlights_on_page": { + "message": "Podświetlenia na tej stronie" + }, + "total_highlights": { + "message": "Łącznie" + }, + "refresh": { + "message": "Odśwież" + }, + "no_highlights_on_page": { + "message": "Nie znaleziono podświetleń na tej stronie" + }, + "previous": { + "message": "Poprzedni" + }, + "next": { + "message": "Następny" } } \ No newline at end of file diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json index af14dc2..9d1fbbb 100644 --- a/_locales/pt_BR/messages.json +++ b/_locales/pt_BR/messages.json @@ -151,5 +151,26 @@ }, "text_color_title": { "message": "Cor do texto" + }, + "tab_page_highlights": { + "message": "Na página" + }, + "highlights_on_page": { + "message": "Destaques nesta página" + }, + "total_highlights": { + "message": "Total" + }, + "refresh": { + "message": "Atualizar" + }, + "no_highlights_on_page": { + "message": "Nenhum destaque encontrado nesta página" + }, + "previous": { + "message": "Anterior" + }, + "next": { + "message": "Próximo" } } \ No newline at end of file diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index 4bcbab8..1df5ad9 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "Цвет текста" + }, + "tab_page_highlights": { + "message": "На странице" + }, + "highlights_on_page": { + "message": "Найдено на этой странице" + }, + "total_highlights": { + "message": "Всего" + }, + "refresh": { + "message": "Обновить" + }, + "no_highlights_on_page": { + "message": "На этой странице не найдены слова из списка" + }, + "previous": { + "message": "Предыдущее" + }, + "next": { + "message": "Следующее" } } \ No newline at end of file diff --git a/_locales/tr/messages.json b/_locales/tr/messages.json index 4111e6f..299bb20 100644 --- a/_locales/tr/messages.json +++ b/_locales/tr/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "Metin rengi" + }, + "tab_page_highlights": { + "message": "Sayfada" + }, + "highlights_on_page": { + "message": "Bu sayfadaki vurgular" + }, + "total_highlights": { + "message": "Toplam" + }, + "refresh": { + "message": "Yenile" + }, + "no_highlights_on_page": { + "message": "Bu sayfada vurgu bulunamadı" + }, + "previous": { + "message": "Önceki" + }, + "next": { + "message": "Sonraki" } } \ No newline at end of file diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index fddcd0a..ec3ec03 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -157,5 +157,26 @@ }, "text_color_title": { "message": "文字颜色" + }, + "tab_page_highlights": { + "message": "页面上" + }, + "highlights_on_page": { + "message": "此页面上的高亮" + }, + "total_highlights": { + "message": "总计" + }, + "refresh": { + "message": "刷新" + }, + "no_highlights_on_page": { + "message": "此页面上未找到高亮" + }, + "previous": { + "message": "上一个" + }, + "next": { + "message": "下一个" } } \ No newline at end of file diff --git a/popup/popup.css b/popup/popup.css index e9e616b..33cf87d 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -306,8 +306,8 @@ input[type="color"] { border: 1.5px solid var(--input-border); border-radius: 6px; box-shadow: var(--shadow-sm); - width: 32px; - height: 32px; + width: 24px; + height: 24px; margin-left: 6px; cursor: pointer; padding: 0; @@ -597,13 +597,14 @@ input[type="file"] { } #wordList input[type="color"] { - width: 26px; - height: 26px; + width: 22px; + height: 22px; padding: 0; border-radius: 3px; border: 1px solid var(--input-border); cursor: pointer; transition: border-color 0.2s; + align-self: center; } #wordList input[type="color"]:hover { @@ -770,3 +771,104 @@ body::-webkit-scrollbar-corner, .exceptions-list::-webkit-scrollbar-corner { background: var(--section-bg); } + +/* Page Highlights Section */ +.section[data-section="page-highlights"] { + flex: 1; + overflow: hidden; + min-height: 0; +} + +.page-highlights-info { + font-size: 0.85em; + padding: 6px 8px; + background: var(--input-bg); + border-radius: 6px; + border: 1px solid var(--input-border); + margin-bottom: 8px; +} + +.page-highlights-list { + flex: 1; + overflow-y: auto; + margin-top: 8px; + border: 1px solid var(--input-border); + border-radius: 6px; + background: var(--input-bg); + min-height: 0; +} + +.page-highlight-item { + display: flex; + justify-content: space-between; + align-items: center; + gap: 8px; + padding: 8px 10px; + border-bottom: 1px solid var(--input-border); + font-size: 0.85em; + cursor: pointer; + transition: all 0.2s; +} + +.page-highlight-item:last-child { + border-bottom: none; +} + +.page-highlight-item:hover { + background: var(--highlight-tag); + border-left: 3px solid var(--accent); + padding-left: 7px; +} + +.page-highlight-word { + flex: 1; + display: flex; + align-items: center; + gap: 8px; + word-break: break-word; + font-weight: 500; +} + +.page-highlight-preview { + display: inline-block; + padding: 2px 6px; + border-radius: 3px; + font-size: 0.9em; +} + +.page-highlight-count { + background: var(--accent); + color: var(--accent-text); + padding: 2px 8px; + border-radius: 12px; + font-size: 0.75em; + font-weight: 600; + flex-shrink: 0; +} + +.page-highlight-nav { + display: flex; + gap: 4px; + flex-shrink: 0; +} + +.page-highlight-nav button { + padding: 4px 8px; + font-size: 0.75em; + min-width: 28px; +} + +.page-highlight-position { + font-size: 0.7em; + color: var(--text-color); + opacity: 0.6; + margin-left: 4px; +} + +.page-highlights-empty { + padding: 20px; + text-align: center; + color: var(--text-color); + opacity: 0.5; + font-size: 0.85em; +} diff --git a/popup/popup.html b/popup/popup.html index e201eb4..4f03c3a 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -35,6 +35,7 @@
+
@@ -92,6 +93,17 @@ +
+
+

Highlights on This Page

+
+ Total: 0 +
+ +
+
+
+

Site Exceptions

diff --git a/src/content/ContentScript.ts b/src/content/ContentScript.ts index 3dfe7ba..bc71a22 100644 --- a/src/content/ContentScript.ts +++ b/src/content/ContentScript.ts @@ -47,21 +47,28 @@ export class ContentScript { } private setupMessageListener(): void { - MessageService.onMessage((message: MessageData) => { + MessageService.onMessage((message: MessageData, sender: any, sendResponse: (response?: any) => void) => { switch (message.type) { case 'WORD_LIST_UPDATED': this.handleWordListUpdate(); - break; + return false; case 'GLOBAL_TOGGLE_UPDATED': this.handleGlobalToggleUpdate(message.enabled!); - break; + return false; case 'MATCH_OPTIONS_UPDATED': this.handleMatchOptionsUpdate(message.matchCase!, message.matchWhole!); - break; + return false; case 'EXCEPTIONS_LIST_UPDATED': this.handleExceptionsUpdate(); - break; + return false; + case 'GET_PAGE_HIGHLIGHTS': + this.handleGetPageHighlights(sendResponse); + return true; + case 'SCROLL_TO_HIGHLIGHT': + this.handleScrollToHighlight(message.word!, message.index!); + return false; } + return false; }); } @@ -106,4 +113,27 @@ export class ContentScript { this.isProcessing = false; } } + + private handleGetPageHighlights(sendResponse: (response: any) => void): void { + const activeWords: ActiveWord[] = []; + + for (const list of this.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 + }); + } + } + + const highlights = this.highlightEngine.getPageHighlights(activeWords); + sendResponse({ highlights }); + } + + private handleScrollToHighlight(word: string, index: number): void { + this.highlightEngine.scrollToHighlight(word, index); + } } \ No newline at end of file diff --git a/src/content/HighlightEngine.ts b/src/content/HighlightEngine.ts index 9955da8..4a7a3f4 100644 --- a/src/content/HighlightEngine.ts +++ b/src/content/HighlightEngine.ts @@ -4,8 +4,10 @@ import { DOMUtils } from '../utils/DOMUtils.js'; export class HighlightEngine { private styleSheet: CSSStyleSheet | null = null; private highlights = new Map(); + private highlightsByWord = new Map(); private observer: MutationObserver; private isHighlighting = false; + private currentMatchCase = false; constructor(private onUpdate: () => void) { this.observer = new MutationObserver(DOMUtils.debounce((mutations: MutationRecord[]) => { @@ -106,6 +108,8 @@ export class HighlightEngine { if (this.isHighlighting) return; this.isHighlighting = true; + this.currentMatchCase = matchCase; + this.observer.disconnect(); this.clearHighlightsInternal(); @@ -143,6 +147,7 @@ export class HighlightEngine { const textNodes = this.getTextNodes(); const rangesByStyle = new Map(); + this.highlightsByWord.clear(); for (const node of textNodes) { if (!node.nodeValue) continue; @@ -164,6 +169,11 @@ export class HighlightEngine { rangesByStyle.set(styleIdx, []); } rangesByStyle.get(styleIdx)!.push(range); + + if (!this.highlightsByWord.has(lookup)) { + this.highlightsByWord.set(lookup, []); + } + this.highlightsByWord.get(lookup)!.push(range); } } } @@ -187,6 +197,7 @@ export class HighlightEngine { CSS.highlights.delete(name); } this.highlights.clear(); + this.highlightsByWord.clear(); if (this.styleSheet && this.styleSheet.cssRules.length > 0) { while (this.styleSheet.cssRules.length > 0) { @@ -195,6 +206,67 @@ export class HighlightEngine { } } + getPageHighlights(activeWords: ActiveWord[]): Array<{ word: string; count: number; background: string; foreground: string }> { + const seen = new Map(); + + for (const activeWord of activeWords) { + const lookup = this.currentMatchCase ? activeWord.text : activeWord.text.toLowerCase(); + const ranges = this.highlightsByWord.get(lookup); + + if (ranges && ranges.length > 0 && !seen.has(lookup)) { + seen.set(lookup, { + word: activeWord.text, + count: ranges.length, + background: activeWord.background, + foreground: activeWord.foreground + }); + } + } + + return Array.from(seen.values()); + } + + scrollToHighlight(word: string, index: number): void { + const lookup = this.currentMatchCase ? word : word.toLowerCase(); + const ranges = this.highlightsByWord.get(lookup); + + if (!ranges || ranges.length === 0) return; + + const targetIndex = Math.min(index, ranges.length - 1); + const range = ranges[targetIndex]; + + if (!range) return; + + try { + const rect = range.getBoundingClientRect(); + + const absoluteTop = window.pageYOffset + rect.top; + const middle = absoluteTop - (window.innerHeight / 2) + (rect.height / 2); + + window.scrollTo({ + top: middle, + behavior: 'smooth' + }); + + const flashHighlight = new Highlight(range); + CSS.highlights.set('gh-flash', flashHighlight); + + if (this.styleSheet) { + const flashRule = '::highlight(gh-flash) { background-color: rgba(255, 165, 0, 0.8); box-shadow: 0 0 10px 3px rgba(255, 165, 0, 0.8); }'; + const ruleIndex = this.styleSheet.insertRule(flashRule, this.styleSheet.cssRules.length); + + setTimeout(() => { + CSS.highlights.delete('gh-flash'); + if (this.styleSheet && ruleIndex < this.styleSheet.cssRules.length) { + this.styleSheet.deleteRule(ruleIndex); + } + }, 600); + } + } catch (e) { + console.error('Error scrolling to highlight:', e); + } + } + stopObserving(): void { this.observer.disconnect(); } diff --git a/src/popup/PopupController.ts b/src/popup/PopupController.ts index 370f665..b64a801 100644 --- a/src/popup/PopupController.ts +++ b/src/popup/PopupController.ts @@ -1,4 +1,4 @@ -import { HighlightList, HighlightWord, ExportData } from '../types.js'; +import { HighlightList, HighlightWord, ExportData, HighlightInfo } from '../types.js'; import { StorageService } from '../services/StorageService.js'; import { MessageService } from '../services/MessageService.js'; import { DOMUtils } from '../utils/DOMUtils.js'; @@ -14,6 +14,8 @@ export class PopupController { private exceptionsList: string[] = []; private currentTabHost = ''; private activeTab = 'lists'; + private pageHighlights: Array<{ word: string; count: number; background: string; foreground: string }> = []; + private highlightIndices = new Map(); async initialize(): Promise { await this.loadData(); @@ -99,6 +101,10 @@ export class PopupController { document.querySelectorAll('.tab-content').forEach(content => { content.classList.toggle('active', content.getAttribute('data-tab-content') === tabName); }); + + if (tabName === 'page-highlights') { + this.loadPageHighlights(); + } } private setupEventListeners(): void { @@ -106,6 +112,7 @@ export class PopupController { this.setupListManagement(); this.setupWordManagement(); this.setupSettings(); + this.setupPageHighlights(); this.setupExceptions(); this.setupImportExport(); this.setupTheme(); @@ -318,6 +325,110 @@ export class PopupController { }); } + private setupPageHighlights(): void { + document.getElementById('refreshHighlightsBtn')?.addEventListener('click', async () => { + await this.loadPageHighlights(); + }); + + document.getElementById('pageHighlightsList')?.addEventListener('click', async (e) => { + const target = e.target as HTMLElement; + const item = target.closest('.page-highlight-item') as HTMLElement; + + if (!item) return; + + const word = item.dataset.word; + if (!word) return; + + if (target.classList.contains('highlight-prev')) { + await this.navigateHighlight(word, -1); + } else if (target.classList.contains('highlight-next')) { + await this.navigateHighlight(word, 1); + } else { + await this.jumpToHighlight(word, 0); + } + }); + } + + private async loadPageHighlights(): Promise { + try { + const response = await MessageService.sendToActiveTab({ type: 'GET_PAGE_HIGHLIGHTS' }); + + if (response && response.highlights) { + this.pageHighlights = response.highlights; + this.highlightIndices.clear(); + this.pageHighlights.forEach(h => this.highlightIndices.set(h.word, 0)); + this.renderPageHighlights(); + } + } catch (e) { + console.error('Error loading page highlights:', e); + this.pageHighlights = []; + this.renderPageHighlights(); + } + } + + private async jumpToHighlight(word: string, index: number): Promise { + this.highlightIndices.set(word, index); + await MessageService.sendToActiveTab({ + type: 'SCROLL_TO_HIGHLIGHT', + word, + index + }); + this.renderPageHighlights(); + } + + private async navigateHighlight(word: string, direction: number): Promise { + const highlight = this.pageHighlights.find(h => h.word === word); + if (!highlight) return; + + const currentIndex = this.highlightIndices.get(word) || 0; + let newIndex = currentIndex + direction; + + if (newIndex < 0) newIndex = highlight.count - 1; + if (newIndex >= highlight.count) newIndex = 0; + + await this.jumpToHighlight(word, newIndex); + } + + private renderPageHighlights(): void { + const container = document.getElementById('pageHighlightsList'); + const countElement = document.getElementById('totalHighlightsCount'); + + if (!container || !countElement) return; + + const totalCount = this.pageHighlights.reduce((sum, h) => sum + h.count, 0); + countElement.textContent = totalCount.toString(); + + if (this.pageHighlights.length === 0) { + container.innerHTML = `
${chrome.i18n.getMessage('no_highlights_on_page') || 'No highlights on this page'}
`; + return; + } + + container.innerHTML = this.pageHighlights.map(highlight => { + const currentIndex = this.highlightIndices.get(highlight.word) || 0; + return ` +
+
+ + ${DOMUtils.escapeHtml(highlight.word)} + + ${highlight.count > 1 ? `${currentIndex + 1}/${highlight.count}` : ''} +
+ ${highlight.count} + ${highlight.count > 1 ? ` +
+ + +
+ ` : ''} +
+ `; + }).join(''); + } + private setupExceptions(): void { document.getElementById('toggleExceptionBtn')?.addEventListener('click', async () => { if (!this.currentTabHost) return; diff --git a/src/services/MessageService.ts b/src/services/MessageService.ts index 93fe198..7fe6168 100644 --- a/src/services/MessageService.ts +++ b/src/services/MessageService.ts @@ -19,7 +19,15 @@ export class MessageService { }); } - static onMessage(callback: (message: MessageData) => void): void { + static onMessage(callback: (message: MessageData, sender: any, sendResponse: (response?: any) => void) => void | boolean): void { chrome.runtime.onMessage.addListener(callback); } + + static async sendToActiveTab(message: MessageData): Promise { + const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); + if (tab.id) { + return chrome.tabs.sendMessage(tab.id, message); + } + return null; + } } \ No newline at end of file diff --git a/src/types.ts b/src/types.ts index 26a5520..a95c266 100644 --- a/src/types.ts +++ b/src/types.ts @@ -28,11 +28,21 @@ export interface ActiveWord { foreground: string; } +export interface HighlightInfo { + word: string; + count: number; + background: string; + foreground: string; +} + export interface MessageData { - type: 'WORD_LIST_UPDATED' | 'GLOBAL_TOGGLE_UPDATED' | 'MATCH_OPTIONS_UPDATED' | 'EXCEPTIONS_LIST_UPDATED'; + type: 'WORD_LIST_UPDATED' | 'GLOBAL_TOGGLE_UPDATED' | 'MATCH_OPTIONS_UPDATED' | 'EXCEPTIONS_LIST_UPDATED' | 'GET_PAGE_HIGHLIGHTS' | 'PAGE_HIGHLIGHTS_RESPONSE' | 'SCROLL_TO_HIGHLIGHT'; enabled?: boolean; matchCase?: boolean; matchWhole?: boolean; + highlights?: HighlightInfo[]; + word?: string; + index?: number; } export interface ExportData {