@cssints/css-grammar 0.1.0 → 0.3.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/README.md +107 -53
- package/dist/support.d.mts +8 -0
- package/dist/support.mjs +19 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,39 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
<img src="https://cssints.dev/logo.svg" alt="" width="96" height="96">
|
|
4
4
|
|
|
5
|
-
cssints is compile-time CSS-in-TypeScript. You write calls such as `css.flex().alignItems("center")`. A Vite plugin runs them at build time and replaces each one with atomic, content-hashed class names in `@layer`s. Nothing of the styling code ships to the browser except
|
|
5
|
+
cssints is compile-time CSS-in-TypeScript. You write calls such as `css.flex().alignItems("center")`. A Vite plugin runs them at build time and replaces each one with atomic, content-hashed class names in `@layer`s. Nothing of the styling code ships to the browser except a few lines that join class names: for a `cn()` with runtime arguments and for `cv`.
|
|
6
6
|
|
|
7
7
|
- Values are checked against the spec grammars (mdn-data) in the types and again at build time. A typo is an error in the editor and in the build.
|
|
8
8
|
- Conditions (`media`, `container`, `supports`, `hover`), variants (`cv`), design tokens and themes (`createTokens`, `createGlobalTheme`, `check.contrast`) are all build-time, and all typed.
|
|
9
9
|
- LightningCSS optimizes the output. Browser support (`@mdn/browser-compat-data` against your browserslist) is reported as warnings, except for what LightningCSS lowers for those targets.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
> **Alpha.** cssints is on npm at 0.x. The API can still change between minor versions, the plugin packages
|
|
12
|
+
> may move, and some browsers and frameworks are checked less than others (docs/API.md, "Browser support and what 0.1
|
|
13
|
+
> does not have"). Pin the version, and report what breaks.
|
|
14
|
+
|
|
15
|
+
Decisions and findings are in [docs/wayfinder.md](docs/wayfinder.md); the API reference is [docs/API.md](docs/API.md). Both are also a site with search and type hovers: [apps/docs](apps/docs) (`cd apps/docs && bun run dev`); deployed to Cloudflare with Alchemy: <https://cssints.dev>.
|
|
12
16
|
|
|
13
17
|
## Install
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
```bash
|
|
20
|
+
npm install --save-dev cssints vite@8 # or: bun add -d cssints vite@8, pnpm add -D cssints vite@8
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
cssints needs Vite 8 (Vite+ works too) and Node 22.18 or later (the plugin runs your modules with type stripping). It is a
|
|
24
|
+
dev dependency: nothing of it ships except the few lines behind `cn` with runtime arguments and `cv`. The plugin packages are installed the same
|
|
25
|
+
way, each beside `cssints` (`npm install --save-dev @cssints/fluid`); the list is on the
|
|
26
|
+
[plugin packages](docs/API.md#plugin-packages-cssints-dk1q) page. In this repository `cssints` is a workspace package
|
|
27
|
+
(`"cssints": "workspace:*"`).
|
|
16
28
|
|
|
17
29
|
```ts
|
|
18
30
|
// vite.config.ts
|
|
19
31
|
import cssints, { cssTarget, targets } from "cssints/vite";
|
|
20
32
|
|
|
21
33
|
export default {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
34
|
+
plugins: [cssints()],
|
|
35
|
+
css: { transformer: "lightningcss", lightningcss: { targets } },
|
|
36
|
+
build: { cssMinify: "lightningcss", cssTarget },
|
|
25
37
|
};
|
|
26
38
|
```
|
|
27
39
|
|
|
28
40
|
```ts
|
|
29
41
|
// the entry, once
|
|
30
42
|
import "virtual:cssints.css";
|
|
43
|
+
import { reset } from "@cssints/reset" with { type: "cssints" };
|
|
44
|
+
|
|
45
|
+
reset();
|
|
31
46
|
```
|
|
32
47
|
|
|
48
|
+
`reset()` is the recommended start: [`@cssints/reset`](packages/reset/README.md) is a small modern reset in a layer below every style, so any style of yours beats it. A project without the call has none, as in any app.
|
|
49
|
+
|
|
33
50
|
`targets` and `cssTarget` come from the browserslist query of the support warnings: the `BROWSERSLIST` variable, else the standard config (`"browserslist"` in `package.json` or `.browserslistrc`, with the `BROWSERSLIST_ENV`, `NODE_ENV` or `production` section), else `defaults`. The exports are computed when `vite.config.ts` is imported, before Vite's root is known, so they look the config up from `process.cwd()` and upward; the support warnings look it up from Vite's `root` (2026-10-09, cssints-p3d2). They are the same when Vite runs from the app's directory; with `vite <dir>` from elsewhere, give `targets` and `cssTarget` the app's config yourself. Vite's CSS minify reads `cssTarget`, not `targets`: without it the minifier merges the declarations of a `firstThatWorks` into the last one. Add `"types": ["vite/client"]` to `tsconfig.json` for the `virtual:` import.
|
|
34
51
|
|
|
35
52
|
### Frameworks
|
|
36
53
|
|
|
37
|
-
Any framework that builds JSX through a Vite plugin works; the engine evaluates your modules itself, so it does not care what the plugin makes of JSX, nor in which order the plugins are listed. `apps/
|
|
54
|
+
Any framework that builds JSX through a Vite plugin works; the engine evaluates your modules itself, so it does not care what the plugin makes of JSX, nor in which order the plugins are listed. `apps/csssky` is the Solid 2 app (`solid-js` and `@solidjs/web` 2.0.0-rc.13, `@solidjs/vite-plugin` 3.0.0-next.47):
|
|
38
55
|
|
|
39
56
|
```ts skip
|
|
40
57
|
// vite.config.ts
|
|
@@ -42,51 +59,89 @@ import solid from "@solidjs/vite-plugin";
|
|
|
42
59
|
import cssints, { cssTarget, targets } from "cssints/vite";
|
|
43
60
|
|
|
44
61
|
export default {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
62
|
+
plugins: [cssints(), solid()],
|
|
63
|
+
css: { transformer: "lightningcss", lightningcss: { targets } },
|
|
64
|
+
build: { cssMinify: "lightningcss", cssTarget },
|
|
48
65
|
};
|
|
49
66
|
```
|
|
50
67
|
|
|
51
|
-
`tsconfig.json` is Solid's: `"jsx": "preserve"`, `"jsxImportSource": "@solidjs/web"`, `"types": ["vite/client"]`. Solid's `class` takes a string, an object or an array, so `
|
|
68
|
+
`tsconfig.json` is Solid's: `"jsx": "preserve"`, `"jsxImportSource": "@solidjs/web"`, `"types": ["vite/client"]`. Solid's `class` takes a string, an object or an array, so `cn` is not needed for the join: `class={[card, on() && p(4)]}` and `class={badge({ tone: tone() })}` work as in React. A site's arguments are still build-time values, so a signal goes in the condition or in a `cv` variant, not in `p(n())`. Under `vite dev` an edit of a component replaces it and resets its state below it (Solid's refresh); an edit of a style changes the class strings and the sheet with no reload.
|
|
52
69
|
|
|
53
70
|
```tsx
|
|
54
|
-
import {
|
|
55
|
-
import {
|
|
71
|
+
import { reset } from "@cssints/reset" with { type: "cssints" };
|
|
72
|
+
import {
|
|
73
|
+
bg,
|
|
74
|
+
color,
|
|
75
|
+
cn,
|
|
76
|
+
cv,
|
|
77
|
+
flex,
|
|
78
|
+
hover,
|
|
79
|
+
media,
|
|
80
|
+
p,
|
|
81
|
+
style,
|
|
82
|
+
token,
|
|
83
|
+
} from "cssints" with { type: "cssints" };
|
|
84
|
+
|
|
85
|
+
reset();
|
|
56
86
|
|
|
57
87
|
const md = media("(width >= 40rem)");
|
|
58
88
|
const accent = token.color("#2563eb", "accent");
|
|
59
89
|
|
|
60
90
|
const button = cv({
|
|
61
|
-
|
|
62
|
-
|
|
91
|
+
base: cn(p(2), color("white"), bg(accent), hover(bg("#1d4ed8"))),
|
|
92
|
+
variants: { wide: { true: md(p(4)) } },
|
|
63
93
|
});
|
|
64
94
|
|
|
65
95
|
export const Row = ({ wide, on }: { wide?: boolean; on?: boolean }) => (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
96
|
+
<div
|
|
97
|
+
className={cn(flex().alignItems("center").gap(2), on && p(1))}
|
|
98
|
+
style={style(token.set(accent, "#dc2626"))}
|
|
99
|
+
>
|
|
100
|
+
<button className={button({ wide })}>Save</button>
|
|
101
|
+
</div>
|
|
69
102
|
);
|
|
70
103
|
```
|
|
71
104
|
|
|
72
|
-
`with { type: "cssints" }` marks what runs at build time. The plugin replaces each call with a class string, so the browser gets `
|
|
105
|
+
`with { type: "cssints" }` marks what runs at build time. The plugin replaces each call with a class string, so the browser gets `__cx([], "_1s47490 _1ob5z5m _g2iyum", on && "_lqk467")` and `button` is a call of the runtime with `{ base: "_1t8gqy5 ...", ... }`, so it never sees `flex()`. `virtual:cssints.css` is one sheet with every rule once, sorted by layer, then condition, then shorthand before longhand, then class name (the `@layer reset { ... }` block of `reset()` comes first and is left out here):
|
|
73
106
|
|
|
74
107
|
```css
|
|
75
108
|
@layer _.k, _.a, _.b, _.c, _.d, _.e;
|
|
76
|
-
@property --accent{
|
|
109
|
+
@property --accent {
|
|
110
|
+
syntax: "<color>";
|
|
111
|
+
inherits: true;
|
|
112
|
+
initial-value: #2563eb;
|
|
113
|
+
}
|
|
77
114
|
@layer _.a {
|
|
78
|
-
._1t8gqy5{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.
|
|
115
|
+
._1t8gqy5 {
|
|
116
|
+
padding: 0.5rem;
|
|
117
|
+
}
|
|
118
|
+
._lqk467 {
|
|
119
|
+
padding: 0.25rem;
|
|
120
|
+
}
|
|
121
|
+
._g2iyum {
|
|
122
|
+
gap: 0.5rem;
|
|
123
|
+
}
|
|
124
|
+
._17xzvrh {
|
|
125
|
+
background-color: var(--accent);
|
|
126
|
+
}
|
|
127
|
+
._1binn6n {
|
|
128
|
+
color: white;
|
|
129
|
+
}
|
|
130
|
+
._1ob5z5m {
|
|
131
|
+
align-items: center;
|
|
132
|
+
}
|
|
133
|
+
._1s47490 {
|
|
134
|
+
display: flex;
|
|
135
|
+
}
|
|
85
136
|
}
|
|
86
137
|
@layer _.b {
|
|
87
|
-
._1tsjws2:hover{
|
|
138
|
+
._1tsjws2:hover {
|
|
139
|
+
background-color: #1d4ed8;
|
|
140
|
+
}
|
|
88
141
|
@media (width >= 40rem) {
|
|
89
|
-
._tdcza3{
|
|
142
|
+
._tdcza3 {
|
|
143
|
+
padding: 1rem;
|
|
144
|
+
}
|
|
90
145
|
}
|
|
91
146
|
}
|
|
92
147
|
```
|
|
@@ -95,7 +150,7 @@ export const Row = ({ wide, on }: { wide?: boolean; on?: boolean }) => (
|
|
|
95
150
|
|
|
96
151
|
`import * as css from "cssints/tui" with { type: "cssints" }` gives the members a terminal has (cells, colours, borders, flex, states, `cursor`), and the plugin compiles them to prop objects for [OpenTUI](https://opentui.com) renderables instead of classes; `@cssints/tui` applies their states and themes: [packages/tui](packages/tui/README.md), docs/API.md "TUI".
|
|
97
152
|
|
|
98
|
-
More in [docs/API.md](docs/API.md): property names and short names, `flex()` and `grid()` chains, conditions and layers, tokens and themes, `
|
|
153
|
+
More in [docs/API.md](docs/API.md): property names and short names, `flex()` and `grid()` chains, conditions and layers, tokens and themes, `cn` and `cv`, and the errors you can get.
|
|
99
154
|
|
|
100
155
|
## Debugging
|
|
101
156
|
|
|
@@ -104,7 +159,7 @@ More in [docs/API.md](docs/API.md): property names and short names, `flex()` and
|
|
|
104
159
|
## For agents
|
|
105
160
|
|
|
106
161
|
`cssints` ships two [agent skills](https://agentskills.io) in its package, `skills/cssints` (writing styles: setup,
|
|
107
|
-
`cn`/`
|
|
162
|
+
`cn`/`cv`, conditions, tokens and themes, the plugin packages, build errors) and `skills/cssints-plugin` (writing
|
|
108
163
|
a plugin on `scope()`, with its tests). Install them into your agent's skills folder:
|
|
109
164
|
|
|
110
165
|
```bash
|
|
@@ -112,8 +167,7 @@ npx skills-npm # links the skills of every instal
|
|
|
112
167
|
npx skills add ./node_modules/cssints/skills # or the skills CLI, for opencode, Claude Code, Codex, Cursor, ...
|
|
113
168
|
```
|
|
114
169
|
|
|
115
|
-
|
|
116
|
-
repository get `.agents/skills/cssints-contributor` (also `.claude/skills`) with no install.
|
|
170
|
+
Agents working on this repository get `.agents/skills/cssints-contributor` (also `.claude/skills`) with no install.
|
|
117
171
|
|
|
118
172
|
`@cssints/mcp` is an MCP server with the build's own checks (`check_declaration`, `check_support`, `check_contrast`,
|
|
119
173
|
`compile`, `search_docs`, `list_plugins`), in [packages/mcp](packages/mcp) with the config for opencode, Claude Code
|
|
@@ -121,15 +175,15 @@ and Cursor. The skills use it when it is configured and work without it.
|
|
|
121
175
|
|
|
122
176
|
## Layout
|
|
123
177
|
|
|
124
|
-
| Path
|
|
125
|
-
|
|
126
|
-
| `packages/cssints`
|
|
127
|
-
| `packages/css-grammar`
|
|
128
|
-
| `packages/icons`
|
|
129
|
-
| `packages/mise-en-mode`
|
|
130
|
-
| `apps/demo`
|
|
131
|
-
| `apps/docs`
|
|
132
|
-
| `docs/research`, `docs/archive` | Comparisons with other libraries; outdated plans
|
|
178
|
+
| Path | What |
|
|
179
|
+
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
180
|
+
| `packages/cssints` | Vite plugin (`cssints/vite`) on the Vite Module Runner, and the `cssints` library |
|
|
181
|
+
| `packages/css-grammar` | Type-level recognizer and its runtime twin over mdn-data grammars, Typed OM values, browser support and prose rules |
|
|
182
|
+
| `packages/icons` | `@cssints/icons`: icons from iconify JSON collections or SVG folders, a mask style with no runtime |
|
|
183
|
+
| `packages/mise-en-mode` | `@cssints/mise-en-mode`: looks as themes in the layers app < author < viewer, on `data-mode` scopes, checked against the tokens and by `check.contrast` |
|
|
184
|
+
| `apps/demo` | React demo of every 0.1 feature |
|
|
185
|
+
| `apps/docs` | The documentation site: this file and `docs/API.md` as pages, with search and type hovers (`cd apps/docs && bun run dev`) |
|
|
186
|
+
| `docs/research`, `docs/archive` | Comparisons with other libraries; outdated plans |
|
|
133
187
|
|
|
134
188
|
## Development
|
|
135
189
|
|
|
@@ -151,16 +205,16 @@ cssints is MIT. It stands on other people's work; this is what we took, from who
|
|
|
151
205
|
|
|
152
206
|
### Data and code that ships
|
|
153
207
|
|
|
154
|
-
| Where
|
|
155
|
-
|
|
156
|
-
| [@cssints/tokens](packages/tokens/README.md)
|
|
157
|
-
| [@cssints/css-grammar](packages/css-grammar/THIRD_PARTY_NOTICES.md) | the CSS syntax strings (`src/mdn.ts`, `keywords.ts`, `functions.ts`), also in the types of `cssints` | [mdn-data](https://github.com/mdn/data); the numeric ranges it omits from [@webref/css](https://github.com/w3c/webref)
|
|
158
|
-
| @cssints/css-grammar
|
|
159
|
-
| [@cssints/fonts](packages/fonts/README.md)
|
|
160
|
-
| [@cssints/icons](packages/icons/README.md)
|
|
161
|
-
| `tools/ai-automation/vendor`
|
|
162
|
-
| [apps/
|
|
163
|
-
| apps/demo
|
|
208
|
+
| Where | What | From | License |
|
|
209
|
+
| ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
|
|
210
|
+
| [@cssints/tokens](packages/tokens/README.md) | the Open Props, Radix Colors, Flexoki and Reasonable Colors sets | [Open Props](https://github.com/argyleink/open-props) (Adam Argyle), [Radix Colors](https://github.com/radix-ui/colors), [Flexoki](https://github.com/kepano/flexoki) (Steph Ango), [Reasonable Colors](https://github.com/matthewhowell/reasonable-colors) (Matthew Howell) | MIT, notices in its README |
|
|
211
|
+
| [@cssints/css-grammar](packages/css-grammar/THIRD_PARTY_NOTICES.md) | the CSS syntax strings (`src/mdn.ts`, `keywords.ts`, `functions.ts`), also in the types of `cssints` | [mdn-data](https://github.com/mdn/data); the numeric ranges it omits from [@webref/css](https://github.com/w3c/webref) | CC0-1.0; MIT (W3C) |
|
|
212
|
+
| @cssints/css-grammar | browser support warnings, read from the package (not copied) | [@mdn/browser-compat-data](https://github.com/mdn/browser-compat-data) | CC0-1.0 |
|
|
213
|
+
| [@cssints/fonts](packages/fonts/README.md) | the latin character weights and the metrics of Arial, Times New Roman and Courier New | [Capsize](https://github.com/seek-oss/capsize) (SEEK) | MIT, notice in its README |
|
|
214
|
+
| [@cssints/icons](packages/icons/README.md) | nothing: the collections are your dependency | [Iconify](https://iconify.design) `@iconify-json/*` | each collection's own |
|
|
215
|
+
| `tools/ai-automation/vendor` | lint rules, not published | [dmmulroy/anti-slop](https://github.com/dmmulroy/anti-slop) (Dillon Mulroy) | MIT, `LICENSE` and `UPSTREAM.md` |
|
|
216
|
+
| [apps/csssky](apps/csssky/NOTICE.md) | layout and token values; Inter; Phosphor icons | Mu and `@bsky.app/alf` (Bluesky Social PBC), [Inter](https://github.com/rsms/inter), [Phosphor](https://phosphoricons.com) | MIT; OFL-1.1; MIT |
|
|
217
|
+
| apps/demo | Material Design Icons (`@iconify-json/mdi`) | Pictogrammers | Apache-2.0 |
|
|
164
218
|
|
|
165
219
|
### Ideas and designs
|
|
166
220
|
|
|
@@ -168,7 +222,7 @@ No code is copied from these; each package README says which part follows which.
|
|
|
168
222
|
|
|
169
223
|
- **Plugin packages.** [Every Layout](https://every-layout.dev) and [smolcss](https://smolcss.dev) (layout), [nytimes/text-balancer](https://github.com/nytimes/text-balancer) and [react-wrap-balancer](https://github.com/shuding/react-wrap-balancer) (balance), [fluid-tailwind](https://github.com/barvian/fluid-tailwind) (fluid), [postcss-easing-gradients](https://github.com/larsenwork/postcss-easing-gradients) (gradient), [tailwindcss-motion](https://github.com/romboHQ/tailwindcss-motion) and [tailwindcss-animate](https://github.com/jamiebuilds/tailwindcss-animate) (motion), [the supersonic plugin](https://github.com/the-illarionov/the-supersonic-plugin-for-scroll-based-animation) and [lax.js](https://github.com/alexfoxy/lax.js) (reveal), [sync-skeleton](https://github.com/crutchcorn/sync-skeleton) (skeleton), [bramus/sticky-observer](https://github.com/bramus/sticky-observer) (stuck), [unpic-placeholder](https://github.com/ascorbic/unpic-placeholder) and [ThumbHash](https://github.com/evanw/thumbhash) (placeholder), [nutelch](https://github.com/meodai/nutelch) and [Leonardo](https://github.com/adobe/leonardo) (ramp), the resets of Josh Comeau, Jake Lazaroff, Vale and Andy Bell (reset), [Mise en Mode](https://standard.mode.place) and its Mode Contract (mise-en-mode), [brendonovich/vite-plugin-opencode](https://github.com/Brendonovich/vite-plugin-opencode) (the prompt box of devtools).
|
|
170
224
|
- **The engine.** The comparisons in [docs/research](docs/research) record what we took from [StyleX](https://stylexjs.com), [vanilla-extract](https://vanilla-extract.style), [Tailwind CSS](https://tailwindcss.com), [Tokenami](https://tokenami.com), [SugarCube](https://sugarcube.sh) and the [React Spectrum](https://react-spectrum.adobe.com) style macros; the first spark was [Haz's post](https://bsky.app/profile/haz.dev/post/3mebm2mx6jk27) on a CSS framework in TypeScript. Tokens follow the [Design Tokens Community Group](https://www.designtokens.org) format.
|
|
171
|
-
- **apps/
|
|
225
|
+
- **apps/csssky** follows the look of Mu and the hue slider of Witchsky.
|
|
172
226
|
|
|
173
227
|
### Built on
|
|
174
228
|
|
package/dist/support.d.mts
CHANGED
|
@@ -20,6 +20,14 @@ export interface Warning {
|
|
|
20
20
|
}
|
|
21
21
|
export declare const lackingOf: (key: string, ts?: Target[], exact?: boolean) => Target[];
|
|
22
22
|
export declare const lacking: (key: string, ts?: Target[] | undefined, exact?: boolean | undefined) => Effect.Effect<Target[], never, never>;
|
|
23
|
+
/**
|
|
24
|
+
* The BCD key of a keyword or function in a value of a property, by the lookup above.
|
|
25
|
+
* @param {string} p the property
|
|
26
|
+
* @param {string} k the keyword, or the name of the function
|
|
27
|
+
* @param {boolean} fn whether `k` is a function
|
|
28
|
+
* @returns {string | undefined} the key, or `undefined` when BCD has none
|
|
29
|
+
*/
|
|
30
|
+
export declare const tokenKey: (p: string, k: string, fn: boolean) => string | undefined;
|
|
23
31
|
export declare function supportOf(p: string, v: string, ts?: Target[]): Warning[];
|
|
24
32
|
export declare function browsers(lacking: string[]): string;
|
|
25
33
|
export declare const support: (p: string, v: string, ts?: Target[] | undefined) => Effect.Effect<Warning[], never, never>;
|
package/dist/support.mjs
CHANGED
|
@@ -77,6 +77,23 @@ const reachOf = (p) => {
|
|
|
77
77
|
}
|
|
78
78
|
return r;
|
|
79
79
|
};
|
|
80
|
+
const tokenKeys = (owners, types, k, fn) => [
|
|
81
|
+
...owners.map((q) => `css.properties.${q}.${fn ? `${k}_function` : k}`),
|
|
82
|
+
...fn ? owners.map((q) => `css.properties.${q}.${k}`) : [],
|
|
83
|
+
...fn ? [`css.types.${k}`] : [],
|
|
84
|
+
...types.map((t) => `css.types.${t}.${k}`)
|
|
85
|
+
];
|
|
86
|
+
/**
|
|
87
|
+
* The BCD key of a keyword or function in a value of a property, by the lookup above.
|
|
88
|
+
* @param {string} p the property
|
|
89
|
+
* @param {string} k the keyword, or the name of the function
|
|
90
|
+
* @param {boolean} fn whether `k` is a function
|
|
91
|
+
* @returns {string | undefined} the key, or `undefined` when BCD has none
|
|
92
|
+
*/
|
|
93
|
+
const tokenKey = (p, k, fn) => {
|
|
94
|
+
const [types, owners] = reachOf(p);
|
|
95
|
+
return tokenKeys(owners, types, k, fn).find((x) => get(x)?.__compat);
|
|
96
|
+
};
|
|
80
97
|
const known = /* @__PURE__ */ new WeakMap();
|
|
81
98
|
function supportOf(p, v, ts = current()) {
|
|
82
99
|
let byDecl = known.get(ts);
|
|
@@ -95,12 +112,7 @@ function compute(p, v, ts) {
|
|
|
95
112
|
for (const { 0: tok, 1: fn, index } of code.matchAll(/(?<![\w.#-])-?[A-Za-z_][\w-]*(\()?/g)) {
|
|
96
113
|
const k = fn ? tok.slice(0, -1) : tok;
|
|
97
114
|
const rel = tok === "from" ? /([a-z-]+)\(\s*$/.exec(code.slice(0, index))?.[1] : void 0;
|
|
98
|
-
const key = (rel ? [`css.types.color.${rel}.relative_syntax`] :
|
|
99
|
-
...owners.map((q) => `css.properties.${q}.${fn ? `${k}_function` : k}`),
|
|
100
|
-
...fn ? owners.map((q) => `css.properties.${q}.${k}`) : [],
|
|
101
|
-
...fn ? [`css.types.${k}`] : [],
|
|
102
|
-
...types.map((t) => `css.types.${t}.${k}`)
|
|
103
|
-
]).find((x) => get(x)?.__compat);
|
|
115
|
+
const key = (rel ? [`css.types.color.${rel}.relative_syntax`] : tokenKeys(owners, types, k, !!fn)).find((x) => get(x)?.__compat);
|
|
104
116
|
if (key) found.push([fn ? `${k}()` : k, key]);
|
|
105
117
|
}
|
|
106
118
|
if (/"[^"]*"|'[^']*'/.test(v)) {
|
|
@@ -145,4 +157,4 @@ const message = Effect.fn("support.message")(function* (p, v, w) {
|
|
|
145
157
|
return yield* Effect.sync(() => messageOf(p, v, w));
|
|
146
158
|
});
|
|
147
159
|
//#endregion
|
|
148
|
-
export { browsers, get, lacking, lackingOf, message, messageOf, support, supportOf, targets, useTargets };
|
|
160
|
+
export { browsers, get, lacking, lackingOf, message, messageOf, support, supportOf, targets, tokenKey, useTargets };
|