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) --- types/ext/anki-controller.d.ts | 27 ++ types/ext/anki-note-builder.d.ts | 120 ++++++ .../anki-template-renderer-content-manager.d.ts | 28 ++ types/ext/anki-templates-internal.d.ts | 60 +++ types/ext/anki-templates.d.ts | 276 ++++++++++++ types/ext/anki.d.ts | 75 ++++ types/ext/api.d.ts | 460 ++++++++++++++++++++ types/ext/audio-controller.d.ts | 24 ++ types/ext/audio-downloader.d.ts | 44 ++ types/ext/audio-system.d.ts | 18 + types/ext/audio.d.ts | 20 + types/ext/backend.d.ts | 123 ++++++ types/ext/backup-controller.d.ts | 35 ++ types/ext/cache-map.d.ts | 23 + types/ext/clipboard-monitor.d.ts | 26 ++ types/ext/core.d.ts | 102 +++++ types/ext/cross-frame-api.d.ts | 54 +++ types/ext/css-style-applier.d.ts | 46 ++ types/ext/database.d.ts | 38 ++ types/ext/deinflector.d.ts | 41 ++ types/ext/dictionary-data-util.d.ts | 94 ++++ types/ext/dictionary-data.d.ts | 147 +++++++ types/ext/dictionary-database.d.ts | 240 +++++++++++ types/ext/dictionary-importer-media-loader.d.ts | 36 ++ types/ext/dictionary-importer.d.ts | 95 ++++ types/ext/dictionary-worker-handler.d.ts | 62 +++ types/ext/dictionary-worker-media-loader.d.ts | 26 ++ types/ext/dictionary-worker.d.ts | 73 ++++ types/ext/dictionary.d.ts | 477 +++++++++++++++++++++ types/ext/display-anki.d.ts | 58 +++ types/ext/display-audio.d.ts | 99 +++++ types/ext/display-content-manager.d.ts | 40 ++ types/ext/display-history.d.ts | 37 ++ types/ext/display.d.ts | 202 +++++++++ types/ext/document-util.d.ts | 53 +++ types/ext/dom-data-binder.d.ts | 98 +++++ types/ext/dynamic-loader.d.ts | 20 + types/ext/dynamic-property.d.ts | 22 + types/ext/environment.d.ts | 25 ++ types/ext/event-listener-collection.d.ts | 81 ++++ types/ext/extension.d.ts | 74 ++++ types/ext/frame-ancestry-handler.d.ts | 26 ++ types/ext/frame-client.d.ts | 35 ++ types/ext/frame-offset-forwarder.d.ts | 23 + types/ext/frontend.d.ts | 58 +++ types/ext/generic-setting-controller.d.ts | 101 +++++ types/ext/hotkey-handler.d.ts | 30 ++ types/ext/input.d.ts | 21 + types/ext/japanese-util.d.ts | 42 ++ types/ext/json-schema.d.ts | 75 ++++ types/ext/keyboard-mouse-input-field.d.ts | 25 ++ types/ext/keyboard-shortcut-controller.d.ts | 26 ++ types/ext/log.d.ts | 24 ++ types/ext/mecab.d.ts | 46 ++ types/ext/options-util.d.ts | 35 ++ types/ext/panel-element.d.ts | 39 ++ types/ext/popup-factory.d.ts | 32 ++ types/ext/popup-menu.d.ts | 39 ++ types/ext/popup.d.ts | 132 ++++++ types/ext/profile-conditions-ui.d.ts | 70 +++ types/ext/profile-conditions-util.d.ts | 38 ++ types/ext/request-builder.d.ts | 21 + types/ext/script-manager.d.ts | 56 +++ types/ext/selector-observer.d.ts | 55 +++ types/ext/settings-controller.d.ts | 51 +++ types/ext/settings-modifications.d.ts | 97 +++++ types/ext/settings.d.ts | 382 +++++++++++++++++ types/ext/simple-dom-parser.d.ts | 37 ++ types/ext/structured-content.d.ts | 205 +++++++++ types/ext/task-accumulator.d.ts | 21 + types/ext/template-patcher.d.ts | 24 ++ types/ext/template-renderer-frame-api.d.ts | 24 ++ types/ext/template-renderer.d.ts | 75 ++++ types/ext/text-scanner.d.ts | 185 ++++++++ types/ext/text-source.d.ts | 18 + types/ext/translation-internal.d.ts | 65 +++ types/ext/translation.d.ts | 171 ++++++++ types/ext/translator.d.ts | 83 ++++ 78 files changed, 6186 insertions(+) create mode 100644 types/ext/anki-controller.d.ts create mode 100644 types/ext/anki-note-builder.d.ts create mode 100644 types/ext/anki-template-renderer-content-manager.d.ts create mode 100644 types/ext/anki-templates-internal.d.ts create mode 100644 types/ext/anki-templates.d.ts create mode 100644 types/ext/anki.d.ts create mode 100644 types/ext/api.d.ts create mode 100644 types/ext/audio-controller.d.ts create mode 100644 types/ext/audio-downloader.d.ts create mode 100644 types/ext/audio-system.d.ts create mode 100644 types/ext/audio.d.ts create mode 100644 types/ext/backend.d.ts create mode 100644 types/ext/backup-controller.d.ts create mode 100644 types/ext/cache-map.d.ts create mode 100644 types/ext/clipboard-monitor.d.ts create mode 100644 types/ext/core.d.ts create mode 100644 types/ext/cross-frame-api.d.ts create mode 100644 types/ext/css-style-applier.d.ts create mode 100644 types/ext/database.d.ts create mode 100644 types/ext/deinflector.d.ts create mode 100644 types/ext/dictionary-data-util.d.ts create mode 100644 types/ext/dictionary-data.d.ts create mode 100644 types/ext/dictionary-database.d.ts create mode 100644 types/ext/dictionary-importer-media-loader.d.ts create mode 100644 types/ext/dictionary-importer.d.ts create mode 100644 types/ext/dictionary-worker-handler.d.ts create mode 100644 types/ext/dictionary-worker-media-loader.d.ts create mode 100644 types/ext/dictionary-worker.d.ts create mode 100644 types/ext/dictionary.d.ts create mode 100644 types/ext/display-anki.d.ts create mode 100644 types/ext/display-audio.d.ts create mode 100644 types/ext/display-content-manager.d.ts create mode 100644 types/ext/display-history.d.ts create mode 100644 types/ext/display.d.ts create mode 100644 types/ext/document-util.d.ts create mode 100644 types/ext/dom-data-binder.d.ts create mode 100644 types/ext/dynamic-loader.d.ts create mode 100644 types/ext/dynamic-property.d.ts create mode 100644 types/ext/environment.d.ts create mode 100644 types/ext/event-listener-collection.d.ts create mode 100644 types/ext/extension.d.ts create mode 100644 types/ext/frame-ancestry-handler.d.ts create mode 100644 types/ext/frame-client.d.ts create mode 100644 types/ext/frame-offset-forwarder.d.ts create mode 100644 types/ext/frontend.d.ts create mode 100644 types/ext/generic-setting-controller.d.ts create mode 100644 types/ext/hotkey-handler.d.ts create mode 100644 types/ext/input.d.ts create mode 100644 types/ext/japanese-util.d.ts create mode 100644 types/ext/json-schema.d.ts create mode 100644 types/ext/keyboard-mouse-input-field.d.ts create mode 100644 types/ext/keyboard-shortcut-controller.d.ts create mode 100644 types/ext/log.d.ts create mode 100644 types/ext/mecab.d.ts create mode 100644 types/ext/options-util.d.ts create mode 100644 types/ext/panel-element.d.ts create mode 100644 types/ext/popup-factory.d.ts create mode 100644 types/ext/popup-menu.d.ts create mode 100644 types/ext/popup.d.ts create mode 100644 types/ext/profile-conditions-ui.d.ts create mode 100644 types/ext/profile-conditions-util.d.ts create mode 100644 types/ext/request-builder.d.ts create mode 100644 types/ext/script-manager.d.ts create mode 100644 types/ext/selector-observer.d.ts create mode 100644 types/ext/settings-controller.d.ts create mode 100644 types/ext/settings-modifications.d.ts create mode 100644 types/ext/settings.d.ts create mode 100644 types/ext/simple-dom-parser.d.ts create mode 100644 types/ext/structured-content.d.ts create mode 100644 types/ext/task-accumulator.d.ts create mode 100644 types/ext/template-patcher.d.ts create mode 100644 types/ext/template-renderer-frame-api.d.ts create mode 100644 types/ext/template-renderer.d.ts create mode 100644 types/ext/text-scanner.d.ts create mode 100644 types/ext/text-source.d.ts create mode 100644 types/ext/translation-internal.d.ts create mode 100644 types/ext/translation.d.ts create mode 100644 types/ext/translator.d.ts (limited to 'types/ext') diff --git a/types/ext/anki-controller.d.ts b/types/ext/anki-controller.d.ts new file mode 100644 index 00000000..f9a3d646 --- /dev/null +++ b/types/ext/anki-controller.d.ts @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type AnkiData = { + deckNames: string[]; + modelNames: string[]; +}; + +export type FieldEntry = { + fieldName: string; + inputField: HTMLInputElement; + fieldNameContainerNode: HTMLElement; +}; diff --git a/types/ext/anki-note-builder.d.ts b/types/ext/anki-note-builder.d.ts new file mode 100644 index 00000000..fbcb9328 --- /dev/null +++ b/types/ext/anki-note-builder.d.ts @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Anki from './anki'; +import type * as AnkiTemplates from './anki-templates'; +import type * as AnkiTemplatesInternal from './anki-templates-internal'; +import type * as Audio from './audio'; +import type * as Dictionary from './dictionary'; +import type * as Extension from './extension'; +import type * as Settings from './settings'; +import type * as TemplateRenderer from './template-renderer'; + +export type CreateNoteDetails = { + dictionaryEntry: Dictionary.DictionaryEntry; + mode: AnkiTemplatesInternal.CreateMode; + context: AnkiTemplatesInternal.Context; + template: string; + deckName: string; + modelName: string; + fields: Field[]; + tags: string[]; + requirements: Requirement[]; + checkForDuplicates: boolean; + duplicateScope: Settings.AnkiDuplicateScope; + duplicateScopeCheckAllModels: boolean; + resultOutputMode: Settings.ResultOutputMode; + glossaryLayoutMode: Settings.GlossaryLayoutMode; + compactTags: boolean; + mediaOptions: MediaOptions | null; +}; + +export type Field = [ + name: string, + value: string, +]; + +export type CreateNoteResult = { + note: Anki.Note; + errors: Error[]; + requirements: Requirement[]; +}; + +export type GetRenderingDataDetails = { + dictionaryEntry: Dictionary.DictionaryEntry; + mode: AnkiTemplatesInternal.CreateMode; + context: AnkiTemplatesInternal.Context; + resultOutputMode?: Settings.ResultOutputMode; + glossaryLayoutMode?: Settings.GlossaryLayoutMode; + compactTags?: boolean; + marker: string; +}; + +export type CommonData = AnkiTemplatesInternal.CreateDetails; + +export type RequirementGeneric = { + type: 'audio' | 'screenshot' | 'clipboardImage' | 'clipboardText' | 'selectionText'; +}; + +export type RequirementTextFurigana = { + type: 'textFurigana'; + text: string; + readingMode: AnkiTemplates.TextFuriganaReadingMode; +}; + +export type RequirementDictionaryMedia = { + type: 'dictionaryMedia'; + dictionary: string; + path: string; +}; + +export type Requirement = RequirementGeneric | RequirementTextFurigana | RequirementDictionaryMedia; + +export type AudioMediaOptions = { + sources: Audio.AudioSourceInfo[]; + preferredAudioIndex: number | null; + idleTimeout: number | null; +}; + +export type MediaOptions = { + audio: AudioMediaOptions | null; + screenshot: { + format: Settings.AnkiScreenshotFormat; + quality: number; + contentOrigin: Extension.ContentOrigin; + }; + textParsing: { + optionsContext: Settings.OptionsContext; + scanLength: number; + }; +}; + +export type TextFuriganaDetails = { + text: string; + readingMode: AnkiTemplates.TextFuriganaReadingMode; +}; + +export type BatchedRequestGroup = { + template: string; + commonDataRequestsMap: Map; +}; + +export type BatchedRequestData = { + resolve: (result: TemplateRenderer.RenderResult) => void; + reject: (reason?: unknown) => void; + marker: string; +}; diff --git a/types/ext/anki-template-renderer-content-manager.d.ts b/types/ext/anki-template-renderer-content-manager.d.ts new file mode 100644 index 00000000..d7667ae2 --- /dev/null +++ b/types/ext/anki-template-renderer-content-manager.d.ts @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** A callback used when a media file has been loaded. */ +export type OnLoadCallback = ( + /** The URL of the media that was loaded. */ + url: string, +) => void; + +/** A callback used when a media file should be unloaded. */ +export type OnUnloadCallback = ( + /** Whether or not the media was fully loaded. */ + fullyLoaded: boolean, +) => void; diff --git a/types/ext/anki-templates-internal.d.ts b/types/ext/anki-templates-internal.d.ts new file mode 100644 index 00000000..4cb50050 --- /dev/null +++ b/types/ext/anki-templates-internal.d.ts @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as AnkiTemplates from './anki-templates'; +import type * as Dictionary from './dictionary'; +import type * as Settings from './settings'; + +export type Context = { + url: string; + documentTitle: string; + query: string; + fullQuery: string; + sentence: ContextSentence; +}; + +export type ContextSentence = { + text?: string; + offset?: number; +}; + +export type CreateModeNoTest = 'kanji' | 'term-kanji' | 'term-kana'; + +export type CreateMode = CreateModeNoTest | 'test'; + +export type CreateDetails = { + /** The dictionary entry. */ + dictionaryEntry: Dictionary.DictionaryEntry; + /** The result output mode. */ + resultOutputMode: Settings.ResultOutputMode; + /** The mode being used to generate the Anki data. */ + mode: CreateMode; + /** The glossary layout mode. */ + glossaryLayoutMode: Settings.GlossaryLayoutMode; + /** Whether or not compact tags mode is enabled. */ + compactTags: boolean; + /** Contextual information about the source of the dictionary entry. */ + context: Context; + /** Media data. */ + media?: AnkiTemplates.Media; +}; + +export type CachedValue = { + getter: () => T; + hasValue: boolean; + value: T | undefined; +}; diff --git a/types/ext/anki-templates.d.ts b/types/ext/anki-templates.d.ts new file mode 100644 index 00000000..c7e49905 --- /dev/null +++ b/types/ext/anki-templates.d.ts @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Dictionary from './dictionary'; +import type * as DictionaryData from './dictionary-data'; +import type * as DictionaryDataUtil from './dictionary-data-util'; + +export type RenderMode = 'ankiNote'; + +export type Context = { + query: string; + fullQuery: string; + document: {title: string}; +}; + +export type Media = { + audio?: MediaObject; + screenshot?: MediaObject; + clipboardImage?: MediaObject; + clipboardText?: MediaObject; + selectionText?: MediaObject; + textFurigana?: TextFuriganaSegment[]; + dictionaryMedia?: DictionaryMedia; +}; + +export type MediaObject = {value: string}; + +export type MediaSimpleType = ( + 'audio' | + 'screenshot' | + 'clipboardImage' | + 'clipboardText' | + 'selectionText' +); + +export type MediaType = ( + MediaSimpleType | + 'textFurigana' | + 'dictionaryMedia' +); + +export type TextFuriganaSegment = { + text: string; + readingMode: TextFuriganaReadingMode; + details: MediaObject; +}; + +export type TextFuriganaReadingMode = 'hiragana' | 'katakana' | null; + +export type DictionaryMedia = { + [dictionary: string]: { + [path: string]: MediaObject; + }; +}; + +export type NoteData = { + marker: string; + readonly definition: DictionaryEntry; + glossaryLayoutMode: string; + compactTags: boolean; + group: boolean; + merge: boolean; + modeTermKanji: boolean; + modeTermKana: boolean; + modeKanji: boolean; + compactGlossaries: boolean; + readonly uniqueExpressions: string[]; + readonly uniqueReadings: string[]; + readonly pitches: PitchGroup[]; + readonly pitchCount: number; + readonly context: Context; + media: Media; + readonly dictionaryEntry: Dictionary.DictionaryEntry; +}; + +export type PitchGroup = { + dictionary: string; + pitches: Pitch[]; +}; + +export type Pitch = { + expressions: string[]; + reading: string; + position: number; + nasalPositions: number[]; + devoicePositions: number[]; + tags: PitchTag[]; + exclusiveExpressions: string[]; + exclusiveReadings: string[]; +}; + +/** + * For legacy reasons, {@link Pitch} has a custom tag type that resembles {@link Dictionary.Tag}. + */ +export type PitchTag = { + name: string; + category: string; + order: number; + score: number; + content: string[]; + dictionaries: string[]; + redundant: boolean; +}; + +export type KanjiDictionaryEntry = { + type: 'kanji'; + character: string; + dictionary: string; + onyomi: string[]; + kunyomi: string[]; + glossary: string[]; + readonly tags: Tag[]; + readonly stats: KanjiStatGroups; + readonly frequencies: KanjiFrequency[]; + url: string; + readonly cloze: Cloze; +}; + +export type KanjiStatGroups = { + [propName: string]: KanjiStat[]; +}; + +export type KanjiStat = { + name: string; + category: string; + notes: string; + order: number; + score: number; + dictionary: string; + value: number | string; +}; + +export type KanjiFrequency = { + index: number; + dictionary: string; + dictionaryOrder: { + index: number; + priority: number; + }; + character: string; + frequency: number | string; +}; + +export type TermDictionaryEntryType = 'term' | 'termGrouped' | 'termMerged'; + +export type TermDictionaryEntry = { + type: TermDictionaryEntryType; + id?: number; + source: string | null; + rawSource: string | null; + sourceTerm?: string | null; + reasons: string[]; + score: number; + isPrimary?: boolean; + readonly sequence: number; + readonly dictionary: string; + dictionaryOrder: { + index: number; + priority: number; + }; + readonly dictionaryNames: string[]; + readonly expression: string | string[]; + readonly reading: string | string[]; + readonly expressions: TermHeadword[]; + readonly glossary?: DictionaryData.TermGlossary[]; + readonly definitionTags?: Tag[]; + readonly termTags?: Tag[]; + readonly definitions?: TermDefinition[]; + readonly frequencies: TermFrequency[]; + readonly pitches: TermPronunciation[]; + sourceTermExactMatchCount: number; + url: string; + readonly cloze: Cloze; + readonly furiganaSegments?: FuriganaSegment[]; +}; + +export type TermDictionaryEntryCommonInfo = { + uniqueTerms: string[]; + uniqueReadings: string[]; + definitionTags: Tag[]; + definitions?: TermDefinition[]; +}; + +export type UnknownDictionaryEntry = Record; + +export type DictionaryEntry = KanjiDictionaryEntry | TermDictionaryEntry | UnknownDictionaryEntry; + +export type Tag = { + name: string; + category: string; + order: number; + score: number; + notes: string; + dictionary: string; + redundant: boolean; +}; + +export type TermDefinition = { + sequence: number; + dictionary: string; + glossary: DictionaryData.TermGlossary[]; + definitionTags: Tag[]; + only?: string[]; +}; + +export type TermFrequency = { + index: number; + expressionIndex: number; + dictionary: string; + dictionaryOrder: { + index: number; + priority: number; + }; + expression: string; + reading: string; + hasReading: boolean; + frequency: number | string; +}; + +export type TermPronunciation = { + index: number; + expressionIndex: number; + dictionary: string; + dictionaryOrder: { + index: number; + priority: number; + }; + expression: string; + reading: string; + readonly pitches: TermPitch[]; +}; + +export type TermPitch = { + position: number; + tags: Tag[]; +}; + +export type TermFrequencyType = DictionaryDataUtil.TermFrequencyType; + +export type TermHeadword = { + sourceTerm: string; + expression: string; + reading: string; + readonly termTags: Tag[]; + readonly frequencies: TermFrequency[]; + readonly pitches: TermPronunciation[]; + readonly furiganaSegments: FuriganaSegment[]; + readonly termFrequency: TermFrequencyType; + wordClasses: string[]; +}; + +export type FuriganaSegment = { + text: string; + furigana: string; +}; + +export type Cloze = { + sentence: string; + prefix: string; + body: string; + suffix: string; +}; diff --git a/types/ext/anki.d.ts b/types/ext/anki.d.ts new file mode 100644 index 00000000..051cd3e9 --- /dev/null +++ b/types/ext/anki.d.ts @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; +import type * as Settings from './settings'; + +export type NoteId = number; + +export type CardId = number; + +export type Note = { + fields: NoteFields; + tags: string[]; + deckName: string; + modelName: string; + options: { + allowDuplicate: boolean; + duplicateScope: Settings.AnkiDuplicateScope; + duplicateScopeOptions: { + deckName: string | null; + checkChildren: boolean; + checkAllModels: boolean; + }; + }; +}; + +export type NoteFields = { + [field: string]: string; +}; + +export type NoteInfoWrapper = { + canAdd: boolean; + valid: boolean; + noteIds: NoteId[] | null; + noteInfos?: (NoteInfo | null)[]; +}; + +export type NoteInfo = { + noteId: NoteId; + tags: string[]; + fields: {[key: string]: NoteFieldInfo}; + modelName: string; + cards: CardId[]; +}; + +export type NoteFieldInfo = { + value: string; + order: number; +}; + +export type ApiReflectResult = { + scopes: string[]; + actions: string[]; +}; + +export type MessageBody = { + action: string; + params: Core.SerializableObject; + version: number; + key?: string; +}; diff --git a/types/ext/api.d.ts b/types/ext/api.d.ts new file mode 100644 index 00000000..19a62c1c --- /dev/null +++ b/types/ext/api.d.ts @@ -0,0 +1,460 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Anki from './anki'; +import type * as AnkiNoteBuilder from './anki-note-builder'; +import type * as Audio from './audio'; +import type * as AudioDownloader from './audio-downloader'; +import type * as Backend from './backend'; +import type * as Core from './core'; +import type * as Dictionary from './dictionary'; +import type * as DictionaryDatabase from './dictionary-database'; +import type * as DictionaryImporter from './dictionary-importer'; +import type * as Environment from './environment'; +import type * as Extension from './extension'; +import type * as Log from './log'; +import type * as Settings from './settings'; +import type * as SettingsModifications from './settings-modifications'; +import type * as Translation from './translation'; +import type * as Translator from './translator'; + +// Generic + +export type Handler = ( + details: TDetails, + sender: (THasSender extends true ? chrome.runtime.MessageSender : void) +) => (TResult | Promise); + +// optionsGet + +export type OptionsGetDetails = { + optionsContext: Settings.OptionsContext; +}; + +export type OptionsGetResult = Settings.ProfileOptions; + +// optionsGetFull + +export type OptionsGetFullDetails = Record; + +export type OptionsGetFullResult = Settings.Options; + +// termsFind + +export type FindTermsDetails = { + matchType?: Translation.FindTermsMatchType; + deinflect?: boolean; +}; + +export type TermsFindDetails = { + text: string; + details: FindTermsDetails; + optionsContext: Settings.OptionsContext; +}; + +export type TermsFindResult = { + dictionaryEntries: Dictionary.TermDictionaryEntry[]; + originalTextLength: number; +}; + +// parseText + +export type ParseTextDetails = { + text: string; + optionsContext: Settings.OptionsContext; + scanLength: number; + useInternalParser: boolean; + useMecabParser: boolean; +}; + +export type ParseTextResult = ParseTextResultItem[]; + +export type ParseTextResultItem = { + id: string; + source: 'scanning-parser' | 'mecab'; + dictionary: null | string; + content: ParseTextLine[]; +}; + +export type ParseTextSegment = { + text: string; + reading: string; +}; + +export type ParseTextLine = ParseTextSegment[]; + +// kanjiFind + +export type KanjiFindDetails = { + text: string; + optionsContext: Settings.OptionsContext; +}; + +export type KanjiFindResult = Dictionary.KanjiDictionaryEntry[]; + +// isAnkiConnected + +export type IsAnkiConnectedDetails = Record; + +export type IsAnkiConnectedResult = boolean; + +// getAnkiConnectVersion + +export type GetAnkiConnectVersionDetails = Record; + +export type GetAnkiConnectVersionResult = number | null; + +// addAnkiNote + +export type AddAnkiNoteDetails = { + note: Anki.Note; +}; + +export type AddAnkiNoteResult = Anki.NoteId | null; + +// getAnkiNoteInfo + +export type GetAnkiNoteInfoDetails = { + notes: Anki.Note[]; + fetchAdditionalInfo: boolean; +}; + +export type GetAnkiNoteInfoResult = Anki.NoteInfoWrapper[]; + +// injectAnkiNoteMedia + +export type InjectAnkiNoteMediaDetails = { + timestamp: number; + definitionDetails: InjectAnkiNoteMediaDefinitionDetails; + audioDetails: InjectAnkiNoteMediaAudioDetails | null; + screenshotDetails: InjectAnkiNoteMediaScreenshotDetails | null; + clipboardDetails: InjectAnkiNoteMediaClipboardDetails | null; + dictionaryMediaDetails: InjectAnkiNoteMediaDictionaryMediaDetails[]; +}; + +export type InjectAnkiNoteMediaTermDefinitionDetails = { + type: 'term'; + term: string; + reading: string; +}; + +export type InjectAnkiNoteMediaKanjiDefinitionDetails = { + type: 'kanji'; + character: string; +}; + +export type InjectAnkiNoteMediaDefinitionDetails = InjectAnkiNoteMediaTermDefinitionDetails | InjectAnkiNoteMediaKanjiDefinitionDetails; + +export type InjectAnkiNoteMediaAudioDetails = AnkiNoteBuilder.AudioMediaOptions; + +export type InjectAnkiNoteMediaScreenshotDetails = { + tabId: number; + frameId: number; + format: Settings.AnkiScreenshotFormat; + quality: number; +}; + +export type InjectAnkiNoteMediaClipboardDetails = { + image: boolean; + text: boolean; +}; + +export type InjectAnkiNoteMediaDictionaryMediaDetails = { + dictionary: string; + path: string; +}; + +export type InjectAnkiNoteMediaResult = { + screenshotFileName: string | null; + clipboardImageFileName: string | null; + clipboardText: string | null; + audioFileName: string | null; + dictionaryMedia: InjectAnkiNoteDictionaryMediaResult[]; + errors: Core.SerializedError[]; +}; + +export type InjectAnkiNoteDictionaryMediaResult = { + dictionary: string; + path: string; + fileName: string | null; +}; + +// noteView + +export type NoteViewDetails = { + noteId: Anki.NoteId; + mode: Settings.AnkiNoteGuiMode; + allowFallback: boolean; +}; + +export type NoteViewResult = Settings.AnkiNoteGuiMode; + +// suspendAnkiCardsForNote + +export type SuspendAnkiCardsForNoteDetails = { + noteId: Anki.NoteId; +}; + +export type SuspendAnkiCardsForNoteResult = number; + +// getTermAudioInfoList + +export type GetTermAudioInfoListDetails = { + source: Audio.AudioSourceInfo; + term: string; + reading: string; +}; + +export type GetTermAudioInfoListResult = AudioDownloader.Info[]; + +// commandExec + +export type CommandExecDetails = { + command: string; + params?: Core.SerializableObject; +}; + +export type CommandExecResult = boolean; + +// sendMessageToFrame + +export type SendMessageToFrameDetails = { + frameId: number; + action: string; + params?: Core.SerializableObject; +}; + +export type SendMessageToFrameResult = boolean; + +// broadcastTab + +export type BroadcastTabDetails = { + action: string; + params?: Core.SerializableObject; +}; + +export type BroadcastTabResult = boolean; + +// frameInformationGet + +export type FrameInformationGetDetails = Record; + +export type FrameInformationGetResult = Extension.ContentOrigin; + +// injectStylesheet + +export type InjectStylesheetDetails = { + type: 'file' | 'code'; + value: string; +}; + +export type InjectStylesheetResult = void; + +// getStylesheetContent + +export type GetStylesheetContentDetails = { + url: string; +}; + +export type GetStylesheetContentResult = string; + +// getEnvironmentInfo + +export type GetEnvironmentInfoDetails = Record; + +export type GetEnvironmentInfoResult = Environment.Info; + +// clipboardGet + +export type ClipboardGetDetails = Record; + +export type ClipboardGetResult = string; + +// getDisplayTemplatesHtml + +export type GetDisplayTemplatesHtmlDetails = Record; + +export type GetDisplayTemplatesHtmlResult = string; + +// getZoom + +export type GetZoomDetails = Record; + +export type GetZoomResult = { + zoomFactor: number; +}; + +// getDefaultAnkiFieldTemplates + +export type GetDefaultAnkiFieldTemplatesDetails = Record; + +export type GetDefaultAnkiFieldTemplatesResult = string; + +// getDictionaryInfo + +export type GetDictionaryInfoDetails = Record; + +export type GetDictionaryInfoResult = DictionaryImporter.Summary[]; + +// purgeDatabase + +export type PurgeDatabaseDetails = Record; + +export type PurgeDatabaseResult = void; + +// getMedia + +export type GetMediaDetails = { + targets: GetMediaDetailsTarget[]; +}; + +export type GetMediaDetailsTarget = { + path: string; + dictionary: string; +}; + +export type GetMediaResult = DictionaryDatabase.MediaDataStringContent[]; + +// log + +export type LogDetails = { + error: Core.SerializedError; + level: Log.LogLevel; + context: Log.LogContext | undefined; +}; + +export type LogResult = void; + +// logIndicatorClear + +export type LogIndicatorClearDetails = Record; + +export type LogIndicatorClearResult = void; + +// modifySettings + +export type ModifySettingsDetails = { + targets: SettingsModifications.ScopedModification[]; + source: string; +}; + +export type ModifySettingsResult = Core.Response[]; + +// getSettings + +export type GetSettingsDetails = { + targets: SettingsModifications.ScopedRead[]; +}; + +export type GetSettingsResult = Core.Response[]; + +// setAllSettings + +export type SetAllSettingsDetails = { + value: Settings.Options; + source: string; +}; + +export type SetAllSettingsResult = void; + +// getOrCreateSearchPopup + +export type GetOrCreateSearchPopupDetails = { + focus?: boolean | 'ifCreated'; + text?: string; +}; + +export type GetOrCreateSearchPopupResult = { + tabId: number | null; + windowId: number; +}; + +// isTabSearchPopup + +export type IsTabSearchPopupDetails = { + tabId: number; +}; + +export type IsTabSearchPopupResult = boolean; + +// triggerDatabaseUpdated + +export type TriggerDatabaseUpdatedDetails = { + type: Backend.DatabaseUpdateType; + cause: Backend.DatabaseUpdateCause; +}; + +export type TriggerDatabaseUpdatedResult = void; + +// testMecab + +export type TestMecabDetails = Record; + +export type TestMecabResult = true; + +// textHasJapaneseCharacters + +export type TextHasJapaneseCharactersDetails = { + text: string; +}; + +export type TextHasJapaneseCharactersResult = boolean; + +// getTermFrequencies + +export type GetTermFrequenciesDetails = { + termReadingList: GetTermFrequenciesDetailsTermReadingListItem[]; + dictionaries: string[]; +}; + +export type GetTermFrequenciesDetailsTermReadingListItem = { + term: string; + reading: string | null; +}; + +export type GetTermFrequenciesResult = Translator.TermFrequencySimple[]; + +// findAnkiNotes + +export type FindAnkiNotesDetails = { + query: string; +}; + +export type FindAnkiNotesResult = Anki.NoteId[]; + +// loadExtensionScripts + +export type LoadExtensionScriptsDetails = { + files: string[]; +}; + +export type LoadExtensionScriptsResult = void; + +// requestBackendReadySignal + +export type RequestBackendReadySignalDetails = Record; + +export type RequestBackendReadySignalResult = boolean; + +// createActionPort + +export type CreateActionPortDetails = Record; + +export type CreateActionPortResult = { + name: string; + id: string; +}; diff --git a/types/ext/audio-controller.d.ts b/types/ext/audio-controller.d.ts new file mode 100644 index 00000000..e8317aaf --- /dev/null +++ b/types/ext/audio-controller.d.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type EventType = 'voicesUpdated'; + +export type VoiceInfo = { + voice: SpeechSynthesisVoice; + isJapanese: boolean; + index: number; +}; diff --git a/types/ext/audio-downloader.d.ts b/types/ext/audio-downloader.d.ts new file mode 100644 index 00000000..b8e812f8 --- /dev/null +++ b/types/ext/audio-downloader.d.ts @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Audio from './audio'; + +export type GetInfoHandler = ( + term: string, + reading: string, + details?: Audio.AudioSourceInfo, +) => Promise; + +export type Info = Info1 | Info2; + +export type Info1 = { + type: 'url'; + url: string; + name?: string; +}; + +export type Info2 = { + type: 'tts'; + text: string; + voice: string; + name?: undefined; +}; + +export type AudioBinaryBase64 = { + data: string; + contentType: string | null; +}; diff --git a/types/ext/audio-system.d.ts b/types/ext/audio-system.d.ts new file mode 100644 index 00000000..e9766ed1 --- /dev/null +++ b/types/ext/audio-system.d.ts @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type EventType = 'voiceschanged'; diff --git a/types/ext/audio.d.ts b/types/ext/audio.d.ts new file mode 100644 index 00000000..4bf952c6 --- /dev/null +++ b/types/ext/audio.d.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as DisplayAudio from './display-audio'; + +export type AudioSourceInfo = DisplayAudio.AudioSourceShort; diff --git a/types/ext/backend.d.ts b/types/ext/backend.d.ts new file mode 100644 index 00000000..5f1bd83d --- /dev/null +++ b/types/ext/backend.d.ts @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Api from './api'; +import type * as Core from './core'; + +export type MessageHandlerDetails = { + async: boolean; + contentScript: boolean; + handler: (params: Core.SerializableObject | undefined, sender: chrome.runtime.MessageSender) => unknown; +}; +export type MessageHandlerMap = Map; +export type MessageHandlerMapInit = [key: string, handlerDetails: MessageHandlerDetails][]; + +export type MessageHandlerWithProgressDetails = { + async: boolean; + contentScript: boolean; + handler: (params: Core.SerializableObject | undefined, sender: chrome.runtime.MessageSender, onProgress: (...data: unknown[]) => void) => (Promise | unknown); +}; +export type MessageHandlerWithProgressMap = Map; +export type MessageHandlerWithProgressMapInit = [key: string, handlerDetails: MessageHandlerWithProgressDetails][]; + +export type DatabaseUpdateType = 'dictionary'; +export type DatabaseUpdateCause = 'purge' | 'delete' | 'import'; + +export type MecabParseResults = [ + dictionary: string, + content: Api.ParseTextLine[], +][]; + +export type TabInfo = { + tab: chrome.tabs.Tab; + url: string | null; +}; + +export type SettingModification = SettingModificationSet | SettingModificationDelete | SettingModificationSwap | SettingModificationSplice | SettingModificationPush; + +export type SettingModificationSet = { + action: 'set'; + path: string; + value: unknown; +}; + +export type SettingModificationDelete = { + action: 'delete'; + path: string; +}; + +export type SettingModificationSwap = { + action: 'swap'; + path1: string; + path2: string; +}; + +export type SettingModificationSplice = { + action: 'splice'; + path: string; + start: number; + deleteCount: number; + items: unknown[]; +}; + +export type SettingModificationPush = { + action: 'push'; + path: string; + items: unknown[]; +}; + +export type FindTabsPredicate = (tabInfo: TabInfo) => boolean | Promise; + +export type InvokeWithProgressRequestMessage = ( + InvokeWithProgressRequestFragmentMessage | + InvokeWithProgressRequestInvokeMessage +); + +export type InvokeWithProgressRequestFragmentMessage = { + action: 'fragment'; + data: string; +}; + +export type InvokeWithProgressRequestInvokeMessage = { + action: 'invoke'; +}; + +export type InvokeWithProgressResponseMessage = ( + InvokeWithProgressResponseProgressMessage | + InvokeWithProgressResponseCompleteMessage | + InvokeWithProgressResponseErrorMessage | + InvokeWithProgressResponseAcknowledgeMessage +); + +export type InvokeWithProgressResponseProgressMessage = { + type: 'progress'; + data: unknown[]; +}; + +export type InvokeWithProgressResponseCompleteMessage = { + type: 'complete'; + data: TReturn; +}; + +export type InvokeWithProgressResponseErrorMessage = { + type: 'error'; + data: Core.SerializedError; +}; + +export type InvokeWithProgressResponseAcknowledgeMessage = { + type: 'ack'; +}; diff --git a/types/ext/backup-controller.d.ts b/types/ext/backup-controller.d.ts new file mode 100644 index 00000000..d494ceb9 --- /dev/null +++ b/types/ext/backup-controller.d.ts @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Environment from './environment'; +import type * as Settings from './settings'; + +export type BackupData = { + version: number; + date: string; + url: string; + manifest: chrome.runtime.Manifest; + environment: Environment.Info; + userAgent: string; + permissions: chrome.permissions.Permissions; + options: Settings.Options; +}; + +export type ShowSettingsImportWarningsResult = { + result: boolean; + sanitize?: boolean; +}; diff --git a/types/ext/cache-map.d.ts b/types/ext/cache-map.d.ts new file mode 100644 index 00000000..a4b8bb1a --- /dev/null +++ b/types/ext/cache-map.d.ts @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export interface Node { + key: K | null; + value: V | null; + previous: Node | null; + next: Node | null; +} diff --git a/types/ext/clipboard-monitor.d.ts b/types/ext/clipboard-monitor.d.ts new file mode 100644 index 00000000..f8cf7d02 --- /dev/null +++ b/types/ext/clipboard-monitor.d.ts @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type EventType = 'change'; + +export type ChangeEvent = { + text: string; +}; + +export type ClipboardReaderLike = { + getText: (useRichText: boolean) => Promise; +}; diff --git a/types/ext/core.d.ts b/types/ext/core.d.ts new file mode 100644 index 00000000..ce3a09f0 --- /dev/null +++ b/types/ext/core.d.ts @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type TypeofResult = 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function'; + +/** This type is used as an explicit way of permitting the `any` type. */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type SafeAny = any; + +/** This type is used as an explicit way of permitting the `Function` type. */ +// eslint-disable-next-line @typescript-eslint/ban-types +export type SafeFunction = Function; + +/** This type is used as an explicit way of permitting the `any` type. */ +export type RejectionReason = SafeAny; + +/** This type is used as an explicit way of permitting the `object` type. */ +export type SerializableObject = {[key: string]: unknown}; + +/** This type is used as an explicit way of permitting the `object` type. */ +export type SerializableObjectAny = {[key: string]: SafeAny}; + +/** This type is used as an explicit way of permitting the `object` type. */ +export type UnknownObject = {[key: string | symbol]: unknown}; + +export type TokenString = string; + +export type TokenObject = Record; + +export type DeferredPromiseDetails = { + promise: Promise; + resolve: (value: T) => void; + reject: (reason?: RejectionReason) => void; +}; + +export type SerializedError1 = { + name: string; + message: string; + stack: string; + data?: unknown; + hasValue?: undefined; +}; + +export type SerializedError2 = { + value: unknown; + hasValue: true; +}; + +export type SerializedError = SerializedError1 | SerializedError2; + +export type ResponseSuccess = { + result: T; + error?: undefined; +}; + +export type ResponseError = { + error: SerializedError; + result?: undefined; +}; + +export type Response = ResponseSuccess | ResponseError; + +export type MessageHandler = (params: SafeAny, ...extraArgs: SafeAny[]) => ( + SafeAny | + Promise | + MessageHandlerAsyncResult +); + +export type MessageHandlerAsyncResult = { + async: boolean; + result: SafeAny | Promise; +}; + +export type MessageHandlerDetails = { + /** + * Whether or not the handler is async or not. Values include `false`, `true`, or `'dynamic'`. + * When the value is `'dynamic'`, the handler should return an object of the format `{async: boolean, result: any}`. + */ + async: boolean | 'dynamic'; + /** + * A handler function which is passed `params` and `...extraArgs` as arguments. + */ + handler: MessageHandler; +}; + +export type MessageHandlerMap = Map; + +export type MessageHandlerArray = [key: string, handlerDetails: MessageHandlerDetails][]; diff --git a/types/ext/cross-frame-api.d.ts b/types/ext/cross-frame-api.d.ts new file mode 100644 index 00000000..5cedbec9 --- /dev/null +++ b/types/ext/cross-frame-api.d.ts @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; + +export type CrossFrameAPIPortEventType = 'disconnect'; + +export type AcknowledgeMessage = { + type: 'ack'; + id: number; +}; + +export type ResultMessage = { + type: 'result'; + id: number; + data: Core.Response; +}; + +export type InvokeMessage = { + type: 'invoke'; + id: number; + data: InvocationData; +}; + +export type InvocationData = { + action: string; + params: Core.SerializableObject; +}; + +export type Message = AcknowledgeMessage | ResultMessage | InvokeMessage; + +export type Invocation = { + id: number; + resolve: (value: Core.SafeAny) => void; + reject: (reason?: unknown) => void; + responseTimeout: number; + action: string; + ack: boolean; + timer: number | null; +}; diff --git a/types/ext/css-style-applier.d.ts b/types/ext/css-style-applier.d.ts new file mode 100644 index 00000000..d4db2da6 --- /dev/null +++ b/types/ext/css-style-applier.d.ts @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type RawStyleData = { + selectors: string[]; + styles: RawStyleDataStyleArray; +}[]; + +export type RawStyleDataStyleArray = [ + property: string, + value: string, +][]; + +/** + * A CSS rule. + */ +export type CssRule = { + /** A CSS selector string representing one or more selectors. */ + selectors: string; + /** A list of CSS property and value pairs. */ + styles: CssDeclaration[]; +}; + +/** + * A single CSS property declaration. + */ +export type CssDeclaration = { + /** A CSS property's name, using kebab-case. */ + property: string; + /** The property's value. */ + value: string; +}; diff --git a/types/ext/database.d.ts b/types/ext/database.d.ts new file mode 100644 index 00000000..e4a58e60 --- /dev/null +++ b/types/ext/database.d.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type StructureDefinition = { + version: number; + stores: {[name in TObjectStoreName]: StoreDefinition}; +}; + +export type StoreDefinition = { + primaryKey: IDBObjectStoreParameters; + indices: string[]; +}; + +export type UpdateFunction = ( + db: IDBDatabase, + transaction: IDBTransaction, + oldVersion: number, + newVersion: number | null, +) => void; + +export type CountTarget = [ + objectStoreOrIndex: IDBObjectStore | IDBIndex, + query: IDBValidKey | IDBKeyRange | undefined, +]; diff --git a/types/ext/deinflector.d.ts b/types/ext/deinflector.d.ts new file mode 100644 index 00000000..e6fc203e --- /dev/null +++ b/types/ext/deinflector.d.ts @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as TranslationInternal from './translation-internal'; + +export type ReasonTypeRaw = 'v1' | 'v5' | 'vs' | 'vk' | 'vz' | 'adj-i' | 'iru'; + +export type ReasonsRaw = { + [reason: string]: { + kanaIn: string; + kanaOut: string; + rulesIn: ReasonTypeRaw[]; + rulesOut: ReasonTypeRaw[]; + }[]; +}; + +export type ReasonVariant = [ + kanaIn: string, + kanaOut: string, + rulesIn: TranslationInternal.DeinflectionRuleFlags, + rulesOut: TranslationInternal.DeinflectionRuleFlags, +]; + +export type Reason = [ + reason: string, + variants: ReasonVariant[], +]; diff --git a/types/ext/dictionary-data-util.d.ts b/types/ext/dictionary-data-util.d.ts new file mode 100644 index 00000000..75128368 --- /dev/null +++ b/types/ext/dictionary-data-util.d.ts @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Dictionary from './dictionary'; + +export type FrequencyData = { + frequency: number; + displayValue: string | null; +}; + +export type KanjiFrequenciesMap3 = Map; + +export type TermFrequenciesMap1 = Map; + +export type TermFrequenciesMap2 = Map; + +export type TermFrequenciesMap2Data = { + term: string; + reading: string | null; + values: TermFrequenciesMap3; +}; + +export type KanjiFrequenciesMap1 = Map; + +export type KanjiFrequenciesMap2 = Map; + +export type KanjiFrequenciesMap2Data = { + character: string; + values: KanjiFrequenciesMap3; +}; + +export type TermFrequenciesMap3 = Map; + +export type DictionaryFrequency = { + dictionary: string; + frequencies: T[]; +}; + +export type TermFrequency = { + term: string; + reading: string | null; + values: FrequencyData[]; +}; + +export type KanjiFrequency = { + character: string; + values: FrequencyData[]; +}; + +export type TermFrequencyType = 'popular' | 'rare' | 'normal'; + +export type GroupedPronunciationInternal = { + terms: Set; + reading: string; + position: number; + nasalPositions: number[]; + devoicePositions: number[]; + tags: Dictionary.Tag[]; +}; + +export type GroupedPronunciation = { + terms: string[]; + reading: string; + position: number; + nasalPositions: number[]; + devoicePositions: number[]; + tags: Dictionary.Tag[]; + exclusiveTerms: string[]; + exclusiveReadings: string[]; +}; + +export type DictionaryGroupedPronunciations = { + dictionary: string; + pronunciations: GroupedPronunciation[]; +}; + +export type TagGroup = { + tag: Dictionary.Tag; + headwordIndices: number[]; +}; diff --git a/types/ext/dictionary-data.d.ts b/types/ext/dictionary-data.d.ts new file mode 100644 index 00000000..f594f913 --- /dev/null +++ b/types/ext/dictionary-data.d.ts @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as StructuredContent from './structured-content'; + +export type IndexVersion = 1 | 2 | 3; + +export type Index = { + format?: IndexVersion; + version?: IndexVersion; + title: string; + revision: string; + sequenced?: boolean; + author?: string; + url?: string; + description?: string; + attribution?: string; + frequencyMode?: 'occurrence-based' | 'rank-based'; + tagMeta?: IndexTagMeta; +}; + +export type IndexTagMeta = { + [name: string]: IndexTag; +}; + +export type IndexTag = { + category: string; + order: number; + notes: string; + score: number; +}; + +export type TermV1 = [ + expression: string, + reading: string, + definitionTags: string | null, + rules: string, + score: number, + ...glossary: string[], +]; + +export type TermV3 = [ + expression: string, + reading: string, + definitionTags: string | null, + rules: string, + score: number, + glossary: TermGlossary[], + sequence: number, + termTags: string, +]; + +export type KanjiV1 = [ + character: string, + onyomi: string, + kunyomi: string, + tags: string, + ...meanings: string[], +]; + +export type KanjiV3 = [ + character: string, + onyomi: string, + kunyomi: string, + tags: string, + meanings: string[], + stats: {[name: string]: string}, +]; + +export type TermGlossary = ( + TermGlossaryString | + TermGlossaryText | + TermGlossaryImage | + TermGlossaryStructuredContent +); + +export type TermGlossaryString = string; +export type TermGlossaryText = {type: 'text', text: string}; +export type TermGlossaryImage = {type: 'image'} & TermImage; +export type TermGlossaryStructuredContent = {type: 'structured-content', content: StructuredContent.Content}; + +export type TermImage = StructuredContent.ImageElementBase; + +export type Tag = [ + name: string, + category: string, + order: number, + notes: string, + score: number, +]; + +export type GenericFrequencyData = string | number | { + value: number; + displayValue?: string; + reading?: undefined; // Used for type disambiguation, field does not actually exist +}; + +export type TermMeta = TermMetaFrequency | TermMetaPitch; + +export type TermMetaFrequencyDataWithReading = { + reading: string; + frequency: GenericFrequencyData; +}; + +export type TermMetaFrequency = [ + expression: string, + mode: 'freq', + data: GenericFrequencyData | TermMetaFrequencyDataWithReading, +]; + +export type TermMetaPitchData = { + reading: string; + pitches: { + position: number; + nasal?: number | number[]; + devoice?: number | number[]; + tags?: string[]; + }[]; +}; + +export type TermMetaPitch = [ + expression: string, + mode: 'pitch', + data: TermMetaPitchData, +]; + +export type KanjiMeta = KanjiMetaFrequency; + +export type KanjiMetaFrequency = [ + character: string, + mode: 'freq', + data: GenericFrequencyData, +]; diff --git a/types/ext/dictionary-database.d.ts b/types/ext/dictionary-database.d.ts new file mode 100644 index 00000000..2e0f854b --- /dev/null +++ b/types/ext/dictionary-database.d.ts @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Dictionary from './dictionary'; +import type * as DictionaryData from './dictionary-data'; +import type * as DictionaryImporter from './dictionary-importer'; + +export type DatabaseId = { + id: number; // Automatic database primary key +}; + +export interface MediaDataBase { + dictionary: string; + path: string; + mediaType: string; + width: number; + height: number; + content: TContentType; +} + +export interface MediaDataArrayBufferContent extends MediaDataBase {} +export interface MediaDataStringContent extends MediaDataBase {} + +export type Media = {index: number} & MediaDataBase; + +export type DatabaseTermEntry = { + expression: string; + reading: string; + expressionReverse?: string; + readingReverse?: string; + definitionTags: string | null; + /** Legacy alias for the `definitionTags` field. */ + tags?: string; + rules: string; + score: number; + glossary: DictionaryData.TermGlossary[]; + sequence?: number; + termTags?: string; + dictionary: string; +}; + +export type DatabaseTermEntryWithId = DatabaseTermEntry & DatabaseId; + +export type TermEntry = { + index: number; + matchType: MatchType; + matchSource: MatchSource; + term: string; + reading: string; + definitionTags: string[]; + termTags: string[]; + rules: string[]; + definitions: DictionaryData.TermGlossary[]; + score: number; + dictionary: string; + id: number; + sequence: number; +}; + +export type DatabaseKanjiEntry = { + character: string; + onyomi: string; + kunyomi: string; + tags: string; + meanings: string[]; + dictionary: string; + stats?: {[name: string]: string}; +}; + +export type KanjiEntry = { + index: number; + character: string; + onyomi: string[]; + kunyomi: string[]; + tags: string[]; + definitions: string[]; + stats: {[name: string]: string}; + dictionary: string; +}; + +export type Tag = { + name: string; + category: string; + order: number; + notes: string; + score: number; + dictionary: string; +}; + +export type DatabaseTermMeta = DatabaseTermMetaFrequency | DatabaseTermMetaPitch; + +export type DatabaseTermMetaFrequency = { + expression: string; + mode: 'freq'; + data: DictionaryData.GenericFrequencyData | DictionaryData.TermMetaFrequencyDataWithReading; + dictionary: string; +}; + +export type DatabaseTermMetaPitch = { + expression: string; + mode: 'pitch'; + data: DictionaryData.TermMetaPitchData; + dictionary: string; +}; + +export type TermMetaFrequencyDataWithReading = { + reading: string; + frequency: DictionaryData.GenericFrequencyData; +}; + +export type TermMeta = TermMetaFrequency | TermMetaPitch; + +export type TermMetaType = TermMeta['mode']; + +export type TermMetaFrequency = { + index: number; + term: string; + mode: 'freq'; + data: DictionaryData.GenericFrequencyData | DictionaryData.TermMetaFrequencyDataWithReading; + dictionary: string; +}; + +export type TermMetaPitch = { + index: number; + term: string; + mode: 'pitch'; + data: DictionaryData.TermMetaPitchData; + dictionary: string; +}; + +export type DatabaseKanjiMeta = DatabaseKanjiMetaFrequency; + +export type DatabaseKanjiMetaFrequency = { + character: string; + mode: 'freq'; + data: DictionaryData.GenericFrequencyData; + dictionary: string; +}; + +export type KanjiMeta = KanjiMetaFrequency; + +export type KanjiMetaType = KanjiMeta['mode']; + +export type KanjiMetaFrequency = { + index: number; + character: string; + mode: 'freq'; + data: DictionaryData.GenericFrequencyData; + dictionary: string; +}; + +export type DictionaryCounts = { + total: DictionaryCountGroup | null; + counts: DictionaryCountGroup[]; +}; + +export type DictionaryCountGroup = { + [key: string]: number; +}; + +export type ObjectStoreName = ( + 'dictionaries' | + 'terms' | + 'termMeta' | + 'kanji' | + 'kanjiMeta' | + 'tagMeta' | + 'media' +); + +/* eslint-disable @stylistic/ts/indent */ +export type ObjectStoreData = ( + T extends 'dictionaries' ? DictionaryImporter.Summary : + T extends 'terms' ? DatabaseTermEntry : + T extends 'termMeta' ? DatabaseTermMeta : + T extends 'kanji' ? DatabaseKanjiEntry : + T extends 'kanjiMeta' ? DatabaseKanjiMeta : + T extends 'tagMeta' ? Tag : + T extends 'media' ? MediaDataArrayBufferContent : + never +); +/* eslint-enable @stylistic/ts/indent */ + +export type DeleteDictionaryProgressData = { + count: number; + processed: number; + storeCount: number; + storesProcesed: number; +}; + +export type DeleteDictionaryProgressCallback = (data: DeleteDictionaryProgressData) => void; + +export type MatchType = Dictionary.TermSourceMatchType; + +export type MatchSource = Dictionary.TermSourceMatchSource; + +export type DictionaryAndQueryRequest = { + query: string | number; + dictionary: string; +}; + +export type TermExactRequest = { + term: string; + reading: string; +}; + +export type MediaRequest = { + path: string; + dictionary: string; +}; + +export type FindMultiBulkData = { + item: TItem; + itemIndex: number; + indexIndex: number; +}; + +export type CreateQuery = (item: TItem) => (IDBValidKey | IDBKeyRange | null); + +export type FindPredicate = (row: TRow, item: TItem) => boolean; + +export type CreateResult = (row: TRow, data: FindMultiBulkData) => TResult; + +export type DictionarySet = { + has(value: string): boolean; +}; diff --git a/types/ext/dictionary-importer-media-loader.d.ts b/types/ext/dictionary-importer-media-loader.d.ts new file mode 100644 index 00000000..afbb1902 --- /dev/null +++ b/types/ext/dictionary-importer-media-loader.d.ts @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * Attempts to load an image using an ArrayBuffer and a media type to return details about it. + * @param content The binary content for the image, encoded as an ArrayBuffer. + * @param mediaType The media type for the image content. + * @param transfer An optional array of data that should be transferred in `postMessage` calls. + * When the resulting promise resolves, this array will contain the `content` object. + * @returns Details about the requested image content. + * @throws {Error} An error can be thrown if the image fails to load. + */ +export type GetImageDetailsFunction = ( + content: ArrayBuffer, + mediaType: string, + transfer?: Transferable[] +) => Promise<{content: ArrayBuffer, width: number, height: number}>; + + +export type GenericMediaLoader = { + getImageDetails: GetImageDetailsFunction; +}; diff --git a/types/ext/dictionary-importer.d.ts b/types/ext/dictionary-importer.d.ts new file mode 100644 index 00000000..16ce66ce --- /dev/null +++ b/types/ext/dictionary-importer.d.ts @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as DictionaryData from './dictionary-data'; +import type * as DictionaryDatabase from './dictionary-database'; +import type * as StructuredContent from './structured-content'; + +export type OnProgressCallback = (data: ProgressData) => void; + +export type ProgressData = { + stepIndex: number; + stepCount: number; + index: number; + count: number; +}; + +export type ImportResult = { + result: Summary; + errors: Error[]; +}; + +export type ImportDetails = { + prefixWildcardsSupported: boolean; +}; + +export type Summary = { + title: string; + revision: string; + sequenced: boolean; + version: number; + importDate: number; + prefixWildcardsSupported: boolean; + counts: SummaryCounts; + author?: string; + url?: string; + description?: string; + attribution?: string; + frequencyMode?: 'occurrence-based' | 'rank-based'; +}; + +export type SummaryCounts = { + terms: SummaryItemCount; + termMeta: SummaryMetaCount; + kanji: SummaryItemCount; + kanjiMeta: SummaryMetaCount; + tagMeta: SummaryItemCount; + media: SummaryItemCount; +}; + +export type SummaryItemCount = { + total: number; +}; + +export type SummaryMetaCount = { + total: number; + [key: string]: number; +}; + +export type ImportRequirement = ( + ImageImportRequirement | + StructuredContentImageImportRequirement +); + +export type ImageImportRequirement = { + type: 'image'; + target: DictionaryData.TermGlossaryImage; + source: DictionaryData.TermGlossaryImage; + entry: DictionaryDatabase.DatabaseTermEntry; +}; + +export type StructuredContentImageImportRequirement = { + type: 'structured-content-image'; + target: StructuredContent.ImageElement; + source: StructuredContent.ImageElement; + entry: DictionaryDatabase.DatabaseTermEntry; +}; + +export type ImportRequirementContext = { + archive: import('jszip'); + media: Map; +}; diff --git a/types/ext/dictionary-worker-handler.d.ts b/types/ext/dictionary-worker-handler.d.ts new file mode 100644 index 00000000..ddd6134c --- /dev/null +++ b/types/ext/dictionary-worker-handler.d.ts @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as DictionaryImporter from './dictionary-importer'; +import type * as DictionaryWorkerMediaLoader from './dictionary-worker-media-loader'; + +export type OnProgressCallback = (...args: unknown[]) => void; + +export type Message = ( + ImportDictionaryMessage | + DeleteDictionaryMessage | + GetDictionaryCountsMessage | + GetImageDetailsResponseMessage +); + +export type ImportDictionaryMessage = { + action: 'importDictionary'; + params: ImportDictionaryMessageParams; +}; + +export type ImportDictionaryMessageParams = { + details: DictionaryImporter.ImportDetails; + archiveContent: ArrayBuffer; +}; + +export type DeleteDictionaryMessage = { + action: 'deleteDictionary'; + params: DeleteDictionaryMessageParams; +}; + +export type DeleteDictionaryMessageParams = { + dictionaryTitle: string; +}; + +export type GetDictionaryCountsMessage = { + action: 'getDictionaryCounts'; + params: GetDictionaryCountsMessageParams; +}; + +export type GetDictionaryCountsMessageParams = { + dictionaryNames: string[]; + getTotal: boolean; +}; + +export type GetImageDetailsResponseMessage = { + action: 'getImageDetails.response'; + params: DictionaryWorkerMediaLoader.HandleMessageParams; +}; diff --git a/types/ext/dictionary-worker-media-loader.d.ts b/types/ext/dictionary-worker-media-loader.d.ts new file mode 100644 index 00000000..fab01283 --- /dev/null +++ b/types/ext/dictionary-worker-media-loader.d.ts @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; + +export type ImageDetails = { + content: ArrayBuffer; + width: number; + height: number; +}; + +export type HandleMessageParams = {id: string} & Core.Response; diff --git a/types/ext/dictionary-worker.d.ts b/types/ext/dictionary-worker.d.ts new file mode 100644 index 00000000..570d37cd --- /dev/null +++ b/types/ext/dictionary-worker.d.ts @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; +import type * as DictionaryImporter from './dictionary-importer'; +import type * as DictionaryDatabase from './dictionary-database'; + +export type InvokeDetails = { + complete: boolean; + worker: Worker | null; + resolve: ((result: TResponse) => void) | null; + reject: ((reason?: Core.RejectionReason) => void) | null; + onMessage: ((event: MessageEvent>) => void) | null; + onProgress: ((...args: unknown[]) => void) | null; + formatResult: ((result: TResponseRaw) => TResponse) | null; +}; + +export type MessageCompleteData = { + action: 'complete'; + params: MessageCompleteParams; +}; + +export type MessageProgressData = { + action: 'progress'; + params: MessageProgressParams; +}; + +export type MessageGetImageDetailsData = { + action: 'getImageDetails'; + params: MessageGetImageDetailsParams; +}; + +export type MessageCompleteParams = Core.Response; + +export type MessageProgressParams = { + args: unknown[]; +}; + +export type MessageGetImageDetailsParams = { + id: string; + content: ArrayBuffer; + mediaType: string; +}; + +export type MessageData = MessageCompleteData | MessageProgressData | MessageGetImageDetailsData; + +export type MessageCompleteResultSerialized = { + result: DictionaryImporter.Summary; + errors: Core.SerializedError[]; +}; + +export type MessageCompleteResult = { + result: DictionaryImporter.Summary; + errors: Error[]; +}; + +export type ImportProgressCallback = (details: DictionaryImporter.ProgressData) => void; + +export type DeleteProgressCallback = (details: DictionaryDatabase.DeleteDictionaryProgressData) => void; diff --git a/types/ext/dictionary.d.ts b/types/ext/dictionary.d.ts new file mode 100644 index 00000000..3e90dec0 --- /dev/null +++ b/types/ext/dictionary.d.ts @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * Copyright (C) 2021-2022 Yomichan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as DictionaryData from './dictionary-data'; + +// Common + +/** + * A generic dictionary entry which is used as the base interface. + */ +export type DictionaryEntry = KanjiDictionaryEntry | TermDictionaryEntry; + +export type DictionaryEntryType = DictionaryEntry['type']; + +/** + * A tag represents some brief information about part of a dictionary entry. + */ +export type Tag = { + /** + * The name of the tag. + */ + name: string; + /** + * The category of the tag. + */ + category: string; + /** + * A number indicating the sorting order of the tag. + */ + order: number; + /** + * A score value for the tag. + */ + score: number; + /** + * An array of descriptions for the tag. * If there are multiple entries, + * the values will typically have originated from different dictionaries. + * However, there is no correlation between the length of this array and + * the length of the `dictionaries` field, as duplicates are removed. + */ + content: string[]; + /** + * An array of dictionary names that contained a tag with this name and category. + */ + dictionaries: string[]; + /** + * Whether or not this tag is redundant with previous tags. + */ + redundant: boolean; +}; + +// Kanji + +/** + * A dictionary entry for a kanji character. + */ +export type KanjiDictionaryEntry = { + /** + * The type of the entry. + */ + type: 'kanji'; + /** + * The kanji character that was looked up. + */ + character: string; + /** + * The name of the dictionary that the information originated from. + */ + dictionary: string; + /** + * Onyomi readings for the kanji character. + */ + onyomi: string[]; + /** + * Kunyomi readings for the kanji character. + */ + kunyomi: string[]; + /** + * Tags for the kanji character. + */ + tags: Tag[]; + /** + * An object containing stats about the kanji character. + */ + stats: KanjiStatGroups; + /** + * Definitions for the kanji character. + */ + definitions: string[]; + /** + * Frequency information for the kanji character. + */ + frequencies: KanjiFrequency[]; +}; + +/** + * An object with groups of stats about a kanji character. + */ +export type KanjiStatGroups = { + /** + * A group of stats. + * @param propName The name of the group. + */ + [propName: string]: KanjiStat[]; +}; + +/** + * A stat represents a generic piece of information about a kanji character. + */ +export type KanjiStat = { + /** + * The name of the stat. + */ + name: string; + /** + * The category of the stat. + */ + category: string; + /** + * A description of the stat. + */ + content: string; + /** + * A number indicating the sorting order of the stat. + */ + order: number; + /** + * A score value for the stat. + */ + score: number; + /** + * The name of the dictionary that the stat originated from. + */ + dictionary: string; + /** + * A value for the stat. + */ + value: number | string; +}; + +/** + * Frequency information corresponds to how frequently a character appears in a corpus, + * which can be a number of occurrences or an overall rank. + */ +export type KanjiFrequency = { + /** + * The original order of the frequency, which is usually used for sorting. + */ + index: number; + /** + * The name of the dictionary that the frequency information originated from. + */ + dictionary: string; + /** + * The index of the dictionary in the original list of dictionaries used for the lookup. + */ + dictionaryIndex: number; + /** + * The priority of the dictionary. + */ + dictionaryPriority: number; + /** + * The kanji character for the frequency. + */ + character: string; + /** + * The frequency for the character, as a number of occurrences or an overall rank. + */ + frequency: number; + /** + * A display value to show to the user. + */ + displayValue: string | null; + /** + * Whether or not the displayValue string was parsed to determine the frequency value. + */ + displayValueParsed: boolean; +}; + +// Terms + +/** + * A dictionary entry for a term or group of terms. + */ +export type TermDictionaryEntry = { + /** + * The type of the entry. + */ + type: 'term'; + /** + * Whether or not any of the sources is a primary source. Primary sources are derived from the + * original search text, while non-primary sources originate from related terms. + */ + isPrimary: boolean; + /** + * A list of inflections that was applied to get the term. + */ + inflections: string[]; + /** + * A score for the dictionary entry. + */ + score: number; + /** + * The sorting value based on the determined term frequency. + */ + frequencyOrder: number; + /** + * The index of the dictionary in the original list of dictionaries used for the lookup. + */ + dictionaryIndex: number; + /** + * The priority of the dictionary. + */ + dictionaryPriority: number; + /** + * The number of primary sources that had an exact text match for the term. + */ + sourceTermExactMatchCount: number; + /** + * The maximum length of the transformed text for all primary sources. + */ + maxTransformedTextLength: number; + /** + * Headwords for the entry. + */ + headwords: TermHeadword[]; + /** + * Definitions for the entry. + */ + definitions: TermDefinition[]; + /** + * Pronunciations for the entry. + */ + pronunciations: TermPronunciation[]; + /** + * Frequencies for the entry. + */ + frequencies: TermFrequency[]; +}; + +/** + * A term headword is a combination of a term, reading, and auxiliary information. + */ +export type TermHeadword = { + /** + * The original order of the headword, which is usually used for sorting. + */ + index: number; + /** + * The text for the term. + */ + term: string; + /** + * The reading of the term. + */ + reading: string; + /** + * The sources of the term. + */ + sources: TermSource[]; + /** + * Tags for the headword. + */ + tags: Tag[]; + /** + * List of word classes (part of speech) for the headword. + */ + wordClasses: string[]; +}; + +/** + * A definition contains a list of entries and information about what what terms it corresponds to. + */ +export type TermDefinition = { + /** + * The original order of the definition, which is usually used for sorting. + */ + index: number; + /** + * A list of headwords that this definition corresponds to. + */ + headwordIndices: number[]; + /** + * The name of the dictionary that the definition information originated from. + */ + dictionary: string; + /** + * The index of the dictionary in the original list of dictionaries used for the lookup. + */ + dictionaryIndex: number; + /** + * The priority of the dictionary. + */ + dictionaryPriority: number; + /** + * Database ID for the definition. + */ + id: number; + /** + * A score for the definition. + */ + score: number; + /** + * The sorting value based on the determined term frequency. + */ + frequencyOrder: number; + /** + * A list of database sequence numbers for the term. A value of `-1` corresponds to no sequence. + * The list can have multiple values if multiple definitions with different sequences have been merged. + * The list should always have at least one item. + */ + sequences: number[]; + /** + * Whether or not any of the sources is a primary source. Primary sources are derived from the + * original search text, while non-primary sources originate from related terms. + */ + isPrimary: boolean; + /** + * Tags for the definition. + */ + tags: Tag[]; + /** + * The definition entries. + */ + entries: DictionaryData.TermGlossary[]; +}; + +/** + * A term pronunciation represents different ways to pronounce one of the headwords. + */ +export type TermPronunciation = { + /** + * The original order of the pronunciation, which is usually used for sorting. + */ + index: number; + /** + * Which headword this pronunciation corresponds to. + */ + headwordIndex: number; + /** + * The name of the dictionary that the proununciation information originated from. + */ + dictionary: string; + /** + * The index of the dictionary in the original list of dictionaries used for the lookup. + */ + dictionaryIndex: number; + /** + * The priority of the dictionary. + */ + dictionaryPriority: number; + /** + * The pitch accent representations for the term. + */ + pitches: TermPitch[]; +}; + +/** + * Pitch accent information for a term, represented as the position of the downstep. + */ +export type TermPitch = { + /** + * Position of the downstep, as a number of mora. + */ + position: number; + /** + * Positions of morae with a nasal sound. + */ + nasalPositions: number[]; + /** + * Positions of morae with a devoiced sound. + */ + devoicePositions: number[]; + /** + * Tags for the pitch accent. + */ + tags: Tag[]; +}; + +/** + * Frequency information corresponds to how frequently a term appears in a corpus, + * which can be a number of occurrences or an overall rank. + */ +export type TermFrequency = { + /** + * The original order of the frequency, which is usually used for sorting. + */ + index: number; + /** + * Which headword this frequency corresponds to. + */ + headwordIndex: number; + /** + * The name of the dictionary that the frequency information originated from. + */ + dictionary: string; + /** + * The index of the dictionary in the original list of dictionaries used for the lookup. + */ + dictionaryIndex: number; + /** + * The priority of the dictionary. + */ + dictionaryPriority: number; + /** + * Whether or not the frequency had an explicit reading specified. + */ + hasReading: boolean; + /** + * The frequency for the term, as a number of occurrences or an overall rank. + */ + frequency: number; + /** + * A display value to show to the user. + */ + displayValue: string | null; + /** + * Whether or not the displayValue string was parsed to determine the frequency value. + */ + displayValueParsed: boolean; +}; + +/** + * Enum representing how the search term relates to the final term. + */ +export type TermSourceMatchType = 'exact' | 'prefix' | 'suffix'; + +/** + * Enum representing what database field was used to match the source term. + */ +export type TermSourceMatchSource = 'term' | 'reading' | 'sequence'; + +/** + * Source information represents how the original text was transformed to get to the final term. + */ +export type TermSource = { + /** + * The original text that was searched. + */ + originalText: string; + /** + * The original text after being transformed, but before applying deinflections. + */ + transformedText: string; + /** + * The final text after applying deinflections. + */ + deinflectedText: string; + /** + * How the deinflected text matches the value from the database. + */ + matchType: TermSourceMatchType; + /** + * Which field was used to match the database entry. + */ + matchSource: TermSourceMatchSource; + /** + * Whether or not this source is a primary source. Primary sources are derived from the + * original search text, while non-primary sources originate from related terms. + */ + isPrimary: boolean; +}; diff --git a/types/ext/display-anki.d.ts b/types/ext/display-anki.d.ts new file mode 100644 index 00000000..cc59a5c3 --- /dev/null +++ b/types/ext/display-anki.d.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Anki from './anki'; +import type * as AnkiNoteBuilder from './anki-note-builder'; +import type * as AnkiTemplates from './anki-templates'; +import type * as AnkiTemplatesInternal from './anki-templates-internal'; + +export type CreateMode = AnkiTemplatesInternal.CreateModeNoTest; + +export type LogData = { + ankiNoteData: AnkiTemplates.NoteData | undefined; + ankiNoteDataException: Error | undefined; + ankiNotes: AnkiNoteLogData[]; +}; + +export type AnkiNoteLogData = { + mode: CreateMode; + note: Anki.Note | undefined; + errors?: Error[]; + requirements?: AnkiNoteBuilder.Requirement[]; +}; + +export type DictionaryEntryDetails = { + modeMap: Map; +}; + +export type DictionaryEntryModeDetails = { + mode: CreateMode; + note: Anki.Note; + errors: Error[]; + requirements: AnkiNoteBuilder.Requirement[]; + canAdd: boolean; + valid: boolean; + noteIds: Anki.NoteId[] | null; + noteInfos?: (Anki.NoteInfo | null)[]; + ankiError: Error | null; +}; + +export type CreateNoteResult = { + note: Anki.Note; + errors: Error[]; + requirements: AnkiNoteBuilder.Requirement[]; +}; diff --git a/types/ext/display-audio.d.ts b/types/ext/display-audio.d.ts new file mode 100644 index 00000000..2ef252b1 --- /dev/null +++ b/types/ext/display-audio.d.ts @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Audio from './audio'; +import type * as Settings from './settings'; +import type * as AudioDownloader from './audio-downloader'; + +export type CacheItem = { + sourceMap: Map; + primaryCardAudio: PrimaryCardAudio | null; +}; + +export type CachedInfoList = { + infoListPromise: Promise; + infoList: AudioInfoList | null; +}; + +export type AudioInfoList = AudioInfoListItem[]; + +export type AudioInfoListItem = { + info: AudioDownloader.Info; + audioPromise: Promise | null; + audioResolved: boolean; + audio: GenericAudio | null; +}; + +export type PrimaryCardAudio = { + index: number; + subIndex: number | null; +}; + +export type SourceInfo = { + source: AudioSource | null; + subIndex: number | null; +}; + +export type AudioSource = { + index: number; + type: Settings.AudioSourceType; + url: string; + voice: string; + isInOptions: boolean; + downloadable: boolean; + name: string; + nameIndex: number; + nameUnique: boolean; +}; + +export type AudioSourceShort = { + type: Settings.AudioSourceType; + url: string; + voice: string; +}; + +export type AudioMediaOptions = { + sources: Audio.AudioSourceInfo[]; + preferredAudioIndex: number | null; +}; + +export type PlayAudioResult = { + audio: GenericAudio | null; + source: AudioSource | null; + subIndex: number; + valid: boolean; +}; + +export type TermAudio = { + audio: GenericAudio; + source: AudioSource; + subIndex: number; +}; + +export type CreateAudioResult = { + audio: GenericAudio | null; + index: number; + cacheUpdated: boolean; +}; + +export type GenericAudio = HTMLAudioElement | TextToSpeechAudio; + +export type MenuItemEntry = { + valid: boolean | null; + index: number | null; + name: string | null; +}; diff --git a/types/ext/display-content-manager.d.ts b/types/ext/display-content-manager.d.ts new file mode 100644 index 00000000..dc2269cf --- /dev/null +++ b/types/ext/display-content-manager.d.ts @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as DictionaryDatabase from './dictionary-database'; + +/** A callback used when a media file has been loaded. */ +export type OnLoadCallback = ( + /** The URL of the media that was loaded. */ + url: string, +) => void; + +/** A callback used when a media file should be unloaded. */ +export type OnUnloadCallback = ( + /** Whether or not the media was fully loaded. */ + fullyLoaded: boolean, +) => void; + +export type CachedMediaDataLoaded = { + data: DictionaryDatabase.MediaDataStringContent; + url: string; +}; + +export type LoadMediaDataInfo = { + onUnload: OnUnloadCallback; + loaded: boolean; +}; \ No newline at end of file diff --git a/types/ext/display-history.d.ts b/types/ext/display-history.d.ts new file mode 100644 index 00000000..2ba5006b --- /dev/null +++ b/types/ext/display-history.d.ts @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Display from './display'; + +export type Entry = { + id: string; + url: string; + next: Entry | null; + previous: Entry | null; + state: EntryState | null; + content: EntryContent | null; +}; + +export type EntryState = Display.HistoryState; + +export type EntryContent = Display.HistoryContent; + +export type EventType = 'stateChanged'; + +export type StateChangedEvent = { + synthetic: boolean; +}; diff --git a/types/ext/display.d.ts b/types/ext/display.d.ts new file mode 100644 index 00000000..feb049fb --- /dev/null +++ b/types/ext/display.d.ts @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; +import type * as Dictionary from './dictionary'; +import type * as Extension from './extension'; +import type * as Settings from './settings'; +import type * as TextScanner from './text-scanner'; +import type * as TextSource from './text-source'; + +export type HistoryMode = 'clear' | 'overwrite' | 'new'; + +export type DisplayPageType = 'search' | 'popup'; + +export type PageType = 'terms' | 'kanji' | 'unloaded' | 'clear'; + +/** + * Information about how popup content should be shown, specifically related to the inner popup content. + */ +export type ContentDetails = { + /** Whether or not the frame should be `focus()`'d. */ + focus: boolean; + /** An object containing key-value pairs representing the URL search params. */ + params: HistoryParams; + /** The semi-persistent state assigned to the navigation entry. */ + state: HistoryState | null; + /** The non-persistent content assigned to the navigation entry. */ + content: HistoryContent | null; + /** How the navigation history should be modified. */ + historyMode: HistoryMode; +}; + +/** + * An object containing key-value pairs representing the URL search params. + */ +export type HistoryParams = { + /** The type of content that is being shown. */ + type?: PageType; + /** The search query. */ + query?: string; + /** Whether or not wildcards can be used for the search query. */ + wildcards?: 'on' | 'off'; + /** The start position of the `query` string as an index into the `full` query string. */ + offset?: string; + /** The full search text. If absent, `query` is the full search text. */ + full?: string; + /** Whether or not the full search query should be forced to be visible. */ + ['full-visible']?: 'true' | 'false'; + /** Whether or not the query should be looked up. If it is not looked up, the content should be provided. */ + lookup?: 'true' | 'false'; + /** Other values; only used for assignment. */ + [otherKey: string]: unknown; +}; + +/** + * The semi-persistent state assigned to the navigation entry. + */ +export type HistoryState = { + /** What was the cause of the navigation. */ + cause?: 'queryParser'; + /** The sentence context. */ + sentence?: HistoryStateSentence; + /** The index of the dictionary entry to focus. */ + focusEntry?: number; + /** The horizontal scroll position. */ + scrollX?: number; + /** The vertical scroll position. */ + scrollY?: number; + /** The options context which should be used for lookups. */ + optionsContext?: Settings.OptionsContext; + /** The originating URL of the content. */ + url?: string; + /** The originating document title of the content. */ + documentTitle?: string; +}; + +/** + * The sentence context. + */ +export type HistoryStateSentence = { + /** The full string. */ + text: string; + /** The offset from the start of `text` to the full search query. */ + offset: number; +}; + +/** + * The non-persistent content assigned to the navigation entry. + */ +export type HistoryContent = { + /** Whether or not any CSS animations should occur. */ + animate?: boolean; + /** An array of dictionary entries to display as content. */ + dictionaryEntries?: Dictionary.DictionaryEntry[]; + /** The identifying information for the frame the content originated from. */ + contentOrigin?: Extension.ContentOrigin; +}; + +export type SearchPersistentStateControllerEventType = 'modeChange'; + +export type SearchMode = null | 'popup' | 'action-popup'; + +export type GetSearchContextCallback = TextScanner.GetSearchContextCallbackSync; + +export type QueryParserConstructorDetails = { + getSearchContext: GetSearchContextCallback; + japaneseUtil: JapaneseUtil; +}; + +export type QueryParserOptions = { + selectedParser: string | null; + termSpacing: boolean; + readingMode: Settings.ParsingReadingMode; + useInternalParser: boolean; + useMecabParser: boolean; + scanning: TextScanner.Options; +}; + +export type QueryParserEventType = 'searched'; + +export type QueryParserSearchedEvent = { + textScanner: TextScanner; + type: PageType; + dictionaryEntries: Dictionary.DictionaryEntry[]; + sentence: HistoryStateSentence; + inputInfo: TextScanner.InputInfo; + textSource: TextSource.TextSource; + optionsContext: Settings.OptionsContext; + sentenceOffset: number | null; +}; + +export type DisplayEventType = ( + 'optionsUpdated' | + 'frameVisibilityChange' | + 'logDictionaryEntryData' | + 'contentClear' | + 'contentUpdateStart' | + 'contentUpdateEntry' | + 'contentUpdateComplete' +); + +export type OptionsUpdatedEvent = { + options: Settings.ProfileOptions; +}; + +export type FrameVisibilityChangeEvent = { + value: boolean; +}; + +export type LogDictionaryEntryDataEvent = { + dictionaryEntry: Dictionary.DictionaryEntry; + promises: Promise[]; +}; + +export type ContentUpdateStartEvent = { + type: PageType; + query: string; +}; + +export type ContentUpdateEntryEvent = { + dictionaryEntry: Dictionary.DictionaryEntry; + element: Element; + index: number; +}; + +export type ContentUpdateCompleteEvent = { + type: PageType; +}; + +export type ConfigureMessageDetails = { + depth: number; + parentPopupId: string; + parentFrameId: number; + childrenSupported: boolean; + scale: number; + optionsContext: Settings.OptionsContext; +}; + +export type MessageDetails = { + action: string; + params: Core.SerializableObject; +}; + +export type DisplayGeneratorConstructorDetails = { + japaneseUtil: JapaneseUtil; + contentManager: DisplayContentManager; + hotkeyHelpController?: HotkeyHelpController | null; +}; diff --git a/types/ext/document-util.d.ts b/types/ext/document-util.d.ts new file mode 100644 index 00000000..28dfe899 --- /dev/null +++ b/types/ext/document-util.d.ts @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type NormalizedWritingMode = 'horizontal-tb' | 'vertical-rl' | 'vertical-lr' | 'sideways-rl' | 'sideways-lr'; + +/** + * Options to configure how element detection is performed. + */ +export type GetRangeFromPointOptions = { + /** + * Whether or deep content scanning should be performed. When deep content scanning is enabled, + * some transparent overlay elements will be ignored when looking for the element at the input position. + */ + deepContentScan: boolean; + /** + * Whether or not zoom coordinates should be normalized. + */ + normalizeCssZoom: boolean; +}; + +/** + * Scans the document for text or elements with text information at the given coordinate. + * Coordinates are provided in [client space](https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View/Coordinate_systems). + * @returns A range for the hovered text or element, or `null` if no applicable content was found. + */ +export type GetRangeFromPointHandler = ( + /** The x coordinate to search at. */ + x: number, + /** The y coordinate to search at. */ + y: number, + /** Options to configure how element detection is performed. */ + options: GetRangeFromPointOptions, +) => (TextSourceRange | TextSourceElement | null); + +export type ToNumberConstraints = { + min?: string | number; + max?: string | number; + step?: string | number; +}; diff --git a/types/ext/dom-data-binder.d.ts b/types/ext/dom-data-binder.d.ts new file mode 100644 index 00000000..ca0036c3 --- /dev/null +++ b/types/ext/dom-data-binder.d.ts @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as TaskAccumulator from './task-accumulator'; + +export type CreateElementMetadataCallback = (element: Element) => T | undefined; + +export type CompareElementMetadataCallback = (metadata1: T, metadata2: T) => boolean; + +export type GetValuesCallback = (args: GetValuesDetails[]) => Promise; + +export type SetValuesCallback = (args: SetValuesDetails[]) => Promise; + +export type GetValuesDetails = { + element: Element; + metadata: T; +}; + +export type SetValuesDetails = { + element: Element; + metadata: T; + value: ValueType; +}; + +export type OnErrorCallback = (error: Error, stale: boolean, element: Element, metadata: T) => void; + +export type ConstructorDetails = { + selector: string; + createElementMetadata: CreateElementMetadataCallback; + compareElementMetadata: CompareElementMetadataCallback; + getValues: GetValuesCallback; + setValues: SetValuesCallback; + onError?: OnErrorCallback | null; +}; + +export type ElementObserver = { + element: Element; + type: NormalizedElementType; + value: unknown; + hasValue: boolean; + onChange: null | (() => void); + metadata: T; +}; + +export type SettingChangedEventData = { + value: boolean | string | number; +}; + +export type SettingChangedEvent = CustomEvent; + +export type NormalizedElementType = 'textarea' | 'select' | 'text' | 'checkbox' | 'number' | null; + +export type UpdateTaskValue = {all: boolean}; + +export type AssignTaskValue = {value: ValueType}; + +export type ValueType = boolean | string | number | null; + +export type UpdateTask = [ + key: ElementObserver | null, + task: TaskAccumulator.Task, +]; + +export type AssignTask = [ + key: ElementObserver | null, + task: TaskAccumulator.Task, +]; + +export type ApplyTarget = [ + observer: ElementObserver, + task: TaskAccumulator.Task | TaskAccumulator.Task | null, +]; + +export type TaskResultError = { + error: Error; + result?: undefined; +}; + +export type TaskResultSuccess = { + error?: undefined; + result: T; +}; + +export type TaskResult = TaskResultError | TaskResultSuccess; diff --git a/types/ext/dynamic-loader.d.ts b/types/ext/dynamic-loader.d.ts new file mode 100644 index 00000000..49011db0 --- /dev/null +++ b/types/ext/dynamic-loader.d.ts @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type DynamicLoaderSentinelDetails = { + scriptUrl: string; +}; diff --git a/types/ext/dynamic-property.d.ts b/types/ext/dynamic-property.d.ts new file mode 100644 index 00000000..5ec886d2 --- /dev/null +++ b/types/ext/dynamic-property.d.ts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type EventType = 'change'; + +export type ChangeEventDetails = { + value: T; +}; diff --git a/types/ext/environment.d.ts b/types/ext/environment.d.ts new file mode 100644 index 00000000..9c0f5bf6 --- /dev/null +++ b/types/ext/environment.d.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type Info = { + browser: Browser; + platform: {os: OperatingSystem}; +}; + +export type Browser = 'chrome' | 'firefox' | 'firefox-mobile' | 'edge' | 'edge-legacy' | 'safari'; + +export type OperatingSystem = chrome.runtime.PlatformOs | 'unknown'; diff --git a/types/ext/event-listener-collection.d.ts b/types/ext/event-listener-collection.d.ts new file mode 100644 index 00000000..daeeecab --- /dev/null +++ b/types/ext/event-listener-collection.d.ts @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; + +export type EventListenerFunction = (...args: Core.SafeAny[]) => unknown; + +export type EventTarget = { + addEventListener( + type: string, + listener: EventListener | EventListenerObject | EventListenerFunction, + options?: AddEventListenerOptions | boolean, + ): void; + removeEventListener( + type: string, + listener: EventListener | EventListenerObject | EventListenerFunction, + options?: EventListenerOptions | boolean, + ): void; +}; + +export type ExtensionEvent = { + addListener(callback: TCallback, ...args: TArgs[]): void; + removeListener(callback: TCallback, ...args: TArgs[]): void; +}; + +export type EventTargetDetails = { + type: 'removeEventListener'; + target: EventTarget; + eventName: string; + listener: EventListener | EventListenerObject | EventListenerFunction; + options: EventListenerOptions | boolean | undefined; +}; + +export type ExtensionEventDetails = { + type: 'removeListener'; + target: ExtensionEvent; + callback: EventListenerFunction; + args: unknown[]; +}; + +export type EventDispatcherDetails = { + type: 'off'; + target: EventDispatcher; + eventName: string; + callback: EventListenerFunction; +}; + +export type EventListenerDetails = EventTargetDetails | ExtensionEventDetails | EventDispatcherDetails; + +export type AddEventListenerArgs = [ + target: EventTarget, + type: string, + listener: EventListener | EventListenerObject | EventListenerFunction, + options?: AddEventListenerOptions | boolean, +]; + +export type AddListenerArgs = [ + target: ExtensionEvent, + callback: TCallback, + ...args: TArgs[], +]; + +export type OnArgs = [ + target: EventDispatcher, + eventName: string, + callback: (details: Core.SafeAny) => void, +]; diff --git a/types/ext/extension.d.ts b/types/ext/extension.d.ts new file mode 100644 index 00000000..1c86a4ca --- /dev/null +++ b/types/ext/extension.d.ts @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; + +export type ChromeRuntimeSendMessageArgs1 = [ + message: Core.SafeAny, +]; + +export type ChromeRuntimeSendMessageArgs2 = [ + message: Core.SafeAny, + responseCallback: (response: Core.SafeAny) => void, +]; + +export type ChromeRuntimeSendMessageArgs3 = [ + message: Core.SafeAny, + options: chrome.runtime.MessageOptions, + responseCallback: (response: Core.SafeAny) => void, +]; + +export type ChromeRuntimeSendMessageArgs4 = [ + extensionId: string | undefined | null, + message: Core.SafeAny, + responseCallback: (response: Core.SafeAny) => void, +]; + +export type ChromeRuntimeSendMessageArgs5 = [ + extensionId: string | undefined | null, + message: Core.SafeAny, + options: chrome.runtime.MessageOptions, + responseCallback: (response: Core.SafeAny) => void, +]; + +export type ChromeRuntimeSendMessageArgs = ChromeRuntimeSendMessageArgs1 | ChromeRuntimeSendMessageArgs2 | ChromeRuntimeSendMessageArgs3 | ChromeRuntimeSendMessageArgs4 | ChromeRuntimeSendMessageArgs5; + +export type ExtensionEventType = 'extensionUnloaded' | 'optionsUpdated' | 'databaseUpdated' | 'zoomChanged' | 'closePopups' | 'dynamicLoaderSentinel' | 'storageChanged'; + +export type HtmlElementWithContentWindow = HTMLIFrameElement | HTMLFrameElement | HTMLObjectElement; + +export type ContentOrigin = { + tabId?: number; + frameId?: number; +}; + +export type ChromeRuntimeMessage = { + action: string; + params?: Core.SerializableObject; +}; + +export type ChromeRuntimeMessageWithFrameId = ChromeRuntimeMessage & { + frameId?: number; +}; + +export type ChromeRuntimeOnMessageCallback = ( + message: TMessage, + sender: chrome.runtime.MessageSender, + sendResponse: ChromeRuntimeMessageSendResponseFunction, +) => boolean | void; + +export type ChromeRuntimeMessageSendResponseFunction = (response?: unknown) => void; diff --git a/types/ext/frame-ancestry-handler.d.ts b/types/ext/frame-ancestry-handler.d.ts new file mode 100644 index 00000000..3c9e32bf --- /dev/null +++ b/types/ext/frame-ancestry-handler.d.ts @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type RequestFrameInfoResponseParams = { + frameId: number; + nonce: string; + more: boolean; +}; + +export type RequestFrameInfoResponseReturn = { + nonce: string; +}; diff --git a/types/ext/frame-client.d.ts b/types/ext/frame-client.d.ts new file mode 100644 index 00000000..54d0d880 --- /dev/null +++ b/types/ext/frame-client.d.ts @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Extension from './extension'; + +export type Message = { + token: string; + secret: string; + data: T; +}; + +export type SetupFrameFunction = (frame: Extension.HtmlElementWithContentWindow) => void; + +export type FrameEndpointReadyDetails = { + secret: string; +}; + +export type FrameEndpointConnectedDetails = { + secret: string; + token: string; +}; diff --git a/types/ext/frame-offset-forwarder.d.ts b/types/ext/frame-offset-forwarder.d.ts new file mode 100644 index 00000000..6cc0aef2 --- /dev/null +++ b/types/ext/frame-offset-forwarder.d.ts @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type ChildFrameRect = { + x: number; + y: number; + width: number; + height: number; +}; diff --git a/types/ext/frontend.d.ts b/types/ext/frontend.d.ts new file mode 100644 index 00000000..3acafe0a --- /dev/null +++ b/types/ext/frontend.d.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** Details about how to set up the instance. */ +export type ConstructorDetails = { + /** The type of page, one of 'web', 'popup', or 'search'. */ + pageType: PageType; + /** A PopupFactory instance to use for generating popups. */ + popupFactory: PopupFactory; + /** The nesting depth value of the popup. */ + depth: number; + /** The tab ID of the host tab. */ + tabId: number | undefined; + /** The frame ID of the host frame. */ + frameId: number; + /** The popup ID of the parent popup if one exists, otherwise null. */ + parentPopupId: string | null; + /** The frame ID of the parent popup if one exists, otherwise null. */ + parentFrameId: number | null; + /** Whether or not proxy popups should be used. */ + useProxyPopup: boolean; + /** Whether or not window popups can be used. */ + canUseWindowPopup?: boolean; + /** Whether or not popups can be hosted in the root frame. */ + allowRootFramePopupProxy: boolean; + /** Whether popups can create child popups or not. */ + childrenSupported?: boolean; + /** A HotkeyHandler instance. */ + hotkeyHandler: HotkeyHandler; +}; + +export type PageType = 'web' | 'popup' | 'search'; + +export type FrontendRequestReadyBroadcastParams = { + frameId: number; +}; + +export type GetPopupInfoResult = { + popupId: string | null; +}; + +export type FrontendReadyDetails = { + frameId: number; +}; diff --git a/types/ext/generic-setting-controller.d.ts b/types/ext/generic-setting-controller.d.ts new file mode 100644 index 00000000..5e3435c5 --- /dev/null +++ b/types/ext/generic-setting-controller.d.ts @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as SettingsModifications from './settings-modifications'; +import type * as DocumentUtil from './document-util'; + +export type TransformType = TransformData['type']; + +export type ElementMetadata = { + path: string; + scope: SettingsModifications.OptionsScopeType | undefined; + transforms: TransformData[]; + transformRaw: string | undefined; +}; + +export type TransformFunction = ( + value: unknown, + data: TransformData, + element: Element, +) => unknown; + +export type TransformStep = 'pre' | 'post'; + +export type TransformData = ( + SetAttributeTransformData | + SetVisibilityTransformData | + SplitTagsTransformData | + JoinTagsTransformData | + ToNumberConstraintsTransformData | + ToBooleanTransformData | + ToStringTransformData | + ConditionalConvertTransformData +); + +export type TransformDataBase = { + step?: TransformStep; +}; + +export type SetAttributeTransformData = TransformDataBase & { + type: 'setAttribute'; + ancestorDistance?: number; + selector?: string; + attribute: string; +}; + +export type SetVisibilityTransformData = TransformDataBase & { + type: 'setVisibility'; + ancestorDistance?: number; + selector?: string; + condition: OperationData; +}; + +export type SplitTagsTransformData = TransformDataBase & { + type: 'splitTags'; +}; + +export type JoinTagsTransformData = TransformDataBase & { + type: 'joinTags'; +}; + +export type ToNumberConstraintsTransformData = TransformDataBase & { + type: 'toNumber'; + constraints?: DocumentUtil.ToNumberConstraints; +}; + +export type ToBooleanTransformData = TransformDataBase & { + type: 'toBoolean'; +}; + +export type ToStringTransformData = TransformDataBase & { + type: 'toString'; +}; + +export type ConditionalConvertTransformData = TransformDataBase & { + type: 'conditionalConvert'; + cases?: ConditionalConvertCase[]; +}; + +export type ConditionalConvertCase = { + default?: boolean; + result: unknown; +} & OperationData; + +export type OperationData = { + op: string; + value: unknown; +}; diff --git a/types/ext/hotkey-handler.d.ts b/types/ext/hotkey-handler.d.ts new file mode 100644 index 00000000..7b2b4cb3 --- /dev/null +++ b/types/ext/hotkey-handler.d.ts @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Input from './input'; + +export type EventType = 'keydownNonHotkey'; + +export type HotkeyInfo = { + modifiers: Set; + action: string; + argument: unknown; +}; + +export type HotkeyHandlers = { + handlers: HotkeyInfo[]; +}; diff --git a/types/ext/input.d.ts b/types/ext/input.d.ts new file mode 100644 index 00000000..fbcb4df3 --- /dev/null +++ b/types/ext/input.d.ts @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type ModifierKey = 'alt' | 'ctrl' | 'meta' | 'shift'; +export type ModifierMouseButton = 'mouse0' | 'mouse1' | 'mouse2' | 'mouse3' | 'mouse4' | 'mouse5'; +export type Modifier = ModifierKey | ModifierMouseButton; +export type ModifierType = 'key' | 'mouse'; diff --git a/types/ext/japanese-util.d.ts b/types/ext/japanese-util.d.ts new file mode 100644 index 00000000..c2d2c411 --- /dev/null +++ b/types/ext/japanese-util.d.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type CodepointRange = [ + minInclusive: number, + maxInclusive: number, +]; + +export type FuriganaGroup = { + isKana: boolean; + text: string; + textNormalized: string | null; +}; + +export type FuriganaSegment = { + text: string; + reading: string; +}; + +export type PitchCategory = ( + 'heiban' | + 'kifuku' | + 'atamadaka' | + 'odaka' | + 'nakadaka' +); + +export type DiacriticType = 'dakuten' | 'handakuten'; diff --git a/types/ext/json-schema.d.ts b/types/ext/json-schema.d.ts new file mode 100644 index 00000000..c959628b --- /dev/null +++ b/types/ext/json-schema.d.ts @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type ValueObject = {[key: string]: Value}; + +export type Value = string | number | boolean | null | Value[] | ValueObject; + +export type ValueObjectOrArray = ValueObject | Value[]; + +export type Type = 'string' | 'number' | 'integer' | 'object' | 'array' | 'boolean' | 'null'; + +export type SchemaObject = { + type?: Type | Type[]; + required?: string[]; + + default?: Value; + enum?: Value[]; + const?: Value; + minimum?: number; + maximum?: number; + exclusiveMinimum?: number; + exclusiveMaximum?: number; + multipleOf?: number; + minLength?: number; + maxLength?: number; + pattern?: string; + patternFlags?: string; + minItems?: number; + maxItems?: number; + minProperties?: number; + maxProperties?: number; + definitions?: {[key: string]: Schema}; + + $ref?: string; + + properties?: {[key: string]: Schema}; + additionalProperties?: Schema; + not?: Schema; + oneOf?: Schema[]; + allOf?: Schema[]; + anyOf?: Schema[]; + contains?: Schema; + prefixItems?: Schema[]; + items?: Schema | Schema[]; // Legacy schema format for the array + additionalItems?: Schema; + if?: Schema; + then?: Schema; + else?: Schema; +}; + +export type Schema = SchemaObject | true | false; + +export type SchemaStackItem = { + schema: Schema | Schema[]; + path: string | number | null; +}; + +export type ValueStackItem = { + value: unknown; + path: string | number | null; +}; diff --git a/types/ext/keyboard-mouse-input-field.d.ts b/types/ext/keyboard-mouse-input-field.d.ts new file mode 100644 index 00000000..321e49cc --- /dev/null +++ b/types/ext/keyboard-mouse-input-field.d.ts @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Input from './input'; + +export type EventType = 'change'; + +export type ChangeEvent = { + key: string | null; + modifiers: Input.Modifier[]; +}; diff --git a/types/ext/keyboard-shortcut-controller.d.ts b/types/ext/keyboard-shortcut-controller.d.ts new file mode 100644 index 00000000..0f276ce9 --- /dev/null +++ b/types/ext/keyboard-shortcut-controller.d.ts @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Settings from './settings'; + +export type ActionDetails = { + scopes: Set; + argument?: { + template: string; + default: string; + }; +}; diff --git a/types/ext/log.d.ts b/types/ext/log.d.ts new file mode 100644 index 00000000..ac2f606b --- /dev/null +++ b/types/ext/log.d.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type LogLevel = 'log' | 'info' | 'debug' | 'warn' | 'error'; + +export type LoggerEventType = 'log'; + +export type LogContext = { + url: string; +}; diff --git a/types/ext/mecab.d.ts b/types/ext/mecab.d.ts new file mode 100644 index 00000000..bcbd476f --- /dev/null +++ b/types/ext/mecab.d.ts @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type ParseResultRaw = { + [key: string]: ParseResultLineRaw[]; +}; + +export type ParseResultLineRaw = ParseResultTermRaw[]; + +export type ParseResultTermRaw = { + expression?: string; + reading?: string; + source?: string; +}; + +/** The resulting data from an invocation of `parseText`. */ +export type ParseResult = { + /** The dictionary name for the parsed result. */ + name: string; + /** The resulting parsed terms. */ + lines: ParseFragment[][]; +}; + +/** A fragment of the parsed text. */ +export type ParseFragment = { + /** The term. */ + term: string; + /** The reading of the term. */ + reading: string; + /** The source text. */ + source: string; +}; diff --git a/types/ext/options-util.d.ts b/types/ext/options-util.d.ts new file mode 100644 index 00000000..e03e4be2 --- /dev/null +++ b/types/ext/options-util.d.ts @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; + +export type LegacyOptions = Core.SafeAny; + +export type IntermediateOptions = Core.SafeAny; + +export type LegacyUpdateFunction = (options: LegacyOptions) => void; + +export type ModernUpdateFunction = ModernUpdateFunctionSync | ModernUpdateFunctionAsync; + +export type ModernUpdateFunctionSync = (options: IntermediateOptions) => IntermediateOptions; + +export type ModernUpdateFunctionAsync = (options: IntermediateOptions) => Promise; + +export type ModernUpdate = { + async: boolean; + update: ModernUpdateFunction; +}; diff --git a/types/ext/panel-element.d.ts b/types/ext/panel-element.d.ts new file mode 100644 index 00000000..d267b836 --- /dev/null +++ b/types/ext/panel-element.d.ts @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type EventType = 'visibilityChanged' | 'closeCompleted'; + +export type VisibilityChangedEvent = { + visible: boolean; +}; + +export type CloseCompletedEvent = { + reopening: boolean; +}; + +/* eslint-disable @stylistic/ts/indent */ +export type Event = ( + T extends 'visibilityChanged' ? VisibilityChangedEvent : + T extends 'closeCompleted' ? CloseCompletedEvent : + never +); +/* eslint-enable @stylistic/ts/indent */ + +export type ConstructorDetails = { + node: HTMLElement; + closingAnimationDuration: number; +}; diff --git a/types/ext/popup-factory.d.ts b/types/ext/popup-factory.d.ts new file mode 100644 index 00000000..a167a6f7 --- /dev/null +++ b/types/ext/popup-factory.d.ts @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** Details about how to acquire the popup. */ +export type GetOrCreatePopupDetails = { + /** The ID of the frame that should host the popup. */ + frameId?: number | null; + /** A specific ID used to find an existing popup, or to assign to the new popup. */ + id?: string | null; + /** The ID of the parent popup. */ + parentPopupId?: string | null; + /** A specific depth value to assign to the popup. */ + depth?: number | null; + /** Whether or not a separate popup window should be used, rather than an iframe. */ + popupWindow?: boolean; + /** Whether or not the popup is able to show child popups. */ + childrenSupported?: boolean; +}; diff --git a/types/ext/popup-menu.d.ts b/types/ext/popup-menu.d.ts new file mode 100644 index 00000000..c20ebf69 --- /dev/null +++ b/types/ext/popup-menu.d.ts @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type EventType = 'close'; + +export type CloseReason = 'close' | 'outside' | 'item' | 'resize'; + +export type MenuOpenEventDetails = { + menu: PopupMenu; +}; + +export type MenuCloseEventDetails = { + menu: PopupMenu; + item: HTMLElement | null; + action: string | null; + cause: CloseReason; + altKey: boolean; + ctrlKey: boolean; + metaKey: boolean; + shiftKey: boolean; +}; + +export type MenuOpenEvent = CustomEvent; + +export type MenuCloseEvent = CustomEvent; diff --git a/types/ext/popup.d.ts b/types/ext/popup.d.ts new file mode 100644 index 00000000..bcbc8662 --- /dev/null +++ b/types/ext/popup.d.ts @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as DocumentUtil from './document-util'; +import type * as Settings from './settings'; + +export type PopupAny = Popup | PopupWindow | PopupProxy; + +/** + * Information about how popup content should be shown, specifically related to the outer popup frame. + */ +export type ContentDetails = { + /** The options context for the content to show. */ + optionsContext: Settings.OptionsContext | null; + /** The rectangles of the source content. */ + sourceRects: Rect[]; + /** The normalized CSS writing-mode value of the source content. */ + writingMode: DocumentUtil.NormalizedWritingMode; +}; + +/** + * A rectangle representing a DOM region, similar to DOMRect. + */ +export type Rect = { + /** The left position of the rectangle. */ + left: number; + /** The top position of the rectangle. */ + top: number; + /** The right position of the rectangle. */ + right: number; + /** The bottom position of the rectangle. */ + bottom: number; +}; + +/** + * A rectangle representing a DOM region, similar to DOMRect but with a `valid` property. + */ +export type ValidRect = { + /** The left position of the rectangle. */ + left: number; + /** The top position of the rectangle. */ + top: number; + /** The right position of the rectangle. */ + right: number; + /** The bottom position of the rectangle. */ + bottom: number; + /** Whether or not the rectangle is valid. */ + valid: boolean; +}; + +/** + * A rectangle representing a DOM region for placing the popup frame. + */ +export type SizeRect = { + /** The left position of the rectangle. */ + left: number; + /** The top position of the rectangle. */ + top: number; + /** The width of the rectangle. */ + width: number; + /** The height of the rectangle. */ + height: number; + /** Whether or not the rectangle is positioned to the right of the source rectangle. */ + after: boolean; + /** Whether or not the rectangle is positioned below the source rectangle. */ + below: boolean; +}; + +export type ValidSize = { + width: number; + height: number; + valid: boolean; +}; + +export type CustomOuterCssChangedEvent = { + node: HTMLStyleElement | HTMLLinkElement | null; + useWebExtensionApi: boolean; + inShadow: boolean; +}; + +export type PopupAnyEventType = PopupEventType | PopupProxyEventType | PopupWindowEventType; + +export type PopupEventType = 'customOuterCssChanged' | 'framePointerOver' | 'framePointerOut' | 'offsetNotFound'; + +export type PopupProxyEventType = 'offsetNotFound'; + +export type PopupWindowEventType = never; + +export type PopupConstructorDetails = { + /** The ID of the popup. */ + id: string; + /** The depth of the popup. */ + depth: number; + /** The ID of the host frame. */ + frameId: number; + /** Whether or not the popup is able to show child popups. */ + childrenSupported: boolean; +}; + +export type PopupWindowConstructorDetails = { + /** The ID of the popup. */ + id: string; + /** The depth of the popup. */ + depth: number; + /** The ID of the host frame. */ + frameId: number; +}; + +export type PopupProxyConstructorDetails = { + /** The ID of the popup. */ + id: string; + /** The depth of the popup. */ + depth: number; + /** The ID of the host frame. */ + frameId: number; + /** A `FrameOffsetForwarder` instance which is used to determine frame positioning. */ + frameOffsetForwarder: FrameOffsetForwarder | null; +}; diff --git a/types/ext/profile-conditions-ui.d.ts b/types/ext/profile-conditions-ui.d.ts new file mode 100644 index 00000000..7aa22e93 --- /dev/null +++ b/types/ext/profile-conditions-ui.d.ts @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Settings from './settings'; + +export type EventType = 'conditionGroupCountChanged'; + +export type DescriptorType = Settings.ProfileConditionType; + +export type Descriptor = { + displayName: string; + defaultOperator: string; + operators: Map; +}; + +export type ValidateFunction = (value: string) => boolean; + +export type NormalizeFunction = (value: unknown) => string; + +export type OperatorInternal = { + displayName: string; + type: string; + defaultValue: string; + resetDefaultOnChange?: boolean; + validate?: ValidateFunction; + normalize?: NormalizeFunction; +}; + +export type Operator = { + displayName: string; + type: string; + defaultValue: string; + resetDefaultOnChange: boolean | null; + validate: ValidateFunction | null; + normalize: NormalizeFunction | null; +}; + +export type ConditionGroupCountChangedEvent = { + count: number; + profileIndex: number; +}; + +export type DescriptorInfo = { + name: DescriptorType; + displayName: string; +}; + +export type OperatorInfo = { + name: string; + displayName: string; +}; + +export type InputData = { + validate: ValidateFunction | null; + normalize: NormalizeFunction | null; +}; diff --git a/types/ext/profile-conditions-util.d.ts b/types/ext/profile-conditions-util.d.ts new file mode 100644 index 00000000..15904410 --- /dev/null +++ b/types/ext/profile-conditions-util.d.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as JsonSchema from './json-schema'; +import type * as Settings from './settings'; + +export type OperatorMapArray = [ + key: string, + function: CreateSchemaFunction, +][]; + +export type CreateSchemaFunction = ( + value: unknown, +) => JsonSchema.Schema; + +export type NormalizedOptionsContext1 = Settings.OptionsContext1 & { + domain?: string; +}; + +export type NormalizedOptionsContext2 = Settings.OptionsContext2; + +export type NormalizedOptionsContext3 = Settings.OptionsContext2; + +export type NormalizedOptionsContext = NormalizedOptionsContext1 | NormalizedOptionsContext2 | NormalizedOptionsContext3; diff --git a/types/ext/request-builder.d.ts b/types/ext/request-builder.d.ts new file mode 100644 index 00000000..0acf5ede --- /dev/null +++ b/types/ext/request-builder.d.ts @@ -0,0 +1,21 @@ +/* +* Copyright (C) 2023 Yomitan Authors +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +export type FetchEventListeners = { + onBeforeSendHeaders: ((details: chrome.webRequest.WebRequestHeadersDetails) => (chrome.webRequest.BlockingResponse | void)) | null; + onErrorOccurred: ((details: chrome.webRequest.WebResponseErrorDetails) => void) | null; +}; diff --git a/types/ext/script-manager.d.ts b/types/ext/script-manager.d.ts new file mode 100644 index 00000000..89337152 --- /dev/null +++ b/types/ext/script-manager.d.ts @@ -0,0 +1,56 @@ +/* +* Copyright (C) 2023 Yomitan Authors +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +export type RunAt = 'document_start' | 'document_end' | 'document_idle'; + +/** The script registration details. */ +export type RegistrationDetails = { + /** Same as `matches` in the `content_scripts` manifest key. */ + matches: string[]; + + /** Regex match pattern to use as a fallback when native content script registration isn't supported. */ + /** Should be equivalent to `matches`. */ + urlMatches: string; + + /** Same as `run_at` in the `content_scripts` manifest key. */ + runAt: RunAt; + + /** Same as `exclude_matches` in the `content_scripts` manifest key. */ + excludeMatches?: string[]; + + /** Same as `match_about_blank` in the `content_scripts` manifest key. */ + matchAboutBlank: boolean; + + /** Same as `all_frames` in the `content_scripts` manifest key. */ + allFrames: boolean; + + /** List of CSS paths. */ + css?: string[]; + + /** List of script paths. */ + js?: string[]; +}; + +export type ContentScriptInjectionDetails = { + allFrames: boolean; + matchAboutBlank: boolean; + runAt: RunAt; + css?: string[]; + js?: string[]; + urlRegex: RegExp | null; +}; + diff --git a/types/ext/selector-observer.d.ts b/types/ext/selector-observer.d.ts new file mode 100644 index 00000000..a84b2add --- /dev/null +++ b/types/ext/selector-observer.d.ts @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type OnAddedCallback = (element: Element) => T | undefined; + +export type OnRemovedCallback = (element: Element, data: T) => void; + +export type OnChildrenUpdatedCallback = (element: Element, data: T) => void; + +export type IsStaleCallback = (element: Element, data: T) => boolean; + +export type ConstructorDetails = { + /** A string CSS selector used to find elements. */ + selector: string; + /** A string CSS selector used to filter elements, or `null` for no filtering. */ + ignoreSelector?: string | null; + /** A function which is invoked for each element that is added that matches the selector. */ + onAdded?: OnAddedCallback | null; + /** A function which is invoked for each element that is removed, or `null`. */ + onRemoved?: OnRemovedCallback | null; + /** A function which is invoked for each element which has its children updated, or `null`. */ + onChildrenUpdated?: OnChildrenUpdatedCallback | null; + /** + * A function which checks if the data is stale for a given element, or `null`. + * If the element is stale, it will be removed and potentially re-added. + */ + isStale?: IsStaleCallback | null; +}; + +export type MutationRecordLike = { + type: string; + addedNodes: Node[]; + removedNodes: Node[]; + target: Node; +}; + +export type Observer = { + element: Element; + ancestors: Node[]; + data: T; +}; diff --git a/types/ext/settings-controller.d.ts b/types/ext/settings-controller.d.ts new file mode 100644 index 00000000..4a5bef3d --- /dev/null +++ b/types/ext/settings-controller.d.ts @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Settings from './settings'; +import type * as SettingsModifications from './settings-modifications'; +import type * as Core from './core'; + +export type PageExitPrevention = { + end: () => void; +}; + +export type EventType = 'optionsChanged' | 'optionsContextChanged' | 'permissionsChanged' | 'dictionarySettingsReordered' | 'scanInputsChanged'; + +export type OptionsChangedEvent = { + options: Settings.ProfileOptions; + optionsContext: Settings.OptionsContext; +}; + +export type PermissionsChangedEvent = { + permissions: chrome.permissions.Permissions; +}; + +export type DictionarySettingsReorderedEvent = { + source: DictionaryController; +}; + +export type ScanInputsChangedEvent = { + source: ScanInputsController | ScanInputsSimpleController; +}; + +export type SettingsRead = THasScope extends true ? SettingsModifications.ScopedRead : SettingsModifications.Read; + +export type SettingsModification = THasScope extends true ? SettingsModifications.ScopedModification : SettingsModifications.Modification; + +export type SettingsExtraFields = THasScope extends true ? null : SettingsModifications.OptionsScope; + +export type ModifyResult = Core.Response; diff --git a/types/ext/settings-modifications.d.ts b/types/ext/settings-modifications.d.ts new file mode 100644 index 00000000..5541383a --- /dev/null +++ b/types/ext/settings-modifications.d.ts @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Settings from './settings'; + +export type OptionsScope = { + scope: OptionsScopeType; + optionsContext: Settings.OptionsContext | null; +}; + +export type OptionsScopeType = 'profile' | 'global'; + +export type Read = { + path: string; +}; + +export type ModificationSet = { + action: 'set'; + path: string; + value: unknown; +}; + +export type ModificationDelete = { + action: 'delete'; + path: string; +}; + +export type ModificationSwap = { + action: 'swap'; + path1: string; + path2: string; +}; + +export type ModificationSplice = { + action: 'splice'; + path: string; + start: number; + deleteCount: number; + items: unknown[]; +}; + +export type ModificationPush = { + action: 'push'; + path: string; + items: unknown[]; +}; + +export type Modification = ( + ModificationSet | + ModificationDelete | + ModificationSwap | + ModificationSplice | + ModificationPush +); + +export type ScopedRead = Read & OptionsScope; +export type ScopedModificationSet = ModificationSet & OptionsScope; +export type ScopedModificationDelete = ModificationDelete & OptionsScope; +export type ScopedModificationSwap = ModificationSwap & OptionsScope; +export type ScopedModificationSplice = ModificationSplice & OptionsScope; +export type ScopedModificationPush = ModificationPush & OptionsScope; + +export type ScopedModification = ( + ScopedModificationSet | + ScopedModificationDelete | + ScopedModificationSwap | + ScopedModificationSplice | + ScopedModificationPush +); + +export type ModificationSetResult = unknown; +export type ModificationDeleteResult = true; +export type ModificationSwapResult = true; +export type ModificationSpliceResult = unknown[]; +export type ModificationPushResult = number; + +export type ModificationResult = ( + ModificationSetResult | + ModificationDeleteResult | + ModificationSwapResult | + ModificationSpliceResult | + ModificationPushResult +); diff --git a/types/ext/settings.d.ts b/types/ext/settings.d.ts new file mode 100644 index 00000000..19c4aa1f --- /dev/null +++ b/types/ext/settings.d.ts @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Input from './input'; + +export type OptionsContextFlag = 'clipboard'; + +export type OptionsContext1 = { + url: string; + depth: number; + index?: undefined; + current?: undefined; + flags?: OptionsContextFlag[]; + modifiers?: Input.Modifier[]; + modifierKeys?: Input.ModifierKey[]; +}; + +export type OptionsContext2 = { + index: number; + url?: undefined; + depth?: undefined; + current?: undefined; + flags?: OptionsContextFlag[]; + modifiers?: Input.Modifier[]; + modifierKeys?: Input.ModifierKey[]; +}; + +export type OptionsContext3 = { + current: true; + url?: undefined; + depth?: undefined; + index?: undefined; + flags?: OptionsContextFlag[]; + modifiers?: Input.Modifier[]; + modifierKeys?: Input.ModifierKey[]; +}; + +export type OptionsContext = OptionsContext1 | OptionsContext2 | OptionsContext3; + +export type Options = { + version: number; + profiles: Profile[]; + profileCurrent: number; + global: GlobalOptions; +}; + +export type GlobalOptions = { + database: GlobalDatabaseOptions; +}; + +export type GlobalDatabaseOptions = { + prefixWildcardsSupported: boolean; +}; + +export type Profile = { + name: string; + conditionGroups: ProfileConditionGroup[]; + options: ProfileOptions; +}; + +export type ProfileConditionGroup = { + conditions: ProfileCondition[]; +}; + +export type ProfileConditionType = 'popupLevel' | 'url' | 'modifierKeys' | 'flags'; + +export type ProfileCondition = { + type: ProfileConditionType; + operator: string; + value: string; +}; + +export type ProfileOptions = { + general: GeneralOptions; + popupWindow: PopupWindowOptions; + audio: AudioOptions; + scanning: ScanningOptions; + translation: TranslationOptions; + dictionaries: DictionariesOptions; + parsing: ParsingOptions; + anki: AnkiOptions; + sentenceParsing: SentenceParsingOptions; + inputs: InputsOptions; + clipboard: ClipboardOptions; + accessibility: AccessibilityOptions; +}; + +export type GeneralOptions = { + enable: boolean; + resultOutputMode: ResultOutputMode; + debugInfo: boolean; + maxResults: number; + showAdvanced: boolean; + popupDisplayMode: PopupDisplayMode; + popupWidth: number; + popupHeight: number; + popupHorizontalOffset: number; + popupVerticalOffset: number; + popupHorizontalOffset2: number; + popupVerticalOffset2: number; + popupHorizontalTextPosition: PopupHorizontalTextPosition; + popupVerticalTextPosition: PopupVerticalTextPosition; + popupScalingFactor: number; + popupScaleRelativeToPageZoom: boolean; + popupScaleRelativeToVisualViewport: boolean; + showGuide: boolean; + compactTags: boolean; + glossaryLayoutMode: GlossaryLayoutMode; + mainDictionary: string; + popupTheme: PopupTheme; + popupOuterTheme: PopupOuterTheme; + customPopupCss: string; + customPopupOuterCss: string; + enableWanakana: boolean; + showPitchAccentDownstepNotation: boolean; + showPitchAccentPositionNotation: boolean; + showPitchAccentGraph: boolean; + showIframePopupsInRootFrame: boolean; + useSecurePopupFrameUrl: boolean; + usePopupShadowDom: boolean; + usePopupWindow: boolean; + popupCurrentIndicatorMode: PopupCurrentIndicatorMode; + popupActionBarVisibility: PopupActionBarVisibility; + popupActionBarLocation: PopupActionBarLocation; + frequencyDisplayMode: FrequencyDisplayMode; + termDisplayMode: TermDisplayMode; + sortFrequencyDictionary: string | null; + sortFrequencyDictionaryOrder: SortFrequencyDictionaryOrder; +}; + +export type PopupWindowOptions = { + width: number; + height: number; + left: number; + top: number; + useLeft: boolean; + useTop: boolean; + windowType: PopupWindowType; + windowState: PopupWindowState; +}; + +export type AudioOptions = { + enabled: boolean; + volume: number; + autoPlay: boolean; + sources: AudioSourceOptions[]; +}; + +export type AudioSourceOptions = { + type: AudioSourceType; + url: string; + voice: string; +}; + +export type ScanningOptions = { + inputs: ScanningInput[]; + preventMiddleMouse: ScanningPreventMiddleMouseOptions; + touchInputEnabled: boolean; + pointerEventsEnabled: boolean; + selectText: boolean; + alphanumeric: boolean; + autoHideResults: boolean; + delay: number; + hideDelay: number; + length: number; + deepDomScan: boolean; + popupNestingMaxDepth: number; + enablePopupSearch: boolean; + enableOnPopupExpressions: boolean; + enableOnSearchPage: boolean; + enableSearchTags: boolean; + layoutAwareScan: boolean; + matchTypePrefix: boolean; + hidePopupOnCursorExit: boolean; + hidePopupOnCursorExitDelay: number; + normalizeCssZoom: boolean; +}; + +export type ScanningInput = { + include: string; + exclude: string; + types: ScanningInputTypes; + options: ScanningInputOptions; +}; + +export type ScanningInputTypes = { + mouse: boolean; + touch: boolean; + pen: boolean; +}; + +export type ScanningInputOptions = { + showAdvanced: boolean; + searchTerms: boolean; + searchKanji: boolean; + scanOnTouchMove: boolean; + scanOnTouchPress: boolean; + scanOnTouchRelease: boolean; + scanOnPenMove: boolean; + scanOnPenHover: boolean; + scanOnPenReleaseHover: boolean; + scanOnPenPress: boolean; + scanOnPenRelease: boolean; + preventTouchScrolling: boolean; + preventPenScrolling: boolean; +}; + +export type ScanningPreventMiddleMouseOptions = { + onWebPages: boolean; + onPopupPages: boolean; + onSearchPages: boolean; + onSearchQuery: boolean; +}; + +export type TranslationOptions = { + convertHalfWidthCharacters: TranslationConvertType; + convertNumericCharacters: TranslationConvertType; + convertAlphabeticCharacters: TranslationConvertType; + convertHiraganaToKatakana: TranslationConvertType; + convertKatakanaToHiragana: TranslationConvertType; + collapseEmphaticSequences: TranslationCollapseEmphaticSequences; + textReplacements: TranslationTextReplacementOptions; +}; + +export type TranslationTextReplacementOptions = { + searchOriginal: boolean; + groups: TranslationTextReplacementGroup[][]; +}; + +export type TranslationTextReplacementGroup = { + pattern: string; + ignoreCase: boolean; + replacement: string; +}; + +export type DictionariesOptions = DictionaryOptions[]; + +export type DictionaryOptions = { + name: string; + priority: number; + enabled: boolean; + allowSecondarySearches: boolean; + definitionsCollapsible: DictionaryDefinitionsCollapsible; +}; + +export type ParsingOptions = { + enableScanningParser: boolean; + enableMecabParser: boolean; + selectedParser: string | null; + termSpacing: boolean; + readingMode: ParsingReadingMode; +}; + +export type AnkiOptions = { + enable: boolean; + server: string; + tags: string[]; + screenshot: AnkiScreenshotOptions; + terms: AnkiNoteOptions; + kanji: AnkiNoteOptions; + duplicateScope: AnkiDuplicateScope; + duplicateScopeCheckAllModels: boolean; + checkForDuplicates: boolean; + fieldTemplates: string | null; + suspendNewCards: boolean; + displayTags: AnkiDisplayTags; + noteGuiMode: AnkiNoteGuiMode; + apiKey: string; + downloadTimeout: number; +}; + +export type AnkiCardType = 'terms' | 'kanji'; + +export type AnkiScreenshotOptions = { + format: AnkiScreenshotFormat; + quality: number; +}; + +export type AnkiNoteOptions = { + deck: string; + model: string; + fields: AnkiNoteFields; +}; + +export type AnkiNoteFields = { + [key: string]: string; +}; + +export type SentenceParsingOptions = { + scanExtent: number; + terminationCharacterMode: SentenceTerminationCharacterMode; + terminationCharacters: SentenceParsingTerminationCharacterOption[]; +}; + +export type SentenceParsingTerminationCharacterOption = { + enabled: boolean; + character1: string; + character2: string | null; + includeCharacterAtStart: boolean; + includeCharacterAtEnd: boolean; +}; + +export type InputsOptions = { + hotkeys: InputsHotkeyOptions[]; +}; + +export type InputsHotkeyOptions = { + action: string; + argument: string; + key: string | null; + modifiers: InputsHotkeyModifier[]; + scopes: InputsHotkeyScope[]; + enabled: boolean; +}; + +export type ClipboardOptions = { + enableBackgroundMonitor: boolean; + enableSearchPageMonitor: boolean; + autoSearchContent: boolean; + maximumSearchLength: number; +}; + +export type AccessibilityOptions = { + forceGoogleDocsHtmlRendering: boolean; +}; + +export type PreventMiddleMouseOptions = { + onWebPages: boolean; + onPopupPages: boolean; + onSearchPages: boolean; + onSearchQuery: boolean; +}; + +export type ResultOutputMode = 'group' | 'merge' | 'split'; +export type PopupDisplayMode = 'default' | 'full-width'; +export type PopupHorizontalTextPosition = 'below' | 'above'; +export type PopupVerticalTextPosition = 'default' | 'before' | 'after' | 'left' | 'right'; +export type GlossaryLayoutMode = 'default' | 'compact'; +export type PopupTheme = 'light' | 'dark' | 'browser'; +export type PopupOuterTheme = 'light' | 'dark' | 'browser' | 'site'; +export type PopupCurrentIndicatorMode = 'none' | 'asterisk' | 'triangle' | 'bar-left' | 'bar-right' | 'dot-left' | 'dot-right'; +export type PopupActionBarVisibility = 'auto' | 'always'; +export type PopupActionBarLocation = 'left' | 'right' | 'top' | 'bottom'; +export type FrequencyDisplayMode = 'tags' | 'tags-grouped' | 'split-tags' | 'split-tags-grouped' | 'inline-list' | 'list'; +export type TermDisplayMode = 'ruby' | 'ruby-and-reading' | 'term-and-reading'; +export type SortFrequencyDictionaryOrder = 'ascending' | 'descending'; + +export type PopupWindowType = 'normal' | 'popup'; +export type PopupWindowState = 'normal' | 'maximized' | 'fullscreen'; + +export type AudioSourceType = 'jpod101' | 'jpod101-alternate' | 'jisho' | 'text-to-speech' | 'text-to-speech-reading' | 'custom' | 'custom-json'; + +export type TranslationConvertType = 'false' | 'true' | 'variant'; +export type TranslationCollapseEmphaticSequences = 'false' | 'true' | 'full'; + +export type DictionaryDefinitionsCollapsible = 'not-collapsible' | 'expanded' | 'collapsed' | 'force-collapsed' | 'force-expanded'; + +export type ParsingReadingMode = 'hiragana' | 'katakana' | 'romaji' | 'dictionary-reading' | 'none'; + +export type AnkiScreenshotFormat = 'png' | 'jpeg'; +export type AnkiDuplicateScope = 'collection' | 'deck' | 'deck-root'; +export type AnkiDisplayTags = 'never' | 'always' | 'non-standard'; +export type AnkiNoteGuiMode = 'browse' | 'edit'; + +export type SentenceTerminationCharacterMode = 'custom' | 'custom-no-newlines' | 'newlines' | 'none'; + +export type InputsHotkeyModifier = 'alt' | 'ctrl' | 'shift' | 'meta'; +export type InputsHotkeyScope = 'popup' | 'search' | 'web'; diff --git a/types/ext/simple-dom-parser.d.ts b/types/ext/simple-dom-parser.d.ts new file mode 100644 index 00000000..5fefe69d --- /dev/null +++ b/types/ext/simple-dom-parser.d.ts @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type { + Document as Parse5Document, + Element as Parse5Element, + ChildNode as Parse5ChildNode, +} from 'parse5/dist/tree-adapters/default'; + +/** + * This type is used as a generic reference to an element object from a generic DOM API. + */ +// eslint-disable-next-line @typescript-eslint/ban-types +export type Element = object; + +export type ISimpleDomParser = { + getElementById(id: string, root?: Element): Element | null; + getElementByTagName(tagName: string, root?: Element): Element | null; + getElementsByTagName(tagName: string, root?: Element): Element[]; + getElementsByClassName(className: string, root?: Element): Element[]; + getAttribute(element: Element, attribute: string): string | null; + getTextContent(element: Element): string; +}; diff --git a/types/ext/structured-content.d.ts b/types/ext/structured-content.d.ts new file mode 100644 index 00000000..09755c88 --- /dev/null +++ b/types/ext/structured-content.d.ts @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as DictionaryData from './dictionary-data'; + +export type VerticalAlign = 'baseline' | 'sub' | 'super' | 'text-top' | 'text-bottom' | 'middle' | 'top' | 'bottom'; + +export type TextDecorationLine = 'underline' | 'overline' | 'line-through'; + +export type TextDecorationLineOrNone = 'none' | TextDecorationLine; + +export type FontStyle = 'normal' | 'italic'; + +export type FontWeight = 'normal' | 'bold'; + +export type TextAlign = 'start' | 'end' | 'left' | 'right' | 'center' | 'justify' | 'justify-all' | 'match-parent'; + +export type SizeUnits = 'px' | 'em'; + +export type ImageRendering = 'auto' | 'pixelated' | 'crisp-edges'; + +export type ImageAppearance = 'auto' | 'monochrome'; + +export type Image = DictionaryData.TermImage & { + verticalAlign: VerticalAlign; + sizeUnits: SizeUnits; +}; + +export type Data = { + [key: string]: string; +}; + +export type StructuredContentStyle = { + fontStyle?: FontStyle; + fontWeight?: FontWeight; + fontSize?: string; + textDecorationLine?: TextDecorationLineOrNone | TextDecorationLine[]; + verticalAlign?: VerticalAlign; + textAlign?: TextAlign; + marginTop?: number; + marginLeft?: number; + marginRight?: number; + marginBottom?: number; + listStyleType?: string; +}; + +export type LineBreak = { + tag: 'br'; + data?: Data; + /** + * This element doesn't support children. + */ + content?: undefined; + /** + * This element doesn't support language. + */ + lang?: undefined; +}; + +export type UnstyledElement = { + tag: 'ruby' | 'rt' | 'rp' | 'table' | 'thead' | 'tbody' | 'tfoot' | 'tr'; + content?: Content; + data?: Data; + /** + * Defines the language of an element in the format defined by RFC 5646. + */ + lang?: string; +}; + +export type TableElement = { + tag: 'td' | 'th'; + content?: Content; + data?: Data; + colSpan?: number; + rowSpan?: number; + style?: StructuredContentStyle; + /** + * Defines the language of an element in the format defined by RFC 5646. + */ + lang?: string; +}; + +export type StyledElement = { + tag: 'span' | 'div' | 'ol' | 'ul' | 'li'; + content?: Content; + data?: Data; + style?: StructuredContentStyle; + /** + * Defines the language of an element in the format defined by RFC 5646. + */ + lang?: string; +}; + +export type ImageElementBase = { + data?: Data; + /** + * Path to the image file in the archive. + */ + path: string; + /** + * Preferred width of the image. + */ + width?: number; + /** + * Preferred width of the image. + */ + height?: number; + /** + * Preferred width of the image. + * This is only used in the internal database. + */ + preferredWidth?: number; + /** + * Preferred width of the image. + * This is only used in the internal database. + */ + preferredHeight?: number; + /** + * Hover text for the image. + */ + title?: string; + /** + * Description of the image. + */ + description?: string; + /** + * Whether or not the image should appear pixelated at sizes larger than the image's native resolution. + */ + pixelated?: boolean; + /** + * Controls how the image is rendered. The value of this field supersedes the pixelated field. + */ + imageRendering?: ImageRendering; + /** + * Controls the appearance of the image. The 'monochrome' value will mask the opaque parts of the image using the current text color. + */ + appearance?: ImageAppearance; + /** + * Whether or not a background color is displayed behind the image. + */ + background?: boolean; + /** + * Whether or not the image is collapsed by default. + */ + collapsed?: boolean; + /** + * Whether or not the image can be collapsed. + */ + collapsible?: boolean; + /** + * This property is not defined on the base class. + */ + verticalAlign?: undefined; + /** + * This property is not defined on the base class. + */ + sizeUnits?: undefined; +}; + +export type ImageElement = ImageElementBase & { + tag: 'img'; + /** + * This element doesn't support children. + */ + content?: undefined; + /** + * The vertical alignment of the image. + */ + verticalAlign?: VerticalAlign; + /** + * The units for the width and height. + */ + sizeUnits?: SizeUnits; +}; + +export type LinkElement = { + tag: 'a'; + content?: Content; + /** + * The URL for the link. URLs starting with a ? are treated as internal links to other dictionary content. + */ + href: string; + /** + * Defines the language of an element in the format defined by RFC 5646. + */ + lang?: string; +}; + +export type Element = LineBreak | UnstyledElement | TableElement | StyledElement | ImageElement | LinkElement; + +export type Content = string | Element | Content[]; diff --git a/types/ext/task-accumulator.d.ts b/types/ext/task-accumulator.d.ts new file mode 100644 index 00000000..772949f6 --- /dev/null +++ b/types/ext/task-accumulator.d.ts @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export interface Task { + data: V; + stale: boolean; +} diff --git a/types/ext/template-patcher.d.ts b/types/ext/template-patcher.d.ts new file mode 100644 index 00000000..852d3768 --- /dev/null +++ b/types/ext/template-patcher.d.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type Patch = { + addition: string; + modifications: { + current: string; + replacement: string; + }[]; +}; diff --git a/types/ext/template-renderer-frame-api.d.ts b/types/ext/template-renderer-frame-api.d.ts new file mode 100644 index 00000000..e00a0711 --- /dev/null +++ b/types/ext/template-renderer-frame-api.d.ts @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; + +export type MessageData = { + action: string; + params: Core.SerializableObject; + id: string; +}; diff --git a/types/ext/template-renderer.d.ts b/types/ext/template-renderer.d.ts new file mode 100644 index 00000000..169fee78 --- /dev/null +++ b/types/ext/template-renderer.d.ts @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as AnkiNoteBuilder from './anki-note-builder'; +import type * as AnkiTemplates from './anki-templates'; +import type * as Core from './core'; + +export type RenderResult = { + result: string; + requirements: AnkiNoteBuilder.Requirement[]; +}; + +export type RenderMultiItem = { + template: string; + templateItems: RenderMultiTemplateItem[]; +}; + +export type RenderMultiTemplateItem = { + type: AnkiTemplates.RenderMode; + commonData: AnkiNoteBuilder.CommonData; + datas: PartialOrCompositeRenderData[]; +}; + +export type PartialRenderData = { + marker: string; + commonData?: undefined; +}; + +export type CompositeRenderData = { + marker: string; + commonData: AnkiNoteBuilder.CommonData; +}; + +export type PartialOrCompositeRenderData = PartialRenderData | CompositeRenderData; + +export type DataType = { + modifier: (data: CompositeRenderData) => AnkiTemplates.NoteData; + composeData: (data: PartialOrCompositeRenderData, commonData: AnkiNoteBuilder.CommonData) => CompositeRenderData; +}; + +export type HelperOptionsFunction = (context: unknown) => TResult; + +export type HelperOptions = { + fn: HelperOptionsFunction; + inverse: HelperOptionsFunction; + hash: Core.SafeAny; + data?: Core.SafeAny; +}; + +export type HelperFunction = (args: unknown[], context: unknown, options: HelperOptions) => TReturn; + +export type HelperFunctionsDescriptor = [ + name: string, + helper: HelperFunction, +][]; + +export type SetupCallbackResult = { + requirements: AnkiNoteBuilder.Requirement[]; +}; + +export type CleanupCallbackResult = void; diff --git a/types/ext/text-scanner.d.ts b/types/ext/text-scanner.d.ts new file mode 100644 index 00000000..494c1a52 --- /dev/null +++ b/types/ext/text-scanner.d.ts @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Dictionary from './dictionary'; +import type * as Display from './display'; +import type * as Input from './input'; +import type * as Settings from './settings'; +import type * as TextSource from './text-source'; + +export type SearchResultDetail = { + documentTitle: string; +}; + +export type Options = { + inputs?: InputOptionsOuter[]; + deepContentScan?: boolean; + normalizeCssZoom?: boolean; + selectText?: boolean; + delay?: number; + touchInputEnabled?: boolean; + pointerEventsEnabled?: boolean; + scanLength?: number; + layoutAwareScan?: boolean; + preventMiddleMouse?: boolean; + matchTypePrefix?: boolean; + sentenceParsingOptions?: SentenceParsingOptions; +}; + +export type InputOptionsOuter = { + include: string; + exclude: string; + types: { + mouse: boolean; + touch: boolean; + pen: boolean; + }; + options: InputOptions; +}; + +export type InputOptions = { + searchTerms: boolean; + searchKanji: boolean; + scanOnTouchMove: boolean; + scanOnTouchPress: boolean; + scanOnTouchRelease: boolean; + scanOnPenMove: boolean; + scanOnPenHover: boolean; + scanOnPenReleaseHover: boolean; + scanOnPenPress: boolean; + scanOnPenRelease: boolean; + preventTouchScrolling: boolean; + preventPenScrolling: boolean; +}; + +export type SentenceParsingOptions = { + scanExtent: number; + terminationCharacterMode: Settings.SentenceTerminationCharacterMode; + terminationCharacters: Settings.SentenceParsingTerminationCharacterOption[]; +}; + +export type InputConfig = { + include: string[]; + exclude: string[]; + types: Set; + searchTerms: boolean; + searchKanji: boolean; + scanOnTouchMove: boolean; + scanOnTouchPress: boolean; + scanOnTouchRelease: boolean; + scanOnPenMove: boolean; + scanOnPenHover: boolean; + scanOnPenReleaseHover: boolean; + scanOnPenPress: boolean; + scanOnPenRelease: boolean; + preventTouchScrolling: boolean; + preventPenScrolling: boolean; +}; + +export type SearchedEventDetails = { + textScanner: TextScanner; + type: Display.PageType | null; + dictionaryEntries: Dictionary.DictionaryEntry[] | null; + sentence: Display.HistoryStateSentence | null; + inputInfo: InputInfo; + textSource: TextSource.TextSource; + optionsContext: Settings.OptionsContext | null; + detail: SearchResultDetail | null; + error: Error | null; +}; + +export type InputInfo = { + input: InputConfig | null; + pointerType: PointerType; + eventType: PointerEventType; + passive: boolean; + modifiers: Input.Modifier[]; + modifierKeys: Input.ModifierKey[]; + detail: InputInfoDetail | undefined; +}; + +export type InputInfoDetail = { + focus: boolean; + restoreSelection: boolean; +}; + +export type EventType = 'searched' | 'clear'; + +export type GetSearchContextCallback = GetSearchContextCallbackSync | GetSearchContextCallbackAsync; + +export type GetSearchContextCallbackSync = () => SearchContext; + +export type GetSearchContextCallbackAsync = () => Promise; + +export type ConstructorDetails = { + node: HTMLElement | Window; + getSearchContext: GetSearchContextCallback; + ignoreElements?: (() => Element[]) | null; + ignorePoint?: ((x: number, y: number) => Promise) | null; + searchTerms?: boolean; + searchKanji?: boolean; + searchOnClick?: boolean; + searchOnClickOnly?: boolean; +}; + +export type SearchContext = { + optionsContext: Settings.OptionsContext; + detail?: SearchResultDetail; +}; + +export type SelectionRestoreInfo = { + ranges: Range[]; +}; + +export type TermSearchResults = { + type: 'terms'; + dictionaryEntries: Dictionary.TermDictionaryEntry[]; + sentence: Sentence; +}; + +export type KanjiSearchResults = { + type: 'kanji'; + dictionaryEntries: Dictionary.KanjiDictionaryEntry[]; + sentence: Sentence; +}; + +export type SearchResults = TermSearchResults | KanjiSearchResults; + +export type Sentence = { + text: string; + offset: number; +}; + +export type PointerType = ( + 'pen' | + 'mouse' | + 'touch' | + 'script' +); + +export type PointerEventType = ( + 'mouseMove' | + 'pointerOver' | + 'pointerDown' | + 'pointerMove' | + 'pointerUp' | + 'touchStart' | + 'touchEnd' | + 'touchMove' | + 'click' | + 'script' +); diff --git a/types/ext/text-source.d.ts b/types/ext/text-source.d.ts new file mode 100644 index 00000000..37c65bd9 --- /dev/null +++ b/types/ext/text-source.d.ts @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export type TextSource = TextSourceRange | TextSourceElement; diff --git a/types/ext/translation-internal.d.ts b/types/ext/translation-internal.d.ts new file mode 100644 index 00000000..00f51b05 --- /dev/null +++ b/types/ext/translation-internal.d.ts @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Translation from './translation'; +import type * as DictionaryDatabase from './dictionary-database'; + +export type TextDeinflectionOptions = [ + textReplacements: Translation.FindTermsTextReplacement[] | null, + halfWidth: boolean, + numeric: boolean, + alphabetic: boolean, + katakana: boolean, + hiragana: boolean, + emphatic: [collapseEmphatic: boolean, collapseEmphaticFull: boolean], +]; + +export type TextDeinflectionOptionsArrays = [ + textReplacements: (Translation.FindTermsTextReplacement[] | null)[], + halfWidth: boolean[], + numeric: boolean[], + alphabetic: boolean[], + katakana: boolean[], + hiragana: boolean[], + emphatic: [collapseEmphatic: boolean, collapseEmphaticFull: boolean][], +]; + +export enum DeinflectionRuleFlags { + None = 0x0, + VerbIchidan = 0b00000001, // Verb ichidan + VerbGodan = 0b00000010, // Verb godan + VerbSuru = 0b00000100, // Verb suru + VerbKuru = 0b00001000, // Verb kuru + VerbZuru = 0b00010000, // Verb zuru + AdjectiveI = 0b00100000, // Adjective i + IruEndingIntermediate = 0b01000000, // Intermediate -iru endings for progressive or perfect tense +} + +export type Deinflection = { + term: string; + rules: DeinflectionRuleFlags; + reasons: string[]; +}; + +export type DatabaseDeinflection = { + originalText: string; + transformedText: string; + deinflectedText: string; + rules: DeinflectionRuleFlags; + reasons: string[]; + databaseEntries: DictionaryDatabase.TermEntry[]; +}; diff --git a/types/ext/translation.d.ts b/types/ext/translation.d.ts new file mode 100644 index 00000000..3c41c9f3 --- /dev/null +++ b/types/ext/translation.d.ts @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * Copyright (C) 2022 Yomichan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Dictionary from './dictionary'; + +// Kanji + +/** + * An options object for use with `Translator.findKanji`. + */ +export type FindKanjiOptions = { + /** + * The mapping of dictionaries to search for kanji in. + * The key is the dictionary name. + */ + enabledDictionaryMap: Map; +}; + +/** + * Details about a dictionary. + */ +export type FindKanjiDictionary = { + /** + * The index of the dictionary + */ + index: number; + /** + * The priority of the dictionary + */ + priority: number; +}; + +// Terms + +/** + * An options object for use with `Translator.findTerms`. + */ +export type FindTermsOptions = { + /** + * The matching type for looking up terms. + */ + matchType: FindTermsMatchType; + /** + * Whether or not deinflection should be performed. + */ + deinflect: boolean; + /** + * The name of the primary dictionary to search. + */ + mainDictionary: string; + /** + * The name of the frequency dictionary used for sorting + */ + sortFrequencyDictionary: string | null; + /** + * The order used when using a sorting dictionary. + */ + sortFrequencyDictionaryOrder: FindTermsSortOrder; + /** + * Whether or not non-Japanese characters should be searched. + */ + removeNonJapaneseCharacters: boolean; + /** + * Whether or not half-width characters should be converted to full-width characters. + */ + convertHalfWidthCharacters: FindTermsVariantMode; + /** + * Whether or not ASCII numeric characters should be converted to full-width numeric characters. + */ + convertNumericCharacters: FindTermsVariantMode; + /** + * Whether or not alphabetic characters should be converted to kana. + */ + convertAlphabeticCharacters: FindTermsVariantMode; + /** + * Whether or not hiragana characters should be converted to katakana. + */ + convertHiraganaToKatakana: FindTermsVariantMode; + /** + * Whether or not katakana characters should be converted to hiragana. + */ + convertKatakanaToHiragana: FindTermsVariantMode; + /** + * How emphatic character sequences should be collapsed. + */ + collapseEmphaticSequences: FindTermsEmphaticSequencesMode; + /** + * An iterable sequence of text replacements to be applied during the term lookup process. + */ + textReplacements: (FindTermsTextReplacement[] | null)[]; + /** + * The mapping of dictionaries to search for terms in. + * The key is the dictionary name. + */ + enabledDictionaryMap: TermEnabledDictionaryMap; + /** + * A set of dictionary names which should have definitions removed. + */ + excludeDictionaryDefinitions: Set | null; +}; + +/** + * The matching type for looking up terms. + */ +export type FindTermsMatchType = Dictionary.TermSourceMatchType; + +/** + * A sorting order to use when finding terms. + */ +export type FindTermsSortOrder = 'ascending' | 'descending'; + +/** + * Mode describing how to handle variations. + */ +export type FindTermsVariantMode = 'false' | 'true' | 'variant'; + +/** + * Mode describing how to handle emphatic sequence variations. + */ +export type FindTermsEmphaticSequencesMode = 'false' | 'true' | 'full'; + +/** + * Information about how text should be replaced when looking up terms. + */ +export type FindTermsTextReplacement = { + /** + * The pattern to replace. + */ + pattern: RegExp; + /** + * The replacement string. This can contain special sequences, such as `$&`. + */ + replacement: string; +}; + +/** + * Details about a dictionary. + */ +export type FindTermDictionary = { + /** + * The index of the dictionary + */ + index: number; + /** + * The priority of the dictionary + */ + priority: number; + /** + * Whether or not secondary term searches are allowed for this dictionary. + */ + allowSecondarySearches: boolean; +}; + +export type TermEnabledDictionaryMap = Map; + +export type KanjiEnabledDictionaryMap = Map; diff --git a/types/ext/translator.d.ts b/types/ext/translator.d.ts new file mode 100644 index 00000000..f17b3bf6 --- /dev/null +++ b/types/ext/translator.d.ts @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Dictionary from './dictionary'; +import type * as DictionaryDatabase from './dictionary-database'; + +export type ConstructorDetails = { + /** An instance of JapaneseUtil. */ + japaneseUtil: JapaneseUtil; + /** An instance of DictionaryDatabase. */ + database: DictionaryDatabase; +}; + +/** + * Information about how popup content should be shown, specifically related to the outer popup frame. + */ +export type TermFrequencySimple = { + /** The term. */ + term: string; + /** The reading of the term. */ + reading: string | null; + /** The name of the dictionary that the term frequency originates from. */ + dictionary: string; + /** Whether or not a reading was specified. */ + hasReading: boolean; + /** The frequency value for the term. */ + frequency: number; + /** The display value for the frequency, or `null` if none is specified. */ + displayValue: string | null; + /** Whether or not the `frequency` field is derived from a parsed string. */ + displayValueParsed: boolean; +}; + +export type TagGroup = { + dictionary: string; + tagNames: string[]; +}; + +export type TagExpansionTarget = { + tags: Dictionary.Tag[]; + tagGroups: TagGroup[]; +}; + +export type DictionaryTagCache = Map; + +export type TagCache = Map; + +export type TagTargetMap = Map>; + +export type TagTargetItem = { + query: string; + dictionary: string; + tagName: string; + cache: TagCache | null; + databaseTag: DictionaryDatabase.Tag | null; + targets: Dictionary.Tag[][]; +}; + +export type DictionaryEntryGroup = { + ids: Set; + dictionaryEntries: Dictionary.TermDictionaryEntry[]; +}; + +export type SequenceQuery = { + query: number; + dictionary: string; +}; + +export type FindTermsMode = 'simple' | 'group' | 'merge' | 'split'; -- cgit v1.2.3 From 7aed9a371b0d74c0d75179a08068e8935b76d780 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 14:55:27 -0500 Subject: Update types --- ext/js/background/backend.js | 22 ++++----- ext/js/background/offscreen-proxy.js | 27 +++++++++-- ext/js/background/offscreen.js | 9 +++- ext/js/background/request-builder.js | 13 ++---- ext/js/comm/api.js | 6 +-- ext/js/comm/clipboard-reader.js | 4 +- ext/js/display/search-action-popup-controller.js | 4 +- ext/js/dom/sandbox/css-style-applier.js | 2 +- ext/js/dom/text-source-element.js | 2 +- ext/js/dom/text-source-range.js | 2 +- ext/js/general/regex-util.js | 2 +- .../__mocks__/dictionary-importer-media-loader.js | 1 + ext/js/language/dictionary-importer.js | 2 +- ext/js/language/dictionary-worker.js | 2 + ext/js/language/sandbox/japanese-util.js | 8 ++-- ext/js/language/text-scanner.js | 1 + ext/js/language/translator.js | 4 +- ext/js/media/audio-downloader.js | 6 +-- ext/js/pages/settings/backup-controller.js | 54 +++++++++------------- .../settings/recommended-permissions-controller.js | 36 +++++++++++++-- types/ext/api.d.ts | 12 +++++ types/ext/request-builder.d.ts | 2 + 22 files changed, 139 insertions(+), 82 deletions(-) (limited to 'types/ext') diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 14877cf1..be68ecf4 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -96,7 +96,7 @@ export class Backend { }); /** @type {?import('settings').Options} */ this._options = null; - /** @type {JsonSchema[]} */ + /** @type {import('../data/json-schema.js').JsonSchema[]} */ this._profileConditionsSchemaCache = []; /** @type {ProfileConditionsUtil} */ this._profileConditionsUtil = new ProfileConditionsUtil(); @@ -665,7 +665,7 @@ export class Backend { async _onApiInjectStylesheet({type, value}, sender) { const {frameId, tab} = sender; if (typeof tab !== 'object' || tab === null || typeof tab.id !== 'number') { throw new Error('Invalid tab'); } - return await this._scriptManager.injectStylesheet(type, value, tab.id, frameId, false, true, 'document_start'); + return await this._scriptManager.injectStylesheet(type, value, tab.id, frameId, false); } /** @type {import('api').Handler} */ @@ -895,13 +895,7 @@ export class Backend { } } - /** - * - * @param root0 - * @param root0.targetTabId - * @param root0.targetFrameId - * @param sender - */ + /** @type {import('api').Handler} */ _onApiOpenCrossFramePort({targetTabId, targetFrameId}, sender) { const sourceTabId = (sender && sender.tab ? sender.tab.id : null); if (typeof sourceTabId !== 'number') { @@ -922,7 +916,9 @@ export class Backend { otherTabId: sourceTabId, otherFrameId: sourceFrameId }; + /** @type {?chrome.runtime.Port} */ let sourcePort = chrome.tabs.connect(sourceTabId, {frameId: sourceFrameId, name: JSON.stringify(sourceDetails)}); + /** @type {?chrome.runtime.Port} */ let targetPort = chrome.tabs.connect(targetTabId, {frameId: targetFrameId, name: JSON.stringify(targetDetails)}); const cleanup = () => { @@ -937,8 +933,12 @@ export class Backend { } }; - sourcePort.onMessage.addListener((message) => { targetPort.postMessage(message); }); - targetPort.onMessage.addListener((message) => { sourcePort.postMessage(message); }); + sourcePort.onMessage.addListener((message) => { + if (targetPort !== null) { targetPort.postMessage(message); } + }); + targetPort.onMessage.addListener((message) => { + if (sourcePort !== null) { sourcePort.postMessage(message); } + }); sourcePort.onDisconnect.addListener(cleanup); targetPort.onDisconnect.addListener(cleanup); diff --git a/ext/js/background/offscreen-proxy.js b/ext/js/background/offscreen-proxy.js index c01f523d..0fb2f269 100644 --- a/ext/js/background/offscreen-proxy.js +++ b/ext/js/background/offscreen-proxy.js @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import {deserializeError, isObject} from '../core.js'; +import {isObject} from '../core.js'; import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; export class OffscreenProxy { @@ -158,15 +158,36 @@ export class TranslatorProxy { } export class ClipboardReaderProxy { + /** + * @param {OffscreenProxy} offscreen + */ constructor(offscreen) { + /** @type {?import('environment').Browser} */ + this._browser = null; + /** @type {OffscreenProxy} */ this._offscreen = offscreen; } + /** @type {?import('environment').Browser} */ + get browser() { return this._browser; } + set browser(value) { + if (this._browser === value) { return; } + this._browser = value; + this._offscreen.sendMessagePromise({action: 'clipboardSetBrowserOffsecreen', params: {value}}); + } + + /** + * @param {boolean} useRichText + * @returns {Promise} + */ async getText(useRichText) { - return this._offscreen.sendMessagePromise({action: 'clipboardGetTextOffscreen', params: {useRichText}}); + return await this._offscreen.sendMessagePromise({action: 'clipboardGetTextOffscreen', params: {useRichText}}); } + /** + * @returns {Promise} + */ async getImage() { - return this._offscreen.sendMessagePromise({action: 'clipboardGetImageOffscreen'}); + return await this._offscreen.sendMessagePromise({action: 'clipboardGetImageOffscreen'}); } } diff --git a/ext/js/background/offscreen.js b/ext/js/background/offscreen.js index 27cee8c4..6302aa84 100644 --- a/ext/js/background/offscreen.js +++ b/ext/js/background/offscreen.js @@ -50,6 +50,7 @@ export class Offscreen { this._messageHandlers = new Map([ ['clipboardGetTextOffscreen', {async: true, contentScript: true, handler: this._getTextHandler.bind(this)}], ['clipboardGetImageOffscreen', {async: true, contentScript: true, handler: this._getImageHandler.bind(this)}], + ['clipboardSetBrowserOffsecreen', {async: false, contentScript: true, handler: this._setClipboardBrowser.bind(this)}], ['databasePrepareOffscreen', {async: true, contentScript: true, handler: this._prepareDatabaseHandler.bind(this)}], ['getDictionaryInfoOffscreen', {async: true, contentScript: true, handler: this._getDictionaryInfoHandler.bind(this)}], ['databasePurgeOffscreen', {async: true, contentScript: true, handler: this._purgeDatabaseHandler.bind(this)}], @@ -59,7 +60,6 @@ export class Offscreen { ['findTermsOffscreen', {async: true, contentScript: true, handler: this._findTermsHandler.bind(this)}], ['getTermFrequenciesOffscreen', {async: true, contentScript: true, handler: this._getTermFrequenciesHandler.bind(this)}], ['clearDatabaseCachesOffscreen', {async: false, contentScript: true, handler: this._clearDatabaseCachesHandler.bind(this)}] - ]); const onMessage = this._onMessage.bind(this); @@ -76,6 +76,13 @@ export class Offscreen { return this._clipboardReader.getImage(); } + /** + * @param {{value: import('environment').Browser}} details + */ + _setClipboardBrowser({value}) { + this._clipboardReader.browser = value; + } + _prepareDatabaseHandler() { if (this._prepareDatabasePromise !== null) { return this._prepareDatabasePromise; diff --git a/ext/js/background/request-builder.js b/ext/js/background/request-builder.js index 48fe2dd9..5ae7fbf5 100644 --- a/ext/js/background/request-builder.js +++ b/ext/js/background/request-builder.js @@ -21,12 +21,6 @@ * with additional controls over anonymity and error handling. */ export class RequestBuilder { - /** - * A progress callback for a fetch read. - * @callback ProgressCallback - * @param {boolean} complete Whether or not the data has been completely read. - */ - /** * Creates a new instance. */ @@ -109,14 +103,17 @@ export class RequestBuilder { /** * Reads the array buffer body of a fetch response, with an optional `onProgress` callback. * @param {Response} response The response of a `fetch` call. - * @param {ProgressCallback} onProgress The progress callback + * @param {?import('request-builder.js').ProgressCallback} onProgress The progress callback * @returns {Promise} The resulting binary data. */ static async readFetchResponseArrayBuffer(response, onProgress) { let reader; try { if (typeof onProgress === 'function') { - reader = response.body.getReader(); + const {body} = response; + if (body !== null) { + reader = body.getReader(); + } } } catch (e) { // Not supported diff --git a/ext/js/comm/api.js b/ext/js/comm/api.js index 62dc98b1..0cfdba59 100644 --- a/ext/js/comm/api.js +++ b/ext/js/comm/api.js @@ -415,9 +415,9 @@ export class API { } /** - * - * @param targetTabId - * @param targetFrameId + * @param {import('api').OpenCrossFramePortDetails['targetTabId']} targetTabId + * @param {import('api').OpenCrossFramePortDetails['targetFrameId']} targetFrameId + * @returns {Promise} */ openCrossFramePort(targetTabId, targetFrameId) { return this._invoke('openCrossFramePort', {targetTabId, targetFrameId}); diff --git a/ext/js/comm/clipboard-reader.js b/ext/js/comm/clipboard-reader.js index c7b45a7c..364e31a3 100644 --- a/ext/js/comm/clipboard-reader.js +++ b/ext/js/comm/clipboard-reader.js @@ -29,7 +29,7 @@ export class ClipboardReader { constructor({document=null, pasteTargetSelector=null, richContentPasteTargetSelector=null}) { /** @type {?Document} */ this._document = document; - /** @type {?string} */ + /** @type {?import('environment').Browser} */ this._browser = null; /** @type {?HTMLTextAreaElement} */ this._pasteTarget = null; @@ -43,7 +43,7 @@ export class ClipboardReader { /** * Gets the browser being used. - * @type {?string} + * @type {?import('environment').Browser} */ get browser() { return this._browser; diff --git a/ext/js/display/search-action-popup-controller.js b/ext/js/display/search-action-popup-controller.js index 733fd70a..3a2057a1 100644 --- a/ext/js/display/search-action-popup-controller.js +++ b/ext/js/display/search-action-popup-controller.js @@ -18,10 +18,10 @@ export class SearchActionPopupController { /** - * @param {SearchPersistentStateController} searchPersistentStateController + * @param {import('./search-persistent-state-controller.js').SearchPersistentStateController} searchPersistentStateController */ constructor(searchPersistentStateController) { - /** @type {SearchPersistentStateController} */ + /** @type {import('./search-persistent-state-controller.js').SearchPersistentStateController} */ this._searchPersistentStateController = searchPersistentStateController; } diff --git a/ext/js/dom/sandbox/css-style-applier.js b/ext/js/dom/sandbox/css-style-applier.js index 332ca4f2..ea36a02d 100644 --- a/ext/js/dom/sandbox/css-style-applier.js +++ b/ext/js/dom/sandbox/css-style-applier.js @@ -24,7 +24,7 @@ export class CssStyleApplier { /** * Creates a new instance of the class. * @param {string} styleDataUrl The local URL to the JSON file continaing the style rules. - * The style rules should follow the format of {@link CssStyleApplierRawStyleData}. + * The style rules should follow the format of `CssStyleApplierRawStyleData`. */ constructor(styleDataUrl) { /** @type {string} */ diff --git a/ext/js/dom/text-source-element.js b/ext/js/dom/text-source-element.js index 47c18e30..40ff5cc9 100644 --- a/ext/js/dom/text-source-element.js +++ b/ext/js/dom/text-source-element.js @@ -173,7 +173,7 @@ export class TextSourceElement { /** * Checks whether another text source has the same starting point. - * @param {TextSourceElement|TextSourceRange} other The other source to test. + * @param {import('text-source').TextSource} other The other source to test. * @returns {boolean} `true` if the starting points are equivalent, `false` otherwise. */ hasSameStart(other) { diff --git a/ext/js/dom/text-source-range.js b/ext/js/dom/text-source-range.js index 5dbbd636..fd09fdda 100644 --- a/ext/js/dom/text-source-range.js +++ b/ext/js/dom/text-source-range.js @@ -206,7 +206,7 @@ export class TextSourceRange { /** * Checks whether another text source has the same starting point. - * @param {TextSourceElement|TextSourceRange} other The other source to test. + * @param {import('text-source').TextSource} other The other source to test. * @returns {boolean} `true` if the starting points are equivalent, `false` otherwise. * @throws {Error} An exception can be thrown if `Range.compareBoundaryPoints` fails, * which shouldn't happen, but the handler is kept in case of unexpected errors. diff --git a/ext/js/general/regex-util.js b/ext/js/general/regex-util.js index 726ce9f2..62248968 100644 --- a/ext/js/general/regex-util.js +++ b/ext/js/general/regex-util.js @@ -25,7 +25,7 @@ export class RegexUtil { * Applies string.replace using a regular expression and replacement string as arguments. * A source map of the changes is also maintained. * @param {string} text A string of the text to replace. - * @param {TextSourceMap} sourceMap An instance of `TextSourceMap` which corresponds to `text`. + * @param {import('./text-source-map.js').TextSourceMap} sourceMap An instance of `TextSourceMap` which corresponds to `text`. * @param {RegExp} pattern A regular expression to use as the replacement. * @param {string} replacement A replacement string that follows the format of the standard * JavaScript regular expression replacement string. diff --git a/ext/js/language/__mocks__/dictionary-importer-media-loader.js b/ext/js/language/__mocks__/dictionary-importer-media-loader.js index 96f0f6dd..ffda29b3 100644 --- a/ext/js/language/__mocks__/dictionary-importer-media-loader.js +++ b/ext/js/language/__mocks__/dictionary-importer-media-loader.js @@ -17,6 +17,7 @@ */ export class DictionaryImporterMediaLoader { + /** @type {import('dictionary-importer-media-loader').GetImageDetailsFunction} */ async getImageDetails(content) { // Placeholder values return {content, width: 100, height: 100}; diff --git a/ext/js/language/dictionary-importer.js b/ext/js/language/dictionary-importer.js index aa6d7ae6..2a2f4063 100644 --- a/ext/js/language/dictionary-importer.js +++ b/ext/js/language/dictionary-importer.js @@ -36,7 +36,7 @@ export class DictionaryImporter { } /** - * @param {DictionaryDatabase} dictionaryDatabase + * @param {import('./dictionary-database.js').DictionaryDatabase} dictionaryDatabase * @param {ArrayBuffer} archiveContent * @param {import('dictionary-importer').ImportDetails} details * @returns {Promise} diff --git a/ext/js/language/dictionary-worker.js b/ext/js/language/dictionary-worker.js index 3e78a6ff..3119dd7b 100644 --- a/ext/js/language/dictionary-worker.js +++ b/ext/js/language/dictionary-worker.js @@ -157,6 +157,8 @@ export class DictionaryWorker { resolve(result2); } else { // If formatResult is not provided, the response is assumed to be the same type + // For some reason, eslint thinks the TResponse type is undefined + // eslint-disable-next-line jsdoc/no-undefined-types resolve(/** @type {TResponse} */ (/** @type {unknown} */ (result))); } } diff --git a/ext/js/language/sandbox/japanese-util.js b/ext/js/language/sandbox/japanese-util.js index f7f20b3b..4c9c46bd 100644 --- a/ext/js/language/sandbox/japanese-util.js +++ b/ext/js/language/sandbox/japanese-util.js @@ -466,7 +466,7 @@ export class JapaneseUtil { /** * @param {string} text - * @param {?TextSourceMap} [sourceMap] + * @param {?import('../../general/text-source-map.js').TextSourceMap} [sourceMap] * @returns {string} */ convertHalfWidthKanaToFullWidth(text, sourceMap=null) { @@ -513,7 +513,7 @@ export class JapaneseUtil { /** * @param {string} text - * @param {?TextSourceMap} sourceMap + * @param {?import('../../general/text-source-map.js').TextSourceMap} sourceMap * @returns {string} */ convertAlphabeticToKana(text, sourceMap=null) { @@ -676,7 +676,7 @@ export class JapaneseUtil { /** * @param {string} text * @param {boolean} fullCollapse - * @param {?TextSourceMap} [sourceMap] + * @param {?import('../../general/text-source-map.js').TextSourceMap} [sourceMap] * @returns {string} */ collapseEmphaticSequences(text, fullCollapse, sourceMap=null) { @@ -816,7 +816,7 @@ export class JapaneseUtil { /** * @param {string} text - * @param {?TextSourceMap} sourceMap + * @param {?import('../../general/text-source-map.js').TextSourceMap} sourceMap * @param {number} sourceMapStart * @returns {string} */ diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js index b4d9a642..f6bcde8d 100644 --- a/ext/js/language/text-scanner.js +++ b/ext/js/language/text-scanner.js @@ -18,6 +18,7 @@ import {EventDispatcher, EventListenerCollection, clone, log} from '../core.js'; import {DocumentUtil} from '../dom/document-util.js'; +import {TextSourceElement} from '../dom/text-source-element.js'; import {yomitan} from '../yomitan.js'; /** diff --git a/ext/js/language/translator.js b/ext/js/language/translator.js index 67cc53c6..c21b16b1 100644 --- a/ext/js/language/translator.js +++ b/ext/js/language/translator.js @@ -29,9 +29,9 @@ export class Translator { * @param {import('translator').ConstructorDetails} details The details for the class. */ constructor({japaneseUtil, database}) { - /** @type {JapaneseUtil} */ + /** @type {import('./sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; - /** @type {DictionaryDatabase} */ + /** @type {import('./dictionary-database.js').DictionaryDatabase} */ this._database = database; /** @type {?Deinflector} */ this._deinflector = null; diff --git a/ext/js/media/audio-downloader.js b/ext/js/media/audio-downloader.js index 7b236790..0847d479 100644 --- a/ext/js/media/audio-downloader.js +++ b/ext/js/media/audio-downloader.js @@ -25,10 +25,10 @@ import {SimpleDOMParser} from '../dom/simple-dom-parser.js'; export class AudioDownloader { /** - * @param {{japaneseUtil: JapaneseUtil, requestBuilder: RequestBuilder}} details + * @param {{japaneseUtil: import('../language/sandbox/japanese-util.js').JapaneseUtil, requestBuilder: RequestBuilder}} details */ constructor({japaneseUtil, requestBuilder}) { - /** @type {JapaneseUtil} */ + /** @type {import('../language/sandbox/japanese-util.js').JapaneseUtil} */ this._japaneseUtil = japaneseUtil; /** @type {RequestBuilder} */ this._requestBuilder = requestBuilder; @@ -314,7 +314,7 @@ export class AudioDownloader { */ async _downloadAudioFromUrl(url, sourceType, idleTimeout) { let signal; - /** @type {?(done: boolean) => void} */ + /** @type {?import('request-builder.js').ProgressCallback} */ let onProgress = null; /** @type {?number} */ let idleTimer = null; diff --git a/ext/js/pages/settings/backup-controller.js b/ext/js/pages/settings/backup-controller.js index 50a50b1a..52c5f418 100644 --- a/ext/js/pages/settings/backup-controller.js +++ b/ext/js/pages/settings/backup-controller.js @@ -534,12 +534,11 @@ export class BackupController { // Exporting Dictionaries Database /** - * - * @param message - * @param isWarning + * @param {string} message + * @param {boolean} [isWarning] */ _databaseExportImportErrorMessage(message, isWarning=false) { - const errorMessageContainer = document.querySelector('#db-ops-error-report'); + const errorMessageContainer = /** @type {HTMLElement} */ (document.querySelector('#db-ops-error-report')); errorMessageContainer.style.display = 'block'; errorMessageContainer.textContent = message; @@ -553,15 +552,11 @@ export class BackupController { } /** - * - * @param root0 - * @param root0.totalRows - * @param root0.completedRows - * @param root0.done + * @param {{totalRows: number, completedRows: number, done: boolean}} details */ _databaseExportProgressCallback({totalRows, completedRows, done}) { console.log(`Progress: ${completedRows} of ${totalRows} rows completed`); - const messageContainer = document.querySelector('#db-ops-progress-report'); + const messageContainer = /** @type {HTMLElement} */ (document.querySelector('#db-ops-progress-report')); messageContainer.style.display = 'block'; messageContainer.textContent = `Export Progress: ${completedRows} of ${totalRows} rows completed`; @@ -572,8 +567,8 @@ export class BackupController { } /** - * - * @param databaseName + * @param {string} databaseName + * @returns {Promise} */ async _exportDatabase(databaseName) { const db = await new Dexie(databaseName).open(); @@ -592,7 +587,7 @@ export class BackupController { return; } - const errorMessageContainer = document.querySelector('#db-ops-error-report'); + const errorMessageContainer = /** @type {HTMLElement} */ (document.querySelector('#db-ops-error-report')); errorMessageContainer.style.display = 'none'; const date = new Date(Date.now()); @@ -616,15 +611,11 @@ export class BackupController { // Importing Dictionaries Database /** - * - * @param root0 - * @param root0.totalRows - * @param root0.completedRows - * @param root0.done + * @param {{totalRows: number, completedRows: number, done: boolean}} details */ _databaseImportProgressCallback({totalRows, completedRows, done}) { console.log(`Progress: ${completedRows} of ${totalRows} rows completed`); - const messageContainer = document.querySelector('#db-ops-progress-report'); + const messageContainer = /** @type {HTMLElement} */ (document.querySelector('#db-ops-progress-report')); messageContainer.style.display = 'block'; messageContainer.style.color = '#4169e1'; messageContainer.textContent = `Import Progress: ${completedRows} of ${totalRows} rows completed`; @@ -637,9 +628,8 @@ export class BackupController { } /** - * - * @param databaseName - * @param file + * @param {string} databaseName + * @param {File} file */ async _importDatabase(databaseName, file) { await yomitan.api.purgeDatabase(); @@ -648,16 +638,13 @@ export class BackupController { yomitan.trigger('storageChanged'); } - /** - * - */ + /** */ _onSettingsImportDatabaseClick() { - document.querySelector('#settings-import-db').click(); + /** @type {HTMLElement} */ (document.querySelector('#settings-import-db')).click(); } /** - * - * @param e + * @param {Event} e */ async _onSettingsImportDatabaseChange(e) { if (this._settingsExportDatabaseToken !== null) { @@ -666,22 +653,23 @@ export class BackupController { return; } - const errorMessageContainer = document.querySelector('#db-ops-error-report'); + const errorMessageContainer = /** @type {HTMLElement} */ (document.querySelector('#db-ops-error-report')); errorMessageContainer.style.display = 'none'; - const files = e.target.files; - if (files.length === 0) { return; } + const element = /** @type {HTMLInputElement} */ (e.currentTarget); + const files = element.files; + if (files === null || files.length === 0) { return; } const pageExitPrevention = this._settingsController.preventPageExit(); const file = files[0]; - e.target.value = null; + element.value = ''; try { const token = {}; this._settingsExportDatabaseToken = token; await this._importDatabase(this._dictionariesDatabaseName, file); } catch (error) { console.log(error); - const messageContainer = document.querySelector('#db-ops-progress-report'); + const messageContainer = /** @type {HTMLElement} */ (document.querySelector('#db-ops-progress-report')); messageContainer.style.color = 'red'; this._databaseExportImportErrorMessage('Encountered errors when importing. Please restart the browser and try again. If it continues to fail, reinstall Yomitan and import dictionaries one-by-one.'); } finally { diff --git a/ext/js/pages/settings/recommended-permissions-controller.js b/ext/js/pages/settings/recommended-permissions-controller.js index e04dbdf7..b19311aa 100644 --- a/ext/js/pages/settings/recommended-permissions-controller.js +++ b/ext/js/pages/settings/recommended-permissions-controller.js @@ -19,13 +19,21 @@ import {EventListenerCollection} from '../../core.js'; export class RecommendedPermissionsController { + /** + * @param {import('./settings-controller.js').SettingsController} settingsController + */ constructor(settingsController) { + /** @type {import('./settings-controller.js').SettingsController} */ this._settingsController = settingsController; + /** @type {?NodeListOf} */ this._originToggleNodes = null; + /** @type {EventListenerCollection} */ this._eventListeners = new EventListenerCollection(); + /** @type {?HTMLElement} */ this._errorContainer = null; } + /** */ async prepare() { this._originToggleNodes = document.querySelectorAll('.recommended-permissions-toggle'); this._errorContainer = document.querySelector('#recommended-permissions-error'); @@ -39,35 +47,53 @@ export class RecommendedPermissionsController { // Private + /** + * @param {import('settings-controller').PermissionsChangedEvent} details + */ _onPermissionsChanged({permissions}) { this._eventListeners.removeAllEventListeners(); const originsSet = new Set(permissions.origins); - for (const node of this._originToggleNodes) { - node.checked = originsSet.has(node.dataset.origin); + if (this._originToggleNodes !== null) { + for (const node of this._originToggleNodes) { + const {origin} = node.dataset; + node.checked = typeof origin === 'string' && originsSet.has(origin); + } } } + /** + * @param {Event} e + */ _onOriginToggleChange(e) { - const node = e.currentTarget; + const node = /** @type {HTMLInputElement} */ (e.currentTarget); const value = node.checked; node.checked = !value; const {origin} = node.dataset; + if (typeof origin !== 'string') { return; } this._setOriginPermissionEnabled(origin, value); } + /** */ async _updatePermissions() { const permissions = await this._settingsController.permissionsUtil.getAllPermissions(); this._onPermissionsChanged({permissions}); } + /** + * @param {string} origin + * @param {boolean} enabled + * @returns {Promise} + */ async _setOriginPermissionEnabled(origin, enabled) { let added = false; try { added = await this._settingsController.permissionsUtil.setPermissionsGranted({origins: [origin]}, enabled); } catch (e) { - this._errorContainer.hidden = false; - this._errorContainer.textContent = e.message; + if (this._errorContainer !== null) { + this._errorContainer.hidden = false; + this._errorContainer.textContent = e instanceof Error ? e.message : `${e}`; + } } if (!added) { return false; } await this._updatePermissions(); diff --git a/types/ext/api.d.ts b/types/ext/api.d.ts index 19a62c1c..6b7b4b19 100644 --- a/types/ext/api.d.ts +++ b/types/ext/api.d.ts @@ -444,6 +444,18 @@ export type LoadExtensionScriptsDetails = { export type LoadExtensionScriptsResult = void; +// openCrossFramePort + +export type OpenCrossFramePortDetails = { + targetTabId: number; + targetFrameId: number; +}; + +export type OpenCrossFramePortResult = { + targetTabId: number; + targetFrameId: number; +}; + // requestBackendReadySignal export type RequestBackendReadySignalDetails = Record; diff --git a/types/ext/request-builder.d.ts b/types/ext/request-builder.d.ts index 0acf5ede..8f375754 100644 --- a/types/ext/request-builder.d.ts +++ b/types/ext/request-builder.d.ts @@ -19,3 +19,5 @@ export type FetchEventListeners = { onBeforeSendHeaders: ((details: chrome.webRequest.WebRequestHeadersDetails) => (chrome.webRequest.BlockingResponse | void)) | null; onErrorOccurred: ((details: chrome.webRequest.WebResponseErrorDetails) => void) | null; }; + +export type ProgressCallback = (complete: boolean) => void; -- cgit v1.2.3 From d897c3b069f80fd170b7f1d0c0362fec4037d714 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 16:09:55 -0500 Subject: Update dictionary importer --- ext/js/language/dictionary-importer.js | 130 ++++++++++++++++++++------------- jsconfig.json | 5 +- package-lock.json | 13 ++++ package.json | 1 + types/ext/dictionary-importer.d.ts | 27 ++++++- 5 files changed, 123 insertions(+), 53 deletions(-) (limited to 'types/ext') diff --git a/ext/js/language/dictionary-importer.js b/ext/js/language/dictionary-importer.js index 2a2f4063..115e0726 100644 --- a/ext/js/language/dictionary-importer.js +++ b/ext/js/language/dictionary-importer.js @@ -16,10 +16,23 @@ * along with this program. If not, see . */ -import * as ajvSchemas from '../../lib/validate-schemas.js'; -import {BlobWriter, TextWriter, Uint8ArrayReader, ZipReader, configure} from '../../lib/zip.js'; +import * as ajvSchemas0 from '../../lib/validate-schemas.js'; +import { + BlobWriter as BlobWriter0, + TextWriter as TextWriter0, + Uint8ArrayReader as Uint8ArrayReader0, + ZipReader as ZipReader0, + configure +} from '../../lib/zip.js'; import {stringReverse} from '../core.js'; import {MediaUtil} from '../media/media-util.js'; +import {ExtensionError} from '../core/extension-error.js'; + +const ajvSchemas = /** @type {import('dictionary-importer').CompiledSchemaValidators} */ (/** @type {unknown} */ (ajvSchemas0)); +const BlobWriter = /** @type {typeof import('@zip.js/zip.js').BlobWriter} */ (/** @type {unknown} */ (BlobWriter0)); +const TextWriter = /** @type {typeof import('@zip.js/zip.js').TextWriter} */ (/** @type {unknown} */ (TextWriter0)); +const Uint8ArrayReader = /** @type {typeof import('@zip.js/zip.js').Uint8ArrayReader} */ (/** @type {unknown} */ (Uint8ArrayReader0)); +const ZipReader = /** @type {typeof import('@zip.js/zip.js').ZipReader} */ (/** @type {unknown} */ (ZipReader0)); export class DictionaryImporter { /** @@ -62,21 +75,21 @@ export class DictionaryImporter { const zipFileReader = new Uint8ArrayReader(new Uint8Array(archiveContent)); const zipReader = new ZipReader(zipFileReader); const zipEntries = await zipReader.getEntries(); - const zipEntriesObject = {}; + /** @type {import('dictionary-importer').ArchiveFileMap} */ + const fileMap = new Map(); for (const entry of zipEntries) { - zipEntriesObject[entry.filename] = entry; + fileMap.set(entry.filename, entry); } // Read and validate index const indexFileName = 'index.json'; - const indexFile = zipEntriesObject[indexFileName]; - if (!indexFile) { + const indexFile = fileMap.get(indexFileName); + if (typeof indexFile === 'undefined') { throw new Error('No dictionary index found in archive'); } + const indexFile2 = /** @type {import('@zip.js/zip.js').Entry} */ (indexFile); - const indexContent = await indexFile.getData( - new TextWriter() - ); - const index = JSON.parse(indexContent); + const indexContent = await this._getData(indexFile2, new TextWriter()); + const index = /** @type {import('dictionary-data').Index} */ (JSON.parse(indexContent)); if (!ajvSchemas.dictionaryIndex(index)) { throw this._formatAjvSchemaError(ajvSchemas.dictionaryIndex, indexFileName); @@ -99,11 +112,11 @@ export class DictionaryImporter { const dataBankSchemas = this._getDataBankSchemas(version); // Files - const termFiles = this._getArchiveFiles(zipEntriesObject, 'term_bank_?.json'); - const termMetaFiles = this._getArchiveFiles(zipEntriesObject, 'term_meta_bank_?.json'); - const kanjiFiles = this._getArchiveFiles(zipEntriesObject, 'kanji_bank_?.json'); - const kanjiMetaFiles = this._getArchiveFiles(zipEntriesObject, 'kanji_meta_bank_?.json'); - const tagFiles = this._getArchiveFiles(zipEntriesObject, 'tag_bank_?.json'); + const termFiles = this._getArchiveFiles(fileMap, 'term_bank_?.json'); + const termMetaFiles = this._getArchiveFiles(fileMap, 'term_meta_bank_?.json'); + const kanjiFiles = this._getArchiveFiles(fileMap, 'kanji_bank_?.json'); + const kanjiMetaFiles = this._getArchiveFiles(fileMap, 'kanji_meta_bank_?.json'); + const tagFiles = this._getArchiveFiles(fileMap, 'tag_bank_?.json'); // Load data this._progressNextStep(termFiles.length + termMetaFiles.length + kanjiFiles.length + kanjiMetaFiles.length + tagFiles.length); @@ -153,7 +166,7 @@ export class DictionaryImporter { // Async requirements this._progressNextStep(requirements.length); - const {media} = await this._resolveAsyncRequirements(requirements, zipEntriesObject); + const {media} = await this._resolveAsyncRequirements(requirements, fileMap); // Add dictionary descriptor this._progressNextStep(termList.length + termMetaList.length + kanjiList.length + kanjiMetaList.length + tagList.length + media.length); @@ -274,20 +287,20 @@ export class DictionaryImporter { } /** - * - * @param schema - * @param fileName + * @param {import('ajv').ValidateFunction} schema + * @param {string} fileName + * @returns {ExtensionError} */ _formatAjvSchemaError(schema, fileName) { - const e2 = new Error(`Dictionary has invalid data in '${fileName}'`); + const e2 = new ExtensionError(`Dictionary has invalid data in '${fileName}'`); e2.data = schema.errors; return e2; } /** - * - * @param version + * @param {number} version + * @returns {import('dictionary-importer').CompiledSchemaNameArray} */ _getDataBankSchemas(version) { const termBank = ( @@ -402,13 +415,15 @@ export class DictionaryImporter { } /** - * - * @param requirements - * @param zipEntriesObject + * @param {import('dictionary-importer').ImportRequirement[]} requirements + * @param {import('dictionary-importer').ArchiveFileMap} fileMap + * @returns {Promise<{media: import('dictionary-database').MediaDataArrayBufferContent[]}>} */ - async _resolveAsyncRequirements(requirements, zipEntriesObject) { + async _resolveAsyncRequirements(requirements, fileMap) { + /** @type {Map} */ const media = new Map(); - const context = {zipEntriesObject, media}; + /** @type {import('dictionary-importer').ImportRequirementContext} */ + const context = {fileMap, media}; for (const requirement of requirements) { await this._resolveAsyncRequirement(context, requirement); @@ -537,15 +552,13 @@ export class DictionaryImporter { } // Find file in archive - const file = context.zipEntriesObject[path]; - if (file === null) { + const file = context.fileMap.get(path); + if (typeof file === 'undefined') { throw createError('Could not find image'); } // Load file content - let content = await (await file.getData( - new BlobWriter() - )).arrayBuffer(); + let content = await (await this._getData(file, new BlobWriter())).arrayBuffer(); const mediaType = MediaUtil.getImageMediaTypeFromFileName(path); if (mediaType === null) { @@ -683,46 +696,48 @@ export class DictionaryImporter { } /** - * - * @param zipEntriesObject - * @param fileNameFormat + * @param {import('dictionary-importer').ArchiveFileMap} fileMap + * @param {string} fileNameFormat + * @returns {import('@zip.js/zip.js').Entry[]} */ - _getArchiveFiles(zipEntriesObject, fileNameFormat) { + _getArchiveFiles(fileMap, fileNameFormat) { const indexPosition = fileNameFormat.indexOf('?'); const prefix = fileNameFormat.substring(0, indexPosition); const suffix = fileNameFormat.substring(indexPosition + 1); + /** @type {import('@zip.js/zip.js').Entry[]} */ const results = []; - for (const f of Object.keys(zipEntriesObject)) { - if (f.startsWith(prefix) && f.endsWith(suffix)) { - results.push(zipEntriesObject[f]); + for (const [name, value] of fileMap.entries()) { + if (name.startsWith(prefix) && name.endsWith(suffix)) { + results.push(value); } } return results; } /** - * - * @param files - * @param convertEntry - * @param schemaName - * @param dictionaryTitle + * @template [TEntry=unknown] + * @template [TResult=unknown] + * @param {import('@zip.js/zip.js').Entry[]} files + * @param {(entry: TEntry, dictionaryTitle: string) => TResult} convertEntry + * @param {import('dictionary-importer').CompiledSchemaName} schemaName + * @param {string} dictionaryTitle + * @returns {Promise} */ async _readFileSequence(files, convertEntry, schemaName, dictionaryTitle) { const progressData = this._progressData; let startIndex = 0; const results = []; - for (const fileName of Object.keys(files)) { - const content = await files[fileName].getData( - new TextWriter() - ); - const entries = JSON.parse(content); + for (const file of files) { + const content = await this._getData(file, new TextWriter()); + const entries = /** @type {unknown} */ (JSON.parse(content)); startIndex = progressData.index; this._progress(); - if (!ajvSchemas[schemaName](entries)) { - throw this._formatAjvSchemaError(ajvSchemas[schemaName], fileName); + const schema = ajvSchemas[schemaName]; + if (!schema(entries)) { + throw this._formatAjvSchemaError(schema, file.filename); } progressData.index = startIndex + 1; @@ -771,4 +786,17 @@ export class DictionaryImporter { // - '\ufa67'.normalize('NFC') => '\u9038' (逸 => 逸) return text; } + + /** + * @template [T=unknown] + * @param {import('@zip.js/zip.js').Entry} entry + * @param {import('@zip.js/zip.js').Writer|import('@zip.js/zip.js').WritableWriter} writer + * @returns {Promise} + */ + async _getData(entry, writer) { + if (typeof entry.getData === 'undefined') { + throw new Error(`Cannot read ${entry.filename}`); + } + return await entry.getData(writer); + } } diff --git a/jsconfig.json b/jsconfig.json index 7d23472f..ace0c2aa 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -20,7 +20,10 @@ "handlebars", "jszip", "parse5", - "wanakana" + "wanakana", + "zip.js", + "dexie", + "ajv" ] }, "include": [ diff --git a/package-lock.json b/package-lock.json index 3fb951f7..8980b096 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@types/jsdom": "^21.1.6", "@types/node": "^20.10.0", "@types/wanakana": "^4.0.6", + "@types/zip.js": "^2.0.32", "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.12.0", "@vitest/coverage-v8": "^0.34.6", @@ -949,6 +950,12 @@ "integrity": "sha512-al8hJELQI+RDcexy6JLV/BqghQ/nP0B9d62m0F3jEvPyxAq9RXFH9xDoGa73oT9/keCUKRxWCA6l37wv4TCfQw==", "dev": true }, + "node_modules/@types/zip.js": { + "version": "2.0.32", + "resolved": "https://registry.npmjs.org/@types/zip.js/-/zip.js-2.0.32.tgz", + "integrity": "sha512-+/r1iYLsLUCTNsDiGcrqK7LQ9ui11GVC98Dj3x0GtpuvzKM2PK8k/gXeu2RyZWTiVR3k6pxodHnAiBMBVsNebw==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", @@ -6477,6 +6484,12 @@ "integrity": "sha512-al8hJELQI+RDcexy6JLV/BqghQ/nP0B9d62m0F3jEvPyxAq9RXFH9xDoGa73oT9/keCUKRxWCA6l37wv4TCfQw==", "dev": true }, + "@types/zip.js": { + "version": "2.0.32", + "resolved": "https://registry.npmjs.org/@types/zip.js/-/zip.js-2.0.32.tgz", + "integrity": "sha512-+/r1iYLsLUCTNsDiGcrqK7LQ9ui11GVC98Dj3x0GtpuvzKM2PK8k/gXeu2RyZWTiVR3k6pxodHnAiBMBVsNebw==", + "dev": true + }, "@typescript-eslint/eslint-plugin": { "version": "6.12.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.12.0.tgz", diff --git a/package.json b/package.json index bc2aebd7..0d9796bb 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@types/jsdom": "^21.1.6", "@types/node": "^20.10.0", "@types/wanakana": "^4.0.6", + "@types/zip.js": "^2.0.32", "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.12.0", "@vitest/coverage-v8": "^0.34.6", diff --git a/types/ext/dictionary-importer.d.ts b/types/ext/dictionary-importer.d.ts index 16ce66ce..de85d04a 100644 --- a/types/ext/dictionary-importer.d.ts +++ b/types/ext/dictionary-importer.d.ts @@ -15,6 +15,8 @@ * along with this program. If not, see . */ +import type * as Ajv from 'ajv'; +import type * as ZipJS from '@zip.js/zip.js'; import type * as DictionaryData from './dictionary-data'; import type * as DictionaryDatabase from './dictionary-database'; import type * as StructuredContent from './structured-content'; @@ -90,6 +92,29 @@ export type StructuredContentImageImportRequirement = { }; export type ImportRequirementContext = { - archive: import('jszip'); + fileMap: ArchiveFileMap; media: Map; }; + +export type ArchiveFileMap = Map; + +export type CompiledSchemaNameArray = [ + termBank: CompiledSchemaName, + termMetaBank: CompiledSchemaName, + kanjiBank: CompiledSchemaName, + kanjiMetaBank: CompiledSchemaName, + tagBank: CompiledSchemaName, +]; + +export type CompiledSchemaValidators = { + dictionaryIndex: Ajv.ValidateFunction; + dictionaryTermBankV1: Ajv.ValidateFunction; + dictionaryTermBankV3: Ajv.ValidateFunction; + dictionaryTermMetaBankV3: Ajv.ValidateFunction; + dictionaryKanjiBankV1: Ajv.ValidateFunction; + dictionaryKanjiBankV3: Ajv.ValidateFunction; + dictionaryKanjiMetaBankV3: Ajv.ValidateFunction; + dictionaryTagBankV3: Ajv.ValidateFunction; +}; + +export type CompiledSchemaName = keyof CompiledSchemaValidators; -- cgit v1.2.3 From 29317da4ea237557e1805a834913dad73c51ed8a Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 17:43:53 -0500 Subject: Update offscreen --- ext/js/background/offscreen-proxy.js | 137 +++++++++++++++++++++++++---------- ext/js/background/offscreen.js | 121 +++++++++++++++++-------------- ext/js/language/translator.js | 4 +- types/ext/dictionary-database.d.ts | 2 +- types/ext/offscreen.d.ts | 115 +++++++++++++++++++++++++++++ types/ext/translator.d.ts | 12 +++ 6 files changed, 298 insertions(+), 93 deletions(-) create mode 100644 types/ext/offscreen.d.ts (limited to 'types/ext') diff --git a/ext/js/background/offscreen-proxy.js b/ext/js/background/offscreen-proxy.js index 0fb2f269..757d78d5 100644 --- a/ext/js/background/offscreen-proxy.js +++ b/ext/js/background/offscreen-proxy.js @@ -18,13 +18,17 @@ import {isObject} from '../core.js'; import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; +import {ExtensionError} from '../core/extension-error.js'; export class OffscreenProxy { constructor() { + /** @type {?Promise} */ this._creatingOffscreen = null; } - // https://developer.chrome.com/docs/extensions/reference/offscreen/ + /** + * @see https://developer.chrome.com/docs/extensions/reference/offscreen/ + */ async prepare() { if (await this._hasOffscreenDocument()) { return; @@ -36,20 +40,30 @@ export class OffscreenProxy { this._creatingOffscreen = chrome.offscreen.createDocument({ url: 'offscreen.html', - reasons: ['CLIPBOARD'], + reasons: [ + /** @type {chrome.offscreen.Reason} */ ('CLIPBOARD') + ], justification: 'Access to the clipboard' }); await this._creatingOffscreen; this._creatingOffscreen = null; } + /** + * @returns {Promise} + */ async _hasOffscreenDocument() { const offscreenUrl = chrome.runtime.getURL('offscreen.html'); - if (!chrome.runtime.getContexts) { // chrome version <116 + // @ts-ignore - API not defined yet + if (!chrome.runtime.getContexts) { // chrome version below 116 + // Clients: https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/clients + // @ts-ignore - Types not set up for service workers yet const matchedClients = await clients.matchAll(); + // @ts-ignore - Types not set up for service workers yet return await matchedClients.some((client) => client.url === offscreenUrl); } + // @ts-ignore - API not defined yet const contexts = await chrome.runtime.getContexts({ contextTypes: ['OFFSCREEN_DOCUMENT'], documentUrls: [offscreenUrl] @@ -57,103 +71,152 @@ export class OffscreenProxy { return !!contexts.length; } - sendMessagePromise(...args) { + /** + * @template {import('offscreen').MessageType} TMessageType + * @param {import('offscreen').Message} message + * @returns {Promise>} + */ + sendMessagePromise(message) { return new Promise((resolve, reject) => { - const callback = (response) => { + chrome.runtime.sendMessage(message, (response) => { try { resolve(this._getMessageResponseResult(response)); } catch (error) { reject(error); } - }; - - chrome.runtime.sendMessage(...args, callback); + }); }); } + /** + * @template [TReturn=unknown] + * @param {import('core').Response} response + * @returns {TReturn} + * @throws {Error} + */ _getMessageResponseResult(response) { - let error = chrome.runtime.lastError; + const error = chrome.runtime.lastError; if (error) { throw new Error(error.message); } if (!isObject(response)) { throw new Error('Offscreen document did not respond'); } - error = response.error; - if (error) { - throw deserializeError(error); + const error2 = response.error; + if (error2) { + throw ExtensionError.deserialize(error2); } return response.result; } } export class DictionaryDatabaseProxy { + /** + * @param {OffscreenProxy} offscreen + */ constructor(offscreen) { + /** @type {OffscreenProxy} */ this._offscreen = offscreen; } - prepare() { - return this._offscreen.sendMessagePromise({action: 'databasePrepareOffscreen'}); + /** + * @returns {Promise} + */ + async prepare() { + await this._offscreen.sendMessagePromise({action: 'databasePrepareOffscreen'}); } - getDictionaryInfo() { + /** + * @returns {Promise} + */ + async getDictionaryInfo() { return this._offscreen.sendMessagePromise({action: 'getDictionaryInfoOffscreen'}); } - purge() { - return this._offscreen.sendMessagePromise({action: 'databasePurgeOffscreen'}); + /** + * @returns {Promise} + */ + async purge() { + return await this._offscreen.sendMessagePromise({action: 'databasePurgeOffscreen'}); } + /** + * @param {import('dictionary-database').MediaRequest[]} targets + * @returns {Promise} + */ async getMedia(targets) { - const serializedMedia = await this._offscreen.sendMessagePromise({action: 'databaseGetMediaOffscreen', params: {targets}}); + const serializedMedia = /** @type {import('dictionary-database').Media[]} */ (await this._offscreen.sendMessagePromise({action: 'databaseGetMediaOffscreen', params: {targets}})); const media = serializedMedia.map((m) => ({...m, content: ArrayBufferUtil.base64ToArrayBuffer(m.content)})); return media; } } export class TranslatorProxy { + /** + * @param {OffscreenProxy} offscreen + */ constructor(offscreen) { + /** @type {OffscreenProxy} */ this._offscreen = offscreen; } - prepare(deinflectionReasons) { - return this._offscreen.sendMessagePromise({action: 'translatorPrepareOffscreen', params: {deinflectionReasons}}); + /** + * @param {import('deinflector').ReasonsRaw} deinflectionReasons + */ + async prepare(deinflectionReasons) { + await this._offscreen.sendMessagePromise({action: 'translatorPrepareOffscreen', params: {deinflectionReasons}}); } - async findKanji(text, findKanjiOptions) { - const enabledDictionaryMapList = [...findKanjiOptions.enabledDictionaryMap]; - const modifiedKanjiOptions = { - ...findKanjiOptions, + /** + * @param {string} text + * @param {import('translation').FindKanjiOptions} options + * @returns {Promise} + */ + async findKanji(text, options) { + const enabledDictionaryMapList = [...options.enabledDictionaryMap]; + /** @type {import('offscreen').FindKanjiOptionsOffscreen} */ + const modifiedOptions = { + ...options, enabledDictionaryMap: enabledDictionaryMapList }; - return this._offscreen.sendMessagePromise({action: 'findKanjiOffscreen', params: {text, findKanjiOptions: modifiedKanjiOptions}}); + return this._offscreen.sendMessagePromise({action: 'findKanjiOffscreen', params: {text, options: modifiedOptions}}); } - async findTerms(mode, text, findTermsOptions) { - const {enabledDictionaryMap, excludeDictionaryDefinitions, textReplacements} = findTermsOptions; + /** + * @param {import('translator').FindTermsMode} mode + * @param {string} text + * @param {import('translation').FindTermsOptions} options + * @returns {Promise} + */ + async findTerms(mode, text, options) { + const {enabledDictionaryMap, excludeDictionaryDefinitions, textReplacements} = options; const enabledDictionaryMapList = [...enabledDictionaryMap]; const excludeDictionaryDefinitionsList = excludeDictionaryDefinitions ? [...excludeDictionaryDefinitions] : null; const textReplacementsSerialized = textReplacements.map((group) => { - if (!group) { - return group; - } - return group.map((opt) => ({...opt, pattern: opt.pattern.toString()})); + return group !== null ? group.map((opt) => ({...opt, pattern: opt.pattern.toString()})) : null; }); - const modifiedFindTermsOptions = { - ...findTermsOptions, + /** @type {import('offscreen').FindTermsOptionsOffscreen} */ + const modifiedOptions = { + ...options, enabledDictionaryMap: enabledDictionaryMapList, excludeDictionaryDefinitions: excludeDictionaryDefinitionsList, textReplacements: textReplacementsSerialized }; - return this._offscreen.sendMessagePromise({action: 'findTermsOffscreen', params: {mode, text, findTermsOptions: modifiedFindTermsOptions}}); + return this._offscreen.sendMessagePromise({action: 'findTermsOffscreen', params: {mode, text, options: modifiedOptions}}); } + /** + * @param {import('translator').TermReadingList} termReadingList + * @param {string[]} dictionaries + * @returns {Promise} + */ async getTermFrequencies(termReadingList, dictionaries) { return this._offscreen.sendMessagePromise({action: 'getTermFrequenciesOffscreen', params: {termReadingList, dictionaries}}); } - clearDatabaseCaches() { - return this._offscreen.sendMessagePromise({action: 'clearDatabaseCachesOffscreen'}); + /** */ + async clearDatabaseCaches() { + await this._offscreen.sendMessagePromise({action: 'clearDatabaseCachesOffscreen'}); } } @@ -173,7 +236,7 @@ export class ClipboardReaderProxy { set browser(value) { if (this._browser === value) { return; } this._browser = value; - this._offscreen.sendMessagePromise({action: 'clipboardSetBrowserOffsecreen', params: {value}}); + this._offscreen.sendMessagePromise({action: 'clipboardSetBrowserOffscreen', params: {value}}); } /** diff --git a/ext/js/background/offscreen.js b/ext/js/background/offscreen.js index 6302aa84..1b68887b 100644 --- a/ext/js/background/offscreen.js +++ b/ext/js/background/offscreen.js @@ -23,7 +23,6 @@ import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; import {DictionaryDatabase} from '../language/dictionary-database.js'; import {JapaneseUtil} from '../language/sandbox/japanese-util.js'; import {Translator} from '../language/translator.js'; -import {yomitan} from '../yomitan.js'; /** * This class controls the core logic of the extension, including API calls @@ -34,12 +33,16 @@ export class Offscreen { * Creates a new instance. */ constructor() { + /** @type {JapaneseUtil} */ this._japaneseUtil = new JapaneseUtil(wanakana); + /** @type {DictionaryDatabase} */ this._dictionaryDatabase = new DictionaryDatabase(); + /** @type {Translator} */ this._translator = new Translator({ japaneseUtil: this._japaneseUtil, database: this._dictionaryDatabase }); + /** @type {ClipboardReader} */ this._clipboardReader = new ClipboardReader({ // eslint-disable-next-line no-undef document: (typeof document === 'object' && document !== null ? document : null), @@ -47,42 +50,45 @@ export class Offscreen { richContentPasteTargetSelector: '#clipboard-rich-content-paste-target' }); + /** @type {import('offscreen').MessageHandlerMap} */ this._messageHandlers = new Map([ - ['clipboardGetTextOffscreen', {async: true, contentScript: true, handler: this._getTextHandler.bind(this)}], - ['clipboardGetImageOffscreen', {async: true, contentScript: true, handler: this._getImageHandler.bind(this)}], - ['clipboardSetBrowserOffsecreen', {async: false, contentScript: true, handler: this._setClipboardBrowser.bind(this)}], - ['databasePrepareOffscreen', {async: true, contentScript: true, handler: this._prepareDatabaseHandler.bind(this)}], - ['getDictionaryInfoOffscreen', {async: true, contentScript: true, handler: this._getDictionaryInfoHandler.bind(this)}], - ['databasePurgeOffscreen', {async: true, contentScript: true, handler: this._purgeDatabaseHandler.bind(this)}], - ['databaseGetMediaOffscreen', {async: true, contentScript: true, handler: this._getMediaHandler.bind(this)}], - ['translatorPrepareOffscreen', {async: false, contentScript: true, handler: this._prepareTranslatorHandler.bind(this)}], - ['findKanjiOffscreen', {async: true, contentScript: true, handler: this._findKanjiHandler.bind(this)}], - ['findTermsOffscreen', {async: true, contentScript: true, handler: this._findTermsHandler.bind(this)}], - ['getTermFrequenciesOffscreen', {async: true, contentScript: true, handler: this._getTermFrequenciesHandler.bind(this)}], - ['clearDatabaseCachesOffscreen', {async: false, contentScript: true, handler: this._clearDatabaseCachesHandler.bind(this)}] + ['clipboardGetTextOffscreen', {async: true, handler: this._getTextHandler.bind(this)}], + ['clipboardGetImageOffscreen', {async: true, handler: this._getImageHandler.bind(this)}], + ['clipboardSetBrowserOffscreen', {async: false, handler: this._setClipboardBrowser.bind(this)}], + ['databasePrepareOffscreen', {async: true, handler: this._prepareDatabaseHandler.bind(this)}], + ['getDictionaryInfoOffscreen', {async: true, handler: this._getDictionaryInfoHandler.bind(this)}], + ['databasePurgeOffscreen', {async: true, handler: this._purgeDatabaseHandler.bind(this)}], + ['databaseGetMediaOffscreen', {async: true, handler: this._getMediaHandler.bind(this)}], + ['translatorPrepareOffscreen', {async: false, handler: this._prepareTranslatorHandler.bind(this)}], + ['findKanjiOffscreen', {async: true, handler: this._findKanjiHandler.bind(this)}], + ['findTermsOffscreen', {async: true, handler: this._findTermsHandler.bind(this)}], + ['getTermFrequenciesOffscreen', {async: true, handler: this._getTermFrequenciesHandler.bind(this)}], + ['clearDatabaseCachesOffscreen', {async: false, handler: this._clearDatabaseCachesHandler.bind(this)}] ]); const onMessage = this._onMessage.bind(this); chrome.runtime.onMessage.addListener(onMessage); + /** @type {?Promise} */ this._prepareDatabasePromise = null; } - _getTextHandler({useRichText}) { - return this._clipboardReader.getText(useRichText); + /** @type {import('offscreen').MessageHandler<'clipboardGetTextOffscreen', true>} */ + async _getTextHandler({useRichText}) { + return await this._clipboardReader.getText(useRichText); } - _getImageHandler() { - return this._clipboardReader.getImage(); + /** @type {import('offscreen').MessageHandler<'clipboardGetImageOffscreen', true>} */ + async _getImageHandler() { + return await this._clipboardReader.getImage(); } - /** - * @param {{value: import('environment').Browser}} details - */ + /** @type {import('offscreen').MessageHandler<'clipboardSetBrowserOffscreen', false>} */ _setClipboardBrowser({value}) { this._clipboardReader.browser = value; } + /** @type {import('offscreen').MessageHandler<'databasePrepareOffscreen', true>} */ _prepareDatabaseHandler() { if (this._prepareDatabasePromise !== null) { return this._prepareDatabasePromise; @@ -91,70 +97,79 @@ export class Offscreen { return this._prepareDatabasePromise; } - _getDictionaryInfoHandler() { - return this._dictionaryDatabase.getDictionaryInfo(); + /** @type {import('offscreen').MessageHandler<'getDictionaryInfoOffscreen', true>} */ + async _getDictionaryInfoHandler() { + return await this._dictionaryDatabase.getDictionaryInfo(); } - _purgeDatabaseHandler() { - return this._dictionaryDatabase.purge(); + /** @type {import('offscreen').MessageHandler<'databasePurgeOffscreen', true>} */ + async _purgeDatabaseHandler() { + return await this._dictionaryDatabase.purge(); } + /** @type {import('offscreen').MessageHandler<'databaseGetMediaOffscreen', true>} */ async _getMediaHandler({targets}) { const media = await this._dictionaryDatabase.getMedia(targets); const serializedMedia = media.map((m) => ({...m, content: ArrayBufferUtil.arrayBufferToBase64(m.content)})); return serializedMedia; } + /** @type {import('offscreen').MessageHandler<'translatorPrepareOffscreen', false>} */ _prepareTranslatorHandler({deinflectionReasons}) { - return this._translator.prepare(deinflectionReasons); + this._translator.prepare(deinflectionReasons); } - _findKanjiHandler({text, findKanjiOptions}) { - findKanjiOptions.enabledDictionaryMap = new Map(findKanjiOptions.enabledDictionaryMap); - return this._translator.findKanji(text, findKanjiOptions); + /** @type {import('offscreen').MessageHandler<'findKanjiOffscreen', true>} */ + async _findKanjiHandler({text, options}) { + /** @type {import('translation').FindKanjiOptions} */ + const modifiedOptions = { + ...options, + enabledDictionaryMap: new Map(options.enabledDictionaryMap) + }; + return await this._translator.findKanji(text, modifiedOptions); } - _findTermsHandler({mode, text, findTermsOptions}) { - findTermsOptions.enabledDictionaryMap = new Map(findTermsOptions.enabledDictionaryMap); - if (findTermsOptions.excludeDictionaryDefinitions) { - findTermsOptions.excludeDictionaryDefinitions = new Set(findTermsOptions.excludeDictionaryDefinitions); - } - findTermsOptions.textReplacements = findTermsOptions.textReplacements.map((group) => { - if (!group) { - return group; - } + /** @type {import('offscreen').MessageHandler<'findTermsOffscreen', true>} */ + _findTermsHandler({mode, text, options}) { + const enabledDictionaryMap = new Map(options.enabledDictionaryMap); + const excludeDictionaryDefinitions = ( + options.excludeDictionaryDefinitions !== null ? + new Set(options.excludeDictionaryDefinitions) : + null + ); + const textReplacements = options.textReplacements.map((group) => { + if (group === null) { return null; } return group.map((opt) => { - const [, pattern, flags] = opt.pattern.match(/\/(.*?)\/([a-z]*)?$/i); // https://stackoverflow.com/a/33642463 + // https://stackoverflow.com/a/33642463 + const match = opt.pattern.match(/\/(.*?)\/([a-z]*)?$/i); + const [, pattern, flags] = match !== null ? match : ['', '', '']; return {...opt, pattern: new RegExp(pattern, flags ?? '')}; }); }); - return this._translator.findTerms(mode, text, findTermsOptions); + /** @type {import('translation').FindTermsOptions} */ + const modifiedOptions = { + ...options, + enabledDictionaryMap, + excludeDictionaryDefinitions, + textReplacements + }; + return this._translator.findTerms(mode, text, modifiedOptions); } + /** @type {import('offscreen').MessageHandler<'getTermFrequenciesOffscreen', true>} */ _getTermFrequenciesHandler({termReadingList, dictionaries}) { return this._translator.getTermFrequencies(termReadingList, dictionaries); } + /** @type {import('offscreen').MessageHandler<'clearDatabaseCachesOffscreen', false>} */ _clearDatabaseCachesHandler() { - return this._translator.clearDatabaseCaches(); + this._translator.clearDatabaseCaches(); } + /** @type {import('extension').ChromeRuntimeOnMessageCallback} */ _onMessage({action, params}, sender, callback) { const messageHandler = this._messageHandlers.get(action); if (typeof messageHandler === 'undefined') { return false; } - this._validatePrivilegedMessageSender(sender); - return invokeMessageHandler(messageHandler, params, callback, sender); } - - _validatePrivilegedMessageSender(sender) { - let {url} = sender; - if (typeof url === 'string' && yomitan.isExtensionUrl(url)) { return; } - const {tab} = url; - if (typeof tab === 'object' && tab !== null) { - ({url} = tab); - if (typeof url === 'string' && yomitan.isExtensionUrl(url)) { return; } - } - throw new Error('Invalid message sender'); - } } diff --git a/ext/js/language/translator.js b/ext/js/language/translator.js index c21b16b1..aa1b71dd 100644 --- a/ext/js/language/translator.js +++ b/ext/js/language/translator.js @@ -157,7 +157,7 @@ export class Translator { /** * Gets a list of frequency information for a given list of term-reading pairs * and a list of dictionaries. - * @param {{term: string, reading: string|null}[]} termReadingList An array of `{term, reading}` pairs. If reading is null, + * @param {import('translator').TermReadingList} termReadingList An array of `{term, reading}` pairs. If reading is null, * the reading won't be compared. * @param {string[]} dictionaries An array of dictionary names. * @returns {Promise} An array of term frequencies. @@ -203,7 +203,7 @@ export class Translator { * @param {Map} enabledDictionaryMap * @param {import('translation').FindTermsOptions} options * @param {TranslatorTagAggregator} tagAggregator - * @returns {Promise<{dictionaryEntries: import('dictionary').TermDictionaryEntry[], originalTextLength: number}>} + * @returns {Promise} */ async _findTermsInternal(text, enabledDictionaryMap, options, tagAggregator) { if (options.removeNonJapaneseCharacters) { diff --git a/types/ext/dictionary-database.d.ts b/types/ext/dictionary-database.d.ts index 2e0f854b..06a246e8 100644 --- a/types/ext/dictionary-database.d.ts +++ b/types/ext/dictionary-database.d.ts @@ -35,7 +35,7 @@ export interface MediaDataBase { export interface MediaDataArrayBufferContent extends MediaDataBase {} export interface MediaDataStringContent extends MediaDataBase {} -export type Media = {index: number} & MediaDataBase; +export type Media = {index: number} & MediaDataBase; export type DatabaseTermEntry = { expression: string; diff --git a/types/ext/offscreen.d.ts b/types/ext/offscreen.d.ts new file mode 100644 index 00000000..7dd64d1e --- /dev/null +++ b/types/ext/offscreen.d.ts @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import type * as Core from './core'; +import type * as Deinflector from './deinflector'; +import type * as Dictionary from './dictionary'; +import type * as DictionaryDatabase from './dictionary-database'; +import type * as DictionaryImporter from './dictionary-importer'; +import type * as Environment from './environment'; +import type * as Translation from './translation'; +import type * as Translator from './translator'; + +export type MessageAny2 = Message; + +export type Message = ( + MessageDetailsMap[T] extends undefined ? + {action: T} : + {action: T, params: MessageDetailsMap[T]} +); + +export type MessageReturn = MessageReturnMap[T]; + +type MessageDetailsMap = { + databasePrepareOffscreen: undefined; + getDictionaryInfoOffscreen: undefined; + databasePurgeOffscreen: undefined; + databaseGetMediaOffscreen: { + targets: DictionaryDatabase.MediaRequest[]; + }; + translatorPrepareOffscreen: { + deinflectionReasons: Deinflector.ReasonsRaw; + }; + findKanjiOffscreen: { + text: string; + options: FindKanjiOptionsOffscreen; + }; + findTermsOffscreen: { + mode: Translator.FindTermsMode; + text: string; + options: FindTermsOptionsOffscreen; + }; + getTermFrequenciesOffscreen: { + termReadingList: Translator.TermReadingList; + dictionaries: string[]; + }; + clearDatabaseCachesOffscreen: undefined; + clipboardSetBrowserOffscreen: { + value: Environment.Browser | null; + }; + clipboardGetTextOffscreen: { + useRichText: boolean; + }; + clipboardGetImageOffscreen: undefined; +}; + +type MessageReturnMap = { + databasePrepareOffscreen: void; + getDictionaryInfoOffscreen: DictionaryImporter.Summary[]; + databasePurgeOffscreen: boolean; + databaseGetMediaOffscreen: DictionaryDatabase.Media[]; + translatorPrepareOffscreen: void; + findKanjiOffscreen: Dictionary.KanjiDictionaryEntry[]; + findTermsOffscreen: Translator.FindTermsResult; + getTermFrequenciesOffscreen: Translator.TermFrequencySimple[]; + clearDatabaseCachesOffscreen: void; + clipboardSetBrowserOffscreen: void; + clipboardGetTextOffscreen: string; + clipboardGetImageOffscreen: string | null; +}; + +export type MessageType = keyof MessageDetailsMap; + +export type FindKanjiOptionsOffscreen = Omit & { + enabledDictionaryMap: [ + key: string, + options: Translation.FindKanjiDictionary, + ][]; +}; + + +export type FindTermsOptionsOffscreen = Omit & { + enabledDictionaryMap: [ + key: string, + options: Translation.FindTermDictionary, + ][]; + excludeDictionaryDefinitions: string[] | null; + textReplacements: (FindTermsTextReplacementOffscreen[] | null)[]; +}; + +export type FindTermsTextReplacementOffscreen = Omit & { + pattern: string; +}; + +export type MessageHandler< + TMessage extends MessageType, + TIsAsync extends boolean, +> = ( + details: MessageDetailsMap[TMessage], +) => (TIsAsync extends true ? Promise> : MessageReturn); + +export type MessageHandlerMap = Map; diff --git a/types/ext/translator.d.ts b/types/ext/translator.d.ts index f17b3bf6..e7d45295 100644 --- a/types/ext/translator.d.ts +++ b/types/ext/translator.d.ts @@ -81,3 +81,15 @@ export type SequenceQuery = { }; export type FindTermsMode = 'simple' | 'group' | 'merge' | 'split'; + +export type TermReadingItem = { + term: string; + reading: string | null; +}; + +export type TermReadingList = TermReadingItem[]; + +export type FindTermsResult = { + dictionaryEntries: Dictionary.TermDictionaryEntry[]; + originalTextLength: number; +}; -- cgit v1.2.3 From fe9905ebed902cc4ea75700e589390f1a6a321a9 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 17:46:10 -0500 Subject: Remove interface keywords --- types/ext/cache-map.d.ts | 4 ++-- types/ext/dictionary-database.d.ts | 9 +++++---- types/ext/task-accumulator.d.ts | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) (limited to 'types/ext') diff --git a/types/ext/cache-map.d.ts b/types/ext/cache-map.d.ts index a4b8bb1a..0af7109a 100644 --- a/types/ext/cache-map.d.ts +++ b/types/ext/cache-map.d.ts @@ -15,9 +15,9 @@ * along with this program. If not, see . */ -export interface Node { +export type Node = { key: K | null; value: V | null; previous: Node | null; next: Node | null; -} +}; diff --git a/types/ext/dictionary-database.d.ts b/types/ext/dictionary-database.d.ts index 06a246e8..6569f76b 100644 --- a/types/ext/dictionary-database.d.ts +++ b/types/ext/dictionary-database.d.ts @@ -23,17 +23,18 @@ export type DatabaseId = { id: number; // Automatic database primary key }; -export interface MediaDataBase { +export type MediaDataBase = { dictionary: string; path: string; mediaType: string; width: number; height: number; content: TContentType; -} +}; + +export type MediaDataArrayBufferContent = MediaDataBase; -export interface MediaDataArrayBufferContent extends MediaDataBase {} -export interface MediaDataStringContent extends MediaDataBase {} +export type MediaDataStringContent = MediaDataBase; export type Media = {index: number} & MediaDataBase; diff --git a/types/ext/task-accumulator.d.ts b/types/ext/task-accumulator.d.ts index 772949f6..f02d449b 100644 --- a/types/ext/task-accumulator.d.ts +++ b/types/ext/task-accumulator.d.ts @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -export interface Task { +export type Task = { data: V; stale: boolean; -} +}; -- cgit v1.2.3 From b9310603865292749d7303f41b7c2d6b6f286078 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 19:22:03 -0500 Subject: Update typescript imports --- types/ext/display-audio.d.ts | 1 + types/ext/display.d.ts | 12 ++++++++---- types/ext/document-util.d.ts | 4 +++- types/ext/event-listener-collection.d.ts | 1 + types/ext/frontend.d.ts | 3 +++ types/ext/popup-menu.d.ts | 2 ++ types/ext/popup.d.ts | 4 ++++ types/ext/settings-controller.d.ts | 5 ++++- types/ext/text-scanner.d.ts | 1 + types/ext/text-source.d.ts | 3 +++ types/ext/translator.d.ts | 8 +++++--- 11 files changed, 35 insertions(+), 9 deletions(-) (limited to 'types/ext') diff --git a/types/ext/display-audio.d.ts b/types/ext/display-audio.d.ts index 2ef252b1..759e5ee6 100644 --- a/types/ext/display-audio.d.ts +++ b/types/ext/display-audio.d.ts @@ -18,6 +18,7 @@ import type * as Audio from './audio'; import type * as Settings from './settings'; import type * as AudioDownloader from './audio-downloader'; +import type {TextToSpeechAudio} from '../../ext/js/media/text-to-speech-audio'; export type CacheItem = { sourceMap: Map; diff --git a/types/ext/display.d.ts b/types/ext/display.d.ts index feb049fb..533fc441 100644 --- a/types/ext/display.d.ts +++ b/types/ext/display.d.ts @@ -19,8 +19,12 @@ import type * as Core from './core'; import type * as Dictionary from './dictionary'; import type * as Extension from './extension'; import type * as Settings from './settings'; -import type * as TextScanner from './text-scanner'; +import type * as TextScannerTypes from './text-scanner'; import type * as TextSource from './text-source'; +import type {DisplayContentManager} from '../../ext/js/display/display-content-manager'; +import type {HotkeyHelpController} from '../../ext/js/input/hotkey-help-controller'; +import type {JapaneseUtil} from '../../ext/js/language/sandbox/japanese-util'; +import type {TextScanner} from '../../ext/js/language/text-scanner'; export type HistoryMode = 'clear' | 'overwrite' | 'new'; @@ -114,7 +118,7 @@ export type SearchPersistentStateControllerEventType = 'modeChange'; export type SearchMode = null | 'popup' | 'action-popup'; -export type GetSearchContextCallback = TextScanner.GetSearchContextCallbackSync; +export type GetSearchContextCallback = TextScannerTypes.GetSearchContextCallbackSync; export type QueryParserConstructorDetails = { getSearchContext: GetSearchContextCallback; @@ -127,7 +131,7 @@ export type QueryParserOptions = { readingMode: Settings.ParsingReadingMode; useInternalParser: boolean; useMecabParser: boolean; - scanning: TextScanner.Options; + scanning: TextScannerTypes.Options; }; export type QueryParserEventType = 'searched'; @@ -137,7 +141,7 @@ export type QueryParserSearchedEvent = { type: PageType; dictionaryEntries: Dictionary.DictionaryEntry[]; sentence: HistoryStateSentence; - inputInfo: TextScanner.InputInfo; + inputInfo: TextScannerTypes.InputInfo; textSource: TextSource.TextSource; optionsContext: Settings.OptionsContext; sentenceOffset: number | null; diff --git a/types/ext/document-util.d.ts b/types/ext/document-util.d.ts index 28dfe899..aa655a67 100644 --- a/types/ext/document-util.d.ts +++ b/types/ext/document-util.d.ts @@ -15,6 +15,8 @@ * along with this program. If not, see . */ +import type * as TextSource from './text-source'; + export type NormalizedWritingMode = 'horizontal-tb' | 'vertical-rl' | 'vertical-lr' | 'sideways-rl' | 'sideways-lr'; /** @@ -44,7 +46,7 @@ export type GetRangeFromPointHandler = ( y: number, /** Options to configure how element detection is performed. */ options: GetRangeFromPointOptions, -) => (TextSourceRange | TextSourceElement | null); +) => (TextSource.TextSource | null); export type ToNumberConstraints = { min?: string | number; diff --git a/types/ext/event-listener-collection.d.ts b/types/ext/event-listener-collection.d.ts index daeeecab..f22d6bcc 100644 --- a/types/ext/event-listener-collection.d.ts +++ b/types/ext/event-listener-collection.d.ts @@ -16,6 +16,7 @@ */ import type * as Core from './core'; +import type {EventDispatcher} from '../../ext/js/core'; export type EventListenerFunction = (...args: Core.SafeAny[]) => unknown; diff --git a/types/ext/frontend.d.ts b/types/ext/frontend.d.ts index 3acafe0a..73b24dc3 100644 --- a/types/ext/frontend.d.ts +++ b/types/ext/frontend.d.ts @@ -15,6 +15,9 @@ * along with this program. If not, see . */ +import type {PopupFactory} from '../../ext/js/app/popup-factory'; +import type {HotkeyHandler} from '../../ext/js/input/hotkey-handler'; + /** Details about how to set up the instance. */ export type ConstructorDetails = { /** The type of page, one of 'web', 'popup', or 'search'. */ diff --git a/types/ext/popup-menu.d.ts b/types/ext/popup-menu.d.ts index c20ebf69..b6e37316 100644 --- a/types/ext/popup-menu.d.ts +++ b/types/ext/popup-menu.d.ts @@ -15,6 +15,8 @@ * along with this program. If not, see . */ +import type {PopupMenu} from '../../ext/js/dom/popup-menu'; + export type EventType = 'close'; export type CloseReason = 'close' | 'outside' | 'item' | 'resize'; diff --git a/types/ext/popup.d.ts b/types/ext/popup.d.ts index bcbc8662..aaeb676a 100644 --- a/types/ext/popup.d.ts +++ b/types/ext/popup.d.ts @@ -17,6 +17,10 @@ import type * as DocumentUtil from './document-util'; import type * as Settings from './settings'; +import type {FrameOffsetForwarder} from '../../ext/js/comm/frame-offset-forwarder'; +import type {Popup} from '../../ext/js/app/popup'; +import type {PopupProxy} from '../../ext/js/app/popup-proxy'; +import type {PopupWindow} from '../../ext/js/app/popup-window'; export type PopupAny = Popup | PopupWindow | PopupProxy; diff --git a/types/ext/settings-controller.d.ts b/types/ext/settings-controller.d.ts index 4a5bef3d..37399bc3 100644 --- a/types/ext/settings-controller.d.ts +++ b/types/ext/settings-controller.d.ts @@ -15,9 +15,12 @@ * along with this program. If not, see . */ +import type * as Core from './core'; import type * as Settings from './settings'; import type * as SettingsModifications from './settings-modifications'; -import type * as Core from './core'; +import type {DictionaryController} from '../../ext/js/pages/settings/dictionary-controller'; +import type {ScanInputsController} from '../../ext/js/pages/settings/scan-inputs-controller'; +import type {ScanInputsSimpleController} from '../../ext/js/pages/settings/scan-inputs-simple-controller'; export type PageExitPrevention = { end: () => void; diff --git a/types/ext/text-scanner.d.ts b/types/ext/text-scanner.d.ts index 494c1a52..5ff62819 100644 --- a/types/ext/text-scanner.d.ts +++ b/types/ext/text-scanner.d.ts @@ -20,6 +20,7 @@ import type * as Display from './display'; import type * as Input from './input'; import type * as Settings from './settings'; import type * as TextSource from './text-source'; +import type {TextScanner} from '../../ext/js/language/text-scanner'; export type SearchResultDetail = { documentTitle: string; diff --git a/types/ext/text-source.d.ts b/types/ext/text-source.d.ts index 37c65bd9..7e085176 100644 --- a/types/ext/text-source.d.ts +++ b/types/ext/text-source.d.ts @@ -15,4 +15,7 @@ * along with this program. If not, see . */ +import type {TextSourceElement} from '../../ext/js/dom/text-source-element'; +import type {TextSourceRange} from '../../ext/js/dom/text-source-range'; + export type TextSource = TextSourceRange | TextSourceElement; diff --git a/types/ext/translator.d.ts b/types/ext/translator.d.ts index e7d45295..838ae171 100644 --- a/types/ext/translator.d.ts +++ b/types/ext/translator.d.ts @@ -16,7 +16,9 @@ */ import type * as Dictionary from './dictionary'; -import type * as DictionaryDatabase from './dictionary-database'; +import type * as DictionaryDatabaseTypes from './dictionary-database'; +import type {DictionaryDatabase} from '../../ext/js/language/dictionary-database'; +import type {JapaneseUtil} from '../../ext/js/language/sandbox/japanese-util'; export type ConstructorDetails = { /** An instance of JapaneseUtil. */ @@ -57,7 +59,7 @@ export type TagExpansionTarget = { export type DictionaryTagCache = Map; -export type TagCache = Map; +export type TagCache = Map; export type TagTargetMap = Map>; @@ -66,7 +68,7 @@ export type TagTargetItem = { dictionary: string; tagName: string; cache: TagCache | null; - databaseTag: DictionaryDatabase.Tag | null; + databaseTag: DictionaryDatabaseTypes.Tag | null; targets: Dictionary.Tag[][]; }; -- cgit v1.2.3 From 14d12f6ba20b837a04c638b935773f3120e194ff Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 19:33:01 -0500 Subject: Update timer types and such --- dev/jsconfig.json | 2 +- ext/js/app/frontend.js | 11 +++++++++-- ext/js/background/backend.js | 4 ++-- ext/js/background/offscreen.js | 4 +++- ext/js/comm/api.js | 2 +- ext/js/comm/clipboard-monitor.js | 2 +- ext/js/comm/cross-frame-api.js | 21 +++++++++++++-------- ext/js/comm/frame-ancestry-handler.js | 2 +- ext/js/comm/frame-client.js | 2 +- ext/js/comm/mecab.js | 2 +- ext/js/core.js | 2 +- ext/js/display/display-audio.js | 2 +- ext/js/display/display-notification.js | 2 +- ext/js/display/display.js | 2 +- ext/js/display/element-overflow-controller.js | 8 ++++---- ext/js/display/option-toggle-hotkey-handler.js | 2 +- ext/js/display/search-display-controller.js | 2 +- ext/js/dom/document-util.js | 2 +- ext/js/dom/panel-element.js | 2 +- ext/js/language/text-scanner.js | 6 +++--- ext/js/media/audio-downloader.js | 2 +- ext/js/pages/settings/popup-preview-frame.js | 2 +- test/jsconfig.json | 2 +- types/ext/core.d.ts | 2 ++ types/ext/cross-frame-api.d.ts | 2 +- types/ext/offscreen.d.ts | 2 +- types/other/globals.d.ts | 22 ++++++++++++++++++++++ types/other/web-set-timeout.d.ts | 24 ------------------------ 28 files changed, 77 insertions(+), 63 deletions(-) create mode 100644 types/other/globals.d.ts delete mode 100644 types/other/web-set-timeout.d.ts (limited to 'types/ext') diff --git a/dev/jsconfig.json b/dev/jsconfig.json index 518f97ad..d4efe694 100644 --- a/dev/jsconfig.json +++ b/dev/jsconfig.json @@ -71,7 +71,7 @@ "../ext/js/language/translator.js", "../ext/js/media/media-util.js", "../types/dev/**/*.ts", - "../types/other/web-set-timeout.d.ts" + "../types/other/globals.d.ts" ], "exclude": [ "../node_modules" diff --git a/ext/js/app/frontend.js b/ext/js/app/frontend.js index 628c504e..e1f8d8c9 100644 --- a/ext/js/app/frontend.js +++ b/ext/js/app/frontend.js @@ -99,7 +99,7 @@ export class Frontend { this._popupEventListeners = new EventListenerCollection(); /** @type {?import('core').TokenObject} */ this._updatePopupToken = null; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._clearSelectionTimer = null; /** @type {boolean} */ this._isPointerOverPopup = false; @@ -840,7 +840,7 @@ export class Frontend { */ async _waitForFrontendReady(frameId, timeout) { return new Promise((resolve, reject) => { - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timeoutId = null; const cleanup = () => { @@ -973,6 +973,13 @@ export class Frontend { await yomitan.api.loadExtensionScripts([ '/js/accessibility/google-docs-util.js' ]); + this._prepareGoogleDocs2(); + } + + /** + * @returns {Promise} + */ + async _prepareGoogleDocs2() { if (typeof GoogleDocsUtil === 'undefined') { return; } DocumentUtil.registerGetRangeFromPointHandler(GoogleDocsUtil.getRangeFromPoint.bind(GoogleDocsUtil)); } diff --git a/ext/js/background/backend.js b/ext/js/background/backend.js index 44f5a42d..f1a47e7f 100644 --- a/ext/js/background/backend.js +++ b/ext/js/background/backend.js @@ -138,7 +138,7 @@ export class Backend { /** @type {?string} */ this._defaultBrowserActionTitle = null; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._badgePrepareDelayTimer = null; /** @type {?import('log').LogLevel} */ this._logErrorLevel = null; @@ -1981,7 +1981,7 @@ export class Backend { */ _waitUntilTabFrameIsReady(tabId, frameId, timeout=null) { return new Promise((resolve, reject) => { - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; /** @type {?import('extension').ChromeRuntimeOnMessageCallback} */ let onMessage = (message, sender) => { diff --git a/ext/js/background/offscreen.js b/ext/js/background/offscreen.js index 45345c01..8da661ad 100644 --- a/ext/js/background/offscreen.js +++ b/ext/js/background/offscreen.js @@ -51,7 +51,7 @@ export class Offscreen { }); /** @type {import('offscreen').MessageHandlerMap} */ - this._messageHandlers = new Map([ + const messageHandlers = new Map([ ['clipboardGetTextOffscreen', {async: true, handler: this._getTextHandler.bind(this)}], ['clipboardGetImageOffscreen', {async: true, handler: this._getImageHandler.bind(this)}], ['clipboardSetBrowserOffscreen', {async: false, handler: this._setClipboardBrowser.bind(this)}], @@ -65,6 +65,8 @@ export class Offscreen { ['getTermFrequenciesOffscreen', {async: true, handler: this._getTermFrequenciesHandler.bind(this)}], ['clearDatabaseCachesOffscreen', {async: false, handler: this._clearDatabaseCachesHandler.bind(this)}] ]); + /** @type {import('offscreen').MessageHandlerMap} */ + this._messageHandlers = messageHandlers; const onMessage = this._onMessage.bind(this); chrome.runtime.onMessage.addListener(onMessage); diff --git a/ext/js/comm/api.js b/ext/js/comm/api.js index 0cfdba59..26218595 100644 --- a/ext/js/comm/api.js +++ b/ext/js/comm/api.js @@ -431,7 +431,7 @@ export class API { */ _createActionPort(timeout) { return new Promise((resolve, reject) => { - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; const portDetails = deferPromise(); diff --git a/ext/js/comm/clipboard-monitor.js b/ext/js/comm/clipboard-monitor.js index 06e95438..3b3a56a9 100644 --- a/ext/js/comm/clipboard-monitor.js +++ b/ext/js/comm/clipboard-monitor.js @@ -31,7 +31,7 @@ export class ClipboardMonitor extends EventDispatcher { this._japaneseUtil = japaneseUtil; /** @type {import('clipboard-monitor').ClipboardReaderLike} */ this._clipboardReader = clipboardReader; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._timerId = null; /** @type {?import('core').TokenObject} */ this._timerToken = null; diff --git a/ext/js/comm/cross-frame-api.js b/ext/js/comm/cross-frame-api.js index 34f3f36a..3ac38cf2 100644 --- a/ext/js/comm/cross-frame-api.js +++ b/ext/js/comm/cross-frame-api.js @@ -25,14 +25,14 @@ import {yomitan} from '../yomitan.js'; */ class CrossFrameAPIPort extends EventDispatcher { /** - * @param {?number} otherTabId + * @param {number} otherTabId * @param {number} otherFrameId * @param {chrome.runtime.Port} port * @param {import('core').MessageHandlerMap} messageHandlers */ constructor(otherTabId, otherFrameId, port, messageHandlers) { super(); - /** @type {?number} */ + /** @type {number} */ this._otherTabId = otherTabId; /** @type {number} */ this._otherFrameId = otherFrameId; @@ -48,7 +48,7 @@ class CrossFrameAPIPort extends EventDispatcher { this._eventListeners = new EventListenerCollection(); } - /** @type {?number} */ + /** @type {number} */ get otherTabId() { return this._otherTabId; } @@ -299,7 +299,7 @@ export class CrossFrameAPI { this._ackTimeout = 3000; // 3 seconds /** @type {number} */ this._responseTimeout = 10000; // 10 seconds - /** @type {Map>} */ + /** @type {Map>} */ this._commPorts = new Map(); /** @type {import('core').MessageHandlerMap} */ this._messageHandlers = new Map(); @@ -339,7 +339,12 @@ export class CrossFrameAPI { * @returns {Promise} */ async invokeTab(targetTabId, targetFrameId, action, params) { - if (typeof targetTabId !== 'number') { targetTabId = this._tabId; } + if (typeof targetTabId !== 'number') { + targetTabId = this._tabId; + if (typeof targetTabId !== 'number') { + throw new Error('Unknown target tab id for invocation'); + } + } const commPort = await this._getOrCreateCommPort(targetTabId, targetFrameId); return await commPort.invoke(action, params, this._ackTimeout, this._responseTimeout); } @@ -405,7 +410,7 @@ export class CrossFrameAPI { } /** - * @param {?number} otherTabId + * @param {number} otherTabId * @param {number} otherFrameId * @returns {Promise} */ @@ -420,7 +425,7 @@ export class CrossFrameAPI { return await this._createCommPort(otherTabId, otherFrameId); } /** - * @param {?number} otherTabId + * @param {number} otherTabId * @param {number} otherFrameId * @returns {Promise} */ @@ -438,7 +443,7 @@ export class CrossFrameAPI { } /** - * @param {?number} otherTabId + * @param {number} otherTabId * @param {number} otherFrameId * @param {chrome.runtime.Port} port * @returns {CrossFrameAPIPort} diff --git a/ext/js/comm/frame-ancestry-handler.js b/ext/js/comm/frame-ancestry-handler.js index 49c96c22..687ec368 100644 --- a/ext/js/comm/frame-ancestry-handler.js +++ b/ext/js/comm/frame-ancestry-handler.js @@ -122,7 +122,7 @@ export class FrameAncestryHandler { const responseMessageId = `${this._responseMessageIdBase}${uniqueId}`; /** @type {number[]} */ const results = []; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; const cleanup = () => { diff --git a/ext/js/comm/frame-client.js b/ext/js/comm/frame-client.js index 1519cf7f..8aa8c6d6 100644 --- a/ext/js/comm/frame-client.js +++ b/ext/js/comm/frame-client.js @@ -83,7 +83,7 @@ export class FrameClient { _connectInternal(frame, targetOrigin, hostFrameId, setupFrame, timeout) { return new Promise((resolve, reject) => { const tokenMap = new Map(); - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; const deferPromiseDetails = /** @type {import('core').DeferredPromiseDetails} */ (deferPromise()); const frameLoadedPromise = deferPromiseDetails.promise; diff --git a/ext/js/comm/mecab.js b/ext/js/comm/mecab.js index 072b42f3..0a87463b 100644 --- a/ext/js/comm/mecab.js +++ b/ext/js/comm/mecab.js @@ -31,7 +31,7 @@ export class Mecab { this._port = null; /** @type {number} */ this._sequence = 0; - /** @type {Map void, reject: (reason?: unknown) => void, timer: number}>} */ + /** @type {Map void, reject: (reason?: unknown) => void, timer: import('core').Timeout}>} */ this._invocations = new Map(); /** @type {EventListenerCollection} */ this._eventListeners = new EventListenerCollection(); diff --git a/ext/js/core.js b/ext/js/core.js index cdac2020..a53d5572 100644 --- a/ext/js/core.js +++ b/ext/js/core.js @@ -307,7 +307,7 @@ export function promiseAnimationFrame(timeout) { return; } - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timer = null; /** @type {?number} */ let frameRequest = null; diff --git a/ext/js/display/display-audio.js b/ext/js/display/display-audio.js index 3fbfc3c8..3576decb 100644 --- a/ext/js/display/display-audio.js +++ b/ext/js/display/display-audio.js @@ -36,7 +36,7 @@ export class DisplayAudio { this._playbackVolume = 1.0; /** @type {boolean} */ this._autoPlay = false; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._autoPlayAudioTimer = null; /** @type {number} */ this._autoPlayAudioDelay = 400; diff --git a/ext/js/display/display-notification.js b/ext/js/display/display-notification.js index b3f20700..d1cfa537 100644 --- a/ext/js/display/display-notification.js +++ b/ext/js/display/display-notification.js @@ -34,7 +34,7 @@ export class DisplayNotification { this._closeButton = /** @type {HTMLElement} */ (node.querySelector('.footer-notification-close-button')); /** @type {EventListenerCollection} */ this._eventListeners = new EventListenerCollection(); - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._closeTimer = null; } diff --git a/ext/js/display/display.js b/ext/js/display/display.js index f14291d1..6e1450c3 100644 --- a/ext/js/display/display.js +++ b/ext/js/display/display.js @@ -117,7 +117,7 @@ export class Display extends EventDispatcher { this._queryOffset = 0; /** @type {HTMLElement} */ this._progressIndicator = /** @type {HTMLElement} */ (document.querySelector('#progress-indicator')); - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._progressIndicatorTimer = null; /** @type {DynamicProperty} */ this._progressIndicatorVisible = new DynamicProperty(false); diff --git a/ext/js/display/element-overflow-controller.js b/ext/js/display/element-overflow-controller.js index 1d2c808f..35277fa5 100644 --- a/ext/js/display/element-overflow-controller.js +++ b/ext/js/display/element-overflow-controller.js @@ -22,7 +22,7 @@ export class ElementOverflowController { constructor() { /** @type {Element[]} */ this._elements = []; - /** @type {?number} */ + /** @type {?(number|import('core').Timeout)} */ this._checkTimer = null; /** @type {EventListenerCollection} */ this._eventListeners = new EventListenerCollection(); @@ -154,7 +154,7 @@ export class ElementOverflowController { /** * @param {() => void} callback * @param {number} timeout - * @returns {number} + * @returns {number|import('core').Timeout} */ _requestIdleCallback(callback, timeout) { if (typeof requestIdleCallback === 'function') { @@ -165,11 +165,11 @@ export class ElementOverflowController { } /** - * @param {number} handle + * @param {number|import('core').Timeout} handle */ _cancelIdleCallback(handle) { if (typeof cancelIdleCallback === 'function') { - cancelIdleCallback(handle); + cancelIdleCallback(/** @type {number} */ (handle)); } else { clearTimeout(handle); } diff --git a/ext/js/display/option-toggle-hotkey-handler.js b/ext/js/display/option-toggle-hotkey-handler.js index 531e208d..edd7de5b 100644 --- a/ext/js/display/option-toggle-hotkey-handler.js +++ b/ext/js/display/option-toggle-hotkey-handler.js @@ -29,7 +29,7 @@ export class OptionToggleHotkeyHandler { this._display = display; /** @type {?import('./display-notification.js').DisplayNotification} */ this._notification = null; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._notificationHideTimer = null; /** @type {number} */ this._notificationHideTimeout = 5000; diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index b93757c2..98a4666b 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -63,7 +63,7 @@ export class SearchDisplayController { this._wanakanaBound = false; /** @type {boolean} */ this._introVisible = true; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._introAnimationTimer = null; /** @type {boolean} */ this._clipboardMonitorEnabled = false; diff --git a/ext/js/dom/document-util.js b/ext/js/dom/document-util.js index cf58d39f..549a8195 100644 --- a/ext/js/dom/document-util.js +++ b/ext/js/dom/document-util.js @@ -360,7 +360,7 @@ export class DocumentUtil { /** * Adds a fullscreen change event listener. This function handles all of the browser-specific variants. * @param {EventListener} onFullscreenChanged The event callback. - * @param {?EventListenerCollection} eventListenerCollection An optional `EventListenerCollection` to add the registration to. + * @param {?import('../core.js').EventListenerCollection} eventListenerCollection An optional `EventListenerCollection` to add the registration to. */ static addFullscreenChangeEventListener(onFullscreenChanged, eventListenerCollection=null) { const target = document; diff --git a/ext/js/dom/panel-element.js b/ext/js/dom/panel-element.js index 314eb2fd..748c3a36 100644 --- a/ext/js/dom/panel-element.js +++ b/ext/js/dom/panel-element.js @@ -37,7 +37,7 @@ export class PanelElement extends EventDispatcher { this._mutationObserver = null; /** @type {boolean} */ this._visible = false; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._closeTimer = null; } diff --git a/ext/js/language/text-scanner.js b/ext/js/language/text-scanner.js index f6bcde8d..d1b033e6 100644 --- a/ext/js/language/text-scanner.js +++ b/ext/js/language/text-scanner.js @@ -120,7 +120,7 @@ export class TextScanner extends EventDispatcher { /** @type {boolean} */ this._preventNextClickScan = false; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._preventNextClickScanTimer = null; /** @type {number} */ this._preventNextClickScanTimerDuration = 50; @@ -145,7 +145,7 @@ export class TextScanner extends EventDispatcher { /** @type {boolean} */ this._canClearSelection = true; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._textSelectionTimer = null; /** @type {boolean} */ this._yomitanIsChangingTextSelectionNow = false; @@ -995,7 +995,7 @@ export class TextScanner extends EventDispatcher { async _scanTimerWait() { const delay = this._delay; const promise = /** @type {Promise} */ (new Promise((resolve) => { - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let timeout = setTimeout(() => { timeout = null; resolve(true); diff --git a/ext/js/media/audio-downloader.js b/ext/js/media/audio-downloader.js index 0847d479..e041cc67 100644 --- a/ext/js/media/audio-downloader.js +++ b/ext/js/media/audio-downloader.js @@ -316,7 +316,7 @@ export class AudioDownloader { let signal; /** @type {?import('request-builder.js').ProgressCallback} */ let onProgress = null; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ let idleTimer = null; if (typeof idleTimeout === 'number') { const abortController = new AbortController(); diff --git a/ext/js/pages/settings/popup-preview-frame.js b/ext/js/pages/settings/popup-preview-frame.js index bb00829f..dab21f4d 100644 --- a/ext/js/pages/settings/popup-preview-frame.js +++ b/ext/js/pages/settings/popup-preview-frame.js @@ -43,7 +43,7 @@ export class PopupPreviewFrame { this._apiOptionsGetOld = null; /** @type {boolean} */ this._popupShown = false; - /** @type {?number} */ + /** @type {?import('core').Timeout} */ this._themeChangeTimeout = null; /** @type {?import('text-source').TextSource} */ this._textSource = null; diff --git a/test/jsconfig.json b/test/jsconfig.json index 261ec345..934aab81 100644 --- a/test/jsconfig.json +++ b/test/jsconfig.json @@ -31,7 +31,7 @@ "../ext/**/*.js", "../types/ext/**/*.ts", "../types/dev/**/*.ts", - "../types/other/web-set-timeout.d.ts" + "../types/other/globals.d.ts" ], "exclude": [ "../node_modules", diff --git a/types/ext/core.d.ts b/types/ext/core.d.ts index ce3a09f0..b83e6a74 100644 --- a/types/ext/core.d.ts +++ b/types/ext/core.d.ts @@ -100,3 +100,5 @@ export type MessageHandlerDetails = { export type MessageHandlerMap = Map; export type MessageHandlerArray = [key: string, handlerDetails: MessageHandlerDetails][]; + +export type Timeout = number | NodeJS.Timeout; diff --git a/types/ext/cross-frame-api.d.ts b/types/ext/cross-frame-api.d.ts index 5cedbec9..88ce59a7 100644 --- a/types/ext/cross-frame-api.d.ts +++ b/types/ext/cross-frame-api.d.ts @@ -50,5 +50,5 @@ export type Invocation = { responseTimeout: number; action: string; ack: boolean; - timer: number | null; + timer: Core.Timeout | null; }; diff --git a/types/ext/offscreen.d.ts b/types/ext/offscreen.d.ts index 7dd64d1e..ddf7eadc 100644 --- a/types/ext/offscreen.d.ts +++ b/types/ext/offscreen.d.ts @@ -112,4 +112,4 @@ export type MessageHandler< details: MessageDetailsMap[TMessage], ) => (TIsAsync extends true ? Promise> : MessageReturn); -export type MessageHandlerMap = Map; +export type MessageHandlerMap = Map; diff --git a/types/other/globals.d.ts b/types/other/globals.d.ts new file mode 100644 index 00000000..330f16c2 --- /dev/null +++ b/types/other/globals.d.ts @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +declare global { + function clearTimeout(timeoutId: NodeJS.Timeout | string | number | undefined): void; +} + +export {}; diff --git a/types/other/web-set-timeout.d.ts b/types/other/web-set-timeout.d.ts deleted file mode 100644 index 98e40dab..00000000 --- a/types/other/web-set-timeout.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2023 Yomitan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -declare module 'web-set-timeout' { - global { - // These types are used to ensure that setTimeout returns a number - function setTimeout(callback: (...args: TArgs) => void, ms?: number, ...args: TArgs): number; - function setTimeout(callback: (args: void) => void, ms?: number): number; - } -} -- cgit v1.2.3 From 97bc188ca6beb2057ab734e791b1afe96b6e4650 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 3 Dec 2023 11:15:50 -0500 Subject: Remove unused types --- types/dev/vm.d.ts | 21 -------------------- types/ext/anki-templates.d.ts | 6 ------ types/ext/backend.d.ts | 33 -------------------------------- types/ext/event-listener-collection.d.ts | 6 ------ types/ext/offscreen.d.ts | 2 -- types/ext/request-builder.d.ts | 5 ----- types/ext/settings.d.ts | 2 -- 7 files changed, 75 deletions(-) (limited to 'types/ext') diff --git a/types/dev/vm.d.ts b/types/dev/vm.d.ts index f103de97..3eb0949f 100644 --- a/types/dev/vm.d.ts +++ b/types/dev/vm.d.ts @@ -17,27 +17,6 @@ import type * as Translation from '../ext/translation'; -export type PseudoURL = { - hash: string; - host: string; - hostname: string; - href: string; - toString(): string; - origin: string; - password: string; - pathname: string; - port: string; - protocol: string; - search: string; - searchParams: URLSearchParams; - username: string; - toJSON(): string; -}; - -export type VMAssert = { - deepStrictEqual: (actual: unknown, expected: unknown) => void; -}; - export type PseudoChrome = { runtime: { getURL(path: string): string; diff --git a/types/ext/anki-templates.d.ts b/types/ext/anki-templates.d.ts index c7e49905..5c40f406 100644 --- a/types/ext/anki-templates.d.ts +++ b/types/ext/anki-templates.d.ts @@ -47,12 +47,6 @@ export type MediaSimpleType = ( 'selectionText' ); -export type MediaType = ( - MediaSimpleType | - 'textFurigana' | - 'dictionaryMedia' -); - export type TextFuriganaSegment = { text: string; readingMode: TextFuriganaReadingMode; diff --git a/types/ext/backend.d.ts b/types/ext/backend.d.ts index 5f1bd83d..08cbf4b0 100644 --- a/types/ext/backend.d.ts +++ b/types/ext/backend.d.ts @@ -47,39 +47,6 @@ export type TabInfo = { url: string | null; }; -export type SettingModification = SettingModificationSet | SettingModificationDelete | SettingModificationSwap | SettingModificationSplice | SettingModificationPush; - -export type SettingModificationSet = { - action: 'set'; - path: string; - value: unknown; -}; - -export type SettingModificationDelete = { - action: 'delete'; - path: string; -}; - -export type SettingModificationSwap = { - action: 'swap'; - path1: string; - path2: string; -}; - -export type SettingModificationSplice = { - action: 'splice'; - path: string; - start: number; - deleteCount: number; - items: unknown[]; -}; - -export type SettingModificationPush = { - action: 'push'; - path: string; - items: unknown[]; -}; - export type FindTabsPredicate = (tabInfo: TabInfo) => boolean | Promise; export type InvokeWithProgressRequestMessage = ( diff --git a/types/ext/event-listener-collection.d.ts b/types/ext/event-listener-collection.d.ts index f22d6bcc..eee05658 100644 --- a/types/ext/event-listener-collection.d.ts +++ b/types/ext/event-listener-collection.d.ts @@ -69,12 +69,6 @@ export type AddEventListenerArgs = [ options?: AddEventListenerOptions | boolean, ]; -export type AddListenerArgs = [ - target: ExtensionEvent, - callback: TCallback, - ...args: TArgs[], -]; - export type OnArgs = [ target: EventDispatcher, eventName: string, diff --git a/types/ext/offscreen.d.ts b/types/ext/offscreen.d.ts index ddf7eadc..85bce1ff 100644 --- a/types/ext/offscreen.d.ts +++ b/types/ext/offscreen.d.ts @@ -24,8 +24,6 @@ import type * as Environment from './environment'; import type * as Translation from './translation'; import type * as Translator from './translator'; -export type MessageAny2 = Message; - export type Message = ( MessageDetailsMap[T] extends undefined ? {action: T} : diff --git a/types/ext/request-builder.d.ts b/types/ext/request-builder.d.ts index 8f375754..b231bcd7 100644 --- a/types/ext/request-builder.d.ts +++ b/types/ext/request-builder.d.ts @@ -15,9 +15,4 @@ * along with this program. If not, see . */ -export type FetchEventListeners = { - onBeforeSendHeaders: ((details: chrome.webRequest.WebRequestHeadersDetails) => (chrome.webRequest.BlockingResponse | void)) | null; - onErrorOccurred: ((details: chrome.webRequest.WebResponseErrorDetails) => void) | null; -}; - export type ProgressCallback = (complete: boolean) => void; diff --git a/types/ext/settings.d.ts b/types/ext/settings.d.ts index 19c4aa1f..8ce82b28 100644 --- a/types/ext/settings.d.ts +++ b/types/ext/settings.d.ts @@ -283,8 +283,6 @@ export type AnkiOptions = { downloadTimeout: number; }; -export type AnkiCardType = 'terms' | 'kanji'; - export type AnkiScreenshotOptions = { format: AnkiScreenshotFormat; quality: number; -- cgit v1.2.3 From 4f24982112e7d4ad7b3f35c21926eafd6f0c8ff3 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 3 Dec 2023 11:17:57 -0500 Subject: Update imports --- types/ext/dictionary-importer.d.ts | 2 +- types/ext/dictionary-worker.d.ts | 2 +- types/ext/display-audio.d.ts | 4 ++-- types/ext/display.d.ts | 8 ++++---- types/ext/event-listener-collection.d.ts | 2 +- types/ext/generic-setting-controller.d.ts | 2 +- types/ext/popup.d.ts | 6 +++--- types/ext/settings-controller.d.ts | 6 +++--- types/ext/simple-dom-parser.d.ts | 5 ++--- types/ext/text-scanner.d.ts | 2 +- types/ext/translation-internal.d.ts | 2 +- types/ext/translator.d.ts | 4 ++-- types/other/globals.d.ts | 2 +- 13 files changed, 23 insertions(+), 24 deletions(-) (limited to 'types/ext') diff --git a/types/ext/dictionary-importer.d.ts b/types/ext/dictionary-importer.d.ts index de85d04a..5ae20dd1 100644 --- a/types/ext/dictionary-importer.d.ts +++ b/types/ext/dictionary-importer.d.ts @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -import type * as Ajv from 'ajv'; import type * as ZipJS from '@zip.js/zip.js'; +import type * as Ajv from 'ajv'; import type * as DictionaryData from './dictionary-data'; import type * as DictionaryDatabase from './dictionary-database'; import type * as StructuredContent from './structured-content'; diff --git a/types/ext/dictionary-worker.d.ts b/types/ext/dictionary-worker.d.ts index 570d37cd..17030691 100644 --- a/types/ext/dictionary-worker.d.ts +++ b/types/ext/dictionary-worker.d.ts @@ -16,8 +16,8 @@ */ import type * as Core from './core'; -import type * as DictionaryImporter from './dictionary-importer'; import type * as DictionaryDatabase from './dictionary-database'; +import type * as DictionaryImporter from './dictionary-importer'; export type InvokeDetails = { complete: boolean; diff --git a/types/ext/display-audio.d.ts b/types/ext/display-audio.d.ts index 759e5ee6..c9590cf2 100644 --- a/types/ext/display-audio.d.ts +++ b/types/ext/display-audio.d.ts @@ -15,10 +15,10 @@ * along with this program. If not, see . */ +import type {TextToSpeechAudio} from '../../ext/js/media/text-to-speech-audio'; import type * as Audio from './audio'; -import type * as Settings from './settings'; import type * as AudioDownloader from './audio-downloader'; -import type {TextToSpeechAudio} from '../../ext/js/media/text-to-speech-audio'; +import type * as Settings from './settings'; export type CacheItem = { sourceMap: Map; diff --git a/types/ext/display.d.ts b/types/ext/display.d.ts index 533fc441..aa0f0353 100644 --- a/types/ext/display.d.ts +++ b/types/ext/display.d.ts @@ -15,16 +15,16 @@ * along with this program. If not, see . */ +import type {DisplayContentManager} from '../../ext/js/display/display-content-manager'; +import type {HotkeyHelpController} from '../../ext/js/input/hotkey-help-controller'; +import type {JapaneseUtil} from '../../ext/js/language/sandbox/japanese-util'; +import type {TextScanner} from '../../ext/js/language/text-scanner'; import type * as Core from './core'; import type * as Dictionary from './dictionary'; import type * as Extension from './extension'; import type * as Settings from './settings'; import type * as TextScannerTypes from './text-scanner'; import type * as TextSource from './text-source'; -import type {DisplayContentManager} from '../../ext/js/display/display-content-manager'; -import type {HotkeyHelpController} from '../../ext/js/input/hotkey-help-controller'; -import type {JapaneseUtil} from '../../ext/js/language/sandbox/japanese-util'; -import type {TextScanner} from '../../ext/js/language/text-scanner'; export type HistoryMode = 'clear' | 'overwrite' | 'new'; diff --git a/types/ext/event-listener-collection.d.ts b/types/ext/event-listener-collection.d.ts index eee05658..988baa76 100644 --- a/types/ext/event-listener-collection.d.ts +++ b/types/ext/event-listener-collection.d.ts @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -import type * as Core from './core'; import type {EventDispatcher} from '../../ext/js/core'; +import type * as Core from './core'; export type EventListenerFunction = (...args: Core.SafeAny[]) => unknown; diff --git a/types/ext/generic-setting-controller.d.ts b/types/ext/generic-setting-controller.d.ts index 5e3435c5..f7a2be5f 100644 --- a/types/ext/generic-setting-controller.d.ts +++ b/types/ext/generic-setting-controller.d.ts @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -import type * as SettingsModifications from './settings-modifications'; import type * as DocumentUtil from './document-util'; +import type * as SettingsModifications from './settings-modifications'; export type TransformType = TransformData['type']; diff --git a/types/ext/popup.d.ts b/types/ext/popup.d.ts index aaeb676a..65725f96 100644 --- a/types/ext/popup.d.ts +++ b/types/ext/popup.d.ts @@ -15,12 +15,12 @@ * along with this program. If not, see . */ -import type * as DocumentUtil from './document-util'; -import type * as Settings from './settings'; -import type {FrameOffsetForwarder} from '../../ext/js/comm/frame-offset-forwarder'; import type {Popup} from '../../ext/js/app/popup'; import type {PopupProxy} from '../../ext/js/app/popup-proxy'; import type {PopupWindow} from '../../ext/js/app/popup-window'; +import type {FrameOffsetForwarder} from '../../ext/js/comm/frame-offset-forwarder'; +import type * as DocumentUtil from './document-util'; +import type * as Settings from './settings'; export type PopupAny = Popup | PopupWindow | PopupProxy; diff --git a/types/ext/settings-controller.d.ts b/types/ext/settings-controller.d.ts index 37399bc3..697de878 100644 --- a/types/ext/settings-controller.d.ts +++ b/types/ext/settings-controller.d.ts @@ -15,12 +15,12 @@ * along with this program. If not, see . */ -import type * as Core from './core'; -import type * as Settings from './settings'; -import type * as SettingsModifications from './settings-modifications'; import type {DictionaryController} from '../../ext/js/pages/settings/dictionary-controller'; import type {ScanInputsController} from '../../ext/js/pages/settings/scan-inputs-controller'; import type {ScanInputsSimpleController} from '../../ext/js/pages/settings/scan-inputs-simple-controller'; +import type * as Core from './core'; +import type * as Settings from './settings'; +import type * as SettingsModifications from './settings-modifications'; export type PageExitPrevention = { end: () => void; diff --git a/types/ext/simple-dom-parser.d.ts b/types/ext/simple-dom-parser.d.ts index 5fefe69d..d9ae3898 100644 --- a/types/ext/simple-dom-parser.d.ts +++ b/types/ext/simple-dom-parser.d.ts @@ -16,9 +16,8 @@ */ export type { - Document as Parse5Document, - Element as Parse5Element, - ChildNode as Parse5ChildNode, + ChildNode as Parse5ChildNode, Document as Parse5Document, + Element as Parse5Element } from 'parse5/dist/tree-adapters/default'; /** diff --git a/types/ext/text-scanner.d.ts b/types/ext/text-scanner.d.ts index 5ff62819..4ec7f204 100644 --- a/types/ext/text-scanner.d.ts +++ b/types/ext/text-scanner.d.ts @@ -15,12 +15,12 @@ * along with this program. If not, see . */ +import type {TextScanner} from '../../ext/js/language/text-scanner'; import type * as Dictionary from './dictionary'; import type * as Display from './display'; import type * as Input from './input'; import type * as Settings from './settings'; import type * as TextSource from './text-source'; -import type {TextScanner} from '../../ext/js/language/text-scanner'; export type SearchResultDetail = { documentTitle: string; diff --git a/types/ext/translation-internal.d.ts b/types/ext/translation-internal.d.ts index 00f51b05..784a5979 100644 --- a/types/ext/translation-internal.d.ts +++ b/types/ext/translation-internal.d.ts @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -import type * as Translation from './translation'; import type * as DictionaryDatabase from './dictionary-database'; +import type * as Translation from './translation'; export type TextDeinflectionOptions = [ textReplacements: Translation.FindTermsTextReplacement[] | null, diff --git a/types/ext/translator.d.ts b/types/ext/translator.d.ts index 838ae171..39d4be81 100644 --- a/types/ext/translator.d.ts +++ b/types/ext/translator.d.ts @@ -15,10 +15,10 @@ * along with this program. If not, see . */ -import type * as Dictionary from './dictionary'; -import type * as DictionaryDatabaseTypes from './dictionary-database'; import type {DictionaryDatabase} from '../../ext/js/language/dictionary-database'; import type {JapaneseUtil} from '../../ext/js/language/sandbox/japanese-util'; +import type * as Dictionary from './dictionary'; +import type * as DictionaryDatabaseTypes from './dictionary-database'; export type ConstructorDetails = { /** An instance of JapaneseUtil. */ diff --git a/types/other/globals.d.ts b/types/other/globals.d.ts index 330f16c2..4f6db6c9 100644 --- a/types/other/globals.d.ts +++ b/types/other/globals.d.ts @@ -19,4 +19,4 @@ declare global { function clearTimeout(timeoutId: NodeJS.Timeout | string | number | undefined): void; } -export {}; +export { }; -- cgit v1.2.3 From 4b80a486181b902f3b1e089b584818ce725a91be Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sun, 3 Dec 2023 11:21:47 -0500 Subject: Adjust settings --- .vscode/settings.json | 17 +++++++++++++---- types/ext/simple-dom-parser.d.ts | 5 +++-- 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'types/ext') diff --git a/.vscode/settings.json b/.vscode/settings.json index 3620e2a4..66e83d21 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,18 @@ { "markdown.extension.toc.levels": "1..3", - "editor.codeActionsOnSave": { - "source.addMissingImports": true, - "source.organizeImports": true, - "source.fixAll.eslint": true + "[javascript]": { + "editor.codeActionsOnSave": { + "source.addMissingImports": true, + "source.organizeImports": true, + "source.fixAll.eslint": true + }, + }, + "[typescript]": { + "editor.codeActionsOnSave": { + "source.addMissingImports": false, + "source.organizeImports": false, + "source.fixAll.eslint": true + }, }, "eslint.format.enable": true, "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false, diff --git a/types/ext/simple-dom-parser.d.ts b/types/ext/simple-dom-parser.d.ts index d9ae3898..971871a2 100644 --- a/types/ext/simple-dom-parser.d.ts +++ b/types/ext/simple-dom-parser.d.ts @@ -16,8 +16,9 @@ */ export type { - ChildNode as Parse5ChildNode, Document as Parse5Document, - Element as Parse5Element + ChildNode as Parse5ChildNode, + Document as Parse5Document, + Element as Parse5Element, } from 'parse5/dist/tree-adapters/default'; /** -- cgit v1.2.3