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) --- .../sandbox/template-renderer-frame-api.js | 86 ++++++++++++---------- 1 file changed, 47 insertions(+), 39 deletions(-) (limited to 'ext/js/templates/sandbox/template-renderer-frame-api.js') diff --git a/ext/js/templates/sandbox/template-renderer-frame-api.js b/ext/js/templates/sandbox/template-renderer-frame-api.js index 7ce2d909..31ba4500 100644 --- a/ext/js/templates/sandbox/template-renderer-frame-api.js +++ b/ext/js/templates/sandbox/template-renderer-frame-api.js @@ -17,15 +17,23 @@ */ export class TemplateRendererFrameApi { + /** + * @param {TemplateRenderer} templateRenderer + */ constructor(templateRenderer) { + /** @type {TemplateRenderer} */ this._templateRenderer = templateRenderer; - this._windowMessageHandlers = new Map([ + /** @type {import('core').MessageHandlerMap} */ + this._windowMessageHandlers = new Map(/** @type {import('core').MessageHandlerArray} */ ([ ['render', {async: false, handler: this._onRender.bind(this)}], ['renderMulti', {async: false, handler: this._onRenderMulti.bind(this)}], ['getModifiedData', {async: false, handler: this._onGetModifiedData.bind(this)}] - ]); + ])); } + /** + * @returns {void} + */ prepare() { window.addEventListener('message', this._onWindowMessage.bind(this), false); this._postMessage(window.parent, 'ready', {}, null); @@ -33,14 +41,24 @@ export class TemplateRendererFrameApi { // Private + /** + * @param {MessageEvent} e + */ _onWindowMessage(e) { const {source, data: {action, params, id}} = e; const messageHandler = this._windowMessageHandlers.get(action); if (typeof messageHandler === 'undefined') { return; } - this._onWindowMessageInner(messageHandler, action, params, source, id); + this._onWindowMessageInner(messageHandler, action, params, /** @type {Window} */ (source), id); } + /** + * @param {import('core').MessageHandlerDetails} handlerItem + * @param {string} action + * @param {import('core').SerializableObject} params + * @param {Window} source + * @param {?string} id + */ async _onWindowMessageInner({handler, async}, action, params, source, id) { let response; try { @@ -50,64 +68,54 @@ export class TemplateRendererFrameApi { } response = {result}; } catch (error) { - response = {error: this._serializeError(error)}; + response = {error: ExtensionError.serialize(error)}; } if (typeof id === 'undefined') { return; } this._postMessage(source, `${action}.response`, response, id); } + /** + * @param {{template: string, data: import('template-renderer').PartialOrCompositeRenderData, type: import('anki-templates').RenderMode}} event + * @returns {import('template-renderer').RenderResult} + */ _onRender({template, data, type}) { return this._templateRenderer.render(template, data, type); } + /** + * @param {{items: import('template-renderer').RenderMultiItem[]}} event + * @returns {import('core').Response[]} + */ _onRenderMulti({items}) { - return this._serializeMulti(this._templateRenderer.renderMulti(items)); + return this._templateRenderer.renderMulti(items); } + /** + * @param {{data: import('template-renderer').CompositeRenderData, type: import('anki-templates').RenderMode}} event + * @returns {import('anki-templates').NoteData} + */ _onGetModifiedData({data, type}) { const result = this._templateRenderer.getModifiedData(data, type); return this._clone(result); } - _serializeError(error) { - try { - if (typeof error === 'object' && error !== null) { - const result = { - name: error.name, - message: error.message, - stack: error.stack - }; - if (Object.prototype.hasOwnProperty.call(error, 'data')) { - result.data = error.data; - } - return result; - } - } catch (e) { - // NOP - } - return { - value: error, - hasValue: true - }; - } - - _serializeMulti(array) { - for (let i = 0, ii = array.length; i < ii; ++i) { - const value = array[i]; - const {error} = value; - if (typeof error !== 'undefined') { - value.error = this._serializeError(error); - } - } - return array; - } - + /** + * @template [T=unknown] + * @param {T} value + * @returns {T} + */ _clone(value) { return JSON.parse(JSON.stringify(value)); } + /** + * @param {Window} target + * @param {string} action + * @param {import('core').SerializableObject} params + * @param {?string} id + */ _postMessage(target, action, params, id) { - return target.postMessage({action, params, id}, '*'); + target.postMessage(/** @type {import('template-renderer-frame-api').MessageData} */ ({action, params, id}), '*'); } } -- cgit v1.2.3 From 6a3dae04de68ab633da15bbc8ec6b350e38e6d2f Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 13:54:43 -0500 Subject: Add extension error imports --- ext/js/app/popup.js | 1 + ext/js/comm/anki-connect.js | 1 + ext/js/data/anki-note-builder.js | 1 + ext/js/display/display-generator.js | 1 + ext/js/display/option-toggle-hotkey-handler.js | 1 + ext/js/language/dictionary-worker-handler.js | 1 + ext/js/language/dictionary-worker-media-loader.js | 1 + ext/js/language/dictionary-worker.js | 1 + ext/js/media/audio-downloader.js | 1 + ext/js/pages/settings/anki-controller.js | 1 + ext/js/pages/settings/anki-templates-controller.js | 1 + ext/js/pages/settings/dictionary-import-controller.js | 1 + ext/js/pages/settings/generic-setting-controller.js | 1 + ext/js/templates/sandbox/template-renderer-frame-api.js | 2 ++ ext/js/templates/sandbox/template-renderer.js | 1 + ext/js/templates/template-renderer-proxy.js | 1 + 16 files changed, 17 insertions(+) (limited to 'ext/js/templates/sandbox/template-renderer-frame-api.js') diff --git a/ext/js/app/popup.js b/ext/js/app/popup.js index 31b18f01..4f201fc3 100644 --- a/ext/js/app/popup.js +++ b/ext/js/app/popup.js @@ -18,6 +18,7 @@ import {FrameClient} from '../comm/frame-client.js'; import {DynamicProperty, EventDispatcher, EventListenerCollection, deepEqual} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; import {DocumentUtil} from '../dom/document-util.js'; import {dynamicLoader} from '../script/dynamic-loader.js'; import {yomitan} from '../yomitan.js'; diff --git a/ext/js/comm/anki-connect.js b/ext/js/comm/anki-connect.js index b876703f..7ff8d0e1 100644 --- a/ext/js/comm/anki-connect.js +++ b/ext/js/comm/anki-connect.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../core/extension-error.js'; import {AnkiUtil} from '../data/anki-util.js'; /** diff --git a/ext/js/data/anki-note-builder.js b/ext/js/data/anki-note-builder.js index f8296ee0..28809e1f 100644 --- a/ext/js/data/anki-note-builder.js +++ b/ext/js/data/anki-note-builder.js @@ -17,6 +17,7 @@ */ import {deferPromise} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; import {TemplateRendererProxy} from '../templates/template-renderer-proxy.js'; import {yomitan} from '../yomitan.js'; import {AnkiUtil} from './anki-util.js'; diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js index 9fc700f3..e8be79d9 100644 --- a/ext/js/display/display-generator.js +++ b/ext/js/display/display-generator.js @@ -17,6 +17,7 @@ */ import {isObject} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; import {HtmlTemplateCollection} from '../dom/html-template-collection.js'; import {DictionaryDataUtil} from '../language/sandbox/dictionary-data-util.js'; import {yomitan} from '../yomitan.js'; diff --git a/ext/js/display/option-toggle-hotkey-handler.js b/ext/js/display/option-toggle-hotkey-handler.js index e73fcf04..9677e86b 100644 --- a/ext/js/display/option-toggle-hotkey-handler.js +++ b/ext/js/display/option-toggle-hotkey-handler.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../core/extension-error.js'; import {yomitan} from '../yomitan.js'; export class OptionToggleHotkeyHandler { diff --git a/ext/js/language/dictionary-worker-handler.js b/ext/js/language/dictionary-worker-handler.js index 3a85cb71..9a724386 100644 --- a/ext/js/language/dictionary-worker-handler.js +++ b/ext/js/language/dictionary-worker-handler.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../core/extension-error.js'; import {DictionaryDatabase} from './dictionary-database.js'; import {DictionaryImporter} from './dictionary-importer.js'; import {DictionaryWorkerMediaLoader} from './dictionary-worker-media-loader.js'; diff --git a/ext/js/language/dictionary-worker-media-loader.js b/ext/js/language/dictionary-worker-media-loader.js index 2701389e..e19a13d3 100644 --- a/ext/js/language/dictionary-worker-media-loader.js +++ b/ext/js/language/dictionary-worker-media-loader.js @@ -17,6 +17,7 @@ */ import {generateId} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; /** * Class used for loading and validating media from a worker thread diff --git a/ext/js/language/dictionary-worker.js b/ext/js/language/dictionary-worker.js index b9d0236c..3e78a6ff 100644 --- a/ext/js/language/dictionary-worker.js +++ b/ext/js/language/dictionary-worker.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../core/extension-error.js'; import {DictionaryImporterMediaLoader} from './dictionary-importer-media-loader.js'; export class DictionaryWorker { diff --git a/ext/js/media/audio-downloader.js b/ext/js/media/audio-downloader.js index 8bd04b2b..7b236790 100644 --- a/ext/js/media/audio-downloader.js +++ b/ext/js/media/audio-downloader.js @@ -17,6 +17,7 @@ */ import {RequestBuilder} from '../background/request-builder.js'; +import {ExtensionError} from '../core/extension-error.js'; import {JsonSchema} from '../data/json-schema.js'; import {ArrayBufferUtil} from '../data/sandbox/array-buffer-util.js'; import {NativeSimpleDOMParser} from '../dom/native-simple-dom-parser.js'; diff --git a/ext/js/pages/settings/anki-controller.js b/ext/js/pages/settings/anki-controller.js index 0ccd018d..722459df 100644 --- a/ext/js/pages/settings/anki-controller.js +++ b/ext/js/pages/settings/anki-controller.js @@ -18,6 +18,7 @@ import {AnkiConnect} from '../../comm/anki-connect.js'; import {EventListenerCollection, log} from '../../core.js'; +import {ExtensionError} from '../../core/extension-error.js'; import {AnkiUtil} from '../../data/anki-util.js'; import {SelectorObserver} from '../../dom/selector-observer.js'; import {ObjectPropertyAccessor} from '../../general/object-property-accessor.js'; diff --git a/ext/js/pages/settings/anki-templates-controller.js b/ext/js/pages/settings/anki-templates-controller.js index d2814880..a0ff96b2 100644 --- a/ext/js/pages/settings/anki-templates-controller.js +++ b/ext/js/pages/settings/anki-templates-controller.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../../core/extension-error.js'; import {AnkiNoteBuilder} from '../../data/anki-note-builder.js'; import {JapaneseUtil} from '../../language/sandbox/japanese-util.js'; import {yomitan} from '../../yomitan.js'; diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js index 106ecbca..af8c2fcd 100644 --- a/ext/js/pages/settings/dictionary-import-controller.js +++ b/ext/js/pages/settings/dictionary-import-controller.js @@ -17,6 +17,7 @@ */ import {log} from '../../core.js'; +import {ExtensionError} from '../../core/extension-error.js'; import {DictionaryWorker} from '../../language/dictionary-worker.js'; import {yomitan} from '../../yomitan.js'; import {DictionaryController} from './dictionary-controller.js'; diff --git a/ext/js/pages/settings/generic-setting-controller.js b/ext/js/pages/settings/generic-setting-controller.js index 3c6104a9..47c0d6fe 100644 --- a/ext/js/pages/settings/generic-setting-controller.js +++ b/ext/js/pages/settings/generic-setting-controller.js @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../../core/extension-error.js'; import {DocumentUtil} from '../../dom/document-util.js'; import {DOMDataBinder} from '../../dom/dom-data-binder.js'; diff --git a/ext/js/templates/sandbox/template-renderer-frame-api.js b/ext/js/templates/sandbox/template-renderer-frame-api.js index 31ba4500..91400ab8 100644 --- a/ext/js/templates/sandbox/template-renderer-frame-api.js +++ b/ext/js/templates/sandbox/template-renderer-frame-api.js @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import {ExtensionError} from '../../core/extension-error.js'; + export class TemplateRendererFrameApi { /** * @param {TemplateRenderer} templateRenderer diff --git a/ext/js/templates/sandbox/template-renderer.js b/ext/js/templates/sandbox/template-renderer.js index c7613533..716e3ccc 100644 --- a/ext/js/templates/sandbox/template-renderer.js +++ b/ext/js/templates/sandbox/template-renderer.js @@ -17,6 +17,7 @@ */ import {Handlebars} from '../../../lib/handlebars.js'; +import {ExtensionError} from '../../core/extension-error.js'; export class TemplateRenderer { constructor() { diff --git a/ext/js/templates/template-renderer-proxy.js b/ext/js/templates/template-renderer-proxy.js index e67b715a..642eea8b 100644 --- a/ext/js/templates/template-renderer-proxy.js +++ b/ext/js/templates/template-renderer-proxy.js @@ -17,6 +17,7 @@ */ import {generateId} from '../core.js'; +import {ExtensionError} from '../core/extension-error.js'; export class TemplateRendererProxy { constructor() { -- cgit v1.2.3 From c8ac0d45bfb94deabd933117ba55d365f43fb1c5 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Mon, 27 Nov 2023 14:08:39 -0500 Subject: Updates --- .vscode/settings.json | 2 +- .../templates/__mocks__/template-renderer-proxy.js | 53 ++++++++-------------- .../anki-template-renderer-content-manager.js | 6 +-- ext/js/templates/sandbox/anki-template-renderer.js | 8 ++-- .../sandbox/template-renderer-frame-api.js | 4 +- ext/js/templates/sandbox/template-renderer.js | 8 ++-- 6 files changed, 32 insertions(+), 49 deletions(-) (limited to 'ext/js/templates/sandbox/template-renderer-frame-api.js') diff --git a/.vscode/settings.json b/.vscode/settings.json index ecfe13c5..81cd7b9c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,7 +3,7 @@ "editor.codeActionsOnSave": { "source.addMissingImports": false, "source.organizeImports": true, - "source.fixAll.eslint": true, + "source.fixAll.eslint": false }, "eslint.format.enable": true, "javascript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false, diff --git a/ext/js/templates/__mocks__/template-renderer-proxy.js b/ext/js/templates/__mocks__/template-renderer-proxy.js index bcacf13b..8823e8f3 100644 --- a/ext/js/templates/__mocks__/template-renderer-proxy.js +++ b/ext/js/templates/__mocks__/template-renderer-proxy.js @@ -20,20 +20,35 @@ import {AnkiTemplateRenderer} from '../sandbox/anki-template-renderer.js'; export class TemplateRendererProxy { constructor() { + /** @type {?Promise} */ this._preparePromise = null; + /** @type {AnkiTemplateRenderer} */ this._ankiTemplateRenderer = new AnkiTemplateRenderer(); } + /** + * @param {string} template + * @param {import('template-renderer').PartialOrCompositeRenderData} data + * @param {import('anki-templates').RenderMode} type + * @returns {Promise} + */ async render(template, data, type) { await this._prepare(); - return await this._ankiTemplateRenderer.templateRenderer.render(template, data, type); + return this._ankiTemplateRenderer.templateRenderer.render(template, data, type); } + /** + * @param {import('template-renderer').RenderMultiItem[]} items + * @returns {Promise[]>} + */ async renderMulti(items) { await this._prepare(); - return await this._serializeMulti(this._ankiTemplateRenderer.templateRenderer.renderMulti(items)); + return this._ankiTemplateRenderer.templateRenderer.renderMulti(items); } + /** + * @returns {Promise} + */ _prepare() { if (this._preparePromise === null) { this._preparePromise = this._prepareInternal(); @@ -41,40 +56,8 @@ export class TemplateRendererProxy { return this._preparePromise; } + /** */ async _prepareInternal() { await this._ankiTemplateRenderer.prepare(); } - - _serializeError(error) { - try { - if (typeof error === 'object' && error !== null) { - const result = { - name: error.name, - message: error.message, - stack: error.stack - }; - if (Object.prototype.hasOwnProperty.call(error, 'data')) { - result.data = error.data; - } - return result; - } - } catch (e) { - // NOP - } - return { - value: error, - hasValue: true - }; - } - - _serializeMulti(array) { - for (let i = 0, ii = array.length; i < ii; ++i) { - const value = array[i]; - const {error} = value; - if (typeof error !== 'undefined') { - value.error = this._serializeError(error); - } - } - return array; - } } diff --git a/ext/js/templates/sandbox/anki-template-renderer-content-manager.js b/ext/js/templates/sandbox/anki-template-renderer-content-manager.js index be80c211..4989ced3 100644 --- a/ext/js/templates/sandbox/anki-template-renderer-content-manager.js +++ b/ext/js/templates/sandbox/anki-template-renderer-content-manager.js @@ -22,12 +22,12 @@ export class AnkiTemplateRendererContentManager { /** * Creates a new instance of the class. - * @param {TemplateRendererMediaProvider} mediaProvider The media provider for the object. + * @param {import('./template-renderer-media-provider.js').TemplateRendererMediaProvider} mediaProvider The media provider for the object. * @param {import('anki-templates').NoteData} data The data object passed to the Handlebars template renderer. - * See {@link AnkiNoteDataCreator.create}'s return value for structure information. + * See AnkiNoteDataCreator.create's return value for structure information. */ constructor(mediaProvider, data) { - /** @type {TemplateRendererMediaProvider} */ + /** @type {import('./template-renderer-media-provider.js').TemplateRendererMediaProvider} */ this._mediaProvider = mediaProvider; /** @type {import('anki-templates').NoteData} */ this._data = data; diff --git a/ext/js/templates/sandbox/anki-template-renderer.js b/ext/js/templates/sandbox/anki-template-renderer.js index ce8e3200..9f4bf6ff 100644 --- a/ext/js/templates/sandbox/anki-template-renderer.js +++ b/ext/js/templates/sandbox/anki-template-renderer.js @@ -151,8 +151,8 @@ export class AnkiTemplateRenderer { } /** - * - * @param text + * @param {string} text + * @returns {string} */ _safeString(text) { return new Handlebars.SafeString(text); @@ -221,8 +221,8 @@ export class AnkiTemplateRenderer { } /** - * - * @param string + * @param {string} string + * @returns {string} */ _stringToMultiLineHtml(string) { return string.split('\n').join('
'); diff --git a/ext/js/templates/sandbox/template-renderer-frame-api.js b/ext/js/templates/sandbox/template-renderer-frame-api.js index 91400ab8..94ebf7fe 100644 --- a/ext/js/templates/sandbox/template-renderer-frame-api.js +++ b/ext/js/templates/sandbox/template-renderer-frame-api.js @@ -20,10 +20,10 @@ import {ExtensionError} from '../../core/extension-error.js'; export class TemplateRendererFrameApi { /** - * @param {TemplateRenderer} templateRenderer + * @param {import('./template-renderer.js').TemplateRenderer} templateRenderer */ constructor(templateRenderer) { - /** @type {TemplateRenderer} */ + /** @type {import('./template-renderer.js').TemplateRenderer} */ this._templateRenderer = templateRenderer; /** @type {import('core').MessageHandlerMap} */ this._windowMessageHandlers = new Map(/** @type {import('core').MessageHandlerArray} */ ([ diff --git a/ext/js/templates/sandbox/template-renderer.js b/ext/js/templates/sandbox/template-renderer.js index 716e3ccc..fe240b5f 100644 --- a/ext/js/templates/sandbox/template-renderer.js +++ b/ext/js/templates/sandbox/template-renderer.js @@ -21,7 +21,7 @@ import {ExtensionError} from '../../core/extension-error.js'; export class TemplateRenderer { constructor() { - /** @type {Map>} */ + /** @type {Map>} */ this._cache = new Map(); /** @type {number} */ this._cacheMaxSize = 5; @@ -110,14 +110,14 @@ export class TemplateRenderer { /** * @param {string} template - * @returns {HandlebarsTemplateDelegate} + * @returns {import('handlebars').TemplateDelegate} */ _getTemplateInstance(template) { const cache = this._cache; let instance = cache.get(template); if (typeof instance === 'undefined') { this._updateCacheSize(this._cacheMaxSize - 1); - instance = /** @type {HandlebarsTemplateDelegate} */ (Handlebars.compileAST(template)); + instance = /** @type {import('handlebars').TemplateDelegate} */ (Handlebars.compileAST(template)); cache.set(template, instance); } @@ -125,7 +125,7 @@ export class TemplateRenderer { } /** - * @param {HandlebarsTemplateDelegate} instance + * @param {import('handlebars').TemplateDelegate} instance * @param {import('anki-templates').NoteData} data * @returns {import('template-renderer').RenderResult} */ -- cgit v1.2.3