]> BookStack Code Mirror - bookstack/blob - resources/js/wysiwyg/lexical/core/nodes/__tests__/unit/LexicalTabNode.test.ts
9831114340def02f0591dd5c76288fe37e161c7a
[bookstack] / resources / js / wysiwyg / lexical / core / nodes / __tests__ / unit / LexicalTabNode.test.ts
1 /**
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  *
7  */
8
9 import {
10   $insertDataTransferForPlainText,
11   $insertDataTransferForRichText,
12 } from '@lexical/clipboard';
13 import {$createListItemNode, $createListNode} from '@lexical/list';
14 import {registerRichText} from '@lexical/rich-text';
15 import {
16   $createParagraphNode,
17   $createRangeSelection,
18   $createTabNode,
19   $createTextNode,
20   $getRoot,
21   $getSelection,
22   $insertNodes,
23   $isElementNode,
24   $isRangeSelection,
25   $isTextNode,
26   $setSelection,
27   KEY_TAB_COMMAND,
28 } from 'lexical';
29
30 import {
31   DataTransferMock,
32   initializeUnitTest,
33   invariant,
34 } from '../../../__tests__/utils';
35 import {$createHeadingNode} from "@lexical/rich-text/LexicalHeadingNode";
36
37 describe('LexicalTabNode tests', () => {
38   initializeUnitTest((testEnv) => {
39     beforeEach(async () => {
40       const {editor} = testEnv;
41       await editor.update(() => {
42         const root = $getRoot();
43         const paragraph = $createParagraphNode();
44         root.append(paragraph);
45         paragraph.select();
46       });
47     });
48
49     test('can paste plain text with tabs and newlines in plain text', async () => {
50       const {editor} = testEnv;
51       const dataTransfer = new DataTransferMock();
52       dataTransfer.setData('text/plain', 'hello\tworld\nhello\tworld');
53       await editor.update(() => {
54         const selection = $getSelection();
55         invariant($isRangeSelection(selection), 'isRangeSelection(selection)');
56         $insertDataTransferForPlainText(dataTransfer, selection);
57       });
58       expect(testEnv.innerHTML).toBe(
59         '<p><span data-lexical-text="true">hello</span><span data-lexical-text="true">\t</span><span data-lexical-text="true">world</span><br><span data-lexical-text="true">hello</span><span data-lexical-text="true">\t</span><span data-lexical-text="true">world</span></p>',
60       );
61     });
62
63     test('can paste plain text with tabs and newlines in rich text', async () => {
64       const {editor} = testEnv;
65       const dataTransfer = new DataTransferMock();
66       dataTransfer.setData('text/plain', 'hello\tworld\nhello\tworld');
67       await editor.update(() => {
68         const selection = $getSelection();
69         invariant($isRangeSelection(selection), 'isRangeSelection(selection)');
70         $insertDataTransferForRichText(dataTransfer, selection, editor);
71       });
72       expect(testEnv.innerHTML).toBe(
73         '<p><span data-lexical-text="true">hello</span><span data-lexical-text="true">\t</span><span data-lexical-text="true">world</span></p><p><span data-lexical-text="true">hello</span><span data-lexical-text="true">\t</span><span data-lexical-text="true">world</span></p>',
74       );
75     });
76
77     // TODO fixme
78     // test('can paste HTML with tabs and new lines #4429', async () => {
79     //       const {editor} = testEnv;
80     //       const dataTransfer = new DataTransferMock();
81     //       // https://codepen.io/zurfyx/pen/bGmrzMR
82     //       dataTransfer.setData(
83     //         'text/html',
84     //         `<meta charset='utf-8'><span style="color: rgb(0, 0, 0); font-family: Times; font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">hello  world
85     // hello    world</span>`,
86     //       );
87     //       await editor.update(() => {
88     //         const selection = $getSelection();
89     //         invariant($isRangeSelection(selection), 'isRangeSelection(selection)');
90     //         $insertDataTransferForRichText(dataTransfer, selection, editor);
91     //       });
92     //       expect(testEnv.innerHTML).toBe(
93     //         '<p><span data-lexical-text="true">hello</span><span data-lexical-text="true">\t</span><span data-lexical-text="true">world</span><br><span data-lexical-text="true">hello</span><span data-lexical-text="true">\t</span><span data-lexical-text="true">world</span></p>',
94     //       );
95     // });
96
97     test('can paste HTML with tabs and new lines (2)', async () => {
98       const {editor} = testEnv;
99       const dataTransfer = new DataTransferMock();
100       // GDoc 2-liner hello\tworld (like previous test)
101       dataTransfer.setData(
102         'text/html',
103         `<meta charset='utf-8'><meta charset="utf-8"><b style="font-weight:normal;" id="docs-internal-guid-123"><p style="line-height:1.38;margin-left: 36pt;margin-top:0pt;margin-bottom:0pt;"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Hello</span><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;"><span class="Apple-tab-span" style="white-space:pre;">        </span></span><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">world</span></p><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Hello</span><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;"><span class="Apple-tab-span" style="white-space:pre;">       </span></span><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">world</span></b>`,
104       );
105       await editor.update(() => {
106         const selection = $getSelection();
107         invariant($isRangeSelection(selection), 'isRangeSelection(selection)');
108         $insertDataTransferForRichText(dataTransfer, selection, editor);
109       });
110       expect(testEnv.innerHTML).toBe(
111         '<p><span style="color: rgb(0, 0, 0);" data-lexical-text="true">Hello</span><span data-lexical-text="true">\t</span><span style="color: rgb(0, 0, 0);" data-lexical-text="true">world</span></p><p><span style="color: rgb(0, 0, 0);" data-lexical-text="true">Hello</span><span data-lexical-text="true">\t</span><span style="color: rgb(0, 0, 0);" data-lexical-text="true">world</span></p>',
112       );
113     });
114
115     test('can type between two (leaf nodes) canInsertBeforeAfter false', async () => {
116       const {editor} = testEnv;
117       await editor.update(() => {
118         const tab1 = $createTabNode();
119         const tab2 = $createTabNode();
120         $insertNodes([tab1, tab2]);
121         tab1.select(1, 1);
122         $getSelection()!.insertText('f');
123       });
124       expect(testEnv.innerHTML).toBe(
125         '<p><span data-lexical-text="true">\t</span><span data-lexical-text="true">f</span><span data-lexical-text="true">\t</span></p>',
126       );
127     });
128   });
129 });