cms-renderer 0.6.11 → 0.6.13
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/lib/block-renderer.d.ts +16 -12
- package/dist/lib/block-renderer.js +107 -8
- package/dist/lib/block-renderer.js.map +1 -1
- package/dist/lib/block-toolbar.js +18 -4
- package/dist/lib/block-toolbar.js.map +1 -1
- package/dist/lib/client-editable-block.js +19 -5
- package/dist/lib/client-editable-block.js.map +1 -1
- package/dist/lib/custom-schemas.js.map +1 -1
- package/dist/lib/docs-markdown.d.ts +2 -2
- package/dist/lib/markdown-utils.js +19 -2
- package/dist/lib/markdown-utils.js.map +1 -1
- package/dist/lib/parametric-route.d.ts +15 -2
- package/dist/lib/parametric-route.js +137 -13
- package/dist/lib/parametric-route.js.map +1 -1
- package/dist/lib/renderer.d.ts +12 -3
- package/dist/lib/renderer.js +148 -13
- package/dist/lib/renderer.js.map +1 -1
- package/package.json +6 -5
package/dist/lib/renderer.js
CHANGED
|
@@ -466,11 +466,14 @@ function generateCmsOverlayScript(cmsParentOrigin) {
|
|
|
466
466
|
var style = document.createElement('style');
|
|
467
467
|
style.setAttribute('data-cms-overlay', '');
|
|
468
468
|
style.textContent = \`
|
|
469
|
+
[data-cms-block],
|
|
469
470
|
[data-cms-editable] {
|
|
470
471
|
cursor: pointer;
|
|
472
|
+
}
|
|
473
|
+
[data-cms-editable] {
|
|
471
474
|
border-radius: 2px;
|
|
472
475
|
}
|
|
473
|
-
[data-cms-editable]:hover {
|
|
476
|
+
[data-cms-editable]:not([data-cms-block]):hover {
|
|
474
477
|
outline: 2px solid #3b82f6;
|
|
475
478
|
outline-offset: 2px;
|
|
476
479
|
}
|
|
@@ -483,8 +486,8 @@ function generateCmsOverlayScript(cmsParentOrigin) {
|
|
|
483
486
|
pointer-events: none;
|
|
484
487
|
z-index: 99998;
|
|
485
488
|
}
|
|
486
|
-
#cms-overlay-root >
|
|
487
|
-
pointer-events:
|
|
489
|
+
#cms-overlay-root > *:not(.cms-block-toolbar) {
|
|
490
|
+
pointer-events: none;
|
|
488
491
|
}
|
|
489
492
|
.cms-block-outline {
|
|
490
493
|
position: fixed;
|
|
@@ -580,10 +583,69 @@ function generateCmsOverlayScript(cmsParentOrigin) {
|
|
|
580
583
|
blockEl.setAttribute('data-cms-block', '');
|
|
581
584
|
blockEl.setAttribute('data-block-id', blockId);
|
|
582
585
|
blockEl.setAttribute('data-block-type', blockType);
|
|
583
|
-
|
|
586
|
+
|
|
587
|
+
injectEditableSpans(
|
|
588
|
+
blockEl,
|
|
589
|
+
blockId,
|
|
590
|
+
blockType,
|
|
591
|
+
sentinel.getAttribute('data-content-entries')
|
|
592
|
+
);
|
|
584
593
|
});
|
|
585
594
|
}
|
|
586
595
|
|
|
596
|
+
function injectEditableSpans(blockEl, blockId, blockType, rawEntries) {
|
|
597
|
+
if (!rawEntries || blockEl.querySelector('[data-cms-editable][data-content-path]')) return;
|
|
598
|
+
|
|
599
|
+
var entries;
|
|
600
|
+
try {
|
|
601
|
+
entries = JSON.parse(rawEntries);
|
|
602
|
+
} catch (_) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
if (!Array.isArray(entries) || entries.length === 0) return;
|
|
606
|
+
|
|
607
|
+
var used = {};
|
|
608
|
+
var walker = document.createTreeWalker(blockEl, NodeFilter.SHOW_TEXT, null);
|
|
609
|
+
var textNodes = [];
|
|
610
|
+
var node = walker.nextNode();
|
|
611
|
+
while (node !== null) {
|
|
612
|
+
if (node.nodeValue && node.nodeValue.trim()) {
|
|
613
|
+
textNodes.push(node);
|
|
614
|
+
}
|
|
615
|
+
node = walker.nextNode();
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
for (var i = 0; i < textNodes.length; i++) {
|
|
619
|
+
var textNode = textNodes[i];
|
|
620
|
+
var parentEl = textNode.parentElement;
|
|
621
|
+
if (!parentEl || parentEl.closest('svg') || parentEl.closest('[data-cms-editable]')) {
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
var text = textNode.nodeValue;
|
|
626
|
+
if (!text) continue;
|
|
627
|
+
|
|
628
|
+
for (var j = 0; j < entries.length; j++) {
|
|
629
|
+
var entry = entries[j];
|
|
630
|
+
if (!entry || typeof entry.v !== 'string' || typeof entry.p !== 'string' || used[entry.p]) {
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
if (text.trim() !== entry.v.trim()) continue;
|
|
634
|
+
|
|
635
|
+
used[entry.p] = true;
|
|
636
|
+
var span = document.createElement('span');
|
|
637
|
+
span.setAttribute('data-cms-editable', '');
|
|
638
|
+
span.setAttribute('data-block-id', blockId);
|
|
639
|
+
span.setAttribute('data-block-type', blockType);
|
|
640
|
+
span.setAttribute('data-content-path', entry.p);
|
|
641
|
+
span.setAttribute('contenteditable', 'true');
|
|
642
|
+
parentEl.insertBefore(span, textNode);
|
|
643
|
+
span.appendChild(textNode);
|
|
644
|
+
break;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
587
649
|
stampBlockElements();
|
|
588
650
|
|
|
589
651
|
var stampObserver = new MutationObserver(function(mutations) {
|
|
@@ -638,6 +700,38 @@ function generateCmsOverlayScript(cmsParentOrigin) {
|
|
|
638
700
|
var toolbarVisible = false;
|
|
639
701
|
var selectedBlockId = null;
|
|
640
702
|
|
|
703
|
+
function decoratePreviewUrl(rawHref) {
|
|
704
|
+
if (!rawHref) return rawHref;
|
|
705
|
+
try {
|
|
706
|
+
var url = new URL(rawHref, window.location.href);
|
|
707
|
+
if (url.origin !== window.location.origin) return rawHref;
|
|
708
|
+
url.searchParams.set('edit_mode', 'true');
|
|
709
|
+
if (CMS_PARENT_ORIGIN) {
|
|
710
|
+
url.searchParams.set('cms_parent_origin', CMS_PARENT_ORIGIN);
|
|
711
|
+
}
|
|
712
|
+
return url.toString();
|
|
713
|
+
} catch (_) {
|
|
714
|
+
return rawHref;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
function preserveEditParamsOnNavigation(e) {
|
|
719
|
+
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
var anchor = e.target.closest('a[href]');
|
|
724
|
+
if (!anchor || (anchor.target && anchor.target !== '_self') || anchor.hasAttribute('download')) {
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
var href = anchor.getAttribute('href');
|
|
729
|
+
var decorated = decoratePreviewUrl(href);
|
|
730
|
+
if (decorated && decorated !== href) {
|
|
731
|
+
anchor.setAttribute('href', decorated);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
641
735
|
function postToParent(message) {
|
|
642
736
|
if (!CMS_PARENT_ORIGIN || !window.parent || window.parent === window) {
|
|
643
737
|
return;
|
|
@@ -756,6 +850,8 @@ function generateCmsOverlayScript(cmsParentOrigin) {
|
|
|
756
850
|
});
|
|
757
851
|
|
|
758
852
|
document.addEventListener('click', function(e) {
|
|
853
|
+
preserveEditParamsOnNavigation(e);
|
|
854
|
+
|
|
759
855
|
if (toolbarVisible && !e.target.closest('[data-cms-toolbar]')) {
|
|
760
856
|
var block = e.target.closest('[data-cms-block]');
|
|
761
857
|
if (!block || block.getAttribute('data-block-id') !== currentBlockId) {
|
|
@@ -785,23 +881,23 @@ function generateCmsOverlayScript(cmsParentOrigin) {
|
|
|
785
881
|
contentPath: null
|
|
786
882
|
});
|
|
787
883
|
}
|
|
788
|
-
});
|
|
884
|
+
}, true);
|
|
789
885
|
|
|
790
886
|
toolbar.querySelector('.move-up').addEventListener('click', function() {
|
|
791
887
|
if (!currentBlockId) return;
|
|
792
|
-
postToParent({ type: 'cms-block-
|
|
888
|
+
postToParent({ type: 'cms-block-action', action: 'move-up', blockId: currentBlockId });
|
|
793
889
|
hideToolbar();
|
|
794
890
|
});
|
|
795
891
|
|
|
796
892
|
toolbar.querySelector('.move-down').addEventListener('click', function() {
|
|
797
893
|
if (!currentBlockId) return;
|
|
798
|
-
postToParent({ type: 'cms-block-
|
|
894
|
+
postToParent({ type: 'cms-block-action', action: 'move-down', blockId: currentBlockId });
|
|
799
895
|
hideToolbar();
|
|
800
896
|
});
|
|
801
897
|
|
|
802
898
|
toolbar.querySelector('.delete').addEventListener('click', function() {
|
|
803
899
|
if (!currentBlockId) return;
|
|
804
|
-
postToParent({ type: 'cms-block-delete', blockId: currentBlockId });
|
|
900
|
+
postToParent({ type: 'cms-block-action', action: 'delete', blockId: currentBlockId });
|
|
805
901
|
hideToolbar();
|
|
806
902
|
});
|
|
807
903
|
|
|
@@ -895,6 +991,27 @@ function getCmsParentTargetOrigin(preferredCmsUrl, explicitParentOrigin) {
|
|
|
895
991
|
|
|
896
992
|
// lib/block-renderer.tsx
|
|
897
993
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
994
|
+
function extractContentValues(content, basePath = []) {
|
|
995
|
+
const map = /* @__PURE__ */ new Map();
|
|
996
|
+
function walk(obj, path) {
|
|
997
|
+
if (typeof obj === "string" && obj.trim() !== "") {
|
|
998
|
+
const contentPath = path.join(".");
|
|
999
|
+
const existing = map.get(obj) || [];
|
|
1000
|
+
existing.push({ contentPath, value: obj });
|
|
1001
|
+
map.set(obj, existing);
|
|
1002
|
+
} else if (Array.isArray(obj)) {
|
|
1003
|
+
for (let index = 0; index < obj.length; index++) {
|
|
1004
|
+
walk(obj[index], [...path, String(index)]);
|
|
1005
|
+
}
|
|
1006
|
+
} else if (obj && typeof obj === "object") {
|
|
1007
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
1008
|
+
walk(value, [...path, key]);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
walk(content, basePath);
|
|
1013
|
+
return map;
|
|
1014
|
+
}
|
|
898
1015
|
function CmsEditableInit({
|
|
899
1016
|
cmsUrl,
|
|
900
1017
|
cmsParentOrigin
|
|
@@ -943,6 +1060,7 @@ function BlockRenderer({
|
|
|
943
1060
|
block,
|
|
944
1061
|
registry,
|
|
945
1062
|
disableEditable,
|
|
1063
|
+
enableContentEditable,
|
|
946
1064
|
routeParams,
|
|
947
1065
|
path
|
|
948
1066
|
}) {
|
|
@@ -958,6 +1076,7 @@ function BlockRenderer({
|
|
|
958
1076
|
if (disableEditable) {
|
|
959
1077
|
return component;
|
|
960
1078
|
}
|
|
1079
|
+
const contentEntries = enableContentEditable ? [...extractContentValues(block.content).values()].flat().map(({ value, contentPath }) => ({ v: value, p: contentPath })) : void 0;
|
|
961
1080
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
962
1081
|
/* @__PURE__ */ jsx(
|
|
963
1082
|
"span",
|
|
@@ -965,6 +1084,7 @@ function BlockRenderer({
|
|
|
965
1084
|
"data-cms-sentinel": "",
|
|
966
1085
|
"data-block-id": block.id,
|
|
967
1086
|
"data-block-type": block.type,
|
|
1087
|
+
"data-content-entries": contentEntries ? JSON.stringify(contentEntries) : void 0,
|
|
968
1088
|
style: { display: "none" },
|
|
969
1089
|
"aria-hidden": "true"
|
|
970
1090
|
}
|
|
@@ -998,7 +1118,7 @@ async function renderParametricRoute({
|
|
|
998
1118
|
apiKey,
|
|
999
1119
|
cmsUrl,
|
|
1000
1120
|
websiteId: providedWebsiteId
|
|
1001
|
-
}) {
|
|
1121
|
+
}, { preview = false } = {}) {
|
|
1002
1122
|
const websiteId = getWebsiteId(providedWebsiteId);
|
|
1003
1123
|
const { slug } = "then" in params ? await params : params;
|
|
1004
1124
|
const resolvedSearchParams = searchParams && "then" in searchParams ? await searchParams : searchParams;
|
|
@@ -1013,10 +1133,11 @@ async function renderParametricRoute({
|
|
|
1013
1133
|
}
|
|
1014
1134
|
}
|
|
1015
1135
|
}
|
|
1016
|
-
const editModeParam = resolvedSearchParams?.edit_mode;
|
|
1017
|
-
const editMode = editModeParam === true || editModeParam === "true" || editModeParam === "1";
|
|
1018
1136
|
const cmsParentOriginParam = resolvedSearchParams?.cms_parent_origin;
|
|
1019
1137
|
const cmsParentOrigin = typeof cmsParentOriginParam === "boolean" ? void 0 : Array.isArray(cmsParentOriginParam) ? cmsParentOriginParam[0] : cmsParentOriginParam;
|
|
1138
|
+
const previewMode = preview === true;
|
|
1139
|
+
const editModeParam = resolvedSearchParams?.edit_mode;
|
|
1140
|
+
const editMode = previewMode || editModeParam === true || editModeParam === "true" || editModeParam === "1";
|
|
1020
1141
|
const rawPath = `/${slug.join("/")}`;
|
|
1021
1142
|
const path = normalizePath(rawPath);
|
|
1022
1143
|
if (/\.[a-zA-Z0-9]+$/.test(path)) {
|
|
@@ -1056,7 +1177,9 @@ async function renderParametricRoute({
|
|
|
1056
1177
|
]);
|
|
1057
1178
|
const blocks = [];
|
|
1058
1179
|
for (const block of blockResults) {
|
|
1059
|
-
if (!block
|
|
1180
|
+
if (!block) continue;
|
|
1181
|
+
const blockContent = previewMode ? block.draft_content : block.published_content;
|
|
1182
|
+
if (blockContent == null) continue;
|
|
1060
1183
|
let content = null;
|
|
1061
1184
|
if (aiPreviewIndex !== null) {
|
|
1062
1185
|
const generatedBlock = generatedBlocks[block.id];
|
|
@@ -1066,7 +1189,7 @@ async function renderParametricRoute({
|
|
|
1066
1189
|
content = variants[variantIndex].content;
|
|
1067
1190
|
}
|
|
1068
1191
|
}
|
|
1069
|
-
content = content ??
|
|
1192
|
+
content = content ?? blockContent;
|
|
1070
1193
|
if (!content) continue;
|
|
1071
1194
|
if (block.schema_name === "article") {
|
|
1072
1195
|
const article = normalizeArticleContent(content);
|
|
@@ -1114,6 +1237,7 @@ async function renderParametricRoute({
|
|
|
1114
1237
|
block,
|
|
1115
1238
|
registry: registry ?? {},
|
|
1116
1239
|
disableEditable: !editMode,
|
|
1240
|
+
enableContentEditable: previewMode,
|
|
1117
1241
|
routeParams,
|
|
1118
1242
|
path
|
|
1119
1243
|
},
|
|
@@ -1142,6 +1266,16 @@ async function ParametricRoutePage(props) {
|
|
|
1142
1266
|
}
|
|
1143
1267
|
return result.node;
|
|
1144
1268
|
}
|
|
1269
|
+
async function ParametricRoutePreviewPage(props) {
|
|
1270
|
+
const result = await renderParametricRoute(props, { preview: true });
|
|
1271
|
+
if (result.status === "not_found") {
|
|
1272
|
+
notFound();
|
|
1273
|
+
}
|
|
1274
|
+
if (result.status === "error") {
|
|
1275
|
+
throw result.error;
|
|
1276
|
+
}
|
|
1277
|
+
return result.node;
|
|
1278
|
+
}
|
|
1145
1279
|
async function generateMetadata({
|
|
1146
1280
|
params,
|
|
1147
1281
|
apiKey,
|
|
@@ -1168,6 +1302,7 @@ async function generateMetadata({
|
|
|
1168
1302
|
}
|
|
1169
1303
|
}
|
|
1170
1304
|
export {
|
|
1305
|
+
ParametricRoutePreviewPage,
|
|
1171
1306
|
ParametricRoutePage as default,
|
|
1172
1307
|
generateMetadata
|
|
1173
1308
|
};
|