@duffcloudservices/cms 0.12.0 → 0.13.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/README.md +244 -8
- package/dist/chunk-A5F4C72F.js +500 -0
- package/dist/chunk-A5F4C72F.js.map +1 -0
- package/dist/{chunk-F3EIWEZD.js → chunk-HVSF23P7.js} +971 -73
- package/dist/chunk-HVSF23P7.js.map +1 -0
- package/dist/editor/editorBridge.d.ts +13 -1
- package/dist/editor/editorBridge.js +75 -5
- package/dist/editor/editorBridge.js.map +1 -1
- package/dist/headHonesty-OzxvLuwd.d.ts +222 -0
- package/dist/index.d.ts +365 -22
- package/dist/index.js +421 -21
- package/dist/index.js.map +1 -1
- package/dist/installSeoHead-kWQwObez.d.ts +627 -0
- package/dist/plugins/index.d.ts +90 -6
- package/dist/plugins/index.js +530 -49
- package/dist/plugins/index.js.map +1 -1
- package/dist/seo/index.d.ts +763 -4
- package/dist/seo/index.js +2 -2
- package/dist/{vitepressTransform-DfmABXmK.d.ts → vitepressTransform-JG_zlaux.d.ts} +99 -6
- package/package.json +17 -6
- package/src/components/DcsCallButton.test.ts +58 -0
- package/src/components/DcsCallButton.vue +19 -4
- package/src/components/LiteMediaEmbed.vue +3 -3
- package/src/components/ManagedImage.test.ts +34 -0
- package/src/components/ManagedImage.vue +5 -0
- package/src/components/PreviewRibbon.vue +4 -1
- package/src/composables/useConversionTracking.test.ts +492 -0
- package/src/composables/useConversionTracking.ts +770 -0
- package/src/composables/useReleaseNotes.ts +7 -1
- package/src/composables/useSEO.applyHead.test.ts +150 -0
- package/src/composables/useSEO.ts +63 -17
- package/src/composables/useSiteVersion.ts +4 -1
- package/src/composables/useSiteVisitorSession.test.ts +56 -0
- package/src/composables/useSiteVisitorSession.ts +39 -3
- package/src/composables/useTextContent.ts +9 -1
- package/dist/chunk-DAYLLSEE.js +0 -3
- package/dist/chunk-DAYLLSEE.js.map +0 -1
- package/dist/chunk-F3EIWEZD.js.map +0 -1
- package/dist/spliceHeadHtml-CsBEucGy.d.ts +0 -254
|
@@ -94,8 +94,20 @@ declare function recordPendingImageOverride(key: string, src: string, alt?: stri
|
|
|
94
94
|
* @returns true when the key was handled as an image revert (skip text handling).
|
|
95
95
|
*/
|
|
96
96
|
declare function revertImageOverrideIfImageKey(key: string, value: string): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Handle a `dcs:update-text` that targets a MANAGED IMAGE **ALT** key
|
|
99
|
+
* (`data-dcs-image-alt-key`). The portal stages an alt change alongside the
|
|
100
|
+
* src change on "Replace without AI"; on discard/undo it reverts each staged
|
|
101
|
+
* key via `dcs:update-text`. Alt keys are attributes, not text nodes, so
|
|
102
|
+
* `updateTextInPlace` would be a silent no-op — instead restore the `<img>`
|
|
103
|
+
* alt and refresh any pending image override (keyed by the SRC key) so a
|
|
104
|
+
* re-render replay does not resurrect the discarded alt.
|
|
105
|
+
*
|
|
106
|
+
* @returns true when the key was handled as an image-alt revert.
|
|
107
|
+
*/
|
|
108
|
+
declare function revertImageAltOverrideIfAltKey(key: string, value: string): boolean;
|
|
97
109
|
/** Clear all pending image overrides (test isolation). */
|
|
98
110
|
declare function clearPendingImageOverrides(): void;
|
|
99
111
|
declare function initEditorBridge(): void;
|
|
100
112
|
|
|
101
|
-
export { type EditorReadyPayload, type SectionInfo, applyImageOverride, applyPendingImageOverrides, clearPendingImageOverrides, initEditorBridge, recordPendingImageOverride, revertImageOverrideIfImageKey };
|
|
113
|
+
export { type EditorReadyPayload, type SectionInfo, applyImageOverride, applyPendingImageOverrides, clearPendingImageOverrides, initEditorBridge, recordPendingImageOverride, revertImageAltOverrideIfAltKey, revertImageOverrideIfImageKey };
|
|
@@ -218,6 +218,7 @@ function applyEditorToElements() {
|
|
|
218
218
|
htmlEl.addEventListener("dblclick", handleTextKeyDblClick);
|
|
219
219
|
htmlEl.addEventListener("blur", handleTextKeyBlur);
|
|
220
220
|
htmlEl.addEventListener("keydown", handleTextKeyKeydown);
|
|
221
|
+
htmlEl.addEventListener("paste", handleTextKeyPaste);
|
|
221
222
|
htmlEl.addEventListener("mouseenter", () => {
|
|
222
223
|
if (activeEditElement) return;
|
|
223
224
|
const key = getTextKey(htmlEl);
|
|
@@ -388,12 +389,21 @@ function handleTextKeyDblClick(e) {
|
|
|
388
389
|
postToParent("dcs:text-key-dblclick", { key, sectionId });
|
|
389
390
|
startInlineEdit(el, key, sectionId);
|
|
390
391
|
}
|
|
392
|
+
function supportsPlaintextOnly() {
|
|
393
|
+
try {
|
|
394
|
+
const probe = document.createElement("div");
|
|
395
|
+
probe.contentEditable = "plaintext-only";
|
|
396
|
+
return probe.getAttribute("contenteditable") === "plaintext-only";
|
|
397
|
+
} catch {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
391
401
|
function startInlineEdit(el, key, sectionId) {
|
|
392
402
|
if (activeEditElement && activeEditElement !== el) {
|
|
393
403
|
finishEdit(activeEditElement);
|
|
394
404
|
}
|
|
395
405
|
originalTextValues.set(el, el.innerText.trim());
|
|
396
|
-
el.setAttribute("contenteditable", "true");
|
|
406
|
+
el.setAttribute("contenteditable", supportsPlaintextOnly() ? "plaintext-only" : "true");
|
|
397
407
|
el.classList.add("dcs-editing");
|
|
398
408
|
el.focus();
|
|
399
409
|
activeEditElement = el;
|
|
@@ -415,8 +425,43 @@ function handleTextKeyKeydown(e) {
|
|
|
415
425
|
}
|
|
416
426
|
if (e.key === "Escape") {
|
|
417
427
|
e.preventDefault();
|
|
418
|
-
e.currentTarget
|
|
428
|
+
cancelInlineEdit(e.currentTarget);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
function handleTextKeyPaste(e) {
|
|
432
|
+
const el = e.currentTarget;
|
|
433
|
+
if (el !== activeEditElement) return;
|
|
434
|
+
if (el.getAttribute("contenteditable") === "plaintext-only") return;
|
|
435
|
+
const text = e.clipboardData?.getData("text/plain") ?? "";
|
|
436
|
+
e.preventDefault();
|
|
437
|
+
insertPlainTextAtCaret(el, text);
|
|
438
|
+
}
|
|
439
|
+
function insertPlainTextAtCaret(el, text) {
|
|
440
|
+
const selection = getSelection();
|
|
441
|
+
if (!selection || selection.rangeCount === 0) {
|
|
442
|
+
el.appendChild(document.createTextNode(text));
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const range = selection.getRangeAt(0);
|
|
446
|
+
if (!el.contains(range.commonAncestorContainer)) return;
|
|
447
|
+
range.deleteContents();
|
|
448
|
+
if (text) {
|
|
449
|
+
const node = document.createTextNode(text);
|
|
450
|
+
range.insertNode(node);
|
|
451
|
+
range.setStartAfter(node);
|
|
419
452
|
}
|
|
453
|
+
range.collapse(true);
|
|
454
|
+
selection.removeAllRanges();
|
|
455
|
+
selection.addRange(range);
|
|
456
|
+
}
|
|
457
|
+
function cancelInlineEdit(el) {
|
|
458
|
+
if (!el.hasAttribute("contenteditable")) return;
|
|
459
|
+
const original = originalTextValues.get(el);
|
|
460
|
+
if (original !== void 0) {
|
|
461
|
+
el.innerText = original;
|
|
462
|
+
}
|
|
463
|
+
el.blur();
|
|
464
|
+
finishEdit(el);
|
|
420
465
|
}
|
|
421
466
|
function finishEdit(el) {
|
|
422
467
|
if (!el.hasAttribute("contenteditable")) return;
|
|
@@ -664,6 +709,9 @@ function createImageEditIcon(label) {
|
|
|
664
709
|
function getManagedImageKey(img) {
|
|
665
710
|
return img.dataset.dcsImageKey || img.closest("[data-dcs-image-key]")?.dataset.dcsImageKey || null;
|
|
666
711
|
}
|
|
712
|
+
function getManagedImageAltKey(img) {
|
|
713
|
+
return img.dataset.dcsImageAltKey || img.closest("[data-dcs-image-alt-key]")?.dataset.dcsImageAltKey || null;
|
|
714
|
+
}
|
|
667
715
|
var pendingImageOverrides = /* @__PURE__ */ new Map();
|
|
668
716
|
function cssEscapeAttributeValue(value) {
|
|
669
717
|
const cssGlobal = globalThis.CSS;
|
|
@@ -716,6 +764,25 @@ function revertImageOverrideIfImageKey(key, value) {
|
|
|
716
764
|
if (value) applyImageOverride(key, value);
|
|
717
765
|
return true;
|
|
718
766
|
}
|
|
767
|
+
function revertImageAltOverrideIfAltKey(key, value) {
|
|
768
|
+
if (!key) return false;
|
|
769
|
+
const escapedKey = cssEscapeAttributeValue(key);
|
|
770
|
+
const hosts = document.querySelectorAll(`[data-dcs-image-alt-key="${escapedKey}"]`);
|
|
771
|
+
if (hosts.length === 0) return false;
|
|
772
|
+
hosts.forEach((host) => {
|
|
773
|
+
const imgs = host instanceof HTMLImageElement ? [host] : Array.from(host.querySelectorAll("img"));
|
|
774
|
+
imgs.forEach((img) => {
|
|
775
|
+
img.alt = value;
|
|
776
|
+
img.dataset.dcsImageAlt = value;
|
|
777
|
+
});
|
|
778
|
+
const srcKey = host.dataset.dcsImageKey || host.closest("[data-dcs-image-key]")?.dataset.dcsImageKey;
|
|
779
|
+
if (srcKey) {
|
|
780
|
+
const pending = pendingImageOverrides.get(srcKey);
|
|
781
|
+
if (pending) pendingImageOverrides.set(srcKey, { ...pending, alt: value });
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
return true;
|
|
785
|
+
}
|
|
719
786
|
function clearPendingImageOverrides() {
|
|
720
787
|
pendingImageOverrides.clear();
|
|
721
788
|
}
|
|
@@ -745,6 +812,7 @@ function showImageEditIcons(images) {
|
|
|
745
812
|
imageWidth: img.naturalWidth,
|
|
746
813
|
imageHeight: img.naturalHeight,
|
|
747
814
|
imageKey: getManagedImageKey(img),
|
|
815
|
+
imageAltKey: getManagedImageAltKey(img),
|
|
748
816
|
sectionId: sectionEl?.dataset.section ?? null,
|
|
749
817
|
sectionLabel: sectionEl?.dataset.sectionLabel ?? null
|
|
750
818
|
});
|
|
@@ -1083,7 +1151,7 @@ function handleMessage(event) {
|
|
|
1083
1151
|
case "dcs:update-text":
|
|
1084
1152
|
if (data && typeof data === "object" && "key" in data && "value" in data) {
|
|
1085
1153
|
const d = data;
|
|
1086
|
-
if (!revertImageOverrideIfImageKey(d.key, d.value)) {
|
|
1154
|
+
if (!revertImageOverrideIfImageKey(d.key, d.value) && !revertImageAltOverrideIfAltKey(d.key, d.value)) {
|
|
1087
1155
|
updateTextInPlace(d.key, d.value);
|
|
1088
1156
|
}
|
|
1089
1157
|
}
|
|
@@ -1201,13 +1269,15 @@ function initEditorBridge() {
|
|
|
1201
1269
|
imageWidth: topImage?.naturalWidth ?? null,
|
|
1202
1270
|
imageHeight: topImage?.naturalHeight ?? null,
|
|
1203
1271
|
imageKey: topImage ? getManagedImageKey(topImage) : null,
|
|
1272
|
+
imageAltKey: topImage ? getManagedImageAltKey(topImage) : null,
|
|
1204
1273
|
// All images at click point (for overlapping image scenarios like before/after sliders)
|
|
1205
1274
|
images: allImages.length > 1 ? allImages.map((img) => ({
|
|
1206
1275
|
imageUrl: img.currentSrc ?? img.src,
|
|
1207
1276
|
imageAlt: img.alt ?? null,
|
|
1208
1277
|
imageWidth: img.naturalWidth,
|
|
1209
1278
|
imageHeight: img.naturalHeight,
|
|
1210
|
-
imageKey: getManagedImageKey(img)
|
|
1279
|
+
imageKey: getManagedImageKey(img),
|
|
1280
|
+
imageAltKey: getManagedImageAltKey(img)
|
|
1211
1281
|
})) : null
|
|
1212
1282
|
});
|
|
1213
1283
|
}, true);
|
|
@@ -1248,6 +1318,6 @@ function initEditorBridge() {
|
|
|
1248
1318
|
observeSectionLayout();
|
|
1249
1319
|
}
|
|
1250
1320
|
|
|
1251
|
-
export { applyImageOverride, applyPendingImageOverrides, clearPendingImageOverrides, initEditorBridge, recordPendingImageOverride, revertImageOverrideIfImageKey };
|
|
1321
|
+
export { applyImageOverride, applyPendingImageOverrides, clearPendingImageOverrides, initEditorBridge, recordPendingImageOverride, revertImageAltOverrideIfAltKey, revertImageOverrideIfImageKey };
|
|
1252
1322
|
//# sourceMappingURL=editorBridge.js.map
|
|
1253
1323
|
//# sourceMappingURL=editorBridge.js.map
|