reading-time
coreAdds readingTime (minutes) and wordCount to your processed MDX output.
document0/reading-time•v0.1.0•Any framework
Installation
$npx @document0/cli add document0/reading-time
Usage
import { processMdx } from "@document0/mdx";
import { readingTime } from "./plugins/document0/reading-time";
const result = await processMdx(source, {
plugins: [readingTime()],
});Source
After installation, this lives at plugins/document0/reading-time/index.ts and you can modify it however you like.
export interface ReadingTimeOptions {
/** Words per minute. @default 250 */
wordsPerMinute?: number;
}
interface ProcessedMdx {
code: string;
frontmatter: Record<string, unknown>;
toc: { id: string; text: string; depth: number }[];
[key: string]: unknown;
}
function stripMarkdown(content: string): string {
return content
.replace(/```[\s\S]*?```/g, "")
.replace(/`[^`]*`/g, "")
.replace(/!\[.*?\]\(.*?\)/g, "")
.replace(/\[([^\]]+)\]\(.*?\)/g, "$1")
.replace(/#{1,6}\s+/g, "")
.replace(/[*_~]{1,3}([^*_~]+)[*_~]{1,3}/g, "$1")
.replace(/^\s*[-*+>]\s+/gm, "")
.replace(/\n{2,}/g, " ")
.trim();
}
/**
* Document0 plugin: adds `readingTime` (minutes) and `wordCount`
* to the processed MDX result.
*
* ```ts
* processMdx(source, { plugins: [readingTime()] });
* // result.readingTime → 3
* // result.wordCount → 742
* ```
*/
export function readingTime(options?: ReadingTimeOptions) {
const wpm = options?.wordsPerMinute ?? 250;
return {
name: "reading-time",
transformResult(
result: ProcessedMdx,
context: { source: string; content: string },
): ProcessedMdx {
const text = stripMarkdown(context.content);
const words = text.split(/\s+/).filter(Boolean).length;
return {
...result,
readingTime: Math.max(1, Math.ceil(words / wpm)),
wordCount: words,
};
},
};
}
Tags
reading-timeword-countmetadata