[6a3a178] | 1 | import postcss from 'postcss';
|
---|
| 2 | import valueParser from 'postcss-values-parser';
|
---|
| 3 |
|
---|
| 4 | // return whether a node is a valid comma
|
---|
| 5 | var getComma = (node => Object(node).type === 'comma');
|
---|
| 6 |
|
---|
| 7 | const imageSetFunctionMatchRegExp = /^(-webkit-)?image-set$/i; // return a valid image
|
---|
| 8 |
|
---|
| 9 | var getImage = (node => // <url> | <image()> | <cross-fade()> | <gradient>
|
---|
| 10 | // the image-set() function can not be nested inside of itself
|
---|
| 11 | 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);
|
---|
| 12 |
|
---|
| 13 | const dpiRatios = {
|
---|
| 14 | dpcm: 2.54,
|
---|
| 15 | dpi: 1,
|
---|
| 16 | dppx: 96,
|
---|
| 17 | x: 96
|
---|
| 18 | }; // return a valid @media rule
|
---|
| 19 |
|
---|
| 20 | var getMedia = ((node, mediasByDpr) => {
|
---|
| 21 | if (Object(node).type === 'number' && node.unit in dpiRatios) {
|
---|
| 22 | // calculate min-device-pixel-ratio and min-resolution
|
---|
| 23 | const dpi = Number(node.value) * dpiRatios[node.unit.toLowerCase()];
|
---|
| 24 | const dpr = Math.floor(dpi / dpiRatios.x * 100) / 100;
|
---|
| 25 |
|
---|
| 26 | if (dpi in mediasByDpr) {
|
---|
| 27 | return false;
|
---|
| 28 | } else {
|
---|
| 29 | const media = mediasByDpr[dpi] = postcss.atRule({
|
---|
| 30 | name: 'media',
|
---|
| 31 | params: `(-webkit-min-device-pixel-ratio: ${dpr}), (min-resolution: ${dpi}dpi)`
|
---|
| 32 | });
|
---|
| 33 | return media;
|
---|
| 34 | }
|
---|
| 35 | } else {
|
---|
| 36 | return false;
|
---|
| 37 | }
|
---|
| 38 | });
|
---|
| 39 |
|
---|
| 40 | var handleInvalidation = ((opts, message, word) => {
|
---|
| 41 | if (opts.oninvalid === 'warn') {
|
---|
| 42 | opts.decl.warn(opts.result, message, {
|
---|
| 43 | word: String(word)
|
---|
| 44 | });
|
---|
| 45 | } else if (opts.oninvalid === 'throw') {
|
---|
| 46 | throw opts.decl.error(message, {
|
---|
| 47 | word: String(word)
|
---|
| 48 | });
|
---|
| 49 | }
|
---|
| 50 | });
|
---|
| 51 |
|
---|
| 52 | var processImageSet = ((imageSetOptionNodes, decl, opts) => {
|
---|
| 53 | const parent = decl.parent;
|
---|
| 54 | const mediasByDpr = {};
|
---|
| 55 | let length = imageSetOptionNodes.length;
|
---|
| 56 | let index = -1;
|
---|
| 57 |
|
---|
| 58 | while (index < length) {
|
---|
| 59 | const _ref = [index < 0 ? true : getComma(imageSetOptionNodes[index]), getImage(imageSetOptionNodes[index + 1]), getMedia(imageSetOptionNodes[index + 2], mediasByDpr)],
|
---|
| 60 | comma = _ref[0],
|
---|
| 61 | value = _ref[1],
|
---|
| 62 | media = _ref[2]; // handle invalidations
|
---|
| 63 |
|
---|
| 64 | if (!comma) {
|
---|
| 65 | return handleInvalidation(opts, 'unexpected comma', imageSetOptionNodes[index]);
|
---|
| 66 | } else if (!value) {
|
---|
| 67 | return handleInvalidation(opts, 'unexpected image', imageSetOptionNodes[index + 1]);
|
---|
| 68 | } else if (!media) {
|
---|
| 69 | return handleInvalidation(opts, 'unexpected resolution', imageSetOptionNodes[index + 2]);
|
---|
| 70 | } // prepare @media { decl: <image> }
|
---|
| 71 |
|
---|
| 72 |
|
---|
| 73 | const parentClone = parent.clone().removeAll();
|
---|
| 74 | const declClone = decl.clone({
|
---|
| 75 | value
|
---|
| 76 | });
|
---|
| 77 | parentClone.append(declClone);
|
---|
| 78 | media.append(parentClone);
|
---|
| 79 | index += 3;
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | const medias = Object.keys(mediasByDpr).sort((a, b) => a - b).map(params => mediasByDpr[params]); // conditionally prepend previous siblings
|
---|
| 83 |
|
---|
| 84 | if (medias.length) {
|
---|
| 85 | const firstDecl = medias[0].nodes[0].nodes[0];
|
---|
| 86 |
|
---|
| 87 | if (medias.length === 1) {
|
---|
| 88 | decl.value = firstDecl.value;
|
---|
| 89 | } else {
|
---|
| 90 | const siblings = parent.nodes;
|
---|
| 91 | const previousSiblings = siblings.slice(0, siblings.indexOf(decl)).concat(firstDecl);
|
---|
| 92 |
|
---|
| 93 | if (previousSiblings.length) {
|
---|
| 94 | const parentClone = parent.cloneBefore().removeAll();
|
---|
| 95 | parentClone.append(previousSiblings);
|
---|
| 96 | } // prepend any @media { decl: <image> } rules
|
---|
| 97 |
|
---|
| 98 |
|
---|
| 99 | parent.before(medias.slice(1)); // conditionally remove the current rule
|
---|
| 100 |
|
---|
| 101 | if (!opts.preserve) {
|
---|
| 102 | decl.remove(); // and then conditionally remove its parent
|
---|
| 103 |
|
---|
| 104 | if (!parent.nodes.length) {
|
---|
| 105 | parent.remove();
|
---|
| 106 | }
|
---|
| 107 | }
|
---|
| 108 | }
|
---|
| 109 | }
|
---|
| 110 | });
|
---|
| 111 |
|
---|
| 112 | const imageSetValueMatchRegExp = /(^|[^\w-])(-webkit-)?image-set\(/;
|
---|
| 113 | const imageSetFunctionMatchRegExp$1 = /^(-webkit-)?image-set$/i;
|
---|
| 114 | var index = postcss.plugin('postcss-image-set-function', opts => {
|
---|
| 115 | // prepare options
|
---|
| 116 | const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : true;
|
---|
| 117 | const oninvalid = 'oninvalid' in Object(opts) ? opts.oninvalid : 'ignore';
|
---|
| 118 | return (root, result) => {
|
---|
| 119 | // for every declaration
|
---|
| 120 | root.walkDecls(decl => {
|
---|
| 121 | const value = decl.value; // if a declaration likely uses an image-set() function
|
---|
| 122 |
|
---|
| 123 | if (imageSetValueMatchRegExp.test(value)) {
|
---|
| 124 | const valueAST = valueParser(value).parse(); // process every image-set() function
|
---|
| 125 |
|
---|
| 126 | valueAST.walkType('func', node => {
|
---|
| 127 | if (imageSetFunctionMatchRegExp$1.test(node.value)) {
|
---|
| 128 | processImageSet(node.nodes.slice(1, -1), decl, {
|
---|
| 129 | decl,
|
---|
| 130 | oninvalid,
|
---|
| 131 | preserve,
|
---|
| 132 | result
|
---|
| 133 | });
|
---|
| 134 | }
|
---|
| 135 | });
|
---|
| 136 | }
|
---|
| 137 | });
|
---|
| 138 | };
|
---|
| 139 | });
|
---|
| 140 |
|
---|
| 141 | export default index;
|
---|
| 142 | //# sourceMappingURL=index.es.mjs.map
|
---|