Skip to content

Commit a6f0c46

Browse files
committed
Inline blocks
1 parent c249509 commit a6f0c46

6 files changed

Lines changed: 93 additions & 42 deletions

File tree

docs/structured-text.md

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ const Page = ({ data }) => {
120120
// },
121121
// ]
122122
// },
123-
// { type: "span", value: " in our team!" },
123+
// { type: "span", value: " in our team! We call him " },
124+
// { type: "block", item: "1984560" }
124125
// ]
125126
// },
126127
// { type: "block", item: "1984559" }
@@ -137,12 +138,19 @@ const Page = ({ data }) => {
137138
// ],
138139
// blocks: [
139140
// {
140-
// id: "324321",
141+
// id: "1984559",
141142
// __typename: "CtaRecord",
142143
// title: "Call to action",
143144
// url: "https://google.com"
144145
// },
145146
// ],
147+
// inlineBlocks: [
148+
// {
149+
// id: "1984560",
150+
// __typename: "MentionRecord",
151+
// username: "steffoz",
152+
// },
153+
// ],
146154
// }
147155

148156
return (
@@ -182,12 +190,24 @@ const Page = ({ data }) => {
182190
return null;
183191
}
184192
}}
193+
renderInlineBlock={({ record }) => {
194+
switch (record.__typename) {
195+
case 'MentionRecord':
196+
return (
197+
<code>
198+
@{record.username}
199+
</code>
200+
);
201+
default:
202+
return null;
203+
}
204+
}}
185205
/>
186206
{/*
187207
Final result:
188208
189209
<h1>Welcome onboard <a href="/team/mark-smith">Mark</a></h1>
190-
<p>So happy to have <a href="/team/mark-smith">this awesome humang being</a> in our team!</p>
210+
<p>So happy to have <a href="/team/mark-smith">this awesome humang being</a> in our team! We call him <code>@steffoz</code></p>
191211
<img src="https://www.datocms-assets.com/205/1597757278-austin-distel-wd1lrb9oeeo-unsplash.jpg" alt="Our team at work" />
192212
*/}
193213
</div>
@@ -220,6 +240,15 @@ const query = gql`
220240
url
221241
}
222242
}
243+
inlineBlocks {
244+
... on RecordInterface {
245+
id
246+
__typename
247+
}
248+
... on MentionRecord {
249+
username
250+
}
251+
}
223252
}
224253
}
225254
}
@@ -230,7 +259,7 @@ export default withQuery(query)(Page);
230259

231260
## Override default rendering of nodes
232261

233-
This component automatically renders all nodes except for `inline_item`, `item_link` and `block` using a set of default rules, but you might want to customize those. For example:
262+
This component automatically renders all nodes (except for `inline_item`, `item_link`, `block` and `inline_block`) using a set of default rules, but you might want to customize those. For example:
234263

235264
For example:
236265

@@ -309,17 +338,18 @@ import SyntaxHighlight from 'components/SyntaxHighlight';
309338
/>;
310339
```
311340

312-
Note: if you override the rules for `inline_item`, `item_link` or `block` nodes, then the `renderInlineRecord`, `renderLinkToRecord` and `renderBlock` props won't be considered!
341+
Note: if you override the rules for `inline_item`, `item_link`, `block` or `inline_block` nodes, then the `renderInlineRecord`, `renderLinkToRecord`, `renderBlock` and `renderInlineBlock` props won't be considered!
313342

314343
## Props
315344

316-
| prop | type | required | description | default |
317-
| ------------------ | --------------------------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
318-
| data | `StructuredTextGraphQlResponse \| DastNode` | :white_check_mark: | The actual [field value](https://www.datocms.com/docs/structured-text/dast) you get from DatoCMS | |
319-
| renderInlineRecord | `({ record }) => ReactElement \| null` | Only required if document contains `inlineItem` nodes | Convert an `inlineItem` DAST node into React | `[]` |
320-
| renderLinkToRecord | `({ record, children }) => ReactElement \| null` | Only required if document contains `itemLink` nodes | Convert an `itemLink` DAST node into React | `null` |
321-
| renderBlock | `({ record }) => ReactElement \| null` | Only required if document contains `block` nodes | Convert a `block` DAST node into React | `null` |
322-
| metaTransformer | `({ node, meta }) => Object \| null` | :x: | Transform `link` and `itemLink` meta property into HTML props | [See function](https://github.com/datocms/structured-text/blob/main/packages/generic-html-renderer/src/index.ts#L61) |
323-
| customNodeRules | `Array<RenderRule>` | :x: | Customize how nodes are converted in JSX (use `renderNodeRule()` to generate rules) | `null` |
324-
| customMarkRules | `Array<RenderMarkRule>` | :x: | Customize how marks are converted in JSX (use `renderMarkRule()` to generate rules) | `null` |
325-
| renderText | `(text: string, key: string) => ReactElement \| string \| null` | :x: | Convert a simple string text into React | `(text) => text` |
345+
| prop | type | required | description | default |
346+
| ------------------ | --------------------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
347+
| data | `StructuredTextGraphQlResponse \| DastNode` | :white_check_mark: | The actual [field value](https://www.datocms.com/docs/structured-text/dast) you get from DatoCMS | |
348+
| renderInlineRecord | `({ record }) => ReactElement \| null` | Only required if document contains `inline_item` nodes | Convert an `inlineItem` DAST node into React | `[]` |
349+
| renderLinkToRecord | `({ record, children }) => ReactElement \| null` | Only required if document contains `item_link` nodes | Convert an `itemLink` DAST node into React | `null` |
350+
| renderBlock | `({ record }) => ReactElement \| null` | Only required if document contains `block` nodes | Convert a `block` DAST node into React | `null` |
351+
| renderInlineBlock | `({ record }) => ReactElement \| null` | Only required if document contains `inline_block` nodes | Convert a `block` DAST node into React | `null` |
352+
| metaTransformer | `({ node, meta }) => Object \| null` | :x: | Transform `link` and `itemLink` meta property into HTML props | [See function](https://github.com/datocms/structured-text/blob/main/packages/generic-html-renderer/src/index.ts#L61) |
353+
| customNodeRules | `Array<RenderRule>` | :x: | Customize how nodes are converted in JSX (use `renderNodeRule()` to generate rules) | `null` |
354+
| customMarkRules | `Array<RenderMarkRule>` | :x: | Customize how marks are converted in JSX (use `renderMarkRule()` to generate rules) | `null` |
355+
| renderText | `(text: string, key: string) => ReactElement \| string \| null` | :x: | Convert a simple string text into React | `(text) => text` |

package-lock.json

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@
135135
"dependencies": {
136136
"@mux/mux-player-react": "*",
137137
"datocms-listen": "^0.1.9",
138-
"datocms-structured-text-generic-html-renderer": "^4.1.2",
139-
"datocms-structured-text-utils": "^4.1.2",
138+
"datocms-structured-text-generic-html-renderer": "^5.0.0",
139+
"datocms-structured-text-utils": "^5.0.0",
140140
"react-intersection-observer": "^9.4.3",
141141
"react-string-replace": "^1.1.0",
142142
"use-deep-compare-effect": "^1.6.1"

src/StructuredText/__tests__/__snapshots__/index.test.tsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,8 @@ exports[`StructuredText with links/blocks with default rules renders the documen
224224
"id": "456",
225225
"quote": "Foo bar.",
226226
},
227+
],
228+
"inlineBlocks": [
227229
{
228230
"__typename": "MentionRecord",
229231
"id": "789",

src/StructuredText/__tests__/index.test.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,9 @@ describe('StructuredText', () => {
150150
};
151151

152152
const structuredText: StructuredTextGraphQlResponse<
153-
QuoteRecord | MentionRecord,
154-
DocPageRecord
153+
QuoteRecord,
154+
DocPageRecord,
155+
MentionRecord
155156
> = {
156157
value: {
157158
schema: 'dast',
@@ -201,6 +202,8 @@ describe('StructuredText', () => {
201202
quote: 'Foo bar.',
202203
author: 'Mark Smith',
203204
},
205+
],
206+
inlineBlocks: [
204207
{
205208
id: '789',
206209
__typename: 'MentionRecord',

src/StructuredText/index.tsx

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,16 @@ export type RenderBlockContext<R extends StructuredTextGraphQlResponseRecord> =
8181
};
8282

8383
export type StructuredTextPropTypes<
84-
R1 extends StructuredTextGraphQlResponseRecord,
85-
R2 extends StructuredTextGraphQlResponseRecord = R1,
84+
BlockRecord extends
85+
StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
86+
LinkRecord extends
87+
StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
88+
InlineBlockRecord extends
89+
StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
8690
> = {
8791
/** The actual field value you get from DatoCMS **/
8892
data:
89-
| StructuredTextGraphQlResponse<R1, R2>
93+
| StructuredTextGraphQlResponse<BlockRecord, LinkRecord, InlineBlockRecord>
9094
| StructuredTextDocument
9195
| Node
9296
| null
@@ -97,16 +101,20 @@ export type StructuredTextPropTypes<
97101
customMarkRules?: RenderMarkRule<H, T, F>[];
98102
/** Fuction that converts an 'inlineItem' node into React **/
99103
renderInlineRecord?: (
100-
context: RenderInlineRecordContext<R2>,
104+
context: RenderInlineRecordContext<LinkRecord>,
101105
) => ReactElement | null;
102106
/** Fuction that converts an 'itemLink' node into React **/
103107
renderLinkToRecord?: (
104-
context: RenderRecordLinkContext<R2>,
108+
context: RenderRecordLinkContext<LinkRecord>,
105109
) => ReactElement | null;
106110
/** Fuction that converts a 'block' node into React **/
107-
renderBlock?: (context: RenderBlockContext<R1>) => ReactElement | null;
111+
renderBlock?: (
112+
context: RenderBlockContext<BlockRecord>,
113+
) => ReactElement | null;
108114
/** Fuction that converts an 'inlineBlock' node into React **/
109-
renderInlineBlock?: (context: RenderBlockContext<R1>) => ReactElement | null;
115+
renderInlineBlock?: (
116+
context: RenderBlockContext<InlineBlockRecord>,
117+
) => ReactElement | null;
110118
/** Function that converts 'link' and 'itemLink' `meta` into HTML props */
111119
metaTransformer?: TransformMetaFn;
112120
/** Fuction that converts a simple string text into React **/
@@ -120,8 +128,12 @@ export type StructuredTextPropTypes<
120128
};
121129

122130
export function StructuredText<
123-
R1 extends StructuredTextGraphQlResponseRecord,
124-
R2 extends StructuredTextGraphQlResponseRecord = R1,
131+
BlockRecord extends
132+
StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
133+
LinkRecord extends
134+
StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
135+
InlineBlockRecord extends
136+
StructuredTextGraphQlResponseRecord = StructuredTextGraphQlResponseRecord,
125137
>({
126138
data,
127139
renderInlineRecord,
@@ -135,7 +147,11 @@ export function StructuredText<
135147
customRules,
136148
customNodeRules,
137149
metaTransformer,
138-
}: StructuredTextPropTypes<R1, R2>): ReactElement | null {
150+
}: StructuredTextPropTypes<
151+
BlockRecord,
152+
LinkRecord,
153+
InlineBlockRecord
154+
>): ReactElement | null {
139155
const result = render(data, {
140156
adapter: {
141157
renderText: renderText || defaultAdapter.renderText,
@@ -246,18 +262,18 @@ export function StructuredText<
246262
);
247263
}
248264

249-
if (!(isStructuredText(data) && data.blocks)) {
265+
if (!(isStructuredText(data) && data.inlineBlocks)) {
250266
throw new RenderError(
251-
`The document contains an 'inlineBlock' node, but the passed data prop is not a Structured Text GraphQL response, or data.blocks is not present!`,
267+
`The document contains an 'inlineBlock' node, but the passed data prop is not a Structured Text GraphQL response, or data.inlineBlocks is not present!`,
252268
node,
253269
);
254270
}
255271

256-
const item = data.blocks.find((item) => item.id === node.item);
272+
const item = data.inlineBlocks.find((item) => item.id === node.item);
257273

258274
if (!item) {
259275
throw new RenderError(
260-
`The Structured Text document contains an 'inlineBlock' node, but cannot find a record with ID ${node.item} inside data.blocks!`,
276+
`The Structured Text document contains an 'inlineBlock' node, but cannot find a record with ID ${node.item} inside data.inlineBlocks!`,
261277
node,
262278
);
263279
}

0 commit comments

Comments
 (0)