Skip to content

Commit

Permalink
feat: enable remark-mdc automatic unwrap
Browse files Browse the repository at this point in the history
  • Loading branch information
farnabaz committed Nov 15, 2024
1 parent ff4e49c commit b5b7759
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 31 deletions.
12 changes: 11 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,17 @@ export default defineNuxtModule<ModuleOptions>({
},
},
build: {
markdown: {},
markdown: {
remarkPlugins: {
'remark-mdc': {
options: {
experimental: {
autoUnwrap: true,
},
},
},
},
},
yaml: {},
csv: {
delimeter: ',',
Expand Down
4 changes: 2 additions & 2 deletions src/types/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ export interface ModuleOptions {
*
* @default []
*/
remarkPlugins?: Array<string | [string, MarkdownPlugin]> | Record<string, false | MarkdownPlugin>
remarkPlugins?: Record<string, false | MarkdownPlugin>
/**
* Register custom remark plugin to provide new feature into your markdown contents.
* Checkout: https://github.com/rehypejs/rehype/blob/main/doc/plugins.md
*
* @default []
*/
rehypePlugins?: Array<string | [string, MarkdownPlugin]> | Record<string, false | MarkdownPlugin>
rehypePlugins?: Record<string, false | MarkdownPlugin>

/**
* Content module uses `shiki` to highlight code blocks.
Expand Down
55 changes: 30 additions & 25 deletions src/utils/content/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ type HighlightedNode = { type: 'element', properties?: Record<string, string | u
let highlightPlugin: {
instance: unknown
key?: string
theme?: Record<string, unknown>
highlighter: Highlighter
options?: {
theme?: Record<string, unknown>
highlighter: Highlighter
}

}
let highlightPluginPromise: Promise<typeof highlightPlugin>
async function getHighlightPluginInstance(options: HighlighterOptions) {
Expand Down Expand Up @@ -61,32 +64,34 @@ async function _getHighlightPlugin(options: HighlighterOptions) {
key,
instance: rehypeHighlight,
...options,
highlighter: async (code, lang, theme, opts) => {
const result = await highlighter(code, lang, theme, opts)
const visitTree = {
type: 'element',
children: result.tree as Array<unknown>,
}
if (options.compress) {
const stylesMap: Record<string, string> = {}
visit(
visitTree,
node => !!(node as HighlightedNode).properties?.style,
(_node) => {
const node = _node as HighlightedNode
const style = node.properties!.style!
stylesMap[style] = stylesMap[style] || 's' + hash(style).substring(0, 4)
node.properties!.class = `${node.properties!.class || ''} ${stylesMap[style]}`.trim()
node.properties!.style = undefined
},
)
options: {
highlighter: async (code, lang, theme, opts) => {
const result = await highlighter(code, lang, theme, opts)
const visitTree = {
type: 'element',
children: result.tree as Array<unknown>,
}
if (options.compress) {
const stylesMap: Record<string, string> = {}
visit(
visitTree,
node => !!(node as HighlightedNode).properties?.style,
(_node) => {
const node = _node as HighlightedNode
const style = node.properties!.style!
stylesMap[style] = stylesMap[style] || 's' + hash(style).substring(0, 4)
node.properties!.class = `${node.properties!.class || ''} ${stylesMap[style]}`.trim()
node.properties!.style = undefined
},
)

result.style = Object.entries(stylesMap).map(([style, cls]) => `.${cls}{${style}}`).join('') + result.style
}
result.style = Object.entries(stylesMap).map(([style, cls]) => `.${cls}{${style}}`).join('') + result.style
}

return result
return result
},
theme: Object.fromEntries(bundledThemes),
},
theme: Object.fromEntries(bundledThemes),
}
}
return highlightPlugin
Expand Down
2 changes: 1 addition & 1 deletion src/utils/content/transformers/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ async function importPlugins(plugins: Record<string, false | MarkdownPlugin> = {
if (plugin) {
resolvedPlugins[name] = {
instance: plugin.instance || await import(/* @vite-ignore */ name).then(m => m.default || m),
options: plugin,
options: plugin.options || {},
}
}
else {
Expand Down
6 changes: 4 additions & 2 deletions src/utils/mdc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import type { ModuleOptions } from '../types'
import { setParserOptions } from './content'

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

options.mdc = defu({
highlight: highlight !== false
Expand All @@ -22,6 +22,8 @@ export async function installMDCModule(contentOptions: ModuleOptions, nuxt: Nuxt
headings: {
anchorLinks: contentOptions.renderer.anchorLinks,
},
remarkPlugins: contentOptions.build?.markdown?.remarkPlugins,
rehypePlugins: contentOptions.build?.markdown?.rehypePlugins,
}, options.mdc) as MDCModuleOptions

// Hook into mdc configs and store them for parser
Expand Down
15 changes: 15 additions & 0 deletions test/unit/parseContent.md-highlighter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ import type { MarkdownRoot } from '../../src/types/content'

const nuxtMock = {
options: {
content: {
build: {
markdown: {
remarkPlugins: {
'remark-mdc': {
options: {
experimental: {
autoUnwrap: true,
},
},
},
},
},
},
},
mdc: {
compress: false,
highlight: {
Expand Down
30 changes: 30 additions & 0 deletions test/unit/parseContent.md.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ import { resolveCollection } from '../../src/utils/collection'

const nuxtMock = {
options: {
content: {
build: {
markdown: {
remarkPlugins: {
'remark-mdc': {
options: {
experimental: {
autoUnwrap: true,
},
},
},
},
},
},
},
mdc: {
compress: false,
markdown: {
Expand Down Expand Up @@ -251,4 +266,19 @@ describe('Parser (.md)', () => {
expect(parsed.body.children[0].props.id).toEqual('alert')
}
})

test('Unwrap component only child', async () => {
const tests = [
{ markdown: `::component\nHello\n::`, firstChild: { type: 'text', value: 'Hello' } },
{ markdown: `::component\nHello :world\n::`, firstChild: { type: 'text', value: 'Hello ' } },
{ markdown: `::component\n - item 1\n - item 2\n::`, firstChild: { type: 'element', tag: 'li' } },
{ markdown: `:::component\n::nested-component\nHello\n::\n:::`, firstChild: { type: 'element', tag: 'nested-component' } },

]
for (const { markdown, firstChild } of tests) {
const parsed = await parseContent('content/index.md', markdown, collection, nuxtMock)

expect(parsed.body.children[0].children[0]).toMatchObject(firstChild)
}
})
})

0 comments on commit b5b7759

Please sign in to comment.