@cmssy/react 4.4.0 → 4.6.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/index.cjs +241 -197
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +241 -197
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -184,163 +184,6 @@ async function resolveBlocks(blocks, loaderMap, locale, defaultLocale, context,
|
|
|
184
184
|
})
|
|
185
185
|
);
|
|
186
186
|
}
|
|
187
|
-
async function CmssyServerPage({
|
|
188
|
-
page,
|
|
189
|
-
blocks,
|
|
190
|
-
locale = "en",
|
|
191
|
-
defaultLocale = "en",
|
|
192
|
-
enabledLocales,
|
|
193
|
-
forms,
|
|
194
|
-
auth,
|
|
195
|
-
workspace
|
|
196
|
-
}) {
|
|
197
|
-
if (!page) return null;
|
|
198
|
-
const map = buildBlockMap(blocks);
|
|
199
|
-
const loaderMap = buildLoaderMap(blocks);
|
|
200
|
-
const context = buildBlockContext(
|
|
201
|
-
locale,
|
|
202
|
-
defaultLocale,
|
|
203
|
-
enabledLocales,
|
|
204
|
-
false,
|
|
205
|
-
forms,
|
|
206
|
-
{ auth, workspace }
|
|
207
|
-
);
|
|
208
|
-
const resolved = await resolveBlocks(
|
|
209
|
-
page.blocks,
|
|
210
|
-
loaderMap,
|
|
211
|
-
locale,
|
|
212
|
-
defaultLocale,
|
|
213
|
-
context,
|
|
214
|
-
enabledLocales
|
|
215
|
-
);
|
|
216
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: page.blocks.map(
|
|
217
|
-
(block, i) => renderResolvedBlock(block, map, locale, defaultLocale, {
|
|
218
|
-
context,
|
|
219
|
-
data: resolved[i]?.data,
|
|
220
|
-
resolvedContent: resolved[i]?.content,
|
|
221
|
-
enabledLocales
|
|
222
|
-
})
|
|
223
|
-
) });
|
|
224
|
-
}
|
|
225
|
-
async function CmssyServerLayout({
|
|
226
|
-
groups,
|
|
227
|
-
blocks,
|
|
228
|
-
position,
|
|
229
|
-
locale = "en",
|
|
230
|
-
defaultLocale = "en",
|
|
231
|
-
enabledLocales
|
|
232
|
-
}) {
|
|
233
|
-
const group = groups.find((g) => g.position === position);
|
|
234
|
-
const layoutBlocks = group ? group.blocks.filter((b) => b.isActive).slice().sort((a, b) => a.order - b.order) : [];
|
|
235
|
-
if (layoutBlocks.length === 0) return null;
|
|
236
|
-
const map = buildBlockMap(blocks);
|
|
237
|
-
const loaderMap = buildLoaderMap(blocks);
|
|
238
|
-
const context = buildBlockContext(locale, defaultLocale, enabledLocales);
|
|
239
|
-
const resolved = await resolveBlocks(
|
|
240
|
-
layoutBlocks,
|
|
241
|
-
loaderMap,
|
|
242
|
-
locale,
|
|
243
|
-
defaultLocale,
|
|
244
|
-
context,
|
|
245
|
-
enabledLocales
|
|
246
|
-
);
|
|
247
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: layoutBlocks.map(
|
|
248
|
-
(block, i) => renderResolvedBlock(block, map, locale, defaultLocale, {
|
|
249
|
-
context,
|
|
250
|
-
data: resolved[i]?.data,
|
|
251
|
-
resolvedContent: resolved[i]?.content,
|
|
252
|
-
enabledLocales
|
|
253
|
-
})
|
|
254
|
-
) });
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// src/bridge/protocol.ts
|
|
258
|
-
var PROTOCOL_VERSION = 2;
|
|
259
|
-
function isProtocolCompatible(version) {
|
|
260
|
-
return version === PROTOCOL_VERSION;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// src/bridge/messages.ts
|
|
264
|
-
function normalizeOrigin(origin) {
|
|
265
|
-
const trimmed = origin.trim();
|
|
266
|
-
if (trimmed === "*") return "*";
|
|
267
|
-
try {
|
|
268
|
-
return new URL(trimmed).origin;
|
|
269
|
-
} catch {
|
|
270
|
-
return trimmed;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
function postToEditor(target, editorOrigin, message) {
|
|
274
|
-
target.postMessage(message, normalizeOrigin(editorOrigin));
|
|
275
|
-
}
|
|
276
|
-
function isOriginAllowed(origin, allowed) {
|
|
277
|
-
const list = Array.isArray(allowed) ? allowed : [allowed];
|
|
278
|
-
const actual = normalizeOrigin(origin);
|
|
279
|
-
return list.some((candidate) => {
|
|
280
|
-
const expected = normalizeOrigin(candidate);
|
|
281
|
-
return expected === "*" || expected === actual;
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
function isObject(value) {
|
|
285
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
286
|
-
}
|
|
287
|
-
function parseEditorMessage(data, origin, expectedOrigin) {
|
|
288
|
-
if (!isOriginAllowed(origin, expectedOrigin)) return null;
|
|
289
|
-
if (!isObject(data)) return null;
|
|
290
|
-
switch (data.type) {
|
|
291
|
-
case "cmssy:select":
|
|
292
|
-
return typeof data.blockId === "string" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
293
|
-
type: "cmssy:select",
|
|
294
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
295
|
-
blockId: data.blockId
|
|
296
|
-
} : null;
|
|
297
|
-
case "cmssy:patch":
|
|
298
|
-
return typeof data.blockId === "string" && isObject(data.content) && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
299
|
-
type: "cmssy:patch",
|
|
300
|
-
blockId: data.blockId,
|
|
301
|
-
content: data.content,
|
|
302
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
303
|
-
...isObject(data.style) ? { style: data.style } : {},
|
|
304
|
-
...isObject(data.advanced) ? { advanced: data.advanced } : {},
|
|
305
|
-
...typeof data.layoutPosition === "string" ? { layoutPosition: data.layoutPosition } : {}
|
|
306
|
-
} : null;
|
|
307
|
-
case "cmssy:parent-ready":
|
|
308
|
-
return data.protocolVersion === PROTOCOL_VERSION ? { type: "cmssy:parent-ready", protocolVersion: PROTOCOL_VERSION } : null;
|
|
309
|
-
case "cmssy:insert":
|
|
310
|
-
return typeof data.blockId === "string" && typeof data.blockType === "string" && isObject(data.content) && typeof data.index === "number" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
311
|
-
type: "cmssy:insert",
|
|
312
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
313
|
-
blockId: data.blockId,
|
|
314
|
-
blockType: data.blockType,
|
|
315
|
-
content: data.content,
|
|
316
|
-
...isObject(data.style) ? { style: data.style } : {},
|
|
317
|
-
...isObject(data.advanced) ? { advanced: data.advanced } : {},
|
|
318
|
-
index: data.index
|
|
319
|
-
} : null;
|
|
320
|
-
case "cmssy:reorder":
|
|
321
|
-
return Array.isArray(data.blockIds) && data.blockIds.every((id) => typeof id === "string") && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
322
|
-
type: "cmssy:reorder",
|
|
323
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
324
|
-
blockIds: data.blockIds
|
|
325
|
-
} : null;
|
|
326
|
-
case "cmssy:remove":
|
|
327
|
-
return typeof data.blockId === "string" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
328
|
-
type: "cmssy:remove",
|
|
329
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
330
|
-
blockId: data.blockId
|
|
331
|
-
} : null;
|
|
332
|
-
case "cmssy:drag-over":
|
|
333
|
-
return typeof data.y === "number" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
334
|
-
type: "cmssy:drag-over",
|
|
335
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
336
|
-
y: data.y
|
|
337
|
-
} : null;
|
|
338
|
-
case "cmssy:drag-end":
|
|
339
|
-
return data.protocolVersion === PROTOCOL_VERSION ? { type: "cmssy:drag-end", protocolVersion: PROTOCOL_VERSION } : null;
|
|
340
|
-
default:
|
|
341
|
-
return null;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
187
|
|
|
345
188
|
// src/data/http.ts
|
|
346
189
|
var CmssyRequestError = class extends Error {
|
|
@@ -717,6 +560,247 @@ var SUBMIT_FORM_MUTATION = `mutation SubmitForm($formId: ID!, $input: SubmitForm
|
|
|
717
560
|
}
|
|
718
561
|
}`;
|
|
719
562
|
|
|
563
|
+
// src/data/site-locales.ts
|
|
564
|
+
var TTL_MS = 6e4;
|
|
565
|
+
var MAX_ENTRIES = 64;
|
|
566
|
+
var cache = /* @__PURE__ */ new Map();
|
|
567
|
+
async function resolveSiteLocales(config, options) {
|
|
568
|
+
const key = `${resolveApiUrl(config.apiUrl)}::${config.org}::${config.workspaceSlug}`;
|
|
569
|
+
const cached = cache.get(key);
|
|
570
|
+
if (cached && cached.expires > Date.now()) return cached.value;
|
|
571
|
+
cache.delete(key);
|
|
572
|
+
let value;
|
|
573
|
+
try {
|
|
574
|
+
const data = await graphqlRequest(
|
|
575
|
+
config,
|
|
576
|
+
SITE_CONFIG_QUERY,
|
|
577
|
+
{ workspaceSlug: config.workspaceSlug },
|
|
578
|
+
{ ...options, public: true, retry: options?.retry ?? {} },
|
|
579
|
+
"site config"
|
|
580
|
+
);
|
|
581
|
+
const siteConfig = data.public?.siteConfig ?? null;
|
|
582
|
+
const defaultLocale = siteConfig?.defaultLanguage || "en";
|
|
583
|
+
const enabled = siteConfig?.enabledLanguages ?? [];
|
|
584
|
+
value = {
|
|
585
|
+
defaultLocale,
|
|
586
|
+
locales: enabled.length > 0 ? enabled : [defaultLocale]
|
|
587
|
+
};
|
|
588
|
+
} catch {
|
|
589
|
+
value = { defaultLocale: "en", locales: ["en"] };
|
|
590
|
+
}
|
|
591
|
+
if (cache.size >= MAX_ENTRIES) cache.clear();
|
|
592
|
+
cache.set(key, { value, expires: Date.now() + TTL_MS });
|
|
593
|
+
return value;
|
|
594
|
+
}
|
|
595
|
+
function splitLocaleFromPath(path, siteLocales) {
|
|
596
|
+
const first = path?.[0];
|
|
597
|
+
if (first && first !== siteLocales.defaultLocale && siteLocales.locales.includes(first)) {
|
|
598
|
+
return { locale: first, path: path.slice(1) };
|
|
599
|
+
}
|
|
600
|
+
return { locale: siteLocales.defaultLocale, path };
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// src/components/resolve-render-locale.ts
|
|
604
|
+
var warned2 = false;
|
|
605
|
+
async function resolveRenderLocale({
|
|
606
|
+
locale,
|
|
607
|
+
defaultLocale,
|
|
608
|
+
enabledLocales,
|
|
609
|
+
config
|
|
610
|
+
}) {
|
|
611
|
+
if (locale && defaultLocale) return { locale, defaultLocale, enabledLocales };
|
|
612
|
+
if (config) {
|
|
613
|
+
const site = await resolveSiteLocales(config);
|
|
614
|
+
return {
|
|
615
|
+
locale: locale ?? defaultLocale ?? site.defaultLocale,
|
|
616
|
+
defaultLocale: defaultLocale ?? site.defaultLocale,
|
|
617
|
+
enabledLocales: enabledLocales ?? site.locales
|
|
618
|
+
};
|
|
619
|
+
}
|
|
620
|
+
if (process.env.NODE_ENV !== "production" && !warned2) {
|
|
621
|
+
warned2 = true;
|
|
622
|
+
console.warn(
|
|
623
|
+
'[cmssy] Rendering in "en": no locale was passed and no config was given to look the workspace\'s default language up. Pass `locale` (from the route) or `config`, or a workspace whose default language is not English will render its chrome in the wrong one.'
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
return {
|
|
627
|
+
locale: locale ?? defaultLocale ?? "en",
|
|
628
|
+
defaultLocale: defaultLocale ?? "en",
|
|
629
|
+
enabledLocales
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
async function CmssyServerPage({
|
|
633
|
+
page,
|
|
634
|
+
blocks,
|
|
635
|
+
locale: localeProp,
|
|
636
|
+
defaultLocale: defaultLocaleProp,
|
|
637
|
+
enabledLocales: enabledLocalesProp,
|
|
638
|
+
config,
|
|
639
|
+
forms,
|
|
640
|
+
auth,
|
|
641
|
+
workspace
|
|
642
|
+
}) {
|
|
643
|
+
if (!page) return null;
|
|
644
|
+
const { locale, defaultLocale, enabledLocales } = await resolveRenderLocale({
|
|
645
|
+
locale: localeProp,
|
|
646
|
+
defaultLocale: defaultLocaleProp,
|
|
647
|
+
enabledLocales: enabledLocalesProp,
|
|
648
|
+
config
|
|
649
|
+
});
|
|
650
|
+
const map = buildBlockMap(blocks);
|
|
651
|
+
const loaderMap = buildLoaderMap(blocks);
|
|
652
|
+
const context = buildBlockContext(
|
|
653
|
+
locale,
|
|
654
|
+
defaultLocale,
|
|
655
|
+
enabledLocales,
|
|
656
|
+
false,
|
|
657
|
+
forms,
|
|
658
|
+
{ auth, workspace }
|
|
659
|
+
);
|
|
660
|
+
const resolved = await resolveBlocks(
|
|
661
|
+
page.blocks,
|
|
662
|
+
loaderMap,
|
|
663
|
+
locale,
|
|
664
|
+
defaultLocale,
|
|
665
|
+
context,
|
|
666
|
+
enabledLocales
|
|
667
|
+
);
|
|
668
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: page.blocks.map(
|
|
669
|
+
(block, i) => renderResolvedBlock(block, map, locale, defaultLocale, {
|
|
670
|
+
context,
|
|
671
|
+
data: resolved[i]?.data,
|
|
672
|
+
resolvedContent: resolved[i]?.content,
|
|
673
|
+
enabledLocales
|
|
674
|
+
})
|
|
675
|
+
) });
|
|
676
|
+
}
|
|
677
|
+
async function CmssyServerLayout({
|
|
678
|
+
groups,
|
|
679
|
+
blocks,
|
|
680
|
+
position,
|
|
681
|
+
locale: localeProp,
|
|
682
|
+
defaultLocale: defaultLocaleProp,
|
|
683
|
+
enabledLocales: enabledLocalesProp,
|
|
684
|
+
config
|
|
685
|
+
}) {
|
|
686
|
+
const { locale, defaultLocale, enabledLocales } = await resolveRenderLocale({
|
|
687
|
+
locale: localeProp,
|
|
688
|
+
defaultLocale: defaultLocaleProp,
|
|
689
|
+
enabledLocales: enabledLocalesProp,
|
|
690
|
+
config
|
|
691
|
+
});
|
|
692
|
+
const group = groups.find((g) => g.position === position);
|
|
693
|
+
const layoutBlocks = group ? group.blocks.filter((b) => b.isActive).slice().sort((a, b) => a.order - b.order) : [];
|
|
694
|
+
if (layoutBlocks.length === 0) return null;
|
|
695
|
+
const map = buildBlockMap(blocks);
|
|
696
|
+
const loaderMap = buildLoaderMap(blocks);
|
|
697
|
+
const context = buildBlockContext(locale, defaultLocale, enabledLocales);
|
|
698
|
+
const resolved = await resolveBlocks(
|
|
699
|
+
layoutBlocks,
|
|
700
|
+
loaderMap,
|
|
701
|
+
locale,
|
|
702
|
+
defaultLocale,
|
|
703
|
+
context,
|
|
704
|
+
enabledLocales
|
|
705
|
+
);
|
|
706
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: layoutBlocks.map(
|
|
707
|
+
(block, i) => renderResolvedBlock(block, map, locale, defaultLocale, {
|
|
708
|
+
context,
|
|
709
|
+
data: resolved[i]?.data,
|
|
710
|
+
resolvedContent: resolved[i]?.content,
|
|
711
|
+
enabledLocales
|
|
712
|
+
})
|
|
713
|
+
) });
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
// src/bridge/protocol.ts
|
|
717
|
+
var PROTOCOL_VERSION = 2;
|
|
718
|
+
function isProtocolCompatible(version) {
|
|
719
|
+
return version === PROTOCOL_VERSION;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
// src/bridge/messages.ts
|
|
723
|
+
function normalizeOrigin(origin) {
|
|
724
|
+
const trimmed = origin.trim();
|
|
725
|
+
if (trimmed === "*") return "*";
|
|
726
|
+
try {
|
|
727
|
+
return new URL(trimmed).origin;
|
|
728
|
+
} catch {
|
|
729
|
+
return trimmed;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function postToEditor(target, editorOrigin, message) {
|
|
733
|
+
target.postMessage(message, normalizeOrigin(editorOrigin));
|
|
734
|
+
}
|
|
735
|
+
function isOriginAllowed(origin, allowed) {
|
|
736
|
+
const list = Array.isArray(allowed) ? allowed : [allowed];
|
|
737
|
+
const actual = normalizeOrigin(origin);
|
|
738
|
+
return list.some((candidate) => {
|
|
739
|
+
const expected = normalizeOrigin(candidate);
|
|
740
|
+
return expected === "*" || expected === actual;
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
function isObject(value) {
|
|
744
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
745
|
+
}
|
|
746
|
+
function parseEditorMessage(data, origin, expectedOrigin) {
|
|
747
|
+
if (!isOriginAllowed(origin, expectedOrigin)) return null;
|
|
748
|
+
if (!isObject(data)) return null;
|
|
749
|
+
switch (data.type) {
|
|
750
|
+
case "cmssy:select":
|
|
751
|
+
return typeof data.blockId === "string" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
752
|
+
type: "cmssy:select",
|
|
753
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
754
|
+
blockId: data.blockId
|
|
755
|
+
} : null;
|
|
756
|
+
case "cmssy:patch":
|
|
757
|
+
return typeof data.blockId === "string" && isObject(data.content) && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
758
|
+
type: "cmssy:patch",
|
|
759
|
+
blockId: data.blockId,
|
|
760
|
+
content: data.content,
|
|
761
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
762
|
+
...isObject(data.style) ? { style: data.style } : {},
|
|
763
|
+
...isObject(data.advanced) ? { advanced: data.advanced } : {},
|
|
764
|
+
...typeof data.layoutPosition === "string" ? { layoutPosition: data.layoutPosition } : {}
|
|
765
|
+
} : null;
|
|
766
|
+
case "cmssy:parent-ready":
|
|
767
|
+
return data.protocolVersion === PROTOCOL_VERSION ? { type: "cmssy:parent-ready", protocolVersion: PROTOCOL_VERSION } : null;
|
|
768
|
+
case "cmssy:insert":
|
|
769
|
+
return typeof data.blockId === "string" && typeof data.blockType === "string" && isObject(data.content) && typeof data.index === "number" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
770
|
+
type: "cmssy:insert",
|
|
771
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
772
|
+
blockId: data.blockId,
|
|
773
|
+
blockType: data.blockType,
|
|
774
|
+
content: data.content,
|
|
775
|
+
...isObject(data.style) ? { style: data.style } : {},
|
|
776
|
+
...isObject(data.advanced) ? { advanced: data.advanced } : {},
|
|
777
|
+
index: data.index
|
|
778
|
+
} : null;
|
|
779
|
+
case "cmssy:reorder":
|
|
780
|
+
return Array.isArray(data.blockIds) && data.blockIds.every((id) => typeof id === "string") && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
781
|
+
type: "cmssy:reorder",
|
|
782
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
783
|
+
blockIds: data.blockIds
|
|
784
|
+
} : null;
|
|
785
|
+
case "cmssy:remove":
|
|
786
|
+
return typeof data.blockId === "string" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
787
|
+
type: "cmssy:remove",
|
|
788
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
789
|
+
blockId: data.blockId
|
|
790
|
+
} : null;
|
|
791
|
+
case "cmssy:drag-over":
|
|
792
|
+
return typeof data.y === "number" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
793
|
+
type: "cmssy:drag-over",
|
|
794
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
795
|
+
y: data.y
|
|
796
|
+
} : null;
|
|
797
|
+
case "cmssy:drag-end":
|
|
798
|
+
return data.protocolVersion === PROTOCOL_VERSION ? { type: "cmssy:drag-end", protocolVersion: PROTOCOL_VERSION } : null;
|
|
799
|
+
default:
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
720
804
|
// src/data/settings-client.ts
|
|
721
805
|
async function fetchSiteConfig(config, options = {}) {
|
|
722
806
|
const data = await graphqlRequest(
|
|
@@ -824,46 +908,6 @@ async function resolveForms(config, blocks, locale, defaultLocale, options) {
|
|
|
824
908
|
return forms;
|
|
825
909
|
}
|
|
826
910
|
|
|
827
|
-
// src/data/site-locales.ts
|
|
828
|
-
var TTL_MS = 6e4;
|
|
829
|
-
var MAX_ENTRIES = 64;
|
|
830
|
-
var cache = /* @__PURE__ */ new Map();
|
|
831
|
-
async function resolveSiteLocales(config, options) {
|
|
832
|
-
const key = `${resolveApiUrl(config.apiUrl)}::${config.org}::${config.workspaceSlug}`;
|
|
833
|
-
const cached = cache.get(key);
|
|
834
|
-
if (cached && cached.expires > Date.now()) return cached.value;
|
|
835
|
-
cache.delete(key);
|
|
836
|
-
let value;
|
|
837
|
-
try {
|
|
838
|
-
const data = await graphqlRequest(
|
|
839
|
-
config,
|
|
840
|
-
SITE_CONFIG_QUERY,
|
|
841
|
-
{ workspaceSlug: config.workspaceSlug },
|
|
842
|
-
{ ...options, public: true, retry: options?.retry ?? {} },
|
|
843
|
-
"site config"
|
|
844
|
-
);
|
|
845
|
-
const siteConfig = data.public?.siteConfig ?? null;
|
|
846
|
-
const defaultLocale = siteConfig?.defaultLanguage || "en";
|
|
847
|
-
const enabled = siteConfig?.enabledLanguages ?? [];
|
|
848
|
-
value = {
|
|
849
|
-
defaultLocale,
|
|
850
|
-
locales: enabled.length > 0 ? enabled : [defaultLocale]
|
|
851
|
-
};
|
|
852
|
-
} catch {
|
|
853
|
-
value = { defaultLocale: "en", locales: ["en"] };
|
|
854
|
-
}
|
|
855
|
-
if (cache.size >= MAX_ENTRIES) cache.clear();
|
|
856
|
-
cache.set(key, { value, expires: Date.now() + TTL_MS });
|
|
857
|
-
return value;
|
|
858
|
-
}
|
|
859
|
-
function splitLocaleFromPath(path, siteLocales) {
|
|
860
|
-
const first = path?.[0];
|
|
861
|
-
if (first && first !== siteLocales.defaultLocale && siteLocales.locales.includes(first)) {
|
|
862
|
-
return { locale: first, path: path.slice(1) };
|
|
863
|
-
}
|
|
864
|
-
return { locale: siteLocales.defaultLocale, path };
|
|
865
|
-
}
|
|
866
|
-
|
|
867
911
|
// src/data/localize-href.ts
|
|
868
912
|
var PROTOCOL_OR_RELATIVE = /^([a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
869
913
|
function isExternalHref(href) {
|
package/dist/index.d.cts
CHANGED
|
@@ -191,6 +191,11 @@ interface CmssyServerPageProps {
|
|
|
191
191
|
defaultLocale?: string;
|
|
192
192
|
/** All languages enabled on the workspace; exposed to blocks via context.locale.enabled. */
|
|
193
193
|
enabledLocales?: string[];
|
|
194
|
+
/**
|
|
195
|
+
* The workspace, so the languages can be looked up when they are not passed.
|
|
196
|
+
* Without it the SDK has to guess, and its guess is "en".
|
|
197
|
+
*/
|
|
198
|
+
config?: CmssyClientConfig;
|
|
194
199
|
/** Form definitions referenced by page blocks, exposed via context.forms. */
|
|
195
200
|
forms?: Record<string, CmssyFormDefinition>;
|
|
196
201
|
/** Member auth state, exposed via context.auth. Resolved by createCmssyPage. */
|
|
@@ -203,23 +208,29 @@ interface CmssyServerPageProps {
|
|
|
203
208
|
* loader server-side before rendering, so it must be rendered in a server
|
|
204
209
|
* component tree (as `createCmssyPage` does) - not in a client component.
|
|
205
210
|
*/
|
|
206
|
-
declare function CmssyServerPage({ page, blocks, locale, defaultLocale, enabledLocales, forms, auth, workspace, }: CmssyServerPageProps): Promise<react_jsx_runtime.JSX.Element | null>;
|
|
211
|
+
declare function CmssyServerPage({ page, blocks, locale: localeProp, defaultLocale: defaultLocaleProp, enabledLocales: enabledLocalesProp, config, forms, auth, workspace, }: CmssyServerPageProps): Promise<react_jsx_runtime.JSX.Element | null>;
|
|
207
212
|
|
|
208
213
|
interface CmssyServerLayoutProps {
|
|
209
214
|
groups: CmssyLayoutGroup[];
|
|
210
215
|
blocks: BlockDefinition[];
|
|
211
216
|
position: string;
|
|
217
|
+
/** The language to render in. Omit it and the workspace's default is used. */
|
|
212
218
|
locale?: string;
|
|
213
219
|
defaultLocale?: string;
|
|
214
220
|
/** All languages enabled on the workspace; exposed to blocks via context.locale.enabled. */
|
|
215
221
|
enabledLocales?: string[];
|
|
222
|
+
/**
|
|
223
|
+
* The workspace, so the languages can be looked up when they are not passed.
|
|
224
|
+
* Without it the SDK has to guess, and its guess is "en".
|
|
225
|
+
*/
|
|
226
|
+
config?: CmssyClientConfig;
|
|
216
227
|
}
|
|
217
228
|
/**
|
|
218
229
|
* Async React Server Component. Like CmssyServerPage it runs each block's
|
|
219
230
|
* loader server-side before rendering, so a header block can list categories
|
|
220
231
|
* the same way a page block can. Must be rendered in a server component tree.
|
|
221
232
|
*/
|
|
222
|
-
declare function CmssyServerLayout({ groups, blocks, position, locale, defaultLocale, enabledLocales, }: CmssyServerLayoutProps): Promise<react_jsx_runtime.JSX.Element | null>;
|
|
233
|
+
declare function CmssyServerLayout({ groups, blocks, position, locale: localeProp, defaultLocale: defaultLocaleProp, enabledLocales: enabledLocalesProp, config, }: CmssyServerLayoutProps): Promise<react_jsx_runtime.JSX.Element | null>;
|
|
223
234
|
|
|
224
235
|
interface PostTarget {
|
|
225
236
|
postMessage: (message: unknown, targetOrigin: string) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -191,6 +191,11 @@ interface CmssyServerPageProps {
|
|
|
191
191
|
defaultLocale?: string;
|
|
192
192
|
/** All languages enabled on the workspace; exposed to blocks via context.locale.enabled. */
|
|
193
193
|
enabledLocales?: string[];
|
|
194
|
+
/**
|
|
195
|
+
* The workspace, so the languages can be looked up when they are not passed.
|
|
196
|
+
* Without it the SDK has to guess, and its guess is "en".
|
|
197
|
+
*/
|
|
198
|
+
config?: CmssyClientConfig;
|
|
194
199
|
/** Form definitions referenced by page blocks, exposed via context.forms. */
|
|
195
200
|
forms?: Record<string, CmssyFormDefinition>;
|
|
196
201
|
/** Member auth state, exposed via context.auth. Resolved by createCmssyPage. */
|
|
@@ -203,23 +208,29 @@ interface CmssyServerPageProps {
|
|
|
203
208
|
* loader server-side before rendering, so it must be rendered in a server
|
|
204
209
|
* component tree (as `createCmssyPage` does) - not in a client component.
|
|
205
210
|
*/
|
|
206
|
-
declare function CmssyServerPage({ page, blocks, locale, defaultLocale, enabledLocales, forms, auth, workspace, }: CmssyServerPageProps): Promise<react_jsx_runtime.JSX.Element | null>;
|
|
211
|
+
declare function CmssyServerPage({ page, blocks, locale: localeProp, defaultLocale: defaultLocaleProp, enabledLocales: enabledLocalesProp, config, forms, auth, workspace, }: CmssyServerPageProps): Promise<react_jsx_runtime.JSX.Element | null>;
|
|
207
212
|
|
|
208
213
|
interface CmssyServerLayoutProps {
|
|
209
214
|
groups: CmssyLayoutGroup[];
|
|
210
215
|
blocks: BlockDefinition[];
|
|
211
216
|
position: string;
|
|
217
|
+
/** The language to render in. Omit it and the workspace's default is used. */
|
|
212
218
|
locale?: string;
|
|
213
219
|
defaultLocale?: string;
|
|
214
220
|
/** All languages enabled on the workspace; exposed to blocks via context.locale.enabled. */
|
|
215
221
|
enabledLocales?: string[];
|
|
222
|
+
/**
|
|
223
|
+
* The workspace, so the languages can be looked up when they are not passed.
|
|
224
|
+
* Without it the SDK has to guess, and its guess is "en".
|
|
225
|
+
*/
|
|
226
|
+
config?: CmssyClientConfig;
|
|
216
227
|
}
|
|
217
228
|
/**
|
|
218
229
|
* Async React Server Component. Like CmssyServerPage it runs each block's
|
|
219
230
|
* loader server-side before rendering, so a header block can list categories
|
|
220
231
|
* the same way a page block can. Must be rendered in a server component tree.
|
|
221
232
|
*/
|
|
222
|
-
declare function CmssyServerLayout({ groups, blocks, position, locale, defaultLocale, enabledLocales, }: CmssyServerLayoutProps): Promise<react_jsx_runtime.JSX.Element | null>;
|
|
233
|
+
declare function CmssyServerLayout({ groups, blocks, position, locale: localeProp, defaultLocale: defaultLocaleProp, enabledLocales: enabledLocalesProp, config, }: CmssyServerLayoutProps): Promise<react_jsx_runtime.JSX.Element | null>;
|
|
223
234
|
|
|
224
235
|
interface PostTarget {
|
|
225
236
|
postMessage: (message: unknown, targetOrigin: string) => void;
|
package/dist/index.js
CHANGED
|
@@ -182,163 +182,6 @@ async function resolveBlocks(blocks, loaderMap, locale, defaultLocale, context,
|
|
|
182
182
|
})
|
|
183
183
|
);
|
|
184
184
|
}
|
|
185
|
-
async function CmssyServerPage({
|
|
186
|
-
page,
|
|
187
|
-
blocks,
|
|
188
|
-
locale = "en",
|
|
189
|
-
defaultLocale = "en",
|
|
190
|
-
enabledLocales,
|
|
191
|
-
forms,
|
|
192
|
-
auth,
|
|
193
|
-
workspace
|
|
194
|
-
}) {
|
|
195
|
-
if (!page) return null;
|
|
196
|
-
const map = buildBlockMap(blocks);
|
|
197
|
-
const loaderMap = buildLoaderMap(blocks);
|
|
198
|
-
const context = buildBlockContext(
|
|
199
|
-
locale,
|
|
200
|
-
defaultLocale,
|
|
201
|
-
enabledLocales,
|
|
202
|
-
false,
|
|
203
|
-
forms,
|
|
204
|
-
{ auth, workspace }
|
|
205
|
-
);
|
|
206
|
-
const resolved = await resolveBlocks(
|
|
207
|
-
page.blocks,
|
|
208
|
-
loaderMap,
|
|
209
|
-
locale,
|
|
210
|
-
defaultLocale,
|
|
211
|
-
context,
|
|
212
|
-
enabledLocales
|
|
213
|
-
);
|
|
214
|
-
return /* @__PURE__ */ jsx(Fragment, { children: page.blocks.map(
|
|
215
|
-
(block, i) => renderResolvedBlock(block, map, locale, defaultLocale, {
|
|
216
|
-
context,
|
|
217
|
-
data: resolved[i]?.data,
|
|
218
|
-
resolvedContent: resolved[i]?.content,
|
|
219
|
-
enabledLocales
|
|
220
|
-
})
|
|
221
|
-
) });
|
|
222
|
-
}
|
|
223
|
-
async function CmssyServerLayout({
|
|
224
|
-
groups,
|
|
225
|
-
blocks,
|
|
226
|
-
position,
|
|
227
|
-
locale = "en",
|
|
228
|
-
defaultLocale = "en",
|
|
229
|
-
enabledLocales
|
|
230
|
-
}) {
|
|
231
|
-
const group = groups.find((g) => g.position === position);
|
|
232
|
-
const layoutBlocks = group ? group.blocks.filter((b) => b.isActive).slice().sort((a, b) => a.order - b.order) : [];
|
|
233
|
-
if (layoutBlocks.length === 0) return null;
|
|
234
|
-
const map = buildBlockMap(blocks);
|
|
235
|
-
const loaderMap = buildLoaderMap(blocks);
|
|
236
|
-
const context = buildBlockContext(locale, defaultLocale, enabledLocales);
|
|
237
|
-
const resolved = await resolveBlocks(
|
|
238
|
-
layoutBlocks,
|
|
239
|
-
loaderMap,
|
|
240
|
-
locale,
|
|
241
|
-
defaultLocale,
|
|
242
|
-
context,
|
|
243
|
-
enabledLocales
|
|
244
|
-
);
|
|
245
|
-
return /* @__PURE__ */ jsx(Fragment, { children: layoutBlocks.map(
|
|
246
|
-
(block, i) => renderResolvedBlock(block, map, locale, defaultLocale, {
|
|
247
|
-
context,
|
|
248
|
-
data: resolved[i]?.data,
|
|
249
|
-
resolvedContent: resolved[i]?.content,
|
|
250
|
-
enabledLocales
|
|
251
|
-
})
|
|
252
|
-
) });
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// src/bridge/protocol.ts
|
|
256
|
-
var PROTOCOL_VERSION = 2;
|
|
257
|
-
function isProtocolCompatible(version) {
|
|
258
|
-
return version === PROTOCOL_VERSION;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// src/bridge/messages.ts
|
|
262
|
-
function normalizeOrigin(origin) {
|
|
263
|
-
const trimmed = origin.trim();
|
|
264
|
-
if (trimmed === "*") return "*";
|
|
265
|
-
try {
|
|
266
|
-
return new URL(trimmed).origin;
|
|
267
|
-
} catch {
|
|
268
|
-
return trimmed;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
function postToEditor(target, editorOrigin, message) {
|
|
272
|
-
target.postMessage(message, normalizeOrigin(editorOrigin));
|
|
273
|
-
}
|
|
274
|
-
function isOriginAllowed(origin, allowed) {
|
|
275
|
-
const list = Array.isArray(allowed) ? allowed : [allowed];
|
|
276
|
-
const actual = normalizeOrigin(origin);
|
|
277
|
-
return list.some((candidate) => {
|
|
278
|
-
const expected = normalizeOrigin(candidate);
|
|
279
|
-
return expected === "*" || expected === actual;
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
function isObject(value) {
|
|
283
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
284
|
-
}
|
|
285
|
-
function parseEditorMessage(data, origin, expectedOrigin) {
|
|
286
|
-
if (!isOriginAllowed(origin, expectedOrigin)) return null;
|
|
287
|
-
if (!isObject(data)) return null;
|
|
288
|
-
switch (data.type) {
|
|
289
|
-
case "cmssy:select":
|
|
290
|
-
return typeof data.blockId === "string" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
291
|
-
type: "cmssy:select",
|
|
292
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
293
|
-
blockId: data.blockId
|
|
294
|
-
} : null;
|
|
295
|
-
case "cmssy:patch":
|
|
296
|
-
return typeof data.blockId === "string" && isObject(data.content) && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
297
|
-
type: "cmssy:patch",
|
|
298
|
-
blockId: data.blockId,
|
|
299
|
-
content: data.content,
|
|
300
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
301
|
-
...isObject(data.style) ? { style: data.style } : {},
|
|
302
|
-
...isObject(data.advanced) ? { advanced: data.advanced } : {},
|
|
303
|
-
...typeof data.layoutPosition === "string" ? { layoutPosition: data.layoutPosition } : {}
|
|
304
|
-
} : null;
|
|
305
|
-
case "cmssy:parent-ready":
|
|
306
|
-
return data.protocolVersion === PROTOCOL_VERSION ? { type: "cmssy:parent-ready", protocolVersion: PROTOCOL_VERSION } : null;
|
|
307
|
-
case "cmssy:insert":
|
|
308
|
-
return typeof data.blockId === "string" && typeof data.blockType === "string" && isObject(data.content) && typeof data.index === "number" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
309
|
-
type: "cmssy:insert",
|
|
310
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
311
|
-
blockId: data.blockId,
|
|
312
|
-
blockType: data.blockType,
|
|
313
|
-
content: data.content,
|
|
314
|
-
...isObject(data.style) ? { style: data.style } : {},
|
|
315
|
-
...isObject(data.advanced) ? { advanced: data.advanced } : {},
|
|
316
|
-
index: data.index
|
|
317
|
-
} : null;
|
|
318
|
-
case "cmssy:reorder":
|
|
319
|
-
return Array.isArray(data.blockIds) && data.blockIds.every((id) => typeof id === "string") && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
320
|
-
type: "cmssy:reorder",
|
|
321
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
322
|
-
blockIds: data.blockIds
|
|
323
|
-
} : null;
|
|
324
|
-
case "cmssy:remove":
|
|
325
|
-
return typeof data.blockId === "string" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
326
|
-
type: "cmssy:remove",
|
|
327
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
328
|
-
blockId: data.blockId
|
|
329
|
-
} : null;
|
|
330
|
-
case "cmssy:drag-over":
|
|
331
|
-
return typeof data.y === "number" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
332
|
-
type: "cmssy:drag-over",
|
|
333
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
334
|
-
y: data.y
|
|
335
|
-
} : null;
|
|
336
|
-
case "cmssy:drag-end":
|
|
337
|
-
return data.protocolVersion === PROTOCOL_VERSION ? { type: "cmssy:drag-end", protocolVersion: PROTOCOL_VERSION } : null;
|
|
338
|
-
default:
|
|
339
|
-
return null;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
185
|
|
|
343
186
|
// src/data/http.ts
|
|
344
187
|
var CmssyRequestError = class extends Error {
|
|
@@ -715,6 +558,247 @@ var SUBMIT_FORM_MUTATION = `mutation SubmitForm($formId: ID!, $input: SubmitForm
|
|
|
715
558
|
}
|
|
716
559
|
}`;
|
|
717
560
|
|
|
561
|
+
// src/data/site-locales.ts
|
|
562
|
+
var TTL_MS = 6e4;
|
|
563
|
+
var MAX_ENTRIES = 64;
|
|
564
|
+
var cache = /* @__PURE__ */ new Map();
|
|
565
|
+
async function resolveSiteLocales(config, options) {
|
|
566
|
+
const key = `${resolveApiUrl(config.apiUrl)}::${config.org}::${config.workspaceSlug}`;
|
|
567
|
+
const cached = cache.get(key);
|
|
568
|
+
if (cached && cached.expires > Date.now()) return cached.value;
|
|
569
|
+
cache.delete(key);
|
|
570
|
+
let value;
|
|
571
|
+
try {
|
|
572
|
+
const data = await graphqlRequest(
|
|
573
|
+
config,
|
|
574
|
+
SITE_CONFIG_QUERY,
|
|
575
|
+
{ workspaceSlug: config.workspaceSlug },
|
|
576
|
+
{ ...options, public: true, retry: options?.retry ?? {} },
|
|
577
|
+
"site config"
|
|
578
|
+
);
|
|
579
|
+
const siteConfig = data.public?.siteConfig ?? null;
|
|
580
|
+
const defaultLocale = siteConfig?.defaultLanguage || "en";
|
|
581
|
+
const enabled = siteConfig?.enabledLanguages ?? [];
|
|
582
|
+
value = {
|
|
583
|
+
defaultLocale,
|
|
584
|
+
locales: enabled.length > 0 ? enabled : [defaultLocale]
|
|
585
|
+
};
|
|
586
|
+
} catch {
|
|
587
|
+
value = { defaultLocale: "en", locales: ["en"] };
|
|
588
|
+
}
|
|
589
|
+
if (cache.size >= MAX_ENTRIES) cache.clear();
|
|
590
|
+
cache.set(key, { value, expires: Date.now() + TTL_MS });
|
|
591
|
+
return value;
|
|
592
|
+
}
|
|
593
|
+
function splitLocaleFromPath(path, siteLocales) {
|
|
594
|
+
const first = path?.[0];
|
|
595
|
+
if (first && first !== siteLocales.defaultLocale && siteLocales.locales.includes(first)) {
|
|
596
|
+
return { locale: first, path: path.slice(1) };
|
|
597
|
+
}
|
|
598
|
+
return { locale: siteLocales.defaultLocale, path };
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// src/components/resolve-render-locale.ts
|
|
602
|
+
var warned2 = false;
|
|
603
|
+
async function resolveRenderLocale({
|
|
604
|
+
locale,
|
|
605
|
+
defaultLocale,
|
|
606
|
+
enabledLocales,
|
|
607
|
+
config
|
|
608
|
+
}) {
|
|
609
|
+
if (locale && defaultLocale) return { locale, defaultLocale, enabledLocales };
|
|
610
|
+
if (config) {
|
|
611
|
+
const site = await resolveSiteLocales(config);
|
|
612
|
+
return {
|
|
613
|
+
locale: locale ?? defaultLocale ?? site.defaultLocale,
|
|
614
|
+
defaultLocale: defaultLocale ?? site.defaultLocale,
|
|
615
|
+
enabledLocales: enabledLocales ?? site.locales
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
if (process.env.NODE_ENV !== "production" && !warned2) {
|
|
619
|
+
warned2 = true;
|
|
620
|
+
console.warn(
|
|
621
|
+
'[cmssy] Rendering in "en": no locale was passed and no config was given to look the workspace\'s default language up. Pass `locale` (from the route) or `config`, or a workspace whose default language is not English will render its chrome in the wrong one.'
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
return {
|
|
625
|
+
locale: locale ?? defaultLocale ?? "en",
|
|
626
|
+
defaultLocale: defaultLocale ?? "en",
|
|
627
|
+
enabledLocales
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
async function CmssyServerPage({
|
|
631
|
+
page,
|
|
632
|
+
blocks,
|
|
633
|
+
locale: localeProp,
|
|
634
|
+
defaultLocale: defaultLocaleProp,
|
|
635
|
+
enabledLocales: enabledLocalesProp,
|
|
636
|
+
config,
|
|
637
|
+
forms,
|
|
638
|
+
auth,
|
|
639
|
+
workspace
|
|
640
|
+
}) {
|
|
641
|
+
if (!page) return null;
|
|
642
|
+
const { locale, defaultLocale, enabledLocales } = await resolveRenderLocale({
|
|
643
|
+
locale: localeProp,
|
|
644
|
+
defaultLocale: defaultLocaleProp,
|
|
645
|
+
enabledLocales: enabledLocalesProp,
|
|
646
|
+
config
|
|
647
|
+
});
|
|
648
|
+
const map = buildBlockMap(blocks);
|
|
649
|
+
const loaderMap = buildLoaderMap(blocks);
|
|
650
|
+
const context = buildBlockContext(
|
|
651
|
+
locale,
|
|
652
|
+
defaultLocale,
|
|
653
|
+
enabledLocales,
|
|
654
|
+
false,
|
|
655
|
+
forms,
|
|
656
|
+
{ auth, workspace }
|
|
657
|
+
);
|
|
658
|
+
const resolved = await resolveBlocks(
|
|
659
|
+
page.blocks,
|
|
660
|
+
loaderMap,
|
|
661
|
+
locale,
|
|
662
|
+
defaultLocale,
|
|
663
|
+
context,
|
|
664
|
+
enabledLocales
|
|
665
|
+
);
|
|
666
|
+
return /* @__PURE__ */ jsx(Fragment, { children: page.blocks.map(
|
|
667
|
+
(block, i) => renderResolvedBlock(block, map, locale, defaultLocale, {
|
|
668
|
+
context,
|
|
669
|
+
data: resolved[i]?.data,
|
|
670
|
+
resolvedContent: resolved[i]?.content,
|
|
671
|
+
enabledLocales
|
|
672
|
+
})
|
|
673
|
+
) });
|
|
674
|
+
}
|
|
675
|
+
async function CmssyServerLayout({
|
|
676
|
+
groups,
|
|
677
|
+
blocks,
|
|
678
|
+
position,
|
|
679
|
+
locale: localeProp,
|
|
680
|
+
defaultLocale: defaultLocaleProp,
|
|
681
|
+
enabledLocales: enabledLocalesProp,
|
|
682
|
+
config
|
|
683
|
+
}) {
|
|
684
|
+
const { locale, defaultLocale, enabledLocales } = await resolveRenderLocale({
|
|
685
|
+
locale: localeProp,
|
|
686
|
+
defaultLocale: defaultLocaleProp,
|
|
687
|
+
enabledLocales: enabledLocalesProp,
|
|
688
|
+
config
|
|
689
|
+
});
|
|
690
|
+
const group = groups.find((g) => g.position === position);
|
|
691
|
+
const layoutBlocks = group ? group.blocks.filter((b) => b.isActive).slice().sort((a, b) => a.order - b.order) : [];
|
|
692
|
+
if (layoutBlocks.length === 0) return null;
|
|
693
|
+
const map = buildBlockMap(blocks);
|
|
694
|
+
const loaderMap = buildLoaderMap(blocks);
|
|
695
|
+
const context = buildBlockContext(locale, defaultLocale, enabledLocales);
|
|
696
|
+
const resolved = await resolveBlocks(
|
|
697
|
+
layoutBlocks,
|
|
698
|
+
loaderMap,
|
|
699
|
+
locale,
|
|
700
|
+
defaultLocale,
|
|
701
|
+
context,
|
|
702
|
+
enabledLocales
|
|
703
|
+
);
|
|
704
|
+
return /* @__PURE__ */ jsx(Fragment, { children: layoutBlocks.map(
|
|
705
|
+
(block, i) => renderResolvedBlock(block, map, locale, defaultLocale, {
|
|
706
|
+
context,
|
|
707
|
+
data: resolved[i]?.data,
|
|
708
|
+
resolvedContent: resolved[i]?.content,
|
|
709
|
+
enabledLocales
|
|
710
|
+
})
|
|
711
|
+
) });
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// src/bridge/protocol.ts
|
|
715
|
+
var PROTOCOL_VERSION = 2;
|
|
716
|
+
function isProtocolCompatible(version) {
|
|
717
|
+
return version === PROTOCOL_VERSION;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
// src/bridge/messages.ts
|
|
721
|
+
function normalizeOrigin(origin) {
|
|
722
|
+
const trimmed = origin.trim();
|
|
723
|
+
if (trimmed === "*") return "*";
|
|
724
|
+
try {
|
|
725
|
+
return new URL(trimmed).origin;
|
|
726
|
+
} catch {
|
|
727
|
+
return trimmed;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
function postToEditor(target, editorOrigin, message) {
|
|
731
|
+
target.postMessage(message, normalizeOrigin(editorOrigin));
|
|
732
|
+
}
|
|
733
|
+
function isOriginAllowed(origin, allowed) {
|
|
734
|
+
const list = Array.isArray(allowed) ? allowed : [allowed];
|
|
735
|
+
const actual = normalizeOrigin(origin);
|
|
736
|
+
return list.some((candidate) => {
|
|
737
|
+
const expected = normalizeOrigin(candidate);
|
|
738
|
+
return expected === "*" || expected === actual;
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
function isObject(value) {
|
|
742
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
743
|
+
}
|
|
744
|
+
function parseEditorMessage(data, origin, expectedOrigin) {
|
|
745
|
+
if (!isOriginAllowed(origin, expectedOrigin)) return null;
|
|
746
|
+
if (!isObject(data)) return null;
|
|
747
|
+
switch (data.type) {
|
|
748
|
+
case "cmssy:select":
|
|
749
|
+
return typeof data.blockId === "string" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
750
|
+
type: "cmssy:select",
|
|
751
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
752
|
+
blockId: data.blockId
|
|
753
|
+
} : null;
|
|
754
|
+
case "cmssy:patch":
|
|
755
|
+
return typeof data.blockId === "string" && isObject(data.content) && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
756
|
+
type: "cmssy:patch",
|
|
757
|
+
blockId: data.blockId,
|
|
758
|
+
content: data.content,
|
|
759
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
760
|
+
...isObject(data.style) ? { style: data.style } : {},
|
|
761
|
+
...isObject(data.advanced) ? { advanced: data.advanced } : {},
|
|
762
|
+
...typeof data.layoutPosition === "string" ? { layoutPosition: data.layoutPosition } : {}
|
|
763
|
+
} : null;
|
|
764
|
+
case "cmssy:parent-ready":
|
|
765
|
+
return data.protocolVersion === PROTOCOL_VERSION ? { type: "cmssy:parent-ready", protocolVersion: PROTOCOL_VERSION } : null;
|
|
766
|
+
case "cmssy:insert":
|
|
767
|
+
return typeof data.blockId === "string" && typeof data.blockType === "string" && isObject(data.content) && typeof data.index === "number" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
768
|
+
type: "cmssy:insert",
|
|
769
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
770
|
+
blockId: data.blockId,
|
|
771
|
+
blockType: data.blockType,
|
|
772
|
+
content: data.content,
|
|
773
|
+
...isObject(data.style) ? { style: data.style } : {},
|
|
774
|
+
...isObject(data.advanced) ? { advanced: data.advanced } : {},
|
|
775
|
+
index: data.index
|
|
776
|
+
} : null;
|
|
777
|
+
case "cmssy:reorder":
|
|
778
|
+
return Array.isArray(data.blockIds) && data.blockIds.every((id) => typeof id === "string") && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
779
|
+
type: "cmssy:reorder",
|
|
780
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
781
|
+
blockIds: data.blockIds
|
|
782
|
+
} : null;
|
|
783
|
+
case "cmssy:remove":
|
|
784
|
+
return typeof data.blockId === "string" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
785
|
+
type: "cmssy:remove",
|
|
786
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
787
|
+
blockId: data.blockId
|
|
788
|
+
} : null;
|
|
789
|
+
case "cmssy:drag-over":
|
|
790
|
+
return typeof data.y === "number" && data.protocolVersion === PROTOCOL_VERSION ? {
|
|
791
|
+
type: "cmssy:drag-over",
|
|
792
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
793
|
+
y: data.y
|
|
794
|
+
} : null;
|
|
795
|
+
case "cmssy:drag-end":
|
|
796
|
+
return data.protocolVersion === PROTOCOL_VERSION ? { type: "cmssy:drag-end", protocolVersion: PROTOCOL_VERSION } : null;
|
|
797
|
+
default:
|
|
798
|
+
return null;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
718
802
|
// src/data/settings-client.ts
|
|
719
803
|
async function fetchSiteConfig(config, options = {}) {
|
|
720
804
|
const data = await graphqlRequest(
|
|
@@ -822,46 +906,6 @@ async function resolveForms(config, blocks, locale, defaultLocale, options) {
|
|
|
822
906
|
return forms;
|
|
823
907
|
}
|
|
824
908
|
|
|
825
|
-
// src/data/site-locales.ts
|
|
826
|
-
var TTL_MS = 6e4;
|
|
827
|
-
var MAX_ENTRIES = 64;
|
|
828
|
-
var cache = /* @__PURE__ */ new Map();
|
|
829
|
-
async function resolveSiteLocales(config, options) {
|
|
830
|
-
const key = `${resolveApiUrl(config.apiUrl)}::${config.org}::${config.workspaceSlug}`;
|
|
831
|
-
const cached = cache.get(key);
|
|
832
|
-
if (cached && cached.expires > Date.now()) return cached.value;
|
|
833
|
-
cache.delete(key);
|
|
834
|
-
let value;
|
|
835
|
-
try {
|
|
836
|
-
const data = await graphqlRequest(
|
|
837
|
-
config,
|
|
838
|
-
SITE_CONFIG_QUERY,
|
|
839
|
-
{ workspaceSlug: config.workspaceSlug },
|
|
840
|
-
{ ...options, public: true, retry: options?.retry ?? {} },
|
|
841
|
-
"site config"
|
|
842
|
-
);
|
|
843
|
-
const siteConfig = data.public?.siteConfig ?? null;
|
|
844
|
-
const defaultLocale = siteConfig?.defaultLanguage || "en";
|
|
845
|
-
const enabled = siteConfig?.enabledLanguages ?? [];
|
|
846
|
-
value = {
|
|
847
|
-
defaultLocale,
|
|
848
|
-
locales: enabled.length > 0 ? enabled : [defaultLocale]
|
|
849
|
-
};
|
|
850
|
-
} catch {
|
|
851
|
-
value = { defaultLocale: "en", locales: ["en"] };
|
|
852
|
-
}
|
|
853
|
-
if (cache.size >= MAX_ENTRIES) cache.clear();
|
|
854
|
-
cache.set(key, { value, expires: Date.now() + TTL_MS });
|
|
855
|
-
return value;
|
|
856
|
-
}
|
|
857
|
-
function splitLocaleFromPath(path, siteLocales) {
|
|
858
|
-
const first = path?.[0];
|
|
859
|
-
if (first && first !== siteLocales.defaultLocale && siteLocales.locales.includes(first)) {
|
|
860
|
-
return { locale: first, path: path.slice(1) };
|
|
861
|
-
}
|
|
862
|
-
return { locale: siteLocales.defaultLocale, path };
|
|
863
|
-
}
|
|
864
|
-
|
|
865
909
|
// src/data/localize-href.ts
|
|
866
910
|
var PROTOCOL_OR_RELATIVE = /^([a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
867
911
|
function isExternalHref(href) {
|