1
0
mirror of https://github.com/tabler/tabler-icons.git synced 2025-01-17 04:38:28 +01:00
tabler-icons/.build/helpers.mjs
Paweł Kuna b54c86433e
Tabler Icons 3.0 (#993)
* fix: fix icons svelte package

* add missing svelte condition #941

* build fix

* react components

* preact components

* solidjs components

* vue components

* add unit tests

* build cleanup

* build fixes

* add icons aliases

* dependencies update

* update gemfile

* dependencies update

* iconfont cache

* Release 3.0.0-alpha.0

* build fix

* rollup plugins fix

* build v3

* Rename 7 icons and add aliases for them

* init react-native package

* React Native new package (#999)

* remove build files

* build files remove (#1000)

* init react-native package

* remove build files

* remove build files

* turbo update

* remove build files

* categories build fix

* 22 new icons: `badge-3d-filled`, `badge-4k-filled`, `badge-8k-filled`, `badge-ad-filled`, `badge-ar-filled`, `badge-cc-filled`, `badge-hd-filled`, `badge-sd-filled`, `badge-tm-filled`, `badge-vo-filled`, `badge-vr-filled`, `badge-wc-filled`, `boom`, `brand-astro`, `car-4wd`, `car-fan-1`, `car-fan-2`, `car-fan-3`, `car-fan-auto`, `car-fan`, `scan-position`, `typeface`

Fixed icons: `badge-3d`

* 25 new icons: `cash-banknote-filled`, `clock-hour-1-filled`, `clock-hour-10-filled`, `clock-hour-11-filled`, `clock-hour-12-filled`, `clock-hour-2-filled`, `clock-hour-3-filled`, `clock-hour-4-filled`, `clock-hour-5-filled`, `clock-hour-6-filled`, `clock-hour-7-filled`, `clock-hour-8-filled`, `clock-hour-9-filled`, `gps-filled`, `layout-align-bottom-filled`, `layout-align-center-filled`, `layout-align-left-filled`, `layout-align-middle-filled`, `layout-align-right-filled`, `layout-align-top-filled`, `radar-filled`, `relation-many-to-many-filled`, `relation-one-to-many-filled`, `relation-one-to-one-filled`, `section-filled`

Fixed icons: `ce-off`

* 7 new icons: `crop-1-1-filled`, `crop-16-9-filled`, `crop-3-2-filled`, `crop-5-4-filled`, `crop-7-5-filled`, `crop-landscape-filled`, `crop-portrait-filled`

* 80 new icons: `circle-letter-a-filled`, `circle-letter-b-filled`, `circle-letter-c-filled`, `circle-letter-d-filled`, `circle-letter-e-filled`, `circle-letter-f-filled`, `circle-letter-g-filled`, `circle-letter-h-filled`, `circle-letter-i-filled`, `circle-letter-j-filled`, `circle-letter-k-filled`, `circle-letter-l-filled`, `circle-letter-letter-v-filled`, `circle-letter-m-filled`, `circle-letter-n-filled`, `circle-letter-o-filled`, `circle-letter-p-filled`, `circle-letter-q-filled`, `circle-letter-r-filled`, `circle-letter-s-filled`, `circle-letter-t-filled`, `circle-letter-u-filled`, `circle-letter-v-filled`, `circle-letter-w-filled`, `circle-letter-x-filled`, `circle-letter-y-filled`, `circle-letter-z-filled`, `square-letter-a-filled`, `square-letter-b-filled`, `square-letter-c-filled`, `square-letter-d-filled`, `square-letter-e-filled`, `square-letter-f-filled`, `square-letter-g-filled`, `square-letter-h-filled`, `square-letter-i-filled`, `square-letter-j-filled`, `square-letter-k-filled`, `square-letter-l-filled`, `square-letter-letter-v-filled`, `square-letter-m-filled`, `square-letter-n-filled`, `square-letter-o-filled`, `square-letter-p-filled`, `square-letter-q-filled`, `square-letter-r-filled`, `square-letter-s-filled`, `square-letter-t-filled`, `square-letter-u-filled`, `square-letter-v-filled`, `square-letter-w-filled`, `square-letter-x-filled`, `square-letter-y-filled`, `square-letter-z-filled`, `square-rounded-letter-a-filled`, `square-rounded-letter-b-filled`, `square-rounded-letter-c-filled`, `square-rounded-letter-d-filled`, `square-rounded-letter-e-filled`, `square-rounded-letter-f-filled`, `square-rounded-letter-g-filled`, `square-rounded-letter-h-filled`, `square-rounded-letter-i-filled`, `square-rounded-letter-j-filled`, `square-rounded-letter-k-filled`, `square-rounded-letter-l-filled`, `square-rounded-letter-m-filled`, `square-rounded-letter-n-filled`, `square-rounded-letter-o-filled`, `square-rounded-letter-p-filled`, `square-rounded-letter-q-filled`, `square-rounded-letter-r-filled`, `square-rounded-letter-s-filled`, `square-rounded-letter-t-filled`, `square-rounded-letter-u-filled`, `square-rounded-letter-v-filled`, `square-rounded-letter-w-filled`, `square-rounded-letter-x-filled`, `square-rounded-letter-y-filled`, `square-rounded-letter-z-filled`

* 3 new icons: `stack-2-filled`, `stack-3-filled`, `stack-filled`

* Fixed icons: `cookie-man`, `cookie`, `copy-check`, `copy-minus`, `copy-x`, `stack-2-filled`, `stack-3-filled`, `stack-filled`

* 3 new icons: `cone-2-filled`, `cone-filled`, `contrast-filled`

* 1 new icons: `contrast-2-filled`

Fixed icons: `contrast-2`

* 4 new icons: `transition-bottom-filled`, `transition-left-filled`, `transition-right-filled`, `transition-top-filled`

* Fixed icons: `square-letter-a-filled`, `square-letter-b-filled`, `square-letter-c-filled`, `square-letter-d-filled`, `square-letter-e-filled`, `square-letter-f-filled`, `square-letter-g-filled`, `square-letter-h-filled`, `square-letter-i-filled`, `square-letter-j-filled`, `square-letter-k-filled`, `square-letter-l-filled`, `square-letter-m-filled`, `square-letter-n-filled`, `square-letter-o-filled`, `square-letter-p-filled`, `square-letter-q-filled`, `square-letter-r-filled`, `square-letter-s-filled`, `square-letter-t-filled`, `square-letter-u-filled`, `square-letter-v-filled`, `square-letter-w-filled`, `square-letter-x-filled`, `square-letter-y-filled`, `square-letter-z-filled`

* 6 new icons: `cookie-filled`, `cookie-man-filled`, `copy-check-filled`, `copy-minus-filled`, `copy-plus-filled`, `copy-x-filled`

Fixed icons: `cookie-man`, `cookie`, `copy-check`, `copy-minus`, `copy-plus`, `copy-x`

* Fixed icons: `brand-graphql`

* icons fix

* 4 new icons: `biohazard-filled`, `microphone-filled`, `microwave-filled`, `soup-filled`

Fixed icons: `bowl-filled`

* Release 3.0.0-alpha.1

* react native package fix

* separate icons to `filled` and `outline` directories (#1002)

* separate icons to solid

* icons separate

* move icons

* init svg icons

* init svg icons

* separate icons

* separate icons

* optimize icons

* optimize icons

* random icons generate

* generate icons preview

* preview icons

* build

* optimize fix

* icons separate

* icons preview

* optimize icons

* 81 new icons: `filled/assembly`, `filled/asset`, `filled/baby-carriage`, `filled/barbell`, `filled/barrier-block`, `filled/bed-flat`, `filled/bone`, `filled/boom`, `filled/bow`, `filled/bowl-chopsticks`, `filled/bowl-spoon`, `filled/brand-spotify`, `filled/bread`, `filled/briefcase-2`, `filled/brightness-auto`, `filled/brightness`, `filled/building-broadcast-tower`, `filled/hexagon-letter-a`, `filled/hexagon-letter-b`, `filled/hexagon-letter-c`, `filled/hexagon-letter-d`, `filled/hexagon-letter-e`, `filled/hexagon-letter-f`, `filled/hexagon-letter-g`, `filled/hexagon-letter-h`, `filled/hexagon-letter-i`, `filled/hexagon-letter-j`, `filled/hexagon-letter-k`, `filled/hexagon-letter-l`, `filled/hexagon-letter-m`, `filled/hexagon-letter-n`, `filled/hexagon-letter-o`, `filled/hexagon-letter-p`, `filled/hexagon-letter-q`, `filled/hexagon-letter-r`, `filled/hexagon-letter-s`, `filled/hexagon-letter-t`, `filled/hexagon-letter-u`, `filled/hexagon-letter-v`, `filled/hexagon-letter-w`, `filled/hexagon-letter-x`, `filled/hexagon-letter-y`, `filled/hexagon-letter-z`, `filled/hexagon-minus`, `filled/hexagon-plus`, `filled/home`, `filled/ironing`, `filled/jetpack`, `filled/key`, `filled/layout-2`, `filled/layout-cards`, `filled/layout-dashboard`, `filled/layout-distribute-horizontal`, `filled/layout-distribute-vertical`, `filled/layout-grid`, `filled/layout-kanban`, `filled/layout-list`, `filled/layout-sidebar-right`, `filled/layout-sidebar`, `filled/layout`, `filled/lego`, `filled/lock`, `filled/lungs`, `filled/macro`, `filled/magnet`, `filled/man`, `filled/manual-gearbox`, `filled/woman`, `filled/xbox-a`, `filled/xbox-b`, `filled/xbox-x`, `filled/xbox-y`, `filled/zeppelin`, `filled/zoom-cancel`, `filled/zoom-code`, `filled/zoom-exclamation`, `filled/zoom-money`, `filled/zoom-out-area`, `filled/zoom-pan`, `filled/zoom-question`, `filled/zoom-scan`

Fixed icons: `filled/archive`, `filled/basket`, `outline/layout-dashboard`, `outline/zoom-pan`

* Fixed icon: `filled/biohazard`

* 4 new icons: `outline/border-bottom-plus`, `outline/border-left-plus`, `outline/border-right-plus`, `outline/border-top-plus`

* debug off

* build `@tabler/icons` package

* build `@tabler/icons` package

* build `@tabler/icons-eps` , `@tabler/icons-pdf`, `@tabler/icons-png`  package

* build `@tabler/icons-react` , `@tabler/icons-preact`, `@tabler/icons-svelte`, `@tabler/icons-vue`, `@tabler/icons-solidjs`  package

* build fixes

* remove unused files

* iconfont build

* build fixes

* update icons unicode

* update icons

* build fixes

* changelog update

* build fixes

* icons images

* Release 3.0.0-beta

* build fix

* icons version fixes

* Fix kerning icon typo for v3 (#1010)

Co-authored-by: Bartłomiej Gawęda <bgaweda@abis.krakow.pl>

* Remove box-seam icon (package duplicate) (#1008)

Co-authored-by: Paweł Kuna <1282324+codecalm@users.noreply.github.com>

* Fix ski jumping icon typo for v3 (#1007)

Change added to aliases.json.

Co-authored-by: Paweł Kuna <1282324+codecalm@users.noreply.github.com>

* dependencies update

* validate icons

* pnpm init

* validate icons

* validate icons

---------

Co-authored-by: Bartłomiej Gawęda <bgaweda@abis.krakow.pl>
Co-authored-by: BG-Software-BG <73077398+BG-Software-BG@users.noreply.github.com>
2024-02-27 00:16:23 +00:00

532 lines
14 KiB
JavaScript

import fs from 'fs'
import path, { resolve, basename } from 'path'
import { fileURLToPath } from 'url'
import svgParse from 'parse-svg-path'
import svgpath from 'svgpath'
import cheerio from 'cheerio';
import { minify } from 'html-minifier';
import { parseSync } from 'svgson'
import { optimize } from 'svgo'
import cp from 'child_process'
import minimist from 'minimist'
import matter from 'gray-matter'
import { globSync } from 'glob'
import { exec } from 'child_process'
export const iconTemplate = (type) => type === 'outline' ? `<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>` : `<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>`
export const blankSquare = '<path stroke="none" d="M0 0h24v24H0z" fill="none"/>'
export const types = ['outline', 'filled']
export const getCurrentDirPath = () => {
return path.dirname(fileURLToPath(import.meta.url));
}
export const HOME_DIR = resolve(getCurrentDirPath(), '..')
export const ICONS_SRC_DIR = resolve(HOME_DIR, 'icons')
export const PACKAGES_DIR = resolve(HOME_DIR, 'packages')
export const GITHUB_DIR = resolve(HOME_DIR, '.github')
export const parseMatter = (icon) => {
const { data, content } = matter.read(icon, { delims: ['<!--', '-->'] })
return { data, content }
}
const getSvgContent = (svg, type, name) => {
return svg
.replace(/<svg([^>]+)>/, (m, m1) => {
return `<svg${m1} class="icon icon-tabler icons-tabler-${type} icon-tabler-${name}"\n>\n ${blankSquare}`
})
.trim()
}
export const getAllIcons = (withContent = false, withObject = false) => {
let icons = {}
const limit = process.env['ICONS_LIMIT'] || Infinity;
types.forEach(type => {
icons[type] = globSync(path.join(ICONS_SRC_DIR, `${type}/*.svg`))
.slice(0, limit)
.sort()
.map(i => {
const { data, content } = parseMatter(i),
name = basename(i, '.svg')
return {
name,
namePascal: toPascalCase(`icon ${name}`),
path: i,
category: data.category || '',
tags: data.tags || [],
version: data.version || '',
unicode: data.unicode || '',
...(withContent ? { content: getSvgContent(content, type, name) } : {}),
...(withObject ? { obj: parseSync(content.replace(blankSquare, '')) } : {})
}
})
.sort()
})
return icons
}
export const getAllIconsMerged = (withContent = false, withObject = false) => {
const allIcons = getAllIcons(true)
const icons = {};
allIcons.outline.forEach(icon => {
icons[icon.name] = {
name: icon.name,
category: icon.category || '',
tags: icon.tags || [],
styles: {
outline: {
version: icon.version || '',
unicode: icon.unicode || '',
...(withContent ? { content: icon.content } : {}),
...(withObject ? { obj: icon.obj } : {})
}
}
}
})
allIcons.filled.forEach(icon => {
if (icons[icon.name]) {
icons[icon.name].styles.filled = {
version: icon.version || '',
unicode: icon.unicode || '',
...(withContent ? { content: icon.content } : {}),
...(withObject ? { obj: icon.obj } : {})
}
}
})
return icons;
}
export const getArgvs = () => {
return minimist(process.argv.slice(2))
}
export const getPackageDir = (packageName) => {
return `${PACKAGES_DIR}/${packageName}`
}
/**
* Return project package.json
* @returns {any}
*/
export const getPackageJson = () => {
return JSON.parse(fs.readFileSync(resolve(HOME_DIR, 'package.json'), 'utf-8'))
}
/**
* Reads SVGs from directory
*
* @param directory
* @returns {string[]}
*/
export const readSvgDirectory = (directory) => {
return fs.readdirSync(directory).filter((file) => path.extname(file) === '.svg')
}
export const getAliases = (groupped = false) => {
const allAliases = JSON.parse(fs.readFileSync(resolve(HOME_DIR, 'aliases.json'), 'utf-8'));
const allIcons = getAllIcons()
if (groupped) {
let aliases = [];
types.forEach(type => {
const icons = allIcons[type].map(i => i.name);
aliases[type] = {};
for (const [key, value] of Object.entries(allAliases[type])) {
if (icons.includes(value)) {
aliases[type][key] = value;
}
}
});
return aliases
} else {
let aliases = [];
types.forEach(type => {
const icons = allIcons[type].map(i => i.name);
for (const [key, value] of Object.entries(allAliases[type])) {
if (icons.includes(value)) {
aliases[`${key}${type !== 'outline' ? `-${type}` : ''}`] = `${value}${type !== 'outline' ? `-${type}` : ''}`;
}
}
});
return aliases
}
}
/**
* Read SVG
*
* @param fileName
* @param directory
* @returns {string}
*/
export const readSvg = (fileName, directory) => {
return fs.readFileSync(path.join(directory, fileName), 'utf-8')
}
/**
* Create directory if not exists
* @param dir
*/
export const createDirectory = (dir) => {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
};
/**
* Get SVG name
* @param fileName
* @returns {string}
*/
export const getSvgName = (fileName) => {
return path.basename(fileName, '.svg')
}
/**
* Convert string to CamelCase
* @param string
* @returns {*}
*/
export const toCamelCase = (string) => {
return string.replace(/^([A-Z])|[\s-_]+(\w)/g, (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase())
}
export const toPascalCase = (string) => {
const camelCase = toCamelCase(string);
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
}
export const addFloats = function (n1, n2) {
return Math.round((parseFloat(n1) + parseFloat(n2)) * 1000) / 1000
}
export const optimizePath = function (path) {
let transformed = svgpath(path).rel().round(3).toString()
return svgParse(transformed).map(function (a) {
return a.join(' ')
}).join('')
}
export const optimizeSVG = (data) => {
return optimize(data, {
js2svg: {
indent: 2,
pretty: true
},
plugins: [
{
name: 'preset-default',
params: {
overrides: {
mergePaths: false
}
}
}]
}).data
}
export function buildIconsObject(svgFiles, getSvg) {
return svgFiles
.map(svgFile => {
const name = path.basename(svgFile, '.svg');
const svg = getSvg(svgFile);
const contents = getSvgContents(svg);
return { name, contents };
})
.reduce((icons, icon) => {
icons[icon.name] = icon.contents;
return icons;
}, {});
}
function getSvgContents(svg) {
const $ = cheerio.load(svg);
return minify($('svg').html(), { collapseWhitespace: true });
}
export const asyncForEach = async (array, callback) => {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array)
}
}
export const createScreenshot = (filePath, retina = true) => {
cp.execSync(`rsvg-convert -x 2 -y 2 ${filePath} > ${filePath.replace('.svg', '.png')}`)
if (retina) {
cp.execSync(`rsvg-convert -x 4 -y 4 ${filePath} > ${filePath.replace('.svg', '@2x.png')}`)
}
}
export const createSvgSymbol = (svg, name, stroke) => {
return svg.replace('<svg', `<symbol id="${name}"`)
.replace(' width="24" height="24"', '')
.replace(' stroke-width="2"', ` stroke-width="${stroke}"`)
.replace('</svg>', '</symbol>')
.replace(/\n\s+/g, ' ')
.replace(/<!--(.*?)-->/gis, '')
.trim()
}
export const generateIconsPreview = async function (files, destFile, {
columnsCount = 19,
paddingOuter = 7,
color = '#354052',
background = '#fff',
png = true,
stroke = 2,
retina = true
} = {}) {
const padding = 20,
iconSize = 24
const iconsCount = files.length,
rowsCount = Math.ceil(iconsCount / columnsCount),
width = columnsCount * (iconSize + padding) + 2 * paddingOuter - padding,
height = rowsCount * (iconSize + padding) + 2 * paddingOuter - padding
let svgContentSymbols = '',
svgContentIcons = '',
x = paddingOuter,
y = paddingOuter
files.forEach(function (file, i) {
const name = file.replace(/^(.*)\/([^\/]+)\/([^.]+).svg$/g, '$2-$3');
let svgFile = fs.readFileSync(file),
svgFileContent = svgFile.toString()
svgFileContent = createSvgSymbol(svgFileContent, name, stroke)
svgContentSymbols += `\t${svgFileContent}\n`
svgContentIcons += `\t<use xlink:href="#${name}" x="${x}" y="${y}" width="${iconSize}" height="${iconSize}" />\n`
x += padding + iconSize
if (i % columnsCount === columnsCount - 1) {
x = paddingOuter
y += padding + iconSize
}
})
const svgContent = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 ${width} ${height}" width="${width}" height="${height}" style="color: ${color}"><rect x="0" y="0" width="${width}" height="${height}" fill="${background}"></rect>\n${svgContentSymbols}\n${svgContentIcons}\n</svg>`
console.log(destFile)
fs.writeFileSync(destFile, svgContent)
if (png) {
await createScreenshot(destFile, retina)
}
}
export const printChangelog = function (newIcons, modifiedIcons, renamedIcons, pretty = false) {
if (newIcons.length > 0) {
if (pretty) {
console.log(`### ${newIcons.length} new icon${newIcons.length > 1 ? 's' : ''}:\n`)
newIcons.forEach(function (icon, i) {
console.log(`- \`${icon}\``)
})
} else {
let str = ''
str += `${newIcons.length} new icon${newIcons.length > 1 ? 's' : ''}: `
newIcons.forEach(function (icon, i) {
str += `\`${icon}\``
if ((i + 1) <= newIcons.length - 1) {
str += ', '
}
})
console.log(str)
}
console.log('')
}
if (modifiedIcons.length > 0) {
let str = ''
str += `Fixed icon${modifiedIcons.length > 1 ? 's' : ''}: `
modifiedIcons.forEach(function (icon, i) {
str += `\`${icon}\``
if ((i + 1) <= modifiedIcons.length - 1) {
str += ', '
}
})
console.log(str)
console.log('')
}
if (renamedIcons.length > 0) {
console.log(`Renamed icons: `)
renamedIcons.forEach(function (icon, i) {
console.log(`- \`${icon[0]}\` renamed to \`${icon[1]}\``)
})
}
}
export const getCompileOptions = () => {
const compileOptions = {
includeIcons: [],
strokeWidth: null,
fontForge: 'fontforge'
}
if (fs.existsSync('../compile-options.json')) {
try {
const tempOptions = JSON.parse(fs.readFileSync('../compile-options.json').toString())
if (typeof tempOptions !== 'object') {
throw 'Compile options file does not contain an json object'
}
if (typeof tempOptions.includeIcons !== 'undefined') {
if (!Array.isArray(tempOptions.includeIcons)) {
throw 'property inludeIcons is not an array'
}
compileOptions.includeIcons = tempOptions.includeIcons
}
if (typeof tempOptions.includeCategories !== 'undefined') {
if (typeof tempOptions.includeCategories === 'string') {
tempOptions.includeCategories = tempOptions.includeCategories.split(' ')
}
if (!Array.isArray(tempOptions.includeCategories)) {
throw 'property includeCategories is not an array or string'
}
const tags = Object.entries(require('./tags.json'))
tempOptions.includeCategories.forEach(function (category) {
category = category.charAt(0).toUpperCase() + category.slice(1)
for (const [icon, data] of tags) {
if (data.category === category && compileOptions.includeIcons.indexOf(icon) === -1) {
compileOptions.includeIcons.push(icon)
}
}
})
}
if (typeof tempOptions.excludeIcons !== 'undefined') {
if (!Array.isArray(tempOptions.excludeIcons)) {
throw 'property excludeIcons is not an array'
}
compileOptions.includeIcons = compileOptions.includeIcons.filter(function (icon) {
return tempOptions.excludeIcons.indexOf(icon) === -1
})
}
if (typeof tempOptions.excludeOffIcons !== 'undefined' && tempOptions.excludeOffIcons) {
// Exclude `*-off` icons
compileOptions.includeIcons = compileOptions.includeIcons.filter(function (icon) {
return !icon.endsWith('-off')
})
}
if (typeof tempOptions.strokeWidth !== 'undefined') {
if (typeof tempOptions.strokeWidth !== 'string' && typeof tempOptions.strokeWidth !== 'number') {
throw 'property strokeWidth is not a string or number'
}
compileOptions.strokeWidth = tempOptions.strokeWidth.toString()
}
if (typeof tempOptions.fontForge !== 'undefined') {
if (typeof tempOptions.fontForge !== 'string') {
throw 'property fontForge is not a string'
}
compileOptions.fontForge = tempOptions.fontForge
}
} catch (error) {
throw `Error reading compile-options.json: ${error}`
}
}
return compileOptions
}
export const convertIconsToImages = async (dir, extension, size = 240) => {
const icons = getAllIcons()
await asyncForEach(Object.entries(icons), async function ([type, svgFiles]) {
fs.mkdirSync(path.join(dir, `./${type}`), { recursive: true })
await asyncForEach(svgFiles, async function (file, i) {
const distPath = path.join(dir, `./${type}/${file.name}.${extension}`)
process.stdout.write(`Building \`icons/${extension}\` ${type} ${i}/${svgFiles.length}: ${file.name.padEnd(42)}\r`)
await new Promise((resolve, reject) => {
exec(`rsvg-convert -f ${extension} -h ${size} ${file.path} > ${distPath}`, (error) => {
error ? reject() : resolve()
})
})
})
})
}
export const getMaxUnicode = () => {
const files = globSync(path.join(ICONS_SRC_DIR, '**/*.svg'))
let maxUnicode = 0
files.forEach(function (file) {
const svgFile = fs.readFileSync(file).toString()
svgFile.replace(/unicode: "([a-f0-9.]+)"/i, function (m, unicode) {
const newUnicode = parseInt(unicode, 16)
if (newUnicode) {
maxUnicode = Math.max(maxUnicode, newUnicode)
}
})
})
console.log(`Max unicode: ${maxUnicode}`)
return maxUnicode
}