From 1a77d28227586bb9d01778414cd31e31762db00a Mon Sep 17 00:00:00 2001 From: Sachin Raja Date: Thu, 28 Oct 2021 16:16:34 -0700 Subject: [PATCH] export bundled icons from one entry point and add types (#6767) * export all icons from a single file (#6189) * fix: revert formatting, add exports to package.json * feat: generate icons.js and add relevant exports field * add minifyAndWrite Co-authored-by: Eric Cornelissen * fix: minifyAndWrite build * add type: commonjs Co-authored-by: Eric Cornelissen * simplify exports Co-authored-by: Eric Cornelissen * add "require" in exports * place objects directly in barrel file * write exports minified Co-authored-by: Eric Cornelissen * fix formatting Co-authored-by: Eric Cornelissen * refactor slugToVariableName code into a function * fix slugToVariableName * change prefix to "si" * move slugToVariableName to local helper functions * unignore icons.js and icons.mjs Co-authored-by: Eric Cornelissen * feat: add types (#6580) * feat: add types * fix linting error * export default from types/index.d.ts * minify * revert formatting changes * revert formatting change * change paths from types/index.d.ts to index.d.ts * mark icons.get as deprecated * move type alias to another file * update readme * update readme.md Co-authored-by: Eric Cornelissen * update typescript usage section Co-authored-by: Eric Cornelissen * fix conflicts * Apply suggestions from code review Co-authored-by: Eric Cornelissen * add writeTs function Co-authored-by: Eric Cornelissen --- .gitignore | 3 +++ .npmignore | 5 +++++ README.md | 18 +++++++++------- alias.d.ts | 6 ++++++ index.d.ts | 25 +++++++++++++++++++++++ package.json | 15 +++++++++++++- scripts/build/package.js | 44 +++++++++++++++++++++++++++++++++++++--- 7 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 alias.d.ts create mode 100644 index.d.ts diff --git a/.gitignore b/.gitignore index a56de62d..1fdb44ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ # Files generated by build script /index.js +/icons.js +/icons.mjs +/icons.d.ts # Ignore all files in the icons folder icons/* diff --git a/.npmignore b/.npmignore index 6570921b..faf9f22d 100644 --- a/.npmignore +++ b/.npmignore @@ -9,3 +9,8 @@ !LICENSE.md !VERSIONING.md !index.js +!index.d.ts +!icons.js +!icons.mjs +!icons.d.ts +!alias.d.ts diff --git a/README.md b/README.md index e9722494..6179e70f 100644 --- a/README.md +++ b/README.md @@ -60,9 +60,17 @@ const icon = simpleIcons.Get('simpleicons'); ``` -Alternatively you can import the needed icons individually, where `[ICON SLUG]` is replaced by a [slug]. -This is useful if you are e.g. compiling your code with [webpack](https://webpack.js.org/) and therefore have to be mindful of your package size: +Alternatively, you can also import all icons from a single file, where `[ICON SLUG]` is replaced by a capitalized [slug]. We highly recommend using a bundler that can tree shake such as [webpack](https://webpack.js.org/) to remove the unused icon code: +```javascript +// Import a specific icon by its slug as: +// import { si[ICON SLUG] } from 'simple-icons/icons' +// For example: +// use import/esm to allow tree shaking +import { siSimpleicons } from 'simple-icons/icons' +``` + +You can also import the needed icons individually, where `[ICON SLUG]` is replaced by a [slug]. ```javascript // Import a specific icon by its slug as: // require('simple-icons/icons/[ICON SLUG]'); @@ -110,11 +118,7 @@ for (const iconSlug in simpleIcons) { #### TypeScript Usage -There are also TypeScript type definitions for the Node package. To use them, simply run: - -```shell -npm install --save-dev @types/simple-icons -``` +Type definitions are bundled with the package. ### PHP Usage diff --git a/alias.d.ts b/alias.d.ts new file mode 100644 index 00000000..99c10e1b --- /dev/null +++ b/alias.d.ts @@ -0,0 +1,6 @@ +import { SimpleIcon } from '.'; + +/** + * @internal + */ +export type I = SimpleIcon; diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 00000000..44c8bfe2 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,25 @@ +export interface SimpleIcon { + title: string; + slug: string; + svg: string; + path: string; + source: string; + hex: string; + guidelines?: string | undefined; + license?: + | { + type: string; + url: string; + } + | undefined; +} + +declare const icons: Record & { + /** + * @deprecated use .Get instead + */ + get(name: string): SimpleIcon; + Get(name: string): SimpleIcon; +}; + +export default icons; diff --git a/package.json b/package.json index ddfde18d..30657fd5 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,20 @@ "svg", "icons" ], + "type": "commonjs", "main": "index.js", + "types": "index.d.ts", + "exports": { + ".": "./index.js", + "./icons": { + "module": "./icons.mjs", + "import": "./icons.mjs", + "require": "./icons.js", + "default": "./icons.js" + }, + "./icons/*": "./icons/*.js" + }, + "sideEffects": false, "repository": { "type": "git", "url": "git+ssh://git@github.com/simple-icons/simple-icons.git" @@ -37,7 +50,7 @@ }, "scripts": { "build": "node scripts/build/package.js", - "clean": "rimraf icons/*.js index.js", + "clean": "rimraf icons/*.js icons/*.d.ts index.js icons.js icons.mjs icons.d.ts", "format": "prettier --write .", "lint": "run-s our-lint jslint jsonlint svglint wslint", "our-lint": "node scripts/lint/ourlint.js", diff --git a/scripts/build/package.js b/scripts/build/package.js index c92963e7..dab8feeb 100644 --- a/scripts/build/package.js +++ b/scripts/build/package.js @@ -18,6 +18,9 @@ const rootDir = path.resolve(__dirname, '..', '..'); const dataFile = path.resolve(rootDir, '_data', 'simple-icons.json'); const indexFile = path.resolve(rootDir, 'index.js'); const iconsDir = path.resolve(rootDir, 'icons'); +const iconsJsFile = path.resolve(rootDir, 'icons.js'); +const iconsMjsFile = path.resolve(rootDir, 'icons.mjs'); +const iconsDtsFile = path.resolve(rootDir, 'icons.d.ts'); const templatesDir = path.resolve(__dirname, 'templates'); const indexTemplateFile = path.resolve(templatesDir, 'index.js'); @@ -58,7 +61,12 @@ const iconToObject = (icon) => { licenseToObject(icon.license), ); }; -const minifyAndWrite = (filepath, rawJavaScript) => { +const slugToVariableName = (slug) => { + const slugFirstLetter = slug[0].toUpperCase(); + const slugRest = slug.slice(1); + return `si${slugFirstLetter}${slugRest}`; +}; +const writeJs = (filepath, rawJavaScript) => { const { error, code } = minify(rawJavaScript); if (error) { console.error(error); @@ -67,8 +75,14 @@ const minifyAndWrite = (filepath, rawJavaScript) => { fs.writeFileSync(filepath, code); } }; +const writeTs = (filepath, rawTypeScript) => { + fs.writeFileSync(filepath, rawTypeScript); +}; // 'main' +const iconsBarrelMjs = []; +const iconsBarrelJs = []; +const iconsBarrelDts = []; const icons = []; data.icons.forEach((icon) => { const filename = getIconSlug(icon); @@ -77,9 +91,23 @@ data.icons.forEach((icon) => { icon.slug = filename; icons.push(icon); + const iconObject = iconToObject(icon); + // write the static .js file for the icon const jsFilepath = path.resolve(iconsDir, `${filename}.js`); - minifyAndWrite(jsFilepath, `module.exports=${iconToObject(icon)};`); + writeJs(jsFilepath, `module.exports=${iconObject};`); + + const dtsFilepath = path.resolve(iconsDir, `${filename}.d.ts`); + writeTs( + dtsFilepath, + 'declare const i:import("../alias").I;export default i;', + ); + + // add object to the barrel file + const iconExportName = slugToVariableName(icon.slug); + iconsBarrelJs.push(`${iconExportName}:${iconObject},`); + iconsBarrelMjs.push(`export const ${iconExportName}=${iconObject}`); + iconsBarrelDts.push(`export const ${iconExportName}:I;`); }); // write our generic index.js @@ -87,4 +115,14 @@ const rawIndexJs = util.format( indexTemplate, icons.map(iconToKeyValue).join(','), ); -minifyAndWrite(indexFile, rawIndexJs); +writeJs(indexFile, rawIndexJs); + +// write our file containing the exports of all icons in CommonJS ... +const rawIconsJs = `module.exports={${iconsBarrelJs.join('')}};`; +writeJs(iconsJsFile, rawIconsJs); +// and ESM +const rawIconsMjs = iconsBarrelMjs.join(''); +writeJs(iconsMjsFile, rawIconsMjs); +// and create a type declaration file +const rawIconsDts = `import {I} from "./alias";${iconsBarrelDts.join('')}`; +writeTs(iconsDtsFile, rawIconsDts);