done first version

This commit is contained in:
Konstantin Vulsonov
2018-09-20 00:58:06 +03:00
parent 0e4fd31a5d
commit ff1ce12bb7
13 changed files with 160 additions and 70 deletions

1
.gitignore vendored
View File

@@ -120,3 +120,4 @@ typings/
#Distribution
dist
.tests

View File

@@ -1,6 +1,8 @@
src/
tests/
.vscode/
.idea/
.tests/
tsconfig.json
tslint.json

View File

@@ -1,47 +1,40 @@
# svg-iconset-builder
Plugin to create iconsets from SVG files
> Disclaimer:<br>
> This plugin was created to prepare iconsets for [Angular Material Icons](https://material.angular.io/components/icon/api#MatIconRegistry)<br>
> The кesult file will be a set of svg's with unique ids as a filename
# @vkl/svg-iconset-builder
Plugin for creating iconsets from SVG files with customizable optimisations
## Installation
Support command line interface:
```
npm install svg-iconset-builder -g
npm install @vkl/svg-iconset-builder -g
```
Or you can install for yout project
```
npm install svg-iconset-builder --save
npm install @vkl/svg-iconset-builder --save
```
## Usage
### Command line
```
svg-iconset --source=<source_folder|required> --name=<output_filename|required> --attrs=<comma separated attributes> --removeViewBox=<boolean>
svg-iconset --source=<source_folder|required> --result=<output_filename|required> --svgoConfig=<path to SVGO configuration json file>
```
Examples:
```
svg-iconset --source=assets/images/icons --name=icons
svg-iconset --source=assets/images/icons --result=icons
```
Creates file `icons-iconset.svg` in same folder
Creates a file `icons-iconset.svg` in same folder
### In Project
```
const SvgIconset = require('svg-iconset');
const config = {
source: 'assets/images/icons', // Reqired
result: 'icons', // Required
// This is optional for optimisations
// This is optional for optimize files using SVGO plugins
optimize: {
attrs: 'width, height, fill, stroke', // Will remove attributes
removeViewBox: true, // Will remove attribute viewBox (default true)
}
}
new SvgIconset(config).createSet();
```

2
package-lock.json generated
View File

@@ -1,5 +1,5 @@
{
"name": "svg-iconset",
"name": "@vkl/svg-iconset-builder",
"version": "0.0.6",
"lockfileVersion": 1,
"requires": true,

View File

@@ -5,9 +5,9 @@
"main": "./dist/app.js",
"scripts": {
"build": "tsc",
"prepublish": "npm run build",
"prepare": "npm run build",
"postpublish": "rm -rf ./dist/",
"test": "./test"
"test": "tsc -p tests/tsconfig.test.json"
},
"bin": {
"svg-iconset": "./dist/bin.js"

View File

@@ -3,13 +3,13 @@ import { join } from 'path';
import { MainConfig, SVGOConfig, OptimizedResponse } from './config';
import { svgClean } from './modules/svgo.clean';
import { makeConfig } from './modules/svgo.config';
import { makeConfig, defaultConfig } from './modules/svgo.config';
const SVGO = require('svgo');
export class SvgIconset {
private optimizeConfig: SVGOConfig;
private optimizeConfig: { [prop: string]: boolean }[];
private isValid: boolean = true;
private svgoPlugin: typeof SVGO;
@@ -18,8 +18,9 @@ export class SvgIconset {
this.isValid = false;
}
this.optimizeConfig = config.optimize !== undefined ? makeConfig(config.optimize) : makeConfig();
this.svgoPlugin = new SVGO(this.optimizeConfig);
this.svgoPlugin = new SVGO({
plugins: this.optimizeConfig
});
}
public createSet() {

View File

@@ -2,16 +2,18 @@
import { exit } from 'process';
import { SvgIconset } from './app';
import { readFileSync } from 'fs';
import { join } from 'path';
const argv = require('yargs').argv;
const exampleString = 'Example: svg-iconset --source=assets/images/icons --name=icons';
const exampleString = 'Example: svg-iconset --source=assets/images/icons --result=icons, check docs https://github.com/DariusNorv/svg-iconset#usage';
let optimize = undefined;
const {
source,
name,
attrs,
removeViewBox
result,
svgoConfig
} = argv;
@@ -21,17 +23,23 @@ if (source === undefined) {
exit();
}
if (name === undefined) {
if (result === undefined) {
console.error('Result filename is not set');
console.error(exampleString);
exit();
}
if (svgoConfig !== undefined) {
try {
optimize = JSON.parse(readFileSync(join(process.cwd(), svgoConfig), 'utf-8'));
} catch (err) {
console.error('SVGO configuration file parse error', err.message);
process.exit(0);
}
}
new SvgIconset({
source,
result: name,
optimize: {
attrs,
removeViewBox
}
result,
optimize
}).createSet();

60
src/config.d.ts vendored
View File

@@ -1,19 +1,3 @@
declare type SVGOConfig = [
{
removeAttrs: {
attrs: string
}
},
{
removeViewBox: boolean
}
]
export interface SvgOptimizeConfig {
attrs?: string;
removeViewBox?: boolean
}
export interface SVGOResponse {
data: string;
info: { [propname: string]: string }
@@ -27,5 +11,47 @@ export interface OptimizedResponse {
export interface MainConfig {
source: string;
result: string;
optimize?: SvgOptimizeConfig
optimize?: SVGOConfig
}
interface SVGOConfig extends Iterable<{ [prop: string]: boolean }>{
removeDoctype?: boolean;
removeXMLProcInst?: boolean;
removeComments?: boolean;
removeMetadata?: boolean;
removeXMLNS?: boolean;
removeEditorsNSData?: boolean;
cleanupAttrs?: boolean;
inlineStyles?: boolean;
minifyStyles?: boolean;
convertStyleToAttrs?: boolean;
cleanupIDs?: boolean;
removeRasterImages?: boolean;
removeUselessDefs?: boolean;
cleanupNumericValues?: boolean;
cleanupListOfValues?: boolean;
convertColors?: boolean;
removeUnknownsAndDefaults?: boolean;
removeNonInheritableGroupAttrs?: boolean;
removeUselessStrokeAndFill?: boolean;
removeViewBox?: boolean;
cleanupEnableBackground?: boolean;
removeHiddenElems?: boolean;
removeEmptyText?: boolean;
convertShapeToPath?: boolean;
moveElemsAttrsToGroup?: boolean;
moveGroupAttrsToElems?: boolean;
collapseGroups?: boolean;
convertPathData?: boolean;
convertTransform?: boolean;
removeEmptyAttrs?: boolean;
removeEmptyContainers?: boolean;
mergePaths?: boolean;
removeUnusedNS?: boolean;
sortAttrs?: boolean;
removeTitle?: boolean;
removeDesc?: boolean;
removeDimensions?: boolean;
removeStyleElement?: boolean;
removeScriptElement?: boolean;
}

View File

@@ -1,27 +1,65 @@
import { SVGOConfig, SvgOptimizeConfig } from '../config';
import { SVGOConfig } from '../config';
const defaultConfig: SVGOConfig = [
{
removeAttrs: {
attrs: '(width|height)'
},
},
{ removeViewBox: false }
];
export const defaultConfig: SVGOConfig = {
removeDoctype: true,
removeXMLProcInst: true,
removeComments: true,
removeMetadata: true,
removeXMLNS: false,
removeEditorsNSData: true,
cleanupAttrs: true,
inlineStyles: true,
minifyStyles: true,
convertStyleToAttrs: true,
cleanupIDs: true,
removeRasterImages: false,
removeUselessDefs: true,
cleanupNumericValues: true,
cleanupListOfValues: false,
convertColors: true,
removeUnknownsAndDefaults: true,
removeNonInheritableGroupAttrs: true,
removeUselessStrokeAndFill: true,
removeViewBox: false,
cleanupEnableBackground: true,
removeHiddenElems: true,
removeEmptyText: true,
convertShapeToPath: true,
moveElemsAttrsToGroup: true,
moveGroupAttrsToElems: true,
collapseGroups: true,
convertPathData: true,
convertTransform: true,
removeEmptyAttrs: true,
removeEmptyContainers: true,
mergePaths: true,
removeUnusedNS: true,
sortAttrs: false,
removeTitle: true,
removeDesc: true,
removeDimensions: true,
removeStyleElement: false,
removeScriptElement: false,
export function makeConfig(config?: SvgOptimizeConfig): SVGOConfig {
if (config !== undefined) {
const { attrs, removeViewBox } = config;
if (attrs !== undefined) {
defaultConfig[0].removeAttrs.attrs = `(${attrs.replace(/,\s/g, '|')})`;
}
if (removeViewBox) {
defaultConfig[1].removeViewBox = removeViewBox;
*[Symbol.iterator]() {
for (const name of Object.keys(this)) {
yield JSON.parse(`{"${name}": ${(this as any)[name]}}`);
}
}
};
return defaultConfig;
export function makeConfig(config?: SVGOConfig): { [prop: string]: boolean }[] {
if (config !== undefined) {
return [...defaultConfig].map(item => {
const key = Object.keys(item)[0];
if (config.hasOwnProperty(key)) {
item[key] = (config as any)[key];
}
return item;
});
}
return [...defaultConfig];
}

8
tests/index.ts Normal file
View File

@@ -0,0 +1,8 @@
import { SvgIconset } from '../src/app';
new SvgIconset(
{
source: './resources',
result: 'test',
}
).createSet();

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="256px" height="256px" preserveAspectRatio="xMidYMid" version="1.1" viewBox="0 0 256 256">
<g>
<path fill="#DD4814" d="M255.637396,127.683191 C255.637396,198.196551 198.47207,255.363378 127.954205,255.363378 C57.4348387,255.363378 0.27026393,198.196551 0.27026393,127.683191 C0.27026393,57.1653255 57.4355894,0 127.954205,0 C198.472821,0 255.637396,57.1653255 255.637396,127.683191 L255.637396,127.683191 Z"/>
<path fill="#FFFFFF" d="M41.1334194,110.63254 C31.7139707,110.63254 24.0827683,118.264493 24.0827683,127.683191 C24.0827683,137.097384 31.7139707,144.728587 41.1334194,144.728587 C50.5476129,144.728587 58.1788152,137.097384 58.1788152,127.683191 C58.1788152,118.264493 50.5476129,110.63254 41.1334194,110.63254 L41.1334194,110.63254 Z M162.848282,188.111202 C154.694569,192.820551 151.898839,203.240727 156.608938,211.389935 C161.313032,219.543648 171.733208,222.338628 179.886921,217.629279 C188.039883,212.925185 190.835613,202.505009 186.126264,194.350545 C181.42217,186.202088 170.995988,183.407109 162.848282,188.111202 L162.848282,188.111202 Z M78.1618299,127.683191 C78.1618299,110.836739 86.5295015,95.9534545 99.3332551,86.9409032 L86.8703343,66.0667683 C71.9555191,76.0365044 60.8581818,91.271132 56.2464282,109.113806 C61.6276833,113.504845 65.0720469,120.189372 65.0720469,127.68244 C65.0720469,135.171003 61.6276833,141.855531 56.2464282,146.246569 C60.852176,164.094499 71.9495132,179.329877 86.8703343,189.299613 L99.3332551,168.420223 C86.5295015,159.412927 78.1618299,144.530393 78.1618299,127.683191 L78.1618299,127.683191 Z M127.954205,77.8855601 C153.967109,77.8855601 175.30895,97.8302874 177.549138,123.265877 L201.839859,122.907777 C200.644692,104.129689 192.441431,87.2719765 179.836622,74.875871 C173.354792,77.3247625 165.86773,76.9501466 159.396411,73.2197537 C152.91383,69.4788504 148.849361,63.1681877 147.738276,56.3177478 C141.438123,54.5790499 134.807648,53.6271202 127.952704,53.6271202 C116.168446,53.6271202 105.026815,56.3950733 95.1344047,61.2913548 L106.979472,82.5175836 C113.351695,79.5521877 120.460387,77.8855601 127.954205,77.8855601 L127.954205,77.8855601 Z M127.954205,177.475566 C120.460387,177.475566 113.351695,175.808188 106.980223,172.843543 L95.1351554,194.069021 C105.027566,198.971308 116.169196,201.740012 127.954205,201.740012 C134.80915,201.740012 141.439625,200.787331 147.739026,199.043378 C148.850111,192.192938 152.916082,185.888282 159.397161,182.140622 C165.872985,178.404223 173.355543,178.036364 179.837372,180.485255 C192.442182,168.08915 200.645443,151.231437 201.84061,132.453349 L177.543883,132.095249 C175.30895,157.537595 153.967859,177.475566 127.954205,177.475566 L127.954205,177.475566 Z M162.842276,67.2446686 C170.995988,71.9532669 181.416915,69.1642933 186.121009,61.0105806 C190.830358,52.856868 188.041384,42.4359413 179.886921,37.7258416 C171.733208,33.0217478 161.313032,35.8167273 156.602182,43.9704399 C151.898839,52.1196481 154.693818,62.5405748 162.842276,67.2446686 L162.842276,67.2446686 Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

5
tests/tsconfig.test.json Normal file
View File

@@ -0,0 +1,5 @@
{
"extends": "../tsconfig.json",
"rootDir": "../tests",
"outDir": "./.tests",
}

View File

@@ -14,6 +14,7 @@
"declaration": true,
"sourceMap": true,
"inlineSources": true,
"downlevelIteration": true,
"types": [
"node"
]