ckeditor5-livewire 1.12.2 → 1.13.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/hooks/editable.d.ts +4 -0
- package/dist/hooks/editable.d.ts.map +1 -1
- package/dist/hooks/editor/editor.d.ts +4 -0
- package/dist/hooks/editor/editor.d.ts.map +1 -1
- package/dist/hooks/editor/utils/assign-editor-roots-to-config.d.ts.map +1 -1
- package/dist/hooks/editor/utils/query-all-editor-editables.d.ts +1 -0
- package/dist/hooks/editor/utils/query-all-editor-editables.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +26 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/hooks/editable.test.ts +34 -0
- package/src/hooks/editable.ts +7 -1
- package/src/hooks/editor/editor.test.ts +165 -1
- package/src/hooks/editor/editor.ts +5 -0
- package/src/hooks/editor/utils/assign-editor-roots-to-config.ts +1 -0
- package/src/hooks/editor/utils/get-editor-roots-values.ts +1 -1
- package/src/hooks/editor/utils/query-all-editor-editables.ts +12 -2
package/package.json
CHANGED
|
@@ -71,6 +71,40 @@ describe('editable component', () => {
|
|
|
71
71
|
expect(root.getAttribute('data-test')).toBe('initial');
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
+
it('should set proper root element name on initial added root', async () => {
|
|
75
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
76
|
+
name: 'ckeditor5-editable',
|
|
77
|
+
el: createEditableHtmlElement(),
|
|
78
|
+
canonical: {
|
|
79
|
+
...createEditableSnapshot('foo', '<p>Initial foo component</p>'),
|
|
80
|
+
modelElement: '$inlineRoot',
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
appendMultirootEditor();
|
|
85
|
+
|
|
86
|
+
const editor = await waitForTestEditor();
|
|
87
|
+
|
|
88
|
+
expect(editor.model.document.getRoot('foo')?.name).to.be.equal('$inlineRoot');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should set proper root element name on lazy added root', async () => {
|
|
92
|
+
appendMultirootEditor();
|
|
93
|
+
|
|
94
|
+
const editor = await waitForTestEditor();
|
|
95
|
+
|
|
96
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
97
|
+
name: 'ckeditor5-editable',
|
|
98
|
+
el: createEditableHtmlElement(),
|
|
99
|
+
canonical: {
|
|
100
|
+
...createEditableSnapshot('foo', '<p>Initial foo component</p>'),
|
|
101
|
+
modelElement: '$inlineRoot',
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
expect(editor.model.document.getRoot('foo')?.name).to.be.equal('$inlineRoot');
|
|
106
|
+
});
|
|
107
|
+
|
|
74
108
|
it('should update root attributes after commit', async () => {
|
|
75
109
|
appendMultirootEditor();
|
|
76
110
|
|
package/src/hooks/editable.ts
CHANGED
|
@@ -26,7 +26,7 @@ export class EditableComponentHook extends ClassHook<Snapshot> {
|
|
|
26
26
|
* Mounts the editable component.
|
|
27
27
|
*/
|
|
28
28
|
override mounted() {
|
|
29
|
-
const { editorId, rootName, content } = this.canonical;
|
|
29
|
+
const { editorId, rootName, content, modelElement } = this.canonical;
|
|
30
30
|
|
|
31
31
|
const unmountEffect = EditorsRegistry.the.mountEffect(editorId, (editor: MultiRootEditor | DecoupledEditor) => {
|
|
32
32
|
/* v8 ignore next if -- @preserve */
|
|
@@ -56,6 +56,7 @@ export class EditableComponentHook extends ClassHook<Snapshot> {
|
|
|
56
56
|
|
|
57
57
|
editor.addRoot(rootName, {
|
|
58
58
|
isUndoable: false,
|
|
59
|
+
modelElement: modelElement ?? '$root',
|
|
59
60
|
...content !== null && {
|
|
60
61
|
initialData: content,
|
|
61
62
|
},
|
|
@@ -267,6 +268,11 @@ export type Snapshot = {
|
|
|
267
268
|
*/
|
|
268
269
|
rootName: string;
|
|
269
270
|
|
|
271
|
+
/**
|
|
272
|
+
* The name of the model element.
|
|
273
|
+
*/
|
|
274
|
+
modelElement: string | null;
|
|
275
|
+
|
|
270
276
|
/**
|
|
271
277
|
* The initial content value for the editable.
|
|
272
278
|
*/
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
import type { Snapshot as EditorSnapshot } from './editor';
|
|
29
29
|
|
|
30
30
|
import { timeout } from '../../shared/timeout';
|
|
31
|
+
import { EditableComponentHook } from '../editable';
|
|
31
32
|
import { registerLivewireComponentHook } from '../hook';
|
|
32
33
|
import { CustomEditorPluginsRegistry } from './custom-editor-plugins';
|
|
33
34
|
import { EditorComponentHook } from './editor';
|
|
@@ -42,6 +43,7 @@ describe('editor component', () => {
|
|
|
42
43
|
livewireStub = window.Livewire = new LivewireStub();
|
|
43
44
|
|
|
44
45
|
registerLivewireComponentHook('ckeditor5', EditorComponentHook);
|
|
46
|
+
registerLivewireComponentHook('ckeditor5-editable', EditableComponentHook);
|
|
45
47
|
});
|
|
46
48
|
|
|
47
49
|
afterEach(async () => {
|
|
@@ -135,6 +137,20 @@ describe('editor component', () => {
|
|
|
135
137
|
|
|
136
138
|
expect(editor.getData()).toBe('');
|
|
137
139
|
});
|
|
140
|
+
|
|
141
|
+
it('should be possible to specify root element name', async () => {
|
|
142
|
+
livewireStub.$internal.appendComponentToDOM<EditorSnapshot>({
|
|
143
|
+
name: 'ckeditor5',
|
|
144
|
+
el: createEditorHtmlElement(),
|
|
145
|
+
canonical: createEditorSnapshot({
|
|
146
|
+
modelElement: '$inlineRoot',
|
|
147
|
+
}),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const editor = await waitForTestEditor();
|
|
151
|
+
|
|
152
|
+
expect(editor.model.document.getRoot()?.name).toBe('$inlineRoot');
|
|
153
|
+
});
|
|
138
154
|
});
|
|
139
155
|
|
|
140
156
|
describe('inline', () => {
|
|
@@ -234,10 +250,86 @@ describe('editor component', () => {
|
|
|
234
250
|
},
|
|
235
251
|
});
|
|
236
252
|
|
|
237
|
-
await expect(waitForTestEditor()).rejects.
|
|
253
|
+
await expect(waitForTestEditor()).rejects.toThrow(
|
|
238
254
|
/It looks like not all required root elements are present yet/,
|
|
239
255
|
);
|
|
240
256
|
});
|
|
257
|
+
|
|
258
|
+
it('should be possible to specify root element name using editable config alone', async () => {
|
|
259
|
+
livewireStub.$internal.appendComponentToDOM<EditorSnapshot>({
|
|
260
|
+
name: 'ckeditor5',
|
|
261
|
+
el: createEditorHtmlElement({ editorType: 'decoupled' }),
|
|
262
|
+
canonical: {
|
|
263
|
+
...createEditorSnapshot(),
|
|
264
|
+
preset: createEditorPreset('decoupled'),
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
269
|
+
name: 'ckeditor5-editable',
|
|
270
|
+
el: createEditableHtmlElement(),
|
|
271
|
+
canonical: {
|
|
272
|
+
...createEditableSnapshot('main'),
|
|
273
|
+
modelElement: '$inlineRoot',
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const editor = await waitForTestEditor<DecoupledEditor>();
|
|
278
|
+
|
|
279
|
+
await vi.waitFor(() => {
|
|
280
|
+
expect(editor.model.document.getRoot()?.name).toEqual('$inlineRoot');
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it('should use editable root element name config if both specified', async () => {
|
|
285
|
+
livewireStub.$internal.appendComponentToDOM<EditorSnapshot>({
|
|
286
|
+
name: 'ckeditor5',
|
|
287
|
+
el: createEditorHtmlElement({ editorType: 'decoupled' }),
|
|
288
|
+
canonical: createEditorSnapshot({
|
|
289
|
+
preset: createEditorPreset('decoupled'),
|
|
290
|
+
modelElement: '$miaMia',
|
|
291
|
+
}),
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
295
|
+
name: 'ckeditor5-editable',
|
|
296
|
+
el: createEditableHtmlElement(),
|
|
297
|
+
canonical: {
|
|
298
|
+
...createEditableSnapshot('main'),
|
|
299
|
+
modelElement: '$inlineRoot',
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const editor = await waitForTestEditor<DecoupledEditor>();
|
|
304
|
+
|
|
305
|
+
await vi.waitFor(() => {
|
|
306
|
+
expect(editor.model.document.getRoot()?.name).toEqual('$inlineRoot');
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
it('should use root editor element if editable root name is not specified', async () => {
|
|
311
|
+
livewireStub.$internal.appendComponentToDOM<EditorSnapshot>({
|
|
312
|
+
name: 'ckeditor5',
|
|
313
|
+
el: createEditorHtmlElement({ editorType: 'decoupled' }),
|
|
314
|
+
canonical: createEditorSnapshot({
|
|
315
|
+
preset: createEditorPreset('decoupled'),
|
|
316
|
+
modelElement: '$inlineRoot',
|
|
317
|
+
content: {},
|
|
318
|
+
}),
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
322
|
+
name: 'ckeditor5-editable',
|
|
323
|
+
el: createEditableHtmlElement(),
|
|
324
|
+
canonical: createEditableSnapshot('main'),
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
const editor = await waitForTestEditor<DecoupledEditor>();
|
|
328
|
+
|
|
329
|
+
await vi.waitFor(() => {
|
|
330
|
+
expect(editor.model.document.getRoot()?.name).toEqual('$inlineRoot');
|
|
331
|
+
});
|
|
332
|
+
});
|
|
241
333
|
});
|
|
242
334
|
|
|
243
335
|
describe('balloon', () => {
|
|
@@ -275,6 +367,78 @@ describe('editor component', () => {
|
|
|
275
367
|
expect(editor).toBeInstanceOf(MultiRootEditor);
|
|
276
368
|
});
|
|
277
369
|
|
|
370
|
+
it('should create a multiroot editor with lazy added inline editables', async () => {
|
|
371
|
+
livewireStub.$internal.appendComponentToDOM<EditorSnapshot>({
|
|
372
|
+
name: 'ckeditor5',
|
|
373
|
+
el: createEditorHtmlElement({ editorType: 'multiroot' }),
|
|
374
|
+
canonical: {
|
|
375
|
+
...createEditorSnapshot(),
|
|
376
|
+
preset: createEditorPreset('multiroot'),
|
|
377
|
+
content: {},
|
|
378
|
+
},
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
const editor = await waitForTestEditor();
|
|
382
|
+
|
|
383
|
+
await timeout(500); // Simulate some delay before adding the root.
|
|
384
|
+
|
|
385
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
386
|
+
name: 'ckeditor5-editable',
|
|
387
|
+
el: createEditableHtmlElement(),
|
|
388
|
+
canonical: {
|
|
389
|
+
...createEditableSnapshot('header', 'Head'),
|
|
390
|
+
modelElement: '$inlineRoot',
|
|
391
|
+
},
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
395
|
+
name: 'ckeditor5-editable',
|
|
396
|
+
el: createEditableHtmlElement(),
|
|
397
|
+
canonical: {
|
|
398
|
+
...createEditableSnapshot('footer', 'Footer'),
|
|
399
|
+
modelElement: '$inlineRoot',
|
|
400
|
+
},
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
expect(editor.model.document.getRoot('header')?.name).toEqual('$inlineRoot');
|
|
404
|
+
expect(editor.model.document.getRoot('footer')?.name).toEqual('$inlineRoot');
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it('should create a multiroot editor with initially added inline editables', async () => {
|
|
408
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
409
|
+
name: 'ckeditor5-editable',
|
|
410
|
+
el: createEditableHtmlElement(),
|
|
411
|
+
canonical: {
|
|
412
|
+
...createEditableSnapshot('header', 'Head'),
|
|
413
|
+
modelElement: '$inlineRoot',
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
livewireStub.$internal.appendComponentToDOM({
|
|
418
|
+
name: 'ckeditor5-editable',
|
|
419
|
+
el: createEditableHtmlElement(),
|
|
420
|
+
canonical: {
|
|
421
|
+
...createEditableSnapshot('footer', 'Footer'),
|
|
422
|
+
modelElement: '$inlineRoot',
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
livewireStub.$internal.appendComponentToDOM<EditorSnapshot>({
|
|
427
|
+
name: 'ckeditor5',
|
|
428
|
+
el: createEditorHtmlElement({ editorType: 'multiroot' }),
|
|
429
|
+
canonical: {
|
|
430
|
+
...createEditorSnapshot(),
|
|
431
|
+
preset: createEditorPreset('multiroot'),
|
|
432
|
+
content: {},
|
|
433
|
+
},
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
const editor = await waitForTestEditor();
|
|
437
|
+
|
|
438
|
+
expect(editor.model.document.getRoot('header')?.name).toEqual('$inlineRoot');
|
|
439
|
+
expect(editor.model.document.getRoot('footer')?.name).toEqual('$inlineRoot');
|
|
440
|
+
});
|
|
441
|
+
|
|
278
442
|
it('should wait and for root elements to be present in DOM if they are not (with content=null value)', async () => {
|
|
279
443
|
livewireStub.$internal.appendComponentToDOM<EditorSnapshot>({
|
|
280
444
|
name: 'ckeditor5',
|
|
@@ -34,6 +34,7 @@ export function assignEditorRootsToConfig<C extends EditorConfig>(
|
|
|
34
34
|
...rootKey === 'main' ? config.root : {},
|
|
35
35
|
...rootKey in editables
|
|
36
36
|
? {
|
|
37
|
+
modelElement: editables[rootKey]!.modelElement || '$root',
|
|
37
38
|
...editables[rootKey]!.content !== null && {
|
|
38
39
|
initialData: editables[rootKey]!.content,
|
|
39
40
|
},
|
|
@@ -18,14 +18,16 @@ export function queryAllEditorEditables(editorId: EditorId): Record<string, Edit
|
|
|
18
18
|
.filter(({ name, canonical }) => name === 'ckeditor5-editable' && canonical['editorId'] === editorId)
|
|
19
19
|
.reduce<Record<string, EditableItem>>((acc, { canonical, el }) => {
|
|
20
20
|
const rootName = canonical['rootName'] as string;
|
|
21
|
+
const modelElement = (canonical['modelElement'] || null) as string | null;
|
|
21
22
|
|
|
22
23
|
acc[rootName] = {
|
|
23
24
|
element: el.querySelector<HTMLElement>('[data-cke-editable-content]'),
|
|
24
25
|
content: canonical['content'],
|
|
26
|
+
modelElement,
|
|
25
27
|
};
|
|
26
28
|
|
|
27
29
|
return acc;
|
|
28
|
-
}, Object.create(
|
|
30
|
+
}, Object.create(null));
|
|
29
31
|
|
|
30
32
|
const rootHook = window.Livewire
|
|
31
33
|
.all()
|
|
@@ -38,12 +40,17 @@ export function queryAllEditorEditables(editorId: EditorId): Record<string, Edit
|
|
|
38
40
|
|
|
39
41
|
// v8 ignore next -- @preserve
|
|
40
42
|
const editorContent: Record<string, string> = (rootHook.canonical.content as Record<string, string>) ?? {};
|
|
43
|
+
const rootEditorModelElement = (rootHook.canonical.modelElement || null) as string || null;
|
|
41
44
|
const classicMainElement = document.querySelector<HTMLElement>(`#${editorId}_editor`);
|
|
42
45
|
|
|
43
|
-
if (
|
|
46
|
+
if ('main' in acc) {
|
|
47
|
+
acc['main'].modelElement ??= rootEditorModelElement;
|
|
48
|
+
}
|
|
49
|
+
else if (classicMainElement) {
|
|
44
50
|
acc['main'] = {
|
|
45
51
|
element: classicMainElement,
|
|
46
52
|
content: editorContent['main'] ?? '',
|
|
53
|
+
modelElement: rootEditorModelElement,
|
|
47
54
|
};
|
|
48
55
|
}
|
|
49
56
|
|
|
@@ -53,6 +60,7 @@ export function queryAllEditorEditables(editorId: EditorId): Record<string, Edit
|
|
|
53
60
|
acc[rootName] = {
|
|
54
61
|
...acc[rootName],
|
|
55
62
|
content: acc[rootName].content ?? rootContent,
|
|
63
|
+
modelElement: acc[rootName].modelElement ?? rootEditorModelElement,
|
|
56
64
|
};
|
|
57
65
|
}
|
|
58
66
|
else {
|
|
@@ -60,6 +68,7 @@ export function queryAllEditorEditables(editorId: EditorId): Record<string, Edit
|
|
|
60
68
|
acc[rootName] = {
|
|
61
69
|
element: null,
|
|
62
70
|
content: rootContent,
|
|
71
|
+
modelElement: rootEditorModelElement,
|
|
63
72
|
};
|
|
64
73
|
}
|
|
65
74
|
}
|
|
@@ -74,4 +83,5 @@ export function queryAllEditorEditables(editorId: EditorId): Record<string, Edit
|
|
|
74
83
|
export type EditableItem = {
|
|
75
84
|
element: HTMLElement | null;
|
|
76
85
|
content: string | null;
|
|
86
|
+
modelElement: string | null;
|
|
77
87
|
};
|