index.cjs.js 4.8 KB

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