{"_id":"@portabletext/astro","_rev":"3-688fa8a19c05f60b1c79f6cf0abee2b0","name":"@portabletext/astro","dist-tags":{"latest":"0.2.0"},"versions":{"0.0.0":{"name":"@portabletext/astro","version":"0.0.0","keywords":["oidc","trusted-publishing","setup"],"_id":"@portabletext/astro@0.0.0","maintainers":[{"name":"kmelve","email":"knut.melvaer@gmail.com"},{"name":"rexxars","email":"espen@hovlandsdal.com"},{"name":"skogsmaskin","email":"per.kristian.nordnes@gmail.com"},{"name":"mariuslundgard","email":"studio@mariuslundgard.com"},{"name":"bjoerge","email":"bjoerge@gmail.com"},{"name":"rbotten","email":"rbotten@gmail.com"},{"name":"sanity-io","email":"developers@sanity.io"},{"name":"snorreeb","email":"snorre.e.brekke@gmail.com"},{"name":"josef-sanity","email":"josef.hlavacek@sanity.io"},{"name":"stipsan","email":"stipsan@gmail.com"},{"name":"christianhg","email":"services@groengaard.dk"}],"dist":{"shasum":"f429f006e5ec573debda7aaf659b05c0d114f241","tarball":"https://registry.npmjs.org/@portabletext/astro/-/astro-0.0.0.tgz","fileCount":2,"integrity":"sha512-dAK8sAESmutQjDehnivUSnj6eYpXrPaLNR9FpNhJA6upqXOuc1hsCwVwcjS+doDSgP9dCUD8W7kCzmVWbUl3HA==","signatures":[{"sig":"MEQCIAXKhFnyg040BhaGO+jOPqRkgJMvYG/A5/lxR/U2cTa7AiBR8jkL2nojzf7+KrhOoP6DfNbkB101GiHtQgRQSEdvCA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":2039},"_npmUser":{"name":"sanity-io","email":"developers@sanity.io"},"_npmVersion":"11.17.0","description":"OIDC trusted publishing setup package for @portabletext/astro","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/astro_0.0.0_1786560177593_0.6450442808659014","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@portabletext/astro","version":"0.1.0","keywords":["astro","astro-component","portable-text","sanity","withastro"],"author":{"name":"Sanity.io","email":"hello@sanity.io"},"license":"ISC","_id":"@portabletext/astro@0.1.0","maintainers":[{"name":"kmelve","email":"knut.melvaer@gmail.com"},{"name":"rexxars","email":"espen@hovlandsdal.com"},{"name":"skogsmaskin","email":"per.kristian.nordnes@gmail.com"},{"name":"mariuslundgard","email":"studio@mariuslundgard.com"},{"name":"bjoerge","email":"bjoerge@gmail.com"},{"name":"rbotten","email":"rbotten@gmail.com"},{"name":"sanity-io","email":"developers@sanity.io"},{"name":"snorreeb","email":"snorre.e.brekke@gmail.com"},{"name":"josef-sanity","email":"josef.hlavacek@sanity.io"},{"name":"stipsan","email":"stipsan@gmail.com"},{"name":"christianhg","email":"services@groengaard.dk"}],"contributors":[{"url":"original author of astro-portabletext","name":"Tom Theisel","email":"tom.theisel@gmail.com"}],"homepage":"https://github.com/portabletext/astro-portabletext#readme","bugs":{"url":"https://github.com/portabletext/astro-portabletext/issues"},"dist":{"shasum":"ab8904f42fd6b562867926423b68b51494a70fcf","tarball":"https://registry.npmjs.org/@portabletext/astro/-/astro-0.1.0.tgz","fileCount":25,"integrity":"sha512-0w+y0ucsk926bN0TUC/iY76W0eZ0xLGOl2L0KSyaeBPeUelcc5Fiw3H4FFeqF+rGVuVGwW4g5KFRV2mbHRqQUg==","signatures":[{"sig":"MEUCIQDmRlkMWu9jxeJ71d/hHGIYmZ3VJWq+3rmvo26K3eTyfgIgCWX4EbNFpA2c02yiT11gAJhZalpS75rTy2t+2nCIClE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@portabletext%2fastro@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":46516},"type":"module","_from":"file:portabletext-astro-0.1.0.tgz","engines":{"node":">=22.12"},"exports":{".":"./lib/index.ts","./types":"./lib/types.ts","./utils":{"types":"./lib/utils.d.ts","import":"./lib/utils.ts","default":"./lib/utils.ts"},"./components":"./lib/components.ts","./package.json":"./package.json"},"scripts":{"dev":"astro dev --root demo","lint":"oxlint","test":"vitest","clean":"rimraf demo/dist test/dist","start":"pnpm dev","format":"oxfmt .","release":"changeset publish","build:demo":"astro build --root demo","type-check":"astro check","prebuild:demo":"pnpm clean"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ddda9fca-476a-4e0a-8a91-d37419561ade"}},"_resolved":"/tmp/47ddb6173dd89fe8af26c4e615988228/portabletext-astro-0.1.0.tgz","_integrity":"sha512-0w+y0ucsk926bN0TUC/iY76W0eZ0xLGOl2L0KSyaeBPeUelcc5Fiw3H4FFeqF+rGVuVGwW4g5KFRV2mbHRqQUg==","repository":{"url":"git+ssh://git@github.com/portabletext/astro-portabletext.git","type":"git"},"_npmVersion":"11.19.0","description":"Render Portable Text with Astro","directories":{},"lint-staged":{"*":["oxfmt"]},"_nodeVersion":"24.19.0","dependencies":{"@portabletext/types":"^4.0.2","@portabletext/toolkit":"^6.0.0"},"typesVersions":{"*":{"*":["lib/*"]}},"_hasShrinkwrap":false,"devDependencies":{"astro":"^7.2.1","oxfmt":"^0.63.0","oxlint":"^1.78.0","rimraf":"^5.0.1","vitest":"^4.1.10","cheerio":"^1.2.0","leaflet":"^1.9.4","typescript":"^6.0.3","@types/node":"^26.2.0","@astrojs/check":"^0.9.10","@types/leaflet":"^1.9.21","@changesets/cli":"^2.31.1","oxlint-tsgolint":"^7.0.2001","@changesets/changelog-github":"^0.7.0"},"peerDependencies":{"astro":">=4.6.0"},"_npmOperationalInternal":{"tmp":"tmp/astro_0.1.0_1786569407607_0.6023693709022457","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@portabletext/astro","version":"0.2.0","description":"Render Portable Text with Astro","keywords":["astro","astro-component","portable-text","sanity","withastro"],"homepage":"https://github.com/portabletext/astro-portabletext#readme","bugs":{"url":"https://github.com/portabletext/astro-portabletext/issues"},"license":"ISC","author":{"name":"Sanity.io","email":"hello@sanity.io"},"contributors":[{"name":"Tom Theisel","email":"tom.theisel@gmail.com","url":"original author of astro-portabletext"}],"repository":{"type":"git","url":"git+ssh://git@github.com/portabletext/astro-portabletext.git"},"type":"module","typesVersions":{"*":{"*":["lib/*"]}},"exports":{".":"./lib/index.ts","./components":"./lib/components.ts","./types":"./lib/types.ts","./utils":{"types":"./lib/utils.d.ts","import":"./lib/utils.ts","default":"./lib/utils.ts"},"./package.json":"./package.json"},"dependencies":{"@portabletext/toolkit":"^6.0.0","@portabletext/types":"^4.0.2"},"devDependencies":{"@astrojs/check":"^0.9.10","@changesets/changelog-github":"^0.7.0","@changesets/cli":"^2.31.1","@types/leaflet":"^1.9.21","@types/node":"^26.2.0","astro":"^7.2.1","cheerio":"^1.2.0","leaflet":"^1.9.4","oxfmt":"^0.63.0","oxlint":"^1.78.0","oxlint-tsgolint":"^7.0.2001","rimraf":"^5.0.1","typescript":"^6.0.3","vitest":"^4.1.10"},"peerDependencies":{"astro":">=4.6.0"},"lint-staged":{"*":["oxfmt"]},"engines":{"node":">=22.12"},"scripts":{"prebuild:demo":"pnpm clean","build:demo":"astro build --root demo","clean":"rimraf demo/dist test/dist","dev":"astro dev --root demo","format":"oxfmt .","lint":"oxlint","release":"changeset publish","start":"pnpm dev","test":"vitest","type-check":"astro check"},"_id":"@portabletext/astro@0.2.0","_integrity":"sha512-USw0iATW3k4HYD5aSCw16VRcXLt6zTxaF5Ah3e1tklbYLO45nkDj2IXV8EbB5Flkxti/f8xXDJpmrn8IXM1UZA==","_resolved":"/tmp/5bc7f4f6a949bb48d30a145c593482bb/portabletext-astro-0.2.0.tgz","_from":"file:portabletext-astro-0.2.0.tgz","_nodeVersion":"24.21.0","_npmVersion":"11.19.1","dist":{"integrity":"sha512-USw0iATW3k4HYD5aSCw16VRcXLt6zTxaF5Ah3e1tklbYLO45nkDj2IXV8EbB5Flkxti/f8xXDJpmrn8IXM1UZA==","shasum":"f1d17bbc25e1372a995562ab454abf4b18cd3935","tarball":"https://registry.npmjs.org/@portabletext/astro/-/astro-0.2.0.tgz","fileCount":25,"unpackedSize":56075,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@portabletext%2fastro@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDGf7OEnSgc4WThFTjv9j/1Dh2I+kcpUGALFhsYvPu1KQIhAJdJuLfETjG78cWlZLwfNYgy8+t0/YPk1UkqFQ1hvZ95"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ddda9fca-476a-4e0a-8a91-d37419561ade"}},"directories":{},"maintainers":[{"name":"kmelve","email":"knut.melvaer@gmail.com"},{"name":"rexxars","email":"espen@hovlandsdal.com"},{"name":"skogsmaskin","email":"per.kristian.nordnes@gmail.com"},{"name":"mariuslundgard","email":"studio@mariuslundgard.com"},{"name":"bjoerge","email":"bjoerge@gmail.com"},{"name":"rbotten","email":"rbotten@gmail.com"},{"name":"sanity-io","email":"developers@sanity.io"},{"name":"snorreeb","email":"snorre.e.brekke@gmail.com"},{"name":"josef-sanity","email":"josef.hlavacek@sanity.io"},{"name":"stipsan","email":"stipsan@gmail.com"},{"name":"christianhg","email":"services@groengaard.dk"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/astro_0.2.0_1789058741661_0.8027193771610848"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-12T18:42:57.397Z","modified":"2026-09-10T16:45:42.206Z","0.0.0":"2026-08-12T18:42:57.749Z","0.1.0":"2026-08-12T21:16:47.763Z","0.2.0":"2026-09-10T16:45:41.815Z"},"bugs":{"url":"https://github.com/portabletext/astro-portabletext/issues"},"author":{"name":"Sanity.io","email":"hello@sanity.io"},"license":"ISC","homepage":"https://github.com/portabletext/astro-portabletext#readme","keywords":["astro","astro-component","portable-text","sanity","withastro"],"repository":{"type":"git","url":"git+ssh://git@github.com/portabletext/astro-portabletext.git"},"description":"Render Portable Text with Astro","contributors":[{"name":"Tom Theisel","email":"tom.theisel@gmail.com","url":"original author of astro-portabletext"}],"maintainers":[{"name":"kmelve","email":"knut.melvaer@gmail.com"},{"name":"rexxars","email":"espen@hovlandsdal.com"},{"name":"skogsmaskin","email":"per.kristian.nordnes@gmail.com"},{"name":"mariuslundgard","email":"studio@mariuslundgard.com"},{"name":"bjoerge","email":"bjoerge@gmail.com"},{"name":"rbotten","email":"rbotten@gmail.com"},{"name":"sanity-io","email":"developers@sanity.io"},{"name":"snorreeb","email":"snorre.e.brekke@gmail.com"},{"name":"josef-sanity","email":"josef.hlavacek@sanity.io"},{"name":"stipsan","email":"stipsan@gmail.com"},{"name":"christianhg","email":"services@groengaard.dk"}],"readme":"# @portabletext/astro\n\n[![npm version](https://img.shields.io/npm/v/@portabletext/astro.svg?style=flat-square)](https://www.npmjs.com/package/@portabletext/astro)\n[![npm downloads](https://img.shields.io/npm/dm/@portabletext/astro.svg?style=flat-square)](https://www.npmjs.com/package/@portabletext/astro)\n![license](https://img.shields.io/npm/l/@portabletext/astro?style=flat-square)\n\nRender [Portable Text](https://portabletext.org) with [Astro](https://astro.build).\n\n> [!NOTE]\n> This package is a fork of [`astro-portabletext`](https://github.com/theisel/astro-portabletext) by [Tom Theisel](https://github.com/theisel), maintained under the [`@portabletext`](https://github.com/portabletext) organization. All credit for the original design and implementation goes to Tom. It remains distributed under the original [ISC License](./LICENSE). See [Migrating from `astro-portabletext`](#migrating-from-astro-portabletext).\n\n## Table of contents\n\n- [Installation](#installation)\n- [Basic usage](#basic-usage)\n- [Sanity integration](#sanity-integration)\n- [Customizing components](#customizing-components)\n  - [Default components](#default-components)\n  - [Custom components](#custom-components)\n  - [Slots](#slots)\n- [`PortableText` component properties](#portabletext-component-properties)\n- [Utility functions](#utility-functions)\n  - [`usePortableText`](#useportabletext)\n  - [`mergeComponents`](#mergecomponents)\n  - [`toPlainText`](#toplaintext)\n- [Migrating from `astro-portabletext`](#migrating-from-astro-portabletext)\n- [License](#license)\n\n## Installation\n\n```bash\nnpm install @portabletext/astro\n```\n\n> **Prerequisites:** Astro v4.6 or newer.\n\n## Basic usage\n\nImport the `PortableText` component and pass it a Portable Text value. The library provides sensible defaults for rendering all standard Portable Text elements, which you can override.\n\n```astro\n---\nimport {PortableText} from '@portabletext/astro'\n\nconst portableText = [\n  {\n    _type: 'block',\n    style: 'normal',\n    markDefs: [],\n    children: [\n      {_type: 'span', marks: [], text: 'This is a '},\n      {_type: 'span', marks: ['strong'], text: 'bold'},\n      {_type: 'span', marks: [], text: ' text example!'},\n    ],\n  },\n]\n---\n\n<PortableText value={portableText} />\n```\n\n## Sanity integration\n\nThis library's predecessor is [officially recommended](https://www.sanity.io/plugins/sanity-astro#rendering-rich-text-and-block-content-with-portable-text) by [Sanity](https://sanity.io) for rendering Portable Text in Astro projects. Helpful resources:\n\n- [Sanity integration for Astro](https://www.sanity.io/plugins/sanity-astro)\n- [Guide: building a blog with Sanity and Astro](https://www.sanity.io/guides/sanity-astro-blog)\n\n## Customizing components\n\n### Default components\n\nDefault components are provided for all standard features of the Portable Text spec, with logical HTML defaults. Provided components are merged with the defaults, so you only need to provide the things you want to override.\n\n<details>\n  <summary>View the default structure and output</summary>\n\n```js\n{\n  type: {\n    /* Custom types go here */\n  },\n  block: {\n    h1: /* <h1 {...attrs}><slot /></h1> */,\n    h2: /* <h2 {...attrs}><slot /></h2> */,\n    h3: /* <h3 {...attrs}><slot /></h3> */,\n    h4: /* <h4 {...attrs}><slot /></h4> */,\n    h5: /* <h5 {...attrs}><slot /></h5> */,\n    h6: /* <h6 {...attrs}><slot /></h6> */,\n    blockquote: /* <blockquote {...attrs}><slot /></blockquote> */,\n    normal: /* <p {...attrs}><slot /></p> */\n  },\n  list: {\n    bullet: /* <ul {...attrs}><slot /></ul> */,\n    number: /* <ol {...attrs}><slot /></ol> */,\n    menu: /* <menu {...attrs}><slot /></menu> */,\n  },\n  listItem: {\n    bullet: /* <li {...attrs}><slot /></li> */,\n    number: /* <li {...attrs}><slot /></li> */,\n    menu: /* <li {...attrs}><slot /></li> */,\n  },\n  mark: {\n    code: /* <code {...attrs}><slot /></code> */,\n    em: /* <em {...attrs}><slot /></em> */,\n    link: /* <a {...attrs} href=\"...\"><slot /></a> */,\n    'strike-through': /* <del {...attrs}><slot /></del> */,\n    strong: /* <strong {...attrs}><slot /></strong> */,\n    underline: /* <span {...attrs} style=\"text-decoration: underline;\"><slot /></span> */\n  },\n  text: /* Renders plain text */,\n  hardBreak: /* <br /> */,\n}\n```\n\n</details>\n\n### Custom components\n\nCustom components give you control over how each node is rendered. Map a component to a whole node type, or to a specific property (style, mark type, list item type, etc.) of that node type.\n\n```astro\n---\nimport {PortableText} from '@portabletext/astro'\nimport Code from '../components/Code.astro'\nimport Link from '../components/Link.astro'\n\nconst portableText = [\n  // ... your Portable Text content\n]\n\nconst components = {\n  // Custom object types, keyed by `_type` (or a single component for all types)\n  type: {code: Code},\n  // Block styles, keyed by `style`\n  block: {/* h1, h2, normal, ... */},\n  // Lists, keyed by `listItem`\n  list: {/* bullet, number, ... */},\n  // List items, keyed by `listItem`\n  listItem: {/* bullet, number, ... */},\n  // Marks (decorators and annotations), keyed by mark type\n  mark: {link: Link},\n  // Fallbacks for unknown nodes\n  unknownType: undefined,\n  unknownBlock: undefined,\n  unknownList: undefined,\n  unknownListItem: undefined,\n  unknownMark: undefined,\n  // Plain text spans and hard breaks\n  text: undefined,\n  hardBreak: undefined,\n}\n---\n\n<PortableText value={portableText} components={components} />\n```\n\nEach custom component receives `node`, `index` and `isInline` props, and renders any children through a `<slot />`. For example, a custom `link` mark:\n\n```astro\n---\nimport type {MarkProps} from '@portabletext/astro/types'\n\nexport type Props = MarkProps<{href?: string}>\n\nconst {node} = Astro.props\nconst href = node.markDef?.href\n---\n\n<a href={href}><slot /></a>\n```\n\n### Slots\n\nSlots provide a flexible way to enhance rendering by passing additional props to the resolved component - for example applying custom classes or wrapping elements - without replacing the default component entirely.\n\n```astro\n---\nimport {PortableText} from '@portabletext/astro'\n\nconst portableText = [\n  // ... your Portable Text content\n]\n---\n\n<PortableText value={portableText}>\n  <fragment slot=\"mark\">\n    {({Component, props, children}) => (\n      <Component {...props} class=\"mark\">{children}</Component>\n    )}\n  </fragment>\n</PortableText>\n\n<style>\n  .mark:where(strong) {\n    /* some styles */\n  }\n</style>\n```\n\nA slot named after a node type applies to every node of that type: `type`, `block`, `list`, `listItem`, `mark`, `text` and `hardBreak`. To target a single block style, list type, mark type or custom type, scope the slot name with `nodeType:type`.\n\n```astro\n<PortableText value={portableText}>\n  <fragment slot=\"block:h1\">\n    {({Component, props, children}) => (\n      <Component {...props} class=\"heading\">{children}</Component>\n    )}\n  </fragment>\n  <fragment slot=\"mark:link\">\n    {({Component, props, children}) => (\n      <Component {...props} rel=\"noopener\">{children}</Component>\n    )}\n  </fragment>\n  <fragment slot=\"type:callout\">\n    {({props}) => <aside class=\"callout\">{props.node.text}</aside>}\n  </fragment>\n</PortableText>\n```\n\nA slot only has a `Component` to render when the node type has one. Standard block styles, list types and mark types all ship defaults, but `components.type` starts out empty - a custom type has no default component. So a slot for a custom type either renders its own markup, as `type:callout` does above, or registers a component to receive:\n\n```astro\n<PortableText value={portableText} components={{type: {callout: Callout}}}>\n  <fragment slot=\"type:callout\">\n    {({Component, props}) => <Component {...props} class=\"callout\" />}\n  </fragment>\n</PortableText>\n```\n\nAsking for `Component` when the node type has none gives you the unknown-type component and reports the missing component through [`onMissingComponent`](#portabletext-component-properties). A slot that never touches `Component` renders cleanly.\n\nA scoped slot takes precedence over the node type it belongs to, so `block` can handle every block while `block:h1` handles headings.\n\n```astro\n<PortableText value={portableText}>\n  <!-- Every block except `h1` -->\n  <fragment slot=\"block\">\n    {({Component, props, children}) => (\n      <Component {...props} class=\"block\">{children}</Component>\n    )}\n  </fragment>\n  <fragment slot=\"block:h1\">\n    {({Component, props, children}) => (\n      <Component {...props} class=\"heading\">{children}</Component>\n    )}\n  </fragment>\n</PortableText>\n```\n\nThe `text` and `hardBreak` node types have no types of their own, so they cannot be scoped.\n\n#### Slots and the `components` prop\n\nA slot does not replace the [`components`](#customizing-components) prop, it wraps it. The `Component` handed to a slot is whatever the `components` prop resolved to for that node, so the two compose - the slot decides how the resolved component is rendered.\n\n```astro\n<PortableText value={portableText} components={{block: {h1: MyHeading}}}>\n  <fragment slot=\"block:h1\">\n    <!-- `Component` is `MyHeading` -->\n    {({Component, props, children}) => (\n      <Component {...props} class=\"heading\">{children}</Component>\n    )}\n  </fragment>\n</PortableText>\n```\n\nSlots belong to the author of the `PortableText` element, so they always win. A component reached through the `components` prop can customize its own children with [`render`](#useportabletext), but a slot for that node type takes precedence over it.\n\n```astro\n<PortableText value={portableText} components={{block: MyBlock}}>\n  <!-- Applies even if `MyBlock` renders its children with `render({mark: ...})` -->\n  <fragment slot=\"mark\">\n    {({Component, props, children}) => (\n      <Component {...props} class=\"mark\">{children}</Component>\n    )}\n  </fragment>\n</PortableText>\n```\n\n## `PortableText` component properties\n\n| Property                        | Type                    | Description                                                                                                                                 |\n| ------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |\n| `value`                         | `array` or `object`     | Portable Text payload                                                                                                                       |\n| `components` (optional)         | `object`                | Mapping of components to node types or their properties.                                                                                    |\n| `onMissingComponent` (optional) | `function` or `boolean` | Disable warning messages or handle unknown types. **Default** prints to console.                                                            |\n| `listNestingMode` (optional)    | `\"html\"` or `\"direct\"`  | List nesting mode. **Default** is `html`. See [ToolkitListNestMode](https://portabletext.github.io/toolkit/types/ToolkitListNestMode.html). |\n\n## Utility functions\n\n```js\nimport {usePortableText, mergeComponents, toPlainText, spanToPlainText} from '@portabletext/astro'\n```\n\n### `usePortableText`\n\nWithin a component passed into the `components` prop, `usePortableText(node)` returns rendering utilities scoped to that node: `getDefaultComponent()`, `getUnknownComponent()` and `render()`.\n\n```astro\n---\nimport type {BlockProps} from '@portabletext/astro/types'\nimport {usePortableText} from '@portabletext/astro'\n\nexport type Props = BlockProps\n\nconst {node} = Astro.props\nconst {getDefaultComponent} = usePortableText(node)\nconst Default = getDefaultComponent()\n---\n\n<Default {...Astro.props}><slot /></Default>\n```\n\n### `mergeComponents`\n\nMerges two component maps, giving priority to the overrides. Useful for extending a shared base set of components.\n\n```js\nimport {mergeComponents} from '@portabletext/astro'\n\nconst components = mergeComponents(baseComponents, {\n  block: {h1: MyHeading},\n})\n```\n\n### `toPlainText`\n\nRenders one or more Portable Text blocks as a plain string - handy for meta descriptions or generating slugs. `spanToPlainText` does the same for a single span's children.\n\n```astro\n---\nimport {toPlainText} from '@portabletext/astro'\n\nconst {node} = Astro.props\nconst text = toPlainText(node)\n---\n```\n\n## Migrating from `astro-portabletext`\n\n`@portabletext/astro` is a drop-in fork of [`astro-portabletext`](https://github.com/theisel/astro-portabletext). To migrate, swap the dependency and update your imports:\n\n```diff\n- import {PortableText} from 'astro-portabletext'\n+ import {PortableText} from '@portabletext/astro'\n\n- import type {BlockProps} from 'astro-portabletext/types'\n+ import type {BlockProps} from '@portabletext/astro/types'\n```\n\nThe component API, props and utility functions are unchanged.\n\n## License\n\n[ISC](./LICENSE) © [Tom Theisel](https://github.com/theisel) (original author) and the Portable Text authors.\n","readmeFilename":"README.md"}