Setup prettier (#6758)

* Add prettier as a dependency

* Add format command and configure prettier

I opted for single quotes to be in line with other simple-icons projects

I ignore the data file because changing its formatting is quite a bit of
trouble for all open PRs.

* Run prettier

* Replace all functions by arrow functions

* Move prettier configuration to config file

Move it to a file so editors (and other software) can pick up on the
configuration. I went with .js because (a) it allows for comments and
(2) it seems most of the config files are in JavaScript already.

* Add prettier --check when running npm run lint (This adds it to the CI as well)

* Add husky and format changes before committing

* Use object destructuring for imports consistently

* Add shebang and fileoverview to jsonlint.js
This commit is contained in:
Eric Cornelissen 2021-10-25 21:13:10 +02:00 committed by GitHub
parent 07c9ba1b54
commit e0df400494
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1000 additions and 796 deletions

View File

@ -41,7 +41,7 @@ body:
This is an open source project and we welcome contributions. Do you want to This is an open source project and we welcome contributions. Do you want to
work on this issue? work on this issue?
options: options:
- "Yes" - Yes
- "No" - No
validations: validations:
required: true required: true

View File

@ -1,6 +1,6 @@
name: Icon removal name: Icon removal
description: Report an icon for removal description: Report an icon for removal
title: "Remove: " title: 'Remove: '
labels: [removal request] labels: [removal request]
body: body:
@ -18,7 +18,7 @@ body:
- type: input - type: input
attributes: attributes:
label: Brand Name label: Brand Name
placeholder: "Example: Simple Icons" placeholder: 'Example: Simple Icons'
validations: validations:
required: true required: true

View File

@ -1,6 +1,6 @@
name: Icon request name: Icon request
description: Request a new icon for Simple Icons description: Request a new icon for Simple Icons
title: "Request: " title: 'Request: '
labels: [new icon] labels: [new icon]
body: body:
@ -25,7 +25,7 @@ body:
- type: input - type: input
attributes: attributes:
label: Brand Name label: Brand Name
placeholder: "Example: Simple Icons" placeholder: 'Example: Simple Icons'
validations: validations:
required: true required: true
@ -35,7 +35,7 @@ body:
description: >- description: >-
For non-web brands you can add a relevant link. You can put "None" if you don't For non-web brands you can add a relevant link. You can put "None" if you don't
think there's a website. think there's a website.
placeholder: "Example: https://simpleicons.org" placeholder: 'Example: https://simpleicons.org'
validations: validations:
required: true required: true
@ -50,7 +50,7 @@ body:
[alexa rank]: https://www.alexa.com/siteinfo [alexa rank]: https://www.alexa.com/siteinfo
placeholder: "Example: The Alexa rank is 249,089. See https://www.alexa.com/siteinfo/simpleicons.org" placeholder: 'Example: The Alexa rank is 249,089. See https://www.alexa.com/siteinfo/simpleicons.org'
validations: validations:
required: true required: true
@ -75,7 +75,7 @@ body:
- Are there multiple options for the logo and/or color? - Are there multiple options for the logo and/or color?
- Is the icon released under a license? - Is the icon released under a license?
- If you think the brand might not be accepted, why do you think it should be considered? - If you think the brand might not be accepted, why do you think it should be considered?
placeholder: "Example: There are two variants of this icon..." placeholder: 'Example: There are two variants of this icon...'
- type: dropdown - type: dropdown
attributes: attributes:
@ -84,7 +84,7 @@ body:
This is an open source project and we welcome contributions. Do you want to This is an open source project and we welcome contributions. Do you want to
add this icon? add this icon?
options: options:
- "Yes" - Yes
- "No" - No
validations: validations:
required: true required: true

View File

@ -1,6 +1,6 @@
name: Icon update name: Icon update
description: Help us improve by reporting outdated icons description: Help us improve by reporting outdated icons
title: "Update: " title: 'Update: '
labels: [icon outdated] labels: [icon outdated]
body: body:
@ -18,7 +18,7 @@ body:
- type: input - type: input
attributes: attributes:
label: Brand Name label: Brand Name
placeholder: "Example: Simple Icons" placeholder: 'Example: Simple Icons'
validations: validations:
required: true required: true
@ -42,7 +42,7 @@ body:
Is there anything else we should know about the brand? Remember that not everyone knows the brand as well as you do. For example: Is there anything else we should know about the brand? Remember that not everyone knows the brand as well as you do. For example:
- Are there multiple options for the logo and/or color? - Are there multiple options for the logo and/or color?
- Is the icon released under a license? - Is the icon released under a license?
placeholder: "Example: There are two variants of this icon..." placeholder: 'Example: There are two variants of this icon...'
- type: dropdown - type: dropdown
attributes: attributes:
@ -51,7 +51,7 @@ body:
This is an open source project and we welcome contributions. Do you want to This is an open source project and we welcome contributions. Do you want to
update this icon? update this icon?
options: options:
- "Yes" - Yes
- "No" - No
validations: validations:
required: true required: true

View File

@ -34,7 +34,7 @@ body:
- type: input - type: input
attributes: attributes:
label: Package Version label: Package Version
placeholder: "Example: 5.11.0" placeholder: 'Example: 5.11.0'
validations: validations:
required: true required: true
@ -59,6 +59,6 @@ body:
- For bugs: "Steps to reproduce" and "Expected behavior" - For bugs: "Steps to reproduce" and "Expected behavior"
- For feature requests: An example of a use case - For feature requests: An example of a use case
- For performance: An example where performance is poor - For performance: An example where performance is poor
placeholder: "Example: The NPM package does not work for my use case..." placeholder: 'Example: The NPM package does not work for my use case...'
validations: validations:
required: true required: true

View File

@ -1,19 +1,19 @@
{ {
extends: [ extends: [
"config:base", 'config:base',
// Make sure we get a single PR combining all updates // Make sure we get a single PR combining all updates
"group:all", 'group:all',
], ],
// Disable dependency dashboard // Disable dependency dashboard
dependencyDashboard: false, dependencyDashboard: false,
// Use our labelling system // Use our labelling system
labels: ["dependencies"], labels: ['dependencies'],
// Schedule the PRs to interleave with our release schedule // Schedule the PRs to interleave with our release schedule
schedule: "on the 2nd and 4th day instance on sunday after 11pm", schedule: 'on the 2nd and 4th day instance on sunday after 11pm',
// We generally always want the major version // We generally always want the major version
separateMajorMinor: false, separateMajorMinor: false,

View File

@ -5,7 +5,7 @@ on:
workflow_dispatch: workflow_dispatch:
schedule: schedule:
# "At 00:00 on Sunday" (https://crontab.guru/once-a-week) # "At 00:00 on Sunday" (https://crontab.guru/once-a-week)
- cron: "0 0 * * 0" - cron: '0 0 * * 0'
# This Workflow can be triggered manually through the GitHub UI or API. For the # This Workflow can be triggered manually through the GitHub UI or API. For the
# API use the following request: # API use the following request:
@ -51,6 +51,6 @@ jobs:
uses: stefanzweifel/git-auto-commit-action@v4.12.0 uses: stefanzweifel/git-auto-commit-action@v4.12.0
with: with:
commit_message: version bump commit_message: version bump
commit_user_name: "github-actions[bot]" commit_user_name: 'github-actions[bot]'
commit_user_email: "github-actions[bot]@users.noreply.github.com" commit_user_email: 'github-actions[bot]@users.noreply.github.com'
commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>" commit_author: 'github-actions[bot] <github-actions[bot]@users.noreply.github.com>'

7
.husky/pre-commit Normal file
View File

@ -0,0 +1,7 @@
#!/bin/sh
. "$(dirname $0)/_/husky.sh"
git stash -q --keep-index
npm run format
git add .
git stash pop -q

10
.prettierignore Normal file
View File

@ -0,0 +1,10 @@
# We prefer our own custom formatting for MarkDown files.
# See the following thread for the discussion:
# https://github.com/simple-icons/simple-icons-font/pull/73
*.md
# 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

4
.prettierrc.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = {
trailingComma: 'all',
singleQuote: true,
};

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,3 @@
module.exports = { module.exports = {
cacheDirectory: "./.cache/jest", cacheDirectory: './.cache/jest',
}; };

View File

@ -19,11 +19,14 @@
"license": "CC0-1.0", "license": "CC0-1.0",
"devDependencies": { "devDependencies": {
"editorconfig-checker": "4.0.2", "editorconfig-checker": "4.0.2",
"husky": "7.0.2",
"is-ci": "3.0.0",
"jest": "27.2.5", "jest": "27.2.5",
"jest-diff": "27.2.5", "jest-diff": "27.2.5",
"jsonschema": "1.4.0", "jsonschema": "1.4.0",
"named-html-entities-json": "0.1.0", "named-html-entities-json": "0.1.0",
"npm-run-all": "4.1.5", "npm-run-all": "4.1.5",
"prettier": "2.4.1",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"svg-path-bbox": "1.0.1", "svg-path-bbox": "1.0.1",
"svg-path-segments": "1.0.0", "svg-path-segments": "1.0.0",
@ -35,11 +38,14 @@
"scripts": { "scripts": {
"build": "node scripts/build/package.js", "build": "node scripts/build/package.js",
"clean": "rimraf icons/*.js index.js", "clean": "rimraf icons/*.js index.js",
"lint": "run-s our-lint jsonlint svglint wslint", "format": "prettier --write .",
"lint": "run-s our-lint jslint jsonlint svglint wslint",
"our-lint": "node scripts/lint/ourlint.js", "our-lint": "node scripts/lint/ourlint.js",
"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",
"wslint": "editorconfig-checker -exclude \\.svg$", "wslint": "editorconfig-checker -exclude \\.svg$",
"postinstall": "is-ci || husky install",
"prepublishOnly": "npm run build", "prepublishOnly": "npm run build",
"postpublish": "npm run clean", "postpublish": "npm run clean",
"test": "jest", "test": "jest",

View File

@ -7,36 +7,36 @@
* tree-shakeable * tree-shakeable
*/ */
const fs = require("fs"); const fs = require('fs');
const path = require("path"); const path = require('path');
const util = require("util"); const util = require('util');
const minify = require("uglify-js").minify; const { minify } = require('uglify-js');
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 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 templatesDir = path.resolve(__dirname, "templates"); 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 indexTemplate = fs.readFileSync(indexTemplateFile, UTF8); const indexTemplate = fs.readFileSync(indexTemplateFile, UTF8);
const iconObjectTemplate = fs.readFileSync(iconObjectTemplateFile, UTF8); const iconObjectTemplate = fs.readFileSync(iconObjectTemplateFile, UTF8);
const data = require(dataFile); const data = require(dataFile);
const { getIconSlug, titleToSlug } = require("../utils.js"); const { getIconSlug } = require('../utils.js');
// Local helper functions // Local helper functions
function escape(value) { const escape = (value) => {
return value.replace(/(?<!\\)'/g, "\\'"); return value.replace(/(?<!\\)'/g, "\\'");
} };
function iconToKeyValue(icon) { const iconToKeyValue = (icon) => {
return `'${icon.slug}':${iconToObject(icon)}`; return `'${icon.slug}':${iconToObject(icon)}`;
} };
function licenseToObject(license) { const licenseToObject = (license) => {
if (license === undefined) { if (license === undefined) {
return; return;
} }
@ -45,9 +45,10 @@ function licenseToObject(license) {
license.url = `https://spdx.org/licenses/${license.type}`; license.url = `https://spdx.org/licenses/${license.type}`;
} }
return license; return license;
} };
function iconToObject(icon) { const iconToObject = (icon) => {
return util.format(iconObjectTemplate, return util.format(
iconObjectTemplate,
escape(icon.title), escape(icon.title),
escape(icon.slug), escape(icon.slug),
escape(icon.svg), escape(icon.svg),
@ -56,8 +57,8 @@ function iconToObject(icon) {
icon.guidelines ? `'${escape(icon.guidelines)}'` : undefined, icon.guidelines ? `'${escape(icon.guidelines)}'` : undefined,
licenseToObject(icon.license), licenseToObject(icon.license),
); );
} };
function minifyAndWrite(filepath, rawJavaScript) { const minifyAndWrite = (filepath, rawJavaScript) => {
const { error, code } = minify(rawJavaScript); const { error, code } = minify(rawJavaScript);
if (error) { if (error) {
console.error(error); console.error(error);
@ -65,11 +66,11 @@ function minifyAndWrite(filepath, rawJavaScript) {
} else { } else {
fs.writeFileSync(filepath, code); fs.writeFileSync(filepath, code);
} }
} };
// 'main' // 'main'
const icons = []; const icons = [];
data.icons.forEach(icon => { data.icons.forEach((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 = fs.readFileSync(svgFilepath, UTF8).replace(/\r?\n/, ''); icon.svg = fs.readFileSync(svgFilepath, UTF8).replace(/\r?\n/, '');
@ -82,5 +83,8 @@ data.icons.forEach(icon => {
}); });
// write our generic index.js // write our generic index.js
const rawIndexJs = util.format(indexTemplate, icons.map(iconToKeyValue).join(',')); const rawIndexJs = util.format(
indexTemplate,
icons.map(iconToKeyValue).join(','),
);
minifyAndWrite(indexFile, rawIndexJs); minifyAndWrite(indexFile, rawIndexJs);

View File

@ -5,13 +5,14 @@
* icon SVG filename to standard output. * icon SVG filename to standard output.
*/ */
const { titleToSlug } = require("./utils.js"); const { titleToSlug } = require('./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');
process.exit(1); process.exit(1);
} else { } else {
const brandName = process.argv.slice(3) const brandName = process.argv
.slice(3)
.reduce((acc, arg) => `${acc} ${arg}`, process.argv[2]); .reduce((acc, arg) => `${acc} ${arg}`, process.argv[2]);
const filename = titleToSlug(brandName); const filename = titleToSlug(brandName);

View File

@ -1,9 +1,15 @@
const path = require("path"); #!/usr/bin/env node
const Validator = require("jsonschema").Validator; /**
* @fileoverview
* CLI tool to run jsonschema on the simple-icons.json data file.
*/
const rootDir = path.resolve(__dirname, "..", ".."); const path = require('path');
const schemaFile = path.resolve(rootDir, ".jsonschema.json"); const { Validator } = require('jsonschema');
const dataFile = path.resolve(rootDir, "_data", "simple-icons.json");
const rootDir = path.resolve(__dirname, '..', '..');
const schemaFile = path.resolve(rootDir, '.jsonschema.json');
const dataFile = path.resolve(rootDir, '_data', 'simple-icons.json');
const schema = require(schemaFile); const schema = require(schemaFile);
const data = require(dataFile); const data = require(dataFile);

View File

@ -5,15 +5,15 @@
* linters (e.g. jsonlint/svglint). * linters (e.g. jsonlint/svglint).
*/ */
const fs = require("fs"); const fs = require('fs');
const path = require("path"); const path = require('path');
const { diffLinesUnified } = require("jest-diff"); const { diffLinesUnified } = require('jest-diff');
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 dataFile = path.resolve(rootDir, '_data', 'simple-icons.json');
const data = require(dataFile); const data = require(dataFile);
/** /**
@ -22,7 +22,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: function() { alphabetical: () => {
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];
@ -39,7 +39,7 @@ const TESTS = {
} }
return invalidEntries; return invalidEntries;
}; };
const format = icon => { const format = (icon) => {
if (icon.slug) { if (icon.slug) {
return `${icon.title} (${icon.slug})`; return `${icon.title} (${icon.slug})`;
} }
@ -49,35 +49,35 @@ const TESTS = {
const invalids = data.icons.reduce(collector, []); const invalids = data.icons.reduce(collector, []);
if (invalids.length) { if (invalids.length) {
return `Some icons aren't in alphabetical order: return `Some icons aren't in alphabetical order:
${invalids.map(icon => format(icon)).join(", ")}`; ${invalids.map((icon) => format(icon)).join(', ')}`;
} }
}, },
/* Check the formatting of the data file */ /* Check the formatting of the data file */
prettified: function() { prettified: () => {
const dataString = fs.readFileSync(dataFile, UTF8).replace(/\r\n/g, '\n'); const dataString = fs.readFileSync(dataFile, UTF8).replace(/\r\n/g, '\n');
const dataPretty = `${JSON.stringify(data, null, " ")}\n`; const dataPretty = `${JSON.stringify(data, null, ' ')}\n`;
if (dataString !== dataPretty) { if (dataString !== dataPretty) {
const dataDiff = diffLinesUnified( const dataDiff = diffLinesUnified(
dataString.split("\n"), dataString.split('\n'),
dataPretty.split("\n"), dataPretty.split('\n'),
{ {
expand: false, expand: false,
omitAnnotationLines: true omitAnnotationLines: true,
}, },
); );
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) const errors = Object.keys(TESTS)
.map(k => TESTS[k]()) .map((k) => TESTS[k]())
.filter(Boolean); .filter(Boolean);
if (errors.length > 0) { if (errors.length > 0) {
errors.forEach(error => console.error(`\u001b[31m${error}\u001b[0m`)); errors.forEach((error) => console.error(`\u001b[31m${error}\u001b[0m`));
process.exit(1); process.exit(1);
} }

View File

@ -4,34 +4,34 @@
* 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"); const fs = require('fs');
const path = require("path"); const path = require('path');
const rootDir = path.resolve(__dirname, "..", ".."); const rootDir = path.resolve(__dirname, '..', '..');
const packageJsonFile = path.resolve(rootDir, "package.json"); const packageJsonFile = path.resolve(rootDir, 'package.json');
function readManifest(file) { const readManifest = (file) => {
const manifestRaw = fs.readFileSync(file).toString(); const manifestRaw = fs.readFileSync(file).toString();
const manifestJson = JSON.parse(manifestRaw); const manifestJson = JSON.parse(manifestRaw);
return manifestJson; return manifestJson;
} };
function writeManifest(file, json) { const writeManifest = (file, json) => {
const manifestRaw = JSON.stringify(json, null, 2) + "\n"; const manifestRaw = JSON.stringify(json, null, 2) + '\n';
fs.writeFileSync(file, manifestRaw); fs.writeFileSync(file, manifestRaw);
} };
function main(newVersion) { const main = (newVersion) => {
try { try {
const manifest = readManifest(packageJsonFile); const manifest = readManifest(packageJsonFile);
manifest.version = newVersion manifest.version = newVersion;
writeManifest(packageJsonFile, manifest); writeManifest(packageJsonFile, manifest);
} catch (error) { } catch (error) {
console.error(`Failed to bump package version to ${newVersion}:`, error); console.error(`Failed to bump package version to ${newVersion}:`, error);
process.exit(1); process.exit(1);
} }
} };
main(process.argv[2]); main(process.argv[2]);

View File

@ -5,24 +5,24 @@
* 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"); const fs = require('fs');
const path = require("path"); const path = require('path');
const rootDir = path.resolve(__dirname, "..", ".."); const rootDir = path.resolve(__dirname, '..', '..');
const packageJsonFile = path.resolve(rootDir, "package.json"); const packageJsonFile = path.resolve(rootDir, 'package.json');
const readmeFile = path.resolve(rootDir, "README.md"); const readmeFile = path.resolve(rootDir, 'README.md');
function getMajorVersion(semVerVersion) { const getMajorVersion = (semVerVersion) => {
const majorVersionAsString = semVerVersion.split('.')[0]; const majorVersionAsString = semVerVersion.split('.')[0];
return parseInt(majorVersionAsString); return parseInt(majorVersionAsString);
} };
function getManifest() { const getManifest = () => {
const manifestRaw = fs.readFileSync(packageJsonFile).toString(); const manifestRaw = fs.readFileSync(packageJsonFile).toString();
return JSON.parse(manifestRaw); return JSON.parse(manifestRaw);
} };
function updateVersionInReadmeIfNecessary(majorVersion) { const updateVersionInReadmeIfNecessary = (majorVersion) => {
let content = fs.readFileSync(readmeFile).toString(); let content = fs.readFileSync(readmeFile).toString();
content = content.replace( content = content.replace(
@ -31,17 +31,17 @@ function updateVersionInReadmeIfNecessary(majorVersion) {
); );
fs.writeFileSync(readmeFile, content); fs.writeFileSync(readmeFile, content);
} };
function main() { const main = () => {
try { try {
const manifest = getManifest(); const manifest = getManifest();
const majorVersion = getMajorVersion(manifest.version); const majorVersion = getMajorVersion(manifest.version);
updateVersionInReadmeIfNecessary(majorVersion); updateVersionInReadmeIfNecessary(majorVersion);
} catch (error) { } catch (error) {
console.error("Failed to update CDN version number:", error); console.error('Failed to update CDN version number:', error);
process.exit(1); process.exit(1);
} }
} };
main(); main();

View File

@ -4,15 +4,15 @@
* 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"); const fs = require('fs');
const path = require("path"); const path = require('path');
const rootDir = path.resolve(__dirname, "..", ".."); const rootDir = path.resolve(__dirname, '..', '..');
const dataFile = path.resolve(rootDir, "_data", "simple-icons.json"); 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 data = require(dataFile);
const { getIconSlug } = require("../utils.js"); 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
@ -25,10 +25,10 @@ update the script at '${path.relative(rootDir, __filename)}'.
| :--- | :--- | | :--- | :--- |
`; `;
data.icons.forEach(icon => { data.icons.forEach((icon) => {
const brandName = icon.title; const brandName = icon.title;
const brandSlug = getIconSlug(icon); const brandSlug = getIconSlug(icon);
content += `| \`${brandName}\` | \`${brandSlug}\` |\n` content += `| \`${brandName}\` | \`${brandSlug}\` |\n`;
}); });
fs.writeFileSync(slugsFile, content); fs.writeFileSync(slugsFile, content);

View File

@ -8,41 +8,39 @@ module.exports = {
* Get the slug/filename for an icon. * Get the slug/filename for an icon.
* @param {Object} icon The icon data as it appears in _data/simple-icons.json * @param {Object} icon The icon data as it appears in _data/simple-icons.json
*/ */
getIconSlug: icon => icon.slug || module.exports.titleToSlug(icon.title), getIconSlug: (icon) => icon.slug || module.exports.titleToSlug(icon.title),
/** /**
* Converts a brand title into a slug/filename. * Converts a brand title into a slug/filename.
* @param {String} title The title to convert * @param {String} title The title to convert
*/ */
titleToSlug: title => ( titleToSlug: (title) =>
title.toLowerCase() title
.replace(/\+/g, "plus") .toLowerCase()
.replace(/\./g, "dot") .replace(/\+/g, 'plus')
.replace(/&/g, "and") .replace(/\./g, 'dot')
.replace(/đ/g, "d") .replace(/&/g, 'and')
.replace(/ħ/g, "h") .replace(/đ/g, 'd')
.replace(/ı/g, "i") .replace(/ħ/g, 'h')
.replace(/ĸ/g, "k") .replace(/ı/g, 'i')
.replace(/ŀ/g, "l") .replace(/ĸ/g, 'k')
.replace(/ł/g, "l") .replace(/ŀ/g, 'l')
.replace(/ß/g, "ss") .replace(/ł/g, 'l')
.replace(/ŧ/g, "t") .replace(/ß/g, 'ss')
.normalize("NFD") .replace(/ŧ/g, 't')
.replace(/[^a-z0-9]/g, "") .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 in HTML/SVG friendly format into a brand title (as
* it is seen in simple-icons.json) * it is seen in simple-icons.json)
* @param {String} htmlFriendlyTitle The title to convert * @param {String} htmlFriendlyTitle The title to convert
*/ */
htmlFriendlyToTitle: htmlFriendlyTitle => ( htmlFriendlyToTitle: (htmlFriendlyTitle) =>
htmlFriendlyTitle.replace( htmlFriendlyTitle
/&#([0-9]+);/g, .replace(/&#([0-9]+);/g, (_, num) => String.fromCharCode(parseInt(num)))
(_, num) => String.fromCharCode(parseInt(num)) .replace(
).replace( /&(quot|amp|lt|gt);/g,
/&(quot|amp|lt|gt);/g, (_, ref) => ({ quot: '"', amp: '&', lt: '<', gt: '>' }[ref]),
(_, ref) => ({quot: '"', amp: '&', lt: '<', gt: '>'}[ref]) ),
) };
),
}

View File

@ -38,9 +38,7 @@ module.exports = {
// Keep the role="img" attribute and automatically add it // Keep the role="img" attribute and automatically add it
// to the <svg> tag if it's not there already // to the <svg> tag if it's not there already
addAttributesToSVGElement: { addAttributesToSVGElement: {
attributes: [ attributes: [{ role: 'img' }],
{role: 'img'},
],
}, },
// Keep the 'role' attribute, if it's already defined // Keep the 'role' attribute, if it's already defined
@ -51,11 +49,7 @@ module.exports = {
// Remove all attributes except 'role', 'viewBox', and 'xmlns' from // Remove all attributes except 'role', 'viewBox', and 'xmlns' from
// <svg> tags // <svg> tags
removeAttrs: { removeAttrs: {
attrs: [ attrs: ['baseProfile', 'version', 'fill-rule'],
'baseProfile',
'version',
'fill-rule',
],
}, },
// Remove paths with fill="none" // Remove paths with fill="none"

View File

@ -1,7 +1,7 @@
const { icons } = require('../_data/simple-icons.json'); const { icons } = require('../_data/simple-icons.json');
const { getIconSlug } = require('../scripts/utils.js'); const { getIconSlug } = require('../scripts/utils.js');
icons.forEach(icon => { icons.forEach((icon) => {
const filename = getIconSlug(icon); const filename = getIconSlug(icon);
const subject = require(`../icons/${filename}.js`); const subject = require(`../icons/${filename}.js`);
@ -34,7 +34,9 @@ icons.forEach(icon => {
expect(subject.path).toMatch(/^[MmZzLlHhVvCcSsQqTtAaEe0-9-,.\s]+$/g); expect(subject.path).toMatch(/^[MmZzLlHhVvCcSsQqTtAaEe0-9-,.\s]+$/g);
}); });
test(`${icon.title} has ${icon.guidelines ? "the correct" : "no"} "guidelines"`, () => { test(`${icon.title} has ${
icon.guidelines ? 'the correct' : 'no'
} "guidelines"`, () => {
if (icon.guidelines) { if (icon.guidelines) {
expect(typeof subject.guidelines).toBe('string'); expect(typeof subject.guidelines).toBe('string');
expect(subject.guidelines).toEqual(icon.guidelines); expect(subject.guidelines).toEqual(icon.guidelines);
@ -43,11 +45,13 @@ icons.forEach(icon => {
} }
}); });
test(`${icon.title} has ${icon.license ? "the correct" : "no"} "license"`, () => { test(`${icon.title} has ${
icon.license ? 'the correct' : 'no'
} "license"`, () => {
if (icon.license) { if (icon.license) {
expect(typeof subject.license).toBe('object'); expect(typeof subject.license).toBe('object');
expect(subject.license).toHaveProperty('type', icon.license.type); expect(subject.license).toHaveProperty('type', icon.license.type);
if (icon.license.type === "custom") { if (icon.license.type === 'custom') {
expect(subject.license).toHaveProperty('url', icon.license.url); expect(subject.license).toHaveProperty('url', icon.license.url);
} else { } else {
expect(typeof subject.license.url).toBe('string'); expect(typeof subject.license.url).toBe('string');

View File

@ -1,8 +1,8 @@
const { icons } = require('../_data/simple-icons.json'); const { icons } = require('../_data/simple-icons.json');
const simpleIcons = require('../index.js'); const simpleIcons = require('../index.js');
const { getIconSlug } = require("../scripts/utils.js"); const { getIconSlug } = require('../scripts/utils.js');
icons.forEach(icon => { icons.forEach((icon) => {
const slug = getIconSlug(icon); const slug = getIconSlug(icon);
const subject = simpleIcons[slug]; const subject = simpleIcons[slug];
@ -35,7 +35,9 @@ icons.forEach(icon => {
expect(subject.path).toMatch(/^[MmZzLlHhVvCcSsQqTtAaEe0-9-,.\s]+$/g); expect(subject.path).toMatch(/^[MmZzLlHhVvCcSsQqTtAaEe0-9-,.\s]+$/g);
}); });
test(`${icon.title} has ${icon.guidelines ? "the correct" : "no"} "guidelines"`, () => { test(`${icon.title} has ${
icon.guidelines ? 'the correct' : 'no'
} "guidelines"`, () => {
if (icon.guidelines) { if (icon.guidelines) {
expect(typeof subject.guidelines).toBe('string'); expect(typeof subject.guidelines).toBe('string');
expect(subject.guidelines).toEqual(icon.guidelines); expect(subject.guidelines).toEqual(icon.guidelines);
@ -44,11 +46,13 @@ icons.forEach(icon => {
} }
}); });
test(`${icon.title} has ${icon.license ? "the correct" : "no"} "license"`, () => { test(`${icon.title} has ${
icon.license ? 'the correct' : 'no'
} "license"`, () => {
if (icon.license) { if (icon.license) {
expect(typeof subject.license).toBe('object'); expect(typeof subject.license).toBe('object');
expect(subject.license).toHaveProperty('type', icon.license.type); expect(subject.license).toHaveProperty('type', icon.license.type);
if (icon.license.type === "custom") { if (icon.license.type === 'custom') {
expect(subject.license).toHaveProperty('url', icon.license.url); expect(subject.license).toHaveProperty('url', icon.license.url);
} else { } else {
expect(typeof subject.license.url).toBe('string'); expect(typeof subject.license.url).toBe('string');