Files
ThothII/frontend/src/viewers/readableParagraphs.ts
T

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;
});
};
}