mirror of https://github.com/keeweb/keeweb.git
109 lines
3.4 KiB
JavaScript
109 lines
3.4 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const SVGIcons2SVGFontStream = require('svgicons2svgfont');
|
|
const svg2ttf = require('svg2ttf');
|
|
const wawoff2 = require('wawoff2');
|
|
|
|
const svgBaseDir = path.resolve('node_modules/@fortawesome/fontawesome-free/svgs/');
|
|
const svgDirs = ['brands', 'regular', 'solid']
|
|
.map((dir) => path.join(svgBaseDir, dir))
|
|
.concat('graphics/svg');
|
|
|
|
const allIcons = {};
|
|
|
|
for (const svgDir of svgDirs) {
|
|
const suffix = svgDir.endsWith('regular') ? '-o' : '';
|
|
fs.readdirSync(path.join(svgDir))
|
|
.filter((icon) => icon.endsWith('.svg'))
|
|
.forEach((icon) => {
|
|
const svgIconPath = path.join(svgDir, icon);
|
|
const iconName = icon.substr(0, icon.length - 4) + suffix;
|
|
allIcons[iconName] = svgIconPath;
|
|
});
|
|
}
|
|
|
|
module.exports = function makeFontAwesomeWoff2() {
|
|
const callback = this.async();
|
|
if (this.cacheable) {
|
|
this.cacheable();
|
|
}
|
|
|
|
const iconFontScssPath = path.resolve('app/styles/base/_icon-font.scss');
|
|
this.addDependency(iconFontScssPath);
|
|
|
|
fs.readFile(iconFontScssPath, 'utf-8', async (err, scssSource) => {
|
|
if (err) {
|
|
return callback(err);
|
|
}
|
|
process.stdout.write('Building fontawesome.woff2... ');
|
|
const startTime = Date.now();
|
|
try {
|
|
const { fontData, iconsCount } = await buildFont(this, scssSource);
|
|
const kb = (fontData.byteLength / 1024).toFixed(2);
|
|
const time = Date.now() - startTime;
|
|
process.stdout.write(`ok: ${time}ms, ${iconsCount} icons, ${kb} KiB\n`);
|
|
const fontCss = fontData.toString('base64');
|
|
callback(null, `module.exports = "data:font/woff2;base64,${fontCss}"`);
|
|
} catch (ex) {
|
|
process.stdout.write('error\n');
|
|
callback(ex);
|
|
}
|
|
});
|
|
};
|
|
|
|
function buildFont(loader, scssSource) {
|
|
const includedIcons = {};
|
|
const includedIconList = [...scssSource.matchAll(/\n\$fa-var-([\w-]+):/g)].map(
|
|
([, name]) => name
|
|
);
|
|
for (const iconName of includedIconList) {
|
|
if (includedIcons[iconName]) {
|
|
throw new Error(`Duplicate icon: $fa-var-${iconName}`);
|
|
}
|
|
if (!allIcons[iconName]) {
|
|
throw new Error(`Icon not found: "${iconName}"`);
|
|
}
|
|
includedIcons[iconName] = true;
|
|
}
|
|
|
|
const fontStream = new SVGIcons2SVGFontStream({
|
|
fontName: 'Font Awesome 5 Free',
|
|
round: 10e12,
|
|
log() {}
|
|
});
|
|
|
|
const fontData = [];
|
|
fontStream.on('data', (chunk) => fontData.push(chunk));
|
|
|
|
let charCode = 0xf000;
|
|
for (const iconName of includedIconList) {
|
|
++charCode;
|
|
const svgIconPath = allIcons[iconName];
|
|
|
|
loader.addDependency(svgIconPath);
|
|
|
|
const glyph = fs.createReadStream(svgIconPath);
|
|
glyph.metadata = { name: iconName, unicode: [String.fromCharCode(charCode)] };
|
|
|
|
fontStream.write(glyph);
|
|
}
|
|
fontStream.end();
|
|
|
|
return new Promise((resolve, reject) => {
|
|
fontStream.on('end', async () => {
|
|
try {
|
|
let data = Buffer.concat(fontData);
|
|
data = Buffer.from(svg2ttf(data.toString('utf8')).buffer);
|
|
data = Buffer.from(await wawoff2.compress(data));
|
|
|
|
resolve({ fontData: data, iconsCount: includedIconList.length });
|
|
} catch (ex) {
|
|
reject(ex);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
module.exports.raw = true;
|