@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,469 +0,0 @@
1
- import { initVal } from "@valbuild/core";
2
- import { parseRichTextSource } from "./parseRichTextSource";
3
-
4
- const { val } = initVal();
5
-
6
- //MD to HTML
7
- describe("richtext", () => {
8
- test("basic h1", () => {
9
- const r = val.richtext`# Title 1`;
10
- expect(parseRichTextSource(r).children).toStrictEqual([
11
- { tag: "h1", children: ["Title 1"] },
12
- ]);
13
- });
14
-
15
- test("basic complete", () => {
16
- const r = val.richtext`# Title 1
17
- ## Title 2
18
-
19
- Paragraph 1 2 3 4 5. Words *italic* **bold**
20
- `;
21
- expect(parseRichTextSource(r).children).toStrictEqual([
22
- { tag: "h1", children: ["Title 1"] },
23
- { tag: "h2", children: ["Title 2"] },
24
- {
25
- tag: "p",
26
- children: [
27
- "Paragraph 1 2 3 4 5. Words ",
28
- { tag: "span", classes: ["italic"], children: ["italic"] },
29
- " ",
30
- { tag: "span", classes: ["bold"], children: ["bold"] },
31
- ],
32
- },
33
- ]);
34
- });
35
-
36
- test.skip("strong and emphasis merged spans", () => {
37
- // TODO: currently we do not merge
38
- const r = val.richtext`Which classes?
39
- ***All of them!***
40
- `;
41
- expect(parseRichTextSource(r).children).toStrictEqual([
42
- {
43
- tag: "p",
44
- children: [
45
- "Which classes?\n",
46
- {
47
- tag: "span",
48
- classes: ["italic", "bold"],
49
- children: ["All of them!"],
50
- },
51
- ],
52
- },
53
- ]);
54
- });
55
-
56
- test("line through", () => {
57
- // TODO: currently we do not merge
58
- const r = val.richtext`~~line through~~`;
59
- expect(parseRichTextSource(r).children).toStrictEqual([
60
- {
61
- tag: "p",
62
- children: [
63
- {
64
- tag: "span",
65
- classes: ["line-through"],
66
- children: ["line through"],
67
- },
68
- ],
69
- },
70
- ]);
71
- });
72
-
73
- test("2 paragraphs", () => {
74
- const r = val.richtext`# Title 1
75
-
76
- First paragraph
77
-
78
- Second paragraph
79
- `;
80
- expect(parseRichTextSource(r).children).toStrictEqual([
81
- { tag: "h1", children: ["Title 1"] },
82
- { tag: "p", children: ["First paragraph"] },
83
- { tag: "p", children: ["Second paragraph"] },
84
- ]);
85
- });
86
-
87
- test("basic lists", () => {
88
- const r = val.richtext`A bullet list:
89
-
90
- - bullet 1
91
- - bullet 2
92
- `;
93
- expect(parseRichTextSource(r).children).toStrictEqual([
94
- { tag: "p", children: ["A bullet list:"] },
95
- {
96
- tag: "ul",
97
- children: [
98
- { tag: "li", children: ["bullet 1"] },
99
- { tag: "li", children: ["bullet 2"] },
100
- ],
101
- },
102
- ]);
103
- });
104
-
105
- test("lists with line breaks", () => {
106
- const r = val.richtext`A bullet list:
107
-
108
- - bullet 1
109
- - bullet 2
110
- break this line
111
- `;
112
- expect(parseRichTextSource(r).children).toStrictEqual([
113
- { tag: "p", children: ["A bullet list:"] },
114
- {
115
- tag: "ul",
116
- children: [
117
- {
118
- tag: "li",
119
- children: ["bullet 1"],
120
- },
121
- {
122
- tag: "li",
123
- children: [
124
- "bullet 2",
125
- { tag: "br", children: [] },
126
- "break this line",
127
- ],
128
- },
129
- ],
130
- },
131
- ]);
132
- });
133
-
134
- test("special chars", () => {
135
- const r = val.richtext`# "Title 1"
136
-
137
- Beautiful "quotes" and 'single quotes'
138
-
139
- Some crocodiles: < >
140
-
141
- Ampersand: &
142
-
143
- `;
144
- expect(parseRichTextSource(r).children).toStrictEqual([
145
- { tag: "h1", children: ['"Title 1"'] },
146
- { tag: "p", children: [`Beautiful "quotes" and 'single quotes'`] },
147
- { tag: "p", children: ["Some crocodiles: < >"] },
148
- { tag: "p", children: ["Ampersand: &"] },
149
- ]);
150
- });
151
-
152
- test("lists", () => {
153
- const r = val.richtext`# Title 1
154
-
155
- A paragraph
156
-
157
- A bullet list:
158
- - bullet 1
159
- - bullet 2
160
-
161
- A numbered list:
162
- 1. number 1
163
- 2. number 2
164
-
165
- A nested list:
166
- - bullet 1:
167
- 1. number 1.1
168
- 2. number 1.2
169
- - bullet 2:
170
- - bullet 2.1
171
- - bullet 2.2
172
- `;
173
- expect(parseRichTextSource(r).children).toStrictEqual([
174
- { tag: "h1", children: ["Title 1"] },
175
- { tag: "p", children: ["A paragraph"] },
176
- { tag: "p", children: ["A bullet list:"] },
177
- {
178
- tag: "ul",
179
- children: [
180
- { tag: "li", children: ["bullet 1"] },
181
- { tag: "li", children: ["bullet 2"] },
182
- ],
183
- },
184
- { tag: "p", children: ["A numbered list:"] },
185
- {
186
- tag: "ol",
187
- children: [
188
- { tag: "li", children: ["number 1"] },
189
- { tag: "li", children: ["number 2"] },
190
- ],
191
- },
192
- { tag: "p", children: ["A nested list:"] },
193
- {
194
- tag: "ul",
195
- children: [
196
- {
197
- tag: "li",
198
- children: [
199
- "bullet 1:",
200
- {
201
- tag: "ol",
202
- children: [
203
- { tag: "li", children: ["number 1.1"] },
204
- { tag: "li", children: ["number 1.2"] },
205
- ],
206
- },
207
- ],
208
- },
209
- {
210
- tag: "li",
211
- children: [
212
- "bullet 2:",
213
- {
214
- tag: "ul",
215
- children: [
216
- { tag: "li", children: ["bullet 2.1"] },
217
- { tag: "li", children: ["bullet 2.2"] },
218
- ],
219
- },
220
- ],
221
- },
222
- ],
223
- },
224
- ]);
225
- });
226
-
227
- test("br tokens", () => {
228
- const r = val.richtext`1 år 400,- kinokveld
229
- 5 år 5000,- en kveld i tretoppene`;
230
- expect(parseRichTextSource(r).children).toStrictEqual([
231
- {
232
- tag: "p",
233
- children: [
234
- "1 år 400,- kinokveld",
235
- { tag: "br", children: [] },
236
- "5 år 5000,- en kveld i tretoppene",
237
- ],
238
- },
239
- ]);
240
- });
241
-
242
- test("multiple br tokens", () => {
243
- const r = val.richtext`1 år 400,- kinokveld
244
- 2 år 1000,- kulturell opplevelse
245
- 3 år 2000,- mat i fjeset
246
- 4 år 500,- nørding i bokhandel
247
- 5 år 5000,- en kveld i tretoppene
248
- 6 år 1200,- ta smaksløkene på trim
249
- 7 år 2500,- gjør en forskjell`;
250
- expect(parseRichTextSource(r).children).toStrictEqual([
251
- {
252
- tag: "p",
253
- children: [
254
- "1 år 400,- kinokveld",
255
- { tag: "br", children: [] },
256
- "2 år 1000,- kulturell opplevelse",
257
- { tag: "br", children: [] },
258
- "3 år 2000,- mat i fjeset",
259
- { tag: "br", children: [] },
260
- "4 år 500,- nørding i bokhandel",
261
- { tag: "br", children: [] },
262
- "5 år 5000,- en kveld i tretoppene",
263
- { tag: "br", children: [] },
264
- "6 år 1200,- ta smaksløkene på trim",
265
- { tag: "br", children: [] },
266
- "7 år 2500,- gjør en forskjell",
267
- ],
268
- },
269
- ]);
270
- });
271
-
272
- test("image", () => {
273
- const r = val.richtext`# Title 1
274
-
275
- Below we have an image block:
276
-
277
- ${val.file("/public/foo.png", {
278
- width: 100,
279
- height: 100,
280
- sha256: "123",
281
- })}`;
282
- expect(parseRichTextSource(r).children).toStrictEqual([
283
- { tag: "h1", children: ["Title 1"] },
284
- { tag: "p", children: ["Below we have an image block:"] },
285
- {
286
- tag: "p",
287
- children: [
288
- {
289
- src: "/foo.png?sha256=123",
290
- tag: "img",
291
- width: 100,
292
- height: 100,
293
- children: [],
294
- },
295
- ],
296
- },
297
- ]);
298
- });
299
-
300
- test("markdown link", () => {
301
- const r = val.richtext`# Title 1
302
-
303
- Below we have a url: [google](https://google.com)`;
304
- expect(parseRichTextSource(r).children).toStrictEqual([
305
- { tag: "h1", children: ["Title 1"] },
306
- {
307
- tag: "p",
308
- children: [
309
- "Below we have a url: ",
310
- {
311
- href: "https://google.com",
312
- tag: "a",
313
- children: ["google"],
314
- },
315
- ],
316
- },
317
- ]);
318
- });
319
-
320
- test("block link", () => {
321
- const r = val.richtext`# Title 1
322
-
323
- Below we have a url:
324
-
325
- ${val.link("google", { href: "https://google.com" })}`;
326
- expect(parseRichTextSource(r).children).toStrictEqual([
327
- { tag: "h1", children: ["Title 1"] },
328
- { tag: "p", children: ["Below we have a url:"] },
329
- {
330
- tag: "p",
331
- children: [
332
- {
333
- tag: "a",
334
- href: "https://google.com",
335
- children: ["google"],
336
- },
337
- ],
338
- },
339
- ]);
340
- });
341
-
342
- test("inline link", () => {
343
- const r = val.richtext`# Title 1
344
-
345
- Below we have a url: ${val.link("google", { href: "https://google.com" })}`;
346
- expect(parseRichTextSource(r).children).toStrictEqual([
347
- { tag: "h1", children: ["Title 1"] },
348
- {
349
- tag: "p",
350
- children: [
351
- "Below we have a url: ",
352
- {
353
- href: "https://google.com",
354
- tag: "a",
355
- children: ["google"],
356
- },
357
- ],
358
- },
359
- ]);
360
- });
361
-
362
- test("inline link with bold", () => {
363
- const r = val.richtext`# Title 1
364
-
365
- Inline link -> ${val.link("**google**", { href: "https://google.com" })}`;
366
-
367
- // source:
368
- expect(parseRichTextSource(r).children).toStrictEqual([
369
- { tag: "h1", children: ["Title 1"] },
370
- {
371
- tag: "p",
372
- children: [
373
- "Inline link -> ",
374
- {
375
- href: "https://google.com",
376
- tag: "a",
377
- children: [
378
- {
379
- tag: "span",
380
- classes: ["bold"],
381
- children: ["google"],
382
- },
383
- ],
384
- },
385
- ],
386
- },
387
- ]);
388
- });
389
-
390
- test("https:// in link description", () => {
391
- const r = val.richtext`# Title 1
392
-
393
- Inline link -> ${val.link("https://google.com", {
394
- href: "https://google.com",
395
- })}`;
396
-
397
- expect(parseRichTextSource(r).children).toStrictEqual([
398
- { tag: "h1", children: ["Title 1"] },
399
- {
400
- tag: "p",
401
- children: [
402
- "Inline link -> ",
403
- {
404
- tag: "a",
405
- href: "https://google.com",
406
- children: ["https://google.com"],
407
- },
408
- ],
409
- },
410
- ]);
411
- });
412
-
413
- test("auto link does nothing", () => {
414
- const r = val.richtext`# Title 1
415
-
416
- No transform here -> https://google.com
417
-
418
- Transform this:
419
- [https://google.com](https://google.com)
420
- `;
421
-
422
- expect(parseRichTextSource(r).children).toStrictEqual([
423
- { tag: "h1", children: ["Title 1"] },
424
- {
425
- tag: "p",
426
- children: ["No transform here -> ", "https://google.com"],
427
- },
428
- {
429
- tag: "p",
430
- children: [
431
- "Transform this:\n",
432
- {
433
- tag: "a",
434
- href: "https://google.com",
435
- children: ["https://google.com"],
436
- },
437
- ],
438
- },
439
- ]);
440
- });
441
-
442
- test("breaks", () => {
443
- const r = val.richtext`
444
- # Title 1
445
-
446
- Foo
447
-
448
- <br>
449
-
450
- Bar
451
- `;
452
- // source:
453
- expect(parseRichTextSource(r).children).toStrictEqual([
454
- { tag: "h1", children: ["Title 1"] },
455
- {
456
- tag: "p",
457
- children: ["Foo"],
458
- },
459
- {
460
- tag: "br",
461
- children: [],
462
- },
463
- {
464
- tag: "p",
465
- children: ["Bar"],
466
- },
467
- ]);
468
- });
469
- });
@@ -1,233 +0,0 @@
1
- import * as marked from "marked";
2
- import {
3
- OrderedListNode,
4
- AnyRichTextOptions,
5
- UnorderedListNode,
6
- LinkSource,
7
- RichTextNode,
8
- SpanNode,
9
- LinkNode,
10
- ListItemNode,
11
- RichTextOptions,
12
- RichTextSource,
13
- RichText,
14
- VAL_EXTENSION,
15
- FileSource,
16
- ParagraphNode,
17
- HeadingNode,
18
- Internal,
19
- } from "@valbuild/core";
20
-
21
- const VAL_START_TAG_PREFIX = '<val value="';
22
- const VAL_START_TAG_SUFFIX = '">';
23
- const VAL_END_TAG = "</val>";
24
-
25
- type AnyListChildren =
26
- | OrderedListNode<AnyRichTextOptions>["children"]
27
- | UnorderedListNode<AnyRichTextOptions>["children"];
28
-
29
- type ImageSource = FileSource<{
30
- width: number;
31
- height: number;
32
- sha256: string;
33
- }>;
34
-
35
- function parseTokens(
36
- tokens: marked.Token[],
37
- sourceNodes: (ImageSource | LinkSource)[],
38
- cursor: number,
39
- insideList = false
40
- ): { children: RichTextNode<AnyRichTextOptions>[]; cursor: number } {
41
- const children: RichTextNode<AnyRichTextOptions>[] = [];
42
- while (cursor < tokens.length) {
43
- const token = tokens[cursor];
44
- if (token.type === "heading") {
45
- children.push({
46
- tag: `h${token.depth as 1 | 2 | 3 | 4 | 5 | 6}`,
47
- children: parseTokens(token.tokens ? token.tokens : [], sourceNodes, 0)
48
- .children as HeadingNode<AnyRichTextOptions>["children"],
49
- });
50
- } else if (token.type === "paragraph") {
51
- children.push({
52
- tag: "p",
53
- children: parseTokens(token.tokens ? token.tokens : [], sourceNodes, 0)
54
- .children as ParagraphNode<AnyRichTextOptions>["children"],
55
- });
56
- } else if (token.type === "strong") {
57
- children.push({
58
- tag: "span",
59
- classes: ["bold"],
60
- children: parseTokens(token.tokens ? token.tokens : [], sourceNodes, 0)
61
- .children as SpanNode<AnyRichTextOptions>["children"],
62
- });
63
- } else if (token.type === "em") {
64
- children.push({
65
- tag: "span",
66
- classes: ["italic"],
67
- children: parseTokens(token.tokens ? token.tokens : [], sourceNodes, 0)
68
- .children as SpanNode<AnyRichTextOptions>["children"],
69
- });
70
- } else if (token.type === "del") {
71
- children.push({
72
- tag: "span",
73
- classes: ["line-through"],
74
- children: parseTokens(token.tokens ? token.tokens : [], sourceNodes, 0)
75
- .children as SpanNode<AnyRichTextOptions>["children"],
76
- });
77
- } else if (token.type === "text") {
78
- if ("tokens" in token && Array.isArray(token.tokens)) {
79
- children.push(
80
- ...parseTokens(token.tokens, sourceNodes, cursor, insideList).children
81
- );
82
- } else {
83
- if (insideList && typeof token.raw === "string") {
84
- const lines = token.raw.split("\n");
85
- const tags: RichTextNode<AnyRichTextOptions>[] = lines.flatMap(
86
- (line, i) => {
87
- if (i === lines.length - 1) return [line];
88
- return [line, { tag: "br", children: [] }];
89
- }
90
- );
91
- children.push(...tags);
92
- } else {
93
- children.push(token.raw);
94
- }
95
- }
96
- } else if (token.type === "list") {
97
- children.push({
98
- tag: token.ordered ? "ol" : "ul",
99
- children: parseTokens(token.items, sourceNodes, 0)
100
- .children as AnyListChildren,
101
- });
102
- } else if (token.type === "list_item") {
103
- children.push({
104
- tag: "li",
105
- children: parseTokens(
106
- token.tokens ? token.tokens : [],
107
- sourceNodes,
108
- 0,
109
- true
110
- ).children as ListItemNode<AnyRichTextOptions>["children"],
111
- });
112
- } else if (token.type === "space") {
113
- // do nothing
114
- } else if (token.type === "html") {
115
- if (token.text === VAL_END_TAG) {
116
- return { children, cursor };
117
- }
118
- const suffixIndex = token.text.indexOf(VAL_START_TAG_SUFFIX);
119
- if (token.text.startsWith(VAL_START_TAG_PREFIX) && suffixIndex > -1) {
120
- const number = Number(
121
- token.text.slice(VAL_START_TAG_PREFIX.length, suffixIndex)
122
- );
123
- if (Number.isNaN(number)) {
124
- throw Error(
125
- `Illegal val intermediate node: ${JSON.stringify(token)}`
126
- );
127
- }
128
- const { children: subChildren, cursor: subCursor } = parseTokens(
129
- tokens.map((token) => {
130
- if (token.type === "link" || token.type === "list") {
131
- return {
132
- type: "text",
133
- raw: token.raw,
134
- text: token.raw,
135
- };
136
- }
137
- return token;
138
- }),
139
- sourceNodes,
140
- cursor + 1
141
- );
142
- const sourceNode = sourceNodes[number];
143
- if (sourceNode._type === "link") {
144
- children.push({
145
- tag: "a",
146
- href: sourceNode.href,
147
- children: subChildren as LinkNode<AnyRichTextOptions>["children"],
148
- });
149
- } else if (sourceNode._type === "file") {
150
- children.push({
151
- tag: "img",
152
- src: Internal.convertFileSource(sourceNode).url,
153
- width: sourceNode.metadata?.width,
154
- height: sourceNode.metadata?.height,
155
- children: [],
156
- });
157
- }
158
-
159
- cursor = subCursor;
160
- }
161
- const br_html_regex = /<br\s*\/?>/gi; // matches <br>, <br/>, <br />; case insensitive
162
- if (token.text.trim().match(br_html_regex)) {
163
- children.push({
164
- tag: "br",
165
- children: [],
166
- });
167
- }
168
- } else if (token.type === "link") {
169
- if (token.raw === token.href) {
170
- // avoid auto-linking (provided by github flavoured markdown, but we want strikethrough so keep it enabled)
171
- children.push(token.raw);
172
- } else {
173
- children.push({
174
- tag: "a",
175
- href: token.href,
176
- children: parseTokens(
177
- token.tokens ? token.tokens : [],
178
- sourceNodes,
179
- 0
180
- ).children as LinkNode<AnyRichTextOptions>["children"],
181
- });
182
- }
183
- } else if (token.type === "br") {
184
- children.push({
185
- tag: "br",
186
- children: [],
187
- });
188
- } else {
189
- console.error(
190
- `Could not parse markdown: unsupported token type: ${token.type}. Found: ${token.raw}`
191
- );
192
- }
193
- cursor++;
194
- }
195
- return { children, cursor };
196
- }
197
-
198
- export function parseRichTextSource<O extends RichTextOptions>({
199
- templateStrings,
200
- exprs: nodes,
201
- }: RichTextSource<O>): RichText<O> {
202
- // TODO: validate that templateStrings does not contain VAL_NODE_PREFIX
203
- const inputText = templateStrings
204
- .flatMap((templateString, i) => {
205
- const node = nodes[i];
206
- if (node) {
207
- if (node[VAL_EXTENSION] === "link") {
208
- return templateString.concat(
209
- `${VAL_START_TAG_PREFIX}${i}${VAL_START_TAG_SUFFIX}${node.children[0]}${VAL_END_TAG}`
210
- );
211
- } else {
212
- return templateString.concat(
213
- `${VAL_START_TAG_PREFIX}${i}${VAL_START_TAG_SUFFIX}${VAL_END_TAG}`
214
- );
215
- }
216
- }
217
- return templateString;
218
- })
219
- .join("");
220
- const tokenList = marked.lexer(inputText, {
221
- gfm: true,
222
- });
223
- const { children, cursor } = parseTokens(tokenList, nodes, 0);
224
- if (cursor !== tokenList.length) {
225
- throw Error(
226
- "Unexpectedly terminated markdown parsing. Possible reason: unclosed html tag?"
227
- );
228
- }
229
- return {
230
- [VAL_EXTENSION]: "richtext",
231
- children,
232
- } as RichText<O>;
233
- }