Giter Site home page Giter Site logo

kreuzerk / svg-to-ts Goto Github PK

View Code? Open in Web Editor NEW
265.0 8.0 44.0 7.04 MB

Build performant SVG icon libraries by converting raw SVG files to TypeScript that is optimized for modern tree shaking mechanisms.

License: MIT License

TypeScript 96.60% JavaScript 3.40%
icons svg svg-icons node typescript library hacktoberfest

svg-to-ts's Introduction

Logo

Supports Angular Supports React Supports Vanilla JS / TS

npm GitHub Repo stars

npms.io (final) GitHub Workflow GitHub npm

All Contributors

What is svg-to-ts?

svg-to-ts is a helper tool that converts your SVG icons to TypeScript or TSX. svg-to-ts can convert SVGs to either one TypeScript / TSX file with exported constants, multiple TypeScript files or even compiled JavaScript files with according TS declaration files. Furthermore, it generates all typings in form of interfaces and types.

The generated output can then be used in combination with a iconregistry to create a tree shakable icon library. (More informations...)

Who is this for?

svg-to-ts is designed for autors of component libraries, icon libraries and SPA authors. Our examples and tutorials are made with Angular, however svg-to-ts can also be used with other frameworks such as React or vanilla TypeScript / JavaScript.

Why you should use svg-to-ts

  • svg-to-ts helps you provide icons in a tree shakable and performant way.
  • You get free step to step guides in form of blog posts, that walk you through the process of creating your own tree shakable icon library
  • svg-to-ts optimizes your SVG icons under the hood
  • svg-to-ts automatically generates types and interfaces for your icons to improve typesafety
  • svg-to-ts was developed based on the experiences of providin an icon library for a large enterprise.
  • svg-to-ts offers the possibility to generate TSX files (react components).
  • offers three different conversion modes ('object', 'constants' and 'files')
  • each method is highly configurable to supports multiple use cases.

Step by step guide on how to create your icon library

We created multiple tutorials to show you how you can use svg-to-ts in the best way. We have two step by step guides. A video course and a blog post. Both cover the same content. Feel free to choose the format you prefer.

Video tutorials

IMAGE ALT TEXT HERE

Written tutorial

This blog post guides you through the process of building your own icon library with svg-to-ts. Logo

How to use svg-to-ts

svg-to-ts is a command line tool, it can either be used directly in your terminal or via npm script.

Usage

Binaries

svg-to-ts provides three different binaries.

  • svg-to-ts-object
  • svg-to-ts-constants
  • svg-to-ts-files

You can either run those binaries with npx

npx -p svg-to-ts svg-to-ts-object

or you can add a new script in your package.json.

"name": "my-icon-library",
"version": "3.4.0",
"scripts": {
  "generate-icons": "svg-to-ts"
}

Configuration

When executing a binary svg-to-ts automatically applies some defaults. However, you have multiple ways to configure svg-to-ts. To get a list of available options you can either execute the binary of your choice with the --help argument or you can find all the available options for your conversion type here in the docs:

Once you found your configurations you have the following possibilities to configure svg-to-ts:

  • Passing arguments to the binary
  • Adding a configuration object in the package.json
  • Adding a .svg-to-tsrc file (javascript, json , yaml or yml) in the root of your project or a path of you choice.

Passing arguments to the binary

When choosing this option you directly pass the arguments to your binary.

svg-to-ts-files -s './inputfiles/*.svg' --compileSources true --additionalModelOutputPath ./additional

A complete list of the available arguments can be found by using the --help argument.

svg-to-ts-files --help

When you start using svg-to-ts in bigger projects, configuration may get more sophisticated. At this point command line arguments are hard to read.

Configure svg-to-ts over package.json

To configure svg-to-ts over package.json you can add a svg-to-ts key in your package.json and use the config options. Once you run svg-to-ts those configurations will be picked up. The config object can eiter be an object or an array containing multiple configurations.

{
  "name": "my-icon-library",
  "version": "3.4.0",
  "scripts": {
    "generate-icons": "svg-to-ts"
  },
  "svg-to-ts": {
    "srcFiles": ["./projects/dinosaur-icons/icons/**/*.svg"],
    "outputDirectory": "./projects/dinosaur-icons/icons",
    "interfaceName": "DinosaurIcon",
    "typeName": "dinosaurIcon",
    "prefix": "dinosaurIcon",
    "svgoConfig": {
      "plugins": ["cleanupAttrs"]
    },
    "fileName": "dinosaur-icon.model",
    "additionalModelOutputPath": "./projects/dinosaur-icons/src/lib",
    "compileSources": true
  }
}

Configuration file

To configure svg-to-ts over a .rc file you can add a .svg-to-tsrc file in the root of your project and use the config options. Once you run svg-to-ts those configurations will be picked up.

{
  "srcFiles": ["./projects/dinosaur-icons/icons/**/*.svg"],
  "outputDirectory": "./projects/dinosaur-icons/icons",
  "interfaceName": "DinosaurIcon",
  "typeName": "dinosaurIcon",
  "prefix": "dinosaurIcon",
  "fileName": "dinosaur-icon.model",
  "svgoConfig": {
    "plugins": ["cleanupAttrs"]
  },
  "additionalModelOutputPath": "./projects/dinosaur-icons/src/lib",
  "compileSources": true
}

An alternative for bigger projects is to use a JavaScript-based configuration file. The main advantage here is there you can create dynamic configurations, but also use plain-old JavaScript objects, allowing you to add comments, etc. This is useful for more complex configurations where comments can clarify why options are defined in a certain way.

JS configurations must be defined as a CommonJS module. Whenever you want to use a JS configuration file your rc file has to end with .js.

Here's an example:

const svgToTsConfig = {
  srcFiles: ['./libs/web-icons/icons/**/*.svg'],
  outputDirectory: './libs/web-icons/src/lib',
  interfaceName: 'MyIcon',
  typeName: 'MyIconName',
  generateType: true,
  modelFileName: 'whatever-icon.model',
  additionalModelOutputPath: './libs/web-icons/src/lib',
  iconsFolderName: 'generated',
  delimiter: 'SNAKE',
  barrelFileName: 'generated-icons-barrel',
  svgoConfig: {
    plugins: ['cleanupAttrs']
  },
  compileSources: false
};

module.exports = svgToTsConfig;

Using a custom path

In case you want to put your configuration under a custom path, you can use the --config property to specify a path your configuration. For example svg-to-ts --config ./myconfig.json.

ConversionTypes

svg-to-ts offers three different kinds of conversion types; Converting your icons to a single object, converting your icons to constants or converting your icons to single files. Each approach is designed to solve a specific kind of problem. You can switch between approaches by passing conversionType property (object, constants or files).

1. Converting to a single object (conversionType==='object')

In this scenario the SVG icons are converted to a single object. It's an approach that is suitable if your icon registry accepts an object with the filename as key and the svg data as key.

Available options:

--version type default description
fileName string my-icons file name of the generated file
tsx boolean false Generate TSX file which can be used as React components out of the box
delimiter CAMEL, KEBAB, SNAKE, UPPER, NONE CAMEL delimiter which is used to generate the types and name properties
svgoConfig null or config object check help command - to large to display by default we search for a svgo.config.js file in the root or an inline configuration object
srcFiles string "/*.svg" input files matching the given filename pattern
outputDirectory string "./dist" name of the output directory
objectName string default - export name of the exported const - if nothing is set - default export will be used
verbose boolean false defines if the log should contain additional information. Can be useful for debugging
generateType boolean true defines if a type should be generated
typeName string MyIconType name of the type to be used when generateType is set to true
namePrefix string prefix to be used for the name property included in the generated constant

Example usage

Let's say we have the following four svg files in a inputfiles folder.

  • expressionless.svg
  • full.svg
  • laughing.svg
  • smiling-face.svg

We can now run svg-to-ts-object -s ./inputfiles -o ./dist and we end up with the following file in our dist folder.

Sample output

export default {
  expressionLess: '<svg xmlns="http://ww...',
  full: '<svg xmlns="http://...',
  laughing: '<svg xmlns="http://ww...',
  smilingFace: '<svg xmlns="http://www....'
} as { [key in MyIconType]: string };

export type MyIconType = 'expressionLess' | 'full' | 'laughing' | 'smilingFace';

2. Multiple constants - Treeshakable and typesafe with one file (conversionType==='constants')

This approach converts your svg icons into multiple constants in the same file so that they can be used in combination with an icon registry. It furthermore also generates all necssary types. We wrote a step to step guide that explains this approach further and helps you create an icon library with this approach. Find out more in this blogpost

Output scenario one Only the icons included in the consuming SPA also end up in the final bundle of the SPA.

Available options:

--version type default description
tsx boolean false Generate TSX file which can be used as React components out of the box
generateType boolean false defines if a type should be generated
typeName string myIcons name of the type to be used when generateType is set to true
generateTypeObject boolean false generate type object
generateEnum boolean false generate enum object
prefix string myIcon prefix for the generated svg constants
namePrefix string prefix to be used for the name property included in the generated constant
interfaceName string MyIcon name for the generated interface
fileName string my-icons file name of the generated file
enumName string MyIcons name for the generated enum
delimiter CAMEL, KEBAB, SNAKE, UPPER, NONE SNAKE delimiter which is used to generate the types and name properties
svgoConfig string or config object check help command - to large to display a path to your svgoConfiguration JSON file or an inline configuration object
srcFiles string "/*.svg" input files matching the given filename pattern
outputDirectory string "./dist" name of the output directory
exportCompleteIconSet boolean true exports a complete icon set
completeIconSetName string completeIconSet Default name of the exported variable
verbose boolean false defines if the log should contain additional information. Can be useful for debugging

Example usage

Let's say we have the following four svg files in a inputfiles folder.

  • expressionless.svg
  • full.svg
  • laughing.svg
  • smiling-face.svg

We can now run svg-to-ts-constants -s ./inputfiles -o ./dist and we end up with the following file in our dist folder.

Sample output

export const myIconExpressionLess: {
  name: 'expression_less',
  data: string
} = {
  name: 'expression_less',
  data: `<svg xmlns="http://...`
};
export const myIconFull: {
  name: 'full',
  data: string
} = {
  name: 'full',
  data: `<svg xmlns="http://www...`
};
export const myIconLaughing: {
  name: 'laughing',
  data: string
} = {
  name: 'laughing',
  data: `<svg xmlns="http://www.w...`
};
export const myIconSmilingFace: {
  name: 'smiling_face',
  data: string
} = {
  name: 'smiling_face',
  data: `<svg xmlns="http://www.w3...`
};
/* ⚠️ Do not edit this file - this file is generated by svg-to-ts*/

export type myIcons = 'expression_less' | 'full' | 'laughing' | 'smiling_face';
export interface MyIcon {
  name: myIcons;
  data: string;
}

3. Tree shakable and optimized for lazy loading (conversionType==='files')

This is the most sophisticated approach and also the approach that doesn't only support tree shaking but also supports code splitting which is especially usefull in scenarios where you are using lazy loading.

(Previously, this was the optimizeForLazyLoading option but it has been removed in version 4.3.0.)

Here's a step by step guide on how to create an icon library that is optimized for tree shaking

fully tree shakable Often, having the SVGs in a single file is enough. However, if you are in a more complex environment with bigger business applications, you may want to make the icons even more tree shakable.

In Angular, for example, having all icons in a single file shakes out the icons that are not used. However, icons always end up together in a chunk. The conversionOption = files allows you to configure svg-to-ts that icons are generated in a way that they can even be split to lazy loaded chunks. Means not only the amount of the icons in the chunk gets reduced, but also, where they end up. Means, an icon that is only used in a lazy loaded Angular feature module, will only end up there.

Available options:

--version type default description
barrelFileName string index name of the generated type
tsx boolean false Generate TSX file which can be used as React components out of the box
generateType boolean false defines if a type should be generated
typeName string myIcons name of the type to be used when generateType is set to true
generateTypeObject boolean false generate type object
generateEnum boolean false generate enum object
exportCompleteIconSet boolean false Specifies if the complete icon set should be exported or not (can be very handy for showcases)
completeIconSetName string completeIconSet Name of the generated complete icon set (only effective if exportCompleteIconSet is set to true)
prefix string myIcon prefix for the generated svg constants
namePrefix string prefix to be used for the name property included in the generated constant
interfaceName string MyIcon name for the generated interface
modelFileName string my-icons file name of the generated file
enumName string MyIcons name for the generated enum
delimiter CAMEL, KEBAB, SNAKE, UPPER, NONE SNAKE delimiter which is used to generate the types and name properties
srcFiles string "/*.svg" input files matching the given filename pattern
svgoConfig null or config object check help command - to large to display by default we search for a svgo.config.js file in the root or an inline configuration object
outputDirectory string "./dist" name of the output directory
additionalModelOutputPath string null if a path is specified we will generate an additional file containing interface and type to this path - can be useful to improve type safety
iconsFolderName string "build" name of the folder we will build the TypeScript files to
compileSources boolean false If set to false, we generate a TypeScript file for each SVG. If set to true we will allready compile those TypeScript files and generate JavaScript files and declaration files
compilationOutput ESM, UMD, ESM_AND_UMD ESM Sets the compilation output. This depends on your target audience. Some consumers require, ESM some UMD. You can choose the correct one or even compile to both.
verbose boolean false defines if the log should contain additional information. Can be useful for debugging

Generating UMD and ESM bundles

When you choose to generate UMD and ESM bundles the generated output will end up in a folder named cjs and esm. In order to correctly access those folders you have to add a exports map to the package.json of your library.

  "main": "./umd/index.js",
  "module": "./esm/index.mjs",
  "exports": {
    ".": {
      "import": "./esm/index.mjs",
      "require": "./umd/index.js"
    }
  }

Example usage

Let's say we have the following four svg files in a inputfiles folder.

  • expressionless.svg
  • full.svg
  • laughing.svg
  • smiling-face.svg

We can now run svg-to-ts-files -s ./inputfiles -o ./dist and we end up with the following file in our dist folder.

Sample output

Output scenario two

SVGO - SVG optimization

Under the hood we use the svgo project to optimize the svg icons. To configure SVGO you can add a svgo.config.js file to your root. Check out the official svgo page for further docs about the configuration.

Note: If you dont pass any options, svgo will apply some default options (more)

Starter project

If you want to build a standalone icon library we recommend you to checkout the svg-icon-lib-starter project on GitHub. This project allows you to build an astonishing framework-agnostic SVG icon library with ease. Out of the box icon optimization, build process, and icon showcase. 🚀

Angular builder

In case you are working with Angular and prefer the usage of a builder we recommend you to check out our offical Angular builder.

FAQ

Which approach should I use

This depends on your use case. If you have a simple application, it's probably enought to go with the single file or even a object. If you build a framework that is used by multiple teams, then you should probably go with the fully tree shakable scenario (generating multiple files).

Is it possilbe to create a standalone library?

Yes, it is. The current configurations also allow you to put your icon registry inside the component library and the icons in a dedicated npm package. This has the following advantages:

  • Icons can be used with different registries
  • Simplified build process
  • Icons can be released independent of the component library
  • No need to let svg-to-ts compile the icons - just set the compile flag to false.

Can I use the icons to generate a type?

If you have a method that decides which icon should be returned its useful to add a return type. To do so you can take advantage of the name subset helper generated by svg-to-ts. The name of the helper will be dynamically generated depending upon the value provided for the interfaceName property. An interfaceName of MyIcon will generate a helper called MyIconNameSubset as shown in the following example.

import {IconNameSubset, myIconSmile, myIconLaugh} from 'my-icon-lib';

type emojiIcons = MyIconNameSubset<[typeof myIconSmile, typeof myIconLaugh]>;

// resulting type is equal to type = 'smile' | 'laugh';

myMethod(): emojiIcons {
  // do stuff here
}

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Kevin Kreuzer
Kevin Kreuzer

💻 🎨 📖 🤔 🚇 🚧 ⚠️
Shahar Kazaz
Shahar Kazaz

💻 📖 🤔 🚧 ⚠️
Felipe Plets
Felipe Plets

💻 📖 🤔 🚧 ⚠️
Raphael Ochsenbein
Raphael Ochsenbein

💻 📖 🤔 🚧 ⚠️
Guillaume M
Guillaume M

💻 📖 🤔 🚧 ⚠️
Jaime Velay Valor
Jaime Velay Valor

💻
Glenn Greibesland
Glenn Greibesland

💻
MrP
MrP

📖
Sebastien Dubois
Sebastien Dubois

📖
Andrew Polhill
Andrew Polhill

💻 🐛 📖 🤔
Joshua Vinters
Joshua Vinters

📖
Matthäus G. Chajdas
Matthäus G. Chajdas

📖
Julian Kimmig
Julian Kimmig

💻
Fernando Montoya
Fernando Montoya

📖
Alexey Evenkov
Alexey Evenkov

💻
nmastereal
nmastereal

💻
Katya Pavlenko
Katya Pavlenko

💻 📖 🤔
Liran Tal
Liran Tal

📖
Ikko Ashimine
Ikko Ashimine

📖
Theo Tonge
Theo Tonge

💻 📖 ⚠️
Kasper Christensen
Kasper Christensen

📖
Antonio
Antonio

📖
weihsma
weihsma

💻 📖
Tomas Trajan
Tomas Trajan

💻
Cory Lewis
Cory Lewis

📖
Logan Cool
Logan Cool

🐛
Justin Dietz
Justin Dietz

🐛 💻 🤔 ⚠️

This project follows the all-contributors specification. Contributions of any kind welcome!

svg-to-ts's People

Contributors

akehir avatar allcontributors[bot] avatar andy-polhill avatar anteru avatar atbostudio avatar cakeinpanic avatar dartwelder avatar dependabot[bot] avatar dsebastien avatar eltociear avatar falkendk avatar felipeplets avatar gagle avatar glenngr avatar guillaume-moreau avatar joa-mos avatar jvinters avatar kreuzerk avatar lirantal avatar mecharmor avatar montogeek avatar nmastereal avatar roman-t-work avatar semantic-release-bot avatar shaharkazaz avatar theotonge avatar tomastrajan avatar toneypk avatar vincentpuget avatar weihsma avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

svg-to-ts's Issues

Export all icons from icons.ts (conversionType==='constants')

Environment

  • Angular 12;
  • svg-to-ts 6.0.2.

Problem

In the second approach to converse types (conversionType==='constants'), generated file icons.ts doesn`t contain export of all icons. So everytime we add new icon in method registerIcons() and we need to add this icon to the import list.

It should be better to have singe export with all constants as : export const all = [icon1, icon2, ...].

Would it be possible to add this functionality?

[Feature request] Union type from array

What do you think about adding the possibility to generate the union type definition like this:

const icons = ['icon-1', 'icon-2', 'icon-3'] as const;
type Icon = typeof icons[number];

This would allow the use of the array to iterate over the available icons for a showcase page for example.
I would be happy to implement this feature.

complier not removing class defination in svg markup?

Hi,
I am trying to generate ts files from SVG using svg-to-ts.
My generated typescript files SVG markup has the class definition.
I am not sure is this the default behaviour of generator.
Because of this class definition in SVG, I am not able to apply colour.
I have to delete classes manually and I need to apply the colour to SVG.
generated SVG file:

/* 🤖 this file was generated by svg-to-ts*/
export const appAnalytics: {
  name: 'analytics';
  data: string;
} = {
  name: 'analytics',
  data: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">**<defs><style>.cls-1{fill:#460073}</style></defs>**<g id="Layer_2" data-name="Layer 2"><path **class="cls-1**" d="M500.23 365.9V145.7a8.59 8.59 0 00-8.59-8.58H108.69a9 9 0 00-8.92 8.69v12.42a8.74 8.74 0 00-.33 2.36v242.48a8.59 8.59 0 008.59 8.58H492a8.58 8.58 0 008.58-8.58zm-384-213.55h367.53V380H116.24zM394.36 446.5h-33.14c-9.13-2.66-21.79-12.21-21.79-26.67h-75.1c0 13.47-13.71 23.86-24.45 26.67h-34.24c-10.89 0-16.51 12.29-16.73 17.83h222.18c-.22-5.54-4.59-17.83-16.73-17.83z"/><path **class="cls-1"** d="M466.2 311.29q-39.7-.15-79.41.41a1.15 1.15 0 100 2.28q39.72-.51 79.43-.43a1.18 1.18 0 001.27-1.12 1.25 1.25 0 00-1.29-1.14zM466.07 304q-39.7-.18-79.39.36a1.15 1.15 0 100 2.28q39.69-.51 79.39-.37a1.18 1.18 0 001.27-1.13 1.26 1.26 0 00-1.27-1.14zM466.34 318.62q-39.73-.12-79.44.46a1.15 1.15 0 100 2.29q39.72-.53 79.45-.49a1.18 1.18 0 001.27-1.13 1.25 1.25 0 00-1.28-1.13zM387 326.49a1.15 1.15 0 100 2.28q39.73-.54 79.48-.55a1.18 1.18 0 001.27-1.12 1.25 1.25 0 00-1.32-1.14q-39.69-.07-79.43.53zM466.61 333.28c-26.5 0-53 .23-79.5.59a1.15 1.15 0 100 2.28c26.51-.36 53-.62 79.51-.6a1.19 1.19 0 001.28-1.13 1.28 1.28 0 00-1.29-1.14zM422.85 345.72a1.21 1.21 0 001.31-1.11 1.25 1.25 0 00-1.3-1.16q-17.89-.27-35.77-.42a1.15 1.15 0 100 2.28q17.91.15 35.76.41zM277.13 308.8q23.75-.23 47.48 0a2.16 2.16 0 002.23-2.27 2.49 2.49 0 00-2.44-2.33q-23.75-.21-47.48 0a2.2 2.2 0 00-2.21 2.32 2.4 2.4 0 002.42 2.28zM276.5 317.58c26.14-.24 52.24 0 78.37.81a2.13 2.13 0 002.25-2.23 2.57 2.57 0 00-2.45-2.41c-26.13-.8-52.24-1-78.39-.76a2.22 2.22 0 00-2.21 2.33 2.4 2.4 0 002.43 2.26zM355.47 334.35c-26.65-1-53.24-1.25-79.9-1a1.18 1.18 0 00-1.25 1.15 1.27 1.27 0 001.35 1.11c26.66-.28 53.25 0 79.89 1a1.1 1.1 0 001.26-1.08 1.35 1.35 0 00-1.35-1.18zM275.26 327c26.67-.26 53.28 0 79.93.91a1.12 1.12 0 001.27-1.08 1.36 1.36 0 00-1.36-1.19c-26.65-.93-53.27-1.16-79.94-.89a1.18 1.18 0 00-1.25 1.15 1.27 1.27 0 001.35 1.1zM357.16 343.61a1.37 1.37 0 00-1.36-1.2c-26.63-1.08-53.21-1.34-79.86-1.06a1.18 1.18 0 00-1.25 1.15 1.27 1.27 0 001.36 1.1c26.65-.28 53.22 0 79.85 1.09a1.12 1.12 0 001.26-1.08zM276.45 349.77a1.18 1.18 0 00-1.24 1.15 1.27 1.27 0 001.35 1.11q24.53-.3 49 .13a1.12 1.12 0 001.24-1.1 1.33 1.33 0 00-1.35-1.17q-24.45-.43-49-.12zM139.6 331.84a25.53 25.53 0 1023.69-27.24l1.78 25.46zM220.34 304.6l1.78 25.46L207.49 351a25.53 25.53 0 1012.85-46.39zM131.82 211.37h25.47v68.03h-25.47zM166.65 196.56h25.47v82.86h-25.47zM201.47 240.56h25.47v38.87h-25.47zM236.31 175.97h25.47v103.48h-25.47zM132.78 290.6H156a1 1 0 000-2h-23.22a1 1 0 000 2zM167.61 290.61h23.22a1 1 0 001-1 1 1 0 00-1-1h-23.22a1 1 0 000 2zM225.8 288.67h-23.22a1 1 0 000 2h23.22a1 1 0 000-2zM260.63 290.66a1 1 0 000-2h-23.22a1 1 0 00-1 1 1 1 0 001 1zM467.7 184.87c-16.26 0-6.43 21.21-58.74 27.74-23.56 2.94-22.56 28.76-38.82 28.76s-23.58-5.11-33.78-2.28c-15.67 4.34-15 13.63-31.26 13.63-12.92 0-20.42-16.45-30.39-21v17c10 4.55 17.47 23.52 30.39 23.52 16.26 0 16.42-12 31.26-18.68 14.16-6.33 17.52 6.07 33.78 6.07s23.27-27.23 38.86-22.5c42.27 12.87 37.77-40.58 58.74-42.65 0 0 .07 63.06.09 89.1 0-28.44-.06-79.1-.08-79.1-16.26 0-8.77 46.11-58.74 39.65-16.12-2.08-22.56 22.46-38.82 22.46s-19.62-12.4-33.78-6.07c-14.84 6.65-15 18.68-31.26 18.68-12.92 0-20.42-19-30.39-23.52v35h193.03s-.06-105.81-.09-105.81z"/></g></svg>`
};

My Configuration

  "svg-to-ts": {
    "generateType": "false",
    "delimiter": "KEBAB",
    "conversionType": "files",
    "iconsFolderName": "svg",
    "prefix": "app",
    "srcFiles": [
      "./src/assets/svg/*.svg"
    ],
    "outputDirectory": "./src/app",
    "svgoConfig": {
      "plugins": [
        {
          "removeDimensions": true,
          "cleanupAttrs": true
        }
      ]
    }
  }

Unable to reproduce fully treshakeable icon library

I've been trying to follow the steps outlined in the README and the Guide on Medium, but I'm unable to get a fully tree-shakeable library.

All icons always end up in the main bundle, even when I clone the PoC repo .

I have been able to create a fully tree-shakeable icon lib, but it requires additional steps.
I had to configure ng-packagr to treat each icon as a secondary entry point.

I moved each icon.ts file into its own directory with the following structure

my_icon_package
├── src
|   ├── public_api.ts
|   └── icon.model.ts
├── ng-package.json
├── package.json
└── icons
    ├── svg-icon-home
    |   ├── src
    |   |   ├── public_api.ts
    |   |   └── svg-icon-home.ts
    |   └── package.json
    ├── svg-icon-back
    |   ├── src
    |   |   ├── public_api.ts
    |   |   └── svg-icon-back.ts
    |   └── package.json
    ├── svg-icon-forward
    |   ├── src
    |   |   ├── public_api.ts
    |   |   └── svg-icon-forward.ts
    |   └── package.json

public_api exports the single icon file and package json just contains

{
    "ngPackage": {}
}

Now when I try to build my lib, it actually builds each icon seperately.

Now I have to import each icon from its own secondary entry point
Before:
import { mySvgIcon } from '@myorg/shared/ui/icons';

now:
`import { mySvgIcon } from '@myorg/shared/ui/icons/my-svg-icon';

This produces the same result you have gotten in your article.

Is this expected or has something changed?

Should support for a new generator "packages" be added?

The setup I have used actually mimics what is being done in the @angular/components and @angular/angular repo

Sample build output:

> ng run shared-ui-icons:build:production 
Building Angular Package

------------------------------------------------------------------------------
Building entry point '@myorg/shared-ui-icons'
------------------------------------------------------------------------------
Compiling TypeScript sources through ngc
Bundling to FESM2015
Bundling to FESM5
Bundling to UMD
Minifying UMD bundle
Writing package metadata
Built @myorg/shared-ui-icons

------------------------------------------------------------------------------
Building entry point '@myorg/shared-ui-icons/src/icons/svg-access-point-network'
------------------------------------------------------------------------------
Compiling TypeScript sources through ngc
Bundling to FESM2015
Bundling to FESM5
Bundling to UMD
Minifying UMD bundle
Writing package metadata
Built @myorg/shared-ui-icons/src/icons/svg-access-point-network

------------------------------------------------------------------------------
Building entry point '@myorg/shared-ui-icons/src/icons/svg-access-point'
------------------------------------------------------------------------------
Compiling TypeScript sources through ngc
Bundling to FESM2015
Bundling to FESM5
Bundling to UMD
Minifying UMD bundle
Writing package metadata
Built @myorg/shared-ui-icons/src/icons/svg-access-point

------------------------------------------------------------------------------
Building entry point '@myorg/shared-ui-icons/src/icons/svg-account-alert'
------------------------------------------------------------------------------
Compiling TypeScript sources through ngc
Bundling to FESM2015
Bundling to FESM5
Bundling to UMD
Minifying UMD bundle
Writing package metadata
Built @myorg/shared-ui-icons/src/icons/svg-account-alert

[Feature request] Angular builder

It would be pretty nice to have an Angular builder to run svg-to-ts. The configuration could then be inlined in angular.json like so:

{
  "architect": {
    "update-icons": {
      "builder": "svg-to-ts",
      "options": {
        "conversionType": "constants",
        "srcFiles": ["./projects/dinosaur-icons/icons/**/*.svg"],
        "outputDirectory": "./projects/dinosaur-icons/icons",
        "interfaceName": "DinosaurIcon",
        "typeName": "dinosaurIcon",
        "prefix": "dinosaurIcon",
        "modelFileName": "dinosaur-icon.model",
        "svgoConfig": {
          "plugins": [
            {
              "cleanupAttrs": true
            }
          ]
        },
        "additionalModelFile": "./projects/dinosaur-icons/src/lib",
        "compileSources": true
      }
    }
  }
}

And the builder could be run via the Angular CLI:

ng run update-icons

Maybe it's even possible to get IntelliSense for the configuration in supported editors. Either way, integrating with the Angular build infrastructure seems desirable to me. What do you think?

svg with masks and clip-paths get broken

If i try to compile svg containing masks or clip-paths, I get broken icons, which look different from the icons before compilation. I have tried all plugins in all values (true/false) with no effect.

SyntaxError: ']' expected

I was using svg-icon-library-starter, following the instructions and using these configurations:

.svg-to-tsrc

{
    "conversionType": "files",
    "srcFiles": [
      "./svg-icons/**/*.svg"
    ],
    "outputDirectory": "./dist/icons",
    "interfaceName": "SalIcon",
    "typeName": "salIcon",
    "prefix": "salIcon",
    "generateType": true,
    "exportCompleteIconSet": true,
    "optimizeForLazyLoading": true,
    "modelFileName": "salIcons.model",
    "compileSources": true
}

I ran npm run serve which produced this error

==========================================================
� Hi I am svg-to-ts - let's build an awesome icon library
==========================================================
svg-to-ts: ℹ️ We are using the conversiontype "files"
svg-to-ts: √ Deleting the output folder
svg-to-ts: √ Processing SVG files
svg-to-ts: √ Generate SVG constants
svg-to-ts: × Export complete icon set
svg-to-ts: SyntaxError: ']' expected. (2:33)
  1 | /* � this file was generated by svg-to-ts*/
> 2 | export const completeIconSet = [
    |                                 ^
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] transform-icons: `svg-to-ts`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] transform-icons script.

I've not altered anything from the starter except the recommended REPLACE_ME text. This seems to be an issue with this package.

Support to have generated file as json instead of js/ts

Hi,
We have a use case where we don't want to have output as a Javascript object in js/ts file but instead a json file.
We are primarily avoiding .ts file so that doesn't get bundled as part of main bundle. We will dynamically import the json file to add icons to icon registry.

Is providing output file to be a json already supported or something that seems like a valid requirement?

Failed svg to ts conversion

Hello,

I'm facing a weird issue with svg-to-ts. It seems to work fine for SVG icons coming from material design icons, but with the following file (and others) that I've received from a designer, it seems to fail silently.

Here's the SVG file:

<?xml version="1.0" encoding="UTF-8"?>
<svg width="72px" height="64px" viewBox="0 0 72 64" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <!-- Generator: Sketch 64 (93537) - https://sketch.com -->
    <title>Icons/icon-main-burger-hover</title>
    <desc>Created with Sketch.</desc>
    <g id="Icons/icon-main-burger-hover" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
        <rect id="Rectangle-Copy-7" x="0" y="0" width="72" height="64"></rect>
        <rect id="Rectangle" fill="#E30F89" x="26" y="23" width="22" height="2"></rect>
        <rect id="Rectangle-Copy-2" fill="#E30F89" x="26" y="31" width="15" height="2"></rect>
        <rect id="Rectangle-Copy" fill="#E30F89" x="26" y="39" width="18" height="2"></rect>
    </g>
</svg>

Once converted into TS, here's what is generated:

import { DidowiIcon } from './didowi-icon.model';
export const didowiIconMainBurgerActive: DidowiIcon = {
  name: 'main_burger_active',
  data: `<svg width="72" height="64" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M0 0h72v64H0z"/><path fill="#FFF" d="M26 23h22v2H26zM26 31h15v2H26zM26 39h18v2H26z"/></g></svg>`
};

As you can see, the generated TS file's data field does not contain the expected SVG data.

Do you have any idea what could be wrong? I've tried removing the comment on top of the SVG, but to no avail.

BTW here's the config of svg-to-ts:

"svg-to-ts": {
    "srcFiles": [
      "./libs/web-icons/icons/**/*.svg"
    ],
    "outputDirectory": "./libs/web-icons/src/lib",
    "interfaceName": "DidowiIcon",
    "typeName": "DidowiIconName",
    "prefix": "didowiIcon",
    "optimizeForLazyLoading": true,
    "modelFileName": "didowi-icon.model",
    "additionalModelFile": "./libs/web-icons/src/lib",
    "iconsFolderName": "generated",
    "delimiter": "SNAKE",
    "svgoConfig": {
      "plugins": [
        {
          "cleanupAttrs": true
        }
      ]
    },
    "compileSources": false
  },

[Feature Request] Prepend generated files with comment

It would be really nice to have the ability to prepend the generated files with a comment that indicates they where generated by svg to ts
or be able to pass in an option with the desired comment ie:
"prependComment": "// generated file: do not edit",

Enum instead of Union type

Hey, guys! Thanks for so usefull tool!
You provide only generateType option that might be inconvenient. I use string Enum for storing all icons names like here:
image
Is there the way to generate Enum instead of Type?

Exit code "1" on failure

svg-to-ts currently always returns the exit code "0", regardless of whether an error occurred. We are using svg-to-ts inside our CI (CircleCI), which assumes that a command returns the exit code "1" on error. This lead to a breaking change slipping through CI!

Support Custom Name Delimiter

We utilize @mdi icons and their docs list icon names with a - delimiter instead of _. Any way we could add an input flag to optionally render name values with a custom delimiter?

Read configuration from package json config

Currently, svg-to-ts offers a lot of possibilities to configure things. It can be confusing when you see all those params in a single npm script.

It would be great if we offer the possibility to either add a key to package.json to configure our module or via a dedicated config file like (.svg-to-ts)

Generate types for "conversionType": "object",

Hi!
I'd like to have an option to generate types even if I'm converting SVGs to one object

Types can be used like that:

export type MyIconsType = 'heart-icon' | 'home-icon'

export const MyIcons: { [key in MyIconsType]: string }= {
 'heart-icon':   '<svg></svg>',
 'home-icon':    '<svg></svg>'
}

Generate correct types

Currently the generated type is wrong. Each icon should have the corrwct type on the name property and not the type of all icons.

Error: EMFILE: too many open files while processing SVG files

i am currently trying to use this project upon a very large icon set.

the error i am fancing happens at the i/o operations using fs.
svg-to-ts: ✖ Processing SVG files svg-to-ts: Error: EMFILE: too many open files, open '[random-icon-on-emfile-error].svg'

this might be a problem depending on the node version, but currently i have no option to update.
i am using node -v v12.13.1 on Microsoft Windows 10 Enterprise (tested and failed with ~10k icons)
and also tested on osx using node -v v15.6.0 (tested and failed with ~10k icons)

the easiest way to avoid this is by using graceful-fs and including it in our filehelper.
therefore i forked this project.

you may do more research due to a slightly performance loss while using graceful-fs, but this fix might also help others, who need to create a very large icon library.

kind regards

delimiter config property does not affect name property in generated files

Hi and thanks for this awesome lib.

According to the documentation, the delimiter property should be used to generate the types and name properties

However, it only affects the file-name.

I have "delimiter": "kebab" in package.json, but the name property of the generated files still has snake-case

Feature request/question: Convert SVGs to <symbol>s

I have been looking for a good solution for icon handling for a long time. In the meantime I wrote my own script to group all my icons in one file and convert each one to a <symbol> for easy referencing:

SVG sprite:

<svg width="0" height="0">
  <symbol xmlns="http://www.w3.org/2000/svg" viewbox="0 0 32 32" id="some-icon-name"><path d="..." fill-rule="nonzero"/></symbol>
  <symbol ...></symbol>
</svg>

Usage:

<svg>
  <use xlink:href="#some-icon-name"></use>
</svg>

But I did not implement tree-shaking, so your tool seems very promising to me.

So I have one suggestion & one question:

  1. Could you provide an option to convert the SVGs to symbols (each one in a separate file) so that I can add each one to the DOM when a symbol is used for the first time? Any other icon instance can then use the icon reference.
  2. I don't know if having multiple symbol files is useful for performance/optimization. Maybe you can give an assessment there?

Update to SVGO version 2.3.X

The svgo package is now on version 2.3.X which introduces a new way of setting the config.

Instead of a JSON file, it's now a JS module.

Docs: https://github.com/svg/svgo#configuration

E.g.

module.exports = {
  plugins: [
    // enable a built-in plugin by name
    'builtinPluginName',
    // or by expanded version
    {
      name: 'builtinPluginName'
    },
    // some plugins allow/require to pass options
    {
      name: 'builtinPluginName',
      params: {
        optionName: 'optionValue'
      }
    }
  ]
}

svg-to-ts has a --svgoConfig option which looks for a JSON file. This should probably be updated to use the new module config instead.

E.g.

--svgoConfig svgo.config.js

`IconNameSubset` duplicate name issue when using multiple icon sets

Hi, I believe we may have uncovered a potential breaking change while making a switch from 5.0.1 to 5.7.1, or alternatively it may be a misuse from our side.

In our project we have two sets of icons, icons and brand-icons. We isolate the two by running different svg-to-ts commands and generating separate files.

this change in v5.6.0 which introduced the IconNameSubset causes us a bit of an issue is we now have two exported types with the same name.

An unhandled exception occurred: projects/canopy/src/public-api.ts:25:1 - error TS2308: Module './lib/icon/index' has already exported a member named 'IconNameSubset'. Consider explicitly re-exporting to resolve the ambiguity.

There are probably a few things we could to fix it in our project, but I thought I would raise it here first to see if you think it had any validity as a bug. If so I'm happy to raise a PR to try and fix it.

One route would be to provide some kind of cli option to prefix the type in the same way it's done for the interface name. With a new option a breaking change could be avoided by deferring back to the default if no option is provided, the downside is that it might be a bit of an obscure option.

Error when having a folder in source dir

Hello,

Thank you for your lib, it does exactly what I need for my project.

However I had an error when having a folder in source dir.

I've made a pull request that fix that. #5

Create configuration for svgo optimizing

For example, we need to save icon size dimensions
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 20 20">...</svg>

Another behavior:
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" fill="none" viewBox="0 0 20 20">...</svg>

Now the parameters for the svgo are set statically and there is no way to disable the plugin
removeDimensions: false

[Feature] add enum support

Add enum type support.

This is very useful for consume the enumeration in storybook or other projects.

For example in the extra generated <file.model.ts> add the:

export enum EnumName {
svgFile= 'svgFile',
svgFile2= 'svgFile2'
}

and a config prop to enable this enum generation or not

Need to escape svg character '

The ts string of the svg should either be escaped, or the svg should be contained in a template literal.

For instance, trying to convert the following svg to a ts file will fail:

<svg><text transform="translate(2126 2126)" font-family="'MyriadPro-Regular'" font-size="12px">ba8f63 </text></svg>

TypeName in own config object in package not working


Captura de pantalla 2020-08-25 a las 12 24 04

TypeName is not working, the additionalModelFile is exported correctly but the compiled model name is of type "string"

But, in command line works perfectly.

We had to switch to own config object in package because console in windows don't likes wildcards, only wildcards inside double coma( "../*.svg") so, execute svg-to-ts with all params in script sections works in Mac but not in Windows, so we had to switch to this object, but is not working the TypeName

Script adds additional space in filename.

Script adds additional space in filename between prefix and icon's filename.
image

Config:


"svg-to-ts": {
    "generateType": "true",
    "delimiter": "KEBAB",
    "conversionType": "files",
    "iconsFolderName": "svg",
    "prefix": "app",
    "srcFiles": [
      "./libs/tetrisly/src/assets/svg/**/*.svg"
    ],
    "outputDirectory": "./libs/tetrisly/src/lib/icons/svg-compiled",
    "svgoConfig": {
      "plugins": [
        {
          "removeDimensions": true,
          "cleanupAttrs": true
        }
      ]
    }
  }
  

Special char simple coma in filename

Simple coma in filenames, for example: "Noah's ark.svg" throw an error at compilation time.

I've tested with:
"q&a.svg" -> OK
"a=b.svg" -> OK
"3name.svg" -> OK

A posible solution when creating the name could be:

function removeSpecialChars(name) {
    let newFilename = '';
    for (let i = 0; i < name.length; i++) {
        const theChar = name.charAt(i);
        if (theChar !== "'") newFilename = newFilename + theChar;
    }
    return newFilename;
}

The error stack:

node:13088) UnhandledPromiseRejectionWarning: TypeError: error is not a function
    at /Users/user/Desktop/developer/icons/node_modules/svg-to-ts/src/lib/converters/files.converter.js:68:9
    at Generator.throw (<anonymous>)
    at rejected (/Users/user/Desktop/developer/icons/node_modules/svg-to-ts/src/lib/converters/files.converter.js:6:65)

my package config:

"svg-to-ts": {
    "srcFiles": [
      "./projects/project-icons/icons/*.svg"
    ],
    "conversionType": "files",
    "outputDirectory": "./projects/project-icons/icons",
    "interfaceName": "ProjectInterface",
    "typeName": "ProjectType",
    "prefix": "p",
    "optimizeForLazyLoading": true,
    "modelFileName": "proj-icon.model",
    "additionalModelFile": "./projects/project-icons/src/lib",
    "compileSources": true
  }

Thanks. Greetings.

Add support for object output

Hey, great library!

I'm about to release a new <svg-icon> library where I recommend and show how to use this library.

In my library, we expect to get an object where the key is the icon name, and the value is the content:

{
  settings: 'svg...'
}

Currently, I expose a function helper that'll make it work with your library:

import * as icons from '../assets/svg/my-icons.model';

SvgIconsModule.forRoot({
  icons: fromSvgProps(icons)
});

Do you think you can add this option as a built-in feature?

[Question] Generate icon presentation in code

Not sure if it possible with Typescript approach, but it will be very helpful to have visual presentation of all icons so developer will be just searching for the specific image which he needs.
Ie use case - find icon and determine it's name/code

Prefix icon name

Hi, I would be willing to create a PR with a feature to prefix not file but icon name.

with for example

...
 "namePrefix": 'my',
...

we wold get

export const myIconExpressionLess: MyIcon = {
  name: 'my_expression_less',
  data: `<svg xmlns="http://...`
};
export const myIconFull: MyIcon = {
  name: 'my_full',
  data: `<svg xmlns="http://www...`
};
export const myIconLaughing: MyIcon = {
  name: 'my_laughing',
  data: `<svg xmlns="http://www.w...`
};
export const myIconSmilingFace: MyIcon = {
  name: 'my_smiling_face',
  data: `<svg xmlns="http://www.w3...`
};
/* ⚠️ Do not edit this file - this file is generated by svg-to-ts*/

export type myIcons = 'my_expression_less' | 'my_full' | 'my_laughing' | 'my_smiling_face';
export interface MyIcon {
  name: myIcons;
  data: string;
}

this will allow creating icon bundles that can be distinguished by icon name.

For example, would be great for @ngeat/svg-icon library to use multiple bundles of icons exp. font-awesome 4 and 5 toogether etc.. fa4_squere ,'fa5_squereandmy_squere`;

A conversionType is required, please specify one by passing it via --conversionType

svg-to-ts:  ℹ️ Configuration found under: /Users/ericaskari/Desktop/WEARE/lo-hi/lo-hi-frontend/package.json
svg-to-ts:  A conversionType is required, please specify one by passing it via --conversionType. 
    Valid conversion types are (object, constants or files)

It gives me this error although i used svg-to-ts --conversionType constants whatever I do I get the same message.

Allowing multiple sets of configurations in the package.json

Hi @kreuzerk,
I pulled the latest version of svg-to-ts, and unfortunately, I can't use it with the new configuration file. If the docs are up to date, you can only have: one set of source files and one output directory. I have a big project, and for performance reasons, I need to generate six files at various locations in my project.

I was wondering if the svg-to-ts entry, in the package.json you could also allow an set of configurations, not just only one.

It is possible to achieve that using command line (multiple times with different parameters) but it would be nice if I can have everything within the same configuration file.

Congratulations on your project, this is a fantastic tool.
Thank you!

Adding svgoConfig file path as a command line argument

Hello. First of all, thank you so much for maintaining this tool!

I've recently updated svg-to-ts to 7.1.0 and noticed that some of my icons were not scaling properly. I figured it had to do with SVGO setting removeViewBox as a default plugin. I wish to use my own SVGO config to disable this behavior.

I have added a svgo.config.js file to the root of my project and successfully gotten the desired behavior. However, I would like to keep the root folder as little "polluted" as possible. I was wondering if on the most recent version (7.1.0) there is a way of providing the path to the svgo.config.js file in the command line. If not, could you provide an example of a "inline configuration object" for the SVGO config?

Cheers!

File names containing dots in the name are not accepted when building (at "conversionType": "object")

Hi, when the filename contains dots in the name, then when the file ts is created, an empty object is output.

for example I have this svg's:
Снимок экрана 2021-06-21 в 23 46 20

and such a config in package.json:

"svg-to-ts": { "conversionType": "object", "srcFiles": [ "./src/shared/assets/svg/*.svg" ], "outputDirectory": "./src/shared/assets/svg", "fileName": "svg-icons", "svgoConfig": { "plugins": [ { "removeDimensions": true, "cleanupAttrs": true } ] } }

and my output contain empty object

export default {}

if you remove the dots in the file names, then everything works

Снимок экрана 2021-06-21 в 23 53 47

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.