mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
fix(docs): preserve UTF-8 in raw Markdown navigation
This commit is contained in:
1 parent
23135e62dc
commit
cb464f1894
5 files changed
+25
-12
No files matched your search
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-09-15-docs-page-markdown-actions.md
|
||||
2026-09-15-docs-page-markdown-actions.md: d89b248496a9b80801f4d213ec2f845c7758cb52
|
||||
2026-09-15-docs-page-markdown-actions.zh.md: 6d2ebc9d72c3fadd46064034d67970723179ccba
|
||||
2026-09-15-docs-page-markdown-actions.md: cd8791f9491a0cbbe653d09753a4c0c7594970f4
|
||||
2026-09-15-docs-page-markdown-actions.zh.md: 211c0c069e4a4c8556458db2d4d226426f419af5
|
||||
@@ -12,7 +12,7 @@ Readers need a visible way to obtain one documentation page as Markdown. The pub
|
||||
|
||||
The [projector](../../../../scripts/project-doc-site.ts) supplies ordinary content pages with a `rawMarkdownPath` from the publication manifest. The [theme](../../../../website/.vitepress/theme/index.ts) combines that path with the site base and exposes copy and view actions above the document. Directory pages use their full `index.md` route, which preserves the same relative-link location in development and static builds. Redirect homes and missing pages have no actions. Raw output excludes projection metadata.
|
||||
|
||||
The [development middleware](../../../../website/raw-markdown.ts) admits explicitly marked `?dsh-raw=1` browser fetches and returns 404 for unpublished raw routes. Script imports always reach Vite. The view link opens the ordinary raw URL in a new tab; copy reads that same projected body on demand. Neither operation reconstructs Markdown from the rendered DOM.
|
||||
The [development middleware](../../../../website/raw-markdown.ts) admits explicitly marked `?dsh-raw=1` browser fetches and returns 404 for unpublished raw routes. Script imports always reach Vite. The view link opens the ordinary raw URL in a new tab; copy reads that same projected body on demand. Emitted Markdown files carry a UTF-8 BOM because static hosts can omit the response charset, causing direct browser navigation to misdecode Chinese and other non-ASCII characters. Fetch decoding removes the BOM before copying. Neither operation reconstructs Markdown from the rendered DOM.
|
||||
|
||||
The [copy component](../../../../website/.vitepress/theme/page-markdown-actions.ts) calls `clipboard.write` within the click gesture and supplies a promise-backed `text/plain` ClipboardItem. Awaiting the network first would lose user activation in browsers that require it. Each route and language gets its own keyed component instance; disposal aborts unfinished data reads and prevents old writes from changing new-page feedback. A system clipboard write that has already consumed its data cannot be withdrawn. Request and clipboard failures provide localized manual-copy guidance, and success follows the completed write. Denied writes may never consume their data promise, so that promise has its own rejection observer.
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Status: implemented
|
||||
|
||||
[投影器](../../../../scripts/project-doc-site.ts) 根据发布 manifest(元数据清单)为普通内容页提供 `rawMarkdownPath`。[主题](../../../../website/.vitepress/theme/index.ts) 将该路径与站点 base 组合,在正文上方提供复制和查看操作。目录页使用完整的 `index.md` 路由,使相对链接在开发环境和静态构建中保持相同的位置。首页重定向和缺失页面不显示操作。原文输出不包含投影元数据。
|
||||
|
||||
[开发中间件](../../../../website/raw-markdown.ts) 接受带有显式 `?dsh-raw=1` 标记的浏览器请求,对未发布的原文路由返回 404。脚本导入始终交给 Vite。查看链接在新标签页打开普通原文 URL;复制按需读取相同的投影正文。两种操作都不从渲染后的 DOM 重建 Markdown。
|
||||
[开发中间件](../../../../website/raw-markdown.ts) 接受带有显式 `?dsh-raw=1` 标记的浏览器请求,对未发布的原文路由返回 404。脚本导入始终交给 Vite。查看链接在新标签页打开普通原文 URL;复制按需读取相同的投影正文。生成的 Markdown 文件携带 UTF-8 BOM,因为静态托管可能省略响应字符集,导致浏览器直接访问时错误解码中文等非 ASCII 字符。Fetch 解码会在复制前移除 BOM。两种操作都不从渲染后的 DOM 重建 Markdown。
|
||||
|
||||
[复制组件](../../../../website/.vitepress/theme/page-markdown-actions.ts) 在点击手势内调用 `clipboard.write`,并提供由 Promise 承载数据的 `text/plain` ClipboardItem。先等待网络会在要求用户激活的浏览器中丢失该激活状态。每个路由和语言组合都有独立的、带 key 的组件实例;释放时取消未完成的数据读取,防止旧写入改变新页面的反馈。已经消费数据的系统剪贴板写入无法撤回。请求失败和剪贴板失败提供本地化的手动复制指引,成功提示在写入完成后显示。被拒绝的写入可能完全不消费数据 Promise,因此该 Promise 有独立的拒绝处理器。
|
||||
|
||||
|
||||
@@ -675,9 +675,9 @@ describe('emitRawMarkdownPages', () => {
|
||||
// The real path, because image placement proves containment via realpath.
|
||||
emitRawMarkdownPages(out, { pages, repoRoot: realpathSync(root), repositoryRef: 'abc123' })
|
||||
|
||||
expect(readFileSync(join(out, 'a.md'), 'utf8')).toBe('[B](./reference-root/b.md) \n')
|
||||
expect(readFileSync(join(out, 'en/a.md'), 'utf8')).toBe('[B](./reference/b.md) \n')
|
||||
expect(readFileSync(join(out, 'reference-root/b.md'), 'utf8')).toBe('# B\n')
|
||||
expect(readFileSync(join(out, 'a.md'), 'utf8')).toBe('\uFEFF[B](./reference-root/b.md) \n')
|
||||
expect(readFileSync(join(out, 'en/a.md'), 'utf8')).toBe('\uFEFF[B](./reference/b.md) \n')
|
||||
expect(readFileSync(join(out, 'reference-root/b.md'), 'utf8')).toBe('\uFEFF# B\n')
|
||||
expect(existsSync(join(out, 'logo.svg'))).toBe(true)
|
||||
expect(existsSync(join(out, 'en/logo.svg'))).toBe(true)
|
||||
})
|
||||
@@ -693,7 +693,7 @@ describe('emitRawMarkdownPages', () => {
|
||||
|
||||
emitRawMarkdownPages(out, { pages, repoRoot: root, repositoryRef: 'abc123' })
|
||||
|
||||
expect(readFileSync(join(out, 'index.md'), 'utf8')).toBe('# Home\n\n[A](./a.md)\n')
|
||||
expect(readFileSync(join(out, 'index.md'), 'utf8')).toBe('\uFEFF# Home\n\n[A](./a.md)\n')
|
||||
})
|
||||
|
||||
it('emits a parent-level alias for an index route with links recomputed', () => {
|
||||
@@ -709,8 +709,20 @@ describe('emitRawMarkdownPages', () => {
|
||||
|
||||
emitRawMarkdownPages(out, { pages, repoRoot: root, repositoryRef: 'abc123' })
|
||||
|
||||
expect(readFileSync(join(out, 'guide/index.md'), 'utf8')).toBe('# C\n\n[A](../a.md)\n')
|
||||
expect(readFileSync(join(out, 'guide.md'), 'utf8')).toBe('# C\n\n[A](./a.md)\n')
|
||||
expect(readFileSync(join(out, 'guide/index.md'), 'utf8')).toBe('\uFEFF# C\n\n[A](../a.md)\n')
|
||||
expect(readFileSync(join(out, 'guide.md'), 'utf8')).toBe('\uFEFF# C\n\n[A](./a.md)\n')
|
||||
})
|
||||
|
||||
it('identifies UTF-8 to document readers while fetch decoding preserves the Markdown body', async () => {
|
||||
const { root, pages } = fixture()
|
||||
const markdown = '# 中文 → Markdown\n'
|
||||
writeFileSync(join(root, 'docs/a.md'), markdown)
|
||||
const out = mirrorDir()
|
||||
emitRawMarkdownPages(out, { pages, repoRoot: root, repositoryRef: 'abc123' })
|
||||
const bytes = readFileSync(join(out, 'a.md'))
|
||||
expect([...bytes.subarray(0, 3)]).toEqual([0xef, 0xbb, 0xbf])
|
||||
expect(await new Response(bytes).text()).toBe(markdown)
|
||||
expect(fromMarkdown(bytes.toString('utf8')).children[0]?.type).toBe('heading')
|
||||
})
|
||||
|
||||
it('refuses to overwrite a file the build already carries', () => {
|
||||
|
||||
@@ -487,7 +487,8 @@ export function rawMarkdownFiles(pages: DocsPage[] = docsPages): string[] {
|
||||
* projected over the alias route so its relative links stay correct.
|
||||
* Referenced images are copied beside the pages, keeping the same relative
|
||||
* URLs valid in both trees. Existing build files stay in place, and a name
|
||||
* collision with one fails the emission.
|
||||
* collision with one fails the emission. Markdown files carry a UTF-8 BOM so
|
||||
* browser navigation decodes them even when static hosting omits a charset.
|
||||
*
|
||||
* @param outDir Build output directory to emit into.
|
||||
* @param context Manifest and repository inputs, defaulting to this repository.
|
||||
@@ -500,7 +501,7 @@ export function emitRawMarkdownPages(outDir: string, context: ProjectionContext
|
||||
projectPagesInto(
|
||||
outDir,
|
||||
context,
|
||||
(markdown, page) => rawMarkdownPageContent(markdown, page.source),
|
||||
(markdown, page) => `\uFEFF${rawMarkdownPageContent(markdown, page.source)}`,
|
||||
[...context.pages, ...aliases],
|
||||
)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user