Webpack loader for converting Markdown files to alive Vue components.
- Live vue/html code blocks
- Use virtual file system to create vue component files
- Cache same vue component
- Hot reload
- Built-in syntax highlighter with highlightjs
- Configurable markdown-it parser
Support two kinds of code blocks to live:
- html code
<u-button>Button</u-button>
<u-input></u-input>
- vue code
<template>
<div :class="$style.root">
<u-button>Button</u-button>
<u-input v-model="value"></u-input>
</div>
</template>
<script>
export default {
data() {
return {
value: 'Hello world!',
};
},
};
</script>
<style module>
.root {
width: 200px;
background: #eee;
}
</style>
npm i -D @vusion/md-vue-loader
Simply use @vusion/md-vue-loader
to load .md
files and chain it with your vue-loader
.
module.exports = {
module: {
rules: [{
test: /\.md$/,
loader: 'vue-loader!@vusion/md-vue-loader',
}],
},
};
Note that to get code highlighting to work, you need to:
- Include one of the highlight.js css files into your project. For example: [https://highlightjs.org/static/demo/styles/atom-one-dark.css].
- Specify a lang in code block. Ref: (creating and highlighting code blocks)[https://help.github.com/articles/creating-and-highlighting-code-blocks/].
module.exports = {
module: {
rules: [{
test: /\.md$/,
use: [
'vue-loader',
{
loader: '@vusion/md-vue-loader',
options: {
// your preferred options
},
},
],
}],
},
};
Remember that you can override options in markdown files query.
const routes = [
{ path: 'article', component: import('./article.md?live=false') },
]
Enable/Disable live detecting and assembling vue/html code blocks.
- Type:
boolean
- Default:
true
Process after fetching live components from code blocks
- Type:
Function
- Default:
null
- @param {string} live - code of live components
- @param {string} code - highlighted code of raw content
- @param {string} content - raw content
- @param {string} lang - code block lang
For example:
codeProcess(live, code, content, lang) {
// do anything
return `<div>${live}</div>` + '\n\n' + code;
}
For another example, suppose you have a complex container component called <code-example>
, with some useful slots.
codeProcess(live, code, content, lang) {
// do anything
return `<code-example lang="${lang}">
<div>${live}</div>
<div slot="code">${code}</div>
</code-example>\n\n`;
}
The wrapper of entire markdown content, can be HTML tag name or Vue component name.
- Type:
string
- Default:
'section'
markdown-it options.
- Type:
Object
- Default:
{
html: true,
langPrefix: 'lang-',
highlight: (content, lang) => {
content = content.trim();
lang = lang.trim();
let hlLang = lang;
if (lang === 'vue')
hlLang = 'html';
let code = '';
if (hlLang && hljs.getLanguage(hlLang)) {
try {
const result = hljs.highlight(hlLang, content).value;
code = `<pre class="hljs ${markdown.options.langPrefix}${lang}"><code>${result}</code></pre>\n`;
} catch (e) {}
} else {
const result = markdown.utils.escapeHtml(content);
code = `<pre class="hljs"><code>${result}</code></pre>\n`;
}
const live = this.options.live ? this.liveComponent(lang, content) : '';
return this.options.codeProcess.call(this, live, code, content, lang);
},
};
markdown-it plugins list.
- Type:
Array
- Default:
[]
For example:
plugins: [
require('markdown-it-task-lists'),
],
markdown-it renderer rules.
- Type:
Object
- Default:
{}
For example:
rules: {
'table_open': () => '<div class="table-responsive"><table class="table">',
'table_close': () => '</table></div>'
}
Process before converting.
- Type:
Function
- Default:
null
- @param {string} source - Markdown source content
For example:
preprocess(source) {
// do anything
return source
}
Process after converting.
- Type:
Function
- Default:
null
- @param {string} result - Final converted result
For example:
postprocess(result) {
// do anything
return result
}
- Type:
Function
- Default:
null
npm run test
open test/index.html
npm run test:options
open test/index.html
npm run test:plugins
open test/index.html
npm run test:dev
See Releases