feature: vor und nachteile

This commit is contained in:
Hikyu
2026-05-31 13:54:31 +02:00
parent 552a947a1c
commit e3dad17446
23270 changed files with 3024794 additions and 200 deletions
+17
View File
@@ -0,0 +1,17 @@
<script setup lang='ts'>
import { ref } from 'vue'
import ComponentA from './README.md'
const current = ref()
</script>
<template>
<router-view v-slot="{ Component }">
<component :is="Component" ref="current" />
</router-view>
<div v-if="current">
accessing frontmatter from outside via expose API:
{{ current.frontmatter }}
</div>
<ComponentA style="padding: 20px 40px" />
</template>
@@ -0,0 +1,26 @@
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps<{ init?: number }>()
const counter = ref(props.init || 0)
</script>
<template>
<div class="counter">
<div>Counter: {{ counter }}</div>
<button @click="counter += 1">
Inc
</button>
<button @click="counter -= 1">
Dec
</button>
</div>
</template>
<style scoped>
.counter {
border: 2px dashed #3eaf7c;
padding: 5px 10px 10px 10px;
}
</style>
@@ -0,0 +1,26 @@
<script setup lang="ts">
import { ref } from 'vue'
const props = defineProps<{ init?: number }>()
const counter = ref(props.init || 0)
</script>
<template>
<div class="counter">
<div>Counter 2: {{ counter }}</div>
<button @click="counter += 1">
Inc
</button>
<button @click="counter -= 1">
Dec
</button>
</div>
</template>
<style scoped>
.counter {
border: 2px dashed skyblue;
padding: 5px 10px 10px 10px;
}
</style>
@@ -0,0 +1,341 @@
# unplugin-vue-markdown
[![NPM version](https://img.shields.io/npm/v/unplugin-vue-markdown?color=a1b858)](https://www.npmjs.com/package/unplugin-vue-markdown)
Compile Markdown to Vue component.
- 📚 Use Markdown as Vue components.
- 💚 Use Vue components in Markdown.
- 🔌 Supports Vite, Webpack, Vue CLI and more, powered by [unplugin](https://github.com/unjs/unplugin).
- ⚡️ The same transformation as [VitePress](https://vitepress.vuejs.org/).
## Install
```bash
npm i unplugin-vue-markdown
```
<details>
<summary>Vite</summary><br>
```ts
// vite.config.ts
import Vue from '@vitejs/plugin-vue'
import Markdown from 'unplugin-vue-markdown/vite'
export default defineConfig({
plugins: [
Vue({
include: [/\.vue$/, /\.md$/], // <-- allows Vue to compile Markdown files
}),
Markdown({ /* options */ }),
],
})
```
Example: [`examples/vite`](./examples/vite/)
<br>
</details>
<details>
<summary>Webpack</summary><br>
```ts
// webpack.config.js
const Markdown = require('unplugin-vue-markdown/webpack')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
/* ... */
module: {
rules: [
// ... other rules
{
test: /\.(vue|md)$/,
loader: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin(),
Markdown({ /* options */ })
]
}
```
<br>
</details>
<details>
<summary>Vue CLI</summary><br>
```ts
// vue.config.js
const Markdown = require('unplugin-vue-markdown/webpack')
module.exports = {
parallel: false, // Disable thread-loader which will cause errors, we are still investigating the root cause
chainWebpack: (config) => {
config.module
.rule('vue')
.test(/\.(vue|md)$/) // <-- allows Vue to compile Markdown files
config
.plugin('markdown')
.use(Markdown({
markdownItUses: [
prism,
],
}))
},
}
```
Example: [`examples/vue-cli`](./examples/vue-cli/)
<br>
</details>
## Import Markdown as Vue components
```html
<template>
<HelloWorld />
</template>
<script>
import HelloWorld from './README.md'
export default {
components: {
HelloWorld,
},
}
</script>
```
## Use Vue Components inside Markdown
You can even use Vue components inside your markdown, for example
```html
<Counter :init='5'/>
```
<Counter :init='5'/>
Note you can either register the components globally, or use the `<script setup>` tag to register them locally.
```ts
import { createApp } from 'vue'
import App from './App.vue'
import Counter from './Counter.vue'
const app = createApp(App)
// register global
app.component('Counter', Counter) // <--
app.mount()
```
```html
<script setup>
import { Counter } from './Counter.vue'
</script>
<Counter :init='5'/>
```
Or you can use [`unplugin-vue-components`](#work-with-unplugin-vue-components) for auto components registration.
## Frontmatter
Frontmatter will be parsed and inject into Vue's instance data `frontmatter` field.
For example:
```md
---
name: My Cool App
---
# Hello World
This is {{frontmatter.name}}
```
Will be rendered as
```html
<h1>Hello World</h1>
<p>This is My Cool App</p>
```
It will also be passed to the wrapper component's props if you have set `wrapperComponent` option.
## Document head and meta
To manage document head and meta, you would need to install [`@unhead/vue`](https://unhead.harlanzw.com/integrations/vue/setup) and do some setup.
```bash
npm i @unhead/vue
```
```js
// vite.config.js
import Vue from '@vitejs/plugin-vue'
import Markdown from 'unplugin-vue-markdown/vite'
export default {
plugins: [
Vue({
include: [/\.vue$/, /\.md$/],
}),
Markdown({
headEnabled: true // <--
})
]
}
```
```js
// src/main.js
import { createHead } from '@unhead/vue' // <--
import { createApp } from 'vue'
const app = createApp(App)
const head = createHead() // <--
app.use(head) // <--
```
Then you can use frontmatter to control the head. For example:
```yaml
---
title: My Cool App
meta:
- name: description
content: Hello World
---
```
For more options available, please refer to [`@unhead/vue`'s docs](https://unhead.harlanzw.com/integrations/vue/setup).
## Options
`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
```ts
// vite.config.js
import MarkdownItAnchor from 'markdown-it-anchor'
import MarkdownItPrism from 'markdown-it-prism'
import Markdown from 'unplugin-vue-markdown/vite'
export default {
plugins: [
Markdown({
// default options passed to markdown-it
// see: https://markdown-it.github.io/markdown-it/
markdownItOptions: {
html: true,
linkify: true,
typographer: true,
},
// A function providing the Markdown It instance gets the ability to apply custom settings/plugins
markdownItSetup(md) {
// for example
md.use(MarkdownItAnchor)
md.use(MarkdownItPrism)
},
// Class names for the wrapper div
wrapperClasses: 'markdown-body'
})
],
}
```
See [the tsdoc](./src/types.ts) for more advanced options
## Example
See the [/examples](./examples).
Or the pre-configured Markdown template [Vitesse](https://github.com/antfu/vitesse).
## Integrations
### Work with [vite-plugin-pages](https://github.com/hannoeru/vite-plugin-pages)
```ts
import Vue from '@vitejs/plugin-vue'
import Markdown from 'unplugin-vue-markdown/vite'
import Pages from 'vite-plugin-pages'
export default {
plugins: [
Vue({
include: [/\.vue$/, /\.md$/],
}),
Pages({
extensions: ['vue', 'md'],
}),
Markdown()
],
}
```
Put your markdown under `./src/pages/xx.md`, then you can access the page via route `/xx`.
### Work with [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)
`unplugin-vue-components` allows you to do on-demand components auto-importing without worrying about registration.
```ts
import Vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import Markdown from 'unplugin-vue-markdown/vite'
export default {
plugins: [
Vue({
include: [/\.vue$/, /\.md$/],
}),
Markdown(),
// should be placed after `Markdown()`
Components({
// allow auto load markdown components under `./src/components/`
extensions: ['vue', 'md'],
// allow auto import and register components used in markdown
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
})
],
}
```
Components under `./src/components` can be directly used in markdown components, and markdown components can also be put under `./src/components` to be auto imported.
## TypeScript Shim
```ts
declare module '*.vue' {
import type { ComponentOptions } from 'vue'
const Component: ComponentOptions
export default Component
}
declare module '*.md' {
import type { ComponentOptions } from 'vue'
const Component: ComponentOptions
export default Component
}
```
## License
MIT License © 2020-PRESENT [Anthony Fu](https://github.com/antfu)
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite MD</title>
<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" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/LukeAskew/prism-github@master/prism-github.css" />
</head>
<body>
<div id="app"></div>
<script type="module" src="./main.ts"></script>
</body>
</html>
+29
View File
@@ -0,0 +1,29 @@
import { createHead } from '@unhead/vue'
import routes from 'pages-generated'
import { createApp } from 'vue'
import {
createRouter,
createWebHistory,
} from 'vue-router'
import App from './App.vue'
import Counter from './Counter.vue'
import 'prismjs'
import 'prismjs/components/prism-bash'
import 'prismjs/components/prism-typescript'
import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-markup'
import 'prismjs/components/prism-markup-templating'
const app = createApp(App)
const head = createHead()
const router = createRouter({
history: createWebHistory(),
routes,
})
app.use(head)
app.use(router)
app.component('Counter', Counter)
app.mount('#app')
@@ -0,0 +1,24 @@
{
"type": "module",
"private": true,
"scripts": {
"dev": "cross-env DEBUG=unplugin-vue-markdown:* vite",
"build": "cross-env DEBUG=unplugin-vue-markdown:* vite build"
},
"dependencies": {
"@unhead/vue": "^1.11.13",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.2.1",
"cross-env": "^7.0.3",
"markdown-it-prism": "^2.3.0",
"prismjs": "^1.29.0",
"typescript": "^5.7.2",
"unplugin-vue-markdown": "workspace:*",
"vite": "^6.0.1",
"vite-plugin-inspect": "^0.10.2",
"vite-plugin-pages": "^0.32.4"
}
}
@@ -0,0 +1,35 @@
---
title: Hello
meta:
- name: description
content: Hello World
test: test
---
# Hello world!
Front matter: {{ frontmatter }}
<style>
h1 {
color: cadetblue;
}
</style>
<script setup>
import Counter2 from '../Counter2.vue'
</script>
<Counter />
<br>
<Counter2 />
<router-link to="/">Home</router-link>
<route>
{
meta: {
layout: 'home'
}
}
</route>
@@ -0,0 +1,11 @@
<template>
route test
</template>
<route>
{
meta: {
layout: 'home'
}
}
</route>
@@ -0,0 +1,31 @@
import Vue from '@vitejs/plugin-vue'
import prism from 'markdown-it-prism'
import Markdown from 'unplugin-vue-markdown/vite'
import { defineConfig } from 'vite'
import Inspect from 'vite-plugin-inspect'
import Pages from 'vite-plugin-pages'
export default defineConfig({
plugins: [
Vue({
include: [/\.vue$/, /\.md$/],
}),
Markdown({
markdownItOptions: {
},
headEnabled: true,
markdownItUses: [
prism,
],
}),
Pages({
pagesDir: 'pages',
extensions: ['vue', 'md'],
}),
Inspect(),
],
build: {
sourcemap: true,
},
})
@@ -0,0 +1,13 @@
declare module '*.vue' {
import type { ComponentOptions } from 'vue'
const Component: ComponentOptions
export default Component
}
declare module '*.md' {
import type { ComponentOptions } from 'vue'
const Component: ComponentOptions
export default Component
}
@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
],
}
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}
@@ -0,0 +1,26 @@
{
"name": "example-vue-cli",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.39.0",
"vue": "^3.5.13"
},
"devDependencies": {
"@babel/core": "^7.26.0",
"@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-service": "~5.0.8",
"unplugin-vue-markdown": "workspace:*"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
}
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
@@ -0,0 +1,25 @@
<script>
import Markdown from './Hi.md'
export default {
name: 'App',
components: {
Markdown,
},
}
</script>
<template>
<Markdown />
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
@@ -0,0 +1,3 @@
# Hello
Hey
@@ -0,0 +1,4 @@
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
@@ -0,0 +1,21 @@
const { defineConfig } = require('@vue/cli-service')
const prism = require('markdown-it-prism')
const Markdown = require('unplugin-vue-markdown/webpack')
module.exports = defineConfig({
transpileDependencies: true,
parallel: false,
chainWebpack: (config) => {
config.module
.rule('vue')
.test(/\.(vue|md)$/)
config
.plugin('markdown')
.use(Markdown({
markdownItUses: [
prism,
],
}))
},
})