@studiocms/wysiwyg 0.1.0-experimental.5 → 0.1.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.
Files changed (164) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +7 -28
  3. package/dist/common/gjs-blocks.d.ts +4 -0
  4. package/dist/common/gjs-blocks.js +27 -0
  5. package/dist/common/gjs-componentRegistry.d.ts +31 -0
  6. package/dist/common/gjs-componentRegistry.js +59 -0
  7. package/dist/common/gjs-editor-settings.d.ts +23 -0
  8. package/dist/common/gjs-editor-settings.js +357 -0
  9. package/dist/common/gjs-editor-utils.d.ts +165 -0
  10. package/dist/common/gjs-editor-utils.js +217 -0
  11. package/dist/common/grapesBlocks/blocks/basics.d.ts +4 -0
  12. package/dist/common/grapesBlocks/blocks/basics.js +279 -0
  13. package/dist/common/grapesBlocks/blocks/extras.d.ts +4 -0
  14. package/dist/common/grapesBlocks/blocks/extras.js +63 -0
  15. package/dist/common/grapesBlocks/blocks/forms.d.ts +4 -0
  16. package/dist/{wysiwyg/editorPlugins/forms/blocks.js → common/grapesBlocks/blocks/forms.js} +15 -14
  17. package/dist/common/grapesBlocks/blocks/index.d.ts +5 -0
  18. package/dist/common/grapesBlocks/blocks/index.js +23 -0
  19. package/dist/common/grapesBlocks/blocks/tabs.d.ts +4 -0
  20. package/dist/{wysiwyg/editorPlugins/tabs/blocks.js → common/grapesBlocks/blocks/tabs.js} +9 -8
  21. package/dist/common/grapesBlocks/commands/clear.d.ts +4 -0
  22. package/dist/common/grapesBlocks/commands/clear.js +21 -0
  23. package/dist/common/grapesBlocks/commands/customCodeCommands.d.ts +4 -0
  24. package/dist/{wysiwyg/editorPlugins/code/commands.js → common/grapesBlocks/commands/customCodeCommands.js} +11 -9
  25. package/dist/common/grapesBlocks/commands/deviceCommands.js +23 -0
  26. package/dist/common/grapesBlocks/commands/index.d.ts +5 -0
  27. package/dist/common/grapesBlocks/commands/index.js +40 -0
  28. package/dist/common/grapesBlocks/commands/openImport.d.ts +4 -0
  29. package/dist/common/grapesBlocks/commands/openImport.js +71 -0
  30. package/dist/common/grapesBlocks/components/countdown.d.ts +12 -0
  31. package/dist/common/grapesBlocks/components/countdown.js +147 -0
  32. package/dist/common/grapesBlocks/components/customCode.d.ts +4 -0
  33. package/dist/{wysiwyg/editorPlugins/code/components.js → common/grapesBlocks/components/customCode.js} +16 -15
  34. package/dist/common/grapesBlocks/components/forms.d.ts +3 -0
  35. package/dist/{wysiwyg/editorPlugins/forms/components.js → common/grapesBlocks/components/forms.js} +30 -36
  36. package/dist/common/grapesBlocks/components/index.d.ts +5 -0
  37. package/dist/common/grapesBlocks/components/index.js +23 -0
  38. package/dist/common/grapesBlocks/components/tabLoader.d.ts +4 -0
  39. package/dist/{wysiwyg/editorPlugins/tabs/components/index.js → common/grapesBlocks/components/tabLoader.js} +7 -7
  40. package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/Tab.d.ts +1 -1
  41. package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/Tab.js +2 -2
  42. package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContainer.d.ts +1 -1
  43. package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContent.d.ts +1 -1
  44. package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContents.d.ts +1 -1
  45. package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/Tabs.d.ts +1 -1
  46. package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/Tabs.js +8 -8
  47. package/dist/common/grapesBlocks/components/tooltip.d.ts +4 -0
  48. package/dist/{wysiwyg/editorPlugins → common/grapesBlocks/components}/tooltip.js +15 -87
  49. package/dist/common/grapesBlocks/components/typed.d.ts +9 -0
  50. package/dist/{wysiwyg/editorPlugins/typed/components.js → common/grapesBlocks/components/typed.js} +7 -7
  51. package/dist/common/grapesBlocks/consts.d.ts +25 -0
  52. package/dist/common/grapesBlocks/consts.js +245 -0
  53. package/dist/common/grapesBlocks/i18n/index.d.ts +3 -0
  54. package/dist/common/grapesBlocks/i18n/index.js +19 -0
  55. package/dist/common/grapesBlocks/panels/index.d.ts +4 -0
  56. package/dist/common/grapesBlocks/panels/index.js +171 -0
  57. package/dist/{wysiwyg/editorPlugins → common/grapesBlocks}/rte/colorPicker.d.ts +9 -0
  58. package/dist/{wysiwyg/editorPlugins → common/grapesBlocks}/rte/colorPicker.js +16 -2
  59. package/dist/{wysiwyg/editorPlugins → common/grapesBlocks}/rte/index.d.ts +3 -3
  60. package/dist/{wysiwyg/editorPlugins → common/grapesBlocks}/rte/index.js +18 -12
  61. package/dist/common/grapesBlocks/selectors/index.d.ts +4 -0
  62. package/dist/common/grapesBlocks/selectors/index.js +9 -0
  63. package/dist/common/grapesBlocks/selectors/tooltip.d.ts +4 -0
  64. package/dist/common/grapesBlocks/selectors/tooltip.js +15 -0
  65. package/dist/common/grapesBlocks/traits/formTraits.d.ts +3 -0
  66. package/dist/{wysiwyg/editorPlugins/forms/traits.js → common/grapesBlocks/traits/formTraits.js} +12 -8
  67. package/dist/common/grapesBlocks/traits/index.d.ts +4 -0
  68. package/dist/common/grapesBlocks/traits/index.js +15 -0
  69. package/dist/common/grapesBlocks/traits/typedTraits.d.ts +3 -0
  70. package/dist/common/grapesBlocks/traits/typedTraits.js +24 -0
  71. package/dist/{wysiwyg/editorPlugins/tuiImageEditor.d.ts → common/grapesBlocks/tuiImageEditor/index.d.ts} +2 -2
  72. package/dist/{wysiwyg/editorPlugins/tuiImageEditor.js → common/grapesBlocks/tuiImageEditor/index.js} +6 -7
  73. package/dist/common/grapesBlocks/types.d.ts +446 -0
  74. package/dist/components/Editor.astro +153 -0
  75. package/dist/components/render.d.ts +15 -0
  76. package/dist/components/render.js +11 -0
  77. package/dist/consts.d.ts +31 -0
  78. package/dist/consts.js +15 -0
  79. package/dist/index.d.ts +39 -0
  80. package/dist/index.js +71 -0
  81. package/dist/lib/db.d.ts +83 -0
  82. package/dist/lib/db.js +50 -0
  83. package/dist/lib/prerender.d.ts +10 -0
  84. package/dist/lib/prerender.js +22 -0
  85. package/dist/{wysiwyg → lib}/shared.d.ts +3 -6
  86. package/dist/lib/shared.js +6 -0
  87. package/dist/{utils.d.ts → lib/utils.d.ts} +1 -1
  88. package/dist/lib/utils.js +10 -0
  89. package/dist/routes/grapes.css.d.ts +7 -0
  90. package/dist/routes/grapes.css.js +13 -0
  91. package/dist/routes/partial.astro +44 -0
  92. package/dist/routes/store.d.ts +1 -0
  93. package/dist/routes/store.js +121 -0
  94. package/dist/schema.d.ts +60 -0
  95. package/dist/schema.js +24 -0
  96. package/dist/styles/editor.css +150 -0
  97. package/dist/styles/grapes.css +71 -0
  98. package/dist/types.d.ts +66 -0
  99. package/dist/types.js +9 -0
  100. package/package.json +30 -28
  101. package/dist/common/prepareRender.d.ts +0 -11
  102. package/dist/common/prepareRender.js +0 -24
  103. package/dist/studio/components/Render.astro +0 -11
  104. package/dist/studio/components/StudioSDKEditor.astro +0 -334
  105. package/dist/studio/index.d.ts +0 -38
  106. package/dist/studio/index.js +0 -58
  107. package/dist/studio/routes/partial.astro +0 -27
  108. package/dist/studio/shared.d.ts +0 -17
  109. package/dist/studio/shared.js +0 -7
  110. package/dist/studio/utils.d.ts +0 -105
  111. package/dist/studio/utils.js +0 -244
  112. package/dist/studio/virtual.d.ts +0 -114
  113. package/dist/utils.js +0 -15
  114. package/dist/wysiwyg/components/Editor.astro +0 -765
  115. package/dist/wysiwyg/components/Render.astro +0 -11
  116. package/dist/wysiwyg/editorPlugins/blocks/blocks.d.ts +0 -3
  117. package/dist/wysiwyg/editorPlugins/blocks/blocks.js +0 -239
  118. package/dist/wysiwyg/editorPlugins/blocks/index.d.ts +0 -80
  119. package/dist/wysiwyg/editorPlugins/blocks/index.js +0 -26
  120. package/dist/wysiwyg/editorPlugins/code/blocks.d.ts +0 -4
  121. package/dist/wysiwyg/editorPlugins/code/blocks.js +0 -20
  122. package/dist/wysiwyg/editorPlugins/code/commands.d.ts +0 -4
  123. package/dist/wysiwyg/editorPlugins/code/components.d.ts +0 -4
  124. package/dist/wysiwyg/editorPlugins/code/index.d.ts +0 -47
  125. package/dist/wysiwyg/editorPlugins/code/index.js +0 -28
  126. package/dist/wysiwyg/editorPlugins/code/utils.d.ts +0 -3
  127. package/dist/wysiwyg/editorPlugins/code/utils.js +0 -8
  128. package/dist/wysiwyg/editorPlugins/countdown.d.ts +0 -86
  129. package/dist/wysiwyg/editorPlugins/countdown.js +0 -163
  130. package/dist/wysiwyg/editorPlugins/forms/blocks.d.ts +0 -3
  131. package/dist/wysiwyg/editorPlugins/forms/components.d.ts +0 -11
  132. package/dist/wysiwyg/editorPlugins/forms/index.d.ts +0 -21
  133. package/dist/wysiwyg/editorPlugins/forms/index.js +0 -18
  134. package/dist/wysiwyg/editorPlugins/forms/traits.d.ts +0 -2
  135. package/dist/wysiwyg/editorPlugins/index.d.ts +0 -9
  136. package/dist/wysiwyg/editorPlugins/index.js +0 -20
  137. package/dist/wysiwyg/editorPlugins/rte/styles.css +0 -63
  138. package/dist/wysiwyg/editorPlugins/tabs/blocks.d.ts +0 -3
  139. package/dist/wysiwyg/editorPlugins/tabs/components/index.d.ts +0 -4
  140. package/dist/wysiwyg/editorPlugins/tabs/index.d.ts +0 -5
  141. package/dist/wysiwyg/editorPlugins/tabs/index.js +0 -15
  142. package/dist/wysiwyg/editorPlugins/tabs/options.d.ts +0 -5
  143. package/dist/wysiwyg/editorPlugins/tabs/options.js +0 -80
  144. package/dist/wysiwyg/editorPlugins/tabs/types.d.ts +0 -81
  145. package/dist/wysiwyg/editorPlugins/tooltip.d.ts +0 -68
  146. package/dist/wysiwyg/editorPlugins/typed/blocks.d.ts +0 -4
  147. package/dist/wysiwyg/editorPlugins/typed/blocks.js +0 -15
  148. package/dist/wysiwyg/editorPlugins/typed/components.d.ts +0 -9
  149. package/dist/wysiwyg/editorPlugins/typed/index.d.ts +0 -35
  150. package/dist/wysiwyg/editorPlugins/typed/index.js +0 -18
  151. package/dist/wysiwyg/editorPlugins/typed/traits.js +0 -18
  152. package/dist/wysiwyg/editorPlugins/typed/utils.d.ts +0 -2
  153. package/dist/wysiwyg/editorPlugins/typed/utils.js +0 -6
  154. package/dist/wysiwyg/index.d.ts +0 -20
  155. package/dist/wysiwyg/index.js +0 -47
  156. package/dist/wysiwyg/routes/partial.astro +0 -27
  157. package/dist/wysiwyg/shared.js +0 -7
  158. package/dist/wysiwyg/styles/main.css +0 -52
  159. package/dist/wysiwyg/virtual.d.ts +0 -3
  160. /package/dist/{wysiwyg/editorPlugins/typed/traits.d.ts → common/grapesBlocks/commands/deviceCommands.d.ts} +0 -0
  161. /package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContainer.js +0 -0
  162. /package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContent.js +0 -0
  163. /package/dist/{wysiwyg/editorPlugins/tabs/components → common/grapesBlocks/components/tabs}/TabContents.js +0 -0
  164. /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
+ };
@@ -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
+ };
@@ -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
+ };
@@ -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 Shared = {
2
- sanitize: import('ultrahtml/transformers/sanitize').SanitizeOptions;
3
- };
1
+ import type { WYSIWYGSchemaOptions } from '../types.js';
4
2
  declare global {
5
- var studiocmsWYSIWYG: Shared;
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: Shared;
17
- export {};
14
+ export declare const shared: WYSIWYGSchemaOptions;
@@ -0,0 +1,6 @@
1
+ const shared = globalThis.studiocmsWYSIWYG || (globalThis.studiocmsWYSIWYG = {
2
+ sanitize: void 0
3
+ });
4
+ export {
5
+ shared
6
+ };
@@ -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 extends object>(data: string): T;
16
+ export declare function parse<T>(data: string): T;
@@ -0,0 +1,10 @@
1
+ function firstUpperCase(text) {
2
+ return text.charAt(0).toUpperCase() + text.slice(1);
3
+ }
4
+ function parse(data) {
5
+ return JSON.parse(data);
6
+ }
7
+ export {
8
+ firstUpperCase,
9
+ parse
10
+ };
@@ -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;