@valbuild/ui 0.26.0 → 0.28.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.
Files changed (145) hide show
  1. package/dist/valbuild-ui.cjs.js +41 -15
  2. package/dist/valbuild-ui.esm.js +41 -15
  3. package/package.json +7 -3
  4. package/server/.tmp/assets/index-18cfa26c.css +1 -0
  5. package/server/.tmp/assets/index-513f7a9c.js +197 -0
  6. package/{index.html → server/.tmp/index.html} +3 -1
  7. package/server/dist/style.css +0 -3
  8. package/server/dist/valbuild-ui-main.cjs.js +60 -34
  9. package/server/dist/valbuild-ui-main.esm.js +60 -34
  10. package/server/dist/valbuild-ui-server.cjs.js +1 -1
  11. package/server/dist/valbuild-ui-server.esm.js +1 -1
  12. package/.babelrc.json +0 -10
  13. package/.storybook/main.js +0 -25
  14. package/.storybook/preview-head.html +0 -6
  15. package/.storybook/preview.js +0 -33
  16. package/.storybook/theme.css +0 -34
  17. package/CHANGELOG.md +0 -0
  18. package/components.json +0 -16
  19. package/fix-server-hack.js +0 -54
  20. package/fullscreen.vite.config.ts +0 -9
  21. package/jest.config.js +0 -4
  22. package/postcss.config.js +0 -6
  23. package/rollup.config.js +0 -23
  24. package/server.vite.config.ts +0 -31
  25. package/src/App.tsx +0 -73
  26. package/src/assets/icons/Bold.tsx +0 -23
  27. package/src/assets/icons/Chevron.tsx +0 -28
  28. package/src/assets/icons/FontColor.tsx +0 -30
  29. package/src/assets/icons/ImageIcon.tsx +0 -29
  30. package/src/assets/icons/Italic.tsx +0 -24
  31. package/src/assets/icons/Logo.tsx +0 -103
  32. package/src/assets/icons/Section.tsx +0 -41
  33. package/src/assets/icons/Strikethrough.tsx +0 -22
  34. package/src/assets/icons/TextIcon.tsx +0 -20
  35. package/src/assets/icons/Underline.tsx +0 -22
  36. package/src/assets/icons/Undo.tsx +0 -20
  37. package/src/components/Button.tsx +0 -68
  38. package/src/components/Checkbox.tsx +0 -51
  39. package/src/components/DraggableList.stories.tsx +0 -20
  40. package/src/components/DraggableList.tsx +0 -95
  41. package/src/components/Dropdown.tsx +0 -101
  42. package/src/components/EditButton.tsx +0 -10
  43. package/src/components/ErrorText.tsx +0 -3
  44. package/src/components/ExpandLogo.tsx +0 -72
  45. package/src/components/Grid.stories.tsx +0 -43
  46. package/src/components/Grid.tsx +0 -139
  47. package/src/components/RichTextEditor/ContentEditable.tsx +0 -117
  48. package/src/components/RichTextEditor/Nodes/ImageNode.tsx +0 -100
  49. package/src/components/RichTextEditor/Plugins/AutoFocus.tsx +0 -12
  50. package/src/components/RichTextEditor/Plugins/ImagePlugin.tsx +0 -45
  51. package/src/components/RichTextEditor/Plugins/LinkEditorPlugin.tsx +0 -58
  52. package/src/components/RichTextEditor/Plugins/Toolbar.tsx +0 -412
  53. package/src/components/RichTextEditor/RichTextEditor.tsx +0 -105
  54. package/src/components/UploadModal.tsx +0 -109
  55. package/src/components/User.tsx +0 -17
  56. package/src/components/ValFormField.tsx +0 -574
  57. package/src/components/ValFullscreen.tsx +0 -1278
  58. package/src/components/ValMenu.tsx +0 -92
  59. package/src/components/ValOverlay.tsx +0 -488
  60. package/src/components/ValOverlayContext.tsx +0 -80
  61. package/src/components/ValWindow.stories.tsx +0 -146
  62. package/src/components/ValWindow.tsx +0 -220
  63. package/src/components/dashboard/DashboardButton.tsx +0 -25
  64. package/src/components/dashboard/DashboardDropdown.tsx +0 -59
  65. package/src/components/dashboard/Dropdown.stories.tsx +0 -11
  66. package/src/components/dashboard/Dropdown.tsx +0 -70
  67. package/src/components/dashboard/FormGroup.stories.tsx +0 -37
  68. package/src/components/dashboard/FormGroup.tsx +0 -42
  69. package/src/components/dashboard/Grid2.stories.tsx +0 -56
  70. package/src/components/dashboard/Grid2.tsx +0 -72
  71. package/src/components/dashboard/Tree.stories.tsx +0 -91
  72. package/src/components/dashboard/Tree.tsx +0 -72
  73. package/src/components/dashboard/ValDashboardEditor.tsx +0 -269
  74. package/src/components/dashboard/ValDashboardGrid.tsx +0 -142
  75. package/src/components/dashboard/ValTreeNavigator.tsx +0 -253
  76. package/src/components/forms/Form.tsx +0 -126
  77. package/src/components/forms/FormContainer.tsx +0 -24
  78. package/src/components/forms/ImageForm.tsx +0 -195
  79. package/src/components/forms/TextArea.tsx +0 -24
  80. package/src/components/ui/accordion.tsx +0 -58
  81. package/src/components/ui/alert-dialog.tsx +0 -139
  82. package/src/components/ui/avatar.tsx +0 -48
  83. package/src/components/ui/button.tsx +0 -56
  84. package/src/components/ui/calendar.tsx +0 -62
  85. package/src/components/ui/card.tsx +0 -86
  86. package/src/components/ui/checkbox.tsx +0 -28
  87. package/src/components/ui/command.tsx +0 -153
  88. package/src/components/ui/dialog.tsx +0 -120
  89. package/src/components/ui/dropdown-menu.tsx +0 -198
  90. package/src/components/ui/form.tsx +0 -177
  91. package/src/components/ui/input.tsx +0 -24
  92. package/src/components/ui/label.tsx +0 -24
  93. package/src/components/ui/popover.tsx +0 -29
  94. package/src/components/ui/progress.tsx +0 -26
  95. package/src/components/ui/radio-group.tsx +0 -42
  96. package/src/components/ui/scroll-area.tsx +0 -51
  97. package/src/components/ui/select.tsx +0 -119
  98. package/src/components/ui/switch.tsx +0 -27
  99. package/src/components/ui/tabs.tsx +0 -53
  100. package/src/components/ui/toggle.tsx +0 -43
  101. package/src/components/ui/tooltip.tsx +0 -28
  102. package/src/components/usePatch.ts +0 -86
  103. package/src/components/useTheme.ts +0 -45
  104. package/src/dto/SerializedSchema.ts +0 -69
  105. package/src/dto/Session.ts +0 -12
  106. package/src/dto/SessionMode.ts +0 -5
  107. package/src/dto/Tree.ts +0 -18
  108. package/src/exports.ts +0 -6
  109. package/src/index.css +0 -115
  110. package/src/index.tsx +0 -14
  111. package/src/lib/IValStore.ts +0 -6
  112. package/src/lib/utils.ts +0 -6
  113. package/src/main.jsx +0 -10
  114. package/src/richtext/conversion/conversion.test.ts +0 -146
  115. package/src/richtext/conversion/lexicalToRichTextSource.test.ts +0 -89
  116. package/src/richtext/conversion/lexicalToRichTextSource.ts +0 -285
  117. package/src/richtext/conversion/parseRichTextSource.test.ts +0 -469
  118. package/src/richtext/conversion/parseRichTextSource.ts +0 -233
  119. package/src/richtext/conversion/richTextSourceToLexical.test.ts +0 -381
  120. package/src/richtext/conversion/richTextSourceToLexical.ts +0 -293
  121. package/src/richtext/shadowRootPolyFill.js +0 -115
  122. package/src/server.ts +0 -70
  123. package/src/stories/Button.stories.tsx +0 -20
  124. package/src/stories/Checkbox.stories.tsx +0 -14
  125. package/src/stories/Dropdown.stories.tsx +0 -23
  126. package/src/stories/Introduction.mdx +0 -221
  127. package/src/stories/RichTextEditor.stories.tsx +0 -24
  128. package/src/stories/assets/code-brackets.svg +0 -1
  129. package/src/stories/assets/colors.svg +0 -1
  130. package/src/stories/assets/comments.svg +0 -1
  131. package/src/stories/assets/direction.svg +0 -1
  132. package/src/stories/assets/flow.svg +0 -1
  133. package/src/stories/assets/plugin.svg +0 -1
  134. package/src/stories/assets/repo.svg +0 -1
  135. package/src/stories/assets/stackalt.svg +0 -1
  136. package/src/utils/Remote.ts +0 -15
  137. package/src/utils/imageMimeType.ts +0 -23
  138. package/src/utils/readImage.ts +0 -54
  139. package/src/utils/resolvePath.ts +0 -32
  140. package/src/vite-env.d.ts +0 -1
  141. package/src/vite-index.tsx +0 -7
  142. package/src/vite-server.ts +0 -42
  143. package/tailwind.config.js +0 -83
  144. package/tsconfig.json +0 -19
  145. package/vite.config.ts +0 -43
@@ -1,146 +0,0 @@
1
- import {
2
- initVal,
3
- RichTextSource,
4
- AnyRichTextOptions,
5
- FILE_REF_PROP,
6
- } from "@valbuild/core";
7
- import { richTextSourceToLexical } from "./richTextSourceToLexical";
8
- import { lexicalToRichTextSource } from "./lexicalToRichTextSource";
9
- import { parseRichTextSource } from "./parseRichTextSource";
10
-
11
- const { val } = initVal();
12
- const cases: {
13
- description: string;
14
- input: RichTextSource<AnyRichTextOptions>;
15
- }[] = [
16
- {
17
- description: "basic",
18
- input: val.richtext`
19
- # Title 1
20
-
21
- ## Title 2
22
-
23
- ### Title 3
24
-
25
- #### Title 4
26
-
27
- ##### Title 5
28
-
29
- ###### Title 6
30
-
31
- Some paragraph. Another sentence.
32
-
33
- Another paragraph.
34
-
35
- Formatting: **bold**, _italic_, ~~line-through~~, ***bold and italic***.
36
-
37
- - List 1
38
- 1. List 1.1
39
- 1. List 1.2
40
- `,
41
- },
42
- {
43
- description: "all features",
44
- input: val.richtext`
45
- # Title 1
46
-
47
- Title 1 content.
48
-
49
- ## Title 2
50
-
51
- Title 2 content.
52
-
53
- ### Title 3
54
-
55
- Title 3 content.
56
-
57
- #### Title 4
58
-
59
- Title 4 content.
60
-
61
- ##### Title 5
62
-
63
- ###### Title 6
64
-
65
- Some paragraph. Another sentence.
66
-
67
- Another paragraph.
68
-
69
- Formatting: **bold**, _italic_, ~~line-through~~, ***bold and italic***.
70
-
71
- - List 1
72
- 1. List 1.1
73
- 1. List 1.2
74
-
75
- Inline link: ${val.link("**link**", { href: "https://link.com" })}
76
-
77
- <br />
78
-
79
- Block link:
80
-
81
- ${val.link("**link**", { href: "https://link.com" })}
82
-
83
- <br />
84
-
85
- Block Image:
86
-
87
- ${val.file("/public/test.jpg", {
88
- width: 100,
89
- height: 100,
90
- sha256: "123",
91
- })}
92
-
93
- <br />
94
-
95
- <br />
96
-
97
- - List 1
98
- 1. List 1.1
99
- 1. List 1.2
100
- - List 2
101
- - List 3
102
- 1. Formatted **list**
103
- Test 123
104
- `,
105
- },
106
- ];
107
-
108
- describe("isomorphic richtext <-> conversion", () => {
109
- test.each(cases)("$description", async ({ input }) => {
110
- const inputSource = input;
111
-
112
- const res = await lexicalToRichTextSource(
113
- richTextSourceToLexical(parseRichTextSource(inputSource))
114
- );
115
-
116
- const output = stringifyRichTextSource(res);
117
- // console.log("EOF>>" + output + "<<EOF");
118
- expect(stringifyRichTextSource(inputSource)).toStrictEqual(output);
119
- });
120
- });
121
-
122
- function stringifyRichTextSource({
123
- templateStrings,
124
- exprs,
125
- }: RichTextSource<AnyRichTextOptions>): string {
126
- let lines = "";
127
- for (let i = 0; i < templateStrings.length; i++) {
128
- const line = templateStrings[i];
129
- const expr = exprs[i];
130
- lines += line;
131
- if (expr) {
132
- if (expr._type === "file") {
133
- lines += `\${val.file("${expr[FILE_REF_PROP]}", ${JSON.stringify(
134
- expr.metadata
135
- )})}`;
136
- } else if (expr._type === "link") {
137
- lines += `\${val.link("${expr.children[0]}", ${JSON.stringify({
138
- href: expr.href,
139
- })})}`;
140
- } else {
141
- throw Error("Unknown expr: " + JSON.stringify(expr, null, 2));
142
- }
143
- }
144
- }
145
- return lines;
146
- }
@@ -1,89 +0,0 @@
1
- import { initVal } from "@valbuild/core";
2
- import { parseRichTextSource } from "./parseRichTextSource";
3
-
4
- const { val } = initVal();
5
-
6
- describe("lexical to RichTextSource", () => {
7
- test("parse empty richtext source", () => {
8
- const output = parseRichTextSource({
9
- _type: "richtext",
10
- templateStrings: [""],
11
- exprs: [],
12
- });
13
- expect(output).toStrictEqual({ _type: "richtext", children: [] });
14
- });
15
-
16
- test("parse basic richtext source", () => {
17
- const output = parseRichTextSource<{
18
- a: true;
19
- li: true;
20
- ul: true;
21
- heading: ["h1"];
22
- }>(val.richtext`
23
- # Title 1
24
-
25
- ${val.link("**link**", { href: "https://link.com" })}
26
-
27
- <br>
28
-
29
- - List 1
30
- 1. List 1.1
31
- 1. List 1.2
32
- Test 123
33
- `);
34
- expect(output).toStrictEqual({
35
- _type: "richtext",
36
- children: [
37
- {
38
- tag: "h1",
39
- children: ["Title 1"],
40
- },
41
- {
42
- tag: "p",
43
- children: [
44
- {
45
- tag: "a",
46
- href: "https://link.com",
47
- children: [
48
- {
49
- tag: "span",
50
- classes: ["bold"],
51
- children: ["link"],
52
- },
53
- ],
54
- },
55
- ],
56
- },
57
- { tag: "br", children: [] },
58
- {
59
- tag: "ul",
60
- children: [
61
- {
62
- tag: "li",
63
- children: [
64
- "List 1",
65
- {
66
- tag: "ol",
67
- children: [
68
- {
69
- tag: "li",
70
- children: ["List 1.1"],
71
- },
72
- {
73
- tag: "li",
74
- children: [
75
- "List 1.2",
76
- { tag: "br", children: [] },
77
- "Test 123",
78
- ],
79
- },
80
- ],
81
- },
82
- ],
83
- },
84
- ],
85
- },
86
- ],
87
- });
88
- });
89
- });
@@ -1,285 +0,0 @@
1
- import {
2
- LinkSource,
3
- FILE_REF_PROP,
4
- Internal,
5
- VAL_EXTENSION,
6
- RichTextSource,
7
- AnyRichTextOptions,
8
- } from "@valbuild/core";
9
- import { getMimeType, mimeTypeToFileExt } from "../../utils/imageMimeType";
10
-
11
- import {
12
- LexicalImageNode,
13
- LexicalLineBreakNode,
14
- LexicalLinkNode,
15
- LexicalListItemNode,
16
- LexicalListNode,
17
- LexicalRootNode,
18
- LexicalTextNode,
19
- } from "./richTextSourceToLexical";
20
-
21
- const HeaderRegEx = /^h([\d+])$/;
22
- // Promise<
23
- // RichTextSource<AnyRichTextOptions> & { files: Record<string, string> }
24
- // >
25
-
26
- type MarkdownIR = {
27
- type: "block";
28
- children: (string | LexicalImageNode | LexicalLinkNode)[];
29
- };
30
-
31
- const MAX_LINE_LENGTH = 80;
32
- export function lexicalToRichTextSource(
33
- node: LexicalRootNode
34
- ): Promise<
35
- RichTextSource<AnyRichTextOptions> & { files: Record<string, string> }
36
- > {
37
- const markdownIRBlocks: MarkdownIR[] = node.children.map(createBlock);
38
- return fromIRToRichTextSource(markdownIRBlocks);
39
- }
40
-
41
- function createBlock(node: LexicalRootNode["children"][number]): MarkdownIR {
42
- if (node.type === "heading") {
43
- let headingTag = "";
44
- const depth = Number(node.tag.match(HeaderRegEx)?.[1]);
45
- if (Number.isNaN(depth)) {
46
- throw new Error("Invalid header depth");
47
- }
48
- for (let i = 0; i < Number(depth); i++) {
49
- headingTag += "#";
50
- }
51
- const headingText: MarkdownIR["children"] = [`${headingTag} `];
52
- return {
53
- type: "block",
54
- children: headingText.concat(...node.children.map(transformLeafNode)),
55
- };
56
- } else if (node.type === "paragraph") {
57
- if (node.children.length === 0) {
58
- return {
59
- type: "block",
60
- children: ["<br />"],
61
- };
62
- }
63
- return {
64
- type: "block",
65
- children: node.children.map((child) => transformLeafNode(child)),
66
- };
67
- } else if (node.type === "list") {
68
- return {
69
- type: "block",
70
- children: node.children.flatMap((child, i) =>
71
- formatListItemNode(getListPrefix(node), child, 0, i === 0)
72
- ),
73
- };
74
- } else {
75
- const exhaustiveCheck: never = node;
76
- throw new Error(
77
- `Unhandled node type: ${
78
- "type" in exhaustiveCheck ? "exhaustiveCheck.type" : "unknown"
79
- }`
80
- );
81
- }
82
- }
83
-
84
- async function fromIRToRichTextSource(
85
- markdownIRBlocks: MarkdownIR[]
86
- ): Promise<
87
- RichTextSource<AnyRichTextOptions> & { files: Record<string, string> }
88
- > {
89
- const templateStrings = ["\n"];
90
- const exprs = [];
91
- const files: Record<string, string> = {};
92
- for (let blockIdx = 0; blockIdx < markdownIRBlocks.length; blockIdx++) {
93
- const block = markdownIRBlocks[blockIdx];
94
- for (const child of block.children) {
95
- if (typeof child === "string") {
96
- templateStrings[templateStrings.length - 1] += child;
97
- } else {
98
- if (child.type === "image") {
99
- exprs.push(await fromLexicalImageNode(child, files));
100
- } else if (child.type === "link") {
101
- exprs.push(fromLexicalLinkNode(child));
102
- } else {
103
- const exhaustiveCheck: never = child;
104
- throw new Error(
105
- `Unexpected node type: ${JSON.stringify(exhaustiveCheck, null, 2)}`
106
- );
107
- }
108
- templateStrings.push("");
109
- }
110
- }
111
- if (blockIdx === markdownIRBlocks.length - 1) {
112
- templateStrings[templateStrings.length - 1] += "\n";
113
- } else {
114
- templateStrings[templateStrings.length - 1] += "\n\n";
115
- }
116
- }
117
- return { [VAL_EXTENSION]: "richtext", templateStrings, exprs: exprs, files };
118
- }
119
-
120
- function formatText(node: LexicalTextNode): string {
121
- const classes =
122
- typeof node.format === "number" ? fromLexicalFormat(node.format) : [];
123
- let text = node.text.trimStart();
124
- const prefixWS = node.text.length - text.length;
125
- text = text.trimEnd();
126
- const suffixWS = node.text.length - text.length - prefixWS;
127
- if (classes.includes("bold") && classes.includes("italic")) {
128
- text = `***${text}***`;
129
- } else if (classes.includes("bold")) {
130
- text = `**${text}**`;
131
- } else if (classes.includes("italic")) {
132
- text = `_${text}_`;
133
- }
134
- if (classes.includes("line-through")) {
135
- text = `~~${text}~~`;
136
- }
137
- // TODO:
138
- // text = splitIntoChunks(text);
139
- return `${" ".repeat(prefixWS)}${text}${" ".repeat(suffixWS)}`;
140
- }
141
-
142
- function transformLeafNode(
143
- node:
144
- | LexicalTextNode
145
- | LexicalImageNode
146
- | LexicalLinkNode
147
- | LexicalLineBreakNode
148
- ): string | LexicalImageNode | LexicalLinkNode {
149
- if (node.type === "text") {
150
- return formatText(node);
151
- } else if (node.type === "linebreak") {
152
- return "\n";
153
- } else {
154
- return node;
155
- }
156
- }
157
-
158
- function formatListItemNode(
159
- listPrefix: string,
160
- node: LexicalListItemNode,
161
- indent: number,
162
- isFirstTopLevelListItem = false
163
- ): (string | LexicalImageNode | LexicalLinkNode)[] {
164
- const newLine = isFirstTopLevelListItem ? "" : "\n";
165
- const prefix: (string | LexicalImageNode | LexicalLinkNode)[] = [
166
- `${newLine}${" ".repeat(indent)}${listPrefix}`,
167
- ];
168
- if (node.children?.[0]?.type !== "list") {
169
- prefix.push(" ");
170
- }
171
-
172
- return prefix.concat(
173
- node.children.flatMap((child) => {
174
- if (child.type === "list") {
175
- return child.children.flatMap((subChild) =>
176
- formatListItemNode(getListPrefix(child), subChild, indent + 4)
177
- );
178
- } else {
179
- return [transformLeafNode(child)];
180
- }
181
- })
182
- );
183
- }
184
-
185
- function getListPrefix(node: LexicalListNode): string {
186
- if (node.listType === "bullet") {
187
- return "-";
188
- } else if (node.listType === "number") {
189
- return "1.";
190
- } else {
191
- throw new Error(`Unhandled list type: ${node.listType}`);
192
- }
193
- }
194
-
195
- const FORMAT_MAPPING = {
196
- bold: 1, // 0001
197
- italic: 2, // 0010
198
- "line-through": 4, // 0100
199
- // underline: 8, // 1000
200
- };
201
-
202
- export function fromLexicalFormat(
203
- format: number
204
- ): (keyof typeof FORMAT_MAPPING)[] {
205
- return Object.entries(FORMAT_MAPPING).flatMap(([key, value]) => {
206
- if ((value & /* bitwise and */ format) === value) {
207
- return [key as keyof typeof FORMAT_MAPPING];
208
- }
209
- return [];
210
- });
211
- }
212
-
213
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
214
- function splitIntoChunks(str: string) {
215
- let line = "";
216
- for (let i = 0; i < str.length; i += 80) {
217
- const chunk = str.substring(i, i + MAX_LINE_LENGTH);
218
- line += chunk;
219
- if (i !== str.length - 1 && chunk.length >= 80) {
220
- line += "\n";
221
- }
222
- }
223
- return line;
224
- }
225
-
226
- const textEncoder = new TextEncoder();
227
- async function fromLexicalImageNode(
228
- node: LexicalImageNode,
229
- files: Record<string, string>
230
- ) {
231
- if (node.src.startsWith("data:")) {
232
- const sha256 = await Internal.getSHA256Hash(textEncoder.encode(node.src));
233
- const mimeType = getMimeType(node.src);
234
- if (mimeType === undefined) {
235
- throw new Error(`Could not detect Mime Type for image: ${node.src}`);
236
- }
237
- const fileExt = mimeTypeToFileExt(mimeType);
238
- const filePath = `/public/${sha256}.${fileExt}`;
239
- files[filePath] = node.src;
240
- return {
241
- [VAL_EXTENSION]: "file" as const,
242
- [FILE_REF_PROP]: filePath,
243
- metadata: {
244
- width: node.width || 0,
245
- height: node.width || 0,
246
- sha256: sha256 || "",
247
- },
248
- };
249
- } else {
250
- const sha256 = getParam("sha256", node.src);
251
- return {
252
- [VAL_EXTENSION]: "file" as const,
253
- [FILE_REF_PROP]: `/public${node.src.split("?")[0]}`,
254
- metadata: {
255
- width: node.width || 0,
256
- height: node.width || 0,
257
- sha256: sha256 || "",
258
- },
259
- };
260
- }
261
- }
262
-
263
- function getParam(param: string, url: string) {
264
- const urlParts = url.split("?");
265
- if (urlParts.length < 2) {
266
- return undefined;
267
- }
268
-
269
- const queryString = urlParts[1];
270
- const params = new URLSearchParams(queryString);
271
-
272
- if (params.has(param)) {
273
- return params.get(param);
274
- }
275
-
276
- return undefined;
277
- }
278
-
279
- function fromLexicalLinkNode(node: LexicalLinkNode): LinkSource {
280
- return {
281
- [VAL_EXTENSION]: "link",
282
- href: node.url,
283
- children: node.children.map(formatText) as LinkSource["children"],
284
- };
285
- }