42 lines
1.7 KiB
TypeScript
42 lines
1.7 KiB
TypeScript
import type { Paragraph, PhrasingContent, Root, RootContent } from "mdast";
|
|
|
|
// Display-only: preserve every inline node and character. Never rewrite source
|
|
// files, SQL, links, existing lists or short authored paragraphs.
|
|
export function readableParagraphs() {
|
|
return (tree: Root) => {
|
|
tree.children = tree.children.flatMap<RootContent>(node => {
|
|
if (node.type !== "paragraph") return [node];
|
|
const length = node.children.reduce((total, child) => total + ("value" in child ? String(child.value).length : 0), 0);
|
|
if (length < 360) return [node];
|
|
const paragraphs: Paragraph[] = [];
|
|
let children: PhrasingContent[] = [];
|
|
let size = 0;
|
|
for (const child of node.children) {
|
|
if (child.type !== "text") {
|
|
children.push(child);
|
|
if ("value" in child) size += String(child.value).length;
|
|
continue;
|
|
}
|
|
// Boundaries must be outside inline code/emphasis/links. Decimal points
|
|
// and identifiers cannot match because they have no following space.
|
|
let start = 0;
|
|
for (const match of child.value.matchAll(/;\s+|[.!?]\s+(?=[A-ZÀ-Ý])/g)) {
|
|
const end = match.index! + match[0].length;
|
|
if (size + end - start < 180) continue;
|
|
children.push({ type: "text", value: child.value.slice(start, end) });
|
|
paragraphs.push({ type: "paragraph", children });
|
|
children = [];
|
|
size = 0;
|
|
start = end;
|
|
}
|
|
if (start < child.value.length) {
|
|
children.push({ type: "text", value: child.value.slice(start) });
|
|
size += child.value.length - start;
|
|
}
|
|
}
|
|
if (children.length) paragraphs.push({ type: "paragraph", children });
|
|
return paragraphs;
|
|
});
|
|
};
|
|
}
|