@ryhrm-gz/xincodo-lib
Version:
Utilities for working with Xincodo body documents.
215 lines (149 loc) • 5.15 kB
Markdown
---
name: validating-body
description: >
Load when validating Xincodo Body data before save or publish with
safeMigrateBody and lintBody; handling BodyLintReport, errors, warnings,
infos, BodyLintOptions, URL validation, image alt checks, duplicate ids,
heading jumps, table consistency, empty content, or maxDepth.
type: core
library: "@ryhrm-gz/xincodo-lib"
library_version: "0.1.0"
requires:
- building-and-parsing-body
sources:
- "ryhrm-gz/xincodo-lib:README.md"
- "ryhrm-gz/xincodo-lib:src/lint.ts"
- "ryhrm-gz/xincodo-lib:src/migration.ts"
- "ryhrm-gz/xincodo-lib:tests/lint.test.ts"
- "ryhrm-gz/xincodo-lib:tests/migration.test.ts"
---
# Validating Body
This skill builds on `building-and-parsing-body`. Read it first for Body
construction and persisted JSON boundaries.
## Setup
```ts
import { lintBody, safeMigrateBody } from "@ryhrm-gz/xincodo-lib";
export function validateBodyForSave(value: unknown) {
const migrated = safeMigrateBody(value);
if (!migrated.success) {
return { ok: false as const, kind: "migration", issue: migrated.issue };
}
const report = lintBody(migrated.output);
if (!report.valid) {
return { ok: false as const, kind: "lint", report };
}
return { ok: true as const, body: migrated.output, warnings: report.warnings };
}
```
The default blocking policy is errors only. Warnings and infos are surfaced
for the consuming application to decide.
## Core Patterns
### Gate saved input with migration then lint
```ts
import { lintBody, safeMigrateBody } from "@ryhrm-gz/xincodo-lib";
const migrated = safeMigrateBody(savedArticle.body);
if (!migrated.success) {
throw new Error(migrated.issue.message);
}
const lint = lintBody(migrated.output);
if (!lint.valid) {
throw new Error(lint.errors.map((issue) => issue.message).join("\n"));
}
```
`safeMigrateBody` verifies the persisted value and version. `lintBody` checks
quality and render-risk issues after a valid current Body exists.
### Surface warnings without blocking by default
```ts
import { lintBody } from "@ryhrm-gz/xincodo-lib";
const report = lintBody(body);
if (!report.valid) {
throw new Error("Body has blocking errors.");
}
for (const warning of report.warnings) {
console.warn(warning.code, warning.message);
}
```
`report.valid` is false only when `errors.length > 0`.
### Configure checks for the product context
```ts
import { lintBody } from "@ryhrm-gz/xincodo-lib";
const report = lintBody(body, {
maxDepth: 3,
requireImageAlt: true,
validateUrls: true,
});
if (!report.valid) {
throw new Error("Body cannot be saved.");
}
```
Use options deliberately. Disabling URL or image alt checks is an application
policy decision, not the safe default.
## Common Mistakes
### CRITICAL Using migration as the only quality gate
Wrong:
```ts
import { safeMigrateBody } from "@ryhrm-gz/xincodo-lib";
const result = safeMigrateBody(rawBody);
if (result.success) {
await save(result.output);
}
```
Correct:
```ts
import { lintBody, safeMigrateBody } from "@ryhrm-gz/xincodo-lib";
const result = safeMigrateBody(rawBody);
if (!result.success) {
throw new Error(result.issue.message);
}
const report = lintBody(result.output);
if (!report.valid) {
throw new Error("Body has blocking lint errors.");
}
await save(result.output);
```
Migration and schema validation accept structurally valid but editorially
risky content; `lintBody` reports issues such as duplicate ids, empty tables,
invalid URLs, missing alt text, and heading jumps.
Source: maintainer interview; `README.md`; `tests/migration.test.ts`;
`tests/lint.test.ts`
### MEDIUM Treating all lint issues as blocking
Wrong:
```ts
import { lintBody } from "@ryhrm-gz/xincodo-lib";
const report = lintBody(body);
if (report.issues.length > 0) {
throw new Error("Cannot save body.");
}
```
Correct:
```ts
import { lintBody } from "@ryhrm-gz/xincodo-lib";
const report = lintBody(body);
if (!report.valid) {
throw new Error("Cannot save body.");
}
const nonBlockingWarnings = report.warnings;
```
`lintBody` separates errors, warnings, and infos. By default, only errors
block save or publish; warning policy belongs to the consuming application.
Source: maintainer interview; `src/lint.ts`; `tests/lint.test.ts`
### HIGH Using local paths for external images
Wrong:
```ts
import { createBody, image, lintBody } from "@ryhrm-gz/xincodo-lib";
const body = createBody([image({ type: "external", url: "/uploads/cover.jpg" })]);
const report = lintBody(body);
```
Correct:
```ts
import { createBody, image, lintBody } from "@ryhrm-gz/xincodo-lib";
const body = createBody([image({ type: "file", url: "/uploads/cover.jpg" }, { alt: "Cover" })]);
const report = lintBody(body);
```
With URL validation enabled, `external` image sources must be absolute
`http` or `https` URLs; local upload paths belong to `file` image sources.
Source: `src/lint.ts`; `tests/lint.test.ts`
## References
- [Lint codes and severities](references/lint-codes-and-severities.md)
See also: `save-before-publish-checks/SKILL.md` — pre-save workflows combine
migration results with lint severity handling.