fix: get mdc configs by calling mdc:configSources hook#3736
fix: get mdc configs by calling mdc:configSources hook#3736
mdc:configSources hook#3736Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
commit: |
📝 WalkthroughWalkthroughThe changes convert MDC configuration handling from eager, synchronous parsing to a lazy, asynchronous resolver pattern. The exported Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
8547381 to
a426486
Compare
nuxt.ready rather than in modules:doneThere was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/utils/mdc.ts (1)
19-30: Prevent duplicate config resolution on concurrent first access.Lines 21-27 can run more than once if multiple calls happen before
_configsis set. Cache the in-flight promise too.♻️ Suggested change
let _configs: MdcConfig[] | undefined +let _configsPromise: Promise<MdcConfig[]> | undefined setMdcConfigResolver(async () => { - if (!_configs) { - const paths: string[] = [] - await nuxt.callHook('mdc:configSources', paths) - const jiti = createJiti(nuxt.options.rootDir) - _configs = paths.length - ? await Promise.all(paths.map(path => jiti.import(path).then(m => (m as { default: MdcConfig }).default || m))) - : [] - } - return _configs + if (_configs) { + return _configs + } + _configsPromise ||= (async () => { + const paths: string[] = [] + await nuxt.callHook('mdc:configSources', paths) + const jiti = createJiti(nuxt.options.rootDir) + _configs = paths.length + ? await Promise.all(paths.map(path => jiti.import(path).then(m => (m as { default: MdcConfig }).default || m))) + : [] + return _configs + })() + return _configsPromise })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/utils/mdc.ts` around lines 19 - 30, The resolver passed to setMdcConfigResolver can run multiple times concurrently because only the resolved _configs is cached; instead cache the in-flight promise so concurrent calls await the same work. Modify the resolver in src/utils/mdc.ts to use a module-level variable (e.g., _configsPromise) and set it when starting the async work (calling nuxt.callHook('mdc:configSources'), createJiti(...) and Promise.all(paths.map(... jiti.import ...))) and have subsequent calls return await _configsPromise; once fulfilled assign the resulting array to _configs and clear/retain the promise as appropriate so only the first invocation does the import work.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/utils/mdc.ts`:
- Around line 23-26: The call to nuxt.callHook('mdc:configSources', paths) uses
an unreleased feature (PR `#471`) so paths may remain empty with
`@nuxtjs/mdc`@0.20.1; update the call to be defensive: detect the installed mdc
version or the presence of the hook support and only call
nuxt.callHook('mdc:configSources', paths) when supported, otherwise fall back to
the existing default sources or explicitly populate paths; reference the symbols
nuxt.callHook, 'mdc:configSources', and the paths variable in src/utils/mdc.ts,
or alternatively update the dependency constraint to a version that includes PR
`#471` before relying on the hook.
---
Nitpick comments:
In `@src/utils/mdc.ts`:
- Around line 19-30: The resolver passed to setMdcConfigResolver can run
multiple times concurrently because only the resolved _configs is cached;
instead cache the in-flight promise so concurrent calls await the same work.
Modify the resolver in src/utils/mdc.ts to use a module-level variable (e.g.,
_configsPromise) and set it when starting the async work (calling
nuxt.callHook('mdc:configSources'), createJiti(...) and
Promise.all(paths.map(... jiti.import ...))) and have subsequent calls return
await _configsPromise; once fulfilled assign the resulting array to _configs and
clear/retain the promise as appropriate so only the first invocation does the
import work.
| await nuxt.callHook('mdc:configSources', paths) | ||
| const jiti = createJiti(nuxt.options.rootDir) | ||
| const configs = await Promise.all(mdcConfigs.map(path => jiti.import(path).then(m => (m as { default: MdcConfig }).default || m))) | ||
|
|
||
| setParserOptions({ | ||
| mdcConfigs: configs, | ||
| }) | ||
| _configs = paths.length | ||
| ? await Promise.all(paths.map(path => jiti.import(path).then(m => (m as { default: MdcConfig }).default || m))) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python - <<'PY'
import json, glob
sections = ("dependencies", "peerDependencies", "devDependencies", "optionalDependencies")
print("Found `@nuxtjs/mdc` version constraints:")
for f in glob.glob("**/package.json", recursive=True):
try:
data = json.load(open(f))
except Exception:
continue
for s in sections:
v = (data.get(s) or {}).get("@nuxtjs/mdc")
if v:
print(f"{f} :: {s} -> {v}")
PY
for lock in pnpm-lock.yaml package-lock.json yarn.lock; do
if [ -f "$lock" ]; then
echo
echo "Entries in $lock:"
rg -n '@nuxtjs/mdc' "$lock" || true
fi
doneRepository: nuxt/content
Length of output: 361
🌐 Web query:
@nuxtjs/mdc mdc:configSources hook release version history PR 471
💡 Result:
- Hook:
mdc:configSourcesis a Nuxt hook exposed by@nuxtjs/mdcwith signature(configs: string[]) => void(i.e., modules can mutate/extend the list of MDC config source files). It’s present at least as far back as@nuxtjs/mdc@0.13.1(in the published type declarations). [3] - Relevant releases (where behavior around the hook is explicitly mentioned):
- v0.20.0 (Jan 15, 2026): “Call
mdc:configSourcesafter all modules have run” (PR Link to edit the page in Github is invalid #455). [2] - v0.20.1 (Feb 5, 2026): latest release shown on GitHub Releases at the time of writing (does not mention further
mdc:configSourceschanges). [2]
- v0.20.0 (Jan 15, 2026): “Call
- PR
#471(release status): PR feat(theme-docs): add locale simplified chinese support #471 titled “fix: don't memoise configs, and allow external modules to callmdc:configSources” is open as of Feb 27, 2026, and is intended to let external modules call the hook (not just listen) and to avoid memoizing configs, coordinated withnuxt/content#3736. It is not released yet (not included in the v0.20.1 notes). [1]
Sources: PR #471 page [1], nuxt-content/mdc GitHub Releases [2], @nuxtjs/mdc@0.13.1 type declarations (unpkg) [3].
🏁 Script executed:
#!/bin/bash
# Check if the code is using any features that would require PR `#471`
# PR `#471` is about allowing external modules to call the hook and avoiding memoization
# First, let's see the full context around the mdc hook usage
cat -n src/utils/mdc.ts | head -40Repository: nuxt/content
Length of output: 2008
🌐 Web query:
@nuxtjs/mdc v0.20.1 mdc:configSources hook usage external modules call
💡 Result:
In @nuxtjs/mdc, the Nuxt hook is typed as:
mdc:configSources:(configs: string[]) => void(you receive a mutable array of file paths and can push your own config source paths into it). [1]
Use it from an external Nuxt module
// modules/my-mdc-config/module.ts
import { defineNuxtModule, createResolver } from '@nuxt/kit'
export default defineNuxtModule({
setup(_options, nuxt) {
const { resolve } = createResolver(import.meta.url)
nuxt.hook('mdc:configSources', (configs) => {
// add your own MDC config source file(s)
configs.push(resolve('./mdc.config.ts'))
// configs.push(resolve('./another.mdc.config.ts'))
})
}
})Add your module after @nuxtjs/mdc in nuxt.config.ts so the hook exists when you register:
export default defineNuxtConfig({
modules: [
'@nuxtjs/mdc',
'~/modules/my-mdc-config'
]
})Notes
- This is a Nuxt (build-time) hook; use it from a Nuxt module (
nuxt.hook(...)), not from a runtime plugin. - The hook expects paths (
string[]), so you typically push resolved absolute paths to config files. [1]
Source(s): @nuxtjs/mdc type declarations showing the hook signature. [1]
References
[1] https://app.unpkg.com/%40nuxtjs/mdc%400.13.1/files/dist/module.d.mts
The mdc:configSources hook call requires unreleased features not available in v0.20.1.
Line 23 calls await nuxt.callHook('mdc:configSources', paths) to allow modules to populate the paths array. However, this requires PR #471 ("allow external modules to call mdc:configSources"), which is currently open and not released. The locked version @nuxtjs/mdc@0.20.1 predates this feature, meaning the hook call will succeed but paths will silently remain empty if no code in v0.20.1 processes it. Either upgrade the version constraint once PR #471 is released, or verify that v0.20.1 supports external hook calls via a different mechanism.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/utils/mdc.ts` around lines 23 - 26, The call to
nuxt.callHook('mdc:configSources', paths) uses an unreleased feature (PR `#471`)
so paths may remain empty with `@nuxtjs/mdc`@0.20.1; update the call to be
defensive: detect the installed mdc version or the presence of the hook support
and only call nuxt.callHook('mdc:configSources', paths) when supported,
otherwise fall back to the existing default sources or explicitly populate
paths; reference the symbols nuxt.callHook, 'mdc:configSources', and the paths
variable in src/utils/mdc.ts, or alternatively update the dependency constraint
to a version that includes PR `#471` before relying on the hook.
🔗 Linked issue
❓ Type of change
📚 Description
discovered whilst working on nuxt-content-twoslash, currently if a module also hooks into
mdc:configSourcesbut does so after nuxt content, any changes it makes will be silently dropped due to ordering.this instead moves to call the hook (and depends on nuxt-content/mdc#471)
Important
this should not be released before nuxt-content/mdc#471. the mdc pr is safe to release on its own, but it should be released, and then this PR should be released, depending on the newer version of mdc, or we'll lose 'local'
mdc.config.tsfiles📝 Checklist