1
0
mirror of https://github.com/akveo/eva-icons.git synced 2025-09-09 05:30:41 +02:00

chore(build): update icons builder, optimize svg, convert svg to png, improve png quality (#20)

This commit is contained in:
Denis Strigo
2018-11-12 13:27:17 +02:00
committed by Dmitry Nehaychik
parent aa96e23cdc
commit cc48a6bc81
503 changed files with 289 additions and 87 deletions

View File

@@ -7,12 +7,11 @@
const path = require('path');
const config = {
'convertOrResizeFormats': [
{
'format': 'png',
'size': ['128']
'convertOptions': {
'png': {
'sizes': ['128']
}
],
},
'copy': [
{
'format': 'svg'

View File

@@ -11,7 +11,7 @@ const fileSystemHelper = {
return fs.remove(srcPath);
},
getSourceFiles(srcPath) {
getFilesByPath(srcPath) {
return new Promise((resolve, reject) => {
fs.readdir(srcPath, (err, files) => {
if (err) {

View File

@@ -0,0 +1,34 @@
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
const gm = require('gm').subClass({imageMagick: true});
const graphicsMagickHelper = {
convertAndResize(size, format, srcPath) {
return gm(srcPath)
.resize(size, size)
.setFormat(format);
},
convert(format, srcPath) {
return gm(srcPath)
.setFormat(format);
},
resize(size, srcPath) {
return gm(srcPath)
.resize(size, size);
},
convertSvgToPng(size, format, srcPath) {
return gm(srcPath)
.in('-size', `${size}x${size}`)
.background('transparent')
.setFormat(format);
}
};
module.exports = graphicsMagickHelper;

View File

@@ -8,13 +8,39 @@ const path = require('path');
const config = require('./config');
const fileSystemHelper = require('./helpers/fs-helper');
const processSvgs = require('./services/process-svgs');
const processPngs = require('./services/process-pngs');
const buildIconsJSON = require('./services/build-icons-json');
const buildSprite = require('./services/build-sprite');
const renameIcon = require('./services/rename-icon');
const renameIcons = require('./services/rename-icon');
const mergeIconsJSON = require('./services/merge-icons-json');
const zip = require('./services/zip');
const buildWebFont = require('./services/build-web-font');
const renameSrcIcons = (srcPath, srcIcons, postfix, extension) => {
if (postfix.toLowerCase() === 'outline') {
return renameIcons(srcPath, srcIcons, postfix, extension);
}
return Promise.resolve(srcIcons);
};
const prepareSvgIcons = (icons, srcPath, desPath) => {
const desSvgPath = path.join(desPath, 'svg');
return processSvgs(icons, srcPath, desSvgPath);
};
const preparePngIcons = (icons, srcPath, desPath) => {
const desPngPath = path.join(desPath, 'png');
return processPngs(icons, srcPath, desPngPath);
};
const merge = () => {
return fileSystemHelper.getFilesByPath(config.desPath)
.then(sourceFiles => {
return mergeIconsJSON(sourceFiles.files)
.then(() => buildSprite('eva'));
});
};
const copyPackageJson = () => {
const fileName = 'package.json';
const srcPath = path.join(__dirname, fileName);
@@ -29,53 +55,29 @@ const copyReadme = () => {
return fileSystemHelper.copy(srcPath, desPath);
};
const copy = (folderPath) => {
const pathFromCopy = path.join(config.srcPath, folderPath);
const pathToCopy = path.join(config.desPath, folderPath.toLowerCase());
return fileSystemHelper.copy(pathFromCopy, pathToCopy);
};
const prepareIcons = (iconType) => {
const folderPath = path.join(config.srcPath, iconType);
const srcPath = path.join(folderPath, config.defaultExtension);
return fileSystemHelper.getSourceFiles(srcPath)
.then((sourceFiles) => {
return buildIconsJSON(sourceFiles.files, srcPath, iconType)
.then(() => buildSprite(iconType));
});
};
const merge = () => {
return fileSystemHelper.getSourceFiles(config.desPath)
.then(sourceFiles => {
return mergeIconsJSON(sourceFiles.files)
.then(() => buildSprite('eva'));
});
};
const renameIcons = (type, folderPath, extension) => {
const srcPath = path.resolve(config.srcPath, folderPath);
return fileSystemHelper.getSourceFiles(srcPath)
.then((sourceFiles) => renameIcon(sourceFiles.files, srcPath, type, extension));
};
fileSystemHelper.remove(config.desPath)
.then(() => {
return fileSystemHelper.getSourceFiles(config.srcPath)
return fileSystemHelper.getFilesByPath(config.srcPath)
.then((srcDirectories) => {
return Promise.all(srcDirectories.files.map((iconType) => {
return Promise.all([
renameIcons(iconType, `${iconType}/${config.defaultExtension}`, config.defaultExtension),
renameIcons(iconType, `${iconType}/png/128`, 'png')
])
.then(() => {
return Promise.all([
copy(`${iconType}/${config.defaultExtension}`),
copy(`${iconType}/png/128`),
]);
})
.then(() => prepareIcons(iconType));
}))
const srcFolders = srcDirectories.files;
return Promise.all(srcFolders.map((folder) => {
const srcIconsPath = path.join(config.srcPath, folder, config.defaultExtension);
const desIconsPath = path.join(config.desPath, folder);
return fileSystemHelper.getFilesByPath(srcIconsPath)
.then((sourceIcons) => {
return renameSrcIcons(srcIconsPath, sourceIcons.files, folder, 'svg')
.then((renamedFiles) => Promise.all([
prepareSvgIcons(renamedFiles, srcIconsPath, desIconsPath),
preparePngIcons(renamedFiles, srcIconsPath, desIconsPath),
])
.then(() => buildIconsJSON(renamedFiles, path.join(desIconsPath, 'svg'), folder))
.then(() => buildSprite(folder))
);
});
}))
.then(() => merge())
.then(() => {
const archivePath = path.join(config.srcPath, '../archive');

View File

@@ -17,10 +17,14 @@ const buildIconsJSON = (srcIcons, srcPath, folder) => {
const outFileName = `${prefix}-icons.json`;
const outFile = path.resolve(config.desPath, outFileName);
return buildIconsObject(srcIcons, getSvg(srcPath)).then((icons) => {
return new Promise((resolve) => {
const icons = buildIconsObject(srcIcons, getSvg(srcPath));
console.log(`Building ${outFile}...`);
fs.writeFileSync(outFile, JSON.stringify(icons));
resolve();
});
};

View File

@@ -8,8 +8,6 @@ const path = require('path');
const cheerio = require('cheerio');
const htmlMinifier = require('html-minifier');
const processSvg = require('./process-svg');
const getSvgContents = (svg) => {
const $ = cheerio.load(svg, { xmlMode: true });
@@ -22,23 +20,19 @@ const getSvgContents = (svg) => {
};
const buildIconsObject = (svgFiles, getSvg) => {
return Promise.all(svgFiles.map((svgFile) => {
const name = path.basename(svgFile, '.svg');
return svgFiles
.map(svgFile => {
const name = path.basename(svgFile, '.svg');
const svg = getSvg(svgFile);
const contents = getSvgContents(svg);
return processSvg(getSvg(svgFile))
.then((svg) => {
const contents = getSvgContents(svg);
return { name, contents };
})
.reduce((icons, icon) => {
icons[icon.name] = icon.contents;
return { name, contents };
});
}))
.then((processed) => {
return processed.reduce((icons, icon) => {
icons[icon.name] = icon.contents;
return icons;
}, {});
});
return icons;
}, {});
};
module.exports = buildIconsObject;

View File

@@ -6,9 +6,10 @@
const Svgo = require('svgo');
const optimize = (svg) => {
const optimizeSvg = (svg) => {
const svgo = new Svgo({
plugins: [
{ removeHiddenElems: false },
{ convertShapeToPath: false },
{ mergePaths: false },
{ inlineStyles: { onlyMatchedOnce: false } },
@@ -21,6 +22,4 @@ const optimize = (svg) => {
.then(({ data }) => data );
};
const processSvg = (svg) => optimize(svg);
module.exports = processSvg;
module.exports = optimizeSvg;

View File

@@ -0,0 +1,25 @@
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
const path = require('path');
const config = require('../config');
const TransformPngIcons = require('./transform-png-icons');
const processPngs = (srcFiles, srcPath, desPath) => {
return Promise.all(srcFiles.map((srcFile) => {
const srcFilePath = path.join(srcPath, srcFile);
const fileTransformOptions = {
convertTo: 'png',
...config.convertOptions.png,
};
const transformPng = new TransformPngIcons(srcFile, srcFilePath, desPath, fileTransformOptions);
transformPng.convertAndResizeSvgToPng();
}));
};
module.exports = processPngs;

View File

@@ -0,0 +1,28 @@
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
const fs = require('fs-extra');
const path = require('path');
const fileSystemHelper = require('../helpers/fs-helper');
const optimizeSvg = require('./oprimize-svg');
const processSvgs = (svgFiles, srcPath, desPath) => {
fileSystemHelper.mkDirByPathSync(desPath);
return Promise.all(svgFiles.map((svgFile) => {
const svgPath = path.join(srcPath, svgFile);
const desSvgPath = path.join(desPath, svgFile);
const svg = fs.readFileSync(svgPath);
return optimizeSvg(svg)
.then((processedSvg) => {
fs.writeFileSync(desSvgPath, processedSvg);
});
}));
};
module.exports = processSvgs;

View File

@@ -7,25 +7,28 @@
const fs = require('fs-extra');
const path = require('path');
const renameIcon = (files, srcPath, type, extension) => {
const folderName = type.toLowerCase();
const fileSystemHelper = require('../helpers/fs-helper');
return Promise.all(files.map((svgFile) => {
const postfix = 'outline';
const isOutline = folderName === postfix;
const shouldRename = isOutline && svgFile.indexOf(postfix) === -1;
const getNewFileName = (srcFile, extension, postfix) => `${path.basename(srcFile, `.${extension}`)}-${postfix}.${extension}`;
if (shouldRename) {
const disExtension = extension;
const disFileName = `${path.basename(svgFile, `.${disExtension}`)}-${postfix}.${disExtension}`;
fs.renameSync(path.resolve(srcPath, svgFile), path.resolve(srcPath, disFileName));
return disFileName;
const renameIcons = (srcPath, srcIcons, postfix, commonExtension) => {
return Promise.all(srcIcons.map((srcFile) => {
if (srcFile.indexOf(postfix) !== -1) {
return srcFile;
}
return svgFile;
let extension = commonExtension;
if (!extension) {
extension = fileSystemHelper.getExtension(srcFile);
}
const newFileName = getNewFileName(srcFile, extension, postfix);
fs.renameSync(path.resolve(srcPath, srcFile), path.resolve(srcPath, newFileName));
return newFileName;
}));
};
module.exports = renameIcon;
module.exports = renameIcons;

View File

@@ -0,0 +1,57 @@
/**
* @license
* Copyright Akveo. All Rights Reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*/
const fs = require('fs-extra');
const path = require('path');
const graphicsMagickHelper = require('../helpers/gm-helper');
const fileSystemHelper = require('../helpers/fs-helper');
class TransformIcons {
constructor(srcFile, srcFilePath, desPath, options) {
this.srcFile = srcFile;
this.srcFilePath = srcFilePath;
this.readableStream = fs.createReadStream(srcFilePath);
this.desPath = desPath;
this.options = options;
fileSystemHelper.mkDirByPathSync(desPath);
}
getAndMakeDesFolder(...desPath) {
const desFolderPath = path.join(...desPath);
fileSystemHelper.mkDirByPathSync(desFolderPath);
return desFolderPath;
}
convert() {
const desFileName = `${fileSystemHelper.trimFileExtension(this.srcFile)}.${this.options.convertTo}`;
const desFilePath = path.join(this.desPath, desFileName);
const writeStream = fs.createWriteStream(desFilePath);
return graphicsMagickHelper.convert(
this.options.convertTo,
this.readableStream,
).stream().pipe(writeStream);
}
resize() {
return this.options.sizes.map((size) => {
const desFolderPath = this.getAndMakeDesFolder(this.desPath, size);
const desFilePath = path.join(desFolderPath, this.srcFile);
const writeStream = fs.createWriteStream(desFilePath);
return graphicsMagickHelper.resize(
size,
this.readableStream
).stream().pipe(writeStream);
});
}
}
module.exports = TransformIcons;

View File

@@ -0,0 +1,54 @@
const fs = require('fs-extra');
const path = require('path');
const fileSystemHelper = require('../helpers/fs-helper');
const graphicsMagickHelper = require('../helpers/gm-helper');
const TransformIcons = require('./transform-icons');
class TransformPngIcons extends TransformIcons {
constructor(...args) {
super(...args);
}
convertAndResizeSvgToPng() {
const desFileName = `${fileSystemHelper.trimFileExtension(this.srcFile)}.${this.options.convertTo}`;
const maxSize = Math.max(...this.options.sizes).toString();
const desFolderPath = this.getAndMakeDesFolder(this.desPath, maxSize);
const desFilePath = path.join(desFolderPath, desFileName);
const writeStream = fs.createWriteStream(desFilePath);
const writableStream = graphicsMagickHelper.convertSvgToPng(
maxSize,
this.options.convertTo,
this.readableStream
).stream().pipe(writeStream);
if (this.options.sizes === 1) {
return ;
}
writableStream.on('finish', () => {
// resize
this.options.sizes.forEach((itemSize) => {
if (itemSize === maxSize) {
return;
}
const desFolderPath = this.getAndMakeDesFolder(this.desPath, itemSize);
const desResizeFilePath = path.join(
desFolderPath,
desFileName,
);
const readableStream = fs.createReadStream(desFilePath);
const writeStream = fs.createWriteStream(desResizeFilePath);
graphicsMagickHelper.resize(
itemSize,
readableStream,
).stream().pipe(writeStream);
});
});
}
}
module.exports = TransformPngIcons;

View File

@@ -40,6 +40,9 @@ const zip = (iconsFolders, archivePath) => {
addToDirectory(archivePath, false, zip);
zip.pipe(fs.createWriteStream(desFolderPath));
console.info(`Build ${desFolderPath}`);
zip.finalize();
};