@ryhrm-gz/xincodo-lib
Version:
Utilities for working with Xincodo body documents.
200 lines (148 loc) • 4.99 kB
Markdown
name: article-render-preparation
description: >
Load when preparing Xincodo Body data for article pages without rendering
HTML or React. Covers composing extractHeadingAnchors, createExcerpt,
estimateReadingTime, collectImageSources, collectLinks, and toPlainText
after save or publish checks have handled linting.
type: lifecycle
library: "@ryhrm-gz/xincodo-lib"
library_version: "0.1.0"
requires:
- extracting-render-metadata
- validating-body
sources:
- "ryhrm-gz/xincodo-lib:README.md"
- "ryhrm-gz/xincodo-lib:src/rendering.ts"
- "ryhrm-gz/xincodo-lib:src/utils.ts"
- "ryhrm-gz/xincodo-lib:src/lint.ts"
- "ryhrm-gz/xincodo-lib:tests/rendering.test.ts"
- "ryhrm-gz/xincodo-lib:tests/lint.test.ts"
# Article Render Preparation
This skill builds on `extracting-render-metadata` and `validating-body`. Use
it to prepare data for article pages. Do not generate HTML, React components,
database persistence, request handlers, or image upload flows here.
## Setup
```ts
import {
collectImageSources,
collectLinks,
createExcerpt,
estimateReadingTime,
extractHeadingAnchors,
toPlainText,
type Body,
} from "@ryhrm-gz/xincodo-lib";
export function prepareArticleBody(body: Body) {
return {
plainText: toPlainText(body),
headings: extractHeadingAnchors(body),
excerpt: createExcerpt(body, { maxLength: 160, preserveWords: true }),
readingTime: estimateReadingTime(body),
images: collectImageSources(body),
links: collectLinks(body),
};
}
```
Standard flow: run `lintBody` in the save or publish pipeline, then focus
article-page preparation on extraction.
## Core Patterns
### Prepare table-of-contents entries
```ts
import { extractHeadingAnchors, type Body } from "@ryhrm-gz/xincodo-lib";
export function prepareTableOfContents(body: Body) {
return extractHeadingAnchors(body).map((heading) => ({
id: heading.anchorId,
href: heading.href,
level: heading.level,
text: heading.text,
}));
}
```
Use the returned `href` value directly; it handles duplicate slugs and URI
encoding.
### Prepare listing or SEO-like text metadata
```ts
import { createExcerpt, estimateReadingTime, toPlainText, type Body } from "@ryhrm-gz/xincodo-lib";
export function prepareArticleSummary(body: Body) {
return {
text: toPlainText(body),
excerpt: createExcerpt(body, { maxLength: 120, preserveWords: true }),
readingTime: estimateReadingTime(body),
};
}
```
The library extracts data. The consuming app decides how to render or store it.
### Prepare linked resource data
```ts
import { collectImageSources, collectLinks, type Body } from "@ryhrm-gz/xincodo-lib";
export function prepareArticleResources(body: Body) {
const links = collectLinks(body);
return {
images: collectImageSources(body),
textLinks: links.filter((link) => link.kind === "text_link"),
pageLinks: links.filter((link) => link.kind === "page_link"),
};
}
```
`collectLinks` supplies fallback text for page links that do not define a
title.
## Common Mistakes
### CRITICAL Asking the library to render UI
Wrong:
```ts
import { renderBodyToHtml } from "@ryhrm-gz/xincodo-lib";
const html = renderBodyToHtml(body);
```
Correct:
```ts
import { collectImageSources, extractHeadingAnchors, toPlainText } from "@ryhrm-gz/xincodo-lib";
const articleData = {
anchors: extractHeadingAnchors(body),
images: collectImageSources(body),
text: toPlainText(body),
};
```
This library provides helpers and metadata, not HTML or React renderers.
Source: maintainer interview; `README.md`
### MEDIUM Ignoring page link fallback text
Wrong:
```ts
const pageLinks = body.content
.filter((block) => block.type === "page_link")
.map((block) => block.title![0].text);
```
Correct:
```ts
import { collectLinks } from "@ryhrm-gz/xincodo-lib";
const pageLinks = collectLinks(body)
.filter((link) => link.kind === "page_link")
.map((link) => link.text);
```
`page_link` blocks may omit `title`; `collectLinks` falls back to the page id
or URL.
Source: `src/rendering.ts`; `tests/rendering.test.ts`
### MEDIUM Linting on every article render by default
Wrong:
```ts
import { extractHeadingAnchors, lintBody } from "@ryhrm-gz/xincodo-lib";
const report = lintBody(body);
if (!report.valid) {
throw new Error("Invalid article body");
}
const anchors = extractHeadingAnchors(body);
```
Correct:
```ts
import { extractHeadingAnchors } from "@ryhrm-gz/xincodo-lib";
const anchors = extractHeadingAnchors(body);
```
The standard flow is linting before save or publish. Runtime article
preparation should focus on extraction unless the app deliberately chooses
runtime linting.
Source: maintainer interview; `README.md`; `src/lint.ts`; `tests/lint.test.ts`
## References
- [Article metadata preparation checklist](references/article-metadata-preparation-checklist.md)
See also: `validating-body/SKILL.md` — heading, id, URL, and image-alt lint
findings affect article output readiness.