/
helpers.ts
153 lines (146 loc) · 4.06 KB
/
helpers.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/**
* Internal dependencies
*/
import type { EntityRecord } from './index';
export interface AvatarUrls {
/**
* Avatar URL with image size of 24 pixels.
*/
'24': string;
/**
* Avatar URL with image size of 48 pixels.
*/
'48': string;
/**
* Avatar URL with image size of 96 pixels.
*/
'96': string;
}
export type MediaType = 'image' | 'file';
export type CommentingStatus = 'open' | 'closed';
export type PingStatus = 'open' | 'closed';
export type PostStatus = 'publish' | 'future' | 'draft' | 'pending' | 'private';
export type PostFormat =
| 'standard'
| 'aside'
| 'chat'
| 'gallery'
| 'link'
| 'image'
| 'quote'
| 'status'
| 'video'
| 'audio';
/**
* The REST API context parameter.
*/
export type Context = 'view' | 'edit' | 'embed';
/**
* ContextualField makes the field available only in the specified given contexts,
* and ensure the field is absent from the object when in a different context.
*
* @example
* ```ts
* interface Post< C extends Context > {
* …
* modified: ContextualField< string, 'edit' | 'view', C >;
* password: ContextualField< string, 'edit', C >;
* …
* }
*
* const post: Post<'edit'> = …
* // post.modified exists as a string
* // post.password exists as a string
*
* const post: Post<'view'> = …
* // post.modified still exists as a string
* // post.password is missing, undefined, because we're not in the `edit` context.
* ```
*/
export type ContextualField<
FieldType,
AvailableInContexts extends Context,
C extends Context
> = AvailableInContexts extends C ? FieldType : never;
/**
* Removes all the properties of type never, even the deeply nested ones.
*
* @example
* ```ts
* type MyType = {
* foo: string;
* bar: never;
* nested: {
* foo: string;
* bar: never;
* }
* }
* const x = {} as OmitNevers<MyType>;
* // x is of type { foo: string; nested: { foo: string; }}
* // The `never` properties were removed entirely
* ```
*/
export type OmitNevers<
T,
Nevers = {
[ K in keyof T ]: Exclude< T[ K ], undefined > extends never
? never
: T[ K ] extends Record< string, unknown >
? OmitNevers< T[ K ] >
: T[ K ];
}
> = Pick<
Nevers,
{
[ K in keyof Nevers ]: Nevers[ K ] extends never ? never : K;
}[ keyof Nevers ]
>;
/**
* A string that the server renders which often involves
* modifications from the raw source string.
*
* For example, block HTML with the comment delimiters exists
* in `post_content` but those comments are stripped out when
* rendering to a page view. Similarly, plugins might modify
* content or replace shortcodes.
*/
export interface RenderedText< C extends Context > {
/**
* The source string which will be rendered on page views.
*/
raw: ContextualField< string, 'edit', C >;
/**
* The output of the raw source after processing and filtering on the server.
*/
rendered: string;
}
/**
* Updatable<EntityRecord> is a type describing Edited Entity Records. They are like
* regular Entity Records, but they have all the local edits applied on top of the REST API data.
*
* This turns certain field from an object into a string.
*
* Entities like Post have fields that only be rendered on the server, like title, excerpt,
* and content. The REST API exposes both the raw markup and the rendered version of those fields.
* For example, in the block editor, content.rendered could used as a visual preview, and
* content.raw could be used to populate the code editor.
*
* When updating these rendered fields, Javascript is not be able to properly render arbitrary block
* markup. Therefore, it stores only the raw markup without the rendered part. And since that's a string,
* the entire field becomes a string.
*
* @example
* ```ts
* type Post< C extends Context > {
* title: RenderedText< C >;
* }
* const post = {} as Post;
* // post.title is an object with raw and rendered properties
*
* const updatablePost = {} as Updatable< Post >;
* // updatablePost.title is a string
* ```
*/
export type Updatable< T extends EntityRecord< 'edit' > > = {
[ K in keyof T ]: T[ K ] extends RenderedText< any > ? string : T[ K ];
};