[
  {
    "path": ".github/FUNDING.yml",
    "content": "open_collective: antfu\ngithub: [antfu]\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    tags:\n      - 'v*'\n\njobs:\n  release:\n    uses: sxzz/workflows/.github/workflows/release.yml@v1\n    with:\n      publish: true\n    permissions:\n      contents: write\n      id-token: write\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Test\n\non:\n  push:\n    branches:\n      - main\n      - master\n\n  pull_request:\n    branches:\n      - main\n      - master\n\njobs:\n  build:\n    runs-on: ${{ matrix.os }}\n\n    strategy:\n      matrix:\n        node-version: [20.x, lts/*]\n        os: [ubuntu-latest, windows-latest, macos-latest]\n      fail-fast: false\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Setup\n        run: npm i -g pnpm @antfu/ni\n\n      - name: Install\n        run: nci\n\n      - name: Build\n        run: nr build\n\n      - name: Test\n        run: nr test --if-present\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\n.DS_Store\ndist\nexample/README.md\n.idea/\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  // Enable the ESlint flat config support\n  \"eslint.experimental.useFlatConfig\": true,\n\n  // Disable the default formatter, use eslint instead\n  \"prettier.enable\": false,\n  \"editor.formatOnSave\": false,\n\n  // Auto fix\n  \"editor.codeActionsOnSave\": {\n    \"source.fixAll\": \"explicit\",\n    \"source.organizeImports\": \"never\"\n  },\n\n  // Silent the stylistic rules in you IDE, but still auto fix them\n  \"eslint.rules.customizations\": [\n    { \"rule\": \"style/*\", \"severity\": \"off\" },\n    { \"rule\": \"*-indent\", \"severity\": \"off\" },\n    { \"rule\": \"*-spacing\", \"severity\": \"off\" },\n    { \"rule\": \"*-spaces\", \"severity\": \"off\" },\n    { \"rule\": \"*-order\", \"severity\": \"off\" },\n    { \"rule\": \"*-dangle\", \"severity\": \"off\" },\n    { \"rule\": \"*-newline\", \"severity\": \"off\" },\n    { \"rule\": \"*quotes\", \"severity\": \"off\" },\n    { \"rule\": \"*semi\", \"severity\": \"off\" }\n  ],\n\n  // Enable eslint for all supported languages\n  \"eslint.validate\": [\n    \"javascript\",\n    \"javascriptreact\",\n    \"typescript\",\n    \"typescriptreact\",\n    \"vue\",\n    \"html\",\n    \"markdown\",\n    \"json\",\n    \"jsonc\",\n    \"yaml\"\n  ]\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020-PRESENT Anthony Fu<https://github.com/antfu>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# unplugin-vue-markdown\n\n[![NPM version](https://img.shields.io/npm/v/unplugin-vue-markdown?color=a1b858)](https://www.npmjs.com/package/unplugin-vue-markdown)\n\nCompile Markdown to Vue component.\n\n- 📚 Use Markdown as Vue components.\n- 💚 Use Vue components in Markdown.\n- 🔌 Supports Vite, Webpack, Vue CLI and more, powered by [unplugin](https://github.com/unjs/unplugin).\n- ⚡️ The same transformation as [VitePress](https://vitepress.vuejs.org/).\n\n## Install\n\n```bash\nnpm i unplugin-vue-markdown\n```\n\n<details>\n<summary>Vite</summary><br>\n\n```ts\n// vite.config.ts\nimport Vue from '@vitejs/plugin-vue'\nimport Markdown from 'unplugin-vue-markdown/vite'\n\nexport default defineConfig({\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/], // <-- allows Vue to compile Markdown files\n    }),\n    Markdown({ /* options */ }),\n  ],\n})\n```\n\nExample: [`examples/vite`](./examples/vite/)\n\n<br>\n</details>\n\n<details>\n<summary>Webpack</summary><br>\n\n```ts\n// webpack.config.js\nconst Markdown = require('unplugin-vue-markdown/webpack')\nconst { VueLoaderPlugin } = require('vue-loader')\n\nmodule.exports = {\n  /* ... */\n  module: {\n    rules: [\n      // ... other rules\n      {\n        test: /\\.(vue|md)$/,\n        loader: 'vue-loader'\n      }\n    ]\n  },\n  plugins: [\n    new VueLoaderPlugin(),\n    Markdown({ /* options */ })\n  ]\n}\n```\n\n<br>\n</details>\n\n<details>\n<summary>Vue CLI</summary><br>\n\n```ts\n// vue.config.js\nconst Markdown = require('unplugin-vue-markdown/webpack')\n\nmodule.exports = {\n  parallel: false, // Disable thread-loader which will cause errors, we are still investigating the root cause\n  chainWebpack: (config) => {\n    config.module\n      .rule('vue')\n      .test(/\\.(vue|md)$/) // <-- allows Vue to compile Markdown files\n\n    config\n      .plugin('markdown')\n      .use(Markdown({\n        markdownUses: [\n          prism,\n        ],\n      }))\n  },\n}\n```\n\nExample: [`examples/vue-cli`](./examples/vue-cli/)\n\n<br>\n</details>\n\n## Import Markdown as Vue components\n\n```html\n<template>\n  <HelloWorld />\n</template>\n\n<script>\nimport HelloWorld from './README.md'\n\nexport default {\n  components: {\n    HelloWorld,\n  },\n}\n</script>\n```\n\n## Use Vue Components inside Markdown\n\nYou can even use Vue components inside your markdown, for example\n\n```html\n<Counter :init='5'/>\n```\n\n<Counter :init='5'/>\n\nNote you can either register the components globally, or use the `<script setup>` tag to register them locally.\n\n```ts\nimport { createApp } from 'vue'\nimport App from './App.vue'\nimport Counter from './Counter.vue'\n\nconst app = createApp(App)\n\n// register global\napp.component('Counter', Counter) // <--\n\napp.mount()\n```\n\n```html\n<script setup>\nimport { Counter } from './Counter.vue'\n</script>\n\n<Counter :init='5'/>\n```\n\nOr you can use [`unplugin-vue-components`](#work-with-unplugin-vue-components) for auto components registration.\n\n## Frontmatter\n\nFrontmatter will be parsed and inject into Vue's instance data `frontmatter` field.\n\nFor example:\n\n```md\n---\nname: My Cool App\n---\n\n# Hello World\n\nThis is {{frontmatter.name}}\n```\n\nWill be rendered as\n\n```html\n<h1>Hello World</h1>\n<p>This is My Cool App</p>\n```\n\nIt will also be passed to the wrapper component's props if you have set `wrapperComponent` option.\n\n## Document head and meta\n\nTo manage document head and meta, you would need to install [`@unhead/vue`](https://unhead.harlanzw.com/integrations/vue/setup) and do some setup.\n\n```bash\nnpm i @unhead/vue\n```\n\n```js\n// vite.config.js\nimport Vue from '@vitejs/plugin-vue'\nimport Markdown from 'unplugin-vue-markdown/vite'\n\nexport default {\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/],\n    }),\n    Markdown({\n      headEnabled: true // <--\n    })\n  ]\n}\n```\n\n```js\n// src/main.js\nimport { createHead } from '@unhead/vue/client' // <--\nimport { createApp } from 'vue'\n\nconst app = createApp(App)\n\nconst head = createHead() // <--\napp.use(head) // <--\n```\n\nThen you can use frontmatter to control the head. For example:\n\n```yaml\n---\ntitle: My Cool App\nmeta:\n  - name: description\n    content: Hello World\n---\n```\n\nFor more options available, please refer to [`@unhead/vue`'s docs](https://unhead.harlanzw.com/integrations/vue/setup).\n\n## Options\n\n`unplugin-vue-markdown` uses [`markdown-exit`](https://github.com/nicepkg/markdown-exit) under the hood, a TypeScript rewrite of markdown-it with built-in async rendering. markdown-it plugins are compatible.\n\n> **Note:** The old option names (`markdownItOptions`, `markdownItUses`, `markdownItSetup`) are deprecated but still functional.\n\n```ts\n// vite.config.js\nimport MarkdownItAnchor from 'markdown-it-anchor'\nimport MarkdownItPrism from 'markdown-it-prism'\nimport Markdown from 'unplugin-vue-markdown/vite'\n\nexport default {\n  plugins: [\n    Markdown({\n      // default options passed to markdown-exit\n      markdownOptions: {\n        html: true,\n        linkify: true,\n        typographer: true,\n      },\n      // A function providing the markdown-exit instance gets the ability to apply custom settings/plugins\n      markdownSetup(md) {\n        // for example\n        md.use(MarkdownItAnchor)\n        md.use(MarkdownItPrism)\n      },\n      // Class names for the wrapper div\n      wrapperClasses: 'markdown-body'\n    })\n  ],\n}\n```\n\nSee [the tsdoc](./src/types.ts) for more advanced options\n\n## Example\n\nSee the [/examples](./examples).\n\nOr the pre-configured Markdown template [Vitesse](https://github.com/antfu/vitesse).\n\n## Integrations\n\n### Work with [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages)\n\n```ts\nimport Vue from '@vitejs/plugin-vue'\nimport Markdown from 'unplugin-vue-markdown/vite'\nimport Pages from 'vite-plugin-pages'\n\nexport default {\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/],\n    }),\n    Pages({\n      extensions: ['vue', 'md'],\n    }),\n    Markdown()\n  ],\n}\n```\n\nPut your markdown under `./src/pages/xx.md`, then you can access the page via route `/xx`.\n\n### Work with [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)\n\n`unplugin-vue-components` allows you to do on-demand components auto-importing without worrying about registration.\n\n```ts\nimport Vue from '@vitejs/plugin-vue'\nimport Components from 'unplugin-vue-components/vite'\nimport Markdown from 'unplugin-vue-markdown/vite'\n\nexport default {\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/],\n    }),\n    Markdown(),\n    // should be placed after `Markdown()`\n    Components({\n      // allow auto load markdown components under `./src/components/`\n      extensions: ['vue', 'md'],\n\n      // allow auto import and register components used in markdown\n      include: [/\\.vue$/, /\\.vue\\?vue/, /\\.md$/],\n    })\n  ],\n}\n```\n\nComponents under `./src/components` can be directly used in markdown components, and markdown components can also be put under `./src/components` to be auto imported.\n\n## TypeScript Shim\n\n```ts\ndeclare module '*.vue' {\n  import type { ComponentOptions } from 'vue'\n\n  const Component: ComponentOptions\n  export default Component\n}\n\ndeclare module '*.md' {\n  import type { ComponentOptions } from 'vue'\n\n  const Component: ComponentOptions\n  export default Component\n}\n```\n\n## License\n\nMIT License © 2020-PRESENT [Anthony Fu](https://github.com/antfu)\n"
  },
  {
    "path": "eslint.config.js",
    "content": "// @ts-check\nimport antfu from '@antfu/eslint-config'\n\nexport default antfu()\n"
  },
  {
    "path": "examples/vite/App.vue",
    "content": "<script setup lang='ts'>\nimport { ref } from 'vue'\nimport ComponentA from './README.md'\n\nconst current = ref()\n</script>\n\n<template>\n  <router-view v-slot=\"{ Component }\">\n    <component :is=\"Component\" ref=\"current\" />\n  </router-view>\n  <div v-if=\"current\">\n    accessing frontmatter from outside via expose API:\n    {{ current.frontmatter }}\n  </div>\n  <ComponentA style=\"padding: 20px 40px\" />\n</template>\n"
  },
  {
    "path": "examples/vite/Counter.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst props = defineProps<{ init?: number }>()\n\nconst counter = ref(props.init || 0)\n</script>\n\n<template>\n  <div class=\"counter\">\n    <div>Counter: {{ counter }}</div>\n    <button @click=\"counter += 1\">\n      Inc\n    </button>\n    <button @click=\"counter -= 1\">\n      Dec\n    </button>\n  </div>\n</template>\n\n<style scoped>\n.counter {\n  border: 2px dashed #3eaf7c;\n  padding: 5px 10px 10px 10px;\n}\n</style>\n"
  },
  {
    "path": "examples/vite/Counter2.vue",
    "content": "<script setup lang=\"ts\">\nimport { ref } from 'vue'\n\nconst props = defineProps<{ init?: number }>()\n\nconst counter = ref(props.init || 0)\n</script>\n\n<template>\n  <div class=\"counter\">\n    <div>Counter 2: {{ counter }}</div>\n    <button @click=\"counter += 1\">\n      Inc\n    </button>\n    <button @click=\"counter -= 1\">\n      Dec\n    </button>\n  </div>\n</template>\n\n<style scoped>\n.counter {\n  border: 2px dashed skyblue;\n  padding: 5px 10px 10px 10px;\n}\n</style>\n"
  },
  {
    "path": "examples/vite/README.md",
    "content": "# unplugin-vue-markdown\n\n[![NPM version](https://img.shields.io/npm/v/unplugin-vue-markdown?color=a1b858)](https://www.npmjs.com/package/unplugin-vue-markdown)\n\nCompile Markdown to Vue component.\n\n- 📚 Use Markdown as Vue components.\n- 💚 Use Vue components in Markdown.\n- 🔌 Supports Vite, Webpack, Vue CLI and more, powered by [unplugin](https://github.com/unjs/unplugin).\n- ⚡️ The same transformation as [VitePress](https://vitepress.vuejs.org/).\n\n## Install\n\n```bash\nnpm i unplugin-vue-markdown\n```\n\n<details>\n<summary>Vite</summary><br>\n\n```ts\n// vite.config.ts\nimport Vue from '@vitejs/plugin-vue'\nimport Markdown from 'unplugin-vue-markdown/vite'\n\nexport default defineConfig({\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/], // <-- allows Vue to compile Markdown files\n    }),\n    Markdown({ /* options */ }),\n  ],\n})\n```\n\nExample: [`examples/vite`](./examples/vite/)\n\n<br>\n</details>\n\n<details>\n<summary>Webpack</summary><br>\n\n```ts\n// webpack.config.js\nconst Markdown = require('unplugin-vue-markdown/webpack')\nconst { VueLoaderPlugin } = require('vue-loader')\n\nmodule.exports = {\n  /* ... */\n  module: {\n    rules: [\n      // ... other rules\n      {\n        test: /\\.(vue|md)$/,\n        loader: 'vue-loader'\n      }\n    ]\n  },\n  plugins: [\n    new VueLoaderPlugin(),\n    Markdown({ /* options */ })\n  ]\n}\n```\n\n<br>\n</details>\n\n<details>\n<summary>Vue CLI</summary><br>\n\n```ts\n// vue.config.js\nconst Markdown = require('unplugin-vue-markdown/webpack')\n\nmodule.exports = {\n  parallel: false, // Disable thread-loader which will cause errors, we are still investigating the root cause\n  chainWebpack: (config) => {\n    config.module\n      .rule('vue')\n      .test(/\\.(vue|md)$/) // <-- allows Vue to compile Markdown files\n\n    config\n      .plugin('markdown')\n      .use(Markdown({\n        markdownItUses: [\n          prism,\n        ],\n      }))\n  },\n}\n```\n\nExample: [`examples/vue-cli`](./examples/vue-cli/)\n\n<br>\n</details>\n\n## Import Markdown as Vue components\n\n```html\n<template>\n  <HelloWorld />\n</template>\n\n<script>\nimport HelloWorld from './README.md'\n\nexport default {\n  components: {\n    HelloWorld,\n  },\n}\n</script>\n```\n\n## Use Vue Components inside Markdown\n\nYou can even use Vue components inside your markdown, for example\n\n```html\n<Counter :init='5'/>\n```\n\n<Counter :init='5'/>\n\nNote you can either register the components globally, or use the `<script setup>` tag to register them locally.\n\n```ts\nimport { createApp } from 'vue'\nimport App from './App.vue'\nimport Counter from './Counter.vue'\n\nconst app = createApp(App)\n\n// register global\napp.component('Counter', Counter) // <--\n\napp.mount()\n```\n\n```html\n<script setup>\nimport { Counter } from './Counter.vue'\n</script>\n\n<Counter :init='5'/>\n```\n\nOr you can use [`unplugin-vue-components`](#work-with-unplugin-vue-components) for auto components registration.\n\n## Frontmatter\n\nFrontmatter will be parsed and inject into Vue's instance data `frontmatter` field.\n\nFor example:\n\n```md\n---\nname: My Cool App\n---\n\n# Hello World\n\nThis is {{frontmatter.name}}\n```\n\nWill be rendered as\n\n```html\n<h1>Hello World</h1>\n<p>This is My Cool App</p>\n```\n\nIt will also be passed to the wrapper component's props if you have set `wrapperComponent` option.\n\n## Document head and meta\n\nTo manage document head and meta, you would need to install [`@unhead/vue`](https://unhead.harlanzw.com/integrations/vue/setup) and do some setup.\n\n```bash\nnpm i @unhead/vue\n```\n\n```js\n// vite.config.js\nimport Vue from '@vitejs/plugin-vue'\nimport Markdown from 'unplugin-vue-markdown/vite'\n\nexport default {\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/],\n    }),\n    Markdown({\n      headEnabled: true // <--\n    })\n  ]\n}\n```\n\n```js\n// src/main.js\nimport { createHead } from '@unhead/vue/client' // <--\nimport { createApp } from 'vue'\n\nconst app = createApp(App)\n\nconst head = createHead() // <--\napp.use(head) // <--\n```\n\nThen you can use frontmatter to control the head. For example:\n\n```yaml\n---\ntitle: My Cool App\nmeta:\n  - name: description\n    content: Hello World\n---\n```\n\nFor more options available, please refer to [`@unhead/vue`'s docs](https://unhead.harlanzw.com/integrations/vue/setup).\n\n## Options\n\n`unplugin-vue-markdown` uses [`markdown-it`](https://github.com/markdown-it/markdown-it) under the hood, see [`markdown-it`'s docs](https://markdown-it.github.io/markdown-it/) for more details\n\n```ts\n// vite.config.js\nimport MarkdownItAnchor from 'markdown-it-anchor'\nimport MarkdownItPrism from 'markdown-it-prism'\nimport Markdown from 'unplugin-vue-markdown/vite'\n\nexport default {\n  plugins: [\n    Markdown({\n      // default options passed to markdown-it\n      // see: https://markdown-it.github.io/markdown-it/\n      markdownItOptions: {\n        html: true,\n        linkify: true,\n        typographer: true,\n      },\n      // A function providing the Markdown It instance gets the ability to apply custom settings/plugins\n      markdownItSetup(md) {\n        // for example\n        md.use(MarkdownItAnchor)\n        md.use(MarkdownItPrism)\n      },\n      // Class names for the wrapper div\n      wrapperClasses: 'markdown-body'\n    })\n  ],\n}\n```\n\nSee [the tsdoc](./src/types.ts) for more advanced options\n\n## Example\n\nSee the [/examples](./examples).\n\nOr the pre-configured Markdown template [Vitesse](https://github.com/antfu/vitesse).\n\n## Integrations\n\n### Work with [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages)\n\n```ts\nimport Vue from '@vitejs/plugin-vue'\nimport Markdown from 'unplugin-vue-markdown/vite'\nimport Pages from 'vite-plugin-pages'\n\nexport default {\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/],\n    }),\n    Pages({\n      extensions: ['vue', 'md'],\n    }),\n    Markdown()\n  ],\n}\n```\n\nPut your markdown under `./src/pages/xx.md`, then you can access the page via route `/xx`.\n\n### Work with [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)\n\n`unplugin-vue-components` allows you to do on-demand components auto-importing without worrying about registration.\n\n```ts\nimport Vue from '@vitejs/plugin-vue'\nimport Components from 'unplugin-vue-components/vite'\nimport Markdown from 'unplugin-vue-markdown/vite'\n\nexport default {\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/],\n    }),\n    Markdown(),\n    // should be placed after `Markdown()`\n    Components({\n      // allow auto load markdown components under `./src/components/`\n      extensions: ['vue', 'md'],\n\n      // allow auto import and register components used in markdown\n      include: [/\\.vue$/, /\\.vue\\?vue/, /\\.md$/],\n    })\n  ],\n}\n```\n\nComponents under `./src/components` can be directly used in markdown components, and markdown components can also be put under `./src/components` to be auto imported.\n\n## TypeScript Shim\n\n```ts\ndeclare module '*.vue' {\n  import type { ComponentOptions } from 'vue'\n\n  const Component: ComponentOptions\n  export default Component\n}\n\ndeclare module '*.md' {\n  import type { ComponentOptions } from 'vue'\n\n  const Component: ComponentOptions\n  export default Component\n}\n```\n\n## License\n\nMIT License © 2020-PRESENT [Anthony Fu](https://github.com/antfu)\n"
  },
  {
    "path": "examples/vite/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Vite MD</title>\n  <link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/4.0.0/github-markdown.min.css\" integrity=\"sha512-Oy18vBnbSJkXTndr2n6lDMO5NN31UljR8e/ICzVPrGpSud4Gkckb8yUpqhKuUNoE+o9gAb4O/rAxxw1ojyUVzg==\" crossorigin=\"anonymous\" />\n  <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/LukeAskew/prism-github@master/prism-github.css\" />\n</head>\n<body>\n  <div id=\"app\"></div>\n  <script type=\"module\" src=\"./main.ts\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "examples/vite/main.ts",
    "content": "import { createHead } from '@unhead/vue/client'\nimport routes from 'pages-generated'\nimport { createApp } from 'vue'\nimport {\n  createRouter,\n  createWebHistory,\n} from 'vue-router'\nimport App from './App.vue'\nimport Counter from './Counter.vue'\n\nimport 'prismjs'\nimport 'prismjs/components/prism-bash'\nimport 'prismjs/components/prism-typescript'\nimport 'prismjs/components/prism-javascript'\nimport 'prismjs/components/prism-markup'\nimport 'prismjs/components/prism-markup-templating'\n\nconst app = createApp(App)\nconst head = createHead()\nconst router = createRouter({\n  history: createWebHistory(),\n  routes,\n})\n\napp.use(head)\napp.use(router)\napp.component('Counter', Counter)\n\napp.mount('#app')\n"
  },
  {
    "path": "examples/vite/package.json",
    "content": "{\n  \"type\": \"module\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"DEBUG=\\\"unplugin-vue-markdown:*\\\" vite\",\n    \"build\": \"DEBUG=\\\"unplugin-vue-markdown:*\\\" vite build\"\n  },\n  \"dependencies\": {\n    \"@unhead/vue\": \"^2.0.17\",\n    \"vue\": \"^3.5.21\",\n    \"vue-router\": \"^4.5.1\"\n  },\n  \"devDependencies\": {\n    \"@vitejs/plugin-vue\": \"^6.0.1\",\n    \"markdown-it-prism\": \"^3.0.0\",\n    \"prismjs\": \"^1.30.0\",\n    \"typescript\": \"^5.9.2\",\n    \"unplugin-vue-markdown\": \"workspace:*\",\n    \"vite\": \"^7.1.7\",\n    \"vite-plugin-inspect\": \"^11.3.3\",\n    \"vite-plugin-pages\": \"^0.33.1\"\n  }\n}\n"
  },
  {
    "path": "examples/vite/pages/index.md",
    "content": "---\ntitle: Hello\nmeta:\n  - name: description\n    content: Hello World\ntest: test\n---\n\n# Hello world!\n\nFront matter: {{ frontmatter }}\n\n<style>\nh1 {\n  color: cadetblue;\n}\n</style>\n\n<script setup>\nimport Counter2 from '../Counter2.vue'\n</script>\n\n<Counter />\n<br>\n<Counter2 />\n\n<router-link to=\"/\">Home</router-link>\n\n<route>\n{\n  meta: {\n    layout: 'home'\n  }\n}\n</route>\n"
  },
  {
    "path": "examples/vite/pages/route.vue",
    "content": "<template>\n  route test\n</template>\n\n<route>\n{\n  meta: {\n    layout: 'home'\n  }\n}\n</route>\n"
  },
  {
    "path": "examples/vite/vite.config.ts",
    "content": "import Vue from '@vitejs/plugin-vue'\nimport prism from 'markdown-it-prism'\nimport Markdown from 'unplugin-vue-markdown/vite'\nimport { defineConfig } from 'vite'\nimport Inspect from 'vite-plugin-inspect'\nimport Pages from 'vite-plugin-pages'\n\nexport default defineConfig({\n  plugins: [\n    Vue({\n      include: [/\\.vue$/, /\\.md$/],\n    }),\n    Markdown({\n      markdownOptions: {\n\n      },\n      headEnabled: true,\n      markdownUses: [\n        prism,\n      ],\n    }),\n    Pages({\n      pagesDir: 'pages',\n      extensions: ['vue', 'md'],\n    }),\n    Inspect(),\n  ],\n  build: {\n    sourcemap: true,\n  },\n})\n"
  },
  {
    "path": "examples/vite/vue-shim.d.ts",
    "content": "declare module '*.vue' {\n  import type { ComponentOptions } from 'vue'\n\n  const Component: ComponentOptions\n  export default Component\n}\n\ndeclare module '*.md' {\n  import type { ComponentOptions } from 'vue'\n\n  const Component: ComponentOptions\n  export default Component\n}\n"
  },
  {
    "path": "examples/vue-cli/babel.config.js",
    "content": "module.exports = {\n  presets: [\n    '@vue/cli-plugin-babel/preset',\n  ],\n}\n"
  },
  {
    "path": "examples/vue-cli/jsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\n      \"esnext\",\n      \"dom\",\n      \"dom.iterable\",\n      \"scripthost\"\n    ],\n    \"baseUrl\": \"./\",\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"paths\": {\n      \"@/*\": [\n        \"src/*\"\n      ]\n    }\n  }\n}\n"
  },
  {
    "path": "examples/vue-cli/package.json",
    "content": "{\n  \"name\": \"example-vue-cli\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"vue-cli-service serve\",\n    \"build\": \"vue-cli-service build\",\n    \"lint\": \"vue-cli-service lint\"\n  },\n  \"dependencies\": {\n    \"core-js\": \"^3.45.1\",\n    \"vue\": \"^3.5.21\"\n  },\n  \"devDependencies\": {\n    \"@babel/core\": \"^7.28.4\",\n    \"@vue/cli-plugin-babel\": \"~5.0.9\",\n    \"@vue/cli-service\": \"~5.0.9\",\n    \"unplugin-vue-markdown\": \"workspace:*\"\n  },\n  \"browserslist\": [\n    \"> 1%\",\n    \"last 2 versions\",\n    \"not dead\",\n    \"not ie 11\"\n  ]\n}\n"
  },
  {
    "path": "examples/vue-cli/public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\n    <title><%= htmlWebpackPlugin.options.title %></title>\n  </head>\n  <body>\n    <noscript>\n      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>\n    </noscript>\n    <div id=\"app\"></div>\n    <!-- built files will be auto injected -->\n  </body>\n</html>\n"
  },
  {
    "path": "examples/vue-cli/src/App.vue",
    "content": "<script>\nimport Markdown from './Hi.md'\n\nexport default {\n  name: 'App',\n  components: {\n    Markdown,\n  },\n}\n</script>\n\n<template>\n  <Markdown />\n</template>\n\n<style>\n#app {\n  font-family: Avenir, Helvetica, Arial, sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-align: center;\n  color: #2c3e50;\n  margin-top: 60px;\n}\n</style>\n"
  },
  {
    "path": "examples/vue-cli/src/Hi.md",
    "content": "# Hello\n\nHey\n"
  },
  {
    "path": "examples/vue-cli/src/main.js",
    "content": "import { createApp } from 'vue'\nimport App from './App.vue'\n\ncreateApp(App).mount('#app')\n"
  },
  {
    "path": "examples/vue-cli/vue.config.js",
    "content": "const { defineConfig } = require('@vue/cli-service')\nconst prism = require('markdown-it-prism')\nconst Markdown = require('unplugin-vue-markdown/webpack')\n\nmodule.exports = defineConfig({\n  transpileDependencies: true,\n  parallel: false,\n  chainWebpack: (config) => {\n    config.module\n      .rule('vue')\n      .test(/\\.(vue|md)$/)\n\n    config\n      .plugin('markdown')\n      .use(Markdown({\n        markdownUses: [\n          prism,\n        ],\n      }))\n  },\n})\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"unplugin-vue-markdown\",\n  \"type\": \"module\",\n  \"version\": \"30.0.0\",\n  \"packageManager\": \"pnpm@10.17.1\",\n  \"description\": \"Compile Markdown to Vue component\",\n  \"author\": \"Anthony Fu <anthonyfu117@hotmail.com>\",\n  \"license\": \"MIT\",\n  \"funding\": \"https://github.com/sponsors/antfu\",\n  \"homepage\": \"https://github.com/unplugin/unplugin-vue-markdown\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/unplugin/unplugin-vue-markdown\"\n  },\n  \"bugs\": \"https://github.com/unplugin/unplugin-vue-markdown/issues\",\n  \"keywords\": [\n    \"vite\",\n    \"unplugin\",\n    \"markdown-exit\"\n  ],\n  \"exports\": {\n    \".\": {\n      \"types\": \"./dist/index.d.ts\",\n      \"import\": \"./dist/index.js\",\n      \"require\": \"./dist/index.cjs\"\n    },\n    \"./vite\": {\n      \"types\": \"./dist/vite.d.ts\",\n      \"import\": \"./dist/vite.js\",\n      \"require\": \"./dist/vite.cjs\"\n    },\n    \"./webpack\": {\n      \"types\": \"./dist/webpack.d.ts\",\n      \"import\": \"./dist/webpack.js\",\n      \"require\": \"./dist/webpack.cjs\"\n    },\n    \"./rollup\": {\n      \"types\": \"./dist/rollup.d.ts\",\n      \"import\": \"./dist/rollup.js\",\n      \"require\": \"./dist/rollup.cjs\"\n    },\n    \"./esbuild\": {\n      \"types\": \"./dist/esbuild.d.ts\",\n      \"import\": \"./dist/esbuild.js\",\n      \"require\": \"./dist/esbuild.cjs\"\n    },\n    \"./types\": {\n      \"types\": \"./dist/types.d.ts\",\n      \"import\": \"./dist/types.js\",\n      \"require\": \"./dist/types.cjs\"\n    },\n    \"./*\": \"./*\"\n  },\n  \"main\": \"dist/index.cjs\",\n  \"module\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"typesVersions\": {\n    \"*\": {\n      \"*\": [\n        \"./dist/*\",\n        \"./*\"\n      ]\n    }\n  },\n  \"engines\": {\n    \"node\": \">=20\"\n  },\n  \"scripts\": {\n    \"dev\": \"tsup --watch\",\n    \"example:dev\": \"pnpm -C examples/vite run dev\",\n    \"example:build\": \"pnpm -C examples/vite run build\",\n    \"build\": \"tsup\",\n    \"build:fix\": \"tsx scripts/postbuild.ts\",\n    \"test\": \"vitest\",\n    \"test:update\": \"vitest -u\",\n    \"lint\": \"eslint .\",\n    \"prepublishOnly\": \"pnpm run build\",\n    \"release\": \"bumpp\"\n  },\n  \"peerDependencies\": {\n    \"vite\": \"^2.0.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0 || ^7.0.0\"\n  },\n  \"dependencies\": {\n    \"@mdit-vue/plugin-component\": \"^3.0.2\",\n    \"@mdit-vue/plugin-frontmatter\": \"^3.0.2\",\n    \"@mdit-vue/types\": \"^3.0.2\",\n    \"markdown-exit\": \"^1.0.0-beta.8\",\n    \"unplugin\": \"^2.3.10\",\n    \"unplugin-utils\": \"^0.3.0\"\n  },\n  \"devDependencies\": {\n    \"@antfu/eslint-config\": \"^5.4.1\",\n    \"@antfu/ni\": \"^26.0.1\",\n    \"@antfu/utils\": \"^9.2.1\",\n    \"@types/node\": \"^24.5.2\",\n    \"@unhead/vue\": \"^2.0.17\",\n    \"@vue/test-utils\": \"^2.4.6\",\n    \"ansis\": \"^4.1.0\",\n    \"bumpp\": \"^10.2.3\",\n    \"eslint\": \"^9.36.0\",\n    \"fast-glob\": \"^3.3.3\",\n    \"rollup\": \"^4.52.2\",\n    \"tsup\": \"^8.5.0\",\n    \"tsx\": \"^4.20.5\",\n    \"typescript\": \"^5.9.2\",\n    \"vite\": \"^7.1.7\",\n    \"vitest\": \"^3.2.4\",\n    \"vue\": \"^3.5.21\",\n    \"webpack\": \"^5.101.3\"\n  },\n  \"pnpm\": {\n    \"onlyBuiltDependencies\": [\n      \"core-js\",\n      \"esbuild\"\n    ]\n  }\n}\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - examples/*\n\nignoreWorkspaceRootCheck: true\nstrictPeerDependencies: false\nshamefullyHoist: true\nshellEmulator: true\n"
  },
  {
    "path": "scripts/postbuild.ts",
    "content": "import { promises as fs } from 'node:fs'\nimport { basename, dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport ansis from 'ansis'\nimport fg from 'fast-glob'\n\nasync function run() {\n  // fix cjs exports\n  const files = await fg('*.cjs', {\n    ignore: ['chunk-*'],\n    absolute: true,\n    cwd: resolve(dirname(fileURLToPath(import.meta.url)), '../dist'),\n  })\n  for (const file of files) {\n    console.log(ansis.cyan.inverse(' POST '), `Fix ${basename(file)}`)\n    let code = await fs.readFile(file, 'utf8')\n    code = code.replace('exports.default =', 'module.exports =')\n    code += 'exports.default = module.exports;'\n    await fs.writeFile(file, code)\n  }\n}\n\nrun()\n"
  },
  {
    "path": "src/core/head.ts",
    "content": "import type { Frontmatter, MetaProperty, ResolvedOptions } from '../types'\n\nconst headProperties = [\n  'title',\n  'meta',\n  'link',\n  'base',\n  'style',\n  'script',\n  'htmlAttrs',\n  'bodyAttrs',\n]\n\nexport function preprocessHead<T extends Frontmatter>(frontmatter: T, options: ResolvedOptions) {\n  if (!options.headEnabled)\n    return frontmatter\n\n  const head: Frontmatter = options.headField\n    ? (frontmatter[options.headField] as Frontmatter || {})\n    : frontmatter\n\n  const meta = (head.meta = head.meta || []) as MetaProperty[]\n\n  if (head.title) {\n    if (!meta.find((i: any) => i.property === 'og:title'))\n      meta.push({ property: 'og:title', content: head.title })\n\n    if (!meta.find((i: any) => i.name === 'twitter:title'))\n      meta.push({ name: 'twitter:title', content: head.title })\n  }\n\n  if (head.description) {\n    if (!meta.find((i: any) => i.name === 'description'))\n      meta.push({ name: 'description', content: head.description })\n\n    if (!meta.find((i: any) => i.property === 'og:description'))\n      meta.push({ property: 'og:description', content: head.description })\n\n    if (!meta.find((i: any) => i.name === 'twitter:description'))\n      meta.push({ name: 'twitter:description', content: head.description })\n  }\n\n  if (head.image) {\n    if (!meta.find((i: any) => i.property === 'og:image'))\n      meta.push({ property: 'og:image', content: head.image })\n\n    if (!meta.find((i: any) => i.name === 'twitter:image'))\n      meta.push({ name: 'twitter:image', content: head.image })\n\n    if (!meta.find((i: any) => i.property === 'twitter:card'))\n      meta.push({ name: 'twitter:card', content: 'summary_large_image' })\n  }\n\n  const result: any = {}\n\n  for (const [key, value] of Object.entries(head)) {\n    if (headProperties.includes(key))\n      result[key] = value\n  }\n\n  return Object.entries(result).length === 0 ? null : result\n}\n"
  },
  {
    "path": "src/core/markdown.ts",
    "content": "import type { TransformResult } from 'vite'\nimport type { MarkdownEnv, ResolvedOptions } from '../types'\nimport { toArray, uniq } from '@antfu/utils'\nimport { componentPlugin } from '@mdit-vue/plugin-component'\nimport { frontmatterPlugin } from '@mdit-vue/plugin-frontmatter'\nimport { createMarkdownExit } from 'markdown-exit'\nimport { preprocessHead } from './head'\n\nconst scriptSetupRE = /<\\s*script([^>]*)\\bsetup\\b([^>]*)>([\\s\\S]*)<\\/script>/g\nconst defineExposeRE = /defineExpose\\s*\\(/g\n\nconst EXPORTS_KEYWORDS = [\n  'class',\n  'default',\n  'export',\n  'function',\n  'import',\n  'let',\n  'var',\n  'const',\n  'from',\n  'as',\n  'return',\n  'if',\n  'else',\n  'switch',\n  'case',\n  'break',\n  'for',\n  'while',\n  'do',\n]\n\ninterface ScriptMeta {\n  code: string\n  attr: string\n}\n\nfunction extractScriptSetup(html: string) {\n  const scripts: ScriptMeta[] = []\n  html = html.replace(scriptSetupRE, (_, attr1, attr2, code) => {\n    scripts.push({\n      code,\n      attr: `${attr1} ${attr2}`.trim(),\n    })\n    return ''\n  })\n\n  return { html, scripts }\n}\n\nfunction extractCustomBlock(html: string, options: ResolvedOptions) {\n  const blocks: string[] = []\n  for (const tag of options.customSfcBlocks) {\n    html = html.replace(new RegExp(`<${tag}[^>]*\\\\b[^>]*>[^<]*<\\\\/${tag}>`, 'gm'), (code) => {\n      blocks.push(code)\n      return ''\n    })\n  }\n\n  return { html, blocks }\n}\n\nexport function createMarkdown(options: ResolvedOptions) {\n  const isVue2 = options.vueVersion.startsWith('2.')\n\n  const setupPromise = (async () => {\n    const md = createMarkdownExit({\n      html: true,\n      linkify: true,\n      typographer: true,\n      ...options.markdownOptions,\n    })\n\n    md.use(componentPlugin as any, options.componentOptions)\n\n    if (options.frontmatter || options.excerpt) {\n      md.use(frontmatterPlugin as any, {\n        ...options.frontmatterOptions,\n        grayMatterOptions: {\n          excerpt: options.excerpt,\n          ...options.frontmatterOptions.grayMatterOptions,\n        },\n      })\n    }\n\n    md.linkify.set({ fuzzyLink: false })\n\n    options.markdownUses.forEach((e) => {\n      const [plugin, options] = toArray(e)\n\n      md.use(plugin, options)\n    })\n\n    await options.markdownSetup(md)\n\n    return md\n  })()\n\n  return async (id: string, raw: string): Promise<TransformResult> => {\n    const md = await setupPromise\n\n    const {\n      wrapperDiv,\n      wrapperClasses,\n      wrapperComponent,\n      transforms,\n      headEnabled,\n      frontmatterPreprocess,\n    } = options\n\n    raw = raw.trimStart()\n    raw = await transforms.before?.(raw, id) ?? raw\n\n    const env: MarkdownEnv = { id }\n    let html = await md.renderAsync(raw, env)\n    const { excerpt = '', frontmatter: data = null } = env\n\n    if (wrapperDiv) {\n      const wrapperClassesResolved = toArray(\n        typeof wrapperClasses === 'function'\n          ? wrapperClasses(id, raw)\n          : wrapperClasses,\n      )\n        .filter(Boolean)\n        .join(' ')\n\n      if (wrapperClassesResolved)\n        html = `<div class=\"${wrapperClassesResolved}\">${html}</div>`\n      else\n        html = `<div>${html}</div>`\n    }\n\n    const wrapperComponentName = typeof wrapperComponent === 'function'\n      ? wrapperComponent(id, raw)\n      : wrapperComponent\n\n    if (wrapperComponentName) {\n      const attrs = [\n        options.frontmatter && ':frontmatter=\"frontmatter\"',\n        options.excerpt && ':excerpt=\"excerpt\"',\n      ].filter(Boolean).join(' ')\n      html = `<${wrapperComponentName} ${attrs}>${html}</${wrapperComponentName}>`\n    }\n\n    html = await transforms.after?.(html, id) ?? html\n\n    if (options.escapeCodeTagInterpolation) {\n      // escape curly brackets interpolation in <code>, #14\n      html = html.replace(/<code(.*?)>/g, '<code$1 v-pre>')\n    }\n\n    const hoistScripts = extractScriptSetup(html)\n    html = hoistScripts.html\n    const customBlocks = extractCustomBlock(html, options)\n    html = customBlocks.html\n\n    const scriptLines: string[] = []\n    let frontmatterExportsLines: string[] = []\n    let excerptExportsLine = ''\n    let excerptKeyOverlapping = false\n\n    function hasExplicitExports() {\n      return defineExposeRE.test(hoistScripts.scripts.map(i => i.code).join(''))\n    }\n\n    if (options.frontmatter) {\n      if (options.excerpt && data) {\n        if (data.excerpt !== undefined)\n          excerptKeyOverlapping = true\n        data.excerpt = excerpt\n      }\n\n      const { head, frontmatter } = frontmatterPreprocess(data || {}, options, id, preprocessHead)\n\n      if (options.excerpt && !excerptKeyOverlapping && frontmatter.excerpt !== undefined)\n        delete frontmatter.excerpt\n\n      scriptLines.push(`const frontmatter = ${JSON.stringify(frontmatter)}`)\n\n      if (options.exportFrontmatter) {\n        frontmatterExportsLines = Object.entries(frontmatter)\n          .map(([key, value]) => {\n            if (EXPORTS_KEYWORDS.includes(key))\n              key = `_${key}`\n            return `export const ${key} = ${JSON.stringify(value)}`\n          })\n      }\n\n      if (!isVue2 && options.exposeFrontmatter && !hasExplicitExports())\n        scriptLines.push('defineExpose({ frontmatter })')\n\n      if (!isVue2 && headEnabled && head) {\n        // @ts-expect-error legacy option\n        if (headEnabled === 'vueuse')\n          throw new Error('unplugin-vue-markdown no longer supports @vueuse/head. Change `headEnabled` to `true` and install `@unhead/vue` instead.')\n        scriptLines.push(`const head = ${JSON.stringify(head)}`)\n        scriptLines.unshift(`import { useHead } from \"@unhead/vue\"`)\n        scriptLines.push('useHead(head)')\n      }\n\n      scriptLines.push(...await transforms.extraScripts?.(frontmatter, id) || [])\n    }\n\n    if (options.excerpt) {\n      scriptLines.push(`const excerpt = ${JSON.stringify(excerpt)}`)\n\n      if (!excerptKeyOverlapping)\n        excerptExportsLine = `export const excerpt = ${JSON.stringify(excerpt)}\\n`\n\n      if (!isVue2 && options.exposeExcerpt && !hasExplicitExports())\n        scriptLines.push('defineExpose({ excerpt })')\n    }\n\n    scriptLines.push(...hoistScripts.scripts.map(i => i.code))\n\n    let attrs = uniq(hoistScripts.scripts.map(i => i.attr)).join(' ').trim()\n    if (attrs)\n      attrs = ` ${attrs}`\n\n    const scripts = isVue2\n      ? [\n          `<script${attrs}>`,\n          ...scriptLines,\n          ...frontmatterExportsLines,\n          excerptExportsLine,\n          'export default { data() { return { frontmatter } } }',\n          '</script>',\n        ]\n      : [\n          `<script setup${attrs}>`,\n          ...scriptLines,\n          '</script>',\n          ...((frontmatterExportsLines.length || excerptExportsLine)\n            ? [\n                `<script${attrs}>`,\n                ...frontmatterExportsLines,\n                excerptExportsLine,\n                '</script>',\n              ]\n            : []),\n        ]\n\n    const code = [\n      `<template>${html}</template>`,\n      ...scripts.map(i => i.trim()).filter(Boolean),\n      ...customBlocks.blocks,\n    ].join('\\n')\n\n    return {\n      code,\n      map: { mappings: '' } as any,\n    }\n  }\n}\n"
  },
  {
    "path": "src/core/options.ts",
    "content": "import type { Options, ResolvedOptions } from '../types'\nimport { getVueVersion } from './utils'\n\nexport function resolveOptions(userOptions: Options): ResolvedOptions {\n  const noop = () => {}\n\n  // Resolve with new names taking precedence over deprecated old names\n  const markdownOptions = userOptions.markdownOptions ?? userOptions.markdownItOptions ?? {}\n  const markdownUses = userOptions.markdownUses ?? userOptions.markdownItUses ?? []\n  const markdownSetup = userOptions.markdownSetup ?? userOptions.markdownItSetup ?? noop\n\n  const defaultOptions: ResolvedOptions = {\n    headEnabled: false,\n    headField: '',\n    frontmatter: true,\n    excerpt: false,\n    exposeFrontmatter: true,\n    exposeExcerpt: false,\n    exportFrontmatter: true,\n    escapeCodeTagInterpolation: true,\n    customSfcBlocks: ['route', 'i18n', 'style'],\n    componentOptions: {},\n    frontmatterOptions: {},\n    markdownOptions: {},\n    markdownUses: [],\n    markdownSetup: noop,\n    markdownItOptions: {},\n    markdownItUses: [],\n    markdownItSetup: noop,\n    wrapperDiv: true,\n    wrapperComponent: null,\n    transforms: {},\n    vueVersion: userOptions.vueVersion || getVueVersion(),\n    wrapperClasses: 'markdown-body',\n    include: null,\n    exclude: null,\n    frontmatterPreprocess: (frontmatter, options, _id, defaults) => {\n      return {\n        head: defaults(frontmatter, options),\n        frontmatter,\n      }\n    },\n  }\n\n  const options = {\n    ...defaultOptions,\n    ...userOptions,\n    // Set both old and new keys to the resolved value\n    markdownOptions,\n    markdownUses,\n    markdownSetup,\n    markdownItOptions: markdownOptions,\n    markdownItUses: markdownUses,\n    markdownItSetup: markdownSetup,\n  }\n\n  return options as ResolvedOptions\n}\n"
  },
  {
    "path": "src/core/utils.ts",
    "content": "import { createRequire } from 'node:module'\n\nconst _require = typeof require === 'undefined'\n  ? createRequire(import.meta.url)\n  : require\n\nexport function getVueVersion(defaultVersion = '3.2.0') {\n  try {\n    let v = _require('vue')\n    if (v.default)\n      v = v.default\n    return v.version || defaultVersion\n  }\n  catch {\n    return defaultVersion\n  }\n}\n"
  },
  {
    "path": "src/esbuild.ts",
    "content": "import { createEsbuildPlugin } from 'unplugin'\nimport { unpluginFactory } from '.'\n\nexport default createEsbuildPlugin(unpluginFactory)\n"
  },
  {
    "path": "src/index.ts",
    "content": "import type { UnpluginFactory } from 'unplugin'\nimport type { Options } from './types'\nimport { createUnplugin } from 'unplugin'\nimport { createFilter } from 'unplugin-utils'\nimport { createMarkdown } from './core/markdown'\nimport { resolveOptions } from './core/options'\n\nconst cssIdRE = /\\.(css|postcss|sass|scss|less|stylus|styl)($|\\?)/\n\nexport const unpluginFactory: UnpluginFactory<Options> = (userOptions = {}) => {\n  const options = resolveOptions(userOptions)\n  const markdownToVue = createMarkdown(options)\n\n  const filter = createFilter(\n    userOptions.include || /\\.md$|\\.md\\?vue/,\n    userOptions.exclude || cssIdRE,\n  )\n\n  return {\n    name: 'unplugin-vue-markdown',\n    enforce: 'pre',\n    transformInclude(id) {\n      return filter(id)\n    },\n    async transform(raw, id) {\n      try {\n        return await markdownToVue(id, raw)\n      }\n      catch (e: any) {\n        this.error(e)\n      }\n    },\n    vite: {\n      async handleHotUpdate(ctx) {\n        if (!filter(ctx.file))\n          return\n\n        const defaultRead = ctx.read\n        ctx.read = async function () {\n          return (await markdownToVue(ctx.file, await defaultRead())).code\n        }\n      },\n    },\n  }\n}\n\nexport default /* #__PURE__ */ createUnplugin(unpluginFactory)\n"
  },
  {
    "path": "src/rollup.ts",
    "content": "import { createRollupPlugin } from 'unplugin'\nimport { unpluginFactory } from '.'\n\nexport default createRollupPlugin(unpluginFactory)\n"
  },
  {
    "path": "src/rspack.ts",
    "content": "import { createRspackPlugin } from 'unplugin'\nimport { unpluginFactory } from '.'\n\nexport default createRspackPlugin(unpluginFactory)\n"
  },
  {
    "path": "src/types.ts",
    "content": "import type { ComponentPluginOptions } from '@mdit-vue/plugin-component'\nimport type { FrontmatterPluginOptions } from '@mdit-vue/plugin-frontmatter'\nimport type { MarkdownItEnv } from '@mdit-vue/types'\nimport type MarkdownExit from 'markdown-exit'\nimport type {\n  MarkdownExitOptions,\n  PluginSimple,\n  PluginWithOptions,\n} from 'markdown-exit'\nimport type { FilterPattern } from 'unplugin-utils'\nimport type { preprocessHead } from './core/head'\n\n/** a `<meta />` property in HTML is defined with the following name/values */\nexport interface MetaProperty {\n  key?: string\n  /**\n   * the \"name\" property used by Facebook and other providers who\n   * use the Opengraph standards\n   */\n  property?: string\n  /**\n   * used by google to identify the \"name\" of the name/value pair\n   */\n  itemprop?: string\n  /**\n   * used by Twitter to indicate the \"name\" field in a meta properties\n   * name/value pairing\n   */\n  name?: string\n  /**\n   * The value of the meta property\n   */\n  content?: any\n  [key: string]: unknown\n}\n\n/**\n * Frontmatter content is represented as key/value dictionary\n */\nexport interface Frontmatter {\n  title?: string\n  name?: string\n  description?: string\n  meta?: MetaProperty[]\n  [key: string]: unknown\n}\n\nexport interface Options {\n  /**\n   * Explicitly set the Vue version\n   *\n   * @default auto detected\n   */\n  vueVersion?: string\n\n  /**\n   * Enable head support, need to install @unhead/vue and register to App in main.js\n   *\n   * @default true\n   */\n  headEnabled?: boolean\n\n  /**\n   * The head field in frontmatter used to be used for @unhead/vue\n   *\n   * When an empty string is passed, it will use the root properties of the frontmatter\n   *\n   * @default ''\n   */\n  headField?: string\n\n  /**\n   * Parse for frontmatter\n   *\n   * @default true\n   */\n  frontmatter?: boolean\n\n  /**\n   * Parse for excerpt\n   *\n   * If `true`, it will be passed to `frontmatterPreprocess` as `frontmatter.excerpt`, replacing the `excerpt` key in frontmatter, if there's any\n   *\n   * @default false\n   */\n  excerpt?: boolean\n\n  /**\n   * Remove custom SFC block\n   *\n   * @default ['route', 'i18n']\n   */\n  customSfcBlocks?: string[]\n\n  /**\n   * Options passed to [@mdit-vue/plugin-component](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-component)\n   */\n  componentOptions?: ComponentPluginOptions\n\n  /**\n   * Options passed to [@mdit-vue/plugin-frontmatter](https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-frontmatter)\n   */\n  frontmatterOptions?: FrontmatterPluginOptions\n\n  /**\n   * Custom function to provide defaults to the frontmatter and\n   * move certain attributes into the \"meta\" category.\n   *\n   * Note: _overriding this will remove built-in functionality setting\n   * \"meta\" properties and the built-in \"head\" support. Do this only\n   * if you know what you're doing._\n   */\n  frontmatterPreprocess?: (\n    frontmatter: Frontmatter,\n    options: ResolvedOptions,\n    id: string,\n    defaultHeadProcess: typeof preprocessHead,\n  ) => {\n    head: Record<string, any>\n    frontmatter: Frontmatter\n  }\n\n  /**\n   * Expose frontmatter via expose API\n   *\n   * @default true\n   */\n  exposeFrontmatter?: boolean\n\n  /**\n   * Expose excerpt via expose API\n   *\n   * @default false\n   */\n  exposeExcerpt?: boolean\n\n  /**\n   * Export frontmatter in component module\n   *\n   * @default true\n   */\n  exportFrontmatter?: boolean\n\n  /**\n   * Add `v-pre` to `<code>` tag to escape curly brackets interpolation\n   *\n   * @see https://github.com/unplugin/unplugin-vue-markdown/issues/14\n   * @default true\n   */\n  escapeCodeTagInterpolation?: boolean\n\n  /**\n   * Options passed to markdown-exit\n   */\n  markdownOptions?: MarkdownExitOptions\n\n  /**\n   * Plugins for markdown-exit\n   */\n  markdownUses?: (\n    | PluginSimple\n    | [PluginSimple | PluginWithOptions<any>, any]\n    | any\n  )[]\n\n  /**\n   * A function providing the markdown-exit instance gets the ability to apply custom\n   * settings/plugins\n   */\n  markdownSetup?: (md: MarkdownExit) => void | Promise<void>\n\n  /**\n   * @deprecated Use `markdownOptions` instead\n   */\n  markdownItOptions?: MarkdownExitOptions\n\n  /**\n   * @deprecated Use `markdownUses` instead\n   */\n  markdownItUses?: (\n    | PluginSimple\n    | [PluginSimple | PluginWithOptions<any>, any]\n    | any\n  )[]\n\n  /**\n   * @deprecated Use `markdownSetup` instead\n   */\n  markdownItSetup?: (md: MarkdownExit) => void | Promise<void>\n\n  /**\n   * Wrap the rendered html in a div\n   *\n   * @default true\n   */\n  wrapperDiv?: boolean\n\n  /**\n   * Class names for wrapper div\n   *\n   * This option will be ignored if `wrapperDiv` is set to `false`\n   *\n   * @default 'markdown-body'\n   */\n  wrapperClasses?: string | string[] | undefined | null | ((id: string, code: string) => string | string[] | undefined | null)\n\n  /**\n   * Component name to wrapper with\n   *\n   * @default undefined\n   */\n  wrapperComponent?: string | undefined | null | ((id: string, code: string) => string | undefined | null)\n\n  /**\n   * Custom tranformations apply before and after the markdown transformation\n   */\n  transforms?: {\n    before?: (code: string, id: string) => string | Promise<string>\n    after?: (code: string, id: string) => string | Promise<string>\n    /**\n     * Return extra code to be injected into the `<script>` tag\n     */\n    extraScripts?: (frontmatter: Record<string, any>, id: string) => string[] | Promise<string[]>\n  }\n\n  include?: FilterPattern\n  exclude?: FilterPattern\n}\n\nexport interface ResolvedOptions extends Required<Options> {}\n\nexport type { MarkdownExit, MarkdownExitOptions }\n\nexport interface MarkdownEnv extends MarkdownItEnv {\n  id: string\n}\n"
  },
  {
    "path": "src/vite.ts",
    "content": "import { createVitePlugin } from 'unplugin'\nimport { unpluginFactory } from '.'\n\nexport default createVitePlugin(unpluginFactory)\n"
  },
  {
    "path": "src/webpack.ts",
    "content": "import { createWebpackPlugin } from 'unplugin'\nimport { unpluginFactory } from '.'\n\nexport default createWebpackPlugin(unpluginFactory) as any\n"
  },
  {
    "path": "test/__snapshots__/excerpt.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`excerpt > raw excerpt 1`] = `\n\"<template><div class=\"markdown-body\"><p>This is an excerpt which is kept as <strong>raw Markdown</strong>.</p>\n<!-- more -->\n<h1>Hello</h1>\n<ul>\n<li>A</li>\n<li>B</li>\n<li>C</li>\n</ul>\n</div></template>\n<script setup>\nconst frontmatter = {\"title\":\"Hey\"}\ndefineExpose({ frontmatter })\nconst excerpt = \"\\\\nThis is an excerpt which is kept as **raw Markdown**.\\\\n\\\\n\"\n</script>\n<script>\nexport const title = \"Hey\"\nexport const excerpt = \"\\\\nThis is an excerpt which is kept as **raw Markdown**.\\\\n\\\\n\"\n</script>\"\n`;\n\nexports[`excerpt > rendered excerpt 1`] = `\n\"<template><div class=\"markdown-body\"><p>This is an excerpt which has been rendered to <strong>HTML</strong>.</p>\n<!-- more -->\n<h1>Hello</h1>\n<ul>\n<li>A</li>\n<li>B</li>\n<li>C</li>\n</ul>\n</div></template>\n<script setup>\nconst frontmatter = {\"title\":\"Hey\"}\ndefineExpose({ frontmatter })\nconst excerpt = \"<p>This is an excerpt which has been rendered to <strong>HTML</strong>.</p>\\\\n\"\n</script>\n<script>\nexport const title = \"Hey\"\nexport const excerpt = \"<p>This is an excerpt which has been rendered to <strong>HTML</strong>.</p>\\\\n\"\n</script>\"\n`;\n"
  },
  {
    "path": "test/__snapshots__/transform.test.ts.snap",
    "content": "// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html\n\nexports[`transform > basic 1`] = `\n\"<template><div class=\"markdown-body\"><h1>Hello</h1>\n<ul>\n<li>A</li>\n<li>B</li>\n<li>C</li>\n</ul>\n</div></template>\n<script setup>\nconst frontmatter = {\"title\":\"Hey\"}\ndefineExpose({ frontmatter })\n</script>\n<script>\nexport const title = \"Hey\"\n</script>\"\n`;\n\nexports[`transform > code escape 1`] = `\n\"<template><div class=\"markdown-body\"><p>Hello <code v-pre>{{ world }}</code></p>\n<pre><code class=\"language-js\" v-pre>console.log(\\`{{ world }}\\`)\n</code></pre>\n</div></template>\n<script setup>\nconst frontmatter = {}\ndefineExpose({ frontmatter })\n</script>\"\n`;\n\nexports[`transform > couldn't expose frontmatter 1`] = `\n\"<template><div class=\"markdown-body\">\n</div></template>\n<script setup>\nconst frontmatter = {\"title\":\"Hey\"}\ndefineExpose({ test: 'test'})\n</script>\n<script>\nexport const title = \"Hey\"\n</script>\"\n`;\n\nexports[`transform > escapeCodeTagInterpolation 1`] = `\n\"<template><div class=\"markdown-body\"><div>{{hello}}</div>\n<pre><code class=\"language-ts\" v-pre>&lt;div&gt;{{hello}}&lt;/div&gt;\n</code></pre>\n</div></template>\n<script setup>\nconst frontmatter = {}\ndefineExpose({ frontmatter })\n</script>\"\n`;\n\nexports[`transform > export keyword frontmatters 1`] = `\n\"<template><div class=\"markdown-body\"><p>Hello</p>\n</div></template>\n<script setup>\nconst frontmatter = {\"class\":\"text\",\"default\":\"foo\"}\ndefineExpose({ frontmatter })\n</script>\n<script>\nexport const _class = \"text\"\nexport const _default = \"foo\"\n</script>\"\n`;\n\nexports[`transform > exposes frontmatter 1`] = `\n\"<template><div class=\"markdown-body\"><h1>Hello</h1>\n</div></template>\n<script setup>\nconst frontmatter = {\"title\":\"Hey\"}\ndefineExpose({ frontmatter })\n</script>\n<script>\nexport const title = \"Hey\"\n</script>\"\n`;\n\nexports[`transform > frontmatter interpolation 1`] = `\n\"<template><div class=\"markdown-body\"><h1>Hello World</h1>\n<p>This is {{frontmatter.name}}</p>\n</div></template>\n<script setup>\nconst frontmatter = {\"name\":\"My Cool App\"}\ndefineExpose({ frontmatter })\n</script>\n<script>\nexport const name = \"My Cool App\"\n</script>\"\n`;\n\nexports[`transform > script setup 1`] = `\n\"<template><div class=\"markdown-body\"><h1>Hello</h1>\n\n</div></template>\n<script setup lang=\"ts\">\nconst frontmatter = {}\ndefineExpose({ frontmatter })\nimport Foo from './Foo.vue'\n</script>\"\n`;\n\nexports[`transform > style 1`] = `\n\"<template><div class=\"markdown-body\"><h1>Hello</h1>\n\n</div></template>\n<script setup>\nconst frontmatter = {}\ndefineExpose({ frontmatter })\n</script>\n<style>h1 { color: red }</style>\"\n`;\n\nexports[`transform > vue directives 1`] = `\n\"<template><div class=\"markdown-body\">\n<p><button @click=\"onClick\"></button></p>\n</div></template>\n<script setup lang=\"ts\">\nconst frontmatter = {\"name\":\"My Cool App\"}\ndefineExpose({ frontmatter })\nfunction onClick() {\n  // ...\n}\n</script>\n<script lang=\"ts\">\nexport const name = \"My Cool App\"\n</script>\"\n`;\n"
  },
  {
    "path": "test/excerpt.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { createMarkdown } from '../src/core/markdown'\nimport { resolveOptions } from '../src/core/options'\n\ndescribe('excerpt', () => {\n  it('rendered excerpt', async () => {\n    const options = resolveOptions({\n      excerpt: true,\n      frontmatterOptions: {\n        grayMatterOptions: {\n          excerpt: true,\n          excerpt_separator: '<!-- more -->',\n        },\n      },\n    })\n    const markdownToVue = createMarkdown(options)\n    const md = `---\ntitle: Hey\n---\n\nThis is an excerpt which has been rendered to **HTML**.\n\n<!-- more -->\n\n# Hello\n\n- A\n- B\n- C`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('raw excerpt', async () => {\n    const options = resolveOptions({\n      excerpt: true,\n      frontmatterOptions: {\n        renderExcerpt: false,\n        grayMatterOptions: {\n          excerpt: true,\n          excerpt_separator: '<!-- more -->',\n        },\n      },\n    })\n    const markdownToVue = createMarkdown(options)\n    const md = `---\ntitle: Hey\n---\n\nThis is an excerpt which is kept as **raw Markdown**.\n\n<!-- more -->\n\n# Hello\n\n- A\n- B\n- C`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "test/fixtures/simple.md",
    "content": "---\ntitle: Hello World\ndescription: testing is the path to true happiness\n---\n\n# My H1\n\nlorem ipsum\n\n## Transformed\n\nbase: {{ title }}\n"
  },
  {
    "path": "test/frontmatterPreprocessor.test.ts",
    "content": "import type { MetaProperty, ResolvedOptions } from '../src/types'\nimport { readFile } from 'node:fs/promises'\nimport { describe, expect, it } from 'vitest'\nimport { createMarkdown } from '../src/core/markdown'\nimport { resolveOptions } from '../src/core/options'\n\nconst frontmatterPreprocess: ResolvedOptions['frontmatterPreprocess'] = (fm) => {\n  const frontmatter = {\n    title: 'default title',\n    description: 'default description',\n    ...fm,\n  }\n  const meta: MetaProperty[] = [\n    { property: 'og:title', name: 'twitter:title', itemprop: 'title', content: frontmatter.title },\n    {\n      property: 'og:description',\n      name: 'twitter:description',\n      itemprop: 'description',\n      content: frontmatter.description,\n    },\n  ]\n  return {\n    head: { ...frontmatter, meta },\n    frontmatter: { ...frontmatter, meta },\n  }\n}\n\ndescribe('provide bespoke frontmatter processor', () => {\n  it('inline markdown is used over default properties', async () => {\n    const markdownToVue = createMarkdown(resolveOptions({ frontmatterPreprocess }))\n    const md = (await markdownToVue('', await readFile('test/fixtures/simple.md', 'utf-8'))).code\n\n    // Positive tests\n    expect(\n      md.includes('Hello World'),\n      'the title attribute is retained over the default \\'title\\' value',\n    ).toBeTruthy()\n    expect(\n      md.includes('testing is the path to true happiness'),\n      'description property is also retained',\n    ).toBeTruthy()\n    // Negative tests\n    expect(\n      md.includes('default title'),\n      'the title attribute is retained over the default \\'title\\' value',\n    ).toBeFalsy()\n    expect(md.includes('default description'), 'default description is ignored').toBeFalsy()\n\n    // Meta props\n    expect(md.includes('og:title')).toBeTruthy()\n    expect(md.includes('og:description')).toBeTruthy()\n  })\n})\n"
  },
  {
    "path": "test/transform.test.ts",
    "content": "import { describe, expect, it } from 'vitest'\nimport { createMarkdown } from '../src/core/markdown'\nimport { resolveOptions } from '../src/core/options'\n\ndescribe('transform', async () => {\n  const options = resolveOptions({})\n  const markdownToVue = createMarkdown(options)\n\n  it('basic', async () => {\n    const md = `---\ntitle: Hey\n---\n\n# Hello\n\n- A\n- B\n- C\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('style', async () => {\n    const md = `\n# Hello\n\n<style>h1 { color: red }</style>\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('script setup', async () => {\n    const md = `\n# Hello\n\n<script setup lang=\"ts\">\nimport Foo from './Foo.vue'\n</script>\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('exposes frontmatter', async () => {\n    const md = `---\ntitle: Hey\n---\n\n# Hello`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('couldn\\'t expose frontmatter', async () => {\n    const md = `---\ntitle: Hey\n---\n\n<script setup>\ndefineExpose({ test: 'test'})\n</script>\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('escapeCodeTagInterpolation', async () => {\n    const md = `\n<div>{{hello}}</div>\n\n\\`\\`\\`ts\n<div>{{hello}}</div>\n\\`\\`\\`\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('frontmatter interpolation', async () => {\n    const md = `\n---\nname: 'My Cool App'\n---\n\n# Hello World\n\nThis is {{frontmatter.name}}\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('vue directives', async () => {\n    const md = `\n---\nname: 'My Cool App'\n---\n\n<script setup lang=\"ts\">\nfunction onClick() {\n  // ...\n}\n</script>\n\n<button @click=\"onClick\"></button>\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('export keyword frontmatters', async () => {\n    const md = `\n---\nclass: 'text'\ndefault: 'foo'\n---\n\nHello\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n\n  it('code escape', async () => {\n    const md = `\nHello \\`{{ world }}\\`\n\n\\`\\`\\`js\nconsole.log(\\`{{ world }}\\`)\n\\`\\`\\`\n`\n    expect((await markdownToVue('', md)).code).toMatchSnapshot()\n  })\n})\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"jsx\": \"preserve\",\n    \"lib\": [\"esnext\", \"DOM\"],\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"strict\": true,\n    \"strictNullChecks\": true,\n    \"esModuleInterop\": true,\n    \"skipLibCheck\": true\n  },\n  \"exclude\": [\n    \"examples/**\",\n    \"dist/**\"\n  ]\n}\n"
  },
  {
    "path": "tsup.config.ts",
    "content": "import type { Options } from 'tsup'\n\nexport default <Options>{\n  entryPoints: [\n    'src/*.ts',\n  ],\n  clean: true,\n  format: ['cjs', 'esm'],\n  dts: true,\n  shims: true,\n  splitting: true,\n  onSuccess: 'npm run build:fix',\n}\n"
  }
]