@webstudio-is/css-engine 0.72.0 → 0.73.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/cjs/core/rules.js +31 -7
- package/lib/cjs/core/to-value.js +1 -1
- package/lib/core/rules.js +31 -7
- package/lib/core/to-value.js +1 -1
- package/lib/types/core/rules.d.ts +9 -1
- package/package.json +4 -4
- package/src/core/css-engine.test.ts +111 -38
- package/src/core/rules.ts +27 -6
- package/src/core/to-value.test.ts +1 -1
- package/src/core/to-value.ts +3 -1
package/lib/cjs/core/rules.js
CHANGED
|
@@ -44,12 +44,13 @@ __export(rules_exports, {
|
|
|
44
44
|
module.exports = __toCommonJS(rules_exports);
|
|
45
45
|
var import_to_value = require("./to-value");
|
|
46
46
|
var import_to_property = require("./to-property");
|
|
47
|
-
var _styleMap, _isDirty, _string, _transformValue, _onChange, _mediaType;
|
|
47
|
+
var _styleMap, _isDirty, _string, _indent, _transformValue, _onChange, _mediaType;
|
|
48
48
|
class StylePropertyMap {
|
|
49
49
|
constructor(transformValue) {
|
|
50
50
|
__privateAdd(this, _styleMap, /* @__PURE__ */ new Map());
|
|
51
51
|
__privateAdd(this, _isDirty, false);
|
|
52
52
|
__privateAdd(this, _string, "");
|
|
53
|
+
__privateAdd(this, _indent, 0);
|
|
53
54
|
__privateAdd(this, _transformValue, void 0);
|
|
54
55
|
__privateSet(this, _transformValue, transformValue);
|
|
55
56
|
}
|
|
@@ -77,20 +78,25 @@ class StylePropertyMap {
|
|
|
77
78
|
__privateSet(this, _isDirty, true);
|
|
78
79
|
this.onChange?.();
|
|
79
80
|
}
|
|
80
|
-
toString() {
|
|
81
|
-
if (__privateGet(this, _isDirty) === false) {
|
|
81
|
+
toString({ indent = 0 } = {}) {
|
|
82
|
+
if (__privateGet(this, _isDirty) === false && indent === __privateGet(this, _indent)) {
|
|
82
83
|
return __privateGet(this, _string);
|
|
83
84
|
}
|
|
85
|
+
__privateSet(this, _indent, indent);
|
|
84
86
|
const block = [];
|
|
87
|
+
const spaces = " ".repeat(indent);
|
|
85
88
|
for (const [property, value] of __privateGet(this, _styleMap)) {
|
|
86
89
|
if (value === void 0) {
|
|
87
90
|
continue;
|
|
88
91
|
}
|
|
89
92
|
block.push(
|
|
90
|
-
`${(0, import_to_property.toProperty)(property)}: ${(0, import_to_value.toValue)(
|
|
93
|
+
`${spaces}${(0, import_to_property.toProperty)(property)}: ${(0, import_to_value.toValue)(
|
|
94
|
+
value,
|
|
95
|
+
__privateGet(this, _transformValue)
|
|
96
|
+
)}`
|
|
91
97
|
);
|
|
92
98
|
}
|
|
93
|
-
__privateSet(this, _string, block.join("
|
|
99
|
+
__privateSet(this, _string, block.join(";\n"));
|
|
94
100
|
__privateSet(this, _isDirty, false);
|
|
95
101
|
return __privateGet(this, _string);
|
|
96
102
|
}
|
|
@@ -98,6 +104,7 @@ class StylePropertyMap {
|
|
|
98
104
|
_styleMap = new WeakMap();
|
|
99
105
|
_isDirty = new WeakMap();
|
|
100
106
|
_string = new WeakMap();
|
|
107
|
+
_indent = new WeakMap();
|
|
101
108
|
_transformValue = new WeakMap();
|
|
102
109
|
class StyleRule {
|
|
103
110
|
constructor(selectorText, style, transformValue) {
|
|
@@ -113,7 +120,15 @@ class StyleRule {
|
|
|
113
120
|
this.styleMap.onChange = __privateGet(this, _onChange);
|
|
114
121
|
}
|
|
115
122
|
get cssText() {
|
|
116
|
-
return
|
|
123
|
+
return this.toString();
|
|
124
|
+
}
|
|
125
|
+
toString(options = { indent: 0 }) {
|
|
126
|
+
const spaces = " ".repeat(options.indent);
|
|
127
|
+
return `${spaces}${this.selectorText} {
|
|
128
|
+
${this.styleMap.toString({
|
|
129
|
+
indent: options.indent + 2
|
|
130
|
+
})}
|
|
131
|
+
${spaces}}`;
|
|
117
132
|
}
|
|
118
133
|
}
|
|
119
134
|
_onChange = new WeakMap();
|
|
@@ -129,12 +144,15 @@ class MediaRule {
|
|
|
129
144
|
return rule;
|
|
130
145
|
}
|
|
131
146
|
get cssText() {
|
|
147
|
+
return this.toString();
|
|
148
|
+
}
|
|
149
|
+
toString() {
|
|
132
150
|
if (this.rules.length === 0) {
|
|
133
151
|
return "";
|
|
134
152
|
}
|
|
135
153
|
const rules = [];
|
|
136
154
|
for (const rule of this.rules) {
|
|
137
|
-
rules.push(
|
|
155
|
+
rules.push(rule.toString({ indent: 2 }));
|
|
138
156
|
}
|
|
139
157
|
let conditionText = "";
|
|
140
158
|
const { minWidth, maxWidth } = this.options;
|
|
@@ -157,12 +175,18 @@ class PlaintextRule {
|
|
|
157
175
|
this.styleMap = new StylePropertyMap();
|
|
158
176
|
this.cssText = cssText;
|
|
159
177
|
}
|
|
178
|
+
toString() {
|
|
179
|
+
return this.cssText;
|
|
180
|
+
}
|
|
160
181
|
}
|
|
161
182
|
class FontFaceRule {
|
|
162
183
|
constructor(options) {
|
|
163
184
|
this.options = options;
|
|
164
185
|
}
|
|
165
186
|
get cssText() {
|
|
187
|
+
return this.toString();
|
|
188
|
+
}
|
|
189
|
+
toString() {
|
|
166
190
|
const decls = [];
|
|
167
191
|
const { fontFamily, fontStyle, fontWeight, fontDisplay, src } = this.options;
|
|
168
192
|
decls.push(
|
package/lib/cjs/core/to-value.js
CHANGED
|
@@ -86,7 +86,7 @@ const toValue = (styleValue, transformValue) => {
|
|
|
86
86
|
return value.value;
|
|
87
87
|
}
|
|
88
88
|
if (value.type === "layers") {
|
|
89
|
-
return value.value.map((value2) => toValue(value2, transformValue)).join(",");
|
|
89
|
+
return value.value.map((value2) => toValue(value2, transformValue)).join(", ");
|
|
90
90
|
}
|
|
91
91
|
if (value.type === "tuple") {
|
|
92
92
|
return value.value.map((value2) => toValue(value2, transformValue)).join(" ");
|
package/lib/core/rules.js
CHANGED
|
@@ -16,7 +16,7 @@ var __privateSet = (obj, member, value, setter) => {
|
|
|
16
16
|
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
17
17
|
return value;
|
|
18
18
|
};
|
|
19
|
-
var _styleMap, _isDirty, _string, _transformValue, _onChange, _mediaType;
|
|
19
|
+
var _styleMap, _isDirty, _string, _indent, _transformValue, _onChange, _mediaType;
|
|
20
20
|
import { toValue } from "./to-value";
|
|
21
21
|
import { toProperty } from "./to-property";
|
|
22
22
|
class StylePropertyMap {
|
|
@@ -24,6 +24,7 @@ class StylePropertyMap {
|
|
|
24
24
|
__privateAdd(this, _styleMap, /* @__PURE__ */ new Map());
|
|
25
25
|
__privateAdd(this, _isDirty, false);
|
|
26
26
|
__privateAdd(this, _string, "");
|
|
27
|
+
__privateAdd(this, _indent, 0);
|
|
27
28
|
__privateAdd(this, _transformValue, void 0);
|
|
28
29
|
__privateSet(this, _transformValue, transformValue);
|
|
29
30
|
}
|
|
@@ -51,20 +52,25 @@ class StylePropertyMap {
|
|
|
51
52
|
__privateSet(this, _isDirty, true);
|
|
52
53
|
this.onChange?.();
|
|
53
54
|
}
|
|
54
|
-
toString() {
|
|
55
|
-
if (__privateGet(this, _isDirty) === false) {
|
|
55
|
+
toString({ indent = 0 } = {}) {
|
|
56
|
+
if (__privateGet(this, _isDirty) === false && indent === __privateGet(this, _indent)) {
|
|
56
57
|
return __privateGet(this, _string);
|
|
57
58
|
}
|
|
59
|
+
__privateSet(this, _indent, indent);
|
|
58
60
|
const block = [];
|
|
61
|
+
const spaces = " ".repeat(indent);
|
|
59
62
|
for (const [property, value] of __privateGet(this, _styleMap)) {
|
|
60
63
|
if (value === void 0) {
|
|
61
64
|
continue;
|
|
62
65
|
}
|
|
63
66
|
block.push(
|
|
64
|
-
`${toProperty(property)}: ${toValue(
|
|
67
|
+
`${spaces}${toProperty(property)}: ${toValue(
|
|
68
|
+
value,
|
|
69
|
+
__privateGet(this, _transformValue)
|
|
70
|
+
)}`
|
|
65
71
|
);
|
|
66
72
|
}
|
|
67
|
-
__privateSet(this, _string, block.join("
|
|
73
|
+
__privateSet(this, _string, block.join(";\n"));
|
|
68
74
|
__privateSet(this, _isDirty, false);
|
|
69
75
|
return __privateGet(this, _string);
|
|
70
76
|
}
|
|
@@ -72,6 +78,7 @@ class StylePropertyMap {
|
|
|
72
78
|
_styleMap = new WeakMap();
|
|
73
79
|
_isDirty = new WeakMap();
|
|
74
80
|
_string = new WeakMap();
|
|
81
|
+
_indent = new WeakMap();
|
|
75
82
|
_transformValue = new WeakMap();
|
|
76
83
|
class StyleRule {
|
|
77
84
|
constructor(selectorText, style, transformValue) {
|
|
@@ -87,7 +94,15 @@ class StyleRule {
|
|
|
87
94
|
this.styleMap.onChange = __privateGet(this, _onChange);
|
|
88
95
|
}
|
|
89
96
|
get cssText() {
|
|
90
|
-
return
|
|
97
|
+
return this.toString();
|
|
98
|
+
}
|
|
99
|
+
toString(options = { indent: 0 }) {
|
|
100
|
+
const spaces = " ".repeat(options.indent);
|
|
101
|
+
return `${spaces}${this.selectorText} {
|
|
102
|
+
${this.styleMap.toString({
|
|
103
|
+
indent: options.indent + 2
|
|
104
|
+
})}
|
|
105
|
+
${spaces}}`;
|
|
91
106
|
}
|
|
92
107
|
}
|
|
93
108
|
_onChange = new WeakMap();
|
|
@@ -103,12 +118,15 @@ class MediaRule {
|
|
|
103
118
|
return rule;
|
|
104
119
|
}
|
|
105
120
|
get cssText() {
|
|
121
|
+
return this.toString();
|
|
122
|
+
}
|
|
123
|
+
toString() {
|
|
106
124
|
if (this.rules.length === 0) {
|
|
107
125
|
return "";
|
|
108
126
|
}
|
|
109
127
|
const rules = [];
|
|
110
128
|
for (const rule of this.rules) {
|
|
111
|
-
rules.push(
|
|
129
|
+
rules.push(rule.toString({ indent: 2 }));
|
|
112
130
|
}
|
|
113
131
|
let conditionText = "";
|
|
114
132
|
const { minWidth, maxWidth } = this.options;
|
|
@@ -131,12 +149,18 @@ class PlaintextRule {
|
|
|
131
149
|
this.styleMap = new StylePropertyMap();
|
|
132
150
|
this.cssText = cssText;
|
|
133
151
|
}
|
|
152
|
+
toString() {
|
|
153
|
+
return this.cssText;
|
|
154
|
+
}
|
|
134
155
|
}
|
|
135
156
|
class FontFaceRule {
|
|
136
157
|
constructor(options) {
|
|
137
158
|
this.options = options;
|
|
138
159
|
}
|
|
139
160
|
get cssText() {
|
|
161
|
+
return this.toString();
|
|
162
|
+
}
|
|
163
|
+
toString() {
|
|
140
164
|
const decls = [];
|
|
141
165
|
const { fontFamily, fontStyle, fontWeight, fontDisplay, src } = this.options;
|
|
142
166
|
decls.push(
|
package/lib/core/to-value.js
CHANGED
|
@@ -63,7 +63,7 @@ const toValue = (styleValue, transformValue) => {
|
|
|
63
63
|
return value.value;
|
|
64
64
|
}
|
|
65
65
|
if (value.type === "layers") {
|
|
66
|
-
return value.value.map((value2) => toValue(value2, transformValue)).join(",");
|
|
66
|
+
return value.value.map((value2) => toValue(value2, transformValue)).join(", ");
|
|
67
67
|
}
|
|
68
68
|
if (value.type === "tuple") {
|
|
69
69
|
return value.value.map((value2) => toValue(value2, transformValue)).join(" ");
|
|
@@ -10,7 +10,9 @@ declare class StylePropertyMap {
|
|
|
10
10
|
keys(): IterableIterator<"clip" | "top" | "right" | `--${string}` | "accentColor" | "alignContent" | "alignItems" | "alignSelf" | "alignTracks" | "animationComposition" | "animationDelay" | "animationDirection" | "animationDuration" | "animationFillMode" | "animationIterationCount" | "animationName" | "animationPlayState" | "animationTimingFunction" | "animationTimeline" | "appearance" | "aspectRatio" | "backdropFilter" | "backfaceVisibility" | "backgroundAttachment" | "backgroundBlendMode" | "backgroundClip" | "backgroundColor" | "backgroundImage" | "backgroundOrigin" | "backgroundPosition" | "backgroundPositionX" | "backgroundPositionY" | "backgroundRepeat" | "backgroundSize" | "blockOverflow" | "blockSize" | "borderBlockColor" | "borderBlockStyle" | "borderBlockWidth" | "borderBlockEndColor" | "borderBlockEndStyle" | "borderBlockEndWidth" | "borderBlockStartColor" | "borderBlockStartStyle" | "borderBlockStartWidth" | "borderBottomColor" | "borderBottomLeftRadius" | "borderBottomRightRadius" | "borderBottomStyle" | "borderBottomWidth" | "borderCollapse" | "borderEndEndRadius" | "borderEndStartRadius" | "borderImageOutset" | "borderImageRepeat" | "borderImageSlice" | "borderImageSource" | "borderImageWidth" | "borderInlineColor" | "borderInlineStyle" | "borderInlineWidth" | "borderInlineEndColor" | "borderInlineEndStyle" | "borderInlineEndWidth" | "borderInlineStartColor" | "borderInlineStartStyle" | "borderInlineStartWidth" | "borderLeftColor" | "borderLeftStyle" | "borderLeftWidth" | "borderRightColor" | "borderRightStyle" | "borderRightWidth" | "borderSpacing" | "borderStartEndRadius" | "borderStartStartRadius" | "borderTopColor" | "borderTopLeftRadius" | "borderTopRightRadius" | "borderTopStyle" | "borderTopWidth" | "bottom" | "boxDecorationBreak" | "boxShadow" | "boxSizing" | "breakAfter" | "breakBefore" | "breakInside" | "captionSide" | "caretColor" | "caretShape" | "clear" | "clipPath" | "color" | "printColorAdjust" | "colorScheme" | "columnCount" | "columnFill" | "columnGap" | "columnRuleColor" | "columnRuleStyle" | "columnRuleWidth" | "columnSpan" | "columnWidth" | "contain" | "containIntrinsicBlockSize" | "containIntrinsicHeight" | "containIntrinsicInlineSize" | "containIntrinsicWidth" | "content" | "contentVisibility" | "counterIncrement" | "counterReset" | "counterSet" | "cursor" | "direction" | "display" | "emptyCells" | "filter" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "float" | "fontFamily" | "fontFeatureSettings" | "fontKerning" | "fontLanguageOverride" | "fontOpticalSizing" | "fontVariationSettings" | "fontSize" | "fontSizeAdjust" | "fontStretch" | "fontStyle" | "fontSynthesis" | "fontVariant" | "fontVariantAlternates" | "fontVariantCaps" | "fontVariantEastAsian" | "fontVariantLigatures" | "fontVariantNumeric" | "fontVariantPosition" | "fontWeight" | "forcedColorAdjust" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridColumnEnd" | "gridColumnStart" | "gridRowEnd" | "gridRowStart" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "hangingPunctuation" | "height" | "hyphenateCharacter" | "hyphens" | "imageOrientation" | "imageRendering" | "imageResolution" | "initialLetter" | "initialLetterAlign" | "inlineSize" | "inputSecurity" | "insetBlockEnd" | "insetBlockStart" | "insetInlineEnd" | "insetInlineStart" | "isolation" | "justifyContent" | "justifyItems" | "justifySelf" | "justifyTracks" | "left" | "letterSpacing" | "lineBreak" | "lineClamp" | "lineHeight" | "lineHeightStep" | "listStyleImage" | "listStylePosition" | "listStyleType" | "marginBlockEnd" | "marginBlockStart" | "marginBottom" | "marginInlineEnd" | "marginInlineStart" | "marginLeft" | "marginRight" | "marginTop" | "marginTrim" | "maskBorderMode" | "maskBorderOutset" | "maskBorderRepeat" | "maskBorderSlice" | "maskBorderSource" | "maskBorderWidth" | "maskClip" | "maskComposite" | "maskImage" | "maskMode" | "maskOrigin" | "maskPosition" | "maskRepeat" | "maskSize" | "maskType" | "masonryAutoFlow" | "mathDepth" | "mathShift" | "mathStyle" | "maxBlockSize" | "maxHeight" | "maxInlineSize" | "maxLines" | "maxWidth" | "minBlockSize" | "minHeight" | "minInlineSize" | "minWidth" | "mixBlendMode" | "objectFit" | "objectPosition" | "offsetAnchor" | "offsetDistance" | "offsetPath" | "offsetPosition" | "offsetRotate" | "opacity" | "order" | "orphans" | "outlineColor" | "outlineOffset" | "outlineStyle" | "outlineWidth" | "overflow" | "overflowAnchor" | "overflowBlock" | "overflowClipMargin" | "overflowInline" | "overflowWrap" | "overflowX" | "overflowY" | "overscrollBehavior" | "overscrollBehaviorBlock" | "overscrollBehaviorInline" | "overscrollBehaviorX" | "overscrollBehaviorY" | "paddingBlockEnd" | "paddingBlockStart" | "paddingBottom" | "paddingInlineEnd" | "paddingInlineStart" | "paddingLeft" | "paddingRight" | "paddingTop" | "pageBreakAfter" | "pageBreakBefore" | "pageBreakInside" | "paintOrder" | "perspective" | "perspectiveOrigin" | "pointerEvents" | "position" | "quotes" | "resize" | "rotate" | "rowGap" | "rubyAlign" | "rubyMerge" | "rubyPosition" | "scale" | "scrollbarColor" | "scrollbarGutter" | "scrollbarWidth" | "scrollBehavior" | "scrollMarginBlockStart" | "scrollMarginBlockEnd" | "scrollMarginBottom" | "scrollMarginInlineStart" | "scrollMarginInlineEnd" | "scrollMarginLeft" | "scrollMarginRight" | "scrollMarginTop" | "scrollPaddingBlockStart" | "scrollPaddingBlockEnd" | "scrollPaddingBottom" | "scrollPaddingInlineStart" | "scrollPaddingInlineEnd" | "scrollPaddingLeft" | "scrollPaddingRight" | "scrollPaddingTop" | "scrollSnapAlign" | "scrollSnapStop" | "scrollSnapType" | "scrollTimelineAxis" | "scrollTimelineName" | "shapeImageThreshold" | "shapeMargin" | "shapeOutside" | "tabSize" | "tableLayout" | "textAlign" | "textAlignLast" | "textCombineUpright" | "textDecorationColor" | "textDecorationLine" | "textDecorationSkip" | "textDecorationSkipInk" | "textDecorationStyle" | "textDecorationThickness" | "textEmphasisColor" | "textEmphasisPosition" | "textEmphasisStyle" | "textIndent" | "textJustify" | "textOrientation" | "textOverflow" | "textRendering" | "textShadow" | "textSizeAdjust" | "textTransform" | "textUnderlineOffset" | "textUnderlinePosition" | "touchAction" | "transform" | "transformBox" | "transformOrigin" | "transformStyle" | "transitionDelay" | "transitionDuration" | "transitionProperty" | "transitionTimingFunction" | "translate" | "unicodeBidi" | "userSelect" | "verticalAlign" | "visibility" | "whiteSpace" | "widows" | "width" | "willChange" | "wordBreak" | "wordSpacing" | "wordWrap" | "writingMode" | "zIndex">;
|
|
11
11
|
delete(property: StyleProperty): void;
|
|
12
12
|
clear(): void;
|
|
13
|
-
toString(
|
|
13
|
+
toString({ indent }?: {
|
|
14
|
+
indent?: number | undefined;
|
|
15
|
+
}): string;
|
|
14
16
|
}
|
|
15
17
|
export declare class StyleRule {
|
|
16
18
|
#private;
|
|
@@ -19,6 +21,9 @@ export declare class StyleRule {
|
|
|
19
21
|
onChange?: () => void;
|
|
20
22
|
constructor(selectorText: string, style: Style, transformValue?: TransformValue);
|
|
21
23
|
get cssText(): string;
|
|
24
|
+
toString(options?: {
|
|
25
|
+
indent: number;
|
|
26
|
+
}): string;
|
|
22
27
|
}
|
|
23
28
|
export type MediaRuleOptions = {
|
|
24
29
|
minWidth?: number;
|
|
@@ -32,11 +37,13 @@ export declare class MediaRule {
|
|
|
32
37
|
constructor(options?: MediaRuleOptions);
|
|
33
38
|
insertRule(rule: StyleRule | PlaintextRule): StyleRule | PlaintextRule;
|
|
34
39
|
get cssText(): string;
|
|
40
|
+
toString(): string;
|
|
35
41
|
}
|
|
36
42
|
export declare class PlaintextRule {
|
|
37
43
|
cssText: string;
|
|
38
44
|
styleMap: StylePropertyMap;
|
|
39
45
|
constructor(cssText: string);
|
|
46
|
+
toString(): string;
|
|
40
47
|
}
|
|
41
48
|
export type FontFaceOptions = {
|
|
42
49
|
fontFamily: string;
|
|
@@ -49,6 +56,7 @@ export declare class FontFaceRule {
|
|
|
49
56
|
options: FontFaceOptions;
|
|
50
57
|
constructor(options: FontFaceOptions);
|
|
51
58
|
get cssText(): string;
|
|
59
|
+
toString(): string;
|
|
52
60
|
}
|
|
53
61
|
export type AnyRule = StyleRule | MediaRule | PlaintextRule | FontFaceRule;
|
|
54
62
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webstudio-is/css-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.73.0",
|
|
4
4
|
"description": "CSS Renderer for Webstudio",
|
|
5
5
|
"author": "Webstudio <github@webstudio.is>",
|
|
6
6
|
"homepage": "https://webstudio.is",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"hyphenate-style-name": "^1.0.4",
|
|
10
10
|
"react": "^18.2.0",
|
|
11
11
|
"react-dom": "^18.2.0",
|
|
12
|
-
"@webstudio-is/css-data": "^0.
|
|
13
|
-
"@webstudio-is/fonts": "^0.
|
|
12
|
+
"@webstudio-is/css-data": "^0.73.0",
|
|
13
|
+
"@webstudio-is/fonts": "^0.73.0"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@jest/globals": "^29.3.1",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@types/react": "^18.0.35",
|
|
20
20
|
"@types/react-dom": "^18.0.11",
|
|
21
21
|
"jest": "^29.3.1",
|
|
22
|
-
"typescript": "5.
|
|
22
|
+
"typescript": "5.1.3",
|
|
23
23
|
"@webstudio-is/jest-config": "^1.0.6",
|
|
24
24
|
"@webstudio-is/scripts": "^0.0.0",
|
|
25
25
|
"@webstudio-is/storybook-config": "^0.0.0",
|
|
@@ -37,7 +37,9 @@ describe("CssEngine", () => {
|
|
|
37
37
|
});
|
|
38
38
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
39
39
|
"@media all and (min-width: 0px) {
|
|
40
|
-
.c1 {
|
|
40
|
+
.c1 {
|
|
41
|
+
color: red
|
|
42
|
+
}
|
|
41
43
|
}"
|
|
42
44
|
`);
|
|
43
45
|
});
|
|
@@ -50,7 +52,9 @@ describe("CssEngine", () => {
|
|
|
50
52
|
});
|
|
51
53
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
52
54
|
"@media all and (max-width: 1000px) {
|
|
53
|
-
.c1 {
|
|
55
|
+
.c1 {
|
|
56
|
+
color: red
|
|
57
|
+
}
|
|
54
58
|
}"
|
|
55
59
|
`);
|
|
56
60
|
});
|
|
@@ -63,7 +67,9 @@ describe("CssEngine", () => {
|
|
|
63
67
|
});
|
|
64
68
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
65
69
|
"@media all and (min-width: 360px) and (max-width: 1000px) {
|
|
66
|
-
.c1 {
|
|
70
|
+
.c1 {
|
|
71
|
+
color: red
|
|
72
|
+
}
|
|
67
73
|
}"
|
|
68
74
|
`);
|
|
69
75
|
});
|
|
@@ -75,7 +81,9 @@ describe("CssEngine", () => {
|
|
|
75
81
|
});
|
|
76
82
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
77
83
|
"@media all {
|
|
78
|
-
.c {
|
|
84
|
+
.c {
|
|
85
|
+
display: block
|
|
86
|
+
}
|
|
79
87
|
}"
|
|
80
88
|
`);
|
|
81
89
|
engine.addStyleRule(".c1", {
|
|
@@ -84,8 +92,12 @@ describe("CssEngine", () => {
|
|
|
84
92
|
});
|
|
85
93
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
86
94
|
"@media all {
|
|
87
|
-
.c {
|
|
88
|
-
|
|
95
|
+
.c {
|
|
96
|
+
display: block
|
|
97
|
+
}
|
|
98
|
+
.c1 {
|
|
99
|
+
color: red
|
|
100
|
+
}
|
|
89
101
|
}"
|
|
90
102
|
`);
|
|
91
103
|
|
|
@@ -97,11 +109,17 @@ describe("CssEngine", () => {
|
|
|
97
109
|
// Default media query should allways be the first to have the lowest source order specificity
|
|
98
110
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
99
111
|
"@media all {
|
|
100
|
-
.c {
|
|
101
|
-
|
|
112
|
+
.c {
|
|
113
|
+
display: block
|
|
114
|
+
}
|
|
115
|
+
.c1 {
|
|
116
|
+
color: red
|
|
117
|
+
}
|
|
102
118
|
}
|
|
103
119
|
@media all and (min-width: 0px) {
|
|
104
|
-
.c1 {
|
|
120
|
+
.c1 {
|
|
121
|
+
color: blue
|
|
122
|
+
}
|
|
105
123
|
}"
|
|
106
124
|
`);
|
|
107
125
|
});
|
|
@@ -127,13 +145,19 @@ describe("CssEngine", () => {
|
|
|
127
145
|
// Default media query should allways be the first to have the lowest source order specificity
|
|
128
146
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
129
147
|
"@media all {
|
|
130
|
-
.c3 {
|
|
148
|
+
.c3 {
|
|
149
|
+
display: block
|
|
150
|
+
}
|
|
131
151
|
}
|
|
132
152
|
@media all and (min-width: 0px) {
|
|
133
|
-
.c1 {
|
|
153
|
+
.c1 {
|
|
154
|
+
display: block
|
|
155
|
+
}
|
|
134
156
|
}
|
|
135
157
|
@media all and (min-width: 300px) {
|
|
136
|
-
.c2 {
|
|
158
|
+
.c2 {
|
|
159
|
+
display: flex
|
|
160
|
+
}
|
|
137
161
|
}"
|
|
138
162
|
`);
|
|
139
163
|
});
|
|
@@ -149,8 +173,12 @@ describe("CssEngine", () => {
|
|
|
149
173
|
});
|
|
150
174
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
151
175
|
"@media all {
|
|
152
|
-
.c0 {
|
|
153
|
-
|
|
176
|
+
.c0 {
|
|
177
|
+
display: block
|
|
178
|
+
}
|
|
179
|
+
.c1 {
|
|
180
|
+
display: flex
|
|
181
|
+
}
|
|
154
182
|
}"
|
|
155
183
|
`);
|
|
156
184
|
|
|
@@ -166,8 +194,12 @@ describe("CssEngine", () => {
|
|
|
166
194
|
});
|
|
167
195
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
168
196
|
"@media all {
|
|
169
|
-
.c1 {
|
|
170
|
-
|
|
197
|
+
.c1 {
|
|
198
|
+
display: flex
|
|
199
|
+
}
|
|
200
|
+
.c0 {
|
|
201
|
+
display: block
|
|
202
|
+
}
|
|
171
203
|
}"
|
|
172
204
|
`);
|
|
173
205
|
});
|
|
@@ -183,7 +215,10 @@ describe("CssEngine", () => {
|
|
|
183
215
|
});
|
|
184
216
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
185
217
|
"@media all and (min-width: 0px) {
|
|
186
|
-
.c {
|
|
218
|
+
.c {
|
|
219
|
+
display: block;
|
|
220
|
+
color: red
|
|
221
|
+
}
|
|
187
222
|
}"
|
|
188
223
|
`);
|
|
189
224
|
});
|
|
@@ -198,7 +233,9 @@ describe("CssEngine", () => {
|
|
|
198
233
|
});
|
|
199
234
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
200
235
|
"@media all and (min-width: 0px) {
|
|
201
|
-
.c {
|
|
236
|
+
.c {
|
|
237
|
+
background-color: red
|
|
238
|
+
}
|
|
202
239
|
}"
|
|
203
240
|
`);
|
|
204
241
|
});
|
|
@@ -214,12 +251,18 @@ describe("CssEngine", () => {
|
|
|
214
251
|
});
|
|
215
252
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
216
253
|
"@media all and (min-width: 0px) {
|
|
217
|
-
.c {
|
|
254
|
+
.c {
|
|
255
|
+
display: block;
|
|
256
|
+
color: red
|
|
257
|
+
}
|
|
258
|
+
}"
|
|
259
|
+
`);
|
|
260
|
+
expect(rule1.cssText).toMatchInlineSnapshot(`
|
|
261
|
+
".c {
|
|
262
|
+
display: block;
|
|
263
|
+
color: red
|
|
218
264
|
}"
|
|
219
265
|
`);
|
|
220
|
-
expect(rule1.cssText).toMatchInlineSnapshot(
|
|
221
|
-
`".c { display: block; color: red }"`
|
|
222
|
-
);
|
|
223
266
|
engine.addStyleRule(".c2", {
|
|
224
267
|
style: {
|
|
225
268
|
...style0,
|
|
@@ -229,8 +272,14 @@ describe("CssEngine", () => {
|
|
|
229
272
|
});
|
|
230
273
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
231
274
|
"@media all and (min-width: 0px) {
|
|
232
|
-
.c {
|
|
233
|
-
|
|
275
|
+
.c {
|
|
276
|
+
display: block;
|
|
277
|
+
color: red
|
|
278
|
+
}
|
|
279
|
+
.c2 {
|
|
280
|
+
display: block;
|
|
281
|
+
color: green
|
|
282
|
+
}
|
|
234
283
|
}"
|
|
235
284
|
`);
|
|
236
285
|
});
|
|
@@ -246,22 +295,34 @@ describe("CssEngine", () => {
|
|
|
246
295
|
});
|
|
247
296
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
248
297
|
"@media all and (min-width: 0px) {
|
|
249
|
-
.c {
|
|
298
|
+
.c {
|
|
299
|
+
display: block;
|
|
300
|
+
color: red
|
|
301
|
+
}
|
|
302
|
+
}"
|
|
303
|
+
`);
|
|
304
|
+
expect(rule.cssText).toMatchInlineSnapshot(`
|
|
305
|
+
".c {
|
|
306
|
+
display: block;
|
|
307
|
+
color: red
|
|
250
308
|
}"
|
|
251
309
|
`);
|
|
252
|
-
expect(rule.cssText).toMatchInlineSnapshot(
|
|
253
|
-
`".c { display: block; color: red }"`
|
|
254
|
-
);
|
|
255
310
|
|
|
256
311
|
rule.styleMap.set("color", { type: "keyword", value: "green" });
|
|
257
312
|
|
|
258
|
-
expect(rule.cssText).toMatchInlineSnapshot(
|
|
259
|
-
|
|
260
|
-
|
|
313
|
+
expect(rule.cssText).toMatchInlineSnapshot(`
|
|
314
|
+
".c {
|
|
315
|
+
display: block;
|
|
316
|
+
color: green
|
|
317
|
+
}"
|
|
318
|
+
`);
|
|
261
319
|
|
|
262
320
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
263
321
|
"@media all and (min-width: 0px) {
|
|
264
|
-
.c {
|
|
322
|
+
.c {
|
|
323
|
+
display: block;
|
|
324
|
+
color: green
|
|
325
|
+
}
|
|
265
326
|
}"
|
|
266
327
|
`);
|
|
267
328
|
});
|
|
@@ -276,13 +337,17 @@ describe("CssEngine", () => {
|
|
|
276
337
|
});
|
|
277
338
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
278
339
|
"@media all and (min-width: 0px) {
|
|
279
|
-
.c {
|
|
340
|
+
.c {
|
|
341
|
+
color: red
|
|
342
|
+
}
|
|
280
343
|
}"
|
|
281
344
|
`);
|
|
282
345
|
engine.addMediaRule(mediaId0, { minWidth: 10 });
|
|
283
346
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
284
347
|
"@media all and (min-width: 10px) {
|
|
285
|
-
.c {
|
|
348
|
+
.c {
|
|
349
|
+
color: red
|
|
350
|
+
}
|
|
286
351
|
}"
|
|
287
352
|
`);
|
|
288
353
|
});
|
|
@@ -295,13 +360,17 @@ describe("CssEngine", () => {
|
|
|
295
360
|
});
|
|
296
361
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
297
362
|
"@media all and (min-width: 0px) {
|
|
298
|
-
.c {
|
|
363
|
+
.c {
|
|
364
|
+
display: block
|
|
365
|
+
}
|
|
299
366
|
}"
|
|
300
367
|
`);
|
|
301
368
|
engine.addMediaRule(mediaId0, mediaRuleOptions0);
|
|
302
369
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
303
370
|
"@media all and (min-width: 0px) {
|
|
304
|
-
.c {
|
|
371
|
+
.c {
|
|
372
|
+
display: block
|
|
373
|
+
}
|
|
305
374
|
}"
|
|
306
375
|
`);
|
|
307
376
|
});
|
|
@@ -366,7 +435,9 @@ describe("CssEngine", () => {
|
|
|
366
435
|
rule.styleMap.delete("display");
|
|
367
436
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
368
437
|
"@media all {
|
|
369
|
-
.c {
|
|
438
|
+
.c {
|
|
439
|
+
color: black
|
|
440
|
+
}
|
|
370
441
|
}"
|
|
371
442
|
`);
|
|
372
443
|
});
|
|
@@ -408,7 +479,9 @@ describe("CssEngine", () => {
|
|
|
408
479
|
rule.styleMap.delete("display");
|
|
409
480
|
expect(engine.cssText).toMatchInlineSnapshot(`
|
|
410
481
|
"@media all {
|
|
411
|
-
.c {
|
|
482
|
+
.c {
|
|
483
|
+
background-image: url(foo.png)
|
|
484
|
+
}
|
|
412
485
|
}"
|
|
413
486
|
`);
|
|
414
487
|
});
|
package/src/core/rules.ts
CHANGED
|
@@ -6,6 +6,7 @@ class StylePropertyMap {
|
|
|
6
6
|
#styleMap: Map<StyleProperty, StyleValue | undefined> = new Map();
|
|
7
7
|
#isDirty = false;
|
|
8
8
|
#string = "";
|
|
9
|
+
#indent = 0;
|
|
9
10
|
#transformValue?: TransformValue;
|
|
10
11
|
onChange?: () => void;
|
|
11
12
|
constructor(transformValue?: TransformValue) {
|
|
@@ -35,20 +36,25 @@ class StylePropertyMap {
|
|
|
35
36
|
this.#isDirty = true;
|
|
36
37
|
this.onChange?.();
|
|
37
38
|
}
|
|
38
|
-
toString() {
|
|
39
|
-
if (this.#isDirty === false) {
|
|
39
|
+
toString({ indent = 0 } = {}) {
|
|
40
|
+
if (this.#isDirty === false && indent === this.#indent) {
|
|
40
41
|
return this.#string;
|
|
41
42
|
}
|
|
43
|
+
this.#indent = indent;
|
|
42
44
|
const block: Array<string> = [];
|
|
45
|
+
const spaces = " ".repeat(indent);
|
|
43
46
|
for (const [property, value] of this.#styleMap) {
|
|
44
47
|
if (value === undefined) {
|
|
45
48
|
continue;
|
|
46
49
|
}
|
|
47
50
|
block.push(
|
|
48
|
-
`${toProperty(property)}: ${toValue(
|
|
51
|
+
`${spaces}${toProperty(property)}: ${toValue(
|
|
52
|
+
value,
|
|
53
|
+
this.#transformValue
|
|
54
|
+
)}`
|
|
49
55
|
);
|
|
50
56
|
}
|
|
51
|
-
this.#string = block.join("
|
|
57
|
+
this.#string = block.join(";\n");
|
|
52
58
|
this.#isDirty = false;
|
|
53
59
|
return this.#string;
|
|
54
60
|
}
|
|
@@ -75,7 +81,13 @@ export class StyleRule {
|
|
|
75
81
|
this.onChange?.();
|
|
76
82
|
};
|
|
77
83
|
get cssText() {
|
|
78
|
-
return
|
|
84
|
+
return this.toString();
|
|
85
|
+
}
|
|
86
|
+
toString(options = { indent: 0 }) {
|
|
87
|
+
const spaces = " ".repeat(options.indent);
|
|
88
|
+
return `${spaces}${this.selectorText} {\n${this.styleMap.toString({
|
|
89
|
+
indent: options.indent + 2,
|
|
90
|
+
})}\n${spaces}}`;
|
|
79
91
|
}
|
|
80
92
|
}
|
|
81
93
|
|
|
@@ -98,12 +110,15 @@ export class MediaRule {
|
|
|
98
110
|
return rule;
|
|
99
111
|
}
|
|
100
112
|
get cssText() {
|
|
113
|
+
return this.toString();
|
|
114
|
+
}
|
|
115
|
+
toString() {
|
|
101
116
|
if (this.rules.length === 0) {
|
|
102
117
|
return "";
|
|
103
118
|
}
|
|
104
119
|
const rules = [];
|
|
105
120
|
for (const rule of this.rules) {
|
|
106
|
-
rules.push(
|
|
121
|
+
rules.push(rule.toString({ indent: 2 }));
|
|
107
122
|
}
|
|
108
123
|
let conditionText = "";
|
|
109
124
|
const { minWidth, maxWidth } = this.options;
|
|
@@ -125,6 +140,9 @@ export class PlaintextRule {
|
|
|
125
140
|
constructor(cssText: string) {
|
|
126
141
|
this.cssText = cssText;
|
|
127
142
|
}
|
|
143
|
+
toString() {
|
|
144
|
+
return this.cssText;
|
|
145
|
+
}
|
|
128
146
|
}
|
|
129
147
|
|
|
130
148
|
export type FontFaceOptions = {
|
|
@@ -141,6 +159,9 @@ export class FontFaceRule {
|
|
|
141
159
|
this.options = options;
|
|
142
160
|
}
|
|
143
161
|
get cssText() {
|
|
162
|
+
return this.toString();
|
|
163
|
+
}
|
|
164
|
+
toString() {
|
|
144
165
|
const decls = [];
|
|
145
166
|
const { fontFamily, fontStyle, fontWeight, fontDisplay, src } =
|
|
146
167
|
this.options;
|
package/src/core/to-value.ts
CHANGED
|
@@ -91,7 +91,9 @@ export const toValue = (
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
if (value.type === "layers") {
|
|
94
|
-
return value.value
|
|
94
|
+
return value.value
|
|
95
|
+
.map((value) => toValue(value, transformValue))
|
|
96
|
+
.join(", ");
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
if (value.type === "tuple") {
|