Skip to content

Commit 43c1346

Browse files
Introducing RenderFn
This commit adds the new RenderFn type which all renders now are based on. The signature is: RenderFn<DataProps, Config>: JSX.Element No tests were touch to maintain backward compatibility.
1 parent bc647a4 commit 43c1346

File tree

12 files changed

+72
-65
lines changed

12 files changed

+72
-65
lines changed

README.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ Blocks are independent and you can import only a set of them and use them diretl
3434
```jsx
3535
import { Header } from 'editorjs-react-renderer';
3636

37-
const dataHeader = {
38-
"text": "Heading 2",
39-
"level": 2
37+
const dataHeader: HeaderBlockData = {
38+
text: "Heading 2",
39+
level: 2
4040
}
4141

42-
export const Heading () => <Header data={dataHeader} />;
42+
export const Heading () => <Header data={dataHeader} className="text-xl" />;
4343
```
4444

4545
## Internal blocks
@@ -144,17 +144,16 @@ So, in theory, any CSS framework (such as Bootstrap) can work seamlessly with th
144144
You can provide your own custom renderers or replace the default ones by passing a `renderers` object to the `Blocks`.
145145

146146
```tsx
147-
const Checklist = ({
147+
const Checklist: RenderFn<{
148+
items: string[]
149+
}> = ({
148150
data, className = ""
149-
}: {
150-
data: {[s:string]: any}
151-
className?: string
152151
}) => {
153152

154153
return (
155154
<>
156155
{data?.items.map((item, i) => (
157-
<p key={i}>
156+
<p key={i} className={className}>
158157
<label>
159158
<input type="checkbox" /> {HTMLReactParser(item)}
160159
</label>

src/index.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import { create } from 'react-test-renderer';
3-
import Blocks, { DataProp } from '.';
3+
import Blocks, { ConfigProp, DataProp, RenderersProp, RenderFn } from '.';
44

55
describe('<Block />', () => {
66
describe('when receives an EditorJS blocks data', () => {

src/index.tsx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,20 @@ import Paragraph from './renderers/paragraph';
99
import Quote from './renderers/quote';
1010
import Table from './renderers/table';
1111

12-
export interface ConfigProp {
13-
[s: string]: {
14-
[s: string]: any;
15-
};
16-
}
12+
export type ConfigProp = Record<string, RenderConfig>
1713

18-
export interface RenderersProp {
19-
[s: string]: any;
20-
}
14+
export type RenderConfig = Record<string, any>
15+
16+
export type RenderFn<T = undefined, K = Record<string, any> | undefined> = (_: {
17+
data?: T
18+
className?: string
19+
} & K) => JSX.Element;
20+
21+
export type RenderersProp = Record<string, RenderFn<any>>
2122

2223
export interface Block {
2324
type: string;
24-
data: {
25-
[s: string]: any;
26-
};
25+
data: Record<string, any>;
2726
}
2827

2928
export interface DataProp {

src/renderers/code/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import React from 'react';
1+
import React, { FC } from 'react';
2+
import { RenderFn } from '../..';
23

34
export interface CodeBlockData {
45
code: string;
56
lang?: string;
67
}
78

8-
const Code = ({ data, className = '' }: { data: CodeBlockData; className?: string }) => {
9+
const Code: RenderFn<CodeBlockData> = ({ data, className = '' }) => {
910
const props: {
1011
[s: string]: string;
1112
} = {};

src/renderers/delimiter/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
2+
import { RenderFn } from '../..';
23

3-
const Delimiter = ({ className = '' }: { className?: string }) => {
4+
const Delimiter: RenderFn = ({ className = '' }) => {
45
const props: {
56
[s: string]: string;
67
} = {};

src/renderers/embed/index.tsx

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import HTMLReactParser from 'html-react-parser';
3+
import { RenderFn } from '../..';
34

45
export interface EmbedBlockData {
56
service: string;
@@ -10,20 +11,20 @@ export interface EmbedBlockData {
1011
caption?: string;
1112
}
1213

13-
const Embed = ({
14+
export interface EmbedBlockConfig {
15+
rel?: string;
16+
sandbox?: string | null;
17+
}
18+
19+
const Embed: RenderFn<EmbedBlockData, EmbedBlockConfig> = ({
1420
data,
1521
className = '',
1622
rel = 'noreferer nofollower external',
1723
sandbox,
18-
}: {
19-
data: EmbedBlockData;
20-
className?: string;
21-
rel?: string;
22-
sandbox?: string | null;
2324
}) => {
2425
const classNames: string[] = [];
2526
if (className) classNames.push(className);
26-
classNames.push(`embed-block-service-${data.service}`);
27+
classNames.push(`embed-block-service-${data?.service}`);
2728

2829
const figureprops: {
2930
[s: string]: string;
@@ -33,11 +34,11 @@ const Embed = ({
3334
figureprops.className = classNames.join(' ');
3435
}
3536

36-
if (data.width) {
37+
if (data?.width) {
3738
figureprops.width = data.width.toString();
3839
}
3940

40-
if (data.height) {
41+
if (data?.height) {
4142
figureprops.height = data.height.toString();
4243
}
4344

@@ -47,14 +48,14 @@ const Embed = ({
4748

4849
return (
4950
<figure>
50-
{data.embed ? (
51+
{data?.embed ? (
5152
<iframe src={data.embed} {...figureprops} frameBorder="0" data-src={data.source}></iframe>
5253
) : (
53-
<a href={data.source} target="_blank" rel={rel}>
54-
{data.source}
54+
<a href={data?.source} target="_blank" rel={rel}>
55+
{data?.source}
5556
</a>
5657
)}
57-
{data.caption && <figcaption>{HTMLReactParser(data.caption)}</figcaption>}
58+
{data?.caption && <figcaption>{HTMLReactParser(data.caption)}</figcaption>}
5859
</figure>
5960
);
6061
};

src/renderers/header/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import React from 'react';
22
import HTMLReactParser from 'html-react-parser';
3+
import { RenderFn } from '../..';
34

45
export interface HeaderBlockData {
56
text: string;
67
level: number;
78
}
89

9-
const Header = ({ data, className = '' }: { data: HeaderBlockData; className?: string }) => {
10+
const Header: RenderFn<HeaderBlockData> = ({ data, className = '' }) => {
1011
const props: {
1112
[s: string]: string;
1213
} = {};
@@ -15,7 +16,7 @@ const Header = ({ data, className = '' }: { data: HeaderBlockData; className?: s
1516
props.className = className;
1617
}
1718

18-
const Tag = `h${data.level || 1}` as keyof JSX.IntrinsicElements;
19+
const Tag = `h${data?.level || 1}` as keyof JSX.IntrinsicElements;
1920
return <Tag {...props}>{data?.text && HTMLReactParser(data.text)}</Tag>;
2021
};
2122

src/renderers/image/index.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import HTMLReactParser from 'html-react-parser';
3+
import { RenderFn } from '../..';
34

45
export interface ImageBlockData {
56
file: {
@@ -13,26 +14,26 @@ export interface ImageBlockData {
1314
[s: string]: any;
1415
}
1516

16-
const Image = ({
17+
export interface ImageBlockConfig {
18+
actionsClassNames?: {
19+
[s: string]: string;
20+
}
21+
}
22+
23+
const Image: RenderFn<ImageBlockData, ImageBlockConfig> = ({
1724
data,
1825
className = '',
1926
actionsClassNames = {
2027
stretched: 'image-block--stretched',
2128
withBorder: 'image-block--with-border',
2229
withBackground: 'image-block--with-background',
2330
},
24-
}: {
25-
data: ImageBlockData;
26-
className?: string;
27-
actionsClassNames?: {
28-
[s: string]: string;
29-
};
3031
}) => {
3132
const classNames: string[] = [];
3233
if (className) classNames.push(className);
3334

3435
Object.keys(actionsClassNames).forEach((actionName) => {
35-
if (data[actionName] === true && actionName in actionsClassNames) {
36+
if (data && data[actionName] === true && actionName in actionsClassNames) {
3637
// @ts-ignore
3738
classNames.push(actionsClassNames[actionName]);
3839
}
@@ -49,7 +50,7 @@ const Image = ({
4950
return (
5051
<figure {...figureprops}>
5152
{data?.file?.url && <img src={data.file.url} alt={data.caption || data.file.name} />}
52-
{data.caption && <figcaption>{HTMLReactParser(data.caption)}</figcaption>}
53+
{data?.caption && <figcaption>{HTMLReactParser(data.caption)}</figcaption>}
5354
</figure>
5455
);
5556
};

src/renderers/list/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import React from 'react';
22
import HTMLReactParser from 'html-react-parser';
3+
import { RenderFn } from '../..';
34

45
export interface ListBlockData {
56
style: 'ordered' | 'unordered';
67
items: string[];
78
}
89

9-
const List = ({ data, className = '' }: { data: ListBlockData; className?: string }) => {
10+
const List: RenderFn<ListBlockData> = ({ data, className = '' }) => {
1011
const props: {
1112
[s: string]: string;
1213
} = {};

src/renderers/paragraph/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import React from 'react';
22
import HTMLReactParser from 'html-react-parser';
3+
import { RenderFn } from '../..';
34

45
export interface ParagraphBlockData {
56
text: string;
67
}
78

8-
const Paragraph = ({ data, className = '' }: { data: ParagraphBlockData; className?: string }) => {
9+
const Paragraph: RenderFn<ParagraphBlockData> = ({ data, className = '' }) => {
910
const props: {
1011
[s: string]: string;
1112
} = {};

0 commit comments

Comments
 (0)