UNPKG

@markdown-vue/mdv

Version:

Markdown-Vue (MDV) lets you write Vue-style components directly inside Markdown files.

261 lines (174 loc) 5.69 kB
# Markdown-Vue (MDV) Documentation (Updated) ## Overview Markdown-Vue (MDV) lets you write Vue-style components directly inside Markdown files. Each `.md` file can contain: - Regular Markdown content - Vue-style templates and components (standard HTML/Vue tags) - YAML frontmatter for metadata - Inline `<script>` and `<style>` blocks - A small inline component shorthand for short components This keeps the source human-readable while enabling Vue integration. --- ## Core principles - **Template-first:** Markdown is the base template; sprinkle Vue/HTML where needed. - **Standard HTML / Vue tags:** Use normal HTML elements and Vue component tags (`<div>`, `<section>`, `<UserBadge>`, etc.). MDV follows standard Vue/HTML semantics. - **Inline component shorthand:** MDV provides a concise inline shorthand for simple, content-driven components. --- ## Syntax reference ### Block elements Use standard HTML elements and Vue component tags. Attributes follow Vue syntax (`v-for`, `v-if`, `:prop`, `@click`, etc.). Example: ```md <div class="card"> # Title inside the card <p>This paragraph lives inside the div</p> </div> ``` ### Interpolation Mustache interpolation (`{{ }}`) works anywhere in the template. ```md Hello, {{ user.name }} ``` ### Inline component syntax MDV supports a compact inline component shorthand in two forms: - Slot content: ```md [text]{ ::ComponentName } ``` - Dynamic/default-slot expression: ```md :[user.name]{ ::UserBadge } ``` Props, directives, and bindings are passed inside the braces: ```md [Click me]{ ::Button :to="user.url" @click="onClick(user)" v-if="user.active" } ``` Notes: - The inline shorthand forms `[text]{ ::Component ... }` and `:[expr]{ ::Component }` are the only MDV-specific shorthands. - For multiple named slots or complex layouts prefer full component tags (`<MyComponent>...</MyComponent>`). --- ### Loops Use Vue's `v-for` on any element or component. Always include `:key`. Example with HTML tags: ```md <ul> <li v-for="(user, i) in users" :key="user.id || i"> <UserBadge>{{ user.name }}</UserBadge> </li> </ul> ``` Inline shorthand in loops: ```md :[item]{ v-for="item in items" :key="item.id || itemIndex" } ``` The `:` inline form places the evaluated expression into the default slot for the inline component. Notes: - Use `:key` with every `v-for`. - Prefer inline loops for small, simple items. --- ### Dynamic tables MDV supports dynamic rows inside standard Markdown tables using a `{ rows }` placeholder. Header is normal Markdown; rows are injected where `{ rows }` appears. A fallback row is optional. Example: ```md | id | name | action | | ------------- | ---- | ------ | | No item found | { rows } ``` How it works: - `{ rows }` is replaced by rendered rows generated from your data source. - If the data is empty and you provided a fallback row (like `| No item found |`), that row is shown. - Rows may contain inline components or full HTML/Vue tags. Simple conceptual example: ```md <!-- body --> | id | name | action | | ------------- | ---- | ------ | | No item found | { rows } <script setup> const rows = items.map(item => `| ${item.id} | ${item.name} | [Edit]{ ::EditButton :id="${item.id}" } |`).join('\\n') </script> ``` Notes: - Fallback row is optional. - Keep header as normal Markdown. --- ### Scripts and Styles You may include `<script>` and `<style>` blocks inside `.md` files. Prefer `<script setup>`. Script example: ```md <script setup lang="ts"> import UserBadge from './UserBadge.vue' import { ref } from 'vue' const users = ref([ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' } ]) </script> ``` Style example: ```md <style scoped> h1 { font-weight: 700 } </style> ``` --- ### Metadata (YAML frontmatter) MDV supports YAML frontmatter, compiled into a `.meta.json` file alongside the component. Example frontmatter: ```md --- title: Hello World description: This is my first MDV page --- # {{ $meta.title }} ``` Emitted files: - `HelloWorld.vue` (compiled component) - `HelloWorld.meta.json` (metadata) Accessing metadata: - From script: `useMeta()` **always returns a Promise** and should be `await`ed. ```ts import { useMeta } from "mdv"; const meta = await useMeta(); const otherMeta = await useMeta("/path/to/other"); ``` - From templates: `$meta` is available (`{{ $meta.title }}`). --- ## Example: Full Vue App in Markdown ```md <v-app> # My Markdown-Vue App This is an MDV page with components and markdown. <section> <h2>Users</h2> <ul> <li v-for="(u, i) in users" :key="u.id || i"> <UserBadge :user="u" /> </li> </ul> </section> </v-app> <script setup> import UserBadge from './UserBadge.vue' import { ref } from 'vue' const users = ref([ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]) </script> ``` --- ## Use cases - Static websites - Repo-based CMS - Documentation & Blogs with interactive components --- ## Notes & best practices - Prefer Vue-style attributes (`v-...` and `:`) and include `:key` on `v-for` lists. - Use the inline shorthand forms only: - `[text]{ ::ComponentName ...props ...directives }` - `:[expression]{ ::ComponentName }` - Use full HTML/Vue tags for multiple named slots or complex layouts. - Keep scripts/styles in-file for small pages; split out for complexity. ---