-
Notifications
You must be signed in to change notification settings - Fork 110
/
index.tsx
127 lines (113 loc) Β· 3.94 KB
/
index.tsx
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
import React, { ReactNode } from 'react';
import { Block, BLOCKS, Document, Inline, INLINES, MARKS, Text } from '@contentful/rich-text-types';
import { nodeToReactComponent } from './util/nodeListToReactComponents';
const defaultNodeRenderers: RenderNode = {
[BLOCKS.DOCUMENT]: (node, children) => children,
[BLOCKS.PARAGRAPH]: (node, children) => <p>{children}</p>,
[BLOCKS.HEADING_1]: (node, children) => <h1>{children}</h1>,
[BLOCKS.HEADING_2]: (node, children) => <h2>{children}</h2>,
[BLOCKS.HEADING_3]: (node, children) => <h3>{children}</h3>,
[BLOCKS.HEADING_4]: (node, children) => <h4>{children}</h4>,
[BLOCKS.HEADING_5]: (node, children) => <h5>{children}</h5>,
[BLOCKS.HEADING_6]: (node, children) => <h6>{children}</h6>,
[BLOCKS.EMBEDDED_ENTRY]: (node, children) => <div>{children}</div>,
[BLOCKS.EMBEDDED_RESOURCE]: (node, children) => <div>{children}</div>,
[BLOCKS.UL_LIST]: (node, children) => <ul>{children}</ul>,
[BLOCKS.OL_LIST]: (node, children) => <ol>{children}</ol>,
[BLOCKS.LIST_ITEM]: (node, children) => <li>{children}</li>,
[BLOCKS.QUOTE]: (node, children) => <blockquote>{children}</blockquote>,
[BLOCKS.HR]: () => <hr />,
[BLOCKS.TABLE]: (node, children) => (
<table>
<tbody>{children}</tbody>
</table>
),
[BLOCKS.TABLE_ROW]: (node, children) => <tr>{children}</tr>,
[BLOCKS.TABLE_HEADER_CELL]: (node, children) => <th>{children}</th>,
[BLOCKS.TABLE_CELL]: (node, children) => <td>{children}</td>,
[INLINES.ASSET_HYPERLINK]: (node) => defaultInline(INLINES.ASSET_HYPERLINK, node as Inline),
[INLINES.ENTRY_HYPERLINK]: (node) => defaultInline(INLINES.ENTRY_HYPERLINK, node as Inline),
[INLINES.RESOURCE_HYPERLINK]: (node) =>
defaultInlineResource(INLINES.RESOURCE_HYPERLINK, node as Inline),
[INLINES.EMBEDDED_ENTRY]: (node) => defaultInline(INLINES.EMBEDDED_ENTRY, node as Inline),
[INLINES.EMBEDDED_RESOURCE]: (node, _children) =>
defaultInlineResource(INLINES.EMBEDDED_RESOURCE, node as Inline),
[INLINES.HYPERLINK]: (node, children) => <a href={node.data.uri}>{children}</a>,
};
const defaultMarkRenderers: RenderMark = {
[MARKS.BOLD]: (text) => <b>{text}</b>,
[MARKS.ITALIC]: (text) => <i>{text}</i>,
[MARKS.UNDERLINE]: (text) => <u>{text}</u>,
[MARKS.CODE]: (text) => <code>{text}</code>,
[MARKS.SUPERSCRIPT]: (text) => <sup>{text}</sup>,
[MARKS.SUBSCRIPT]: (text) => <sub>{text}</sub>,
[MARKS.STRIKETHROUGH]: (text) => <s>{text}</s>,
};
function defaultInline(type: string, node: Inline): ReactNode {
return (
<span key={node.data.target.sys.id}>
type: {node.nodeType} id: {node.data.target.sys.id}
</span>
);
}
function defaultInlineResource(type: string, node: Inline) {
return (
<span key={node.data.target.sys.urn}>
type: {node.nodeType} urn: {node.data.target.sys.urn}
</span>
);
}
export type CommonNode = Text | Block | Inline;
export interface NodeRenderer {
(node: Block | Inline, children: ReactNode): ReactNode;
}
export interface RenderNode {
[k: string]: NodeRenderer;
}
export interface RenderMark {
[k: string]: (text: ReactNode) => ReactNode;
}
export interface RenderText {
(text: string): ReactNode;
}
export interface Options {
/**
* Node renderers
*/
renderNode?: RenderNode;
/**
* Mark renderers
*/
renderMark?: RenderMark;
/**
* Text renderer
*/
renderText?: RenderText;
/**
* Keep line breaks and multiple spaces
*/
preserveWhitespace?: boolean;
}
/**
* Serialize a Contentful Rich Text `document` to React tree
*/
export function documentToReactComponents(
richTextDocument: Document,
options: Options = {},
): ReactNode {
if (!richTextDocument) {
return null;
}
return nodeToReactComponent(richTextDocument, {
renderNode: {
...defaultNodeRenderers,
...options.renderNode,
},
renderMark: {
...defaultMarkRenderers,
...options.renderMark,
},
renderText: options.renderText,
preserveWhitespace: options.preserveWhitespace,
});
}