From 299f8360ab7cf0b88409ed9072368d886639b132 Mon Sep 17 00:00:00 2001 From: mvm Date: Wed, 22 Jul 2026 23:59:55 -0500 Subject: [PATCH 1/3] Include Render partial headings in page TOC --- package.json | 2 +- pnpm-lock.yaml | 31 ++++++++++++++++--------------- src/pages/[...slug].astro | 9 ++++++++- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index b8e85d816a0..36f7cff3bf3 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@astrojs/rss": "4.0.18", "@astrojs/sitemap": "3.7.3", "@base-ui/react": "1.5.0", + "@cloudflare/nimbus-docs": "https://pkg.pr.new/@cloudflare/nimbus-docs@36", "@cloudflare/vitest-pool-workers": "0.16.15", "@cloudflare/workers-types": "4.20260615.1", "@docsearch/css": "3.9.0", @@ -112,7 +113,6 @@ "mermaid": "11.15.0", "micromark-extension-mdxjs": "3.0.0", "nanostores": "1.3.0", - "@cloudflare/nimbus-docs": "^0.6.1", "node-html-parser": "7.1.0", "openapi-types": "12.1.3", "parse-duration": "2.1.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3d0339d74ec..dc9a4151c93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,8 +39,8 @@ importers: specifier: 1.5.0 version: 1.5.0(@types/react@19.0.7)(date-fns@4.4.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@cloudflare/nimbus-docs': - specifier: ^0.6.1 - version: 0.6.1(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: https://pkg.pr.new/@cloudflare/nimbus-docs@36 + version: https://pkg.pr.new/@cloudflare/nimbus-docs@36(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@cloudflare/vitest-pool-workers': specifier: 0.16.15 version: 0.16.15(@cloudflare/workers-types@4.20260615.1)(@vitest/runner@4.1.9)(@vitest/snapshot@4.1.9)(vitest@4.1.9(@types/node@25.9.3)(happy-dom@20.10.3)(vite@8.1.5(@types/node@25.9.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))) @@ -779,8 +779,9 @@ packages: resolution: {integrity: sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==} engines: {node: '>=22.0.0'} - '@cloudflare/nimbus-docs@0.6.1': - resolution: {integrity: sha512-lqbzU/5MOGy5MvLv9uuKtKzBBA+ZQf1Od2svRE/7VLgRgqw5QVLOerNqs2sQ+at0Ipwd30IQgjj03bmVGn3C+Q==} + '@cloudflare/nimbus-docs@https://pkg.pr.new/@cloudflare/nimbus-docs@36': + resolution: {integrity: sha512-W8hUL1/EwUm0/4DZX21pyMbntjDs3/0D+QIbWuG6xxHToaLa24L7QDgss5GKDwawAUHl6PngRHCvUkRfM+uklQ==, tarball: https://pkg.pr.new/@cloudflare/nimbus-docs@36} + version: 0.7.0 engines: {node: '>=22.12.0'} hasBin: true peerDependencies: @@ -810,61 +811,61 @@ packages: vitest: ^4.1.0 '@cloudflare/workerd-darwin-64@1.20260611.1': - resolution: {integrity: sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260611.1.tgz} + resolution: {integrity: sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA==} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-64@1.20260701.1': - resolution: {integrity: sha512-Zd9Y1bah6DwwBN2RW8vJohffQrIUazb8UXnqSNecOxM+jJLhUuvv5IOG8dbHcV83TyZAubea6gsQXo2yH1lDdw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260701.1.tgz} + resolution: {integrity: sha512-Zd9Y1bah6DwwBN2RW8vJohffQrIUazb8UXnqSNecOxM+jJLhUuvv5IOG8dbHcV83TyZAubea6gsQXo2yH1lDdw==} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20260611.1': - resolution: {integrity: sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260611.1.tgz} + resolution: {integrity: sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20260701.1': - resolution: {integrity: sha512-yBLsjS1qCWqFyCY37qRUrYfzHHvMGvjh8zRKJ6MvUivYDhkZTzqduppK38FoqYvayLJ5KbcxH7zo5rkxGqbsaA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260701.1.tgz} + resolution: {integrity: sha512-yBLsjS1qCWqFyCY37qRUrYfzHHvMGvjh8zRKJ6MvUivYDhkZTzqduppK38FoqYvayLJ5KbcxH7zo5rkxGqbsaA==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-linux-64@1.20260611.1': - resolution: {integrity: sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260611.1.tgz} + resolution: {integrity: sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg==} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-64@1.20260701.1': - resolution: {integrity: sha512-vMfqSIMfoo4xmZXEuUVqLpSFS921YKjiR9q7kDXPi6Vld1PK74UHg9LZuBavT2KSyemHUCTpj9y/4JSYOEyQbQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260701.1.tgz} + resolution: {integrity: sha512-vMfqSIMfoo4xmZXEuUVqLpSFS921YKjiR9q7kDXPi6Vld1PK74UHg9LZuBavT2KSyemHUCTpj9y/4JSYOEyQbQ==} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20260611.1': - resolution: {integrity: sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260611.1.tgz} + resolution: {integrity: sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ==} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20260701.1': - resolution: {integrity: sha512-HRfwbKU2pK44V2NhoM0+iH0JJSj7nQ9Wv13ifIiGYCmTtDL8/zKtEhX7kQ3D4Vy/Cpjhttl0FkfqXj1aqLDPPg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260701.1.tgz} + resolution: {integrity: sha512-HRfwbKU2pK44V2NhoM0+iH0JJSj7nQ9Wv13ifIiGYCmTtDL8/zKtEhX7kQ3D4Vy/Cpjhttl0FkfqXj1aqLDPPg==} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-windows-64@1.20260611.1': - resolution: {integrity: sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260611.1.tgz} + resolution: {integrity: sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw==} engines: {node: '>=16'} cpu: [x64] os: [win32] '@cloudflare/workerd-windows-64@1.20260701.1': - resolution: {integrity: sha512-ngxCiIN9s/fM2o1IBMD0o1/mcXrv2NJVdyznh51UH8sQuvrTrXvV2nM0Uj/qU2wMwF6prgNBcdcd7AZeZGiBQA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260701.1.tgz} + resolution: {integrity: sha512-ngxCiIN9s/fM2o1IBMD0o1/mcXrv2NJVdyznh51UH8sQuvrTrXvV2nM0Uj/qU2wMwF6prgNBcdcd7AZeZGiBQA==} engines: {node: '>=16'} cpu: [x64] os: [win32] @@ -6884,7 +6885,7 @@ snapshots: '@cloudflare/kv-asset-handler@0.5.0': {} - '@cloudflare/nimbus-docs@0.6.1(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@cloudflare/nimbus-docs@https://pkg.pr.new/@cloudflare/nimbus-docs@36(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@astrojs/markdown-satteri': 0.3.4 '@astrojs/mdx': 7.0.3(@astrojs/markdown-satteri@0.3.4)(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0)) diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index 4a11d2d8c35..7ecfc02921f 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -20,7 +20,14 @@ const NOINDEX_PRODUCTS = ["email-security"]; export const prerender = true; export const getStaticPaths = getDocsStaticPaths; -const { entry, Content, headings } = await getDocsPageProps(Astro); +const { entry, Content, headings } = await getDocsPageProps(Astro, { + partialHeadings: { + resolvePartialId: ({ file, product }) => { + if (!file) return undefined; + return product ? `${product}/${file}` : file; + }, + }, +}); const currentSlug = Astro.url.pathname.replace(/\/$/, "") || "/"; const sectionSegment = currentSlug.split("/").filter(Boolean)[0]; From 0dcec8a83821228b2d4e3c657aa37da2336f69d1 Mon Sep 17 00:00:00 2001 From: mohamedh Date: Thu, 23 Jul 2026 12:55:32 +0100 Subject: [PATCH 2/3] fix: toc headers --- package.json | 7 +++- pnpm-lock.yaml | 35 +++++++++--------- src/pages/[...slug].astro | 19 +++++++++- src/util/rendered-toc.ts | 76 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 18 deletions(-) create mode 100644 src/util/rendered-toc.ts diff --git a/package.json b/package.json index 36f7cff3bf3..510089533c9 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@astrojs/rss": "4.0.18", "@astrojs/sitemap": "3.7.3", "@base-ui/react": "1.5.0", - "@cloudflare/nimbus-docs": "https://pkg.pr.new/@cloudflare/nimbus-docs@36", + "@cloudflare/nimbus-docs": "0.7.1", "@cloudflare/vitest-pool-workers": "0.16.15", "@cloudflare/workers-types": "4.20260615.1", "@docsearch/css": "3.9.0", @@ -158,5 +158,10 @@ "version": ">=24.0.0", "onFail": "error" } + }, + "pnpm": { + "overrides": { + "@cloudflare/nimbus-docs": "https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz" + } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc9a4151c93..65197a84e78 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + '@cloudflare/nimbus-docs': https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz + importers: .: @@ -39,8 +42,8 @@ importers: specifier: 1.5.0 version: 1.5.0(@types/react@19.0.7)(date-fns@4.4.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@cloudflare/nimbus-docs': - specifier: https://pkg.pr.new/@cloudflare/nimbus-docs@36 - version: https://pkg.pr.new/@cloudflare/nimbus-docs@36(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + specifier: https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz + version: https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@cloudflare/vitest-pool-workers': specifier: 0.16.15 version: 0.16.15(@cloudflare/workers-types@4.20260615.1)(@vitest/runner@4.1.9)(@vitest/snapshot@4.1.9)(vitest@4.1.9(@types/node@25.9.3)(happy-dom@20.10.3)(vite@8.1.5(@types/node@25.9.3)(esbuild@0.28.1)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))) @@ -779,9 +782,9 @@ packages: resolution: {integrity: sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==} engines: {node: '>=22.0.0'} - '@cloudflare/nimbus-docs@https://pkg.pr.new/@cloudflare/nimbus-docs@36': - resolution: {integrity: sha512-W8hUL1/EwUm0/4DZX21pyMbntjDs3/0D+QIbWuG6xxHToaLa24L7QDgss5GKDwawAUHl6PngRHCvUkRfM+uklQ==, tarball: https://pkg.pr.new/@cloudflare/nimbus-docs@36} - version: 0.7.0 + '@cloudflare/nimbus-docs@https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz': + resolution: {integrity: sha512-SkjnlaTY1qeE4W28SbRg9mOYTEbczIrfVd0+IseIKDT7RvoR7TjzAQForR4PfIZVeCwoiqkIWqS10KeJ28Q+UQ==, tarball: https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz} + version: 0.7.1 engines: {node: '>=22.12.0'} hasBin: true peerDependencies: @@ -811,61 +814,61 @@ packages: vitest: ^4.1.0 '@cloudflare/workerd-darwin-64@1.20260611.1': - resolution: {integrity: sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA==} + resolution: {integrity: sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260611.1.tgz} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-64@1.20260701.1': - resolution: {integrity: sha512-Zd9Y1bah6DwwBN2RW8vJohffQrIUazb8UXnqSNecOxM+jJLhUuvv5IOG8dbHcV83TyZAubea6gsQXo2yH1lDdw==} + resolution: {integrity: sha512-Zd9Y1bah6DwwBN2RW8vJohffQrIUazb8UXnqSNecOxM+jJLhUuvv5IOG8dbHcV83TyZAubea6gsQXo2yH1lDdw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260701.1.tgz} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20260611.1': - resolution: {integrity: sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ==} + resolution: {integrity: sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260611.1.tgz} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20260701.1': - resolution: {integrity: sha512-yBLsjS1qCWqFyCY37qRUrYfzHHvMGvjh8zRKJ6MvUivYDhkZTzqduppK38FoqYvayLJ5KbcxH7zo5rkxGqbsaA==} + resolution: {integrity: sha512-yBLsjS1qCWqFyCY37qRUrYfzHHvMGvjh8zRKJ6MvUivYDhkZTzqduppK38FoqYvayLJ5KbcxH7zo5rkxGqbsaA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260701.1.tgz} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-linux-64@1.20260611.1': - resolution: {integrity: sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg==} + resolution: {integrity: sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260611.1.tgz} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-64@1.20260701.1': - resolution: {integrity: sha512-vMfqSIMfoo4xmZXEuUVqLpSFS921YKjiR9q7kDXPi6Vld1PK74UHg9LZuBavT2KSyemHUCTpj9y/4JSYOEyQbQ==} + resolution: {integrity: sha512-vMfqSIMfoo4xmZXEuUVqLpSFS921YKjiR9q7kDXPi6Vld1PK74UHg9LZuBavT2KSyemHUCTpj9y/4JSYOEyQbQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260701.1.tgz} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20260611.1': - resolution: {integrity: sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ==} + resolution: {integrity: sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260611.1.tgz} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20260701.1': - resolution: {integrity: sha512-HRfwbKU2pK44V2NhoM0+iH0JJSj7nQ9Wv13ifIiGYCmTtDL8/zKtEhX7kQ3D4Vy/Cpjhttl0FkfqXj1aqLDPPg==} + resolution: {integrity: sha512-HRfwbKU2pK44V2NhoM0+iH0JJSj7nQ9Wv13ifIiGYCmTtDL8/zKtEhX7kQ3D4Vy/Cpjhttl0FkfqXj1aqLDPPg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260701.1.tgz} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-windows-64@1.20260611.1': - resolution: {integrity: sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw==} + resolution: {integrity: sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260611.1.tgz} engines: {node: '>=16'} cpu: [x64] os: [win32] '@cloudflare/workerd-windows-64@1.20260701.1': - resolution: {integrity: sha512-ngxCiIN9s/fM2o1IBMD0o1/mcXrv2NJVdyznh51UH8sQuvrTrXvV2nM0Uj/qU2wMwF6prgNBcdcd7AZeZGiBQA==} + resolution: {integrity: sha512-ngxCiIN9s/fM2o1IBMD0o1/mcXrv2NJVdyznh51UH8sQuvrTrXvV2nM0Uj/qU2wMwF6prgNBcdcd7AZeZGiBQA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260701.1.tgz} engines: {node: '>=16'} cpu: [x64] os: [win32] @@ -6885,7 +6888,7 @@ snapshots: '@cloudflare/kv-asset-handler@0.5.0': {} - '@cloudflare/nimbus-docs@https://pkg.pr.new/@cloudflare/nimbus-docs@36(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@cloudflare/nimbus-docs@https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@astrojs/markdown-satteri': 0.3.4 '@astrojs/mdx': 7.0.3(@astrojs/markdown-satteri@0.3.4)(astro@7.1.3(@astrojs/markdown-remark@7.2.1)(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@types/node@25.9.3)(jiti@2.7.0)(rollup@4.62.2)(tsx@4.22.4)(yaml@2.9.0)) diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index 7ecfc02921f..83e79ee19e5 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -14,6 +14,10 @@ import { config } from "virtual:nimbus/config"; import { docsSidebarTransform, getCfBreadcrumbs } from "../util/sidebar"; import { components } from "../mdx-components"; import { getOgImage } from "~/util/og"; +import { + pageHasRuntimeHeadings, + scrapeRenderedHeadings, +} from "../util/rendered-toc"; const NOINDEX_PRODUCTS = ["email-security"]; @@ -73,7 +77,20 @@ const editUrl = await getEditUrl(entry); // Frontmatter wins; git is the fallback. const lastUpdated = entry.data.lastUpdated ?? (await getLastUpdated(entry)); const tocConfig = entry.data.tableOfContents; -const tocHeadings = headings.filter((h) => h.slug !== "footnote-label"); +// Runtime (set:html) headings are missing from compile-time `headings`. +let tocSource = headings; +if ( + tocOn && + tocConfig !== false && + (await pageHasRuntimeHeadings(entry.body ?? "")) +) { + try { + tocSource = await scrapeRenderedHeadings(Content, components); + } catch (err) { + console.error(`[toc] rendered-heading scrape failed for ${entry.id}:`, err); + } +} +const tocHeadings = tocSource.filter((h) => h.slug !== "footnote-label"); const toc = tocOn && tocConfig !== false ? getTOC(tocHeadings, tocConfig) : false; const markdownPath = `/${entry.id}/index.md`; diff --git a/src/util/rendered-toc.ts b/src/util/rendered-toc.ts new file mode 100644 index 00000000000..bf281fda2fa --- /dev/null +++ b/src/util/rendered-toc.ts @@ -0,0 +1,76 @@ +import { getCollection } from "astro:content"; +import { experimental_AstroContainer as AstroContainer } from "astro/container"; +import { loadRenderers } from "astro:container"; +import { getContainerRenderer as getMdxRenderer } from "@astrojs/mdx"; +import { getContainerRenderer as getReactRenderer } from "@astrojs/react"; +import { getHeadingsFromHtml, type Heading } from "@cloudflare/nimbus-docs"; +import type { AstroComponentFactory } from "astro/runtime/server/index.js"; + +// AnchorHeading emits its at runtime via set:html, so those headings are +// absent from compile-time `render().headings`. Pages using it (directly or +// through a partial) must read headings from rendered HTML instead. +const RENDER_MARKER = "AnchorHeading"; + +function resolvePartialId(file?: string, product?: string): string | undefined { + if (!file) return undefined; + return product ? `${product}/${file}` : file; +} + +function renderRefs(body: string): string[] { + const ids: string[] = []; + for (const match of body.matchAll(/]*>/g)) { + const tag = match[0]; + const file = /\bfile=["']([^"']+)["']/.exec(tag)?.[1]; + const product = /\bproduct=["']([^"']+)["']/.exec(tag)?.[1]; + const id = resolvePartialId(file, product); + if (id) ids.push(id); + } + return ids; +} + +let dynamicPartials: Promise> | undefined; +async function computeDynamicPartials(): Promise> { + const bodies = new Map(); + for (const partial of await getCollection("partials")) { + bodies.set(partial.id, partial.body ?? ""); + } + + const dynamic = new Set(); + for (const [id, body] of bodies) { + if (body.includes(RENDER_MARKER)) dynamic.add(id); + } + let changed = true; + while (changed) { + changed = false; + for (const [id, body] of bodies) { + if (dynamic.has(id)) continue; + if (renderRefs(body).some((ref) => dynamic.has(ref))) { + dynamic.add(id); + changed = true; + } + } + } + return dynamic; +} + +export async function pageHasRuntimeHeadings(body: string): Promise { + if (!body) return false; + if (body.includes(RENDER_MARKER)) return true; + const dynamic = await (dynamicPartials ??= computeDynamicPartials()); + return renderRefs(body).some((ref) => dynamic.has(ref)); +} + +let containerPromise: Promise | undefined; +export async function scrapeRenderedHeadings( + Content: AstroComponentFactory, + components: Record, +): Promise { + containerPromise ??= loadRenderers([ + getMdxRenderer(), + getReactRenderer(), + ]).then((renderers) => AstroContainer.create({ renderers })); + const html = await ( + await containerPromise + ).renderToString(Content, { props: { components } }); + return getHeadingsFromHtml(html); +} From 42c2e4a05fd4d9aa1ca1071a7f94f483cf82b2f8 Mon Sep 17 00:00:00 2001 From: mohamedh Date: Thu, 23 Jul 2026 13:01:12 +0100 Subject: [PATCH 3/3] chore: deps --- package.json | 5 ----- pnpm-workspace.yaml | 8 ++++++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 510089533c9..cfd06ab0867 100644 --- a/package.json +++ b/package.json @@ -158,10 +158,5 @@ "version": ">=24.0.0", "onFail": "error" } - }, - "pnpm": { - "overrides": { - "@cloudflare/nimbus-docs": "https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz" - } } } diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index da1b4da06f8..5ccde3b6b7f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -18,6 +18,14 @@ minimumReleaseAgeExclude: # natively (nimbus-docs pulls markdown-satteri 0.3.4, @astrojs/mdx@7 peers # ^0.3.1), so the old allowedVersions override is obsolete and has been removed. +# Resolve @cloudflare/nimbus-docs from the public npm tarball. It is published to +# public npm, but a machine-global .npmrc rule routes the whole @cloudflare scope +# to the internal registry gateway (which does not mirror it). Pinning the tarball +# URL here bypasses that routing for this one package, leaving the scope rule (and +# every other @cloudflare/* dependency) untouched. Bump this URL on each release. +overrides: + "@cloudflare/nimbus-docs": "https://registry.npmjs.org/@cloudflare/nimbus-docs/-/nimbus-docs-0.7.1.tgz" + # Prevent transitive dependencies from using exotic sources (git repos, direct tarball URLs). # Only direct dependencies may use exotic sources. blockExoticSubdeps: true