]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/ui/defaults/forms/objects.ts
7a388751bc420733df52ecfce6605fb178ea139a
[bookstack] / resources / js / wysiwyg / ui / defaults / forms / objects.ts
1 import {EditorFormDefinition, EditorFormTabs, EditorSelectFormFieldDefinition} from "../../framework/forms";
2 import {EditorUiContext} from "../../framework/core";
3 import {$createTextNode, $getSelection} from "lexical";
4 import {$createImageNode} from "../../../nodes/image";
5 import {$createLinkNode} from "@lexical/link";
6 import {$createMediaNodeFromHtml, $createMediaNodeFromSrc, $isMediaNode, MediaNode} from "../../../nodes/media";
7 import {$getNodeFromSelection} from "../../../helpers";
8 import {$insertNodeToNearestRoot} from "@lexical/utils";
9
10 export const image: EditorFormDefinition = {
11     submitText: 'Apply',
12     async action(formData, context: EditorUiContext) {
13         context.editor.update(() => {
14             const selection = $getSelection();
15             const imageNode = $createImageNode(formData.get('src')?.toString() || '', {
16                 alt: formData.get('alt')?.toString() || '',
17                 height: Number(formData.get('height')?.toString() || '0'),
18                 width: Number(formData.get('width')?.toString() || '0'),
19             });
20             selection?.insertNodes([imageNode]);
21         });
22         return true;
23     },
24     fields: [
25         {
26             label: 'Source',
27             name: 'src',
28             type: 'text',
29         },
30         {
31             label: 'Alternative description',
32             name: 'alt',
33             type: 'text',
34         },
35         {
36             label: 'Width',
37             name: 'width',
38             type: 'text',
39         },
40         {
41             label: 'Height',
42             name: 'height',
43             type: 'text',
44         },
45     ],
46 };
47
48 export const link: EditorFormDefinition = {
49     submitText: 'Apply',
50     async action(formData, context: EditorUiContext) {
51         context.editor.update(() => {
52
53             const selection = $getSelection();
54
55             const linkNode = $createLinkNode(formData.get('url')?.toString() || '', {
56                 title: formData.get('title')?.toString() || '',
57                 target: formData.get('target')?.toString() || '',
58             });
59             linkNode.append($createTextNode(formData.get('text')?.toString() || ''));
60
61             selection?.insertNodes([linkNode]);
62         });
63         return true;
64     },
65     fields: [
66         {
67             label: 'URL',
68             name: 'url',
69             type: 'text',
70         },
71         {
72             label: 'Text to display',
73             name: 'text',
74             type: 'text',
75         },
76         {
77             label: 'Title',
78             name: 'title',
79             type: 'text',
80         },
81         {
82             label: 'Open link in...',
83             name: 'target',
84             type: 'select',
85             valuesByLabel: {
86                 'Current window': '',
87                 'New window': '_blank',
88             }
89         } as EditorSelectFormFieldDefinition,
90     ],
91 };
92
93 export const media: EditorFormDefinition = {
94     submitText: 'Save',
95     async action(formData, context: EditorUiContext) {
96         const selectedNode: MediaNode|null = await (new Promise((res, rej) => {
97             context.editor.getEditorState().read(() => {
98                 const node = $getNodeFromSelection($getSelection(), $isMediaNode);
99                 res(node as MediaNode|null);
100             });
101         }));
102
103         const embedCode = (formData.get('embed') || '').toString().trim();
104         if (embedCode) {
105             context.editor.update(() => {
106                 const node = $createMediaNodeFromHtml(embedCode);
107                 if (selectedNode && node) {
108                     selectedNode.replace(node)
109                 } else if (node) {
110                     $insertNodeToNearestRoot(node);
111                 }
112             });
113
114             return true;
115         }
116
117         context.editor.update(() => {
118             const src = (formData.get('src') || '').toString().trim();
119             const height = (formData.get('height') || '').toString().trim();
120             const width = (formData.get('width') || '').toString().trim();
121
122             const updateNode = selectedNode || $createMediaNodeFromSrc(src);
123             updateNode.setSrc(src);
124             updateNode.setWidthAndHeight(width, height);
125             if (!selectedNode) {
126                 $insertNodeToNearestRoot(updateNode);
127             }
128         });
129
130         return true;
131     },
132     fields: [
133         {
134             build() {
135                 return new EditorFormTabs([
136                     {
137                         label: 'General',
138                         contents: [
139                             {
140                                 label: 'Source',
141                                 name: 'src',
142                                 type: 'text',
143                             },
144                             {
145                                 label: 'Width',
146                                 name: 'width',
147                                 type: 'text',
148                             },
149                             {
150                                 label: 'Height',
151                                 name: 'height',
152                                 type: 'text',
153                             },
154                         ],
155                     },
156                     {
157                         label: 'Embed',
158                         contents: [
159                             {
160                                 label: 'Paste your embed code below:',
161                                 name: 'embed',
162                                 type: 'textarea',
163                             },
164                         ],
165                     }
166                 ])
167             }
168         },
169     ],
170 };