postcss-minify-gradients 5.0.5 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "postcss-minify-gradients",
3
- "version": "5.0.5",
3
+ "version": "5.1.1",
4
4
  "description": "Minify gradient parameters with PostCSS.",
5
- "main": "dist/index.js",
5
+ "main": "src/index.js",
6
+ "types": "types/index.d.ts",
6
7
  "files": [
7
8
  "LICENSE-MIT",
8
- "dist"
9
+ "src",
10
+ "types"
9
11
  ],
10
12
  "keywords": [
11
13
  "css",
@@ -22,7 +24,7 @@
22
24
  "repository": "cssnano/cssnano",
23
25
  "dependencies": {
24
26
  "colord": "^2.9.1",
25
- "cssnano-utils": "^3.0.1",
27
+ "cssnano-utils": "^3.1.0",
26
28
  "postcss-value-parser": "^4.2.0"
27
29
  },
28
30
  "bugs": {
@@ -37,9 +39,5 @@
37
39
  "peerDependencies": {
38
40
  "postcss": "^8.2.15"
39
41
  },
40
- "scripts": {
41
- "prebuild": "rimraf dist",
42
- "build": "babel src --config-file ../../babel.config.json --out-dir dist --ignore \"**/__tests__/\""
43
- },
44
42
  "readme": "# [postcss][postcss]-minify-gradients\n\n> Minify gradient parameters with PostCSS.\n\n## Install\n\nWith [npm](https://npmjs.org/package/postcss-minify-gradients) do:\n\n```\nnpm install postcss-minify-gradients\n```\n\n\n## Example\n\nWhere possible, this module will minify gradient parameters. It can convert\nlinear gradient directional syntax to angles, remove the unnecessary `0%` and\n`100%` start and end values, and minimise color stops that use the same length\nvalues (the browser will adjust the value automatically).\n\n### Input\n\n```css\nh1 {\n background: linear-gradient(to bottom, #ffe500 0%, #ffe500 50%, #121 50%, #121 100%)\n}\n```\n\n### Output\n\n```css\nh1 {\n background: linear-gradient(180deg, #ffe500, #ffe500 50%, #121 0, #121)\n}\n```\n\n\n## Usage\n\nSee the [PostCSS documentation](https://github.com/postcss/postcss#usage) for\nexamples for your environment.\n\n\n## Contributors\n\nSee [CONTRIBUTORS.md](https://github.com/cssnano/cssnano/blob/master/CONTRIBUTORS.md).\n\n\n## License\n\nMIT © [Ben Briggs](http://beneb.info)\n\n[postcss]: https://github.com/postcss/postcss\n"
45
43
  }
package/src/index.js ADDED
@@ -0,0 +1,224 @@
1
+ 'use strict';
2
+ const valueParser = require('postcss-value-parser');
3
+ const { getArguments } = require('cssnano-utils');
4
+ const isColorStop = require('./isColorStop.js');
5
+
6
+ const angles = {
7
+ top: '0deg',
8
+ right: '90deg',
9
+ bottom: '180deg',
10
+ left: '270deg',
11
+ };
12
+
13
+ /**
14
+ * @param {valueParser.Dimension} a
15
+ * @param {valueParser.Dimension} b
16
+ * @return {boolean}
17
+ */
18
+ function isLessThan(a, b) {
19
+ return (
20
+ a.unit.toLowerCase() === b.unit.toLowerCase() &&
21
+ parseFloat(a.number) >= parseFloat(b.number)
22
+ );
23
+ }
24
+ /**
25
+ * @param {import('postcss').Declaration} decl
26
+ * @return {void}
27
+ */
28
+ function optimise(decl) {
29
+ const value = decl.value;
30
+
31
+ if (!value) {
32
+ return;
33
+ }
34
+
35
+ const normalizedValue = value.toLowerCase();
36
+
37
+ if (normalizedValue.includes('var(') || normalizedValue.includes('env(')) {
38
+ return;
39
+ }
40
+
41
+ if (!normalizedValue.includes('gradient')) {
42
+ return;
43
+ }
44
+
45
+ decl.value = valueParser(value)
46
+ .walk((node) => {
47
+ if (node.type !== 'function' || !node.nodes.length) {
48
+ return false;
49
+ }
50
+
51
+ const lowerCasedValue = node.value.toLowerCase();
52
+
53
+ if (
54
+ lowerCasedValue === 'linear-gradient' ||
55
+ lowerCasedValue === 'repeating-linear-gradient' ||
56
+ lowerCasedValue === '-webkit-linear-gradient' ||
57
+ lowerCasedValue === '-webkit-repeating-linear-gradient'
58
+ ) {
59
+ let args = getArguments(node);
60
+
61
+ if (
62
+ node.nodes[0].value.toLowerCase() === 'to' &&
63
+ args[0].length === 3
64
+ ) {
65
+ node.nodes = node.nodes.slice(2);
66
+ node.nodes[0].value =
67
+ angles[
68
+ /** @type {'top'|'right'|'bottom'|'left'}*/ (
69
+ node.nodes[0].value.toLowerCase()
70
+ )
71
+ ];
72
+ }
73
+
74
+ /** @type {valueParser.Dimension | false} */
75
+ let lastStop;
76
+
77
+ args.forEach((arg, index) => {
78
+ if (arg.length !== 3) {
79
+ return;
80
+ }
81
+
82
+ let isFinalStop = index === args.length - 1;
83
+ let thisStop = valueParser.unit(arg[2].value);
84
+
85
+ if (lastStop === undefined) {
86
+ lastStop = thisStop;
87
+
88
+ if (
89
+ !isFinalStop &&
90
+ lastStop &&
91
+ lastStop.number === '0' &&
92
+ lastStop.unit.toLowerCase() !== 'deg'
93
+ ) {
94
+ arg[1].value = arg[2].value = '';
95
+ }
96
+
97
+ return;
98
+ }
99
+
100
+ if (lastStop && thisStop && isLessThan(lastStop, thisStop)) {
101
+ arg[2].value = '0';
102
+ }
103
+
104
+ lastStop = thisStop;
105
+
106
+ if (isFinalStop && arg[2].value === '100%') {
107
+ arg[1].value = arg[2].value = '';
108
+ }
109
+ });
110
+
111
+ return false;
112
+ }
113
+
114
+ if (
115
+ lowerCasedValue === 'radial-gradient' ||
116
+ lowerCasedValue === 'repeating-radial-gradient'
117
+ ) {
118
+ let args = getArguments(node);
119
+ /** @type {valueParser.Dimension | false} */
120
+ let lastStop;
121
+
122
+ const hasAt = args[0].find((n) => n.value.toLowerCase() === 'at');
123
+
124
+ args.forEach((arg, index) => {
125
+ if (!arg[2] || (!index && hasAt)) {
126
+ return;
127
+ }
128
+
129
+ let thisStop = valueParser.unit(arg[2].value);
130
+
131
+ if (!lastStop) {
132
+ lastStop = thisStop;
133
+
134
+ return;
135
+ }
136
+
137
+ if (lastStop && thisStop && isLessThan(lastStop, thisStop)) {
138
+ arg[2].value = '0';
139
+ }
140
+
141
+ lastStop = thisStop;
142
+ });
143
+
144
+ return false;
145
+ }
146
+
147
+ if (
148
+ lowerCasedValue === '-webkit-radial-gradient' ||
149
+ lowerCasedValue === '-webkit-repeating-radial-gradient'
150
+ ) {
151
+ let args = getArguments(node);
152
+ /** @type {valueParser.Dimension | false} */
153
+ let lastStop;
154
+
155
+ args.forEach((arg) => {
156
+ let color;
157
+ let stop;
158
+
159
+ if (arg[2] !== undefined) {
160
+ if (arg[0].type === 'function') {
161
+ color = `${arg[0].value}(${valueParser.stringify(arg[0].nodes)})`;
162
+ } else {
163
+ color = arg[0].value;
164
+ }
165
+
166
+ if (arg[2].type === 'function') {
167
+ stop = `${arg[2].value}(${valueParser.stringify(arg[2].nodes)})`;
168
+ } else {
169
+ stop = arg[2].value;
170
+ }
171
+ } else {
172
+ if (arg[0].type === 'function') {
173
+ color = `${arg[0].value}(${valueParser.stringify(arg[0].nodes)})`;
174
+ }
175
+
176
+ color = arg[0].value;
177
+ }
178
+
179
+ color = color.toLowerCase();
180
+
181
+ const colorStop =
182
+ stop !== undefined
183
+ ? isColorStop(color, stop.toLowerCase())
184
+ : isColorStop(color);
185
+
186
+ if (!colorStop || !arg[2]) {
187
+ return;
188
+ }
189
+
190
+ let thisStop = valueParser.unit(arg[2].value);
191
+
192
+ if (!lastStop) {
193
+ lastStop = thisStop;
194
+
195
+ return;
196
+ }
197
+
198
+ if (lastStop && thisStop && isLessThan(lastStop, thisStop)) {
199
+ arg[2].value = '0';
200
+ }
201
+
202
+ lastStop = thisStop;
203
+ });
204
+
205
+ return false;
206
+ }
207
+ })
208
+ .toString();
209
+ }
210
+ /**
211
+ * @type {import('postcss').PluginCreator<void>}
212
+ * @return {import('postcss').Plugin}
213
+ */
214
+ function pluginCreator() {
215
+ return {
216
+ postcssPlugin: 'postcss-minify-gradients',
217
+ OnceExit(css) {
218
+ css.walkDecls(optimise);
219
+ },
220
+ };
221
+ }
222
+
223
+ pluginCreator.postcss = true;
224
+ module.exports = pluginCreator;
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+ const { unit } = require('postcss-value-parser');
3
+ const { colord, extend } = require('colord');
4
+ const namesPlugin = require('colord/plugins/names');
5
+
6
+ extend([/** @type {any} */ (namesPlugin)]);
7
+
8
+ /* Code derived from https://github.com/pigcan/is-color-stop */
9
+
10
+ const lengthUnits = new Set([
11
+ 'PX',
12
+ 'IN',
13
+ 'CM',
14
+ 'MM',
15
+ 'EM',
16
+ 'REM',
17
+ 'POINTS',
18
+ 'PC',
19
+ 'EX',
20
+ 'CH',
21
+ 'VW',
22
+ 'VH',
23
+ 'VMIN',
24
+ 'VMAX',
25
+ '%',
26
+ ]);
27
+
28
+ /**
29
+ * @param {string} input
30
+ * @return {boolean}
31
+ */
32
+ function isCSSLengthUnit(input) {
33
+ return lengthUnits.has(input.toUpperCase());
34
+ }
35
+ /**
36
+ * @param {string|undefined} str
37
+ * @return {boolean}
38
+ */
39
+ function isStop(str) {
40
+ if (str) {
41
+ let stop = false;
42
+ const node = unit(str);
43
+ if (node) {
44
+ const number = Number(node.number);
45
+ if (number === 0 || (!isNaN(number) && isCSSLengthUnit(node.unit))) {
46
+ stop = true;
47
+ }
48
+ } else {
49
+ stop = /^calc\(\S+\)$/g.test(str);
50
+ }
51
+ return stop;
52
+ }
53
+ return true;
54
+ }
55
+ /**
56
+ * @param {string} color
57
+ * @param {string} [stop]
58
+ * @return {boolean}
59
+ */
60
+ module.exports = function isColorStop(color, stop) {
61
+ return colord(color).isValid() && isStop(stop);
62
+ };
@@ -0,0 +1,9 @@
1
+ export = pluginCreator;
2
+ /**
3
+ * @type {import('postcss').PluginCreator<void>}
4
+ * @return {import('postcss').Plugin}
5
+ */
6
+ declare function pluginCreator(): import('postcss').Plugin;
7
+ declare namespace pluginCreator {
8
+ const postcss: true;
9
+ }
@@ -0,0 +1,2 @@
1
+ declare function _exports(color: string, stop?: string | undefined): boolean;
2
+ export = _exports;
package/dist/index.js DELETED
@@ -1,186 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
-
8
- var _postcssValueParser = _interopRequireWildcard(require("postcss-value-parser"));
9
-
10
- var _cssnanoUtils = require("cssnano-utils");
11
-
12
- var _isColorStop = _interopRequireDefault(require("./isColorStop.js"));
13
-
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
-
18
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
-
20
- const angles = {
21
- top: '0deg',
22
- right: '90deg',
23
- bottom: '180deg',
24
- left: '270deg'
25
- };
26
-
27
- function isLessThan(a, b) {
28
- return a.unit.toLowerCase() === b.unit.toLowerCase() && parseFloat(a.number) >= parseFloat(b.number);
29
- }
30
-
31
- function optimise(decl) {
32
- const value = decl.value;
33
-
34
- if (!value) {
35
- return;
36
- }
37
-
38
- const normalizedValue = value.toLowerCase();
39
-
40
- if (normalizedValue.includes('var(') || normalizedValue.includes('env(')) {
41
- return;
42
- }
43
-
44
- if (!normalizedValue.includes('gradient')) {
45
- return;
46
- }
47
-
48
- decl.value = (0, _postcssValueParser.default)(value).walk(node => {
49
- if (node.type !== 'function' || !node.nodes.length) {
50
- return false;
51
- }
52
-
53
- const lowerCasedValue = node.value.toLowerCase();
54
-
55
- if (lowerCasedValue === 'linear-gradient' || lowerCasedValue === 'repeating-linear-gradient' || lowerCasedValue === '-webkit-linear-gradient' || lowerCasedValue === '-webkit-repeating-linear-gradient') {
56
- let args = (0, _cssnanoUtils.getArguments)(node);
57
-
58
- if (node.nodes[0].value.toLowerCase() === 'to' && args[0].length === 3) {
59
- node.nodes = node.nodes.slice(2);
60
- node.nodes[0].value = angles[node.nodes[0].value.toLowerCase()];
61
- }
62
-
63
- let lastStop = null;
64
- args.forEach((arg, index) => {
65
- if (arg.length !== 3) {
66
- return;
67
- }
68
-
69
- let isFinalStop = index === args.length - 1;
70
- let thisStop = (0, _postcssValueParser.unit)(arg[2].value);
71
-
72
- if (lastStop === null) {
73
- lastStop = thisStop;
74
-
75
- if (!isFinalStop && lastStop && lastStop.number === '0' && lastStop.unit.toLowerCase() !== 'deg') {
76
- arg[1].value = arg[2].value = '';
77
- }
78
-
79
- return;
80
- }
81
-
82
- if (lastStop && thisStop && isLessThan(lastStop, thisStop)) {
83
- arg[2].value = 0;
84
- }
85
-
86
- lastStop = thisStop;
87
-
88
- if (isFinalStop && arg[2].value === '100%') {
89
- arg[1].value = arg[2].value = '';
90
- }
91
- });
92
- return false;
93
- }
94
-
95
- if (lowerCasedValue === 'radial-gradient' || lowerCasedValue === 'repeating-radial-gradient') {
96
- let args = (0, _cssnanoUtils.getArguments)(node);
97
- let lastStop;
98
- const hasAt = args[0].find(n => n.value.toLowerCase() === 'at');
99
- args.forEach((arg, index) => {
100
- if (!arg[2] || !index && hasAt) {
101
- return;
102
- }
103
-
104
- let thisStop = (0, _postcssValueParser.unit)(arg[2].value);
105
-
106
- if (!lastStop) {
107
- lastStop = thisStop;
108
- return;
109
- }
110
-
111
- if (lastStop && thisStop && isLessThan(lastStop, thisStop)) {
112
- arg[2].value = 0;
113
- }
114
-
115
- lastStop = thisStop;
116
- });
117
- return false;
118
- }
119
-
120
- if (lowerCasedValue === '-webkit-radial-gradient' || lowerCasedValue === '-webkit-repeating-radial-gradient') {
121
- let args = (0, _cssnanoUtils.getArguments)(node);
122
- let lastStop;
123
- args.forEach(arg => {
124
- let color;
125
- let stop;
126
-
127
- if (arg[2] !== undefined) {
128
- if (arg[0].type === 'function') {
129
- color = `${arg[0].value}(${(0, _postcssValueParser.stringify)(arg[0].nodes)})`;
130
- } else {
131
- color = arg[0].value;
132
- }
133
-
134
- if (arg[2].type === 'function') {
135
- stop = `${arg[2].value}(${(0, _postcssValueParser.stringify)(arg[2].nodes)})`;
136
- } else {
137
- stop = arg[2].value;
138
- }
139
- } else {
140
- if (arg[0].type === 'function') {
141
- color = `${arg[0].value}(${(0, _postcssValueParser.stringify)(arg[0].nodes)})`;
142
- }
143
-
144
- color = arg[0].value;
145
- }
146
-
147
- color = color.toLowerCase();
148
- const colorStop = stop || stop === 0 ? (0, _isColorStop.default)(color, stop.toLowerCase()) : (0, _isColorStop.default)(color);
149
-
150
- if (!colorStop || !arg[2]) {
151
- return;
152
- }
153
-
154
- let thisStop = (0, _postcssValueParser.unit)(arg[2].value);
155
-
156
- if (!lastStop) {
157
- lastStop = thisStop;
158
- return;
159
- }
160
-
161
- if (lastStop && thisStop && isLessThan(lastStop, thisStop)) {
162
- arg[2].value = 0;
163
- }
164
-
165
- lastStop = thisStop;
166
- });
167
- return false;
168
- }
169
- }).toString();
170
- }
171
-
172
- function pluginCreator() {
173
- return {
174
- postcssPlugin: 'postcss-minify-gradients',
175
-
176
- OnceExit(css) {
177
- css.walkDecls(optimise);
178
- }
179
-
180
- };
181
- }
182
-
183
- pluginCreator.postcss = true;
184
- var _default = pluginCreator;
185
- exports.default = _default;
186
- module.exports = exports.default;
@@ -1,47 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = isColorStop;
7
-
8
- var _postcssValueParser = require("postcss-value-parser");
9
-
10
- var _colord = require("colord");
11
-
12
- var _names = _interopRequireDefault(require("colord/plugins/names"));
13
-
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
- (0, _colord.extend)([_names.default]);
17
- /* Code derived from https://github.com/pigcan/is-color-stop */
18
-
19
- const lengthUnits = new Set(['PX', 'IN', 'CM', 'MM', 'EM', 'REM', 'POINTS', 'PC', 'EX', 'CH', 'VW', 'VH', 'VMIN', 'VMAX', '%']);
20
-
21
- function isCSSLengthUnit(input) {
22
- return lengthUnits.has(input.toUpperCase());
23
- }
24
-
25
- function isStop(str) {
26
- let stop = !str;
27
-
28
- if (!stop) {
29
- const node = (0, _postcssValueParser.unit)(str);
30
-
31
- if (node) {
32
- if (node.number === 0 || !isNaN(node.number) && isCSSLengthUnit(node.unit)) {
33
- stop = true;
34
- }
35
- } else {
36
- stop = /^calc\(\S+\)$/g.test(str);
37
- }
38
- }
39
-
40
- return stop;
41
- }
42
-
43
- function isColorStop(color, stop) {
44
- return (0, _colord.colord)(color).isValid() && isStop(stop);
45
- }
46
-
47
- module.exports = exports.default;