@datocms/astro 0.1.13 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -38
- package/package.json +63 -50
- package/src/Image/Image.astro +14 -22
- package/src/Image/README.md +124 -0
- package/src/Image/buildSrcSet.ts +9 -16
- package/src/Image/index.ts +3 -1
- package/src/Image/types.ts +2 -2
- package/src/QueryListener/QueryListener.astro +56 -0
- package/src/QueryListener/README.md +67 -0
- package/src/QueryListener/index.ts +4 -0
- package/src/QueryListener/types.ts +12 -0
- package/src/Seo/README.md +57 -0
- package/src/Seo/Seo.astro +2 -2
- package/src/Seo/index.ts +3 -3
- package/src/Seo/renderMetaTagsToString.tsx +1 -3
- package/src/Seo/types.ts +9 -20
- package/src/StructuredText/Node.astro +15 -26
- package/src/StructuredText/README.md +42 -96
- package/src/StructuredText/StructuredText.astro +4 -6
- package/src/StructuredText/index.ts +2 -2
- package/src/StructuredText/nodes/Blockquote.astro +1 -1
- package/src/StructuredText/nodes/Code.astro +3 -3
- package/src/StructuredText/nodes/Heading.astro +1 -1
- package/src/StructuredText/nodes/Link.astro +3 -3
- package/src/StructuredText/nodes/List.astro +2 -2
- package/src/StructuredText/nodes/ListItem.astro +1 -1
- package/src/StructuredText/nodes/Paragraph.astro +1 -1
- package/src/StructuredText/nodes/Root.astro +1 -1
- package/src/StructuredText/nodes/Span.astro +8 -8
- package/src/StructuredText/nodes/ThematicBreak.astro +1 -1
- package/src/StructuredText/types.ts +1 -1
- package/src/StructuredText/utils.ts +71 -73
- package/src/index.ts +4 -0
- package/src/VideoPlayer/VideoPlayer.astro +0 -30
- package/src/VideoPlayer/index.ts +0 -2
- package/src/VideoPlayer/types.ts +0 -72
- package/src/VideoPlayer/utils.ts +0 -50
- package/src/useVideoPlayer/index.ts +0 -55
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Options } from 'datocms-listen';
|
|
2
|
+
|
|
3
|
+
export type QueryListenerOptions<QueryResult, QueryVariables> = Omit<
|
|
4
|
+
Options<QueryResult, QueryVariables>,
|
|
5
|
+
| 'onStatusChange'
|
|
6
|
+
| 'onUpdate'
|
|
7
|
+
| 'onChannelError'
|
|
8
|
+
| 'onError'
|
|
9
|
+
| 'onEvent'
|
|
10
|
+
| 'fetcher'
|
|
11
|
+
| 'eventSourceClass'
|
|
12
|
+
>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Social share, SEO and Favicon meta tags
|
|
2
|
+
|
|
3
|
+
Just like the image component, `<Seo />` is a component specially designed to work seamlessly with DatoCMS’s [`_seoMetaTags` and `faviconMetaTags` GraphQL queries](https://www.datocms.com/docs/content-delivery-api/seo) so that you can handle proper SEO in your pages.
|
|
4
|
+
|
|
5
|
+
You can use `<Seo />` in your pages, and it will inject title, meta and link tags in the document's `<head>` tag.
|
|
6
|
+
|
|
7
|
+
### Table of contents
|
|
8
|
+
|
|
9
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
10
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
11
|
+
|
|
12
|
+
- [Usage](#usage)
|
|
13
|
+
- [Example](#example)
|
|
14
|
+
|
|
15
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
`<Seo />`'s `data` prop takes an array of `Tag`s in the exact form they're returned by the following [DatoCMS GraphQL API](https://www.datocms.com/docs/content-delivery-api/seo) queries:
|
|
20
|
+
|
|
21
|
+
- `_seoMetaTags` query on any record, or
|
|
22
|
+
- `faviconMetaTags` on the global `_site` object.
|
|
23
|
+
|
|
24
|
+
## Example
|
|
25
|
+
|
|
26
|
+
Here is an example:
|
|
27
|
+
|
|
28
|
+
```astro
|
|
29
|
+
---
|
|
30
|
+
import { Seo } from '@datocms/astro/Seo';
|
|
31
|
+
import { executeQuery } from '@datocms/cda-client';
|
|
32
|
+
|
|
33
|
+
const query = gql`
|
|
34
|
+
query {
|
|
35
|
+
page: homepage {
|
|
36
|
+
title
|
|
37
|
+
seo: _seoMetaTags {
|
|
38
|
+
attributes
|
|
39
|
+
content
|
|
40
|
+
tag
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
site: _site {
|
|
44
|
+
favicon: faviconMetaTags {
|
|
45
|
+
attributes
|
|
46
|
+
content
|
|
47
|
+
tag
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const result = await executeQuery(query, { token: '<YOUR-API-TOKEN>' });
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
<Seo data={[...result.page.seo, ...result.site.favicon]} />
|
|
57
|
+
```
|
package/src/Seo/Seo.astro
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { renderMetaTagsToString } from
|
|
3
|
-
import type { SeoOrFaviconTag, TitleMetaLinkTag } from
|
|
2
|
+
import { renderMetaTagsToString } from './renderMetaTagsToString';
|
|
3
|
+
import type { SeoOrFaviconTag, TitleMetaLinkTag } from './types';
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
6
|
data: TitleMetaLinkTag[] | SeoOrFaviconTag[];
|
package/src/Seo/index.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { SeoOrFaviconTag, TitleMetaLinkTag } from './types.js';
|
|
2
2
|
|
|
3
|
-
export function renderMetaTagsToString(
|
|
4
|
-
data: TitleMetaLinkTag[] | SeoOrFaviconTag[],
|
|
5
|
-
): string {
|
|
3
|
+
export function renderMetaTagsToString(data: TitleMetaLinkTag[] | SeoOrFaviconTag[]): string {
|
|
6
4
|
return data
|
|
7
5
|
.map((tag) => {
|
|
8
6
|
if (tag.tag === 'title') {
|
package/src/Seo/types.ts
CHANGED
|
@@ -55,8 +55,7 @@ export type SeoOrFaviconTag = SeoTag | FaviconTag;
|
|
|
55
55
|
export const isSeoTitleTag = (tag: any): tag is SeoTitleTag =>
|
|
56
56
|
'tag' in tag && tag.tag === 'title' && !tag.attributes;
|
|
57
57
|
|
|
58
|
-
export const isSeoTag = (tag: any): tag is SeoTag =>
|
|
59
|
-
isSeoTitleTag(tag) || isSeoMetaTag(tag);
|
|
58
|
+
export const isSeoTag = (tag: any): tag is SeoTag => isSeoTitleTag(tag) || isSeoMetaTag(tag);
|
|
60
59
|
|
|
61
60
|
export const isFaviconAttributes = (tag: any): tag is FaviconAttributes =>
|
|
62
61
|
'sizes' in tag &&
|
|
@@ -68,9 +67,7 @@ export const isFaviconAttributes = (tag: any): tag is FaviconAttributes =>
|
|
|
68
67
|
'href' in tag &&
|
|
69
68
|
typeof tag.href === 'string';
|
|
70
69
|
|
|
71
|
-
export const isAppleTouchIconAttributes = (
|
|
72
|
-
tag: any,
|
|
73
|
-
): tag is AppleTouchIconAttributes =>
|
|
70
|
+
export const isAppleTouchIconAttributes = (tag: any): tag is AppleTouchIconAttributes =>
|
|
74
71
|
'sizes' in tag &&
|
|
75
72
|
typeof tag.sizes === 'string' &&
|
|
76
73
|
'rel' in tag &&
|
|
@@ -82,32 +79,24 @@ export const isSeoLinkTag = (tag: any): tag is SeoLinkTag =>
|
|
|
82
79
|
'tag' in tag &&
|
|
83
80
|
tag.tag === 'link' &&
|
|
84
81
|
!tag.content &&
|
|
85
|
-
(isFaviconAttributes(tag.attributes) ||
|
|
86
|
-
isAppleTouchIconAttributes(tag.attributes));
|
|
82
|
+
(isFaviconAttributes(tag.attributes) || isAppleTouchIconAttributes(tag.attributes));
|
|
87
83
|
|
|
88
|
-
export const isFaviconTag = (tag: any): tag is FaviconTag =>
|
|
89
|
-
isSeoMetaTag(tag) || isSeoLinkTag(tag);
|
|
84
|
+
export const isFaviconTag = (tag: any): tag is FaviconTag => isSeoMetaTag(tag) || isSeoLinkTag(tag);
|
|
90
85
|
|
|
91
86
|
export const isSeoOrFaviconTag = (
|
|
92
87
|
seoOrFaviconTag: TitleMetaLinkTag | SeoOrFaviconTag,
|
|
93
|
-
): seoOrFaviconTag is SeoOrFaviconTag =>
|
|
94
|
-
isSeoTag(seoOrFaviconTag) || isFaviconTag(seoOrFaviconTag);
|
|
88
|
+
): seoOrFaviconTag is SeoOrFaviconTag => isSeoTag(seoOrFaviconTag) || isFaviconTag(seoOrFaviconTag);
|
|
95
89
|
|
|
96
90
|
export const isRegularMetaAttributes = (
|
|
97
91
|
attributes: RegularMetaAttributes | OgMetaAttributes,
|
|
98
|
-
): attributes is RegularMetaAttributes =>
|
|
99
|
-
'name' in attributes && 'content' in attributes;
|
|
92
|
+
): attributes is RegularMetaAttributes => 'name' in attributes && 'content' in attributes;
|
|
100
93
|
|
|
101
94
|
export const isOgMetaAttributes = (
|
|
102
95
|
attributes: RegularMetaAttributes | OgMetaAttributes,
|
|
103
|
-
): attributes is OgMetaAttributes =>
|
|
104
|
-
'property' in attributes && 'content' in attributes;
|
|
96
|
+
): attributes is OgMetaAttributes => 'property' in attributes && 'content' in attributes;
|
|
105
97
|
|
|
106
|
-
export const isSeoMetaTag = (
|
|
107
|
-
seoMetaTag: SeoOrFaviconTag,
|
|
108
|
-
): seoMetaTag is SeoMetaTag =>
|
|
98
|
+
export const isSeoMetaTag = (seoMetaTag: SeoOrFaviconTag): seoMetaTag is SeoMetaTag =>
|
|
109
99
|
'tag' in seoMetaTag &&
|
|
110
100
|
seoMetaTag.tag === 'meta' &&
|
|
111
101
|
!seoMetaTag.content &&
|
|
112
|
-
(isRegularMetaAttributes(seoMetaTag.attributes) ||
|
|
113
|
-
isOgMetaAttributes(seoMetaTag.attributes));
|
|
102
|
+
(isRegularMetaAttributes(seoMetaTag.attributes) || isOgMetaAttributes(seoMetaTag.attributes));
|
|
@@ -9,48 +9,41 @@ import {
|
|
|
9
9
|
isBlock,
|
|
10
10
|
isInlineItem,
|
|
11
11
|
isItemLink,
|
|
12
|
-
} from
|
|
12
|
+
} from 'datocms-structured-text-utils';
|
|
13
13
|
|
|
14
14
|
import {
|
|
15
15
|
defaultComponents,
|
|
16
16
|
throwRenderErrorForMissingBlock,
|
|
17
17
|
throwRenderErrorForMissingComponent,
|
|
18
18
|
throwRenderErrorForMissingLink,
|
|
19
|
-
} from
|
|
19
|
+
} from './utils';
|
|
20
20
|
|
|
21
|
-
import type { PredicateComponentTuple } from
|
|
21
|
+
import type { PredicateComponentTuple } from './types';
|
|
22
22
|
|
|
23
23
|
interface Props {
|
|
24
24
|
node: Node;
|
|
25
|
-
blocks: StructuredText[
|
|
26
|
-
links: StructuredText[
|
|
25
|
+
blocks: StructuredText['blocks'];
|
|
26
|
+
links: StructuredText['links'];
|
|
27
27
|
components: PredicateComponentTuple[];
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const { node, blocks, links, components = [] } = Astro.props;
|
|
31
31
|
|
|
32
|
-
const findBlock = (node: Block, blocks: StructuredText[
|
|
32
|
+
const findBlock = (node: Block, blocks: StructuredText['blocks']) =>
|
|
33
33
|
(blocks || []).find(({ id }) => id === node.item);
|
|
34
34
|
|
|
35
|
-
const findLink = (
|
|
36
|
-
|
|
37
|
-
links: StructuredText["links"]
|
|
38
|
-
) => (links || []).find(({ id }) => id === node.item);
|
|
35
|
+
const findLink = (node: ItemLink | InlineItem, links: StructuredText['links']) =>
|
|
36
|
+
(links || []).find(({ id }) => id === node.item);
|
|
39
37
|
|
|
40
|
-
const block =
|
|
41
|
-
isBlock(node) &&
|
|
42
|
-
(findBlock(node, blocks) || throwRenderErrorForMissingBlock(node));
|
|
38
|
+
const block = isBlock(node) && (findBlock(node, blocks) || throwRenderErrorForMissingBlock(node));
|
|
43
39
|
|
|
44
40
|
const link =
|
|
45
|
-
(isItemLink(node) &&
|
|
46
|
-
|
|
47
|
-
(isInlineItem(node) &&
|
|
48
|
-
(findLink(node, links) || throwRenderErrorForMissingLink(node)));
|
|
41
|
+
(isItemLink(node) && (findLink(node, links) || throwRenderErrorForMissingLink(node))) ||
|
|
42
|
+
(isInlineItem(node) && (findLink(node, links) || throwRenderErrorForMissingLink(node)));
|
|
49
43
|
|
|
50
44
|
const predicateComponentTuple =
|
|
51
|
-
[...components, ...defaultComponents].find(([predicate, component]) =>
|
|
52
|
-
|
|
53
|
-
) || throwRenderErrorForMissingComponent(node);
|
|
45
|
+
[...components, ...defaultComponents].find(([predicate, component]) => predicate(node)) ||
|
|
46
|
+
throwRenderErrorForMissingComponent(node);
|
|
54
47
|
|
|
55
48
|
const Component = (predicateComponentTuple ?? [])[1];
|
|
56
49
|
---
|
|
@@ -65,16 +58,12 @@ const Component = (predicateComponentTuple ?? [])[1];
|
|
|
65
58
|
) : isItemLink(node) ? (
|
|
66
59
|
<Component {node} {link}>
|
|
67
60
|
{hasChildren(node) &&
|
|
68
|
-
node.children.map((child) =>
|
|
69
|
-
<Astro.self node={child} {blocks} {links} {components} />
|
|
70
|
-
))}
|
|
61
|
+
node.children.map((child) => <Astro.self node={child} {blocks} {links} {components} />)}
|
|
71
62
|
</Component>
|
|
72
63
|
) : (
|
|
73
64
|
<Component {node}>
|
|
74
65
|
{hasChildren(node) &&
|
|
75
|
-
node.children.map((child) =>
|
|
76
|
-
<Astro.self node={child} {blocks} {links} {components} />
|
|
77
|
-
))}
|
|
66
|
+
node.children.map((child) => <Astro.self node={child} {blocks} {links} {components} />)}
|
|
78
67
|
</Component>
|
|
79
68
|
))
|
|
80
69
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Structured text
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`<StructuredText />` is an Astro component that you can use to render the value contained inside a DatoCMS [Structured Text field type](https://www.datocms.com/docs/structured-text/dast).
|
|
4
4
|
|
|
5
5
|
### Table of contents
|
|
6
6
|
|
|
7
7
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
8
8
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
- [Setup](#setup)
|
|
11
11
|
- [Basic usage](#basic-usage)
|
|
12
12
|
- [Customization](#customization)
|
|
13
13
|
- [Custom components for blocks](#custom-components-for-blocks)
|
|
@@ -21,19 +21,17 @@
|
|
|
21
21
|
Import the component like this:
|
|
22
22
|
|
|
23
23
|
```js
|
|
24
|
-
import { StructuredText } from '@datocms/
|
|
24
|
+
import { StructuredText } from '@datocms/astro/StructuredText';
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
## Basic usage
|
|
28
28
|
|
|
29
|
-
```
|
|
30
|
-
|
|
29
|
+
```astro
|
|
30
|
+
---
|
|
31
|
+
import { StructuredText } from '@datocms/astro/StructuredText';
|
|
32
|
+
import { executeQuery } from '@datocms/cda-client';
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
import { StructuredText } from '@datocms/svelte';
|
|
35
|
-
|
|
36
|
-
const query = `
|
|
34
|
+
const query = gql`
|
|
37
35
|
query {
|
|
38
36
|
blogPost {
|
|
39
37
|
title
|
|
@@ -44,30 +42,12 @@ const query = `
|
|
|
44
42
|
}
|
|
45
43
|
`;
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
onMount(async () => {
|
|
50
|
-
const response = await fetch('https://graphql.datocms.com/', {
|
|
51
|
-
method: 'POST',
|
|
52
|
-
headers: {
|
|
53
|
-
'Content-Type': 'application/json',
|
|
54
|
-
Authorization: "Bearer AN_API_TOKEN",
|
|
55
|
-
},
|
|
56
|
-
body: JSON.stringify({ query })
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
const json = await response.json()
|
|
60
|
-
|
|
61
|
-
data = json.data;
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
</script>
|
|
45
|
+
const { blogPost } = await executeQuery(query, { token: '<YOUR-API-TOKEN>' });
|
|
46
|
+
---
|
|
65
47
|
|
|
66
48
|
<article>
|
|
67
|
-
{
|
|
68
|
-
|
|
69
|
-
<StructuredText data={data.blogPost.content} />
|
|
70
|
-
{/if}
|
|
49
|
+
<h1>{data.blogPost.title}</h1>
|
|
50
|
+
<StructuredText data={data.blogPost.content} />
|
|
71
51
|
</article>
|
|
72
52
|
```
|
|
73
53
|
|
|
@@ -84,20 +64,16 @@ You need to use custom components in the following cases:
|
|
|
84
64
|
|
|
85
65
|
Here is an example using custom components for blocks, inline and item links. Take a look at the [test fixtures](https://github.com/datocms/datocms-svelte/tree/main/src/lib/components/StructuredText/__tests__/__fixtures__) to see examples on how to implement these components.
|
|
86
66
|
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
import { onMount } from 'svelte';
|
|
91
|
-
|
|
67
|
+
```astro
|
|
68
|
+
---
|
|
92
69
|
import { isBlock, isInlineItem, isItemLink } from 'datocms-structured-text-utils';
|
|
70
|
+
import { StructuredText } from '@datocms/astro/StructuredText';
|
|
93
71
|
|
|
94
|
-
import
|
|
72
|
+
import Block from '~/components/Block/index.astro';
|
|
73
|
+
import InlineItem from '~/components/InlineItem/index.astro';
|
|
74
|
+
import ItemLink from '~/components/ItemLink/index.astro';
|
|
95
75
|
|
|
96
|
-
|
|
97
|
-
import InlineItem from './InlineItem.svelte';
|
|
98
|
-
import ItemLink from './ItemLink.svelte';
|
|
99
|
-
|
|
100
|
-
const query = `
|
|
76
|
+
const query = gql`
|
|
101
77
|
query {
|
|
102
78
|
blogPost {
|
|
103
79
|
title
|
|
@@ -116,9 +92,7 @@ const query = `
|
|
|
116
92
|
... on ImageRecord {
|
|
117
93
|
id
|
|
118
94
|
image {
|
|
119
|
-
responsiveImage(
|
|
120
|
-
imgixParams: { fit: crop, w: 300, h: 300, auto: format }
|
|
121
|
-
) {
|
|
95
|
+
responsiveImage(imgixParams: { fit: crop, w: 300, h: 300, auto: format }) {
|
|
122
96
|
srcSet
|
|
123
97
|
webpSrcSet
|
|
124
98
|
sizes
|
|
@@ -138,37 +112,19 @@ const query = `
|
|
|
138
112
|
}
|
|
139
113
|
`;
|
|
140
114
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
onMount(async () => {
|
|
144
|
-
const response = await fetch('https://graphql.datocms.com/', {
|
|
145
|
-
method: 'POST',
|
|
146
|
-
headers: {
|
|
147
|
-
'Content-Type': 'application/json',
|
|
148
|
-
Authorization: "Bearer AN_API_TOKEN",
|
|
149
|
-
},
|
|
150
|
-
body: JSON.stringify({ query })
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
const json = await response.json()
|
|
154
|
-
|
|
155
|
-
data = json.data;
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
</script>
|
|
115
|
+
const { blogPost } = await executeQuery(query, { token: '<YOUR-API-TOKEN>' });
|
|
116
|
+
---
|
|
159
117
|
|
|
160
118
|
<article>
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
/>
|
|
171
|
-
{/if}
|
|
119
|
+
<h1>{blogPost.title}</h1>
|
|
120
|
+
<StructuredText
|
|
121
|
+
data={blogPost.content}
|
|
122
|
+
components={[
|
|
123
|
+
[isInlineItem, InlineItem],
|
|
124
|
+
[isItemLink, ItemLink],
|
|
125
|
+
[isBlock, Block],
|
|
126
|
+
]}
|
|
127
|
+
/>
|
|
172
128
|
</article>
|
|
173
129
|
```
|
|
174
130
|
|
|
@@ -179,30 +135,20 @@ onMount(async () => {
|
|
|
179
135
|
- For `heading` nodes, you might want to add an anchor;
|
|
180
136
|
- For `code` nodes, you might want to use a custom syntax highlighting component;
|
|
181
137
|
|
|
182
|
-
In this case, you can easily override default rendering rules with the `components` props.
|
|
183
|
-
|
|
184
|
-
```svelte
|
|
185
|
-
<script>
|
|
186
|
-
import { isHeading, isCode } from 'datocms-structured-text-utils';
|
|
187
|
-
|
|
188
|
-
import Heading from './Heading.svelte';
|
|
189
|
-
import Code from './Code.svelte';
|
|
138
|
+
In this case, you can easily override default rendering rules with the `components` props.
|
|
190
139
|
|
|
191
|
-
|
|
192
|
-
|
|
140
|
+
```astro
|
|
141
|
+
---
|
|
142
|
+
import { isHeading } from 'datocms-structured-text-utils';
|
|
143
|
+
import HeadingWithAnchorLink from '~/components/HeadingWithAnchorLink/index.astro';
|
|
144
|
+
---
|
|
193
145
|
|
|
194
|
-
<StructuredText
|
|
195
|
-
data={data.blogPost.content}
|
|
196
|
-
components={[
|
|
197
|
-
[isHeading, Heading],
|
|
198
|
-
[isCode, Code]
|
|
199
|
-
]}
|
|
200
|
-
/>
|
|
146
|
+
<StructuredText data={blogPost.content} components={[[isHeading, HeadingWithAnchorLink]]} />
|
|
201
147
|
```
|
|
202
148
|
|
|
203
149
|
## Props
|
|
204
150
|
|
|
205
|
-
| prop | type
|
|
206
|
-
| ---------- |
|
|
207
|
-
| data | `StructuredText \| DastNode`
|
|
208
|
-
| components | [`PredicateComponentTuple[] \| null`](https://github.com/datocms/datocms
|
|
151
|
+
| prop | type | required | description | default |
|
|
152
|
+
| ---------- | ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------- |
|
|
153
|
+
| data | `StructuredText \| DastNode` | :white_check_mark: | The actual [field value](https://www.datocms.com/docs/structured-text/dast) you get from DatoCMS | |
|
|
154
|
+
| components | [`PredicateComponentTuple[] \| null`](https://github.com/datocms/astro-datocms/blob/main/src/StructuredText/types.ts#L6) | Only required if data contain `block`, `inline_item` or `item_link` nodes | Array of tuples formed by a predicate function and custom component | `[]` |
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
type StructuredText,
|
|
4
4
|
type Document,
|
|
5
5
|
isStructuredText,
|
|
6
|
-
} from
|
|
6
|
+
} from 'datocms-structured-text-utils';
|
|
7
7
|
|
|
8
|
-
import Node from
|
|
9
|
-
import type { PredicateComponentTuple } from
|
|
8
|
+
import Node from './Node.astro';
|
|
9
|
+
import type { PredicateComponentTuple } from './types';
|
|
10
10
|
|
|
11
11
|
interface Props {
|
|
12
12
|
data: StructuredText | Document | null;
|
|
@@ -15,9 +15,7 @@ interface Props {
|
|
|
15
15
|
|
|
16
16
|
const { data, components = [] } = Astro.props;
|
|
17
17
|
|
|
18
|
-
const node =
|
|
19
|
-
data != null &&
|
|
20
|
-
(isStructuredText(data) ? (data.value as Document) : data).document;
|
|
18
|
+
const node = data != null && (isStructuredText(data) ? (data.value as Document) : data).document;
|
|
21
19
|
|
|
22
20
|
const blocks = isStructuredText(data) ? data?.blocks : undefined;
|
|
23
21
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { Code as AstroCode } from
|
|
3
|
-
import type { Code as CodeNode } from
|
|
2
|
+
import { Code as AstroCode } from 'astro:components';
|
|
3
|
+
import type { Code as CodeNode } from 'datocms-structured-text-utils';
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
6
|
// https://www.datocms.com/docs/structured-text/dast#code
|
|
@@ -10,4 +10,4 @@ interface Props {
|
|
|
10
10
|
const { node } = Astro.props;
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
<AstroCode code={node.code} lang={node.language as
|
|
13
|
+
<AstroCode code={node.code} lang={node.language as 'js'} />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type { Link } from
|
|
2
|
+
import type { Link } from 'datocms-structured-text-utils';
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
node: Link;
|
|
@@ -11,7 +11,7 @@ const { url, meta } = node;
|
|
|
11
11
|
|
|
12
12
|
let target: string | undefined = undefined;
|
|
13
13
|
|
|
14
|
-
const targetMetaEntry = meta?.find((metaEntry) => metaEntry.id ===
|
|
14
|
+
const targetMetaEntry = meta?.find((metaEntry) => metaEntry.id === 'target');
|
|
15
15
|
|
|
16
16
|
if (targetMetaEntry?.value) {
|
|
17
17
|
target = targetMetaEntry.value;
|
|
@@ -19,7 +19,7 @@ if (targetMetaEntry?.value) {
|
|
|
19
19
|
|
|
20
20
|
let rel: string | undefined = undefined;
|
|
21
21
|
|
|
22
|
-
const relMetaEntry = meta?.find((metaEntry) => metaEntry.id ===
|
|
22
|
+
const relMetaEntry = meta?.find((metaEntry) => metaEntry.id === 'rel');
|
|
23
23
|
|
|
24
24
|
if (relMetaEntry?.value) {
|
|
25
25
|
rel = relMetaEntry.value;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type { List } from
|
|
2
|
+
import type { List } from 'datocms-structured-text-utils';
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
5
|
node: List;
|
|
@@ -9,7 +9,7 @@ const { node } = Astro.props;
|
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
{
|
|
12
|
-
node.style ===
|
|
12
|
+
node.style === 'numbered' ? (
|
|
13
13
|
<ol>
|
|
14
14
|
<slot />
|
|
15
15
|
</ol>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type { Span } from
|
|
3
|
-
import Lines from
|
|
2
|
+
import type { Span } from 'datocms-structured-text-utils';
|
|
3
|
+
import Lines from '../Lines.astro';
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
6
|
node: Span;
|
|
@@ -16,37 +16,37 @@ const [mark, ...otherMarks] = marks ?? [];
|
|
|
16
16
|
{
|
|
17
17
|
!mark ? (
|
|
18
18
|
<Lines lines={node.value.split(/\n/)} />
|
|
19
|
-
) : mark ===
|
|
19
|
+
) : mark === 'emphasis' ? (
|
|
20
20
|
<em>
|
|
21
21
|
<Astro.self node={{ type, value, marks: otherMarks }}>
|
|
22
22
|
<slot />
|
|
23
23
|
</Astro.self>
|
|
24
24
|
</em>
|
|
25
|
-
) : mark ===
|
|
25
|
+
) : mark === 'highlight' ? (
|
|
26
26
|
<mark>
|
|
27
27
|
<Astro.self node={{ type, value, marks: otherMarks }}>
|
|
28
28
|
<slot />
|
|
29
29
|
</Astro.self>
|
|
30
30
|
</mark>
|
|
31
|
-
) : mark ===
|
|
31
|
+
) : mark === 'strikethrough' ? (
|
|
32
32
|
<del>
|
|
33
33
|
<Astro.self node={{ type, value, marks: otherMarks }}>
|
|
34
34
|
<slot />
|
|
35
35
|
</Astro.self>
|
|
36
36
|
</del>
|
|
37
|
-
) : mark ===
|
|
37
|
+
) : mark === 'strong' ? (
|
|
38
38
|
<strong>
|
|
39
39
|
<Astro.self node={{ type, value, marks: otherMarks }}>
|
|
40
40
|
<slot />
|
|
41
41
|
</Astro.self>
|
|
42
42
|
</strong>
|
|
43
|
-
) : mark ===
|
|
43
|
+
) : mark === 'underline' ? (
|
|
44
44
|
<u>
|
|
45
45
|
<Astro.self node={{ type, value, marks: otherMarks }}>
|
|
46
46
|
<slot />
|
|
47
47
|
</Astro.self>
|
|
48
48
|
</u>
|
|
49
|
-
) : mark ===
|
|
49
|
+
) : mark === 'code' ? (
|
|
50
50
|
<code>
|
|
51
51
|
<Astro.self node={{ type, value, marks: otherMarks }}>
|
|
52
52
|
<slot />
|