@orion-studios/payload-studio 0.6.0-beta.12 → 0.6.0-beta.121
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/dist/admin/client.js +2062 -547
- package/dist/admin/client.mjs +2079 -577
- package/dist/admin/index.js +124 -15
- package/dist/admin/index.mjs +1 -1
- package/dist/admin-app/client.js +14 -5
- package/dist/admin-app/client.mjs +1 -1
- package/dist/admin-app/styles.css +277 -1
- package/dist/admin.css +98 -2
- package/dist/builder-v2/client.d.mts +18 -0
- package/dist/builder-v2/client.d.ts +18 -0
- package/dist/builder-v2/client.js +3674 -0
- package/dist/builder-v2/client.mjs +3549 -0
- package/dist/builder-v2/index.d.mts +242 -0
- package/dist/builder-v2/index.d.ts +242 -0
- package/dist/builder-v2/index.js +805 -0
- package/dist/builder-v2/index.mjs +755 -0
- package/dist/builder-v2/styles.css +2463 -0
- package/dist/{chunk-PF3EBZXF.mjs → chunk-7ZMXZRBP.mjs} +39 -3
- package/dist/{chunk-XZQILJK3.mjs → chunk-JC3UV74N.mjs} +124 -15
- package/dist/{chunk-KPIX7OSV.mjs → chunk-NF37A575.mjs} +14 -5
- package/dist/{chunk-XKUTZ7IU.mjs → chunk-NGLIA2OE.mjs} +53 -2
- package/dist/{chunk-OTHERBGX.mjs → chunk-ZADL33R6.mjs} +1 -1
- package/dist/{index-Cv-6qnrw.d.mts → index-D5zrOdyv.d.mts} +3 -1
- package/dist/{index-Crx_MtPw.d.ts → index-Dv-Alx4h.d.ts} +3 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +215 -19
- package/dist/index.mjs +4 -4
- package/dist/nextjs/index.js +39 -3
- package/dist/nextjs/index.mjs +2 -2
- package/dist/studio-pages/builder.css +66 -5
- package/dist/studio-pages/client.js +618 -73
- package/dist/studio-pages/client.mjs +641 -96
- package/dist/studio-pages/index.d.mts +1 -1
- package/dist/studio-pages/index.d.ts +1 -1
- package/dist/studio-pages/index.js +91 -4
- package/dist/studio-pages/index.mjs +2 -2
- package/package.json +22 -3
|
@@ -0,0 +1,805 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/builder-v2/index.ts
|
|
31
|
+
var builder_v2_exports = {};
|
|
32
|
+
__export(builder_v2_exports, {
|
|
33
|
+
BuilderPageRuntime: () => BuilderPageRuntime,
|
|
34
|
+
appendBuilderV2PageFields: () => appendBuilderV2PageFields,
|
|
35
|
+
buildBuilderV2PageTree: () => buildBuilderV2PageTree,
|
|
36
|
+
compileBuilderV2Output: () => compileBuilderV2Output,
|
|
37
|
+
createBuilderV2PageFields: () => createBuilderV2PageFields,
|
|
38
|
+
createBuilderV2PageService: () => createBuilderV2PageService,
|
|
39
|
+
createEmptyBuilderV2ProjectData: () => createEmptyBuilderV2ProjectData,
|
|
40
|
+
hasBlockingBuilderV2Issues: () => hasBlockingBuilderV2Issues,
|
|
41
|
+
normalizeBuilderV2ProjectData: () => normalizeBuilderV2ProjectData,
|
|
42
|
+
parseBuilderV2DynamicComponents: () => parseBuilderV2DynamicComponents,
|
|
43
|
+
sanitizeBuilderCss: () => sanitizeBuilderCss,
|
|
44
|
+
sanitizeBuilderHtml: () => sanitizeBuilderHtml,
|
|
45
|
+
scopeBuilderCss: () => scopeBuilderCss,
|
|
46
|
+
splitBuilderV2HtmlIntoChunks: () => splitBuilderV2HtmlIntoChunks,
|
|
47
|
+
toBuilderV2EditorInitialData: () => toBuilderV2EditorInitialData,
|
|
48
|
+
validateBuilderV2Output: () => validateBuilderV2Output
|
|
49
|
+
});
|
|
50
|
+
module.exports = __toCommonJS(builder_v2_exports);
|
|
51
|
+
|
|
52
|
+
// src/builder-v2/payload/builderFields.ts
|
|
53
|
+
var withHiddenAdmin = (field, hidden) => ({
|
|
54
|
+
...field,
|
|
55
|
+
admin: {
|
|
56
|
+
...field.admin || {},
|
|
57
|
+
hidden
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
var createBuilderV2PageFields = (options = {}) => {
|
|
61
|
+
const hidden = options.hidden ?? true;
|
|
62
|
+
return [
|
|
63
|
+
withHiddenAdmin(
|
|
64
|
+
{
|
|
65
|
+
name: "builderMode",
|
|
66
|
+
type: "select",
|
|
67
|
+
defaultValue: "studio-v1",
|
|
68
|
+
options: [
|
|
69
|
+
{ label: "Classic Studio Builder", value: "studio-v1" },
|
|
70
|
+
{ label: "Website Builder V2", value: "grapes-v2" }
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
hidden
|
|
74
|
+
),
|
|
75
|
+
withHiddenAdmin(
|
|
76
|
+
{
|
|
77
|
+
name: "builderProjectData",
|
|
78
|
+
type: "json"
|
|
79
|
+
},
|
|
80
|
+
hidden
|
|
81
|
+
),
|
|
82
|
+
withHiddenAdmin(
|
|
83
|
+
{
|
|
84
|
+
name: "builderAutosaveProjectData",
|
|
85
|
+
type: "json"
|
|
86
|
+
},
|
|
87
|
+
hidden
|
|
88
|
+
),
|
|
89
|
+
withHiddenAdmin(
|
|
90
|
+
{
|
|
91
|
+
name: "builderPublishedProjectData",
|
|
92
|
+
type: "json"
|
|
93
|
+
},
|
|
94
|
+
hidden
|
|
95
|
+
),
|
|
96
|
+
withHiddenAdmin(
|
|
97
|
+
{
|
|
98
|
+
name: "compiledHtml",
|
|
99
|
+
type: "textarea"
|
|
100
|
+
},
|
|
101
|
+
hidden
|
|
102
|
+
),
|
|
103
|
+
withHiddenAdmin(
|
|
104
|
+
{
|
|
105
|
+
name: "compiledCss",
|
|
106
|
+
type: "textarea"
|
|
107
|
+
},
|
|
108
|
+
hidden
|
|
109
|
+
),
|
|
110
|
+
withHiddenAdmin(
|
|
111
|
+
{
|
|
112
|
+
name: "builderDynamicComponents",
|
|
113
|
+
type: "json"
|
|
114
|
+
},
|
|
115
|
+
hidden
|
|
116
|
+
),
|
|
117
|
+
withHiddenAdmin(
|
|
118
|
+
{
|
|
119
|
+
name: "builderValidationIssues",
|
|
120
|
+
type: "json"
|
|
121
|
+
},
|
|
122
|
+
hidden
|
|
123
|
+
),
|
|
124
|
+
withHiddenAdmin(
|
|
125
|
+
{
|
|
126
|
+
name: "builderVersions",
|
|
127
|
+
type: "json"
|
|
128
|
+
},
|
|
129
|
+
hidden
|
|
130
|
+
),
|
|
131
|
+
withHiddenAdmin(
|
|
132
|
+
{
|
|
133
|
+
name: "builderPublishedSnapshot",
|
|
134
|
+
type: "json"
|
|
135
|
+
},
|
|
136
|
+
hidden
|
|
137
|
+
),
|
|
138
|
+
withHiddenAdmin(
|
|
139
|
+
{
|
|
140
|
+
name: "builderReusableSections",
|
|
141
|
+
type: "json"
|
|
142
|
+
},
|
|
143
|
+
hidden
|
|
144
|
+
),
|
|
145
|
+
withHiddenAdmin(
|
|
146
|
+
{
|
|
147
|
+
name: "builderThemeTokens",
|
|
148
|
+
type: "json"
|
|
149
|
+
},
|
|
150
|
+
hidden
|
|
151
|
+
),
|
|
152
|
+
withHiddenAdmin(
|
|
153
|
+
{
|
|
154
|
+
name: "builderLockedAreas",
|
|
155
|
+
type: "json"
|
|
156
|
+
},
|
|
157
|
+
hidden
|
|
158
|
+
),
|
|
159
|
+
withHiddenAdmin(
|
|
160
|
+
{
|
|
161
|
+
name: "builderSeo",
|
|
162
|
+
type: "json"
|
|
163
|
+
},
|
|
164
|
+
hidden
|
|
165
|
+
),
|
|
166
|
+
withHiddenAdmin(
|
|
167
|
+
{
|
|
168
|
+
name: "builderLastSavedAt",
|
|
169
|
+
type: "date"
|
|
170
|
+
},
|
|
171
|
+
hidden
|
|
172
|
+
),
|
|
173
|
+
withHiddenAdmin(
|
|
174
|
+
{
|
|
175
|
+
name: "builderLastPublishedAt",
|
|
176
|
+
type: "date"
|
|
177
|
+
},
|
|
178
|
+
hidden
|
|
179
|
+
)
|
|
180
|
+
];
|
|
181
|
+
};
|
|
182
|
+
var appendBuilderV2PageFields = (fields, options) => [
|
|
183
|
+
...fields,
|
|
184
|
+
...createBuilderV2PageFields(options)
|
|
185
|
+
];
|
|
186
|
+
|
|
187
|
+
// src/builder-v2/runtime/placeholders.ts
|
|
188
|
+
var placeholderPattern = /<(?<tag>[a-zA-Z][a-zA-Z0-9-]*)\b(?<attrs>[^>]*)data-orion-component=["'](?<component>[^"']+)["'](?<rest>[^>]*)>/gis;
|
|
189
|
+
var attrPattern = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)=(?:"([^"]*)"|'([^']*)')/g;
|
|
190
|
+
var decodeHtmlAttribute = (value) => value.replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
191
|
+
var parseAttributes = (value) => {
|
|
192
|
+
const props = {};
|
|
193
|
+
let match;
|
|
194
|
+
while ((match = attrPattern.exec(value)) !== null) {
|
|
195
|
+
const name = match[1];
|
|
196
|
+
const rawValue = match[2] ?? match[3] ?? "";
|
|
197
|
+
if (!name.startsWith("data-")) {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (name === "data-orion-component" || name === "data-orion-id") {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
if (name === "data-orion-props") {
|
|
204
|
+
const decoded = decodeHtmlAttribute(rawValue);
|
|
205
|
+
try {
|
|
206
|
+
const parsed = JSON.parse(decoded);
|
|
207
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
208
|
+
Object.assign(props, parsed);
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
props.propsJson = decoded;
|
|
212
|
+
}
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
const propName = name.replace(/^data-orion-/, "").replace(/^data-/, "").replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
216
|
+
props[propName] = decodeHtmlAttribute(rawValue);
|
|
217
|
+
}
|
|
218
|
+
return props;
|
|
219
|
+
};
|
|
220
|
+
var extractAttribute = (attrs, name) => {
|
|
221
|
+
attrPattern.lastIndex = 0;
|
|
222
|
+
let match;
|
|
223
|
+
while ((match = attrPattern.exec(attrs)) !== null) {
|
|
224
|
+
if (match[1] === name) {
|
|
225
|
+
return decodeHtmlAttribute(match[2] ?? match[3] ?? "");
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
};
|
|
230
|
+
var extractWrapperAttributes = (attrs) => {
|
|
231
|
+
const id = extractAttribute(attrs, "id") || void 0;
|
|
232
|
+
const className = extractAttribute(attrs, "class") || void 0;
|
|
233
|
+
const style = extractAttribute(attrs, "style") || void 0;
|
|
234
|
+
return id || className || style ? { className, id, style } : void 0;
|
|
235
|
+
};
|
|
236
|
+
var findPlaceholderEnd = (html, tag, startIndex) => {
|
|
237
|
+
const tagPattern = new RegExp(`<\\/?${tag}\\b[^>]*>`, "gi");
|
|
238
|
+
tagPattern.lastIndex = startIndex;
|
|
239
|
+
let depth = 1;
|
|
240
|
+
let match;
|
|
241
|
+
while ((match = tagPattern.exec(html)) !== null) {
|
|
242
|
+
const token = match[0];
|
|
243
|
+
const isClosing = token.startsWith("</");
|
|
244
|
+
const isSelfClosing = /\/\s*>$/.test(token);
|
|
245
|
+
if (isClosing) {
|
|
246
|
+
depth -= 1;
|
|
247
|
+
} else if (!isSelfClosing) {
|
|
248
|
+
depth += 1;
|
|
249
|
+
}
|
|
250
|
+
if (depth === 0) {
|
|
251
|
+
return tagPattern.lastIndex;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return startIndex;
|
|
255
|
+
};
|
|
256
|
+
var parseBuilderV2DynamicComponents = (html) => {
|
|
257
|
+
const instances = [];
|
|
258
|
+
let match;
|
|
259
|
+
while ((match = placeholderPattern.exec(html)) !== null) {
|
|
260
|
+
const attrs = `${match.groups?.attrs ?? ""} ${match.groups?.rest ?? ""}`;
|
|
261
|
+
const component = match.groups?.component ?? "";
|
|
262
|
+
if (!component) {
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
265
|
+
instances.push({
|
|
266
|
+
component,
|
|
267
|
+
id: extractAttribute(attrs, "data-orion-id") || `component-${instances.length + 1}`,
|
|
268
|
+
props: parseAttributes(attrs),
|
|
269
|
+
wrapperAttributes: extractWrapperAttributes(attrs)
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
return instances;
|
|
273
|
+
};
|
|
274
|
+
var splitBuilderV2HtmlIntoChunks = (html) => {
|
|
275
|
+
const chunks = [];
|
|
276
|
+
let lastIndex = 0;
|
|
277
|
+
let componentIndex = 0;
|
|
278
|
+
let match;
|
|
279
|
+
while ((match = placeholderPattern.exec(html)) !== null) {
|
|
280
|
+
const before = html.slice(lastIndex, match.index);
|
|
281
|
+
if (before.length > 0) {
|
|
282
|
+
chunks.push({ html: before, kind: "html" });
|
|
283
|
+
}
|
|
284
|
+
const attrs = `${match.groups?.attrs ?? ""} ${match.groups?.rest ?? ""}`;
|
|
285
|
+
const component = match.groups?.component ?? "";
|
|
286
|
+
const tag = match.groups?.tag ?? "";
|
|
287
|
+
const placeholderEnd = tag ? findPlaceholderEnd(html, tag, placeholderPattern.lastIndex) : placeholderPattern.lastIndex;
|
|
288
|
+
chunks.push({
|
|
289
|
+
instance: {
|
|
290
|
+
component,
|
|
291
|
+
id: extractAttribute(attrs, "data-orion-id") || `component-${componentIndex + 1}`,
|
|
292
|
+
props: parseAttributes(attrs),
|
|
293
|
+
wrapperAttributes: extractWrapperAttributes(attrs)
|
|
294
|
+
},
|
|
295
|
+
kind: "component"
|
|
296
|
+
});
|
|
297
|
+
componentIndex += 1;
|
|
298
|
+
lastIndex = placeholderEnd;
|
|
299
|
+
placeholderPattern.lastIndex = placeholderEnd;
|
|
300
|
+
}
|
|
301
|
+
const after = html.slice(lastIndex);
|
|
302
|
+
if (after.length > 0) {
|
|
303
|
+
chunks.push({ html: after, kind: "html" });
|
|
304
|
+
}
|
|
305
|
+
return chunks;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
// src/builder-v2/sanitize.ts
|
|
309
|
+
var import_sanitize_html = __toESM(require("sanitize-html"));
|
|
310
|
+
var allowedTags = import_sanitize_html.default.defaults.allowedTags.concat([
|
|
311
|
+
"article",
|
|
312
|
+
"aside",
|
|
313
|
+
"button",
|
|
314
|
+
"figure",
|
|
315
|
+
"figcaption",
|
|
316
|
+
"footer",
|
|
317
|
+
"header",
|
|
318
|
+
"main",
|
|
319
|
+
"nav",
|
|
320
|
+
"section",
|
|
321
|
+
"source",
|
|
322
|
+
"video"
|
|
323
|
+
]);
|
|
324
|
+
var allowedAttributes = {
|
|
325
|
+
...import_sanitize_html.default.defaults.allowedAttributes,
|
|
326
|
+
"*": [
|
|
327
|
+
"aria-*",
|
|
328
|
+
"class",
|
|
329
|
+
"data-*",
|
|
330
|
+
"id",
|
|
331
|
+
"role",
|
|
332
|
+
"style",
|
|
333
|
+
"title"
|
|
334
|
+
],
|
|
335
|
+
a: ["aria-*", "class", "data-*", "href", "id", "name", "rel", "style", "target", "title"],
|
|
336
|
+
button: ["aria-*", "class", "data-*", "disabled", "id", "style", "title", "type"],
|
|
337
|
+
iframe: ["allow", "allowfullscreen", "class", "data-*", "height", "loading", "src", "style", "title", "width"],
|
|
338
|
+
img: ["alt", "class", "data-*", "height", "id", "loading", "sizes", "src", "srcset", "style", "title", "width"],
|
|
339
|
+
source: ["media", "src", "srcset", "type"],
|
|
340
|
+
video: ["autoplay", "class", "controls", "height", "loop", "muted", "playsinline", "poster", "preload", "src", "style", "width"]
|
|
341
|
+
};
|
|
342
|
+
var allowedIframeHosts = [
|
|
343
|
+
"calendar.google.com",
|
|
344
|
+
"calendly.com",
|
|
345
|
+
"player.vimeo.com",
|
|
346
|
+
"www.google.com",
|
|
347
|
+
"www.youtube.com",
|
|
348
|
+
"youtube.com"
|
|
349
|
+
];
|
|
350
|
+
var sanitizeBuilderHtml = (value) => {
|
|
351
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
352
|
+
return "";
|
|
353
|
+
}
|
|
354
|
+
return (0, import_sanitize_html.default)(value, {
|
|
355
|
+
allowedAttributes,
|
|
356
|
+
allowedIframeHostnames: allowedIframeHosts,
|
|
357
|
+
allowedSchemes: ["http", "https", "mailto", "tel"],
|
|
358
|
+
allowedSchemesByTag: {
|
|
359
|
+
img: ["http", "https", "data"]
|
|
360
|
+
},
|
|
361
|
+
allowedTags,
|
|
362
|
+
allowProtocolRelative: false,
|
|
363
|
+
parseStyleAttributes: false
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
var sanitizeBuilderCss = (value) => {
|
|
367
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
368
|
+
return "";
|
|
369
|
+
}
|
|
370
|
+
return value.replace(/@import\s+[^;]+;/gi, "").replace(/expression\s*\(/gi, "").replace(/javascript\s*:/gi, "");
|
|
371
|
+
};
|
|
372
|
+
var scopeSelector = (selector, scope) => selector.split(",").map((part) => {
|
|
373
|
+
const trimmed = part.trim();
|
|
374
|
+
if (!trimmed || trimmed.startsWith(scope) || trimmed.startsWith("@")) {
|
|
375
|
+
return trimmed;
|
|
376
|
+
}
|
|
377
|
+
if (/^(html|body|:root)\b/i.test(trimmed)) {
|
|
378
|
+
return trimmed.replace(/^(html|body|:root)\b/i, scope);
|
|
379
|
+
}
|
|
380
|
+
return `${scope} ${trimmed}`;
|
|
381
|
+
}).filter(Boolean).join(", ");
|
|
382
|
+
var scopeBuilderCss = (value, scope = ".orion-builder-v2-runtime") => {
|
|
383
|
+
const css = sanitizeBuilderCss(value);
|
|
384
|
+
if (!css) {
|
|
385
|
+
return "";
|
|
386
|
+
}
|
|
387
|
+
let output = "";
|
|
388
|
+
let cursor = 0;
|
|
389
|
+
const rulePattern = /([^{}]+)\{/g;
|
|
390
|
+
let match;
|
|
391
|
+
while ((match = rulePattern.exec(css)) !== null) {
|
|
392
|
+
const selectorStart = match.index;
|
|
393
|
+
const selector = match[1];
|
|
394
|
+
output += css.slice(cursor, selectorStart);
|
|
395
|
+
const trimmedSelector = selector.trim();
|
|
396
|
+
if (trimmedSelector.startsWith("@keyframes") || trimmedSelector.startsWith("@font-face") || trimmedSelector.startsWith("@page")) {
|
|
397
|
+
output += `${selector}{`;
|
|
398
|
+
} else if (trimmedSelector.startsWith("@media") || trimmedSelector.startsWith("@supports")) {
|
|
399
|
+
output += `${selector}{`;
|
|
400
|
+
} else {
|
|
401
|
+
output += `${scopeSelector(selector, scope)} {`;
|
|
402
|
+
}
|
|
403
|
+
cursor = rulePattern.lastIndex;
|
|
404
|
+
}
|
|
405
|
+
output += css.slice(cursor);
|
|
406
|
+
return output;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
// src/builder-v2/validation.ts
|
|
410
|
+
var hasMatch = (value, pattern) => pattern.test(value);
|
|
411
|
+
var validateBuilderV2Output = (input) => {
|
|
412
|
+
const html = typeof input.html === "string" ? input.html : "";
|
|
413
|
+
const css = typeof input.css === "string" ? input.css : "";
|
|
414
|
+
const issues = [];
|
|
415
|
+
if (!html.trim()) {
|
|
416
|
+
issues.push({
|
|
417
|
+
code: "empty-page",
|
|
418
|
+
message: "This page has no rendered content.",
|
|
419
|
+
path: "compiledHtml",
|
|
420
|
+
severity: "error"
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
if (!hasMatch(html, /<h1\b/i)) {
|
|
424
|
+
issues.push({
|
|
425
|
+
code: "missing-h1",
|
|
426
|
+
message: "Add one H1 so the published page has a clear primary heading.",
|
|
427
|
+
path: "compiledHtml",
|
|
428
|
+
severity: "warning"
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
if (hasMatch(html, /\son[a-z]+\s*=/i)) {
|
|
432
|
+
issues.push({
|
|
433
|
+
code: "inline-event-handler",
|
|
434
|
+
message: "Inline event handlers are not allowed in published builder HTML.",
|
|
435
|
+
path: "compiledHtml",
|
|
436
|
+
severity: "error"
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
if (hasMatch(html, /<(script|object|embed)\b/i)) {
|
|
440
|
+
issues.push({
|
|
441
|
+
code: "unsafe-element",
|
|
442
|
+
message: "Script, object, and embed tags are not allowed in builder content.",
|
|
443
|
+
path: "compiledHtml",
|
|
444
|
+
severity: "error"
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
if (hasMatch(html, /\b(?:href|src)=["']\s*javascript:/i)) {
|
|
448
|
+
issues.push({
|
|
449
|
+
code: "unsafe-url",
|
|
450
|
+
message: "Links and media cannot use javascript URLs.",
|
|
451
|
+
path: "compiledHtml",
|
|
452
|
+
severity: "error"
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
if (hasMatch(css, /@import\s/i)) {
|
|
456
|
+
issues.push({
|
|
457
|
+
code: "css-import",
|
|
458
|
+
message: "CSS imports are removed at publish time. Use the site font and theme managers instead.",
|
|
459
|
+
path: "compiledCss",
|
|
460
|
+
severity: "warning"
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
if (hasMatch(css, /position\s*:\s*fixed/i)) {
|
|
464
|
+
issues.push({
|
|
465
|
+
code: "fixed-position",
|
|
466
|
+
message: "Fixed positioning can cover site navigation or dialogs. Review this before publishing.",
|
|
467
|
+
path: "compiledCss",
|
|
468
|
+
severity: "warning"
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
return issues;
|
|
472
|
+
};
|
|
473
|
+
var hasBlockingBuilderV2Issues = (issues) => issues.some((issue) => issue.severity === "error");
|
|
474
|
+
|
|
475
|
+
// src/builder-v2/payload/compile.ts
|
|
476
|
+
var compileBuilderV2Output = (input) => {
|
|
477
|
+
const html = sanitizeBuilderHtml(input.html);
|
|
478
|
+
const css = scopeBuilderCss(input.css);
|
|
479
|
+
const validationIssues = validateBuilderV2Output({ css: input.css, html: input.html });
|
|
480
|
+
return {
|
|
481
|
+
css,
|
|
482
|
+
dynamicComponents: parseBuilderV2DynamicComponents(html),
|
|
483
|
+
html,
|
|
484
|
+
validationIssues
|
|
485
|
+
};
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// src/builder-v2/projectData.ts
|
|
489
|
+
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
490
|
+
var createEmptyBuilderV2ProjectData = (title = "Untitled Page") => ({
|
|
491
|
+
assets: [],
|
|
492
|
+
pages: [
|
|
493
|
+
{
|
|
494
|
+
component: {
|
|
495
|
+
components: [
|
|
496
|
+
{
|
|
497
|
+
attributes: {
|
|
498
|
+
class: "orion-builder-v2-section"
|
|
499
|
+
},
|
|
500
|
+
components: [
|
|
501
|
+
{
|
|
502
|
+
content: title,
|
|
503
|
+
tagName: "h1",
|
|
504
|
+
type: "text"
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
content: "Start building this page by dragging blocks from the panel.",
|
|
508
|
+
tagName: "p",
|
|
509
|
+
type: "text"
|
|
510
|
+
}
|
|
511
|
+
],
|
|
512
|
+
tagName: "section"
|
|
513
|
+
}
|
|
514
|
+
],
|
|
515
|
+
type: "wrapper"
|
|
516
|
+
},
|
|
517
|
+
id: "page",
|
|
518
|
+
name: title
|
|
519
|
+
}
|
|
520
|
+
],
|
|
521
|
+
styles: []
|
|
522
|
+
});
|
|
523
|
+
var normalizeBuilderV2ProjectData = (value, fallbackTitle = "Untitled Page") => {
|
|
524
|
+
if (!isRecord(value)) {
|
|
525
|
+
return createEmptyBuilderV2ProjectData(fallbackTitle);
|
|
526
|
+
}
|
|
527
|
+
return value;
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// src/builder-v2/payload/pageService.ts
|
|
531
|
+
var pageTitle = (page) => typeof page.title === "string" && page.title.trim().length > 0 ? page.title : "Untitled Page";
|
|
532
|
+
var normalizeVersions = (value) => Array.isArray(value) ? value.filter((item) => Boolean(item && typeof item === "object")) : [];
|
|
533
|
+
var createVersionSnapshot = ({
|
|
534
|
+
compiled,
|
|
535
|
+
label,
|
|
536
|
+
projectData,
|
|
537
|
+
published = false
|
|
538
|
+
}) => {
|
|
539
|
+
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
540
|
+
return {
|
|
541
|
+
compiledCss: compiled.css,
|
|
542
|
+
compiledHtml: compiled.html,
|
|
543
|
+
createdAt,
|
|
544
|
+
id: `builder-v2-${createdAt.replace(/[^0-9]/g, "")}`,
|
|
545
|
+
label,
|
|
546
|
+
projectData,
|
|
547
|
+
published
|
|
548
|
+
};
|
|
549
|
+
};
|
|
550
|
+
var appendVersionSnapshot = (current, snapshot) => [snapshot, ...normalizeVersions(current)].slice(0, 50);
|
|
551
|
+
var toBuilderV2EditorInitialData = (page) => ({
|
|
552
|
+
projectData: normalizeBuilderV2ProjectData(
|
|
553
|
+
page.builderProjectData || page.builderPublishedProjectData,
|
|
554
|
+
pageTitle(page)
|
|
555
|
+
),
|
|
556
|
+
title: pageTitle(page)
|
|
557
|
+
});
|
|
558
|
+
var createBuilderV2PageService = ({
|
|
559
|
+
collectionSlug = "pages",
|
|
560
|
+
payload,
|
|
561
|
+
user
|
|
562
|
+
}) => ({
|
|
563
|
+
getPageForBuilder: async (pageID) => {
|
|
564
|
+
const page = await payload.findByID({
|
|
565
|
+
collection: collectionSlug,
|
|
566
|
+
depth: 2,
|
|
567
|
+
draft: true,
|
|
568
|
+
id: pageID,
|
|
569
|
+
overrideAccess: false,
|
|
570
|
+
user
|
|
571
|
+
});
|
|
572
|
+
return {
|
|
573
|
+
id: String(page.id),
|
|
574
|
+
initialData: toBuilderV2EditorInitialData(page),
|
|
575
|
+
page
|
|
576
|
+
};
|
|
577
|
+
},
|
|
578
|
+
saveDraft: async (pageID, input) => {
|
|
579
|
+
const compiled = compileBuilderV2Output(input.compiled);
|
|
580
|
+
const existing = await payload.findByID({
|
|
581
|
+
collection: collectionSlug,
|
|
582
|
+
depth: 0,
|
|
583
|
+
draft: true,
|
|
584
|
+
id: pageID,
|
|
585
|
+
overrideAccess: false,
|
|
586
|
+
user
|
|
587
|
+
});
|
|
588
|
+
const validationIssues = input.validationIssues || compiled.validationIssues || [];
|
|
589
|
+
await payload.update({
|
|
590
|
+
collection: collectionSlug,
|
|
591
|
+
data: {
|
|
592
|
+
_status: "draft",
|
|
593
|
+
builderAutosaveProjectData: null,
|
|
594
|
+
builderDynamicComponents: compiled.dynamicComponents,
|
|
595
|
+
builderLastSavedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
596
|
+
builderMode: "grapes-v2",
|
|
597
|
+
builderProjectData: input.projectData,
|
|
598
|
+
builderValidationIssues: validationIssues,
|
|
599
|
+
builderVersions: appendVersionSnapshot(
|
|
600
|
+
existing.builderVersions,
|
|
601
|
+
createVersionSnapshot({
|
|
602
|
+
compiled,
|
|
603
|
+
label: "Draft saved",
|
|
604
|
+
projectData: input.projectData
|
|
605
|
+
})
|
|
606
|
+
),
|
|
607
|
+
compiledCss: compiled.css,
|
|
608
|
+
compiledHtml: compiled.html,
|
|
609
|
+
...input.title ? { title: input.title } : {}
|
|
610
|
+
},
|
|
611
|
+
id: pageID,
|
|
612
|
+
overrideAccess: false,
|
|
613
|
+
user
|
|
614
|
+
});
|
|
615
|
+
return {
|
|
616
|
+
compiled,
|
|
617
|
+
id: pageID,
|
|
618
|
+
status: "draft"
|
|
619
|
+
};
|
|
620
|
+
},
|
|
621
|
+
publish: async (pageID, input) => {
|
|
622
|
+
const compiled = compileBuilderV2Output(input.compiled);
|
|
623
|
+
const existing = await payload.findByID({
|
|
624
|
+
collection: collectionSlug,
|
|
625
|
+
depth: 0,
|
|
626
|
+
draft: true,
|
|
627
|
+
id: pageID,
|
|
628
|
+
overrideAccess: false,
|
|
629
|
+
user
|
|
630
|
+
});
|
|
631
|
+
const validationIssues = input.validationIssues || compiled.validationIssues || [];
|
|
632
|
+
const snapshot = createVersionSnapshot({
|
|
633
|
+
compiled,
|
|
634
|
+
label: "Published",
|
|
635
|
+
projectData: input.projectData,
|
|
636
|
+
published: true
|
|
637
|
+
});
|
|
638
|
+
await payload.update({
|
|
639
|
+
collection: collectionSlug,
|
|
640
|
+
data: {
|
|
641
|
+
_status: "published",
|
|
642
|
+
builderAutosaveProjectData: null,
|
|
643
|
+
builderDynamicComponents: compiled.dynamicComponents,
|
|
644
|
+
builderLastPublishedAt: snapshot.createdAt,
|
|
645
|
+
builderLastSavedAt: snapshot.createdAt,
|
|
646
|
+
builderMode: "grapes-v2",
|
|
647
|
+
builderProjectData: input.projectData,
|
|
648
|
+
builderPublishedProjectData: input.projectData,
|
|
649
|
+
builderPublishedSnapshot: snapshot,
|
|
650
|
+
builderValidationIssues: validationIssues,
|
|
651
|
+
builderVersions: appendVersionSnapshot(existing.builderVersions, snapshot),
|
|
652
|
+
compiledCss: compiled.css,
|
|
653
|
+
compiledHtml: compiled.html,
|
|
654
|
+
...input.title ? { title: input.title } : {}
|
|
655
|
+
},
|
|
656
|
+
id: pageID,
|
|
657
|
+
overrideAccess: false,
|
|
658
|
+
user
|
|
659
|
+
});
|
|
660
|
+
return {
|
|
661
|
+
compiled,
|
|
662
|
+
id: pageID,
|
|
663
|
+
status: "published"
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
// src/builder-v2/pageTree.ts
|
|
669
|
+
var relationId = (value) => {
|
|
670
|
+
if (typeof value === "number" || typeof value === "string") {
|
|
671
|
+
return value;
|
|
672
|
+
}
|
|
673
|
+
if (value && typeof value === "object") {
|
|
674
|
+
const id = value.id;
|
|
675
|
+
return typeof id === "number" || typeof id === "string" ? id : null;
|
|
676
|
+
}
|
|
677
|
+
return null;
|
|
678
|
+
};
|
|
679
|
+
var buildBuilderV2PageTree = (pages) => {
|
|
680
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
681
|
+
const roots = [];
|
|
682
|
+
pages.forEach((page) => {
|
|
683
|
+
nodes.set(page.id, {
|
|
684
|
+
children: [],
|
|
685
|
+
id: page.id,
|
|
686
|
+
parentId: page.parentId ?? relationId(page.parent),
|
|
687
|
+
path: page.path || (page.slug ? `/${page.slug}` : "/"),
|
|
688
|
+
slug: page.slug || "",
|
|
689
|
+
status: page._status,
|
|
690
|
+
title: page.title || "Untitled page"
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
nodes.forEach((node) => {
|
|
694
|
+
if (node.parentId && nodes.has(node.parentId)) {
|
|
695
|
+
nodes.get(node.parentId)?.children?.push(node);
|
|
696
|
+
} else {
|
|
697
|
+
roots.push(node);
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
const sortNodes = (items) => {
|
|
701
|
+
items.sort((a, b) => a.path.localeCompare(b.path));
|
|
702
|
+
items.forEach((item) => sortNodes(item.children || []));
|
|
703
|
+
};
|
|
704
|
+
sortNodes(roots);
|
|
705
|
+
return roots;
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
// src/builder-v2/runtime/BuilderPageRuntime.tsx
|
|
709
|
+
var import_react = require("react");
|
|
710
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
711
|
+
var resolveRuntimeComponent = (adapter, type) => {
|
|
712
|
+
const definition = adapter?.components?.[type];
|
|
713
|
+
if (!definition) {
|
|
714
|
+
return null;
|
|
715
|
+
}
|
|
716
|
+
if (typeof definition === "function") {
|
|
717
|
+
return definition;
|
|
718
|
+
}
|
|
719
|
+
return definition.render;
|
|
720
|
+
};
|
|
721
|
+
var styleStringToReactStyle = (value) => {
|
|
722
|
+
if (!value) {
|
|
723
|
+
return void 0;
|
|
724
|
+
}
|
|
725
|
+
const style = value.split(";").map((declaration) => declaration.trim()).filter(Boolean).reduce((result, declaration) => {
|
|
726
|
+
const separatorIndex = declaration.indexOf(":");
|
|
727
|
+
if (separatorIndex <= 0) {
|
|
728
|
+
return result;
|
|
729
|
+
}
|
|
730
|
+
const property = declaration.slice(0, separatorIndex).trim();
|
|
731
|
+
const propertyValue = declaration.slice(separatorIndex + 1).trim();
|
|
732
|
+
if (!property || !propertyValue) {
|
|
733
|
+
return result;
|
|
734
|
+
}
|
|
735
|
+
const reactProperty = property.startsWith("--") ? property : property.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
736
|
+
result[reactProperty] = propertyValue;
|
|
737
|
+
return result;
|
|
738
|
+
}, {});
|
|
739
|
+
return Object.keys(style).length > 0 ? style : void 0;
|
|
740
|
+
};
|
|
741
|
+
function BuilderPageRuntime({ adapter, className, page }) {
|
|
742
|
+
const html = sanitizeBuilderHtml(page.compiledHtml);
|
|
743
|
+
const css = scopeBuilderCss(page.compiledCss);
|
|
744
|
+
const chunks = splitBuilderV2HtmlIntoChunks(html);
|
|
745
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: ["orion-builder-v2-runtime", className].filter(Boolean).join(" "), children: [
|
|
746
|
+
css ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { dangerouslySetInnerHTML: { __html: css } }) : null,
|
|
747
|
+
chunks.map((chunk, index) => {
|
|
748
|
+
if (chunk.kind === "html") {
|
|
749
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
750
|
+
"div",
|
|
751
|
+
{
|
|
752
|
+
className: "orion-builder-v2-html-chunk",
|
|
753
|
+
dangerouslySetInnerHTML: { __html: chunk.html }
|
|
754
|
+
},
|
|
755
|
+
`html-${index}`
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
const Component = resolveRuntimeComponent(adapter, chunk.instance.component);
|
|
759
|
+
if (!Component) {
|
|
760
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
761
|
+
"div",
|
|
762
|
+
{
|
|
763
|
+
className: "orion-builder-v2-missing-component",
|
|
764
|
+
"data-orion-missing-component": chunk.instance.component
|
|
765
|
+
},
|
|
766
|
+
`component-${chunk.instance.id}-${index}`
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
const renderedComponent = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { instance: chunk.instance, page });
|
|
770
|
+
const wrapperAttributes = chunk.instance.wrapperAttributes;
|
|
771
|
+
if (wrapperAttributes?.id || wrapperAttributes?.className || wrapperAttributes?.style) {
|
|
772
|
+
return (0, import_react.createElement)(
|
|
773
|
+
"div",
|
|
774
|
+
{
|
|
775
|
+
className: wrapperAttributes.className,
|
|
776
|
+
id: wrapperAttributes.id,
|
|
777
|
+
key: `component-${chunk.instance.id}-${index}`,
|
|
778
|
+
style: styleStringToReactStyle(wrapperAttributes.style)
|
|
779
|
+
},
|
|
780
|
+
renderedComponent
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
return (0, import_react.createElement)(import_react.Fragment, { key: `component-${chunk.instance.id}-${index}` }, renderedComponent);
|
|
784
|
+
})
|
|
785
|
+
] });
|
|
786
|
+
}
|
|
787
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
788
|
+
0 && (module.exports = {
|
|
789
|
+
BuilderPageRuntime,
|
|
790
|
+
appendBuilderV2PageFields,
|
|
791
|
+
buildBuilderV2PageTree,
|
|
792
|
+
compileBuilderV2Output,
|
|
793
|
+
createBuilderV2PageFields,
|
|
794
|
+
createBuilderV2PageService,
|
|
795
|
+
createEmptyBuilderV2ProjectData,
|
|
796
|
+
hasBlockingBuilderV2Issues,
|
|
797
|
+
normalizeBuilderV2ProjectData,
|
|
798
|
+
parseBuilderV2DynamicComponents,
|
|
799
|
+
sanitizeBuilderCss,
|
|
800
|
+
sanitizeBuilderHtml,
|
|
801
|
+
scopeBuilderCss,
|
|
802
|
+
splitBuilderV2HtmlIntoChunks,
|
|
803
|
+
toBuilderV2EditorInitialData,
|
|
804
|
+
validateBuilderV2Output
|
|
805
|
+
});
|