Skip to content

Commit f4190d5

Browse files
authored
postcss-progressive-custom-properties : fix double position gradients (#256)
* postcss-progressive-custom-properties : fix double position gradients * cleanup * more cleanup
1 parent 0f22eed commit f4190d5

23 files changed

+364
-53
lines changed

plugin-packs/postcss-preset-env/.tape.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,14 @@ postcssTape(plugin)({
467467
});
468468
}
469469
},
470+
'progressive-custom-properties': {
471+
message: 'supports progressive custom properties plugin',
472+
options: {
473+
preserve: true,
474+
stage: 0,
475+
browsers: '> 0%'
476+
},
477+
},
470478
'unknown-feature': {
471479
message: 'warns on unknown features',
472480
warnings: 3,

plugin-packs/postcss-preset-env/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changes to PostCSS Preset Env
22

3+
### Unreleased (patch?)
4+
5+
- Updated `@csstools/postcss-progressive-custom-properties` to ???.
6+
- Updated `postcss-double-position-gradients` to ???.
7+
38
### 7.3.3 (February 13, 2022)
49

510
- Updated `cssdb` to `6.3.0` (minor)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
:root {
2+
/* gradients */
3+
--gradient-prop-1: conic-gradient(yellowgreen 40%, gold 0deg, gold 75%, #f06 0deg);
4+
--gradient-prop-2: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
5+
--gradient-prop-3: radial-gradient(cyan 0%, transparent 20% 30%, salmon 40%);
6+
--gradient-prop-4: repeating-conic-gradient(from 0deg, yellowgreen 40deg, gold 60deg 75deg, #f06 0deg);
7+
--gradient-prop-5: repeating-linear-gradient(90deg, black 25% 50%, blue 50% 75%);
8+
--gradient-prop-6: repeating-radial-gradient(red 0 8%, yellow 8% 16%, blue 16% 24%);
9+
10+
--hwb: hwb(20 10% 10%);
11+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
:root {
2+
/* gradients */
3+
--gradient-prop-1: conic-gradient(yellowgreen 40%, gold 0deg, gold 75%, #f06 0deg);
4+
--gradient-prop-2: linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
5+
--gradient-prop-3: radial-gradient(cyan 0%, transparent 20%,transparent 30%, salmon 40%);
6+
--gradient-prop-4: repeating-conic-gradient(from 0deg, yellowgreen 40deg, gold 60deg,gold 75deg, #f06 0deg);
7+
--gradient-prop-5: repeating-linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
8+
--gradient-prop-6: repeating-radial-gradient(red 0,red 8%, yellow 8%,yellow 16%, blue 16%, blue 24%);
9+
10+
--hwb: rgb(230, 93, 26);
11+
}
12+
13+
@supports (background: linear-gradient(0deg, red 0% 1%, red 2%)) {
14+
:root {
15+
--gradient-prop-2: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
16+
}
17+
}
18+
19+
@supports (background: radial-gradient(red, red 1px 2px, red 3px)) {
20+
:root {
21+
--gradient-prop-3: radial-gradient(cyan 0%, transparent 20% 30%, salmon 40%);
22+
}
23+
}
24+
25+
@supports (background: repeating-conic-gradient(from 0deg, red 0deg, red 0deg 1deg, red 2deg)) {
26+
:root {
27+
--gradient-prop-4: repeating-conic-gradient(from 0deg, yellowgreen 40deg, gold 60deg 75deg, #f06 0deg);
28+
}
29+
}
30+
31+
@supports (background: repeating-linear-gradient(0deg, red 0% 1%, red 2%)) {
32+
:root {
33+
--gradient-prop-5: repeating-linear-gradient(90deg, black 25% 50%, blue 50% 75%);
34+
}
35+
}
36+
37+
@supports (background: repeating-radial-gradient(red, red 1px 2px, red 3px)) {
38+
:root {
39+
--gradient-prop-6: repeating-radial-gradient(red 0 8%, yellow 8% 16%, blue 16% 24%);
40+
}
41+
}
42+
43+
@supports (color: hwb(0% 0 0)) {:root {
44+
45+
--hwb: hwb(20 10% 10%);
46+
}
47+
}

plugins/postcss-double-position-gradients/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Changes to PostCSS Double Position Gradients
22

3+
### Unreleased (minor)
4+
5+
- Ignore values in relevant `@supports` rules.
6+
- Support double position gradients in Custom Properties.
7+
8+
```css
9+
@supports (order: linear-gradient(90deg, black 25% 50%, blue 50% 75%)) {
10+
.support {
11+
/* is not processed */
12+
order: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
13+
}
14+
}
15+
```
16+
317
### 3.0.5 (February 5, 2022)
418

519
- Improved `es module` and `commonjs` compatibility

plugins/postcss-double-position-gradients/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,30 @@ postcssDoublePositionGradients({ preserve: false })
9292
}
9393
```
9494

95+
### enableProgressiveCustomProperties
96+
97+
The `enableProgressiveCustomProperties` option determines whether the original notation
98+
is wrapped with `@supports` when used in Custom Properties. By default, it is enabled.
99+
100+
⚠️ We only recommend disabling this when you set `preserve` to `false` or if you bring your own fix for Custom Properties. See what the plugin does in its [README](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-progressive-custom-properties#readme).
101+
102+
```js
103+
postcssDoublePositionGradients({ enableProgressiveCustomProperties: false })
104+
```
105+
106+
```pcss
107+
:root {
108+
--a-gradient: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
109+
}
110+
111+
/* becomes */
112+
113+
:root {
114+
--a-gradient: linear-gradient(90deg, black 25%, black 50%, blue 50%, blue 75%); /* will never be used, not even in older browser */
115+
--a-gradient: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
116+
}
117+
```
118+
95119
[css-url]: https://cssdb.org/#double-position-gradients
96120
[discord]: https://discord.gg/bUadyRwkJS
97121
[npm-url]: https://www.npmjs.com/package/postcss-double-position-gradients

plugins/postcss-double-position-gradients/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"node": "^12 || ^14 || >=16"
3636
},
3737
"dependencies": {
38+
"@csstools/postcss-progressive-custom-properties": "^1.1.0",
3839
"postcss-value-parser": "^4.2.0"
3940
},
4041
"peerDependencies": {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { includesGradientsFunction } from './is-gradient';
2+
3+
export function hasSupportsAtRuleAncestor(node) {
4+
let parent = node.parent;
5+
while (parent) {
6+
if (parent.type !== 'atrule') {
7+
parent = parent.parent;
8+
continue;
9+
}
10+
11+
if (parent.name === 'supports' && includesGradientsFunction(parent.params)) {
12+
return true;
13+
}
14+
15+
parent = parent.parent;
16+
}
17+
18+
return false;
19+
}

plugins/postcss-double-position-gradients/src/index.js

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
import postcssProgressiveCustomProperties from '@csstools/postcss-progressive-custom-properties';
12
import valueParser from 'postcss-value-parser';
2-
3-
// whether the value has a lab() or lch() matcher
4-
const gradientRegExp = /(repeating-)?(conic|linear|radial)-gradient\([\W\w]*\)/i;
5-
const gradientPartsRegExp = /^(repeating-)?(conic|linear|radial)-gradient$/i;
3+
import { hasSupportsAtRuleAncestor } from './has-supports-at-rule-ancestor';
4+
import { includesGradientsFunction, isGradientsFunctions } from './is-gradient';
65

76
const isPunctuationCommaNode = node => node.type === 'div' && node.value === ',';
87

@@ -26,13 +25,15 @@ function isNumericNode(node) {
2625
* @param {{preserve?: boolean}} opts
2726
* @returns {import('postcss').Plugin}
2827
*/
29-
function creator(opts) {
30-
const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : true;
31-
28+
const basePlugin = (opts) => {
3229
return {
3330
postcssPlugin: 'postcss-double-position-gradients',
3431
Declaration(decl, { result }) {
35-
if (!gradientRegExp.test(decl.value)) {
32+
if (!includesGradientsFunction(decl.value)) {
33+
return;
34+
}
35+
36+
if (hasSupportsAtRuleAncestor(decl)) {
3637
return;
3738
}
3839

@@ -53,7 +54,7 @@ function creator(opts) {
5354
}
5455

5556
valueAST.walk(func => {
56-
if (func.type !== 'function' || !gradientPartsRegExp.test(func.value)) {
57+
if (func.type !== 'function' || !isGradientsFunctions(func.value)) {
5758
return;
5859
}
5960

@@ -89,7 +90,7 @@ function creator(opts) {
8990
const modifiedValue = valueAST.toString();
9091

9192
if (modifiedValue !== decl.value) {
92-
if (preserve) {
93+
if (opts.preserve) {
9394
decl.cloneBefore({ value: modifiedValue });
9495
return;
9596
}
@@ -98,8 +99,34 @@ function creator(opts) {
9899
}
99100
},
100101
};
101-
}
102+
};
103+
104+
basePlugin.postcss = true;
105+
106+
/**
107+
* Transform double-position gradients in CSS.
108+
* @param {{preserve?: boolean}} opts
109+
* @returns {import('postcss').Plugin}
110+
*/
111+
const postcssPlugin = (opts) => {
112+
const options = Object.assign({
113+
enableProgressiveCustomProperties: true,
114+
preserve: true,
115+
}, opts);
116+
117+
if (options.enableProgressiveCustomProperties && options.preserve) {
118+
return {
119+
postcssPlugin: 'postcss-double-position-gradients',
120+
plugins: [
121+
postcssProgressiveCustomProperties(),
122+
basePlugin(options),
123+
],
124+
};
125+
}
126+
127+
return basePlugin(options);
128+
};
102129

103-
creator.postcss = true;
130+
postcssPlugin.postcss = true;
104131

105-
export default creator;
132+
export default postcssPlugin;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export function includesGradientsFunction(str) {
2+
return (
3+
str.includes('conic-gradient(') ||
4+
str.includes('linear-gradient(') ||
5+
str.includes('radial-gradient(') ||
6+
str.includes('repeating-conic-gradient(') ||
7+
str.includes('repeating-linear-gradient(') ||
8+
str.includes('repeating-radial-gradient(')
9+
);
10+
}
11+
12+
export function isGradientsFunctions(str) {
13+
return (
14+
str ==='conic-gradient' ||
15+
str ==='linear-gradient' ||
16+
str ==='radial-gradient' ||
17+
str ==='repeating-conic-gradient' ||
18+
str ==='repeating-linear-gradient' ||
19+
str ==='repeating-radial-gradient'
20+
);
21+
}

plugins/postcss-double-position-gradients/test/basic.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,12 @@
3434
transparent
3535
);
3636
}
37+
38+
.test-all-functions-as-custom-properties {
39+
--gradient-prop-1: conic-gradient(yellowgreen 40%, gold 0deg, gold 75%, #f06 0deg);
40+
--gradient-prop-2: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
41+
--gradient-prop-3: radial-gradient(cyan 0%, transparent 20% 30%, salmon 40%);
42+
--gradient-prop-4: repeating-conic-gradient(from 0deg, yellowgreen 40deg, gold 60deg 75deg, #f06 0deg);
43+
--gradient-prop-5: repeating-linear-gradient(90deg, black 25% 50%, blue 50% 75%);
44+
--gradient-prop-6: repeating-radial-gradient(red 0 8%, yellow 8% 16%, blue 16% 24%);
45+
}

plugins/postcss-double-position-gradients/test/basic.expect.css

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,42 @@
3636
transparent
3737
);
3838
}
39+
40+
.test-all-functions-as-custom-properties {
41+
--gradient-prop-1: conic-gradient(yellowgreen 40%, gold 0deg, gold 75%, #f06 0deg);
42+
--gradient-prop-2: linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
43+
--gradient-prop-3: radial-gradient(cyan 0%, transparent 20%,transparent 30%, salmon 40%);
44+
--gradient-prop-4: repeating-conic-gradient(from 0deg, yellowgreen 40deg, gold 60deg,gold 75deg, #f06 0deg);
45+
--gradient-prop-5: repeating-linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
46+
--gradient-prop-6: repeating-radial-gradient(red 0,red 8%, yellow 8%,yellow 16%, blue 16%, blue 24%);
47+
}
48+
49+
@supports (background: linear-gradient(0deg, red 0% 1%, red 2%)) {
50+
.test-all-functions-as-custom-properties {
51+
--gradient-prop-2: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
52+
}
53+
}
54+
55+
@supports (background: radial-gradient(red, red 1px 2px, red 3px)) {
56+
.test-all-functions-as-custom-properties {
57+
--gradient-prop-3: radial-gradient(cyan 0%, transparent 20% 30%, salmon 40%);
58+
}
59+
}
60+
61+
@supports (background: repeating-conic-gradient(from 0deg, red 0deg, red 0deg 1deg, red 2deg)) {
62+
.test-all-functions-as-custom-properties {
63+
--gradient-prop-4: repeating-conic-gradient(from 0deg, yellowgreen 40deg, gold 60deg 75deg, #f06 0deg);
64+
}
65+
}
66+
67+
@supports (background: repeating-linear-gradient(0deg, red 0% 1%, red 2%)) {
68+
.test-all-functions-as-custom-properties {
69+
--gradient-prop-5: repeating-linear-gradient(90deg, black 25% 50%, blue 50% 75%);
70+
}
71+
}
72+
73+
@supports (background: repeating-radial-gradient(red, red 1px 2px, red 3px)) {
74+
.test-all-functions-as-custom-properties {
75+
--gradient-prop-6: repeating-radial-gradient(red 0 8%, yellow 8% 16%, blue 16% 24%);
76+
}
77+
}

plugins/postcss-double-position-gradients/test/basic.preserve.expect.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,12 @@
3434
transparent
3535
);
3636
}
37+
38+
.test-all-functions-as-custom-properties {
39+
--gradient-prop-1: conic-gradient(yellowgreen 40%, gold 0deg, gold 75%, #f06 0deg);
40+
--gradient-prop-2: linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
41+
--gradient-prop-3: radial-gradient(cyan 0%, transparent 20%,transparent 30%, salmon 40%);
42+
--gradient-prop-4: repeating-conic-gradient(from 0deg, yellowgreen 40deg, gold 60deg,gold 75deg, #f06 0deg);
43+
--gradient-prop-5: repeating-linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
44+
--gradient-prop-6: repeating-radial-gradient(red 0,red 8%, yellow 8%,yellow 16%, blue 16%, blue 24%);
45+
}

plugins/postcss-double-position-gradients/test/generated-value-cases.expect.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@
2626

2727
@supports (order: linear-gradient(90deg, black 25% 50%, blue 50% 75%)) {
2828
.support {
29-
order: linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
29+
order: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
3030
}
3131
}

plugins/postcss-double-position-gradients/test/generated-value-cases.preserve.expect.css

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,20 @@
2222

2323
:root {
2424
--some-var: linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
25+
}
26+
27+
@supports (background: linear-gradient(0deg, red 0% 1%, red 2%)) {
28+
:root {
2529
--some-var: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
2630
}
31+
}
2732

2833
.content {
2934
content: 'linear-gradient(90deg, black 25% 50%, blue 50% 75%)';
3035
}
3136

3237
@supports (order: linear-gradient(90deg, black 25% 50%, blue 50% 75%)) {
3338
.support {
34-
order: linear-gradient(90deg, black 25%,black 50%, blue 50%, blue 75%);
3539
order: linear-gradient(90deg, black 25% 50%, blue 50% 75%);
3640
}
3741
}

plugins/postcss-lab-function/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changes to PostCSS Lab Function
22

3+
### Unreleased (patch)
4+
5+
- Fix plugin name
6+
37
### 4.1.0 (February 12, 2022)
48

59
- Add gamut mapping for out of gamut colors.

plugins/postcss-lab-function/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ const postcssPlugin: PluginCreator<pluginOptions> = (opts?: pluginOptions) => {
8181

8282
if (options.enableProgressiveCustomProperties && (options.preserve || options.subFeatures.displayP3)) {
8383
return {
84-
postcssPlugin: 'postcss-color-function',
84+
postcssPlugin: 'postcss-lab-function',
8585
plugins: [
8686
postcssProgressiveCustomProperties(),
8787
basePlugin(options),

0 commit comments

Comments
 (0)