diff --git a/docs/shared/support-timeline-generation.md b/docs/shared/support-timeline-generation.md index 26b0a03..39ee591 100644 --- a/docs/shared/support-timeline-generation.md +++ b/docs/shared/support-timeline-generation.md @@ -177,7 +177,7 @@ The shared display-window file is required when at least one configured roadmap Each branch matching a documented major (for example `2.x`) links to that version's published landing page when it exists: `v2/index.md` in portable Markdown and the corresponding explicit `.html` resource on the website. A missing, draft, or unlisted version landing page leaves the branch label as plain text. No documentation page is invented. -Published version landing pages absent from the branch list remain accessible through a short documentation-version list below the support table. +The Documentation versions section below the support table links to every published version landing page, including versions already linked in the table. When no roadmap is established, that list follows the default message; it is navigation, not a support schedule. Navigation and version-status messages link to the library index, including when its roadmap has not yet been established. diff --git a/scripts/roadmap-publication.mjs b/scripts/roadmap-publication.mjs index 78e7eed..ba789ba 100644 --- a/scripts/roadmap-publication.mjs +++ b/scripts/roadmap-publication.mjs @@ -16,18 +16,16 @@ function versionLink(library, version, label, html) { children: [text(label)] }; } -function remainingVersionNodes(roadmap, library, versions, html) { - const represented = new Set((roadmap?.branches ?? []).map(({ version }) => /^(?:v)?([1-9][0-9]*)\.x$/u.exec(version)?.[1])); - const remaining = versions.filter((version) => !represented.has(version.slice(1))); - if (!remaining.length) return []; +function documentationVersionNodes(library, versions, html) { + if (!versions.length) return []; return [heading('Documentation versions'), { type: 'list', ordered: false, spread: false, - children: remaining.map((version) => ({ type: 'listItem', spread: false, children: [{ type: 'paragraph', + children: versions.map((version) => ({ type: 'listItem', spread: false, children: [{ type: 'paragraph', children: [versionLink(library, version, version, html)] }] })) }]; } /** Portable MDAST shared by Docusaurus and Markdown export; no HTML or MDX. */ export function roadmapSupportNodes(input, { library = input?.library, versions = [], html = false } = {}) { - if (input === null) return [paragraph('The roadmap for this library has not been established yet.'), ...remainingVersionNodes(null, library, versions, html)]; + if (input === null) return [paragraph('The roadmap for this library has not been established yet.'), ...documentationVersionNodes(library, versions, html)]; const roadmap = validateRoadmapData(input); if (!roadmap.branches.length) return roadmapSupportNodes(null, { library: roadmap.library, versions, html }); const image = `../assets/roadmaps/${roadmap.library}.svg`; @@ -64,7 +62,7 @@ export function roadmapSupportNodes(input, { library = input?.library, versions align: headers.map(() => null), children: [ { type: 'tableRow', children: headers.map((value) => ({ type: 'tableCell', children: [text(value)] })) }, ...rows, ] }); - return [...children, ...remainingVersionNodes(roadmap, roadmap.library, versions, html)]; + return [...children, ...documentationVersionNodes(roadmap.library, versions, html)]; } export function appendRoadmapSupport(tree, sourcePath, roadmaps, { html = false } = {}) { diff --git a/tests/roadmap-publication.test.mjs b/tests/roadmap-publication.test.mjs index d778d4c..134e10c 100644 --- a/tests/roadmap-publication.test.mjs +++ b/tests/roadmap-publication.test.mjs @@ -199,12 +199,18 @@ test('fully unannounced branches remain a configured roadmap', async (t) => { }); -test('documented versions absent from the schedule stay reachable without inventing branch data', () => { +test('documentation versions list includes every published version even when linked in the support table', () => { for (const input of [roadmap(), null]) { - const nodes = roadmapSupportNodes(input, { library: 'example-library', versions: ['v1', 'v2'] }); - const list = nodes.find(({ type }) => type === 'list'); - const links = list.children.map((item) => item.children[0].children[0]); - assert.deepEqual(links.map(({ url }) => url), input ? ['v2/index.md'] : ['v1/index.md', 'v2/index.md']); - if (!input) assert.ok(!nodes.some(({ type }) => type === 'table')); + for (const html of [false, true]) { + const nodes = roadmapSupportNodes(input, { library: 'example-library', versions: ['v1', 'v2'], html }); + const list = nodes.find(({ type }) => type === 'list'); + const links = list.children.map((item) => item.children[0].children[0]); + assert.deepEqual(links.map(({ url }) => url), html + ? ['pathname:///example-library/v1/index.html', 'pathname:///example-library/v2/index.html'] + : ['v1/index.md', 'v2/index.md']); + assert.deepEqual(links.map(({ children }) => children[0].value), ['v1', 'v2']); + if (!input) assert.ok(!nodes.some(({ type }) => type === 'table')); + } } + assert.ok(!roadmapSupportNodes(roadmap(), { versions: [] }).some(({ type }) => type === 'list')); });