@portabletext/markdown 1.0.3 → 1.0.4
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/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -6
- package/src/default-schema.ts +0 -166
- package/src/example-document.md +0 -237
- package/src/example-document.out.md +0 -235
- package/src/example-document.terse-pt.json +0 -124
- package/src/example-document.test.ts +0 -87
- package/src/from-portable-text/build-list-index-map.ts +0 -133
- package/src/from-portable-text/portable-text-to-markdown.ts +0 -135
- package/src/from-portable-text/render-node.ts +0 -176
- package/src/from-portable-text/renderers/block-spacing.ts +0 -39
- package/src/from-portable-text/renderers/hard-break.ts +0 -4
- package/src/from-portable-text/renderers/list-item.ts +0 -32
- package/src/from-portable-text/renderers/marks.ts +0 -113
- package/src/from-portable-text/renderers/style.ts +0 -79
- package/src/from-portable-text/renderers/type.ts +0 -126
- package/src/from-portable-text/types.ts +0 -240
- package/src/index.ts +0 -51
- package/src/key-generator.ts +0 -32
- package/src/markdown-to-portable-text.test.ts +0 -3273
- package/src/portable-text-to-markdown.test.ts +0 -803
- package/src/to-portable-text/markdown-to-portable-text.ts +0 -1204
- package/src/to-portable-text/matchers.ts +0 -192
|
@@ -1,803 +0,0 @@
|
|
|
1
|
-
import {compileSchema, defineSchema} from '@portabletext/schema'
|
|
2
|
-
import {createTestKeyGenerator} from '@portabletext/test'
|
|
3
|
-
import {
|
|
4
|
-
isPortableTextBlock,
|
|
5
|
-
isPortableTextListItemBlock,
|
|
6
|
-
} from '@portabletext/toolkit'
|
|
7
|
-
import {describe, expect, test} from 'vitest'
|
|
8
|
-
import {portableTextToMarkdown} from './from-portable-text/portable-text-to-markdown'
|
|
9
|
-
import {DefaultListItemRenderer} from './from-portable-text/renderers/list-item'
|
|
10
|
-
import {
|
|
11
|
-
DefaultCodeBlockRenderer,
|
|
12
|
-
DefaultTableRenderer,
|
|
13
|
-
} from './from-portable-text/renderers/type'
|
|
14
|
-
import {markdownToPortableText} from './to-portable-text/markdown-to-portable-text'
|
|
15
|
-
import {buildObjectMatcher} from './to-portable-text/matchers'
|
|
16
|
-
|
|
17
|
-
describe(portableTextToMarkdown.name, () => {
|
|
18
|
-
test('empty array', () => {
|
|
19
|
-
const markdown = ''
|
|
20
|
-
const portableText = markdownToPortableText(markdown)
|
|
21
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
describe('paragraph', () => {
|
|
25
|
-
test('one paragraph', () => {
|
|
26
|
-
const markdown = 'foo'
|
|
27
|
-
const portableText = markdownToPortableText(markdown)
|
|
28
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
test('one paragraph with hard breaks', () => {
|
|
32
|
-
const markdown = 'foo \nbar \nbaz'
|
|
33
|
-
const portableText = markdownToPortableText(markdown)
|
|
34
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
test('multiple lines', () => {
|
|
38
|
-
const markdown = ['foo', '', 'bar', '', 'baz'].join('')
|
|
39
|
-
const portableText = markdownToPortableText(markdown)
|
|
40
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
41
|
-
})
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
describe('block spacing', () => {
|
|
45
|
-
const markdown = ['foo', '', 'bar', '', 'baz', '', '- fizz', '- buzz'].join(
|
|
46
|
-
'\n',
|
|
47
|
-
)
|
|
48
|
-
const portableText = markdownToPortableText(markdown)
|
|
49
|
-
|
|
50
|
-
test('default', () => {
|
|
51
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
test('custom list item spacing', () => {
|
|
55
|
-
expect(
|
|
56
|
-
portableTextToMarkdown(portableText, {
|
|
57
|
-
blockSpacing: ({current, next}) => {
|
|
58
|
-
if (
|
|
59
|
-
isPortableTextListItemBlock(current) &&
|
|
60
|
-
isPortableTextListItemBlock(next)
|
|
61
|
-
) {
|
|
62
|
-
return '\n\n'
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return undefined
|
|
66
|
-
},
|
|
67
|
-
}),
|
|
68
|
-
).toBe(
|
|
69
|
-
['foo', '', 'bar', '', 'baz', '', '- fizz', '', '- buzz'].join('\n'),
|
|
70
|
-
)
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
test('custom blockquote spacing', () => {
|
|
74
|
-
const markdown = ['foo', '', '> bar', '>', '> baz', '', 'fizz'].join('\n')
|
|
75
|
-
const portableText = markdownToPortableText(markdown)
|
|
76
|
-
expect(
|
|
77
|
-
portableTextToMarkdown(portableText, {
|
|
78
|
-
blockSpacing: ({current, next}) => {
|
|
79
|
-
if (
|
|
80
|
-
isPortableTextBlock(current) &&
|
|
81
|
-
isPortableTextBlock(next) &&
|
|
82
|
-
current.style === 'blockquote' &&
|
|
83
|
-
next.style === 'blockquote'
|
|
84
|
-
) {
|
|
85
|
-
return '\n\n'
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return undefined
|
|
89
|
-
},
|
|
90
|
-
}),
|
|
91
|
-
).toBe(['foo', '', '> bar', '', '> baz', '', 'fizz'].join('\n'))
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
describe('decorators', () => {
|
|
96
|
-
describe('strong', () => {
|
|
97
|
-
const markdown = 'foo **bar** baz'
|
|
98
|
-
const portableText = markdownToPortableText(markdown)
|
|
99
|
-
|
|
100
|
-
test('default renderer', () => {
|
|
101
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
test('custom renderer', () => {
|
|
105
|
-
expect(
|
|
106
|
-
portableTextToMarkdown(portableText, {
|
|
107
|
-
marks: {
|
|
108
|
-
strong: ({children}) => `*${children}*`,
|
|
109
|
-
},
|
|
110
|
-
}),
|
|
111
|
-
).toBe('foo *bar* baz')
|
|
112
|
-
})
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
describe('emphasis', () => {
|
|
116
|
-
const markdown = 'foo _bar_ baz'
|
|
117
|
-
const portableText = markdownToPortableText(markdown)
|
|
118
|
-
|
|
119
|
-
test('default renderer', () => {
|
|
120
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
121
|
-
})
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
describe('strike-through', () => {
|
|
125
|
-
const markdown = 'foo ~~bar~~ baz'
|
|
126
|
-
const portableText = markdownToPortableText(markdown)
|
|
127
|
-
|
|
128
|
-
test('default renderer', () => {
|
|
129
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
130
|
-
})
|
|
131
|
-
})
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
describe('link', () => {
|
|
135
|
-
const markdown = 'foo [bar](https://example.com) baz'
|
|
136
|
-
const portableText = markdownToPortableText(markdown)
|
|
137
|
-
|
|
138
|
-
test('default renderer', () => {
|
|
139
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
test('custom renderer', () => {
|
|
143
|
-
expect(
|
|
144
|
-
portableTextToMarkdown(portableText, {
|
|
145
|
-
marks: {
|
|
146
|
-
link: ({children, value}) =>
|
|
147
|
-
`<a href="${value.href}">${children}</a>`,
|
|
148
|
-
},
|
|
149
|
-
}),
|
|
150
|
-
).toBe('foo <a href="https://example.com">bar</a> baz')
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
test('with title', () => {
|
|
154
|
-
const markdown = 'foo [bar](https://example.com "Link Title") baz'
|
|
155
|
-
const portableText = markdownToPortableText(markdown)
|
|
156
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
157
|
-
})
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
describe('hard breaks', () => {
|
|
161
|
-
test('default', () => {
|
|
162
|
-
const markdown = 'foo \nbar \nbaz'
|
|
163
|
-
const portableText = markdownToPortableText(markdown)
|
|
164
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
test('trailing newline', () => {
|
|
168
|
-
const markdownIn = 'foo\n'
|
|
169
|
-
const markdownOut = 'foo'
|
|
170
|
-
const portableText = markdownToPortableText(markdownIn)
|
|
171
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdownOut)
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
test('custom renderer', () => {
|
|
175
|
-
const markdownIn = 'foo \nbar \nbaz'
|
|
176
|
-
const markdownOut = 'foo<br />bar<br />baz'
|
|
177
|
-
const portableText = markdownToPortableText(markdownIn)
|
|
178
|
-
expect(
|
|
179
|
-
portableTextToMarkdown(portableText, {
|
|
180
|
-
hardBreak: () => '<br />',
|
|
181
|
-
}),
|
|
182
|
-
).toBe(markdownOut)
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
test('from explicit PT with newline in span', () => {
|
|
186
|
-
const portableText = [
|
|
187
|
-
{
|
|
188
|
-
_type: 'block',
|
|
189
|
-
_key: 'k0',
|
|
190
|
-
style: 'normal',
|
|
191
|
-
children: [{_type: 'span', _key: 'k1', text: 'foo\nbar', marks: []}],
|
|
192
|
-
markDefs: [],
|
|
193
|
-
},
|
|
194
|
-
]
|
|
195
|
-
expect(portableTextToMarkdown(portableText)).toBe('foo \nbar')
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
test('multiple hard breaks from explicit PT', () => {
|
|
199
|
-
const portableText = [
|
|
200
|
-
{
|
|
201
|
-
_type: 'block',
|
|
202
|
-
_key: 'k0',
|
|
203
|
-
style: 'normal',
|
|
204
|
-
children: [
|
|
205
|
-
{_type: 'span', _key: 'k1', text: 'foo\nbar\nbaz', marks: []},
|
|
206
|
-
],
|
|
207
|
-
markDefs: [],
|
|
208
|
-
},
|
|
209
|
-
]
|
|
210
|
-
expect(portableTextToMarkdown(portableText)).toBe('foo \nbar \nbaz')
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
test('hard break in list item from explicit PT', () => {
|
|
214
|
-
const portableText = [
|
|
215
|
-
{
|
|
216
|
-
_type: 'block',
|
|
217
|
-
_key: 'k0',
|
|
218
|
-
style: 'normal',
|
|
219
|
-
listItem: 'bullet',
|
|
220
|
-
level: 1,
|
|
221
|
-
children: [{_type: 'span', _key: 'k1', text: 'foo\nbar', marks: []}],
|
|
222
|
-
markDefs: [],
|
|
223
|
-
},
|
|
224
|
-
]
|
|
225
|
-
expect(portableTextToMarkdown(portableText)).toBe('- foo \nbar')
|
|
226
|
-
})
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
describe('paragraphs', () => {
|
|
230
|
-
const markdown = 'foo\n\nbar\n\nbaz'
|
|
231
|
-
|
|
232
|
-
test('default definition', () => {
|
|
233
|
-
const portableText = markdownToPortableText(markdown)
|
|
234
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
test('custom definition', () => {
|
|
238
|
-
const schema = compileSchema(
|
|
239
|
-
defineSchema({styles: [{name: 'paragraph'}]}),
|
|
240
|
-
)
|
|
241
|
-
const portableText = markdownToPortableText(markdown, {
|
|
242
|
-
schema,
|
|
243
|
-
block: {
|
|
244
|
-
normal: () => 'paragraph',
|
|
245
|
-
},
|
|
246
|
-
})
|
|
247
|
-
expect(
|
|
248
|
-
portableTextToMarkdown(portableText, {
|
|
249
|
-
block: {
|
|
250
|
-
paragraph: ({children}) => `${children}`,
|
|
251
|
-
},
|
|
252
|
-
}),
|
|
253
|
-
).toBe(markdown)
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
test('no definition', () => {
|
|
257
|
-
const schema = compileSchema(defineSchema({}))
|
|
258
|
-
const portableText = markdownToPortableText(markdown, {schema})
|
|
259
|
-
expect(portableTextToMarkdown(portableText)).toBe('foo\n\nbar\n\nbaz')
|
|
260
|
-
})
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
describe('style', () => {
|
|
264
|
-
describe('blockquote', () => {
|
|
265
|
-
describe('single', () => {
|
|
266
|
-
const markdown = '> foo'
|
|
267
|
-
|
|
268
|
-
test('default renderer', () => {
|
|
269
|
-
const portableText = markdownToPortableText(markdown)
|
|
270
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
test('custom renderer', () => {
|
|
274
|
-
const portableText = markdownToPortableText(markdown)
|
|
275
|
-
expect(
|
|
276
|
-
portableTextToMarkdown(portableText, {
|
|
277
|
-
block: {blockquote: ({children}) => `q:${children}`},
|
|
278
|
-
}),
|
|
279
|
-
).toBe('q:foo')
|
|
280
|
-
})
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
describe('single with hard break', () => {
|
|
284
|
-
const markdown = '> foo \n> bar'
|
|
285
|
-
|
|
286
|
-
test('default renderer', () => {
|
|
287
|
-
const portableText = markdownToPortableText(markdown)
|
|
288
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
test('custom renderer', () => {
|
|
292
|
-
const portableText = markdownToPortableText(markdown)
|
|
293
|
-
expect(
|
|
294
|
-
portableTextToMarkdown(portableText, {
|
|
295
|
-
block: {blockquote: ({children}) => `q:${children}`},
|
|
296
|
-
}),
|
|
297
|
-
).toBe('q:foo \nbar')
|
|
298
|
-
})
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
describe('multiple lines', () => {
|
|
302
|
-
const markdown = '> foo\n>\n> bar'
|
|
303
|
-
const portableText = markdownToPortableText(markdown)
|
|
304
|
-
|
|
305
|
-
test('default renderer', () => {
|
|
306
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
test('custom renderer', () => {
|
|
310
|
-
expect(
|
|
311
|
-
portableTextToMarkdown(portableText, {
|
|
312
|
-
block: {
|
|
313
|
-
blockquote: ({children}) => `q:${children}`,
|
|
314
|
-
},
|
|
315
|
-
blockSpacing: ({current, next}) => {
|
|
316
|
-
if (
|
|
317
|
-
isPortableTextBlock(current) &&
|
|
318
|
-
isPortableTextBlock(next) &&
|
|
319
|
-
current.style === 'blockquote' &&
|
|
320
|
-
next.style === 'blockquote'
|
|
321
|
-
) {
|
|
322
|
-
return '\nq:\n'
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return undefined
|
|
326
|
-
},
|
|
327
|
-
}),
|
|
328
|
-
).toBe('q:foo\nq:\nq:bar')
|
|
329
|
-
})
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
describe('nested', () => {
|
|
333
|
-
const markdown = '> foo\n>> bar'
|
|
334
|
-
const portableText = markdownToPortableText(markdown)
|
|
335
|
-
|
|
336
|
-
test('default renderer', () => {
|
|
337
|
-
expect(portableTextToMarkdown(portableText)).toBe('> foo\n>\n> bar')
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
test('custom renderer', () => {
|
|
341
|
-
expect(
|
|
342
|
-
portableTextToMarkdown(portableText, {
|
|
343
|
-
block: {
|
|
344
|
-
blockquote: ({children}) => `q:${children}`,
|
|
345
|
-
},
|
|
346
|
-
blockSpacing: ({current, next}) => {
|
|
347
|
-
if (
|
|
348
|
-
isPortableTextBlock(current) &&
|
|
349
|
-
isPortableTextBlock(next) &&
|
|
350
|
-
current.style === 'blockquote' &&
|
|
351
|
-
next.style === 'blockquote'
|
|
352
|
-
) {
|
|
353
|
-
return '\nq:\n'
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
return undefined
|
|
357
|
-
},
|
|
358
|
-
}),
|
|
359
|
-
).toBe('q:foo\nq:\nq:bar')
|
|
360
|
-
})
|
|
361
|
-
})
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
describe('h1', () => {
|
|
365
|
-
const markdown = '# foo'
|
|
366
|
-
const portableText = markdownToPortableText(markdown)
|
|
367
|
-
|
|
368
|
-
test('default renderer', () => {
|
|
369
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
test('custom renderer', () => {
|
|
373
|
-
expect(
|
|
374
|
-
portableTextToMarkdown(portableText, {
|
|
375
|
-
block: {h1: ({children}) => `h1:${children}`},
|
|
376
|
-
}),
|
|
377
|
-
).toBe('h1:foo')
|
|
378
|
-
})
|
|
379
|
-
})
|
|
380
|
-
|
|
381
|
-
describe('unknown style', () => {
|
|
382
|
-
const markdown = '# foo'
|
|
383
|
-
const portableText = markdownToPortableText(markdown, {
|
|
384
|
-
schema: compileSchema(defineSchema({styles: [{name: 'heading 1'}]})),
|
|
385
|
-
block: {h1: () => 'heading 1'},
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
test('default renderer', () => {
|
|
389
|
-
expect(portableTextToMarkdown(portableText)).toBe('foo')
|
|
390
|
-
})
|
|
391
|
-
|
|
392
|
-
test('custom renderer', () => {
|
|
393
|
-
expect(
|
|
394
|
-
portableTextToMarkdown(portableText, {
|
|
395
|
-
block: {
|
|
396
|
-
'heading 1': ({children}) => `# ${children}`,
|
|
397
|
-
},
|
|
398
|
-
}),
|
|
399
|
-
).toBe(markdown)
|
|
400
|
-
})
|
|
401
|
-
})
|
|
402
|
-
})
|
|
403
|
-
|
|
404
|
-
describe('list items', () => {
|
|
405
|
-
describe('unordered', () => {
|
|
406
|
-
const markdown = '- foo'
|
|
407
|
-
|
|
408
|
-
test('default render', () => {
|
|
409
|
-
const portableText = markdownToPortableText(markdown)
|
|
410
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
411
|
-
})
|
|
412
|
-
|
|
413
|
-
describe('unknown list item', () => {
|
|
414
|
-
const schema = compileSchema(defineSchema({lists: [{name: 'dot'}]}))
|
|
415
|
-
const portableText = markdownToPortableText(markdown, {
|
|
416
|
-
schema,
|
|
417
|
-
listItem: {bullet: () => 'dot'},
|
|
418
|
-
})
|
|
419
|
-
|
|
420
|
-
test('default renderer', () => {
|
|
421
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
422
|
-
})
|
|
423
|
-
|
|
424
|
-
test('pluggable default renderer', () => {
|
|
425
|
-
expect(
|
|
426
|
-
portableTextToMarkdown(portableText, {
|
|
427
|
-
listItem: {
|
|
428
|
-
dot: DefaultListItemRenderer,
|
|
429
|
-
},
|
|
430
|
-
}),
|
|
431
|
-
).toBe(markdown)
|
|
432
|
-
})
|
|
433
|
-
})
|
|
434
|
-
|
|
435
|
-
test('no definition', () => {
|
|
436
|
-
const schema = compileSchema(defineSchema({}))
|
|
437
|
-
const portableText = markdownToPortableText(markdown, {schema})
|
|
438
|
-
expect(portableTextToMarkdown(portableText)).toBe('foo')
|
|
439
|
-
})
|
|
440
|
-
})
|
|
441
|
-
})
|
|
442
|
-
|
|
443
|
-
describe('lists', () => {
|
|
444
|
-
const markdown = ['- foo', ' - bar', ' - baz'].join('\n')
|
|
445
|
-
|
|
446
|
-
test('default definition', () => {
|
|
447
|
-
const portableText = markdownToPortableText(markdown)
|
|
448
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
449
|
-
})
|
|
450
|
-
|
|
451
|
-
test('custom definition', () => {
|
|
452
|
-
const markdownOut = ['• foo', ' • bar', ' • baz'].join('\n')
|
|
453
|
-
const schema = compileSchema(defineSchema({lists: [{name: 'dot'}]}))
|
|
454
|
-
const portableText = markdownToPortableText(markdown, {
|
|
455
|
-
schema,
|
|
456
|
-
listItem: {bullet: () => 'dot'},
|
|
457
|
-
})
|
|
458
|
-
expect(
|
|
459
|
-
portableTextToMarkdown(portableText, {
|
|
460
|
-
listItem: {
|
|
461
|
-
dot: ({children, value}) => {
|
|
462
|
-
const level = value.level || 1
|
|
463
|
-
const indent = ' '.repeat(level - 1)
|
|
464
|
-
return `${indent}• ${children}`
|
|
465
|
-
},
|
|
466
|
-
},
|
|
467
|
-
}),
|
|
468
|
-
).toBe(markdownOut)
|
|
469
|
-
})
|
|
470
|
-
|
|
471
|
-
test('no definition', () => {
|
|
472
|
-
const schema = compileSchema(defineSchema({}))
|
|
473
|
-
const portableText = markdownToPortableText(markdown, {schema})
|
|
474
|
-
expect(portableTextToMarkdown(portableText)).toBe('foo\n\nbar\n\nbaz')
|
|
475
|
-
})
|
|
476
|
-
|
|
477
|
-
test('mixed, deeply nested lists', () => {
|
|
478
|
-
const keyGenerator = createTestKeyGenerator()
|
|
479
|
-
const markdown = [
|
|
480
|
-
'1. Ordered parent',
|
|
481
|
-
' - Unordered child',
|
|
482
|
-
' - Another unordered',
|
|
483
|
-
' 1. Back to ordered',
|
|
484
|
-
' 2. Still ordered',
|
|
485
|
-
'2. Continue ordered parent',
|
|
486
|
-
].join('\n')
|
|
487
|
-
const portableText = markdownToPortableText(markdown, {keyGenerator})
|
|
488
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdown)
|
|
489
|
-
})
|
|
490
|
-
})
|
|
491
|
-
|
|
492
|
-
describe('block image', () => {
|
|
493
|
-
const markdownIn =
|
|
494
|
-
'foo\n\n\n\nbar'
|
|
495
|
-
|
|
496
|
-
describe('supported by deserializer', () => {
|
|
497
|
-
const keyGenerator = createTestKeyGenerator()
|
|
498
|
-
const portableText = markdownToPortableText(markdownIn, {keyGenerator})
|
|
499
|
-
|
|
500
|
-
test('default renderer', () => {
|
|
501
|
-
const markdownOut = [
|
|
502
|
-
'foo',
|
|
503
|
-
'',
|
|
504
|
-
'```json',
|
|
505
|
-
'{',
|
|
506
|
-
' "_key": "k3",',
|
|
507
|
-
' "_type": "image",',
|
|
508
|
-
' "src": "https://example.com/image.png",',
|
|
509
|
-
' "alt": "alt text"',
|
|
510
|
-
'}',
|
|
511
|
-
'```',
|
|
512
|
-
'',
|
|
513
|
-
'bar',
|
|
514
|
-
].join('\n')
|
|
515
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdownOut)
|
|
516
|
-
})
|
|
517
|
-
|
|
518
|
-
test('custom renderer', () => {
|
|
519
|
-
expect(
|
|
520
|
-
portableTextToMarkdown(portableText, {
|
|
521
|
-
types: {
|
|
522
|
-
image: ({value}) => ``,
|
|
523
|
-
},
|
|
524
|
-
}),
|
|
525
|
-
).toBe(markdownIn)
|
|
526
|
-
})
|
|
527
|
-
})
|
|
528
|
-
|
|
529
|
-
test('not supported by deserializer', () => {
|
|
530
|
-
const portableText = markdownToPortableText(markdownIn, {
|
|
531
|
-
schema: compileSchema(defineSchema({})),
|
|
532
|
-
})
|
|
533
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdownIn)
|
|
534
|
-
})
|
|
535
|
-
})
|
|
536
|
-
|
|
537
|
-
describe('inline image', () => {
|
|
538
|
-
const keyGenerator = createTestKeyGenerator()
|
|
539
|
-
const markdown = 'foo  bar'
|
|
540
|
-
|
|
541
|
-
describe('supported by deserializer', () => {
|
|
542
|
-
const portableText = markdownToPortableText(markdown, {keyGenerator})
|
|
543
|
-
|
|
544
|
-
test('default renderer', () => {
|
|
545
|
-
const markdownOut = [
|
|
546
|
-
'foo ',
|
|
547
|
-
'```json',
|
|
548
|
-
'{',
|
|
549
|
-
' "_key": "k2",',
|
|
550
|
-
' "_type": "image",',
|
|
551
|
-
' "src": "https://example.com/image.png",',
|
|
552
|
-
' "alt": "alt text"',
|
|
553
|
-
'}',
|
|
554
|
-
'```',
|
|
555
|
-
' bar',
|
|
556
|
-
].join('\n')
|
|
557
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdownOut)
|
|
558
|
-
})
|
|
559
|
-
|
|
560
|
-
test('custom renderer', () => {
|
|
561
|
-
const markdownOut = 'foo  bar'
|
|
562
|
-
expect(
|
|
563
|
-
portableTextToMarkdown(portableText, {
|
|
564
|
-
types: {
|
|
565
|
-
image: ({value}) => ``,
|
|
566
|
-
},
|
|
567
|
-
}),
|
|
568
|
-
).toBe(markdownOut)
|
|
569
|
-
})
|
|
570
|
-
|
|
571
|
-
test('skip inline images by returning empty string', () => {
|
|
572
|
-
const markdownOut = 'foo bar'
|
|
573
|
-
expect(
|
|
574
|
-
portableTextToMarkdown(portableText, {
|
|
575
|
-
types: {
|
|
576
|
-
image: () => '',
|
|
577
|
-
},
|
|
578
|
-
}),
|
|
579
|
-
).toBe(markdownOut)
|
|
580
|
-
})
|
|
581
|
-
|
|
582
|
-
test('render block images but skip inline images', () => {
|
|
583
|
-
const blockAndInlineImages = [
|
|
584
|
-
{
|
|
585
|
-
_type: 'image',
|
|
586
|
-
_key: 'block-img',
|
|
587
|
-
src: 'https://example.com/block.png',
|
|
588
|
-
alt: 'block image',
|
|
589
|
-
},
|
|
590
|
-
{
|
|
591
|
-
_type: 'block',
|
|
592
|
-
_key: 'b1',
|
|
593
|
-
style: 'normal',
|
|
594
|
-
children: [
|
|
595
|
-
{_type: 'span', _key: 's1', text: 'text with ', marks: []},
|
|
596
|
-
{
|
|
597
|
-
_type: 'image',
|
|
598
|
-
_key: 'inline-img',
|
|
599
|
-
src: 'https://example.com/inline.png',
|
|
600
|
-
alt: 'inline image',
|
|
601
|
-
},
|
|
602
|
-
{_type: 'span', _key: 's2', text: ' inside', marks: []},
|
|
603
|
-
],
|
|
604
|
-
markDefs: [],
|
|
605
|
-
},
|
|
606
|
-
]
|
|
607
|
-
const markdownOut =
|
|
608
|
-
'\n\ntext with inside'
|
|
609
|
-
expect(
|
|
610
|
-
portableTextToMarkdown(blockAndInlineImages, {
|
|
611
|
-
types: {
|
|
612
|
-
image: ({value, isInline}) =>
|
|
613
|
-
isInline ? '' : ``,
|
|
614
|
-
},
|
|
615
|
-
}),
|
|
616
|
-
).toBe(markdownOut)
|
|
617
|
-
})
|
|
618
|
-
})
|
|
619
|
-
|
|
620
|
-
test('not supported by deserializer', () => {
|
|
621
|
-
const portableText = markdownToPortableText(markdown, {
|
|
622
|
-
schema: compileSchema(defineSchema({})),
|
|
623
|
-
})
|
|
624
|
-
const markdownOut = 'foo  bar'
|
|
625
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdownOut)
|
|
626
|
-
})
|
|
627
|
-
})
|
|
628
|
-
|
|
629
|
-
describe('code block', () => {
|
|
630
|
-
describe('single line', () => {
|
|
631
|
-
const keyGenerator = createTestKeyGenerator()
|
|
632
|
-
const markdownIn = ['```js', `const foo = 'bar'`, '```'].join('\n')
|
|
633
|
-
const portableText = markdownToPortableText(markdownIn, {keyGenerator})
|
|
634
|
-
|
|
635
|
-
test('default renderer', () => {
|
|
636
|
-
const markdownOut = [
|
|
637
|
-
'```json',
|
|
638
|
-
'{',
|
|
639
|
-
' "_key": "k0",',
|
|
640
|
-
' "_type": "code",',
|
|
641
|
-
' "language": "js",',
|
|
642
|
-
' "code": "const foo = \'bar\'"',
|
|
643
|
-
'}',
|
|
644
|
-
'```',
|
|
645
|
-
].join('\n')
|
|
646
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdownOut)
|
|
647
|
-
})
|
|
648
|
-
|
|
649
|
-
test('custom renderer', () => {
|
|
650
|
-
const markdownOut = ['```js', `const foo = 'bar'`, '```'].join('\n')
|
|
651
|
-
expect(
|
|
652
|
-
portableTextToMarkdown(portableText, {
|
|
653
|
-
types: {
|
|
654
|
-
code: ({value}) =>
|
|
655
|
-
`\`\`\`${value.language}\n${value.code}\n\`\`\``,
|
|
656
|
-
},
|
|
657
|
-
}),
|
|
658
|
-
).toBe(markdownOut)
|
|
659
|
-
})
|
|
660
|
-
|
|
661
|
-
test('no language field', () => {
|
|
662
|
-
const markdownOut = ['```', `const foo = 'bar'`, '```'].join('\n')
|
|
663
|
-
const portableText = markdownToPortableText(markdownIn, {
|
|
664
|
-
schema: compileSchema(
|
|
665
|
-
defineSchema({
|
|
666
|
-
blockObjects: [
|
|
667
|
-
{name: 'code', fields: [{name: 'code', type: 'string'}]},
|
|
668
|
-
],
|
|
669
|
-
}),
|
|
670
|
-
),
|
|
671
|
-
})
|
|
672
|
-
|
|
673
|
-
expect(
|
|
674
|
-
portableTextToMarkdown(portableText, {
|
|
675
|
-
types: {
|
|
676
|
-
code: ({value}) => `\`\`\`\n${value.code}\n\`\`\``,
|
|
677
|
-
},
|
|
678
|
-
}),
|
|
679
|
-
).toBe(markdownOut)
|
|
680
|
-
})
|
|
681
|
-
|
|
682
|
-
test('no code field', () => {
|
|
683
|
-
const markdownOut = "const foo = 'bar'"
|
|
684
|
-
const portableText = markdownToPortableText(markdownIn, {
|
|
685
|
-
schema: compileSchema(
|
|
686
|
-
defineSchema({
|
|
687
|
-
blockObjects: [
|
|
688
|
-
{name: 'code', fields: [{name: 'language', type: 'string'}]},
|
|
689
|
-
],
|
|
690
|
-
}),
|
|
691
|
-
),
|
|
692
|
-
})
|
|
693
|
-
|
|
694
|
-
expect(
|
|
695
|
-
portableTextToMarkdown(portableText, {
|
|
696
|
-
types: {
|
|
697
|
-
code: ({value}) => `\`\`\`\n${value.code}\n\`\`\``,
|
|
698
|
-
},
|
|
699
|
-
}),
|
|
700
|
-
).toBe(markdownOut)
|
|
701
|
-
})
|
|
702
|
-
})
|
|
703
|
-
|
|
704
|
-
describe('multiple lines', () => {
|
|
705
|
-
const keyGenerator = createTestKeyGenerator()
|
|
706
|
-
const markdownIn = [
|
|
707
|
-
'```js',
|
|
708
|
-
`const foo = 'bar'`,
|
|
709
|
-
`const bar = 'baz'`,
|
|
710
|
-
'```',
|
|
711
|
-
].join('\n')
|
|
712
|
-
const portableText = markdownToPortableText(markdownIn, {keyGenerator})
|
|
713
|
-
|
|
714
|
-
test('default renderer', () => {
|
|
715
|
-
const markdownOut = [
|
|
716
|
-
'```json',
|
|
717
|
-
'{',
|
|
718
|
-
' "_key": "k0",',
|
|
719
|
-
' "_type": "code",',
|
|
720
|
-
' "language": "js",',
|
|
721
|
-
' "code": "const foo = \'bar\'\\nconst bar = \'baz\'"',
|
|
722
|
-
'}',
|
|
723
|
-
'```',
|
|
724
|
-
].join('\n')
|
|
725
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdownOut)
|
|
726
|
-
})
|
|
727
|
-
|
|
728
|
-
test('pluggable default renderer', () => {
|
|
729
|
-
const markdownOut = [
|
|
730
|
-
'```js',
|
|
731
|
-
`const foo = 'bar'`,
|
|
732
|
-
`const bar = 'baz'`,
|
|
733
|
-
'```',
|
|
734
|
-
].join('\n')
|
|
735
|
-
expect(
|
|
736
|
-
portableTextToMarkdown(portableText, {
|
|
737
|
-
types: {
|
|
738
|
-
code: DefaultCodeBlockRenderer,
|
|
739
|
-
},
|
|
740
|
-
}),
|
|
741
|
-
).toBe(markdownOut)
|
|
742
|
-
})
|
|
743
|
-
})
|
|
744
|
-
})
|
|
745
|
-
|
|
746
|
-
describe('tables', () => {
|
|
747
|
-
describe('simple table', () => {
|
|
748
|
-
const keyGenerator = createTestKeyGenerator()
|
|
749
|
-
const markdownIn = [
|
|
750
|
-
'| Header 1 | Header 2 |',
|
|
751
|
-
'| -------- | -------- |',
|
|
752
|
-
'| Cell 1 | Cell 2 |',
|
|
753
|
-
'| Cell 3 | Cell 4 |',
|
|
754
|
-
].join('\n')
|
|
755
|
-
const tableObjectDefinition = {
|
|
756
|
-
name: 'table',
|
|
757
|
-
fields: [
|
|
758
|
-
{name: 'headerRows', type: 'number'},
|
|
759
|
-
{name: 'rows', type: 'array'},
|
|
760
|
-
],
|
|
761
|
-
} as const
|
|
762
|
-
const schema = compileSchema(
|
|
763
|
-
defineSchema({
|
|
764
|
-
blockObjects: [tableObjectDefinition],
|
|
765
|
-
}),
|
|
766
|
-
)
|
|
767
|
-
const portableText = markdownToPortableText(markdownIn, {
|
|
768
|
-
keyGenerator,
|
|
769
|
-
schema,
|
|
770
|
-
types: {
|
|
771
|
-
table: buildObjectMatcher(tableObjectDefinition),
|
|
772
|
-
},
|
|
773
|
-
})
|
|
774
|
-
|
|
775
|
-
test('default renderer', () => {
|
|
776
|
-
const markdownOut = [
|
|
777
|
-
'```json',
|
|
778
|
-
JSON.stringify(portableText.at(0), null, 2),
|
|
779
|
-
'```',
|
|
780
|
-
].join('\n')
|
|
781
|
-
|
|
782
|
-
expect(portableTextToMarkdown(portableText)).toBe(markdownOut)
|
|
783
|
-
})
|
|
784
|
-
|
|
785
|
-
test('pluggable default renderer', () => {
|
|
786
|
-
const markdownOut = [
|
|
787
|
-
'| Header 1 | Header 2 |',
|
|
788
|
-
'| --- | --- |',
|
|
789
|
-
'| Cell 1 | Cell 2 |',
|
|
790
|
-
'| Cell 3 | Cell 4 |',
|
|
791
|
-
].join('\n')
|
|
792
|
-
|
|
793
|
-
expect(
|
|
794
|
-
portableTextToMarkdown(portableText, {
|
|
795
|
-
types: {
|
|
796
|
-
table: DefaultTableRenderer,
|
|
797
|
-
},
|
|
798
|
-
}),
|
|
799
|
-
).toBe(markdownOut)
|
|
800
|
-
})
|
|
801
|
-
})
|
|
802
|
-
})
|
|
803
|
-
})
|