mirror of
https://github.com/Mibew/simple-icons.git
synced 2024-11-15 09:54:11 +03:00
convert scripts to esm (#6946)
* convert scripts to esm * fix tests * fix tests * fix lints * syncFs to fsSync * named export for fs Co-authored-by: LitoMore <LitoMore@users.noreply.github.com> * fsSync to { promises as fs } * convert update-svgs-count to esm * rename data to icons * fix build script * switch svglintrc file to mjs * use node: protocol * pluralize getIcons Co-authored-by: LitoMore <LitoMore@users.noreply.github.com>
This commit is contained in:
parent
0150cbd986
commit
a930dc57ec
@ -1,11 +1,28 @@
|
|||||||
const fs = require('fs');
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import {
|
||||||
|
getDirnameFromImportMeta,
|
||||||
|
htmlFriendlyToTitle,
|
||||||
|
} from './scripts/utils.js';
|
||||||
|
import svgpath from 'svgpath';
|
||||||
|
import svgPathBbox from 'svg-path-bbox';
|
||||||
|
import parsePath from 'svg-path-segments';
|
||||||
|
|
||||||
const data = require('./_data/simple-icons.json');
|
const __dirname = getDirnameFromImportMeta(import.meta.url);
|
||||||
const { htmlFriendlyToTitle } = require('./scripts/utils.js');
|
const dataFile = path.join(__dirname, '_data', 'simple-icons.json');
|
||||||
const htmlNamedEntities = require('named-html-entities-json');
|
const htmlNamedEntitiesFile = path.join(
|
||||||
const svgpath = require('svgpath');
|
__dirname,
|
||||||
const svgPathBbox = require('svg-path-bbox');
|
'node_modules',
|
||||||
const parsePath = require('svg-path-segments');
|
'named-html-entities-json',
|
||||||
|
'index.json',
|
||||||
|
);
|
||||||
|
const svglintIgnoredFile = path.join(__dirname, '.svglint-ignored.json');
|
||||||
|
|
||||||
|
const data = JSON.parse(fs.readFileSync(dataFile, 'utf8'));
|
||||||
|
const htmlNamedEntities = JSON.parse(
|
||||||
|
fs.readFileSync(htmlNamedEntitiesFile, 'utf8'),
|
||||||
|
);
|
||||||
|
const svglintIgnores = JSON.parse(fs.readFileSync(svglintIgnoredFile, 'utf8'));
|
||||||
|
|
||||||
const svgRegexp =
|
const svgRegexp =
|
||||||
/^<svg( [^\s]*=".*"){3}><title>.*<\/title><path d=".*"\/><\/svg>\n?$/;
|
/^<svg( [^\s]*=".*"){3}><title>.*<\/title><path d=".*"\/><\/svg>\n?$/;
|
||||||
@ -19,7 +36,7 @@ const iconTolerance = 0.001;
|
|||||||
// set env SI_UPDATE_IGNORE to recreate the ignore file
|
// set env SI_UPDATE_IGNORE to recreate the ignore file
|
||||||
const updateIgnoreFile = process.env.SI_UPDATE_IGNORE === 'true';
|
const updateIgnoreFile = process.env.SI_UPDATE_IGNORE === 'true';
|
||||||
const ignoreFile = './.svglint-ignored.json';
|
const ignoreFile = './.svglint-ignored.json';
|
||||||
const iconIgnored = !updateIgnoreFile ? require(ignoreFile) : {};
|
const iconIgnored = !updateIgnoreFile ? svglintIgnores : {};
|
||||||
|
|
||||||
const sortObjectByKey = (obj) => {
|
const sortObjectByKey = (obj) => {
|
||||||
return Object.keys(obj)
|
return Object.keys(obj)
|
||||||
@ -126,7 +143,7 @@ const ignoreIcon = (linterName, path, $) => {
|
|||||||
iconIgnored[linterName][path] = iconName;
|
iconIgnored[linterName][path] = iconName;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
export default {
|
||||||
rules: {
|
rules: {
|
||||||
elm: {
|
elm: {
|
||||||
svg: 1,
|
svg: 1,
|
@ -56,12 +56,12 @@
|
|||||||
"our-lint": "node scripts/lint/ourlint.js",
|
"our-lint": "node scripts/lint/ourlint.js",
|
||||||
"jslint": "prettier --check .",
|
"jslint": "prettier --check .",
|
||||||
"jsonlint": "node scripts/lint/jsonlint.js",
|
"jsonlint": "node scripts/lint/jsonlint.js",
|
||||||
"svglint": "svglint icons/*.svg --ci",
|
"svglint": "svglint icons/*.svg --ci --config .svglintrc.mjs",
|
||||||
"wslint": "editorconfig-checker",
|
"wslint": "editorconfig-checker",
|
||||||
"prepare": "is-ci || husky install",
|
"prepare": "is-ci || husky install",
|
||||||
"prepublishOnly": "npm run build",
|
"prepublishOnly": "npm run build",
|
||||||
"postpublish": "npm run clean",
|
"postpublish": "npm run clean",
|
||||||
"test": "node --experimental-specifier-resolution=node node_modules/uvu/bin.js",
|
"test": "uvu",
|
||||||
"pretest": "npm run prepublishOnly",
|
"pretest": "npm run prepublishOnly",
|
||||||
"posttest": "npm run postpublish",
|
"posttest": "npm run postpublish",
|
||||||
"svgo": "svgo --config svgo.config.js",
|
"svgo": "svgo --config svgo.config.js",
|
||||||
|
@ -7,15 +7,24 @@
|
|||||||
* tree-shakeable
|
* tree-shakeable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs').promises;
|
import { promises as fs } from 'node:fs';
|
||||||
const path = require('path');
|
import path from 'node:path';
|
||||||
const util = require('util');
|
import util from 'node:util';
|
||||||
const { transform: esbuildTransform } = require('esbuild');
|
import { transform as esbuildTransform } from 'esbuild';
|
||||||
|
import {
|
||||||
|
getIconSlug,
|
||||||
|
svgToPath,
|
||||||
|
titleToHtmlFriendly,
|
||||||
|
slugToVariableName,
|
||||||
|
getIconsData,
|
||||||
|
getDirnameFromImportMeta,
|
||||||
|
} from '../utils.js';
|
||||||
|
|
||||||
|
const __dirname = getDirnameFromImportMeta(import.meta.url);
|
||||||
|
|
||||||
const UTF8 = 'utf8';
|
const UTF8 = 'utf8';
|
||||||
|
|
||||||
const rootDir = path.resolve(__dirname, '..', '..');
|
const rootDir = path.resolve(__dirname, '..', '..');
|
||||||
const dataFile = path.resolve(rootDir, '_data', 'simple-icons.json');
|
|
||||||
const indexFile = path.resolve(rootDir, 'index.js');
|
const indexFile = path.resolve(rootDir, 'index.js');
|
||||||
const iconsDir = path.resolve(rootDir, 'icons');
|
const iconsDir = path.resolve(rootDir, 'icons');
|
||||||
const iconsJsFile = path.resolve(rootDir, 'icons.js');
|
const iconsJsFile = path.resolve(rootDir, 'icons.js');
|
||||||
@ -26,15 +35,8 @@ const templatesDir = path.resolve(__dirname, 'templates');
|
|||||||
const indexTemplateFile = path.resolve(templatesDir, 'index.js');
|
const indexTemplateFile = path.resolve(templatesDir, 'index.js');
|
||||||
const iconObjectTemplateFile = path.resolve(templatesDir, 'icon-object.js');
|
const iconObjectTemplateFile = path.resolve(templatesDir, 'icon-object.js');
|
||||||
|
|
||||||
const data = require(dataFile);
|
|
||||||
const {
|
|
||||||
getIconSlug,
|
|
||||||
svgToPath,
|
|
||||||
titleToHtmlFriendly,
|
|
||||||
slugToVariableName,
|
|
||||||
} = require('../utils.js');
|
|
||||||
|
|
||||||
const build = async () => {
|
const build = async () => {
|
||||||
|
const icons = await getIconsData();
|
||||||
const indexTemplate = await fs.readFile(indexTemplateFile, UTF8);
|
const indexTemplate = await fs.readFile(indexTemplateFile, UTF8);
|
||||||
const iconObjectTemplate = await fs.readFile(iconObjectTemplateFile, UTF8);
|
const iconObjectTemplate = await fs.readFile(iconObjectTemplateFile, UTF8);
|
||||||
|
|
||||||
@ -82,16 +84,16 @@ const build = async () => {
|
|||||||
const iconsBarrelMjs = [];
|
const iconsBarrelMjs = [];
|
||||||
const iconsBarrelJs = [];
|
const iconsBarrelJs = [];
|
||||||
const iconsBarrelDts = [];
|
const iconsBarrelDts = [];
|
||||||
const icons = [];
|
const buildIcons = [];
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
data.icons.map(async (icon) => {
|
icons.map(async (icon) => {
|
||||||
const filename = getIconSlug(icon);
|
const filename = getIconSlug(icon);
|
||||||
const svgFilepath = path.resolve(iconsDir, `${filename}.svg`);
|
const svgFilepath = path.resolve(iconsDir, `${filename}.svg`);
|
||||||
icon.svg = (await fs.readFile(svgFilepath, UTF8)).replace(/\r?\n/, '');
|
icon.svg = (await fs.readFile(svgFilepath, UTF8)).replace(/\r?\n/, '');
|
||||||
icon.path = svgToPath(icon.svg);
|
icon.path = svgToPath(icon.svg);
|
||||||
icon.slug = filename;
|
icon.slug = filename;
|
||||||
icons.push(icon);
|
buildIcons.push(icon);
|
||||||
|
|
||||||
const iconObject = iconToObject(icon);
|
const iconObject = iconToObject(icon);
|
||||||
|
|
||||||
@ -126,7 +128,7 @@ const build = async () => {
|
|||||||
// write our generic index.js
|
// write our generic index.js
|
||||||
const rawIndexJs = util.format(
|
const rawIndexJs = util.format(
|
||||||
indexTemplate,
|
indexTemplate,
|
||||||
icons.map(iconToKeyValue).join(','),
|
buildIcons.map(iconToKeyValue).join(','),
|
||||||
);
|
);
|
||||||
await writeJs(indexFile, rawIndexJs);
|
await writeJs(indexFile, rawIndexJs);
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* icon SVG filename to standard output.
|
* icon SVG filename to standard output.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { titleToSlug } = require('./utils.js');
|
import { titleToSlug } from './utils.js';
|
||||||
|
|
||||||
if (process.argv.length < 3) {
|
if (process.argv.length < 3) {
|
||||||
console.error('Provide a brand name as argument');
|
console.error('Provide a brand name as argument');
|
||||||
|
@ -4,23 +4,30 @@
|
|||||||
* CLI tool to run jsonschema on the simple-icons.json data file.
|
* CLI tool to run jsonschema on the simple-icons.json data file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const path = require('path');
|
import { promises as fs } from 'node:fs';
|
||||||
const { Validator } = require('jsonschema');
|
import path from 'node:path';
|
||||||
|
import { Validator } from 'jsonschema';
|
||||||
|
import { getDirnameFromImportMeta, getIconsData } from '../utils.js';
|
||||||
|
|
||||||
|
const __dirname = getDirnameFromImportMeta(import.meta.url);
|
||||||
|
|
||||||
const rootDir = path.resolve(__dirname, '..', '..');
|
const rootDir = path.resolve(__dirname, '..', '..');
|
||||||
const schemaFile = path.resolve(rootDir, '.jsonschema.json');
|
const schemaFile = path.resolve(rootDir, '.jsonschema.json');
|
||||||
const dataFile = path.resolve(rootDir, '_data', 'simple-icons.json');
|
|
||||||
|
|
||||||
const schema = require(schemaFile);
|
(async () => {
|
||||||
const data = require(dataFile);
|
const icons = await getIconsData();
|
||||||
|
const schema = JSON.parse(await fs.readFile(schemaFile, 'utf8'));
|
||||||
|
|
||||||
const validator = new Validator();
|
const validator = new Validator();
|
||||||
const result = validator.validate(data, schema);
|
const result = validator.validate({ icons }, schema);
|
||||||
if (result.errors.length > 0) {
|
if (result.errors.length > 0) {
|
||||||
result.errors.forEach((error) => {
|
result.errors.forEach((error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.error(`Found ${result.errors.length} error(s) in simple-icons.json`);
|
console.error(
|
||||||
process.exit(1);
|
`Found ${result.errors.length} error(s) in simple-icons.json`,
|
||||||
}
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
@ -5,16 +5,8 @@
|
|||||||
* linters (e.g. jsonlint/svglint).
|
* linters (e.g. jsonlint/svglint).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
import fakeDiff from 'fake-diff';
|
||||||
const path = require('path');
|
import { getIconsDataString } from '../utils.js';
|
||||||
|
|
||||||
const fakeDiff = require('fake-diff');
|
|
||||||
|
|
||||||
const UTF8 = 'utf8';
|
|
||||||
|
|
||||||
const rootDir = path.resolve(__dirname, '..', '..');
|
|
||||||
const dataFile = path.resolve(rootDir, '_data', 'simple-icons.json');
|
|
||||||
const data = require(dataFile);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains our tests so they can be isolated from each other.
|
* Contains our tests so they can be isolated from each other.
|
||||||
@ -22,7 +14,7 @@ const data = require(dataFile);
|
|||||||
*/
|
*/
|
||||||
const TESTS = {
|
const TESTS = {
|
||||||
/* Tests whether our icons are in alphabetical order */
|
/* Tests whether our icons are in alphabetical order */
|
||||||
alphabetical: () => {
|
alphabetical: (data) => {
|
||||||
const collector = (invalidEntries, icon, index, array) => {
|
const collector = (invalidEntries, icon, index, array) => {
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
const prev = array[index - 1];
|
const prev = array[index - 1];
|
||||||
@ -54,22 +46,30 @@ const TESTS = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/* Check the formatting of the data file */
|
/* Check the formatting of the data file */
|
||||||
prettified: () => {
|
prettified: async (data, dataString) => {
|
||||||
const dataString = fs.readFileSync(dataFile, UTF8).replace(/\r\n/g, '\n');
|
const normalizedDataString = dataString.replace(/\r\n/g, '\n');
|
||||||
const dataPretty = `${JSON.stringify(data, null, ' ')}\n`;
|
const dataPretty = `${JSON.stringify(data, null, ' ')}\n`;
|
||||||
if (dataString !== dataPretty) {
|
|
||||||
const dataDiff = fakeDiff(dataString, dataPretty);
|
if (normalizedDataString !== dataPretty) {
|
||||||
|
const dataDiff = fakeDiff(normalizedDataString, dataPretty);
|
||||||
return `Data file is formatted incorrectly:\n\n${dataDiff}`;
|
return `Data file is formatted incorrectly:\n\n${dataDiff}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// execute all tests and log all errors
|
// execute all tests and log all errors
|
||||||
const errors = Object.keys(TESTS)
|
(async () => {
|
||||||
.map((k) => TESTS[k]())
|
const dataString = await getIconsDataString();
|
||||||
.filter(Boolean);
|
const data = JSON.parse(dataString);
|
||||||
|
|
||||||
if (errors.length > 0) {
|
const errors = (
|
||||||
errors.forEach((error) => console.error(`\u001b[31m${error}\u001b[0m`));
|
await Promise.all(
|
||||||
process.exit(1);
|
Object.keys(TESTS).map((test) => TESTS[test](data, dataString)),
|
||||||
}
|
)
|
||||||
|
).filter(Boolean);
|
||||||
|
|
||||||
|
if (errors.length > 0) {
|
||||||
|
errors.forEach((error) => console.error(`\u001b[31m${error}\u001b[0m`));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
3
scripts/package.json
Normal file
3
scripts/package.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
@ -4,8 +4,11 @@
|
|||||||
* Updates the version of this package to the CLI specified version.
|
* Updates the version of this package to the CLI specified version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
import fs from 'node:fs';
|
||||||
const path = require('path');
|
import path from 'node:path';
|
||||||
|
import { getDirnameFromImportMeta } from '../utils.js';
|
||||||
|
|
||||||
|
const __dirname = getDirnameFromImportMeta(import.meta.url);
|
||||||
|
|
||||||
const rootDir = path.resolve(__dirname, '..', '..');
|
const rootDir = path.resolve(__dirname, '..', '..');
|
||||||
const packageJsonFile = path.resolve(rootDir, 'package.json');
|
const packageJsonFile = path.resolve(rootDir, 'package.json');
|
||||||
|
@ -5,8 +5,11 @@
|
|||||||
* NPM package manifest. Does nothing if the README.md is already up-to-date.
|
* NPM package manifest. Does nothing if the README.md is already up-to-date.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
import fs from 'node:fs';
|
||||||
const path = require('path');
|
import path from 'node:path';
|
||||||
|
import { getDirnameFromImportMeta } from '../utils.js';
|
||||||
|
|
||||||
|
const __dirname = getDirnameFromImportMeta(import.meta.url);
|
||||||
|
|
||||||
const rootDir = path.resolve(__dirname, '..', '..');
|
const rootDir = path.resolve(__dirname, '..', '..');
|
||||||
const packageJsonFile = path.resolve(rootDir, 'package.json');
|
const packageJsonFile = path.resolve(rootDir, 'package.json');
|
||||||
|
@ -4,16 +4,17 @@
|
|||||||
* Generates a MarkDown file that lists every brand name and their slug.
|
* Generates a MarkDown file that lists every brand name and their slug.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const fs = require('fs');
|
import { promises as fs } from 'node:fs';
|
||||||
const path = require('path');
|
import path from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
import { getIconsData, getIconSlug } from '../utils.js';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
const rootDir = path.resolve(__dirname, '..', '..');
|
const rootDir = path.resolve(__dirname, '..', '..');
|
||||||
const dataFile = path.resolve(rootDir, '_data', 'simple-icons.json');
|
|
||||||
const slugsFile = path.resolve(rootDir, 'slugs.md');
|
const slugsFile = path.resolve(rootDir, 'slugs.md');
|
||||||
|
|
||||||
const data = require(dataFile);
|
|
||||||
const { getIconSlug } = require('../utils.js');
|
|
||||||
|
|
||||||
let content = `<!--
|
let content = `<!--
|
||||||
This file is automatically generated. If you want to change something, please
|
This file is automatically generated. If you want to change something, please
|
||||||
update the script at '${path.relative(rootDir, __filename)}'.
|
update the script at '${path.relative(rootDir, __filename)}'.
|
||||||
@ -25,10 +26,14 @@ update the script at '${path.relative(rootDir, __filename)}'.
|
|||||||
| :--- | :--- |
|
| :--- | :--- |
|
||||||
`;
|
`;
|
||||||
|
|
||||||
data.icons.forEach((icon) => {
|
(async () => {
|
||||||
const brandName = icon.title;
|
const icons = await getIconsData();
|
||||||
const brandSlug = getIconSlug(icon);
|
|
||||||
content += `| \`${brandName}\` | \`${brandSlug}\` |\n`;
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.writeFileSync(slugsFile, content);
|
icons.forEach((icon) => {
|
||||||
|
const brandName = icon.title;
|
||||||
|
const brandSlug = getIconSlug(icon);
|
||||||
|
content += `| \`${brandName}\` | \`${brandSlug}\` |\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
await fs.writeFile(slugsFile, content);
|
||||||
|
})();
|
||||||
|
@ -5,34 +5,39 @@
|
|||||||
* at README every time the number of current icons is more than `updateRange`
|
* at README every time the number of current icons is more than `updateRange`
|
||||||
* more than the previous milestone.
|
* more than the previous milestone.
|
||||||
*/
|
*/
|
||||||
|
import { promises as fs } from 'node:fs';
|
||||||
const fs = require('fs');
|
import path from 'node:path';
|
||||||
const path = require('path');
|
import { getDirnameFromImportMeta, getIconsData } from '../utils.js';
|
||||||
|
|
||||||
const regexMatcher = /Over\s(\d+)\s/;
|
const regexMatcher = /Over\s(\d+)\s/;
|
||||||
const updateRange = 100;
|
const updateRange = 100;
|
||||||
|
|
||||||
|
const __dirname = getDirnameFromImportMeta(import.meta.url);
|
||||||
|
|
||||||
const rootDir = path.resolve(__dirname, '..', '..');
|
const rootDir = path.resolve(__dirname, '..', '..');
|
||||||
const dataFile = path.resolve(rootDir, '_data', 'simple-icons.json');
|
|
||||||
const readmeFile = path.resolve(rootDir, 'README.md');
|
const readmeFile = path.resolve(rootDir, 'README.md');
|
||||||
const readmeContent = fs.readFileSync(readmeFile, 'utf-8');
|
|
||||||
|
|
||||||
let overNIconsInReadme;
|
(async () => {
|
||||||
try {
|
const readmeContent = await fs.readFile(readmeFile, 'utf-8');
|
||||||
overNIconsInReadme = parseInt(regexMatcher.exec(readmeContent)[1]);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(
|
|
||||||
'Failed to obtain number of SVG icons of current milestone in README:',
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const nIcons = require(dataFile).icons.length,
|
let overNIconsInReadme;
|
||||||
newNIcons = overNIconsInReadme + updateRange;
|
try {
|
||||||
if (nIcons <= newNIcons) {
|
overNIconsInReadme = parseInt(regexMatcher.exec(readmeContent)[1]);
|
||||||
process.exit(0);
|
} catch (err) {
|
||||||
}
|
console.error(
|
||||||
|
'Failed to obtain number of SVG icons of current milestone in README:',
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
const newContent = readmeContent.replace(regexMatcher, `Over ${newNIcons} `);
|
const nIcons = (await getIconsData()).length;
|
||||||
fs.writeFileSync(readmeFile, newContent);
|
const newNIcons = overNIconsInReadme + updateRange;
|
||||||
|
|
||||||
|
if (nIcons <= newNIcons) {
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newContent = readmeContent.replace(regexMatcher, `Over ${newNIcons} `);
|
||||||
|
await fs.writeFile(readmeFile, newContent);
|
||||||
|
})();
|
||||||
|
163
scripts/utils.js
163
scripts/utils.js
@ -3,76 +3,103 @@
|
|||||||
* Some common utilities for scripts.
|
* Some common utilities for scripts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = {
|
import path from 'node:path';
|
||||||
/**
|
import { promises as fs } from 'node:fs';
|
||||||
* Get the slug/filename for an icon.
|
import { fileURLToPath } from 'node:url';
|
||||||
* @param {Object} icon The icon data as it appears in _data/simple-icons.json
|
|
||||||
*/
|
|
||||||
getIconSlug: (icon) => icon.slug || module.exports.titleToSlug(icon.title),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the path from an icon SVG content.
|
* Get the slug/filename for an icon.
|
||||||
* @param {Object} svg The icon SVG content
|
* @param {Object} icon The icon data as it appears in _data/simple-icons.json
|
||||||
**/
|
*/
|
||||||
svgToPath: (svg) => svg.match(/<path\s+d="([^"]*)/)[1],
|
export const getIconSlug = (icon) => icon.slug || titleToSlug(icon.title);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a brand title into a slug/filename.
|
* Extract the path from an icon SVG content.
|
||||||
* @param {String} title The title to convert
|
* @param {Object} svg The icon SVG content
|
||||||
*/
|
**/
|
||||||
titleToSlug: (title) =>
|
export const svgToPath = (svg) => svg.match(/<path\s+d="([^"]*)/)[1];
|
||||||
title
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/\+/g, 'plus')
|
|
||||||
.replace(/\./g, 'dot')
|
|
||||||
.replace(/&/g, 'and')
|
|
||||||
.replace(/đ/g, 'd')
|
|
||||||
.replace(/ħ/g, 'h')
|
|
||||||
.replace(/ı/g, 'i')
|
|
||||||
.replace(/ĸ/g, 'k')
|
|
||||||
.replace(/ŀ/g, 'l')
|
|
||||||
.replace(/ł/g, 'l')
|
|
||||||
.replace(/ß/g, 'ss')
|
|
||||||
.replace(/ŧ/g, 't')
|
|
||||||
.normalize('NFD')
|
|
||||||
.replace(/[^a-z0-9]/g, ''),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a brand title in HTML/SVG friendly format into a brand title (as
|
* Converts a brand title into a slug/filename.
|
||||||
* it is seen in simple-icons.json)
|
* @param {String} title The title to convert
|
||||||
* @param {String} htmlFriendlyTitle The title to convert
|
*/
|
||||||
*/
|
export const titleToSlug = (title) =>
|
||||||
htmlFriendlyToTitle: (htmlFriendlyTitle) =>
|
title
|
||||||
htmlFriendlyTitle
|
.toLowerCase()
|
||||||
.replace(/&#([0-9]+);/g, (_, num) => String.fromCharCode(parseInt(num)))
|
.replace(/\+/g, 'plus')
|
||||||
.replace(
|
.replace(/\./g, 'dot')
|
||||||
/&(quot|amp|lt|gt);/g,
|
.replace(/&/g, 'and')
|
||||||
(_, ref) => ({ quot: '"', amp: '&', lt: '<', gt: '>' }[ref]),
|
.replace(/đ/g, 'd')
|
||||||
),
|
.replace(/ħ/g, 'h')
|
||||||
|
.replace(/ı/g, 'i')
|
||||||
|
.replace(/ĸ/g, 'k')
|
||||||
|
.replace(/ŀ/g, 'l')
|
||||||
|
.replace(/ł/g, 'l')
|
||||||
|
.replace(/ß/g, 'ss')
|
||||||
|
.replace(/ŧ/g, 't')
|
||||||
|
.normalize('NFD')
|
||||||
|
.replace(/[^a-z0-9]/g, '');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a slug into a variable name that can be exported.
|
* Converts a slug into a variable name that can be exported.
|
||||||
* @param {String} slug The slug to convert
|
* @param {String} slug The slug to convert
|
||||||
*/
|
*/
|
||||||
slugToVariableName: (slug) => {
|
export const slugToVariableName = (slug) => {
|
||||||
const slugFirstLetter = slug[0].toUpperCase();
|
const slugFirstLetter = slug[0].toUpperCase();
|
||||||
const slugRest = slug.slice(1);
|
const slugRest = slug.slice(1);
|
||||||
return `si${slugFirstLetter}${slugRest}`;
|
return `si${slugFirstLetter}${slugRest}`;
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a brand title (as it is seen in simple-icons.json) into a brand
|
|
||||||
* title in HTML/SVG friendly format.
|
|
||||||
* @param {String} brandTitle The title to convert
|
|
||||||
*/
|
|
||||||
titleToHtmlFriendly: (brandTitle) =>
|
|
||||||
brandTitle
|
|
||||||
.replace(/&/g, '&')
|
|
||||||
.replace(/"/g, '"')
|
|
||||||
.replace(/</g, '<')
|
|
||||||
.replace(/>/g, '>')
|
|
||||||
.replace(/./g, (char) => {
|
|
||||||
const charCode = char.charCodeAt(0);
|
|
||||||
return charCode > 127 ? `&#${charCode};` : char;
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a brand title (as it is seen in simple-icons.json) into a brand
|
||||||
|
* title in HTML/SVG friendly format.
|
||||||
|
* @param {String} brandTitle The title to convert
|
||||||
|
*/
|
||||||
|
export const titleToHtmlFriendly = (brandTitle) =>
|
||||||
|
brandTitle
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/./g, (char) => {
|
||||||
|
const charCode = char.charCodeAt(0);
|
||||||
|
return charCode > 127 ? `&#${charCode};` : char;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a brand title in HTML/SVG friendly format into a brand title (as
|
||||||
|
* it is seen in simple-icons.json)
|
||||||
|
* @param {String} htmlFriendlyTitle The title to convert
|
||||||
|
*/
|
||||||
|
export const htmlFriendlyToTitle = (htmlFriendlyTitle) =>
|
||||||
|
htmlFriendlyTitle
|
||||||
|
.replace(/&#([0-9]+);/g, (_, num) => String.fromCharCode(parseInt(num)))
|
||||||
|
.replace(
|
||||||
|
/&(quot|amp|lt|gt);/g,
|
||||||
|
(_, ref) => ({ quot: '"', amp: '&', lt: '<', gt: '>' }[ref]),
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get contents of _data/simple-icons.json.
|
||||||
|
*/
|
||||||
|
export const getIconsDataString = () => {
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const rootDir = path.resolve(__dirname, '..');
|
||||||
|
const iconDataPath = path.resolve(rootDir, '_data', 'simple-icons.json');
|
||||||
|
return fs.readFile(iconDataPath, 'utf8');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get icon data as object from _data/simple-icons.json.
|
||||||
|
*/
|
||||||
|
export const getIconsData = async () => {
|
||||||
|
const fileContents = await getIconsDataString();
|
||||||
|
return JSON.parse(fileContents).icons;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the directory name from import.meta.url.
|
||||||
|
* @param {String} importMetaUrl import.meta.url
|
||||||
|
*/
|
||||||
|
export const getDirnameFromImportMeta = (importMetaUrl) =>
|
||||||
|
path.dirname(fileURLToPath(importMetaUrl));
|
||||||
|
19
tests/icons-cjs.test.js
Normal file
19
tests/icons-cjs.test.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { exec } from 'uvu';
|
||||||
|
import { testIcon } from './test-icon.js';
|
||||||
|
import { getIconSlug, getIconsData } from '../scripts/utils.js';
|
||||||
|
(async () => {
|
||||||
|
console.warn = () => {};
|
||||||
|
|
||||||
|
const icons = await getIconsData();
|
||||||
|
|
||||||
|
const tests = icons.map(async (icon) => {
|
||||||
|
const slug = getIconSlug(icon);
|
||||||
|
const { default: subject } = await import(`../icons/${slug}.js`);
|
||||||
|
|
||||||
|
testIcon(icon, subject, slug);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(tests);
|
||||||
|
|
||||||
|
exec();
|
||||||
|
})();
|
22
tests/icons-esm.test.js
Normal file
22
tests/icons-esm.test.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import {
|
||||||
|
getIconsData,
|
||||||
|
getIconSlug,
|
||||||
|
slugToVariableName,
|
||||||
|
} from '../scripts/utils.js';
|
||||||
|
import * as simpleIcons from '../icons.mjs';
|
||||||
|
import { testIcon } from './test-icon.js';
|
||||||
|
import { exec } from 'uvu';
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const icons = await getIconsData();
|
||||||
|
|
||||||
|
icons.map((icon) => {
|
||||||
|
const slug = getIconSlug(icon);
|
||||||
|
const variableName = slugToVariableName(slug);
|
||||||
|
const subject = simpleIcons[variableName];
|
||||||
|
|
||||||
|
testIcon(icon, subject, slug);
|
||||||
|
});
|
||||||
|
|
||||||
|
exec();
|
||||||
|
})();
|
@ -1,12 +0,0 @@
|
|||||||
const { icons } = require('../_data/simple-icons.json');
|
|
||||||
const { getIconSlug } = require('../scripts/utils.js');
|
|
||||||
const testIcon = require('./test-icon.js');
|
|
||||||
|
|
||||||
console.warn = () => {};
|
|
||||||
|
|
||||||
icons.forEach((icon) => {
|
|
||||||
const slug = getIconSlug(icon);
|
|
||||||
const subject = require(`../icons/${slug}.js`);
|
|
||||||
|
|
||||||
testIcon(icon, subject, slug);
|
|
||||||
});
|
|
@ -1,14 +0,0 @@
|
|||||||
import simpleIconsData from '../_data/simple-icons.json';
|
|
||||||
import utils from '../scripts/utils.js';
|
|
||||||
import * as simpleIcons from '../icons.mjs';
|
|
||||||
import testIcon from './test-icon.js';
|
|
||||||
|
|
||||||
const { getIconSlug, slugToVariableName } = utils;
|
|
||||||
|
|
||||||
simpleIconsData.icons.forEach((icon) => {
|
|
||||||
const slug = getIconSlug(icon);
|
|
||||||
const variableName = slugToVariableName(slug);
|
|
||||||
const subject = simpleIcons[variableName];
|
|
||||||
|
|
||||||
testIcon(icon, subject, slug);
|
|
||||||
});
|
|
@ -1,27 +1,32 @@
|
|||||||
const { icons } = require('../_data/simple-icons.json');
|
import simpleIcons from '../index.js';
|
||||||
const simpleIcons = require('../index.js');
|
import { getIconSlug, getIconsData } from '../scripts/utils.js';
|
||||||
const { getIconSlug } = require('../scripts/utils');
|
import { test, exec } from 'uvu';
|
||||||
const { test } = require('uvu');
|
import * as assert from 'uvu/assert';
|
||||||
const assert = require('uvu/assert');
|
|
||||||
|
|
||||||
icons.forEach((icon) => {
|
(async () => {
|
||||||
const slug = getIconSlug(icon);
|
const icons = await getIconsData();
|
||||||
|
|
||||||
test(`'Get' ${icon.title} by its slug`, () => {
|
icons.forEach((icon) => {
|
||||||
const found = simpleIcons.Get(slug);
|
const slug = getIconSlug(icon);
|
||||||
assert.ok(found);
|
|
||||||
assert.is(found.title, icon.title);
|
test(`'Get' ${icon.title} by its slug`, () => {
|
||||||
assert.is(found.hex, icon.hex);
|
const found = simpleIcons.Get(slug);
|
||||||
assert.is(found.source, icon.source);
|
assert.ok(found);
|
||||||
|
assert.is(found.title, icon.title);
|
||||||
|
assert.is(found.hex, icon.hex);
|
||||||
|
assert.is(found.source, icon.source);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
test(`Iterating over simpleIcons only exposes icons`, () => {
|
test(`Iterating over simpleIcons only exposes icons`, () => {
|
||||||
const iconArray = Object.values(simpleIcons);
|
const iconArray = Object.values(simpleIcons);
|
||||||
for (let icon of iconArray) {
|
for (let icon of iconArray) {
|
||||||
assert.ok(icon);
|
assert.ok(icon);
|
||||||
assert.type(icon, 'object');
|
assert.type(icon, 'object');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test.run();
|
test.run();
|
||||||
|
|
||||||
|
exec();
|
||||||
|
})();
|
||||||
|
3
tests/package.json
Normal file
3
tests/package.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
const fs = require('fs');
|
import fs from 'node:fs';
|
||||||
const path = require('path');
|
import path from 'node:path';
|
||||||
|
import { suite } from 'uvu';
|
||||||
|
import * as assert from 'uvu/assert';
|
||||||
|
|
||||||
const iconsDir = path.resolve(process.cwd(), 'icons');
|
const iconsDir = path.resolve(process.cwd(), 'icons');
|
||||||
const { suite } = require('uvu');
|
|
||||||
const assert = require('uvu/assert');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if icon data matches a subject icon.
|
* Checks if icon data matches a subject icon.
|
||||||
@ -11,7 +11,7 @@ const assert = require('uvu/assert');
|
|||||||
* @param {import('..').SimpleIcon} subject Icon to check against icon data
|
* @param {import('..').SimpleIcon} subject Icon to check against icon data
|
||||||
* @param {String} slug Icon data slug
|
* @param {String} slug Icon data slug
|
||||||
*/
|
*/
|
||||||
const testIcon = (icon, subject, slug) => {
|
export const testIcon = (icon, subject, slug) => {
|
||||||
const test = suite(icon.title);
|
const test = suite(icon.title);
|
||||||
const svgPath = path.resolve(iconsDir, `${slug}.svg`);
|
const svgPath = path.resolve(iconsDir, `${slug}.svg`);
|
||||||
|
|
||||||
@ -69,5 +69,3 @@ const testIcon = (icon, subject, slug) => {
|
|||||||
|
|
||||||
test.run();
|
test.run();
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = testIcon;
|
|
||||||
|
Loading…
Reference in New Issue
Block a user