postcss-custom-supports 0.1.0
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/LICENSE.md +21 -0
- package/README.md +96 -0
- package/index.js +57 -0
- package/package.json +27 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Chloe Burroughs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# postcss-custom-supports
|
|
2
|
+
|
|
3
|
+
_Note: I created this plugin for a specific project because I was tired of remembering the advanced attributes @supports query and fighting VS Code's parser. I'm releasing it because I hope it’s helpful. It was built with Claude Opus 4.6._
|
|
4
|
+
|
|
5
|
+
A [PostCSS](https://postcss.org/) plugin that brings the [`@custom-media`](https://www.w3.org/TR/mediaqueries-5/#custom-mq) authoring pattern to `@supports` queries. Define a feature-detection condition once, give it a `--name`, and reference it from any number of `@supports` rules.
|
|
6
|
+
|
|
7
|
+
```css
|
|
8
|
+
@custom-supports --inert interactivity: inert;
|
|
9
|
+
@custom-supports --scroll animation-timeline: scroll();
|
|
10
|
+
@custom-supports --attr x: attr(x type(*));
|
|
11
|
+
|
|
12
|
+
@supports (--inert) {
|
|
13
|
+
[hidden-while-animating] { interactivity: inert; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@supports not (--scroll) {
|
|
17
|
+
/* IntersectionObserver fallback */
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@supports (--attr) and (--inert) {
|
|
21
|
+
/* combined */
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
becomes
|
|
26
|
+
|
|
27
|
+
```css
|
|
28
|
+
@supports (interactivity: inert) {
|
|
29
|
+
[hidden-while-animating] { interactivity: inert; }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@supports not (animation-timeline: scroll()) {
|
|
33
|
+
/* IntersectionObserver fallback */
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@supports (x: attr(x type(*))) and (interactivity: inert) {
|
|
37
|
+
/* combined */
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Why
|
|
42
|
+
|
|
43
|
+
Real-world `@supports` conditions are often verbose (`x: attr(x type(*))`), brittle to type, and visually noisy when repeated across a stylesheet. They also confuse some editor parsers when the value uses bleeding-edge syntax. Aliasing them behind a stable `--name` mirrors how `@custom-media` keeps breakpoints readable.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
npm install --save-dev postcss-custom-supports
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Usage
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
const postcss = require('postcss');
|
|
55
|
+
const customSupports = require('postcss-custom-supports');
|
|
56
|
+
|
|
57
|
+
postcss([customSupports(/* options */)]).process(css);
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Options
|
|
61
|
+
|
|
62
|
+
| Option | Type | Default | Description |
|
|
63
|
+
| --- | --- | --- | --- |
|
|
64
|
+
| `preserve` | `boolean` | `false` | Keep `@custom-supports` declarations in the output (useful for downstream tools that consume the source CSS). |
|
|
65
|
+
|
|
66
|
+
## Syntax
|
|
67
|
+
|
|
68
|
+
A declaration:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
@custom-supports --<name> <condition>;
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`<condition>` is any string that would be valid inside the parentheses of a normal `@supports` query — typically `property: value`, but also `selector(...)`, `font-tech(...)`, etc.
|
|
75
|
+
|
|
76
|
+
A reference is the literal token `(--<name>)`, used anywhere a parenthesized supports condition is allowed:
|
|
77
|
+
|
|
78
|
+
```css
|
|
79
|
+
@supports (--name) { … }
|
|
80
|
+
@supports not (--name) { … }
|
|
81
|
+
@supports (--a) and (--b) { … }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
References inside function calls (`var(--name)`, `attr(--name)`, etc.) are **not** rewritten, so it is safe to reference custom properties in supports conditions.
|
|
85
|
+
|
|
86
|
+
## Warnings
|
|
87
|
+
|
|
88
|
+
The plugin emits PostCSS warnings (not errors) for:
|
|
89
|
+
|
|
90
|
+
- Malformed `@custom-supports` declarations (missing condition).
|
|
91
|
+
- Redefinition of a name (the last definition wins).
|
|
92
|
+
- References to undefined names (left untouched in the output).
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
MIT
|
package/index.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Matches a single @custom-supports declaration:
|
|
4
|
+
// @custom-supports --name <condition>;
|
|
5
|
+
// PostCSS strips the trailing semicolon and normalizes whitespace before
|
|
6
|
+
// handing us `rule.params`, so a single space between name and condition
|
|
7
|
+
// is all we need to require here.
|
|
8
|
+
const DEFINITION_RE = /^(--[\w-]+)\s+(.+)$/;
|
|
9
|
+
|
|
10
|
+
// Matches a (--name) reference inside an @supports condition. The negative
|
|
11
|
+
// lookbehind prevents accidental rewrites of identifiers like var(--foo) or
|
|
12
|
+
// attr(--bar), where the leading character before "(" is an ident-char.
|
|
13
|
+
const REFERENCE_RE = /(?<![\w-])\(--[\w-]+\)/g;
|
|
14
|
+
|
|
15
|
+
const creator = (opts = {}) => {
|
|
16
|
+
const preserve = opts.preserve === true;
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
postcssPlugin: 'postcss-custom-supports',
|
|
20
|
+
Once(root, { result }) {
|
|
21
|
+
const customs = new Map();
|
|
22
|
+
|
|
23
|
+
root.walkAtRules('custom-supports', rule => {
|
|
24
|
+
const match = rule.params.match(DEFINITION_RE);
|
|
25
|
+
if (!match) {
|
|
26
|
+
rule.warn(result, `Invalid @custom-supports declaration: "${rule.params}"`);
|
|
27
|
+
if (!preserve) rule.remove();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const [, name, condition] = match;
|
|
32
|
+
if (customs.has(name)) {
|
|
33
|
+
rule.warn(result, `@custom-supports ${name} is redefined; the last definition wins`);
|
|
34
|
+
}
|
|
35
|
+
customs.set(name, condition.trim());
|
|
36
|
+
|
|
37
|
+
if (!preserve) rule.remove();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
root.walkAtRules('supports', rule => {
|
|
41
|
+
rule.params = rule.params.replace(REFERENCE_RE, token => {
|
|
42
|
+
const name = token.slice(1, -1);
|
|
43
|
+
const value = customs.get(name);
|
|
44
|
+
if (value === undefined) {
|
|
45
|
+
rule.warn(result, `Unknown @custom-supports reference: ${name}`);
|
|
46
|
+
return token;
|
|
47
|
+
}
|
|
48
|
+
return `(${value})`;
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
creator.postcss = true;
|
|
56
|
+
|
|
57
|
+
module.exports = creator;
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "postcss-custom-supports",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "PostCSS plugin that mirrors @custom-media for @supports queries, letting you alias verbose or experimental feature-detection conditions behind a custom name.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"index.js"
|
|
8
|
+
],
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "node --test index.test.js"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"postcss",
|
|
14
|
+
"postcss-plugin",
|
|
15
|
+
"css",
|
|
16
|
+
"supports",
|
|
17
|
+
"custom-supports",
|
|
18
|
+
"feature-queries"
|
|
19
|
+
],
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"postcss": "^8.4.0"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
},
|
|
26
|
+
"license": "MIT"
|
|
27
|
+
}
|