npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@portabletext/repair

v1.0.0

Published

Structural corrections for Portable Text values

Readme

@portabletext/repair

Structural corrections for Portable Text values

A Portable Text value can arrive structurally broken: a block without _type, a node without _key, two siblings sharing a key, a span without text, a text block without children. Code that walks or patches such a value can't address nodes reliably, so the Portable Text Editor corrects these five flaws before anything else. This package exposes the same rules, so other code that writes Portable Text can make a value structurally sound the same way the editor does.

You might not need this

The Portable Text Editor already runs these rules on its own value whenever it changes. Reach for this package only when you handle Portable Text outside the editor and need it to come out structurally sound, such as a server or sync layer that receives values from other writers.

Installation

npm install @portabletext/repair

Usage

getStructuralCorrection(context, entry) looks at one node and returns the first correction it needs, or undefined when the node is sound. A correction names the rule that found the flaw in type and carries the patches that fix it, typed as @portabletext/patches patches. Apply the patches in order, then ask again for the same node until no correction is returned, since one node can need more than one.

import {getStructuralCorrection} from '@portabletext/repair'
import {compileSchema, defineSchema} from '@portabletext/schema'

const schema = compileSchema(defineSchema({}))

const value = [
  {_type: 'block', _key: 'b1', children: []},
  {_type: 'block', _key: 'b1', children: []},
]

getStructuralCorrection(
  {schema, keyGenerator: () => crypto.randomUUID()},
  {
    node: value[1],
    path: [1],
    parent: undefined,
    siblings: () => value,
  },
)
// => {
//   type: 'duplicate-key',
//   patches: [{type: 'set', path: [1, '_key'], value: '...'}],
// }

The entry describes the node and where it sits:

| Field | Meaning | | ---------- | --------------------------------------------------------------------------------------- | | node | The node to check. It's unknown because it may be broken | | path | The node's path in the value | | parent | The parent node and its path, or undefined for a block at the root | | siblings | A function returning the array that holds the node, used only by the duplicate key rule |

siblings may return undefined when you already know the array has no duplicate keys, which skips the scan.

Rules

The rules run in this order, and the first one that applies wins:

| Rule | Flaw | Correction | | ------------------ | ----------------------------------------- | ---------------------------------------------------------------------- | | missing-type | A node has no _type | The span type inside a text block, the text block type everywhere else | | missing-key | A node's _key is missing or empty | A key from keyGenerator | | duplicate-key | A later sibling repeats the node's _key | A new key for the later sibling, addressed by index | | span-text | A span's text isn't a string | '' | | missing-children | A text block's children isn't an array | [] |

Anything else, such as missing markDefs, adjacent spans with the same marks or an empty text block, is left to the caller.