{"_id":"@portabletext/repair","_rev":"4-0db19951f235bbe1ad6be0cc77351654","name":"@portabletext/repair","dist-tags":{"latest":"1.0.1"},"versions":{"0.0.0-stage":{"name":"@portabletext/repair","version":"0.0.0-stage","_id":"@portabletext/repair@0.0.0-stage","stub":true,"maintainers":[{"name":"christianhg","email":"services@groengaard.dk"}],"dist":{"shasum":"7bb2b8abe6c1a890fe8390ea66839be535333c92","tarball":"https://registry.npmjs.org/@portabletext/repair/-/repair-0.0.0-stage.tgz","fileCount":2,"integrity":"sha512-ApVzt321kMeiplVYvSu/HBODNijj81T/rnmyya6zJgCppnYk96UvvQuelc5spfwbJfdYduUI0EJew+3kn+AmLA==","signatures":[{"sig":"MEUCIQDdHQWcpexOV4PYNc0J7YDjCgXDrsGjqylqfH8h9PrV9AIgTpjXHw8Vog07ATEIcdGdv8zWodbNPIpUmu7ZMVBMvYc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":342},"_npmUser":{"name":"christianhg","email":"services@groengaard.dk"},"description":"Temporary package placeholder for staged publishing","directories":{}},"1.0.0":{"name":"@portabletext/repair","version":"1.0.0","keywords":["portabletext","repair"],"author":{"name":"Sanity.io","email":"hello@sanity.io"},"license":"MIT","_id":"@portabletext/repair@1.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"}],"homepage":"https://www.portabletext.org/","bugs":{"url":"https://github.com/portabletext/editor/issues"},"dist":{"shasum":"cc4eee0985861a1a8ac362ec9f84416eb3d0c444","tarball":"https://registry.npmjs.org/@portabletext/repair/-/repair-1.0.0.tgz","fileCount":7,"integrity":"sha512-5oH5Osa1Cka07kK0w3y/ehS6gy64+dlyAwCiiuu74S0uceScvGuUFo6qSJDhsg1x9zxv46wMpZyObox3Aej9ag==","signatures":[{"sig":"MEQCIFW13SQr0HM2MXarMbErTBvHrwxXwIb2AcGGZDRxRCe+AiAvlt6vhPUUyA77KYeUoZ8kcczTkr5L9L8z/bC8zuuoBg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCoXeto7hAjGYHFvJnAWYkWlFIcyvy2YMJ0QH1TnBa3kAIgGUyGX+ne7gq/nuSSgP+VlfcDbGgVBe2hsBYaVqtgxuY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":19791},"type":"module","_from":"file:portabletext-repair-1.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=22.12"},"exports":{".":"./dist/index.js","./package.json":"./package.json"},"scripts":{"dev":"pkg-utils watch","build":"pkg-utils build --strict --check","clean":"del .turbo && del lib && del node_modules","test:unit":"vitest run","check:types":"tsc","test:unit:watch":"vitest watch","check:types:watch":"tsc --watch"},"_npmUser":{"name":"christianhg","email":"services@groengaard.dk"},"_resolved":"/private/var/folders/tk/v4wjs8ys3qg845n0bcflmnv00000gp/T/ab6f0b2ccf5221e21a49240f5d4843b4/portabletext-repair-1.0.0.tgz","_integrity":"sha512-5oH5Osa1Cka07kK0w3y/ehS6gy64+dlyAwCiiuu74S0uceScvGuUFo6qSJDhsg1x9zxv46wMpZyObox3Aej9ag==","repository":{"url":"git+https://github.com/portabletext/editor.git","type":"git","directory":"packages/repair"},"_npmVersion":"11.17.0","description":"Structural corrections for Portable Text values","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","dependencies":{"@portabletext/schema":"^3.1.0","@portabletext/patches":"^3.0.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.0","vitest":"^5.0.4","typescript":"^7.0.2","@sanity/tsconfig":"^2.1.0","@sanity/pkg-utils":"^12.3.0"},"_npmOperationalInternal":{"tmp":"tmp/repair_1.0.0_1792563445952_0.1512197584751267","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"_id":"@portabletext/repair@1.0.1","bugs":{"url":"https://github.com/portabletext/editor/issues"},"dist":{"shasum":"da5860a185fecefa9ac7e5c0959fdbf015384766","tarball":"https://registry.npmjs.org/@portabletext/repair/-/repair-1.0.1.tgz","fileCount":7,"integrity":"sha512-EjXME6S/gIhucbd42pZ8i5p+rxWSkWB6Ce7aK32trQpPZZSe/ZX2+B9m2X/UEBU/xlHsMFgK4wSfeZIwU1tu2w==","signatures":[{"sig":"MEYCIQDBEtLwJJyABiJYQcxbt7Ql5EuJIxVvWexOe0+NYyUZEAIhAOODxnhqOvhjcEFJ1L8e+RPn/UPduZ9F+Ftgk3cOxyzI","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIF62uzKHQA1UwuOL6lmi6ljEzmIyPUunIPM66v8baOpGAiBkM6YjikMJqapBHIyMbaSG4Y+xlj/IyBsiJwT+aUwMjg=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@portabletext%2frepair@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":19825},"name":"@portabletext/repair","type":"module","_from":"file:portabletext-repair-1.0.1.tgz","types":"./dist/index.d.ts","author":{"name":"Sanity.io","email":"hello@sanity.io"},"engines":{"node":">=22.12"},"exports":{".":"./dist/index.js","./package.json":"./package.json"},"license":"MIT","scripts":{"dev":"pkg-utils watch","build":"pkg-utils build --strict --check","clean":"del .turbo && del lib && del node_modules","test:unit":"vitest run","check:types":"tsc","test:unit:watch":"vitest watch","check:types:watch":"tsc --watch"},"version":"1.0.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"d9270454-ba48-4834-8103-4a8b4d1896da"}},"homepage":"https://www.portabletext.org/","keywords":["portabletext","repair"],"_resolved":"/tmp/1c43a54b901c9110e7b2e7a101774f3a/portabletext-repair-1.0.1.tgz","_integrity":"sha512-EjXME6S/gIhucbd42pZ8i5p+rxWSkWB6Ce7aK32trQpPZZSe/ZX2+B9m2X/UEBU/xlHsMFgK4wSfeZIwU1tu2w==","repository":{"url":"git+https://github.com/portabletext/editor.git","type":"git","directory":"packages/repair"},"_npmVersion":"11.21.1","description":"Structural corrections for Portable Text values","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"}],"sideEffects":false,"_nodeVersion":"24.22.1","dependencies":{"@portabletext/schema":"^3.1.0","@portabletext/patches":"^3.0.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.3.3","vitest":"^5.0.5","typescript":"^7.0.2","@sanity/tsconfig":"^2.1.0","@sanity/pkg-utils":"^12.3.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/repair_1.0.1_1793016056715_0.41784281270843615"}}},"time":{"created":"2026-10-21T06:16:29.987Z","modified":"2026-10-26T12:01:05.659Z","0.0.0-stage":"2026-10-21T06:16:29.987Z","1.0.0":"2026-10-21T06:17:26.041Z","1.0.1":"2026-10-26T12:00:56.796Z"},"bugs":{"url":"https://github.com/portabletext/editor/issues"},"author":{"name":"Sanity.io","email":"hello@sanity.io"},"license":"MIT","homepage":"https://www.portabletext.org/","keywords":["portabletext","repair"],"repository":{"url":"git+https://github.com/portabletext/editor.git","type":"git","directory":"packages/repair"},"description":"Structural corrections for Portable Text values","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/repair`\n\n> Structural corrections for Portable Text values\n\nA 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.\n\n## You might not need this\n\nThe 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.\n\n## Installation\n\n```bash\nnpm install @portabletext/repair\n```\n\n## Usage\n\n`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.\n\n```ts\nimport {getStructuralCorrection} from '@portabletext/repair'\nimport {compileSchema, defineSchema} from '@portabletext/schema'\n\nconst schema = compileSchema(defineSchema({}))\n\nconst value = [\n  {_type: 'block', _key: 'b1', children: []},\n  {_type: 'block', _key: 'b1', children: []},\n]\n\ngetStructuralCorrection(\n  {schema, keyGenerator: () => crypto.randomUUID()},\n  {\n    node: value[1],\n    path: [1],\n    parent: undefined,\n    siblings: () => value,\n  },\n)\n// => {\n//   type: 'duplicate-key',\n//   patches: [{type: 'set', path: [1, '_key'], value: '...'}],\n// }\n```\n\nThe entry describes the node and where it sits:\n\n| Field      | Meaning                                                                                 |\n| ---------- | --------------------------------------------------------------------------------------- |\n| `node`     | The node to check. It's `unknown` because it may be broken                              |\n| `path`     | The node's path in the value                                                            |\n| `parent`   | The parent node and its path, or `undefined` for a block at the root                    |\n| `siblings` | A function returning the array that holds the node, used only by the duplicate key rule |\n\n`siblings` may return `undefined` when you already know the array has no duplicate keys, which skips the scan.\n\n## Rules\n\nThe rules run in this order, and the first one that applies wins:\n\n| Rule               | Flaw                                      | Correction                                                             |\n| ------------------ | ----------------------------------------- | ---------------------------------------------------------------------- |\n| `missing-type`     | A node has no `_type`                     | The span type inside a text block, the text block type everywhere else |\n| `missing-key`      | A node's `_key` is missing or empty       | A key from `keyGenerator`                                              |\n| `duplicate-key`    | A later sibling repeats the node's `_key` | A new key for the later sibling, addressed by index                    |\n| `span-text`        | A span's `text` isn't a string            | `''`                                                                   |\n| `missing-children` | A text block's `children` isn't an array  | `[]`                                                                   |\n\nAnything else, such as missing `markDefs`, adjacent spans with the same marks or an empty text block, is left to the caller.\n","readmeFilename":"README.md"}