@fluidframework/react 2.91.0 → 2.92.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/lib/alpha.d.ts +1 -1
- package/lib/beta.d.ts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/test/text/textEditor.test.js +88 -731
- package/lib/test/text/textEditor.test.js.map +1 -1
- package/lib/text/index.d.ts +3 -2
- package/lib/text/index.d.ts.map +1 -1
- package/lib/text/index.js +1 -2
- package/lib/text/index.js.map +1 -1
- package/lib/text/plain/index.d.ts +1 -1
- package/lib/text/plain/index.d.ts.map +1 -1
- package/lib/text/plain/index.js +1 -1
- package/lib/text/plain/index.js.map +1 -1
- package/lib/text/plain/plainTextView.d.ts +5 -2
- package/lib/text/plain/plainTextView.d.ts.map +1 -1
- package/lib/text/plain/plainTextView.js.map +1 -1
- package/lib/text/plain/plainUtils.d.ts +1 -0
- package/lib/text/plain/plainUtils.d.ts.map +1 -1
- package/lib/text/plain/plainUtils.js +1 -0
- package/lib/text/plain/plainUtils.js.map +1 -1
- package/package.json +14 -16
- package/react.test-files.tar +0 -0
- package/src/index.ts +1 -9
- package/src/text/index.ts +3 -10
- package/src/text/plain/index.ts +1 -1
- package/src/text/plain/plainTextView.tsx +2 -2
- package/src/text/plain/plainUtils.ts +1 -0
- package/tsconfig.json +0 -6
- package/lib/test/mochaHooks.js +0 -13
- package/lib/test/mochaHooks.js.map +0 -1
- package/lib/text/formatted/index.d.ts +0 -6
- package/lib/text/formatted/index.d.ts.map +0 -1
- package/lib/text/formatted/index.js +0 -6
- package/lib/text/formatted/index.js.map +0 -1
- package/lib/text/formatted/quillFormattedView.d.ts +0 -66
- package/lib/text/formatted/quillFormattedView.d.ts.map +0 -1
- package/lib/text/formatted/quillFormattedView.js +0 -520
- package/lib/text/formatted/quillFormattedView.js.map +0 -1
- package/lib/text/plain/quillView.d.ts +0 -22
- package/lib/text/plain/quillView.d.ts.map +0 -1
- package/lib/text/plain/quillView.js +0 -106
- package/lib/text/plain/quillView.js.map +0 -1
- package/src/text/formatted/index.ts +0 -11
- package/src/text/formatted/quillFormattedView.tsx +0 -627
- package/src/text/plain/quillView.tsx +0 -149
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textEditor.test.js","sourceRoot":"","sources":["../../../src/test/text/textEditor.test.tsx"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { TreeViewConfiguration, type TreeView } from \"@fluidframework/tree\";\nimport { TreeAlpha } from \"@fluidframework/tree/alpha\";\nimport { independentView, TextAsTree } from \"@fluidframework/tree/internal\";\nimport { render } from \"@testing-library/react\";\nimport globalJsdom from \"global-jsdom\";\nimport DeltaPackage from \"quill-delta\";\nimport { createRef, type FC } from \"react\";\n\nimport { toPropTreeNode } from \"../../propNode.js\";\nimport {\n\tclipboardFormatMatcher,\n\tFormattedTextAsTree,\n\tFormattedMainView,\n\ttype FormattedEditorHandle,\n\tparseCssFontFamily,\n\tparseCssFontSize,\n\tparseLineTag,\n\tbuildDeltaFromTree,\n\t// Allow import of files being tested\n\t// eslint-disable-next-line import-x/no-internal-modules\n} from \"../../text/formatted/quillFormattedView.js\";\nimport {\n\tPlainTextMainView,\n\tQuillMainView,\n\ttype MainViewProps,\n\t// Allow import of files being tested\n\t// eslint-disable-next-line import-x/no-internal-modules\n} from \"../../text/plain/index.js\";\nimport { UndoRedoStacks } from \"../../undoRedo.js\";\n\n// Workaround for quill-delta's export style not working well with node16 module resolution.\ntype Delta = DeltaPackage.default;\nconst Delta = DeltaPackage.default;\n\n// Configuration for creating formatted text views\nconst formattedTreeConfig = new TreeViewConfiguration({ schema: FormattedTextAsTree.Tree });\n\n/**\n * Creates a TreeView for formatted text, initialized with the provided initial value.\n */\nfunction createFormattedTreeView(initialValue = \"\"): {\n\ttree: FormattedTextAsTree.Tree;\n} {\n\tconst treeView = independentView(formattedTreeConfig);\n\ttreeView.initialize(FormattedTextAsTree.Tree.fromString(initialValue));\n\treturn { tree: treeView.root };\n}\n\n/**\n * Creates a TreeView for formatted text with events access (needed for undo/redo tests).\n */\nfunction createFormattedTreeViewWithEvents(\n\tinitialValue = \"\",\n): TreeView<typeof FormattedTextAsTree.Tree> {\n\tconst treeView = independentView(formattedTreeConfig);\n\ttreeView.initialize(FormattedTextAsTree.Tree.fromString(initialValue));\n\treturn treeView;\n}\n\nconst views: { name: string; component: FC<MainViewProps> }[] = [\n\t{ name: \"Quill\", component: QuillMainView },\n\t{ name: \"Plain TextArea\", component: PlainTextMainView },\n];\n\n// TODO add collaboration tests when rich formatting is supported using TestContainerRuntimeFactory from\n// @fluidframework/test-utils to test rich formatting data sync between multiple collaborators\ndescribe(\"textEditor\", () => {\n\t// Note: JSDOM is initialized once in mochaHooks.ts before Quill is imported,\n\t// since Quill requires document at import time. See src/test/mochaHooks.ts.\n\t// These tests reset up a clean DOM.\n\n\tlet cleanup: () => void;\n\n\t// TODO: why does making this beforeEach/afterEach instead of before/after cause cleanup to crash?\n\t// It seems like each test should be able to have its own clean DOM.\n\tbefore(() => {\n\t\tcleanup = globalJsdom();\n\t});\n\n\tafter(() => {\n\t\tcleanup();\n\t});\n\n\t// Loop through all registered views\n\tfor (const view of views) {\n\t\tdescribe(`${view.name} view`, () => {\n\t\t\tdescribe(\"dom tests\", () => {\n\t\t\t\t// Run without strict mode to make sure it works in a normal production setup.\n\t\t\t\t// Run with strict mode to potentially detect additional issues.\n\t\t\t\tfor (const reactStrictMode of [false, true]) {\n\t\t\t\t\tdescribe(`StrictMode: ${reactStrictMode}`, () => {\n\t\t\t\t\t\tconst ViewComponent = view.component;\n\n\t\t\t\t\t\tit(\"renders MainView with editor container\", () => {\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.match(\n\t\t\t\t\t\t\t\trendered.baseElement.textContent ?? \"\",\n\t\t\t\t\t\t\t\t/Collaborative Text Editor/,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"renders MainView with initial text content\", () => {\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Hello World\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello World/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"invalidates view when tree is mutated\", () => {\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Hello\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\t// Mutate the tree by inserting text\n\t\t\t\t\t\t\ttext.insertAt(5, \" World\");\n\n\t\t\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello World/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"invalidates view when text is removed\", () => {\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Hello World\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\t// Mutate the tree by removing \" World\" (indices 5 to 11)\n\t\t\t\t\t\t\ttext.removeRange(5, 11);\n\n\t\t\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello/);\n\t\t\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /World/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"invalidates view when text is cleared and replaced\", () => {\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Original\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\t// Clear all text\n\t\t\t\t\t\t\tconst length = [...text.characters()].length;\n\t\t\t\t\t\t\ttext.removeRange(0, length);\n\n\t\t\t\t\t\t\t// Insert new text\n\t\t\t\t\t\t\ttext.insertAt(0, \"Replaced\");\n\n\t\t\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Replaced/);\n\t\t\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /Original/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// Tests for surrogate pair characters (emojis use 2 UTF-16 code units)\n\t\t\t\t\t\t// These verify correct handling where editor indexing may differ from iteration.\n\n\t\t\t\t\t\tit(\"renders MainView with surrogate pair characters\", () => {\n\t\t\t\t\t\t\t// 😀 is a surrogate pair: \"😀\".length === 2, but [...\"😀\"].length === 1\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Hello 😀 World\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello 😀 World/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"inserts text after surrogate pair characters\", () => {\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"A😀B\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\t// Insert after the emoji (index 2 in character count: A, 😀, B)\n\t\t\t\t\t\t\ttext.insertAt(2, \"X\");\n\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /A😀XB/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"removes surrogate pair characters\", () => {\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"A😀B\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\t// Remove the emoji (index 1, length 1 in character count)\n\t\t\t\t\t\t\ttext.removeRange(1, 2);\n\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /AB/);\n\t\t\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /😀/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"handles multiple surrogate pair characters\", () => {\n\t\t\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"👋🌍🎉\");\n\t\t\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\t// Insert between emojis\n\t\t\t\t\t\t\ttext.insertAt(2, \"!\");\n\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /👋🌍!🎉/);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// Formatted text view tests - Initial view rendering (matching plain text test structure)\n\tdescribe(\"Formatted Quill view\", () => {\n\t\tdescribe(\"dom tests\", () => {\n\t\t\tfor (const reactStrictMode of [false, true]) {\n\t\t\t\tdescribe(`StrictMode: ${reactStrictMode}`, () => {\n\t\t\t\t\tit(\"renders FormattedMainView with editor container\", () => {\n\t\t\t\t\t\tconst { tree } = createFormattedTreeView();\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(tree)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\tassert.match(\n\t\t\t\t\t\t\trendered.baseElement.textContent ?? \"\",\n\t\t\t\t\t\t\t/Collaborative Formatted Text Editor/,\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"renders FormattedMainView with initial text content\", () => {\n\t\t\t\t\t\tconst { tree } = createFormattedTreeView(\"Hello World\");\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(tree)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello World/);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"invalidates view when tree is mutated\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello\");\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Mutate the tree by inserting text\n\t\t\t\t\t\ttext.insertAt(5, \" World\");\n\n\t\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello World/);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"invalidates view when text is removed\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello World\");\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Mutate the tree by removing \" World\" (indices 5 to 11)\n\t\t\t\t\t\ttext.removeRange(5, 11);\n\n\t\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello/);\n\t\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /World/);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"invalidates view when text is cleared and replaced\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Original\");\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Clear all text\n\t\t\t\t\t\tconst length = [...text.characters()].length;\n\t\t\t\t\t\ttext.removeRange(0, length);\n\n\t\t\t\t\t\t// Insert new text\n\t\t\t\t\t\ttext.insertAt(0, \"Replaced\");\n\n\t\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Replaced/);\n\t\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /Original/);\n\t\t\t\t\t});\n\n\t\t\t\t\t// Tests for surrogate pair characters (emojis use 2 UTF-16 code units)\n\t\t\t\t\t// These verify correct handling where editor indexing may differ from iteration.\n\n\t\t\t\t\tit(\"renders FormattedMainView with surrogate pair characters\", () => {\n\t\t\t\t\t\t// 😀 is a surrogate pair: \"😀\".length === 2, but [...\"😀\"].length === 1\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello 😀 World\");\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello 😀 World/);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"inserts text after surrogate pair characters\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"A😀B\");\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Insert after the emoji (index 2 in character count: A, 😀, B)\n\t\t\t\t\t\ttext.insertAt(2, \"X\");\n\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /A😀XB/);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"removes surrogate pair characters\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"A😀B\");\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Remove the emoji (index 1, length 1 in character count)\n\t\t\t\t\t\ttext.removeRange(1, 2);\n\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /AB/);\n\t\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /😀/);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"handles multiple surrogate pair characters\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"👋🌍🎉\");\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Insert between emojis\n\t\t\t\t\t\ttext.insertAt(2, \"!\");\n\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /👋🌍!🎉/);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t// Helper to create default format\n\t\tfunction createPlainFormat(): FormattedTextAsTree.CharacterFormat {\n\t\t\treturn new FormattedTextAsTree.CharacterFormat({\n\t\t\t\tbold: false,\n\t\t\t\titalic: false,\n\t\t\t\tunderline: false,\n\t\t\t\tsize: 12,\n\t\t\t\tfont: \"Arial\",\n\t\t\t});\n\t\t}\n\n\t\t// Essential tests for character attributes\n\t\t// Each attribute needs: insert, delete, and formatRange tests\n\t\tdescribe(\"character attribute tests\", () => {\n\t\t\tfor (const reactStrictMode of [false, true]) {\n\t\t\t\tdescribe(`StrictMode: ${reactStrictMode}`, () => {\n\t\t\t\t\tit(\"delete on empty string does not throw\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView();\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\tassert.doesNotThrow(() => {\n\t\t\t\t\t\t\ttext.removeRange(0, 0);\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tdescribe(\"bold\", () => {\n\t\t\t\t\t\tit(\"inserts bold text and renders with <strong> tag\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(!rendered.container.querySelector(\"strong\"), \"Initially: no <strong>\");\n\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: true,\n\t\t\t\t\t\t\t\titalic: false,\n\t\t\t\t\t\t\t\tunderline: false,\n\t\t\t\t\t\t\t\tsize: 12,\n\t\t\t\t\t\t\t\tfont: \"Arial\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(2, \"BOLD\");\n\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\"strong\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected <strong> tag\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /BOLD/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"deletes bold text and removes <strong> tag\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView();\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: true,\n\t\t\t\t\t\t\t\titalic: false,\n\t\t\t\t\t\t\t\tunderline: false,\n\t\t\t\t\t\t\t\tsize: 12,\n\t\t\t\t\t\t\t\tfont: \"Arial\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(0, \"BOLD\");\n\t\t\t\t\t\t\ttext.defaultFormat = createPlainFormat();\n\t\t\t\t\t\t\ttext.insertAt(4, \"plain\");\n\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(rendered.container.querySelector(\"strong\"), \"Initially: has <strong>\");\n\n\t\t\t\t\t\t\ttext.removeRange(0, 4);\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t\t!rendered.container.querySelector(\"strong\"),\n\t\t\t\t\t\t\t\t\"After delete: no <strong>\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"applies bold via formatRange\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello World\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\ttext.formatRange(6, 11, { bold: true });\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\"strong\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected <strong> after formatRange\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /World/);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tdescribe(\"italic\", () => {\n\t\t\t\t\t\tit(\"inserts italic text and renders with <em> tag\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(!rendered.container.querySelector(\"em\"), \"Initially: no <em>\");\n\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: false,\n\t\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t\t\tunderline: false,\n\t\t\t\t\t\t\t\tsize: 12,\n\t\t\t\t\t\t\t\tfont: \"Arial\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(2, \"ITAL\");\n\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\"em\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected <em> tag\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /ITAL/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"deletes italic text and removes <em> tag\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView();\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: false,\n\t\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t\t\tunderline: false,\n\t\t\t\t\t\t\t\tsize: 12,\n\t\t\t\t\t\t\t\tfont: \"Arial\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(0, \"ITAL\");\n\t\t\t\t\t\t\ttext.defaultFormat = createPlainFormat();\n\t\t\t\t\t\t\ttext.insertAt(4, \"plain\");\n\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(rendered.container.querySelector(\"em\"), \"Initially: has <em>\");\n\n\t\t\t\t\t\t\ttext.removeRange(0, 4);\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tassert.ok(!rendered.container.querySelector(\"em\"), \"After delete: no <em>\");\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"applies italic via formatRange\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello World\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\ttext.formatRange(6, 11, { italic: true });\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\"em\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected <em> after formatRange\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /World/);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tdescribe(\"underline\", () => {\n\t\t\t\t\t\tit(\"inserts underlined text and renders with <u> tag\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(!rendered.container.querySelector(\"u\"), \"Initially: no <u>\");\n\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: false,\n\t\t\t\t\t\t\t\titalic: false,\n\t\t\t\t\t\t\t\tunderline: true,\n\t\t\t\t\t\t\t\tsize: 12,\n\t\t\t\t\t\t\t\tfont: \"Arial\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(2, \"UNDER\");\n\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\"u\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected <u> tag\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /UNDER/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"deletes underlined text and removes <u> tag\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView();\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: false,\n\t\t\t\t\t\t\t\titalic: false,\n\t\t\t\t\t\t\t\tunderline: true,\n\t\t\t\t\t\t\t\tsize: 12,\n\t\t\t\t\t\t\t\tfont: \"Arial\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(0, \"UNDER\");\n\t\t\t\t\t\t\ttext.defaultFormat = createPlainFormat();\n\t\t\t\t\t\t\ttext.insertAt(5, \"plain\");\n\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(rendered.container.querySelector(\"u\"), \"Initially: has <u>\");\n\n\t\t\t\t\t\t\ttext.removeRange(0, 5);\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tassert.ok(!rendered.container.querySelector(\"u\"), \"After delete: no <u>\");\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"applies underline via formatRange\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello World\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\ttext.formatRange(6, 11, { underline: true });\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\"u\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected <u> after formatRange\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /World/);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tdescribe(\"size\", () => {\n\t\t\t\t\t\tit(\"inserts huge size text and renders with .ql-size-huge\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t\t!rendered.container.querySelector(\".ql-size-huge\"),\n\t\t\t\t\t\t\t\t\"Initially: no .ql-size-huge\",\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: false,\n\t\t\t\t\t\t\t\titalic: false,\n\t\t\t\t\t\t\t\tunderline: false,\n\t\t\t\t\t\t\t\tsize: 24,\n\t\t\t\t\t\t\t\tfont: \"Arial\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(2, \"HUGE\");\n\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\".ql-size-huge\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected .ql-size-huge\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /HUGE/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"deletes huge size text and removes .ql-size-huge\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView();\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: false,\n\t\t\t\t\t\t\t\titalic: false,\n\t\t\t\t\t\t\t\tunderline: false,\n\t\t\t\t\t\t\t\tsize: 24,\n\t\t\t\t\t\t\t\tfont: \"Arial\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(0, \"HUGE\");\n\t\t\t\t\t\t\ttext.defaultFormat = createPlainFormat();\n\t\t\t\t\t\t\ttext.insertAt(4, \"plain\");\n\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t\trendered.container.querySelector(\".ql-size-huge\"),\n\t\t\t\t\t\t\t\t\"Initially: has .ql-size-huge\",\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\ttext.removeRange(0, 4);\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t\t!rendered.container.querySelector(\".ql-size-huge\"),\n\t\t\t\t\t\t\t\t\"After delete: no .ql-size-huge\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"applies size via formatRange\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello World\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\ttext.formatRange(6, 11, { size: 24 });\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\".ql-size-huge\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected .ql-size-huge after formatRange\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /World/);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\n\t\t\t\t\tdescribe(\"font\", () => {\n\t\t\t\t\t\tit(\"inserts monospace font text and renders with .ql-font-monospace\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t\t!rendered.container.querySelector(\".ql-font-monospace\"),\n\t\t\t\t\t\t\t\t\"Initially: no .ql-font-monospace\",\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: false,\n\t\t\t\t\t\t\t\titalic: false,\n\t\t\t\t\t\t\t\tunderline: false,\n\t\t\t\t\t\t\t\tsize: 12,\n\t\t\t\t\t\t\t\tfont: \"monospace\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(2, \"MONO\");\n\n\t\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\".ql-font-monospace\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected .ql-font-monospace\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /MONO/);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"deletes monospace font text and removes .ql-font-monospace\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView();\n\t\t\t\t\t\t\ttext.defaultFormat = new FormattedTextAsTree.CharacterFormat({\n\t\t\t\t\t\t\t\tbold: false,\n\t\t\t\t\t\t\t\titalic: false,\n\t\t\t\t\t\t\t\tunderline: false,\n\t\t\t\t\t\t\t\tsize: 12,\n\t\t\t\t\t\t\t\tfont: \"monospace\",\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttext.insertAt(0, \"MONO\");\n\t\t\t\t\t\t\ttext.defaultFormat = createPlainFormat();\n\t\t\t\t\t\t\ttext.insertAt(4, \"plain\");\n\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t\trendered.container.querySelector(\".ql-font-monospace\"),\n\t\t\t\t\t\t\t\t\"Initially: has .ql-font-monospace\",\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\ttext.removeRange(0, 4);\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t\t!rendered.container.querySelector(\".ql-font-monospace\"),\n\t\t\t\t\t\t\t\t\"After delete: no .ql-font-monospace\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tit(\"applies font via formatRange\", () => {\n\t\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(\"Hello World\");\n\t\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t\ttext.formatRange(6, 11, { font: \"monospace\" });\n\t\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\t\tconst el = rendered.container.querySelector(\".ql-font-monospace\");\n\t\t\t\t\t\t\tassert.ok(el, \"Expected .ql-font-monospace after formatRange\");\n\t\t\t\t\t\t\tassert.match(el.textContent ?? \"\", /World/);\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t// Undo/Redo tests for non-transactional edits\n\t\tdescribe(\"undo/redo\", () => {\n\t\t\tfor (const reactStrictMode of [false, true]) {\n\t\t\t\tdescribe(`StrictMode: ${reactStrictMode}`, () => {\n\t\t\t\t\tit(\"insert character, undo removes it, redo restores it\", () => {\n\t\t\t\t\t\tconst treeView = createFormattedTreeViewWithEvents();\n\t\t\t\t\t\tconst text = treeView.root;\n\t\t\t\t\t\tconst undoRedo = new UndoRedoStacks(treeView.events);\n\t\t\t\t\t\tconst editorRef = createRef<FormattedEditorHandle>();\n\t\t\t\t\t\tconst content = (\n\t\t\t\t\t\t\t<FormattedMainView\n\t\t\t\t\t\t\t\tref={editorRef}\n\t\t\t\t\t\t\t\troot={toPropTreeNode(text)}\n\t\t\t\t\t\t\t\tundoRedo={undoRedo}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Insert a character\n\t\t\t\t\t\ttext.insertAt(0, \"A\");\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /A/);\n\n\t\t\t\t\t\t// Undo - character should be removed\n\t\t\t\t\t\teditorRef.current?.undo();\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /A/);\n\n\t\t\t\t\t\t// Redo - character should be restored\n\t\t\t\t\t\teditorRef.current?.redo();\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /A/);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"insert character, make bold, undo removes bold but keeps character\", () => {\n\t\t\t\t\t\tconst treeView = createFormattedTreeViewWithEvents();\n\t\t\t\t\t\tconst text = treeView.root;\n\t\t\t\t\t\tconst undoRedo = new UndoRedoStacks(treeView.events);\n\t\t\t\t\t\tconst editorRef = createRef<FormattedEditorHandle>();\n\t\t\t\t\t\tconst content = (\n\t\t\t\t\t\t\t<FormattedMainView\n\t\t\t\t\t\t\t\tref={editorRef}\n\t\t\t\t\t\t\t\troot={toPropTreeNode(text)}\n\t\t\t\t\t\t\t\tundoRedo={undoRedo}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Insert a character\n\t\t\t\t\t\ttext.insertAt(0, \"B\");\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /B/);\n\t\t\t\t\t\tassert.ok(!rendered.container.querySelector(\"strong\"), \"Initially: no <strong>\");\n\n\t\t\t\t\t\t// Make it bold\n\t\t\t\t\t\ttext.formatRange(0, 1, { bold: true });\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\trendered.container.querySelector(\"strong\"),\n\t\t\t\t\t\t\t\"After format: has <strong>\",\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// Undo - bold should be removed, character should remain\n\t\t\t\t\t\teditorRef.current?.undo();\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /B/);\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t!rendered.container.querySelector(\"strong\"),\n\t\t\t\t\t\t\t\"After undo: no <strong>, character remains\",\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"multiple operations in transaction undo together as one unit\", () => {\n\t\t\t\t\t\tconst treeView = createFormattedTreeViewWithEvents();\n\t\t\t\t\t\tconst text = treeView.root;\n\t\t\t\t\t\tconst undoRedo = new UndoRedoStacks(treeView.events);\n\t\t\t\t\t\tconst editorRef = createRef<FormattedEditorHandle>();\n\t\t\t\t\t\tconst content = (\n\t\t\t\t\t\t\t<FormattedMainView\n\t\t\t\t\t\t\t\tref={editorRef}\n\t\t\t\t\t\t\t\troot={toPropTreeNode(text)}\n\t\t\t\t\t\t\t\tundoRedo={undoRedo}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\t// Two operations in one transaction\n\t\t\t\t\t\tTreeAlpha.branch(text)?.runTransaction(() => {\n\t\t\t\t\t\t\ttext.insertAt(0, \"A\");\n\t\t\t\t\t\t\ttext.insertAt(1, \"B\");\n\t\t\t\t\t\t});\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /AB/);\n\n\t\t\t\t\t\t// Single undo should remove both characters\n\t\t\t\t\t\teditorRef.current?.undo();\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /A/);\n\t\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /B/);\n\n\t\t\t\t\t\t// Single redo should restore both characters\n\t\t\t\t\t\teditorRef.current?.redo();\n\t\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /AB/);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tdescribe(\"copy-paste helpers\", () => {\n\t\t\t/** Helper to create an HTMLElement with inline styles. */\n\t\t\tfunction styledElement(styles: Partial<CSSStyleDeclaration>): HTMLElement {\n\t\t\t\tconst el = document.createElement(\"span\");\n\t\t\t\tObject.assign(el.style, styles);\n\t\t\t\treturn el;\n\t\t\t}\n\n\t\t\tdescribe(\"parseCssFontSize\", () => {\n\t\t\t\tit(\"returns undefined when no fontSize is set\", () => {\n\t\t\t\t\tassert.equal(parseCssFontSize(styledElement({})), undefined);\n\t\t\t\t});\n\n\t\t\t\tit(\"returns Quill size name for supported pixel values\", () => {\n\t\t\t\t\tassert.equal(parseCssFontSize(styledElement({ fontSize: \"10px\" })), \"small\");\n\t\t\t\t\tassert.equal(parseCssFontSize(styledElement({ fontSize: \"18px\" })), \"large\");\n\t\t\t\t\tassert.equal(parseCssFontSize(styledElement({ fontSize: \"24px\" })), \"huge\");\n\t\t\t\t});\n\n\t\t\t\tit(\"returns undefined for default or unrecognized sizes\", () => {\n\t\t\t\t\tassert.equal(parseCssFontSize(styledElement({ fontSize: \"12px\" })), undefined);\n\t\t\t\t\tassert.equal(parseCssFontSize(styledElement({ fontSize: \"42px\" })), undefined);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tdescribe(\"parseCssFontFamily\", () => {\n\t\t\t\tit(\"returns undefined when no fontFamily is set\", () => {\n\t\t\t\t\tassert.equal(parseCssFontFamily(styledElement({})), undefined);\n\t\t\t\t});\n\n\t\t\t\tit(\"returns first recognized font in a comma-separated stack\", () => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tparseCssFontFamily(styledElement({ fontFamily: \"monospace\" })),\n\t\t\t\t\t\t\"monospace\",\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tparseCssFontFamily(styledElement({ fontFamily: '\"Courier New\", monospace' })),\n\t\t\t\t\t\t\"monospace\",\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tparseCssFontFamily(\n\t\t\t\t\t\t\tstyledElement({ fontFamily: '\"Times New Roman\", \"Arial\", serif' }),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t\"Arial\",\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t\tit(\"strips single quotes around recognized font names\", () => {\n\t\t\t\t\tassert.equal(parseCssFontFamily(styledElement({ fontFamily: \"'Arial'\" })), \"Arial\");\n\t\t\t\t});\n\t\t\t\tit(\"returns undefined for unrecognized fonts\", () => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tparseCssFontFamily(styledElement({ fontFamily: '\"Courier New\", fantasy' })),\n\t\t\t\t\t\tundefined,\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tdescribe(\"clipboardFormatMatcher\", () => {\n\t\t\t\tit(\"returns delta unchanged for non-HTMLElement nodes\", () => {\n\t\t\t\t\tconst delta = new Delta().insert(\"hello\");\n\t\t\t\t\tconst text = document.createTextNode(\"hello\");\n\t\t\t\t\tconst result = clipboardFormatMatcher(text, delta);\n\t\t\t\t\tassert.deepEqual(result.ops, delta.ops);\n\t\t\t\t});\n\n\t\t\t\tit(\"applies size and font attributes from inline styles\", () => {\n\t\t\t\t\tconst delta = new Delta().insert(\"hello\");\n\t\t\t\t\tconst el = styledElement({ fontSize: \"18px\", fontFamily: \"serif\" });\n\t\t\t\t\tconst result = clipboardFormatMatcher(el, delta);\n\t\t\t\t\tassert.equal(result.ops[0]?.attributes?.size, \"large\");\n\t\t\t\t\tassert.equal(result.ops[0]?.attributes?.font, \"serif\");\n\t\t\t\t});\n\n\t\t\t\tit(\"returns delta unchanged when no recognized styles\", () => {\n\t\t\t\t\tconst delta = new Delta().insert(\"hello\");\n\t\t\t\t\tconst el = styledElement({});\n\t\t\t\t\tconst result = clipboardFormatMatcher(el, delta);\n\t\t\t\t\tassert.deepEqual(result.ops, delta.ops);\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\t// Unicode 16+ (joined emojis) section - test attribute cycling\n\t\tdescribe(\"Unicode 16+ joined emoji attribute cycling\", () => {\n\t\t\t// ZWJ (Zero Width Joiner) emoji sequence: 👨👩👧👦 = family emoji\n\t\t\tconst joinedEmoji = \"👨👩👧👦\";\n\n\t\t\tfor (const reactStrictMode of [false, true]) {\n\t\t\t\tdescribe(`StrictMode: ${reactStrictMode}`, () => {\n\t\t\t\t\tit(\"applies bold to joined emoji and removes it preserving text\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(`Test ${joinedEmoji} Text`);\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\tconst emojiStart = 5; // \"Test \" is 5 chars\n\t\t\t\t\t\tconst emojiLength = [...joinedEmoji].length;\n\t\t\t\t\t\ttext.formatRange(emojiStart, emojiStart + emojiLength, { bold: true });\n\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\trendered.container.querySelector(\"strong\"),\n\t\t\t\t\t\t\t\"After bold: expected <strong>\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t(rendered.baseElement.textContent ?? \"\").includes(joinedEmoji),\n\t\t\t\t\t\t\t\"After bold: emoji should be preserved\",\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\ttext.formatRange(emojiStart, emojiStart + emojiLength, { bold: false });\n\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t!rendered.container.querySelector(\"strong\"),\n\t\t\t\t\t\t\t\"After remove bold: no <strong> expected\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t(rendered.baseElement.textContent ?? \"\").includes(joinedEmoji),\n\t\t\t\t\t\t\t\"After remove bold: emoji should still be preserved\",\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\n\t\t\t\t\tit(\"applies size to joined emoji and removes it preserving text\", () => {\n\t\t\t\t\t\tconst { tree: text } = createFormattedTreeView(`Test ${joinedEmoji} Text`);\n\t\t\t\t\t\tconst content = <FormattedMainView root={toPropTreeNode(text)} />;\n\t\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t\tconst emojiStart = 5;\n\t\t\t\t\t\tconst emojiLength = [...joinedEmoji].length;\n\t\t\t\t\t\ttext.formatRange(emojiStart, emojiStart + emojiLength, { size: 24 });\n\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\trendered.container.querySelector(\".ql-size-huge\"),\n\t\t\t\t\t\t\t\"After size: expected .ql-size-huge\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t(rendered.baseElement.textContent ?? \"\").includes(joinedEmoji),\n\t\t\t\t\t\t\t\"Emoji preserved\",\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\ttext.formatRange(emojiStart, emojiStart + emojiLength, { size: 12 });\n\t\t\t\t\t\trendered.rerender(content);\n\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t!rendered.container.querySelector(\".ql-size-huge\"),\n\t\t\t\t\t\t\t\"After remove: no .ql-size-huge\",\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.ok(\n\t\t\t\t\t\t\t(rendered.baseElement.textContent ?? \"\").includes(joinedEmoji),\n\t\t\t\t\t\t\t\"Emoji still preserved\",\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\tdescribe(\"parseLineTag\", () => {\n\t\t\tit(\"return lineTag for valid header\", () => {\n\t\t\t\tconst result = parseLineTag({ header: 1 });\n\t\t\t\tassert.ok(result, \"Expected a line tag for header 1\");\n\t\t\t\tassert.equal(result.value, \"h1\", \"Expected tag to be h1\");\n\t\t\t});\n\t\t\tit(\"returns lineTag for valid bullet list\", () => {\n\t\t\t\tconst result = parseLineTag({ list: \"bullet\" });\n\t\t\t\tassert.ok(result, \"Expected a line tag for bullet list\");\n\t\t\t\tassert.equal(result.value, \"li\", \"Expected tag to be li)\");\n\t\t\t});\n\t\t\t// Tests for unsupported parameters - should return default header (\"h5\"), not throw an error.\n\t\t\t// Also used for when formatting is stripped from a newline and it becomes a default newline\n\t\t\tit(\"returns undefined for unsupported parameter\", () => {\n\t\t\t\tconst result = parseLineTag({ header: 7 });\n\t\t\t\tassert.ok(result, \"Expected a line tag for header 5\");\n\t\t\t\tassert.equal(result.value, \"h5\", \"Expected tag to be h5 for unsupported header level\");\n\t\t\t});\n\t\t});\n\t\t// tests quillFormattedview conversion that feeds into quill delta generation,\n\t\t// specifically for line atoms which have special handling for headers and lists.\n\t\t// Quill always has a trailing newline, so these tests set up the string with a newline,\n\t\t// then replace it with a line atom with the appropriate tag.\n\t\tdescribe(\"buildDeltaFromTree with line Atoms\", () => {\n\t\t\tit(\"emits header attribute for h1 line atom\", () => {\n\t\t\t\tconst { tree } = createFormattedTreeView(\"Hello\\n\");\n\t\t\t\ttree.removeRange(5, 6);\n\t\t\t\ttree.insertWithFormattingAt(5, [\n\t\t\t\t\tnew FormattedTextAsTree.StringAtom({\n\t\t\t\t\t\tcontent: new FormattedTextAsTree.StringLineAtom({\n\t\t\t\t\t\t\ttag: FormattedTextAsTree.LineTag(\"h1\"),\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tformat: createPlainFormat(),\n\t\t\t\t\t}),\n\t\t\t\t]);\n\n\t\t\t\tconst ops = buildDeltaFromTree(tree);\n\t\t\t\tconst lineOp = ops.find((op) => op.insert === \"\\n\" && op.attributes?.header === 1);\n\t\t\t\tassert.ok(lineOp, \"Expected { insert : `\\\\n`, attributes: { header: 1 } } in delta\");\n\t\t\t});\n\t\t\tit(\"emits header attribute for li line atom\", () => {\n\t\t\t\tconst { tree } = createFormattedTreeView(\"item\\n\");\n\t\t\t\ttree.removeRange(4, 5);\n\t\t\t\ttree.insertWithFormattingAt(4, [\n\t\t\t\t\tnew FormattedTextAsTree.StringAtom({\n\t\t\t\t\t\tcontent: new FormattedTextAsTree.StringLineAtom({\n\t\t\t\t\t\t\ttag: FormattedTextAsTree.LineTag(\"li\"),\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tformat: createPlainFormat(),\n\t\t\t\t\t}),\n\t\t\t\t]);\n\n\t\t\t\tconst ops = buildDeltaFromTree(tree);\n\t\t\t\tconst lineOp = ops.find(\n\t\t\t\t\t(op) => op.insert === \"\\n\" && op.attributes?.list === \"bullet\",\n\t\t\t\t);\n\t\t\t\tassert.ok(\n\t\t\t\t\tlineOp,\n\t\t\t\t\t\"Expected { insert : `\\\\n`, attributes: { list: 'bullet' } } in delta\",\n\t\t\t\t);\n\t\t\t});\n\t\t});\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"textEditor.test.js","sourceRoot":"","sources":["../../../src/test/text/textEditor.test.tsx"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { strict as assert } from \"node:assert\";\n\nimport { TextAsTree } from \"@fluidframework/tree/internal\";\nimport { render } from \"@testing-library/react\";\nimport globalJsdom from \"global-jsdom\";\n\nimport { toPropTreeNode } from \"../../propNode.js\";\nimport { PlainTextMainView } from \"../../text/index.js\";\n\ndescribe(\"Plain TextArea view\", () => {\n\tlet cleanup: () => void;\n\tbefore(() => {\n\t\tcleanup = globalJsdom();\n\t});\n\tafter(() => {\n\t\tcleanup();\n\t});\n\n\tdescribe(\"dom tests\", () => {\n\t\t// Run without strict mode to make sure it works in a normal production setup.\n\t\t// Run with strict mode to potentially detect additional issues.\n\t\tfor (const reactStrictMode of [false, true]) {\n\t\t\tdescribe(`StrictMode: ${reactStrictMode}`, () => {\n\t\t\t\tconst ViewComponent = PlainTextMainView;\n\n\t\t\t\tit(\"renders MainView with editor container\", () => {\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Collaborative Text Editor/);\n\t\t\t\t});\n\n\t\t\t\tit(\"renders MainView with initial text content\", () => {\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Hello World\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello World/);\n\t\t\t\t});\n\n\t\t\t\tit(\"invalidates view when tree is mutated\", () => {\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Hello\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t// Mutate the tree by inserting text\n\t\t\t\t\ttext.insertAt(5, \" World\");\n\n\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello World/);\n\t\t\t\t});\n\n\t\t\t\tit(\"invalidates view when text is removed\", () => {\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Hello World\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t// Mutate the tree by removing \" World\" (indices 5 to 11)\n\t\t\t\t\ttext.removeRange(5, 11);\n\n\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello/);\n\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /World/);\n\t\t\t\t});\n\n\t\t\t\tit(\"invalidates view when text is cleared and replaced\", () => {\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Original\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t// Clear all text\n\t\t\t\t\tconst length = [...text.characters()].length;\n\t\t\t\t\ttext.removeRange(0, length);\n\n\t\t\t\t\t// Insert new text\n\t\t\t\t\ttext.insertAt(0, \"Replaced\");\n\n\t\t\t\t\t// Rerender and verify the view updates\n\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Replaced/);\n\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /Original/);\n\t\t\t\t});\n\n\t\t\t\t// Tests for surrogate pair characters (emojis use 2 UTF-16 code units)\n\t\t\t\t// These verify correct handling where editor indexing may differ from iteration.\n\n\t\t\t\tit(\"renders MainView with surrogate pair characters\", () => {\n\t\t\t\t\t// 😀 is a surrogate pair: \"😀\".length === 2, but [...\"😀\"].length === 1\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"Hello 😀 World\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /Hello 😀 World/);\n\t\t\t\t});\n\n\t\t\t\tit(\"inserts text after surrogate pair characters\", () => {\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"A😀B\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t// Insert after the emoji (index 2 in character count: A, 😀, B)\n\t\t\t\t\ttext.insertAt(2, \"X\");\n\n\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /A😀XB/);\n\t\t\t\t});\n\n\t\t\t\tit(\"removes surrogate pair characters\", () => {\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"A😀B\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t// Remove the emoji (index 1, length 1 in character count)\n\t\t\t\t\ttext.removeRange(1, 2);\n\n\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /AB/);\n\t\t\t\t\tassert(rendered.baseElement.textContent !== null);\n\t\t\t\t\tassert.doesNotMatch(rendered.baseElement.textContent, /😀/);\n\t\t\t\t});\n\n\t\t\t\tit(\"handles multiple surrogate pair characters\", () => {\n\t\t\t\t\tconst text = TextAsTree.Tree.fromString(\"👋🌍🎉\");\n\t\t\t\t\tconst content = <ViewComponent root={toPropTreeNode(text)} />;\n\t\t\t\t\tconst rendered = render(content, { reactStrictMode });\n\n\t\t\t\t\t// Insert between emojis\n\t\t\t\t\ttext.insertAt(2, \"!\");\n\n\t\t\t\t\trendered.rerender(content);\n\t\t\t\t\tassert.match(rendered.baseElement.textContent ?? \"\", /👋🌍!🎉/);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t});\n});\n"]}
|
package/lib/text/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
5
|
+
export { type PropTreeNode } from "../propNode.js";
|
|
6
|
+
export { type UndoRedo } from "../undoRedo.js";
|
|
7
|
+
export { PlainTextMainView, syncTextToTree } from "./plain/index.js";
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/text/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/text/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/text/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
package/lib/text/index.js
CHANGED
|
@@ -2,6 +2,5 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export {
|
|
6
|
-
export { PlainTextMainView, QuillMainView as PlainQuillView, } from "./plain/index.js";
|
|
5
|
+
export { PlainTextMainView, syncTextToTree } from "./plain/index.js";
|
|
7
6
|
//# sourceMappingURL=index.js.map
|
package/lib/text/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/text/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/text/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { type PropTreeNode } from \"../propNode.js\";\nexport { type UndoRedo } from \"../undoRedo.js\";\nexport { PlainTextMainView, syncTextToTree } from \"./plain/index.js\";\n"]}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
export { MainView as PlainTextMainView } from "./plainTextView.js";
|
|
6
|
-
export {
|
|
6
|
+
export { syncTextToTree } from "./plainUtils.js";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/text/plain/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/text/plain/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
package/lib/text/plain/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/text/plain/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/text/plain/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { MainView as PlainTextMainView } from \"./plainTextView.js\";\nexport { syncTextToTree } from \"./plainUtils.js\";\n"]}
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
+
import type { TextAsTree } from "@fluidframework/tree/internal";
|
|
5
6
|
import { type FC } from "react";
|
|
6
|
-
import type {
|
|
7
|
+
import type { PropTreeNode } from "../../propNode.js";
|
|
7
8
|
/**
|
|
8
9
|
* A React component for plain text editing.
|
|
9
10
|
* @remarks
|
|
10
11
|
* Uses {@link @fluidframework/tree#TextAsTree.Tree} for the data-model and an HTML textarea for the UI.
|
|
11
12
|
* @internal
|
|
12
13
|
*/
|
|
13
|
-
export declare const MainView: FC<
|
|
14
|
+
export declare const MainView: FC<{
|
|
15
|
+
root: PropTreeNode<TextAsTree.Tree>;
|
|
16
|
+
}>;
|
|
14
17
|
//# sourceMappingURL=plainTextView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plainTextView.d.ts","sourceRoot":"","sources":["../../../src/text/plain/plainTextView.tsx"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"plainTextView.d.ts","sourceRoot":"","sources":["../../../src/text/plain/plainTextView.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAoB,KAAK,EAAE,EAAuB,MAAM,OAAO,CAAC;AAEvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAKtD;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,EAAE,CAAC;IAAE,IAAI,EAAE,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;CAAE,CAEhE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plainTextView.js","sourceRoot":"","sources":["../../../src/text/plain/plainTextView.tsx"],"names":[],"mappings":";AAMA,OAAO,EAA6B,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"plainTextView.js","sourceRoot":"","sources":["../../../src/text/plain/plainTextView.tsx"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { TextAsTree } from \"@fluidframework/tree/internal\";\nimport { type ChangeEvent, type FC, useCallback, useRef } from \"react\";\n\nimport type { PropTreeNode } from \"../../propNode.js\";\nimport { withMemoizedTreeObservations } from \"../../useTree.js\";\n\nimport { syncTextToTree } from \"./plainUtils.js\";\n\n/**\n * A React component for plain text editing.\n * @remarks\n * Uses {@link @fluidframework/tree#TextAsTree.Tree} for the data-model and an HTML textarea for the UI.\n * @internal\n */\nexport const MainView: FC<{ root: PropTreeNode<TextAsTree.Tree> }> = ({ root }) => {\n\treturn <PlainTextEditorView root={root} />;\n};\n\n/**\n * A plain text editor view component using a native HTML textarea.\n * Uses TextAsTree for collaborative plain text storage.\n *\n * @remarks\n * This uses withMemoizedTreeObservations to automatically re-render\n * when the tree changes.\n */\nconst PlainTextEditorView = withMemoizedTreeObservations(\n\t({ root }: { root: TextAsTree.Tree }) => {\n\t\t// Reference to the textarea element\n\t\tconst textareaRef = useRef<HTMLTextAreaElement>(null);\n\t\t// Guards against update loops between textarea and the tree\n\t\tconst isUpdatingRef = useRef<boolean>(false);\n\n\t\t// Access tree content during render to establish observation.\n\t\t// The HOC will automatically re-render when this content changes.\n\t\tconst currentText = root.fullString();\n\n\t\t// Handle textarea changes - sync textarea → tree\n\t\tconst handleChange = useCallback(\n\t\t\t(event: ChangeEvent<HTMLTextAreaElement>) => {\n\t\t\t\tif (isUpdatingRef.current) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tisUpdatingRef.current = true;\n\n\t\t\t\tconst newText = event.target.value;\n\t\t\t\tsyncTextToTree(root, newText);\n\n\t\t\t\tisUpdatingRef.current = false;\n\t\t\t},\n\t\t\t[root],\n\t\t);\n\n\t\t// Sync textarea when tree changes externally.\n\t\t// We skip this if isUpdatingRef is true, meaning we caused the tree change ourselves\n\t\t// via the handleChange above - in that case textarea already has the correct content.\n\t\tif (textareaRef.current && !isUpdatingRef.current) {\n\t\t\tconst textareaValue = textareaRef.current.value;\n\n\t\t\t// Only update if content actually differs (avoids cursor jump on local edits)\n\t\t\tif (textareaValue !== currentText) {\n\t\t\t\tisUpdatingRef.current = true;\n\n\t\t\t\t// Preserve cursor position\n\t\t\t\tconst selectionStart = textareaRef.current.selectionStart;\n\t\t\t\tconst selectionEnd = textareaRef.current.selectionEnd;\n\n\t\t\t\ttextareaRef.current.value = currentText;\n\n\t\t\t\t// Restore cursor position, clamped to new text length\n\t\t\t\tconst newPosition = Math.min(selectionStart, currentText.length);\n\t\t\t\tconst newEnd = Math.min(selectionEnd, currentText.length);\n\t\t\t\ttextareaRef.current.setSelectionRange(newPosition, newEnd);\n\n\t\t\t\tisUpdatingRef.current = false;\n\t\t\t}\n\t\t}\n\n\t\treturn (\n\t\t\t<div\n\t\t\t\tclassName=\"text-editor-container\"\n\t\t\t\tstyle={{ height: \"100%\", display: \"flex\", flexDirection: \"column\" }}\n\t\t\t>\n\t\t\t\t<h2 style={{ margin: \"10px 0\" }}>Collaborative Text Editor</h2>\n\t\t\t\t<textarea\n\t\t\t\t\tref={textareaRef}\n\t\t\t\t\tdefaultValue={currentText}\n\t\t\t\t\tonChange={handleChange}\n\t\t\t\t\tplaceholder=\"Start typing...\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\tflex: 1,\n\t\t\t\t\t\tminHeight: \"300px\",\n\t\t\t\t\t\tborder: \"1px solid #ccc\",\n\t\t\t\t\t\tborderRadius: \"4px\",\n\t\t\t\t\t\tpadding: \"8px\",\n\t\t\t\t\t\tfontSize: \"14px\",\n\t\t\t\t\t\tfontFamily: \"inherit\",\n\t\t\t\t\t\tresize: \"vertical\",\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t);\n\t},\n);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plainUtils.d.ts","sourceRoot":"","sources":["../../../src/text/plain/plainUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE
|
|
1
|
+
{"version":3,"file":"plainUtils.d.ts","sourceRoot":"","sources":["../../../src/text/plain/plainUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAS3E;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC5B,QAAQ,EAAE,SAAS,CAAC,EAAE,EACtB,KAAK,EAAE,SAAS,CAAC,EAAE,GACjB;IAAE,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,CAAC,EAAE,CAAA;KAAE,CAAA;CAAE,CAwCxF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plainUtils.js","sourceRoot":"","sources":["../../../src/text/plain/plainUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH
|
|
1
|
+
{"version":3,"file":"plainUtils.js","sourceRoot":"","sources":["../../../src/text/plain/plainUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAqB,EAAE,OAAe;IACpE,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAE9D,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;AACF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAC1B,QAAsB,EACtB,KAAmB;IAEnB,oDAAoD;IAEpD,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,OACC,YAAY,GAAG,QAAQ,CAAC,MAAM;QAC9B,YAAY,GAAG,KAAK,CAAC,MAAM;QAC3B,QAAQ,CAAC,YAAY,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC,EAC7C,CAAC;QACF,YAAY,EAAE,CAAC;IAChB,CAAC;IAED,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,OACC,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC,MAAM;QAC7C,YAAY,GAAG,YAAY,GAAG,KAAK,CAAC,MAAM;QAC1C,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,GAAG,YAAY,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,GAAG,YAAY,CAAC,EACtF,CAAC;QACF,YAAY,EAAE,CAAC;IAChB,CAAC;IAED,qDAAqD;IACrD,MAAM,mBAAmB,GAAG,YAAY,CAAC;IACzC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,GAAG,YAAY,CAAC;IACzD,MAAM,cAAc,GAAG,YAAY,CAAC;IACpC,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,GAAG,YAAY,CAAC;IAEjD,OAAO;QACN,MAAM,EACL,mBAAmB,GAAG,iBAAiB;YACtC,CAAC,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,EAAE,iBAAiB,EAAE;YACxD,CAAC,CAAC,SAAS;QACb,MAAM,EACL,cAAc,GAAG,YAAY;YAC5B,CAAC,CAAC;gBACA,QAAQ,EAAE,mBAAmB;gBAC7B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,EAAE,YAAY,CAAC;aAChD;YACF,CAAC,CAAC,SAAS;KACb,CAAC;AACH,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { TextAsTree } from \"@fluidframework/tree/internal\";\n\n/**\n * Sync `newText` into the provided `root` tree.\n * @internal\n */\nexport function syncTextToTree(root: TextAsTree.Tree, newText: string): void {\n\tconst sync = computeSync(root.charactersCopy(), [...newText]);\n\n\tif (sync.remove) {\n\t\troot.removeRange(sync.remove.start, sync.remove.end);\n\t}\n\tif (sync.insert) {\n\t\troot.insertAt(sync.insert.location, sync.insert.slice.join(\"\"));\n\t}\n}\n\n/**\n * Sync `newText` into the provided `root` tree.\n */\nexport function computeSync<T>(\n\texisting: readonly T[],\n\tfinal: readonly T[],\n): { remove?: { start: number; end: number }; insert?: { location: number; slice: T[] } } {\n\t// Find common prefix and suffix to minimize changes\n\n\tlet prefixLength = 0;\n\twhile (\n\t\tprefixLength < existing.length &&\n\t\tprefixLength < final.length &&\n\t\texisting[prefixLength] === final[prefixLength]\n\t) {\n\t\tprefixLength++;\n\t}\n\n\tlet suffixLength = 0;\n\twhile (\n\t\tsuffixLength + prefixLength < existing.length &&\n\t\tsuffixLength + prefixLength < final.length &&\n\t\texisting[existing.length - 1 - suffixLength] === final[final.length - 1 - suffixLength]\n\t) {\n\t\tsuffixLength++;\n\t}\n\n\t// Locate middle replaced range in existing and final\n\tconst existingMiddleStart = prefixLength;\n\tconst existingMiddleEnd = existing.length - suffixLength;\n\tconst newMiddleStart = prefixLength;\n\tconst newMiddleEnd = final.length - suffixLength;\n\n\treturn {\n\t\tremove:\n\t\t\texistingMiddleStart < existingMiddleEnd\n\t\t\t\t? { start: existingMiddleStart, end: existingMiddleEnd }\n\t\t\t\t: undefined,\n\t\tinsert:\n\t\t\tnewMiddleStart < newMiddleEnd\n\t\t\t\t? {\n\t\t\t\t\t\tlocation: existingMiddleStart,\n\t\t\t\t\t\tslice: final.slice(newMiddleStart, newMiddleEnd),\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t};\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.92.0",
|
|
4
4
|
"description": "Utilities for integrating content powered by the Fluid Framework into React applications",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -63,28 +63,26 @@
|
|
|
63
63
|
"temp-directory": "nyc/.nyc_output"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@fluidframework/aqueduct": "~2.
|
|
67
|
-
"@fluidframework/core-interfaces": "~2.
|
|
68
|
-
"@fluidframework/core-utils": "~2.
|
|
69
|
-
"@fluidframework/datastore-definitions": "~2.
|
|
70
|
-
"@fluidframework/fluid-static": "~2.
|
|
71
|
-
"@fluidframework/runtime-definitions": "~2.
|
|
72
|
-
"@fluidframework/shared-object-base": "~2.
|
|
73
|
-
"@fluidframework/tree": "~2.
|
|
74
|
-
"quill": "^2.0.3",
|
|
75
|
-
"quill-delta": "^5.1.0",
|
|
66
|
+
"@fluidframework/aqueduct": "~2.92.0",
|
|
67
|
+
"@fluidframework/core-interfaces": "~2.92.0",
|
|
68
|
+
"@fluidframework/core-utils": "~2.92.0",
|
|
69
|
+
"@fluidframework/datastore-definitions": "~2.92.0",
|
|
70
|
+
"@fluidframework/fluid-static": "~2.92.0",
|
|
71
|
+
"@fluidframework/runtime-definitions": "~2.92.0",
|
|
72
|
+
"@fluidframework/shared-object-base": "~2.92.0",
|
|
73
|
+
"@fluidframework/tree": "~2.92.0",
|
|
76
74
|
"react": "^18.3.1",
|
|
77
75
|
"react-dom": "^18.3.1"
|
|
78
76
|
},
|
|
79
77
|
"devDependencies": {
|
|
80
78
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
81
79
|
"@biomejs/biome": "~2.4.5",
|
|
82
|
-
"@fluid-internal/mocha-test-setup": "~2.
|
|
83
|
-
"@fluid-tools/build-cli": "^0.
|
|
80
|
+
"@fluid-internal/mocha-test-setup": "~2.92.0",
|
|
81
|
+
"@fluid-tools/build-cli": "^0.64.0",
|
|
84
82
|
"@fluidframework/build-common": "^2.0.3",
|
|
85
|
-
"@fluidframework/build-tools": "^0.
|
|
86
|
-
"@fluidframework/eslint-config-fluid": "
|
|
87
|
-
"@fluidframework/tinylicious-client": "~2.
|
|
83
|
+
"@fluidframework/build-tools": "^0.64.0",
|
|
84
|
+
"@fluidframework/eslint-config-fluid": "^9.0.0",
|
|
85
|
+
"@fluidframework/tinylicious-client": "~2.92.0",
|
|
88
86
|
"@microsoft/api-extractor": "7.52.11",
|
|
89
87
|
"@testing-library/react": "^16.3.0",
|
|
90
88
|
"@types/mocha": "^10.0.10",
|
package/react.test-files.tar
CHANGED
|
Binary file
|
package/src/index.ts
CHANGED
|
@@ -45,13 +45,5 @@ export {
|
|
|
45
45
|
withMemoizedTreeObservations,
|
|
46
46
|
} from "./useTree.js";
|
|
47
47
|
export { objectIdNumber } from "./simpleIdentifier.js";
|
|
48
|
-
|
|
49
|
-
export {
|
|
50
|
-
FormattedMainView,
|
|
51
|
-
PlainTextMainView,
|
|
52
|
-
PlainQuillView,
|
|
53
|
-
type FormattedMainViewProps,
|
|
54
|
-
type PlainMainViewProps,
|
|
55
|
-
type FormattedEditorHandle,
|
|
56
|
-
} from "./text/index.js";
|
|
48
|
+
export { syncTextToTree, PlainTextMainView } from "./text/index.js";
|
|
57
49
|
export { UndoRedoStacks, type UndoRedo } from "./undoRedo.js";
|
package/src/text/index.ts
CHANGED
|
@@ -3,13 +3,6 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
export {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type FormattedEditorHandle,
|
|
10
|
-
} from "./formatted/index.js";
|
|
11
|
-
export {
|
|
12
|
-
PlainTextMainView,
|
|
13
|
-
QuillMainView as PlainQuillView,
|
|
14
|
-
type MainViewProps as PlainMainViewProps,
|
|
15
|
-
} from "./plain/index.js";
|
|
6
|
+
export { type PropTreeNode } from "../propNode.js";
|
|
7
|
+
export { type UndoRedo } from "../undoRedo.js";
|
|
8
|
+
export { PlainTextMainView, syncTextToTree } from "./plain/index.js";
|
package/src/text/plain/index.ts
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
import type { TextAsTree } from "@fluidframework/tree/internal";
|
|
7
7
|
import { type ChangeEvent, type FC, useCallback, useRef } from "react";
|
|
8
8
|
|
|
9
|
+
import type { PropTreeNode } from "../../propNode.js";
|
|
9
10
|
import { withMemoizedTreeObservations } from "../../useTree.js";
|
|
10
11
|
|
|
11
12
|
import { syncTextToTree } from "./plainUtils.js";
|
|
12
|
-
import type { MainViewProps } from "./quillView.js";
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* A React component for plain text editing.
|
|
@@ -17,7 +17,7 @@ import type { MainViewProps } from "./quillView.js";
|
|
|
17
17
|
* Uses {@link @fluidframework/tree#TextAsTree.Tree} for the data-model and an HTML textarea for the UI.
|
|
18
18
|
* @internal
|
|
19
19
|
*/
|
|
20
|
-
export const MainView: FC<
|
|
20
|
+
export const MainView: FC<{ root: PropTreeNode<TextAsTree.Tree> }> = ({ root }) => {
|
|
21
21
|
return <PlainTextEditorView root={root} />;
|
|
22
22
|
};
|
|
23
23
|
|
|
@@ -7,6 +7,7 @@ import type { TextAsTree } from "@fluidframework/tree/internal";
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Sync `newText` into the provided `root` tree.
|
|
10
|
+
* @internal
|
|
10
11
|
*/
|
|
11
12
|
export function syncTextToTree(root: TextAsTree.Tree, newText: string): void {
|
|
12
13
|
const sync = computeSync(root.charactersCopy(), [...newText]);
|
package/tsconfig.json
CHANGED
|
@@ -9,11 +9,5 @@
|
|
|
9
9
|
"noUnusedLocals": false,
|
|
10
10
|
// ES2021 needed for FinalizationRegistry
|
|
11
11
|
"lib": ["ES2021", "DOM", "DOM.Iterable"],
|
|
12
|
-
// Suppress type errors in Quill's use of quill-delta.
|
|
13
|
-
// Without this, the quill code gives a lot of errors like:
|
|
14
|
-
// node_modules/.pnpm/quill@2.0.3/node_modules/quill/blots/block.d.ts:6:17 - error TS2709: Cannot use namespace 'Delta' as a type.
|
|
15
|
-
// These issues (and others, see imports of quill-delta) are likely related to quill-delta's export style not working well with node16 module resolution.
|
|
16
|
-
// Quill internally uses `"moduleResolution": "bundler"` which seems to work properly with quill-delta's exports, but would be inconsistent with the rest of this repo.
|
|
17
|
-
"skipLibCheck": true,
|
|
18
12
|
},
|
|
19
13
|
}
|
package/lib/test/mochaHooks.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
import globalJsdom from "global-jsdom";
|
|
6
|
-
// Set up JSDOM before any modules are loaded (Quill needs document at import time)
|
|
7
|
-
const cleanup = globalJsdom();
|
|
8
|
-
// Remove JSDOM after imports are done, but before we run any tests.
|
|
9
|
-
// Tests which require JSDOM can call globalJsdom() to setup their own clean dom.
|
|
10
|
-
before(() => {
|
|
11
|
-
cleanup();
|
|
12
|
-
});
|
|
13
|
-
//# sourceMappingURL=mochaHooks.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mochaHooks.js","sourceRoot":"","sources":["../../src/test/mochaHooks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC,mFAAmF;AACnF,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AAE9B,oEAAoE;AACpE,iFAAiF;AACjF,MAAM,CAAC,GAAG,EAAE;IACX,OAAO,EAAE,CAAC;AACX,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport globalJsdom from \"global-jsdom\";\n\n// Set up JSDOM before any modules are loaded (Quill needs document at import time)\nconst cleanup = globalJsdom();\n\n// Remove JSDOM after imports are done, but before we run any tests.\n// Tests which require JSDOM can call globalJsdom() to setup their own clean dom.\nbefore(() => {\n\tcleanup();\n});\n"]}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
export { FormattedTextAsTree, FormattedMainView, type FormattedMainViewProps, type FormattedEditorHandle, } from "./quillFormattedView.js";
|
|
6
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/text/formatted/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC1B,MAAM,yBAAyB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/text/formatted/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,mBAAmB,EACnB,iBAAiB,GAGjB,MAAM,yBAAyB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport {\n\tFormattedTextAsTree,\n\tFormattedMainView,\n\ttype FormattedMainViewProps,\n\ttype FormattedEditorHandle,\n} from \"./quillFormattedView.js\";\n"]}
|