@valbuild/core 0.20.2 → 0.21.1
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/dist/declarations/src/index.d.ts +3 -3
- package/dist/declarations/src/initVal.d.ts +2 -0
- package/dist/declarations/src/source/link.d.ts +9 -0
- package/dist/declarations/src/source/richtext.d.ts +44 -30
- package/dist/{index-601a7d73.cjs.prod.js → index-067cff4a.cjs.prod.js} +1 -1
- package/dist/{index-a6e642dd.cjs.dev.js → index-31991dd7.cjs.dev.js} +3 -0
- package/dist/{index-bccf1907.esm.js → index-4bb14a92.esm.js} +4 -1
- package/dist/{index-8706c87e.cjs.prod.js → index-75b79c89.cjs.prod.js} +3 -0
- package/dist/{index-5d1ab97c.esm.js → index-870205b5.esm.js} +1 -1
- package/dist/{index-486c7fbf.cjs.dev.js → index-d17f9503.cjs.dev.js} +1 -1
- package/dist/{ops-b0a33248.cjs.dev.js → ops-0f7617a0.cjs.dev.js} +1 -1
- package/dist/{ops-def81fc3.cjs.prod.js → ops-451ffb3f.cjs.prod.js} +1 -1
- package/dist/{ops-22b624eb.esm.js → ops-9b396073.esm.js} +1 -1
- package/dist/valbuild-core.cjs.dev.js +39 -159
- package/dist/valbuild-core.cjs.prod.js +39 -159
- package/dist/valbuild-core.esm.js +40 -140
- package/expr/dist/valbuild-core-expr.cjs.dev.js +2 -2
- package/expr/dist/valbuild-core-expr.cjs.prod.js +2 -2
- package/expr/dist/valbuild-core-expr.esm.js +2 -2
- package/package.json +2 -4
- package/patch/dist/valbuild-core-patch.cjs.dev.js +2 -2
- package/patch/dist/valbuild-core-patch.cjs.prod.js +2 -2
- package/patch/dist/valbuild-core-patch.esm.js +3 -3
- package/src/index.ts +4 -4
- package/src/initVal.ts +3 -0
- package/src/schema/image.ts +5 -0
- package/src/source/link.ts +14 -0
- package/src/source/richtext.ts +91 -234
- package/src/source/richtext.test.ts +0 -178
package/src/source/richtext.ts
CHANGED
@@ -1,84 +1,95 @@
|
|
1
|
-
import * as marked from "marked";
|
2
1
|
import { FileSource } from "./file";
|
3
2
|
import { VAL_EXTENSION } from ".";
|
4
|
-
import {
|
3
|
+
import { LinkSource } from "./link";
|
4
|
+
import { ImageMetadata } from "../schema/image";
|
5
5
|
|
6
6
|
export type RichTextOptions = {
|
7
7
|
headings?: ("h1" | "h2" | "h3" | "h4" | "h5" | "h6")[];
|
8
8
|
img?: boolean;
|
9
|
-
|
10
|
-
|
9
|
+
a?: boolean;
|
10
|
+
ul?: boolean;
|
11
|
+
ol?: boolean;
|
11
12
|
lineThrough?: boolean;
|
12
13
|
bold?: boolean;
|
13
14
|
italic?: boolean;
|
14
|
-
// link?: boolean;
|
15
|
-
// fontFamily?: Record<string, string[]>;
|
16
|
-
// fontSize?: Record<string, string[]>;
|
17
|
-
// blockQuote?: boolean; // TODO: naming
|
18
15
|
};
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
16
|
+
export type AnyRichTextOptions = {
|
17
|
+
headings: ("h1" | "h2" | "h3" | "h4" | "h5" | "h6")[];
|
18
|
+
img: true;
|
19
|
+
a: true;
|
20
|
+
ul: true;
|
21
|
+
ol: true;
|
22
|
+
lineThrough: true;
|
23
|
+
bold: true;
|
24
|
+
italic: true;
|
24
25
|
};
|
25
26
|
|
27
|
+
// Classes
|
26
28
|
export type LineThrough<O extends RichTextOptions> =
|
27
29
|
O["lineThrough"] extends true ? "line-through" : never;
|
30
|
+
|
28
31
|
export type Italic<O extends RichTextOptions> = O["italic"] extends true
|
29
32
|
? "italic"
|
30
33
|
: never;
|
34
|
+
|
31
35
|
export type Bold<O extends RichTextOptions> = O["bold"] extends true
|
32
36
|
? "bold"
|
33
37
|
: never;
|
34
|
-
// export type FontFamily<O extends RichTextOptions> =
|
35
|
-
// O["fontFamily"] extends Record<string, unknown>
|
36
|
-
// ? `font-${keyof O["fontFamily"] & string}`
|
37
|
-
// : never;
|
38
|
-
// export type FontSize<O extends RichTextOptions> = O["fontSize"] extends Record<
|
39
|
-
// string,
|
40
|
-
// unknown
|
41
|
-
// >
|
42
|
-
// ? `text-${keyof O["fontSize"] & string}`
|
43
|
-
// : never;
|
44
38
|
|
45
39
|
export type Classes<O extends RichTextOptions> =
|
46
40
|
| LineThrough<O>
|
47
41
|
| Italic<O>
|
48
42
|
| Bold<O>;
|
49
|
-
// | FontFamily<O>
|
50
|
-
// | FontSize<O>;
|
51
43
|
|
44
|
+
/// Paragraph
|
45
|
+
export type ParagraphNode<O extends RichTextOptions> = {
|
46
|
+
tag: "p";
|
47
|
+
children: (string | SpanNode<O> | BrNode | LinkNode<O> | ImageNode<O>)[];
|
48
|
+
};
|
49
|
+
|
50
|
+
/// Break
|
51
|
+
export type BrNode = {
|
52
|
+
tag: "br";
|
53
|
+
children: [];
|
54
|
+
};
|
55
|
+
|
56
|
+
/// Span
|
52
57
|
export type SpanNode<O extends RichTextOptions> = {
|
53
58
|
tag: "span";
|
54
59
|
classes: Classes<O>[];
|
55
60
|
children: [string | SpanNode<O>];
|
56
61
|
};
|
57
62
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
/// Image
|
64
|
+
type ImageTagNode = {
|
65
|
+
tag: "img";
|
66
|
+
src: string;
|
67
|
+
height?: number;
|
68
|
+
width?: number;
|
69
|
+
children: [];
|
70
|
+
};
|
67
71
|
export type ImageNode<O extends RichTextOptions> = O["img"] extends true
|
68
|
-
?
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
? ImageTagNode
|
73
|
+
: never;
|
74
|
+
|
75
|
+
/// Link
|
76
|
+
type LinkTagNode<O extends RichTextOptions> = {
|
77
|
+
tag: "a";
|
78
|
+
href: string;
|
79
|
+
children: (string | SpanNode<O>)[];
|
80
|
+
};
|
81
|
+
export type LinkNode<O extends RichTextOptions> = O["a"] extends true
|
82
|
+
? LinkTagNode<O>
|
74
83
|
: never;
|
75
84
|
|
85
|
+
/// List
|
76
86
|
export type ListItemNode<O extends RichTextOptions> = {
|
77
87
|
tag: "li";
|
78
88
|
children: (
|
79
89
|
| string
|
80
90
|
| SpanNode<O>
|
81
|
-
|
91
|
+
| LinkNode<O>
|
92
|
+
| BrNode
|
82
93
|
| UnorderedListNode<O>
|
83
94
|
| OrderedListNode<O>
|
84
95
|
)[];
|
@@ -100,222 +111,68 @@ export type OrderedListNode<O extends RichTextOptions> = O["ol"] extends true
|
|
100
111
|
}
|
101
112
|
: never;
|
102
113
|
|
103
|
-
|
104
|
-
export type HeadingNode<O extends RichTextOptions> = O["headings"] extends
|
114
|
+
/// Heading
|
115
|
+
export type HeadingNode<O extends RichTextOptions> = O["headings"] extends (
|
116
|
+
| "h1"
|
117
|
+
| "h2"
|
118
|
+
| "h3"
|
119
|
+
| "h4"
|
120
|
+
| "h5"
|
121
|
+
| "h6"
|
122
|
+
)[]
|
105
123
|
? {
|
106
124
|
tag: O["headings"][number];
|
107
125
|
children: (string | SpanNode<O>)[];
|
108
|
-
// | AnchorNode<O>
|
109
126
|
}
|
110
127
|
: never;
|
111
128
|
|
112
|
-
|
113
|
-
// O["blockQuote"] extends true
|
114
|
-
// ? { tag: "blockquote"; children: [string] }
|
115
|
-
// : never;
|
116
|
-
|
117
|
-
type ImageSource = FileSource<{
|
118
|
-
width: number;
|
119
|
-
height: number;
|
120
|
-
sha256: string;
|
121
|
-
}>;
|
122
|
-
|
123
|
-
export type SourceNode<O extends RichTextOptions> = O["img"] extends true
|
124
|
-
? ImageSource
|
125
|
-
: never;
|
126
|
-
|
127
|
-
export type AnyRichTextOptions = {
|
128
|
-
headings: ("h1" | "h2" | "h3" | "h4" | "h5" | "h6")[];
|
129
|
-
img: true;
|
130
|
-
ul: true;
|
131
|
-
ol: true;
|
132
|
-
lineThrough: true;
|
133
|
-
bold: true;
|
134
|
-
italic: true;
|
135
|
-
// blockQuote: true;
|
136
|
-
// fontFamily: Record<string, string[]>;
|
137
|
-
// fontSize: Record<string, string[]>;
|
138
|
-
};
|
139
|
-
|
140
|
-
export type RichTextSourceNode<O extends RichTextOptions> =
|
141
|
-
| Exclude<RichTextNode<O>, { tag: "img" }>
|
142
|
-
| SourceNode<O>;
|
143
|
-
|
144
|
-
export type RichTextSource<O extends RichTextOptions> = {
|
145
|
-
[VAL_EXTENSION]: "richtext";
|
146
|
-
children: (
|
147
|
-
| HeadingNode<O>
|
148
|
-
| ParagraphNode<O>
|
149
|
-
| UnorderedListNode<O>
|
150
|
-
| OrderedListNode<O>
|
151
|
-
// | BlockQuoteNode<O>
|
152
|
-
| SourceNode<O>
|
153
|
-
)[];
|
154
|
-
};
|
155
|
-
|
129
|
+
/// Root and nodes
|
156
130
|
export type RichTextNode<O extends RichTextOptions> =
|
157
131
|
| string
|
158
|
-
|
|
159
|
-
| ParagraphNode<O>
|
160
|
-
| UnorderedListNode<O>
|
161
|
-
| OrderedListNode<O>
|
132
|
+
| RootNode<O>
|
162
133
|
| ListItemNode<O>
|
134
|
+
| BrNode
|
163
135
|
| SpanNode<O>
|
164
|
-
|
136
|
+
| LinkNode<O>
|
165
137
|
| ImageNode<O>;
|
166
138
|
|
167
139
|
export type RootNode<O extends RichTextOptions> =
|
168
140
|
| HeadingNode<O>
|
169
141
|
| ParagraphNode<O>
|
142
|
+
| BrNode
|
170
143
|
| UnorderedListNode<O>
|
171
|
-
| OrderedListNode<O
|
172
|
-
// | BlockQuoteNode<O>
|
173
|
-
| ImageNode<O>;
|
144
|
+
| OrderedListNode<O>;
|
174
145
|
|
175
|
-
|
146
|
+
/// Main types
|
147
|
+
|
148
|
+
/**
|
149
|
+
* RichTextSource is defined in ValModules
|
150
|
+
**/
|
151
|
+
export type RichTextSource<O extends RichTextOptions> = {
|
152
|
+
[VAL_EXTENSION]: "richtext";
|
153
|
+
templateStrings: string[];
|
154
|
+
exprs: (
|
155
|
+
| (O["img"] extends true ? FileSource<ImageMetadata> : never)
|
156
|
+
| (O["a"] extends true ? LinkSource : never)
|
157
|
+
)[];
|
158
|
+
};
|
159
|
+
/**
|
160
|
+
* RichText is accessible by users (after conversion via useVal / fetchVal)
|
161
|
+
* Internally it is a Selector
|
162
|
+
**/
|
176
163
|
export type RichText<O extends RichTextOptions> = {
|
177
164
|
[VAL_EXTENSION]: "richtext";
|
178
165
|
children: RootNode<O>[];
|
179
166
|
};
|
180
167
|
|
181
|
-
function
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
if (token.type === "heading") {
|
186
|
-
return [
|
187
|
-
{
|
188
|
-
tag: `h${token.depth}`,
|
189
|
-
children: parseTokens(token.tokens ? token.tokens : []),
|
190
|
-
},
|
191
|
-
];
|
192
|
-
}
|
193
|
-
if (token.type === "paragraph") {
|
194
|
-
return [
|
195
|
-
{
|
196
|
-
tag: "p",
|
197
|
-
children: parseTokens(token.tokens ? token.tokens : []),
|
198
|
-
},
|
199
|
-
];
|
200
|
-
}
|
201
|
-
if (token.type === "strong") {
|
202
|
-
return [
|
203
|
-
{
|
204
|
-
tag: "span",
|
205
|
-
classes: ["bold"],
|
206
|
-
children: parseTokens(token.tokens ? token.tokens : []),
|
207
|
-
},
|
208
|
-
];
|
209
|
-
}
|
210
|
-
if (token.type === "em") {
|
211
|
-
return [
|
212
|
-
{
|
213
|
-
tag: "span",
|
214
|
-
classes: ["italic"],
|
215
|
-
children: parseTokens(token.tokens ? token.tokens : []),
|
216
|
-
},
|
217
|
-
];
|
218
|
-
}
|
219
|
-
if (token.type === "del") {
|
220
|
-
return [
|
221
|
-
{
|
222
|
-
tag: "span",
|
223
|
-
classes: ["line-through"],
|
224
|
-
children: parseTokens(token.tokens ? token.tokens : []),
|
225
|
-
},
|
226
|
-
];
|
227
|
-
}
|
228
|
-
if (token.type === "text") {
|
229
|
-
if ("tokens" in token && Array.isArray(token.tokens)) {
|
230
|
-
return parseTokens(token.tokens);
|
231
|
-
}
|
232
|
-
return [token.text];
|
233
|
-
}
|
234
|
-
if (token.type === "list") {
|
235
|
-
return [
|
236
|
-
{
|
237
|
-
tag: token.ordered ? "ol" : "ul",
|
238
|
-
children: parseTokens(token.items),
|
239
|
-
},
|
240
|
-
];
|
241
|
-
}
|
242
|
-
if (token.type === "list_item") {
|
243
|
-
return [
|
244
|
-
{
|
245
|
-
tag: "li",
|
246
|
-
children: parseTokens(token.tokens ? token.tokens : []),
|
247
|
-
},
|
248
|
-
];
|
249
|
-
}
|
250
|
-
if (token.type === "space") {
|
251
|
-
return [];
|
252
|
-
}
|
253
|
-
|
254
|
-
if (token.type === "code") {
|
255
|
-
return [
|
256
|
-
{
|
257
|
-
tag: "span",
|
258
|
-
classes: [],
|
259
|
-
children: [token.text],
|
260
|
-
},
|
261
|
-
];
|
262
|
-
}
|
263
|
-
// console.error(
|
264
|
-
// `Could not parse markdown: unsupported token type: ${token.type}. Found: ${token.raw}`
|
265
|
-
// );
|
266
|
-
return [token.raw];
|
267
|
-
});
|
268
|
-
}
|
269
|
-
|
270
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
271
|
-
function nodeToTag(node: any): any {
|
272
|
-
if (node[VAL_EXTENSION] === "file") {
|
273
|
-
return node;
|
274
|
-
}
|
275
|
-
throw Error(`Unexpected node: ${JSON.stringify(node)}`);
|
276
|
-
}
|
277
|
-
|
278
|
-
function imgSrcToImgTag<O extends RichTextOptions>(
|
279
|
-
imageSrc: ImageSource
|
280
|
-
): ImageNode<O> {
|
281
|
-
const converted = convertFileSource(imageSrc);
|
282
|
-
return {
|
283
|
-
tag: "img",
|
284
|
-
src: converted.url,
|
285
|
-
width: imageSrc.metadata?.width,
|
286
|
-
height: imageSrc.metadata?.height,
|
287
|
-
} as ImageNode<O>;
|
288
|
-
}
|
289
|
-
|
290
|
-
export function convertRichTextSource<O extends RichTextOptions>(
|
291
|
-
src: RichTextSource<O>
|
292
|
-
): RichText<O> {
|
293
|
-
return {
|
294
|
-
[VAL_EXTENSION]: "richtext",
|
295
|
-
children: src.children.map((source) => {
|
296
|
-
if (VAL_EXTENSION in source && source[VAL_EXTENSION] === "file") {
|
297
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
298
|
-
return imgSrcToImgTag(source as any);
|
299
|
-
}
|
300
|
-
return source;
|
301
|
-
}),
|
302
|
-
} as RichText<O>;
|
303
|
-
}
|
304
|
-
|
305
|
-
export function richtext<
|
306
|
-
O extends RichTextOptions,
|
307
|
-
Nodes extends never | ImageSource
|
308
|
-
>(templateStrings: TemplateStringsArray, ...expr: Nodes[]): RichTextSource<O> {
|
168
|
+
export function richtext<O extends RichTextOptions>(
|
169
|
+
templateStrings: TemplateStringsArray,
|
170
|
+
...nodes: (FileSource<ImageMetadata> | LinkSource)[]
|
171
|
+
): RichTextSource<O> {
|
309
172
|
return {
|
310
173
|
[VAL_EXTENSION]: "richtext",
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
});
|
315
|
-
if (expr[i]) {
|
316
|
-
return parseTokens(lex).concat(nodeToTag(expr[i]));
|
317
|
-
}
|
318
|
-
return parseTokens(lex);
|
319
|
-
}),
|
174
|
+
templateStrings: templateStrings as unknown as string[],
|
175
|
+
exprs:
|
176
|
+
nodes as RichTextSource<AnyRichTextOptions>["exprs"] as RichTextSource<O>["exprs"],
|
320
177
|
};
|
321
178
|
}
|
@@ -1,178 +0,0 @@
|
|
1
|
-
import { file } from "../source/file";
|
2
|
-
import { richtext } from "./richtext";
|
3
|
-
|
4
|
-
//MD to HTML
|
5
|
-
describe("richtext", () => {
|
6
|
-
test("basic h1", () => {
|
7
|
-
const r = richtext`# Title 1`;
|
8
|
-
expect(r.children).toStrictEqual([{ tag: "h1", children: ["Title 1"] }]);
|
9
|
-
});
|
10
|
-
|
11
|
-
test("basic complete", () => {
|
12
|
-
const r = richtext`# Title 1
|
13
|
-
## Title 2
|
14
|
-
|
15
|
-
Paragraph 1 2 3 4 5. Words *italic* **bold**
|
16
|
-
`;
|
17
|
-
expect(r.children).toStrictEqual([
|
18
|
-
{ tag: "h1", children: ["Title 1"] },
|
19
|
-
{ tag: "h2", children: ["Title 2"] },
|
20
|
-
{
|
21
|
-
tag: "p",
|
22
|
-
children: [
|
23
|
-
"Paragraph 1 2 3 4 5. Words ",
|
24
|
-
{ tag: "span", classes: ["italic"], children: ["italic"] },
|
25
|
-
" ",
|
26
|
-
{ tag: "span", classes: ["bold"], children: ["bold"] },
|
27
|
-
],
|
28
|
-
},
|
29
|
-
]);
|
30
|
-
});
|
31
|
-
|
32
|
-
test.skip("strong and emphasis merged spans", () => {
|
33
|
-
// TODO: currently we do not merge
|
34
|
-
const r = richtext`Which classes?
|
35
|
-
***All of them!***
|
36
|
-
`;
|
37
|
-
expect(r.children).toStrictEqual([
|
38
|
-
{
|
39
|
-
tag: "p",
|
40
|
-
children: [
|
41
|
-
"Which classes?\n",
|
42
|
-
{
|
43
|
-
tag: "span",
|
44
|
-
classes: ["italic", "bold"],
|
45
|
-
children: ["All of them!"],
|
46
|
-
},
|
47
|
-
],
|
48
|
-
},
|
49
|
-
]);
|
50
|
-
});
|
51
|
-
|
52
|
-
test("line through", () => {
|
53
|
-
// TODO: currently we do not merge
|
54
|
-
const r = richtext`~~line through~~`;
|
55
|
-
expect(r.children).toStrictEqual([
|
56
|
-
{
|
57
|
-
tag: "p",
|
58
|
-
children: [
|
59
|
-
{
|
60
|
-
tag: "span",
|
61
|
-
classes: ["line-through"],
|
62
|
-
children: ["line through"],
|
63
|
-
},
|
64
|
-
],
|
65
|
-
},
|
66
|
-
]);
|
67
|
-
});
|
68
|
-
|
69
|
-
test("2 paragraphs", () => {
|
70
|
-
const r = richtext`# Title 1
|
71
|
-
|
72
|
-
First paragraph
|
73
|
-
|
74
|
-
Second paragraph
|
75
|
-
`;
|
76
|
-
expect(r.children).toStrictEqual([
|
77
|
-
{ tag: "h1", children: ["Title 1"] },
|
78
|
-
{ tag: "p", children: ["First paragraph"] },
|
79
|
-
{ tag: "p", children: ["Second paragraph"] },
|
80
|
-
]);
|
81
|
-
});
|
82
|
-
|
83
|
-
test("lists", () => {
|
84
|
-
const r = richtext`# Title 1
|
85
|
-
|
86
|
-
A paragraph
|
87
|
-
|
88
|
-
A bullet list:
|
89
|
-
- bullet 1
|
90
|
-
- bullet 2
|
91
|
-
|
92
|
-
A numbered list:
|
93
|
-
1. number 1
|
94
|
-
2. number 2
|
95
|
-
|
96
|
-
A nested list:
|
97
|
-
- bullet 1:
|
98
|
-
1. number 1.1
|
99
|
-
2. number 1.2
|
100
|
-
- bullet 2:
|
101
|
-
- bullet 2.1
|
102
|
-
- bullet 2.2
|
103
|
-
`;
|
104
|
-
expect(r.children).toStrictEqual([
|
105
|
-
{ tag: "h1", children: ["Title 1"] },
|
106
|
-
{ tag: "p", children: ["A paragraph"] },
|
107
|
-
{ tag: "p", children: ["A bullet list:"] },
|
108
|
-
{
|
109
|
-
tag: "ul",
|
110
|
-
children: [
|
111
|
-
{ tag: "li", children: ["bullet 1"] },
|
112
|
-
{ tag: "li", children: ["bullet 2"] },
|
113
|
-
],
|
114
|
-
},
|
115
|
-
{ tag: "p", children: ["A numbered list:"] },
|
116
|
-
{
|
117
|
-
tag: "ol",
|
118
|
-
children: [
|
119
|
-
{ tag: "li", children: ["number 1"] },
|
120
|
-
{ tag: "li", children: ["number 2"] },
|
121
|
-
],
|
122
|
-
},
|
123
|
-
{ tag: "p", children: ["A nested list:"] },
|
124
|
-
{
|
125
|
-
tag: "ul",
|
126
|
-
children: [
|
127
|
-
{
|
128
|
-
tag: "li",
|
129
|
-
children: [
|
130
|
-
"bullet 1:",
|
131
|
-
{
|
132
|
-
tag: "ol",
|
133
|
-
children: [
|
134
|
-
{ tag: "li", children: ["number 1.1"] },
|
135
|
-
{ tag: "li", children: ["number 1.2"] },
|
136
|
-
],
|
137
|
-
},
|
138
|
-
],
|
139
|
-
},
|
140
|
-
{
|
141
|
-
tag: "li",
|
142
|
-
children: [
|
143
|
-
"bullet 2:",
|
144
|
-
{
|
145
|
-
tag: "ul",
|
146
|
-
children: [
|
147
|
-
{ tag: "li", children: ["bullet 2.1"] },
|
148
|
-
{ tag: "li", children: ["bullet 2.2"] },
|
149
|
-
],
|
150
|
-
},
|
151
|
-
],
|
152
|
-
},
|
153
|
-
],
|
154
|
-
},
|
155
|
-
]);
|
156
|
-
});
|
157
|
-
|
158
|
-
test("image", () => {
|
159
|
-
const r = richtext`# Title 1
|
160
|
-
|
161
|
-
Below we have an image block:
|
162
|
-
|
163
|
-
${file("/public/foo.png", {
|
164
|
-
width: 100,
|
165
|
-
height: 100,
|
166
|
-
sha256: "123",
|
167
|
-
})}`;
|
168
|
-
expect(r.children).toStrictEqual([
|
169
|
-
{ tag: "h1", children: ["Title 1"] },
|
170
|
-
{ tag: "p", children: ["Below we have an image block:"] },
|
171
|
-
{
|
172
|
-
_ref: "/public/foo.png",
|
173
|
-
_type: "file",
|
174
|
-
metadata: { width: 100, height: 100, sha256: "123" },
|
175
|
-
},
|
176
|
-
]);
|
177
|
-
});
|
178
|
-
});
|