@fluidframework/react 2.90.0 → 2.91.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/CHANGELOG.md +4 -0
- package/api-report/react.alpha.api.md +8 -8
- package/lib/reactSharedTreeView.d.ts +6 -6
- package/lib/reactSharedTreeView.d.ts.map +1 -1
- package/lib/reactSharedTreeView.js +16 -18
- package/lib/reactSharedTreeView.js.map +1 -1
- package/lib/test/reactSharedTreeView.spec.js +3 -3
- package/lib/test/reactSharedTreeView.spec.js.map +1 -1
- package/lib/test/text/textEditor.test.js +100 -44
- package/lib/test/text/textEditor.test.js.map +1 -1
- package/lib/test/useObservation.spec.js +8 -8
- package/lib/test/useObservation.spec.js.map +1 -1
- package/lib/test/useTree.spec.js +15 -15
- package/lib/test/useTree.spec.js.map +1 -1
- package/lib/text/formatted/quillFormattedView.d.ts +14 -2
- package/lib/text/formatted/quillFormattedView.d.ts.map +1 -1
- package/lib/text/formatted/quillFormattedView.js +165 -71
- package/lib/text/formatted/quillFormattedView.js.map +1 -1
- package/lib/text/plain/plainTextView.d.ts +2 -2
- package/lib/text/plain/plainTextView.d.ts.map +1 -1
- package/lib/text/plain/plainTextView.js +16 -21
- package/lib/text/plain/plainTextView.js.map +1 -1
- package/lib/text/plain/quillView.d.ts +2 -2
- package/lib/text/plain/quillView.d.ts.map +1 -1
- package/lib/text/plain/quillView.js +15 -21
- package/lib/text/plain/quillView.js.map +1 -1
- package/lib/useObservation.js +6 -6
- package/lib/useObservation.js.map +1 -1
- package/lib/useTree.d.ts +7 -7
- package/lib/useTree.d.ts.map +1 -1
- package/lib/useTree.js +6 -6
- package/lib/useTree.js.map +1 -1
- package/package.json +14 -13
- package/react.test-files.tar +0 -0
- package/src/reactSharedTreeView.tsx +11 -13
- package/src/text/formatted/quillFormattedView.tsx +176 -58
- package/src/text/plain/plainTextView.tsx +6 -6
- package/src/text/plain/quillView.tsx +6 -6
- package/src/useObservation.ts +6 -6
- package/src/useTree.ts +19 -12
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
2
|
/*!
|
|
2
3
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
4
|
* Licensed under the MIT License.
|
|
@@ -9,9 +10,9 @@ import { independentView, TextAsTree } from "@fluidframework/tree/internal";
|
|
|
9
10
|
import { render } from "@testing-library/react";
|
|
10
11
|
import globalJsdom from "global-jsdom";
|
|
11
12
|
import DeltaPackage from "quill-delta";
|
|
12
|
-
import
|
|
13
|
+
import { createRef } from "react";
|
|
13
14
|
import { toPropTreeNode } from "../../propNode.js";
|
|
14
|
-
import { clipboardFormatMatcher, FormattedTextAsTree, FormattedMainView, parseCssFontFamily, parseCssFontSize,
|
|
15
|
+
import { clipboardFormatMatcher, FormattedTextAsTree, FormattedMainView, parseCssFontFamily, parseCssFontSize, parseLineTag, buildDeltaFromTree,
|
|
15
16
|
// Allow import of files being tested
|
|
16
17
|
// eslint-disable-next-line import-x/no-internal-modules
|
|
17
18
|
} from "../../text/formatted/quillFormattedView.js";
|
|
@@ -69,19 +70,19 @@ describe("textEditor", () => {
|
|
|
69
70
|
const ViewComponent = view.component;
|
|
70
71
|
it("renders MainView with editor container", () => {
|
|
71
72
|
const text = TextAsTree.Tree.fromString("");
|
|
72
|
-
const content =
|
|
73
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
73
74
|
const rendered = render(content, { reactStrictMode });
|
|
74
75
|
assert.match(rendered.baseElement.textContent ?? "", /Collaborative Text Editor/);
|
|
75
76
|
});
|
|
76
77
|
it("renders MainView with initial text content", () => {
|
|
77
78
|
const text = TextAsTree.Tree.fromString("Hello World");
|
|
78
|
-
const content =
|
|
79
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
79
80
|
const rendered = render(content, { reactStrictMode });
|
|
80
81
|
assert.match(rendered.baseElement.textContent ?? "", /Hello World/);
|
|
81
82
|
});
|
|
82
83
|
it("invalidates view when tree is mutated", () => {
|
|
83
84
|
const text = TextAsTree.Tree.fromString("Hello");
|
|
84
|
-
const content =
|
|
85
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
85
86
|
const rendered = render(content, { reactStrictMode });
|
|
86
87
|
// Mutate the tree by inserting text
|
|
87
88
|
text.insertAt(5, " World");
|
|
@@ -91,7 +92,7 @@ describe("textEditor", () => {
|
|
|
91
92
|
});
|
|
92
93
|
it("invalidates view when text is removed", () => {
|
|
93
94
|
const text = TextAsTree.Tree.fromString("Hello World");
|
|
94
|
-
const content =
|
|
95
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
95
96
|
const rendered = render(content, { reactStrictMode });
|
|
96
97
|
// Mutate the tree by removing " World" (indices 5 to 11)
|
|
97
98
|
text.removeRange(5, 11);
|
|
@@ -103,7 +104,7 @@ describe("textEditor", () => {
|
|
|
103
104
|
});
|
|
104
105
|
it("invalidates view when text is cleared and replaced", () => {
|
|
105
106
|
const text = TextAsTree.Tree.fromString("Original");
|
|
106
|
-
const content =
|
|
107
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
107
108
|
const rendered = render(content, { reactStrictMode });
|
|
108
109
|
// Clear all text
|
|
109
110
|
const length = [...text.characters()].length;
|
|
@@ -121,13 +122,13 @@ describe("textEditor", () => {
|
|
|
121
122
|
it("renders MainView with surrogate pair characters", () => {
|
|
122
123
|
// 😀 is a surrogate pair: "😀".length === 2, but [..."😀"].length === 1
|
|
123
124
|
const text = TextAsTree.Tree.fromString("Hello 😀 World");
|
|
124
|
-
const content =
|
|
125
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
125
126
|
const rendered = render(content, { reactStrictMode });
|
|
126
127
|
assert.match(rendered.baseElement.textContent ?? "", /Hello 😀 World/);
|
|
127
128
|
});
|
|
128
129
|
it("inserts text after surrogate pair characters", () => {
|
|
129
130
|
const text = TextAsTree.Tree.fromString("A😀B");
|
|
130
|
-
const content =
|
|
131
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
131
132
|
const rendered = render(content, { reactStrictMode });
|
|
132
133
|
// Insert after the emoji (index 2 in character count: A, 😀, B)
|
|
133
134
|
text.insertAt(2, "X");
|
|
@@ -136,7 +137,7 @@ describe("textEditor", () => {
|
|
|
136
137
|
});
|
|
137
138
|
it("removes surrogate pair characters", () => {
|
|
138
139
|
const text = TextAsTree.Tree.fromString("A😀B");
|
|
139
|
-
const content =
|
|
140
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
140
141
|
const rendered = render(content, { reactStrictMode });
|
|
141
142
|
// Remove the emoji (index 1, length 1 in character count)
|
|
142
143
|
text.removeRange(1, 2);
|
|
@@ -147,7 +148,7 @@ describe("textEditor", () => {
|
|
|
147
148
|
});
|
|
148
149
|
it("handles multiple surrogate pair characters", () => {
|
|
149
150
|
const text = TextAsTree.Tree.fromString("👋🌍🎉");
|
|
150
|
-
const content =
|
|
151
|
+
const content = _jsx(ViewComponent, { root: toPropTreeNode(text) });
|
|
151
152
|
const rendered = render(content, { reactStrictMode });
|
|
152
153
|
// Insert between emojis
|
|
153
154
|
text.insertAt(2, "!");
|
|
@@ -166,19 +167,19 @@ describe("textEditor", () => {
|
|
|
166
167
|
describe(`StrictMode: ${reactStrictMode}`, () => {
|
|
167
168
|
it("renders FormattedMainView with editor container", () => {
|
|
168
169
|
const { tree } = createFormattedTreeView();
|
|
169
|
-
const content =
|
|
170
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(tree) });
|
|
170
171
|
const rendered = render(content, { reactStrictMode });
|
|
171
172
|
assert.match(rendered.baseElement.textContent ?? "", /Collaborative Formatted Text Editor/);
|
|
172
173
|
});
|
|
173
174
|
it("renders FormattedMainView with initial text content", () => {
|
|
174
175
|
const { tree } = createFormattedTreeView("Hello World");
|
|
175
|
-
const content =
|
|
176
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(tree) });
|
|
176
177
|
const rendered = render(content, { reactStrictMode });
|
|
177
178
|
assert.match(rendered.baseElement.textContent ?? "", /Hello World/);
|
|
178
179
|
});
|
|
179
180
|
it("invalidates view when tree is mutated", () => {
|
|
180
181
|
const { tree: text } = createFormattedTreeView("Hello");
|
|
181
|
-
const content =
|
|
182
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
182
183
|
const rendered = render(content, { reactStrictMode });
|
|
183
184
|
// Mutate the tree by inserting text
|
|
184
185
|
text.insertAt(5, " World");
|
|
@@ -188,7 +189,7 @@ describe("textEditor", () => {
|
|
|
188
189
|
});
|
|
189
190
|
it("invalidates view when text is removed", () => {
|
|
190
191
|
const { tree: text } = createFormattedTreeView("Hello World");
|
|
191
|
-
const content =
|
|
192
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
192
193
|
const rendered = render(content, { reactStrictMode });
|
|
193
194
|
// Mutate the tree by removing " World" (indices 5 to 11)
|
|
194
195
|
text.removeRange(5, 11);
|
|
@@ -200,7 +201,7 @@ describe("textEditor", () => {
|
|
|
200
201
|
});
|
|
201
202
|
it("invalidates view when text is cleared and replaced", () => {
|
|
202
203
|
const { tree: text } = createFormattedTreeView("Original");
|
|
203
|
-
const content =
|
|
204
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
204
205
|
const rendered = render(content, { reactStrictMode });
|
|
205
206
|
// Clear all text
|
|
206
207
|
const length = [...text.characters()].length;
|
|
@@ -218,13 +219,13 @@ describe("textEditor", () => {
|
|
|
218
219
|
it("renders FormattedMainView with surrogate pair characters", () => {
|
|
219
220
|
// 😀 is a surrogate pair: "😀".length === 2, but [..."😀"].length === 1
|
|
220
221
|
const { tree: text } = createFormattedTreeView("Hello 😀 World");
|
|
221
|
-
const content =
|
|
222
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
222
223
|
const rendered = render(content, { reactStrictMode });
|
|
223
224
|
assert.match(rendered.baseElement.textContent ?? "", /Hello 😀 World/);
|
|
224
225
|
});
|
|
225
226
|
it("inserts text after surrogate pair characters", () => {
|
|
226
227
|
const { tree: text } = createFormattedTreeView("A😀B");
|
|
227
|
-
const content =
|
|
228
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
228
229
|
const rendered = render(content, { reactStrictMode });
|
|
229
230
|
// Insert after the emoji (index 2 in character count: A, 😀, B)
|
|
230
231
|
text.insertAt(2, "X");
|
|
@@ -233,7 +234,7 @@ describe("textEditor", () => {
|
|
|
233
234
|
});
|
|
234
235
|
it("removes surrogate pair characters", () => {
|
|
235
236
|
const { tree: text } = createFormattedTreeView("A😀B");
|
|
236
|
-
const content =
|
|
237
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
237
238
|
const rendered = render(content, { reactStrictMode });
|
|
238
239
|
// Remove the emoji (index 1, length 1 in character count)
|
|
239
240
|
text.removeRange(1, 2);
|
|
@@ -244,7 +245,7 @@ describe("textEditor", () => {
|
|
|
244
245
|
});
|
|
245
246
|
it("handles multiple surrogate pair characters", () => {
|
|
246
247
|
const { tree: text } = createFormattedTreeView("👋🌍🎉");
|
|
247
|
-
const content =
|
|
248
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
248
249
|
const rendered = render(content, { reactStrictMode });
|
|
249
250
|
// Insert between emojis
|
|
250
251
|
text.insertAt(2, "!");
|
|
@@ -271,7 +272,7 @@ describe("textEditor", () => {
|
|
|
271
272
|
describe(`StrictMode: ${reactStrictMode}`, () => {
|
|
272
273
|
it("delete on empty string does not throw", () => {
|
|
273
274
|
const { tree: text } = createFormattedTreeView();
|
|
274
|
-
const content =
|
|
275
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
275
276
|
const rendered = render(content, { reactStrictMode });
|
|
276
277
|
assert.doesNotThrow(() => {
|
|
277
278
|
text.removeRange(0, 0);
|
|
@@ -281,7 +282,7 @@ describe("textEditor", () => {
|
|
|
281
282
|
describe("bold", () => {
|
|
282
283
|
it("inserts bold text and renders with <strong> tag", () => {
|
|
283
284
|
const { tree: text } = createFormattedTreeView("Hello");
|
|
284
|
-
const content =
|
|
285
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
285
286
|
const rendered = render(content, { reactStrictMode });
|
|
286
287
|
assert.ok(!rendered.container.querySelector("strong"), "Initially: no <strong>");
|
|
287
288
|
text.defaultFormat = new FormattedTextAsTree.CharacterFormat({
|
|
@@ -309,7 +310,7 @@ describe("textEditor", () => {
|
|
|
309
310
|
text.insertAt(0, "BOLD");
|
|
310
311
|
text.defaultFormat = createPlainFormat();
|
|
311
312
|
text.insertAt(4, "plain");
|
|
312
|
-
const content =
|
|
313
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
313
314
|
const rendered = render(content, { reactStrictMode });
|
|
314
315
|
assert.ok(rendered.container.querySelector("strong"), "Initially: has <strong>");
|
|
315
316
|
text.removeRange(0, 4);
|
|
@@ -318,7 +319,7 @@ describe("textEditor", () => {
|
|
|
318
319
|
});
|
|
319
320
|
it("applies bold via formatRange", () => {
|
|
320
321
|
const { tree: text } = createFormattedTreeView("Hello World");
|
|
321
|
-
const content =
|
|
322
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
322
323
|
const rendered = render(content, { reactStrictMode });
|
|
323
324
|
text.formatRange(6, 11, { bold: true });
|
|
324
325
|
rendered.rerender(content);
|
|
@@ -330,7 +331,7 @@ describe("textEditor", () => {
|
|
|
330
331
|
describe("italic", () => {
|
|
331
332
|
it("inserts italic text and renders with <em> tag", () => {
|
|
332
333
|
const { tree: text } = createFormattedTreeView("Hello");
|
|
333
|
-
const content =
|
|
334
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
334
335
|
const rendered = render(content, { reactStrictMode });
|
|
335
336
|
assert.ok(!rendered.container.querySelector("em"), "Initially: no <em>");
|
|
336
337
|
text.defaultFormat = new FormattedTextAsTree.CharacterFormat({
|
|
@@ -358,7 +359,7 @@ describe("textEditor", () => {
|
|
|
358
359
|
text.insertAt(0, "ITAL");
|
|
359
360
|
text.defaultFormat = createPlainFormat();
|
|
360
361
|
text.insertAt(4, "plain");
|
|
361
|
-
const content =
|
|
362
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
362
363
|
const rendered = render(content, { reactStrictMode });
|
|
363
364
|
assert.ok(rendered.container.querySelector("em"), "Initially: has <em>");
|
|
364
365
|
text.removeRange(0, 4);
|
|
@@ -367,7 +368,7 @@ describe("textEditor", () => {
|
|
|
367
368
|
});
|
|
368
369
|
it("applies italic via formatRange", () => {
|
|
369
370
|
const { tree: text } = createFormattedTreeView("Hello World");
|
|
370
|
-
const content =
|
|
371
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
371
372
|
const rendered = render(content, { reactStrictMode });
|
|
372
373
|
text.formatRange(6, 11, { italic: true });
|
|
373
374
|
rendered.rerender(content);
|
|
@@ -379,7 +380,7 @@ describe("textEditor", () => {
|
|
|
379
380
|
describe("underline", () => {
|
|
380
381
|
it("inserts underlined text and renders with <u> tag", () => {
|
|
381
382
|
const { tree: text } = createFormattedTreeView("Hello");
|
|
382
|
-
const content =
|
|
383
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
383
384
|
const rendered = render(content, { reactStrictMode });
|
|
384
385
|
assert.ok(!rendered.container.querySelector("u"), "Initially: no <u>");
|
|
385
386
|
text.defaultFormat = new FormattedTextAsTree.CharacterFormat({
|
|
@@ -407,7 +408,7 @@ describe("textEditor", () => {
|
|
|
407
408
|
text.insertAt(0, "UNDER");
|
|
408
409
|
text.defaultFormat = createPlainFormat();
|
|
409
410
|
text.insertAt(5, "plain");
|
|
410
|
-
const content =
|
|
411
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
411
412
|
const rendered = render(content, { reactStrictMode });
|
|
412
413
|
assert.ok(rendered.container.querySelector("u"), "Initially: has <u>");
|
|
413
414
|
text.removeRange(0, 5);
|
|
@@ -416,7 +417,7 @@ describe("textEditor", () => {
|
|
|
416
417
|
});
|
|
417
418
|
it("applies underline via formatRange", () => {
|
|
418
419
|
const { tree: text } = createFormattedTreeView("Hello World");
|
|
419
|
-
const content =
|
|
420
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
420
421
|
const rendered = render(content, { reactStrictMode });
|
|
421
422
|
text.formatRange(6, 11, { underline: true });
|
|
422
423
|
rendered.rerender(content);
|
|
@@ -428,7 +429,7 @@ describe("textEditor", () => {
|
|
|
428
429
|
describe("size", () => {
|
|
429
430
|
it("inserts huge size text and renders with .ql-size-huge", () => {
|
|
430
431
|
const { tree: text } = createFormattedTreeView("Hello");
|
|
431
|
-
const content =
|
|
432
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
432
433
|
const rendered = render(content, { reactStrictMode });
|
|
433
434
|
assert.ok(!rendered.container.querySelector(".ql-size-huge"), "Initially: no .ql-size-huge");
|
|
434
435
|
text.defaultFormat = new FormattedTextAsTree.CharacterFormat({
|
|
@@ -456,7 +457,7 @@ describe("textEditor", () => {
|
|
|
456
457
|
text.insertAt(0, "HUGE");
|
|
457
458
|
text.defaultFormat = createPlainFormat();
|
|
458
459
|
text.insertAt(4, "plain");
|
|
459
|
-
const content =
|
|
460
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
460
461
|
const rendered = render(content, { reactStrictMode });
|
|
461
462
|
assert.ok(rendered.container.querySelector(".ql-size-huge"), "Initially: has .ql-size-huge");
|
|
462
463
|
text.removeRange(0, 4);
|
|
@@ -465,7 +466,7 @@ describe("textEditor", () => {
|
|
|
465
466
|
});
|
|
466
467
|
it("applies size via formatRange", () => {
|
|
467
468
|
const { tree: text } = createFormattedTreeView("Hello World");
|
|
468
|
-
const content =
|
|
469
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
469
470
|
const rendered = render(content, { reactStrictMode });
|
|
470
471
|
text.formatRange(6, 11, { size: 24 });
|
|
471
472
|
rendered.rerender(content);
|
|
@@ -477,7 +478,7 @@ describe("textEditor", () => {
|
|
|
477
478
|
describe("font", () => {
|
|
478
479
|
it("inserts monospace font text and renders with .ql-font-monospace", () => {
|
|
479
480
|
const { tree: text } = createFormattedTreeView("Hello");
|
|
480
|
-
const content =
|
|
481
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
481
482
|
const rendered = render(content, { reactStrictMode });
|
|
482
483
|
assert.ok(!rendered.container.querySelector(".ql-font-monospace"), "Initially: no .ql-font-monospace");
|
|
483
484
|
text.defaultFormat = new FormattedTextAsTree.CharacterFormat({
|
|
@@ -505,7 +506,7 @@ describe("textEditor", () => {
|
|
|
505
506
|
text.insertAt(0, "MONO");
|
|
506
507
|
text.defaultFormat = createPlainFormat();
|
|
507
508
|
text.insertAt(4, "plain");
|
|
508
|
-
const content =
|
|
509
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
509
510
|
const rendered = render(content, { reactStrictMode });
|
|
510
511
|
assert.ok(rendered.container.querySelector(".ql-font-monospace"), "Initially: has .ql-font-monospace");
|
|
511
512
|
text.removeRange(0, 4);
|
|
@@ -514,7 +515,7 @@ describe("textEditor", () => {
|
|
|
514
515
|
});
|
|
515
516
|
it("applies font via formatRange", () => {
|
|
516
517
|
const { tree: text } = createFormattedTreeView("Hello World");
|
|
517
|
-
const content =
|
|
518
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
518
519
|
const rendered = render(content, { reactStrictMode });
|
|
519
520
|
text.formatRange(6, 11, { font: "monospace" });
|
|
520
521
|
rendered.rerender(content);
|
|
@@ -534,8 +535,8 @@ describe("textEditor", () => {
|
|
|
534
535
|
const treeView = createFormattedTreeViewWithEvents();
|
|
535
536
|
const text = treeView.root;
|
|
536
537
|
const undoRedo = new UndoRedoStacks(treeView.events);
|
|
537
|
-
const editorRef =
|
|
538
|
-
const content = (
|
|
538
|
+
const editorRef = createRef();
|
|
539
|
+
const content = (_jsx(FormattedMainView, { ref: editorRef, root: toPropTreeNode(text), undoRedo: undoRedo }));
|
|
539
540
|
const rendered = render(content, { reactStrictMode });
|
|
540
541
|
// Insert a character
|
|
541
542
|
text.insertAt(0, "A");
|
|
@@ -555,8 +556,8 @@ describe("textEditor", () => {
|
|
|
555
556
|
const treeView = createFormattedTreeViewWithEvents();
|
|
556
557
|
const text = treeView.root;
|
|
557
558
|
const undoRedo = new UndoRedoStacks(treeView.events);
|
|
558
|
-
const editorRef =
|
|
559
|
-
const content = (
|
|
559
|
+
const editorRef = createRef();
|
|
560
|
+
const content = (_jsx(FormattedMainView, { ref: editorRef, root: toPropTreeNode(text), undoRedo: undoRedo }));
|
|
560
561
|
const rendered = render(content, { reactStrictMode });
|
|
561
562
|
// Insert a character
|
|
562
563
|
text.insertAt(0, "B");
|
|
@@ -577,8 +578,8 @@ describe("textEditor", () => {
|
|
|
577
578
|
const treeView = createFormattedTreeViewWithEvents();
|
|
578
579
|
const text = treeView.root;
|
|
579
580
|
const undoRedo = new UndoRedoStacks(treeView.events);
|
|
580
|
-
const editorRef =
|
|
581
|
-
const content = (
|
|
581
|
+
const editorRef = createRef();
|
|
582
|
+
const content = (_jsx(FormattedMainView, { ref: editorRef, root: toPropTreeNode(text), undoRedo: undoRedo }));
|
|
582
583
|
const rendered = render(content, { reactStrictMode });
|
|
583
584
|
// Two operations in one transaction
|
|
584
585
|
TreeAlpha.branch(text)?.runTransaction(() => {
|
|
@@ -668,7 +669,7 @@ describe("textEditor", () => {
|
|
|
668
669
|
describe(`StrictMode: ${reactStrictMode}`, () => {
|
|
669
670
|
it("applies bold to joined emoji and removes it preserving text", () => {
|
|
670
671
|
const { tree: text } = createFormattedTreeView(`Test ${joinedEmoji} Text`);
|
|
671
|
-
const content =
|
|
672
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
672
673
|
const rendered = render(content, { reactStrictMode });
|
|
673
674
|
const emojiStart = 5; // "Test " is 5 chars
|
|
674
675
|
const emojiLength = [...joinedEmoji].length;
|
|
@@ -683,7 +684,7 @@ describe("textEditor", () => {
|
|
|
683
684
|
});
|
|
684
685
|
it("applies size to joined emoji and removes it preserving text", () => {
|
|
685
686
|
const { tree: text } = createFormattedTreeView(`Test ${joinedEmoji} Text`);
|
|
686
|
-
const content =
|
|
687
|
+
const content = _jsx(FormattedMainView, { root: toPropTreeNode(text) });
|
|
687
688
|
const rendered = render(content, { reactStrictMode });
|
|
688
689
|
const emojiStart = 5;
|
|
689
690
|
const emojiLength = [...joinedEmoji].length;
|
|
@@ -699,6 +700,61 @@ describe("textEditor", () => {
|
|
|
699
700
|
});
|
|
700
701
|
}
|
|
701
702
|
});
|
|
703
|
+
describe("parseLineTag", () => {
|
|
704
|
+
it("return lineTag for valid header", () => {
|
|
705
|
+
const result = parseLineTag({ header: 1 });
|
|
706
|
+
assert.ok(result, "Expected a line tag for header 1");
|
|
707
|
+
assert.equal(result.value, "h1", "Expected tag to be h1");
|
|
708
|
+
});
|
|
709
|
+
it("returns lineTag for valid bullet list", () => {
|
|
710
|
+
const result = parseLineTag({ list: "bullet" });
|
|
711
|
+
assert.ok(result, "Expected a line tag for bullet list");
|
|
712
|
+
assert.equal(result.value, "li", "Expected tag to be li)");
|
|
713
|
+
});
|
|
714
|
+
// Tests for unsupported parameters - should return default header ("h5"), not throw an error.
|
|
715
|
+
// Also used for when formatting is stripped from a newline and it becomes a default newline
|
|
716
|
+
it("returns undefined for unsupported parameter", () => {
|
|
717
|
+
const result = parseLineTag({ header: 7 });
|
|
718
|
+
assert.ok(result, "Expected a line tag for header 5");
|
|
719
|
+
assert.equal(result.value, "h5", "Expected tag to be h5 for unsupported header level");
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
// tests quillFormattedview conversion that feeds into quill delta generation,
|
|
723
|
+
// specifically for line atoms which have special handling for headers and lists.
|
|
724
|
+
// Quill always has a trailing newline, so these tests set up the string with a newline,
|
|
725
|
+
// then replace it with a line atom with the appropriate tag.
|
|
726
|
+
describe("buildDeltaFromTree with line Atoms", () => {
|
|
727
|
+
it("emits header attribute for h1 line atom", () => {
|
|
728
|
+
const { tree } = createFormattedTreeView("Hello\n");
|
|
729
|
+
tree.removeRange(5, 6);
|
|
730
|
+
tree.insertWithFormattingAt(5, [
|
|
731
|
+
new FormattedTextAsTree.StringAtom({
|
|
732
|
+
content: new FormattedTextAsTree.StringLineAtom({
|
|
733
|
+
tag: FormattedTextAsTree.LineTag("h1"),
|
|
734
|
+
}),
|
|
735
|
+
format: createPlainFormat(),
|
|
736
|
+
}),
|
|
737
|
+
]);
|
|
738
|
+
const ops = buildDeltaFromTree(tree);
|
|
739
|
+
const lineOp = ops.find((op) => op.insert === "\n" && op.attributes?.header === 1);
|
|
740
|
+
assert.ok(lineOp, "Expected { insert : `\\n`, attributes: { header: 1 } } in delta");
|
|
741
|
+
});
|
|
742
|
+
it("emits header attribute for li line atom", () => {
|
|
743
|
+
const { tree } = createFormattedTreeView("item\n");
|
|
744
|
+
tree.removeRange(4, 5);
|
|
745
|
+
tree.insertWithFormattingAt(4, [
|
|
746
|
+
new FormattedTextAsTree.StringAtom({
|
|
747
|
+
content: new FormattedTextAsTree.StringLineAtom({
|
|
748
|
+
tag: FormattedTextAsTree.LineTag("li"),
|
|
749
|
+
}),
|
|
750
|
+
format: createPlainFormat(),
|
|
751
|
+
}),
|
|
752
|
+
]);
|
|
753
|
+
const ops = buildDeltaFromTree(tree);
|
|
754
|
+
const lineOp = ops.find((op) => op.insert === "\n" && op.attributes?.list === "bullet");
|
|
755
|
+
assert.ok(lineOp, "Expected { insert : `\\n`, attributes: { list: 'bullet' } } in delta");
|
|
756
|
+
});
|
|
757
|
+
});
|
|
702
758
|
});
|
|
703
759
|
});
|
|
704
760
|
//# sourceMappingURL=textEditor.test.js.map
|