diff --git a/docs/scripts/blog-articles-manifest.json b/docs/scripts/blog-articles-manifest.json index db0513f9a..252d9521e 100644 --- a/docs/scripts/blog-articles-manifest.json +++ b/docs/scripts/blog-articles-manifest.json @@ -445,6 +445,11 @@ "sha256": "1e2ee21c697ab9c2320094874889e2ac0bd2fc44efb529eafa4d895393ca5691", "bytes": 161907 }, + { + "path": "/images/articles/langbot-wechat-official-account-qr.png", + "sha256": "233aede79ed71fd721f1f77c839d726b9dd8ed667f5e951d994c19f962c6bff5", + "bytes": 14931 + }, { "path": "/images/articles/source/images/article-mcp/01-init-page.png", "sha256": "b392e42d582c8c1723a2eb63596801b9d459df0465377246d9a4015edcae1ca0", @@ -589,6 +594,31 @@ "path": "/images/articles/source/images/sandbox-skills/skills.png", "sha256": "6ad86d972c7438fbef898d9d339f3f17a30277bf1626e8a9dd11b0b46583c817", "bytes": 362173 + }, + { + "path": "/images/articles/telegram-sandbox-qr.png", + "sha256": "8b4ead3dacb357fd28b650d2a6761b265effdeecc8e6a3f1f9feed10122da04b", + "bytes": 5583 + }, + { + "path": "/images/articles/telegram-sandbox.jpg", + "sha256": "0dab8f9c9c6846f8ac3b8848d118bca3528868254a7249d0d26772175eabae84", + "bytes": 349163 + }, + { + "path": "/images/articles/wecom-customer-service-qr.png", + "sha256": "3d2c2be11af63528a1b09871157ba58b4f3b64d7ddcbdf4420b99ecd41984c3b", + "bytes": 202053 + }, + { + "path": "/images/articles/wecom-customer-service.jpg", + "sha256": "2b94049e6265ffb1ac67cde661c596780d7fcfaeae46517ebd82f4dbfe3a1e19", + "bytes": 310163 + }, + { + "path": "/images/articles/wecom-knowledge-base-config.png", + "sha256": "0e4b12cec9bccf7c8a4958e9a53d312707ad818ac4376b707a20e8793af8f8be", + "bytes": 112097 } ] } diff --git a/docs/scripts/sync-blog-articles.mjs b/docs/scripts/sync-blog-articles.mjs index a3c90d024..76c1f7f29 100755 --- a/docs/scripts/sync-blog-articles.mjs +++ b/docs/scripts/sync-blog-articles.mjs @@ -231,6 +231,8 @@ async function renderArticle(sourceRoot, post, locale, fallback, assetRoot, imag const config = LANGUAGE_CONFIG[locale]; const title = locale === "ja" && fallback ? (JAPANESE_TITLES[post.slug] || post.data.title) : post.data.title; let body = post.body; + // Root-relative Blog links belong to the landing site, not the embedded docs. + body = body.replace(/(\]\()\/(en|zh|ja)\/blog\//g, "$1https://langbot.app/$2/blog/"); const refs = imageReferences(body); for (const ref of refs) if (!imageCache.has(ref.url)) imageCache.set(ref.url, await materializeImage(sourceRoot, ref.url, assetRoot)); if (post.data.cover?.image && !imageCache.has(post.data.cover.image)) imageCache.set(post.data.cover.image, await materializeImage(sourceRoot, post.data.cover.image, assetRoot)); diff --git a/docs/tests/agent-static-build.test.mjs b/docs/tests/agent-static-build.test.mjs index a03bf5ee1..c477e5971 100644 --- a/docs/tests/agent-static-build.test.mjs +++ b/docs/tests/agent-static-build.test.mjs @@ -23,7 +23,8 @@ function links(node, result = []) { } test("every sitemap page has meaningful canonical Markdown and HTML discovery", async () => { - assert.equal(urls.length, 509 + zhOnlyArticleRoutes.length); + const manifest = JSON.parse(await readFile(path.join(root, "scripts/blog-articles-manifest.json"), "utf8")); + assert.equal(urls.length, 473 + zhOnlyArticleRoutes.length + manifest.articles.length); for (const url of urls) { const route = relative(url); const text = await read(`${route}.md`); diff --git a/docs/tests/blog-articles.test.mjs b/docs/tests/blog-articles.test.mjs index 3fe853c4a..1b5f68cda 100644 --- a/docs/tests/blog-articles.test.mjs +++ b/docs/tests/blog-articles.test.mjs @@ -58,6 +58,7 @@ test("generated articles use only non-empty Wiki-local images", () => { const file = path.join(root, `${article.page}.mdx`); assert.ok(existsSync(file), `missing ${article.page}.mdx`); const content = readFileSync(file, "utf8"); + assert.doesNotMatch(content, /\]\(\/(?:en|zh|ja)\/blog\//, `${article.page} has a Blog link relative to the docs mount`); const imageUrls = [...content.matchAll(/!\[[^\]]*\]\(([^)]+)\)/g)].map((match) => match[1]); for (const imageUrl of imageUrls) { assert.match(imageUrl, /^\/images\/articles\//, `${article.page} hotlinks ${imageUrl}`); diff --git a/docs/tests/locale-static-build.test.mjs b/docs/tests/locale-static-build.test.mjs index 91ebc66db..6ececb51b 100644 --- a/docs/tests/locale-static-build.test.mjs +++ b/docs/tests/locale-static-build.test.mjs @@ -35,6 +35,7 @@ test("every localized HTML payload includes the preference client provider", asy } } for (const locale of ["en", "zh", "ja"]) await visit(path.join(root, locale)); - // 509 canonical content pages plus one framework 404 page per locale. - assert.equal(count, 515); + // Every sitemap page plus one framework 404 page per locale. + const sitemap = await readFile(path.join(root, "sitemap.xml"), "utf8"); + assert.equal(count, [...sitemap.matchAll(//g)].length + 3); });