From 512e4cbf4a224e03b0898ba41a3db93f67dd7d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Mond=C3=A9jar=20Rubio?= Date: Thu, 6 Jun 2024 21:24:29 +0200 Subject: [PATCH] Resolve all possible TODO comments (#11119) --- scripts/build/package.js | 18 +++++++++++++----- scripts/lint/ourlint.js | 28 +++++++++++++++------------- svglint.config.mjs | 22 ++++++++++++++-------- tests/test-icon.js | 1 - 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/scripts/build/package.js b/scripts/build/package.js index 2fa563da..a2b2de2a 100644 --- a/scripts/build/package.js +++ b/scripts/build/package.js @@ -41,6 +41,14 @@ const iconObjectTemplateFile = path.resolve( 'icon-object.js.template', ); +/** + * Merged type from icon data and icon JS object needed to build by reference + * to not decrease performance in the build process. + * @typedef {import('../../types.js').SimpleIcon & import('../../sdk.d.ts').IconData} IconDataAndObject + */ + +/** @type {IconDataAndObject[]} */ +// @ts-ignore const icons = await getIconsData(); const iconObjectTemplate = await fs.readFile(iconObjectTemplateFile, UTF8); @@ -64,8 +72,11 @@ const licenseToObject = (license) => { return license; }; -// TODO: Find a way to type this object without decreasing performance -// @ts-ignore +/** + * Converts an icon object to a JavaScript object. + * @param {IconDataAndObject} icon The icon object + * @returns {string} The JavaScript object + */ const iconToJsObject = (icon) => { return util.format( iconObjectTemplate, @@ -106,10 +117,7 @@ const build = async () => { icons.map(async (icon) => { const filename = getIconSlug(icon); const svgFilepath = path.resolve(iconsDirectory, `${filename}.svg`); - // TODO: Find a way to type these objects without decreasing performance - // @ts-ignore icon.svg = await fs.readFile(svgFilepath, UTF8); - // @ts-ignore icon.path = svgToPath(icon.svg); icon.slug = filename; const iconObject = iconToJsObject(icon); diff --git a/scripts/lint/ourlint.js b/scripts/lint/ourlint.js index b76b90b6..3463bc7b 100644 --- a/scripts/lint/ourlint.js +++ b/scripts/lint/ourlint.js @@ -98,19 +98,21 @@ const TESTS = { const allUrlFields = [ ...new Set( - data.icons - .flatMap((icon) => { - // TODO: `Omit` is not working smoothly here - const license = - // @ts-ignore - icon.license && icon.license.url - ? // @ts-ignore - [icon.license.url] - : []; - return [icon.source, icon.guidelines, ...license]; - }) - - .filter(Boolean), + data.icons.flatMap((icon) => { + /** @type {string[]} */ + const license = + icon.license !== undefined && Object.hasOwn(icon.license, 'url') + ? [ + // TODO: `hasOwn` is not currently supported by TS. + // See https://github.com/microsoft/TypeScript/issues/44253 + /** @type {string} */ + // @ts-ignore + icon.license.url, + ] + : []; + const guidelines = icon.guidelines ? [icon.guidelines] : []; + return [icon.source, ...guidelines, ...license]; + }), ), ]; diff --git a/svglint.config.mjs b/svglint.config.mjs index 82eb0b2f..1a11bc11 100644 --- a/svglint.config.mjs +++ b/svglint.config.mjs @@ -163,6 +163,14 @@ const maybeShortenedWithEllipsis = (string_) => { return string_.length > 20 ? `${string_.slice(0, 20)}...` : string_; }; +/** + * Check if a string is a number. + * @param {string} string_ The string to check. + * @returns {boolean} Whether the string is a number. + */ +const isNumber = (string_) => + [...string_].every((character) => '0123456789'.includes(character)); + /** * Memoize a function which accepts a single argument. * A second argument can be passed to be used as key. @@ -367,7 +375,7 @@ const config = { } else { // Encode all non ascii characters plus "'&<> (XML named entities) /** @type {number} */ - // @ts-ignore Coerce to number + // @ts-ignore const charDecimalCode = iconTitleText.codePointAt(i); if (charDecimalCode > 127) { @@ -398,12 +406,10 @@ const config = { // Check if there are some other encoded characters in decimal notation // which shouldn't be encoded - for (const match of encodingMatches.filter((m) => { - // TODO: this fails using `Number.isNaN`, investigate - // @ts-ignore - // eslint-disable-next-line unicorn/prefer-number-properties - return !isNaN(m[2]); - })) { + const numberMatches = encodingMatches.filter( + (m) => m[2] !== undefined && isNumber(m[2]), + ); + for (const match of numberMatches) { const decimalNumber = Number.parseInt(match[2], 10); if (decimalNumber > 127) { continue; @@ -514,7 +520,7 @@ const config = { const segments = getIconPathSegments(iconPath); /** @type {import('svg-path-segments').Segment[]} */ - // TODO: svgpath does not includes the segment property on the interface, + // 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; diff --git a/tests/test-icon.js b/tests/test-icon.js index c9fe8f04..8b1c22e1 100644 --- a/tests/test-icon.js +++ b/tests/test-icon.js @@ -64,7 +64,6 @@ export const testIcon = (icon, subject, slug) => { if (icon.license) { assert.equal(subject.license?.type, icon.license.type); if (icon.license.type === 'custom') { - // TODO: `Omit` not working smoothly here // @ts-ignore assert.equal(subject.license.url, icon.license.url); }