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.

121 lines
3.4 KiB

4 years ago
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. var _path = require('path');
  6. var _path2 = _interopRequireDefault(_path);
  7. var _postcss = require('postcss');
  8. var _postcss2 = _interopRequireDefault(_postcss);
  9. var _postcssValueParser = require('postcss-value-parser');
  10. var _postcssValueParser2 = _interopRequireDefault(_postcssValueParser);
  11. var _normalizeUrl = require('normalize-url');
  12. var _normalizeUrl2 = _interopRequireDefault(_normalizeUrl);
  13. var _isAbsoluteUrl = require('is-absolute-url');
  14. var _isAbsoluteUrl2 = _interopRequireDefault(_isAbsoluteUrl);
  15. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  16. const multiline = /\\[\r\n]/;
  17. const escapeChars = /([\s\(\)"'])/g;
  18. function convert(url, options) {
  19. if ((0, _isAbsoluteUrl2.default)(url) || url.startsWith('//')) {
  20. let normalizedURL = null;
  21. try {
  22. normalizedURL = (0, _normalizeUrl2.default)(url, options);
  23. } catch (e) {
  24. normalizedURL = url;
  25. }
  26. return normalizedURL;
  27. }
  28. // `path.normalize` always returns backslashes on Windows, need replace in `/`
  29. return _path2.default.normalize(url).replace(new RegExp('\\' + _path2.default.sep, 'g'), '/');
  30. }
  31. function transformNamespace(rule) {
  32. rule.params = (0, _postcssValueParser2.default)(rule.params).walk(node => {
  33. if (node.type === 'function' && node.value.toLowerCase() === 'url' && node.nodes.length) {
  34. node.type = 'string';
  35. node.quote = node.nodes[0].quote || '"';
  36. node.value = node.nodes[0].value;
  37. }
  38. if (node.type === 'string') {
  39. node.value = node.value.trim();
  40. }
  41. return false;
  42. }).toString();
  43. }
  44. function transformDecl(decl, opts) {
  45. decl.value = (0, _postcssValueParser2.default)(decl.value).walk(node => {
  46. if (node.type !== 'function' || node.value.toLowerCase() !== 'url' || !node.nodes.length) {
  47. return false;
  48. }
  49. let url = node.nodes[0];
  50. let escaped;
  51. node.before = node.after = '';
  52. url.value = url.value.trim().replace(multiline, '');
  53. // Skip empty URLs
  54. // Empty URL function equals request to current stylesheet where it is declared
  55. if (url.value.length === 0) {
  56. url.quote = '';
  57. return false;
  58. }
  59. if (/^data:(.*)?,/i.test(url.value)) {
  60. return false;
  61. }
  62. if (!/^.+-extension:\//i.test(url.value)) {
  63. url.value = convert(url.value, opts);
  64. }
  65. if (escapeChars.test(url.value) && url.type === 'string') {
  66. escaped = url.value.replace(escapeChars, '\\$1');
  67. if (escaped.length < url.value.length + 2) {
  68. url.value = escaped;
  69. url.type = 'word';
  70. }
  71. } else {
  72. url.type = 'word';
  73. }
  74. return false;
  75. }).toString();
  76. }
  77. exports.default = _postcss2.default.plugin('postcss-normalize-url', opts => {
  78. opts = Object.assign({}, {
  79. normalizeProtocol: false,
  80. stripFragment: false,
  81. stripWWW: false
  82. }, opts);
  83. return css => {
  84. css.walk(node => {
  85. if (node.type === 'decl') {
  86. return transformDecl(node, opts);
  87. } else if (node.type === 'atrule' && node.name.toLowerCase() === 'namespace') {
  88. return transformNamespace(node);
  89. }
  90. });
  91. };
  92. });
  93. module.exports = exports['default'];