mirror of
https://github.com/simple-icons/simple-icons.git
synced 2024-11-16 00:59:07 +02:00
Stricter rules for JSDoc documentation blocks (#11881)
This commit is contained in:
parent
1a5a37cc2d
commit
5183e3c06b
@ -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": [
|
||||
{
|
||||
|
@ -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",
|
||||
|
@ -41,8 +41,9 @@ const licenseTypes =
|
||||
);
|
||||
|
||||
/**
|
||||
* @param {string} input URL input
|
||||
* @returns {Promise<boolean|string>} Whether the input is a valid URL
|
||||
* Whether an input is a valid URL.
|
||||
* @param {string} input URL input.
|
||||
* @returns {Promise<boolean|string>} 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);
|
||||
|
@ -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<boolean>} True if the file exists, false otherwise.
|
||||
*/
|
||||
const fileExists = async (fpath) => {
|
||||
try {
|
||||
await fs.access(fpath);
|
||||
|
@ -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(/(?<!\\)'/g, "\\'");
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {License} license The license object or URL
|
||||
* @returns {License} The license object with a URL
|
||||
* Converts a license object to a URL if the URL is not defined.
|
||||
* @param {License} license The license object or URL.
|
||||
* @returns {License} The license object with a URL.
|
||||
*/
|
||||
const licenseToObject = (license) => {
|
||||
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);
|
||||
|
@ -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} */
|
||||
|
@ -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');
|
||||
|
@ -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) => {
|
||||
|
@ -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 = [];
|
||||
|
69
sdk.mjs
69
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<RegExp>} Regex to validate HTTPs URLs
|
||||
* @param {string} jsonschemaPath Path to the *.jsonschema.json* file.
|
||||
* @returns {Promise<RegExp>} 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<string>} Content of *_data/simple-icons.json*
|
||||
* @param {string} rootDirectory Path to the root directory of the project.
|
||||
* @returns {Promise<string>} 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<IconData[]>} Icons data as array from *_data/simple-icons.json*
|
||||
* @param {string} rootDirectory Path to the root directory of the project.
|
||||
* @returns {Promise<IconData[]>} 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<ThirdPartyExtension[]>} Information about third party extensions
|
||||
* @param {string} readmePath Path to the README file.
|
||||
* @returns {Promise<ThirdPartyExtension[]>} 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<ThirdPartyExtension[]>} Information about third party libraries
|
||||
* @param {string} readmePath Path to the README file.
|
||||
* @returns {Promise<ThirdPartyExtension[]>} Information about third party libraries.
|
||||
*/
|
||||
export const getThirdPartyLibraries = async (
|
||||
readmePath = path.join(
|
||||
|
@ -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],
|
||||
|
@ -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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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`);
|
||||
|
Loading…
Reference in New Issue
Block a user