代码拉取完成,页面将自动刷新
{
"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"
}
}
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'), // 要转换的markdown文件
filename: 'test.html',
})
]
}
function randomNum() {
return new Date().getTime() + parseInt(Math.random() * 10000);
}
module.exports = {
randomNum
}
<!-- inner -->
<!DOCTYPE html>
<html lang="en">
<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>Document</title>
</head>
<body>
<!-- inner -->
</body>
</html>
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);
// 因为存在null,所以真才处理
if(matched) {
const mark = matched[1],
input = matched['input'];
// 以#号开头
if(reg_sharp.test(mark)) {
// 有几个#号就是h几
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`;
// 判断当前上一次的mark是否匹配正则
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 {
_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;
// console.log(_htmlPool);
for(var k in _htmlPool) {
// console.log(k, _htmlPool[k]);
item = _htmlPool[k];
// console.log(item);
if(item.type === 'single') {
// 遍历拼接type 为single的html字符串
item.tags.map(tag => {
console.log(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;
}
}
// console.log(_htmlStr);
return _htmlStr;
}
module.exports = {
compileHTML
}
/**
* {
* h1: {
* type: 'single',
* tags: [<h1>这是一个h1的标题</h1>]
* },
* ul: {
* type: 'wrap'
* tags: [
* '<li>这是UL列表的第1项</li>',
* '<li>这是UL列表的第1项</li>',
* '<li>这是UL列表的第1项</li>',
* '<li>这是UL列表的第1项</li>',
* ]
* }
* }
*/
md.html
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';
}
// webpack为每个插件提供一个方法apply
// 编译的过程中都是在apply中做的
// 有一个参数编译器 compiler
apply(compiler) {
// 编译器 下的hooks 下有个发射器
compiler.hooks.emit.tap('md-to-html-plugin', (compilation) => {
const _assets = compilation.assets;
// 读取用户webpack中配置的模板文件
const _mdContent = readFileSync(this.template, 'utf8');
// 读取模板html
const _templateHTML = readFileSync(resolve(__dirname, 'template.html'), 'utf8')
// 将md文件一行一行的存储到数组中
const _mdContentArr = _mdContent.split('\n');
// 编译md字符串为html字符串
const _htmlStr = compileHTML(_mdContentArr);
console.log(_htmlStr);
// 将注释替换成md字符串转换成的html字符串
const _finalHTML = _templateHTML.replace(INNER_MARK, _htmlStr);
// 在_assets上增加资源
_assets[this.filename] = {
source() { // 方法返回一个资源
return _finalHTML;
},
size() { // 一般return 资源的长度
return _finalHTML.length;
}
}
// console.log(_assets);
})
}
}
module.exports = MdToHtmlPlugin;
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。