@domandigital/sanity-copy

中文文档
0.4.13发布于 2026/11/02Apache-2.0TypeScriptESM + CJS构建来源已验证近 30 天下载 5074

The Doman Digital house copy check in Sanity Studio: every document type gains craft's copy rules as validation warnings on the field that caused them. Also a pure checker for a document or an export. No Sanity dependency.

原始使用文档
文档目录7 节
  1. In a Studio
  2. Localised content
  3. Blocking publish (opt-in)
  4. Sweeping a whole dataset
  5. The claims list
  6. In code
  7. Licence

@domandigital/sanity-copy

The Doman Digital house copy check inside Sanity Studio. Every document type gains craft's copy rules as validation warnings, on the exact field that caused them, including inside Portable Text. Publishing always still works: copy the owner types is advised on, never overridden.

The rules are COPY.md in @domandigital/craft. This package only decides which strings in a document are copy, and where each finding belongs.

In a Studio

Works in any Sanity Studio, v3 or later. It uses only Rule.custom(), Rule.warning() and plain document-action functions, and imports nothing from Sanity, so no Studio version is pinned. Its tests run against stand-ins for those shapes, not a live Studio. Nothing in it is specific to one site. Two steps:

  1. pnpm add @domandigital/sanity-copy (or npm, or yarn) in the Studio's app.
  2. Wrap the types array in sanity.config.ts, as below.
import { defineConfig } from "sanity";
import { withCopyCheck } from "@domandigital/sanity-copy";
import { schemaTypes } from "./schemas";

export default defineConfig({
  // ...
  schema: { types: withCopyCheck(schemaTypes) },
});

An editor sees, on the field:

House rule (Em dash): "local businesses — built". Use a full stop, a comma, or a colon.

Why a wrapper and not a plugin: a plugin's schema.types function runs before the Studio's own types are added, so a plugin never sees them.

Options, all optional:

OptionDefaultWhat it does
excludeTypestestimonial, review, proofQuote, quote, assist.instruction.contextNever checked. A person's own words are exempt from every house rule, and AI Assist instruction documents are prompts, not copy.
skipFieldsslug, url, href, link, email, phone, language, locale, ids, enumsNever read, at any depth.
reviewtrueShow the review and density tiers as well as the house rules.
languagesevery languageCheck only these, e.g. ["en"]. See below.
hiddenPathsfrom the schemaDot paths never read. withCopyCheck fills this in from every static hidden: true.

What is read: strings, Portable Text (a block's spans joined, so a template split across spans is still caught), and the alt text and caption of images. What is not: slugs, links, references, enum values, language tags, asset data, and fields the schema hides with hidden: true. A hidden function is not evaluated: it is decided per document and per editor, and the check has no way to know the answer for a nested field, so those fields are still read.

Localised content

The rules are English. On a localised Studio, pass languages: ["en"] so the other languages are left alone ("en" also covers en-GB and en_US). Four shapes are recognised:

ShapeExampleHow the language is found
sanity-plugin-internationalized-array v5[{ _key: "k8f2a", language: "fr", value }]the item's language field
the same plugin, v4 and earlier[{ _key: "fr", value }]the item's _key
field-level translation{ en: "...", fr: "..." }the object key, when every key is a two-letter language tag
@sanity/document-internationalization{ _type: "page", language: "fr" }the document's language field

Blocking publish (opt-in)

Everything above warns. A Studio that wants the house rules enforced can wrap the publish action, which then stays disabled while the document has a blocking-tier finding, with the finding as its tooltip. The review tier never blocks.

import { withCopyCheck, withCopyGuard } from "@domandigital/sanity-copy";

export default defineConfig({
  schema: { types: withCopyCheck(schemaTypes) },
  document: {
    actions: (prev) => prev.map((a) => (a.action === "publish" ? withCopyGuard(a) : a)),
  },
});

The original action is always called, so its behaviour is unchanged apart from disabled and the tooltip. Excluded types (testimonials and the rest) are never blocked.

Sweeping a whole dataset

npx @domandigital/sanity-copy --project <id>                 # a public dataset
SANITY_API_TOKEN=... npx @domandigital/sanity-copy --project <id> --types homepage,service
npx @domandigital/sanity-copy --file export.json --json

Findings are listed per document and field. Exit 0 no house-rule finding, 1 at least one, 2 nothing was checked. A token is read from the environment, never a flag. It reports and changes nothing.

The claims list

npx @domandigital/sanity-copy --project <id> --claims

No style rule can say whether a figure is true. --claims lists every sentence holding a price, a figure, a date or a named source, on its field, marked sourced (a source is named, in the sentence or a footnote) or UNSOURCED. Check each against its primary source, then source it, correct it or cut it. It always exits 0: a checklist, not a verdict. documentClaims(doc) does the same in code.

In code

import { checkDocumentCopy, pathToString, describeFinding } from "@domandigital/sanity-copy";

for (const f of checkDocumentCopy(doc)) console.log(pathToString(f.path), describeFinding(f));

No Sanity dependency, and nothing a Studio imports touches Node, so the same check runs in the Studio, a script and a test.

Licence

Apache-2.0.

版本与发布记录

@domandigital/sanity-copy 共发布 17 个版本,首次发布于 2026/09/24;过去 12 个月发布了 17 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.4.13latest2026/11/0211 天前
0.4.122026/10/2321 天前
0.4.112026/10/2024 天前
0.4.102026/10/2024 天前
0.4.92026/10/1430 天前
0.4.82026/10/091 个月前

关于 @domandigital/sanity-copy 的常见问题

@domandigital/sanity-copy 是什么?

The Doman Digital house copy check in Sanity Studio: every document type gains craft's copy rules as validation warnings on the field that caused them. Also a pure checker for a document or an export. No Sanity dependency.

如何安装 @domandigital/sanity-copy?

在项目目录运行 npm install @domandigital/sanity-copy,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 sanity-copy,可以用 npx sanity-copy 直接运行。

@domandigital/sanity-copy 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@domandigital/sanity-copy 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@domandigital/sanity-copy 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.12。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@domandigital/sanity-copy 可以商用吗?

@domandigital/sanity-copy 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@domandigital/sanity-copy 的下载量有多少?

根据 npm 官方下载统计,@domandigital/sanity-copy 在 2026/10/13 – 2026/11/11 这 30 天内被下载 5,074 次,日均约 169 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@domandigital/sanity-copy 还在维护吗?

最新版本 0.4.13 发布于 2026/11/02(11 天前);至今共发布 17 个版本,其中过去 12 个月发布了 17 个;首次发布于 2026/09/24。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。