postcss-minify-font-values
Version:
Minify font declarations with PostCSS
123 lines (103 loc) • 3.25 kB
JavaScript
import minifyWeight from './lib/minify-weight.js';
import minifyFamily from './lib/minify-family.js';
import minifyFont from './lib/minify-font.js';
import cssnanoUtils from 'cssnano-utils';
const { asciiLowerCase } = cssnanoUtils;
const fontRegex =
/^(?:[fF][oO][nN][tT]|[fF][oO][nN][tT]-[fF][aA][mM][iI][lL][yY]|[fF][oO][nN][tT]-[wW][eE][iI][gG][hH][tT])$/v;
/**
* @param {string} value
* @return {boolean}
*/
function hasVariableFunction(value) {
const lowerCasedValue = asciiLowerCase(value);
return lowerCasedValue.includes('var(') || lowerCasedValue.includes('env(');
}
/** @type {Map<string, (value: string, opts: Options, removeQuotes: boolean | ((prop: string) => '' | 'font' | 'font-family' | 'font-weight') | undefined) => string>} */
const propertyMinifiers = new Map([
[
'font-weight',
(value) => (hasVariableFunction(value) ? value : minifyWeight(value)),
],
[
'font-family',
(value, opts, removeQuotes) =>
hasVariableFunction(value)
? value
: minifyFamily(value, opts, removeQuotes),
],
[
'font',
(value, opts, removeQuotes) => minifyFont(value, opts, removeQuotes),
],
]);
/**
* @param {string} prop
* @param {string} value
* @param {Options} opts
* @return {string}
*/
function transform(prop, value, opts) {
let targetType = asciiLowerCase(prop);
let removeQuotes = opts.removeQuotes;
if (typeof opts.removeQuotes === 'function') {
targetType = opts.removeQuotes(prop) || targetType;
removeQuotes = true;
}
const minifier = propertyMinifiers.get(targetType);
if (minifier) {
return minifier(value, opts, removeQuotes);
}
return value;
}
/** @typedef {{removeAfterKeyword?: boolean, removeDuplicates?: boolean, removeQuotes?: boolean | ((prop: string) => '' | 'font' | 'font-family' | 'font-weight')}} Options */
/**
* @param {Options} opts
* @return {import('postcss').Plugin}
*/
function pluginCreator(opts) {
const normalizedOpts = {
removeAfterKeyword: false,
removeDuplicates: true,
removeQuotes: true,
...opts,
};
return {
postcssPlugin: 'postcss-minify-font-values',
prepare() {
const cache = new Map();
return {
/**
* @param {import('postcss').Root} css
*/
OnceExit(css) {
/** @param {import('postcss').Declaration} decl */
const handleDecl = (decl) => {
const value = decl.value;
if (!value) {
return;
}
const prop = decl.prop;
const cacheKey = `${prop}|${value}`;
if (cache.has(cacheKey)) {
decl.value = cache.get(cacheKey);
return;
}
const newValue = transform(prop, value, normalizedOpts);
decl.value = newValue;
cache.set(cacheKey, newValue);
};
if (typeof normalizedOpts.removeQuotes === 'function') {
css.walkDecls(handleDecl);
} else {
css.walkDecls(fontRegex, handleDecl);
}
},
};
},
};
}
/** @type {true} */
pluginCreator.postcss = true;
const moduleExports = pluginCreator;
export { moduleExports as default, moduleExports as 'module.exports' };