packages/posthtml-transform/lib/utils.js (68 lines of code) (raw):
/* eslint-disable no-shadow */
const { parseQuery } = require('loader-utils');
const { isEmpty, cloneDeep } = require('lodash');
const colorParser = require('color-parse');
const { name: packageName } = require('../package.json');
const Rule = require('./rule');
/**
* @param {string} value
* @return {{space: string, alpha: number, values: number[]}|null}
*/
function parseColor(value) {
const parsed = colorParser(value);
return parsed.space && !isEmpty(parsed.values) ? parsed : null;
}
module.exports.parseColor = parseColor;
function convertAlphaColorsRules(rules) {
const additionalRules = [];
const transformedRules = rules.map(rule => {
const clonedRule = cloneDeep(rule);
const opacityRule = cloneDeep(rule);
const fillColor = rule.value && rule.attr && rule.attr === 'fill'
? parseColor(rule.value)
: null;
const strokeColor = rule.value && rule.attr && rule.attr === 'stroke'
? parseColor(rule.value)
: null;
if (fillColor && fillColor.alpha < 1) {
clonedRule.value = `${fillColor.space}(${fillColor.values.join(', ')})`;
opacityRule.attr = 'fill-opacity';
opacityRule.value = fillColor.alpha.toString();
additionalRules.push({ rule: clonedRule, ruleToAppend: opacityRule });
}
if (strokeColor && strokeColor.alpha < 1) {
clonedRule.value = `${strokeColor.space}(${strokeColor.values.join(', ')})`;
opacityRule.attr = 'stroke-opacity';
opacityRule.value = strokeColor.alpha.toString();
additionalRules.push({ rule: clonedRule, ruleToAppend: opacityRule });
}
return clonedRule;
});
additionalRules.forEach(({ rule, ruleToAppend }) => {
transformedRules.splice(transformedRules.indexOf(rule) + 1, 0, ruleToAppend);
});
return transformedRules;
}
module.exports.convertAlphaColorsRules = convertAlphaColorsRules;
/**
* @param {Object[]|string} rules
* @param {Object} options
* @return {Rule[]}
*/
function normalizeRules(rules, options = {}) {
let normalized = null;
// Parse query string to rules
if (typeof rules === 'string') {
// Append ? to the beginning so parseQuery able to parse
const query = rules.substr(0, 1) !== '?' ? `?${rules}` : rules;
const parsedQuery = parseQuery(query);
normalized = Object.keys(parsedQuery).reduce((rules, attr) => {
const value = parsedQuery[attr];
rules.push(new Rule({ attr, value }));
return rules;
}, []);
} else if (Array.isArray(rules)) {
normalized = cloneDeep(rules).map(r => new Rule(r));
} else {
throw new Error(`${packageName}: rules should be \`Array<Object>|string\``);
}
// Split rule with multiple value into several single valued rules
const replacements = normalized
.filter(rule => rule.isMultiple)
.map(rule => ({ rule, replaceTo: rule.splitByMultipleValue() }));
replacements.forEach(({ rule, replaceTo }) => {
normalized.splice(...[normalized.indexOf(rule), 1].concat(replaceTo));
});
if (options.convertAlphaColors) {
normalized = convertAlphaColorsRules(normalized);
}
return normalized;
}
module.exports.normalizeRules = normalizeRules;