fix duplicate documentation homepage content

This commit is contained in:
Yichen Jiang
2026-07-20 15:25:47 +08:00
parent 5833d70447
commit 99ce2ce8b4
3 changed files with 54 additions and 2 deletions

View File

@@ -14,6 +14,8 @@ Canonical Markdown remains in the repository tier that owns it. Product-facing g
`scripts/project-doc-site.ts` projects the manifest into the ignored `website/.generated/` directory before VitePress starts or builds. The generated tree follows public routes so VitePress navigation, locale detection, and local search share the same route vocabulary. Each page receives an `editSource` frontmatter field pointing to its canonical repository file; the edit-link callback reads only that page data, so public URLs remain independent of the source layout.
Locale home projections retain only the canonical YAML frontmatter. The repository-facing body can keep its H1 and bilingual source links, while the VitePress home theme owns the rendered hero and features and the site navigation owns locale switching.
The projector parses Markdown links without reserializing the document. A link to another published source becomes a site-relative route; a link to an unpublished repository file becomes a GitHub source link; a repository image becomes a raw GitHub URL. Missing relative targets fail projection. Unit tests pin these transformations, and `docs:check` runs the projector tests plus a production VitePress build as part of `doc-sync` and the parallel documentation gates.
Mermaid renders the canonical diagrams. The website workspace explicitly declares the five packages that `vitepress-plugin-mermaid` asks Vite to prebundle because pnpm's strict dependency isolation otherwise makes those transitive packages unavailable to the local development server; Knip records this runtime-only use as an intentional dependency exception.

View File

@@ -5,7 +5,7 @@ import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import { docsPages, type DocsPage } from '../website/docs.ts'
import { addProjectionFrontmatter, rewriteMarkdown } from './project-doc-site.ts'
import { addProjectionFrontmatter, projectedPageContent, rewriteMarkdown } from './project-doc-site.ts'
const roots: string[] = []
@@ -175,3 +175,33 @@ describe('addProjectionFrontmatter', () => {
)
})
})
describe('projectedPageContent', () => {
const page = (sidebar: DocsPage['sidebar']): DocsPage => ({
locale: 'root',
contentLocale: 'zh-CN',
source: 'docs/index.zh.md',
route: 'index.md',
label: 'Home',
sidebar,
section: 'Home',
order: 0,
})
it('omits the source-only body from locale home pages', () => {
expect(projectedPageContent(
'---\nlayout: home\nhero:\n name: Harness\n---\n\n# Harness\n\n[English](index.md) | 中文\n',
page(null),
)).toBe('---\nlayout: home\nhero:\n name: Harness\n---\n')
})
it('keeps the full body for ordinary pages', () => {
const markdown = '---\ntitle: Guide\n---\n\n# Guide\n'
expect(projectedPageContent(markdown, page('zh-guide'))).toBe(markdown)
})
it('rejects a locale home source without frontmatter', () => {
expect(() => projectedPageContent('# Harness\n', page(null)))
.toThrow('locale home source "docs/index.zh.md" must start with YAML frontmatter')
})
})

View File

@@ -268,6 +268,26 @@ export function addProjectionFrontmatter(markdown: string, sourcePath: string):
return `---\n${field}\n---\n\n${markdown}`
}
/**
* Select the Markdown rendered for one published page.
*
* @param markdown Rewritten canonical Markdown content.
* @param page Publication manifest entry for the content.
* @returns Full Markdown for ordinary pages or frontmatter-only Markdown for a locale home page.
*/
export function projectedPageContent(markdown: string, page: DocsPage): string {
if (page.sidebar !== null) return markdown
if (!markdown.startsWith('---\n')) {
throw new Error(`project-doc-site: locale home source ${JSON.stringify(page.source)} must start with YAML frontmatter.`)
}
const closingDelimiter = '\n---\n'
const closing = markdown.indexOf(closingDelimiter, 4)
if (closing === -1) {
throw new Error(`project-doc-site: locale home source ${JSON.stringify(page.source)} has unclosed YAML frontmatter.`)
}
return markdown.slice(0, closing + closingDelimiter.length)
}
/** Canonical Markdown files watched by the local VitePress dev server. */
export function docsSourceFiles(): string[] {
return [...new Set(docsPages.map(page => resolve(root, page.source)))]
@@ -297,6 +317,6 @@ export function projectDocs(): void {
repoRoot: root,
repositoryRef,
})
writeFileSync(output, addProjectionFrontmatter(projected, page.source))
writeFileSync(output, addProjectionFrontmatter(projectedPageContent(projected, page), page.source))
}
}