Skip to content

Commit b5b7759

Browse files
committed
feat: enable remark-mdc automatic unwrap
1 parent ff4e49c commit b5b7759

File tree

7 files changed

+93
-31
lines changed

7 files changed

+93
-31
lines changed

src/module.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,17 @@ export default defineNuxtModule<ModuleOptions>({
6565
},
6666
},
6767
build: {
68-
markdown: {},
68+
markdown: {
69+
remarkPlugins: {
70+
'remark-mdc': {
71+
options: {
72+
experimental: {
73+
autoUnwrap: true,
74+
},
75+
},
76+
},
77+
},
78+
},
6979
yaml: {},
7080
csv: {
7181
delimeter: ',',

src/types/module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,14 @@ export interface ModuleOptions {
8585
*
8686
* @default []
8787
*/
88-
remarkPlugins?: Array<string | [string, MarkdownPlugin]> | Record<string, false | MarkdownPlugin>
88+
remarkPlugins?: Record<string, false | MarkdownPlugin>
8989
/**
9090
* Register custom remark plugin to provide new feature into your markdown contents.
9191
* Checkout: https://github.com/rehypejs/rehype/blob/main/doc/plugins.md
9292
*
9393
* @default []
9494
*/
95-
rehypePlugins?: Array<string | [string, MarkdownPlugin]> | Record<string, false | MarkdownPlugin>
95+
rehypePlugins?: Record<string, false | MarkdownPlugin>
9696

9797
/**
9898
* Content module uses `shiki` to highlight code blocks.

src/utils/content/index.ts

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ type HighlightedNode = { type: 'element', properties?: Record<string, string | u
2222
let highlightPlugin: {
2323
instance: unknown
2424
key?: string
25-
theme?: Record<string, unknown>
26-
highlighter: Highlighter
25+
options?: {
26+
theme?: Record<string, unknown>
27+
highlighter: Highlighter
28+
}
29+
2730
}
2831
let highlightPluginPromise: Promise<typeof highlightPlugin>
2932
async function getHighlightPluginInstance(options: HighlighterOptions) {
@@ -61,32 +64,34 @@ async function _getHighlightPlugin(options: HighlighterOptions) {
6164
key,
6265
instance: rehypeHighlight,
6366
...options,
64-
highlighter: async (code, lang, theme, opts) => {
65-
const result = await highlighter(code, lang, theme, opts)
66-
const visitTree = {
67-
type: 'element',
68-
children: result.tree as Array<unknown>,
69-
}
70-
if (options.compress) {
71-
const stylesMap: Record<string, string> = {}
72-
visit(
73-
visitTree,
74-
node => !!(node as HighlightedNode).properties?.style,
75-
(_node) => {
76-
const node = _node as HighlightedNode
77-
const style = node.properties!.style!
78-
stylesMap[style] = stylesMap[style] || 's' + hash(style).substring(0, 4)
79-
node.properties!.class = `${node.properties!.class || ''} ${stylesMap[style]}`.trim()
80-
node.properties!.style = undefined
81-
},
82-
)
67+
options: {
68+
highlighter: async (code, lang, theme, opts) => {
69+
const result = await highlighter(code, lang, theme, opts)
70+
const visitTree = {
71+
type: 'element',
72+
children: result.tree as Array<unknown>,
73+
}
74+
if (options.compress) {
75+
const stylesMap: Record<string, string> = {}
76+
visit(
77+
visitTree,
78+
node => !!(node as HighlightedNode).properties?.style,
79+
(_node) => {
80+
const node = _node as HighlightedNode
81+
const style = node.properties!.style!
82+
stylesMap[style] = stylesMap[style] || 's' + hash(style).substring(0, 4)
83+
node.properties!.class = `${node.properties!.class || ''} ${stylesMap[style]}`.trim()
84+
node.properties!.style = undefined
85+
},
86+
)
8387

84-
result.style = Object.entries(stylesMap).map(([style, cls]) => `.${cls}{${style}}`).join('') + result.style
85-
}
88+
result.style = Object.entries(stylesMap).map(([style, cls]) => `.${cls}{${style}}`).join('') + result.style
89+
}
8690

87-
return result
91+
return result
92+
},
93+
theme: Object.fromEntries(bundledThemes),
8894
},
89-
theme: Object.fromEntries(bundledThemes),
9095
}
9196
}
9297
return highlightPlugin

src/utils/content/transformers/markdown.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async function importPlugins(plugins: Record<string, false | MarkdownPlugin> = {
6868
if (plugin) {
6969
resolvedPlugins[name] = {
7070
instance: plugin.instance || await import(/* @vite-ignore */ name).then(m => m.default || m),
71-
options: plugin,
71+
options: plugin.options || {},
7272
}
7373
}
7474
else {

src/utils/mdc.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import type { ModuleOptions } from '../types'
77
import { setParserOptions } from './content'
88

99
export async function installMDCModule(contentOptions: ModuleOptions, nuxt: Nuxt) {
10-
const options = nuxt.options as unknown as { mdc: MDCModuleOptions, content: ModuleOptions }
10+
const options = nuxt.options as unknown as { mdc: MDCModuleOptions }
1111
// Install mdc module
12-
const highlight = options.content?.build?.markdown?.highlight as unknown as MDCModuleOptions['highlight']
12+
const highlight = contentOptions.build?.markdown?.highlight as unknown as MDCModuleOptions['highlight']
1313

1414
options.mdc = defu({
1515
highlight: highlight !== false
@@ -22,6 +22,8 @@ export async function installMDCModule(contentOptions: ModuleOptions, nuxt: Nuxt
2222
headings: {
2323
anchorLinks: contentOptions.renderer.anchorLinks,
2424
},
25+
remarkPlugins: contentOptions.build?.markdown?.remarkPlugins,
26+
rehypePlugins: contentOptions.build?.markdown?.rehypePlugins,
2527
}, options.mdc) as MDCModuleOptions
2628

2729
// Hook into mdc configs and store them for parser

test/unit/parseContent.md-highlighter.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@ import type { MarkdownRoot } from '../../src/types/content'
1010

1111
const nuxtMock = {
1212
options: {
13+
content: {
14+
build: {
15+
markdown: {
16+
remarkPlugins: {
17+
'remark-mdc': {
18+
options: {
19+
experimental: {
20+
autoUnwrap: true,
21+
},
22+
},
23+
},
24+
},
25+
},
26+
},
27+
},
1328
mdc: {
1429
compress: false,
1530
highlight: {

test/unit/parseContent.md.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@ import { resolveCollection } from '../../src/utils/collection'
88

99
const nuxtMock = {
1010
options: {
11+
content: {
12+
build: {
13+
markdown: {
14+
remarkPlugins: {
15+
'remark-mdc': {
16+
options: {
17+
experimental: {
18+
autoUnwrap: true,
19+
},
20+
},
21+
},
22+
},
23+
},
24+
},
25+
},
1126
mdc: {
1227
compress: false,
1328
markdown: {
@@ -251,4 +266,19 @@ describe('Parser (.md)', () => {
251266
expect(parsed.body.children[0].props.id).toEqual('alert')
252267
}
253268
})
269+
270+
test('Unwrap component only child', async () => {
271+
const tests = [
272+
{ markdown: `::component\nHello\n::`, firstChild: { type: 'text', value: 'Hello' } },
273+
{ markdown: `::component\nHello :world\n::`, firstChild: { type: 'text', value: 'Hello ' } },
274+
{ markdown: `::component\n - item 1\n - item 2\n::`, firstChild: { type: 'element', tag: 'li' } },
275+
{ markdown: `:::component\n::nested-component\nHello\n::\n:::`, firstChild: { type: 'element', tag: 'nested-component' } },
276+
277+
]
278+
for (const { markdown, firstChild } of tests) {
279+
const parsed = await parseContent('content/index.md', markdown, collection, nuxtMock)
280+
281+
expect(parsed.body.children[0].children[0]).toMatchObject(firstChild)
282+
}
283+
})
254284
})

0 commit comments

Comments
 (0)