45 lines
1.2 KiB
TypeScript
45 lines
1.2 KiB
TypeScript
import type { PortableTextBlock } from "emdash";
|
|
|
|
const WORDS_PER_MINUTE = 200;
|
|
const WHITESPACE_REGEX = /\s+/;
|
|
|
|
/**
|
|
* Extract plain text from Portable Text blocks
|
|
*/
|
|
export function extractText(blocks: PortableTextBlock[] | undefined): string {
|
|
if (!blocks || !Array.isArray(blocks)) return "";
|
|
|
|
return blocks
|
|
.filter(
|
|
(
|
|
block,
|
|
): block is PortableTextBlock & {
|
|
children: Array<{ _type: string; text?: string }>;
|
|
} => block._type === "block" && Array.isArray(block.children),
|
|
)
|
|
.map((block) =>
|
|
block.children
|
|
.filter((child) => child._type === "span" && typeof child.text === "string")
|
|
.map((span) => span.text)
|
|
.join(""),
|
|
)
|
|
.join(" ");
|
|
}
|
|
|
|
/**
|
|
* Calculate reading time in minutes from Portable Text content
|
|
*/
|
|
export function getReadingTime(content: PortableTextBlock[] | undefined): number {
|
|
const text = extractText(content);
|
|
const wordCount = text.split(WHITESPACE_REGEX).filter(Boolean).length;
|
|
const minutes = Math.ceil(wordCount / WORDS_PER_MINUTE);
|
|
return Math.max(1, minutes);
|
|
}
|
|
|
|
/**
|
|
* Format reading time for display
|
|
*/
|
|
export function formatReadingTime(minutes: number): string {
|
|
return `${minutes} min read`;
|
|
}
|