@webstudio-is/css-data 0.74.0 → 0.76.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/lib/__generated__/properties.js +2 -2
- package/lib/__generated__/property-value-descriptions.js +2733 -2930
- package/lib/cjs/__generated__/properties.js +2 -2
- package/lib/cjs/__generated__/property-value-descriptions.js +2733 -2930
- package/lib/cjs/property-parsers/box-shadow.js +128 -0
- package/lib/cjs/property-parsers/index.js +1 -0
- package/lib/cjs/property-parsers/parsers.js +3 -1
- package/lib/cjs/schema.js +17 -12
- package/lib/property-parsers/box-shadow.js +98 -0
- package/lib/property-parsers/index.js +1 -0
- package/lib/property-parsers/parsers.js +3 -1
- package/lib/schema.js +17 -12
- package/lib/types/{src/__generated__ → __generated__}/properties.d.ts +2 -2
- package/lib/types/__generated__/property-value-descriptions.d.ts +5446 -0
- package/lib/types/{src/index.d.ts → index.d.ts} +2 -2
- package/lib/types/property-parsers/box-shadow.d.ts +3 -0
- package/lib/types/{src/property-parsers → property-parsers}/index.d.ts +1 -0
- package/lib/types/{src/property-parsers → property-parsers}/parsers.d.ts +1 -0
- package/lib/types/{src/schema.d.ts → schema.d.ts} +671 -0
- package/package.json +5 -7
- package/src/__generated__/properties.ts +2 -2
- package/src/__generated__/property-value-descriptions.ts +3020 -3590
- package/src/property-parsers/background.ts +0 -1
- package/src/property-parsers/box-shadow.test.ts +294 -0
- package/src/property-parsers/box-shadow.ts +134 -0
- package/src/property-parsers/index.ts +1 -0
- package/src/property-parsers/parsers.ts +1 -0
- package/src/schema.ts +18 -11
- package/lib/types/bin/property-value-descriptions.d.ts +0 -1
- package/lib/types/src/__generated__/property-value-descriptions.d.ts +0 -2933
- /package/lib/types/{src/__generated__ → __generated__}/keyword-values.d.ts +0 -0
- /package/lib/types/{src/__generated__ → __generated__}/units.d.ts +0 -0
- /package/lib/types/{src/html-check.d.ts → html-check.d.ts} +0 -0
- /package/lib/types/{src/html.d.ts → html.d.ts} +0 -0
- /package/lib/types/{src/parse-css-value.d.ts → parse-css-value.d.ts} +0 -0
- /package/lib/types/{src/parse-css-value.test.d.ts → parse-css-value.test.d.ts} +0 -0
- /package/lib/types/{src/parse-css.d.ts → parse-css.d.ts} +0 -0
- /package/lib/types/{src/parse-css.test.d.ts → parse-css.test.d.ts} +0 -0
- /package/lib/types/{src/popularity-index.d.ts → popularity-index.d.ts} +0 -0
- /package/lib/types/{src/property-parsers → property-parsers}/background.d.ts +0 -0
- /package/lib/types/{src/property-parsers → property-parsers}/background.test.d.ts +0 -0
- /package/lib/types/{bin/mdn-data.d.ts → property-parsers/box-shadow.test.d.ts} +0 -0
- /package/lib/types/{src/property-parsers → property-parsers}/to-longhand.d.ts +0 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
|
|
3
|
+
import { parseBoxShadow } from "./box-shadow";
|
|
4
|
+
|
|
5
|
+
describe("parseBoxShadow", () => {
|
|
6
|
+
test("parses value and returns invalid when used a invalid color", () => {
|
|
7
|
+
expect(parseBoxShadow(`10px 10px 5px foo`)).toMatchInlineSnapshot(`
|
|
8
|
+
{
|
|
9
|
+
"type": "invalid",
|
|
10
|
+
"value": "10px 10px 5px foo",
|
|
11
|
+
}
|
|
12
|
+
`);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("throws error when passed a value without a unit", () => {
|
|
16
|
+
expect(parseBoxShadow(`10 10px 5px red`)).toMatchInlineSnapshot(`
|
|
17
|
+
{
|
|
18
|
+
"type": "invalid",
|
|
19
|
+
"value": "10 10px 5px red",
|
|
20
|
+
}
|
|
21
|
+
`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("inset and color values can be interchanged", () => {
|
|
25
|
+
expect(parseBoxShadow(`inset 10px 10px 5px black;`)).toMatchInlineSnapshot(`
|
|
26
|
+
{
|
|
27
|
+
"type": "layers",
|
|
28
|
+
"value": [
|
|
29
|
+
{
|
|
30
|
+
"type": "tuple",
|
|
31
|
+
"value": [
|
|
32
|
+
{
|
|
33
|
+
"type": "keyword",
|
|
34
|
+
"value": "inset",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"type": "unit",
|
|
38
|
+
"unit": "px",
|
|
39
|
+
"value": 10,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"type": "unit",
|
|
43
|
+
"unit": "px",
|
|
44
|
+
"value": 10,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"type": "unit",
|
|
48
|
+
"unit": "px",
|
|
49
|
+
"value": 5,
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"type": "keyword",
|
|
53
|
+
"value": "black",
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
}
|
|
59
|
+
`);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("parses value when inset is used but missing blur-radius", () => {
|
|
63
|
+
expect(parseBoxShadow(`box-shadow: inset 5em 1em gold`))
|
|
64
|
+
.toMatchInlineSnapshot(`
|
|
65
|
+
{
|
|
66
|
+
"type": "layers",
|
|
67
|
+
"value": [
|
|
68
|
+
{
|
|
69
|
+
"type": "tuple",
|
|
70
|
+
"value": [
|
|
71
|
+
{
|
|
72
|
+
"type": "keyword",
|
|
73
|
+
"value": "inset",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"type": "unit",
|
|
77
|
+
"unit": "em",
|
|
78
|
+
"value": 5,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"type": "unit",
|
|
82
|
+
"unit": "em",
|
|
83
|
+
"value": 1,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"type": "keyword",
|
|
87
|
+
"value": "gold",
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
}
|
|
93
|
+
`);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("parses value when offsetX and offsetY are used", () => {
|
|
97
|
+
expect(parseBoxShadow(`box-shadow: 60px -16px teal;`))
|
|
98
|
+
.toMatchInlineSnapshot(`
|
|
99
|
+
{
|
|
100
|
+
"type": "layers",
|
|
101
|
+
"value": [
|
|
102
|
+
{
|
|
103
|
+
"type": "tuple",
|
|
104
|
+
"value": [
|
|
105
|
+
{
|
|
106
|
+
"type": "unit",
|
|
107
|
+
"unit": "px",
|
|
108
|
+
"value": 60,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"type": "unit",
|
|
112
|
+
"unit": "px",
|
|
113
|
+
"value": -16,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"type": "keyword",
|
|
117
|
+
"value": "teal",
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
}
|
|
123
|
+
`);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("parses value from figma", () => {
|
|
127
|
+
expect(
|
|
128
|
+
parseBoxShadow(
|
|
129
|
+
"box-shadow: 0 60px 80px rgba(0,0,0,0.60), 0 45px 26px rgba(0,0,0,0.14);"
|
|
130
|
+
)
|
|
131
|
+
).toMatchInlineSnapshot(`
|
|
132
|
+
{
|
|
133
|
+
"type": "layers",
|
|
134
|
+
"value": [
|
|
135
|
+
{
|
|
136
|
+
"type": "tuple",
|
|
137
|
+
"value": [
|
|
138
|
+
{
|
|
139
|
+
"type": "unit",
|
|
140
|
+
"unit": "number",
|
|
141
|
+
"value": 0,
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"type": "unit",
|
|
145
|
+
"unit": "px",
|
|
146
|
+
"value": 60,
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"type": "unit",
|
|
150
|
+
"unit": "px",
|
|
151
|
+
"value": 80,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"alpha": 0.6,
|
|
155
|
+
"b": 0,
|
|
156
|
+
"g": 0,
|
|
157
|
+
"r": 0,
|
|
158
|
+
"type": "rgb",
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"type": "tuple",
|
|
164
|
+
"value": [
|
|
165
|
+
{
|
|
166
|
+
"type": "unit",
|
|
167
|
+
"unit": "number",
|
|
168
|
+
"value": 0,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"type": "unit",
|
|
172
|
+
"unit": "px",
|
|
173
|
+
"value": 45,
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"type": "unit",
|
|
177
|
+
"unit": "px",
|
|
178
|
+
"value": 26,
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"alpha": 0.14,
|
|
182
|
+
"b": 0,
|
|
183
|
+
"g": 0,
|
|
184
|
+
"r": 0,
|
|
185
|
+
"type": "rgb",
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
}
|
|
191
|
+
`);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test(`parses multiple layers of box-shadow property`, () => {
|
|
195
|
+
expect(
|
|
196
|
+
parseBoxShadow(`box-shadow:
|
|
197
|
+
0 0 5px rgba(0, 0, 0, 0.2),
|
|
198
|
+
inset 0 0 10px rgba(0, 0, 0, 0.3),
|
|
199
|
+
0 0 15px rgba(0, 0, 0, 0.4);
|
|
200
|
+
`)
|
|
201
|
+
).toMatchInlineSnapshot(`
|
|
202
|
+
{
|
|
203
|
+
"type": "layers",
|
|
204
|
+
"value": [
|
|
205
|
+
{
|
|
206
|
+
"type": "tuple",
|
|
207
|
+
"value": [
|
|
208
|
+
{
|
|
209
|
+
"type": "unit",
|
|
210
|
+
"unit": "number",
|
|
211
|
+
"value": 0,
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"type": "unit",
|
|
215
|
+
"unit": "number",
|
|
216
|
+
"value": 0,
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"type": "unit",
|
|
220
|
+
"unit": "px",
|
|
221
|
+
"value": 5,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"alpha": 0.2,
|
|
225
|
+
"b": 0,
|
|
226
|
+
"g": 0,
|
|
227
|
+
"r": 0,
|
|
228
|
+
"type": "rgb",
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"type": "tuple",
|
|
234
|
+
"value": [
|
|
235
|
+
{
|
|
236
|
+
"type": "keyword",
|
|
237
|
+
"value": "inset",
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
"type": "unit",
|
|
241
|
+
"unit": "number",
|
|
242
|
+
"value": 0,
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"type": "unit",
|
|
246
|
+
"unit": "number",
|
|
247
|
+
"value": 0,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"type": "unit",
|
|
251
|
+
"unit": "px",
|
|
252
|
+
"value": 10,
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"alpha": 0.3,
|
|
256
|
+
"b": 0,
|
|
257
|
+
"g": 0,
|
|
258
|
+
"r": 0,
|
|
259
|
+
"type": "rgb",
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"type": "tuple",
|
|
265
|
+
"value": [
|
|
266
|
+
{
|
|
267
|
+
"type": "unit",
|
|
268
|
+
"unit": "number",
|
|
269
|
+
"value": 0,
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"type": "unit",
|
|
273
|
+
"unit": "number",
|
|
274
|
+
"value": 0,
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"type": "unit",
|
|
278
|
+
"unit": "px",
|
|
279
|
+
"value": 15,
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"alpha": 0.4,
|
|
283
|
+
"b": 0,
|
|
284
|
+
"g": 0,
|
|
285
|
+
"r": 0,
|
|
286
|
+
"type": "rgb",
|
|
287
|
+
},
|
|
288
|
+
],
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
}
|
|
292
|
+
`);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import * as csstree from "css-tree";
|
|
2
|
+
import { LayersValue, TupleValue } from "@webstudio-is/css-data";
|
|
3
|
+
import type {
|
|
4
|
+
InvalidValue,
|
|
5
|
+
TupleValueItem,
|
|
6
|
+
Unit,
|
|
7
|
+
} from "@webstudio-is/css-data";
|
|
8
|
+
import { colord } from "colord";
|
|
9
|
+
|
|
10
|
+
const cssTreeTryParseValue = (input: string) => {
|
|
11
|
+
try {
|
|
12
|
+
const ast = csstree.parse(input, { context: "value" });
|
|
13
|
+
return ast;
|
|
14
|
+
} catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const parseBoxShadow = (
|
|
20
|
+
boxShadow: string
|
|
21
|
+
): LayersValue | InvalidValue => {
|
|
22
|
+
let tokenStream = boxShadow.trim();
|
|
23
|
+
tokenStream = tokenStream.endsWith(";")
|
|
24
|
+
? tokenStream.slice(0, -1)
|
|
25
|
+
: tokenStream;
|
|
26
|
+
|
|
27
|
+
const cleanupKeywords = ["box-shadow:"];
|
|
28
|
+
|
|
29
|
+
for (const cleanupKeyword of cleanupKeywords) {
|
|
30
|
+
tokenStream = tokenStream.startsWith(cleanupKeyword)
|
|
31
|
+
? tokenStream.slice(cleanupKeyword.length).trim()
|
|
32
|
+
: tokenStream;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const cssAst = cssTreeTryParseValue(tokenStream);
|
|
36
|
+
|
|
37
|
+
if (cssAst === undefined) {
|
|
38
|
+
return {
|
|
39
|
+
type: "invalid",
|
|
40
|
+
value: boxShadow,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const parsed = csstree.lexer.matchProperty("box-shadow", cssAst);
|
|
45
|
+
if (parsed.error) {
|
|
46
|
+
return {
|
|
47
|
+
type: "invalid",
|
|
48
|
+
value: boxShadow,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const layers: TupleValue[] = [];
|
|
53
|
+
|
|
54
|
+
csstree.walk(cssAst, (node) => {
|
|
55
|
+
if (node.type === "Value") {
|
|
56
|
+
const children = node.children;
|
|
57
|
+
let layer: csstree.CssNode[] = [];
|
|
58
|
+
|
|
59
|
+
for (const child of children) {
|
|
60
|
+
if (children.last === child) {
|
|
61
|
+
layer.push(child);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (child.type === "Operator" || children.last === child) {
|
|
65
|
+
const shadow: TupleValueItem[] = [];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow#syntax
|
|
69
|
+
* `inset` and color can be at the start or end and their sequence can be anywhere.
|
|
70
|
+
* The rest need to foolow the sequence all the time
|
|
71
|
+
*/
|
|
72
|
+
|
|
73
|
+
for (let index = 0; index < layer.length; index++) {
|
|
74
|
+
const item = layer[index];
|
|
75
|
+
|
|
76
|
+
if (item.type === "Identifier") {
|
|
77
|
+
shadow.push({
|
|
78
|
+
type: "keyword",
|
|
79
|
+
value: item.name,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (item.type === "Function" || item.type === "Hash") {
|
|
84
|
+
const colorValue = colord(csstree.generate(item));
|
|
85
|
+
if (!colorValue.isValid()) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const rgb = colorValue.toRgb();
|
|
89
|
+
shadow.push({
|
|
90
|
+
type: "rgb",
|
|
91
|
+
alpha: rgb.a,
|
|
92
|
+
r: rgb.r,
|
|
93
|
+
g: rgb.g,
|
|
94
|
+
b: rgb.b,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (item.type === "Dimension") {
|
|
99
|
+
shadow.push({
|
|
100
|
+
type: "unit",
|
|
101
|
+
value: Number(item.value),
|
|
102
|
+
unit: item.unit as Unit,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (item.type === "Number") {
|
|
107
|
+
shadow.push({
|
|
108
|
+
type: "unit",
|
|
109
|
+
value: Number(item.value),
|
|
110
|
+
unit: "number",
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
layers.push({
|
|
116
|
+
type: "tuple",
|
|
117
|
+
value: shadow,
|
|
118
|
+
});
|
|
119
|
+
layer = [];
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
layer.push(child);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
return layers.length > 0
|
|
129
|
+
? {
|
|
130
|
+
type: "layers",
|
|
131
|
+
value: layers,
|
|
132
|
+
}
|
|
133
|
+
: { type: "invalid", value: boxShadow };
|
|
134
|
+
};
|
package/src/schema.ts
CHANGED
|
@@ -99,31 +99,38 @@ const UnsetValue = z.object({
|
|
|
99
99
|
});
|
|
100
100
|
export type UnsetValue = z.infer<typeof UnsetValue>;
|
|
101
101
|
|
|
102
|
-
export const TupleValueItem = z.union([
|
|
102
|
+
export const TupleValueItem = z.union([
|
|
103
|
+
UnitValue,
|
|
104
|
+
KeywordValue,
|
|
105
|
+
UnparsedValue,
|
|
106
|
+
RgbValue,
|
|
107
|
+
]);
|
|
103
108
|
export type TupleValueItem = z.infer<typeof TupleValueItem>;
|
|
104
109
|
|
|
105
110
|
export const TupleValue = z.object({
|
|
106
111
|
type: z.literal("tuple"),
|
|
107
112
|
value: z.array(TupleValueItem),
|
|
113
|
+
hidden: z.boolean().optional(),
|
|
108
114
|
});
|
|
109
115
|
|
|
110
116
|
export type TupleValue = z.infer<typeof TupleValue>;
|
|
111
117
|
|
|
118
|
+
const LayerValueItem = z.union([
|
|
119
|
+
UnitValue,
|
|
120
|
+
KeywordValue,
|
|
121
|
+
UnparsedValue,
|
|
122
|
+
ImageValue,
|
|
123
|
+
TupleValue,
|
|
124
|
+
InvalidValue,
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
export type LayerValueItem = z.infer<typeof LayerValueItem>;
|
|
112
128
|
// To support background layers https://developer.mozilla.org/en-US/docs/Web/CSS/background
|
|
113
129
|
// and similar comma separated css properties
|
|
114
130
|
// InvalidValue used in case of asset not found
|
|
115
131
|
export const LayersValue = z.object({
|
|
116
132
|
type: z.literal("layers"),
|
|
117
|
-
value: z.array(
|
|
118
|
-
z.union([
|
|
119
|
-
UnitValue,
|
|
120
|
-
KeywordValue,
|
|
121
|
-
UnparsedValue,
|
|
122
|
-
ImageValue,
|
|
123
|
-
TupleValue,
|
|
124
|
-
InvalidValue,
|
|
125
|
-
])
|
|
126
|
-
),
|
|
133
|
+
value: z.array(LayerValueItem),
|
|
127
134
|
});
|
|
128
135
|
|
|
129
136
|
export type LayersValue = z.infer<typeof LayersValue>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|