Skip to content

Commit cef1084

Browse files
committed
chore: opt-in reading time
1 parent 7670a78 commit cef1084

8 files changed

Lines changed: 27 additions & 7 deletions

File tree

.changeset/opt-in-reading-time.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@doc-kit/generator-react': minor
3+
---
4+
5+
Make reading time opt-in via `showReadingTime`

packages/react/src/html/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,9 @@ export default ({ metadata }) => (
416416
- `metadata` {Object} Serialized page metadata — all YAML frontmatter properties
417417
plus `addedIn`, `basename`, `path`, and any custom user-defined fields.
418418
- `headings` {Array} Pre-computed table of contents heading entries.
419-
- `readingTime` {string} Estimated reading time (e.g. `'5 min read'`).
419+
- `readingTime` {string|undefined} Estimated reading time (e.g. `'5 min read'`).
420+
Only present when the `jsx-ast` generator's `showReadingTime` option is
421+
enabled.
420422
- `children` {ComponentChildren} Processed page content.
421423

422424
The `Layout` component receives the props above. Custom Layout components can use

packages/react/src/html/ui/components/Layout/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import SideBar from '#theme/Sidebar';
1818
* main content, meta bar, and footer. Override via `#theme/Layout` in your
1919
* configuration's `imports` to customize the entire page structure.
2020
*
21-
* @param {{ metadata: import('../../types').SerializedMetadata, headings: Array, readingTime: string, children: import('preact').ComponentChildren }} props
21+
* @param {{ metadata: import('../../types').SerializedMetadata, headings: Array, readingTime?: string, children: import('preact').ComponentChildren }} props
2222
*/
2323
export default ({ metadata, headings, readingTime, children }) => {
2424
const crossLinkItems = navigation.showCrossLinks

packages/react/src/html/ui/components/MetaBar/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const HeadingValue = ({ value, stability }) => {
4949

5050
/**
5151
* MetaBar component that displays table of contents and page metadata
52-
* @param {{ metadata: import('../../types').SerializedMetadata, headings: Array, readingTime: string }} props
52+
* @param {{ metadata: import('../../types').SerializedMetadata, headings: Array, readingTime?: string }} props
5353
*/
5454
export default ({ metadata, headings = [], readingTime }) => {
5555
const editThisPage = editURL?.replace('{path}', metadata.path);

packages/react/src/jsx-ast/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ The `jsx-ast` generator converts MDAST (Markdown Abstract Syntax Tree) to JSX AS
1212
for `all.html`. **Default:** `true`.
1313
- `generateNotFoundPage` {boolean} When `true`, creates a synthetic JSX AST
1414
entry for `404.html`. **Default:** `true`.
15+
- `showReadingTime` {boolean} When `true`, computes an estimated reading time
16+
for each page and displays it in the MetaBar. **Default:** `false`.
1517

1618
## Index page
1719

packages/react/src/jsx-ast/index.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default {
1818
ref: 'main',
1919
generateAllPage: true,
2020
generateNotFoundPage: true,
21+
showReadingTime: false,
2122
},
2223

2324
hasParallelProcessor: true,

packages/react/src/jsx-ast/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export type Generator = GeneratorMetadata<
66
ref: string;
77
generateAllPage: boolean;
88
generateNotFoundPage: boolean;
9+
showReadingTime: boolean;
910
},
1011
Generate<Array<MetadataEntry>, AsyncGenerator<JSXContent>>,
1112
ProcessChunk<

packages/react/src/jsx-ast/utils/buildContent.mjs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { UNIST } from '@doc-kit/core/utils/queries/index.mjs';
1111
import { transformNodesToString } from '@doc-kit/core/utils/unist.mjs';
1212
import { h as createElement } from 'hastscript';
1313
import { slice } from 'mdast-util-slice-markdown';
14-
import readingTime from 'reading-time';
1514
import remarkParse from 'remark-parse';
1615
import { unified } from 'unified';
1716
import { u as createTree } from 'unist-builder';
@@ -50,6 +49,12 @@ const toPlainText = markdown =>
5049
unified().use(remarkParse).parse(markdown).children
5150
).trim();
5251

52+
/**
53+
*
54+
*/
55+
const readingTime = text =>
56+
import('reading-time').then(({ default: rt }) => rt(text).text);
57+
5358
/**
5459
* Processes lifecycle and change history data into a sorted array of change entries.
5560
* @param {import('@doc-kit/core/generators/metadata/types').MetadataEntry} entry - The metadata entry
@@ -315,16 +320,20 @@ export const processEntry = entry => {
315320
* @param {Array<import('@doc-kit/core/generators/metadata/types').MetadataEntry>} entries - API documentation metadata entries
316321
* @param {Object} metadata - Raw page metadata from the head entry
317322
*/
318-
export const createDocumentLayout = (entries, metadata) => {
323+
export const createDocumentLayout = async (entries, metadata) => {
319324
// Collapse overloaded function headings into one stable ToC entry, tagging the
320325
// underlying headings with compact anchors / overload flags read just below.
321326
annotateOverloads(entries);
322327

328+
const { showReadingTime } = getConfig('jsx-ast');
329+
323330
return createTree('root', [
324331
createJSXElement(JSX_IMPORTS.Layout.name, {
325332
metadata,
326333
headings: extractHeadings(entries),
327-
readingTime: readingTime(extractTextContent(entries)).text,
334+
readingTime: showReadingTime
335+
? await readingTime(extractTextContent(entries))
336+
: undefined,
328337
children: entries.map(processEntry),
329338
}),
330339
]);
@@ -348,7 +357,7 @@ const buildContent = async (metadataEntries, head) => {
348357
]);
349358

350359
// Create root document AST with all layout components and processed content
351-
const root = createDocumentLayout(metadataEntries, metadata);
360+
const root = await createDocumentLayout(metadataEntries, metadata);
352361

353362
// Run remark processor to transform AST (parse markdown, plugins, etc.)
354363
const ast = await remark().run(root);

0 commit comments

Comments
 (0)