1
1
import {
2
- Element ,
3
2
RichTextFunctionSerializer ,
4
3
RichTextMapSerializer ,
5
4
RichTextMapSerializerFunction ,
@@ -43,11 +42,26 @@ export type HTMLRichTextFunctionSerializer = (
43
42
*
44
43
* Unlike a typical `@prismicio/richtext` map serializer, this serializer
45
44
* converts the `children` property to a single string rather than an array of
46
- * strings.
45
+ * strings and accepts shorthand declarations .
47
46
*
48
47
* @see Templating rich text and title fields from Prismic {@link https://prismic.io/docs/template-content-vanilla-javascript#rich-text-and-title}
49
48
*/
50
49
export type HTMLRichTextMapSerializer = {
50
+ [ P in keyof RichTextMapSerializer < string > ] : P extends RichTextMapSerializer < string > [ "span" ]
51
+ ? HTMLStrictRichTextMapSerializer [ P ]
52
+ : HTMLStrictRichTextMapSerializer [ P ] | HTMLRichTextMapSerializerShorthand ;
53
+ } ;
54
+
55
+ /**
56
+ * Serializes a node from a rich text or title field with a map to HTML
57
+ *
58
+ * Unlike a typical `@prismicio/richtext` map serializer, this serializer
59
+ * converts the `children` property to a single string rather than an array of
60
+ * strings but doesn't accept shorthand declarations.
61
+ *
62
+ * @see Templating rich text and title fields from Prismic {@link https://prismic.io/docs/template-content-vanilla-javascript#rich-text-and-title}
63
+ */
64
+ export type HTMLStrictRichTextMapSerializer = {
51
65
[ P in keyof RichTextMapSerializer < string > ] : ( payload : {
52
66
type : Parameters < HTMLRichTextMapSerializerFunction < P > > [ 0 ] [ "type" ] ;
53
67
node : Parameters < HTMLRichTextMapSerializerFunction < P > > [ 0 ] [ "node" ] ;
@@ -105,6 +119,21 @@ type ExtractTextTypeGeneric<T> = T extends RichTextMapSerializerFunction<
105
119
? U
106
120
: never ;
107
121
122
+ /**
123
+ * A shorthand definition for {@link HTMLRichTextMapSerializer} element types.
124
+ */
125
+ export type HTMLRichTextMapSerializerShorthand = {
126
+ /**
127
+ * Classes to apply to the element type.
128
+ */
129
+ class ?: string ;
130
+
131
+ /**
132
+ * Other attributes to apply to the element type.
133
+ */
134
+ [ Attribute : string ] : string | boolean | null | undefined ;
135
+ } ;
136
+
108
137
/**
109
138
* Serializes a node from a rich text or title field with a map or a function to
110
139
* HTML
@@ -117,57 +146,113 @@ export type HTMLRichTextSerializer =
117
146
| HTMLRichTextFunctionSerializer ;
118
147
119
148
/**
120
- * Creates a default HTML rich text serializer with a given link resolver
121
- * providing sensible and safe defaults for every node type
149
+ * Creates a HTML rich text serializer with a given link resolver and provide
150
+ * sensible and safe defaults for every node type
122
151
*
123
152
* @internal
124
153
*/
125
- const createDefaultHTMLRichTextSerializer = (
154
+ const createHTMLRichTextSerializer = (
126
155
linkResolver : LinkResolverFunction | undefined | null ,
156
+ serializer ?: HTMLRichTextMapSerializer | null ,
127
157
) : RichTextFunctionSerializer < string > => {
128
- return ( _type , node , text , children , _key ) => {
129
- switch ( node . type ) {
130
- case Element . heading1 :
131
- return serializeStandardTag ( "h1" , node , children ) ;
132
- case Element . heading2 :
133
- return serializeStandardTag ( "h2" , node , children ) ;
134
- case Element . heading3 :
135
- return serializeStandardTag ( "h3" , node , children ) ;
136
- case Element . heading4 :
137
- return serializeStandardTag ( "h4" , node , children ) ;
138
- case Element . heading5 :
139
- return serializeStandardTag ( "h5" , node , children ) ;
140
- case Element . heading6 :
141
- return serializeStandardTag ( "h6" , node , children ) ;
142
- case Element . paragraph :
143
- return serializeStandardTag ( "p" , node , children ) ;
144
- case Element . preformatted :
145
- return serializePreFormatted ( node ) ;
146
- case Element . strong :
147
- return serializeStandardTag ( "strong" , node , children ) ;
148
- case Element . em :
149
- return serializeStandardTag ( "em" , node , children ) ;
150
- case Element . listItem :
151
- return serializeStandardTag ( "li" , node , children ) ;
152
- case Element . oListItem :
153
- return serializeStandardTag ( "li" , node , children ) ;
154
- case Element . list :
155
- return serializeStandardTag ( "ul" , node , children ) ;
156
- case Element . oList :
157
- return serializeStandardTag ( "ol" , node , children ) ;
158
- case Element . image :
159
- return serializeImage ( linkResolver , node ) ;
160
- case Element . embed :
161
- return serializeEmbed ( node ) ;
162
- case Element . hyperlink :
163
- return serializeHyperlink ( linkResolver , node , children ) ;
164
- case Element . label :
165
- return serializeStandardTag ( "span" , node , children ) ;
166
- case Element . span :
167
- default :
168
- return serializeSpan ( text ) ;
158
+ const useSerializerOrDefault = <
159
+ BlockType extends keyof RichTextMapSerializer < string > ,
160
+ > (
161
+ nodeSerializerOrShorthand : HTMLRichTextMapSerializer [ BlockType ] ,
162
+ defaultWithShorthand : NonNullable <
163
+ HTMLStrictRichTextMapSerializer [ BlockType ]
164
+ > ,
165
+ ) : NonNullable < HTMLStrictRichTextMapSerializer [ BlockType ] > => {
166
+ if ( typeof nodeSerializerOrShorthand === "function" ) {
167
+ return ( ( payload ) => {
168
+ return (
169
+ (
170
+ nodeSerializerOrShorthand as HTMLStrictRichTextMapSerializer [ BlockType ]
171
+ ) ( payload ) || defaultWithShorthand ( payload )
172
+ ) ;
173
+ } ) as NonNullable < HTMLStrictRichTextMapSerializer [ BlockType ] > ;
169
174
}
175
+
176
+ return defaultWithShorthand ;
170
177
} ;
178
+
179
+ const mapSerializer : Required < HTMLStrictRichTextMapSerializer > = {
180
+ heading1 : useSerializerOrDefault < "heading1" > (
181
+ serializer ?. heading1 ,
182
+ serializeStandardTag < "heading1" > ( "h1" , serializer ?. heading1 ) ,
183
+ ) ,
184
+ heading2 : useSerializerOrDefault < "heading2" > (
185
+ serializer ?. heading2 ,
186
+ serializeStandardTag < "heading2" > ( "h2" , serializer ?. heading2 ) ,
187
+ ) ,
188
+ heading3 : useSerializerOrDefault < "heading3" > (
189
+ serializer ?. heading3 ,
190
+ serializeStandardTag < "heading3" > ( "h3" , serializer ?. heading3 ) ,
191
+ ) ,
192
+ heading4 : useSerializerOrDefault < "heading4" > (
193
+ serializer ?. heading4 ,
194
+ serializeStandardTag < "heading4" > ( "h4" , serializer ?. heading4 ) ,
195
+ ) ,
196
+ heading5 : useSerializerOrDefault < "heading5" > (
197
+ serializer ?. heading5 ,
198
+ serializeStandardTag < "heading5" > ( "h5" , serializer ?. heading5 ) ,
199
+ ) ,
200
+ heading6 : useSerializerOrDefault < "heading6" > (
201
+ serializer ?. heading6 ,
202
+ serializeStandardTag < "heading6" > ( "h6" , serializer ?. heading6 ) ,
203
+ ) ,
204
+ paragraph : useSerializerOrDefault < "paragraph" > (
205
+ serializer ?. paragraph ,
206
+ serializeStandardTag < "paragraph" > ( "p" , serializer ?. paragraph ) ,
207
+ ) ,
208
+ preformatted : useSerializerOrDefault < "preformatted" > (
209
+ serializer ?. preformatted ,
210
+ serializePreFormatted ( serializer ?. preformatted ) ,
211
+ ) ,
212
+ strong : useSerializerOrDefault < "strong" > (
213
+ serializer ?. strong ,
214
+ serializeStandardTag < "strong" > ( "strong" , serializer ?. strong ) ,
215
+ ) ,
216
+ em : useSerializerOrDefault < "em" > (
217
+ serializer ?. em ,
218
+ serializeStandardTag < "em" > ( "em" , serializer ?. em ) ,
219
+ ) ,
220
+ listItem : useSerializerOrDefault < "listItem" > (
221
+ serializer ?. listItem ,
222
+ serializeStandardTag < "listItem" > ( "li" , serializer ?. listItem ) ,
223
+ ) ,
224
+ oListItem : useSerializerOrDefault < "oListItem" > (
225
+ serializer ?. oListItem ,
226
+ serializeStandardTag < "oListItem" > ( "li" , serializer ?. oListItem ) ,
227
+ ) ,
228
+ list : useSerializerOrDefault < "list" > (
229
+ serializer ?. list ,
230
+ serializeStandardTag < "list" > ( "ul" , serializer ?. list ) ,
231
+ ) ,
232
+ oList : useSerializerOrDefault < "oList" > (
233
+ serializer ?. oList ,
234
+ serializeStandardTag < "oList" > ( "ol" , serializer ?. oList ) ,
235
+ ) ,
236
+ image : useSerializerOrDefault < "image" > (
237
+ serializer ?. image ,
238
+ serializeImage ( linkResolver , serializer ?. image ) ,
239
+ ) ,
240
+ embed : useSerializerOrDefault < "embed" > (
241
+ serializer ?. embed ,
242
+ serializeEmbed ( serializer ?. embed ) ,
243
+ ) ,
244
+ hyperlink : useSerializerOrDefault < "hyperlink" > (
245
+ serializer ?. hyperlink ,
246
+ serializeHyperlink ( linkResolver , serializer ?. hyperlink ) ,
247
+ ) ,
248
+ label : useSerializerOrDefault < "label" > (
249
+ serializer ?. label ,
250
+ serializeStandardTag < "label" > ( "span" , serializer ?. label ) ,
251
+ ) ,
252
+ span : useSerializerOrDefault < "span" > ( serializer ?. span , serializeSpan ( ) ) ,
253
+ } ;
254
+
255
+ return wrapMapSerializerWithStringChildren ( mapSerializer ) ;
171
256
} ;
172
257
173
258
/**
@@ -180,7 +265,7 @@ const createDefaultHTMLRichTextSerializer = (
180
265
* @returns A regular function serializer
181
266
*/
182
267
const wrapMapSerializerWithStringChildren = (
183
- mapSerializer : HTMLRichTextMapSerializer ,
268
+ mapSerializer : HTMLStrictRichTextMapSerializer ,
184
269
) : RichTextFunctionSerializer < string > => {
185
270
const modifiedMapSerializer = { } as RichTextMapSerializer < string > ;
186
271
@@ -292,22 +377,27 @@ export const asHTML: {
292
377
293
378
let serializer : RichTextFunctionSerializer < string > ;
294
379
if ( config . serializer ) {
295
- serializer = composeSerializers (
296
- typeof config . serializer === "object"
297
- ? wrapMapSerializerWithStringChildren ( config . serializer )
298
- : ( type , node , text , children , key ) =>
299
- // TypeScript doesn't narrow the type correctly here since it is now in a callback function, so we have to cast it here.
300
- ( config . serializer as HTMLRichTextFunctionSerializer ) (
301
- type ,
302
- node ,
303
- text ,
304
- children . join ( "" ) ,
305
- key ,
306
- ) ,
307
- createDefaultHTMLRichTextSerializer ( config . linkResolver ) ,
308
- ) ;
380
+ if ( typeof config . serializer === "function" ) {
381
+ serializer = composeSerializers (
382
+ ( type , node , text , children , key ) =>
383
+ // TypeScript doesn't narrow the type correctly here since it is now in a callback function, so we have to cast it here.
384
+ ( config . serializer as HTMLRichTextFunctionSerializer ) (
385
+ type ,
386
+ node ,
387
+ text ,
388
+ children . join ( "" ) ,
389
+ key ,
390
+ ) ,
391
+ createHTMLRichTextSerializer ( config . linkResolver ) ,
392
+ ) ;
393
+ } else {
394
+ serializer = createHTMLRichTextSerializer (
395
+ config . linkResolver ,
396
+ config . serializer ,
397
+ ) ;
398
+ }
309
399
} else {
310
- serializer = createDefaultHTMLRichTextSerializer ( config . linkResolver ) ;
400
+ serializer = createHTMLRichTextSerializer ( config . linkResolver ) ;
311
401
}
312
402
313
403
return serialize ( richTextField , serializer ) . join (
0 commit comments