@studiocms/wysiwyg 0.1.0-experimental.5 → 0.1.1
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/LICENSE +1 -1
- package/README.md +7 -28
- package/dist/common/gjs-blocks.d.ts +4 -0
- package/dist/common/gjs-blocks.js +27 -0
- package/dist/common/gjs-componentRegistry.d.ts +31 -0
- package/dist/common/gjs-componentRegistry.js +59 -0
- package/dist/common/gjs-editor-settings.d.ts +23 -0
- package/dist/common/gjs-editor-settings.js +357 -0
- package/dist/common/gjs-editor-utils.d.ts +165 -0
- package/dist/common/gjs-editor-utils.js +217 -0
- package/dist/common/grapesBlocks/blocks/basics.d.ts +4 -0
- package/dist/common/grapesBlocks/blocks/basics.js +279 -0
- package/dist/common/grapesBlocks/blocks/extras.d.ts +4 -0
- package/dist/common/grapesBlocks/blocks/extras.js +63 -0
- package/dist/common/grapesBlocks/blocks/forms.d.ts +4 -0
- package/dist/{wysiwyg/editorPlugins/forms/blocks.js → common/grapesBlocks/blocks/forms.js} +15 -14
- package/dist/common/grapesBlocks/blocks/index.d.ts +5 -0
- package/dist/common/grapesBlocks/blocks/index.js +23 -0
- package/dist/common/grapesBlocks/blocks/tabs.d.ts +4 -0
- package/dist/{wysiwyg/editorPlugins/tabs/blocks.js → common/grapesBlocks/blocks/tabs.js} +9 -8
- package/dist/common/grapesBlocks/commands/clear.d.ts +4 -0
- package/dist/common/grapesBlocks/commands/clear.js +21 -0
- package/dist/common/grapesBlocks/commands/customCodeCommands.d.ts +4 -0
- package/dist/{wysiwyg/editorPlugins/code/commands.js → common/grapesBlocks/commands/customCodeCommands.js} +11 -9
- package/dist/common/grapesBlocks/commands/deviceCommands.js +23 -0
- package/dist/common/grapesBlocks/commands/index.d.ts +5 -0
- package/dist/common/grapesBlocks/commands/index.js +40 -0
- package/dist/common/grapesBlocks/commands/openImport.d.ts +4 -0
- package/dist/common/grapesBlocks/commands/openImport.js +71 -0
- package/dist/common/grapesBlocks/components/countdown.d.ts +12 -0
- package/dist/common/grapesBlocks/components/countdown.js +147 -0
- package/dist/common/grapesBlocks/components/customCode.d.ts +4 -0
- package/dist/{wysiwyg/editorPlugins/code/components.js → common/grapesBlocks/components/customCode.js} +16 -15
- package/dist/common/grapesBlocks/components/forms.d.ts +3 -0
- package/dist/{wysiwyg/editorPlugins/forms/components.js → common/grapesBlocks/components/forms.js} +30 -36
- package/dist/common/grapesBlocks/components/index.d.ts +5 -0
- package/dist/common/grapesBlocks/components/index.js +23 -0
- package/dist/common/grapesBlocks/components/tabLoader.d.ts +4 -0
- package/dist/{wysiwyg/editorPlugins/tabs/components/index.js → common/grapesBlocks/components/tabLoader.js} +7 -7
- package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/Tab.d.ts +1 -1
- package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/Tab.js +2 -2
- package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContainer.d.ts +1 -1
- package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContent.d.ts +1 -1
- package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContents.d.ts +1 -1
- package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/Tabs.d.ts +1 -1
- package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/Tabs.js +8 -8
- package/dist/common/grapesBlocks/components/tooltip.d.ts +4 -0
- package/dist/{wysiwyg/editorPlugins → common/grapesBlocks/components}/tooltip.js +15 -87
- package/dist/common/grapesBlocks/components/typed.d.ts +9 -0
- package/dist/{wysiwyg/editorPlugins/typed/components.js → common/grapesBlocks/components/typed.js} +7 -7
- package/dist/common/grapesBlocks/consts.d.ts +25 -0
- package/dist/common/grapesBlocks/consts.js +245 -0
- package/dist/common/grapesBlocks/i18n/index.d.ts +3 -0
- package/dist/common/grapesBlocks/i18n/index.js +19 -0
- package/dist/common/grapesBlocks/panels/index.d.ts +4 -0
- package/dist/common/grapesBlocks/panels/index.js +171 -0
- package/dist/{wysiwyg/editorPlugins → common/grapesBlocks}/rte/colorPicker.d.ts +9 -0
- package/dist/{wysiwyg/editorPlugins → common/grapesBlocks}/rte/colorPicker.js +16 -2
- package/dist/{wysiwyg/editorPlugins → common/grapesBlocks}/rte/index.d.ts +3 -3
- package/dist/{wysiwyg/editorPlugins → common/grapesBlocks}/rte/index.js +18 -12
- package/dist/common/grapesBlocks/selectors/index.d.ts +4 -0
- package/dist/common/grapesBlocks/selectors/index.js +9 -0
- package/dist/common/grapesBlocks/selectors/tooltip.d.ts +4 -0
- package/dist/common/grapesBlocks/selectors/tooltip.js +15 -0
- package/dist/common/grapesBlocks/traits/formTraits.d.ts +3 -0
- package/dist/{wysiwyg/editorPlugins/forms/traits.js → common/grapesBlocks/traits/formTraits.js} +12 -8
- package/dist/common/grapesBlocks/traits/index.d.ts +4 -0
- package/dist/common/grapesBlocks/traits/index.js +15 -0
- package/dist/common/grapesBlocks/traits/typedTraits.d.ts +3 -0
- package/dist/common/grapesBlocks/traits/typedTraits.js +24 -0
- package/dist/{wysiwyg/editorPlugins/tuiImageEditor.d.ts → common/grapesBlocks/tuiImageEditor/index.d.ts} +2 -2
- package/dist/{wysiwyg/editorPlugins/tuiImageEditor.js → common/grapesBlocks/tuiImageEditor/index.js} +6 -7
- package/dist/common/grapesBlocks/types.d.ts +446 -0
- package/dist/components/Editor.astro +153 -0
- package/dist/components/render.d.ts +15 -0
- package/dist/components/render.js +11 -0
- package/dist/consts.d.ts +31 -0
- package/dist/consts.js +15 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +71 -0
- package/dist/lib/db.d.ts +83 -0
- package/dist/lib/db.js +50 -0
- package/dist/lib/prerender.d.ts +10 -0
- package/dist/lib/prerender.js +22 -0
- package/dist/{wysiwyg → lib}/shared.d.ts +3 -6
- package/dist/lib/shared.js +6 -0
- package/dist/{utils.d.ts → lib/utils.d.ts} +1 -1
- package/dist/lib/utils.js +10 -0
- package/dist/routes/grapes.css.d.ts +7 -0
- package/dist/routes/grapes.css.js +13 -0
- package/dist/routes/partial.astro +44 -0
- package/dist/routes/store.d.ts +1 -0
- package/dist/routes/store.js +121 -0
- package/dist/schema.d.ts +60 -0
- package/dist/schema.js +24 -0
- package/dist/styles/editor.css +150 -0
- package/dist/styles/grapes.css +71 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.js +9 -0
- package/package.json +30 -28
- package/dist/common/prepareRender.d.ts +0 -11
- package/dist/common/prepareRender.js +0 -24
- package/dist/studio/components/Render.astro +0 -11
- package/dist/studio/components/StudioSDKEditor.astro +0 -334
- package/dist/studio/index.d.ts +0 -38
- package/dist/studio/index.js +0 -58
- package/dist/studio/routes/partial.astro +0 -27
- package/dist/studio/shared.d.ts +0 -17
- package/dist/studio/shared.js +0 -7
- package/dist/studio/utils.d.ts +0 -105
- package/dist/studio/utils.js +0 -244
- package/dist/studio/virtual.d.ts +0 -114
- package/dist/utils.js +0 -15
- package/dist/wysiwyg/components/Editor.astro +0 -765
- package/dist/wysiwyg/components/Render.astro +0 -11
- package/dist/wysiwyg/editorPlugins/blocks/blocks.d.ts +0 -3
- package/dist/wysiwyg/editorPlugins/blocks/blocks.js +0 -239
- package/dist/wysiwyg/editorPlugins/blocks/index.d.ts +0 -80
- package/dist/wysiwyg/editorPlugins/blocks/index.js +0 -26
- package/dist/wysiwyg/editorPlugins/code/blocks.d.ts +0 -4
- package/dist/wysiwyg/editorPlugins/code/blocks.js +0 -20
- package/dist/wysiwyg/editorPlugins/code/commands.d.ts +0 -4
- package/dist/wysiwyg/editorPlugins/code/components.d.ts +0 -4
- package/dist/wysiwyg/editorPlugins/code/index.d.ts +0 -47
- package/dist/wysiwyg/editorPlugins/code/index.js +0 -28
- package/dist/wysiwyg/editorPlugins/code/utils.d.ts +0 -3
- package/dist/wysiwyg/editorPlugins/code/utils.js +0 -8
- package/dist/wysiwyg/editorPlugins/countdown.d.ts +0 -86
- package/dist/wysiwyg/editorPlugins/countdown.js +0 -163
- package/dist/wysiwyg/editorPlugins/forms/blocks.d.ts +0 -3
- package/dist/wysiwyg/editorPlugins/forms/components.d.ts +0 -11
- package/dist/wysiwyg/editorPlugins/forms/index.d.ts +0 -21
- package/dist/wysiwyg/editorPlugins/forms/index.js +0 -18
- package/dist/wysiwyg/editorPlugins/forms/traits.d.ts +0 -2
- package/dist/wysiwyg/editorPlugins/index.d.ts +0 -9
- package/dist/wysiwyg/editorPlugins/index.js +0 -20
- package/dist/wysiwyg/editorPlugins/rte/styles.css +0 -63
- package/dist/wysiwyg/editorPlugins/tabs/blocks.d.ts +0 -3
- package/dist/wysiwyg/editorPlugins/tabs/components/index.d.ts +0 -4
- package/dist/wysiwyg/editorPlugins/tabs/index.d.ts +0 -5
- package/dist/wysiwyg/editorPlugins/tabs/index.js +0 -15
- package/dist/wysiwyg/editorPlugins/tabs/options.d.ts +0 -5
- package/dist/wysiwyg/editorPlugins/tabs/options.js +0 -80
- package/dist/wysiwyg/editorPlugins/tabs/types.d.ts +0 -81
- package/dist/wysiwyg/editorPlugins/tooltip.d.ts +0 -68
- package/dist/wysiwyg/editorPlugins/typed/blocks.d.ts +0 -4
- package/dist/wysiwyg/editorPlugins/typed/blocks.js +0 -15
- package/dist/wysiwyg/editorPlugins/typed/components.d.ts +0 -9
- package/dist/wysiwyg/editorPlugins/typed/index.d.ts +0 -35
- package/dist/wysiwyg/editorPlugins/typed/index.js +0 -18
- package/dist/wysiwyg/editorPlugins/typed/traits.js +0 -18
- package/dist/wysiwyg/editorPlugins/typed/utils.d.ts +0 -2
- package/dist/wysiwyg/editorPlugins/typed/utils.js +0 -6
- package/dist/wysiwyg/index.d.ts +0 -20
- package/dist/wysiwyg/index.js +0 -47
- package/dist/wysiwyg/routes/partial.astro +0 -27
- package/dist/wysiwyg/shared.js +0 -7
- package/dist/wysiwyg/styles/main.css +0 -52
- package/dist/wysiwyg/virtual.d.ts +0 -3
- /package/dist/{wysiwyg/editorPlugins/typed/traits.d.ts → common/grapesBlocks/commands/deviceCommands.d.ts} +0 -0
- /package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContainer.js +0 -0
- /package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContent.js +0 -0
- /package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContents.js +0 -0
- /package/dist/{wysiwyg/editorPlugins/tabs → common/grapesBlocks}/types.js +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
import '@studiocms/ui/css/colors.css';
|
|
3
|
+
import 'grapesjs/dist/css/grapes.min.css';
|
|
4
|
+
import '../styles/editor.css';
|
|
5
|
+
import { getRegistryComponents } from 'studiocms:component-registry/runtime';
|
|
6
|
+
import type { PluginPageTypeEditorProps } from 'studiocms/types';
|
|
7
|
+
|
|
8
|
+
// Get the component registry for the editor
|
|
9
|
+
const componentRegistry = getRegistryComponents();
|
|
10
|
+
|
|
11
|
+
interface Props extends PluginPageTypeEditorProps {}
|
|
12
|
+
|
|
13
|
+
// Extract the content from Astro props
|
|
14
|
+
const { content, id = '' } = Astro.props as Props;
|
|
15
|
+
|
|
16
|
+
const token = Astro.locals?.StudioCMS?.plugins?.editorCSRFToken;
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<div
|
|
20
|
+
class="scms-grapesjs-container"
|
|
21
|
+
data-page-id={id}
|
|
22
|
+
data-component-registry={JSON.stringify(componentRegistry)}
|
|
23
|
+
data-editor-csrf-token={token}
|
|
24
|
+
>
|
|
25
|
+
<div class="editor">
|
|
26
|
+
<div id="gjs"></div>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<textarea id="page-content" name="page-content" style="display: none;"
|
|
31
|
+
>{content}</textarea
|
|
32
|
+
>
|
|
33
|
+
|
|
34
|
+
<script>
|
|
35
|
+
const [
|
|
36
|
+
{ toast },
|
|
37
|
+
{ default: grapesjs, usePlugin },
|
|
38
|
+
{ baseConfig },
|
|
39
|
+
{ getEditorElmData, StudioCMSDbStorageAdapter },
|
|
40
|
+
{ astroComponents },
|
|
41
|
+
{ default: grapesBlocks },
|
|
42
|
+
] = await Promise.all([
|
|
43
|
+
import('@studiocms/ui/components/Toast/toast.js'),
|
|
44
|
+
import('grapesjs'),
|
|
45
|
+
import('../common/gjs-editor-settings'),
|
|
46
|
+
import('../common/gjs-editor-utils'),
|
|
47
|
+
import('../common/gjs-componentRegistry'),
|
|
48
|
+
import('../common/gjs-blocks'),
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
// Get the editor options for Astro components and inline storage
|
|
52
|
+
// This will be used to initialize the plugins with the correct settings
|
|
53
|
+
const { astroComponentsOpts, StudioCMSDbStorageAdapterOpts } =
|
|
54
|
+
getEditorElmData(document, {
|
|
55
|
+
container: ".scms-grapesjs-container",
|
|
56
|
+
pageContent: "#page-content",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Initialize the GrapesJS editor with the base configuration and plugins
|
|
60
|
+
// The plugins include custom components, inline storage, and various editor features
|
|
61
|
+
// such as blocks, tabs, countdown, custom code, tooltips, image editor,
|
|
62
|
+
// typed text, forms, rich text editor, and the StudioCMS GrapesJS plugin
|
|
63
|
+
// This setup allows for a rich editing experience with various functionalities
|
|
64
|
+
const editor = grapesjs.init({
|
|
65
|
+
...baseConfig,
|
|
66
|
+
plugins: [
|
|
67
|
+
usePlugin(astroComponents, astroComponentsOpts),
|
|
68
|
+
usePlugin(StudioCMSDbStorageAdapter, StudioCMSDbStorageAdapterOpts),
|
|
69
|
+
usePlugin(grapesBlocks),
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Simple warn notifier
|
|
74
|
+
const origWarn = console.warn;
|
|
75
|
+
console.warn = function (msg) {
|
|
76
|
+
if (msg.indexOf("[undefined]") == -1) {
|
|
77
|
+
toast({
|
|
78
|
+
title: "Warning",
|
|
79
|
+
type: "warning",
|
|
80
|
+
description: msg,
|
|
81
|
+
duration: 5000,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
origWarn(msg);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Do stuff on load
|
|
88
|
+
editor.on("load", function () {
|
|
89
|
+
const $ = grapesjs.$;
|
|
90
|
+
|
|
91
|
+
// Load and show settings and style manager
|
|
92
|
+
let openTmBtn = editor.Panels.getButton("views", "open-tm");
|
|
93
|
+
openTmBtn && openTmBtn.set("active", 1);
|
|
94
|
+
let openSm = editor.Panels.getButton("views", "open-sm");
|
|
95
|
+
openSm && openSm.set("active", 1);
|
|
96
|
+
|
|
97
|
+
// Remove trait view
|
|
98
|
+
editor.Panels.removeButton("views", "open-tm");
|
|
99
|
+
|
|
100
|
+
// Add Settings Sector
|
|
101
|
+
let traitsSector = $(
|
|
102
|
+
'<div class="gjs-sm-sector no-select">' +
|
|
103
|
+
'<div class="gjs-sm-sector-title"><span class="icon-settings fa fa-cog"></span> <span class="gjs-sm-sector-label">Settings</span></div>' +
|
|
104
|
+
'<div class="gjs-sm-properties" style="display: none;"></div></div>',
|
|
105
|
+
);
|
|
106
|
+
let traitsProps = traitsSector.find(".gjs-sm-properties");
|
|
107
|
+
traitsProps.append($(".gjs-traits-cs"));
|
|
108
|
+
$(".gjs-sm-sectors").before(traitsSector);
|
|
109
|
+
traitsSector.find(".gjs-sm-sector-title").on("click", function () {
|
|
110
|
+
let traitStyle = traitsProps.get(0).style;
|
|
111
|
+
let hidden = traitStyle.display === "none";
|
|
112
|
+
if (hidden) {
|
|
113
|
+
traitStyle.display = "block";
|
|
114
|
+
} else {
|
|
115
|
+
traitStyle.display = "none";
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Open block manager
|
|
120
|
+
let openBlocksBtn = editor.Panels.getButton("views", "open-blocks");
|
|
121
|
+
openBlocksBtn && openBlocksBtn.set("active", 1);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const updateSaveIndicator = () => {
|
|
125
|
+
const saveIndicator = document.querySelector(
|
|
126
|
+
".save-indicator",
|
|
127
|
+
) as HTMLElement;
|
|
128
|
+
|
|
129
|
+
if (saveIndicator) {
|
|
130
|
+
const isDirty = editor.getDirtyCount() > 0;
|
|
131
|
+
|
|
132
|
+
if (isDirty) {
|
|
133
|
+
saveIndicator.classList.add("dirty");
|
|
134
|
+
} else {
|
|
135
|
+
saveIndicator.classList.remove("dirty");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const updateIndicatorEvents = [
|
|
141
|
+
"load",
|
|
142
|
+
"update",
|
|
143
|
+
"component:add",
|
|
144
|
+
"component:remove",
|
|
145
|
+
"component:update",
|
|
146
|
+
"undo",
|
|
147
|
+
"redo",
|
|
148
|
+
];
|
|
149
|
+
|
|
150
|
+
updateIndicatorEvents.forEach((event) =>
|
|
151
|
+
editor.on(event, updateSaveIndicator),
|
|
152
|
+
);
|
|
153
|
+
</script>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare const renderer: {
|
|
2
|
+
name: string;
|
|
3
|
+
renderer: (content: string) => Promise<string>;
|
|
4
|
+
sanitizeOpts: {
|
|
5
|
+
allowElements?: string[] | undefined;
|
|
6
|
+
blockElements?: string[] | undefined;
|
|
7
|
+
dropElements?: string[] | undefined;
|
|
8
|
+
allowAttributes?: Record<string, string[]> | undefined;
|
|
9
|
+
dropAttributes?: Record<string, string[]> | undefined;
|
|
10
|
+
allowComponents?: boolean | undefined;
|
|
11
|
+
allowCustomElements?: boolean | undefined;
|
|
12
|
+
allowComments?: boolean | undefined;
|
|
13
|
+
} | undefined;
|
|
14
|
+
};
|
|
15
|
+
export default renderer;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { preRenderer } from "../lib/prerender.js";
|
|
2
|
+
import { shared } from "../lib/shared.js";
|
|
3
|
+
const renderer = {
|
|
4
|
+
name: "@studiocms/wysiwyg",
|
|
5
|
+
renderer: preRenderer,
|
|
6
|
+
sanitizeOpts: shared?.sanitize
|
|
7
|
+
};
|
|
8
|
+
var render_default = renderer;
|
|
9
|
+
export {
|
|
10
|
+
render_default as default
|
|
11
|
+
};
|
package/dist/consts.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The endpoint path for the WYSIWYG editor's partial HTML file.
|
|
3
|
+
* This file contains the structure of the WYSIWYG editor's UI.
|
|
4
|
+
*/
|
|
5
|
+
export declare const PARTIAL_PATH = "/studiocms_api/wysiwyg_editor/partial";
|
|
6
|
+
/**
|
|
7
|
+
* The endpoint path for the WYSIWYG editor's CSS file.
|
|
8
|
+
* This file contains styles specific to the WYSIWYG editor.
|
|
9
|
+
*/
|
|
10
|
+
export declare const GRAPES_CSS_PATH = "/studiocms_api/wysiwyg_editor/grapes.css";
|
|
11
|
+
/**
|
|
12
|
+
* The endpoint path for storing WYSIWYG editor data.
|
|
13
|
+
* This endpoint is used to save the state of the WYSIWYG editor,
|
|
14
|
+
* allowing users to persist their content.
|
|
15
|
+
*/
|
|
16
|
+
export declare const STORE_ENDPOINT_PATH = "/studiocms_api/wysiwyg_editor/store";
|
|
17
|
+
/**
|
|
18
|
+
* The unique identifier for the WYSIWYG plugin within the StudioCMS ecosystem.
|
|
19
|
+
* Used to register and reference the plugin in the system.
|
|
20
|
+
*/
|
|
21
|
+
export declare const WYSIWYG_TABLE_PLUGIN_ID = "studiocms-wysiwyg";
|
|
22
|
+
/**
|
|
23
|
+
* The name of the CSRF header used for WYSIWYG editor requests.
|
|
24
|
+
* This header is used to validate requests and prevent CSRF attacks.
|
|
25
|
+
*/
|
|
26
|
+
export declare const CSRF_HEADER_NAME = "X-CSRF-Token";
|
|
27
|
+
/**
|
|
28
|
+
* The name of the CSRF cookie used for WYSIWYG editor requests.
|
|
29
|
+
* This cookie stores the CSRF token to be validated against incoming requests.
|
|
30
|
+
*/
|
|
31
|
+
export declare const CSRF_COOKIE_NAME = "studiocms-editor-csrf-token";
|
package/dist/consts.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const API_BASE = "/studiocms_api/wysiwyg_editor";
|
|
2
|
+
const PARTIAL_PATH = `${API_BASE}/partial`;
|
|
3
|
+
const GRAPES_CSS_PATH = `${API_BASE}/grapes.css`;
|
|
4
|
+
const STORE_ENDPOINT_PATH = `${API_BASE}/store`;
|
|
5
|
+
const WYSIWYG_TABLE_PLUGIN_ID = "studiocms-wysiwyg";
|
|
6
|
+
const CSRF_HEADER_NAME = "X-CSRF-Token";
|
|
7
|
+
const CSRF_COOKIE_NAME = "studiocms-editor-csrf-token";
|
|
8
|
+
export {
|
|
9
|
+
CSRF_COOKIE_NAME,
|
|
10
|
+
CSRF_HEADER_NAME,
|
|
11
|
+
GRAPES_CSS_PATH,
|
|
12
|
+
PARTIAL_PATH,
|
|
13
|
+
STORE_ENDPOINT_PATH,
|
|
14
|
+
WYSIWYG_TABLE_PLUGIN_ID
|
|
15
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* These triple-slash directives defines dependencies to various declaration files that will be
|
|
3
|
+
* loaded when a user imports the StudioCMS plugin in their Astro configuration file. These
|
|
4
|
+
* directives must be first at the top of the file and can only be preceded by this comment.
|
|
5
|
+
*/
|
|
6
|
+
import type { AstroIntegration } from 'astro';
|
|
7
|
+
import { type StudioCMSPlugin } from 'studiocms/plugins';
|
|
8
|
+
import { type WYSIWYGSchemaOptions } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Creates an internal Astro integration for WYSIWYG rendering.
|
|
11
|
+
* This is used for testing and internal purposes.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} packageIdentifier - The package identifier for the integration.
|
|
14
|
+
* @param {WYSIWYGSchemaOptions} [options] - Optional configuration options for the WYSIWYG plugin.
|
|
15
|
+
* @returns {AstroIntegration} The configured Astro integration.
|
|
16
|
+
*/
|
|
17
|
+
export declare function internalWysiwygIntegration(packageIdentifier: string, options?: WYSIWYGSchemaOptions): AstroIntegration;
|
|
18
|
+
/**
|
|
19
|
+
* Creates and configures the StudioCMS WYSIWYG Editor plugin.
|
|
20
|
+
*
|
|
21
|
+
* This plugin integrates a WYSIWYG editor into the StudioCMS environment,
|
|
22
|
+
* registering custom routes, rendering components, and handling configuration hooks.
|
|
23
|
+
*
|
|
24
|
+
* @param options - Optional configuration for the WYSIWYG schema, including sanitization options.
|
|
25
|
+
* @returns A configured StudioCMS plugin instance for the WYSIWYG editor.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import wysiwyg from '@studiocms/wysiwyg';
|
|
30
|
+
*
|
|
31
|
+
* plugins: [
|
|
32
|
+
* wysiwyg({
|
|
33
|
+
* sanitize: {}
|
|
34
|
+
* })
|
|
35
|
+
* ]
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare function wysiwyg(opts?: WYSIWYGSchemaOptions): StudioCMSPlugin;
|
|
39
|
+
export default wysiwyg;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createResolver } from "astro-integration-kit";
|
|
2
|
+
import { definePlugin } from "studiocms/plugins";
|
|
3
|
+
import { GRAPES_CSS_PATH, PARTIAL_PATH, STORE_ENDPOINT_PATH } from "./consts.js";
|
|
4
|
+
import { shared } from "./lib/shared.js";
|
|
5
|
+
import { WYSIWYGSchema } from "./types.js";
|
|
6
|
+
function internalWysiwygIntegration(packageIdentifier, options) {
|
|
7
|
+
const resolvedOptions = WYSIWYGSchema.parse(options);
|
|
8
|
+
const resEntrypoint = (path) => `@studiocms/wysiwyg/routes/${path}`;
|
|
9
|
+
const routes = [
|
|
10
|
+
{
|
|
11
|
+
entrypoint: resEntrypoint("partial.astro"),
|
|
12
|
+
pattern: PARTIAL_PATH,
|
|
13
|
+
prerender: false
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
entrypoint: resEntrypoint("grapes.css.js"),
|
|
17
|
+
pattern: GRAPES_CSS_PATH,
|
|
18
|
+
prerender: false
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
entrypoint: resEntrypoint("store.js"),
|
|
22
|
+
pattern: STORE_ENDPOINT_PATH,
|
|
23
|
+
prerender: false
|
|
24
|
+
}
|
|
25
|
+
];
|
|
26
|
+
return {
|
|
27
|
+
name: packageIdentifier,
|
|
28
|
+
hooks: {
|
|
29
|
+
"astro:config:setup": ({ injectRoute }) => {
|
|
30
|
+
for (const route of routes) {
|
|
31
|
+
injectRoute(route);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"astro:config:done": () => {
|
|
35
|
+
shared.sanitize = resolvedOptions?.sanitize;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function wysiwyg(opts) {
|
|
41
|
+
const { resolve } = createResolver(import.meta.url);
|
|
42
|
+
const options = WYSIWYGSchema.parse(opts);
|
|
43
|
+
const packageIdentifier = "@studiocms/wysiwyg";
|
|
44
|
+
return definePlugin({
|
|
45
|
+
identifier: packageIdentifier,
|
|
46
|
+
name: "StudioCMS WYSIWYG Editor",
|
|
47
|
+
studiocmsMinimumVersion: "0.1.0-beta.23",
|
|
48
|
+
hooks: {
|
|
49
|
+
"studiocms:astro-config": ({ addIntegrations }) => {
|
|
50
|
+
addIntegrations(internalWysiwygIntegration(packageIdentifier, options));
|
|
51
|
+
},
|
|
52
|
+
"studiocms:rendering": ({ setRendering }) => {
|
|
53
|
+
setRendering({
|
|
54
|
+
pageTypes: [
|
|
55
|
+
{
|
|
56
|
+
identifier: "studiocms/wysiwyg",
|
|
57
|
+
label: "WYSIWYG",
|
|
58
|
+
rendererComponent: resolve("./components/render.js"),
|
|
59
|
+
pageContentComponent: resolve("./components/Editor.astro")
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
var index_default = wysiwyg;
|
|
68
|
+
export {
|
|
69
|
+
index_default as default,
|
|
70
|
+
internalWysiwygIntegration
|
|
71
|
+
};
|
package/dist/lib/db.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Effect } from 'studiocms/effect';
|
|
2
|
+
/**
|
|
3
|
+
* Provides an SDK for interacting with StudioCMS plugin data using Effect-based operations.
|
|
4
|
+
*
|
|
5
|
+
* This generator function yields an object with methods to retrieve, load, and store
|
|
6
|
+
* WYSIWYG editor plugin data, leveraging schema inference for type safety.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* - Utilizes `InferType` to infer types from `studioCMSProjectDataSchema`.
|
|
10
|
+
* - All operations are effectful and return Effect-based results.
|
|
11
|
+
*
|
|
12
|
+
* @returns An object containing methods for plugin data access:
|
|
13
|
+
* - `getAll`: Retrieves all plugin data entries.
|
|
14
|
+
* - `load`: Loads a specific plugin data entry by ID.
|
|
15
|
+
* - `store`: Inserts or updates a plugin data entry by ID.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const sdk = yield* UseSDK;
|
|
20
|
+
* const allEntries = sdk.getAll();
|
|
21
|
+
* const entry = yield* sdk.load('entry-id');
|
|
22
|
+
* yield* sdk.store('entry-id', { ...data });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare const UseSDK: Effect.Effect<{
|
|
26
|
+
/**
|
|
27
|
+
* Retrieves all entries of the plugin data for the WYSIWYG editor.
|
|
28
|
+
*
|
|
29
|
+
* @returns An array of all plugin data entries.
|
|
30
|
+
*/
|
|
31
|
+
getAll: () => Effect.Effect<import("@withstudiocms/sdk/types").PluginDataEntry<any>[], import("@withstudiocms/sdk/errors.js").StudioCMSSDKError, never>;
|
|
32
|
+
/**
|
|
33
|
+
* Retrieves a specific entry of the plugin data by its ID.
|
|
34
|
+
*
|
|
35
|
+
* @param id - The unique identifier for the plugin data entry.
|
|
36
|
+
* @returns An Effect that resolves to the plugin data entry with the specified ID.
|
|
37
|
+
*/
|
|
38
|
+
load: (id: string) => Effect.Effect<import("@withstudiocms/sdk/types").PluginDataEntry<any> | undefined, import("@withstudiocms/sdk/errors.js").StudioCMSSDKError, never>;
|
|
39
|
+
/**
|
|
40
|
+
* Inserts or updates a plugin data entry with the specified ID and data.
|
|
41
|
+
*
|
|
42
|
+
* @param id - The unique identifier for the plugin data entry.
|
|
43
|
+
* @param data - The data to be inserted or updated in the plugin data entry.
|
|
44
|
+
* @returns An Effect that resolves to the inserted or updated plugin data entry.
|
|
45
|
+
*/
|
|
46
|
+
store: (id: string, data: {
|
|
47
|
+
dataSources: unknown[];
|
|
48
|
+
assets: unknown[];
|
|
49
|
+
styles: unknown[];
|
|
50
|
+
symbols: unknown[];
|
|
51
|
+
pages: unknown[];
|
|
52
|
+
__STUDIOCMS_HTML?: string | undefined;
|
|
53
|
+
}) => Effect.Effect<import("@withstudiocms/sdk/types").PluginDataEntry<any>, import("@withstudiocms/sdk/errors.js").StudioCMSSDKError, never>;
|
|
54
|
+
/**
|
|
55
|
+
* Returns the inferred type for the plugin data schema.
|
|
56
|
+
*/
|
|
57
|
+
types: {
|
|
58
|
+
readonly _Schema: import("effect/Schema").Struct<{
|
|
59
|
+
dataSources: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
60
|
+
assets: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
61
|
+
styles: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
62
|
+
symbols: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
63
|
+
pages: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
64
|
+
__STUDIOCMS_HTML: import("effect/Schema").optional<import("effect/Schema").mutable<typeof import("effect/Schema").String>>;
|
|
65
|
+
}>;
|
|
66
|
+
readonly $UsePluginData: import("effect/Schema").Struct<{
|
|
67
|
+
dataSources: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
68
|
+
assets: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
69
|
+
styles: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
70
|
+
symbols: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
71
|
+
pages: import("effect/Schema").mutable<import("effect/Schema").Array$<typeof import("effect/Schema").Unknown>>;
|
|
72
|
+
__STUDIOCMS_HTML: import("effect/Schema").optional<import("effect/Schema").mutable<typeof import("effect/Schema").String>>;
|
|
73
|
+
}>;
|
|
74
|
+
readonly $Insert: {
|
|
75
|
+
dataSources: unknown[];
|
|
76
|
+
assets: unknown[];
|
|
77
|
+
styles: unknown[];
|
|
78
|
+
symbols: unknown[];
|
|
79
|
+
pages: unknown[];
|
|
80
|
+
__STUDIOCMS_HTML?: string | undefined;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
}, import("studiocms/sdk/base").DBClientInitializationError | import("studiocms/sdk/base").SDKInitializationError, never>;
|
package/dist/lib/db.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SDKCore } from "studiocms:sdk";
|
|
2
|
+
import { Effect } from "studiocms/effect";
|
|
3
|
+
import { WYSIWYG_TABLE_PLUGIN_ID } from "../consts.js";
|
|
4
|
+
import { studioCMSProjectDataSchema } from "../schema.js";
|
|
5
|
+
const UseSDK = Effect.gen(function* () {
|
|
6
|
+
const {
|
|
7
|
+
PLUGINS: { usePluginData, InferType }
|
|
8
|
+
} = yield* SDKCore;
|
|
9
|
+
const infer = new InferType(studioCMSProjectDataSchema);
|
|
10
|
+
const { getEntries, getEntry } = usePluginData(
|
|
11
|
+
WYSIWYG_TABLE_PLUGIN_ID,
|
|
12
|
+
{
|
|
13
|
+
validator: { effectSchema: studioCMSProjectDataSchema }
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
const updateOrInsert = (entry) => (id, data) => {
|
|
17
|
+
if (entry) return getEntry(id).update(data);
|
|
18
|
+
return getEntry(id).insert(data);
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
/**
|
|
22
|
+
* Retrieves all entries of the plugin data for the WYSIWYG editor.
|
|
23
|
+
*
|
|
24
|
+
* @returns An array of all plugin data entries.
|
|
25
|
+
*/
|
|
26
|
+
getAll: () => getEntries((data) => data.filter((entry) => entry.data.__STUDIOCMS_HTML)),
|
|
27
|
+
/**
|
|
28
|
+
* Retrieves a specific entry of the plugin data by its ID.
|
|
29
|
+
*
|
|
30
|
+
* @param id - The unique identifier for the plugin data entry.
|
|
31
|
+
* @returns An Effect that resolves to the plugin data entry with the specified ID.
|
|
32
|
+
*/
|
|
33
|
+
load: (id) => getEntry(id).select(),
|
|
34
|
+
/**
|
|
35
|
+
* Inserts or updates a plugin data entry with the specified ID and data.
|
|
36
|
+
*
|
|
37
|
+
* @param id - The unique identifier for the plugin data entry.
|
|
38
|
+
* @param data - The data to be inserted or updated in the plugin data entry.
|
|
39
|
+
* @returns An Effect that resolves to the inserted or updated plugin data entry.
|
|
40
|
+
*/
|
|
41
|
+
store: (id, data) => getEntry(id).select().pipe(Effect.flatMap((entry) => updateOrInsert(entry)(id, data))),
|
|
42
|
+
/**
|
|
43
|
+
* Returns the inferred type for the plugin data schema.
|
|
44
|
+
*/
|
|
45
|
+
types: infer
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
export {
|
|
49
|
+
UseSDK
|
|
50
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asynchronously pre-renders HTML content from a serialized string.
|
|
3
|
+
*
|
|
4
|
+
* Attempts to parse the provided content string and extract the `__STUDIOCMS_HTML` property.
|
|
5
|
+
* If the content is missing, invalid, or parsing fails, returns an appropriate error message as HTML.
|
|
6
|
+
*
|
|
7
|
+
* @param content - The serialized content string to be parsed and rendered.
|
|
8
|
+
* @returns A promise that resolves to the rendered HTML string or an error message in HTML format.
|
|
9
|
+
*/
|
|
10
|
+
export declare const preRenderer: (content: string) => Promise<string>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { parse } from "./utils.js";
|
|
2
|
+
const preRenderer = async (content) => {
|
|
3
|
+
let parsedContent = "<h1>Error: No content found</h1>";
|
|
4
|
+
if (!content) {
|
|
5
|
+
return parsedContent;
|
|
6
|
+
}
|
|
7
|
+
try {
|
|
8
|
+
const { __STUDIOCMS_HTML } = parse(content);
|
|
9
|
+
if (__STUDIOCMS_HTML) {
|
|
10
|
+
parsedContent = __STUDIOCMS_HTML;
|
|
11
|
+
} else {
|
|
12
|
+
parsedContent = "<h1>Error: Content found but invalid format</h1>";
|
|
13
|
+
}
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error("Error parsing content:", error);
|
|
16
|
+
parsedContent = "<h1>Error parsing content</h1>";
|
|
17
|
+
}
|
|
18
|
+
return parsedContent;
|
|
19
|
+
};
|
|
20
|
+
export {
|
|
21
|
+
preRenderer
|
|
22
|
+
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
type
|
|
2
|
-
sanitize: import('ultrahtml/transformers/sanitize').SanitizeOptions;
|
|
3
|
-
};
|
|
1
|
+
import type { WYSIWYGSchemaOptions } from '../types.js';
|
|
4
2
|
declare global {
|
|
5
|
-
var studiocmsWYSIWYG:
|
|
3
|
+
var studiocmsWYSIWYG: WYSIWYGSchemaOptions;
|
|
6
4
|
}
|
|
7
5
|
/**
|
|
8
6
|
* A shared object used across the WYSIWYG module. This object is either retrieved
|
|
@@ -13,5 +11,4 @@ declare global {
|
|
|
13
11
|
* The `sanitize` property is initialized as an empty object and can be used to store
|
|
14
12
|
* sanitization-related configurations or utilities.
|
|
15
13
|
*/
|
|
16
|
-
export declare const shared:
|
|
17
|
-
export {};
|
|
14
|
+
export declare const shared: WYSIWYGSchemaOptions;
|
|
@@ -13,4 +13,4 @@ export declare function firstUpperCase(text: string): string;
|
|
|
13
13
|
* @returns The parsed object of type `T`.
|
|
14
14
|
* @throws {SyntaxError} If the input string is not valid JSON.
|
|
15
15
|
*/
|
|
16
|
-
export declare function parse<T
|
|
16
|
+
export declare function parse<T>(data: string): T;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles all HTTP methods for serving a CSS stylesheet.
|
|
3
|
+
*
|
|
4
|
+
* @returns {Promise<Response>} A promise that resolves to a Response object containing the CSS stylesheet,
|
|
5
|
+
* with appropriate headers for content type and CORS.
|
|
6
|
+
*/
|
|
7
|
+
export declare function ALL(): Promise<Response>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import stylesheet from "../styles/grapes.css?raw";
|
|
2
|
+
async function ALL() {
|
|
3
|
+
return new Response(stylesheet, {
|
|
4
|
+
headers: {
|
|
5
|
+
"Content-Type": "text/css",
|
|
6
|
+
"Access-Control-Allow-Origin": "*",
|
|
7
|
+
"Access-Control-Allow-Methods": "GET, HEAD, OPTIONS"
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
ALL
|
|
13
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
export const partial = true;
|
|
3
|
+
|
|
4
|
+
import { getRendererComponents } from 'studiocms:component-registry/runtime';
|
|
5
|
+
import { apiResponseLogger } from 'studiocms:logger';
|
|
6
|
+
|
|
7
|
+
// Define the PropData type
|
|
8
|
+
type PropData = {
|
|
9
|
+
componentKey: string;
|
|
10
|
+
// biome-ignore lint/suspicious/noExplicitAny: this is a dynamic prop type
|
|
11
|
+
props?: Record<string, any>;
|
|
12
|
+
slot?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Import components
|
|
16
|
+
const componentRegistry = await getRendererComponents();
|
|
17
|
+
|
|
18
|
+
// Parse the request body as JSON
|
|
19
|
+
let data: PropData;
|
|
20
|
+
try {
|
|
21
|
+
data = await Astro.request.json();
|
|
22
|
+
} catch (error) {
|
|
23
|
+
return apiResponseLogger(400, 'Invalid JSON in request body', error);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Validate the data
|
|
27
|
+
if (!data || typeof data.componentKey !== 'string' || !data.componentKey.trim()) {
|
|
28
|
+
return apiResponseLogger(400, 'Missing or invalid componentKey');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Destructure the componentKey, props, and slot from the data
|
|
32
|
+
const { componentKey, props = {}, slot } = data;
|
|
33
|
+
|
|
34
|
+
// Check if the component exists in the registry
|
|
35
|
+
const Component = componentRegistry[componentKey];
|
|
36
|
+
|
|
37
|
+
// Handle case where component doesn't exist
|
|
38
|
+
if (!Component) {
|
|
39
|
+
return apiResponseLogger(404, `Component "${componentKey}" not found`);
|
|
40
|
+
}
|
|
41
|
+
---
|
|
42
|
+
<Component {...props}>
|
|
43
|
+
{slot && <Fragment set:html={slot} />}
|
|
44
|
+
</Component>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const GET: import("astro").APIRoute, POST: import("astro").APIRoute, OPTIONS: import("astro").APIRoute, ALL: import("astro").APIRoute;
|