diff --git a/README.md b/README.md index 76e99ff..e1467e6 100644 --- a/README.md +++ b/README.md @@ -159,6 +159,7 @@ For example: ```md --- name: My Cool App +description: This is My Cool App --- # Hello World @@ -170,9 +171,49 @@ Will be rendered as ```html

Hello World

-

This is My Cool App

+

{{frontmatter.description}}

``` +You can override existing frontmatter values by passing the :frontmatter-merge prop to the component. + +```html + + + +``` + +Alternatively, you can replace all frontmatter values using the `:frontmatter-replace` prop. Any remaining frontmatter properties will not render and will be `undefined`. + +```html + + + +``` + +For example, if you use `:frontmatter-replace`, the `description` property will not be shown on the screen. + +> Use either `:frontmatter-merge` or `:frontmatter-replace` for a component. If both props are provided, only `:frontmatter-replace` will take effect. + It will also be passed to the wrapper component's props if you have set `wrapperComponent` option. ## Document head and meta diff --git a/src/core/markdown.ts b/src/core/markdown.ts index 141b62a..92ef599 100644 --- a/src/core/markdown.ts +++ b/src/core/markdown.ts @@ -171,7 +171,19 @@ export function createMarkdown(options: ResolvedOptions) { if (options.excerpt && !excerptKeyOverlapping && frontmatter.excerpt !== undefined) delete frontmatter.excerpt - scriptLines.push(`const frontmatter = ${JSON.stringify(frontmatter)}`) + scriptLines.push( + `import { computed } from 'vue'`, + 'const props = defineProps({ frontmatterMerge: { type: Object } })', + `const _frontmatter = ${JSON.stringify(frontmatter)}`, + `const frontmatter = computed(() => { + if (props.frontmatterReplace && typeof props.frontmatterReplace === 'object') { + const replaceKeys = Object.keys(props.frontmatterReplace) + return Object.entries(_frontmatter).reduce((acc, [key, value]) => ({ ...acc, [key]: replaceKeys.includes(key) ? value : undefined }), {}) + } + + return { ..._frontmatter, ...props.frontmatterMerge } +})`, + ) if (options.exportFrontmatter) { frontmatterExportsLines = Object.entries(frontmatter) @@ -183,7 +195,7 @@ export function createMarkdown(options: ResolvedOptions) { } if (!isVue2 && options.exposeFrontmatter && !hasExplicitExports()) - scriptLines.push('defineExpose({ frontmatter })') + scriptLines.push('defineExpose({ frontmatter: frontmatter.value })') if (!isVue2 && headEnabled && head) { // @ts-expect-error legacy option diff --git a/test/__snapshots__/excerpt.test.ts.snap b/test/__snapshots__/excerpt.test.ts.snap index fcbd749..0ae9c97 100644 --- a/test/__snapshots__/excerpt.test.ts.snap +++ b/test/__snapshots__/excerpt.test.ts.snap @@ -11,8 +11,18 @@ exports[`excerpt > raw excerpt 1`] = ` " `; @@ -32,7 +52,17 @@ exports[`transform > couldn't expose frontmatter 1`] = ` " " `; @@ -55,8 +95,18 @@ exports[`transform > export keyword frontmatters 1`] = ` " " `; @@ -105,8 +185,18 @@ exports[`transform > style 1`] = ` " `; @@ -116,8 +206,18 @@ exports[`transform > vue directives 1`] = `