@duffcloudservices/cms 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/editor/editorBridge.d.ts +41 -1
- package/dist/editor/editorBridge.js +68 -2
- package/dist/editor/editorBridge.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/index.d.ts +85 -2
- package/dist/plugins/index.js +100 -7
- package/dist/plugins/index.js.map +1 -1
- package/package.json +12 -13
- package/src/components/DcsReviewShowcase.vue +5 -1
- package/src/components/ManagedImage.test.ts +60 -0
- package/src/components/ManagedImage.vue +53 -6
- package/src/composables/useResponsiveImage.ts +6 -0
|
@@ -56,6 +56,46 @@ interface EditorReadyPayload {
|
|
|
56
56
|
/** Keys of all [data-dcs-reviews] elements found on the page */
|
|
57
57
|
reviewKeys: string[];
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Swap the live `<img>`(s) carrying a managed image key to a new source.
|
|
61
|
+
*
|
|
62
|
+
* Mirrors the self-heal invariant: a `<picture>` does NOT re-resolve after its
|
|
63
|
+
* `<source>` set changes, so the stale `<source>` siblings are removed and the
|
|
64
|
+
* `srcset` on the `<img>` cleared — otherwise the browser keeps serving the old
|
|
65
|
+
* variant. `data-dcs-image-url`/`-alt` are updated too so a subsequent
|
|
66
|
+
* right-click reports the new image, not the replaced one.
|
|
67
|
+
*
|
|
68
|
+
* @returns the number of elements updated (0 when the key isn't on the page).
|
|
69
|
+
*/
|
|
70
|
+
declare function applyImageOverride(key: string, src: string, alt?: string | null): number;
|
|
71
|
+
/**
|
|
72
|
+
* Re-apply all pending image overrides. Called after a re-render (HMR / SPA nav)
|
|
73
|
+
* so a hot reload doesn't revert a not-yet-saved swap.
|
|
74
|
+
*/
|
|
75
|
+
declare function applyPendingImageOverrides(): void;
|
|
76
|
+
/**
|
|
77
|
+
* Record a pending image override (test/utility seam for the replay path).
|
|
78
|
+
*/
|
|
79
|
+
declare function recordPendingImageOverride(key: string, src: string, alt?: string | null): void;
|
|
80
|
+
/**
|
|
81
|
+
* Handle a `dcs:update-text` that actually targets a MANAGED IMAGE key.
|
|
82
|
+
*
|
|
83
|
+
* The portal's discard/undo paths (discardTextChanges / discardSingleTextChange
|
|
84
|
+
* in visualEditor.ts) revert EVERY staged key — including image keys — via the
|
|
85
|
+
* text revert callback, which sends `dcs:update-text`. `updateTextInPlace` only
|
|
86
|
+
* touches `data-text-key` elements, a no-op for image keys (which live on
|
|
87
|
+
* `data-dcs-image-key`), while `pendingImageOverrides` would keep re-applying
|
|
88
|
+
* the discarded src on every re-render — the discarded swap stayed sticky until
|
|
89
|
+
* a manual refresh. So: if the key has a pending image override (or a managed
|
|
90
|
+
* image element on the page), drop the sticky override and swap the live
|
|
91
|
+
* `<img>` back to the reverted URL. Covers discard-all, discard-single, undo,
|
|
92
|
+
* and reload-drops-staged-swap in one place.
|
|
93
|
+
*
|
|
94
|
+
* @returns true when the key was handled as an image revert (skip text handling).
|
|
95
|
+
*/
|
|
96
|
+
declare function revertImageOverrideIfImageKey(key: string, value: string): boolean;
|
|
97
|
+
/** Clear all pending image overrides (test isolation). */
|
|
98
|
+
declare function clearPendingImageOverrides(): void;
|
|
59
99
|
declare function initEditorBridge(): void;
|
|
60
100
|
|
|
61
|
-
export { type EditorReadyPayload, type SectionInfo, initEditorBridge };
|
|
101
|
+
export { type EditorReadyPayload, type SectionInfo, applyImageOverride, applyPendingImageOverrides, clearPendingImageOverrides, initEditorBridge, recordPendingImageOverride, revertImageOverrideIfImageKey };
|
|
@@ -193,6 +193,7 @@ function rediscoverAndNotify() {
|
|
|
193
193
|
hasReviews: reviewKeys.length > 0,
|
|
194
194
|
reviewKeys
|
|
195
195
|
});
|
|
196
|
+
applyPendingImageOverrides();
|
|
196
197
|
if (editorActive) {
|
|
197
198
|
applyEditorToElements();
|
|
198
199
|
if (sectionResizeObserver) {
|
|
@@ -663,6 +664,61 @@ function createImageEditIcon(label) {
|
|
|
663
664
|
function getManagedImageKey(img) {
|
|
664
665
|
return img.dataset.dcsImageKey || img.closest("[data-dcs-image-key]")?.dataset.dcsImageKey || null;
|
|
665
666
|
}
|
|
667
|
+
var pendingImageOverrides = /* @__PURE__ */ new Map();
|
|
668
|
+
function cssEscapeAttributeValue(value) {
|
|
669
|
+
const cssGlobal = globalThis.CSS;
|
|
670
|
+
if (typeof cssGlobal?.escape === "function") return cssGlobal.escape(value);
|
|
671
|
+
return value.replace(/[\\"]/g, "\\$&");
|
|
672
|
+
}
|
|
673
|
+
function applyImageOverride(key, src, alt) {
|
|
674
|
+
if (!key) return 0;
|
|
675
|
+
const escapedKey = cssEscapeAttributeValue(key);
|
|
676
|
+
const targets = /* @__PURE__ */ new Set();
|
|
677
|
+
document.querySelectorAll(`img[data-dcs-image-key="${escapedKey}"]`).forEach((img) => targets.add(img));
|
|
678
|
+
document.querySelectorAll(`[data-dcs-image-key="${escapedKey}"]`).forEach((el) => {
|
|
679
|
+
if (el instanceof HTMLImageElement) {
|
|
680
|
+
targets.add(el);
|
|
681
|
+
} else {
|
|
682
|
+
el.querySelectorAll("img").forEach((img) => targets.add(img));
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
targets.forEach((img) => {
|
|
686
|
+
img.closest("picture")?.querySelectorAll("source").forEach((s) => s.remove());
|
|
687
|
+
img.removeAttribute("srcset");
|
|
688
|
+
img.src = src;
|
|
689
|
+
img.dataset.dcsImageUrl = src;
|
|
690
|
+
if (alt != null) {
|
|
691
|
+
img.alt = alt;
|
|
692
|
+
img.dataset.dcsImageAlt = alt;
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
return targets.size;
|
|
696
|
+
}
|
|
697
|
+
function setImageOverride(key, src, alt) {
|
|
698
|
+
pendingImageOverrides.set(key, { src, alt });
|
|
699
|
+
applyImageOverride(key, src, alt);
|
|
700
|
+
scheduleRediscovery();
|
|
701
|
+
}
|
|
702
|
+
function applyPendingImageOverrides() {
|
|
703
|
+
for (const [key, override] of pendingImageOverrides) {
|
|
704
|
+
applyImageOverride(key, override.src, override.alt);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
function recordPendingImageOverride(key, src, alt) {
|
|
708
|
+
pendingImageOverrides.set(key, { src, alt });
|
|
709
|
+
}
|
|
710
|
+
function revertImageOverrideIfImageKey(key, value) {
|
|
711
|
+
if (!key) return false;
|
|
712
|
+
const isPending = pendingImageOverrides.has(key);
|
|
713
|
+
const isImageElement = !isPending && !!document.querySelector(`[data-dcs-image-key="${cssEscapeAttributeValue(key)}"]`);
|
|
714
|
+
if (!isPending && !isImageElement) return false;
|
|
715
|
+
pendingImageOverrides.delete(key);
|
|
716
|
+
if (value) applyImageOverride(key, value);
|
|
717
|
+
return true;
|
|
718
|
+
}
|
|
719
|
+
function clearPendingImageOverrides() {
|
|
720
|
+
pendingImageOverrides.clear();
|
|
721
|
+
}
|
|
666
722
|
function showImageEditIcons(images) {
|
|
667
723
|
if (!editingEnabled) return;
|
|
668
724
|
if (imageEditIconTargets.length === images.length && images.every((img, i) => imageEditIconTargets[i] === img)) return;
|
|
@@ -1027,7 +1083,9 @@ function handleMessage(event) {
|
|
|
1027
1083
|
case "dcs:update-text":
|
|
1028
1084
|
if (data && typeof data === "object" && "key" in data && "value" in data) {
|
|
1029
1085
|
const d = data;
|
|
1030
|
-
|
|
1086
|
+
if (!revertImageOverrideIfImageKey(d.key, d.value)) {
|
|
1087
|
+
updateTextInPlace(d.key, d.value);
|
|
1088
|
+
}
|
|
1031
1089
|
}
|
|
1032
1090
|
break;
|
|
1033
1091
|
case "dcs:set-mode":
|
|
@@ -1066,6 +1124,14 @@ function handleMessage(event) {
|
|
|
1066
1124
|
}
|
|
1067
1125
|
}
|
|
1068
1126
|
break;
|
|
1127
|
+
case "dcs:image-set":
|
|
1128
|
+
if (data && typeof data === "object" && "key" in data && "src" in data) {
|
|
1129
|
+
const d = data;
|
|
1130
|
+
if (typeof d.key === "string" && typeof d.src === "string") {
|
|
1131
|
+
setImageOverride(d.key, d.src, d.alt ?? null);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
break;
|
|
1069
1135
|
case "dcs:update-reviews":
|
|
1070
1136
|
if (data && typeof data === "object" && "key" in data) {
|
|
1071
1137
|
const d = data;
|
|
@@ -1182,6 +1248,6 @@ function initEditorBridge() {
|
|
|
1182
1248
|
observeSectionLayout();
|
|
1183
1249
|
}
|
|
1184
1250
|
|
|
1185
|
-
export { initEditorBridge };
|
|
1251
|
+
export { applyImageOverride, applyPendingImageOverrides, clearPendingImageOverrides, initEditorBridge, recordPendingImageOverride, revertImageOverrideIfImageKey };
|
|
1186
1252
|
//# sourceMappingURL=editorBridge.js.map
|
|
1187
1253
|
//# sourceMappingURL=editorBridge.js.map
|