accounts-frontend/webpack-utils/fontgen-loader.js
2019-08-21 07:52:48 +03:00

202 lines
5.5 KiB
JavaScript

/* eslint-env node */
/**
* Forked from
*
* https://github.com/DragonsInn/fontgen-loader
*/
const loaderUtils = require('loader-utils');
const fontgen = require('webfonts-generator');
const path = require('path');
const glob = require('glob');
const mimeTypes = {
eot: 'application/vnd.ms-fontobject',
svg: 'image/svg+xml',
ttf: 'application/x-font-ttf',
woff: 'application/font-woff'
};
function absolute(from, to) {
if (arguments.length < 2) {
return function(to) {
return path.resolve(from, to);
};
}
return path.resolve(from, to);
}
function getFilesAndDeps(patterns, context) {
let files = [];
const filesDeps = [];
let directoryDeps = [];
function addFile(file) {
filesDeps.push(file);
files.push(absolute(context, file));
}
function addByGlob(globExp) {
const globOptions = { cwd: context };
const foundFiles = glob.sync(globExp, globOptions);
files = files.concat(foundFiles.map(absolute(context)));
const globDirs = glob.sync(`${path.dirname(globExp)}/`, globOptions);
directoryDeps = directoryDeps.concat(globDirs.map(absolute(context)));
}
// Re-work the files array.
patterns.forEach((pattern) => {
if (glob.hasMagic(pattern)) {
addByGlob(pattern);
} else {
addFile(pattern);
}
});
return {
files,
dependencies: {
directories: directoryDeps,
files: filesDeps
}
};
}
module.exports = function(content) {
this.cacheable();
const params = loaderUtils.getOptions(this) || {};
let config;
try {
config = JSON.parse(content);
} catch (ex) {
config = this.exec(content, this.resourcePath);
}
config.__dirname = path.dirname(this.resourcePath);
// Sanity check
/*
if(typeof config.fontName != "string" || typeof config.files != "array") {
this.reportError("Typemismatch in your config. Verify your config for correct types.");
return false;
}
*/
const filesAndDeps = getFilesAndDeps(config.files, this.context);
filesAndDeps.dependencies.files.forEach(this.addDependency.bind(this));
filesAndDeps.dependencies.directories.forEach(
this.addContextDependency.bind(this)
);
config.files = filesAndDeps.files;
// With everything set up, let's make an ACTUAL config.
let formats = config.types || ['eot', 'woff', 'ttf', 'svg'];
if (formats.constructor !== Array) {
formats = [formats];
}
const fontconf = {
files: config.files,
fontName: config.fontName,
types: formats,
order: formats,
fontHeight: config.fontHeight || 1000, // Fixes conversion issues with small svgs
templateOptions: {
baseClass: config.baseClass || 'icon',
classPrefix: 'classPrefix' in config ? config.classPrefix : 'icon-'
},
dest: '',
writeFiles: false,
formatOptions: config.formatOptions || {}
};
// This originally was in the object notation itself.
// Unfortunately that actually broke my editor's syntax-highlighting...
// ... what a shame.
if (typeof config.rename == 'function') {
fontconf.rename = config.rename;
} else {
fontconf.rename = function(filePath) {
return path.basename(filePath, '.svg');
};
}
if (config.cssTemplate) {
fontconf.cssTemplate = absolute(this.context, config.cssTemplate);
}
for (const option in config.templateOptions) {
if (config.templateOptions.hasOwnProperty(option)) {
fontconf.templateOptions[option] = config.templateOptions[option];
}
}
// svgicons2svgfont stuff
const keys = [
'fixedWidth',
'centerHorizontally',
'normalize',
'fontHeight',
'round',
'descent'
];
for (const x in keys) {
if (typeof config[keys[x]] != 'undefined') {
fontconf[keys[x]] = config[keys[x]];
}
}
const cb = this.async();
const opts = this._compiler.options;
const pub = opts.output.publicPath || '/';
const embed = !!params.embed;
if (fontconf.cssTemplate) {
this.addDependency(fontconf.cssTemplate);
}
fontgen(fontconf, (err, res) => {
if (err) {
return cb(err);
}
const urls = {};
for (const i in formats) {
const format = formats[i];
if (embed) {
urls[format] = `data:${
mimeTypes[format]
};charset=utf-8;base64,${new Buffer(res[format]).toString(
'base64'
)}`;
} else {
let filename
= config.fileName
|| params.fileName
|| '[hash]-[fontname][ext]';
filename = filename
.replace('[fontname]', fontconf.fontName)
.replace('[ext]', `.${format}`);
const url = loaderUtils.interpolateName(
this.context,
filename,
{
content: res[format]
}
);
urls[format] = path.join(pub, url).replace(/\\/g, '/');
this.emitFile(url, res[format]);
}
}
const code = res.generateCss(urls);
cb(null, `module.exports = ${JSON.stringify(code)}`);
});
};