From 5183e3c06bf602225f8cae80e33637ec2fae833d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?= Date: Sun, 29 Sep 2024 16:28:34 +0200 Subject: [PATCH] Stricter rules for JSDoc documentation blocks (#11881) --- .xo-config.json | 18 ++++++- package.json | 2 +- scripts/add-icon-data.js | 20 ++++---- scripts/build/clean.js | 5 ++ scripts/build/package.js | 30 +++++++----- scripts/lint/ourlint.js | 50 ++++++++++--------- scripts/release/reformat-markdown.js | 2 +- scripts/release/update-cdn-urls.js | 2 + scripts/release/update-sdk-ts-defs.js | 6 +-- sdk.mjs | 69 ++++++++++++++------------- svglint.config.mjs | 64 +++++++++---------------- tests/min-reporter.cjs | 11 +++-- tests/test-icon.js | 7 +-- 13 files changed, 150 insertions(+), 136 deletions(-) diff --git a/.xo-config.json b/.xo-config.json index 3d48af531..047fa0592 100644 --- a/.xo-config.json +++ b/.xo-config.json @@ -2,7 +2,7 @@ "prettier": true, "space": 2, "plugins": ["import"], - "extends": ["plugin:jsdoc/recommended"], + "extends": ["plugin:jsdoc/recommended-error"], "rules": { "sort-imports": [ "error", @@ -29,7 +29,21 @@ } ], "no-console": ["error", {"allow": ["warn", "error"]}], - "jsdoc/require-file-overview": "error" + "no-warning-comments": [ + "warn", + { + "terms": ["fixme", "xxx"] + } + ], + "jsdoc/require-file-overview": "error", + "jsdoc/require-description": "error", + "jsdoc/no-bad-blocks": "error", + "jsdoc/no-blank-blocks": "error", + "jsdoc/no-blank-block-descriptions": "error", + "jsdoc/check-syntax": "error", + "jsdoc/require-asterisk-prefix": "error", + "jsdoc/require-description-complete-sentence": "error", + "jsdoc/require-hyphen-before-param-description": ["error", "never"] }, "overrides": [ { diff --git a/package.json b/package.json index 912b1b24c..5dbb1a2e8 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "editorconfig-checker": "5.1.5", "esbuild": "0.20.2", "eslint-plugin-import": "2.29.1", - "eslint-plugin-jsdoc": "48.2.8", + "eslint-plugin-jsdoc": "50.3.0", "fake-diff": "1.0.0", "fast-fuzzy": "1.12.0", "get-relative-luminance": "1.0.0", diff --git a/scripts/add-icon-data.js b/scripts/add-icon-data.js index 2719bcdd8..91c05890c 100644 --- a/scripts/add-icon-data.js +++ b/scripts/add-icon-data.js @@ -41,8 +41,9 @@ const licenseTypes = ); /** - * @param {string} input URL input - * @returns {Promise} Whether the input is a valid URL + * Whether an input is a valid URL. + * @param {string} input URL input. + * @returns {Promise} Whether the input is a valid URL. */ const isValidURL = async (input) => { const regex = await urlRegex(); @@ -50,15 +51,17 @@ const isValidURL = async (input) => { }; /** - * @param {string} input Hex color - * @returns {boolean|string} Whether the input is a valid hex color + * Whether an input is a valid hex color. + * @param {string} input Hex color. + * @returns {boolean|string} Whether the input is a valid hex color. */ const isValidHexColor = (input) => HEX_REGEX.test(input) || 'Must be a valid hex code.'; /** - * @param {string} input New icon input - * @returns {boolean} Whether the icon is new + * Whether an icon is not already in the dataset. + * @param {string} input New icon input. + * @returns {boolean} Whether the icon is new. */ const isNewIcon = (input) => !iconsData.icons.some( @@ -67,8 +70,9 @@ const isNewIcon = (input) => ); /** - * @param {string} input Color input - * @returns {string} Preview of the color + * Compute a preview of a color to use in prompt background. + * @param {string} input Color input. + * @returns {string} Preview of the color. */ const previewHexColor = (input) => { const color = normalizeColor(input); diff --git a/scripts/build/clean.js b/scripts/build/clean.js index 485c8e1f9..3cee8ecd4 100644 --- a/scripts/build/clean.js +++ b/scripts/build/clean.js @@ -13,6 +13,11 @@ const __dirname = getDirnameFromImportMeta(import.meta.url); const rootDirectory = path.resolve(__dirname, '..', '..'); const files = ['index.js', 'index.mjs', 'index.d.ts', 'sdk.js']; +/** + * Check if a file exists. + * @param {string} fpath File path to check. + * @returns {Promise} True if the file exists, false otherwise. + */ const fileExists = async (fpath) => { try { await fs.access(fpath); diff --git a/scripts/build/package.js b/scripts/build/package.js index 125ff17d4..53fb9beea 100644 --- a/scripts/build/package.js +++ b/scripts/build/package.js @@ -53,18 +53,20 @@ const icons = await getIconsData(); const iconObjectTemplate = await fs.readFile(iconObjectTemplateFile, UTF8); /** - * @param {string} value The value to escape - * @returns {string} The escaped value + * Escape a string for use in a JavaScript string. + * @param {string} value The value to escape. + * @returns {string} The escaped value. */ const escape = (value) => { return value.replaceAll(/(? { +const licenseToString = (license) => { if (license.url === undefined) { license.url = `https://spdx.org/licenses/${license.type}`; } @@ -74,8 +76,8 @@ const licenseToObject = (license) => { /** * Converts an icon object to a JavaScript object. - * @param {IconDataAndObject} icon The icon object - * @returns {string} The JavaScript object + * @param {IconDataAndObject} icon The icon object. + * @returns {string} The JavaScript object. */ const iconToJsObject = (icon) => { return format( @@ -89,14 +91,15 @@ const iconToJsObject = (icon) => { icon.guidelines ? `\n guidelines: '${escape(icon.guidelines)}',` : '', icon.license === undefined ? '' - : `\n license: ${JSON.stringify(licenseToObject(icon.license))},`, + : `\n license: ${JSON.stringify(licenseToString(icon.license))},`, ); }; /** - * @param {string} filepath The path to the file to write - * @param {string} rawJavaScript The raw JavaScript content to write to the file - * @param {EsBuildTransformOptions | null} options The options to pass to esbuild + * Write JavaScript content to a file. + * @param {string} filepath The path to the file to write. + * @param {string} rawJavaScript The raw JavaScript content to write to the file. + * @param {EsBuildTransformOptions | null} options The options to pass to esbuild. */ const writeJs = async (filepath, rawJavaScript, options = null) => { options = options === null ? {minify: true} : options; @@ -105,8 +108,9 @@ const writeJs = async (filepath, rawJavaScript, options = null) => { }; /** - * @param {string} filepath The path to the file to write - * @param {string} rawTypeScript The raw TypeScript content to write to the file + * Write TypeScript content to a file. + * @param {string} filepath The path to the file to write. + * @param {string} rawTypeScript The raw TypeScript content to write to the file. */ const writeTs = async (filepath, rawTypeScript) => { await fs.writeFile(filepath, rawTypeScript); diff --git a/scripts/lint/ourlint.js b/scripts/lint/ourlint.js index 13c52ad20..b75617162 100644 --- a/scripts/lint/ourlint.js +++ b/scripts/lint/ourlint.js @@ -1,8 +1,7 @@ #!/usr/bin/env node /** * @file - * Linters for the package that can't easily be implemented in the existing - * linters (e.g. jsonlint/svglint). + * Linters for the package that can't easily be implemented in the existing ones. */ /** @@ -22,18 +21,18 @@ import {collator, getIconsDataString, normalizeNewlines} from '../../sdk.mjs'; */ const TESTS = { /** - * Tests whether our icons are in alphabetical order - * @param {{icons: IconsData}} data Icons data - * @returns {string|undefined} Error message or undefined + * Tests whether our icons are in alphabetical order. + * @param {{icons: IconsData}} data Icons data. + * @returns {string|undefined} Error message or undefined. */ alphabetical(data) { /** - * Collects invalid alphabet ordered icons - * @param {IconData[]} invalidEntries Invalid icons reference - * @param {IconData} icon Icon to check - * @param {number} index Index of the icon - * @param {IconData[]} array Array of icons - * @returns {IconData[]} Invalid icons + * Collects invalid alphabet ordered icons. + * @param {IconData[]} invalidEntries Invalid icons reference. + * @param {IconData} icon Icon to check. + * @param {number} index Index of the icon. + * @param {IconData[]} array Array of icons. + * @returns {IconData[]} Invalid icons. */ const collector = (invalidEntries, icon, index, array) => { if (index > 0) { @@ -54,9 +53,9 @@ const TESTS = { }; /** - * Format an icon for display in the error message - * @param {IconData} icon Icon to format - * @returns {string} Formatted icon + * Format an icon for display in the error message. + * @param {IconData} icon Icon to format. + * @returns {string} Formatted icon. */ const format = (icon) => { if (icon.slug) { @@ -89,32 +88,32 @@ const TESTS = { checkUrl(data) { /** * Check if an URL has a redundant trailing slash. - * @param {URL} $url URL instance - * @param {string} url Original URL string - * @returns {boolean} Whether the URL has a redundant trailing slash + * @param {URL} $url URL instance. + * @param {string} url Original URL string. + * @returns {boolean} Whether the URL has a redundant trailing slash. */ const hasRedundantTrailingSlash = ($url, url) => url === $url.origin + '/'; /** * Check if an URL is static wikimedia asset URL. - * @param {URL} $url URL instance - * @returns {boolean} Whether the URL is static wikimedia asset URL + * @param {URL} $url URL instance. + * @returns {boolean} Whether the URL is static wikimedia asset URL. */ const isStaticWikimediaAssetUrl = ($url) => $url.hostname === 'upload.wikimedia.org'; /** * Check if an URL is raw GitHub asset URL. - * @param {URL} $url URL instance - * @returns {boolean} Whether the URL is raw GitHub asset URL + * @param {URL} $url URL instance. + * @returns {boolean} Whether the URL is raw GitHub asset URL. */ const isRawGithubAssetUrl = ($url) => $url.hostname === 'raw.githubusercontent.com'; /** * Check if an URL is a GitHub URL. - * @param {URL} $url URL instance - * @returns {boolean} Whether the URL is a GitHub URL + * @param {URL} $url URL instance. + * @returns {boolean} Whether the URL is a GitHub URL. */ const isGitHubUrl = ($url) => $url.hostname === 'github.com'; @@ -135,8 +134,8 @@ const TESTS = { /** * Check if an URL is a permanent GitHub URL for a file. - * @param {string} url URL string - * @returns {boolean} Whether the URL is a GitHub URL for a file + * @param {string} url URL string. + * @returns {boolean} Whether the URL is a GitHub URL for a file. */ const isPermalinkGitHubFileUrl = (url) => permalinkGitHubRegex.test(url); @@ -154,7 +153,6 @@ const TESTS = { if (icon.license !== undefined && Object.hasOwn(icon.license, 'url')) { allUrlFields.push([ false, - // eslint-disable-next-line no-warning-comments // TODO: `hasOwn` is not currently supported by TS. // See https://github.com/microsoft/TypeScript/issues/44253 /** @type {string} */ diff --git a/scripts/release/reformat-markdown.js b/scripts/release/reformat-markdown.js index 657f4220e..dca2252dc 100644 --- a/scripts/release/reformat-markdown.js +++ b/scripts/release/reformat-markdown.js @@ -19,7 +19,7 @@ const disclaimerFile = path.resolve(rootDirectory, 'DISCLAIMER.md'); /** * Reformat a file. - * @param {string} filePath Path to the file + * @param {string} filePath Path to the file. */ const reformat = async (filePath) => { const fileContent = await readFile(filePath, 'utf8'); diff --git a/scripts/release/update-cdn-urls.js b/scripts/release/update-cdn-urls.js index d436deb78..f84293d7b 100644 --- a/scripts/release/update-cdn-urls.js +++ b/scripts/release/update-cdn-urls.js @@ -17,6 +17,7 @@ const packageJsonFile = path.resolve(rootDirectory, 'package.json'); const readmeFile = path.resolve(rootDirectory, 'README.md'); /** + * Get the major version number from a semantic version string. * @param {string} semVersion A semantic version string. * @returns {number} The major version number. */ @@ -35,6 +36,7 @@ const getManifest = async () => { }; /** + * Update the version number in the README.md. * @param {number} majorVersion The major version number. */ const updateVersionInReadmeIfNecessary = async (majorVersion) => { diff --git a/scripts/release/update-sdk-ts-defs.js b/scripts/release/update-sdk-ts-defs.js index 049d2f95b..cab3d7cda 100644 --- a/scripts/release/update-sdk-ts-defs.js +++ b/scripts/release/update-sdk-ts-defs.js @@ -56,9 +56,9 @@ const generateSdkMts = async () => { /** * We must remove the duplicated export types that tsc generates from * JSDoc `typedef` comments. - * See {@link https://github.com/microsoft/TypeScript/issues/46011} - * @param {string} content Content of the file - * @returns {string} The content without duplicated export types + * See {@link https://github.com/microsoft/TypeScript/issues/46011}. + * @param {string} content Content of the file. + * @returns {string} The content without duplicated export types. */ const removeDuplicatedExportTypes = (content) => { const newContent = []; diff --git a/sdk.mjs b/sdk.mjs index 426773aff..f89c19576 100644 --- a/sdk.mjs +++ b/sdk.mjs @@ -42,16 +42,16 @@ export const SVG_PATH_REGEX = /^m[-mzlhvcsqtae\d,. ]+$/i; /** * Get the directory name where this file is located from `import.meta.url`, * equivalent to the `__dirname` global variable in CommonJS. - * @param {string} importMetaUrl import.meta.url - * @returns {string} Directory name in which this file is located + * @param {string} importMetaUrl Relative `import.meta.url` value of the caller. + * @returns {string} Directory name in which this file is located. */ export const getDirnameFromImportMeta = (importMetaUrl) => path.dirname(fileURLToPath(importMetaUrl)); /** * Build a regex to validate HTTPs URLs. - * @param {string} jsonschemaPath Path to the *.jsonschema.json* file - * @returns {Promise} Regex to validate HTTPs URLs + * @param {string} jsonschemaPath Path to the *.jsonschema.json* file. + * @returns {Promise} Regex to validate HTTPs URLs. */ export const urlRegex = async ( jsonschemaPath = path.join( @@ -68,22 +68,22 @@ export const urlRegex = async ( /** * Get the slug/filename for an icon. - * @param {IconData} icon The icon data as it appears in *_data/simple-icons.json* - * @returns {string} The slug/filename for the icon + * @param {IconData} icon The icon data as it appears in *_data/simple-icons.json*. + * @returns {string} The slug/filename for the icon. */ export const getIconSlug = (icon) => icon.slug || titleToSlug(icon.title); /** * Extract the path from an icon SVG content. - * @param {string} svg The icon SVG content - * @returns {string} The path from the icon SVG content + * @param {string} svg The icon SVG content. + * @returns {string} The path from the icon SVG content. */ export const svgToPath = (svg) => svg.split('"', 8)[7]; /** * Converts a brand title into a slug/filename. - * @param {string} title The title to convert - * @returns {string} The slug/filename for the title + * @param {string} title The title to convert. + * @returns {string} The slug/filename for the title. */ export const titleToSlug = (title) => title @@ -97,8 +97,8 @@ export const titleToSlug = (title) => /** * Converts a slug into a variable name that can be exported. - * @param {string} slug The slug to convert - * @returns {string} The variable name for the slug + * @param {string} slug The slug to convert. + * @returns {string} The variable name for the slug. */ export const slugToVariableName = (slug) => { const slugFirstLetter = slug[0].toUpperCase(); @@ -108,8 +108,8 @@ export const slugToVariableName = (slug) => { /** * Converts a brand title as defined in *_data/simple-icons.json* into a brand * title in HTML/SVG friendly format. - * @param {string} brandTitle The title to convert - * @returns {string} The brand title in HTML/SVG friendly format + * @param {string} brandTitle The title to convert. + * @returns {string} The brand title in HTML/SVG friendly format. */ export const titleToHtmlFriendly = (brandTitle) => brandTitle @@ -126,9 +126,9 @@ export const titleToHtmlFriendly = (brandTitle) => /** * Converts a brand title in HTML/SVG friendly format into a brand title (as - * it is seen in *_data/simple-icons.json*) - * @param {string} htmlFriendlyTitle The title to convert - * @returns {string} The brand title in HTML/SVG friendly format + * it is seen in *_data/simple-icons.json*). + * @param {string} htmlFriendlyTitle The title to convert. + * @returns {string} The brand title in HTML/SVG friendly format. */ export const htmlFriendlyToTitle = (htmlFriendlyTitle) => htmlFriendlyTitle @@ -138,17 +138,18 @@ export const htmlFriendlyToTitle = (htmlFriendlyTitle) => .replaceAll( /&(quot|amp|lt|gt);/g, /** - * @param {string} _ Full match - * @param {'quot' | 'amp' | 'lt' | 'gt'} reference Reference to replace - * @returns {string} Replacement for the reference + * Replace HTML entity references with their respective decoded characters. + * @param {string} _ Full match. + * @param {'quot' | 'amp' | 'lt' | 'gt'} reference Reference to replace. + * @returns {string} Replacement for the reference. */ (_, reference) => ({quot: '"', amp: '&', lt: '<', gt: '>'})[reference], ); /** * Get path of *_data/simple-icons.json*. - * @param {string} rootDirectory Path to the root directory of the project - * @returns {string} Path of *_data/simple-icons.json* + * @param {string} rootDirectory Path to the root directory of the project. + * @returns {string} Path of *_data/simple-icons.json*. */ export const getIconDataPath = ( rootDirectory = getDirnameFromImportMeta(import.meta.url), @@ -158,8 +159,8 @@ export const getIconDataPath = ( /** * Get contents of *_data/simple-icons.json*. - * @param {string} rootDirectory Path to the root directory of the project - * @returns {Promise} Content of *_data/simple-icons.json* + * @param {string} rootDirectory Path to the root directory of the project. + * @returns {Promise} Content of *_data/simple-icons.json*. */ export const getIconsDataString = ( rootDirectory = getDirnameFromImportMeta(import.meta.url), @@ -169,8 +170,8 @@ export const getIconsDataString = ( /** * Get icons data as object from *_data/simple-icons.json*. - * @param {string} rootDirectory Path to the root directory of the project - * @returns {Promise} Icons data as array from *_data/simple-icons.json* + * @param {string} rootDirectory Path to the root directory of the project. + * @returns {Promise} Icons data as array from *_data/simple-icons.json*. */ export const getIconsData = async ( rootDirectory = getDirnameFromImportMeta(import.meta.url), @@ -181,8 +182,8 @@ export const getIconsData = async ( /** * Replace Windows newline characters by Unix ones. - * @param {string} text The text to replace - * @returns {string} The text with Windows newline characters replaced by Unix ones + * @param {string} text The text to replace. + * @returns {string} The text with Windows newline characters replaced by Unix ones. */ export const normalizeNewlines = (text) => { return text.replaceAll('\r\n', '\n'); @@ -190,8 +191,8 @@ export const normalizeNewlines = (text) => { /** * Convert non-6-digit hex color to 6-digit with the character `#` stripped. - * @param {string} text The color text - * @returns {string} The color text in 6-digit hex format + * @param {string} text The color text. + * @returns {string} The color text in 6-digit hex format. */ export const normalizeColor = (text) => { let color = text.replace('#', '').toUpperCase(); @@ -207,8 +208,8 @@ export const normalizeColor = (text) => { /** * Get information about third party extensions from the README table. - * @param {string} readmePath Path to the README file - * @returns {Promise} Information about third party extensions + * @param {string} readmePath Path to the README file. + * @returns {Promise} Information about third party extensions. */ export const getThirdPartyExtensions = async ( readmePath = path.join( @@ -258,8 +259,8 @@ export const getThirdPartyExtensions = async ( /** * Get information about third party libraries from the README table. - * @param {string} readmePath Path to the README file - * @returns {Promise} Information about third party libraries + * @param {string} readmePath Path to the README file. + * @returns {Promise} Information about third party libraries. */ export const getThirdPartyLibraries = async ( readmePath = path.join( diff --git a/svglint.config.mjs b/svglint.config.mjs index 41103fe13..b62a7b4bd 100644 --- a/svglint.config.mjs +++ b/svglint.config.mjs @@ -51,8 +51,9 @@ const ignoreFile = './.svglint-ignored.json'; const iconIgnored = updateIgnoreFile ? {} : svglintIgnores; /** - * @param {{ [key: string]: any }} object Object to sort by key - * @returns {{ [key: string]: any }} Object sorted by key + * Sort an object alphabetically by key converting it to an array. + * @param {{ [key: string]: any }} object Object to sort by key. + * @returns {{ [key: string]: any }} Object sorted by key. */ const sortObjectByKey = (object) => { return Object.fromEntries( @@ -63,8 +64,9 @@ const sortObjectByKey = (object) => { }; /** - * @param {{ [key: string]: any }} object Object to sort by value - * @returns {{ [key: string]: any }} Object sorted by value + * Sort an object alphabetically by value converting it to an array. + * @param {{ [key: string]: any }} object Object to sort by value. + * @returns {{ [key: string]: any }} Object sorted by value. */ const sortObjectByValue = (object) => { return Object.fromEntries( @@ -222,7 +224,7 @@ if (updateIgnoreFile) { * Check if an icon is ignored by a linter rule. * @param {string} linterRule The name of the linter rule. * @param {string} path SVG path of the icon. - * @returns {boolean} Whether the icon is ignored by the linter rule + * @returns {boolean} Whether the icon is ignored by the linter rule. */ const isIgnored = (linterRule, path) => { return ( @@ -234,7 +236,7 @@ const isIgnored = (linterRule, path) => { * Ignore an icon for a linter rule. * @param {string} linterRule The name of the linter rule. * @param {string} path SVG path of the icon. - * @param {Cheerio} $ The SVG object + * @param {Cheerio} $ The SVG object. */ const ignoreIcon = (linterRule, path, $) => { iconIgnored[linterRule] ||= {}; @@ -520,11 +522,14 @@ const config = { const segments = getIconPathSegments(iconPath); /** @type {import('svg-path-segments').Segment[]} */ - // eslint-disable-next-line no-warning-comments // TODO: svgpath does not includes the `segments` property on the interface, // see https://github.com/fontello/svgpath/pull/67/files - // @ts-ignore - const absSegments = svgpath(iconPath).abs().unshort().segments; + // + /** @typedef {[string, ...number[]]} Segment */ + /** @type {Segment[]} */ + const absSegments = + // @ts-ignore + svgpath(iconPath).abs().unshort().segments; const lowerMovementCommands = ['m', 'l']; const lowerDirectionCommands = ['h', 'v']; @@ -608,8 +613,11 @@ const config = { ].reverse(); // If the previous command was a direction one, // we need to iterate back until we find the missing coordinates + // @ts-ignore if (upperDirectionCommands.includes(xPreviousCoord)) { + // @ts-ignore xPreviousCoord = undefined; + // @ts-ignore yPreviousCoord = undefined; let index_ = index; while ( @@ -624,12 +632,14 @@ const config = { // we need to consider the single coordinate as x if (upperHorDirectionCommand === xPreviousCoordDeep) { xPreviousCoordDeep = yPreviousCoordDeep; + // @ts-ignore yPreviousCoordDeep = undefined; } // If the previous command was a vertical movement, // we need to consider the single coordinate as y if (upperVersionDirectionCommand === xPreviousCoordDeep) { + // @ts-ignore xPreviousCoordDeep = undefined; } @@ -791,10 +801,8 @@ const config = { // Next switch cases have been ordered by frequency // of occurrence in the SVG paths of the icons case 'M': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = parms[1]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = parms[2]; // SVG 1.1: @@ -808,10 +816,8 @@ const config = { } case 'm': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = (currentAbsCoord[0] || 0) + parms[1]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = (currentAbsCoord[1] || 0) + parms[2]; if (seg.chain === undefined || seg.chain.start === seg.start) { @@ -822,48 +828,40 @@ const config = { } case 'H': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = parms[1]; break; } case 'h': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = (currentAbsCoord[0] || 0) + parms[1]; break; } case 'V': { - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = parms[1]; break; } case 'v': { - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = (currentAbsCoord[1] || 0) + parms[1]; break; } case 'L': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = parms[1]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = parms[2]; break; } case 'l': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = (currentAbsCoord[0] || 0) + parms[1]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = (currentAbsCoord[1] || 0) + parms[2]; break; @@ -871,108 +869,88 @@ const config = { case 'Z': case 'z': { - // eslint-disable-next-line no-warning-comments // TODO: Overlapping in Z should be handled in another rule + // @ts-ignore currentAbsCoord = [startPoint[0], startPoint[1]]; _resetStartPoint = true; break; } case 'C': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = parms[5]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = parms[6]; break; } case 'c': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = (currentAbsCoord[0] || 0) + parms[5]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = (currentAbsCoord[1] || 0) + parms[6]; break; } case 'A': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = parms[6]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = parms[7]; break; } case 'a': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = (currentAbsCoord[0] || 0) + parms[6]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = (currentAbsCoord[1] || 0) + parms[7]; break; } case 's': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = (currentAbsCoord[0] || 0) + parms[1]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = (currentAbsCoord[1] || 0) + parms[2]; break; } case 'S': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = parms[1]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = parms[2]; break; } case 't': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = (currentAbsCoord[0] || 0) + parms[1]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = (currentAbsCoord[1] || 0) + parms[2]; break; } case 'T': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = parms[1]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = parms[2]; break; } case 'Q': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = parms[3]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = parms[4]; break; } case 'q': { - /** @type {number} */ // @ts-ignore currentAbsCoord[0] = (currentAbsCoord[0] || 0) + parms[3]; - /** @type {number} */ // @ts-ignore currentAbsCoord[1] = (currentAbsCoord[1] || 0) + parms[4]; break; @@ -990,6 +968,7 @@ const config = { _resetStartPoint = false; } + // @ts-ignore _nextInStraightLine = straightLineCommands.includes(nextCmd); const _exitingStraightLine = _inStraightLine && !_nextInStraightLine; @@ -1006,6 +985,7 @@ const config = { // Get collinear coordinates for (let p = 1; p < currentLine.length - 1; p++) { const _collinearCoord = collinear( + // @ts-ignore currentLine[p - 1][0], currentLine[p - 1][1], currentLine[p][0], diff --git a/tests/min-reporter.cjs b/tests/min-reporter.cjs index a54a57908..ecbe953e7 100644 --- a/tests/min-reporter.cjs +++ b/tests/min-reporter.cjs @@ -2,7 +2,7 @@ * @file Custom mocha reporter. * * Serves to clear the console after the test run is finished. - * See {@link https://github.com/mochajs/mocha/issues/2312} + * See {@link https://github.com/mochajs/mocha/issues/2312}. */ const {reporters, Runner} = require('mocha'); @@ -11,11 +11,16 @@ const {EVENT_RUN_END} = Runner.constants; class EvenMoreMin extends reporters.Base { /** - * @param {import('mocha').Runner} runner Mocha test runner + * Construct a new `EvenMoreMin` reporter. + * @param {import('mocha').Runner} runner Mocha test runner. */ constructor(runner) { super(runner); - runner.once(EVENT_RUN_END, () => this.epilogue()); + runner.once(EVENT_RUN_END, () => { + // TODO: mocha's base reporters are not typed + // @ts-ignore + return this.epilogue(); + }); } } diff --git a/tests/test-icon.js b/tests/test-icon.js index 8b1c22e10..db530e29f 100644 --- a/tests/test-icon.js +++ b/tests/test-icon.js @@ -20,9 +20,10 @@ const iconsDirectory = path.resolve( /** * Checks if icon data matches a subject icon. - * @param {import('../sdk.d.ts').IconData} icon Icon data - * @param {import('../types.d.ts').SimpleIcon} subject Icon object to check against icon data - * @param {string} slug Icon data slug + * @param {import('../sdk.d.ts').IconData} icon Icon data. + * @param {import('../types.d.ts').SimpleIcon} subject + * Icon object to check against icon data. + * @param {string} slug Icon data slug. */ export const testIcon = (icon, subject, slug) => { const svgPath = path.resolve(iconsDirectory, `${slug}.svg`);