/
asserters.ts
70 lines (66 loc) · 2.07 KB
/
asserters.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import type {PortableTextTextBlock, PortableTextSpan, PortableTextObject} from './types'
function isRecord(value: unknown): value is Record<string, unknown> {
return !!value && (typeof value == 'object' || typeof value == 'function')
}
/**
* Assert that a given object is a portable-text text-block type object
*
* @remarks
* * The `markDefs` and `style` property of a block is optional.
* * Block types can be named, so expect anything of the _type property.
*
* @alpha
*/
export function isPortableTextTextBlock<T = PortableTextSpan | PortableTextObject>(
value: unknown
): value is PortableTextTextBlock<T> {
return (
isRecord(value) &&
typeof value._type === 'string' && // block types can be named, so expect anything here.
Array.isArray(value.children) &&
value.children.every((child) => isRecord(child)) &&
('markDefs' in value // optional property
? Array.isArray(value.markDefs) && value.markDefs.every((def) => isRecord(def))
: false) &&
('style' in value ? typeof value.style === 'string' : true) // optional property
)
}
/**
* Assert that a given object is a portable-text span-type object
*
* @remarks
* The `marks` property of a block is optional.
*
* @alpha
*/
export function isPortableTextSpan(value: unknown): value is PortableTextSpan {
return (
isRecord(value) &&
value._type === 'span' &&
typeof value.text === 'string' &&
('marks' in value // optional property
? Array.isArray(value.marks) && value.marks.every((mark) => typeof mark === 'string')
: true)
)
}
/**
* Assert that a given object is a portable-text list-text-block-type object
*
* @remarks
* Uses `isPortableTextTextBlock` and checks for `listItem` and `level`
*
* @see isPortableTextTextBlock
*
* @alpha
*/
export function isPortableTextListBlock<T = PortableTextSpan | PortableTextObject>(
value: unknown
): value is PortableTextTextBlock<T> {
return (
isPortableTextTextBlock(value) &&
'listItem' in value &&
typeof value.listItem === 'string' &&
'level' in value &&
Number.isInteger(value.level)
)
}