ESlint JSdoc (#2148)

* Install eslint-plugin-jsdoc

* Initial rules setup

* Update lists

* Use @returns rather than @return

* Remove error throwing code which is never executed

* Fix issues relating to @throws

* General error fixes

* Update Display type documentation

* Various doc fixes

* Fix invalid tuple syntax

* Doc updates

* Remove unused

* Doc updates

* Enable jsdoc/require-returns

* Update rules

* Update remaining rules
This commit is contained in:
toasted-nutbread 2022-05-20 10:28:38 -04:00 committed by GitHub
parent ae0ad227c0
commit 31e20c889e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 544 additions and 249 deletions

View File

@ -16,7 +16,8 @@
}, },
"plugins": [ "plugins": [
"no-unsanitized", "no-unsanitized",
"header" "header",
"jsdoc"
], ],
"ignorePatterns": [ "ignorePatterns": [
"/ext/lib/" "/ext/lib/"
@ -87,6 +88,41 @@
"no-unsanitized/method": "error", "no-unsanitized/method": "error",
"no-unsanitized/property": "error", "no-unsanitized/property": "error",
"jsdoc/check-access": "error",
"jsdoc/check-alignment": "error",
"jsdoc/check-line-alignment": "error",
"jsdoc/check-param-names": "error",
"jsdoc/check-property-names": "error",
"jsdoc/check-tag-names": "error",
"jsdoc/check-types": "error",
"jsdoc/check-values": "error",
"jsdoc/empty-tags": "error",
"jsdoc/implements-on-classes": "error",
"jsdoc/multiline-blocks": "error",
"jsdoc/newline-after-description": ["error", "never"],
"jsdoc/no-bad-blocks": "error",
"jsdoc/no-multi-asterisks": "error",
"jsdoc/require-asterisk-prefix": "error",
"jsdoc/require-hyphen-before-param-description": ["error", "never"],
"jsdoc/require-jsdoc": "off",
"jsdoc/require-param": "error",
"jsdoc/require-param-description": "error",
"jsdoc/require-param-name": "error",
"jsdoc/require-param-type": "error",
"jsdoc/require-property": "error",
"jsdoc/require-property-description": "error",
"jsdoc/require-property-name": "error",
"jsdoc/require-property-type": "error",
"jsdoc/require-returns": "error",
"jsdoc/require-returns-check": "error",
"jsdoc/require-returns-description": "error",
"jsdoc/require-returns-type": "error",
"jsdoc/require-throws": "error",
"jsdoc/require-yields": "error",
"jsdoc/require-yields-check": "error",
"jsdoc/tag-lines": "error",
"jsdoc/valid-types": "error",
"header/header": ["error", "block", [ "header/header": ["error", "block", [
"", "",
{"pattern": " \\* Copyright \\(C\\) (\\d+-)?2022 Yomichan Authors"}, {"pattern": " \\* Copyright \\(C\\) (\\d+-)?2022 Yomichan Authors"},

View File

@ -20,8 +20,8 @@ const assert = require('assert');
/** /**
* This function patches the following bug: * This function patches the following bug:
* * https://github.com/jsdom/jsdom/issues/3211 * - https://github.com/jsdom/jsdom/issues/3211
* * https://github.com/dperini/nwsapi/issues/48 * - https://github.com/dperini/nwsapi/issues/48
*/ */
function patchNwsapi() { function patchNwsapi() {
const nwsapiPath = require.resolve('nwsapi'); const nwsapiPath = require.resolve('nwsapi');

View File

@ -27,7 +27,7 @@
class Frontend { class Frontend {
/** /**
* Creates a new instance. * Creates a new instance.
* @param {object} details * @param {object} details Details about how to set up the instance.
* @param {string} details.pageType The type of page, one of 'web', 'popup', or 'search'. * @param {string} details.pageType The type of page, one of 'web', 'popup', or 'search'.
* @param {PopupFactory} details.popupFactory A PopupFactory instance to use for generating popups. * @param {PopupFactory} details.popupFactory A PopupFactory instance to use for generating popups.
* @param {number} details.depth The nesting depth value of the popup. * @param {number} details.depth The nesting depth value of the popup.

View File

@ -63,7 +63,7 @@ class PopupFactory {
/** /**
* Gets or creates a popup based on a set of parameters * Gets or creates a popup based on a set of parameters
* @param {object} details * @param {object} details Details about how to acquire the popup.
* @param {?number} [details.frameId] The ID of the frame that should host the popup. * @param {?number} [details.frameId] The ID of the frame that should host the popup.
* @param {?string} [details.id] A specific ID used to find an existing popup, or to assign to the new popup. * @param {?string} [details.id] A specific ID used to find an existing popup, or to assign to the new popup.
* @param {?string} [details.parentPopupId] The ID of the parent popup. * @param {?string} [details.parentPopupId] The ID of the parent popup.

View File

@ -22,7 +22,7 @@
class PopupProxy extends EventDispatcher { class PopupProxy extends EventDispatcher {
/** /**
* Creates a new instance. * Creates a new instance.
* @param {object} details * @param {object} details Details about how to set up the instance.
* @param {string} details.id The ID of the popup. * @param {string} details.id The ID of the popup.
* @param {number} details.depth The depth of the popup. * @param {number} details.depth The depth of the popup.
* @param {number} details.frameId The ID of the host frame. * @param {number} details.frameId The ID of the host frame.
@ -66,10 +66,10 @@ class PopupProxy extends EventDispatcher {
/** /**
* Attempts to set the parent popup. * Attempts to set the parent popup.
* @param {Popup} value * @param {Popup} _value The parent to assign.
* @throws Throws an error, since this class doesn't support a direct parent. * @throws {Error} Throws an error, since this class doesn't support a direct parent.
*/ */
set parent(value) { set parent(_value) {
throw new Error('Not supported on PopupProxy'); throw new Error('Not supported on PopupProxy');
} }
@ -84,10 +84,10 @@ class PopupProxy extends EventDispatcher {
/** /**
* Attempts to set the child popup. * Attempts to set the child popup.
* @param {Popup} value * @param {Popup} _child The child to assign.
* @throws Throws an error, since this class doesn't support children. * @throws {Error} Throws an error, since this class doesn't support children.
*/ */
set child(value) { set child(_child) {
throw new Error('Not supported on PopupProxy'); throw new Error('Not supported on PopupProxy');
} }
@ -233,7 +233,6 @@ class PopupProxy extends EventDispatcher {
/** /**
* Returns whether or not the popup is currently visible, synchronously. * Returns whether or not the popup is currently visible, synchronously.
* @returns {boolean} `true` if the popup is visible, `false` otherwise.
* @throws An exception is thrown for `PopupProxy` since it cannot synchronously detect visibility. * @throws An exception is thrown for `PopupProxy` since it cannot synchronously detect visibility.
*/ */
isVisibleSync() { isVisibleSync() {

View File

@ -21,7 +21,7 @@
class PopupWindow extends EventDispatcher { class PopupWindow extends EventDispatcher {
/** /**
* Creates a new instance. * Creates a new instance.
* @param {object} details * @param {object} details Details about how to set up the instance.
* @param {string} details.id The ID of the popup. * @param {string} details.id The ID of the popup.
* @param {number} details.depth The depth of the popup. * @param {number} details.depth The depth of the popup.
* @param {number} details.frameId The ID of the host frame. * @param {number} details.frameId The ID of the host frame.
@ -53,10 +53,10 @@ class PopupWindow extends EventDispatcher {
/** /**
* The parent of the popup, which is always `null` for `PopupWindow` instances, * The parent of the popup, which is always `null` for `PopupWindow` instances,
* since any potential parent popups are in a different frame. * since any potential parent popups are in a different frame.
* @param {Popup} value * @param {Popup} _value The parent to assign.
* @type {Popup} * @throws {Error} Throws an error, since this class doesn't support children.
*/ */
set parent(value) { set parent(_value) {
throw new Error('Not supported on PopupWindow'); throw new Error('Not supported on PopupWindow');
} }
@ -71,10 +71,10 @@ class PopupWindow extends EventDispatcher {
/** /**
* Attempts to set the child popup. * Attempts to set the child popup.
* @param {Popup} value * @param {Popup} _value The child to assign.
* @throws Throws an error, since this class doesn't support children. * @throws Throws an error, since this class doesn't support children.
*/ */
set child(value) { set child(_value) {
throw new Error('Not supported on PopupWindow'); throw new Error('Not supported on PopupWindow');
} }
@ -168,7 +168,7 @@ class PopupWindow extends EventDispatcher {
/** /**
* Shows and updates the positioning and content of the popup. * Shows and updates the positioning and content of the popup.
* @param {Popup.ContentDetails} details Settings for the outer popup. * @param {Popup.ContentDetails} _details Settings for the outer popup.
* @param {Display.ContentDetails} displayDetails The details parameter passed to `Display.setContent`. * @param {Display.ContentDetails} displayDetails The details parameter passed to `Display.setContent`.
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
@ -180,6 +180,7 @@ class PopupWindow extends EventDispatcher {
/** /**
* Sets the custom styles for the popup content. * Sets the custom styles for the popup content.
* @param {string} css The CSS rules. * @param {string} css The CSS rules.
* @returns {Promise<void>}
*/ */
setCustomCss(css) { setCustomCss(css) {
return this._invoke(false, 'Display.setCustomCss', {id: this._id, css}); return this._invoke(false, 'Display.setCustomCss', {id: this._id, css});
@ -187,6 +188,7 @@ class PopupWindow extends EventDispatcher {
/** /**
* Stops the audio auto-play timer, if one has started. * Stops the audio auto-play timer, if one has started.
* @returns {Promise<void>}
*/ */
clearAutoPlayTimer() { clearAutoPlayTimer() {
return this._invoke(false, 'Display.clearAutoPlayTimer', {id: this._id}); return this._invoke(false, 'Display.clearAutoPlayTimer', {id: this._id});
@ -194,7 +196,7 @@ class PopupWindow extends EventDispatcher {
/** /**
* Sets the scaling factor of the popup content. * Sets the scaling factor of the popup content.
* @param {number} scale The scaling factor. * @param {number} _scale The scaling factor.
*/ */
setContentScale(_scale) { setContentScale(_scale) {
// NOP // NOP
@ -202,7 +204,6 @@ class PopupWindow extends EventDispatcher {
/** /**
* Returns whether or not the popup is currently visible, synchronously. * Returns whether or not the popup is currently visible, synchronously.
* @returns {boolean} `true` if the popup is visible, `false` otherwise.
* @throws An exception is thrown for `PopupWindow` since it cannot synchronously detect visibility. * @throws An exception is thrown for `PopupWindow` since it cannot synchronously detect visibility.
*/ */
isVisibleSync() { isVisibleSync() {

View File

@ -66,7 +66,7 @@ class Popup extends EventDispatcher {
/** /**
* Creates a new instance. * Creates a new instance.
* @param {object} details * @param {object} details The details used to construct the new instance.
* @param {string} details.id The ID of the popup. * @param {string} details.id The ID of the popup.
* @param {number} details.depth The depth of the popup. * @param {number} details.depth The depth of the popup.
* @param {number} details.frameId The ID of the host frame. * @param {number} details.frameId The ID of the host frame.
@ -673,9 +673,11 @@ class Popup extends EventDispatcher {
} }
/** /**
* @param {Rect[]} sourceRects * Computes the position where the popup should be placed relative to the source content.
* @param {string} writingMode * @param {Rect[]} sourceRects The rectangles of the source content.
* @returns {SizeRect} * @param {string} writingMode The CSS writing mode of the source text.
* @param {Rect} viewport The viewport that the popup can be placed within.
* @returns {SizeRect} The calculated rectangle for where to position the popup.
*/ */
_getPosition(sourceRects, writingMode, viewport) { _getPosition(sourceRects, writingMode, viewport) {
const scale = this._contentScale; const scale = this._contentScale;
@ -720,7 +722,15 @@ class Popup extends EventDispatcher {
} }
/** /**
* @returns {SizeRect} * Computes the position where the popup should be placed for horizontal text.
* @param {Rect} sourceRect The rectangle of the source content.
* @param {number} frameWidth The preferred width of the frame.
* @param {number} frameHeight The preferred height of the frame.
* @param {Rect} viewport The viewport that the frame can be placed within.
* @param {number} horizontalOffset The horizontal offset from the source rect that the popup will be placed.
* @param {number} verticalOffset The vertical offset from the source rect that the popup will be placed.
* @param {boolean} preferBelow Whether or not the popup is preferred to be placed below the source content.
* @returns {SizeRect} The calculated rectangle for where to position the popup.
*/ */
_getPositionForHorizontalText(sourceRect, frameWidth, frameHeight, viewport, horizontalOffset, verticalOffset, preferBelow) { _getPositionForHorizontalText(sourceRect, frameWidth, frameHeight, viewport, horizontalOffset, verticalOffset, preferBelow) {
const [left, width, after] = this._getConstrainedPosition( const [left, width, after] = this._getConstrainedPosition(
@ -743,7 +753,15 @@ class Popup extends EventDispatcher {
} }
/** /**
* @returns {SizeRect} * Computes the position where the popup should be placed for vertical text.
* @param {Rect} sourceRect The rectangle of the source content.
* @param {number} frameWidth The preferred width of the frame.
* @param {number} frameHeight The preferred height of the frame.
* @param {Rect} viewport The viewport that the frame can be placed within.
* @param {number} horizontalOffset The horizontal offset from the source rect that the popup will be placed.
* @param {number} verticalOffset The vertical offset from the source rect that the popup will be placed.
* @param {boolean} preferRight Whether or not the popup is preferred to be placed to the right of the source content.
* @returns {SizeRect} The calculated rectangle for where to position the popup.
*/ */
_getPositionForVerticalText(sourceRect, frameWidth, frameHeight, viewport, horizontalOffset, verticalOffset, preferRight) { _getPositionForVerticalText(sourceRect, frameWidth, frameHeight, viewport, horizontalOffset, verticalOffset, preferRight) {
const [left, width, after] = this._getConstrainedPositionBinary( const [left, width, after] = this._getConstrainedPositionBinary(
@ -824,6 +842,11 @@ class Popup extends EventDispatcher {
return [position, size, after]; return [position, size, after];
} }
/**
* Gets the visual viewport.
* @param {boolean} useVisualViewport Whether or not the `window.visualViewport` should be used.
* @returns {Rect} The rectangle of the visual viewport.
*/
_getViewport(useVisualViewport) { _getViewport(useVisualViewport) {
const visualViewport = window.visualViewport; const visualViewport = window.visualViewport;
if (visualViewport !== null && typeof visualViewport === 'object') { if (visualViewport !== null && typeof visualViewport === 'object') {
@ -887,8 +910,9 @@ class Popup extends EventDispatcher {
} }
/** /**
* @param {Rect[]} sourceRects * Computes the bounding rectangle for a set of rectangles.
* @returns {Rect} * @param {Rect[]} sourceRects An array of rectangles.
* @returns {Rect} The bounding rectangle for all of the source rectangles.
*/ */
_getBoundingSourceRect(sourceRects) { _getBoundingSourceRect(sourceRects) {
switch (sourceRects.length) { switch (sourceRects.length) {
@ -907,10 +931,11 @@ class Popup extends EventDispatcher {
} }
/** /**
* @param {SizeRect} sizeRect * Checks whether or not a rectangle is overlapping any other rectangles.
* @param {Rect[]} sourceRects * @param {SizeRect} sizeRect The rectangles to check for overlaps.
* @param {number} ignoreIndex * @param {Rect[]} sourceRects The list of rectangles to compare against.
* @returns {boolean} * @param {number} ignoreIndex The index of an item in `sourceRects` to ignore.
* @returns {boolean} `true` if `sizeRect` overlaps any one of `sourceRects`, excluding `sourceRects[ignoreIndex]`; `false` otherwise.
*/ */
_isOverlapping(sizeRect, sourceRects, ignoreIndex) { _isOverlapping(sizeRect, sourceRects, ignoreIndex) {
const {left, top} = sizeRect; const {left, top} = sizeRect;

View File

@ -174,7 +174,7 @@ class ThemeController {
/** /**
* Adds the value of a CSS color to an accumulation target. * Adds the value of a CSS color to an accumulation target.
* @param {[number, number, number]} target The target color buffer to accumulate into. * @param {number[]} target The target color buffer to accumulate into, as an array of [r, g, b].
* @param {string|*} cssColor The CSS color value to add to the target. If this value is not a string, * @param {string|*} cssColor The CSS color value to add to the target. If this value is not a string,
* the target will not be modified. * the target will not be modified.
*/ */
@ -196,7 +196,7 @@ class ThemeController {
/** /**
* Decomposes a CSS color string into its RGBA values. * Decomposes a CSS color string into its RGBA values.
* @param {string} cssColor The color value to decompose. This value is expected to be in the form RGB(r, g, b) or RGBA(r, g, b, a). * @param {string} cssColor The color value to decompose. This value is expected to be in the form RGB(r, g, b) or RGBA(r, g, b, a).
* @returns {?[number, number, number, number]} The color and alpha values. The color component values range from [0, 255], and the alpha ranges from [0, 1]. * @returns {?number[]} The color and alpha values as [r, g, b, a]. The color component values range from [0, 255], and the alpha ranges from [0, 1].
*/ */
_getColorInfo(cssColor) { _getColorInfo(cssColor) {
const m = /^\s*rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+)\s*)?\)\s*$/.exec(cssColor); const m = /^\s*rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+)\s*)?\)\s*$/.exec(cssColor);

View File

@ -23,6 +23,20 @@
* Utility class to help processing profile conditions. * Utility class to help processing profile conditions.
*/ */
class ProfileConditionsUtil { class ProfileConditionsUtil {
/**
* A group of conditions.
* @typedef {object} ProfileConditionGroup
* @property {ProfileCondition[]} conditions The list of conditions for this group.
*/
/**
* A single condition.
* @typedef {object} ProfileCondition
* @property {string} type The type of the condition.
* @property {string} operator The condition operator.
* @property {string} value The value to compare against.
*/
/** /**
* Creates a new instance. * Creates a new instance.
*/ */
@ -78,20 +92,9 @@ class ProfileConditionsUtil {
/** /**
* Creates a new JSON schema descriptor for the given set of condition groups. * Creates a new JSON schema descriptor for the given set of condition groups.
* @param conditionGroups An array of condition groups in the following format: * @param {ProfileConditionGroup[]} conditionGroups An array of condition groups.
* conditionGroups = [ * For a profile match, all of the items must return successfully in at least one of the groups.
* { * @returns {JsonSchema} A new `JsonSchema` object.
* conditions: [
* {
* type: (condition type: string),
* operator: (condition sub-type: string),
* value: (value to compare against: string)
* },
* ...
* ]
* },
* ...
* ]
*/ */
createSchema(conditionGroups) { createSchema(conditionGroups) {
const anyOf = []; const anyOf = [];
@ -125,8 +128,8 @@ class ProfileConditionsUtil {
/** /**
* Creates a normalized version of the context object to test, * Creates a normalized version of the context object to test,
* assigning dependent fields as needed. * assigning dependent fields as needed.
* @param context A context object which is used during schema validation. * @param {object} context A context object which is used during schema validation.
* @returns A normalized context object. * @returns {object} A normalized context object.
*/ */
normalizeContext(context) { normalizeContext(context) {
const normalizedContext = Object.assign({}, context); const normalizedContext = Object.assign({}, context);

View File

@ -25,9 +25,10 @@
class ClipboardReader { class ClipboardReader {
/** /**
* Creates a new instances of a clipboard reader. * Creates a new instances of a clipboard reader.
* @param document The Document object to be used, or null for no support. * @param {object} details Details about how to set up the instance.
* @param pasteTargetSelector The selector for the paste target element. * @param {?Document} details.document The Document object to be used, or null for no support.
* @param imagePasteTargetSelector The selector for the image paste target element. * @param {?string} details.pasteTargetSelector The selector for the paste target element.
* @param {?string} details.imagePasteTargetSelector The selector for the image paste target element.
*/ */
constructor({document=null, pasteTargetSelector=null, imagePasteTargetSelector=null}) { constructor({document=null, pasteTargetSelector=null, imagePasteTargetSelector=null}) {
this._document = document; this._document = document;
@ -40,6 +41,7 @@ class ClipboardReader {
/** /**
* Gets the browser being used. * Gets the browser being used.
* @type {?string}
*/ */
get browser() { get browser() {
return this._browser; return this._browser;
@ -54,8 +56,8 @@ class ClipboardReader {
/** /**
* Gets the text in the clipboard. * Gets the text in the clipboard.
* @returns A string containing the clipboard text. * @returns {string} A string containing the clipboard text.
* @throws Error if not supported. * @throws {Error} Error if not supported.
*/ */
async getText() { async getText() {
/* /*
@ -103,8 +105,8 @@ class ClipboardReader {
/** /**
* Gets the first image in the clipboard. * Gets the first image in the clipboard.
* @returns A string containing a data URL of the image file, or null if no image was found. * @returns {string} A string containing a data URL of the image file, or null if no image was found.
* @throws Error if not supported. * @throws {Error} Error if not supported.
*/ */
async getImage() { async getImage() {
// See browser-specific notes in getText // See browser-specific notes in getText

View File

@ -24,7 +24,7 @@
class FrameAncestryHandler { class FrameAncestryHandler {
/** /**
* Creates a new instance. * Creates a new instance.
* @param frameId The frame ID of the current frame the instance is instantiated in. * @param {number} frameId The frame ID of the current frame the instance is instantiated in.
*/ */
constructor(frameId) { constructor(frameId) {
this._frameId = frameId; this._frameId = frameId;
@ -37,6 +37,7 @@ class FrameAncestryHandler {
/** /**
* Gets the frame ID that the instance is instantiated in. * Gets the frame ID that the instance is instantiated in.
* @type {number}
*/ */
get frameId() { get frameId() {
return this._frameId; return this._frameId;
@ -53,7 +54,7 @@ class FrameAncestryHandler {
/** /**
* Returns whether or not this frame is the root frame in the tab. * Returns whether or not this frame is the root frame in the tab.
* @returns `true` if it is the root, otherwise `false`. * @returns {boolean} `true` if it is the root, otherwise `false`.
*/ */
isRootFrame() { isRootFrame() {
return (window === window.parent); return (window === window.parent);
@ -63,8 +64,7 @@ class FrameAncestryHandler {
* Gets the frame ancestry information for the current frame. If the frame is the * Gets the frame ancestry information for the current frame. If the frame is the
* root frame, an empty array is returned. Otherwise, an array of frame IDs is returned, * root frame, an empty array is returned. Otherwise, an array of frame IDs is returned,
* starting from the nearest ancestor. * starting from the nearest ancestor.
* @param timeout The maximum time to wait to receive a response to frame information requests. * @returns {number[]} An array of frame IDs corresponding to the ancestors of the current frame.
* @returns An array of frame IDs corresponding to the ancestors of the current frame.
*/ */
async getFrameAncestryInfo() { async getFrameAncestryInfo() {
if (this._getFrameAncestryInfoPromise === null) { if (this._getFrameAncestryInfoPromise === null) {
@ -77,8 +77,8 @@ class FrameAncestryHandler {
* Gets the frame element of a child frame given a frame ID. * Gets the frame element of a child frame given a frame ID.
* For this function to work, the `getFrameAncestryInfo` function needs to have * For this function to work, the `getFrameAncestryInfo` function needs to have
* been invoked previously. * been invoked previously.
* @param frameId The frame ID of the child frame to get. * @param {number} frameId The frame ID of the child frame to get.
* @returns The element corresponding to the frame with ID `frameId`, otherwise `null`. * @returns {HTMLElement} The element corresponding to the frame with ID `frameId`, otherwise `null`.
*/ */
getChildFrameElement(frameId) { getChildFrameElement(frameId) {
const frameInfo = this._childFrameMap.get(frameId); const frameInfo = this._childFrameMap.get(frameId);

View File

@ -20,6 +20,21 @@
* used to parse text into individual terms. * used to parse text into individual terms.
*/ */
class Mecab { class Mecab {
/**
* The resulting data from an invocation of `parseText`.
* @typedef {object} ParseResult
* @property {string} name The dictionary name for the parsed result.
* @property {ParseTerm[]} lines The resulting parsed terms.
*/
/**
* A fragment of the parsed text.
* @typedef {object} ParseFragment
* @property {string} term The term.
* @property {string} reading The reading of the term.
* @property {string} source The source text.
*/
/** /**
* Creates a new instance of the class. * Creates a new instance of the class.
*/ */
@ -37,6 +52,7 @@ class Mecab {
/** /**
* Returns whether or not the component is enabled. * Returns whether or not the component is enabled.
* @returns {boolean} Whether or not the object is enabled.
*/ */
isEnabled() { isEnabled() {
return this._enabled; return this._enabled;
@ -44,7 +60,7 @@ class Mecab {
/** /**
* Changes whether or not the component connection is enabled. * Changes whether or not the component connection is enabled.
* @param enabled A boolean indicating whether or not the component should be enabled. * @param {boolean} enabled A boolean indicating whether or not the component should be enabled.
*/ */
setEnabled(enabled) { setEnabled(enabled) {
this._enabled = !!enabled; this._enabled = !!enabled;
@ -64,7 +80,7 @@ class Mecab {
/** /**
* Returns whether or not the connection to the native application is active. * Returns whether or not the connection to the native application is active.
* @returns `true` if the connection is active, `false` otherwise. * @returns {boolean} `true` if the connection is active, `false` otherwise.
*/ */
isConnected() { isConnected() {
return (this._port !== null); return (this._port !== null);
@ -72,7 +88,7 @@ class Mecab {
/** /**
* Returns whether or not any invocation is currently active. * Returns whether or not any invocation is currently active.
* @returns `true` if an invocation is active, `false` otherwise. * @returns {boolean} `true` if an invocation is active, `false` otherwise.
*/ */
isActive() { isActive() {
return (this._invocations.size > 0); return (this._invocations.size > 0);
@ -80,7 +96,7 @@ class Mecab {
/** /**
* Gets the local API version being used. * Gets the local API version being used.
* @returns An integer representing the API version that Yomichan uses. * @returns {number} An integer representing the API version that Yomichan uses.
*/ */
getLocalVersion() { getLocalVersion() {
return this._version; return this._version;
@ -88,7 +104,7 @@ class Mecab {
/** /**
* Gets the version of the MeCab component. * Gets the version of the MeCab component.
* @returns The version of the MeCab component, or `null` if the component was not found. * @returns {?number} The version of the MeCab component, or `null` if the component was not found.
*/ */
async getVersion() { async getVersion() {
try { try {
@ -115,8 +131,8 @@ class Mecab {
* ... * ...
* ] * ]
* ``` * ```
* @param text The string to parse. * @param {string} text The string to parse.
* @returns A collection of parsing results of the text. * @returns {ParseResult[]} A collection of parsing results of the text.
*/ */
async parseText(text) { async parseText(text) {
await this._setupPort(); await this._setupPort();

View File

@ -250,7 +250,7 @@ function generateId(length) {
/** /**
* Creates an unresolved promise that can be resolved later, outside the promise's executor function. * Creates an unresolved promise that can be resolved later, outside the promise's executor function.
* @returns {{promise: Promise, resolve: function, reject: function}} An object `{promise, resolve, reject}`, containing the promise and the resolve/reject functions. * @returns {{promise: Promise, resolve: Function, reject: Function}} An object `{promise, resolve, reject}`, containing the promise and the resolve/reject functions.
*/ */
function deferPromise() { function deferPromise() {
let resolve; let resolve;
@ -349,15 +349,15 @@ function promiseAnimationFrame(timeout=null) {
/** /**
* Invokes a standard message handler. This function is used to react and respond * Invokes a standard message handler. This function is used to react and respond
* to communication messages within the extension. * to communication messages within the extension.
* @param {object} details * @param {object} details Details about how to handle messages.
* @param {function} details.handler A handler function which is passed `params` and `...extraArgs` as arguments. * @param {Function} details.handler A handler function which is passed `params` and `...extraArgs` as arguments.
* @param {boolean|string} details.async Whether or not the handler is async or not. Values include `false`, `true`, or `'dynamic'`. * @param {boolean|string} details.async 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}`. * When the value is `'dynamic'`, the handler should return an object of the format `{async: boolean, result: any}`.
* @param {object} params Information which was passed with the original message. * @param {object} params Information which was passed with the original message.
* @param {function} callback A callback function which is invoked after the handler has completed. The value passed * @param {Function} callback A callback function which is invoked after the handler has completed. The value passed
* to the function is in the format: * to the function is in the format:
* * `{result: any}` if the handler invoked successfully. * - `{result: any}` if the handler invoked successfully.
* * `{error: object}` if the handler thew an error. The error is serialized. * - `{error: object}` if the handler thew an error. The error is serialized.
* @param {...*} extraArgs Additional arguments which are passed to the `handler` function. * @param {...*} extraArgs Additional arguments which are passed to the `handler` function.
* @returns {boolean} `true` if the function is invoked asynchronously, `false` otherwise. * @returns {boolean} `true` if the function is invoked asynchronously, `false` otherwise.
*/ */
@ -413,7 +413,7 @@ class EventDispatcher {
/** /**
* Adds a single event listener to a specific event. * Adds a single event listener to a specific event.
* @param {string} eventName The string representing the event's name. * @param {string} eventName The string representing the event's name.
* @param {function} callback The event listener callback to add. * @param {Function} callback The event listener callback to add.
*/ */
on(eventName, callback) { on(eventName, callback) {
let callbacks = this._eventMap.get(eventName); let callbacks = this._eventMap.get(eventName);
@ -427,7 +427,7 @@ class EventDispatcher {
/** /**
* Removes a single event listener from a specific event. * Removes a single event listener from a specific event.
* @param {string} eventName The string representing the event's name. * @param {string} eventName The string representing the event's name.
* @param {function} callback The event listener callback to add. * @param {Function} callback The event listener callback to add.
* @returns {boolean} `true` if the callback was removed, `false` otherwise. * @returns {boolean} `true` if the callback was removed, `false` otherwise.
*/ */
off(eventName, callback) { off(eventName, callback) {
@ -482,6 +482,7 @@ class EventListenerCollection {
* @param {string} type The type of event listener, which can be 'addEventListener', 'addListener', or 'on'. * @param {string} type The type of event listener, which can be 'addEventListener', 'addListener', or 'on'.
* @param {object} object The object to add the event listener to. * @param {object} object The object to add the event listener to.
* @param {...*} args The argument array passed to the object's event listener adding function. * @param {...*} args The argument array passed to the object's event listener adding function.
* @returns {void}
* @throws An error if type is not an expected value. * @throws An error if type is not an expected value.
*/ */
addGeneric(type, object, ...args) { addGeneric(type, object, ...args) {
@ -539,8 +540,6 @@ class EventListenerCollection {
case 'off': case 'off':
object.off(...args); object.off(...args);
break; break;
default:
throw new Error(`Unknown remove function: ${removeFunctionName}`);
} }
} }
this._eventListeners = []; this._eventListeners = [];

View File

@ -22,8 +22,8 @@ class AnkiUtil {
/** /**
* Gets the root deck name of a full deck name. If the deck is a root deck, * Gets the root deck name of a full deck name. If the deck is a root deck,
* the same name is returned. Nested decks are separated using '::'. * the same name is returned. Nested decks are separated using '::'.
* @param deckName A string of the deck name. * @param {string} deckName A string of the deck name.
* @returns A string corresponding to the name of the root deck. * @returns {string} A string corresponding to the name of the root deck.
*/ */
static getRootDeckName(deckName) { static getRootDeckName(deckName) {
const index = deckName.indexOf('::'); const index = deckName.indexOf('::');
@ -32,8 +32,8 @@ class AnkiUtil {
/** /**
* Checks whether or not any marker is contained in a string. * Checks whether or not any marker is contained in a string.
* @param string A string to check. * @param {string} string A string to check.
* @return `true` if the text contains an Anki field marker, `false` otherwise. * @returns {boolean} `true` if the text contains an Anki field marker, `false` otherwise.
*/ */
static stringContainsAnyFieldMarker(string) { static stringContainsAnyFieldMarker(string) {
const result = this._markerPattern.test(string); const result = this._markerPattern.test(string);
@ -43,8 +43,8 @@ class AnkiUtil {
/** /**
* Gets a list of all markers that are contained in a string. * Gets a list of all markers that are contained in a string.
* @param string A string to check. * @param {string} string A string to check.
* @return An array of marker strings. * @returns {string[]} An array of marker strings.
*/ */
static getFieldMarkers(string) { static getFieldMarkers(string) {
const pattern = this._markerPattern; const pattern = this._markerPattern;
@ -57,26 +57,10 @@ class AnkiUtil {
return markers; return markers;
} }
/**
* Checks whether an object of key-value pairs has a value which contains a specific marker.
* @param fieldsObject An object with key-value pairs, where the value corresponds to the field value.
* @param marker The marker string to check for, excluding brackets.
* @returns `true` if any of the fields contains the marker, `false` otherwise.
*/
static fieldsObjectContainsMarker(fieldsObject, marker) {
marker = `{${marker}}`;
for (const [, fieldValue] of fieldsObject) {
if (fieldValue.includes(marker)) {
return true;
}
}
return false;
}
/** /**
* Returns a regular expression which can be used to find markers in a string. * Returns a regular expression which can be used to find markers in a string.
* @param global Whether or not the regular expression should have the global flag. * @param {boolean} global Whether or not the regular expression should have the global flag.
* @returns A new `RegExp` instance. * @returns {RegExp} A new `RegExp` instance.
*/ */
static cloneFieldMarkerPattern(global) { static cloneFieldMarkerPattern(global) {
return new RegExp(this._markerPattern.source, global ? 'g' : ''); return new RegExp(this._markerPattern.source, global ? 'g' : '');
@ -84,8 +68,8 @@ class AnkiUtil {
/** /**
* Checks whether or not a note object is valid. * Checks whether or not a note object is valid.
* @param note A note object to check. * @param {*} note A note object to check.
* @return `true` if the note is valid, `false` otherwise. * @returns {boolean} `true` if the note is valid, `false` otherwise.
*/ */
static isNoteDataValid(note) { static isNoteDataValid(note) {
if (!isObject(note)) { return false; } if (!isObject(note)) { return false; }

View File

@ -26,7 +26,7 @@
class AnkiNoteDataCreator { class AnkiNoteDataCreator {
/** /**
* Creates a new instance. * Creates a new instance.
* @param japaneseUtil An instance of `JapaneseUtil`. * @param {JapaneseUtil} japaneseUtil An instance of `JapaneseUtil`.
*/ */
constructor(japaneseUtil) { constructor(japaneseUtil) {
this._japaneseUtil = japaneseUtil; this._japaneseUtil = japaneseUtil;
@ -34,8 +34,16 @@ class AnkiNoteDataCreator {
/** /**
* Creates a compatibility representation of the specified data. * Creates a compatibility representation of the specified data.
* @param marker The marker that is being used for template rendering. * @param {string} marker The marker that is being used for template rendering.
* @returns An object used for rendering Anki templates. * @param {object} details Information which is used to generate the data.
* @param {Translation.DictionaryEntry} details.dictionaryEntry The dictionary entry.
* @param {string} details.resultOutputMode The result output mode.
* @param {string} details.mode The mode being used to generate the Anki data.
* @param {string} details.glossaryLayoutMode The glossary layout mode.
* @param {boolean} details.compactTags Whether or not compact tags mode is enabled.
* @param {{documentTitle: string, query: string, fullQuery: string}} details.context Contextual information about the source of the dictionary entry.
* @param {object} details.media Media data.
* @returns {object} An object used for rendering Anki templates.
*/ */
create(marker, { create(marker, {
dictionaryEntry, dictionaryEntry,
@ -83,8 +91,8 @@ class AnkiNoteDataCreator {
/** /**
* Creates a deferred-evaluation value. * Creates a deferred-evaluation value.
* @param getter The function to invoke to get the return value. * @param {Function} getter The function to invoke to get the return value.
* @returns An object which can be passed into `getCachedValue`. * @returns {{getter: Function, hasValue: false, value: undefined}} An object which can be passed into `getCachedValue`.
*/ */
createCachedValue(getter) { createCachedValue(getter) {
return {getter, hasValue: false, value: void 0}; return {getter, hasValue: false, value: void 0};
@ -92,8 +100,8 @@ class AnkiNoteDataCreator {
/** /**
* Gets the value of a cached object. * Gets the value of a cached object.
* @param item An object that was returned from `createCachedValue`. * @param {{getter: Function, hasValue: boolean, value: *}} item An object that was returned from `createCachedValue`.
* @returns The result of evaluating the getter, which is cached after the first invocation. * @returns {*} The result of evaluating the getter, which is cached after the first invocation.
*/ */
getCachedValue(item) { getCachedValue(item) {
if (item.hasValue) { return item.value; } if (item.hasValue) { return item.value; }

View File

@ -21,8 +21,8 @@
class StringUtil { class StringUtil {
/** /**
* Decodes the contents of an ArrayBuffer using UTF8. * Decodes the contents of an ArrayBuffer using UTF8.
* @param arrayBuffer The input ArrayBuffer. * @param {ArrayBuffer} arrayBuffer The input ArrayBuffer.
* @returns A UTF8-decoded string. * @returns {string} A UTF8-decoded string.
*/ */
static arrayBufferUtf8Decode(arrayBuffer) { static arrayBufferUtf8Decode(arrayBuffer) {
try { try {
@ -34,8 +34,8 @@ class StringUtil {
/** /**
* Converts the contents of an ArrayBuffer to a base64 string. * Converts the contents of an ArrayBuffer to a base64 string.
* @param arrayBuffer The input ArrayBuffer. * @param {ArrayBuffer} arrayBuffer The input ArrayBuffer.
* @returns A base64 string representing the binary content. * @returns {string} A base64 string representing the binary content.
*/ */
static arrayBufferToBase64(arrayBuffer) { static arrayBufferToBase64(arrayBuffer) {
return btoa(this.arrayBufferToBinaryString(arrayBuffer)); return btoa(this.arrayBufferToBinaryString(arrayBuffer));
@ -43,8 +43,8 @@ class StringUtil {
/** /**
* Converts the contents of an ArrayBuffer to a binary string. * Converts the contents of an ArrayBuffer to a binary string.
* @param arrayBuffer The input ArrayBuffer. * @param {ArrayBuffer} arrayBuffer The input ArrayBuffer.
* @returns A string representing the binary content. * @returns {string} A string representing the binary content.
*/ */
static arrayBufferToBinaryString(arrayBuffer) { static arrayBufferToBinaryString(arrayBuffer) {
const bytes = new Uint8Array(arrayBuffer); const bytes = new Uint8Array(arrayBuffer);
@ -61,8 +61,8 @@ class StringUtil {
/** /**
* Converts a base64 string to an ArrayBuffer. * Converts a base64 string to an ArrayBuffer.
* @param content The binary content string encoded in base64. * @param {string} content The binary content string encoded in base64.
* @returns A new `ArrayBuffer` object corresponding to the specified content. * @returns {ArrayBuffer} A new `ArrayBuffer` object corresponding to the specified content.
*/ */
static base64ToArrayBuffer(content) { static base64ToArrayBuffer(content) {
const binaryContent = atob(content); const binaryContent = atob(content);

View File

@ -39,6 +39,49 @@ class Display extends EventDispatcher {
/** /**
* Information about how popup content should be shown, specifically related to the inner popup content. * Information about how popup content should be shown, specifically related to the inner popup content.
* @typedef {object} ContentDetails * @typedef {object} ContentDetails
* @property {boolean} focus Whether or not the frame should be `focus()`'d.
* @property {HistoryParams} params An object containing key-value pairs representing the URL search params.
* @property {?HistoryState} state The semi-persistent state assigned to the navigation entry.
* @property {?HistoryContent} content The non-persistent content assigned to the navigation entry.
* @property {'clear'|'overwrite'|'new'} historyMode How the navigation history should be modified.
*/
/**
* An object containing key-value pairs representing the URL search params.
* @typedef {object} HistoryParams
* @property {'terms'|'kanji'|'unloaded'|'clear'} [type] The type of content that is being shown.
* @property {string} [query] The search query.
* @property {'on'|'off'} [wildcards] Whether or not wildcards can be used for the search query.
* @property {string} [offset] The start position of the `query` string as an index into the `full` query string.
* @property {string} [full] The full search text. If absent, `query` is the full search text.
* @property {'true'|'false'} [full-visible] Whether or not the full search query should be forced to be visible.
* @property {'true'|'false'} [lookup] Whether or not the query should be looked up. If it is not looked up,
* the content should be provided.
*/
/**
* The semi-persistent state assigned to the navigation entry.
* @typedef {object} HistoryState
* @property {'queryParser'} [cause] What was the cause of the navigation.
* @property {object} [sentence] The sentence context.
* @property {string} sentence.text The full string.
* @property {number} sentence.offset The offset from the start of `text` to the full search query.
* @property {number} [focusEntry] The index of the dictionary entry to focus.
* @property {number} [scrollX] The horizontal scroll position.
* @property {number} [scrollY] The vertical scroll position.
* @property {object} [optionsContext] The options context which should be used for lookups.
* @property {string} [url] The originating URL of the content.
* @property {string} [documentTitle] The originating document title of the content.
*/
/**
* The non-persistent content assigned to the navigation entry.
* @typedef {object} HistoryContent
* @property {boolean} [animate] Whether or not any CSS animations should occur.
* @property {object[]} [dictionaryEntries] An array of dictionary entries to display as content.
* @property {object} [contentOrigin] The identifying information for the frame the content originated from.
* @property {number} [contentOrigin.tabId] The tab id.
* @property {number} [contentOrigin.frameId] The frame id within the tab.
*/ */
constructor(tabId, frameId, pageType, japaneseUtil, documentFocusController, hotkeyHandler) { constructor(tabId, frameId, pageType, japaneseUtil, documentFocusController, hotkeyHandler) {
@ -348,7 +391,7 @@ class Display extends EventDispatcher {
/** /**
* Updates the content of the display. * Updates the content of the display.
* @param {ContentDetails} details * @param {ContentDetails} details Information about the content to show.
*/ */
setContent(details) { setContent(details) {
const {focus, params, state, content} = details; const {focus, params, state, content} = details;

View File

@ -68,27 +68,27 @@ class DocumentUtil {
/** /**
* Extract a sentence from a document. * Extract a sentence from a document.
* @param source The text source object, either `TextSourceRange` or `TextSourceElement`. * @param {TextSourceRange|TextSourceElement} source The text source object, either `TextSourceRange` or `TextSourceElement`.
* @param layoutAwareScan Whether or not layout-aware scan mode should be used. * @param {boolean} layoutAwareScan Whether or not layout-aware scan mode should be used.
* @param extent The length of the sentence to extract. * @param {number} extent The length of the sentence to extract.
* @param terminateAtNewlines Whether or not a sentence should be terminated at newline characters. * @param {boolean} terminateAtNewlines Whether or not a sentence should be terminated at newline characters.
* @param terminatorMap A mapping of characters that terminate a sentence. * @param {Map<string, *[]>} terminatorMap A mapping of characters that terminate a sentence.
* Format: * Format:
* ```js * ```js
* new Map([ [character: string, [includeCharacterAtStart: boolean, includeCharacterAtEnd: boolean]], ... ]) * new Map([ [character: string, [includeCharacterAtStart: boolean, includeCharacterAtEnd: boolean]], ... ])
* ``` * ```
* @param forwardQuoteMap A mapping of quote characters that delimit a sentence. * @param {Map<string, *[]>} forwardQuoteMap A mapping of quote characters that delimit a sentence.
* Format: * Format:
* ```js * ```js
* new Map([ [character: string, [otherCharacter: string, includeCharacterAtStart: boolean]], ... ]) * new Map([ [character: string, [otherCharacter: string, includeCharacterAtStart: boolean]], ... ])
* ``` * ```
* @param backwardQuoteMap A mapping of quote characters that delimit a sentence, * @param {Map<string, *[]>} backwardQuoteMap A mapping of quote characters that delimit a sentence,
* which is the inverse of forwardQuoteMap. * which is the inverse of forwardQuoteMap.
* Format: * Format:
* ```js * ```js
* new Map([ [character: string, [otherCharacter: string, includeCharacterAtEnd: boolean]], ... ]) * new Map([ [character: string, [otherCharacter: string, includeCharacterAtEnd: boolean]], ... ])
* ``` * ```
* @returns The sentence and the offset to the original source: `{sentence: string, offset: integer}`. * @returns {{sentence: string, offset: number}} The sentence and the offset to the original source.
*/ */
extractSentence(source, layoutAwareScan, extent, terminateAtNewlines, terminatorMap, forwardQuoteMap, backwardQuoteMap) { extractSentence(source, layoutAwareScan, extent, terminateAtNewlines, terminatorMap, forwardQuoteMap, backwardQuoteMap) {
// Scan text // Scan text

View File

@ -21,9 +21,12 @@
class DOMTextScanner { class DOMTextScanner {
/** /**
* Creates a new instance of a DOMTextScanner. * Creates a new instance of a DOMTextScanner.
* @param node The DOM Node to start at. * @param {Node} node The DOM Node to start at.
* @param offset The character offset in to start at when node is a text node. * @param {number} offset The character offset in to start at when node is a text node.
* Use 0 for non-text nodes. * Use 0 for non-text nodes.
* @param {boolean} forcePreserveWhitespace Whether or not whitespace should be forced to be preserved,
* regardless of CSS styling.
* @param {boolean} generateLayoutContent Whether or not newlines should be added based on CSS styling.
*/ */
constructor(node, offset, forcePreserveWhitespace=false, generateLayoutContent=true) { constructor(node, offset, forcePreserveWhitespace=false, generateLayoutContent=true) {
const ruby = DOMTextScanner.getParentRubyElement(node); const ruby = DOMTextScanner.getParentRubyElement(node);
@ -393,6 +396,7 @@ class DOMTextScanner {
/** /**
* Gets seek information about an element. * Gets seek information about an element.
* @param {Element} element The element to check.
* @returns {{enterable: boolean, newlines: number}} The seek information. * @returns {{enterable: boolean, newlines: number}} The seek information.
* The `enterable` value indicates whether the content of this node should be entered. * The `enterable` value indicates whether the content of this node should be entered.
* The `newlines` value corresponds to the number of newline characters that should be added. * The `newlines` value corresponds to the number of newline characters that should be added.
@ -443,6 +447,8 @@ class DOMTextScanner {
/** /**
* Gets attributes for the specified character. * Gets attributes for the specified character.
* @param {string} character A string containing a single character. * @param {string} character A string containing a single character.
* @param {boolean} preserveNewlines Whether or not newlines should be preserved.
* @param {boolean} preserveWhitespace Whether or not whitespace should be preserved.
* @returns {number} An integer representing the attributes of the character. * @returns {number} An integer representing the attributes of the character.
* 0: Character should be ignored. * 0: Character should be ignored.
* 1: Character is collapsible whitespace. * 1: Character is collapsible whitespace.

View File

@ -36,8 +36,9 @@ class CssStyleApplier {
/** /**
* Creates a new instance of the class. * Creates a new instance of the class.
* @param styleDataUrl The local URL to the JSON file continaing the style rules. * @param {string} styleDataUrl The local URL to the JSON file continaing the style rules.
* The style rules should be of the format: * The style rules should be of the format:
* ```
* [ * [
* { * {
* selectors: [(selector:string)...], * selectors: [(selector:string)...],
@ -46,6 +47,7 @@ class CssStyleApplier {
* ] * ]
* }... * }...
* ] * ]
* ```
*/ */
constructor(styleDataUrl) { constructor(styleDataUrl) {
this._styleDataUrl = styleDataUrl; this._styleDataUrl = styleDataUrl;
@ -84,7 +86,7 @@ class CssStyleApplier {
/** /**
* Applies CSS styles directly to the "style" attribute using the "class" attribute. * Applies CSS styles directly to the "style" attribute using the "class" attribute.
* This only works for elements with a single class. * This only works for elements with a single class.
* @param elements An iterable collection of HTMLElement objects. * @param {Iterable<HTMLElement>} elements An iterable collection of HTMLElement objects.
*/ */
applyClassStyles(elements) { applyClassStyles(elements) {
const elementStyles = []; const elementStyles = [];

View File

@ -19,19 +19,41 @@
* Class which is used to observe elements matching a selector in specific element. * Class which is used to observe elements matching a selector in specific element.
*/ */
class SelectorObserver { class SelectorObserver {
/**
* @function OnAddedCallback
* @param {Element} element The element which was added.
* @returns {*} Custom data which is assigned to element and passed to callbacks.
*/
/**
* @function OnRemovedCallback
* @param {Element} element The element which was removed.
* @param {*} data The custom data corresponding to the element.
*/
/**
* @function OnChildrenUpdatedCallback
* @param {Element} element The element which had its children updated.
* @param {*} data The custom data corresponding to the element.
*/
/**
* @function IsStaleCallback
* @param {Element} element The element which had its children updated.
* @param {*} data The custom data corresponding to the element.
* @returns {boolean} Whether or not the data is stale for the element.
*/
/** /**
* Creates a new instance. * Creates a new instance.
* @param selector A string CSS selector used to find elements. * @param {object} details The configuration for the object.
* @param ignoreSelector A string CSS selector used to filter elements, or null for no filtering. * @param {string} details.selector A string CSS selector used to find elements.
* @param onAdded A function which is invoked for each element that is added that matches the selector. * @param {?string} details.ignoreSelector A string CSS selector used to filter elements, or `null` for no filtering.
* The signature is (element) => data. * @param {OnAddedCallback} details.onAdded A function which is invoked for each element that is added that matches the selector.
* @param onRemoved A function which is invoked for each element that is removed, or null. * @param {?OnRemovedCallback} details.onRemoved A function which is invoked for each element that is removed, or `null`.
* The signature is (element, data) => void. * @param {?OnChildrenUpdatedCallback} details.onChildrenUpdated A function which is invoked for each element which has its children updated, or `null`.
* @param onChildrenUpdated A function which is invoked for each element which has its children updated, or null. * @param {?IsStaleCallback} details.isStale A function which checks if the data is stale for a given element, or `null`.
* The signature is (element, data) => void.
* @param isStale 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. * If the element is stale, it will be removed and potentially re-added.
* The signature is (element, data) => bool.
*/ */
constructor({selector, ignoreSelector=null, onAdded=null, onRemoved=null, onChildrenUpdated=null, isStale=null}) { constructor({selector, ignoreSelector=null, onAdded=null, onRemoved=null, onChildrenUpdated=null, isStale=null}) {
this._selector = selector; this._selector = selector;
@ -49,7 +71,7 @@ class SelectorObserver {
/** /**
* Returns whether or not an element is currently being observed. * Returns whether or not an element is currently being observed.
* @returns True if an element is being observed, false otherwise. * @returns {boolean} `true` if an element is being observed, `false` otherwise.
*/ */
get isObserving() { get isObserving() {
return this._observingElement !== null; return this._observingElement !== null;
@ -57,10 +79,10 @@ class SelectorObserver {
/** /**
* Starts DOM mutation observing the target element. * Starts DOM mutation observing the target element.
* @param element The element to observe changes in. * @param {Element} element The element to observe changes in.
* @param attributes A boolean for whether or not attribute changes should be observed. * @param {boolean} [attributes] A boolean for whether or not attribute changes should be observed.
* @throws An error if element is null. * @throws {Error} An error if element is null.
* @throws An error if an element is already being observed. * @throws {Error} An error if an element is already being observed.
*/ */
observe(element, attributes=false) { observe(element, attributes=false) {
if (element === null) { if (element === null) {

View File

@ -21,7 +21,7 @@
class CacheMap { class CacheMap {
/** /**
* Creates a new CacheMap. * Creates a new CacheMap.
* @param maxSize The maximum number of entries able to be stored in the cache. * @param {number} maxSize The maximum number of entries able to be stored in the cache.
*/ */
constructor(maxSize) { constructor(maxSize) {
if (!( if (!(
@ -42,6 +42,7 @@ class CacheMap {
/** /**
* Returns the number of items in the cache. * Returns the number of items in the cache.
* @type {number}
*/ */
get size() { get size() {
return this._map.size; return this._map.size;
@ -49,6 +50,7 @@ class CacheMap {
/** /**
* Returns the maximum number of items that can be added to the cache. * Returns the maximum number of items that can be added to the cache.
* @type {number}
*/ */
get maxSize() { get maxSize() {
return this._maxSize; return this._maxSize;
@ -56,8 +58,8 @@ class CacheMap {
/** /**
* Returns whether or not an element exists at the given key. * Returns whether or not an element exists at the given key.
* @param key The key of the element. * @param {*} key The key of the element.
* @returns `true` if an element with the specified key exists, `false` otherwise. * @returns {boolean} `true` if an element with the specified key exists, `false` otherwise.
*/ */
has(key) { has(key) {
return this._map.has(key); return this._map.has(key);
@ -65,8 +67,8 @@ class CacheMap {
/** /**
* Gets an element at the given key, if it exists. Otherwise, returns undefined. * Gets an element at the given key, if it exists. Otherwise, returns undefined.
* @param key The key of the element. * @param {*} key The key of the element.
* @returns The existing value at the key, if any; `undefined` otherwise. * @returns {*} The existing value at the key, if any; `undefined` otherwise.
*/ */
get(key) { get(key) {
const node = this._map.get(key); const node = this._map.get(key);
@ -77,8 +79,8 @@ class CacheMap {
/** /**
* Sets a value at a given key. * Sets a value at a given key.
* @param key The key of the element. * @param {*} key The key of the element.
* @param value The value to store in the cache. * @param {*} value The value to store in the cache.
*/ */
set(key, value) { set(key, value) {
let node = this._map.get(key); let node = this._map.get(key);

View File

@ -21,8 +21,7 @@
class ObjectPropertyAccessor { class ObjectPropertyAccessor {
/** /**
* Create a new accessor for a specific object. * Create a new accessor for a specific object.
* @param target The object which the getter and mutation methods are applied to. * @param {object} target The object which the getter and mutation methods are applied to.
* @returns A new ObjectPropertyAccessor instance.
*/ */
constructor(target) { constructor(target) {
this._target = target; this._target = target;
@ -30,11 +29,11 @@ class ObjectPropertyAccessor {
/** /**
* Gets the value at the specified path. * Gets the value at the specified path.
* @param pathArray The path to the property on the target object. * @param {(string|number)[]} pathArray The path to the property on the target object.
* @param pathLength How many parts of the pathArray to use. * @param {number} [pathLength] How many parts of the pathArray to use.
* This parameter is optional and defaults to the length of pathArray. * This parameter is optional and defaults to the length of pathArray.
* @returns The value found at the path. * @returns {*} The value found at the path.
* @throws An error is thrown if pathArray is not valid for the target object. * @throws {Error} An error is thrown if pathArray is not valid for the target object.
*/ */
get(pathArray, pathLength) { get(pathArray, pathLength) {
let target = this._target; let target = this._target;
@ -51,9 +50,9 @@ class ObjectPropertyAccessor {
/** /**
* Sets the value at the specified path. * Sets the value at the specified path.
* @param pathArray The path to the property on the target object. * @param {(string|number)[]} pathArray The path to the property on the target object.
* @param value The value to assign to the property. * @param {*} value The value to assign to the property.
* @throws An error is thrown if pathArray is not valid for the target object. * @throws {Error} An error is thrown if pathArray is not valid for the target object.
*/ */
set(pathArray, value) { set(pathArray, value) {
const ii = pathArray.length - 1; const ii = pathArray.length - 1;
@ -70,8 +69,8 @@ class ObjectPropertyAccessor {
/** /**
* Deletes the property of the target object at the specified path. * Deletes the property of the target object at the specified path.
* @param pathArray The path to the property on the target object. * @param {(string|number)[]}pathArray The path to the property on the target object.
* @throws An error is thrown if pathArray is not valid for the target object. * @throws {Error} An error is thrown if pathArray is not valid for the target object.
*/ */
delete(pathArray) { delete(pathArray) {
const ii = pathArray.length - 1; const ii = pathArray.length - 1;
@ -92,8 +91,8 @@ class ObjectPropertyAccessor {
/** /**
* Swaps two properties of an object or array. * Swaps two properties of an object or array.
* @param pathArray1 The path to the first property on the target object. * @param {(string|number)[]} pathArray1 The path to the first property on the target object.
* @param pathArray2 The path to the second property on the target object. * @param {(string|number)[]} pathArray2 The path to the second property on the target object.
* @throws An error is thrown if pathArray1 or pathArray2 is not valid for the target object, * @throws An error is thrown if pathArray1 or pathArray2 is not valid for the target object,
* or if the swap cannot be performed. * or if the swap cannot be performed.
*/ */
@ -129,8 +128,9 @@ class ObjectPropertyAccessor {
/** /**
* Converts a path string to a path array. * Converts a path string to a path array.
* @param pathArray The path array to convert. * @param {(string|number)[]} pathArray The path array to convert.
* @returns A string representation of pathArray. * @returns {string} A string representation of `pathArray`.
* @throws {Error} An error is thrown if any item of `pathArray` is not a string or an integer.
*/ */
static getPathString(pathArray) { static getPathString(pathArray) {
const regexShort = /^[a-zA-Z_][a-zA-Z0-9_]*$/; const regexShort = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
@ -166,8 +166,9 @@ class ObjectPropertyAccessor {
/** /**
* Converts a path array to a path string. For the most part, the format of this string * Converts a path array to a path string. For the most part, the format of this string
* matches Javascript's notation for property access. * matches Javascript's notation for property access.
* @param pathString The path string to convert. * @param {string} pathString The path string to convert.
* @returns An array representation of pathString. * @returns {(string | number)[]} An array representation of `pathString`.
* @throws {Error} An error is thrown if `pathString` is malformed.
*/ */
static getPathArray(pathString) { static getPathArray(pathString) {
const pathArray = []; const pathArray = [];
@ -286,11 +287,11 @@ class ObjectPropertyAccessor {
/** /**
* Checks whether an object or array has the specified property. * Checks whether an object or array has the specified property.
* @param object The object to test. * @param {*} object The object to test.
* @param property The property to check for existence. * @param {string|number} property The property to check for existence.
* This value should be a string if the object is a non-array object. * This value should be a string if the object is a non-array object.
* For arrays, it should be an integer. * For arrays, it should be an integer.
* @returns true if the property exists, otherwise false. * @returns {boolean} `true` if the property exists, otherwise `false`.
*/ */
static hasProperty(object, property) { static hasProperty(object, property) {
switch (typeof property) { switch (typeof property) {
@ -315,9 +316,9 @@ class ObjectPropertyAccessor {
/** /**
* Checks whether a property is valid for the given object * Checks whether a property is valid for the given object
* @param object The object to test. * @param {object} object The object to test.
* @param property The property to check for existence. * @param {string|number} property The property to check for existence.
* @returns true if the property is correct for the given object type, otherwise false. * @returns {boolean} `true` if the property is correct for the given object type, otherwise `false`.
* For arrays, this means that the property should be a positive integer. * For arrays, this means that the property should be a positive integer.
* For non-array objects, the property should be a string. * For non-array objects, the property should be a string.
*/ */

View File

@ -22,12 +22,12 @@ class RegexUtil {
/** /**
* Applies string.replace using a regular expression and replacement string as arguments. * Applies string.replace using a regular expression and replacement string as arguments.
* A source map of the changes is also maintained. * A source map of the changes is also maintained.
* @param text A string of the text to replace. * @param {string} text A string of the text to replace.
* @param sourceMap An instance of `TextSourceMap` which corresponds to `text`. * @param {TextSourceMap} sourceMap An instance of `TextSourceMap` which corresponds to `text`.
* @param pattern A regular expression to use as the replacement. * @param {RegExp} pattern A regular expression to use as the replacement.
* @param replacement A replacement string that follows the format of the standard * @param {string} replacement A replacement string that follows the format of the standard
* JavaScript regular expression replacement string. * JavaScript regular expression replacement string.
* @return A new string with the pattern replacements applied and the source map updated. * @returns {string} A new string with the pattern replacements applied and the source map updated.
*/ */
static applyTextReplacement(text, sourceMap, pattern, replacement) { static applyTextReplacement(text, sourceMap, pattern, replacement) {
const isGlobal = pattern.global; const isGlobal = pattern.global;
@ -57,10 +57,10 @@ class RegexUtil {
/** /**
* Applies the replacement string for a given regular expression match. * Applies the replacement string for a given regular expression match.
* @param replacement The replacement string that follows the format of the standard * @param {string} replacement The replacement string that follows the format of the standard
* JavaScript regular expression replacement string. * JavaScript regular expression replacement string.
* @param match A match object returned from RegExp.match. * @param {object} match A match object returned from RegExp.match.
* @return A new string with the pattern replacement applied. * @returns {string} A new string with the pattern replacement applied.
*/ */
static applyMatchReplacement(replacement, match) { static applyMatchReplacement(replacement, match) {
const pattern = this._matchReplacementPattern; const pattern = this._matchReplacementPattern;

View File

@ -23,6 +23,16 @@
* Class which handles hotkey events and actions. * Class which handles hotkey events and actions.
*/ */
class HotkeyHandler extends EventDispatcher { class HotkeyHandler extends EventDispatcher {
/**
* Information describing a hotkey.
* @typedef {object} HotkeyDefinition
* @property {string} action A string indicating which action to perform.
* @property {string} key A keyboard key code indicating which key needs to be pressed.
* @property {string[]} modifiers An array of keyboard modifiers which also need to be pressed. Supports: `'alt', 'ctrl', 'shift', 'meta'`.
* @property {string[]} scopes An array of scopes for which the hotkey is valid. If this array does not contain `this.scope`, the hotkey will not be registered.
* @property {boolean} enabled A boolean indicating whether the hotkey is currently enabled.
*/
/** /**
* Creates a new instance of the class. * Creates a new instance of the class.
*/ */
@ -49,7 +59,7 @@ class HotkeyHandler extends EventDispatcher {
/** /**
* Registers a set of actions that this hotkey handler supports. * Registers a set of actions that this hotkey handler supports.
* @param actions An array of `[name, handler]` entries, where `name` is a string and `handler` is a function. * @param {*[][]} actions An array of `[name, handler]` entries, where `name` is a string and `handler` is a function.
*/ */
registerActions(actions) { registerActions(actions) {
for (const [name, handler] of actions) { for (const [name, handler] of actions) {
@ -59,13 +69,8 @@ class HotkeyHandler extends EventDispatcher {
/** /**
* Registers a set of hotkeys for a given scope. * Registers a set of hotkeys for a given scope.
* @param scope The scope that the hotkey definitions must be for in order to be activated. * @param {string} scope The scope that the hotkey definitions must be for in order to be activated.
* @param hotkeys An array of hotkey definitions of the format `{action, key, modifiers, scopes, enabled}`. * @param {HotkeyDefinition[]} hotkeys An array of hotkey definitions.
* * `action` - a string indicating which action to perform.
* * `key` - a keyboard key code indicating which key needs to be pressed.
* * `modifiers` - an array of keyboard modifiers which also need to be pressed. Supports: `'alt', 'ctrl', 'shift', 'meta'`.
* * `scopes` - an array of scopes for which the hotkey is valid. If this array does not contain `this.scope`, the hotkey will not be registered.
* * `enabled` - a boolean indicating whether the hotkey is currently enabled.
*/ */
registerHotkeys(scope, hotkeys) { registerHotkeys(scope, hotkeys) {
let registrations = this._hotkeyRegistrations.get(scope); let registrations = this._hotkeyRegistrations.get(scope);
@ -79,6 +84,7 @@ class HotkeyHandler extends EventDispatcher {
/** /**
* Removes all registered hotkeys for a given scope. * Removes all registered hotkeys for a given scope.
* @param {string} scope The scope that the hotkey definitions were registered in.
*/ */
clearHotkeys(scope) { clearHotkeys(scope) {
const registrations = this._hotkeyRegistrations.get(scope); const registrations = this._hotkeyRegistrations.get(scope);
@ -91,7 +97,8 @@ class HotkeyHandler extends EventDispatcher {
/** /**
* Assigns a set of hotkeys for a given scope. This is an optimized shorthand for calling * Assigns a set of hotkeys for a given scope. This is an optimized shorthand for calling
* `clearHotkeys`, then calling `registerHotkeys`. * `clearHotkeys`, then calling `registerHotkeys`.
* @see registerHotkeys for argument information. * @param {string} scope The scope that the hotkey definitions must be for in order to be activated.
* @param {HotkeyDefinition[]} hotkeys An array of hotkey definitions.
*/ */
setHotkeys(scope, hotkeys) { setHotkeys(scope, hotkeys) {
let registrations = this._hotkeyRegistrations.get(scope); let registrations = this._hotkeyRegistrations.get(scope);
@ -107,8 +114,9 @@ class HotkeyHandler extends EventDispatcher {
/** /**
* Adds a single event listener to a specific event. * Adds a single event listener to a specific event.
* @param eventName The string representing the event's name. * @param {string} eventName The string representing the event's name.
* @param callback The event listener callback to add. * @param {Function} callback The event listener callback to add.
* @returns {void}
*/ */
on(eventName, callback) { on(eventName, callback) {
const result = super.on(eventName, callback); const result = super.on(eventName, callback);
@ -119,9 +127,9 @@ class HotkeyHandler extends EventDispatcher {
/** /**
* Removes a single event listener from a specific event. * Removes a single event listener from a specific event.
* @param eventName The string representing the event's name. * @param {string} eventName The string representing the event's name.
* @param callback The event listener callback to add. * @param {Function} callback The event listener callback to add.
* @returns `true` if the callback was removed, `false` otherwise. * @returns {boolean} `true` if the callback was removed, `false` otherwise.
*/ */
off(eventName, callback) { off(eventName, callback) {
const result = super.off(eventName, callback); const result = super.off(eventName, callback);
@ -132,9 +140,9 @@ class HotkeyHandler extends EventDispatcher {
/** /**
* Attempts to simulate an action for a given combination of key and modifiers. * Attempts to simulate an action for a given combination of key and modifiers.
* @param key A keyboard key code indicating which key needs to be pressed. * @param {string} key A keyboard key code indicating which key needs to be pressed.
* @param modifiers An array of keyboard modifiers which also need to be pressed. Supports: `'alt', 'ctrl', 'shift', 'meta'`. * @param {string[]} modifiers An array of keyboard modifiers which also need to be pressed. Supports: `'alt', 'ctrl', 'shift', 'meta'`.
* @returns `true` if an action was performed, `false` otherwise. * @returns {boolean} `true` if an action was performed, `false` otherwise.
*/ */
simulate(key, modifiers) { simulate(key, modifiers) {
const hotkeyInfo = this._hotkeys.get(key); const hotkeyInfo = this._hotkeys.get(key);

View File

@ -21,6 +21,7 @@
class HotkeyUtil { class HotkeyUtil {
/** /**
* Creates a new instance. * Creates a new instance.
* @param {?string} os The operating system for this instance.
*/ */
constructor(os=null) { constructor(os=null) {
this._os = os; this._os = os;
@ -41,6 +42,7 @@ class HotkeyUtil {
/** /**
* Gets the operating system for this instance. * Gets the operating system for this instance.
* The operating system is used to display system-localized modifier key names. * The operating system is used to display system-localized modifier key names.
* @type {?string}
*/ */
get os() { get os() {
return this._os; return this._os;
@ -48,7 +50,7 @@ class HotkeyUtil {
/** /**
* Sets the operating system for this instance. * Sets the operating system for this instance.
* @param value The value to assign. * @param {?string} value The value to assign.
* Valid values are: win, mac, linux, openbsd, cros, android. * Valid values are: win, mac, linux, openbsd, cros, android.
*/ */
set os(value) { set os(value) {
@ -59,10 +61,10 @@ class HotkeyUtil {
/** /**
* Gets a display string for a key and a set of modifiers. * Gets a display string for a key and a set of modifiers.
* @param key The key code string, or `null` for no key. * @param {?string} key The key code string, or `null` for no key.
* @param modifiers An array of modifiers. * @param {string[]} modifiers An array of modifiers.
* Valid values are: ctrl, alt, shift, meta, or mouseN, where N is an integer. * Valid values are: ctrl, alt, shift, meta, or mouseN, where N is an integer.
* @returns A user-friendly string for the combination of key and modifiers. * @returns {string} A user-friendly string for the combination of key and modifiers.
*/ */
getInputDisplayValue(key, modifiers) { getInputDisplayValue(key, modifiers) {
const separator = this._inputSeparator; const separator = this._inputSeparator;
@ -85,9 +87,9 @@ class HotkeyUtil {
/** /**
* Gets a display string for a single modifier. * Gets a display string for a single modifier.
* @param modifier A string representing a modifier. * @param {string} modifier A string representing a modifier.
* Valid values are: ctrl, alt, shift, meta, or mouseN, where N is an integer. * Valid values are: ctrl, alt, shift, meta, or mouseN, where N is an integer.
* @returns A user-friendly string for the modifier. * @returns {string} A user-friendly string for the modifier.
*/ */
getModifierDisplayValue(modifier) { getModifierDisplayValue(modifier) {
const match = this._mouseInputNamePattern.exec(modifier); const match = this._mouseInputNamePattern.exec(modifier);
@ -101,8 +103,8 @@ class HotkeyUtil {
/** /**
* Gets a display string for a key. * Gets a display string for a key.
* @param key The key code string, or `null` for no key. * @param {?string} key The key code string, or `null` for no key.
* @returns A user-friendly string for the combination of key and modifiers, or `null` if key was already `null`. * @returns {?string} A user-friendly string for the combination of key and modifiers, or `null` if key was already `null`.
*/ */
getKeyDisplayValue(key) { getKeyDisplayValue(key) {
if (typeof key === 'string' && key.length === 4 && key.startsWith('Key')) { if (typeof key === 'string' && key.length === 4 && key.startsWith('Key')) {
@ -113,9 +115,9 @@ class HotkeyUtil {
/** /**
* Gets a display string for a single modifier. * Gets a display string for a single modifier.
* @param modifier A string representing a modifier. * @param {string} modifier A string representing a modifier.
* Valid values are: ctrl, alt, shift, meta, or mouseN, where N is an integer. * Valid values are: ctrl, alt, shift, meta, or mouseN, where N is an integer.
* @returns `'mouse'` if the modifier represents a mouse button, `'key'` otherwise. * @returns {'mouse'|'key'} `'mouse'` if the modifier represents a mouse button, `'key'` otherwise.
*/ */
getModifierType(modifier) { getModifierType(modifier) {
return (this._mouseInputNamePattern.test(modifier) ? 'mouse' : 'key'); return (this._mouseInputNamePattern.test(modifier) ? 'mouse' : 'key');
@ -123,8 +125,8 @@ class HotkeyUtil {
/** /**
* Converts an extension command string into a standard input. * Converts an extension command string into a standard input.
* @param command An extension command string. * @param {string} command An extension command string.
* @returns An object `{key, modifiers}`, where key is a string (or `null`) representing the key, and modifiers is an array of modifier keys. * @returns {{key: ?string, modifiers: string[]}} An object `{key, modifiers}`, where key is a string (or `null`) representing the key, and modifiers is an array of modifier keys.
*/ */
convertCommandToInput(command) { convertCommandToInput(command) {
let key = null; let key = null;
@ -142,10 +144,10 @@ class HotkeyUtil {
/** /**
* Gets a command string for a specified input. * Gets a command string for a specified input.
* @param key The key code string, or `null` for no key. * @param {?string} key The key code string, or `null` for no key.
* @param modifiers An array of modifier keys. * @param {string[]} modifiers An array of modifier keys.
* Valid values are: ctrl, alt, shift, meta. * Valid values are: ctrl, alt, shift, meta.
* @returns An extension command string representing the input. * @returns {string} An extension command string representing the input.
*/ */
convertInputToCommand(key, modifiers) { convertInputToCommand(key, modifiers) {
const separator = '+'; const separator = '+';
@ -168,9 +170,9 @@ class HotkeyUtil {
/** /**
* Sorts an array of modifiers. * Sorts an array of modifiers.
* @param modifiers An array of modifiers. * @param {string[]} modifiers An array of modifiers.
* Valid values are: ctrl, alt, shift, meta. * Valid values are: ctrl, alt, shift, meta.
* @returns A sorted array of modifiers. The array instance is the same as the input array. * @returns {string[]} A sorted array of modifiers. The array instance is the same as the input array.
*/ */
sortModifiers(modifiers) { sortModifiers(modifiers) {
const pattern = this._mouseInputNamePattern; const pattern = this._mouseInputNamePattern;

View File

@ -21,9 +21,12 @@
class DictionaryImporterMediaLoader { class DictionaryImporterMediaLoader {
/** /**
* Attempts to load an image using an ArrayBuffer and a media type to return details about it. * 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 {ArrayBuffer} content The binary content for the image, encoded as an ArrayBuffer.
* @param mediaType The media type for the image content. * @param {string} mediaType The media type for the image content.
* @returns A Promise which resolves with {content, width, height} on success, otherwise an error is thrown. * @param {Transferable[]} [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 {Promise<{content: ArrayBuffer, width: number, height: number}>} Details about the requested image content.
* @throws {Error} An error can be thrown if the image fails to load.
*/ */
getImageDetails(content, mediaType, transfer) { getImageDetails(content, mediaType, transfer) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -29,7 +29,7 @@ class DictionaryWorkerMediaLoader {
/** /**
* Handles a response message posted to the worker thread. * Handles a response message posted to the worker thread.
* @param params Details of the response. * @param {{id: string, error: object|undefined, result: any|undefined}} params Details of the response.
*/ */
handleMessage(params) { handleMessage(params) {
const {id} = params; const {id} = params;
@ -46,9 +46,10 @@ class DictionaryWorkerMediaLoader {
/** /**
* Attempts to load an image using an ArrayBuffer and a media type to return details about it. * 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 {ArrayBuffer} content The binary content for the image, encoded as an ArrayBuffer.
* @param mediaType The media type for the image content. * @param {string} mediaType The media type for the image content.
* @returns A Promise which resolves with {content, width, height} on success, otherwise an error is thrown. * @returns {Promise<{content: ArrayBuffer, width: number, height: number}>} Details about the requested image content.
* @throws {Error} An error can be thrown if the image fails to load.
*/ */
getImageDetails(content, mediaType) { getImageDetails(content, mediaType) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -25,6 +25,16 @@
* Class which finds term and kanji dictionary entries for text. * Class which finds term and kanji dictionary entries for text.
*/ */
class Translator { class Translator {
/**
* Information about how popup content should be shown, specifically related to the outer popup frame.
* @typedef {object} TermFrequency
* @property {string} term The term.
* @property {string} reading The reading of the term.
* @property {string} dictionary The name of the dictionary that the term frequency originates from.
* @property {boolean} hasReading Whether or not a reading was specified.
* @property {number|string} frequency The frequency value for the term.
*/
/** /**
* Creates a new Translator instance. * Creates a new Translator instance.
* @param {object} details The details for the class. * @param {object} details The details for the class.

View File

@ -22,8 +22,8 @@ class MediaUtil {
/** /**
* Gets the file extension of a file path. URL search queries and hash * Gets the file extension of a file path. URL search queries and hash
* fragments are not handled. * fragments are not handled.
* @param path The path to the file. * @param {string} path The path to the file.
* @returns The file extension, including the '.', or an empty string * @returns {string} The file extension, including the '.', or an empty string
* if there is no file extension. * if there is no file extension.
*/ */
static getFileNameExtension(path) { static getFileNameExtension(path) {
@ -33,9 +33,9 @@ class MediaUtil {
/** /**
* Gets an image file's media type using a file path. * Gets an image file's media type using a file path.
* @param path The path to the file. * @param {string} path The path to the file.
* @returns The media type string if it can be determined from the file path, * @returns {?string} The media type string if it can be determined from the file path,
* otherwise null. * otherwise `null`.
*/ */
static getImageMediaTypeFromFileName(path) { static getImageMediaTypeFromFileName(path) {
switch (this.getFileNameExtension(path).toLowerCase()) { switch (this.getFileNameExtension(path).toLowerCase()) {
@ -70,9 +70,9 @@ class MediaUtil {
/** /**
* Gets the file extension for a corresponding media type. * Gets the file extension for a corresponding media type.
* @param mediaType The media type to use. * @param {string} mediaType The media type to use.
* @returns A file extension including the dot for the media type, * @returns {?string} A file extension including the dot for the media type,
* otherwise null. * otherwise `null`.
*/ */
static getFileExtensionFromImageMediaType(mediaType) { static getFileExtensionFromImageMediaType(mediaType) {
switch (mediaType) { switch (mediaType) {
@ -101,9 +101,9 @@ class MediaUtil {
/** /**
* Gets the file extension for a corresponding media type. * Gets the file extension for a corresponding media type.
* @param mediaType The media type to use. * @param {string} mediaType The media type to use.
* @returns A file extension including the dot for the media type, * @returns {string} A file extension including the dot for the media type,
* otherwise null. * otherwise `null`.
*/ */
static getFileExtensionFromAudioMediaType(mediaType) { static getFileExtensionFromAudioMediaType(mediaType) {
switch (mediaType) { switch (mediaType) {

View File

@ -53,6 +53,7 @@ class AnkiTemplateRenderer {
/** /**
* Gets the generic TemplateRenderer instance. * Gets the generic TemplateRenderer instance.
* @type {TemplateRenderer}
*/ */
get templateRenderer() { get templateRenderer() {
return this._templateRenderer; return this._templateRenderer;

View File

@ -150,16 +150,17 @@ class Yomichan extends EventDispatcher {
/** /**
* Checks whether or not a URL is an extension URL. * Checks whether or not a URL is an extension URL.
* @param {string} url The URL to check. * @param {string} url The URL to check.
* @returns true if the URL is an extension URL, false otherwise. * @returns {boolean} `true` if the URL is an extension URL, `false` otherwise.
*/ */
isExtensionUrl(url) { isExtensionUrl(url) {
return this._extensionUrlBase !== null && url.startsWith(this._extensionUrlBase); return this._extensionUrlBase !== null && url.startsWith(this._extensionUrlBase);
} }
/** /**
* Runs chrome.runtime.sendMessage() with additional exception handling events. * Runs `chrome.runtime.sendMessage()` with additional exception handling events.
* @param {...*} args The arguments to be passed to chrome.runtime.sendMessage(). * @param {...*} args The arguments to be passed to `chrome.runtime.sendMessage()`.
* @returns {void} The result of the chrome.runtime.sendMessage() call. * @returns {void} The result of the `chrome.runtime.sendMessage()` call.
* @throws {Error} Errors thrown by `chrome.runtime.sendMessage()` are re-thrown.
*/ */
sendMessage(...args) { sendMessage(...args) {
try { try {
@ -171,9 +172,10 @@ class Yomichan extends EventDispatcher {
} }
/** /**
* Runs chrome.runtime.connect() with additional exception handling events. * Runs `chrome.runtime.connect()` with additional exception handling events.
* @param {...*} args The arguments to be passed to chrome.runtime.connect(). * @param {...*} args The arguments to be passed to `chrome.runtime.connect()`.
* @returns {Port} The resulting port. * @returns {Port} The resulting port.
* @throws {Error} Errors thrown by `chrome.runtime.connect()` are re-thrown.
*/ */
connect(...args) { connect(...args) {
try { try {

118
package-lock.json generated
View File

@ -15,6 +15,7 @@
"css": "^3.0.0", "css": "^3.0.0",
"eslint": "^8.15.0", "eslint": "^8.15.0",
"eslint-plugin-header": "^3.1.1", "eslint-plugin-header": "^3.1.1",
"eslint-plugin-jsdoc": "^39.2.9",
"eslint-plugin-no-unsanitized": "^4.0.1", "eslint-plugin-no-unsanitized": "^4.0.1",
"fake-indexeddb": "^3.1.7", "fake-indexeddb": "^3.1.7",
"html-validate": "^7.1.0", "html-validate": "^7.1.0",
@ -197,6 +198,20 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true "dev": true
}, },
"node_modules/@es-joy/jsdoccomment": {
"version": "0.29.0",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.29.0.tgz",
"integrity": "sha512-4yKy5t+/joLihG+ei6CCU6sc08sjUdEdXCQ2U+9h9VP13EiqHQ4YMgDC18ys/AsLdJDBX3KRx/AWY6PR7hn52Q==",
"dev": true,
"dependencies": {
"comment-parser": "1.3.1",
"esquery": "^1.4.0",
"jsdoc-type-pratt-parser": "~3.0.1"
},
"engines": {
"node": "^14 || ^16 || ^17 || ^18"
}
},
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
@ -1801,6 +1816,15 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true "dev": true
}, },
"node_modules/comment-parser": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz",
"integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==",
"dev": true,
"engines": {
"node": ">= 12.0.0"
}
},
"node_modules/common-tags": { "node_modules/common-tags": {
"version": "1.8.2", "version": "1.8.2",
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
@ -3145,6 +3169,42 @@
"eslint": ">=7.7.0" "eslint": ">=7.7.0"
} }
}, },
"node_modules/eslint-plugin-jsdoc": {
"version": "39.2.9",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-39.2.9.tgz",
"integrity": "sha512-gaPYJT94rWlWyQcisQyyEJHtLaaJqN4baFlLCEr/LcXVibS9wzQTL2dskqk327ggwqQopR+Xecu2Lng1IJ9Ypw==",
"dev": true,
"dependencies": {
"@es-joy/jsdoccomment": "~0.29.0",
"comment-parser": "1.3.1",
"debug": "^4.3.4",
"escape-string-regexp": "^4.0.0",
"esquery": "^1.4.0",
"semver": "^7.3.7",
"spdx-expression-parse": "^3.0.1"
},
"engines": {
"node": "^14 || ^16 || ^17 || ^18"
},
"peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0"
}
},
"node_modules/eslint-plugin-jsdoc/node_modules/semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/eslint-plugin-no-unsanitized": { "node_modules/eslint-plugin-no-unsanitized": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.1.tgz",
@ -5404,6 +5464,15 @@
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"dev": true "dev": true
}, },
"node_modules/jsdoc-type-pratt-parser": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.0.1.tgz",
"integrity": "sha512-vqMCdAFVIiFhVgBYE/X8naf3L/7qiJsaYWTfUJZZZ124dR3OUz9HrmaMUGpYIYAN4VSuodf6gIZY0e8ktPw9cg==",
"dev": true,
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/jsdom": { "node_modules/jsdom": {
"version": "19.0.0", "version": "19.0.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz",
@ -10348,6 +10417,17 @@
"async": "~0.2.9" "async": "~0.2.9"
} }
}, },
"@es-joy/jsdoccomment": {
"version": "0.29.0",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.29.0.tgz",
"integrity": "sha512-4yKy5t+/joLihG+ei6CCU6sc08sjUdEdXCQ2U+9h9VP13EiqHQ4YMgDC18ys/AsLdJDBX3KRx/AWY6PR7hn52Q==",
"dev": true,
"requires": {
"comment-parser": "1.3.1",
"esquery": "^1.4.0",
"jsdoc-type-pratt-parser": "~3.0.1"
}
},
"@eslint/eslintrc": { "@eslint/eslintrc": {
"version": "1.2.3", "version": "1.2.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
@ -11683,6 +11763,12 @@
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true "dev": true
}, },
"comment-parser": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz",
"integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==",
"dev": true
},
"common-tags": { "common-tags": {
"version": "1.8.2", "version": "1.8.2",
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
@ -12810,6 +12896,32 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"eslint-plugin-jsdoc": {
"version": "39.2.9",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-39.2.9.tgz",
"integrity": "sha512-gaPYJT94rWlWyQcisQyyEJHtLaaJqN4baFlLCEr/LcXVibS9wzQTL2dskqk327ggwqQopR+Xecu2Lng1IJ9Ypw==",
"dev": true,
"requires": {
"@es-joy/jsdoccomment": "~0.29.0",
"comment-parser": "1.3.1",
"debug": "^4.3.4",
"escape-string-regexp": "^4.0.0",
"esquery": "^1.4.0",
"semver": "^7.3.7",
"spdx-expression-parse": "^3.0.1"
},
"dependencies": {
"semver": {
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
}
}
},
"eslint-plugin-no-unsanitized": { "eslint-plugin-no-unsanitized": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.1.tgz",
@ -14501,6 +14613,12 @@
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"dev": true "dev": true
}, },
"jsdoc-type-pratt-parser": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-3.0.1.tgz",
"integrity": "sha512-vqMCdAFVIiFhVgBYE/X8naf3L/7qiJsaYWTfUJZZZ124dR3OUz9HrmaMUGpYIYAN4VSuodf6gIZY0e8ktPw9cg==",
"dev": true
},
"jsdom": { "jsdom": {
"version": "19.0.0", "version": "19.0.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz",

View File

@ -41,6 +41,7 @@
"css": "^3.0.0", "css": "^3.0.0",
"eslint": "^8.15.0", "eslint": "^8.15.0",
"eslint-plugin-header": "^3.1.1", "eslint-plugin-header": "^3.1.1",
"eslint-plugin-jsdoc": "^39.2.9",
"eslint-plugin-no-unsanitized": "^4.0.1", "eslint-plugin-no-unsanitized": "^4.0.1",
"fake-indexeddb": "^3.1.7", "fake-indexeddb": "^3.1.7",
"html-validate": "^7.1.0", "html-validate": "^7.1.0",

View File

@ -20,8 +20,8 @@ const {testMain} = require('../dev/util');
/** /**
* This function tests the following bug: * This function tests the following bug:
* * https://github.com/jsdom/jsdom/issues/3211 * - https://github.com/jsdom/jsdom/issues/3211
* * https://github.com/dperini/nwsapi/issues/48 * - https://github.com/dperini/nwsapi/issues/48
*/ */
function testJSDOMSelectorBug() { function testJSDOMSelectorBug() {
// nwsapi is used by JSDOM // nwsapi is used by JSDOM