@puckeditor/plugin-ai 0.8.3-canary.fb947b91 → 0.8.3
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/index.js +314 -186
- package/dist/index.mjs +314 -186
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -2490,7 +2490,6 @@ function ExamplePrompt({
|
|
|
2490
2490
|
// src/components/Chat/index.tsx
|
|
2491
2491
|
var import_qler = __toESM(require("qler"));
|
|
2492
2492
|
var import_reducer = __toESM(require_dist());
|
|
2493
|
-
var import_html2canvas_pro = __toESM(require("html2canvas-pro"));
|
|
2494
2493
|
var import_use_debounce = require("use-debounce");
|
|
2495
2494
|
|
|
2496
2495
|
// src/lib/scroll-tracking-events.ts
|
|
@@ -2550,147 +2549,16 @@ var import_react24 = require("react");
|
|
|
2550
2549
|
|
|
2551
2550
|
// src/lib/morph-html.ts
|
|
2552
2551
|
init_react_import();
|
|
2553
|
-
var PROTECTED_ATTRS = /* @__PURE__ */ new Set([
|
|
2554
|
-
"contenteditable",
|
|
2555
|
-
"data-puck-overlay-portal"
|
|
2556
|
-
]);
|
|
2557
|
-
var SLOT_OWNED_ATTRS = /* @__PURE__ */ new Set(["style", "class"]);
|
|
2558
|
-
var isEventHandlerAttr = (name) => /^on/i.test(name);
|
|
2559
|
-
var cssEscape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/["\\]/g, "\\$&");
|
|
2560
|
-
var FIELD_ATTR_PREFIX = "data-puck-field-";
|
|
2561
|
-
var hasJsonFieldBinding = (el) => {
|
|
2562
|
-
const attrBoundNames = /* @__PURE__ */ new Set();
|
|
2563
|
-
const jsonFieldNames = [];
|
|
2564
|
-
for (const attr of Array.from(el.attributes)) {
|
|
2565
|
-
if (!attr.name.startsWith(FIELD_ATTR_PREFIX)) continue;
|
|
2566
|
-
if (attr.name.startsWith("data-puck-field-value-")) continue;
|
|
2567
|
-
if (attr.value.trimStart().startsWith("{")) {
|
|
2568
|
-
const fieldName = attr.name.slice(FIELD_ATTR_PREFIX.length);
|
|
2569
|
-
if (fieldName && fieldName !== "name") {
|
|
2570
|
-
jsonFieldNames.push(fieldName);
|
|
2571
|
-
}
|
|
2572
|
-
} else {
|
|
2573
|
-
const fieldName = attr.value.trim();
|
|
2574
|
-
if (fieldName) attrBoundNames.add(fieldName);
|
|
2575
|
-
}
|
|
2576
|
-
}
|
|
2577
|
-
return jsonFieldNames.some((name) => !attrBoundNames.has(name));
|
|
2578
|
-
};
|
|
2579
|
-
var ownsItsChildren = (el) => el.hasAttribute("data-puck-slot") || el.hasAttribute("data-puck-field-name") || el.hasAttribute("data-puck-array") || hasJsonFieldBinding(el);
|
|
2580
|
-
var syncAttributes = (target, source) => {
|
|
2581
|
-
const isSlot = target.hasAttribute("data-puck-slot");
|
|
2582
|
-
for (const attr of Array.from(target.attributes)) {
|
|
2583
|
-
if (PROTECTED_ATTRS.has(attr.name)) continue;
|
|
2584
|
-
if (isSlot && SLOT_OWNED_ATTRS.has(attr.name)) continue;
|
|
2585
|
-
if (isEventHandlerAttr(attr.name) || !source.hasAttribute(attr.name)) {
|
|
2586
|
-
target.removeAttribute(attr.name);
|
|
2587
|
-
}
|
|
2588
|
-
}
|
|
2589
|
-
for (const attr of Array.from(source.attributes)) {
|
|
2590
|
-
if (PROTECTED_ATTRS.has(attr.name)) continue;
|
|
2591
|
-
if (isSlot && SLOT_OWNED_ATTRS.has(attr.name)) continue;
|
|
2592
|
-
if (isEventHandlerAttr(attr.name)) continue;
|
|
2593
|
-
if (target.getAttribute(attr.name) !== attr.value) {
|
|
2594
|
-
target.setAttribute(attr.name, attr.value);
|
|
2595
|
-
}
|
|
2596
|
-
}
|
|
2597
|
-
};
|
|
2598
|
-
var isSameKind = (a, b) => a.nodeType === b.nodeType && (a.nodeType !== Node.ELEMENT_NODE || a.tagName === b.tagName);
|
|
2599
|
-
var isIncompleteTagArtifact = (node) => node.nodeType === Node.TEXT_NODE && /^<\/?[a-zA-Z]*$/.test(node.nodeValue ?? "");
|
|
2600
|
-
var stripIncompleteTagArtifacts = (root) => {
|
|
2601
|
-
for (const child of Array.from(root.childNodes)) {
|
|
2602
|
-
if (isIncompleteTagArtifact(child)) {
|
|
2603
|
-
root.removeChild(child);
|
|
2604
|
-
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
2605
|
-
stripIncompleteTagArtifacts(child);
|
|
2606
|
-
}
|
|
2607
|
-
}
|
|
2608
|
-
};
|
|
2609
|
-
var stripEventHandlerAttrs = (root) => {
|
|
2610
|
-
root.querySelectorAll("*").forEach((el) => {
|
|
2611
|
-
for (const attr of Array.from(el.attributes)) {
|
|
2612
|
-
if (isEventHandlerAttr(attr.name)) el.removeAttribute(attr.name);
|
|
2613
|
-
}
|
|
2614
|
-
});
|
|
2615
|
-
};
|
|
2616
|
-
var morphChildren = (target, source, skipChildrenOf = ownsItsChildren) => {
|
|
2617
|
-
const sourceChildren = Array.from(source.childNodes);
|
|
2618
|
-
for (let i = 0; i < sourceChildren.length; i++) {
|
|
2619
|
-
const sourceChild = sourceChildren[i];
|
|
2620
|
-
const targetChild = target.childNodes[i];
|
|
2621
|
-
if (!targetChild) {
|
|
2622
|
-
target.appendChild(sourceChild);
|
|
2623
|
-
continue;
|
|
2624
|
-
}
|
|
2625
|
-
if (!isSameKind(targetChild, sourceChild)) {
|
|
2626
|
-
target.replaceChild(sourceChild, targetChild);
|
|
2627
|
-
continue;
|
|
2628
|
-
}
|
|
2629
|
-
if (sourceChild.nodeType !== Node.ELEMENT_NODE) {
|
|
2630
|
-
if (targetChild.nodeValue !== sourceChild.nodeValue) {
|
|
2631
|
-
targetChild.nodeValue = sourceChild.nodeValue;
|
|
2632
|
-
}
|
|
2633
|
-
continue;
|
|
2634
|
-
}
|
|
2635
|
-
const targetEl = targetChild;
|
|
2636
|
-
syncAttributes(targetEl, sourceChild);
|
|
2637
|
-
if (!skipChildrenOf(targetEl)) {
|
|
2638
|
-
morphChildren(targetEl, sourceChild, skipChildrenOf);
|
|
2639
|
-
}
|
|
2640
|
-
}
|
|
2641
|
-
while (target.childNodes.length > sourceChildren.length) {
|
|
2642
|
-
target.removeChild(target.lastChild);
|
|
2643
|
-
}
|
|
2644
|
-
};
|
|
2645
|
-
function morphHtml(container, html, attrOverrides = [], skipChildrenOf = ownsItsChildren) {
|
|
2646
|
-
const template = container.ownerDocument.createElement("template");
|
|
2647
|
-
template.innerHTML = html;
|
|
2648
|
-
stripIncompleteTagArtifacts(template.content);
|
|
2649
|
-
stripEventHandlerAttrs(template.content);
|
|
2650
|
-
for (const { name, attr, value } of attrOverrides) {
|
|
2651
|
-
template.content.querySelectorAll(`[data-puck-field-${attr}="${cssEscape(name)}"]`).forEach((el) => {
|
|
2652
|
-
if (el.closest("[data-puck-array]")) return;
|
|
2653
|
-
el.setAttribute(attr, value);
|
|
2654
|
-
});
|
|
2655
|
-
}
|
|
2656
|
-
morphChildren(container, template.content, skipChildrenOf);
|
|
2657
|
-
}
|
|
2658
2552
|
|
|
2659
|
-
// src/lib/design/
|
|
2553
|
+
// src/lib/design/annotations.ts
|
|
2660
2554
|
init_react_import();
|
|
2661
|
-
var wrapScriptWithObserverGuard = (script) => {
|
|
2662
|
-
if (!script.includes("MutationObserver")) return script;
|
|
2663
|
-
return `(function () {
|
|
2664
|
-
var __NativeMutationObserver = window.MutationObserver;
|
|
2665
|
-
function MutationObserver(callback) {
|
|
2666
|
-
var observed = [];
|
|
2667
|
-
var inner = new __NativeMutationObserver(function (records) {
|
|
2668
|
-
inner.disconnect();
|
|
2669
|
-
try {
|
|
2670
|
-
callback(records, inner);
|
|
2671
|
-
} finally {
|
|
2672
|
-
for (var i = 0; i < observed.length; i++) {
|
|
2673
|
-
__nativeObserve.call(inner, observed[i][0], observed[i][1]);
|
|
2674
|
-
}
|
|
2675
|
-
}
|
|
2676
|
-
});
|
|
2677
|
-
var __nativeObserve = inner.observe;
|
|
2678
|
-
inner.observe = function (target, options) {
|
|
2679
|
-
observed.push([target, options]);
|
|
2680
|
-
return __nativeObserve.call(inner, target, options);
|
|
2681
|
-
};
|
|
2682
|
-
return inner;
|
|
2683
|
-
}
|
|
2684
|
-
${script}
|
|
2685
|
-
})();`;
|
|
2686
|
-
};
|
|
2687
2555
|
|
|
2688
2556
|
// src/lib/html-annotations.ts
|
|
2689
2557
|
init_react_import();
|
|
2690
2558
|
var import_htmlparser2 = require("htmlparser2");
|
|
2691
2559
|
var import_domutils = require("domutils");
|
|
2692
2560
|
var import_domhandler = require("domhandler");
|
|
2693
|
-
var
|
|
2561
|
+
var FIELD_ATTR_PREFIX = "data-puck-field-";
|
|
2694
2562
|
var OPTIONS_ATTR_PREFIX = "data-puck-options-";
|
|
2695
2563
|
var BIND_ATTR_PREFIX = "data-puck-bind-";
|
|
2696
2564
|
var BIND_INPUT_ATTR_PREFIX = "data-puck-bind-input-";
|
|
@@ -2738,6 +2606,19 @@ var textContentWithBreaks = (node) => {
|
|
|
2738
2606
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2739
2607
|
var FIELD_NAME_RE = /^[A-Za-z0-9_]+(?:[-.][A-Za-z0-9_]+)*$/;
|
|
2740
2608
|
var isValidFieldName = (name) => FIELD_NAME_RE.test(name);
|
|
2609
|
+
var isFieldNameClaimed = (name, claimed, includeExact = true) => {
|
|
2610
|
+
for (const entry of claimed) {
|
|
2611
|
+
if (includeExact && entry === name || entry.startsWith(`${name}.`) || name.startsWith(`${entry}.`)) {
|
|
2612
|
+
return true;
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
return false;
|
|
2616
|
+
};
|
|
2617
|
+
var attrBoundFieldNames = (attribs) => new Set(
|
|
2618
|
+
Object.entries(attribs).filter(
|
|
2619
|
+
([name, value]) => name.startsWith(FIELD_ATTR_PREFIX) && name !== `${FIELD_ATTR_PREFIX}name` && !name.startsWith(`${FIELD_ATTR_PREFIX}value-`) && !tryParseFieldShape(value)
|
|
2620
|
+
).map(([, value]) => value.trim()).filter(isValidFieldName)
|
|
2621
|
+
);
|
|
2741
2622
|
var getDeepValue = (source, path) => {
|
|
2742
2623
|
if (!path.includes(".")) return source[path];
|
|
2743
2624
|
let current = source;
|
|
@@ -2838,6 +2719,7 @@ var collectElementFields = (element, acc) => {
|
|
|
2838
2719
|
return true;
|
|
2839
2720
|
}
|
|
2840
2721
|
let skipChildren = false;
|
|
2722
|
+
const attrBound = attrBoundFieldNames(attribs);
|
|
2841
2723
|
for (const [attrName, attrValue] of Object.entries(attribs)) {
|
|
2842
2724
|
if (attrName.startsWith(OPTIONS_ATTR_PREFIX)) {
|
|
2843
2725
|
const fieldName = attrName.slice(OPTIONS_ATTR_PREFIX.length);
|
|
@@ -2866,8 +2748,8 @@ var collectElementFields = (element, acc) => {
|
|
|
2866
2748
|
}
|
|
2867
2749
|
continue;
|
|
2868
2750
|
}
|
|
2869
|
-
if (!attrName.startsWith(
|
|
2870
|
-
const target = attrName.slice(
|
|
2751
|
+
if (!attrName.startsWith(FIELD_ATTR_PREFIX)) continue;
|
|
2752
|
+
const target = attrName.slice(FIELD_ATTR_PREFIX.length);
|
|
2871
2753
|
if (!target) continue;
|
|
2872
2754
|
const shape = tryParseFieldShape(attrValue);
|
|
2873
2755
|
if (shape) {
|
|
@@ -2881,6 +2763,9 @@ var collectElementFields = (element, acc) => {
|
|
|
2881
2763
|
if (existing) existing.shape = shape;
|
|
2882
2764
|
continue;
|
|
2883
2765
|
}
|
|
2766
|
+
if (isFieldNameClaimed(name2, attrBound, false) || isFieldNameClaimed(name2, acc.seenFields)) {
|
|
2767
|
+
continue;
|
|
2768
|
+
}
|
|
2884
2769
|
acc.seenFields.add(name2);
|
|
2885
2770
|
if (shape.type === "richtext") {
|
|
2886
2771
|
acc.fields.push({ name: name2, binding: "text", shape, format: "json" });
|
|
@@ -2935,6 +2820,9 @@ var collectElementFields = (element, acc) => {
|
|
|
2935
2820
|
}
|
|
2936
2821
|
continue;
|
|
2937
2822
|
}
|
|
2823
|
+
if (target === "name" && isFieldNameClaimed(name, attrBound) || isFieldNameClaimed(name, acc.seenFields)) {
|
|
2824
|
+
continue;
|
|
2825
|
+
}
|
|
2938
2826
|
acc.seenFields.add(name);
|
|
2939
2827
|
const fieldType = getTypeModifier(attribs, name);
|
|
2940
2828
|
const constraints = fieldType === "number" ? getNumberConstraints(attribs, name) : {};
|
|
@@ -3028,7 +2916,7 @@ var parseHtmlAnnotations = (html) => {
|
|
|
3028
2916
|
if (slotName && isValidFieldName(slotName) && !seenSlots.has(slotName)) {
|
|
3029
2917
|
seenSlots.add(slotName);
|
|
3030
2918
|
const shape = tryParseFieldShape(
|
|
3031
|
-
attribs[
|
|
2919
|
+
attribs[FIELD_ATTR_PREFIX + slotName.toLowerCase()] ?? ""
|
|
3032
2920
|
);
|
|
3033
2921
|
const allow = shape?.type === "slot" ? sanitizeStringArray(shape.allow) : void 0;
|
|
3034
2922
|
const disallow = shape?.type === "slot" ? sanitizeStringArray(shape.disallow) : void 0;
|
|
@@ -3177,21 +3065,16 @@ var patchElement = (element, props) => {
|
|
|
3177
3065
|
}
|
|
3178
3066
|
return { didPatch, skipChildren: true };
|
|
3179
3067
|
}
|
|
3180
|
-
const attrBoundFields =
|
|
3181
|
-
for (const [an, av] of Object.entries(attribs)) {
|
|
3182
|
-
if (an.startsWith(FIELD_ATTR_PREFIX2) && an !== `${FIELD_ATTR_PREFIX2}name` && !tryParseFieldShape(av)) {
|
|
3183
|
-
attrBoundFields.add(av.trim());
|
|
3184
|
-
}
|
|
3185
|
-
}
|
|
3068
|
+
const attrBoundFields = attrBoundFieldNames(attribs);
|
|
3186
3069
|
for (const [attrName, attrValue] of Object.entries(attribs)) {
|
|
3187
|
-
if (!attrName.startsWith(
|
|
3188
|
-
const target = attrName.slice(
|
|
3070
|
+
if (!attrName.startsWith(FIELD_ATTR_PREFIX)) continue;
|
|
3071
|
+
const target = attrName.slice(FIELD_ATTR_PREFIX.length);
|
|
3189
3072
|
if (!target) continue;
|
|
3190
3073
|
const shape = tryParseFieldShape(attrValue);
|
|
3191
3074
|
if (shape) {
|
|
3192
3075
|
if (shape.type === "slot") continue;
|
|
3193
3076
|
const name2 = target;
|
|
3194
|
-
if (
|
|
3077
|
+
if (isFieldNameClaimed(name2, attrBoundFields)) continue;
|
|
3195
3078
|
const value2 = getDeepValue(props, name2);
|
|
3196
3079
|
if (shape.type === "richtext") {
|
|
3197
3080
|
if (typeof value2 !== "string") continue;
|
|
@@ -3209,6 +3092,9 @@ var patchElement = (element, props) => {
|
|
|
3209
3092
|
}
|
|
3210
3093
|
const name = attrValue.trim();
|
|
3211
3094
|
if (!name) continue;
|
|
3095
|
+
if (target === "name" && isFieldNameClaimed(name, attrBoundFields)) {
|
|
3096
|
+
continue;
|
|
3097
|
+
}
|
|
3212
3098
|
const value = getDeepValue(props, name);
|
|
3213
3099
|
if (target === "name" && getTypeModifier(attribs, name) === "richtext") {
|
|
3214
3100
|
if (typeof value !== "string") continue;
|
|
@@ -3281,7 +3167,6 @@ var renderHtmlArrayItems = (html, arrayName, items) => {
|
|
|
3281
3167
|
};
|
|
3282
3168
|
|
|
3283
3169
|
// src/lib/design/annotations.ts
|
|
3284
|
-
init_react_import();
|
|
3285
3170
|
var cache = /* @__PURE__ */ new Map();
|
|
3286
3171
|
var MAX_CACHE_ENTRIES = 32;
|
|
3287
3172
|
var getAnnotations = (html) => {
|
|
@@ -3298,6 +3183,160 @@ var getSlotFields = (html) => Object.fromEntries(
|
|
|
3298
3183
|
getAnnotations(html).slots.map((slot) => [slot.name, toSlotField(slot)])
|
|
3299
3184
|
);
|
|
3300
3185
|
|
|
3186
|
+
// src/lib/morph-html.ts
|
|
3187
|
+
var PROTECTED_ATTRS = /* @__PURE__ */ new Set([
|
|
3188
|
+
"contenteditable",
|
|
3189
|
+
"data-puck-overlay-portal"
|
|
3190
|
+
]);
|
|
3191
|
+
var SLOT_OWNED_ATTRS = /* @__PURE__ */ new Set(["style", "class"]);
|
|
3192
|
+
var isEventHandlerAttr = (name) => /^on/i.test(name);
|
|
3193
|
+
var FIELD_ATTR_PREFIX2 = "data-puck-field-";
|
|
3194
|
+
var LEGACY_TEXT_ATTR = `${FIELD_ATTR_PREFIX2}name`;
|
|
3195
|
+
var VALUE_ATTR_PREFIX = `${FIELD_ATTR_PREFIX2}value-`;
|
|
3196
|
+
var hasTextBinding = (el, parsedTextFields) => {
|
|
3197
|
+
for (const attr of Array.from(el.attributes)) {
|
|
3198
|
+
if (!attr.name.startsWith(FIELD_ATTR_PREFIX2)) continue;
|
|
3199
|
+
if (attr.name.startsWith(VALUE_ATTR_PREFIX)) continue;
|
|
3200
|
+
const isShape = attr.value.trimStart().startsWith("{");
|
|
3201
|
+
const fieldName = isShape ? attr.name.slice(FIELD_ATTR_PREFIX2.length) : attr.value.trim();
|
|
3202
|
+
if (isValidFieldName(fieldName) && (attr.name === LEGACY_TEXT_ATTR || isShape) && (!parsedTextFields || parsedTextFields.has(fieldName))) {
|
|
3203
|
+
return true;
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
return false;
|
|
3207
|
+
};
|
|
3208
|
+
var ownsItsChildren = (el, parsedTextFields) => el.hasAttribute("data-puck-slot") || el.hasAttribute("data-puck-array") || hasTextBinding(el, parsedTextFields);
|
|
3209
|
+
var syncAttributes = (target, source) => {
|
|
3210
|
+
const isSlot = target.hasAttribute("data-puck-slot");
|
|
3211
|
+
for (const attr of Array.from(target.attributes)) {
|
|
3212
|
+
if (PROTECTED_ATTRS.has(attr.name)) continue;
|
|
3213
|
+
if (isSlot && SLOT_OWNED_ATTRS.has(attr.name)) continue;
|
|
3214
|
+
if (isEventHandlerAttr(attr.name) || !source.hasAttribute(attr.name)) {
|
|
3215
|
+
target.removeAttribute(attr.name);
|
|
3216
|
+
}
|
|
3217
|
+
}
|
|
3218
|
+
for (const attr of Array.from(source.attributes)) {
|
|
3219
|
+
if (PROTECTED_ATTRS.has(attr.name)) continue;
|
|
3220
|
+
if (isSlot && SLOT_OWNED_ATTRS.has(attr.name)) continue;
|
|
3221
|
+
if (isEventHandlerAttr(attr.name)) continue;
|
|
3222
|
+
if (target.getAttribute(attr.name) !== attr.value) {
|
|
3223
|
+
target.setAttribute(attr.name, attr.value);
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3226
|
+
};
|
|
3227
|
+
var isSameKind = (a, b) => a.nodeType === b.nodeType && (a.nodeType !== Node.ELEMENT_NODE || a.tagName === b.tagName);
|
|
3228
|
+
var isIncompleteTagArtifact = (node) => node.nodeType === Node.TEXT_NODE && /^<\/?[a-zA-Z]*$/.test(node.nodeValue ?? "");
|
|
3229
|
+
var stripIncompleteTagArtifacts = (root) => {
|
|
3230
|
+
for (const child of Array.from(root.childNodes)) {
|
|
3231
|
+
if (isIncompleteTagArtifact(child)) {
|
|
3232
|
+
root.removeChild(child);
|
|
3233
|
+
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
3234
|
+
stripIncompleteTagArtifacts(child);
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
};
|
|
3238
|
+
var stripEventHandlerAttrs = (root) => {
|
|
3239
|
+
root.querySelectorAll("*").forEach((el) => {
|
|
3240
|
+
for (const attr of Array.from(el.attributes)) {
|
|
3241
|
+
if (isEventHandlerAttr(attr.name)) el.removeAttribute(attr.name);
|
|
3242
|
+
}
|
|
3243
|
+
});
|
|
3244
|
+
};
|
|
3245
|
+
var morphChildren = (target, source, skipChildrenOf = ownsItsChildren) => {
|
|
3246
|
+
const sourceChildren = Array.from(source.childNodes);
|
|
3247
|
+
for (let i = 0; i < sourceChildren.length; i++) {
|
|
3248
|
+
const sourceChild = sourceChildren[i];
|
|
3249
|
+
const targetChild = target.childNodes[i];
|
|
3250
|
+
if (!targetChild) {
|
|
3251
|
+
target.appendChild(sourceChild);
|
|
3252
|
+
continue;
|
|
3253
|
+
}
|
|
3254
|
+
if (!isSameKind(targetChild, sourceChild)) {
|
|
3255
|
+
target.replaceChild(sourceChild, targetChild);
|
|
3256
|
+
continue;
|
|
3257
|
+
}
|
|
3258
|
+
if (sourceChild.nodeType !== Node.ELEMENT_NODE) {
|
|
3259
|
+
if (targetChild.nodeValue !== sourceChild.nodeValue) {
|
|
3260
|
+
targetChild.nodeValue = sourceChild.nodeValue;
|
|
3261
|
+
}
|
|
3262
|
+
continue;
|
|
3263
|
+
}
|
|
3264
|
+
const targetEl = targetChild;
|
|
3265
|
+
syncAttributes(targetEl, sourceChild);
|
|
3266
|
+
if (!skipChildrenOf(targetEl)) {
|
|
3267
|
+
morphChildren(targetEl, sourceChild, skipChildrenOf);
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
while (target.childNodes.length > sourceChildren.length) {
|
|
3271
|
+
target.removeChild(target.lastChild);
|
|
3272
|
+
}
|
|
3273
|
+
};
|
|
3274
|
+
function morphHtml(container, html, attrOverrides = [], skipChildrenOf) {
|
|
3275
|
+
const template = container.ownerDocument.createElement("template");
|
|
3276
|
+
template.innerHTML = html;
|
|
3277
|
+
stripIncompleteTagArtifacts(template.content);
|
|
3278
|
+
stripEventHandlerAttrs(template.content);
|
|
3279
|
+
if (attrOverrides.length > 0) {
|
|
3280
|
+
const overridesByAttr = /* @__PURE__ */ new Map();
|
|
3281
|
+
for (const override of attrOverrides) {
|
|
3282
|
+
if (isEventHandlerAttr(override.attr)) continue;
|
|
3283
|
+
const bindingAttr = `${FIELD_ATTR_PREFIX2}${override.attr}`;
|
|
3284
|
+
const fields = overridesByAttr.get(bindingAttr) ?? /* @__PURE__ */ new Map();
|
|
3285
|
+
fields.set(override.name, override);
|
|
3286
|
+
overridesByAttr.set(bindingAttr, fields);
|
|
3287
|
+
}
|
|
3288
|
+
template.content.querySelectorAll("*").forEach((el) => {
|
|
3289
|
+
for (const attr of Array.from(el.attributes)) {
|
|
3290
|
+
const override = overridesByAttr.get(attr.name)?.get(attr.value.trim());
|
|
3291
|
+
if (!override) continue;
|
|
3292
|
+
if (el.closest("[data-puck-array]")) return;
|
|
3293
|
+
el.setAttribute(override.attr, override.value);
|
|
3294
|
+
}
|
|
3295
|
+
});
|
|
3296
|
+
}
|
|
3297
|
+
if (skipChildrenOf) {
|
|
3298
|
+
morphChildren(container, template.content, skipChildrenOf);
|
|
3299
|
+
return;
|
|
3300
|
+
}
|
|
3301
|
+
const parsedTextFields = new Set(
|
|
3302
|
+
getAnnotations(html).fields.filter((field) => field.binding === "text").map((field) => field.name)
|
|
3303
|
+
);
|
|
3304
|
+
morphChildren(
|
|
3305
|
+
container,
|
|
3306
|
+
template.content,
|
|
3307
|
+
(el) => ownsItsChildren(el, parsedTextFields)
|
|
3308
|
+
);
|
|
3309
|
+
}
|
|
3310
|
+
|
|
3311
|
+
// src/lib/design/observer-guard.ts
|
|
3312
|
+
init_react_import();
|
|
3313
|
+
var wrapScriptWithObserverGuard = (script) => {
|
|
3314
|
+
if (!script.includes("MutationObserver")) return script;
|
|
3315
|
+
return `(function () {
|
|
3316
|
+
var __NativeMutationObserver = window.MutationObserver;
|
|
3317
|
+
function MutationObserver(callback) {
|
|
3318
|
+
var observed = [];
|
|
3319
|
+
var inner = new __NativeMutationObserver(function (records) {
|
|
3320
|
+
inner.disconnect();
|
|
3321
|
+
try {
|
|
3322
|
+
callback(records, inner);
|
|
3323
|
+
} finally {
|
|
3324
|
+
for (var i = 0; i < observed.length; i++) {
|
|
3325
|
+
__nativeObserve.call(inner, observed[i][0], observed[i][1]);
|
|
3326
|
+
}
|
|
3327
|
+
}
|
|
3328
|
+
});
|
|
3329
|
+
var __nativeObserve = inner.observe;
|
|
3330
|
+
inner.observe = function (target, options) {
|
|
3331
|
+
observed.push([target, options]);
|
|
3332
|
+
return __nativeObserve.call(inner, target, options);
|
|
3333
|
+
};
|
|
3334
|
+
return inner;
|
|
3335
|
+
}
|
|
3336
|
+
${script}
|
|
3337
|
+
})();`;
|
|
3338
|
+
};
|
|
3339
|
+
|
|
3301
3340
|
// src/lib/design/registration-store.ts
|
|
3302
3341
|
init_react_import();
|
|
3303
3342
|
var RegistrationStore = class {
|
|
@@ -3371,7 +3410,7 @@ init_react_import();
|
|
|
3371
3410
|
var import_core2 = require("@puckeditor/core");
|
|
3372
3411
|
var CONTENT_EDITABLE_ATTR = "data-puck-content-editable";
|
|
3373
3412
|
var isInlineEditingDisabled = (el) => el.closest(`[${CONTENT_EDITABLE_ATTR}="false"]`) !== null;
|
|
3374
|
-
var
|
|
3413
|
+
var cssEscape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/["\\]/g, "\\$&");
|
|
3375
3414
|
var queryScopedFields = (entry, selector) => Array.from(entry.querySelectorAll(selector)).filter((el) => {
|
|
3376
3415
|
if (el.closest("[data-puck-array]")) return false;
|
|
3377
3416
|
const closestSlot = el.closest("[data-puck-slot]");
|
|
@@ -3379,7 +3418,7 @@ var queryScopedFields = (entry, selector) => Array.from(entry.querySelectorAll(s
|
|
|
3379
3418
|
return true;
|
|
3380
3419
|
});
|
|
3381
3420
|
var findOwnArrayContainer = (entry, arrayName) => {
|
|
3382
|
-
const selector = `[data-puck-array="${
|
|
3421
|
+
const selector = `[data-puck-array="${cssEscape(arrayName)}"]`;
|
|
3383
3422
|
for (const el of entry.querySelectorAll(selector)) {
|
|
3384
3423
|
const closestSlot = el.closest("[data-puck-slot]");
|
|
3385
3424
|
if (!closestSlot || !entry.contains(closestSlot)) return el;
|
|
@@ -3394,7 +3433,7 @@ var inlineEditModeFor = (field) => {
|
|
|
3394
3433
|
const type = field.shape?.type ?? field.fieldType;
|
|
3395
3434
|
return type === "richtext" ? "richtext" : type === "number" ? "number" : "text";
|
|
3396
3435
|
};
|
|
3397
|
-
var textFieldSelector = (field) => field.format === "json" ? `[${
|
|
3436
|
+
var textFieldSelector = (field) => field.format === "json" ? `[${cssEscape(`data-puck-field-${field.name}`)}]` : `[data-puck-field-name="${cssEscape(field.name)}"]`;
|
|
3398
3437
|
var isHTMLElement = (el) => {
|
|
3399
3438
|
const HTMLElementCtor = el.ownerDocument.defaultView?.HTMLElement;
|
|
3400
3439
|
return !!HTMLElementCtor && el instanceof HTMLElementCtor;
|
|
@@ -3741,7 +3780,7 @@ var SlotPortal = ({
|
|
|
3741
3780
|
[slotStyle]
|
|
3742
3781
|
);
|
|
3743
3782
|
(0, import_react23.useEffect)(() => {
|
|
3744
|
-
const el = entry.querySelector(`[data-puck-slot="${
|
|
3783
|
+
const el = entry.querySelector(`[data-puck-slot="${cssEscape(slotName)}"]`);
|
|
3745
3784
|
if (el !== lastTarget.current) {
|
|
3746
3785
|
el?.replaceChildren();
|
|
3747
3786
|
lastTarget.current = el;
|
|
@@ -4392,6 +4431,123 @@ var waitForIframeReady = async (root, imageTimeout = 1e4) => {
|
|
|
4392
4431
|
await waitForNextPaint(document2);
|
|
4393
4432
|
};
|
|
4394
4433
|
|
|
4434
|
+
// src/lib/capture-screenshot.ts
|
|
4435
|
+
init_react_import();
|
|
4436
|
+
var import_html2canvas_pro = __toESM(require("html2canvas-pro"));
|
|
4437
|
+
|
|
4438
|
+
// src/lib/screenshot-size.ts
|
|
4439
|
+
init_react_import();
|
|
4440
|
+
var MAX_WEBP_DIMENSION = 16383;
|
|
4441
|
+
var CAPTURE_SCALE = 2;
|
|
4442
|
+
var getFitRatio = (width, height, dimensionLimit = MAX_WEBP_DIMENSION) => {
|
|
4443
|
+
if (width <= 0 || height <= 0) return 1;
|
|
4444
|
+
return Math.min(1, dimensionLimit / Math.max(width, height));
|
|
4445
|
+
};
|
|
4446
|
+
var getCaptureScale = (width, height, scale) => scale * getFitRatio(width * scale, height * scale);
|
|
4447
|
+
var scaleDimension = (value, ratio) => Math.max(1, Math.floor(value * ratio));
|
|
4448
|
+
var getDocumentSize = (root) => {
|
|
4449
|
+
const { body, documentElement } = root.ownerDocument;
|
|
4450
|
+
return {
|
|
4451
|
+
width: Math.max(
|
|
4452
|
+
body?.scrollWidth ?? 0,
|
|
4453
|
+
body?.offsetWidth ?? 0,
|
|
4454
|
+
body?.clientWidth ?? 0,
|
|
4455
|
+
documentElement?.scrollWidth ?? 0,
|
|
4456
|
+
documentElement?.offsetWidth ?? 0,
|
|
4457
|
+
documentElement?.clientWidth ?? 0
|
|
4458
|
+
),
|
|
4459
|
+
height: Math.max(
|
|
4460
|
+
body?.scrollHeight ?? 0,
|
|
4461
|
+
body?.offsetHeight ?? 0,
|
|
4462
|
+
body?.clientHeight ?? 0,
|
|
4463
|
+
documentElement?.scrollHeight ?? 0,
|
|
4464
|
+
documentElement?.offsetHeight ?? 0,
|
|
4465
|
+
documentElement?.clientHeight ?? 0
|
|
4466
|
+
)
|
|
4467
|
+
};
|
|
4468
|
+
};
|
|
4469
|
+
|
|
4470
|
+
// src/lib/capture-screenshot.ts
|
|
4471
|
+
var editorOnlyClassPrefixes = ["_DraggableComponent--hover", "_ActionBar"];
|
|
4472
|
+
var releaseCanvas = (canvas) => {
|
|
4473
|
+
canvas.width = 0;
|
|
4474
|
+
canvas.height = 0;
|
|
4475
|
+
};
|
|
4476
|
+
var drawScaled = (source, ratio) => {
|
|
4477
|
+
const target = document.createElement("canvas");
|
|
4478
|
+
target.width = scaleDimension(source.width, ratio);
|
|
4479
|
+
target.height = scaleDimension(source.height, ratio);
|
|
4480
|
+
const ctx2 = target.getContext("2d");
|
|
4481
|
+
if (!ctx2) {
|
|
4482
|
+
releaseCanvas(target);
|
|
4483
|
+
return source;
|
|
4484
|
+
}
|
|
4485
|
+
ctx2.imageSmoothingEnabled = true;
|
|
4486
|
+
ctx2.imageSmoothingQuality = "high";
|
|
4487
|
+
ctx2.drawImage(source, 0, 0, target.width, target.height);
|
|
4488
|
+
return target;
|
|
4489
|
+
};
|
|
4490
|
+
var fitCanvas = (canvas) => {
|
|
4491
|
+
let remaining = getFitRatio(canvas.width, canvas.height);
|
|
4492
|
+
if (remaining >= 1) return canvas;
|
|
4493
|
+
let current = canvas;
|
|
4494
|
+
while (remaining < 0.5) {
|
|
4495
|
+
const next = drawScaled(current, 0.5);
|
|
4496
|
+
if (current !== canvas) releaseCanvas(current);
|
|
4497
|
+
current = next;
|
|
4498
|
+
remaining *= 2;
|
|
4499
|
+
}
|
|
4500
|
+
const fitted = drawScaled(current, remaining);
|
|
4501
|
+
if (current !== canvas) releaseCanvas(current);
|
|
4502
|
+
return fitted;
|
|
4503
|
+
};
|
|
4504
|
+
var toWebp = (canvas, quality) => new Promise((resolve, reject) => {
|
|
4505
|
+
canvas.toBlob(
|
|
4506
|
+
(blob) => {
|
|
4507
|
+
if (blob && blob.size > 0) {
|
|
4508
|
+
resolve(blob);
|
|
4509
|
+
return;
|
|
4510
|
+
}
|
|
4511
|
+
reject(
|
|
4512
|
+
new Error(
|
|
4513
|
+
`Could not encode a ${canvas.width}x${canvas.height} canvas as WebP`
|
|
4514
|
+
)
|
|
4515
|
+
);
|
|
4516
|
+
},
|
|
4517
|
+
"image/webp",
|
|
4518
|
+
quality
|
|
4519
|
+
);
|
|
4520
|
+
});
|
|
4521
|
+
var captureScreenshot = async (root, { scale = CAPTURE_SCALE, quality = 0.8, width } = {}) => {
|
|
4522
|
+
const documentSize = getDocumentSize(root);
|
|
4523
|
+
const safeWebPScale = getCaptureScale(
|
|
4524
|
+
width ?? documentSize.width,
|
|
4525
|
+
documentSize.height,
|
|
4526
|
+
scale
|
|
4527
|
+
);
|
|
4528
|
+
const canvas = await (0, import_html2canvas_pro.default)(root, {
|
|
4529
|
+
scale: safeWebPScale,
|
|
4530
|
+
backgroundColor: "#ffffff",
|
|
4531
|
+
...width === void 0 ? {} : { width, windowWidth: width },
|
|
4532
|
+
foreignObjectRendering: false,
|
|
4533
|
+
imageTimeout: 3e4,
|
|
4534
|
+
logging: false,
|
|
4535
|
+
allowTaint: false,
|
|
4536
|
+
useCORS: true,
|
|
4537
|
+
scrollY: 0,
|
|
4538
|
+
ignoreElements: (el) => Array.from(el.classList).some(
|
|
4539
|
+
(c) => editorOnlyClassPrefixes.some((prefix) => c.startsWith(prefix))
|
|
4540
|
+
)
|
|
4541
|
+
});
|
|
4542
|
+
const fitted = fitCanvas(canvas);
|
|
4543
|
+
try {
|
|
4544
|
+
return await toWebp(fitted, quality);
|
|
4545
|
+
} finally {
|
|
4546
|
+
if (fitted !== canvas) releaseCanvas(fitted);
|
|
4547
|
+
releaseCanvas(canvas);
|
|
4548
|
+
}
|
|
4549
|
+
};
|
|
4550
|
+
|
|
4395
4551
|
// src/lib/client-tool-response.ts
|
|
4396
4552
|
init_react_import();
|
|
4397
4553
|
async function postClientToolResponse(host, body) {
|
|
@@ -4413,7 +4569,7 @@ var q = (0, import_qler.default)();
|
|
|
4413
4569
|
var DEFAULT_API_VERSION = "v2";
|
|
4414
4570
|
var BUILD_OP_DEBOUNCE_MS = 1e3 / 60;
|
|
4415
4571
|
var CLIENT_TOOL_ENDPOINT_UNAVAILABLE_ERROR_MESSAGE = "Unable to verify the page data. Please enable the `/chat/tool` endpoint on the server and try again.";
|
|
4416
|
-
var PLUGIN_AI_VERSION = true ? "0.8.3
|
|
4572
|
+
var PLUGIN_AI_VERSION = true ? "0.8.3" : "unknown";
|
|
4417
4573
|
var BENCHMARK = false;
|
|
4418
4574
|
var prefixedUlid = (prefix = "") => `${prefix ? `${prefix}_` : ""}${(0, import_ulid.ulid)()}`;
|
|
4419
4575
|
var getClassName18 = getClassNameFactory("Chat", styles_module_default);
|
|
@@ -4498,24 +4654,7 @@ function Chat2(props) {
|
|
|
4498
4654
|
throw new Error("Preview frame not found");
|
|
4499
4655
|
}
|
|
4500
4656
|
await waitForIframeReady(iframeDocument);
|
|
4501
|
-
const
|
|
4502
|
-
scale: 2,
|
|
4503
|
-
backgroundColor: "#ffffff",
|
|
4504
|
-
width,
|
|
4505
|
-
windowWidth: width,
|
|
4506
|
-
foreignObjectRendering: false,
|
|
4507
|
-
imageTimeout: 3e4,
|
|
4508
|
-
logging: false,
|
|
4509
|
-
allowTaint: false,
|
|
4510
|
-
useCORS: true,
|
|
4511
|
-
scrollY: 0,
|
|
4512
|
-
ignoreElements: (el) => Array.from(el.classList).some(
|
|
4513
|
-
(c) => c.startsWith("_DraggableComponent--hover") || c.startsWith("_ActionBar")
|
|
4514
|
-
)
|
|
4515
|
-
});
|
|
4516
|
-
const image = canvas.toDataURL("image/webp", 0.8);
|
|
4517
|
-
const imageResponse = await fetch(image);
|
|
4518
|
-
const blob = await imageResponse.blob();
|
|
4657
|
+
const blob = await captureScreenshot(iframeDocument, { width });
|
|
4519
4658
|
const uploadResponse = await fetch(bucketUrl, {
|
|
4520
4659
|
method: "PUT",
|
|
4521
4660
|
body: blob
|
|
@@ -4655,22 +4794,7 @@ function Chat2(props) {
|
|
|
4655
4794
|
throw new Error("Preview frame not found");
|
|
4656
4795
|
}
|
|
4657
4796
|
await waitForIframeReady(iframeDocument);
|
|
4658
|
-
const
|
|
4659
|
-
scale: 2,
|
|
4660
|
-
backgroundColor: "#ffffff",
|
|
4661
|
-
foreignObjectRendering: false,
|
|
4662
|
-
imageTimeout: 3e4,
|
|
4663
|
-
logging: false,
|
|
4664
|
-
allowTaint: false,
|
|
4665
|
-
useCORS: true,
|
|
4666
|
-
scrollY: 0,
|
|
4667
|
-
ignoreElements: (el) => Array.from(el.classList).some(
|
|
4668
|
-
(c) => c.startsWith("_DraggableComponent--hover") || c.startsWith("_ActionBar")
|
|
4669
|
-
)
|
|
4670
|
-
});
|
|
4671
|
-
const image = canvas.toDataURL("image/webp", 0.8);
|
|
4672
|
-
const imageResponse = await fetch(image);
|
|
4673
|
-
const blob = await imageResponse.blob();
|
|
4797
|
+
const blob = await captureScreenshot(iframeDocument);
|
|
4674
4798
|
const uploadResponse = await fetch(putUrl, {
|
|
4675
4799
|
method: "PUT",
|
|
4676
4800
|
body: blob
|
|
@@ -4686,6 +4810,10 @@ function Chat2(props) {
|
|
|
4686
4810
|
});
|
|
4687
4811
|
}).catch((e) => {
|
|
4688
4812
|
console.error("Failed to respond to client request:", e);
|
|
4813
|
+
return sendClientToolResponse({
|
|
4814
|
+
id: requestId,
|
|
4815
|
+
responses: [{ action, output: { sizeBytes: 0 } }]
|
|
4816
|
+
});
|
|
4689
4817
|
});
|
|
4690
4818
|
}
|
|
4691
4819
|
return;
|
package/dist/index.mjs
CHANGED
|
@@ -2510,7 +2510,6 @@ function ExamplePrompt({
|
|
|
2510
2510
|
// src/components/Chat/index.tsx
|
|
2511
2511
|
var import_reducer = __toESM(require_dist());
|
|
2512
2512
|
import qler from "qler";
|
|
2513
|
-
import html2canvas from "html2canvas-pro";
|
|
2514
2513
|
import { useDebouncedCallback } from "use-debounce";
|
|
2515
2514
|
|
|
2516
2515
|
// src/lib/scroll-tracking-events.ts
|
|
@@ -2582,147 +2581,16 @@ import {
|
|
|
2582
2581
|
|
|
2583
2582
|
// src/lib/morph-html.ts
|
|
2584
2583
|
init_react_import();
|
|
2585
|
-
var PROTECTED_ATTRS = /* @__PURE__ */ new Set([
|
|
2586
|
-
"contenteditable",
|
|
2587
|
-
"data-puck-overlay-portal"
|
|
2588
|
-
]);
|
|
2589
|
-
var SLOT_OWNED_ATTRS = /* @__PURE__ */ new Set(["style", "class"]);
|
|
2590
|
-
var isEventHandlerAttr = (name) => /^on/i.test(name);
|
|
2591
|
-
var cssEscape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/["\\]/g, "\\$&");
|
|
2592
|
-
var FIELD_ATTR_PREFIX = "data-puck-field-";
|
|
2593
|
-
var hasJsonFieldBinding = (el) => {
|
|
2594
|
-
const attrBoundNames = /* @__PURE__ */ new Set();
|
|
2595
|
-
const jsonFieldNames = [];
|
|
2596
|
-
for (const attr of Array.from(el.attributes)) {
|
|
2597
|
-
if (!attr.name.startsWith(FIELD_ATTR_PREFIX)) continue;
|
|
2598
|
-
if (attr.name.startsWith("data-puck-field-value-")) continue;
|
|
2599
|
-
if (attr.value.trimStart().startsWith("{")) {
|
|
2600
|
-
const fieldName = attr.name.slice(FIELD_ATTR_PREFIX.length);
|
|
2601
|
-
if (fieldName && fieldName !== "name") {
|
|
2602
|
-
jsonFieldNames.push(fieldName);
|
|
2603
|
-
}
|
|
2604
|
-
} else {
|
|
2605
|
-
const fieldName = attr.value.trim();
|
|
2606
|
-
if (fieldName) attrBoundNames.add(fieldName);
|
|
2607
|
-
}
|
|
2608
|
-
}
|
|
2609
|
-
return jsonFieldNames.some((name) => !attrBoundNames.has(name));
|
|
2610
|
-
};
|
|
2611
|
-
var ownsItsChildren = (el) => el.hasAttribute("data-puck-slot") || el.hasAttribute("data-puck-field-name") || el.hasAttribute("data-puck-array") || hasJsonFieldBinding(el);
|
|
2612
|
-
var syncAttributes = (target, source) => {
|
|
2613
|
-
const isSlot = target.hasAttribute("data-puck-slot");
|
|
2614
|
-
for (const attr of Array.from(target.attributes)) {
|
|
2615
|
-
if (PROTECTED_ATTRS.has(attr.name)) continue;
|
|
2616
|
-
if (isSlot && SLOT_OWNED_ATTRS.has(attr.name)) continue;
|
|
2617
|
-
if (isEventHandlerAttr(attr.name) || !source.hasAttribute(attr.name)) {
|
|
2618
|
-
target.removeAttribute(attr.name);
|
|
2619
|
-
}
|
|
2620
|
-
}
|
|
2621
|
-
for (const attr of Array.from(source.attributes)) {
|
|
2622
|
-
if (PROTECTED_ATTRS.has(attr.name)) continue;
|
|
2623
|
-
if (isSlot && SLOT_OWNED_ATTRS.has(attr.name)) continue;
|
|
2624
|
-
if (isEventHandlerAttr(attr.name)) continue;
|
|
2625
|
-
if (target.getAttribute(attr.name) !== attr.value) {
|
|
2626
|
-
target.setAttribute(attr.name, attr.value);
|
|
2627
|
-
}
|
|
2628
|
-
}
|
|
2629
|
-
};
|
|
2630
|
-
var isSameKind = (a, b) => a.nodeType === b.nodeType && (a.nodeType !== Node.ELEMENT_NODE || a.tagName === b.tagName);
|
|
2631
|
-
var isIncompleteTagArtifact = (node) => node.nodeType === Node.TEXT_NODE && /^<\/?[a-zA-Z]*$/.test(node.nodeValue ?? "");
|
|
2632
|
-
var stripIncompleteTagArtifacts = (root) => {
|
|
2633
|
-
for (const child of Array.from(root.childNodes)) {
|
|
2634
|
-
if (isIncompleteTagArtifact(child)) {
|
|
2635
|
-
root.removeChild(child);
|
|
2636
|
-
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
2637
|
-
stripIncompleteTagArtifacts(child);
|
|
2638
|
-
}
|
|
2639
|
-
}
|
|
2640
|
-
};
|
|
2641
|
-
var stripEventHandlerAttrs = (root) => {
|
|
2642
|
-
root.querySelectorAll("*").forEach((el) => {
|
|
2643
|
-
for (const attr of Array.from(el.attributes)) {
|
|
2644
|
-
if (isEventHandlerAttr(attr.name)) el.removeAttribute(attr.name);
|
|
2645
|
-
}
|
|
2646
|
-
});
|
|
2647
|
-
};
|
|
2648
|
-
var morphChildren = (target, source, skipChildrenOf = ownsItsChildren) => {
|
|
2649
|
-
const sourceChildren = Array.from(source.childNodes);
|
|
2650
|
-
for (let i = 0; i < sourceChildren.length; i++) {
|
|
2651
|
-
const sourceChild = sourceChildren[i];
|
|
2652
|
-
const targetChild = target.childNodes[i];
|
|
2653
|
-
if (!targetChild) {
|
|
2654
|
-
target.appendChild(sourceChild);
|
|
2655
|
-
continue;
|
|
2656
|
-
}
|
|
2657
|
-
if (!isSameKind(targetChild, sourceChild)) {
|
|
2658
|
-
target.replaceChild(sourceChild, targetChild);
|
|
2659
|
-
continue;
|
|
2660
|
-
}
|
|
2661
|
-
if (sourceChild.nodeType !== Node.ELEMENT_NODE) {
|
|
2662
|
-
if (targetChild.nodeValue !== sourceChild.nodeValue) {
|
|
2663
|
-
targetChild.nodeValue = sourceChild.nodeValue;
|
|
2664
|
-
}
|
|
2665
|
-
continue;
|
|
2666
|
-
}
|
|
2667
|
-
const targetEl = targetChild;
|
|
2668
|
-
syncAttributes(targetEl, sourceChild);
|
|
2669
|
-
if (!skipChildrenOf(targetEl)) {
|
|
2670
|
-
morphChildren(targetEl, sourceChild, skipChildrenOf);
|
|
2671
|
-
}
|
|
2672
|
-
}
|
|
2673
|
-
while (target.childNodes.length > sourceChildren.length) {
|
|
2674
|
-
target.removeChild(target.lastChild);
|
|
2675
|
-
}
|
|
2676
|
-
};
|
|
2677
|
-
function morphHtml(container, html, attrOverrides = [], skipChildrenOf = ownsItsChildren) {
|
|
2678
|
-
const template = container.ownerDocument.createElement("template");
|
|
2679
|
-
template.innerHTML = html;
|
|
2680
|
-
stripIncompleteTagArtifacts(template.content);
|
|
2681
|
-
stripEventHandlerAttrs(template.content);
|
|
2682
|
-
for (const { name, attr, value } of attrOverrides) {
|
|
2683
|
-
template.content.querySelectorAll(`[data-puck-field-${attr}="${cssEscape(name)}"]`).forEach((el) => {
|
|
2684
|
-
if (el.closest("[data-puck-array]")) return;
|
|
2685
|
-
el.setAttribute(attr, value);
|
|
2686
|
-
});
|
|
2687
|
-
}
|
|
2688
|
-
morphChildren(container, template.content, skipChildrenOf);
|
|
2689
|
-
}
|
|
2690
2584
|
|
|
2691
|
-
// src/lib/design/
|
|
2585
|
+
// src/lib/design/annotations.ts
|
|
2692
2586
|
init_react_import();
|
|
2693
|
-
var wrapScriptWithObserverGuard = (script) => {
|
|
2694
|
-
if (!script.includes("MutationObserver")) return script;
|
|
2695
|
-
return `(function () {
|
|
2696
|
-
var __NativeMutationObserver = window.MutationObserver;
|
|
2697
|
-
function MutationObserver(callback) {
|
|
2698
|
-
var observed = [];
|
|
2699
|
-
var inner = new __NativeMutationObserver(function (records) {
|
|
2700
|
-
inner.disconnect();
|
|
2701
|
-
try {
|
|
2702
|
-
callback(records, inner);
|
|
2703
|
-
} finally {
|
|
2704
|
-
for (var i = 0; i < observed.length; i++) {
|
|
2705
|
-
__nativeObserve.call(inner, observed[i][0], observed[i][1]);
|
|
2706
|
-
}
|
|
2707
|
-
}
|
|
2708
|
-
});
|
|
2709
|
-
var __nativeObserve = inner.observe;
|
|
2710
|
-
inner.observe = function (target, options) {
|
|
2711
|
-
observed.push([target, options]);
|
|
2712
|
-
return __nativeObserve.call(inner, target, options);
|
|
2713
|
-
};
|
|
2714
|
-
return inner;
|
|
2715
|
-
}
|
|
2716
|
-
${script}
|
|
2717
|
-
})();`;
|
|
2718
|
-
};
|
|
2719
2587
|
|
|
2720
2588
|
// src/lib/html-annotations.ts
|
|
2721
2589
|
init_react_import();
|
|
2722
2590
|
import { parseDocument } from "htmlparser2";
|
|
2723
2591
|
import { appendChild, getInnerHTML, getOuterHTML, textContent } from "domutils";
|
|
2724
2592
|
import { Text } from "domhandler";
|
|
2725
|
-
var
|
|
2593
|
+
var FIELD_ATTR_PREFIX = "data-puck-field-";
|
|
2726
2594
|
var OPTIONS_ATTR_PREFIX = "data-puck-options-";
|
|
2727
2595
|
var BIND_ATTR_PREFIX = "data-puck-bind-";
|
|
2728
2596
|
var BIND_INPUT_ATTR_PREFIX = "data-puck-bind-input-";
|
|
@@ -2770,6 +2638,19 @@ var textContentWithBreaks = (node) => {
|
|
|
2770
2638
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2771
2639
|
var FIELD_NAME_RE = /^[A-Za-z0-9_]+(?:[-.][A-Za-z0-9_]+)*$/;
|
|
2772
2640
|
var isValidFieldName = (name) => FIELD_NAME_RE.test(name);
|
|
2641
|
+
var isFieldNameClaimed = (name, claimed, includeExact = true) => {
|
|
2642
|
+
for (const entry of claimed) {
|
|
2643
|
+
if (includeExact && entry === name || entry.startsWith(`${name}.`) || name.startsWith(`${entry}.`)) {
|
|
2644
|
+
return true;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
return false;
|
|
2648
|
+
};
|
|
2649
|
+
var attrBoundFieldNames = (attribs) => new Set(
|
|
2650
|
+
Object.entries(attribs).filter(
|
|
2651
|
+
([name, value]) => name.startsWith(FIELD_ATTR_PREFIX) && name !== `${FIELD_ATTR_PREFIX}name` && !name.startsWith(`${FIELD_ATTR_PREFIX}value-`) && !tryParseFieldShape(value)
|
|
2652
|
+
).map(([, value]) => value.trim()).filter(isValidFieldName)
|
|
2653
|
+
);
|
|
2773
2654
|
var getDeepValue = (source, path) => {
|
|
2774
2655
|
if (!path.includes(".")) return source[path];
|
|
2775
2656
|
let current = source;
|
|
@@ -2870,6 +2751,7 @@ var collectElementFields = (element, acc) => {
|
|
|
2870
2751
|
return true;
|
|
2871
2752
|
}
|
|
2872
2753
|
let skipChildren = false;
|
|
2754
|
+
const attrBound = attrBoundFieldNames(attribs);
|
|
2873
2755
|
for (const [attrName, attrValue] of Object.entries(attribs)) {
|
|
2874
2756
|
if (attrName.startsWith(OPTIONS_ATTR_PREFIX)) {
|
|
2875
2757
|
const fieldName = attrName.slice(OPTIONS_ATTR_PREFIX.length);
|
|
@@ -2898,8 +2780,8 @@ var collectElementFields = (element, acc) => {
|
|
|
2898
2780
|
}
|
|
2899
2781
|
continue;
|
|
2900
2782
|
}
|
|
2901
|
-
if (!attrName.startsWith(
|
|
2902
|
-
const target = attrName.slice(
|
|
2783
|
+
if (!attrName.startsWith(FIELD_ATTR_PREFIX)) continue;
|
|
2784
|
+
const target = attrName.slice(FIELD_ATTR_PREFIX.length);
|
|
2903
2785
|
if (!target) continue;
|
|
2904
2786
|
const shape = tryParseFieldShape(attrValue);
|
|
2905
2787
|
if (shape) {
|
|
@@ -2913,6 +2795,9 @@ var collectElementFields = (element, acc) => {
|
|
|
2913
2795
|
if (existing) existing.shape = shape;
|
|
2914
2796
|
continue;
|
|
2915
2797
|
}
|
|
2798
|
+
if (isFieldNameClaimed(name2, attrBound, false) || isFieldNameClaimed(name2, acc.seenFields)) {
|
|
2799
|
+
continue;
|
|
2800
|
+
}
|
|
2916
2801
|
acc.seenFields.add(name2);
|
|
2917
2802
|
if (shape.type === "richtext") {
|
|
2918
2803
|
acc.fields.push({ name: name2, binding: "text", shape, format: "json" });
|
|
@@ -2967,6 +2852,9 @@ var collectElementFields = (element, acc) => {
|
|
|
2967
2852
|
}
|
|
2968
2853
|
continue;
|
|
2969
2854
|
}
|
|
2855
|
+
if (target === "name" && isFieldNameClaimed(name, attrBound) || isFieldNameClaimed(name, acc.seenFields)) {
|
|
2856
|
+
continue;
|
|
2857
|
+
}
|
|
2970
2858
|
acc.seenFields.add(name);
|
|
2971
2859
|
const fieldType = getTypeModifier(attribs, name);
|
|
2972
2860
|
const constraints = fieldType === "number" ? getNumberConstraints(attribs, name) : {};
|
|
@@ -3060,7 +2948,7 @@ var parseHtmlAnnotations = (html) => {
|
|
|
3060
2948
|
if (slotName && isValidFieldName(slotName) && !seenSlots.has(slotName)) {
|
|
3061
2949
|
seenSlots.add(slotName);
|
|
3062
2950
|
const shape = tryParseFieldShape(
|
|
3063
|
-
attribs[
|
|
2951
|
+
attribs[FIELD_ATTR_PREFIX + slotName.toLowerCase()] ?? ""
|
|
3064
2952
|
);
|
|
3065
2953
|
const allow = shape?.type === "slot" ? sanitizeStringArray(shape.allow) : void 0;
|
|
3066
2954
|
const disallow = shape?.type === "slot" ? sanitizeStringArray(shape.disallow) : void 0;
|
|
@@ -3209,21 +3097,16 @@ var patchElement = (element, props) => {
|
|
|
3209
3097
|
}
|
|
3210
3098
|
return { didPatch, skipChildren: true };
|
|
3211
3099
|
}
|
|
3212
|
-
const attrBoundFields =
|
|
3213
|
-
for (const [an, av] of Object.entries(attribs)) {
|
|
3214
|
-
if (an.startsWith(FIELD_ATTR_PREFIX2) && an !== `${FIELD_ATTR_PREFIX2}name` && !tryParseFieldShape(av)) {
|
|
3215
|
-
attrBoundFields.add(av.trim());
|
|
3216
|
-
}
|
|
3217
|
-
}
|
|
3100
|
+
const attrBoundFields = attrBoundFieldNames(attribs);
|
|
3218
3101
|
for (const [attrName, attrValue] of Object.entries(attribs)) {
|
|
3219
|
-
if (!attrName.startsWith(
|
|
3220
|
-
const target = attrName.slice(
|
|
3102
|
+
if (!attrName.startsWith(FIELD_ATTR_PREFIX)) continue;
|
|
3103
|
+
const target = attrName.slice(FIELD_ATTR_PREFIX.length);
|
|
3221
3104
|
if (!target) continue;
|
|
3222
3105
|
const shape = tryParseFieldShape(attrValue);
|
|
3223
3106
|
if (shape) {
|
|
3224
3107
|
if (shape.type === "slot") continue;
|
|
3225
3108
|
const name2 = target;
|
|
3226
|
-
if (
|
|
3109
|
+
if (isFieldNameClaimed(name2, attrBoundFields)) continue;
|
|
3227
3110
|
const value2 = getDeepValue(props, name2);
|
|
3228
3111
|
if (shape.type === "richtext") {
|
|
3229
3112
|
if (typeof value2 !== "string") continue;
|
|
@@ -3241,6 +3124,9 @@ var patchElement = (element, props) => {
|
|
|
3241
3124
|
}
|
|
3242
3125
|
const name = attrValue.trim();
|
|
3243
3126
|
if (!name) continue;
|
|
3127
|
+
if (target === "name" && isFieldNameClaimed(name, attrBoundFields)) {
|
|
3128
|
+
continue;
|
|
3129
|
+
}
|
|
3244
3130
|
const value = getDeepValue(props, name);
|
|
3245
3131
|
if (target === "name" && getTypeModifier(attribs, name) === "richtext") {
|
|
3246
3132
|
if (typeof value !== "string") continue;
|
|
@@ -3313,7 +3199,6 @@ var renderHtmlArrayItems = (html, arrayName, items) => {
|
|
|
3313
3199
|
};
|
|
3314
3200
|
|
|
3315
3201
|
// src/lib/design/annotations.ts
|
|
3316
|
-
init_react_import();
|
|
3317
3202
|
var cache = /* @__PURE__ */ new Map();
|
|
3318
3203
|
var MAX_CACHE_ENTRIES = 32;
|
|
3319
3204
|
var getAnnotations = (html) => {
|
|
@@ -3330,6 +3215,160 @@ var getSlotFields = (html) => Object.fromEntries(
|
|
|
3330
3215
|
getAnnotations(html).slots.map((slot) => [slot.name, toSlotField(slot)])
|
|
3331
3216
|
);
|
|
3332
3217
|
|
|
3218
|
+
// src/lib/morph-html.ts
|
|
3219
|
+
var PROTECTED_ATTRS = /* @__PURE__ */ new Set([
|
|
3220
|
+
"contenteditable",
|
|
3221
|
+
"data-puck-overlay-portal"
|
|
3222
|
+
]);
|
|
3223
|
+
var SLOT_OWNED_ATTRS = /* @__PURE__ */ new Set(["style", "class"]);
|
|
3224
|
+
var isEventHandlerAttr = (name) => /^on/i.test(name);
|
|
3225
|
+
var FIELD_ATTR_PREFIX2 = "data-puck-field-";
|
|
3226
|
+
var LEGACY_TEXT_ATTR = `${FIELD_ATTR_PREFIX2}name`;
|
|
3227
|
+
var VALUE_ATTR_PREFIX = `${FIELD_ATTR_PREFIX2}value-`;
|
|
3228
|
+
var hasTextBinding = (el, parsedTextFields) => {
|
|
3229
|
+
for (const attr of Array.from(el.attributes)) {
|
|
3230
|
+
if (!attr.name.startsWith(FIELD_ATTR_PREFIX2)) continue;
|
|
3231
|
+
if (attr.name.startsWith(VALUE_ATTR_PREFIX)) continue;
|
|
3232
|
+
const isShape = attr.value.trimStart().startsWith("{");
|
|
3233
|
+
const fieldName = isShape ? attr.name.slice(FIELD_ATTR_PREFIX2.length) : attr.value.trim();
|
|
3234
|
+
if (isValidFieldName(fieldName) && (attr.name === LEGACY_TEXT_ATTR || isShape) && (!parsedTextFields || parsedTextFields.has(fieldName))) {
|
|
3235
|
+
return true;
|
|
3236
|
+
}
|
|
3237
|
+
}
|
|
3238
|
+
return false;
|
|
3239
|
+
};
|
|
3240
|
+
var ownsItsChildren = (el, parsedTextFields) => el.hasAttribute("data-puck-slot") || el.hasAttribute("data-puck-array") || hasTextBinding(el, parsedTextFields);
|
|
3241
|
+
var syncAttributes = (target, source) => {
|
|
3242
|
+
const isSlot = target.hasAttribute("data-puck-slot");
|
|
3243
|
+
for (const attr of Array.from(target.attributes)) {
|
|
3244
|
+
if (PROTECTED_ATTRS.has(attr.name)) continue;
|
|
3245
|
+
if (isSlot && SLOT_OWNED_ATTRS.has(attr.name)) continue;
|
|
3246
|
+
if (isEventHandlerAttr(attr.name) || !source.hasAttribute(attr.name)) {
|
|
3247
|
+
target.removeAttribute(attr.name);
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
for (const attr of Array.from(source.attributes)) {
|
|
3251
|
+
if (PROTECTED_ATTRS.has(attr.name)) continue;
|
|
3252
|
+
if (isSlot && SLOT_OWNED_ATTRS.has(attr.name)) continue;
|
|
3253
|
+
if (isEventHandlerAttr(attr.name)) continue;
|
|
3254
|
+
if (target.getAttribute(attr.name) !== attr.value) {
|
|
3255
|
+
target.setAttribute(attr.name, attr.value);
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
};
|
|
3259
|
+
var isSameKind = (a, b) => a.nodeType === b.nodeType && (a.nodeType !== Node.ELEMENT_NODE || a.tagName === b.tagName);
|
|
3260
|
+
var isIncompleteTagArtifact = (node) => node.nodeType === Node.TEXT_NODE && /^<\/?[a-zA-Z]*$/.test(node.nodeValue ?? "");
|
|
3261
|
+
var stripIncompleteTagArtifacts = (root) => {
|
|
3262
|
+
for (const child of Array.from(root.childNodes)) {
|
|
3263
|
+
if (isIncompleteTagArtifact(child)) {
|
|
3264
|
+
root.removeChild(child);
|
|
3265
|
+
} else if (child.nodeType === Node.ELEMENT_NODE) {
|
|
3266
|
+
stripIncompleteTagArtifacts(child);
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
};
|
|
3270
|
+
var stripEventHandlerAttrs = (root) => {
|
|
3271
|
+
root.querySelectorAll("*").forEach((el) => {
|
|
3272
|
+
for (const attr of Array.from(el.attributes)) {
|
|
3273
|
+
if (isEventHandlerAttr(attr.name)) el.removeAttribute(attr.name);
|
|
3274
|
+
}
|
|
3275
|
+
});
|
|
3276
|
+
};
|
|
3277
|
+
var morphChildren = (target, source, skipChildrenOf = ownsItsChildren) => {
|
|
3278
|
+
const sourceChildren = Array.from(source.childNodes);
|
|
3279
|
+
for (let i = 0; i < sourceChildren.length; i++) {
|
|
3280
|
+
const sourceChild = sourceChildren[i];
|
|
3281
|
+
const targetChild = target.childNodes[i];
|
|
3282
|
+
if (!targetChild) {
|
|
3283
|
+
target.appendChild(sourceChild);
|
|
3284
|
+
continue;
|
|
3285
|
+
}
|
|
3286
|
+
if (!isSameKind(targetChild, sourceChild)) {
|
|
3287
|
+
target.replaceChild(sourceChild, targetChild);
|
|
3288
|
+
continue;
|
|
3289
|
+
}
|
|
3290
|
+
if (sourceChild.nodeType !== Node.ELEMENT_NODE) {
|
|
3291
|
+
if (targetChild.nodeValue !== sourceChild.nodeValue) {
|
|
3292
|
+
targetChild.nodeValue = sourceChild.nodeValue;
|
|
3293
|
+
}
|
|
3294
|
+
continue;
|
|
3295
|
+
}
|
|
3296
|
+
const targetEl = targetChild;
|
|
3297
|
+
syncAttributes(targetEl, sourceChild);
|
|
3298
|
+
if (!skipChildrenOf(targetEl)) {
|
|
3299
|
+
morphChildren(targetEl, sourceChild, skipChildrenOf);
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
while (target.childNodes.length > sourceChildren.length) {
|
|
3303
|
+
target.removeChild(target.lastChild);
|
|
3304
|
+
}
|
|
3305
|
+
};
|
|
3306
|
+
function morphHtml(container, html, attrOverrides = [], skipChildrenOf) {
|
|
3307
|
+
const template = container.ownerDocument.createElement("template");
|
|
3308
|
+
template.innerHTML = html;
|
|
3309
|
+
stripIncompleteTagArtifacts(template.content);
|
|
3310
|
+
stripEventHandlerAttrs(template.content);
|
|
3311
|
+
if (attrOverrides.length > 0) {
|
|
3312
|
+
const overridesByAttr = /* @__PURE__ */ new Map();
|
|
3313
|
+
for (const override of attrOverrides) {
|
|
3314
|
+
if (isEventHandlerAttr(override.attr)) continue;
|
|
3315
|
+
const bindingAttr = `${FIELD_ATTR_PREFIX2}${override.attr}`;
|
|
3316
|
+
const fields = overridesByAttr.get(bindingAttr) ?? /* @__PURE__ */ new Map();
|
|
3317
|
+
fields.set(override.name, override);
|
|
3318
|
+
overridesByAttr.set(bindingAttr, fields);
|
|
3319
|
+
}
|
|
3320
|
+
template.content.querySelectorAll("*").forEach((el) => {
|
|
3321
|
+
for (const attr of Array.from(el.attributes)) {
|
|
3322
|
+
const override = overridesByAttr.get(attr.name)?.get(attr.value.trim());
|
|
3323
|
+
if (!override) continue;
|
|
3324
|
+
if (el.closest("[data-puck-array]")) return;
|
|
3325
|
+
el.setAttribute(override.attr, override.value);
|
|
3326
|
+
}
|
|
3327
|
+
});
|
|
3328
|
+
}
|
|
3329
|
+
if (skipChildrenOf) {
|
|
3330
|
+
morphChildren(container, template.content, skipChildrenOf);
|
|
3331
|
+
return;
|
|
3332
|
+
}
|
|
3333
|
+
const parsedTextFields = new Set(
|
|
3334
|
+
getAnnotations(html).fields.filter((field) => field.binding === "text").map((field) => field.name)
|
|
3335
|
+
);
|
|
3336
|
+
morphChildren(
|
|
3337
|
+
container,
|
|
3338
|
+
template.content,
|
|
3339
|
+
(el) => ownsItsChildren(el, parsedTextFields)
|
|
3340
|
+
);
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3343
|
+
// src/lib/design/observer-guard.ts
|
|
3344
|
+
init_react_import();
|
|
3345
|
+
var wrapScriptWithObserverGuard = (script) => {
|
|
3346
|
+
if (!script.includes("MutationObserver")) return script;
|
|
3347
|
+
return `(function () {
|
|
3348
|
+
var __NativeMutationObserver = window.MutationObserver;
|
|
3349
|
+
function MutationObserver(callback) {
|
|
3350
|
+
var observed = [];
|
|
3351
|
+
var inner = new __NativeMutationObserver(function (records) {
|
|
3352
|
+
inner.disconnect();
|
|
3353
|
+
try {
|
|
3354
|
+
callback(records, inner);
|
|
3355
|
+
} finally {
|
|
3356
|
+
for (var i = 0; i < observed.length; i++) {
|
|
3357
|
+
__nativeObserve.call(inner, observed[i][0], observed[i][1]);
|
|
3358
|
+
}
|
|
3359
|
+
}
|
|
3360
|
+
});
|
|
3361
|
+
var __nativeObserve = inner.observe;
|
|
3362
|
+
inner.observe = function (target, options) {
|
|
3363
|
+
observed.push([target, options]);
|
|
3364
|
+
return __nativeObserve.call(inner, target, options);
|
|
3365
|
+
};
|
|
3366
|
+
return inner;
|
|
3367
|
+
}
|
|
3368
|
+
${script}
|
|
3369
|
+
})();`;
|
|
3370
|
+
};
|
|
3371
|
+
|
|
3333
3372
|
// src/lib/design/registration-store.ts
|
|
3334
3373
|
init_react_import();
|
|
3335
3374
|
var RegistrationStore = class {
|
|
@@ -3403,7 +3442,7 @@ init_react_import();
|
|
|
3403
3442
|
import { registerOverlayPortal, setDeep } from "@puckeditor/core";
|
|
3404
3443
|
var CONTENT_EDITABLE_ATTR = "data-puck-content-editable";
|
|
3405
3444
|
var isInlineEditingDisabled = (el) => el.closest(`[${CONTENT_EDITABLE_ATTR}="false"]`) !== null;
|
|
3406
|
-
var
|
|
3445
|
+
var cssEscape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/["\\]/g, "\\$&");
|
|
3407
3446
|
var queryScopedFields = (entry, selector) => Array.from(entry.querySelectorAll(selector)).filter((el) => {
|
|
3408
3447
|
if (el.closest("[data-puck-array]")) return false;
|
|
3409
3448
|
const closestSlot = el.closest("[data-puck-slot]");
|
|
@@ -3411,7 +3450,7 @@ var queryScopedFields = (entry, selector) => Array.from(entry.querySelectorAll(s
|
|
|
3411
3450
|
return true;
|
|
3412
3451
|
});
|
|
3413
3452
|
var findOwnArrayContainer = (entry, arrayName) => {
|
|
3414
|
-
const selector = `[data-puck-array="${
|
|
3453
|
+
const selector = `[data-puck-array="${cssEscape(arrayName)}"]`;
|
|
3415
3454
|
for (const el of entry.querySelectorAll(selector)) {
|
|
3416
3455
|
const closestSlot = el.closest("[data-puck-slot]");
|
|
3417
3456
|
if (!closestSlot || !entry.contains(closestSlot)) return el;
|
|
@@ -3426,7 +3465,7 @@ var inlineEditModeFor = (field) => {
|
|
|
3426
3465
|
const type = field.shape?.type ?? field.fieldType;
|
|
3427
3466
|
return type === "richtext" ? "richtext" : type === "number" ? "number" : "text";
|
|
3428
3467
|
};
|
|
3429
|
-
var textFieldSelector = (field) => field.format === "json" ? `[${
|
|
3468
|
+
var textFieldSelector = (field) => field.format === "json" ? `[${cssEscape(`data-puck-field-${field.name}`)}]` : `[data-puck-field-name="${cssEscape(field.name)}"]`;
|
|
3430
3469
|
var isHTMLElement = (el) => {
|
|
3431
3470
|
const HTMLElementCtor = el.ownerDocument.defaultView?.HTMLElement;
|
|
3432
3471
|
return !!HTMLElementCtor && el instanceof HTMLElementCtor;
|
|
@@ -3773,7 +3812,7 @@ var SlotPortal = ({
|
|
|
3773
3812
|
[slotStyle]
|
|
3774
3813
|
);
|
|
3775
3814
|
useEffect10(() => {
|
|
3776
|
-
const el = entry.querySelector(`[data-puck-slot="${
|
|
3815
|
+
const el = entry.querySelector(`[data-puck-slot="${cssEscape(slotName)}"]`);
|
|
3777
3816
|
if (el !== lastTarget.current) {
|
|
3778
3817
|
el?.replaceChildren();
|
|
3779
3818
|
lastTarget.current = el;
|
|
@@ -4424,6 +4463,123 @@ var waitForIframeReady = async (root, imageTimeout = 1e4) => {
|
|
|
4424
4463
|
await waitForNextPaint(document2);
|
|
4425
4464
|
};
|
|
4426
4465
|
|
|
4466
|
+
// src/lib/capture-screenshot.ts
|
|
4467
|
+
init_react_import();
|
|
4468
|
+
import html2canvas from "html2canvas-pro";
|
|
4469
|
+
|
|
4470
|
+
// src/lib/screenshot-size.ts
|
|
4471
|
+
init_react_import();
|
|
4472
|
+
var MAX_WEBP_DIMENSION = 16383;
|
|
4473
|
+
var CAPTURE_SCALE = 2;
|
|
4474
|
+
var getFitRatio = (width, height, dimensionLimit = MAX_WEBP_DIMENSION) => {
|
|
4475
|
+
if (width <= 0 || height <= 0) return 1;
|
|
4476
|
+
return Math.min(1, dimensionLimit / Math.max(width, height));
|
|
4477
|
+
};
|
|
4478
|
+
var getCaptureScale = (width, height, scale) => scale * getFitRatio(width * scale, height * scale);
|
|
4479
|
+
var scaleDimension = (value, ratio) => Math.max(1, Math.floor(value * ratio));
|
|
4480
|
+
var getDocumentSize = (root) => {
|
|
4481
|
+
const { body, documentElement } = root.ownerDocument;
|
|
4482
|
+
return {
|
|
4483
|
+
width: Math.max(
|
|
4484
|
+
body?.scrollWidth ?? 0,
|
|
4485
|
+
body?.offsetWidth ?? 0,
|
|
4486
|
+
body?.clientWidth ?? 0,
|
|
4487
|
+
documentElement?.scrollWidth ?? 0,
|
|
4488
|
+
documentElement?.offsetWidth ?? 0,
|
|
4489
|
+
documentElement?.clientWidth ?? 0
|
|
4490
|
+
),
|
|
4491
|
+
height: Math.max(
|
|
4492
|
+
body?.scrollHeight ?? 0,
|
|
4493
|
+
body?.offsetHeight ?? 0,
|
|
4494
|
+
body?.clientHeight ?? 0,
|
|
4495
|
+
documentElement?.scrollHeight ?? 0,
|
|
4496
|
+
documentElement?.offsetHeight ?? 0,
|
|
4497
|
+
documentElement?.clientHeight ?? 0
|
|
4498
|
+
)
|
|
4499
|
+
};
|
|
4500
|
+
};
|
|
4501
|
+
|
|
4502
|
+
// src/lib/capture-screenshot.ts
|
|
4503
|
+
var editorOnlyClassPrefixes = ["_DraggableComponent--hover", "_ActionBar"];
|
|
4504
|
+
var releaseCanvas = (canvas) => {
|
|
4505
|
+
canvas.width = 0;
|
|
4506
|
+
canvas.height = 0;
|
|
4507
|
+
};
|
|
4508
|
+
var drawScaled = (source, ratio) => {
|
|
4509
|
+
const target = document.createElement("canvas");
|
|
4510
|
+
target.width = scaleDimension(source.width, ratio);
|
|
4511
|
+
target.height = scaleDimension(source.height, ratio);
|
|
4512
|
+
const ctx2 = target.getContext("2d");
|
|
4513
|
+
if (!ctx2) {
|
|
4514
|
+
releaseCanvas(target);
|
|
4515
|
+
return source;
|
|
4516
|
+
}
|
|
4517
|
+
ctx2.imageSmoothingEnabled = true;
|
|
4518
|
+
ctx2.imageSmoothingQuality = "high";
|
|
4519
|
+
ctx2.drawImage(source, 0, 0, target.width, target.height);
|
|
4520
|
+
return target;
|
|
4521
|
+
};
|
|
4522
|
+
var fitCanvas = (canvas) => {
|
|
4523
|
+
let remaining = getFitRatio(canvas.width, canvas.height);
|
|
4524
|
+
if (remaining >= 1) return canvas;
|
|
4525
|
+
let current = canvas;
|
|
4526
|
+
while (remaining < 0.5) {
|
|
4527
|
+
const next = drawScaled(current, 0.5);
|
|
4528
|
+
if (current !== canvas) releaseCanvas(current);
|
|
4529
|
+
current = next;
|
|
4530
|
+
remaining *= 2;
|
|
4531
|
+
}
|
|
4532
|
+
const fitted = drawScaled(current, remaining);
|
|
4533
|
+
if (current !== canvas) releaseCanvas(current);
|
|
4534
|
+
return fitted;
|
|
4535
|
+
};
|
|
4536
|
+
var toWebp = (canvas, quality) => new Promise((resolve, reject) => {
|
|
4537
|
+
canvas.toBlob(
|
|
4538
|
+
(blob) => {
|
|
4539
|
+
if (blob && blob.size > 0) {
|
|
4540
|
+
resolve(blob);
|
|
4541
|
+
return;
|
|
4542
|
+
}
|
|
4543
|
+
reject(
|
|
4544
|
+
new Error(
|
|
4545
|
+
`Could not encode a ${canvas.width}x${canvas.height} canvas as WebP`
|
|
4546
|
+
)
|
|
4547
|
+
);
|
|
4548
|
+
},
|
|
4549
|
+
"image/webp",
|
|
4550
|
+
quality
|
|
4551
|
+
);
|
|
4552
|
+
});
|
|
4553
|
+
var captureScreenshot = async (root, { scale = CAPTURE_SCALE, quality = 0.8, width } = {}) => {
|
|
4554
|
+
const documentSize = getDocumentSize(root);
|
|
4555
|
+
const safeWebPScale = getCaptureScale(
|
|
4556
|
+
width ?? documentSize.width,
|
|
4557
|
+
documentSize.height,
|
|
4558
|
+
scale
|
|
4559
|
+
);
|
|
4560
|
+
const canvas = await html2canvas(root, {
|
|
4561
|
+
scale: safeWebPScale,
|
|
4562
|
+
backgroundColor: "#ffffff",
|
|
4563
|
+
...width === void 0 ? {} : { width, windowWidth: width },
|
|
4564
|
+
foreignObjectRendering: false,
|
|
4565
|
+
imageTimeout: 3e4,
|
|
4566
|
+
logging: false,
|
|
4567
|
+
allowTaint: false,
|
|
4568
|
+
useCORS: true,
|
|
4569
|
+
scrollY: 0,
|
|
4570
|
+
ignoreElements: (el) => Array.from(el.classList).some(
|
|
4571
|
+
(c) => editorOnlyClassPrefixes.some((prefix) => c.startsWith(prefix))
|
|
4572
|
+
)
|
|
4573
|
+
});
|
|
4574
|
+
const fitted = fitCanvas(canvas);
|
|
4575
|
+
try {
|
|
4576
|
+
return await toWebp(fitted, quality);
|
|
4577
|
+
} finally {
|
|
4578
|
+
if (fitted !== canvas) releaseCanvas(fitted);
|
|
4579
|
+
releaseCanvas(canvas);
|
|
4580
|
+
}
|
|
4581
|
+
};
|
|
4582
|
+
|
|
4427
4583
|
// src/lib/client-tool-response.ts
|
|
4428
4584
|
init_react_import();
|
|
4429
4585
|
async function postClientToolResponse(host, body) {
|
|
@@ -4445,7 +4601,7 @@ var q = qler();
|
|
|
4445
4601
|
var DEFAULT_API_VERSION = "v2";
|
|
4446
4602
|
var BUILD_OP_DEBOUNCE_MS = 1e3 / 60;
|
|
4447
4603
|
var CLIENT_TOOL_ENDPOINT_UNAVAILABLE_ERROR_MESSAGE = "Unable to verify the page data. Please enable the `/chat/tool` endpoint on the server and try again.";
|
|
4448
|
-
var PLUGIN_AI_VERSION = true ? "0.8.3
|
|
4604
|
+
var PLUGIN_AI_VERSION = true ? "0.8.3" : "unknown";
|
|
4449
4605
|
var BENCHMARK = false;
|
|
4450
4606
|
var prefixedUlid = (prefix = "") => `${prefix ? `${prefix}_` : ""}${ulid()}`;
|
|
4451
4607
|
var getClassName18 = getClassNameFactory("Chat", styles_module_default);
|
|
@@ -4530,24 +4686,7 @@ function Chat2(props) {
|
|
|
4530
4686
|
throw new Error("Preview frame not found");
|
|
4531
4687
|
}
|
|
4532
4688
|
await waitForIframeReady(iframeDocument);
|
|
4533
|
-
const
|
|
4534
|
-
scale: 2,
|
|
4535
|
-
backgroundColor: "#ffffff",
|
|
4536
|
-
width,
|
|
4537
|
-
windowWidth: width,
|
|
4538
|
-
foreignObjectRendering: false,
|
|
4539
|
-
imageTimeout: 3e4,
|
|
4540
|
-
logging: false,
|
|
4541
|
-
allowTaint: false,
|
|
4542
|
-
useCORS: true,
|
|
4543
|
-
scrollY: 0,
|
|
4544
|
-
ignoreElements: (el) => Array.from(el.classList).some(
|
|
4545
|
-
(c) => c.startsWith("_DraggableComponent--hover") || c.startsWith("_ActionBar")
|
|
4546
|
-
)
|
|
4547
|
-
});
|
|
4548
|
-
const image = canvas.toDataURL("image/webp", 0.8);
|
|
4549
|
-
const imageResponse = await fetch(image);
|
|
4550
|
-
const blob = await imageResponse.blob();
|
|
4689
|
+
const blob = await captureScreenshot(iframeDocument, { width });
|
|
4551
4690
|
const uploadResponse = await fetch(bucketUrl, {
|
|
4552
4691
|
method: "PUT",
|
|
4553
4692
|
body: blob
|
|
@@ -4687,22 +4826,7 @@ function Chat2(props) {
|
|
|
4687
4826
|
throw new Error("Preview frame not found");
|
|
4688
4827
|
}
|
|
4689
4828
|
await waitForIframeReady(iframeDocument);
|
|
4690
|
-
const
|
|
4691
|
-
scale: 2,
|
|
4692
|
-
backgroundColor: "#ffffff",
|
|
4693
|
-
foreignObjectRendering: false,
|
|
4694
|
-
imageTimeout: 3e4,
|
|
4695
|
-
logging: false,
|
|
4696
|
-
allowTaint: false,
|
|
4697
|
-
useCORS: true,
|
|
4698
|
-
scrollY: 0,
|
|
4699
|
-
ignoreElements: (el) => Array.from(el.classList).some(
|
|
4700
|
-
(c) => c.startsWith("_DraggableComponent--hover") || c.startsWith("_ActionBar")
|
|
4701
|
-
)
|
|
4702
|
-
});
|
|
4703
|
-
const image = canvas.toDataURL("image/webp", 0.8);
|
|
4704
|
-
const imageResponse = await fetch(image);
|
|
4705
|
-
const blob = await imageResponse.blob();
|
|
4829
|
+
const blob = await captureScreenshot(iframeDocument);
|
|
4706
4830
|
const uploadResponse = await fetch(putUrl, {
|
|
4707
4831
|
method: "PUT",
|
|
4708
4832
|
body: blob
|
|
@@ -4718,6 +4842,10 @@ function Chat2(props) {
|
|
|
4718
4842
|
});
|
|
4719
4843
|
}).catch((e) => {
|
|
4720
4844
|
console.error("Failed to respond to client request:", e);
|
|
4845
|
+
return sendClientToolResponse({
|
|
4846
|
+
id: requestId,
|
|
4847
|
+
responses: [{ action, output: { sizeBytes: 0 } }]
|
|
4848
|
+
});
|
|
4721
4849
|
});
|
|
4722
4850
|
}
|
|
4723
4851
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@puckeditor/plugin-ai",
|
|
3
|
-
"version": "0.8.3
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"author": "Chris Villa <chris@puckeditor.com>",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
"tsup": "^8.2.4",
|
|
53
53
|
"typescript": "^5.5.4",
|
|
54
54
|
"vitest": "^4.1.0",
|
|
55
|
-
"@puckeditor/ai-types": "0.8.3
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
55
|
+
"@puckeditor/ai-types": "0.8.3",
|
|
56
|
+
"@puckeditor/platform-types": "0.8.3",
|
|
57
|
+
"eslint-config-custom": "0.8.3",
|
|
58
|
+
"reducer": "0.8.3",
|
|
59
|
+
"tsconfig": "0.8.3",
|
|
60
|
+
"tsup-config": "0.8.3"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"@puckeditor/core": "^0",
|