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:
committed by
Dmitry Nehaychik
parent
aa96e23cdc
commit
cc48a6bc81
@@ -7,12 +7,11 @@
|
||||
const path = require('path');
|
||||
|
||||
const config = {
|
||||
'convertOrResizeFormats': [
|
||||
{
|
||||
'format': 'png',
|
||||
'size': ['128']
|
||||
'convertOptions': {
|
||||
'png': {
|
||||
'sizes': ['128']
|
||||
}
|
||||
],
|
||||
},
|
||||
'copy': [
|
||||
{
|
||||
'format': 'svg'
|
||||
|
@@ -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) {
|
||||
|
34
scripts/helpers/gm-helper.js
Normal file
34
scripts/helpers/gm-helper.js
Normal 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;
|
@@ -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');
|
||||
|
@@ -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();
|
||||
});
|
||||
};
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
25
scripts/services/process-pngs.js
Normal file
25
scripts/services/process-pngs.js
Normal 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;
|
28
scripts/services/process-svgs.js
Normal file
28
scripts/services/process-svgs.js
Normal 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;
|
@@ -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;
|
||||
|
57
scripts/services/transform-icons.js
Normal file
57
scripts/services/transform-icons.js
Normal 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;
|
54
scripts/services/transform-png-icons.js
Normal file
54
scripts/services/transform-png-icons.js
Normal 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;
|
@@ -40,6 +40,9 @@ const zip = (iconsFolders, archivePath) => {
|
||||
addToDirectory(archivePath, false, zip);
|
||||
|
||||
zip.pipe(fs.createWriteStream(desFolderPath));
|
||||
|
||||
console.info(`Build ${desFolderPath}`);
|
||||
|
||||
zip.finalize();
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user