0.11.1 • Published 5 months ago

astro-portabletext v0.11.1

Weekly downloads
-
License
ISC
Repository
github
Last release
5 months ago

astro-portabletext

npm license

A flexible and customizable library for rendering Portable Text content in Astro projects.

⚠️ Prerequisites:

  • Astro v4.6+ (as of v0.11.0)

Table of Contents

  • 🧩 Core components: Provides pre-built components for common Portable Text elements.
  • 🔧 Customizable: Use components or slots to tailor output to your needs.
  • 🛠 Flexible control: Use render function via usePortableText to fine-tune rendering.
  • 📘 Typescript: Built with full TypeScript support.

Jump in and see it in action:

Pick your favorite package manager and run one of these:

npm install astro-portabletext
# or
pnpm add astro-portabletext
# or
yarn add astro-portabletext
# or
bun add astro-portabletext

Sanity Integration

This library is officially recommended by Sanity for rendering Portable Text in Astro projects.

Helpful resources:

PortableText component

This component provides a simple and flexible way to display rich text, from using slots to custom components.

Basic usage

Import the PortableText component and start rendering. This library provides sensible defaults for rendering common Portable Text elements, which you can easily override.

Use the following default mapping to understand what each node type outputs.

{
  type: {
    /* Custom types go here */
  },
  block: {
    h1: /* <h1 {...attrs}><slot /></h1> */,
    h2: /* <h2 {...attrs}><slot /></h2> */,
    h3: /* <h3 {...attrs}><slot /></h3> */,
    h4: /* <h4 {...attrs}><slot /></h4> */,
    h5: /* <h5 {...attrs}><slot /></h5> */,
    h6: /* <h6 {...attrs}><slot /></h6> */,
    blockquote: /* <blockquote {...attrs}><slot /></blockquote> */,
    normal: /* <p {...attrs}><slot /></p> */
  },
  list: {
    bullet: /* <ul {...attrs}><slot /></ul> */,
    number: /* <ol {...attrs}><slot /></ol> */,
    menu: /* <menu {...attrs}><slot /></menu> */,
  },
  listItem: {
    bullet: /* <li {...attrs}><slot /></li> */,
    number: /* <li {...attrs}><slot /></li> */,
    menu: /* <li {...attrs}><slot /></li> */,
  },
  mark: {
    code: /* <code {...attrs}><slot /></code> */,
    em: /* <em {...attrs}><slot /></em> */,
    link: /* <a {...attrs} href="..."><slot /></a> */,
    'strike-through': /* <del {...attrs}><slot /></del> */,
    strong: /* <strong {...attrs}><slot /></strong> */,
    underline: /* <span {...attrs} style="text-decoration: underline;"><slot /></span> */
  },
  text: /* Renders plain text */
  hardBreak: /* <br /> */,
}
/* .astro */
---
import { PortableText } from "astro-portabletext";

const portableText = [
  {
    _type: "block",
    children: [
      {
        _type: "span",
        marks: [],
        text: "This is a ",
      },
      {
        _type: "span",
        marks: ["strong"],
        text: "bold",
      },
      {
        _type: "span",
        marks: [],
        text: " text example!",
      },
    ],
    markDefs: [],
    style: "normal",
  },
];
---

<PortableText value={portableText} />

Custom components

Custom components allow for better control over rendering of rich text elements. You can map a component to a node type or map the component to the property of the node type.

/* .astro */
---
import { PortableText } from "astro-portabletext";

const portableText = [
  // ... your Portable Text content
];

const components = {
  // custom types
  type: { [_type]: Component } | Component,
  unknownType: Component,
  // block style
  block: { [style]: Component } | Component,
  unknownBlock: Component,
  // list
  list: { [listItem]: Component } | Component,
  unknownList: Component,
  // list item
  listItem: { [listItem]: Component } | Component,
  unknownListItem: Component,
  // mark
  mark: { [markType]: Component } | Component,
  unknownMark: Component,
  // strings; added in `v0.11.0`
  text: Component,
  // line break
  hardBreak: Component
};
---

<PortableText value={portableText} components={components} />

💡 Refer to custom components documentation for more details.

Slots

Added in v0.11.0

Slots provide a flexible way to enhance the rendering of Portable Text elements by passing additional props to the component. This allows you to customize the output in various ways, such as:

  • Applying custom styles or classes
  • Wrapping elements in custom components
  • Modifying the output based on specific conditions

Here's an example of using a slot to apply custom styles to strong elements:

/* .astro */
---
import { PortableText } from "astro-portabletext";

const portableText = [
  // ... your Portable Text content
];
---

<PortableText value={portableText}>
  <fragment slot="mark">{({ Component, props, children }) => (
    <Component {...props} class="mark">{children}</Component>
  )}</fragment>
</PortableText>

<style>
  .mark:where(strong) {
    /* some styles */
  }
</style>

💡 Refer to slots documentation for more details.

PortableText component properties

PropertyTypeDescription
valuearray or objectPortable Text payload
components (optional)objectMapping of components to node types or its properties.
onMissingComponent (optional)function or booleanDisable warning messages or handle unknown types. Default prints to console.
listNestingMode (optional)"html" or "direct"List nesting mode. Default is html. See ToolkitListNestMode

Utility functions

This library provides utility functions to help you work with Portable Text content:

import {
  usePortableText,
  mergeComponents,
  toPlainText,
  spanToPlainText, // added in `v0.11.0`
} from "astro-portabletext";

💡 Refer to the utility functions documentation for more details.

We welcome contributions to improve astro-portabletext!

If you find a bug or have a feature request, please open an issue on GitHub. If you'd like to contribute code, feel free to submit a pull request.

This project is licensed under the ISC License.

0.11.1

5 months ago

0.11.0

6 months ago

0.10.1

8 months ago

0.10.0

1 year ago

0.9.9

1 year ago

0.9.8

1 year ago

0.9.7

1 year ago

0.9.4

2 years ago

0.9.6

2 years ago

0.9.5

2 years ago

0.9.0-next.2

2 years ago

0.9.0-next.1

2 years ago

0.9.0-next.4

2 years ago

0.9.0-next.3

2 years ago

0.9.0

2 years ago

0.9.1

2 years ago

0.9.0-next.0

2 years ago

0.8.1

2 years ago

0.8.0-next.0

2 years ago

0.8.0

2 years ago

0.7.0-next.1

3 years ago

0.7.0-next.2

3 years ago

0.7.0-next.3

3 years ago

0.7.0-next.4

3 years ago

0.7.0-next.0

3 years ago

0.5.0

3 years ago

0.7.0

3 years ago

0.6.1

3 years ago

0.6.0

3 years ago

0.4.0-next.2

3 years ago

0.4.0-next.3

3 years ago

0.4.0-next.4

3 years ago

0.4.0-next.5

3 years ago

0.4.1

3 years ago

0.4.0

3 years ago

0.4.0-next.0

3 years ago

0.4.0-next.1

3 years ago

0.2.3-next.1

3 years ago

0.2.3-next.0

3 years ago

0.3.0

3 years ago

0.3.0-next.0

3 years ago

0.2.3

3 years ago

0.2.4

3 years ago

0.2.2

3 years ago

0.2.1

3 years ago

0.2.1-next.2

3 years ago

0.2.1-next.1

3 years ago

0.2.1-next.0

3 years ago

0.2.0

3 years ago

0.1.0

3 years ago