@cloudcannon/editable-regions 0.0.15 → 0.0.16
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/integrations/astro/react-renderer.mjs +18 -3
- package/integrations/astro/svelte-renderer.mjs +65 -0
- package/integrations/svelte.mjs +40 -0
- package/nodes/editable-source.ts +6 -0
- package/package.json +16 -8
- package/types/astro.d.ts +4 -0
- package/types/modules.d.ts +8 -0
- package/types/svelte.d.ts +3 -0
|
@@ -10,10 +10,25 @@ addFrameworkRenderer({
|
|
|
10
10
|
clientEntrypoint: "@astrojs/react/client.js",
|
|
11
11
|
ssr: {
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
* @returns {boolean}
|
|
13
|
+
* @param {any} Component
|
|
14
|
+
* @returns {boolean}
|
|
15
15
|
*/
|
|
16
|
-
check: () =>
|
|
16
|
+
check: (Component) => {
|
|
17
|
+
if (typeof Component !== "function") return false;
|
|
18
|
+
|
|
19
|
+
// React class components have render on the prototype
|
|
20
|
+
if (typeof Component.prototype?.render === "function") return true;
|
|
21
|
+
|
|
22
|
+
// React functional components return vnodes with $$typeof
|
|
23
|
+
try {
|
|
24
|
+
const vnode = Component({});
|
|
25
|
+
return (
|
|
26
|
+
vnode != null && typeof vnode === "object" && "$$typeof" in vnode
|
|
27
|
+
);
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
},
|
|
17
32
|
/**
|
|
18
33
|
* Renders a React component to static markup or queues for client-side rendering.
|
|
19
34
|
* @param {any} Component - The React component function
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { addFrameworkRenderer, queueForClientSideRender } from "./index.mjs";
|
|
2
|
+
|
|
3
|
+
/** @type{((component: any, args: { target: HTMLElement, props: unknown }) => void) | undefined} */
|
|
4
|
+
let mount;
|
|
5
|
+
/** @type{() => void} */
|
|
6
|
+
let flushSync;
|
|
7
|
+
try {
|
|
8
|
+
({ mount, flushSync } = await import("svelte"));
|
|
9
|
+
} catch {
|
|
10
|
+
// Svelte 4 — no mount export
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
addFrameworkRenderer({
|
|
14
|
+
name: "@astrojs/svelte",
|
|
15
|
+
clientEntrypoint: "@astrojs/svelte/client.js",
|
|
16
|
+
ssr: {
|
|
17
|
+
/**
|
|
18
|
+
* @param {any} Component
|
|
19
|
+
* @returns {boolean}
|
|
20
|
+
*/
|
|
21
|
+
check: (Component) => {
|
|
22
|
+
if (typeof Component !== "function") return false;
|
|
23
|
+
|
|
24
|
+
// Svelte 5: compiled components reference $$payload or $$renderer
|
|
25
|
+
const str = Component.toString();
|
|
26
|
+
if (
|
|
27
|
+
str.includes("$$payload") ||
|
|
28
|
+
str.includes("$$renderer") ||
|
|
29
|
+
str.includes("$$anchor")
|
|
30
|
+
) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Svelte 4: class-based components have a render static method
|
|
35
|
+
if (typeof Component.render === "function") {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return false;
|
|
40
|
+
},
|
|
41
|
+
/**
|
|
42
|
+
* @param {any} Component
|
|
43
|
+
* @param {unknown} props
|
|
44
|
+
* @returns {Promise<{html: string}>}
|
|
45
|
+
*/
|
|
46
|
+
renderToStaticMarkup: async (Component, props) => {
|
|
47
|
+
const id = queueForClientSideRender((node) => {
|
|
48
|
+
if (mount) {
|
|
49
|
+
mount(Component, {
|
|
50
|
+
target: /** @type{any}*/ (node),
|
|
51
|
+
props,
|
|
52
|
+
});
|
|
53
|
+
} else {
|
|
54
|
+
new Component({ target: node, props });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
flushSync();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
html: `<div data-editable-region-csr-id=${id}></div>`,
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { addEditableComponentRenderer } from "../helpers/cloudcannon.mjs";
|
|
2
|
+
|
|
3
|
+
/** @type{((component: any, args: { target: HTMLElement, props: unknown }) => void) | undefined} */
|
|
4
|
+
let mount;
|
|
5
|
+
/** @type{() => void} */
|
|
6
|
+
let flushSync;
|
|
7
|
+
try {
|
|
8
|
+
({ mount, flushSync } = await import("svelte"));
|
|
9
|
+
} catch {
|
|
10
|
+
// Svelte 4 — no mount export
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} key
|
|
15
|
+
* @param {any} component
|
|
16
|
+
*/
|
|
17
|
+
export const registerSvelteComponent = (key, component) => {
|
|
18
|
+
/**
|
|
19
|
+
* @param {unknown} props
|
|
20
|
+
* @returns
|
|
21
|
+
*/
|
|
22
|
+
const wrappedComponent = (props) => {
|
|
23
|
+
const rootEl = document.createElement("div");
|
|
24
|
+
|
|
25
|
+
if (mount) {
|
|
26
|
+
mount(component, {
|
|
27
|
+
target: rootEl,
|
|
28
|
+
props,
|
|
29
|
+
});
|
|
30
|
+
} else {
|
|
31
|
+
new component({ target: rootEl, props });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
flushSync();
|
|
35
|
+
|
|
36
|
+
return rootEl;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
addEditableComponentRenderer(key, wrappedComponent);
|
|
40
|
+
};
|
package/nodes/editable-source.ts
CHANGED
|
@@ -247,6 +247,12 @@ export default class EditableSource extends EditableText {
|
|
|
247
247
|
|
|
248
248
|
onChange(value?: string | null) {
|
|
249
249
|
this.file?.get().then((source) => {
|
|
250
|
+
if (!source) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
"Source editable region tried to update a non-existent file",
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
250
256
|
value = beautifyHtml(value ?? "", {
|
|
251
257
|
indent_char: this.format.indentChar,
|
|
252
258
|
indent_size: this.format.indentSize,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcannon/editable-regions",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Visual Editing for the CloudCannon CMS.",
|
|
6
6
|
"keywords": [
|
|
@@ -49,25 +49,33 @@
|
|
|
49
49
|
"types": "./types/react.d.ts",
|
|
50
50
|
"default": "./integrations/react.mjs"
|
|
51
51
|
},
|
|
52
|
+
"./svelte": {
|
|
53
|
+
"types": "./types/svelte.d.ts",
|
|
54
|
+
"default": "./integrations/svelte.mjs"
|
|
55
|
+
},
|
|
56
|
+
"./astro-svelte-renderer": {
|
|
57
|
+
"types": "./types/astro.d.ts",
|
|
58
|
+
"default": "./integrations/astro/svelte-renderer.mjs"
|
|
59
|
+
},
|
|
52
60
|
"./liquid": "./integrations/liquid/index.mjs",
|
|
53
61
|
"./eleventy": "./integrations/eleventy.mjs",
|
|
54
62
|
"./internal/components": "./components/index.js",
|
|
55
63
|
"./internal/styles": "./styles/index.js"
|
|
56
64
|
},
|
|
57
65
|
"devDependencies": {
|
|
58
|
-
"@biomejs/biome": "2.
|
|
59
|
-
"@cloudcannon/visual-editor-api": "0.0.
|
|
66
|
+
"@biomejs/biome": "2.5.0",
|
|
67
|
+
"@cloudcannon/visual-editor-api": "0.0.18",
|
|
60
68
|
"@sindresorhus/slugify": "3.0.0",
|
|
61
69
|
"@types/js-beautify": "1.14.3",
|
|
62
|
-
"@types/node": "25.
|
|
63
|
-
"@types/react": "19.2.
|
|
70
|
+
"@types/node": "25.9.4",
|
|
71
|
+
"@types/react": "19.2.17",
|
|
64
72
|
"@types/react-dom": "19.2.3",
|
|
65
|
-
"astro": "6.
|
|
73
|
+
"astro": "6.4.8",
|
|
66
74
|
"js-beautify": "1.15.4",
|
|
67
|
-
"liquidjs": "10.
|
|
75
|
+
"liquidjs": "10.27.0",
|
|
68
76
|
"typescript": "6.0.3"
|
|
69
77
|
},
|
|
70
78
|
"dependencies": {
|
|
71
|
-
"esbuild": "0.28.
|
|
79
|
+
"esbuild": "0.28.1"
|
|
72
80
|
}
|
|
73
81
|
}
|
package/types/astro.d.ts
CHANGED
|
@@ -17,3 +17,7 @@ declare module "@cloudcannon/editable-regions/astro" {
|
|
|
17
17
|
declare module "@cloudcannon/editable-regions/astro-react-renderer" {
|
|
18
18
|
// Side-effect only module that registers React renderer
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
declare module "@cloudcannon/editable-regions/astro-svelte-renderer" {
|
|
22
|
+
// Side-effect only module that registers Svelte renderer
|
|
23
|
+
}
|
package/types/modules.d.ts
CHANGED
|
@@ -10,3 +10,11 @@ declare module "astro/runtime/server/index.js" {
|
|
|
10
10
|
declare module "react-dom/server.browser" {
|
|
11
11
|
export function renderToStaticMarkup(element: any): string;
|
|
12
12
|
}
|
|
13
|
+
declare module "svelte" {
|
|
14
|
+
export function mount(
|
|
15
|
+
component: any,
|
|
16
|
+
args: { target: HTMLElement; props: unknown },
|
|
17
|
+
): void;
|
|
18
|
+
|
|
19
|
+
export function flushSync(): void;
|
|
20
|
+
}
|