@datocms/astro 0.4.1 → 0.5.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 CHANGED
@@ -44,27 +44,44 @@ npm install @datocms/astro
44
44
 
45
45
  # What is DatoCMS?
46
46
 
47
- <a href="https://www.datocms.com/"><img src="https://www.datocms.com/images/full_logo.svg" height="60"></a>
47
+ <a href="https://www.datocms.com/"><img src="https://www.datocms.com/images/full_logo.svg" height="60" alt="DatoCMS - The Headless CMS for the Modern Web"></a>
48
48
 
49
49
  [DatoCMS](https://www.datocms.com/) is the REST & GraphQL Headless CMS for the modern web.
50
50
 
51
- Trusted by over 25,000 enterprise businesses, agency partners, and individuals across the world, DatoCMS users create online content at scale from a central hub and distribute it via API. We ❤️ our [developers](https://www.datocms.com/team/best-cms-for-developers), [content editors](https://www.datocms.com/team/content-creators) and [marketers](https://www.datocms.com/team/cms-digital-marketing)!
51
+ Trusted by over 25,000 enterprise businesses, agencies, and individuals across the world, DatoCMS users create online content at scale from a central hub and distribute it via API. We ❤️ our [developers](https://www.datocms.com/team/best-cms-for-developers), [content editors](https://www.datocms.com/team/content-creators) and [marketers](https://www.datocms.com/team/cms-digital-marketing)!
52
+
53
+ **Why DatoCMS?**
54
+
55
+ - **API-First Architecture**: Built for both REST and GraphQL, enabling flexible content delivery
56
+ - **Just Enough Features**: We believe in keeping things simple, and giving you [the right feature-set tools](https://www.datocms.com/features) to get the job done
57
+ - **Developer Experience**: First-class TypeScript support with powerful developer tools
58
+
59
+ **Getting Started:**
60
+
61
+ - ⚡️ [Create Free Account](https://dashboard.datocms.com/signup) - Get started with DatoCMS in minutes
62
+ - 🔖 [Documentation](https://www.datocms.com/docs) - Comprehensive guides and API references
63
+ - ⚙️ [Community Support](https://community.datocms.com/) - Get help from our team and community
64
+ - 🆕 [Changelog](https://www.datocms.com/product-updates) - Latest features and improvements
65
+
66
+ **Official Libraries:**
67
+
68
+ - [**Content Delivery Client**](https://github.com/datocms/cda-client) - TypeScript GraphQL client for content fetching
69
+ - [**REST API Clients**](https://github.com/datocms/js-rest-api-clients) - Node.js/Browser clients for content management
70
+ - [**CLI Tools**](https://github.com/datocms/cli) - Command-line utilities for schema migrations (includes [Contentful](https://github.com/datocms/cli/tree/main/packages/cli-plugin-contentful) and [WordPress](https://github.com/datocms/cli/tree/main/packages/cli-plugin-wordpress) importers)
52
71
 
53
- **Quick links:**
72
+ **Official Framework Integrations**
54
73
 
55
- - ⚡️ Get started with a [free DatoCMS account](https://dashboard.datocms.com/signup)
56
- - 🔖 Go through the [docs](https://www.datocms.com/docs)
57
- - ⚙️ Get [support from us and the community](https://community.datocms.com/)
58
- - 🆕 Stay up to date on new features and fixes on the [changelog](https://www.datocms.com/product-updates)
74
+ Helpers to manage SEO, images, video and Structured Text coming from your DatoCMS projects:
59
75
 
60
- **Our featured repos:**
76
+ - [**React Components**](https://github.com/datocms/react-datocms)
77
+ - [**Vue Components**](https://github.com/datocms/vue-datocms)
78
+ - [**Svelte Components**](https://github.com/datocms/datocms-svelte)
79
+ - [**Astro Components**](https://github.com/datocms/astro-datocms)
61
80
 
62
- - [datocms/react-datocms](https://github.com/datocms/react-datocms): React helper components for images, Structured Text rendering, and more
63
- - [datocms/js-rest-api-clients](https://github.com/datocms/js-rest-api-clients): Node and browser JavaScript clients for updating and administering your content. For frontend fetches, we recommend using our [GraphQL Content Delivery API](https://www.datocms.com/docs/content-delivery-api) instead.
64
- - [datocms/cli](https://github.com/datocms/cli): Command-line interface that includes our [Contentful importer](https://github.com/datocms/cli/tree/main/packages/cli-plugin-contentful) and [Wordpress importer](https://github.com/datocms/cli/tree/main/packages/cli-plugin-wordpress)
65
- - [datocms/plugins](https://github.com/datocms/plugins): Example plugins we've made that extend the editor/admin dashboard
66
- - [DatoCMS Starters](https://www.datocms.com/marketplace/starters) has examples for various Javascript frontend frameworks
81
+ **Additional Resources:**
67
82
 
68
- Or see [all our public repos](https://github.com/orgs/datocms/repositories?q=&type=public&language=&sort=stargazers)
83
+ - [**Plugin Examples**](https://github.com/datocms/plugins) - Example plugins we've made that extend the editor/admin dashboard
84
+ - [**Starter Projects**](https://www.datocms.com/marketplace/starters) - Example website implementations for popular frameworks
85
+ - [**All Public Repositories**](https://github.com/orgs/datocms/repositories?q=&type=public&language=&sort=stargazers)
69
86
 
70
87
  <!--datocms-autoinclude-footer end-->
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@datocms/astro",
3
3
  "description": "A set of components and utilities to work faster with DatoCMS in Astro projects.",
4
4
  "type": "module",
5
- "version": "0.4.1",
5
+ "version": "0.5.1",
6
6
  "sideEffects": false,
7
7
  "repository": {
8
8
  "type": "git",
@@ -45,8 +45,8 @@
45
45
  "dependencies": {
46
46
  "@0no-co/graphql.web": "^1.0.7",
47
47
  "datocms-listen": "^1.0.1",
48
- "datocms-structured-text-generic-html-renderer": "^4.0.1",
49
- "datocms-structured-text-utils": "^4.0.1"
48
+ "datocms-structured-text-generic-html-renderer": "^4.1.2",
49
+ "datocms-structured-text-utils": "^4.1.2"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "astro": "*"
@@ -14,6 +14,7 @@ const {
14
14
  usePlaceholder = true,
15
15
  sizes,
16
16
  srcSetCandidates = [0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4],
17
+ referrerPolicy = 'strict-origin',
17
18
  } = Astro.props;
18
19
 
19
20
  const placeholderStyle =
@@ -59,6 +60,7 @@ const sizingStyle = {
59
60
  title={data.title ?? null}
60
61
  fetchpriority={priority ? 'high' : undefined}
61
62
  loading={priority ? undefined : 'lazy'}
63
+ referrerpolicy={referrerPolicy}
62
64
  class={imgClass}
63
65
  style={{
64
66
  ...placeholderStyle,
@@ -122,3 +122,4 @@ Here's a complete recap of what `responsiveImage` offers:
122
122
  | sizes | string | undefined | :x: | The HTML5 [`sizes`](https://web.dev/learn/design/responsive-images/#sizes) attribute for the image (will be used `data.sizes` as a fallback) |
123
123
  | usePlaceholder | Boolean | true | :x: | Whether the image should use a blurred image placeholder |
124
124
  | srcSetCandidates | Array<number> | [0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4] | :x: | If `data` does not contain `srcSet`, the candidates for the `srcset` attribute of the image will be auto-generated based on these width multipliers |
125
+ | referrerPolicy | string | `strict-origin` | :x: | Defines which referrer is sent when fetching the image. Defaults to `strict-origin` to give more useful stats in DatoCMS Project Usages |
@@ -63,4 +63,11 @@ export type ImageProps = {
63
63
  * Default candidate multipliers are [0.25, 0.5, 0.75, 1, 1.5, 2, 3, 4]
64
64
  **/
65
65
  srcSetCandidates?: number[];
66
+ /**
67
+ * Defines which referrer is sent when fetching the image
68
+ * Read more: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#referrerpolicy
69
+ *
70
+ * Defaults to `strict-origin` to give more useful stats in DatoCMS Project Usages
71
+ **/
72
+ referrerPolicy?: JSX.HTMLAttributeReferrerPolicy;
66
73
  };
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  import {
3
3
  type Block,
4
+ type InlineBlock,
4
5
  type Record as DatocmsRecord,
5
6
  type InlineItem,
6
7
  type ItemLink,
7
8
  type Node as DastNode,
8
9
  hasChildren,
9
10
  isBlock,
11
+ isInlineBlock,
10
12
  isInlineItem,
11
13
  isItemLink,
12
14
  RenderError,
@@ -25,11 +27,13 @@ import Root from './nodes/Root.astro';
25
27
  import Span from './nodes/Span.astro';
26
28
  import ThematicBreak from './nodes/ThematicBreak.astro';
27
29
  import BlockComponent from './nodes/Block.astro';
30
+ import InlineBlockComponent from './nodes/InlineBlock.astro';
28
31
  import InlineItemComponent from './nodes/InlineItem.astro';
29
32
  import ItemLinkComponent from './nodes/ItemLink.astro';
30
33
 
31
34
  import type {
32
35
  BlockComponents,
36
+ InlineBlockComponents,
33
37
  InlineRecordComponents,
34
38
  LinkToRecordComponents,
35
39
  NodeOverrides,
@@ -44,6 +48,7 @@ interface Props {
44
48
  links?: DatocmsRecord[];
45
49
 
46
50
  blockComponents?: BlockComponents<DatocmsRecord, DatocmsRecord>;
51
+ inlineBlockComponents?: InlineBlockComponents<DatocmsRecord, DatocmsRecord>;
47
52
  linkToRecordComponents?: LinkToRecordComponents<DatocmsRecord, DatocmsRecord>;
48
53
  inlineRecordComponents?: InlineRecordComponents<DatocmsRecord, DatocmsRecord>;
49
54
 
@@ -57,18 +62,19 @@ const {
57
62
  blocks,
58
63
  links,
59
64
  blockComponents,
65
+ inlineBlockComponents,
60
66
  linkToRecordComponents,
61
67
  inlineRecordComponents,
62
68
  nodeOverrides,
63
69
  markOverrides,
64
70
  } = rest;
65
71
 
66
- function findRecordInBlocks(node: Block) {
72
+ function findRecordInBlocks(node: Block | InlineBlock) {
67
73
  const record = (blocks || []).find(({ id }) => id === node.item);
68
74
 
69
75
  if (!record) {
70
76
  throw new RenderError(
71
- `The Structured Text document contains a 'block' node, but cannot find a record with ID ${node.item} inside data.blocks!`,
77
+ `The Structured Text document contains a '${node.type}' node, but cannot find a record with ID ${node.item} inside data.blocks!`,
72
78
  node,
73
79
  );
74
80
  }
@@ -103,6 +109,7 @@ const defaultComponents: NodeOverrides = {
103
109
  itemLink: ItemLinkComponent,
104
110
  inlineItem: InlineItemComponent,
105
111
  block: BlockComponent,
112
+ inlineBlock: InlineBlockComponent,
106
113
  };
107
114
 
108
115
  const otherNodeComponents: Record<NodeType, AstroComponent> = {
@@ -117,6 +124,8 @@ const Component = otherNodeComponents[node.type] as AstroComponent;
117
124
  {
118
125
  isBlock(node) ? (
119
126
  <Component {node} block={findRecordInBlocks(node)} {blockComponents} />
127
+ ) : isInlineBlock(node) ? (
128
+ <Component {node} block={findRecordInBlocks(node)} {inlineBlockComponents} />
120
129
  ) : isInlineItem(node) ? (
121
130
  <Component {node} record={findRecordInLinks(node)} {inlineRecordComponents} />
122
131
  ) : isItemLink(node) ? (
@@ -10,8 +10,9 @@
10
10
  - [Setup](#setup)
11
11
  - [Basic usage](#basic-usage)
12
12
  - [Customization](#customization)
13
- - [Custom components for blocks, inline records or links to records](#custom-components-for-blocks-inline-records-or-links-to-records)
13
+ - [Custom components for blocks, inline blocks, inline records or links to records](#custom-components-for-blocks-inline-blocks-inline-records-or-links-to-records)
14
14
  - [Override default rendering of nodes](#override-default-rendering-of-nodes)
15
+ - [Strict props type checking](#strict-props-type-checking)
15
16
  - [Props](#props)
16
17
 
17
18
  <!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -60,9 +61,10 @@ You need to use custom components in the following cases:
60
61
  - you have to render blocks, inline records or links to records: there's no conventional way of rendering theses nodes, so you must create and pass custom components;
61
62
  - you need to render a conventional node differently (e.g. you may want a custom render for blockquotes)
62
63
 
63
- ### Custom components for blocks, inline records or links to records
64
+ ### Custom components for blocks, inline blocks, inline records or links to records
64
65
 
65
66
  - Astro components passed in `blockComponents` will be used to render blocks and will receive a `block` prop containing the actual block data.
67
+ - Astro components passed in `inlineBlockComponents` will be used to render inline blocks and will receive a `block` prop containing the actual block data.
66
68
  - Astro components passed in `inlineRecordComponents` will be used to render inline records and will receive a `record` prop containing the actual record.
67
69
  - Astro components passed in `linkToRecordComponents` will be used to render links to records and will receive the following props: `node` (the actual `'inlineItem'` node), `record` (the record linked to the node), and `attrs` (the custom attributes for the link specified by the node).
68
70
 
@@ -129,7 +131,7 @@ const { blogPost } = await executeQuery(query, { token: '<YOUR-API-TOKEN>' });
129
131
  TeamMemberRecord: LinkToTeamMember,
130
132
  }}
131
133
  />
132
- </article>
134
+ </article>gql.tada
133
135
  ```
134
136
 
135
137
  ### Override default rendering of nodes
@@ -143,6 +145,7 @@ In this case, you can easily override default rendering rules with the `nodeOver
143
145
 
144
146
  ```astro
145
147
  ---
148
+ import { StructuredText } from '@datocms/astro/StructuredText';
146
149
  import { isHeading } from 'datocms-structured-text-utils';
147
150
  import HeadingWithAnchorLink from '~/components/HeadingWithAnchorLink/index.astro';
148
151
  import Code from '~/components/Code/index.astro';
@@ -157,13 +160,42 @@ import Code from '~/components/Code/index.astro';
157
160
  />
158
161
  ```
159
162
 
163
+ ### Strict props type checking
164
+
165
+ Since [Astro doesn't support generics-typed components](https://github.com/withastro/roadmap/discussions/601) yet, you can use `ensureValidStructuredTextProps()` to strictly validate that all possible block and linked record types are managed in your `blockComponents`, `inlineRecordComponents` and `linkToRecordComponents` props.
166
+
167
+ This is especially useful when working with tools like [gql.tada](https://gql-tada.0no.co/) that provide precise typing for your `data`:
168
+
169
+ ```astro
170
+ ---
171
+ import { StructuredText, ensureValidStructuredTextProps } from '@datocms/astro/StructuredText';
172
+ ---
173
+
174
+ <StructuredText
175
+ {...ensureValidStructuredTextProps({
176
+ data: blogPost.content,
177
+ blockComponents: {
178
+ CtaRecord: Cta,
179
+ NewsletterSignupRecord: NewsletterSignup,
180
+ },
181
+ inlineRecordComponents: {
182
+ TeamMemberRecord: InlineTeamMember,
183
+ },
184
+ linkToRecordComponents: {
185
+ TeamMemberRecord: LinkToTeamMember,
186
+ },
187
+ })}
188
+ />
189
+ ```
190
+
160
191
  ## Props
161
192
 
162
- | prop | type | required | description |
163
- | ---------------------- | -------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
164
- | data | `StructuredText \| DastNode` | :white_check_mark: | The actual [field value](https://www.datocms.com/docs/structured-text/dast) you get from DatoCMS |
165
- | blockComponents | `Record<string, AstroComponent>` | | An object in which the keys are the `__typename` of the blocks to be rendered, and the values are the Astro components |
166
- | linkToRecordComponents | `Record<string, AstroComponent>` | | An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components |
167
- | inlineRecordComponents | `Record<string, AstroComponent>` | | An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components |
168
- | nodeOverrides | `Record<string, AstroComponent>` | | An object in which the keys are the types of DAST nodes to override, and the values are the Astro components |
169
- | markOverrides | `Record<string, AstroComponent>` | | An object in which the keys are the types of `span` node marks to override, and the values are the Astro components |
193
+ | prop | type | required | description |
194
+ | ---------------------- | -------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
195
+ | data | `StructuredText \| DastNode` | :white_check_mark: | The actual [field value](https://www.datocms.com/docs/structured-text/dast) you get from DatoCMS |
196
+ | blockComponents | `Record<string, AstroComponent>` | | An object in which the keys are the `__typename` of the blocks to be rendered, and the values are the Astro components |
197
+ | inlineBlockComponents | `Record<string, AstroComponent>` | | An object in which the keys are the `__typename` of the inline blocks to be rendered, and the values are the Astro components |
198
+ | linkToRecordComponents | `Record<string, AstroComponent>` | | An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components |
199
+ | inlineRecordComponents | `Record<string, AstroComponent>` | | An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components |
200
+ | nodeOverrides | `Record<string, AstroComponent>` | | An object in which the keys are the types of DAST nodes to override, and the values are the Astro components |
201
+ | markOverrides | `Record<string, AstroComponent>` | | An object in which the keys are the types of `span` node marks to override, and the values are the Astro components |
@@ -26,6 +26,8 @@ interface Props {
26
26
 
27
27
  /** An object in which the keys are the `__typename` of the blocks to be rendered, and the values are the Astro components */
28
28
  blockComponents?: Record<string, AstroComponent>;
29
+ /** An object in which the keys are the `__typename` of the inline blocks to be rendered, and the values are the Astro components */
30
+ inlineBlockComponents?: Record<string, AstroComponent>;
29
31
  /** An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components */
30
32
  linkToRecordComponents?: Record<string, AstroComponent>;
31
33
  /** An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components */
@@ -4,13 +4,19 @@ import {
4
4
  type Document,
5
5
  type StructuredText,
6
6
  } from 'datocms-structured-text-utils';
7
- import type { BlockComponents, InlineRecordComponents, LinkToRecordComponents } from './types';
7
+ import type {
8
+ BlockComponents,
9
+ InlineBlockComponents,
10
+ InlineRecordComponents,
11
+ LinkToRecordComponents,
12
+ } from './types';
8
13
 
9
14
  type Props<R1 extends DatocmsRecord, R2 extends DatocmsRecord> =
10
15
  | {
11
16
  /** The actual [field value](https://www.datocms.com/docs/structured-text/dast) you get from a DatoCMS Structured Text field */
12
17
  data: Document | DastNode | null | undefined;
13
18
  blockComponents?: never;
19
+ inlineBlockComponents?: never;
14
20
  linkToRecordComponents?: never;
15
21
  inlineRecordComponents?: never;
16
22
  }
@@ -22,6 +28,8 @@ type Props<R1 extends DatocmsRecord, R2 extends DatocmsRecord> =
22
28
  | undefined;
23
29
  /** An object in which the keys are the `__typename` of the blocks to be rendered, and the values are the Astro components */
24
30
  blockComponents: BlockComponents<R1, R2>;
31
+ /** An object in which the keys are the `__typename` of the inline blocks to be rendered, and the values are the Astro components */
32
+ inlineBlockComponents: BlockComponents<R1, R2>;
25
33
  /** An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components */
26
34
  linkToRecordComponents: LinkToRecordComponents<R1, R2>;
27
35
  /** An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components */
@@ -35,6 +43,7 @@ type Props<R1 extends DatocmsRecord, R2 extends DatocmsRecord> =
35
43
  | undefined;
36
44
  /** An object in which the keys are the `__typename` of the blocks to be rendered, and the values are the Astro components */
37
45
  blockComponents: BlockComponents<R1, R2>;
46
+ inlineBlockComponents: InlineBlockComponents<R1, R2>;
38
47
  linkToRecordComponents?: never;
39
48
  inlineRecordComponents?: never;
40
49
  }
@@ -45,6 +54,7 @@ type Props<R1 extends DatocmsRecord, R2 extends DatocmsRecord> =
45
54
  | null
46
55
  | undefined;
47
56
  blockComponents?: never;
57
+ inlineBlockComponents?: never;
48
58
  /** An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components */
49
59
  linkToRecordComponents: LinkToRecordComponents<R1, R2>;
50
60
  /** An object in which the keys are the `__typename` of the records to be rendered, and the values are the Astro components */
@@ -57,6 +67,7 @@ type Props<R1 extends DatocmsRecord, R2 extends DatocmsRecord> =
57
67
  | null
58
68
  | undefined;
59
69
  blockComponents?: never;
70
+ inlineBlockComponents?: never;
60
71
  linkToRecordComponents?: never;
61
72
  inlineRecordComponents?: never;
62
73
  };
@@ -0,0 +1,27 @@
1
+ ---
2
+ import {
3
+ type Record as DatocmsRecord,
4
+ RenderError,
5
+ type InlineBlock,
6
+ } from 'datocms-structured-text-utils';
7
+ import type { InlineBlockComponents } from '../types';
8
+
9
+ interface Props {
10
+ node: InlineBlock;
11
+ block: DatocmsRecord;
12
+ inlineBlockComponents?: InlineBlockComponents<DatocmsRecord, DatocmsRecord>;
13
+ }
14
+
15
+ const { node, block, inlineBlockComponents } = Astro.props;
16
+
17
+ const Component = inlineBlockComponents?.[block.__typename];
18
+
19
+ if (!Component) {
20
+ throw new RenderError(
21
+ `The Structured Text document contains an 'inlineBlock' node, but no component for rendering it is specified in inlineBlockComponents prop!`,
22
+ node,
23
+ );
24
+ }
25
+ ---
26
+
27
+ <Component block={block} />
@@ -2,6 +2,7 @@ import type { TransformedMeta } from 'datocms-structured-text-generic-html-rende
2
2
  import type {
3
3
  Block,
4
4
  Record as DatocmsRecord,
5
+ InlineBlock,
5
6
  InlineItem,
6
7
  ItemLink,
7
8
  Mark,
@@ -16,6 +17,10 @@ export type BlockComponents<R1 extends DatocmsRecord, _R2 extends DatocmsRecord>
16
17
  [R in R1 as R['__typename']]: AstroComponent<{ block: R }>;
17
18
  };
18
19
 
20
+ export type InlineBlockComponents<R1 extends DatocmsRecord, _R2 extends DatocmsRecord> = {
21
+ [R in R1 as R['__typename']]: AstroComponent<{ block: R }>;
22
+ };
23
+
19
24
  export type LinkToRecordComponents<_R1 extends DatocmsRecord, R2 extends DatocmsRecord> = {
20
25
  [R in R2 as R['__typename']]: AstroComponent<{
21
26
  node: ItemLink;
@@ -53,7 +58,13 @@ export type NodeOverrides = Partial<{
53
58
  node: N;
54
59
  markOverrides?: MarkOverrides;
55
60
  }
56
- : { node: N }
61
+ : N extends InlineBlock
62
+ ? {
63
+ node: N;
64
+ block: DatocmsRecord;
65
+ inlineBlockComponents: InlineBlockComponents<DatocmsRecord, DatocmsRecord>;
66
+ }
67
+ : { node: N }
57
68
  >;
58
69
  }>;
59
70