You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
4.6 KiB

4 years ago
import postcss from 'postcss';
import valueParser from 'postcss-values-parser';
// return whether a node is a valid comma
var getComma = (node => Object(node).type === 'comma');
const imageSetFunctionMatchRegExp = /^(-webkit-)?image-set$/i; // return a valid image
var getImage = (node => // <url> | <image()> | <cross-fade()> | <gradient>
// the image-set() function can not be nested inside of itself
Object(node).type === 'func' && /^(cross-fade|image|(repeating-)?(conic|linear|radial)-gradient|url)$/i.test(node.value) && !(node.parent.parent && node.parent.parent.type === 'func' && imageSetFunctionMatchRegExp.test(node.parent.parent.value)) ? String(node) : Object(node).type === 'string' ? node.value : false);
const dpiRatios = {
dpcm: 2.54,
dpi: 1,
dppx: 96,
x: 96
}; // return a valid @media rule
var getMedia = ((node, mediasByDpr) => {
if (Object(node).type === 'number' && node.unit in dpiRatios) {
// calculate min-device-pixel-ratio and min-resolution
const dpi = Number(node.value) * dpiRatios[node.unit.toLowerCase()];
const dpr = Math.floor(dpi / dpiRatios.x * 100) / 100;
if (dpi in mediasByDpr) {
return false;
} else {
const media = mediasByDpr[dpi] = postcss.atRule({
name: 'media',
params: `(-webkit-min-device-pixel-ratio: ${dpr}), (min-resolution: ${dpi}dpi)`
});
return media;
}
} else {
return false;
}
});
var handleInvalidation = ((opts, message, word) => {
if (opts.oninvalid === 'warn') {
opts.decl.warn(opts.result, message, {
word: String(word)
});
} else if (opts.oninvalid === 'throw') {
throw opts.decl.error(message, {
word: String(word)
});
}
});
var processImageSet = ((imageSetOptionNodes, decl, opts) => {
const parent = decl.parent;
const mediasByDpr = {};
let length = imageSetOptionNodes.length;
let index = -1;
while (index < length) {
const _ref = [index < 0 ? true : getComma(imageSetOptionNodes[index]), getImage(imageSetOptionNodes[index + 1]), getMedia(imageSetOptionNodes[index + 2], mediasByDpr)],
comma = _ref[0],
value = _ref[1],
media = _ref[2]; // handle invalidations
if (!comma) {
return handleInvalidation(opts, 'unexpected comma', imageSetOptionNodes[index]);
} else if (!value) {
return handleInvalidation(opts, 'unexpected image', imageSetOptionNodes[index + 1]);
} else if (!media) {
return handleInvalidation(opts, 'unexpected resolution', imageSetOptionNodes[index + 2]);
} // prepare @media { decl: <image> }
const parentClone = parent.clone().removeAll();
const declClone = decl.clone({
value
});
parentClone.append(declClone);
media.append(parentClone);
index += 3;
}
const medias = Object.keys(mediasByDpr).sort((a, b) => a - b).map(params => mediasByDpr[params]); // conditionally prepend previous siblings
if (medias.length) {
const firstDecl = medias[0].nodes[0].nodes[0];
if (medias.length === 1) {
decl.value = firstDecl.value;
} else {
const siblings = parent.nodes;
const previousSiblings = siblings.slice(0, siblings.indexOf(decl)).concat(firstDecl);
if (previousSiblings.length) {
const parentClone = parent.cloneBefore().removeAll();
parentClone.append(previousSiblings);
} // prepend any @media { decl: <image> } rules
parent.before(medias.slice(1)); // conditionally remove the current rule
if (!opts.preserve) {
decl.remove(); // and then conditionally remove its parent
if (!parent.nodes.length) {
parent.remove();
}
}
}
}
});
const imageSetValueMatchRegExp = /(^|[^\w-])(-webkit-)?image-set\(/;
const imageSetFunctionMatchRegExp$1 = /^(-webkit-)?image-set$/i;
var index = postcss.plugin('postcss-image-set-function', opts => {
// prepare options
const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : true;
const oninvalid = 'oninvalid' in Object(opts) ? opts.oninvalid : 'ignore';
return (root, result) => {
// for every declaration
root.walkDecls(decl => {
const value = decl.value; // if a declaration likely uses an image-set() function
if (imageSetValueMatchRegExp.test(value)) {
const valueAST = valueParser(value).parse(); // process every image-set() function
valueAST.walkType('func', node => {
if (imageSetFunctionMatchRegExp$1.test(node.value)) {
processImageSet(node.nodes.slice(1, -1), decl, {
decl,
oninvalid,
preserve,
result
});
}
});
}
});
};
});
export default index;
//# sourceMappingURL=index.es.mjs.map