From d38bb11c4da04d48dcd0fa2e0ceaeb870d05e1bf Mon Sep 17 00:00:00 2001 From: yi-ge Date: Sat, 19 Sep 2026 04:32:47 -0400 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=81=A2=E5=A4=8D=E5=8F=91=E8=A1=8C?= =?UTF-8?q?=E7=89=88=E6=9B=B4=E6=96=B0=E6=97=A5=E5=BF=97=E7=AB=A0=E8=8A=82?= =?UTF-8?q?=EF=BC=88=E4=B8=80=E5=BE=8B=20draft=EF=BC=89=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E8=AE=A9=E6=8E=A5=E5=8F=A3=E4=B8=8E=E5=B0=81=E9=9D=A2=E5=B0=8A?= =?UTF-8?q?=E9=87=8D=E8=8D=89=E7=A8=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 恢复发行版更新日志章节(中英)与 changelog-editions 条目:章节 index 带 draft: true, _category_.json 不再写 link(index 是草稿,生产构建里不存在);不恢复 05-more 的入口链接(死链会让构建失败) - changelog-json-plugin 尊重草稿:生产构建时草稿版本不进 /api/(仍输出合法的空列表), 草稿页面(中英)引用的封面图从站点输出中移除;开发环境行为不变 - 条目描述里写明草稿规则:发布流程写入的版本页面一律 draft: true,公开某个版本 = 把该页面的 draft 改为 false --- .../12-damo-solver-changelog/_category_.json | 4 + .../05-more/12-damo-solver-changelog/index.md | 17 ++++ .../12-damo-solver-changelog/_category_.json | 4 + .../05-more/12-damo-solver-changelog/index.md | 17 ++++ plugins/changelog-editions.json | 15 ++- plugins/changelog-json-plugin.ts | 96 +++++++++++++++++-- 6 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 docs/05-more/12-damo-solver-changelog/_category_.json create mode 100644 docs/05-more/12-damo-solver-changelog/index.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog/_category_.json create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog/index.md diff --git a/docs/05-more/12-damo-solver-changelog/_category_.json b/docs/05-more/12-damo-solver-changelog/_category_.json new file mode 100644 index 0000000..7288831 --- /dev/null +++ b/docs/05-more/12-damo-solver-changelog/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "达摩院AgentOS更新日志", + "position": 10 +} diff --git a/docs/05-more/12-damo-solver-changelog/index.md b/docs/05-more/12-damo-solver-changelog/index.md new file mode 100644 index 0000000..fc9dda8 --- /dev/null +++ b/docs/05-more/12-damo-solver-changelog/index.md @@ -0,0 +1,17 @@ +--- +title: "达摩院AgentOS更新日志" +description: "达摩院AgentOS版本更新历史记录" +keywords: [更新日志, 版本历史, changelog] +draft: true +--- + +# 达摩院AgentOS更新日志 + +本页记录达摩院AgentOS各版本的重要变更。 + +## 版本索引 + + + +| 版本 | 日期 | 概要 | +|------|------|------| diff --git a/i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog/_category_.json b/i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog/_category_.json new file mode 100644 index 0000000..02157f2 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "达摩院AgentOS Changelog", + "position": 10 +} diff --git a/i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog/index.md b/i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog/index.md new file mode 100644 index 0000000..c29b226 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog/index.md @@ -0,0 +1,17 @@ +--- +title: "达摩院AgentOS Changelog" +description: "达摩院AgentOS version changelog" +keywords: [changelog, version history, release notes] +draft: true +--- + +# 达摩院AgentOS Changelog + +This page records important changes in each version of 达摩院AgentOS. + +## Version Index + + + +| Version | Date | Summary | +|---------|------|---------| diff --git a/plugins/changelog-editions.json b/plugins/changelog-editions.json index 4247a7c..789c8d1 100644 --- a/plugins/changelog-editions.json +++ b/plugins/changelog-editions.json @@ -1,12 +1,12 @@ { - "description": "更新日志章节配置:每个条目是一个产品发行版的独立更新日志。plugins/changelog-json-plugin.ts 按条目读取 zhSourceDir 下的 v.md,构建时生成站点 /api/(客户端按发行版拉取);scripts/generate-changelog-cover.mjs --edition 按条目生成封面。DesireCore 发布流程只写 desirecore 章节;OEM 发布流程按 id 读取本文件定位章节目录,条目缺失时拒绝写入。新增发行版时追加条目并创建中英文两个章节目录(_category_.json 与 index.md,index.md 的表格分隔行与 desirecore 章节一致,发布流程据此插入版本行)。", + "description": "更新日志章节配置:每个条目是一个产品发行版的独立更新日志。plugins/changelog-json-plugin.ts 按条目读取 zhSourceDir 下的 v.md,构建时生成站点 /api/(客户端按发行版拉取);scripts/generate-changelog-cover.mjs --edition 按条目生成封面。DesireCore 发布流程只写 desirecore 章节;OEM 发布流程按 id 读取本文件定位章节目录,条目缺失时拒绝写入。新增发行版时追加条目并创建中英文两个章节目录(_category_.json 与 index.md,index.md 的表格分隔行与 desirecore 章节一致,发布流程据此插入版本行)。草稿:front matter 含 draft: true 的版本页面只在开发环境可见——生产构建不生成页面、不进 /api/(该文件仍会生成,版本列表为空)、其封面图也不随站点发布(见插件)。OEM 发布流程写入的版本页面一律带 draft: true,OEM 章节的 index.md 也应带 draft: true 且不在其他页面加入口链接(指向草稿页面的链接在生产构建中是死链);要公开某个版本,把该页面(中英)的 draft 改为 false 或删除该行。", "fields": { "id": "发行版更新日志 id(desirecore 仓库 editions//edition.json#distribution.changelogEdition)", "zhSourceDir": "中文章节目录(相对仓库根):版本页面 v.md 与 index.md 所在目录", "enSourceDir": "英文章节目录(相对仓库根)", "outputFile": "构建输出到站点 api/ 下的 JSON 文件名", "urlPrefix": "版本页面路由前缀(Docusaurus 去掉目录数字前缀后的路径);JSON 中 url = 站点地址 + urlPrefix + /v", - "coverImageDir": "封面图片输出目录(相对仓库根)", + "coverImageDir": "封面图片输出目录(相对仓库根);草稿页面引用的封面在生产构建中会从站点输出移除", "coverImageUrlPrefix": "版本页面中引用封面图片的路径前缀", "coverBrandText": "封面左上角的品牌字样", "coverWebsite": "封面右下角的网址;null 表示不显示" @@ -22,6 +22,17 @@ "coverImageUrlPrefix": "/img/changelog", "coverBrandText": "DESIRECORE", "coverWebsite": "www.desirecore.cn" + }, + { + "id": "damo-solver", + "zhSourceDir": "docs/05-more/12-damo-solver-changelog", + "enSourceDir": "i18n/en/docusaurus-plugin-content-docs/current/05-more/12-damo-solver-changelog", + "outputFile": "changelog-damo-solver.json", + "urlPrefix": "/more/damo-solver-changelog", + "coverImageDir": "static/img/changelog/damo-solver", + "coverImageUrlPrefix": "/img/changelog/damo-solver", + "coverBrandText": "达摩院AgentOS", + "coverWebsite": null } ] } diff --git a/plugins/changelog-json-plugin.ts b/plugins/changelog-json-plugin.ts index 2cfc057..b1a4127 100644 --- a/plugins/changelog-json-plugin.ts +++ b/plugins/changelog-json-plugin.ts @@ -4,6 +4,12 @@ * 按 plugins/changelog-editions.json 的每个发行版条目读取 /v*.md,解析 frontmatter 和 markdown sections, * 输出结构化 JSON 到 static/api/(开发+构建均可用)。 * desirecore 条目的源目录、输出名与 url 前缀与改为配置之前相同(api/changelog.json);OEM 发行版条目输出 api/changelog-.json。 + * + * 草稿:front matter 声明 draft: true 的版本页面,与 Docusaurus 对页面的处理一致——只在开发环境可见。 + * 生产构建时: + * - 草稿版本不进 JSON(条目仍输出合法的空列表:客户端拿到「没有版本」而不是 404); + * - 草稿页面(中英)引用的封面图从站点输出中移除——static/ 会原样复制进站点,不处理就能凭 URL 直接访问。 + * OEM 发行版的版本页面由发布流程一律写入 draft: true;公开某个版本 = 人工把该页面(中英)的 draft 改为 false 或删除该行。 */ import type { LoadContext, Plugin } from '@docusaurus/types' @@ -37,6 +43,8 @@ interface ChangelogJson { interface ChangelogEditionConfig { id: string zhSourceDir: string + /** 可选:草稿封面清理需要同时扫描英文章节;缺省只扫中文章节 */ + enSourceDir?: string outputFile: string urlPrefix: string } @@ -50,6 +58,23 @@ const SECTION_MAP: Record = { const SITE_URL = 'https://docs.desirecore.com' +/** 版本页面文件名(v10.0.16.md) */ +const VERSION_FILE_PATTERN = /^v\d+\.\d+\.\d+\.md$/ + +/** 版本页面中的配图(![...](/img/changelog/v10.0.17.png) 格式);JSON 的 coverImage 与草稿封面清理共用这一条规则 */ +const COVER_IMAGE_PATTERN = /!\[.*?\]\((\/img\/changelog\/[^)]+)\)/ + +/** 生产构建(docusaurus build)不发布草稿;开发环境(docusaurus start)草稿可见,与 Docusaurus 自身行为一致 */ +function isProduction(): boolean { + return process.env.NODE_ENV === 'production' +} + +/** front matter 是否声明 draft: true(Docusaurus 只认布尔 true) */ +function isDraft(content: string): boolean { + const frontMatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/) + return frontMatter !== null && /^draft:\s*true\s*$/m.test(frontMatter[1]) +} + /** * 从 markdown 文件内容中解析版本信息 */ @@ -63,8 +88,8 @@ function parseChangelogMd(content: string, fileName: string, urlPrefix: string): const dateMatch = content.match(/\*\*发布日期\*\*[::]\s*(\d{4}-\d{2}-\d{2})/) const date = dateMatch ? dateMatch[1] : '' - // 提取配图(![...](/img/changelog/v10.0.17.png) 格式) - const imageMatch = content.match(/!\[.*?\]\((\/img\/changelog\/[^)]+)\)/) + // 提取配图 + const imageMatch = content.match(COVER_IMAGE_PATTERN) const coverImage = imageMatch ? `${SITE_URL}${imageMatch[1]}` : undefined // 按 ## 标题分段解析 @@ -107,17 +132,26 @@ function parseChangelogMd(content: string, fileName: string, urlPrefix: string): } /** - * 生成 changelog.json 内容 + * 生成 changelog.json 内容;includeDrafts 为 false 时跳过草稿版本并返回跳过的个数 */ -function generateChangelogJson(changelogDir: string, urlPrefix: string): ChangelogJson { +function generateChangelogJson( + changelogDir: string, + urlPrefix: string, + includeDrafts: boolean, +): { data: ChangelogJson; skippedDrafts: number } { // 章节目录尚不存在时输出空列表:客户端拿到「没有版本」而不是 404 const files = fs.existsSync(changelogDir) - ? fs.readdirSync(changelogDir).filter((f) => /^v\d+\.\d+\.\d+\.md$/.test(f)) + ? fs.readdirSync(changelogDir).filter((f) => VERSION_FILE_PATTERN.test(f)) : [] const versions: ChangelogVersion[] = [] + let skippedDrafts = 0 for (const file of files) { const content = fs.readFileSync(path.join(changelogDir, file), 'utf-8') + if (!includeDrafts && isDraft(content)) { + skippedDrafts++ + continue + } const parsed = parseChangelogMd(content, file, urlPrefix) if (parsed) { versions.push(parsed) @@ -134,8 +168,11 @@ function generateChangelogJson(changelogDir: string, urlPrefix: string): Changel }) return { - generatedAt: new Date().toISOString(), - versions, + data: { + generatedAt: new Date().toISOString(), + versions, + }, + skippedDrafts, } } @@ -148,6 +185,31 @@ function writeChangelogJson(targetDir: string, outputFile: string, data: Changel fs.writeFileSync(path.join(apiDir, outputFile), JSON.stringify(data, null, 2), 'utf-8') } +/** + * 从站点输出目录移除草稿页面引用的封面图,返回移除的张数。 + * 封面路径来自页面正文,必须仍落在输出目录之内才会删除。 + */ +function removeDraftCovers(outDir: string, sourceDirs: string[]): number { + const root = path.resolve(outDir) + let removed = 0 + for (const dir of sourceDirs) { + if (!fs.existsSync(dir)) continue + for (const file of fs.readdirSync(dir).filter((f) => VERSION_FILE_PATTERN.test(f))) { + const content = fs.readFileSync(path.join(dir, file), 'utf-8') + if (!isDraft(content)) continue + const image = content.match(COVER_IMAGE_PATTERN)?.[1] + if (!image) continue + const target = path.resolve(root, `.${image}`) + if (!target.startsWith(root + path.sep)) continue + if (fs.existsSync(target)) { + fs.rmSync(target) + removed++ + } + } + } + return removed +} + /** * 读取并校验 plugins/changelog-editions.json;配置错误直接让构建失败 */ @@ -179,11 +241,17 @@ export default function changelogJsonPlugin(context: LoadContext): Plugin { /** 为每个发行版生成并写入 JSON */ function generateAll(targetDir: string, label: string): Record { + const includeDrafts = !isProduction() const results: Record = {} for (const edition of editions) { - const data = generateChangelogJson(path.join(context.siteDir, edition.zhSourceDir), edition.urlPrefix) + const { data, skippedDrafts } = generateChangelogJson( + path.join(context.siteDir, edition.zhSourceDir), + edition.urlPrefix, + includeDrafts, + ) writeChangelogJson(targetDir, edition.outputFile, data) - console.log(`[changelog-json-plugin] 已生成 ${label}/api/${edition.outputFile}(${data.versions.length} 个版本)`) + const skipped = skippedDrafts > 0 ? `,${skippedDrafts} 个草稿未收录` : '' + console.log(`[changelog-json-plugin] 已生成 ${label}/api/${edition.outputFile}(${data.versions.length} 个版本${skipped})`) results[edition.id] = data } return results @@ -197,9 +265,17 @@ export default function changelogJsonPlugin(context: LoadContext): Plugin { return generateAll(path.join(context.siteDir, 'static'), 'static') }, - // 构建模式:复制到 build 输出目录 + // 构建模式:复制到 build 输出目录;生产构建再移除草稿页面的封面(static/ 已被原样复制进输出目录) async postBuild({ outDir }) { generateAll(outDir, 'build') + if (!isProduction()) return + for (const edition of editions) { + const sourceDirs = [edition.zhSourceDir, edition.enSourceDir] + .filter((dir): dir is string => typeof dir === 'string' && dir !== '') + .map((dir) => path.join(context.siteDir, dir)) + const removed = removeDraftCovers(outDir, sourceDirs) + if (removed > 0) console.log(`[changelog-json-plugin] 已从 build 移除 ${edition.id} 的草稿封面 ${removed} 张`) + } }, } }