diff --git a/.github/renovate.json5 b/.github/renovate.json5
index 051d2a373fd9..a6accf89b68d 100644
--- a/.github/renovate.json5
+++ b/.github/renovate.json5
@@ -16,5 +16,5 @@
separateMajorMinor: false,
// We manually update digest dependencies (eg. hashes in Github actions)
- digest: { enabled: false },
+ digest: {enabled: false},
}
diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml
index 77a4b5243840..7eacca8d50b4 100644
--- a/.github/workflows/create-release.yml
+++ b/.github/workflows/create-release.yml
@@ -54,13 +54,13 @@ jobs:
- name: Install dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Update major version in CDN URLs
- run: node ./scripts/release/update-cdn-urls.js
+ run: ./scripts/release/update-cdn-urls.js
- name: Update SVGs count milestone
- run: node ./scripts/release/update-svgs-count.js
+ run: ./scripts/release/update-svgs-count.js
- name: Update slugs table
- run: node ./scripts/release/update-slugs-table.js
+ run: ./scripts/release/update-slugs-table.js
- name: Update SDK Typescript definitions
- run: node ./scripts/release/update-sdk-ts-defs.js
+ run: ./scripts/release/update-sdk-ts-defs.js
- name: Commit version bump
uses: stefanzweifel/git-auto-commit-action@v5
with:
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 7158e9541323..24af181537e4 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -43,9 +43,9 @@ jobs:
- name: Install dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Reformat to regular markdown
- run: node ./scripts/release/reformat-markdown.js "${{ steps.get-version.outputs.version }}"
+ run: ./scripts/release/reformat-markdown.js "${{ steps.get-version.outputs.version }}"
- name: Update SDK Typescript definitions
- run: node ./scripts/release/update-sdk-ts-defs.js
+ run: ./scripts/release/update-sdk-ts-defs.js
- name: Build NodeJS package
run: npm run build
- name: Deploy to NPM
@@ -65,7 +65,7 @@ jobs:
- id: get-version
uses: ./.github/actions/get-version
- name: Reformat to regular markdown
- run: node ./scripts/release/reformat-markdown.js "${{ steps.get-version.outputs.version }}"
+ run: ./scripts/release/reformat-markdown.js "${{ steps.get-version.outputs.version }}"
- name: Configure GIT credentials
run: |
git config user.name "${GITHUB_ACTOR}"
diff --git a/.jsonschema.json b/.jsonschema.json
index 881e74011c20..2bc5ac875b18 100644
--- a/.jsonschema.json
+++ b/.jsonschema.json
@@ -32,12 +32,12 @@
"aka": {
"description": "The brand is also known as (e.g. full length name or abbreviation)",
"type": "array",
- "items": { "type": "string" }
+ "items": {"type": "string"}
},
"dup": {
"description": "Different brands that use the exact same icon",
"type": "array",
- "items": { "$ref": "#/definitions/duplicate" }
+ "items": {"$ref": "#/definitions/duplicate"}
},
"loc": {
"description": "Localized names of the brand",
@@ -46,7 +46,7 @@
"old": {
"description": "Old names, for backwards compatibility",
"type": "array",
- "items": { "type": "string" }
+ "items": {"type": "string"}
}
},
"minProperties": 1,
@@ -702,7 +702,7 @@
"icons": {
"description": "A list of brands",
"type": "array",
- "items": { "$ref": "#/definitions/brand" }
+ "items": {"$ref": "#/definitions/brand"}
}
},
"additionalProperties": false,
diff --git a/.prettierignore b/.prettierignore
index a2378b87c728..c055463eec7b 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -6,12 +6,3 @@
# We use our own formatting for the data files.
_data/simple-icons.json
-
-# JavaScript templates are invalid JavaScript so cannot be formatted.
-scripts/build/templates/*.js
-
-# Generated JavaScript files don't need to be formatted
-index.js
-index.mjs
-index.d.ts
-sdk.js
diff --git a/.prettierrc.json b/.prettierrc.json
index 544138be4565..a0f24c991eba 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -1,3 +1,4 @@
{
- "singleQuote": true
+ "singleQuote": true,
+ "bracketSpacing": false
}
diff --git a/.xo-config.json b/.xo-config.json
new file mode 100644
index 000000000000..6cd08b29b73c
--- /dev/null
+++ b/.xo-config.json
@@ -0,0 +1,49 @@
+{
+ "prettier": true,
+ "space": 2,
+ "plugins": ["import"],
+ "rules": {
+ "n/no-unsupported-features": "off",
+ "n/no-unsupported-features/node-builtins": "off",
+ "n/file-extension-in-import": "off",
+ "sort-imports": [
+ "error",
+ {
+ "ignoreCase": false,
+ "ignoreDeclarationSort": true,
+ "ignoreMemberSort": false,
+ "memberSyntaxSortOrder": ["none", "all", "multiple", "single"],
+ "allowSeparatedGroups": false
+ }
+ ],
+ "import/no-named-as-default": "off",
+ "import/extensions": "off",
+ "import/order": [
+ "error",
+ {
+ "groups": ["builtin", "external", "parent", "sibling", "index"],
+ "alphabetize": {
+ "order": "asc",
+ "caseInsensitive": true
+ },
+ "warnOnUnassignedImports": true,
+ "newlines-between": "never"
+ }
+ ]
+ },
+ "overrides": [
+ {
+ "files": ["sdk.mjs", "sdk.d.ts"],
+ "nodeVersion": ">=14"
+ },
+ {
+ "files": [
+ "scripts/**/*",
+ "tests/**/*",
+ "svglint.config.mjs",
+ "svgo.config.mjs"
+ ],
+ "nodeVersion": ">=18"
+ }
+ ]
+}
diff --git a/package.json b/package.json
index f73db04c221e..e8cade0f1185 100644
--- a/package.json
+++ b/package.json
@@ -88,6 +88,7 @@
"chalk": "5.3.0",
"editorconfig-checker": "5.1.5",
"esbuild": "0.19.4",
+ "eslint-plugin-import": "2.29.1",
"fake-diff": "1.0.0",
"fast-fuzzy": "1.12.0",
"get-relative-luminance": "1.0.0",
@@ -97,23 +98,24 @@
"markdown-link-check": "3.11.2",
"mocha": "10.2.0",
"named-html-entities-json": "1.0.0",
- "prettier": "3.0.3",
"svg-path-bbox": "1.2.5",
"svg-path-segments": "1.0.0",
"svglint": "2.4.0",
"svgo": "3.0.2",
"svgpath": "2.6.0",
- "typescript": "5.2.2"
+ "typescript": "5.2.2",
+ "xo": "0.58.0"
},
"scripts": {
- "build": "node scripts/build/package.js",
- "clean": "node scripts/build/clean.js",
- "format": "prettier --cache --write .",
- "lint": "npm run ourlint && npm run jslint && npm run jsonlint && npm run svglint && npm run wslint",
- "ourlint": "node scripts/lint/ourlint.js",
- "jslint": "prettier --cache --check .",
- "jsonlint": "node scripts/lint/jsonlint.js",
- "svglint": "svglint --ci $npm_config_icons",
+ "build": "./scripts/build/package.js",
+ "clean": "./scripts/build/clean.js",
+ "format": "prettier --cache --write --ignore-unknown '**/*.!(js|jsx|mjs|cjs|ts|tsx|mts|cts|svg)' && xo --fix",
+ "lint": "npm run ourlint && npm run prettierlint && npm run jslint && npm run jsonlint && npm run svglint && npm run wslint",
+ "ourlint": "./scripts/lint/ourlint.js",
+ "prettierlint": "prettier --cache --check --ignore-unknown '**/*.!(js|jsx|mjs|cjs|ts|tsx|mts|cts|svg)'",
+ "jslint": "xo",
+ "jsonlint": "./scripts/lint/jsonlint.js",
+ "svglint": "svglint --ci $npm_config_icons --config svglint.config.mjs",
"wslint": "editorconfig-checker",
"prepare": "husky",
"prepublishOnly": "npm run build",
@@ -121,8 +123,8 @@
"test": "mocha tests --reporter tests/min-reporter.cjs --inline-diffs",
"pretest": "npm run prepublishOnly",
"posttest": "npm run postpublish",
- "get-filename": "node scripts/get-filename.js",
- "add-icon-data": "node scripts/add-icon-data.js"
+ "get-filename": "./scripts/get-filename.js",
+ "add-icon-data": "./scripts/add-icon-data.js"
},
"engines": {
"node": ">=0.12.18"
diff --git a/scripts/add-icon-data.js b/scripts/add-icon-data.js
old mode 100644
new mode 100755
index 785130d5c213..7ee85e258bb2
--- a/scripts/add-icon-data.js
+++ b/scripts/add-icon-data.js
@@ -1,22 +1,23 @@
+#!/usr/bin/env node
import process from 'node:process';
+import {ExitPromptError, checkbox, confirm, input} from '@inquirer/prompts';
import chalk from 'chalk';
-import { input, confirm, checkbox, ExitPromptError } from '@inquirer/prompts';
-import autocomplete from 'inquirer-autocomplete-standalone';
+import {search} from 'fast-fuzzy';
import getRelativeLuminance from 'get-relative-luminance';
-import { search } from 'fast-fuzzy';
+import autocomplete from 'inquirer-autocomplete-standalone';
import {
URL_REGEX,
collator,
getIconsDataString,
- titleToSlug,
normalizeColor,
+ titleToSlug,
} from '../sdk.mjs';
-import { getJsonSchemaData, writeIconsData } from './utils.js';
+import {getJsonSchemaData, writeIconsData} from './utils.js';
const iconsData = JSON.parse(await getIconsDataString());
const jsonSchema = await getJsonSchemaData();
-const HEX_REGEX = /^#?[a-f0-9]{3,8}$/i;
+const HEX_REGEX = /^#?[a-f\d]{3,8}$/i;
const aliasTypes = ['aka', 'old'].map((key) => ({
name: `${key} (${jsonSchema.definitions.brand.properties.aliases.properties[key].description})`,
@@ -25,7 +26,7 @@ const aliasTypes = ['aka', 'old'].map((key) => ({
const licenseTypes =
jsonSchema.definitions.brand.properties.license.oneOf[0].properties.type.enum.map(
- (license) => ({ name: license, value: license }),
+ (license) => ({name: license, value: license}),
);
const isValidURL = (input) =>
@@ -35,7 +36,7 @@ const isValidHexColor = (input) =>
HEX_REGEX.test(input) || 'Must be a valid hex code.';
const isNewIcon = (input) =>
- !iconsData.icons.find(
+ !iconsData.icons.some(
(icon) =>
icon.title === input || titleToSlug(icon.title) === titleToSlug(input),
) || 'This icon title or slug already exists.';
@@ -83,10 +84,10 @@ try {
? {
type: await autocomplete({
message: "What is the icon's license?",
- source: async (input) => {
+ async source(input) {
input = (input || '').trim();
return input
- ? search(input, licenseTypes, { keySelector: (x) => x.value })
+ ? search(input, licenseTypes, {keySelector: (x) => x.value})
: licenseTypes;
},
}),
@@ -107,12 +108,14 @@ try {
}).then(async (aliases) => {
const result = {};
for (const alias of aliases) {
+ // eslint-disable-next-line no-await-in-loop
result[alias] = await input({
message: `What ${alias} aliases would you like to add? (separate with commas)`,
}).then((aliases) =>
aliases.split(',').map((alias) => alias.trim()),
);
}
+
return result;
})
: undefined,
@@ -136,11 +139,11 @@ try {
console.log(chalk.red('\nAborted.'));
process.exit(1);
}
-} catch (err) {
- if (err instanceof ExitPromptError) {
+} catch (error) {
+ if (error instanceof ExitPromptError) {
console.log(chalk.red('\nAborted.'));
process.exit(1);
}
- throw err;
+ throw error;
}
diff --git a/scripts/build/clean.js b/scripts/build/clean.js
old mode 100644
new mode 100755
index ff95c4b9e1ca..83423f25d7a5
--- a/scripts/build/clean.js
+++ b/scripts/build/clean.js
@@ -1,29 +1,37 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Clean files built by the build process.
*/
-import fs from 'node:fs';
+import fs from 'node:fs/promises';
import path from 'node:path';
-import { getDirnameFromImportMeta } from '../../sdk.mjs';
+import process from 'node:process';
+import {getDirnameFromImportMeta} from '../../sdk.mjs';
const __dirname = getDirnameFromImportMeta(import.meta.url);
const rootDirectory = path.resolve(__dirname, '..', '..');
const files = ['index.js', 'index.mjs', 'index.d.ts', 'sdk.js'];
const fileExists = (fpath) =>
- new Promise((r) => fs.access(fpath, fs.constants.F_OK, (e) => r(!e)));
+ fs
+ .access(fpath, fs.constants.F_OK)
+ .then(() => true)
+ .catch(() => false);
-Promise.all(
- files.map(async (file) => {
- const filepath = path.join(rootDirectory, file);
- if (!(await fileExists(filepath))) {
- console.error(`File ${file} does not exist, skipping...`);
- return;
- }
- return fs.promises.unlink(filepath);
- }),
-).catch((error) => {
- console.error(`Error cleaning files: ${error.message}`);
+try {
+ Promise.all(
+ files.map(async (file) => {
+ const filepath = path.join(rootDirectory, file);
+ if (!(await fileExists(filepath))) {
+ console.error(`File ${file} does not exist, skipping...`);
+ return;
+ }
+
+ return fs.unlink(filepath);
+ }),
+ );
+} catch (error) {
+ console.error('Error cleaning files:', error);
process.exit(1);
-});
+}
diff --git a/scripts/build/package.js b/scripts/build/package.js
old mode 100644
new mode 100755
index 05ca17bba437..edf73768223b
--- a/scripts/build/package.js
+++ b/scripts/build/package.js
@@ -1,36 +1,40 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Simple Icons package build script.
*/
-import { promises as fs } from 'node:fs';
+import {promises as fs} from 'node:fs';
import path from 'node:path';
import util from 'node:util';
-import { transform as esbuildTransform } from 'esbuild';
+import {transform as esbuildTransform} from 'esbuild';
import {
+ collator,
+ getDirnameFromImportMeta,
getIconSlug,
+ getIconsData,
+ slugToVariableName,
svgToPath,
titleToHtmlFriendly,
- slugToVariableName,
- getIconsData,
- getDirnameFromImportMeta,
- collator,
} from '../../sdk.mjs';
const __dirname = getDirnameFromImportMeta(import.meta.url);
const UTF8 = 'utf8';
-const rootDir = path.resolve(__dirname, '..', '..');
-const iconsDir = path.resolve(rootDir, 'icons');
-const indexJsFile = path.resolve(rootDir, 'index.js');
-const indexMjsFile = path.resolve(rootDir, 'index.mjs');
-const sdkJsFile = path.resolve(rootDir, 'sdk.js');
-const sdkMjsFile = path.resolve(rootDir, 'sdk.mjs');
-const indexDtsFile = path.resolve(rootDir, 'index.d.ts');
+const rootDirectory = path.resolve(__dirname, '..', '..');
+const iconsDirectory = path.resolve(rootDirectory, 'icons');
+const indexJsFile = path.resolve(rootDirectory, 'index.js');
+const indexMjsFile = path.resolve(rootDirectory, 'index.mjs');
+const sdkJsFile = path.resolve(rootDirectory, 'sdk.js');
+const sdkMjsFile = path.resolve(rootDirectory, 'sdk.mjs');
+const indexDtsFile = path.resolve(rootDirectory, 'index.d.ts');
-const templatesDir = path.resolve(__dirname, 'templates');
-const iconObjectTemplateFile = path.resolve(templatesDir, 'icon-object.js');
+const templatesDirectory = path.resolve(__dirname, 'templates');
+const iconObjectTemplateFile = path.resolve(
+ templatesDirectory,
+ 'icon-object.js.template',
+);
const build = async () => {
const icons = await getIconsData();
@@ -38,8 +42,9 @@ const build = async () => {
// Local helper functions
const escape = (value) => {
- return value.replace(/(? {
if (license === undefined) {
return;
@@ -48,8 +53,10 @@ const build = async () => {
if (license.url === undefined) {
license.url = `https://spdx.org/licenses/${license.type}`;
}
+
return license;
};
+
const iconToObject = (icon) => {
return util.format(
iconObjectTemplate,
@@ -65,11 +72,13 @@ const build = async () => {
: '',
);
};
- const writeJs = async (filepath, rawJavaScript, opts = null) => {
- opts = opts === null ? { minify: true } : opts;
- const { code } = await esbuildTransform(rawJavaScript, opts);
+
+ const writeJs = async (filepath, rawJavaScript, options = null) => {
+ options = options === null ? {minify: true} : options;
+ const {code} = await esbuildTransform(rawJavaScript, options);
await fs.writeFile(filepath, code);
};
+
const writeTs = async (filepath, rawTypeScript) => {
await fs.writeFile(filepath, rawTypeScript);
};
@@ -78,13 +87,13 @@ const build = async () => {
const buildIcons = await Promise.all(
icons.map(async (icon) => {
const filename = getIconSlug(icon);
- const svgFilepath = path.resolve(iconsDir, `${filename}.svg`);
+ const svgFilepath = path.resolve(iconsDirectory, `${filename}.svg`);
icon.svg = await fs.readFile(svgFilepath, UTF8);
icon.path = svgToPath(icon.svg);
icon.slug = filename;
const iconObject = iconToObject(icon);
const iconExportName = slugToVariableName(icon.slug);
- return { icon, iconObject, iconExportName };
+ return {icon, iconObject, iconExportName};
}),
);
@@ -93,33 +102,33 @@ const build = async () => {
const iconsBarrelMjs = [];
buildIcons.sort((a, b) => collator.compare(a.icon.title, b.icon.title));
- for (const { iconObject, iconExportName } of buildIcons) {
+ for (const {iconObject, iconExportName} of buildIcons) {
iconsBarrelDts.push(`export const ${iconExportName}:I;`);
iconsBarrelJs.push(`${iconExportName}:${iconObject},`);
iconsBarrelMjs.push(`export const ${iconExportName}=${iconObject}`);
}
- // constants used in templates to reduce package size
+ // Constants used in templates to reduce package size
const constantsString = `const a='';`;
- // write our file containing the exports of all icons in CommonJS ...
+ // Write our file containing the exports of all icons in CommonJS ...
const rawIndexJs = `${constantsString}module.exports={${iconsBarrelJs.join(
'',
)}};`;
await writeJs(indexJsFile, rawIndexJs);
- // and ESM
+ // ... and ESM
const rawIndexMjs = constantsString + iconsBarrelMjs.join('');
await writeJs(indexMjsFile, rawIndexMjs);
- // and create a type declaration file
+ // ... and create a type declaration file
const rawIndexDts = `import {SimpleIcon} from "./types";export {SimpleIcon};type I=SimpleIcon;${iconsBarrelDts.join(
'',
)}`;
await writeTs(indexDtsFile, rawIndexDts);
- // create a CommonJS SDK file
+ // Create a CommonJS SDK file
await writeJs(sdkJsFile, await fs.readFile(sdkMjsFile, UTF8), {
format: 'cjs',
});
};
-build();
+await build();
diff --git a/scripts/build/templates/icon-object.js b/scripts/build/templates/icon-object.js.template
similarity index 100%
rename from scripts/build/templates/icon-object.js
rename to scripts/build/templates/icon-object.js.template
diff --git a/scripts/get-filename.js b/scripts/get-filename.js
old mode 100644
new mode 100755
index 826b43c3ebc7..29118cbc7e92
--- a/scripts/get-filename.js
+++ b/scripts/get-filename.js
@@ -1,3 +1,4 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Script that takes a brand name as argument and outputs the corresponding
@@ -5,16 +6,13 @@
*/
import process from 'node:process';
-import { titleToSlug } from '../sdk.mjs';
+import {titleToSlug} from '../sdk.mjs';
if (process.argv.length < 3) {
console.error('Provide a brand name as argument');
process.exit(1);
} else {
- const brandName = process.argv
- .slice(3)
- .reduce((acc, arg) => `${acc} ${arg}`, process.argv[2]);
-
+ const brandName = process.argv[2];
const filename = titleToSlug(brandName);
console.log(`For '${brandName}' use the file 'icons/${filename}.svg'`);
}
diff --git a/scripts/lint/jsonlint.js b/scripts/lint/jsonlint.js
old mode 100644
new mode 100755
index 0479dc988f41..a439bd732b29
--- a/scripts/lint/jsonlint.js
+++ b/scripts/lint/jsonlint.js
@@ -1,20 +1,21 @@
+#!/usr/bin/env node
/**
* @fileoverview
* CLI tool to run jsonschema on the simple-icons.json data file.
*/
import process from 'node:process';
-import { Validator } from 'jsonschema';
-import { getIconsData } from '../../sdk.mjs';
-import { getJsonSchemaData } from '../utils.js';
+import {Validator} from 'jsonschema';
+import {getIconsData} from '../../sdk.mjs';
+import {getJsonSchemaData} from '../utils.js';
const icons = await getIconsData();
const schema = await getJsonSchemaData();
const validator = new Validator();
-const result = validator.validate({ icons }, schema);
+const result = validator.validate({icons}, schema);
if (result.errors.length > 0) {
- result.errors.forEach((error) => console.error(error));
+ for (const error of result.errors) console.error(error);
console.error(`Found ${result.errors.length} error(s) in simple-icons.json`);
process.exit(1);
}
diff --git a/scripts/lint/ourlint.js b/scripts/lint/ourlint.js
old mode 100644
new mode 100755
index 49abcb206b62..fcb320498c8a
--- a/scripts/lint/ourlint.js
+++ b/scripts/lint/ourlint.js
@@ -1,3 +1,4 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Linters for the package that can't easily be implemented in the existing
@@ -5,9 +6,8 @@
*/
import process from 'node:process';
-import { URL } from 'node:url';
import fakeDiff from 'fake-diff';
-import { getIconsDataString, normalizeNewlines, collator } from '../../sdk.mjs';
+import {collator, getIconsDataString, normalizeNewlines} from '../../sdk.mjs';
/**
* Contains our tests so they can be isolated from each other.
@@ -15,39 +15,43 @@ import { getIconsDataString, normalizeNewlines, collator } from '../../sdk.mjs';
*/
const TESTS = {
/* Tests whether our icons are in alphabetical order */
- alphabetical: (data) => {
+ alphabetical(data) {
const collector = (invalidEntries, icon, index, array) => {
if (index > 0) {
- const prev = array[index - 1];
- const comparison = collator.compare(icon.title, prev.title);
+ const previous = array[index - 1];
+ const comparison = collator.compare(icon.title, previous.title);
if (comparison < 0) {
invalidEntries.push(icon);
- } else if (comparison === 0) {
- if (prev.slug) {
- if (!icon.slug || collator.compare(icon.slug, prev.slug) < 0) {
- invalidEntries.push(icon);
- }
- }
+ } else if (
+ comparison === 0 &&
+ previous.slug &&
+ (!icon.slug || collator.compare(icon.slug, previous.slug) < 0)
+ ) {
+ invalidEntries.push(icon);
}
}
+
return invalidEntries;
};
+
const format = (icon) => {
if (icon.slug) {
return `${icon.title} (${icon.slug})`;
}
+
return icon.title;
};
+ // eslint-disable-next-line unicorn/no-array-reduce, unicorn/no-array-callback-reference
const invalids = data.icons.reduce(collector, []);
- if (invalids.length) {
+ if (invalids.length > 0) {
return `Some icons aren't in alphabetical order:
${invalids.map((icon) => format(icon)).join(', ')}`;
}
},
/* Check the formatting of the data file */
- prettified: (data, dataString) => {
+ prettified(data, dataString) {
const normalizedDataString = normalizeNewlines(dataString);
const dataPretty = `${JSON.stringify(data, null, 4)}\n`;
@@ -58,9 +62,9 @@ const TESTS = {
},
/* Check redundant trailing slash in URL */
- checkUrl: (data) => {
+ checkUrl(data) {
const hasRedundantTrailingSlash = (url) => {
- const origin = new URL(url).origin;
+ const {origin} = new global.URL(url);
return /^\/+$/.test(url.replace(origin, ''));
};
@@ -89,9 +93,11 @@ const data = JSON.parse(dataString);
const errors = (
await Promise.all(Object.values(TESTS).map((test) => test(data, dataString)))
-).filter(Boolean);
+)
+ // eslint-disable-next-line unicorn/no-await-expression-member
+ .filter(Boolean);
if (errors.length > 0) {
- errors.forEach((error) => console.error(`\u001b[31m${error}\u001b[0m`));
+ for (const error of errors) console.error(`\u001B[31m${error}\u001B[0m`);
process.exit(1);
}
diff --git a/scripts/release/reformat-markdown.js b/scripts/release/reformat-markdown.js
old mode 100644
new mode 100755
index 2606a58da8e6..8cbc9196dd02
--- a/scripts/release/reformat-markdown.js
+++ b/scripts/release/reformat-markdown.js
@@ -1,19 +1,21 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Rewrite some Markdown files.
*/
+import {readFile, writeFile} from 'node:fs/promises';
import path from 'node:path';
-import { writeFile, readFile } from 'node:fs/promises';
-import { getDirnameFromImportMeta } from '../../sdk.mjs';
+import process from 'node:process';
+import {getDirnameFromImportMeta} from '../../sdk.mjs';
const LINKS_BRANCH = process.argv[2] || 'develop';
const __dirname = getDirnameFromImportMeta(import.meta.url);
-const rootDir = path.resolve(__dirname, '..', '..');
-const readmeFile = path.resolve(rootDir, 'README.md');
-const disclaimerFile = path.resolve(rootDir, 'DISCLAIMER.md');
+const rootDirectory = path.resolve(__dirname, '..', '..');
+const readmeFile = path.resolve(rootDirectory, 'README.md');
+const disclaimerFile = path.resolve(rootDirectory, 'DISCLAIMER.md');
const reformat = async (filePath) => {
const fileContent = await readFile(filePath, 'utf8');
@@ -21,17 +23,17 @@ const reformat = async (filePath) => {
filePath,
fileContent
// Replace all CDN links with raw links
- .replace(
+ .replaceAll(
/https:\/\/cdn.simpleicons.org\/(.+)\/000\/fff/g,
`https://raw.githubusercontent.com/simple-icons/simple-icons/${LINKS_BRANCH}/icons/$1.svg`,
)
// Replace all GitHub blockquotes with regular markdown
// Reference: https://github.com/orgs/community/discussions/16925
- .replace(
- /\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\](?!\()/g,
- function (str, $0) {
- const capital = $0.substr(0, 1);
- const body = $0.substr(1).toLowerCase();
+ .replaceAll(
+ /\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)](?!\()/g,
+ function (string_, $0) {
+ const capital = $0.slice(0, 1);
+ const body = $0.slice(1).toLowerCase();
return `**${capital + body}**`;
},
),
diff --git a/scripts/release/update-cdn-urls.js b/scripts/release/update-cdn-urls.js
old mode 100644
new mode 100755
index f6be9e9ba611..38a1f76ea7c5
--- a/scripts/release/update-cdn-urls.js
+++ b/scripts/release/update-cdn-urls.js
@@ -1,35 +1,36 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Updates the CDN URLs in the README.md to match the major version in the
* NPM package manifest. Does nothing if the README.md is already up-to-date.
*/
-import process from 'node:process';
import fs from 'node:fs/promises';
import path from 'node:path';
-import { getDirnameFromImportMeta } from '../../sdk.mjs';
+import process from 'node:process';
+import {getDirnameFromImportMeta} from '../../sdk.mjs';
const __dirname = getDirnameFromImportMeta(import.meta.url);
-const rootDir = path.resolve(__dirname, '..', '..');
-const packageJsonFile = path.resolve(rootDir, 'package.json');
-const readmeFile = path.resolve(rootDir, 'README.md');
+const rootDirectory = path.resolve(__dirname, '..', '..');
+const packageJsonFile = path.resolve(rootDirectory, 'package.json');
+const readmeFile = path.resolve(rootDirectory, 'README.md');
-const getMajorVersion = (semVerVersion) => {
- const majorVersionAsString = semVerVersion.split('.')[0];
- return parseInt(majorVersionAsString);
+const getMajorVersion = (semVersion) => {
+ const majorVersionAsString = semVersion.split('.')[0];
+ return Number.parseInt(majorVersionAsString, 10);
};
const getManifest = async () => {
- const manifestRaw = await fs.readFile(packageJsonFile, 'utf-8');
+ const manifestRaw = await fs.readFile(packageJsonFile, 'utf8');
return JSON.parse(manifestRaw);
};
const updateVersionInReadmeIfNecessary = async (majorVersion) => {
let content = await fs.readFile(readmeFile, 'utf8');
- content = content.replace(
- /simple-icons@v[0-9]+/g,
+ content = content.replaceAll(
+ /simple-icons@v\d+/g,
`simple-icons@v${majorVersion}`,
);
diff --git a/scripts/release/update-sdk-ts-defs.js b/scripts/release/update-sdk-ts-defs.js
old mode 100644
new mode 100755
index c87e87625a82..7d0bc04152ec
--- a/scripts/release/update-sdk-ts-defs.js
+++ b/scripts/release/update-sdk-ts-defs.js
@@ -1,33 +1,34 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Updates the SDK Typescript definitions located in the file sdk.d.ts
* to match the current definitions of functions of sdk.mjs.
*/
-import process from 'node:process';
+import {execSync} from 'node:child_process';
import fs from 'node:fs/promises';
import path from 'node:path';
-import { execSync } from 'node:child_process';
-import { getDirnameFromImportMeta } from '../../sdk.mjs';
+import process from 'node:process';
+import {getDirnameFromImportMeta} from '../../sdk.mjs';
const __dirname = getDirnameFromImportMeta(import.meta.url);
-const rootDir = path.resolve(__dirname, '..', '..');
+const rootDirectory = path.resolve(__dirname, '..', '..');
-const sdkTs = path.resolve(rootDir, 'sdk.d.ts');
-const sdkMts = path.resolve(rootDir, 'sdk.d.mts');
-const sdkMjs = path.resolve(rootDir, 'sdk.mjs');
+const sdkTs = path.resolve(rootDirectory, 'sdk.d.ts');
+const sdkMts = path.resolve(rootDirectory, 'sdk.d.mts');
+const sdkMjs = path.resolve(rootDirectory, 'sdk.mjs');
const generateSdkMts = async () => {
- // remove temporally type definitions imported with comments
+ // Remove temporally type definitions imported with comments
// in sdk.mjs to avoid circular imports
- const originalSdkMjsContent = await fs.readFile(sdkMjs, 'utf-8');
- const tempSdkMjsContent = originalSdkMjsContent
+ const originalSdkMjsContent = await fs.readFile(sdkMjs, 'utf8');
+ const temporarySdkMjsContent = originalSdkMjsContent
.split('\n')
.filter((line) => {
return !line.startsWith(' * @typedef {import("./sdk")');
})
.join('\n');
- await fs.writeFile(sdkMjs, tempSdkMjsContent);
+ await fs.writeFile(sdkMjs, temporarySdkMjsContent);
try {
execSync(
'npx tsc sdk.mjs' +
@@ -41,6 +42,7 @@ const generateSdkMts = async () => {
);
process.exit(1);
}
+
await fs.writeFile(sdkMjs, originalSdkMjsContent);
};
@@ -49,13 +51,15 @@ const generateSdkTs = async () => {
.access(sdkMts)
.then(() => true)
.catch(() => false);
- fileExists && (await fs.unlink(sdkMts));
+ if (fileExists) await fs.unlink(sdkMts);
await generateSdkMts();
- const autogeneratedMsg = '/* The next code is autogenerated from sdk.mjs */';
+ const autogeneratedMessage =
+ '/* The next code is autogenerated from sdk.mjs */';
const newSdkTsContent =
- (await fs.readFile(sdkTs, 'utf-8')).split(autogeneratedMsg)[0] +
- `${autogeneratedMsg}\n\n${await fs.readFile(sdkMts, 'utf-8')}`;
+ // eslint-disable-next-line unicorn/no-await-expression-member
+ (await fs.readFile(sdkTs, 'utf8')).split(autogeneratedMessage)[0] +
+ `${autogeneratedMessage}\n\n${await fs.readFile(sdkMts, 'utf8')}`;
await fs.writeFile(sdkTs, newSdkTsContent);
await fs.unlink(sdkMts);
diff --git a/scripts/release/update-slugs-table.js b/scripts/release/update-slugs-table.js
old mode 100644
new mode 100755
index fffe85f7e0c4..74f61dbaa993
--- a/scripts/release/update-slugs-table.js
+++ b/scripts/release/update-slugs-table.js
@@ -1,22 +1,23 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Generates a MarkDown file that lists every brand name and their slug.
*/
-import { promises as fs } from 'node:fs';
+import fs from 'node:fs/promises';
import path from 'node:path';
-import { fileURLToPath } from 'node:url';
-import { getIconsData, getIconSlug } from '../../sdk.mjs';
+import {fileURLToPath} from 'node:url';
+import {getIconSlug, getIconsData} from '../../sdk.mjs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
-const rootDir = path.resolve(__dirname, '..', '..');
-const slugsFile = path.resolve(rootDir, 'slugs.md');
+const rootDirectory = path.resolve(__dirname, '..', '..');
+const slugsFile = path.resolve(rootDirectory, 'slugs.md');
let content = `
# Simple Icons slugs
@@ -31,4 +32,5 @@ for (const icon of icons) {
const brandSlug = getIconSlug(icon);
content += `| \`${brandName}\` | \`${brandSlug}\` |\n`;
}
+
await fs.writeFile(slugsFile, content);
diff --git a/scripts/release/update-svgs-count.js b/scripts/release/update-svgs-count.js
old mode 100644
new mode 100755
index 05af0fc17a95..b90f7af1c02f
--- a/scripts/release/update-svgs-count.js
+++ b/scripts/release/update-svgs-count.js
@@ -1,3 +1,4 @@
+#!/usr/bin/env node
/**
* @fileoverview
* Replaces the SVG count milestone "Over Free SVG icons..." located
@@ -5,32 +6,33 @@
* more than the previous milestone.
*/
-import process from 'node:process';
import fs from 'node:fs/promises';
import path from 'node:path';
-import { getDirnameFromImportMeta, getIconsData } from '../../sdk.mjs';
+import process from 'node:process';
+import {getDirnameFromImportMeta, getIconsData} from '../../sdk.mjs';
const regexMatcher = /Over\s(\d+)\s/;
const updateRange = 100;
const __dirname = getDirnameFromImportMeta(import.meta.url);
-const rootDir = path.resolve(__dirname, '..', '..');
-const readmeFile = path.resolve(rootDir, 'README.md');
+const rootDirectory = path.resolve(__dirname, '..', '..');
+const readmeFile = path.resolve(rootDirectory, 'README.md');
-const readmeContent = await fs.readFile(readmeFile, 'utf-8');
+const readmeContent = await fs.readFile(readmeFile, 'utf8');
let overNIconsInReadme;
try {
- overNIconsInReadme = parseInt(regexMatcher.exec(readmeContent)[1]);
-} catch (err) {
+ overNIconsInReadme = Number.parseInt(regexMatcher.exec(readmeContent)[1], 10);
+} catch (error) {
console.error(
'Failed to obtain number of SVG icons of current milestone in README:',
- err,
+ error,
);
process.exit(1);
}
-const nIcons = (await getIconsData()).length;
+const iconsData = await getIconsData();
+const nIcons = iconsData.length;
const newNIcons = overNIconsInReadme + updateRange;
if (nIcons > newNIcons) {
diff --git a/scripts/utils.js b/scripts/utils.js
index dfea7d75a4cf..474a4ba4ae20 100644
--- a/scripts/utils.js
+++ b/scripts/utils.js
@@ -1,17 +1,17 @@
-import path from 'node:path';
import fs from 'node:fs/promises';
-import { getDirnameFromImportMeta, getIconDataPath } from '../sdk.mjs';
+import path from 'node:path';
+import {getDirnameFromImportMeta, getIconDataPath} from '../sdk.mjs';
const __dirname = getDirnameFromImportMeta(import.meta.url);
/**
* Get JSON schema data.
- * @param {String} rootDir Path to the root directory of the project.
+ * @param {String} rootDirectory Path to the root directory of the project.
*/
export const getJsonSchemaData = async (
- rootDir = path.resolve(__dirname, '..'),
+ rootDirectory = path.resolve(__dirname, '..'),
) => {
- const jsonSchemaPath = path.resolve(rootDir, '.jsonschema.json');
+ const jsonSchemaPath = path.resolve(rootDirectory, '.jsonschema.json');
const jsonSchemaString = await fs.readFile(jsonSchemaPath, 'utf8');
return JSON.parse(jsonSchemaString);
};
@@ -19,14 +19,14 @@ export const getJsonSchemaData = async (
/**
* Write icons data to _data/simple-icons.json.
* @param {Object} iconsData Icons data object.
- * @param {String} rootDir Path to the root directory of the project.
+ * @param {String} rootDirectory Path to the root directory of the project.
*/
export const writeIconsData = async (
iconsData,
- rootDir = path.resolve(__dirname, '..'),
+ rootDirectory = path.resolve(__dirname, '..'),
) => {
await fs.writeFile(
- getIconDataPath(rootDir),
+ getIconDataPath(rootDirectory),
`${JSON.stringify(iconsData, null, 4)}\n`,
'utf8',
);
diff --git a/sdk.d.ts b/sdk.d.ts
index 517cbd013258..371b69f7d4e6 100644
--- a/sdk.d.ts
+++ b/sdk.d.ts
@@ -3,7 +3,7 @@
* Types for Simple Icons SDK.
*/
-import type { CustomLicense, SPDXLicense } from './types';
+import type {CustomLicense, SPDXLicense} from './types';
/**
* The data for a third-party extension.
@@ -33,14 +33,14 @@ type ThirdPartyExtensionSubject = {
export type Aliases = {
aka?: string[];
dup?: DuplicateAlias[];
- loc?: { [key: string]: string };
+ loc?: Record;
};
type DuplicateAlias = {
title: string;
hex?: string;
guidelines?: string;
- loc?: { [key: string]: string };
+ loc?: Record;
};
/**
@@ -62,8 +62,8 @@ export type IconData = {
/* The next code is autogenerated from sdk.mjs */
-export const URL_REGEX: RegExp;
-export const SVG_PATH_REGEX: RegExp;
+export const URL_REGEX: RegExp; // eslint-disable-line @typescript-eslint/naming-convention
+export const SVG_PATH_REGEX: RegExp; // eslint-disable-line @typescript-eslint/naming-convention
export function getDirnameFromImportMeta(importMetaUrl: string): string;
export function getIconSlug(icon: IconData): string;
export function svgToPath(svg: string): string;
@@ -71,9 +71,9 @@ export function titleToSlug(title: string): string;
export function slugToVariableName(slug: string): string;
export function titleToHtmlFriendly(brandTitle: string): string;
export function htmlFriendlyToTitle(htmlFriendlyTitle: string): string;
-export function getIconDataPath(rootDir?: string): string;
-export function getIconsDataString(rootDir?: string): string;
-export function getIconsData(rootDir?: string): IconData[];
+export function getIconDataPath(rootDirectory?: string): string;
+export function getIconsDataString(rootDirectory?: string): string;
+export function getIconsData(rootDirectory?: string): IconData[];
export function normalizeNewlines(text: string): string;
export function normalizeColor(text: string): string;
export function getThirdPartyExtensions(
diff --git a/sdk.mjs b/sdk.mjs
index 90dfc8449c07..945c58c8b31d 100644
--- a/sdk.mjs
+++ b/sdk.mjs
@@ -3,9 +3,9 @@
* Simple Icons SDK.
*/
-import path from 'node:path';
import fs from 'node:fs/promises';
-import { fileURLToPath } from 'node:url';
+import path from 'node:path';
+import {fileURLToPath} from 'node:url';
/**
* @typedef {import("./sdk").ThirdPartyExtension} ThirdPartyExtension
@@ -26,12 +26,12 @@ const TITLE_TO_SLUG_REPLACEMENTS = {
ŧ: 't',
};
-const TITLE_TO_SLUG_CHARS_REGEX = RegExp(
+const TITLE_TO_SLUG_CHARS_REGEX = new RegExp(
`[${Object.keys(TITLE_TO_SLUG_REPLACEMENTS).join('')}]`,
'g',
);
-const TITLE_TO_SLUG_RANGE_REGEX = /[^a-z0-9]/g;
+const TITLE_TO_SLUG_RANGE_REGEX = /[^a-z\d]/g;
/**
* Regex to validate HTTPs URLs.
@@ -41,7 +41,7 @@ export const URL_REGEX = /^https:\/\/[^\s"']+$/;
/**
* Regex to validate SVG paths.
*/
-export const SVG_PATH_REGEX = /^m[-mzlhvcsqtae0-9,. ]+$/i;
+export const SVG_PATH_REGEX = /^m[-mzlhvcsqtae\d,. ]+$/i;
/**
* Get the directory name where this file is located from `import.meta.url`,
@@ -74,12 +74,12 @@ export const svgToPath = (svg) => svg.split('"', 8)[7];
export const titleToSlug = (title) =>
title
.toLowerCase()
- .replace(
+ .replaceAll(
TITLE_TO_SLUG_CHARS_REGEX,
(char) => TITLE_TO_SLUG_REPLACEMENTS[char],
)
.normalize('NFD')
- .replace(TITLE_TO_SLUG_RANGE_REGEX, '');
+ .replaceAll(TITLE_TO_SLUG_RANGE_REGEX, '');
/**
* Converts a slug into a variable name that can be exported.
@@ -99,12 +99,12 @@ export const slugToVariableName = (slug) => {
*/
export const titleToHtmlFriendly = (brandTitle) =>
brandTitle
- .replace(/&/g, '&')
- .replace(/"/g, '"')
- .replace(//g, '>')
- .replace(/./g, (char) => {
- const charCode = char.charCodeAt(0);
+ .replaceAll('&', '&')
+ .replaceAll('"', '"')
+ .replaceAll('<', '<')
+ .replaceAll('>', '>')
+ .replaceAll(/./g, (char) => {
+ const charCode = char.codePointAt(0);
return charCode > 127 ? `${charCode};` : char;
});
@@ -116,43 +116,45 @@ export const titleToHtmlFriendly = (brandTitle) =>
*/
export const htmlFriendlyToTitle = (htmlFriendlyTitle) =>
htmlFriendlyTitle
- .replace(/([0-9]+);/g, (_, num) => String.fromCodePoint(parseInt(num)))
- .replace(
+ .replaceAll(/(\d+);/g, (_, number_) =>
+ String.fromCodePoint(Number.parseInt(number_, 10)),
+ )
+ .replaceAll(
/&(quot|amp|lt|gt);/g,
- (_, ref) => ({ quot: '"', amp: '&', lt: '<', gt: '>' })[ref],
+ (_, reference) => ({quot: '"', amp: '&', lt: '<', gt: '>'})[reference],
);
/**
* Get path of *_data/simpe-icons.json*.
- * @param {String} rootDir Path to the root directory of the project
+ * @param {String} rootDirectory Path to the root directory of the project
* @returns {String} Path of *_data/simple-icons.json*
*/
export const getIconDataPath = (
- rootDir = getDirnameFromImportMeta(import.meta.url),
+ rootDirectory = getDirnameFromImportMeta(import.meta.url),
) => {
- return path.resolve(rootDir, '_data', 'simple-icons.json');
+ return path.resolve(rootDirectory, '_data', 'simple-icons.json');
};
/**
* Get contents of *_data/simple-icons.json*.
- * @param {String} rootDir Path to the root directory of the project
+ * @param {String} rootDirectory Path to the root directory of the project
* @returns {String} Content of *_data/simple-icons.json*
*/
export const getIconsDataString = (
- rootDir = getDirnameFromImportMeta(import.meta.url),
+ rootDirectory = getDirnameFromImportMeta(import.meta.url),
) => {
- return fs.readFile(getIconDataPath(rootDir), 'utf8');
+ return fs.readFile(getIconDataPath(rootDirectory), 'utf8');
};
/**
* Get icons data as object from *_data/simple-icons.json*.
- * @param {String} rootDir Path to the root directory of the project
+ * @param {String} rootDirectory Path to the root directory of the project
* @returns {IconData[]} Icons data as array from *_data/simple-icons.json*
*/
export const getIconsData = async (
- rootDir = getDirnameFromImportMeta(import.meta.url),
+ rootDirectory = getDirnameFromImportMeta(import.meta.url),
) => {
- const fileContents = await getIconsDataString(rootDir);
+ const fileContents = await getIconsDataString(rootDirectory);
return JSON.parse(fileContents).icons;
};
@@ -162,7 +164,7 @@ export const getIconsData = async (
* @returns {String} The text with Windows newline characters replaced by Unix ones
*/
export const normalizeNewlines = (text) => {
- return text.replace(/\r\n/g, '\n');
+ return text.replaceAll('\r\n', '\n');
};
/**
@@ -173,10 +175,14 @@ export const normalizeNewlines = (text) => {
export const normalizeColor = (text) => {
let color = text.replace('#', '').toUpperCase();
if (color.length < 6) {
- color = [...color.slice(0, 3)].map((x) => x.repeat(2)).join('');
+ color = color
+ .slice(0, 3)
+ .map((x) => x.repeat(2))
+ .join('');
} else if (color.length > 6) {
color = color.slice(0, 6);
}
+
return color;
};
@@ -201,11 +207,11 @@ export const getThirdPartyExtensions = async (
module = module.split('.*<\/title><\/svg>$/;
-const negativeZerosRegexp = /-0(?=[^\.]|[\s\d\w]|$)/g;
+ /^