gradient.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. "use strict";
  2. function _defaults(obj, defaults) { var keys = Object.getOwnPropertyNames(defaults); for (var i = 0; i < keys.length; i++) { var key = keys[i]; var value = Object.getOwnPropertyDescriptor(defaults, key); if (value && value.configurable && obj[key] === undefined) { Object.defineProperty(obj, key, value); } } return obj; }
  3. function _createForOfIteratorHelperLoose(o) { var i = 0; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) return function () { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }; throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } i = o[Symbol.iterator](); return i.next.bind(i); }
  4. function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(n); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
  5. function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
  6. function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
  7. function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
  8. function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
  9. function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
  10. function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
  11. function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; _defaults(subClass, superClass); }
  12. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  13. var parser = require('postcss-value-parser');
  14. var range = require('normalize-range');
  15. var OldValue = require('../old-value');
  16. var Value = require('../value');
  17. var utils = require('../utils');
  18. var IS_DIRECTION = /top|left|right|bottom/gi;
  19. var Gradient = /*#__PURE__*/function (_Value) {
  20. _inheritsLoose(Gradient, _Value);
  21. var _super = _createSuper(Gradient);
  22. function Gradient() {
  23. var _this;
  24. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  25. args[_key] = arguments[_key];
  26. }
  27. _this = _Value.call.apply(_Value, [this].concat(args)) || this;
  28. _defineProperty(_assertThisInitialized(_this), "directions", {
  29. top: 'bottom',
  30. left: 'right',
  31. bottom: 'top',
  32. right: 'left'
  33. });
  34. _defineProperty(_assertThisInitialized(_this), "oldDirections", {
  35. 'top': 'left bottom, left top',
  36. 'left': 'right top, left top',
  37. 'bottom': 'left top, left bottom',
  38. 'right': 'left top, right top',
  39. 'top right': 'left bottom, right top',
  40. 'top left': 'right bottom, left top',
  41. 'right top': 'left bottom, right top',
  42. 'right bottom': 'left top, right bottom',
  43. 'bottom right': 'left top, right bottom',
  44. 'bottom left': 'right top, left bottom',
  45. 'left top': 'right bottom, left top',
  46. 'left bottom': 'right top, left bottom'
  47. });
  48. return _this;
  49. }
  50. var _proto = Gradient.prototype;
  51. /**
  52. * Change degrees for webkit prefix
  53. */
  54. _proto.replace = function replace(string, prefix) {
  55. var ast = parser(string);
  56. for (var _iterator = _createForOfIteratorHelperLoose(ast.nodes), _step; !(_step = _iterator()).done;) {
  57. var node = _step.value;
  58. if (node.type === 'function' && node.value === this.name) {
  59. node.nodes = this.newDirection(node.nodes);
  60. node.nodes = this.normalize(node.nodes);
  61. if (prefix === '-webkit- old') {
  62. var changes = this.oldWebkit(node);
  63. if (!changes) {
  64. return false;
  65. }
  66. } else {
  67. node.nodes = this.convertDirection(node.nodes);
  68. node.value = prefix + node.value;
  69. }
  70. }
  71. }
  72. return ast.toString();
  73. }
  74. /**
  75. * Replace first token
  76. */
  77. ;
  78. _proto.replaceFirst = function replaceFirst(params) {
  79. for (var _len2 = arguments.length, words = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
  80. words[_key2 - 1] = arguments[_key2];
  81. }
  82. var prefix = words.map(function (i) {
  83. if (i === ' ') {
  84. return {
  85. type: 'space',
  86. value: i
  87. };
  88. }
  89. return {
  90. type: 'word',
  91. value: i
  92. };
  93. });
  94. return prefix.concat(params.slice(1));
  95. }
  96. /**
  97. * Convert angle unit to deg
  98. */
  99. ;
  100. _proto.normalizeUnit = function normalizeUnit(str, full) {
  101. var num = parseFloat(str);
  102. var deg = num / full * 360;
  103. return deg + "deg";
  104. }
  105. /**
  106. * Normalize angle
  107. */
  108. ;
  109. _proto.normalize = function normalize(nodes) {
  110. if (!nodes[0]) return nodes;
  111. if (/-?\d+(.\d+)?grad/.test(nodes[0].value)) {
  112. nodes[0].value = this.normalizeUnit(nodes[0].value, 400);
  113. } else if (/-?\d+(.\d+)?rad/.test(nodes[0].value)) {
  114. nodes[0].value = this.normalizeUnit(nodes[0].value, 2 * Math.PI);
  115. } else if (/-?\d+(.\d+)?turn/.test(nodes[0].value)) {
  116. nodes[0].value = this.normalizeUnit(nodes[0].value, 1);
  117. } else if (nodes[0].value.includes('deg')) {
  118. var num = parseFloat(nodes[0].value);
  119. num = range.wrap(0, 360, num);
  120. nodes[0].value = num + "deg";
  121. }
  122. if (nodes[0].value === '0deg') {
  123. nodes = this.replaceFirst(nodes, 'to', ' ', 'top');
  124. } else if (nodes[0].value === '90deg') {
  125. nodes = this.replaceFirst(nodes, 'to', ' ', 'right');
  126. } else if (nodes[0].value === '180deg') {
  127. nodes = this.replaceFirst(nodes, 'to', ' ', 'bottom');
  128. } else if (nodes[0].value === '270deg') {
  129. nodes = this.replaceFirst(nodes, 'to', ' ', 'left');
  130. }
  131. return nodes;
  132. }
  133. /**
  134. * Replace old direction to new
  135. */
  136. ;
  137. _proto.newDirection = function newDirection(params) {
  138. if (params[0].value === 'to') {
  139. return params;
  140. }
  141. IS_DIRECTION.lastIndex = 0; // reset search index of global regexp
  142. if (!IS_DIRECTION.test(params[0].value)) {
  143. return params;
  144. }
  145. params.unshift({
  146. type: 'word',
  147. value: 'to'
  148. }, {
  149. type: 'space',
  150. value: ' '
  151. });
  152. for (var i = 2; i < params.length; i++) {
  153. if (params[i].type === 'div') {
  154. break;
  155. }
  156. if (params[i].type === 'word') {
  157. params[i].value = this.revertDirection(params[i].value);
  158. }
  159. }
  160. return params;
  161. }
  162. /**
  163. * Look for at word
  164. */
  165. ;
  166. _proto.isRadial = function isRadial(params) {
  167. var state = 'before';
  168. for (var _iterator2 = _createForOfIteratorHelperLoose(params), _step2; !(_step2 = _iterator2()).done;) {
  169. var param = _step2.value;
  170. if (state === 'before' && param.type === 'space') {
  171. state = 'at';
  172. } else if (state === 'at' && param.value === 'at') {
  173. state = 'after';
  174. } else if (state === 'after' && param.type === 'space') {
  175. return true;
  176. } else if (param.type === 'div') {
  177. break;
  178. } else {
  179. state = 'before';
  180. }
  181. }
  182. return false;
  183. }
  184. /**
  185. * Change new direction to old
  186. */
  187. ;
  188. _proto.convertDirection = function convertDirection(params) {
  189. if (params.length > 0) {
  190. if (params[0].value === 'to') {
  191. this.fixDirection(params);
  192. } else if (params[0].value.includes('deg')) {
  193. this.fixAngle(params);
  194. } else if (this.isRadial(params)) {
  195. this.fixRadial(params);
  196. }
  197. }
  198. return params;
  199. }
  200. /**
  201. * Replace `to top left` to `bottom right`
  202. */
  203. ;
  204. _proto.fixDirection = function fixDirection(params) {
  205. params.splice(0, 2);
  206. for (var _iterator3 = _createForOfIteratorHelperLoose(params), _step3; !(_step3 = _iterator3()).done;) {
  207. var param = _step3.value;
  208. if (param.type === 'div') {
  209. break;
  210. }
  211. if (param.type === 'word') {
  212. param.value = this.revertDirection(param.value);
  213. }
  214. }
  215. }
  216. /**
  217. * Add 90 degrees
  218. */
  219. ;
  220. _proto.fixAngle = function fixAngle(params) {
  221. var first = params[0].value;
  222. first = parseFloat(first);
  223. first = Math.abs(450 - first) % 360;
  224. first = this.roundFloat(first, 3);
  225. params[0].value = first + "deg";
  226. }
  227. /**
  228. * Fix radial direction syntax
  229. */
  230. ;
  231. _proto.fixRadial = function fixRadial(params) {
  232. var first = [];
  233. var second = [];
  234. var a, b, c, i, next;
  235. for (i = 0; i < params.length - 2; i++) {
  236. a = params[i];
  237. b = params[i + 1];
  238. c = params[i + 2];
  239. if (a.type === 'space' && b.value === 'at' && c.type === 'space') {
  240. next = i + 3;
  241. break;
  242. } else {
  243. first.push(a);
  244. }
  245. }
  246. var div;
  247. for (i = next; i < params.length; i++) {
  248. if (params[i].type === 'div') {
  249. div = params[i];
  250. break;
  251. } else {
  252. second.push(params[i]);
  253. }
  254. }
  255. params.splice.apply(params, [0, i].concat(second, [div], first));
  256. };
  257. _proto.revertDirection = function revertDirection(word) {
  258. return this.directions[word.toLowerCase()] || word;
  259. }
  260. /**
  261. * Round float and save digits under dot
  262. */
  263. ;
  264. _proto.roundFloat = function roundFloat(_float, digits) {
  265. return parseFloat(_float.toFixed(digits));
  266. }
  267. /**
  268. * Convert to old webkit syntax
  269. */
  270. ;
  271. _proto.oldWebkit = function oldWebkit(node) {
  272. var nodes = node.nodes;
  273. var string = parser.stringify(node.nodes);
  274. if (this.name !== 'linear-gradient') {
  275. return false;
  276. }
  277. if (nodes[0] && nodes[0].value.includes('deg')) {
  278. return false;
  279. }
  280. if (string.includes('px') || string.includes('-corner') || string.includes('-side')) {
  281. return false;
  282. }
  283. var params = [[]];
  284. for (var _iterator4 = _createForOfIteratorHelperLoose(nodes), _step4; !(_step4 = _iterator4()).done;) {
  285. var i = _step4.value;
  286. params[params.length - 1].push(i);
  287. if (i.type === 'div' && i.value === ',') {
  288. params.push([]);
  289. }
  290. }
  291. this.oldDirection(params);
  292. this.colorStops(params);
  293. node.nodes = [];
  294. for (var _i = 0, _params = params; _i < _params.length; _i++) {
  295. var param = _params[_i];
  296. node.nodes = node.nodes.concat(param);
  297. }
  298. node.nodes.unshift({
  299. type: 'word',
  300. value: 'linear'
  301. }, this.cloneDiv(node.nodes));
  302. node.value = '-webkit-gradient';
  303. return true;
  304. }
  305. /**
  306. * Change direction syntax to old webkit
  307. */
  308. ;
  309. _proto.oldDirection = function oldDirection(params) {
  310. var div = this.cloneDiv(params[0]);
  311. if (params[0][0].value !== 'to') {
  312. return params.unshift([{
  313. type: 'word',
  314. value: this.oldDirections.bottom
  315. }, div]);
  316. } else {
  317. var words = [];
  318. for (var _iterator5 = _createForOfIteratorHelperLoose(params[0].slice(2)), _step5; !(_step5 = _iterator5()).done;) {
  319. var node = _step5.value;
  320. if (node.type === 'word') {
  321. words.push(node.value.toLowerCase());
  322. }
  323. }
  324. words = words.join(' ');
  325. var old = this.oldDirections[words] || words;
  326. params[0] = [{
  327. type: 'word',
  328. value: old
  329. }, div];
  330. return params[0];
  331. }
  332. }
  333. /**
  334. * Get div token from exists parameters
  335. */
  336. ;
  337. _proto.cloneDiv = function cloneDiv(params) {
  338. for (var _iterator6 = _createForOfIteratorHelperLoose(params), _step6; !(_step6 = _iterator6()).done;) {
  339. var i = _step6.value;
  340. if (i.type === 'div' && i.value === ',') {
  341. return i;
  342. }
  343. }
  344. return {
  345. type: 'div',
  346. value: ',',
  347. after: ' '
  348. };
  349. }
  350. /**
  351. * Change colors syntax to old webkit
  352. */
  353. ;
  354. _proto.colorStops = function colorStops(params) {
  355. var result = [];
  356. for (var i = 0; i < params.length; i++) {
  357. var pos = void 0;
  358. var param = params[i];
  359. var item = void 0;
  360. if (i === 0) {
  361. continue;
  362. }
  363. var color = parser.stringify(param[0]);
  364. if (param[1] && param[1].type === 'word') {
  365. pos = param[1].value;
  366. } else if (param[2] && param[2].type === 'word') {
  367. pos = param[2].value;
  368. }
  369. var stop = void 0;
  370. if (i === 1 && (!pos || pos === '0%')) {
  371. stop = "from(" + color + ")";
  372. } else if (i === params.length - 1 && (!pos || pos === '100%')) {
  373. stop = "to(" + color + ")";
  374. } else if (pos) {
  375. stop = "color-stop(" + pos + ", " + color + ")";
  376. } else {
  377. stop = "color-stop(" + color + ")";
  378. }
  379. var div = param[param.length - 1];
  380. params[i] = [{
  381. type: 'word',
  382. value: stop
  383. }];
  384. if (div.type === 'div' && div.value === ',') {
  385. item = params[i].push(div);
  386. }
  387. result.push(item);
  388. }
  389. return result;
  390. }
  391. /**
  392. * Remove old WebKit gradient too
  393. */
  394. ;
  395. _proto.old = function old(prefix) {
  396. if (prefix === '-webkit-') {
  397. var type = this.name === 'linear-gradient' ? 'linear' : 'radial';
  398. var string = '-gradient';
  399. var regexp = utils.regexp("-webkit-(" + type + "-gradient|gradient\\(\\s*" + type + ")", false);
  400. return new OldValue(this.name, prefix + this.name, string, regexp);
  401. } else {
  402. return _Value.prototype.old.call(this, prefix);
  403. }
  404. }
  405. /**
  406. * Do not add non-webkit prefixes for list-style and object
  407. */
  408. ;
  409. _proto.add = function add(decl, prefix) {
  410. var p = decl.prop;
  411. if (p.includes('mask')) {
  412. if (prefix === '-webkit-' || prefix === '-webkit- old') {
  413. return _Value.prototype.add.call(this, decl, prefix);
  414. }
  415. } else if (p === 'list-style' || p === 'list-style-image' || p === 'content') {
  416. if (prefix === '-webkit-' || prefix === '-webkit- old') {
  417. return _Value.prototype.add.call(this, decl, prefix);
  418. }
  419. } else {
  420. return _Value.prototype.add.call(this, decl, prefix);
  421. }
  422. return undefined;
  423. };
  424. return Gradient;
  425. }(Value);
  426. _defineProperty(Gradient, "names", ['linear-gradient', 'repeating-linear-gradient', 'radial-gradient', 'repeating-radial-gradient']);
  427. module.exports = Gradient;