Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/index-page-from-input.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@doc-kit/generator-react': patch
---

Generate `index.html` from the input `index` document instead of a synthetic page
9 changes: 7 additions & 2 deletions packages/react/src/jsx-ast/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ The `jsx-ast` generator converts MDAST (Markdown Abstract Syntax Tree) to JSX AS
documentation structure.
- `generateAllPage` {boolean} When `true`, creates a synthetic JSX AST entry
for `all.html`. **Default:** `true`.
- `generateIndexPage` {boolean} When `true`, creates a synthetic JSX AST entry
for `index.html`. **Default:** `true`.
- `generateNotFoundPage` {boolean} When `true`, creates a synthetic JSX AST
entry for `404.html`. **Default:** `true`.

## Index page

`index.html` is generated when an `index` document is part of the input, and
is rendered from that document like any other page. A section containing a
`<!-- DOCUMENTATION_INDEX -->` comment additionally receives the Stability
Overview table of all modules.
47 changes: 46 additions & 1 deletion packages/react/src/jsx-ast/__tests__/generate.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ describe('jsx-ast generate', () => {

const jsxAstConfig = getConfig('jsx-ast');
jsxAstConfig.generateAllPage = false;
jsxAstConfig.generateIndexPage = false;
jsxAstConfig.generateNotFoundPage = false;

const seenItems = [];
Expand All @@ -95,4 +94,50 @@ describe('jsx-ast generate', () => {
['index', 'fs']
);
});

it('only generates an index page when an index document is an input', async () => {
await setConfig({ target: ['jsx-ast'] });

const jsxAstConfig = getConfig('jsx-ast');
jsxAstConfig.generateAllPage = false;
jsxAstConfig.generateNotFoundPage = false;

const seenItems = [];
await collect(
generate([createEntry('fs', 'File system')], createWorker(seenItems))
);

assert.deepEqual(
seenItems.map(({ head }) => head.api),
['fs']
);
});

it('places the stability overview at the DOCUMENTATION_INDEX comment', async () => {
await setConfig({ target: ['jsx-ast'] });

const jsxAstConfig = getConfig('jsx-ast');
jsxAstConfig.generateAllPage = false;
jsxAstConfig.generateNotFoundPage = false;

const index = createEntry('index', 'Index', { stabilityIndex: null });
// The metadata parser turns a `<!-- DOCUMENTATION_INDEX -->` comment into
// this tag on the entry of the section containing it.
index.tags = ['DOCUMENTATION_INDEX'];

const seenItems = [];
await collect(
generate(
[index, createEntry('fs', 'File system')],
createWorker(seenItems)
)
);

const [{ entries }] = seenItems;
const table = entries[0].content.children.at(-1);

assert.equal(table.tagName, 'table');
const [row] = table.children.at(-1).children;
assert.equal(row.children[0].children[0].properties.href, 'fs.html');
});
});
11 changes: 8 additions & 3 deletions packages/react/src/jsx-ast/generate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { groupNodesByModule } from '@doc-kit/core/utils/generators.mjs';
import { jsx, toJs } from 'estree-util-to-js';

import buildContent from './utils/buildContent.mjs';
import { injectDocumentationIndex } from './utils/documentationIndex.mjs';
import { getSortedHeadNodes } from './utils/getSortedHeadNodes.mjs';
import { buildNotFoundPage } from './utils/synthetic/404.mjs';
import { buildAllPage } from './utils/synthetic/all.mjs';
import { buildIndexPage } from './utils/synthetic/index.mjs';

/**
* Builds the `{ head, entries }` page descriptors for all configured synthetic
Expand All @@ -21,7 +21,6 @@ const buildSyntheticDescriptors = input => {

return [
config.generateAllPage && buildAllPage(input),
config.generateIndexPage && buildIndexPage(input),
config.generateNotFoundPage && buildNotFoundPage(),
].filter(Boolean);
};
Expand Down Expand Up @@ -60,9 +59,15 @@ export async function processChunk(slicedInput, itemIndices) {
* @type {import('./types').Generator['generate']}
*/
export async function* generate(input, worker) {
// The synthetic `index` page replaces the Core `index` document.
// The `index` page is only generated when an `index` document is part of
// the input; the module list for the synthetic pages and the stability
// overview excludes it.
const moduleInput = input.filter(entry => entry.api !== 'index');

// Sections tagged with a `<!-- DOCUMENTATION_INDEX -->` comment (e.g. in
// the `index` document) receive the Stability Overview of all modules.
injectDocumentationIndex(input, moduleInput);

// Create sliced input: each item contains head + its module's entries
// This avoids sending all 4700+ entries to every worker
const groupedModules = groupNodesByModule(input);
Expand Down
1 change: 0 additions & 1 deletion packages/react/src/jsx-ast/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default {
defaultConfiguration: {
ref: 'main',
generateAllPage: true,
generateIndexPage: true,
generateNotFoundPage: true,
},

Expand Down
1 change: 0 additions & 1 deletion packages/react/src/jsx-ast/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export type Generator = GeneratorMetadata<
{
ref: string;
generateAllPage: boolean;
generateIndexPage: boolean;
generateNotFoundPage: boolean;
},
Generate<Array<MetadataEntry>, AsyncGenerator<JSXContent>>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';

import { buildIndexPage, buildStabilityOverview } from '../index.mjs';
import {
buildStabilityOverview,
injectDocumentationIndex,
} from '../documentationIndex.mjs';

const fakeHead = (api, name, stabilityIndex, depth = 1) => ({
api,
Expand All @@ -20,32 +23,59 @@ const fakeHead = (api, name, stabilityIndex, depth = 1) => ({
const findChild = (node, tagName) =>
node.children.find(child => child.tagName === tagName);

describe('buildIndexPage', () => {
it('returns a synthetic `index` head with an "Index" heading', () => {
const { head } = buildIndexPage([]);
describe('injectDocumentationIndex', () => {
const createEntry = tags => ({
...fakeHead('index', 'Index', null),
tags,
content: { type: 'root', children: [] },
});

it('appends the overview to entries tagged DOCUMENTATION_INDEX', () => {
const tagged = createEntry(['DOCUMENTATION_INDEX']);
const untagged = createEntry(undefined);

injectDocumentationIndex(
[tagged, untagged],
[fakeHead('fs', 'fs', 2), fakeHead('assert', 'assert', 2)]
);

assert.equal(head.api, 'index');
assert.equal(head.path, '/index');
assert.equal(head.basename, 'index');
assert.equal(head.heading.data.name, 'Index');
assert.equal(head.synthetic, true);
const table = findChild(tagged.content, 'table');
assert.equal(findChild(table, 'tbody').children.length, 2);
assert.equal(untagged.content.children.length, 0);
});

it('sorts the stability overview rows alphabetically by API name', () => {
const { entries } = buildIndexPage([
fakeHead('fs', 'fs', 2),
fakeHead('assert', 'assert', 2),
fakeHead('crypto', 'crypto', 2),
]);
const entry = createEntry(['DOCUMENTATION_INDEX']);

injectDocumentationIndex(
[entry],
[
fakeHead('fs', 'fs', 2),
fakeHead('assert', 'assert', 2),
fakeHead('crypto', 'crypto', 2),
]
);

const table = findChild(entries[0].content, 'table');
const table = findChild(entry.content, 'table');
const rows = findChild(table, 'tbody').children;
const names = rows.map(
row => row.children[0].children[0].children[0].value
);

assert.deepEqual(names, ['assert', 'crypto', 'fs']);
});

it('excludes module heads without a stability index', () => {
const entry = createEntry(['DOCUMENTATION_INDEX']);

injectDocumentationIndex(
[entry],
[fakeHead('fs', 'fs', 2), fakeHead('synopsis', 'Usage', null)]
);

const table = findChild(entry.content, 'table');
assert.equal(findChild(table, 'tbody').children.length, 1);
});
});

describe('buildStabilityOverview', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import { h as createElement } from 'hastscript';

import { createSyntheticHead, wrapAsEntry } from './synthetic.mjs';
import { JSX_IMPORTS } from '../../../html/constants.mjs';
import { createJSXElement } from '../ast.mjs';
import { getSortedHeadNodes } from '../getSortedHeadNodes.mjs';
import { createJSXElement } from './ast.mjs';
import { getSortedHeadNodes } from './getSortedHeadNodes.mjs';
import { JSX_IMPORTS } from '../../html/constants.mjs';

// The metadata parser turns bare HTML comments into entry tags, so a
// `<!-- DOCUMENTATION_INDEX -->` comment in a source document surfaces as
// this tag on the entry for the section containing it.
export const DOCUMENTATION_INDEX_TAG = 'DOCUMENTATION_INDEX';

const STABILITY_BADGE_KINDS = [
'error',
Expand Down Expand Up @@ -62,20 +66,21 @@ export const buildStabilityOverview = headEntries =>
]);

/**
* Builds the page descriptor for `index.html`
* Places the Stability Overview into every entry whose source section
* contains a `<!-- DOCUMENTATION_INDEX -->` comment. The parser strips the
* comment itself, so the table lands at the end of the tagged section.
*
* @param {Array<import('@doc-kit/core/generators/metadata/types').MetadataEntry>} entries
* @param {Array<import('@doc-kit/core/generators/metadata/types').MetadataEntry>} entries - Entries to scan for the tag
* @param {Array<import('@doc-kit/core/generators/metadata/types').MetadataEntry>} moduleEntries - Entries providing the module heads for the overview
*/
export const buildIndexPage = entries => {
const head = createSyntheticHead('index', 'Index');
const moduleEntries = getSortedHeadNodes(entries);
export const injectDocumentationIndex = (entries, moduleEntries) => {
const headEntries = getSortedHeadNodes(moduleEntries).filter(
entry => entry.stability
);

return {
head,
entries: [
wrapAsEntry(head, [
buildStabilityOverview(moduleEntries.filter(entry => entry.stability)),
]),
],
};
for (const entry of entries) {
if (entry.tags?.includes(DOCUMENTATION_INDEX_TAG)) {
entry.content.children.push(buildStabilityOverview(headEntries));
}
}
};
1 change: 0 additions & 1 deletion scripts/vercel-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ node packages/cli/bin/cli.mjs generate \
-c "./node/CHANGELOG.md" \
-v "$NODE_VERSION" \
--type-map "./node/doc/type-map.json" \
--index "./node/doc/api/index.md" \
--config-file "./beta/doc-kit.config.mjs" \
--log-level debug

Expand Down
3 changes: 3 additions & 0 deletions scripts/vercel-prepare.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ cd node
# Enable sparse checkout and specify the folder
git sparse-checkout set lib doc .

sed 's/STABILITY_OVERVIEW_SLOT_BEGIN/DOCUMENTATION_INDEX/g' ./doc/api/documentation.md > ./doc/api/index.md
rm ./doc/api/documentation.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is a content change not design/build pipeline. IMO we must not change the content for now but only change the ui/way to have info.

So to solve that just copy the index.html as documentation.md

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plan (at least for me) is to duplicate this change in core as a part of the migration, so making the preview mirror that ideal change is something I wanted to do. We spoke a bit on this in a web team meeting, and iirc we agreed that moving these pages was ideal, hence this change


# Move back out
cd ..

Expand Down
7 changes: 0 additions & 7 deletions www/doc-kit.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,6 @@ export default {
minify: true,
},

'jsx-ast': {
// `jsx-ast` otherwise synthesizes an `index.html` holding the Node.js API
// stability overview, and it silently overrides an authored `index.md`.
// This site has no stability metadata, so that page would render empty.
generateIndexPage: false,
},

html: {
title: '{project} documentation',

Expand Down
Loading