simple-icons/scripts/utils.js
2022-05-08 04:48:32 -07:00

156 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @fileoverview
* Some common utilities for scripts.
*/
import path from 'node:path';
import { promises as fs } from 'node:fs';
import { fileURLToPath } from 'node:url';
const TITLE_TO_SLUG_REPLACEMENTS = {
'+': 'plus',
'.': 'dot',
'&': 'and',
đ: 'd',
ħ: 'h',
ı: 'i',
ĸ: 'k',
ŀ: 'l',
ł: 'l',
ß: 'ss',
ŧ: 't',
};
const TITLE_TO_SLUG_CHARS_REGEX = RegExp(
`[${Object.keys(TITLE_TO_SLUG_REPLACEMENTS).join('')}]`,
'g',
);
const TITLE_TO_SLUG_RANGE_REGEX = /[^a-z0-9]/g;
/**
* Get the slug/filename for an icon.
* @param {Object} icon The icon data as it appears in _data/simple-icons.json
*/
export const getIconSlug = (icon) => icon.slug || titleToSlug(icon.title);
/**
* Extract the path from an icon SVG content.
* @param {Object} svg The icon SVG content
**/
export const svgToPath = (svg) => svg.match(/<path\s+d="([^"]*)/)[1];
/**
* Converts a brand title into a slug/filename.
* @param {String} title The title to convert
*/
export const titleToSlug = (title) =>
title
.toLowerCase()
.replace(
TITLE_TO_SLUG_CHARS_REGEX,
(char) => TITLE_TO_SLUG_REPLACEMENTS[char],
)
.normalize('NFD')
.replace(TITLE_TO_SLUG_RANGE_REGEX, '');
/**
* Converts a slug into a variable name that can be exported.
* @param {String} slug The slug to convert
*/
export const slugToVariableName = (slug) => {
const slugFirstLetter = slug[0].toUpperCase();
const slugRest = slug.slice(1);
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
*/
export const titleToHtmlFriendly = (brandTitle) =>
brandTitle
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.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.
* @param {String|undefined} rootDir Path to the root directory of the project.
*/
export const getIconsDataString = (rootDir) => {
if (rootDir === undefined) {
rootDir = path.resolve(getDirnameFromImportMeta(import.meta.url), '..');
}
const iconDataPath = path.resolve(rootDir, '_data', 'simple-icons.json');
return fs.readFile(iconDataPath, 'utf8');
};
/**
* Get icons data as object from _data/simple-icons.json.
* @param {String|undefined} rootDir Path to the root directory of the project.
*/
export const getIconsData = async (rootDir) => {
const fileContents = await getIconsDataString(rootDir);
return JSON.parse(fileContents).icons;
};
/**
* Get the directory name where this file is located from `import.meta.url`,
* equivalent to the `__dirname` global variable in CommonJS.
* @param {String} importMetaUrl import.meta.url
*/
export const getDirnameFromImportMeta = (importMetaUrl) =>
path.dirname(fileURLToPath(importMetaUrl));
/**
* Replace Windows newline characters by Unix ones.
* @param {String} text The text to replace
*/
export const normalizeNewlines = (text) => {
return text.replace(/\r\n/g, '\n');
};
/**
* Get information about third party extensions.
* @param {String} readmePath Path to the README file
*/
export const getThirdPartyExtensions = async (readmePath) =>
normalizeNewlines(await fs.readFile(readmePath, 'utf8'))
.split('## Third-Party Extensions\n\n')[1]
.split('\n\n')[0]
.split('\n')
.slice(2)
.map((line) => {
const [module, author] = line.split(' | ');
return {
module: {
name: /\[(.+)\]/.exec(module)[1],
url: /\((.+)\)/.exec(module)[1],
},
author: {
name: /\[(.+)\]/.exec(author)[1],
url: /\((.+)\)/.exec(author)[1],
},
};
});