### Install Dependencies Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Installs project dependencies. Skips husky for production builds. ```bash RELEASE_BUILD=1 pnpm install ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Install all necessary project dependencies using `pnpm`. This command should be run after cloning the repository. ```bash pnpm install ``` -------------------------------- ### Run Development Server for Firefox Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Start the development server for manual testing with Firefox. This command enables automatic reloading for faster development cycles. ```bash pnpm start:firefox ``` -------------------------------- ### Run Development Server for Chrome Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Start the development server for manual testing with Chrome. This command enables automatic reloading for faster development cycles. ```bash pnpm start:chrome ``` -------------------------------- ### Install Dependencies Ignoring Scripts (Older Versions) Source: https://github.com/birchill/10ten-ja-reader/blob/main/README.md For versions prior to and including 0.5.5, use this command to install dependencies while ignoring scripts that might cause issues with husky. ```bash pnpm install --ignore-scripts ``` -------------------------------- ### Development Watch Mode Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Starts the development server in watch mode for different browsers. This will continuously rebuild the extension as changes are made. ```bash pnpm start:firefox # watches → dist-firefox/ ``` ```bash pnpm start:chrome # watches → dist-chrome/ ``` ```bash pnpm start:edge # watches → dist-edge/ ``` -------------------------------- ### Fork and Clone Repository with gh CLI Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Use the `gh` CLI tool to fork the repository and clone it locally in a single command. This is a convenient way to start contributing. ```bash gh repo fork birchill/10ten-ja-reader --clone=true ``` -------------------------------- ### Build Firefox Release Package Source: https://github.com/birchill/10ten-ja-reader/blob/main/README.md Use these commands to build the Firefox add-on package from source. Ensure you have the correct Node.js package manager (pnpm or yarn) installed. ```bash export RELEASE_BUILD=1 pnpm install pnpm package:firefox ``` -------------------------------- ### Build Safari Extension Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Initiate the build process for the Safari extension. This command prepares the project for Xcode integration. ```bash pnpm build:safari ``` -------------------------------- ### Build and Package Commands Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Commands for building the extension with Rspack and packaging it for different browsers. ```bash ``` -------------------------------- ### Run Firefox for Android with web-ext Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Execute the `web-ext` command to run the extension on an Android device. Ensure `adb` is set up correctly and provide the device ID. ```bash pnpm web-ext run -t firefox-android --adb-device --firefox-apk org.mozilla.fenix ``` -------------------------------- ### Run Firefox with Specific Version Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Launch the development server for Firefox, specifying a particular version like 'nightly'. This allows testing against different Firefox releases. ```bash pnpm start:firefox --env firefox=nightly ``` -------------------------------- ### Get Text at Viewport Coordinate Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Dispatches to specialized handlers for hit-testing the page at a given viewport coordinate. Results are cached by glyph bounding box and cursor offset to avoid redundant DOM queries during fast mouse movement. ```typescript // src/content/get-text.ts import { getTextAtPoint } from './get-text'; // Called from mousemove handler in content script document.addEventListener('mousemove', (evt) => { const result = getTextAtPoint({ point: { x: evt.clientX, y: evt.clientY }, maxLength: 16, matchCurrency: true, matchText: true, matchImages: true, // scan alt/title attributes of }); if (result) { console.log(result.text); // e.g. "食べています" console.log(result.startElement); // DOM element where text begins console.log(result.textRange); // Range for highlight underline, or null // result.meta may contain era, currency, or area metadata } }); ``` -------------------------------- ### Production Builds Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Creates production-ready builds of the extension for various browsers. These builds are optimized for performance and size. ```bash pnpm build:firefox ``` ```bash pnpm build:chrome ``` ```bash pnpm build:safari ``` ```bash pnpm build:edge ``` ```bash pnpm build:thunderbird ``` -------------------------------- ### Check Release Notes Parsing Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Run a script to verify that the release notes are being parsed correctly. ```bash pnpm tsx scripts/release-notes.js ``` -------------------------------- ### Initialize Content Handler Configuration Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Sets up the configuration object for the ContentHandler, defining various display and interaction settings for popups. ```javascript const config = { accentDisplay: 'binary', copyState: { kind: 'inactive' }, displayMode: 'static', holdToShowKeys: [], holdToShowImageKeys: [], kanjiReferences: ['radical', 'nelson_r', 'kk', 'unicode', 'henshall'], keys: { toggleDefinition: ['d'], nextDictionary: ['Shift', 'Enter'], expandPopup: ['x'], kanjiLookup: [], pinPopup: ['Ctrl'], startCopy: ['c'], }, noTextHighlight: false, popupStyle: 'blue', posDisplay: 'expl', readingOnly: false, showKanjiComponents: true, showPriority: true, showRomaji: false, switchDictionaryKeys: [], }; const contentHandler = new ContentHandler(config); ``` -------------------------------- ### Run All Tests Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Execute all tests in the project. ```bash pnpm test ``` -------------------------------- ### Build Safari Release Package Source: https://github.com/birchill/10ten-ja-reader/blob/main/README.md Command to build the Safari add-on package from source. This is an alternative to building for Firefox. ```bash pnpm package:safari ``` -------------------------------- ### Package Extension as Zip Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Package the extension into a zip file for distribution. Use the appropriate command for the target browser (e.g., `pnpm package:firefox`). ```bash pnpm package:firefox ``` -------------------------------- ### Build Edge Release Package Source: https://github.com/birchill/10ten-ja-reader/blob/main/README.md Command to build the Edge add-on package from source. This is an alternative to building for Firefox. ```bash pnpm package:edge ``` -------------------------------- ### Build Thunderbird Release Package Source: https://github.com/birchill/10ten-ja-reader/blob/main/README.md Command to build the Thunderbird add-on package from source. This is an alternative to building for Firefox. ```bash pnpm package:thunderbird ``` -------------------------------- ### Config Class Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Manages extension settings by wrapping `browser.storage.sync` and `browser.storage.local`. It provides typed getters for all settings and supports listeners for changes. ```APIDOC ## `Config` class — extension settings Wraps `browser.storage.sync` and `browser.storage.local` with snapshot semantics: only user-modified values are persisted, so syncing to a new device never overwrites defaults. Exposes every setting as a typed getter and accepts `ChangeCallback` listeners that fire with a diff object when settings change. ### Methods - **`ready`**: A promise that resolves when storage read is complete. - **`addChangeListener(callback)`**: Adds a listener for setting changes. ### Properties - **`dictLang`**: (string) Dictionary language setting. - **`accentDisplay`**: (string) Accent display style. - **`fontSize`**: (string) Font size setting. - **`holdToShowKeys`**: (Array) Keys to hold to show elements. - **`keys`**: (object) Keyboard shortcut configurations. - **`keys.startCopy`**: (Array) Keys to start copying. - **`showRomaji`**: (boolean) Whether to show Romaji. - **`contentConfig`**: (ContentConfigParams) Configuration object for content scripts. ### Example Usage ```typescript import { Config } from './config'; const config = new Config(); await config.ready; // wait for storage read to complete // Read settings console.log(config.dictLang); console.log(config.accentDisplay); console.log(config.fontSize); console.log(config.holdToShowKeys); console.log(config.keys.startCopy); console.log(config.showRomaji); // Write a setting config.dictLang = 'de'; // Listen for changes config.addChangeListener((changes) => { if (changes.dictLang) { console.log('Language changed to', changes.dictLang.newValue); } if (changes.fontSize) { console.log('Font size changed:', changes.fontSize.newValue); } }); // Snapshot for sending to content script const params = config.contentConfig; // ContentConfigParams — fully typed ``` ``` -------------------------------- ### Build Firefox Extension Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Build the Firefox version of the extension using `pnpm`. The output will be placed in the `dist-firefox` directory. ```bash pnpm build:firefox ``` -------------------------------- ### Build Thunderbird Extension Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Build the Thunderbird version of the extension using `pnpm`. The output will be placed in the `dist-thunderbird` directory. ```bash pnpm build:thunderbird ``` -------------------------------- ### Render Interactive Popups with Themes Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Demonstrates rendering interactive popups using different themes, applying 'touch' display mode and specific result types. ```javascript const kankokuWordsResult = { words: { type: 'words', data: [ { k: [{ ent: '韓国語', p: ['s1'], match: true }], r: [{ ent: 'かんこくご', p: ['s1'], a: 0, match: true }], s: [{ g: [{ str: 'Korean (language)' }], pos: ['n'], match: true }], }, { k: [{ ent: '韓国', p: ['n1', 'nf01'], wk: 29, match: true }], r: [{ ent: 'かんこく', p: ['n1', 'nf01'], a: 0, match: true }], s: [ { g: [{ str: 'South Korea' }, { str: 'Republic of Korea' }], pos: ['n', 'adj-no'], misc: ['abbr'], match: true, }, { g: [{ str: 'Korean Empire (1897-1910)' }], pos: ['n', 'adj-no'], misc: ['abbr'], match: true, }, ], }, { k: [ { ent: '唐国', match: false }, { ent: '韓国', match: true }, ], r: [{ ent: 'からくに', match: true }], s: [ { g: [{ str: 'China' }, { str: 'Korea' }], pos: ['n'], misc: ['arch'], match: true, }, ], }, { k: [ { ent: '唐', match: false }, { ent: '韓', match: true }, { ent: '漢', match: false }, ], r: [{ ent: 'から', a: 1, match: true }], s: [ { g: [ { str': 'China (sometimes also used in ref. to Korea or other foreign countries)', }, ], pos: ['n', 'n-pref'], misc: ['arch'], match: true, }, ], }, ], more: false, matchLen: 3, }, kanji: { type: 'kanji', data: [ { c: '士', r: { on: ['シ'], kun: ['さむらい'], na: ['お', 'ま'] }, m: ['gentleman', 'scholar', 'samurai', 'samurai radical (no. 33)'], rad: { x: 33, b: '⼠', k: '士', na: ['さむらい'], m: ['gentleman', 'scholar', 'samurai'], m_lang: 'en', }, refs: { nelson_c: 1160, nelson_n: 1117, halpern_njecd: 3405, halpern_kkld: 2129, halpern_kkld_2ed: 2877, heisig: 319, heisig6: 341, henshall: 494, sh_kk: 572, sh_kk2: 581, kanji_in_context: 755, kodansha_compact: 393, skip: '4-3-2', sh_desc: '3p0.1', conning: 350, }, misc: { sc: 3, gr: 4, freq: 526, jlpt: 1, kk: 7 }, m_lang: 'en', comp: [], }, ], }, }; addHeading('Interactive mode tabs', 3); const themes = ['light', 'blue', 'lightblue', 'black', 'yellow']; for (const theme of themes) { const label = document.createElement('div'); label.classList.add('label'); label.append(`Theme: ${theme}`); container.append(label); const popup = contentHandler._renderPopup(kankokuWordsResult, { ...config, container: createPopupContainer(), displayMode: 'touch', dictToShow: 'words', popupStyle: theme, showDefinitions: true, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, waniKaniVocabDisplay: 'show-matches', }); popup.classList.add('-inline'); } ``` -------------------------------- ### Build Chrome Release Package Source: https://github.com/birchill/10ten-ja-reader/blob/main/README.md Command to build the Chrome add-on package from source. This is an alternative to building for Firefox. ```bash pnpm package:chrome ``` -------------------------------- ### Config Class for Extension Settings Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Wraps browser.storage.sync and browser.storage.local with snapshot semantics. Only user-modified values are persisted, so syncing to a new device never overwrites defaults. Exposes every setting as a typed getter and accepts ChangeCallback listeners that fire with a diff object when settings change. ```typescript // src/common/config.ts import { Config } from './config'; const config = new Config(); await config.ready; // wait for storage read to complete // Read settings console.log(config.dictLang); // 'en' | 'de' | 'fr' | 'zh' | … console.log(config.accentDisplay); // 'downstep' | 'binary' | 'binary-hi-contrast' | 'none' console.log(config.fontSize); // 'xs' | 'small' | 'normal' | 'large' | 'xl' console.log(config.holdToShowKeys); // e.g. ['Alt'] console.log(config.keys.startCopy); // e.g. ['c'] console.log(config.showRomaji); // boolean // Write a setting config.dictLang = 'de'; // Listen for changes (fired on all open extension pages/content scripts) config.addChangeListener((changes) => { if (changes.dictLang) { console.log('Language changed to', changes.dictLang.newValue); } if (changes.fontSize) { console.log('Font size changed:', changes.fontSize.newValue); } }); // Snapshot for sending to content script const params = config.contentConfig; // ContentConfigParams — fully typed ``` -------------------------------- ### Run Unit Tests Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Execute only the unit tests for the project. ```bash pnpm test:unit ``` -------------------------------- ### Build Chrome Extension Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Build the Chrome version of the extension using `pnpm`. The output will be placed in the `dist-chrome` directory. ```bash pnpm build:chrome ``` -------------------------------- ### Build Edge Extension Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Build the Edge version of the extension using `pnpm`. The output will be placed in the `dist-edge` directory. ```bash pnpm build:edge ``` -------------------------------- ### Verify Zip Archive for Firefox Build Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Generate a zip archive of the source code and verify it can be used to build the Firefox add-on. ```bash pnpm zip-src mkdir ~/test-src cp dist-src/10ten-ja-reader--src.zip ~/test-src/test.zip cd ~/test-src unzip test.zip # Check it builds pnpm install pnpm build:firefox # Check it runs pnpm start:firefox # Clean up cd .. rm -rf ~/test-src ``` -------------------------------- ### Render Basic Popup Results Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Iterates through test cases to render popup content for basic search results, applying specific configurations for language and display. ```javascript addHeading('Basic results'); for (const test of htmlTests) { addLabel(test.description); const dictToShow = Object.keys(test.queryResult).find( (key) => key === 'words' || key === 'kanji' || key === 'names' ) || 'words'; const popup = contentHandler._renderPopup(test.queryResult, { ...config, container: createPopupContainer(), dictLang: test.description.indexOf('language') !== -1 ? 'fr' : undefined, dictToShow: getDictFromResult(test.queryResult), popupStyle: 'blue', showDefinitions: !test.extraConfig || !test.extraConfig.readingOnly, waniKaniVocabDisplay: 'show-matches', }); popup.classList.add('-inline'); } ``` -------------------------------- ### Run Browser-Based Tests Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Execute browser-based tests, specifying the browser to use. ```bash pnpm test:firefox ``` ```bash pnpm test:chrome ``` -------------------------------- ### Render Popup with Constrained Height, Status Bar, and Top Tabs Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders a popup with a constrained height, database updating status, and tabs at the top. Tests combined configurations. ```javascript const popup = contentHandler._renderPopup( { ...kankokuWordsResult, resultType: 'db-updating' }, { ...config, container: createPopupContainer(), dictToShow: 'words', popupStyle: 'default', showDefinitions: true, switchDictionaryKeys: ['Shift', 'Enter'], tabDisplay, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, } ); popup.classList.add('-inline'); popup.style.setProperty('--tenten-max-height', '200px'); ``` -------------------------------- ### Packaged Zips for Store Submission Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Packages the built extension into zip files, ready for submission to respective browser stores. ```bash pnpm package:firefox ``` ```bash pnpm package:chrome ``` ```bash pnpm package:edge ``` ```bash pnpm package:thunderbird ``` -------------------------------- ### Format Dictionary Entry for Copying Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Formats a dictionary entry into a clipboard-ready string. Supports different copy types like 'entry', 'tab', and 'word'. ```typescript // src/content/copy-text.ts import { getTextToCopy } from './copy-text'; import type { CopyEntry } from './copy-text'; const wordEntry: CopyEntry = { type: 'word', data: { id: 1234567, k: [{ ent: '食べる', p: ['ichi1'], i: [] }], r: [{ ent: 'たべる', p: ['ichi1'], romaji: 'taberu', i: [] }], s: [{ pos: ['v1'], g: [{ str: 'to eat' }] }], matchLen: 3, reasonChains: [], }, }; // Full human-readable entry const fullEntry = getTextToCopy({ entry: wordEntry, copyType: 'entry', getMessage: (key) => key, // pass browser.i18n.getMessage in real usage includeAllSenses: true, includePartOfSpeech: true, showRomaji: true, }); // → "食べる [たべる / taberu]\nIchidan verb\n1. to eat" ``` ```typescript // Tab-separated for Anki const tabEntry = getTextToCopy({ entry: wordEntry, copyType: 'tab', getMessage: (key) => key, includeAllSenses: false, includePartOfSpeech: true, }); // → "食べる\tたべる\tv1\tto eat" ``` ```typescript // Headword only const word = getTextToCopy({ entry: wordEntry, copyType: 'word', getMessage: (k) => k }); // → "食べる" ``` -------------------------------- ### Lint and Test Commands Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Runs code quality checks and automated tests. Includes linting, unit tests, and browser-specific integration tests. ```bash pnpm lint # web-ext lint + ESLint ``` ```bash pnpm test # all unit tests via Vitest ``` ```bash pnpm test:chrome # browser tests in Chrome via WebdriverIO ``` ```bash pnpm test:firefox # browser tests in Firefox ``` -------------------------------- ### Run Single Browser Test in Watch Mode Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Execute a specific browser-based test file and keep it running in watch mode. ```bash pnpm test:firefox src/content/get-text.browser.test.ts --watch ``` -------------------------------- ### Debug Browser Test with Headless Disabled Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Run a browser-based test with headless mode turned off for easier debugging. ```bash pnpm test:firefox src/content/get-text.browser.test.ts --browser.headless=false ``` -------------------------------- ### Render Popup with Ghost Display Mode Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders a popup with 'ghost' display mode for a given theme. This is used for initial theme testing. ```javascript const popup = contentHandler._renderPopup(kankokuWordsResult, { ...config, container: createPopupContainer(), displayMode: 'ghost', dictToShow: 'words', popupStyle: theme, showDefinitions: true, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, }); popup.classList.add('-inline'); ``` -------------------------------- ### Render Popup with Constrained Height, Status Bar, and Interactive Top Tabs Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders a popup with constrained height, database updating status, interactive mode, and tabs at the top. Tests complex interactive scenarios. ```javascript const popup = contentHandler._renderPopup( { ...kankokuWordsResult, resultType: 'db-updating' }, { ...config, container: createPopupContainer(), dictToShow: 'words', displayMode: 'touch', popupStyle: 'default', showDefinitions: true, switchDictionaryKeys: ['Shift', 'Enter'], tabDisplay, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, } ); popup.classList.add('-inline'); popup.style.setProperty('--tenten-max-height', '200px'); ``` -------------------------------- ### getTextToCopy Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Formats dictionary entries into clipboard-ready strings based on specified copy types and formatting options. ```APIDOC ## getTextToCopy({ entry, copyType, getMessage, ... }): string ### Description Formats a dictionary entry (word, kanji, or name) into a clipboard-ready string. Supports three `copyType` modes: `'entry'` (human-readable full entry), `'tab'` (tab-separated fields for Anki/spreadsheets), and `'word'` (headword only). Respects `includeAllSenses`, `includeLessCommonHeadwords`, `includePartOfSpeech`, enabled `kanjiReferences`, and `showRomaji` flags. ### Parameters - **entry** (CopyEntry) - Required - The dictionary entry object to format. - **copyType** (string) - Required - The type of copy format ('entry', 'tab', or 'word'). - **getMessage** (function) - Required - A function to retrieve localized messages. - **includeAllSenses** (boolean) - Optional - Whether to include all senses of a word. - **includeLessCommonHeadwords** (boolean) - Optional - Whether to include less common headwords. - **includePartOfSpeech** (boolean) - Optional - Whether to include the part of speech. - **kanjiReferences** (boolean) - Optional - Whether to include Kanji references. - **showRomaji** (boolean) - Optional - Whether to display Romaji. ### Returns string - The formatted string ready for copying. ``` -------------------------------- ### Render Ghost Mode Popups with Themes Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders popups in 'ghost' mode, cycling through various themes to demonstrate different visual styles. ```javascript addHeading('Ghost mode', 3); for (const theme of themes) { const label = document.createElement('div'); label.classList.add('label'); label.append(`Theme: ${theme}`); container.append(label); const popup = contentHandler._renderPopup(kankokuWordsResult, { ...config, container: createPopupContainer(), displayMode: 'ghost', dictToShow: 'words', popupStyle: theme, showDefinitions: true, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, waniKaniVocabDisplay: 'show-matches', }); popup.classList.add('-inline'); } ``` -------------------------------- ### Render Interactive Popup with Copy Overlay Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders an interactive popup with a copy overlay, configured for hover display mode. Ideal for scenarios where users can copy content via hover interactions. ```javascript const popup = contentHandler._renderPopup(kankokuWordsResult, { ...config, container: createPopupContainer(), copyState: { kind: 'active', index: 1, mode: 'touch' }, dictToShow: 'words', displayMode: 'hover', popupStyle: 'default', showDefinitions: true, switchDictionaryKeys: ['Shift', 'Enter'], tabDisplay, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, }); popup.classList.add('-inline'); popup.style.setProperty('--tenten-min-height', '400px'); ``` -------------------------------- ### Render Popup with Constrained Height and Interactive Top Tabs Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders a popup with constrained height, interactive mode, and tabs at the top. Tests height constraints in interactive mode. ```javascript const popup = contentHandler._renderPopup(kankokuWordsResult, { ...config, container: createPopupContainer(), dictToShow: 'words', displayMode: 'touch', popupStyle: 'default', showDefinitions: true, switchDictionaryKeys: ['Shift', 'Enter'], tabDisplay, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, }); popup.classList.add('-inline'); popup.style.setProperty('--tenten-max-height', '200px'); ``` -------------------------------- ### Generate Table of Contents and Headings Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Utility functions to dynamically create a table of contents and headings within a container, based on provided text and levels. ```javascript const toc = document.getElementById('toc'); const container = document.getElementById('container'); const addHeading = (heading, level = 2) => { if (level < 2) { return; } const href = heading.replace(/\s/g, '-').toLowerCase(); if (level === 2) { const li = toc.appendChild(document.createElement('li')); const a = li.appendChild(document.createElement('a')); a.textContent = heading; a.href = `#${href}`; } const headingElement = document.createElement(`h${level}`); headingElement.textContent = heading; headingElement.id = href; container.appendChild(headingElement); }; const addLabel = (labelText) => { const label = document.createElement('div'); label.classList.add('label'); label.append(labelText); container.append(label); }; const createPopupContainer = () => { const popupContainer = document.createElement('div'); popupContainer.style.width = 'max-content'; container.append(popupContainer); return popupContainer; }; const getDictFromResult = (queryResult) => Object.keys(queryResult).find( (key) => key === 'words' || key === 'kanji' || key === 'names' ) || 'words'; ``` -------------------------------- ### Create Custom Element with Shadow DOM Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/playground.html Defines a custom HTML element 'my-elem' that attaches an open Shadow DOM. Use this to encapsulate component-specific styles and markup. ```javascript class MyElement extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); const para = document.createElement('p'); shadowRoot.appendChild(para); para.append('日本語 (Custom element)'); } } customElements.define('my-elem', MyElement); ``` -------------------------------- ### Render Popup with Constrained Height and Top Tabs Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders a popup with a constrained height of 200px and tabs displayed at the top. Tests height limitations with different tab layouts. ```javascript const popup = contentHandler._renderPopup(kankokuWordsResult, { ...config, container: createPopupContainer(), dictToShow: 'words', popupStyle: 'default', showDefinitions: true, switchDictionaryKeys: ['Shift', 'Enter'], tabDisplay, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, }); popup.classList.add('-inline'); popup.style.setProperty('--tenten-max-height', '200px'); ``` -------------------------------- ### ContentConfigParams Interface Source: https://context7.com/birchill/10ten-ja-reader/llms.txt Defines the structure of parameters sent from the background to content scripts, controlling the visual and behavioral aspects of the popup. ```APIDOC ## `ContentConfigParams` interface — popup rendering contract Typed parameter object produced by `Config.contentConfig` and sent from the background to every content script on enable/update. Controls every visual and behavioral aspect of the popup: language, accent display style, font, keyboard shortcuts, kanji references, copy formatting, WaniKani/Bunpro integration, and puck position. ### Interface Fields - **`accentDisplay`**: ('downstep' | 'binary' | 'binary-hi-contrast' | 'none') - Accent display style. - **`autoExpand`**: (Array) - Automatically expand elements. - **`bunproDisplay`**: (boolean) - Whether to display Bunpro integration. - **`copyHeadwords`**: ('common' | ...) - How to copy headwords. - **`copyPos`**: ('code' | ...) - How to copy part of speech. - **`copySenses`**: ('first' | ...) - How to copy senses. - **`dictLang`**: (string) - Dictionary language. - **`enableTapLookup`**: (boolean) - Enable tap lookup. - **`fx`**: (object) - Foreign exchange rate information. - **`currency`**: (string) - Currency type. - **`rate`**: (number) - Exchange rate. - **`timestamp`**: (number) - Timestamp of the rate. - **`fontFace`**: ('bundled' | ...) - Font face to use. - **`fontSize`**: ('xs' | 'small' | 'normal' | 'large' | 'xl') - Font size. - **`highlightStyle`**: (string) - Style for highlighting. - **`handedness`**: ('right' | 'left') - Handedness setting. - **`holdToShowKeys`**: (Array) - Keys to hold to show elements. - **`holdToShowImageKeys`**: (Array) - Keys to hold to show images. - **`kanjiReferences`**: (Array) - Kanji reference types to show. - **`keys`**: (object) - Keyboard shortcut configurations. - **`nextDictionary`**: (Array) - Keys to cycle through dictionaries. - **`startCopy`**: (Array) - Keys to start copying. - **`closePopup`**: (Array) - Keys to close the popup. - **`pinPopup`**: (Array) - Keys to pin the popup. - **`kanjiLookup`**: (Array) - Keys for Kanji lookup. - **`toggleDefinition`**: (Array) - Keys to toggle definitions. - **`expandPopup`**: (Array) - Keys to expand the popup. - **`movePopupUp`**: (Array) - Keys to move the popup up. - **`movePopupDown`**: (Array) - Keys to move the popup down. - **`noTextHighlight`**: (boolean) - Disable text highlighting. - **`popupInteractive`**: (boolean) - Make the popup interactive. - **`popupStyle`**: (string) - Style of the popup. - **`posDisplay`**: (string) - How part of speech is displayed. - **`preferredUnits`**: ('metric' | 'imperial') - Preferred units of measurement. - **`puckState`**: (any) - State of the puck UI element. - **`readingOnly`**: (boolean) - Enable reading-only mode. - **`showKanjiComponents`**: (boolean) - Show Kanji components. - **`showPriority`**: (boolean) - Show priority indicators. - **`showPuck`**: ('auto' | ...) - Control visibility of the puck UI element. - **`showRomaji`**: (boolean) - Show Romaji. - **`tabDisplay`**: (string) - How tabs are displayed. - **`toolbarIcon`**: (string) - Toolbar icon style. - **`waniKaniVocabDisplay`**: ('hide' | ...) - Control WaniKani vocabulary display. ### Example Object Structure ```typescript const params: ContentConfigParams = { accentDisplay: 'downstep', autoExpand: ['words'], bunproDisplay: false, copyHeadwords: 'common', copyPos: 'code', copySenses: 'first', dictLang: 'en', enableTapLookup: true, fx: { currency: 'USD', rate: 149.5, timestamp: 1700000000000 }, fontFace: 'bundled', fontSize: 'normal', highlightStyle: 'yellow', handedness: 'right', holdToShowKeys: [], holdToShowImageKeys: [], kanjiReferences: ['radical', 'nelson_r', 'kk', 'jlpt', 'unicode'], keys: { nextDictionary: ['Shift', 'Enter'], startCopy: ['c'], closePopup: ['Escape'], pinPopup: [], kanjiLookup: [], toggleDefinition: ['d'], expandPopup: [], movePopupUp: ['k'], movePopupDown: ['j'], }, noTextHighlight: false, popupInteractive: true, popupStyle: 'default', posDisplay: 'expl', preferredUnits: 'metric', puckState: undefined, readingOnly: false, showKanjiComponents: true, showPriority: true, showPuck: 'auto', showRomaji: false, tabDisplay: 'top', toolbarIcon: 'default', waniKaniVocabDisplay: 'hide', }; ``` ``` -------------------------------- ### Debug Chrome Test with Inspect Source: https://github.com/birchill/10ten-ja-reader/blob/main/CONTRIBUTING.md Run a Chrome-based test with headless mode disabled, enabling Node.js inspector for debugging. ```bash pnpm test:chrome src/content/get-text.browser.test.ts --browser.headless=false --inspect-brk --no-file-parallelism ``` -------------------------------- ### Populate Shadow DOM with HTML Strings Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/playground.html Iterates through an array of HTML strings and sets the innerHTML of shadow roots. This is useful for rendering predefined HTML structures within shadow DOMs. ```javascript const cases = [ '

日本語 (element in shadow DOM element)

', '

日本語 (element with margin in shadow DOM)

', '

日本語 (element with margin+border in shadow DOM)

', '

日本語 (element with margin+border in shadow DOM, box-sizing: border-box)

', '

日本語 (element with margin in shadow DOM, box-sizing: content-box)

', '

これは日本語だよ。 (element in shadow DOM with inlines and line wrapping)

', ]; for (const source of cases) { const container = document.createElement('div'); groupContainer.append(container); const shadowRoot = container.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = source; } ``` -------------------------------- ### Render Popup with Status Bar Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders a popup with a status bar, specifically testing the 'db-updating' state with 'touch' display mode and 'none' tab display. ```javascript const popup = contentHandler._renderPopup( { ...kankokuWordsResult, resultType: 'db-updating' }, { ...config, container: createPopupContainer(), dictToShow: 'words', displayMode: 'touch', popupStyle: 'default', showDefinitions: true, tabDisplay: 'none', onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, } ); popup.classList.add('-inline'); ``` -------------------------------- ### Render Popup with Forced Height and Top Tabs Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/popups.html Renders a popup with a forced height and tabs displayed at the top. This tests explicit height settings. ```javascript const popup = contentHandler._renderPopup(kankokuWordsResult, { ...config, container: createPopupContainer(), dictToShow: 'words', popupStyle: 'default', showDefinitions: true, switchDictionaryKeys: ['Shift', 'Enter'], tabDisplay, onClosePopup: () => {}, onShowSettings: () => {}, onTogglePin: () => {}, }); ``` -------------------------------- ### Nested Shadow DOM with Styles and Complex HTML Source: https://github.com/birchill/10ten-ja-reader/blob/main/tests/playground.html Creates deeply nested Shadow DOMs, including styles and complex HTML markup with links and citations. This test case is designed to verify rendering and style inheritance in complex scenarios, particularly for elements like footnotes. ```javascript const outerContainer = document.createElement('div'); groupContainer.append(outerContainer); const outerShadowRoot = outerContainer.attachShadow({ mode: 'open' }); const innerContainer = document.createElement('div'); outerShadowRoot.append(innerContainer); const innerShadowRoot = innerContainer.attachShadow({ mode: 'open' }); const style = document.createElement('style'); style.append( ` sup { position: relative; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; vertical-align: top; top: -1px; margin: 0px 2px; min-width: 14px; height: 14px; border-radius: 3px; text-decoration-color: transparent; color: var(--cib-color-brand-tertiary-foreground); background: var(--cib-color-brand-tertiary-background); outline: transparent solid 1px; } ` ); innerShadowRoot.append(style); const innerElem = document.createElement('div'); innerShadowRoot.append(innerElem); innerElem.innerHTML = ''; const explanationElem = document.createElement('div'); innerShadowRoot.append(explanationElem); explanationElem.append( '(In particular we want to check towards the end of the line)' ); ```