fix: respect global tableOfContents config with zod v4#3751
fix: respect global tableOfContents config with zod v4#3751delucis merged 5 commits intowithastro:mainfrom
tableOfContents config with zod v4#3751Conversation
🦋 Changeset detectedLatest commit: 2339c0b The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for astro-starlight ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Hello! Thank you for opening your first PR to Starlight! ✨ Here’s what will happen next:
|
With zod v4, `.default(value).optional()` returns the default value for `undefined` input instead of `undefined` itself. This caused frontmatter `tableOfContents` to always resolve to the schema default, preventing the global Starlight config from being used as a fallback. This fix introduces a separate `FrontmatterTableOfContentsSchema` that omits `.default()` so `undefined` is preserved, and updates `getToC()` to properly merge frontmatter values with the global config. Closes withastro#3748
a22e322 to
18a01d0
Compare
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
- Remove old TableOfContentsSchema and duplicate FrontmatterTableOfContentsSchema - Rename TableOfContentsSchema to UserConfigTableOfContentsSchema in user-config.ts - Revert test additions (no logic changes in data.ts)
delucis
left a comment
There was a problem hiding this comment.
Perfect, thank you! I just pushed up some tests I was using to diagnose the issue locally, but this should be good to go!
Thanks again for contributing 🙌
|
this seems to fix the issue in dev ( |
|
Do you have an example you could point to @voytxt for us to debug? In theory at least there should be no dev/build difference to this API 🤔 |
|
I would presume this is some obscure caching bug? Could very easily be something completely different I have no idea... I managed to solve it however, both local prod and Vercel prod work properly now! I'm not exactly sure what solved it, but I can reitarate what steps I did. For local prod, I first tried deleting all gitignored directories and also building with For Vercel prod, nothing seemed to work, until I bumped Astro from 6.0.3 to 6.0.4. That seemed to magically fix it and I now also can't reproduce it on Vercel, even if I deploy the version with Astro 6.0.3. If it's not vite/astro directly, my hunch would be on pnpm (I use pnpm 10.32.1) doing some weird shenanigans, or possibly some dependency (tho I'm not sure if that's possible). For the sake of completeness, here they are: (latest versions of everything) "devDependencies": {
"@astrojs/starlight": "^0.38.1",
"@astrojs/vercel": "^10.0.0",
"astro": "^6.0.4",
"astro-vtbot": "^2.1.11",
"prettier": "^3.8.1",
"prettier-plugin-astro": "^0.14.1",
"sharp": "^0.34.5",
"starlight-sidebar-topics": "^0.7.1"
} |
|
Ohh, interesting. It is theoretically possible that the content collection cache could have caused an issue here! I would have expected that updating Starlight to 0.38.1 would have been enough to invalidate that but maybe not for some reason. Glad it’s working now anyway and thanks for letting us know — I’ll keep an eye out for anyone else hitting it. |
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@astrojs/starlight](https://starlight.astro.build) ([source](https://github.com/withastro/starlight/tree/HEAD/packages/starlight)) | [`0.38.0` → `0.38.1`](https://renovatebot.com/diffs/npm/@astrojs%2fstarlight/0.38.0/0.38.1) |  |  | --- ### Release Notes <details> <summary>withastro/starlight (@​astrojs/starlight)</summary> ### [`v0.38.1`](https://github.com/withastro/starlight/blob/HEAD/packages/starlight/CHANGELOG.md#0381) [Compare Source](https://github.com/withastro/starlight/compare/@astrojs/starlight@0.38.0...@astrojs/starlight@0.38.1) ##### Patch Changes - [#​3751](withastro/starlight#3751) [`fb955ff`](withastro/starlight@fb955ff) Thanks [@​pyxelr](https://github.com/pyxelr)! - Fixes a regression causing global `tableOfContents` config to be ignored </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41OS41IiwidXBkYXRlZEluVmVyIjoiNDMuNTkuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==--> Co-authored-by: Renovate Bot <renovate@zarantonello.dev> Co-committed-by: Renovate Bot <renovate@zarantonello.dev>

Description
tableOfContentsconfig ignored due to zod v4.default().optional()behavior change #3748.default(value).optional()returns the default value forundefinedinput instead ofundefineditself. This caused the frontmattertableOfContentsfield to always resolve to the schema default ({ minHeadingLevel: 2, maxHeadingLevel: 3 }), preventing the global Starlight config from being used as a fallback.Changes
schemas/tableOfContents.ts: Extracted a sharedTableOfContentsBaseSchemaand created two separate exports:UserConfigTableOfContentsSchema()— wraps the base with.default(defaults)for the user config.FrontmatterTableOfContentsSchema()— wraps the base with.optional()soundefinedis preserved when frontmatter does not set the field.schema.ts: Updated the frontmatter schema to useFrontmatterTableOfContentsSchema().utils/user-config.ts: Updated to useUserConfigTableOfContentsSchema().Testing
All 511 existing unit tests pass. The fix can be verified by setting a global
tableOfContentsconfig (e.g.,maxHeadingLevel: 4) and confirming it applies to pages that do not override it in frontmatter.A StackBlitz reproduction is available in the linked issue.