
plugins/md-to-html-plugin/compiler.js
const { randomNum } = require('./utils');
const reg_mark = /^(.+?)\s/;
const reg_sharp = /^\#/;
const reg_crossbar = /^\-/;
const reg_number = /^\d/;
function createTree (mdArr) {
let _htmlPool = {};
let _lastMark = '';
let _key = 0;
mdArr.forEach((mdFragment) => {
const matched = mdFragment.match(reg_mark);
if (matched) {
const mark = matched[1];
const input = matched['input'];
if (reg_sharp.test(mark)) {
const tag = `h${mark.length}`;
const tagContent = input.replace(reg_mark, '');
if (_lastMark === mark) {
_htmlPool[`${tag}-${_key}`].tags = [..._htmlPool[`${tag}-${_key}`].tags, `<${tag}>${tagContent}</${tag}>`];
} else {
_lastMark = mark;
_key = randomNum();
_htmlPool[`${tag}-${_key}`] = {
type: 'single',
tags: [`<${tag}>${tagContent}</${tag}>`]
}
}
}
if (reg_crossbar.test(mark)) {
const tagContent = input.replace(reg_mark, '');
const tag = `li`;
if (reg_crossbar.test(_lastMark)) {
_htmlPool[`ul-${_key}`].tags = [..._htmlPool[`ul-${_key}`].tags, `<${tag}>${tagContent}</${tag}>`]
} else {
_lastMark = mark;
_key = randomNum();
_htmlPool[`ul-${_key}`] = {
type: 'wrap',
tags: [`<${tag}>${tagContent}</${tag}>`]
}
}
}
if (reg_number.test(mark)) {
const tagContent = input.replace(reg_mark, '');
const tag = `li`;
if (reg_number.test(_lastMark)) {
_htmlPool[`ol-${_key}`].tags = [..._htmlPool[`ol-${_key}`].tags, `<${tag}>${tagContent}</${tag}>`]
} else {
console.log(_lastMark, mark);
_lastMark = mark;
_key = randomNum();
_htmlPool[`ol-${_key}`] = {
type: 'wrap',
tags: [`<${tag}>${tagContent}</${tag}>`]
}
}
}
}
});
return _htmlPool;
}
function compileHTML (_mdArr) {
const _htmlPool = createTree(_mdArr);
let _htmlStr = '';
let item;
for (let k in _htmlPool) {
item = _htmlPool[k];
if (item.type === 'single') {
item.tags.forEach((tag) => {
_htmlStr += tag;
});
} else if (item.type === 'wrap') {
let _list = `<${k.split('-')[0]}>`;
item.tags.forEach((tag) => {
_list += tag;
});
_list += `</${k.split('-')[0]}>`;
_htmlStr += _list;
}
}
return _htmlStr;
}
module.exports = {
compileHTML
}
plugins/md-to-html-plugin/index.js
const { readFileSync } = require('fs');
const { resolve } = require('path');
const { compileHTML } = require('./compiler');
const INNER_MARK = '<!-- inner -->';
class MdToHtmlPlugin {
constructor ({ template, filename }) {
if (!template) {
throw new Error('The config for "template" must be configured');
}
this.template = template;
this.filename = filename ? filename : 'md.html';
}
apply (compiler) {
compiler.hooks.emit.tap('md-to-html-plugin', (compilation) => {
const _assets = compilation.assets;
const _mdContent = readFileSync(this.template, 'utf8');
const _templateHTML = readFileSync(resolve(__dirname, 'template.html'), 'utf8');
const _mdContentArr = _mdContent.split('\n');
const _htmlStr = compileHTML(_mdContentArr);
const _finalHTML = _templateHTML.replace(INNER_MARK, _htmlStr);
_assets[this.filename] = {
source () {
return _finalHTML;
},
size () {
return _finalHTML.length;
}
}
})
}
}
module.exports = MdToHtmlPlugin;
plugins/md-to-html-plugin/template.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
</html>
plugins/md-to-html-plugin/utils.js
function randomNum () {
return new Date().getTime() + parseInt(Math.random() * 10000);
}
module.exports = {
randomNum
}
test.md
# 这是一个h1的标题
- 这是UL列表第1项
- 这是UL列表第2项
- 这是UL列表第3项
- 这是UL列表第4项
## 这是一个h2的标题
1. 这是OL列表第1项
2. 这是OL列表第2项
3. 这是OL列表第3项
4. 这是OL列表第4项
package.json
{
"name": "md-to-html-plugin",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.30.0",
"webpack-cli": "^3.3.0",
"webpack-dev-server": "^3.7.2"
}
}
webpack.config.js
const { resolve } = require('path')
const MdToHtmlPlugin = require('./plugins/md-to-html-plugin')
module.exports = {
mode: 'development',
entry: resolve(__dirname, 'src/app.js'),
output: {
path: resolve(__dirname, 'dist'),
filename: 'app.js'
},
plugins: [
new MdToHtmlPlugin({
template: resolve(__dirname, 'test.md'),
filename: 'test.html'
})
]
}