@webstudio-is/css-data 0.65.0 → 0.67.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__/keyword-values.js +2 -2
- package/lib/__generated__/properties.js +2 -2
- package/lib/cjs/__generated__/keyword-values.js +2 -2
- package/lib/cjs/__generated__/properties.js +2 -2
- package/lib/cjs/html.js +1 -3
- package/lib/cjs/index.js +3 -0
- package/lib/cjs/parse-css-value.js +152 -0
- package/lib/cjs/parse-css.js +125 -0
- package/lib/cjs/property-parsers/background.js +105 -0
- package/lib/cjs/property-parsers/index.js +18 -0
- package/lib/cjs/property-parsers/parsers.js +24 -0
- package/lib/cjs/property-parsers/to-longhand.js +24 -0
- package/lib/html.js +1 -3
- package/lib/index.js +3 -0
- package/lib/parse-css-value.js +122 -0
- package/lib/parse-css.js +95 -0
- package/lib/property-parsers/background.js +75 -0
- package/lib/property-parsers/index.js +1 -0
- package/lib/property-parsers/parsers.js +4 -0
- package/lib/property-parsers/to-longhand.js +4 -0
- package/lib/types/src/__generated__/keyword-values.d.ts +1 -1
- package/lib/types/src/__generated__/properties.d.ts +2 -2
- package/lib/types/src/index.d.ts +5 -2
- package/lib/types/src/parse-css-value.d.ts +3 -0
- package/lib/types/src/parse-css-value.test.d.ts +1 -0
- package/lib/types/src/parse-css.d.ts +9 -0
- package/lib/types/src/parse-css.test.d.ts +1 -0
- package/lib/types/src/property-parsers/background.d.ts +11 -0
- package/lib/types/src/property-parsers/background.test.d.ts +1 -0
- package/lib/types/src/property-parsers/index.d.ts +1 -0
- package/lib/types/src/property-parsers/parsers.d.ts +1 -0
- package/lib/types/src/property-parsers/to-longhand.d.ts +1 -0
- package/package.json +12 -4
- package/src/__generated__/keyword-values.ts +2 -2
- package/src/__generated__/properties.ts +2 -2
- package/src/html.ts +1 -3
- package/src/index.ts +6 -0
- package/src/parse-css-value.test.ts +136 -0
- package/src/parse-css-value.ts +157 -0
- package/src/parse-css.test.ts +101 -0
- package/src/parse-css.ts +124 -0
- package/src/property-parsers/README.md +11 -0
- package/src/property-parsers/background.test.ts +184 -0
- package/src/property-parsers/background.ts +132 -0
- package/src/property-parsers/index.ts +1 -0
- package/src/property-parsers/parsers.ts +4 -0
- package/src/property-parsers/to-longhand.ts +4 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { colord } from "colord";
|
|
2
|
+
import * as csstree from "css-tree";
|
|
3
|
+
import hyphenate from "hyphenate-style-name";
|
|
4
|
+
import warnOnce from "warn-once";
|
|
5
|
+
import { keywordValues } from "./__generated__/keyword-values";
|
|
6
|
+
import { units } from "./__generated__/units";
|
|
7
|
+
import type { StyleProperty, StyleValue, Unit } from "./schema";
|
|
8
|
+
|
|
9
|
+
const cssTryParseValue = (input: string) => {
|
|
10
|
+
try {
|
|
11
|
+
const ast = csstree.parse(input, { context: "value" });
|
|
12
|
+
return ast;
|
|
13
|
+
} catch {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const isValidDeclaration = (
|
|
19
|
+
property: string,
|
|
20
|
+
value: string
|
|
21
|
+
): boolean => {
|
|
22
|
+
const ast = cssTryParseValue(value);
|
|
23
|
+
|
|
24
|
+
if (ast == null) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const cssPropertyName = hyphenate(property);
|
|
29
|
+
|
|
30
|
+
const matchResult = csstree.lexer.matchProperty(cssPropertyName, ast);
|
|
31
|
+
|
|
32
|
+
const isValidDeclaration = matchResult.matched != null;
|
|
33
|
+
|
|
34
|
+
// @todo remove after fix https://github.com/csstree/csstree/issues/246
|
|
35
|
+
if (isValidDeclaration && typeof CSSStyleValue !== "undefined") {
|
|
36
|
+
try {
|
|
37
|
+
CSSStyleValue.parse(cssPropertyName, value);
|
|
38
|
+
} catch {
|
|
39
|
+
warnOnce(
|
|
40
|
+
true,
|
|
41
|
+
`Css property "${property}" with value "${value}" is invalid according to CSSStyleValue.parse
|
|
42
|
+
but valid according to csstree.lexer.matchProperty.`
|
|
43
|
+
);
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return isValidDeclaration;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const parseCssValue = (
|
|
52
|
+
property: StyleProperty, // Handles only long-hand values.
|
|
53
|
+
input: string
|
|
54
|
+
): StyleValue => {
|
|
55
|
+
const invalidValue = {
|
|
56
|
+
type: "invalid",
|
|
57
|
+
value: input,
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
60
|
+
if (input.length === 0) {
|
|
61
|
+
return invalidValue;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!isValidDeclaration(property, input)) {
|
|
65
|
+
return invalidValue;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const ast = cssTryParseValue(input);
|
|
69
|
+
|
|
70
|
+
if (ast == null) {
|
|
71
|
+
warnOnce(
|
|
72
|
+
true,
|
|
73
|
+
`Can't parse css property "${property}" with value "${input}"`
|
|
74
|
+
);
|
|
75
|
+
return invalidValue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (
|
|
79
|
+
ast != null &&
|
|
80
|
+
ast.type === "Value" &&
|
|
81
|
+
ast.children.first === ast.children.last
|
|
82
|
+
) {
|
|
83
|
+
// Try extract units from 1st children
|
|
84
|
+
const first = ast.children.first;
|
|
85
|
+
|
|
86
|
+
if (first?.type === "Number") {
|
|
87
|
+
return {
|
|
88
|
+
type: "unit",
|
|
89
|
+
unit: "number",
|
|
90
|
+
value: Number(first.value),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (first?.type === "Dimension") {
|
|
95
|
+
const unit = first.unit as (typeof units)[keyof typeof units][number];
|
|
96
|
+
|
|
97
|
+
for (const unitGroup of Object.values(units)) {
|
|
98
|
+
if (unitGroup.includes(unit as never)) {
|
|
99
|
+
return {
|
|
100
|
+
type: "unit",
|
|
101
|
+
unit: unit as Unit,
|
|
102
|
+
value: Number(first.value),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return invalidValue;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (first?.type === "Percentage") {
|
|
110
|
+
return {
|
|
111
|
+
type: "unit",
|
|
112
|
+
unit: "%",
|
|
113
|
+
value: Number(first.value),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (first?.type === "Identifier") {
|
|
118
|
+
const values = keywordValues[
|
|
119
|
+
property as keyof typeof keywordValues
|
|
120
|
+
] as ReadonlyArray<string>;
|
|
121
|
+
const lettersRegex = /[^a-zA-Z]+/g;
|
|
122
|
+
const searchValues = values.map((value) =>
|
|
123
|
+
value.replace(lettersRegex, "").toLowerCase()
|
|
124
|
+
);
|
|
125
|
+
const keywordInput = input.replace(lettersRegex, "").toLowerCase();
|
|
126
|
+
|
|
127
|
+
const index = searchValues.indexOf(keywordInput);
|
|
128
|
+
|
|
129
|
+
if (index > -1) {
|
|
130
|
+
return {
|
|
131
|
+
type: "keyword",
|
|
132
|
+
value: values[index],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Probably a color (we can use csstree.lexer.matchProperty(cssPropertyName, ast) to extract the type but this looks much simpler)
|
|
139
|
+
if (property.toLocaleLowerCase().includes("color")) {
|
|
140
|
+
const mayBeColor = colord(input);
|
|
141
|
+
if (mayBeColor.isValid()) {
|
|
142
|
+
const rgb = mayBeColor.toRgb();
|
|
143
|
+
return {
|
|
144
|
+
type: "rgb",
|
|
145
|
+
alpha: rgb.a,
|
|
146
|
+
r: rgb.r,
|
|
147
|
+
g: rgb.g,
|
|
148
|
+
b: rgb.b,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
type: "unparsed",
|
|
155
|
+
value: input,
|
|
156
|
+
};
|
|
157
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import { parseCss } from "./parse-css";
|
|
3
|
+
|
|
4
|
+
describe("Parse CSS", () => {
|
|
5
|
+
test("one class selector rules", () => {
|
|
6
|
+
expect(parseCss(`.test { color: #ff0000 }`)).toMatchInlineSnapshot(`
|
|
7
|
+
{
|
|
8
|
+
"test": [
|
|
9
|
+
{
|
|
10
|
+
"property": "color",
|
|
11
|
+
"value": {
|
|
12
|
+
"alpha": 1,
|
|
13
|
+
"b": 0,
|
|
14
|
+
"g": 0,
|
|
15
|
+
"r": 255,
|
|
16
|
+
"type": "rgb",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
}
|
|
21
|
+
`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("parses supported shorthand values", () => {
|
|
25
|
+
expect(
|
|
26
|
+
parseCss(
|
|
27
|
+
`.test { background: #ff0000 linear-gradient(180deg, #11181C 0%, rgba(17, 24, 28, 0) 36.09%), #EBFFFC; }`
|
|
28
|
+
).test
|
|
29
|
+
).toMatchInlineSnapshot(`
|
|
30
|
+
[
|
|
31
|
+
{
|
|
32
|
+
"property": "backgroundImage",
|
|
33
|
+
"value": {
|
|
34
|
+
"type": "layers",
|
|
35
|
+
"value": [
|
|
36
|
+
{
|
|
37
|
+
"type": "unparsed",
|
|
38
|
+
"value": "linear-gradient(180deg,#11181C 0%,rgba(17,24,28,0) 36.09%)",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"property": "backgroundColor",
|
|
45
|
+
"value": {
|
|
46
|
+
"alpha": 1,
|
|
47
|
+
"b": 252,
|
|
48
|
+
"g": 255,
|
|
49
|
+
"r": 235,
|
|
50
|
+
"type": "rgb",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
]
|
|
54
|
+
`);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("parses unsupported shorthand values", () => {
|
|
58
|
+
expect(parseCss(`.test { padding: 4px }`).test[0]).toMatchInlineSnapshot(`
|
|
59
|
+
{
|
|
60
|
+
"property": "padding",
|
|
61
|
+
"value": {
|
|
62
|
+
"type": "unit",
|
|
63
|
+
"unit": "px",
|
|
64
|
+
"value": 4,
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
`);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("complex selector rules", () => {
|
|
71
|
+
expect(parseCss(`.test, a, .test2, .test:hover { color: #ff0000 }`))
|
|
72
|
+
.toMatchInlineSnapshot(`
|
|
73
|
+
{
|
|
74
|
+
"test": [
|
|
75
|
+
{
|
|
76
|
+
"property": "color",
|
|
77
|
+
"value": {
|
|
78
|
+
"alpha": 1,
|
|
79
|
+
"b": 0,
|
|
80
|
+
"g": 0,
|
|
81
|
+
"r": 255,
|
|
82
|
+
"type": "rgb",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
"test2": [
|
|
87
|
+
{
|
|
88
|
+
"property": "color",
|
|
89
|
+
"value": {
|
|
90
|
+
"alpha": 1,
|
|
91
|
+
"b": 0,
|
|
92
|
+
"g": 0,
|
|
93
|
+
"r": 255,
|
|
94
|
+
"type": "rgb",
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
}
|
|
99
|
+
`);
|
|
100
|
+
});
|
|
101
|
+
});
|
package/src/parse-css.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import * as csstree from "css-tree";
|
|
2
|
+
import { parseCssValue as parseCssValueLonghand } from "./parse-css-value";
|
|
3
|
+
import * as parsers from "./property-parsers/parsers";
|
|
4
|
+
import * as toLonghand from "./property-parsers/to-longhand";
|
|
5
|
+
import { StyleValue, type Style as S, type StyleProperty } from "./schema";
|
|
6
|
+
|
|
7
|
+
type Selector = string;
|
|
8
|
+
type Style = {
|
|
9
|
+
// @todo add support for states and media queries in addition to declarations
|
|
10
|
+
property: StyleProperty;
|
|
11
|
+
value: StyleValue;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type Styles = Record<Selector, Style[]>;
|
|
15
|
+
|
|
16
|
+
type Longhand = keyof typeof toLonghand;
|
|
17
|
+
|
|
18
|
+
const parseCssValue = function parseCssValue(
|
|
19
|
+
property: Longhand | StyleProperty,
|
|
20
|
+
value: string
|
|
21
|
+
): S {
|
|
22
|
+
const unwrap = toLonghand[property as Longhand];
|
|
23
|
+
|
|
24
|
+
if (typeof unwrap === "function") {
|
|
25
|
+
const longhands = unwrap(value);
|
|
26
|
+
|
|
27
|
+
return Object.fromEntries(
|
|
28
|
+
Object.entries(longhands).map(([property, value]) => {
|
|
29
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
30
|
+
// @ts-ignore @todo remove this ignore: property is a `keyof typeof longhands` which is a key in parsers but TS can't infer the link
|
|
31
|
+
const valueParser = parsers[property];
|
|
32
|
+
|
|
33
|
+
if (typeof valueParser === "function") {
|
|
34
|
+
return [property, valueParser(value)];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (Array.isArray(value)) {
|
|
38
|
+
return [
|
|
39
|
+
property,
|
|
40
|
+
{
|
|
41
|
+
type: "invalid",
|
|
42
|
+
value: value.join(""),
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!value) {
|
|
48
|
+
return [property, { type: "invalid", value: "" }];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return [
|
|
52
|
+
property,
|
|
53
|
+
parseCssValueLonghand(property as StyleProperty, value),
|
|
54
|
+
];
|
|
55
|
+
})
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
[property]: parseCssValueLonghand(property as StyleProperty, value),
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const parseCss = function cssToWS(css: string) {
|
|
65
|
+
const ast = csstree.parse(css);
|
|
66
|
+
|
|
67
|
+
let selectors: Selector[] = [];
|
|
68
|
+
const styles: Styles = {};
|
|
69
|
+
|
|
70
|
+
csstree.walk(ast, (node, item) => {
|
|
71
|
+
if (node.type === "SelectorList") {
|
|
72
|
+
selectors = [];
|
|
73
|
+
}
|
|
74
|
+
if (node.type === "ClassSelector") {
|
|
75
|
+
if (!item.prev && !item.next) {
|
|
76
|
+
selectors.push(node.name);
|
|
77
|
+
}
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (node.type === "Declaration") {
|
|
82
|
+
const stringValue = csstree.generate(node.value);
|
|
83
|
+
|
|
84
|
+
const parsedCss = parseCssValue(
|
|
85
|
+
node.property as Longhand | StyleProperty,
|
|
86
|
+
stringValue
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
(Object.entries(parsedCss) as [StyleProperty, StyleValue][]).forEach(
|
|
90
|
+
([property, value]) => {
|
|
91
|
+
try {
|
|
92
|
+
StyleValue.parse(value);
|
|
93
|
+
selectors.forEach((selector) => {
|
|
94
|
+
if (Array.isArray(styles[selector])) {
|
|
95
|
+
styles[selector].push({
|
|
96
|
+
property,
|
|
97
|
+
value,
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
styles[selector] = [{ property, value }];
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
} catch (error) {
|
|
104
|
+
if (process.env.NODE_ENV !== "production") {
|
|
105
|
+
// eslint-disable-next-line no-console
|
|
106
|
+
console.warn(
|
|
107
|
+
true,
|
|
108
|
+
`Declaration parsing for \`${selectors.join(", ")}.${
|
|
109
|
+
node.property
|
|
110
|
+
}: ${stringValue}\` failed:\n\n${JSON.stringify(
|
|
111
|
+
parsedCss,
|
|
112
|
+
null,
|
|
113
|
+
2
|
|
114
|
+
)}`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return styles;
|
|
124
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Properties Parsers
|
|
2
|
+
|
|
3
|
+
This folder contains:
|
|
4
|
+
|
|
5
|
+
- `parsers.ts` individual properties parses
|
|
6
|
+
- `to-longhand.ts` shorthand forms unwrappers
|
|
7
|
+
|
|
8
|
+
The idea is that these two modules export a number of utilities whose name match the property that they parse or unwrap e.g.:
|
|
9
|
+
|
|
10
|
+
- `backgroundImage` is a property parser
|
|
11
|
+
- `background` is a "to-longhand" unwrapper
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
|
|
3
|
+
import { parseBackground } from "./background";
|
|
4
|
+
|
|
5
|
+
describe("parseBackground", () => {
|
|
6
|
+
test("parse background from figma", () => {
|
|
7
|
+
expect(
|
|
8
|
+
parseBackground(
|
|
9
|
+
"linear-gradient(180deg, #11181C 0%, rgba(17, 24, 28, 0) 36.09%), none, linear-gradient(180deg, rgba(230, 60, 254, 0.33) 0%, rgba(255, 174, 60, 0) 100%), radial-gradient(54.1% 95.83% at 100% 100%, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%), linear-gradient(122.33deg, rgba(74, 78, 250, 0.2) 0%, rgba(0, 0, 0, 0) 69.38%), radial-gradient(92.26% 201.29% at 98.6% 10.65%, rgba(255, 174, 60, 0.3) 0%, rgba(227, 53, 255, 0) 100%) /* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */, radial-gradient(84.64% 267.51% at 10.07% 81.45%, rgba(53, 255, 182, 0.2) 0%, rgba(74, 78, 250, 0.2) 100%) /* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */, #EBFFFC;"
|
|
10
|
+
)
|
|
11
|
+
).toMatchInlineSnapshot(`
|
|
12
|
+
{
|
|
13
|
+
"backgroundColor": {
|
|
14
|
+
"alpha": 1,
|
|
15
|
+
"b": 252,
|
|
16
|
+
"g": 255,
|
|
17
|
+
"r": 235,
|
|
18
|
+
"type": "rgb",
|
|
19
|
+
},
|
|
20
|
+
"backgroundImage": {
|
|
21
|
+
"type": "layers",
|
|
22
|
+
"value": [
|
|
23
|
+
{
|
|
24
|
+
"type": "unparsed",
|
|
25
|
+
"value": "linear-gradient(180deg,#11181C 0%,rgba(17,24,28,0) 36.09%)",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"type": "unparsed",
|
|
29
|
+
"value": "linear-gradient(180deg,rgba(230,60,254,0.33) 0%,rgba(255,174,60,0) 100%)",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"type": "unparsed",
|
|
33
|
+
"value": "radial-gradient(54.1% 95.83%at 100% 100%,#FFFFFF 0%,rgba(255,255,255,0) 100%)",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"type": "unparsed",
|
|
37
|
+
"value": "linear-gradient(122.33deg,rgba(74,78,250,0.2) 0%,rgba(0,0,0,0) 69.38%)",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"type": "unparsed",
|
|
41
|
+
"value": "radial-gradient(92.26% 201.29%at 98.6% 10.65%,rgba(255,174,60,0.3) 0%,rgba(227,53,255,0) 100%)",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"type": "unparsed",
|
|
45
|
+
"value": "radial-gradient(84.64% 267.51%at 10.07% 81.45%,rgba(53,255,182,0.2) 0%,rgba(74,78,250,0.2) 100%)",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
`);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("parse background from figma without backgroundColor", () => {
|
|
54
|
+
expect(
|
|
55
|
+
parseBackground(
|
|
56
|
+
"linear-gradient(180deg, #11181C 0%, rgba(17, 24, 28, 0) 36.09%), linear-gradient(180deg, rgba(230, 60, 254, 0.33) 0%, rgba(255, 174, 60, 0) 100%), radial-gradient(54.1% 95.83% at 100% 100%, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%), linear-gradient(122.33deg, rgba(74, 78, 250, 0.2) 0%, rgba(0, 0, 0, 0) 69.38%), radial-gradient(92.26% 201.29% at 98.6% 10.65%, rgba(255, 174, 60, 0.3) 0%, rgba(227, 53, 255, 0) 100%) /* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */, radial-gradient(84.64% 267.51% at 10.07% 81.45%, rgba(53, 255, 182, 0.2) 0%, rgba(74, 78, 250, 0.2) 100%) /* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */"
|
|
57
|
+
)
|
|
58
|
+
).toMatchInlineSnapshot(`
|
|
59
|
+
{
|
|
60
|
+
"backgroundColor": undefined,
|
|
61
|
+
"backgroundImage": {
|
|
62
|
+
"type": "layers",
|
|
63
|
+
"value": [
|
|
64
|
+
{
|
|
65
|
+
"type": "unparsed",
|
|
66
|
+
"value": "linear-gradient(180deg,#11181C 0%,rgba(17,24,28,0) 36.09%)",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"type": "unparsed",
|
|
70
|
+
"value": "linear-gradient(180deg,rgba(230,60,254,0.33) 0%,rgba(255,174,60,0) 100%)",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"type": "unparsed",
|
|
74
|
+
"value": "radial-gradient(54.1% 95.83%at 100% 100%,#FFFFFF 0%,rgba(255,255,255,0) 100%)",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"type": "unparsed",
|
|
78
|
+
"value": "linear-gradient(122.33deg,rgba(74,78,250,0.2) 0%,rgba(0,0,0,0) 69.38%)",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"type": "unparsed",
|
|
82
|
+
"value": "radial-gradient(92.26% 201.29%at 98.6% 10.65%,rgba(255,174,60,0.3) 0%,rgba(227,53,255,0) 100%)",
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"type": "unparsed",
|
|
86
|
+
"value": "radial-gradient(84.64% 267.51%at 10.07% 81.45%,rgba(53,255,182,0.2) 0%,rgba(74,78,250,0.2) 100%)",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
`);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("parse background and skips url background", () => {
|
|
95
|
+
expect(
|
|
96
|
+
parseBackground(
|
|
97
|
+
"url(https://hello.world/some-image), linear-gradient(180deg, rgba(230, 60, 254, 0.33) 0%, rgba(255, 174, 60, 0) 100%), radial-gradient(54.1% 95.83% at 100% 100%, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%), linear-gradient(122.33deg, rgba(74, 78, 250, 0.2) 0%, rgba(0, 0, 0, 0) 69.38%), radial-gradient(92.26% 201.29% at 98.6% 10.65%, rgba(255, 174, 60, 0.3) 0%, rgba(227, 53, 255, 0) 100%) /* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */, radial-gradient(84.64% 267.51% at 10.07% 81.45%, rgba(53, 255, 182, 0.2) 0%, rgba(74, 78, 250, 0.2) 100%) /* warning: gradient uses a rotation that is not supported by CSS and may not behave as expected */"
|
|
98
|
+
)
|
|
99
|
+
).toMatchInlineSnapshot(`
|
|
100
|
+
{
|
|
101
|
+
"backgroundColor": undefined,
|
|
102
|
+
"backgroundImage": {
|
|
103
|
+
"type": "layers",
|
|
104
|
+
"value": [
|
|
105
|
+
{
|
|
106
|
+
"type": "unparsed",
|
|
107
|
+
"value": "linear-gradient(180deg,rgba(230,60,254,0.33) 0%,rgba(255,174,60,0) 100%)",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"type": "unparsed",
|
|
111
|
+
"value": "radial-gradient(54.1% 95.83%at 100% 100%,#FFFFFF 0%,rgba(255,255,255,0) 100%)",
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"type": "unparsed",
|
|
115
|
+
"value": "linear-gradient(122.33deg,rgba(74,78,250,0.2) 0%,rgba(0,0,0,0) 69.38%)",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"type": "unparsed",
|
|
119
|
+
"value": "radial-gradient(92.26% 201.29%at 98.6% 10.65%,rgba(255,174,60,0.3) 0%,rgba(227,53,255,0) 100%)",
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"type": "unparsed",
|
|
123
|
+
"value": "radial-gradient(84.64% 267.51%at 10.07% 81.45%,rgba(53,255,182,0.2) 0%,rgba(74,78,250,0.2) 100%)",
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
}
|
|
128
|
+
`);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("parse background partially copied background", () => {
|
|
132
|
+
expect(
|
|
133
|
+
parseBackground(
|
|
134
|
+
"linear-gradient(180deg, #11181C 0%, rgba(17, 24, 28, 0) 36.09%), linear-gradient(180deg, "
|
|
135
|
+
)
|
|
136
|
+
).toMatchInlineSnapshot(`
|
|
137
|
+
{
|
|
138
|
+
"backgroundColor": undefined,
|
|
139
|
+
"backgroundImage": {
|
|
140
|
+
"type": "layers",
|
|
141
|
+
"value": [
|
|
142
|
+
{
|
|
143
|
+
"type": "unparsed",
|
|
144
|
+
"value": "linear-gradient(180deg,#11181C 0%,rgba(17,24,28,0) 36.09%)",
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
}
|
|
149
|
+
`);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("parse background partially commented", () => {
|
|
153
|
+
expect(
|
|
154
|
+
parseBackground(
|
|
155
|
+
"linear-gradient(180deg, rgba(230, 60, 254, 0.33) 0%, rgba(255, 174, 60, 0) 100%), /* radial-gradient(54.1% 95.83% at 100% 100%, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%) */"
|
|
156
|
+
)
|
|
157
|
+
).toMatchInlineSnapshot(`
|
|
158
|
+
{
|
|
159
|
+
"backgroundColor": undefined,
|
|
160
|
+
"backgroundImage": {
|
|
161
|
+
"type": "layers",
|
|
162
|
+
"value": [
|
|
163
|
+
{
|
|
164
|
+
"type": "unparsed",
|
|
165
|
+
"value": "linear-gradient(180deg,rgba(230,60,254,0.33) 0%,rgba(255,174,60,0) 100%)",
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
`);
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("parse bad background", () => {
|
|
174
|
+
expect(parseBackground("linear-gradient(180deg,")).toMatchInlineSnapshot(`
|
|
175
|
+
{
|
|
176
|
+
"backgroundColor": undefined,
|
|
177
|
+
"backgroundImage": {
|
|
178
|
+
"type": "invalid",
|
|
179
|
+
"value": "linear-gradient(180deg,)",
|
|
180
|
+
},
|
|
181
|
+
}
|
|
182
|
+
`);
|
|
183
|
+
});
|
|
184
|
+
});
|