From 4da4827bcbcdd1ef163f635d9b29416ff272b0bb Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 12:48:14 -0500 Subject: Add JSDoc type annotations to project (rebased) --- ext/js/display/query-parser.js | 127 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 114 insertions(+), 13 deletions(-) (limited to 'ext/js/display/query-parser.js') diff --git a/ext/js/display/query-parser.js b/ext/js/display/query-parser.js index 85ec3031..fd173bde 100644 --- a/ext/js/display/query-parser.js +++ b/ext/js/display/query-parser.js @@ -20,22 +20,42 @@ import {EventDispatcher, log} from '../core.js'; import {TextScanner} from '../language/text-scanner.js'; import {yomitan} from '../yomitan.js'; +/** + * @augments EventDispatcher + */ export class QueryParser extends EventDispatcher { + /** + * @param {import('display').QueryParserConstructorDetails} details + */ constructor({getSearchContext, japaneseUtil}) { super(); + /** @type {import('display').GetSearchContextCallback} */ this._getSearchContext = getSearchContext; + /** @type {JapaneseUtil} */ this._japaneseUtil = japaneseUtil; + /** @type {string} */ this._text = ''; + /** @type {?import('core').TokenObject} */ this._setTextToken = null; + /** @type {?string} */ this._selectedParser = null; + /** @type {import('settings').ParsingReadingMode} */ this._readingMode = 'none'; + /** @type {number} */ this._scanLength = 1; + /** @type {boolean} */ this._useInternalParser = true; + /** @type {boolean} */ this._useMecabParser = false; + /** @type {import('api').ParseTextResult} */ this._parseResults = []; - this._queryParser = document.querySelector('#query-parser-content'); - this._queryParserModeContainer = document.querySelector('#query-parser-mode-container'); - this._queryParserModeSelect = document.querySelector('#query-parser-mode-select'); + /** @type {HTMLElement} */ + this._queryParser = /** @type {HTMLElement} */ (document.querySelector('#query-parser-content')); + /** @type {HTMLElement} */ + this._queryParserModeContainer = /** @type {HTMLElement} */ (document.querySelector('#query-parser-mode-container')); + /** @type {HTMLSelectElement} */ + this._queryParserModeSelect = /** @type {HTMLSelectElement} */ (document.querySelector('#query-parser-mode-select')); + /** @type {TextScanner} */ this._textScanner = new TextScanner({ node: this._queryParser, getSearchContext, @@ -45,10 +65,12 @@ export class QueryParser extends EventDispatcher { }); } + /** @type {string} */ get text() { return this._text; } + /** */ prepare() { this._textScanner.prepare(); this._textScanner.on('clear', this._onTextScannerClear.bind(this)); @@ -56,6 +78,9 @@ export class QueryParser extends EventDispatcher { this._queryParserModeSelect.addEventListener('change', this._onParserChange.bind(this), false); } + /** + * @param {import('display').QueryParserOptions} display + */ setOptions({selectedParser, termSpacing, readingMode, useInternalParser, useMecabParser, scanning}) { let selectedParserChanged = false; if (selectedParser === null || typeof selectedParser === 'string') { @@ -87,10 +112,14 @@ export class QueryParser extends EventDispatcher { } } + /** + * @param {string} text + */ async setText(text) { this._text = text; this._setPreview(text); + /** @type {?import('core').TokenObject} */ const token = {}; this._setTextToken = token; this._parseResults = await yomitan.api.parseText(text, this._getOptionsContext(), this._scanLength, this._useInternalParser, this._useMecabParser); @@ -104,32 +133,63 @@ export class QueryParser extends EventDispatcher { // Private + /** */ _onTextScannerClear() { this._textScanner.clearSelection(); } + /** + * @param {import('text-scanner').SearchedEventDetails} e + */ _onSearched(e) { const {error} = e; if (error !== null) { log.error(error); return; } - if (e.type === null) { return; } - - e.sentenceOffset = this._getSentenceOffset(e.textSource); - this.trigger('searched', e); + const { + textScanner, + type, + dictionaryEntries, + sentence, + inputInfo, + textSource, + optionsContext + } = e; + if (type === null || dictionaryEntries === null || sentence === null || optionsContext === null) { return; } + + /** @type {import('display').QueryParserSearchedEvent} */ + const event2 = { + textScanner, + type, + dictionaryEntries, + sentence, + inputInfo, + textSource, + optionsContext, + sentenceOffset: this._getSentenceOffset(e.textSource) + }; + this.trigger('searched', event2); } + /** + * @param {Event} e + */ _onParserChange(e) { - const value = e.currentTarget.value; + const element = /** @type {HTMLInputElement} */ (e.currentTarget); + const value = element.value; this._setSelectedParser(value); } + /** + * @returns {import('settings').OptionsContext} + */ _getOptionsContext() { return this._getSearchContext().optionsContext; } + /** */ _refreshSelectedParser() { if (this._parseResults.length > 0 && !this._getParseResult()) { const value = this._parseResults[0].id; @@ -137,22 +197,33 @@ export class QueryParser extends EventDispatcher { } } + /** + * @param {string} value + */ _setSelectedParser(value) { const optionsContext = this._getOptionsContext(); - yomitan.api.modifySettings([{ + /** @type {import('settings-modifications').ScopedModificationSet} */ + const modification = { action: 'set', path: 'parsing.selectedParser', value, scope: 'profile', optionsContext - }], 'search'); + }; + yomitan.api.modifySettings([modification], 'search'); } + /** + * @returns {import('api').ParseTextResultItem|undefined} + */ _getParseResult() { const selectedParser = this._selectedParser; return this._parseResults.find((r) => r.id === selectedParser); } + /** + * @param {string} text + */ _setPreview(text) { const terms = [[{text, reading: ''}]]; this._queryParser.textContent = ''; @@ -160,6 +231,7 @@ export class QueryParser extends EventDispatcher { this._queryParser.appendChild(this._createParseResult(terms)); } + /** */ _renderParserSelect() { const visible = (this._parseResults.length > 1); if (visible) { @@ -168,6 +240,7 @@ export class QueryParser extends EventDispatcher { this._queryParserModeContainer.hidden = !visible; } + /** */ _renderParseResult() { const parseResult = this._getParseResult(); this._queryParser.textContent = ''; @@ -176,6 +249,11 @@ export class QueryParser extends EventDispatcher { this._queryParser.appendChild(this._createParseResult(parseResult.content)); } + /** + * @param {HTMLSelectElement} select + * @param {import('api').ParseTextResult} parseResults + * @param {?string} selectedParser + */ _updateParserModeSelect(select, parseResults, selectedParser) { const fragment = document.createDocumentFragment(); @@ -208,6 +286,10 @@ export class QueryParser extends EventDispatcher { select.selectedIndex = selectedIndex; } + /** + * @param {import('api').ParseTextLine[]} data + * @returns {DocumentFragment} + */ _createParseResult(data) { let offset = 0; const fragment = document.createDocumentFragment(); @@ -229,6 +311,12 @@ export class QueryParser extends EventDispatcher { return fragment; } + /** + * @param {string} text + * @param {string} reading + * @param {number} offset + * @returns {HTMLElement} + */ _createSegment(text, reading, offset) { const segmentNode = document.createElement('ruby'); segmentNode.className = 'query-parser-segment'; @@ -249,6 +337,11 @@ export class QueryParser extends EventDispatcher { return segmentNode; } + /** + * @param {string} term + * @param {string} reading + * @returns {string} + */ _convertReading(term, reading) { switch (this._readingMode) { case 'hiragana': @@ -271,11 +364,15 @@ export class QueryParser extends EventDispatcher { } } + /** + * @param {import('text-source').TextSource} textSource + * @returns {?number} + */ _getSentenceOffset(textSource) { if (textSource.type === 'range') { const {range} = textSource; const node = this._getParentElement(range.startContainer); - if (node !== null) { + if (node !== null && node instanceof HTMLElement) { const {offset} = node.dataset; if (typeof offset === 'string') { const value = Number.parseInt(offset, 10); @@ -288,12 +385,16 @@ export class QueryParser extends EventDispatcher { return null; } + /** + * @param {?Node} node + * @returns {?Element} + */ _getParentElement(node) { const {ELEMENT_NODE} = Node; while (true) { - node = node.parentNode; if (node === null) { return null; } - if (node.nodeType === ELEMENT_NODE) { return node; } + if (node.nodeType === ELEMENT_NODE) { return /** @type {Element} */ (node); } + node = node.parentNode; } } } -- cgit v1.2.3 From ac562ca36417f2d9fdb860d1f8a879fdccde438d Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 15:16:07 -0500 Subject: Update types --- .vscode/settings.json | 2 +- ext/js/data/anki-note-builder.js | 4 ++-- ext/js/data/options-util.js | 7 +++++++ ext/js/data/sandbox/anki-note-data-creator.js | 4 ++-- ext/js/display/display-anki.js | 14 +++++++------- ext/js/display/display-audio.js | 4 ++-- ext/js/display/display-content-manager.js | 4 ++-- ext/js/display/display-generator.js | 6 +++--- ext/js/display/display-profile-selection.js | 4 ++-- ext/js/display/display-resizer.js | 4 ++-- ext/js/display/display.js | 18 +++++++++--------- ext/js/display/option-toggle-hotkey-handler.js | 7 ++++--- ext/js/display/query-parser.js | 2 +- ext/js/display/sandbox/pronunciation-generator.js | 4 ++-- ext/js/display/sandbox/structured-content-generator.js | 8 ++++---- ext/js/display/search-display-controller.js | 14 +++++++------- 16 files changed, 57 insertions(+), 49 deletions(-) (limited to 'ext/js/display/query-parser.js') diff --git a/.vscode/settings.json b/.vscode/settings.json index 81cd7b9c..734f6360 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,7 +2,7 @@ "markdown.extension.toc.levels": "1..3", "editor.codeActionsOnSave": { "source.addMissingImports": false, - "source.organizeImports": true, + "source.organizeImports": false, "source.fixAll.eslint": false }, "eslint.format.enable": true, diff --git a/ext/js/data/anki-note-builder.js b/ext/js/data/anki-note-builder.js index 28809e1f..4920db39 100644 --- a/ext/js/data/anki-note-builder.js +++ b/ext/js/data/anki-note-builder.js @@ -24,10 +24,10 @@ import {AnkiUtil} from './anki-util.js'; export class AnkiNoteBuilder { /** - * @param {{japaneseUtil: JapaneseUtil}} details + * @param {{japaneseUtil: import('../language/sandbox/japanese-util.js').JapaneseUtil}} details */ constructor({japaneseUtil}) { - /** @type {JapaneseUtil} */ + /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; /** @type {RegExp} */ this._markerPattern = AnkiUtil.cloneFieldMarkerPattern(true); diff --git a/ext/js/data/options-util.js b/ext/js/data/options-util.js index e8723f1f..70c1622f 100644 --- a/ext/js/data/options-util.js +++ b/ext/js/data/options-util.js @@ -1144,6 +1144,9 @@ export class OptionsUtil { return options; } + /** + * @type {import('options-util').ModernUpdateFunctionAsync} + */ async _updateVersion21(options) { await this._applyAnkiFieldTemplatesPatch(options, '/data/templates/anki-field-templates-upgrade-v21.handlebars'); @@ -1163,6 +1166,10 @@ export class OptionsUtil { return options; } + /** + * @param {string} url + * @returns {Promise} + */ _createTab(url) { return new Promise((resolve, reject) => { chrome.tabs.create({url}, (tab) => { diff --git a/ext/js/data/sandbox/anki-note-data-creator.js b/ext/js/data/sandbox/anki-note-data-creator.js index 821d4024..dce71938 100644 --- a/ext/js/data/sandbox/anki-note-data-creator.js +++ b/ext/js/data/sandbox/anki-note-data-creator.js @@ -25,10 +25,10 @@ import {DictionaryDataUtil} from '../../language/sandbox/dictionary-data-util.js export class AnkiNoteDataCreator { /** * Creates a new instance. - * @param {JapaneseUtil} japaneseUtil An instance of `JapaneseUtil`. + * @param {import('../../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil An instance of `JapaneseUtil`. */ constructor(japaneseUtil) { - /** @type {JapaneseUtil} */ + /** @type {import('../../language/sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; } diff --git a/ext/js/display/display-anki.js b/ext/js/display/display-anki.js index c0173697..d0da568c 100644 --- a/ext/js/display/display-anki.js +++ b/ext/js/display/display-anki.js @@ -24,14 +24,14 @@ import {yomitan} from '../yomitan.js'; export class DisplayAnki { /** - * @param {Display} display - * @param {DisplayAudio} displayAudio - * @param {JapaneseUtil} japaneseUtil + * @param {import('./display.js').Display} display + * @param {import('./display-audio.js').DisplayAudio} displayAudio + * @param {import('../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil */ constructor(display, displayAudio, japaneseUtil) { - /** @type {Display} */ + /** @type {import('./display.js').Display} */ this._display = display; - /** @type {DisplayAudio} */ + /** @type {import('./display-audio.js').DisplayAudio} */ this._displayAudio = displayAudio; /** @type {?string} */ this._ankiFieldTemplates = null; @@ -39,11 +39,11 @@ export class DisplayAnki { this._ankiFieldTemplatesDefault = null; /** @type {AnkiNoteBuilder} */ this._ankiNoteBuilder = new AnkiNoteBuilder({japaneseUtil}); - /** @type {?DisplayNotification} */ + /** @type {?import('./display-notification.js').DisplayNotification} */ this._errorNotification = null; /** @type {?EventListenerCollection} */ this._errorNotificationEventListeners = null; - /** @type {?DisplayNotification} */ + /** @type {?import('./display-notification.js').DisplayNotification} */ this._tagsNotification = null; /** @type {?Promise} */ this._updateAdderButtonsPromise = null; diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js index 8d917e81..3fbfc3c8 100644 --- a/ext/js/display/display-audio.js +++ b/ext/js/display/display-audio.js @@ -23,10 +23,10 @@ import {yomitan} from '../yomitan.js'; export class DisplayAudio { /** - * @param {Display} display + * @param {import('./display.js').Display} display */ constructor(display) { - /** @type {Display} */ + /** @type {import('./display.js').Display} */ this._display = display; /** @type {?import('display-audio').GenericAudio} */ this._audioPlaying = null; diff --git a/ext/js/display/display-content-manager.js b/ext/js/display/display-content-manager.js index fa8ad0fa..c78ef7e8 100644 --- a/ext/js/display/display-content-manager.js +++ b/ext/js/display/display-content-manager.js @@ -26,10 +26,10 @@ import {yomitan} from '../yomitan.js'; export class DisplayContentManager { /** * Creates a new instance of the class. - * @param {Display} display The display instance that owns this object. + * @param {import('./display.js').Display} display The display instance that owns this object. */ constructor(display) { - /** @type {Display} */ + /** @type {import('./display.js').Display} */ this._display = display; /** @type {import('core').TokenObject} */ this._token = {}; diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js index e8be79d9..eb464001 100644 --- a/ext/js/display/display-generator.js +++ b/ext/js/display/display-generator.js @@ -29,11 +29,11 @@ export class DisplayGenerator { * @param {import('display').DisplayGeneratorConstructorDetails} details */ constructor({japaneseUtil, contentManager, hotkeyHelpController=null}) { - /** @type {JapaneseUtil} */ + /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; - /** @type {DisplayContentManager} */ + /** @type {import('./display-content-manager.js').DisplayContentManager} */ this._contentManager = contentManager; - /** @type {?HotkeyHelpController} */ + /** @type {?import('../input/hotkey-help-controller.js').HotkeyHelpController} */ this._hotkeyHelpController = hotkeyHelpController; /** @type {HtmlTemplateCollection} */ this._templates = new HtmlTemplateCollection(); diff --git a/ext/js/display/display-profile-selection.js b/ext/js/display/display-profile-selection.js index 619d07aa..c5cb7d06 100644 --- a/ext/js/display/display-profile-selection.js +++ b/ext/js/display/display-profile-selection.js @@ -22,10 +22,10 @@ import {yomitan} from '../yomitan.js'; export class DisplayProfileSelection { /** - * @param {Display} display + * @param {import('./display.js').Display} display */ constructor(display) { - /** @type {Display} */ + /** @type {import('./display.js').Display} */ this._display = display; /** @type {HTMLElement} */ this._profielList = /** @type {HTMLElement} */ (document.querySelector('#profile-list')); diff --git a/ext/js/display/display-resizer.js b/ext/js/display/display-resizer.js index 6280286d..8ce7e91a 100644 --- a/ext/js/display/display-resizer.js +++ b/ext/js/display/display-resizer.js @@ -20,10 +20,10 @@ import {EventListenerCollection} from '../core.js'; export class DisplayResizer { /** - * @param {Display} display + * @param {import('./display.js').Display} display */ constructor(display) { - /** @type {Display} */ + /** @type {import('./display.js').Display} */ this._display = display; /** @type {?import('core').TokenObject} */ this._token = null; diff --git a/ext/js/display/display.js b/ext/js/display/display.js index f9c36a67..f14291d1 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -43,9 +43,9 @@ export class Display extends EventDispatcher { * @param {number|undefined} tabId * @param {number|undefined} frameId * @param {import('display').DisplayPageType} pageType - * @param {JapaneseUtil} japaneseUtil - * @param {DocumentFocusController} documentFocusController - * @param {HotkeyHandler} hotkeyHandler + * @param {import('../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil + * @param {import('../dom/document-focus-controller.js').DocumentFocusController} documentFocusController + * @param {import('../input/hotkey-handler.js').HotkeyHandler} hotkeyHandler */ constructor(tabId, frameId, pageType, japaneseUtil, documentFocusController, hotkeyHandler) { super(); @@ -55,11 +55,11 @@ export class Display extends EventDispatcher { this._frameId = frameId; /** @type {import('display').DisplayPageType} */ this._pageType = pageType; - /** @type {JapaneseUtil} */ + /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; - /** @type {DocumentFocusController} */ + /** @type {import('../dom/document-focus-controller.js').DocumentFocusController} */ this._documentFocusController = documentFocusController; - /** @type {HotkeyHandler} */ + /** @type {import('../input/hotkey-handler.js').HotkeyHandler} */ this._hotkeyHandler = hotkeyHandler; /** @type {HTMLElement} */ this._container = /** @type {HTMLElement} */ (document.querySelector('#dictionary-entries')); @@ -168,7 +168,7 @@ export class Display extends EventDispatcher { this._copyTextarea = null; /** @type {?TextScanner} */ this._contentTextScanner = null; - /** @type {?DisplayNotification} */ + /** @type {?import('./display-notification.js').DisplayNotification} */ this._tagNotification = null; /** @type {HTMLElement} */ this._footerNotificationContainer = /** @type {HTMLElement} */ (document.querySelector('#content-footer')); @@ -235,7 +235,7 @@ export class Display extends EventDispatcher { this._updateQueryParser(); } - /** @type {JapaneseUtil} */ + /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ get japaneseUtil() { return this._japaneseUtil; } @@ -245,7 +245,7 @@ export class Display extends EventDispatcher { return this._depth; } - /** @type {HotkeyHandler} */ + /** @type {import('../input/hotkey-handler.js').HotkeyHandler} */ get hotkeyHandler() { return this._hotkeyHandler; } diff --git a/ext/js/display/option-toggle-hotkey-handler.js b/ext/js/display/option-toggle-hotkey-handler.js index 9677e86b..531e208d 100644 --- a/ext/js/display/option-toggle-hotkey-handler.js +++ b/ext/js/display/option-toggle-hotkey-handler.js @@ -16,17 +16,18 @@ * along with this program. If not, see . */ +import {generateId} from '../core.js'; import {ExtensionError} from '../core/extension-error.js'; import {yomitan} from '../yomitan.js'; export class OptionToggleHotkeyHandler { /** - * @param {Display} display + * @param {import('./display.js').Display} display */ constructor(display) { - /** @type {Display} */ + /** @type {import('./display.js').Display} */ this._display = display; - /** @type {?DisplayNotification} */ + /** @type {?import('./display-notification.js').DisplayNotification} */ this._notification = null; /** @type {?number} */ this._notificationHideTimer = null; diff --git a/ext/js/display/query-parser.js b/ext/js/display/query-parser.js index fd173bde..03b54fd5 100644 --- a/ext/js/display/query-parser.js +++ b/ext/js/display/query-parser.js @@ -31,7 +31,7 @@ export class QueryParser extends EventDispatcher { super(); /** @type {import('display').GetSearchContextCallback} */ this._getSearchContext = getSearchContext; - /** @type {JapaneseUtil} */ + /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; /** @type {string} */ this._text = ''; diff --git a/ext/js/display/sandbox/pronunciation-generator.js b/ext/js/display/sandbox/pronunciation-generator.js index eeedc574..d113485f 100644 --- a/ext/js/display/sandbox/pronunciation-generator.js +++ b/ext/js/display/sandbox/pronunciation-generator.js @@ -18,10 +18,10 @@ export class PronunciationGenerator { /** - * @param {JapaneseUtil} japaneseUtil + * @param {import('../../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil */ constructor(japaneseUtil) { - /** @type {JapaneseUtil} */ + /** @type {import('../../language/sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; } diff --git a/ext/js/display/sandbox/structured-content-generator.js b/ext/js/display/sandbox/structured-content-generator.js index af49b643..5a91b01c 100644 --- a/ext/js/display/sandbox/structured-content-generator.js +++ b/ext/js/display/sandbox/structured-content-generator.js @@ -18,14 +18,14 @@ export class StructuredContentGenerator { /** - * @param {DisplayContentManager|AnkiTemplateRendererContentManager} contentManager - * @param {JapaneseUtil} japaneseUtil + * @param {import('../../display/display-content-manager.js').DisplayContentManager|import('../../templates/sandbox/anki-template-renderer-content-manager.js').AnkiTemplateRendererContentManager} contentManager + * @param {import('../../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil * @param {Document} document */ constructor(contentManager, japaneseUtil, document) { - /** @type {DisplayContentManager|AnkiTemplateRendererContentManager} */ + /** @type {import('../../display/display-content-manager.js').DisplayContentManager|import('../../templates/sandbox/anki-template-renderer-content-manager.js').AnkiTemplateRendererContentManager} */ this._contentManager = contentManager; - /** @type {JapaneseUtil} */ + /** @type {import('../../language/sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; /** @type {Document} */ this._document = document; diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index 76e7bebe..a9bf2217 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -25,21 +25,21 @@ export class SearchDisplayController { /** * @param {number|undefined} tabId * @param {number|undefined} frameId - * @param {Display} display - * @param {DisplayAudio} displayAudio - * @param {JapaneseUtil} japaneseUtil - * @param {SearchPersistentStateController} searchPersistentStateController + * @param {import('./display.js').Display} display + * @param {import('./display-audio.js').DisplayAudio} displayAudio + * @param {import('../language/sandbox/japanese-util.js').JapaneseUtil} japaneseUtil + * @param {import('./search-persistent-state-controller.js').SearchPersistentStateController} searchPersistentStateController */ constructor(tabId, frameId, display, displayAudio, japaneseUtil, searchPersistentStateController) { /** @type {number|undefined} */ this._tabId = tabId; /** @type {number|undefined} */ this._frameId = frameId; - /** @type {Display} */ + /** @type {import('./display.js').Display} */ this._display = display; - /** @type {DisplayAudio} */ + /** @type {import('./display-audio.js').DisplayAudio} */ this._displayAudio = displayAudio; - /** @type {SearchPersistentStateController} */ + /** @type {import('./search-persistent-state-controller.js').SearchPersistentStateController} */ this._searchPersistentStateController = searchPersistentStateController; /** @type {HTMLButtonElement} */ this._searchButton = /** @type {HTMLButtonElement} */ (document.querySelector('#search-button')); -- cgit v1.2.3