@webstudio-is/sdk 0.95.0 → 0.97.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/index.js +390 -13
- package/package.json +5 -5
- package/lib/instances-utils.js +0 -44
- package/lib/instances-utils.test.js +0 -63
- package/lib/schema/assets.js +0 -30
- package/lib/schema/breakpoints.js +0 -22
- package/lib/schema/data-sources.js +0 -39
- package/lib/schema/deployment.js +0 -6
- package/lib/schema/instances.js +0 -19
- package/lib/schema/pages.js +0 -51
- package/lib/schema/props.js +0 -67
- package/lib/schema/style-source-selections.js +0 -9
- package/lib/schema/style-sources.js +0 -14
- package/lib/schema/styles.js +0 -16
- package/lib/scope.js +0 -25
- package/lib/scope.test.js +0 -15
package/lib/index.js
CHANGED
|
@@ -1,13 +1,390 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
// src/schema/assets.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { FontFormat, FontMeta } from "@webstudio-is/fonts";
|
|
4
|
+
var AssetId = z.string();
|
|
5
|
+
var baseAsset = {
|
|
6
|
+
id: AssetId,
|
|
7
|
+
projectId: z.string(),
|
|
8
|
+
size: z.number(),
|
|
9
|
+
name: z.string(),
|
|
10
|
+
description: z.union([z.string(), z.null()]),
|
|
11
|
+
createdAt: z.string()
|
|
12
|
+
};
|
|
13
|
+
var FontAsset = z.object({
|
|
14
|
+
...baseAsset,
|
|
15
|
+
format: FontFormat,
|
|
16
|
+
meta: FontMeta,
|
|
17
|
+
type: z.literal("font")
|
|
18
|
+
});
|
|
19
|
+
var ImageMeta = z.object({
|
|
20
|
+
width: z.number(),
|
|
21
|
+
height: z.number()
|
|
22
|
+
});
|
|
23
|
+
var ImageAsset = z.object({
|
|
24
|
+
...baseAsset,
|
|
25
|
+
format: z.string(),
|
|
26
|
+
meta: ImageMeta,
|
|
27
|
+
type: z.literal("image")
|
|
28
|
+
});
|
|
29
|
+
var Asset = z.union([FontAsset, ImageAsset]);
|
|
30
|
+
var Assets = z.map(AssetId, Asset);
|
|
31
|
+
|
|
32
|
+
// src/schema/pages.ts
|
|
33
|
+
import { z as z2 } from "zod";
|
|
34
|
+
var MIN_TITLE_LENGTH = 2;
|
|
35
|
+
var PageName = z2.string().refine((value) => value.trim() !== "", "Can't be empty");
|
|
36
|
+
var PageTitle = z2.string().refine(
|
|
37
|
+
(val) => val.length >= MIN_TITLE_LENGTH,
|
|
38
|
+
`Minimum ${MIN_TITLE_LENGTH} characters required`
|
|
39
|
+
);
|
|
40
|
+
var commonPageFields = {
|
|
41
|
+
id: z2.string(),
|
|
42
|
+
name: PageName,
|
|
43
|
+
title: PageTitle,
|
|
44
|
+
meta: z2.record(z2.string(), z2.string()),
|
|
45
|
+
rootInstanceId: z2.string()
|
|
46
|
+
};
|
|
47
|
+
var HomePagePath = z2.string().refine((path) => path === "", "Home page path must be empty");
|
|
48
|
+
var HomePage = z2.object({
|
|
49
|
+
...commonPageFields,
|
|
50
|
+
path: HomePagePath
|
|
51
|
+
});
|
|
52
|
+
var pathValidators = (baseValidator) => baseValidator.refine((path) => path !== "", "Can't be empty").refine((path) => path !== "/", "Can't be just a /").refine(
|
|
53
|
+
(path) => path === "" || path.startsWith("/"),
|
|
54
|
+
"Must start with a /"
|
|
55
|
+
).refine((path) => path.endsWith("/") === false, "Can't end with a /").refine(
|
|
56
|
+
(path) => path.includes("//") === false,
|
|
57
|
+
"Can't contain repeating /"
|
|
58
|
+
).refine(
|
|
59
|
+
(path) => /^[-_a-z0-9\\/]*$/.test(path),
|
|
60
|
+
"Only a-z, 0-9, -, _ and / are allowed"
|
|
61
|
+
).refine(
|
|
62
|
+
// We use /s for our system stuff like /s/css or /s/uploads
|
|
63
|
+
(path) => path !== "/s" && path.startsWith("/s/") === false,
|
|
64
|
+
"/s prefix is reserved for the system"
|
|
65
|
+
).refine(
|
|
66
|
+
// Remix serves build artefacts like JS bundles from /build
|
|
67
|
+
// And we cannot customize it due to bug in Remix: https://github.com/remix-run/remix/issues/2933
|
|
68
|
+
(path) => path !== "/build" && path.startsWith("/build/") === false,
|
|
69
|
+
"/build prefix is reserved for the system"
|
|
70
|
+
);
|
|
71
|
+
var PagePath = pathValidators(z2.string());
|
|
72
|
+
var Page = z2.object({
|
|
73
|
+
...commonPageFields,
|
|
74
|
+
path: PagePath
|
|
75
|
+
});
|
|
76
|
+
var Pages = z2.object({
|
|
77
|
+
homePage: HomePage,
|
|
78
|
+
pages: z2.array(Page).refine(
|
|
79
|
+
(array) => new Set(array.map((page) => page.path)).size === array.length,
|
|
80
|
+
"All paths must be unique"
|
|
81
|
+
)
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// src/schema/instances.ts
|
|
85
|
+
import { z as z3 } from "zod";
|
|
86
|
+
var Text = z3.object({
|
|
87
|
+
type: z3.literal("text"),
|
|
88
|
+
value: z3.string()
|
|
89
|
+
});
|
|
90
|
+
var InstanceId = z3.string();
|
|
91
|
+
var Id = z3.object({
|
|
92
|
+
type: z3.literal("id"),
|
|
93
|
+
value: InstanceId
|
|
94
|
+
});
|
|
95
|
+
var Instance = z3.object({
|
|
96
|
+
type: z3.literal("instance"),
|
|
97
|
+
id: InstanceId,
|
|
98
|
+
component: z3.string(),
|
|
99
|
+
label: z3.string().optional(),
|
|
100
|
+
children: z3.array(z3.union([Id, Text]))
|
|
101
|
+
});
|
|
102
|
+
var Instances = z3.map(InstanceId, Instance);
|
|
103
|
+
|
|
104
|
+
// src/schema/data-sources.ts
|
|
105
|
+
import { z as z4 } from "zod";
|
|
106
|
+
var DataSourceId = z4.string();
|
|
107
|
+
var DataSourceVariableValue = z4.union([
|
|
108
|
+
z4.object({
|
|
109
|
+
type: z4.literal("number"),
|
|
110
|
+
// initial value of variable store
|
|
111
|
+
value: z4.number()
|
|
112
|
+
}),
|
|
113
|
+
z4.object({
|
|
114
|
+
type: z4.literal("string"),
|
|
115
|
+
value: z4.string()
|
|
116
|
+
}),
|
|
117
|
+
z4.object({
|
|
118
|
+
type: z4.literal("boolean"),
|
|
119
|
+
value: z4.boolean()
|
|
120
|
+
}),
|
|
121
|
+
z4.object({
|
|
122
|
+
type: z4.literal("string[]"),
|
|
123
|
+
value: z4.array(z4.string())
|
|
124
|
+
})
|
|
125
|
+
]);
|
|
126
|
+
var DataSource = z4.union([
|
|
127
|
+
z4.object({
|
|
128
|
+
type: z4.literal("variable"),
|
|
129
|
+
id: DataSourceId,
|
|
130
|
+
scopeInstanceId: z4.optional(z4.string()),
|
|
131
|
+
name: z4.string(),
|
|
132
|
+
value: DataSourceVariableValue
|
|
133
|
+
}),
|
|
134
|
+
z4.object({
|
|
135
|
+
type: z4.literal("expression"),
|
|
136
|
+
id: DataSourceId,
|
|
137
|
+
scopeInstanceId: z4.optional(z4.string()),
|
|
138
|
+
name: z4.string(),
|
|
139
|
+
code: z4.string()
|
|
140
|
+
})
|
|
141
|
+
]);
|
|
142
|
+
var DataSources = z4.map(DataSourceId, DataSource);
|
|
143
|
+
|
|
144
|
+
// src/schema/props.ts
|
|
145
|
+
import { z as z5 } from "zod";
|
|
146
|
+
var PropId = z5.string();
|
|
147
|
+
var baseProp = {
|
|
148
|
+
id: PropId,
|
|
149
|
+
instanceId: z5.string(),
|
|
150
|
+
name: z5.string(),
|
|
151
|
+
required: z5.optional(z5.boolean())
|
|
152
|
+
};
|
|
153
|
+
var Prop = z5.union([
|
|
154
|
+
z5.object({
|
|
155
|
+
...baseProp,
|
|
156
|
+
type: z5.literal("number"),
|
|
157
|
+
value: z5.number()
|
|
158
|
+
}),
|
|
159
|
+
z5.object({
|
|
160
|
+
...baseProp,
|
|
161
|
+
type: z5.literal("string"),
|
|
162
|
+
value: z5.string()
|
|
163
|
+
}),
|
|
164
|
+
z5.object({
|
|
165
|
+
...baseProp,
|
|
166
|
+
type: z5.literal("boolean"),
|
|
167
|
+
value: z5.boolean()
|
|
168
|
+
}),
|
|
169
|
+
z5.object({
|
|
170
|
+
...baseProp,
|
|
171
|
+
type: z5.literal("asset"),
|
|
172
|
+
value: z5.string()
|
|
173
|
+
// asset id
|
|
174
|
+
}),
|
|
175
|
+
z5.object({
|
|
176
|
+
...baseProp,
|
|
177
|
+
type: z5.literal("page"),
|
|
178
|
+
value: z5.union([
|
|
179
|
+
z5.string(),
|
|
180
|
+
// page id
|
|
181
|
+
z5.object({
|
|
182
|
+
pageId: z5.string(),
|
|
183
|
+
instanceId: z5.string()
|
|
184
|
+
})
|
|
185
|
+
])
|
|
186
|
+
}),
|
|
187
|
+
z5.object({
|
|
188
|
+
...baseProp,
|
|
189
|
+
type: z5.literal("string[]"),
|
|
190
|
+
value: z5.array(z5.string())
|
|
191
|
+
}),
|
|
192
|
+
z5.object({
|
|
193
|
+
...baseProp,
|
|
194
|
+
type: z5.literal("dataSource"),
|
|
195
|
+
// data source id
|
|
196
|
+
value: z5.string()
|
|
197
|
+
}),
|
|
198
|
+
z5.object({
|
|
199
|
+
...baseProp,
|
|
200
|
+
type: z5.literal("action"),
|
|
201
|
+
value: z5.array(
|
|
202
|
+
z5.object({
|
|
203
|
+
type: z5.literal("execute"),
|
|
204
|
+
args: z5.array(z5.string()),
|
|
205
|
+
code: z5.string()
|
|
206
|
+
})
|
|
207
|
+
)
|
|
208
|
+
})
|
|
209
|
+
]);
|
|
210
|
+
var Props = z5.map(PropId, Prop);
|
|
211
|
+
|
|
212
|
+
// src/schema/breakpoints.ts
|
|
213
|
+
import { z as z6 } from "zod";
|
|
214
|
+
var BreakpointId = z6.string();
|
|
215
|
+
var Breakpoint = z6.object({
|
|
216
|
+
id: BreakpointId,
|
|
217
|
+
label: z6.string(),
|
|
218
|
+
minWidth: z6.number().optional(),
|
|
219
|
+
maxWidth: z6.number().optional()
|
|
220
|
+
}).refine(({ minWidth, maxWidth }) => {
|
|
221
|
+
return (
|
|
222
|
+
// Either min or max width have to be defined
|
|
223
|
+
minWidth !== void 0 && maxWidth === void 0 || minWidth === void 0 && maxWidth !== void 0 || // This is a base breakpoint
|
|
224
|
+
minWidth === void 0 && maxWidth === void 0
|
|
225
|
+
);
|
|
226
|
+
}, "Either minWidth or maxWidth should be defined");
|
|
227
|
+
var Breakpoints = z6.map(BreakpointId, Breakpoint);
|
|
228
|
+
var initialBreakpoints = [
|
|
229
|
+
{ id: "placeholder", label: "Base" },
|
|
230
|
+
{ id: "placeholder", label: "Tablet", maxWidth: 991 },
|
|
231
|
+
{ id: "placeholder", label: "Mobile landscape", maxWidth: 767 },
|
|
232
|
+
{ id: "placeholder", label: "Mobile portrait", maxWidth: 479 }
|
|
233
|
+
];
|
|
234
|
+
|
|
235
|
+
// src/schema/style-sources.ts
|
|
236
|
+
import { z as z7 } from "zod";
|
|
237
|
+
var StyleSourceId = z7.string();
|
|
238
|
+
var StyleSourceToken = z7.object({
|
|
239
|
+
type: z7.literal("token"),
|
|
240
|
+
id: StyleSourceId,
|
|
241
|
+
name: z7.string()
|
|
242
|
+
});
|
|
243
|
+
var StyleSourceLocal = z7.object({
|
|
244
|
+
type: z7.literal("local"),
|
|
245
|
+
id: StyleSourceId
|
|
246
|
+
});
|
|
247
|
+
var StyleSource = z7.union([StyleSourceToken, StyleSourceLocal]);
|
|
248
|
+
var StyleSources = z7.map(StyleSourceId, StyleSource);
|
|
249
|
+
|
|
250
|
+
// src/schema/style-source-selections.ts
|
|
251
|
+
import { z as z8 } from "zod";
|
|
252
|
+
var InstanceId2 = z8.string();
|
|
253
|
+
var StyleSourceId2 = z8.string();
|
|
254
|
+
var StyleSourceSelection = z8.object({
|
|
255
|
+
instanceId: InstanceId2,
|
|
256
|
+
values: z8.array(StyleSourceId2)
|
|
257
|
+
});
|
|
258
|
+
var StyleSourceSelections = z8.map(InstanceId2, StyleSourceSelection);
|
|
259
|
+
|
|
260
|
+
// src/schema/styles.ts
|
|
261
|
+
import { z as z9 } from "zod";
|
|
262
|
+
import { StyleValue } from "@webstudio-is/css-engine";
|
|
263
|
+
var StyleDeclRaw = z9.object({
|
|
264
|
+
styleSourceId: z9.string(),
|
|
265
|
+
breakpointId: z9.string(),
|
|
266
|
+
state: z9.optional(z9.string()),
|
|
267
|
+
// @todo can't figure out how to make property to be enum
|
|
268
|
+
property: z9.string(),
|
|
269
|
+
value: StyleValue
|
|
270
|
+
});
|
|
271
|
+
var StyleDecl = StyleDeclRaw;
|
|
272
|
+
var getStyleDeclKey = (styleDecl) => {
|
|
273
|
+
return `${styleDecl.styleSourceId}:${styleDecl.breakpointId}:${styleDecl.property}:${styleDecl.state ?? ""}`;
|
|
274
|
+
};
|
|
275
|
+
var Styles = z9.map(z9.string(), StyleDecl);
|
|
276
|
+
|
|
277
|
+
// src/schema/deployment.ts
|
|
278
|
+
import { z as z10 } from "zod";
|
|
279
|
+
var Deployment = z10.object({
|
|
280
|
+
domains: z10.array(z10.string()),
|
|
281
|
+
projectDomain: z10.string()
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// src/instances-utils.ts
|
|
285
|
+
var traverseInstances = (instances, instanceId, callback) => {
|
|
286
|
+
const instance = instances.get(instanceId);
|
|
287
|
+
if (instance === void 0) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const skipTraversingChildren = callback(instance);
|
|
291
|
+
if (skipTraversingChildren === false) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
for (const child of instance.children) {
|
|
295
|
+
if (child.type === "id") {
|
|
296
|
+
traverseInstances(instances, child.value, callback);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
var findTreeInstanceIds = (instances, rootInstanceId) => {
|
|
301
|
+
const ids = /* @__PURE__ */ new Set();
|
|
302
|
+
traverseInstances(instances, rootInstanceId, (instance) => {
|
|
303
|
+
ids.add(instance.id);
|
|
304
|
+
});
|
|
305
|
+
return ids;
|
|
306
|
+
};
|
|
307
|
+
var findTreeInstanceIdsExcludingSlotDescendants = (instances, rootInstanceId) => {
|
|
308
|
+
const ids = /* @__PURE__ */ new Set();
|
|
309
|
+
traverseInstances(instances, rootInstanceId, (instance) => {
|
|
310
|
+
ids.add(instance.id);
|
|
311
|
+
if (instance.component === "Slot") {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
return ids;
|
|
316
|
+
};
|
|
317
|
+
var parseComponentName = (componentName) => {
|
|
318
|
+
const parts = componentName.split(":");
|
|
319
|
+
let namespace;
|
|
320
|
+
let name;
|
|
321
|
+
if (parts.length === 1) {
|
|
322
|
+
[name] = parts;
|
|
323
|
+
} else {
|
|
324
|
+
[namespace, name] = parts;
|
|
325
|
+
}
|
|
326
|
+
return [namespace, name];
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
// src/scope.ts
|
|
330
|
+
var createScope = (occupiedIdentifiers = []) => {
|
|
331
|
+
const freeIndexByPreferredName = /* @__PURE__ */ new Map();
|
|
332
|
+
const scopedNameByIdMap = /* @__PURE__ */ new Map();
|
|
333
|
+
for (const identifier of occupiedIdentifiers) {
|
|
334
|
+
freeIndexByPreferredName.set(identifier, 1);
|
|
335
|
+
}
|
|
336
|
+
const getName = (id, preferredName) => {
|
|
337
|
+
const cachedName = scopedNameByIdMap.get(id);
|
|
338
|
+
if (cachedName !== void 0) {
|
|
339
|
+
return cachedName;
|
|
340
|
+
}
|
|
341
|
+
const index = freeIndexByPreferredName.get(preferredName);
|
|
342
|
+
freeIndexByPreferredName.set(preferredName, (index ?? 0) + 1);
|
|
343
|
+
let scopedName = preferredName;
|
|
344
|
+
if (index !== void 0) {
|
|
345
|
+
scopedName = `${preferredName}_${index}`;
|
|
346
|
+
}
|
|
347
|
+
scopedNameByIdMap.set(id, scopedName);
|
|
348
|
+
return scopedName;
|
|
349
|
+
};
|
|
350
|
+
return {
|
|
351
|
+
getName
|
|
352
|
+
};
|
|
353
|
+
};
|
|
354
|
+
export {
|
|
355
|
+
Asset,
|
|
356
|
+
Assets,
|
|
357
|
+
Breakpoint,
|
|
358
|
+
Breakpoints,
|
|
359
|
+
DataSource,
|
|
360
|
+
DataSourceVariableValue,
|
|
361
|
+
DataSources,
|
|
362
|
+
Deployment,
|
|
363
|
+
FontAsset,
|
|
364
|
+
HomePagePath,
|
|
365
|
+
Id,
|
|
366
|
+
ImageAsset,
|
|
367
|
+
ImageMeta,
|
|
368
|
+
Instance,
|
|
369
|
+
Instances,
|
|
370
|
+
PageName,
|
|
371
|
+
PagePath,
|
|
372
|
+
PageTitle,
|
|
373
|
+
Pages,
|
|
374
|
+
Prop,
|
|
375
|
+
Props,
|
|
376
|
+
StyleDecl,
|
|
377
|
+
StyleSource,
|
|
378
|
+
StyleSourceSelection,
|
|
379
|
+
StyleSourceSelections,
|
|
380
|
+
StyleSources,
|
|
381
|
+
Styles,
|
|
382
|
+
Text,
|
|
383
|
+
createScope,
|
|
384
|
+
findTreeInstanceIds,
|
|
385
|
+
findTreeInstanceIdsExcludingSlotDescendants,
|
|
386
|
+
getStyleDeclKey,
|
|
387
|
+
initialBreakpoints,
|
|
388
|
+
parseComponentName,
|
|
389
|
+
pathValidators
|
|
390
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webstudio-is/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.97.0",
|
|
4
4
|
"description": "Webstudio site data schema",
|
|
5
5
|
"author": "Webstudio <github@webstudio.is>",
|
|
6
6
|
"homepage": "https://webstudio.is",
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"sideEffects": false,
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"zod": "^3.21.4",
|
|
22
|
-
"@webstudio-is/fonts": "^0.
|
|
23
|
-
"@webstudio-is/css-engine": "^0.
|
|
22
|
+
"@webstudio-is/fonts": "^0.97.0",
|
|
23
|
+
"@webstudio-is/css-engine": "^0.97.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@jest/globals": "^29.6.4",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"typecheck": "tsc",
|
|
33
33
|
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
|
34
34
|
"checks": "pnpm typecheck && pnpm test",
|
|
35
|
-
"dev": "
|
|
36
|
-
"build": "rm -rf lib && esbuild
|
|
35
|
+
"dev": "rm -rf lib && esbuild 'src/**/*.ts' 'src/**/*.tsx' --outdir=lib --watch",
|
|
36
|
+
"build": "rm -rf lib && esbuild src/index.ts --outdir=lib --bundle --format=esm --packages=external",
|
|
37
37
|
"dts": "tsc --project tsconfig.dts.json"
|
|
38
38
|
}
|
|
39
39
|
}
|
package/lib/instances-utils.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const traverseInstances = (instances, instanceId, callback) => {
|
|
3
|
-
const instance = instances.get(instanceId);
|
|
4
|
-
if (instance === void 0) {
|
|
5
|
-
return;
|
|
6
|
-
}
|
|
7
|
-
const skipTraversingChildren = callback(instance);
|
|
8
|
-
if (skipTraversingChildren === false) {
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
for (const child of instance.children) {
|
|
12
|
-
if (child.type === "id") {
|
|
13
|
-
traverseInstances(instances, child.value, callback);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
export const findTreeInstanceIds = (instances, rootInstanceId) => {
|
|
18
|
-
const ids = /* @__PURE__ */ new Set();
|
|
19
|
-
traverseInstances(instances, rootInstanceId, (instance) => {
|
|
20
|
-
ids.add(instance.id);
|
|
21
|
-
});
|
|
22
|
-
return ids;
|
|
23
|
-
};
|
|
24
|
-
export const findTreeInstanceIdsExcludingSlotDescendants = (instances, rootInstanceId) => {
|
|
25
|
-
const ids = /* @__PURE__ */ new Set();
|
|
26
|
-
traverseInstances(instances, rootInstanceId, (instance) => {
|
|
27
|
-
ids.add(instance.id);
|
|
28
|
-
if (instance.component === "Slot") {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
return ids;
|
|
33
|
-
};
|
|
34
|
-
export const parseComponentName = (componentName) => {
|
|
35
|
-
const parts = componentName.split(":");
|
|
36
|
-
let namespace;
|
|
37
|
-
let name;
|
|
38
|
-
if (parts.length === 1) {
|
|
39
|
-
[name] = parts;
|
|
40
|
-
} else {
|
|
41
|
-
[namespace, name] = parts;
|
|
42
|
-
}
|
|
43
|
-
return [namespace, name];
|
|
44
|
-
};
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { expect, test } from "@jest/globals";
|
|
3
|
-
import {
|
|
4
|
-
findTreeInstanceIds,
|
|
5
|
-
findTreeInstanceIdsExcludingSlotDescendants,
|
|
6
|
-
parseComponentName
|
|
7
|
-
} from "./instances-utils";
|
|
8
|
-
const createInstance = (id, component, children) => {
|
|
9
|
-
return {
|
|
10
|
-
type: "instance",
|
|
11
|
-
id,
|
|
12
|
-
component,
|
|
13
|
-
children
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
const createInstancePair = (id, component, children) => {
|
|
17
|
-
return [id, createInstance(id, component, children)];
|
|
18
|
-
};
|
|
19
|
-
test("find all tree instances", () => {
|
|
20
|
-
const instances = new Map([
|
|
21
|
-
createInstancePair("1", "Body", [{ type: "id", value: "3" }]),
|
|
22
|
-
// this is outside of subtree
|
|
23
|
-
createInstancePair("2", "Box", []),
|
|
24
|
-
// these should be matched
|
|
25
|
-
createInstancePair("3", "Box", [
|
|
26
|
-
{ type: "id", value: "4" },
|
|
27
|
-
{ type: "id", value: "5" }
|
|
28
|
-
]),
|
|
29
|
-
createInstancePair("4", "Box", []),
|
|
30
|
-
createInstancePair("5", "Box", []),
|
|
31
|
-
// this one is from other tree
|
|
32
|
-
createInstancePair("6", "Box", [])
|
|
33
|
-
]);
|
|
34
|
-
expect(findTreeInstanceIds(instances, "3")).toEqual(/* @__PURE__ */ new Set(["3", "4", "5"]));
|
|
35
|
-
});
|
|
36
|
-
test("find all tree instances excluding slot descendants", () => {
|
|
37
|
-
const instances = new Map([
|
|
38
|
-
createInstancePair("root", "Body", [
|
|
39
|
-
{ type: "id", value: "box1" },
|
|
40
|
-
{ type: "id", value: "box2" }
|
|
41
|
-
]),
|
|
42
|
-
// this is outside of subtree
|
|
43
|
-
createInstancePair("outside", "Box", []),
|
|
44
|
-
// these should be matched
|
|
45
|
-
createInstancePair("box1", "Box", [
|
|
46
|
-
{ type: "id", value: "slot11" },
|
|
47
|
-
{ type: "id", value: "box12" }
|
|
48
|
-
]),
|
|
49
|
-
createInstancePair("slot11", "Slot", [
|
|
50
|
-
{ type: "id", value: "box111" },
|
|
51
|
-
{ type: "id", value: "box112" }
|
|
52
|
-
]),
|
|
53
|
-
createInstancePair("box12", "Box", []),
|
|
54
|
-
createInstancePair("box2", "Box", [])
|
|
55
|
-
]);
|
|
56
|
-
expect(
|
|
57
|
-
findTreeInstanceIdsExcludingSlotDescendants(instances, "box1")
|
|
58
|
-
).toEqual(/* @__PURE__ */ new Set(["box1", "box12", "slot11"]));
|
|
59
|
-
});
|
|
60
|
-
test("extract short name and namespace from component name", () => {
|
|
61
|
-
expect(parseComponentName("Box")).toEqual([void 0, "Box"]);
|
|
62
|
-
expect(parseComponentName("radix:Box")).toEqual(["radix", "Box"]);
|
|
63
|
-
});
|
package/lib/schema/assets.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { FontFormat, FontMeta } from "@webstudio-is/fonts";
|
|
4
|
-
const AssetId = z.string();
|
|
5
|
-
const baseAsset = {
|
|
6
|
-
id: AssetId,
|
|
7
|
-
projectId: z.string(),
|
|
8
|
-
size: z.number(),
|
|
9
|
-
name: z.string(),
|
|
10
|
-
description: z.union([z.string(), z.null()]),
|
|
11
|
-
createdAt: z.string()
|
|
12
|
-
};
|
|
13
|
-
export const FontAsset = z.object({
|
|
14
|
-
...baseAsset,
|
|
15
|
-
format: FontFormat,
|
|
16
|
-
meta: FontMeta,
|
|
17
|
-
type: z.literal("font")
|
|
18
|
-
});
|
|
19
|
-
export const ImageMeta = z.object({
|
|
20
|
-
width: z.number(),
|
|
21
|
-
height: z.number()
|
|
22
|
-
});
|
|
23
|
-
export const ImageAsset = z.object({
|
|
24
|
-
...baseAsset,
|
|
25
|
-
format: z.string(),
|
|
26
|
-
meta: ImageMeta,
|
|
27
|
-
type: z.literal("image")
|
|
28
|
-
});
|
|
29
|
-
export const Asset = z.union([FontAsset, ImageAsset]);
|
|
30
|
-
export const Assets = z.map(AssetId, Asset);
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
const BreakpointId = z.string();
|
|
4
|
-
export const Breakpoint = z.object({
|
|
5
|
-
id: BreakpointId,
|
|
6
|
-
label: z.string(),
|
|
7
|
-
minWidth: z.number().optional(),
|
|
8
|
-
maxWidth: z.number().optional()
|
|
9
|
-
}).refine(({ minWidth, maxWidth }) => {
|
|
10
|
-
return (
|
|
11
|
-
// Either min or max width have to be defined
|
|
12
|
-
minWidth !== void 0 && maxWidth === void 0 || minWidth === void 0 && maxWidth !== void 0 || // This is a base breakpoint
|
|
13
|
-
minWidth === void 0 && maxWidth === void 0
|
|
14
|
-
);
|
|
15
|
-
}, "Either minWidth or maxWidth should be defined");
|
|
16
|
-
export const Breakpoints = z.map(BreakpointId, Breakpoint);
|
|
17
|
-
export const initialBreakpoints = [
|
|
18
|
-
{ id: "placeholder", label: "Base" },
|
|
19
|
-
{ id: "placeholder", label: "Tablet", maxWidth: 991 },
|
|
20
|
-
{ id: "placeholder", label: "Mobile landscape", maxWidth: 767 },
|
|
21
|
-
{ id: "placeholder", label: "Mobile portrait", maxWidth: 479 }
|
|
22
|
-
];
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
const DataSourceId = z.string();
|
|
4
|
-
export const DataSourceVariableValue = z.union([
|
|
5
|
-
z.object({
|
|
6
|
-
type: z.literal("number"),
|
|
7
|
-
// initial value of variable store
|
|
8
|
-
value: z.number()
|
|
9
|
-
}),
|
|
10
|
-
z.object({
|
|
11
|
-
type: z.literal("string"),
|
|
12
|
-
value: z.string()
|
|
13
|
-
}),
|
|
14
|
-
z.object({
|
|
15
|
-
type: z.literal("boolean"),
|
|
16
|
-
value: z.boolean()
|
|
17
|
-
}),
|
|
18
|
-
z.object({
|
|
19
|
-
type: z.literal("string[]"),
|
|
20
|
-
value: z.array(z.string())
|
|
21
|
-
})
|
|
22
|
-
]);
|
|
23
|
-
export const DataSource = z.union([
|
|
24
|
-
z.object({
|
|
25
|
-
type: z.literal("variable"),
|
|
26
|
-
id: DataSourceId,
|
|
27
|
-
scopeInstanceId: z.optional(z.string()),
|
|
28
|
-
name: z.string(),
|
|
29
|
-
value: DataSourceVariableValue
|
|
30
|
-
}),
|
|
31
|
-
z.object({
|
|
32
|
-
type: z.literal("expression"),
|
|
33
|
-
id: DataSourceId,
|
|
34
|
-
scopeInstanceId: z.optional(z.string()),
|
|
35
|
-
name: z.string(),
|
|
36
|
-
code: z.string()
|
|
37
|
-
})
|
|
38
|
-
]);
|
|
39
|
-
export const DataSources = z.map(DataSourceId, DataSource);
|
package/lib/schema/deployment.js
DELETED
package/lib/schema/instances.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
export const Text = z.object({
|
|
4
|
-
type: z.literal("text"),
|
|
5
|
-
value: z.string()
|
|
6
|
-
});
|
|
7
|
-
const InstanceId = z.string();
|
|
8
|
-
export const Id = z.object({
|
|
9
|
-
type: z.literal("id"),
|
|
10
|
-
value: InstanceId
|
|
11
|
-
});
|
|
12
|
-
export const Instance = z.object({
|
|
13
|
-
type: z.literal("instance"),
|
|
14
|
-
id: InstanceId,
|
|
15
|
-
component: z.string(),
|
|
16
|
-
label: z.string().optional(),
|
|
17
|
-
children: z.array(z.union([Id, Text]))
|
|
18
|
-
});
|
|
19
|
-
export const Instances = z.map(InstanceId, Instance);
|
package/lib/schema/pages.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
const MIN_TITLE_LENGTH = 2;
|
|
4
|
-
export const PageName = z.string().refine((value) => value.trim() !== "", "Can't be empty");
|
|
5
|
-
export const PageTitle = z.string().refine(
|
|
6
|
-
(val) => val.length >= MIN_TITLE_LENGTH,
|
|
7
|
-
`Minimum ${MIN_TITLE_LENGTH} characters required`
|
|
8
|
-
);
|
|
9
|
-
const commonPageFields = {
|
|
10
|
-
id: z.string(),
|
|
11
|
-
name: PageName,
|
|
12
|
-
title: PageTitle,
|
|
13
|
-
meta: z.record(z.string(), z.string()),
|
|
14
|
-
rootInstanceId: z.string()
|
|
15
|
-
};
|
|
16
|
-
export const HomePagePath = z.string().refine((path) => path === "", "Home page path must be empty");
|
|
17
|
-
const HomePage = z.object({
|
|
18
|
-
...commonPageFields,
|
|
19
|
-
path: HomePagePath
|
|
20
|
-
});
|
|
21
|
-
export const pathValidators = (baseValidator) => baseValidator.refine((path) => path !== "", "Can't be empty").refine((path) => path !== "/", "Can't be just a /").refine(
|
|
22
|
-
(path) => path === "" || path.startsWith("/"),
|
|
23
|
-
"Must start with a /"
|
|
24
|
-
).refine((path) => path.endsWith("/") === false, "Can't end with a /").refine(
|
|
25
|
-
(path) => path.includes("//") === false,
|
|
26
|
-
"Can't contain repeating /"
|
|
27
|
-
).refine(
|
|
28
|
-
(path) => /^[-_a-z0-9\\/]*$/.test(path),
|
|
29
|
-
"Only a-z, 0-9, -, _ and / are allowed"
|
|
30
|
-
).refine(
|
|
31
|
-
// We use /s for our system stuff like /s/css or /s/uploads
|
|
32
|
-
(path) => path !== "/s" && path.startsWith("/s/") === false,
|
|
33
|
-
"/s prefix is reserved for the system"
|
|
34
|
-
).refine(
|
|
35
|
-
// Remix serves build artefacts like JS bundles from /build
|
|
36
|
-
// And we cannot customize it due to bug in Remix: https://github.com/remix-run/remix/issues/2933
|
|
37
|
-
(path) => path !== "/build" && path.startsWith("/build/") === false,
|
|
38
|
-
"/build prefix is reserved for the system"
|
|
39
|
-
);
|
|
40
|
-
export const PagePath = pathValidators(z.string());
|
|
41
|
-
const Page = z.object({
|
|
42
|
-
...commonPageFields,
|
|
43
|
-
path: PagePath
|
|
44
|
-
});
|
|
45
|
-
export const Pages = z.object({
|
|
46
|
-
homePage: HomePage,
|
|
47
|
-
pages: z.array(Page).refine(
|
|
48
|
-
(array) => new Set(array.map((page) => page.path)).size === array.length,
|
|
49
|
-
"All paths must be unique"
|
|
50
|
-
)
|
|
51
|
-
});
|
package/lib/schema/props.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
const PropId = z.string();
|
|
4
|
-
const baseProp = {
|
|
5
|
-
id: PropId,
|
|
6
|
-
instanceId: z.string(),
|
|
7
|
-
name: z.string(),
|
|
8
|
-
required: z.optional(z.boolean())
|
|
9
|
-
};
|
|
10
|
-
export const Prop = z.union([
|
|
11
|
-
z.object({
|
|
12
|
-
...baseProp,
|
|
13
|
-
type: z.literal("number"),
|
|
14
|
-
value: z.number()
|
|
15
|
-
}),
|
|
16
|
-
z.object({
|
|
17
|
-
...baseProp,
|
|
18
|
-
type: z.literal("string"),
|
|
19
|
-
value: z.string()
|
|
20
|
-
}),
|
|
21
|
-
z.object({
|
|
22
|
-
...baseProp,
|
|
23
|
-
type: z.literal("boolean"),
|
|
24
|
-
value: z.boolean()
|
|
25
|
-
}),
|
|
26
|
-
z.object({
|
|
27
|
-
...baseProp,
|
|
28
|
-
type: z.literal("asset"),
|
|
29
|
-
value: z.string()
|
|
30
|
-
// asset id
|
|
31
|
-
}),
|
|
32
|
-
z.object({
|
|
33
|
-
...baseProp,
|
|
34
|
-
type: z.literal("page"),
|
|
35
|
-
value: z.union([
|
|
36
|
-
z.string(),
|
|
37
|
-
// page id
|
|
38
|
-
z.object({
|
|
39
|
-
pageId: z.string(),
|
|
40
|
-
instanceId: z.string()
|
|
41
|
-
})
|
|
42
|
-
])
|
|
43
|
-
}),
|
|
44
|
-
z.object({
|
|
45
|
-
...baseProp,
|
|
46
|
-
type: z.literal("string[]"),
|
|
47
|
-
value: z.array(z.string())
|
|
48
|
-
}),
|
|
49
|
-
z.object({
|
|
50
|
-
...baseProp,
|
|
51
|
-
type: z.literal("dataSource"),
|
|
52
|
-
// data source id
|
|
53
|
-
value: z.string()
|
|
54
|
-
}),
|
|
55
|
-
z.object({
|
|
56
|
-
...baseProp,
|
|
57
|
-
type: z.literal("action"),
|
|
58
|
-
value: z.array(
|
|
59
|
-
z.object({
|
|
60
|
-
type: z.literal("execute"),
|
|
61
|
-
args: z.array(z.string()),
|
|
62
|
-
code: z.string()
|
|
63
|
-
})
|
|
64
|
-
)
|
|
65
|
-
})
|
|
66
|
-
]);
|
|
67
|
-
export const Props = z.map(PropId, Prop);
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
const InstanceId = z.string();
|
|
4
|
-
const StyleSourceId = z.string();
|
|
5
|
-
export const StyleSourceSelection = z.object({
|
|
6
|
-
instanceId: InstanceId,
|
|
7
|
-
values: z.array(StyleSourceId)
|
|
8
|
-
});
|
|
9
|
-
export const StyleSourceSelections = z.map(InstanceId, StyleSourceSelection);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
const StyleSourceId = z.string();
|
|
4
|
-
const StyleSourceToken = z.object({
|
|
5
|
-
type: z.literal("token"),
|
|
6
|
-
id: StyleSourceId,
|
|
7
|
-
name: z.string()
|
|
8
|
-
});
|
|
9
|
-
const StyleSourceLocal = z.object({
|
|
10
|
-
type: z.literal("local"),
|
|
11
|
-
id: StyleSourceId
|
|
12
|
-
});
|
|
13
|
-
export const StyleSource = z.union([StyleSourceToken, StyleSourceLocal]);
|
|
14
|
-
export const StyleSources = z.map(StyleSourceId, StyleSource);
|
package/lib/schema/styles.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { StyleValue } from "@webstudio-is/css-engine";
|
|
4
|
-
const StyleDeclRaw = z.object({
|
|
5
|
-
styleSourceId: z.string(),
|
|
6
|
-
breakpointId: z.string(),
|
|
7
|
-
state: z.optional(z.string()),
|
|
8
|
-
// @todo can't figure out how to make property to be enum
|
|
9
|
-
property: z.string(),
|
|
10
|
-
value: StyleValue
|
|
11
|
-
});
|
|
12
|
-
export const StyleDecl = StyleDeclRaw;
|
|
13
|
-
export const getStyleDeclKey = (styleDecl) => {
|
|
14
|
-
return `${styleDecl.styleSourceId}:${styleDecl.breakpointId}:${styleDecl.property}:${styleDecl.state ?? ""}`;
|
|
15
|
-
};
|
|
16
|
-
export const Styles = z.map(z.string(), StyleDecl);
|
package/lib/scope.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
export const createScope = (occupiedIdentifiers = []) => {
|
|
3
|
-
const freeIndexByPreferredName = /* @__PURE__ */ new Map();
|
|
4
|
-
const scopedNameByIdMap = /* @__PURE__ */ new Map();
|
|
5
|
-
for (const identifier of occupiedIdentifiers) {
|
|
6
|
-
freeIndexByPreferredName.set(identifier, 1);
|
|
7
|
-
}
|
|
8
|
-
const getName = (id, preferredName) => {
|
|
9
|
-
const cachedName = scopedNameByIdMap.get(id);
|
|
10
|
-
if (cachedName !== void 0) {
|
|
11
|
-
return cachedName;
|
|
12
|
-
}
|
|
13
|
-
const index = freeIndexByPreferredName.get(preferredName);
|
|
14
|
-
freeIndexByPreferredName.set(preferredName, (index ?? 0) + 1);
|
|
15
|
-
let scopedName = preferredName;
|
|
16
|
-
if (index !== void 0) {
|
|
17
|
-
scopedName = `${preferredName}_${index}`;
|
|
18
|
-
}
|
|
19
|
-
scopedNameByIdMap.set(id, scopedName);
|
|
20
|
-
return scopedName;
|
|
21
|
-
};
|
|
22
|
-
return {
|
|
23
|
-
getName
|
|
24
|
-
};
|
|
25
|
-
};
|
package/lib/scope.test.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
import { expect, test } from "@jest/globals";
|
|
3
|
-
import { createScope } from "./scope";
|
|
4
|
-
test("use variable name for specific id and suffix on collision", () => {
|
|
5
|
-
const scope = createScope();
|
|
6
|
-
expect(scope.getName("1", "myName")).toEqual("myName");
|
|
7
|
-
expect(scope.getName("2", "myName")).toEqual("myName_1");
|
|
8
|
-
expect(scope.getName("1", "myName")).toEqual("myName");
|
|
9
|
-
});
|
|
10
|
-
test("allow to predefine already occupied identifiers", () => {
|
|
11
|
-
const scope = createScope(["myName", "anotherName"]);
|
|
12
|
-
expect(scope.getName("1", "myName")).toEqual("myName_1");
|
|
13
|
-
expect(scope.getName("2", "anotherName")).toEqual("anotherName_1");
|
|
14
|
-
expect(scope.getName("3", "newName")).toEqual("newName");
|
|
15
|
-
});
|