Skip to content
This repository was archived by the owner on Aug 18, 2023. It is now read-only.

Commit 59e505d

Browse files
committed
add fallback serializer
1 parent 25ad96c commit 59e505d

File tree

3 files changed

+123
-12
lines changed

3 files changed

+123
-12
lines changed

src/index.ts

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,31 @@ import {
1919

2020
const notNull = <T>(x: T | null): x is T => x !== null;
2121

22+
const FallbackSerializer = defineComponent({
23+
props: {
24+
_type: {
25+
type: String,
26+
required: true,
27+
},
28+
},
29+
setup(props) {
30+
return () =>
31+
h(
32+
'p',
33+
{
34+
style: {
35+
color: 'red',
36+
background: 'white',
37+
border: '4px solid red',
38+
margin: '0 0 4px 0',
39+
padding: '24px',
40+
},
41+
},
42+
`Serializer for ${props._type} does not exist.`
43+
);
44+
},
45+
});
46+
2247
const createElementFromStyle = (
2348
block: BlockText | BlockListItem,
2449
serializers: Serializers,
@@ -141,14 +166,36 @@ const linkSerializer: MarkSerializer = (props, children) => {
141166
);
142167
};
143168

144-
const listSerializer = (block: BlockListItem, serializers: Serializers) => {
169+
const listSerializer = (
170+
block: BlockListItem,
171+
serializers: Serializers,
172+
useFallbackSerializer: boolean
173+
) => {
145174
const el = block.listItem === 'number' ? 'ol' : 'ul';
146-
return h(el, {}, renderBlocks(block.children, serializers, block.level));
175+
return h(
176+
el,
177+
{},
178+
renderBlocks(
179+
block.children,
180+
serializers,
181+
block.level,
182+
useFallbackSerializer
183+
)
184+
);
147185
};
148186

149-
const listItemSerializer = (block: BlockListItem, serializers: Serializers) => {
187+
const listItemSerializer = (
188+
block: BlockListItem,
189+
serializers: Serializers,
190+
useFallbackSerializer: boolean
191+
) => {
150192
// Array of array of strings or nodes
151-
const children = renderBlocks(block.children, serializers, block.level);
193+
const children = renderBlocks(
194+
block.children,
195+
serializers,
196+
block.level,
197+
useFallbackSerializer
198+
);
152199
const shouldWrap = block.style && block.style !== 'normal';
153200
return h(
154201
'li',
@@ -166,11 +213,22 @@ const extractProps = (item: CustomBlock | MarkDefinition | undefined) => {
166213
return {};
167214
};
168215

169-
const serializeBlock = (block: Block | BlockSpan, serializers: Serializers) => {
216+
const serializeBlock = (
217+
block: Block | BlockSpan,
218+
serializers: Serializers,
219+
useFallbackSerializer: boolean
220+
) => {
170221
// Find the serializer for this type of block
171222
const serializer = findBlockSerializer(block, serializers);
172-
// If none found, return null
173-
if (!serializer) return null;
223+
// If none found, use fallback or null
224+
if (!serializer) {
225+
if (useFallbackSerializer) {
226+
return h(FallbackSerializer, {
227+
_type: block._type,
228+
});
229+
}
230+
return null;
231+
}
174232
// If the serializer is a vue component, render it
175233
if (serializerIsVueComponent(serializer)) {
176234
const props = extractProps(block);
@@ -184,7 +242,11 @@ const serializeBlock = (block: Block | BlockSpan, serializers: Serializers) => {
184242
if (blockIsSpan(block)) {
185243
return (serializer as SpanSerializer)(block, serializers, []);
186244
}
187-
return (serializer as BlockSerializer)(block, serializers);
245+
return (serializer as BlockSerializer)(
246+
block,
247+
serializers,
248+
useFallbackSerializer
249+
);
188250
}
189251
// Must be a string by this point
190252
return h(serializer, {});
@@ -246,14 +308,15 @@ const nestBlocks = (blocks: Array<Block | BlockSpan>, level = 0) => {
246308
const renderBlocks = (
247309
blocks: Block[] | BlockSpan[],
248310
serializers: Serializers,
249-
level = 0
311+
level = 0,
312+
useFallbackSerializer: boolean
250313
) => {
251314
// Nest list items in lists
252315
const nestedBlocks = nestBlocks(blocks, level);
253316

254317
// Loop through each block, and serialize it
255318
return nestedBlocks
256-
.map((block) => serializeBlock(block, serializers))
319+
.map((block) => serializeBlock(block, serializers, useFallbackSerializer))
257320
.filter(notNull);
258321
};
259322

@@ -297,9 +360,14 @@ export const SanityBlocks = defineComponent({
297360
type: Object as PropType<Partial<Serializers>>,
298361
default: () => ({}),
299362
},
363+
useFallbackSerializer: {
364+
type: Boolean as PropType<boolean>,
365+
default: false,
366+
},
300367
},
301368
setup(props) {
302369
const serializers = merge({}, defaultSerializers, props.serializers);
303-
return () => renderBlocks(props.blocks, serializers);
370+
return () =>
371+
renderBlocks(props.blocks, serializers, 0, props.useFallbackSerializer);
304372
},
305373
});

src/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ export type SerializedNode = string | VNode;
4747

4848
export type BlockSerializer<T = Block> = (
4949
block: T,
50-
serializers: Serializers
50+
serializers: Serializers,
51+
useFallbackSerializer: boolean
5152
) => SerializedNode | SerializedNode[];
5253

5354
export type MarkSerializer = (

test/serializer.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,48 @@ import { h, defineComponent } from 'vue';
22
import { mount } from '@vue/test-utils';
33
import { SanityBlocks } from '../src';
44

5+
test('undefined custom type serializer with fallback', () => {
6+
const wrapper = mount(SanityBlocks, {
7+
props: {
8+
blocks: [
9+
{
10+
_type: 'message',
11+
_key: '3l37kf8jq1b4',
12+
msg: 'Foobar!',
13+
},
14+
],
15+
serializers: {
16+
types: {},
17+
},
18+
useFallbackSerializer: true,
19+
},
20+
});
21+
22+
expect(wrapper.html()).toMatch(
23+
'<p style="color: red; background: white; border: 4px solid red; margin: 0px 0px 4px 0px; padding: 24px;">Serializer for message does not exist.</p>'
24+
);
25+
});
26+
27+
test('undefined custom type serializer without fallback', () => {
28+
const wrapper = mount(SanityBlocks, {
29+
props: {
30+
blocks: [
31+
{
32+
_type: 'message',
33+
_key: '3l37kf8jq1b4',
34+
msg: 'Foobar!',
35+
},
36+
],
37+
serializers: {
38+
types: {},
39+
},
40+
useFallbackSerializer: false,
41+
},
42+
});
43+
44+
expect(wrapper.html()).toMatch('');
45+
});
46+
547
test('custom type serializer with template', () => {
648
const wrapper = mount(SanityBlocks, {
749
props: {

0 commit comments

Comments
 (0)