Skip to content

Commit 2f55cff

Browse files
committed
feat: replace a with NuxtLink
1 parent 557f6a4 commit 2f55cff

File tree

4 files changed

+56
-10
lines changed

4 files changed

+56
-10
lines changed

playground/components/Docs.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### Markdown as Component
2+
3+
This is a components the wrote as markdown

playground/pages/foo.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Foo
2+
3+
[Go back](/)

playground/pages/index.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,11 @@
33
Nuxt Page as Markdown
44

55
<Counter />
6+
7+
<Docs />
8+
9+
Go to [/foo](/foo)
10+
11+
---
12+
13+
For [Nuxt](http://nuxt.com/)

src/module.ts

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,40 +10,72 @@ export default defineNuxtModule<ModuleOptions>({
1010
configKey: 'markdown',
1111
},
1212
setup(options, nuxt) {
13-
nuxt.options.extensions.push('.md')
13+
const extensions = ['md', 'markdown']
14+
15+
const reVue = /\.vue$/
16+
const reVueOrQuery = /\.vue($|\?)/
17+
const reEnding = new RegExp(`\\.(${extensions.join('|')})$`)
18+
const reEndingOrQuery = new RegExp(`\\.(${extensions.join('|')})($|\\?)`)
19+
const reWithVue = new RegExp(`\\.(${[...extensions, 'vue'].join('|')})$`)
20+
21+
nuxt.options.extensions.push(...extensions.map(ext => `.${ext}`))
1422

1523
nuxt.options.imports.transform ||= {}
16-
nuxt.options.imports.transform.include ||= [/\.vue$/]
24+
nuxt.options.imports.transform.include ||= [reVue]
1725
if (Array.isArray(nuxt.options.imports.transform.include))
18-
nuxt.options.imports.transform.include.push(/\.md$/)
26+
nuxt.options.imports.transform.include.push(reEnding)
1927

2028
if (nuxt.options.components !== false) {
2129
nuxt.options.components ||= {} as any
2230
const components = nuxt.options.components as any
2331
components.transform ||= {}
24-
components.transform.include ||= [/\.vue$/]
32+
components.transform.include ||= [reVue]
2533
if (Array.isArray(components.transform.include))
26-
components.transform.include.push(/\.md$/)
34+
components.transform.include.push(reEnding)
2735
}
2836

2937
if (nuxt.options.builder === '@nuxt/webpack-builder') {
3038
nuxt.hook('webpack:config', (configs) => {
3139
for (const config of configs) {
32-
const rule = config.module?.rules.find((r: any) => r.loader === 'vue-loader')
40+
const rule = config.module?.rules?.find((r: any) => r.loader === 'vue-loader')
3341
if (rule)
34-
rule.test = /\.(vue|md)$/
42+
(rule as any).test = reWithVue
3543
}
3644
})
3745
}
3846
else {
3947
nuxt.options.vite ||= {}
4048
nuxt.options.vite.vue ||= {}
41-
nuxt.options.vite.vue.include ||= [/\.vue($|\?)/]
49+
nuxt.options.vite.vue.include ||= [reVueOrQuery]
4250
if (Array.isArray(nuxt.options.vite.vue.include))
43-
nuxt.options.vite.vue.include.push(/\.md($|\?)/)
51+
nuxt.options.vite.vue.include.push(reEndingOrQuery)
4452
}
4553

46-
options.include = [/\.md($|\?)/]
54+
options.include = [reEndingOrQuery]
55+
const originalMarkdownItSetup = options.markdownItSetup
56+
options.markdownItSetup = async (md) => {
57+
await originalMarkdownItSetup?.(md)
58+
59+
// Replace <a> with <NuxtLink>
60+
md.core.ruler.push(
61+
'NuxtLink',
62+
(state) => {
63+
type Token = (typeof state.tokens)[0]
64+
function visit(token: Token) {
65+
if (token.tag === 'a') {
66+
token.tag = 'NuxtLink'
67+
// Replace `href` with `to`
68+
const hrefTag = token.attrs?.find(([name]) => name === 'href')
69+
if (hrefTag)
70+
hrefTag[0] = 'to'
71+
}
72+
token.children?.forEach(visit)
73+
}
74+
75+
state.tokens.forEach(visit)
76+
},
77+
)
78+
}
4779

4880
addVitePlugin(() => Markdown.vite(options))
4981
addWebpackPlugin(() => Markdown.webpack(options))

0 commit comments

Comments
 (0)