Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions src/utils/content/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@ import { getOrderedSchemaKeys } from '../../runtime/internal/schema'
import { transformContent } from './transformers'
import pathMetaTransformer from './transformers/path-meta'

let parserOptions = {
mdcConfigs: [] as MdcConfig[],
}
export function setParserOptions(opts: Partial<typeof parserOptions>) {
parserOptions = defu(opts, parserOptions)
let _getMdcConfigs: (() => Promise<MdcConfig[]>) | undefined

export function setMdcConfigResolver(fn: () => Promise<MdcConfig[]>) {
_getMdcConfigs = fn
}

type HighlighterOptions = Exclude<MDCModuleOptions['highlight'], false | undefined> & { compress: boolean }
Expand Down Expand Up @@ -70,7 +69,7 @@ async function _getHighlightPlugin(key: string, options: HighlighterOptions) {
// Configure the bundled languages
bundledLangs: Object.fromEntries(bundledLangs),
engine: createOnigurumaEngine(import('shiki/wasm')),
getMdcConfigs: () => Promise.resolve(parserOptions.mdcConfigs),
getMdcConfigs: () => _getMdcConfigs?.() ?? Promise.resolve([]),
})

highlightPlugin = {
Expand Down
23 changes: 14 additions & 9 deletions src/utils/mdc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Nuxt } from '@nuxt/schema'
import { extendViteConfig } from '@nuxt/kit'
import { createJiti } from 'jiti'
import type { ModuleOptions } from '../types'
import { setParserOptions } from './content'
import { setMdcConfigResolver } from './content'

export async function configureMDCModule(contentOptions: ModuleOptions, nuxt: Nuxt) {
const mdcOptions = (nuxt.options as unknown as { mdc: MDCModuleOptions }).mdc
Expand All @@ -12,16 +12,21 @@ export async function configureMDCModule(contentOptions: ModuleOptions, nuxt: Nu
...(contentOptions.renderer.alias || {}),
}

// Hook into mdc configs and store them for parser
nuxt.hook('mdc:configSources', async (mdcConfigs) => {
if (mdcConfigs.length) {
// Provide a lazy resolver for mdc configs. When the highlighter needs
// configs it fires mdc:configSources to collect paths from all modules
// (including file-based configs registered by @nuxtjs/mdc), then imports
// them. This avoids any dependency on modules:done hook ordering.
let _configs: MdcConfig[] | undefined
setMdcConfigResolver(async () => {
if (!_configs) {
const paths: string[] = []
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)))
Comment on lines +23 to +26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

🧩 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
done

Repository: nuxt/content

Length of output: 361


🌐 Web query:

@nuxtjs/mdc mdc:configSources hook release version history PR 471

πŸ’‘ Result:

  • Hook: mdc:configSources is a Nuxt hook exposed by @nuxtjs/mdc with 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:configSources after 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:configSources changes). [2]
  • 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 call mdc: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 with nuxt/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 -40

Repository: 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.

: []
}
return _configs
})

// Update mdc optimizeDeps options
Expand Down
Loading