Convert simple-icons manual backup from submodule to tracked files

This commit is contained in:
MayaChat
2025-11-24 14:51:23 -05:00
parent 30bbe7a0a4
commit f363db5e47
3467 changed files with 42987 additions and 1 deletions

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env node
// @ts-check
/**
* @file
* Send release message to Discord #releases channel.
*/
import process from 'node:process';
const releaseVersion = process.argv[2];
const discordReleasesRoleId = process.env.DISCORD_RELEASES_ROLE_ID;
const discordReleasesWebhookUrl = process.env.DISCORD_RELEASES_WEBHOOK_URL;
const githubReleaseUrl = `https://github.com/simple-icons/simple-icons/releases/tag/${releaseVersion}`;
if (discordReleasesRoleId === undefined) {
console.error('DISCORD_RELEASES_ROLE_ID environment variable is not set.');
process.exit(1);
}
if (discordReleasesWebhookUrl === undefined) {
console.error(
'DISCORD_RELEASES_WEBHOOK_URL environment variable is not set.',
);
process.exit(1);
}
try {
await globalThis.fetch(discordReleasesWebhookUrl, {
method: 'post',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: `<@&${discordReleasesRoleId}> ${githubReleaseUrl}`,
}),
});
} catch {
console.error('Failed to send release message to Discord.');
process.exit(1);
}

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env node
// @ts-check
/**
* @file
* Minify data/simple-icons.json file.
*/
import {getIconSlug, getIconsData} from '../../sdk.mjs';
import {formatIconData, writeIconsData} from '../utils.js';
const plainIcons = await getIconsData();
const iconsWithSlugs = plainIcons.map((icon) =>
icon.slug ? icon : {...icon, slug: getIconSlug(icon)},
);
await writeIconsData(formatIconData(iconsWithSlugs), true);

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env node
// @ts-check
/**
* @file
* Rewrite some Markdown files.
*/
import {readFile, writeFile} from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
const LINKS_BRANCH = process.argv[2] || 'develop';
const rootDirectory = path.resolve(import.meta.dirname, '..', '..');
const readmeFile = path.resolve(rootDirectory, 'README.md');
const disclaimerFile = path.resolve(rootDirectory, 'DISCLAIMER.md');
/**
* Reformat a file.
* @param {string} filePath Path to the file.
*/
const reformat = async (filePath) => {
const fileContent = await readFile(filePath, 'utf8');
await writeFile(
filePath,
fileContent
// Replace all CDN links with raw links
.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
.replaceAll(
/\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)](?!\()/g,
(string_, $0) => {
const capital = $0.slice(0, 1);
const body = $0.slice(1).toLowerCase();
return `**${capital + body}**`;
},
),
);
};
await Promise.all([reformat(readmeFile), reformat(disclaimerFile)]);

View File

@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "es2022",
"lib": ["es2022"],
"module": "es2022",
"allowJs": true,
"skipLibCheck": true,
"removeComments": true,
"esModuleInterop": true,
"checkJs": false,
"strict": true,
"noImplicitAny": true,
"noImplicitThis": true,
"forceConsistentCasingInFileNames": true
},
"include": ["../../sdk.mjs"]
}

View File

@@ -0,0 +1,62 @@
#!/usr/bin/env node
// @ts-check
/**
* @file
* 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 fs from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
const rootDirectory = path.resolve(import.meta.dirname, '..', '..');
const packageJsonFile = path.resolve(rootDirectory, 'package.json');
const readmeFile = path.resolve(rootDirectory, 'README.md');
/**
* Get the major version number from a semantic version string.
* @param {string} semVersion A semantic version string.
* @returns {number} The major version number.
*/
const getMajorVersion = (semVersion) => {
const majorVersionAsString = semVersion.split('.')[0];
return Number.parseInt(majorVersionAsString, 10);
};
/**
* Get the package.json manifest.
* @returns {Promise<{version: string}>} The package.json manifest.
*/
const getManifest = async () => {
const manifestRaw = await fs.readFile(packageJsonFile, 'utf8');
return JSON.parse(manifestRaw);
};
/**
* Update the version number in the README.md.
* @param {number} majorVersion The major version number.
*/
const updateVersionInReadmeIfNecessary = async (majorVersion) => {
let content = await fs.readFile(readmeFile, 'utf8');
content = content.replaceAll(
/simple-icons@v\d+/g,
`simple-icons@v${majorVersion}`,
);
await fs.writeFile(readmeFile, content);
};
const main = async () => {
try {
const manifest = await getManifest();
const majorVersion = getMajorVersion(manifest.version);
await updateVersionInReadmeIfNecessary(majorVersion);
} catch (error) {
console.error('Failed to update CDN version number:', error);
process.exit(1);
}
};
await main();

View File

@@ -0,0 +1,132 @@
#!/usr/bin/env node
// @ts-check
/**
* @file
* Updates the SDK Typescript definitions located in the file sdk.d.ts
* to match the current definitions of functions of sdk.mjs.
*/
import {spawnSync} from 'node:child_process';
import fs from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
import {fileExists} from '../utils.js';
const rootDirectory = path.resolve(import.meta.dirname, '..', '..');
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
// in sdk.mjs to avoid circular imports
const originalSdkMjsContent = await fs.readFile(sdkMjs, 'utf8');
const temporarySdkMjsContent = originalSdkMjsContent
.split('\n')
.filter((line) => !line.startsWith(' * @typedef {import("./sdk")'))
.join('\n');
await fs.writeFile(sdkMjs, temporarySdkMjsContent);
let cmd;
let error = false;
try {
cmd = spawnSync(
'npx',
[
'tsc',
'-p',
path.join('scripts', 'release', 'sdk-ts-defs-jsconfig.json'),
'--declaration',
'--emitDeclarationOnly',
],
{stdio: 'inherit'},
);
} catch {
await fs.writeFile(sdkMjs, originalSdkMjsContent);
error = true;
}
let errorMessage = "Command 'npx tsc sdk.mjs' failed for an unknown reason";
if (cmd && cmd.stderr) {
errorMessage = cmd.stderr.toString();
}
if (error || cmd === undefined) {
process.stdout.write(
`Error generating Typescript definitions: '${errorMessage}'\n`,
);
process.exit(1);
}
await fs.writeFile(sdkMjs, originalSdkMjsContent);
};
/**
* We must remove the duplicated export types that tsc generates from
* JSDoc `typedef` comments.
* See {@link https://github.com/microsoft/TypeScript/issues/46011}.
* @param {string} content Content of the file.
* @returns {string} The content without duplicated export types.
*/
const removeDuplicatedExportTypes = (content) => {
const newContent = [];
const lines = content.split('\n');
/** @type {string[]} */
const exportTypesFound = [];
for (const line of lines) {
if (line.startsWith('export type ')) {
const type = line.split(' ')[2];
if (!exportTypesFound.includes(type)) {
newContent.push(line);
exportTypesFound.push(type);
}
} else {
newContent.push(line);
}
}
return newContent.join('\n');
};
const generateSdkTs = async () => {
const sdkMtsExists = await fileExists(sdkMts);
if (sdkMtsExists) await fs.unlink(sdkMts);
await generateSdkMts();
const autogeneratedMessage =
'/* The next code is autogenerated from sdk.mjs */\n/* eslint-disable */';
const newSdkTsContent =
// 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, removeDuplicatedExportTypes(newSdkTsContent));
await fs.unlink(sdkMts);
let cmd;
let error = false;
try {
cmd = spawnSync('npx', ['prettier', '-w', 'sdk.d.ts'], {stdio: 'inherit'});
} catch {
error = true;
}
let errorMessage =
"Command 'npx prettier -w sdk.d.ts' failed for an unknown reason";
if (cmd && cmd.stderr) {
errorMessage = cmd.stderr.toString();
}
if (error || cmd === undefined) {
process.stdout.write(
'Error executing Prettier to prettify' +
` SDK TS definitions: '${errorMessage}'\n`,
);
process.exit(1);
}
};
await generateSdkTs();

View File

@@ -0,0 +1,33 @@
#!/usr/bin/env node
// @ts-check
/**
* @file
* Generates a MarkDown file that lists every brand name and their slug.
*/
import fs from 'node:fs/promises';
import path from 'node:path';
import {getIconSlug, getIconsData} from '../../sdk.mjs';
const rootDirectory = path.resolve(import.meta.dirname, '..', '..');
const slugsFile = path.resolve(rootDirectory, 'slugs.md');
let content = `<!--
update the script at '${path.relative(rootDirectory, import.meta.filename)}'.
-->
# Simple Icons slugs
| Brand name | Brand slug |
| :--- | :--- |
`;
const icons = await getIconsData();
for (const icon of icons) {
const brandName = icon.title;
const brandSlug = getIconSlug(icon);
content += `| \`${brandName}\` | \`${brandSlug}\` |\n`;
}
await fs.writeFile(slugsFile, content);

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env node
// @ts-check
/**
* @file
* Replaces the SVG count milestone "Over <NUMBER> SVG icons..." located
* at README every time the number of current icons is more than `updateRange`
* more than the previous milestone.
*/
import fs from 'node:fs/promises';
import path from 'node:path';
import process from 'node:process';
import {getIconsData} from '../../sdk.mjs';
const regexMatcher = /Over\s(\d+)\s/;
const updateRange = 100;
const rootDirectory = path.resolve(import.meta.dirname, '..', '..');
const readmeFile = path.resolve(rootDirectory, 'README.md');
const readmeContent = await fs.readFile(readmeFile, 'utf8');
try {
const match = regexMatcher.exec(readmeContent);
if (match === null) {
console.error(
'Failed to obtain number of SVG icons of current milestone in README:',
'No match found',
);
process.exit(1);
} else {
const overNIconsInReadme = Number.parseInt(match[1], 10);
const iconsData = await getIconsData();
const nIcons = iconsData.length;
const nIconsRounded = Math.floor(nIcons / updateRange) * updateRange;
if (overNIconsInReadme !== nIconsRounded) {
const newContent = readmeContent.replace(
regexMatcher,
`Over ${nIconsRounded} `,
);
await fs.writeFile(readmeFile, newContent);
}
}
} catch (error) {
console.error(
'Failed to update number of SVG icons of current milestone in README:',
error,
);
process.exit(1);
}