代码拉取完成,页面将自动刷新
// 加载 md 配置文件
const config = require('./md-doc.json');
const ossConfig = require('./md-oss.json')
const fs = require('fs-extra');
const path = require('path');
const marked = require('marked');
const open = require('open');
const url = require('url');
const http = require('http');
const OSS = require('ali-oss');
const md_template_path = "./md-doc.html";
const md_menu_path = "./md-menu.md";
const args = process.argv.slice(1);
let has_open = "OFF"
let push_oss = "OFF"
if (args.length > 1) {
has_open = args[1];
}
if (args.length > 2) {
push_oss = args[2];
}
// todo 代码目录
const dir_src = "./" + config.src;
// todo 编译后目录
const dir_dist = "./" + config.dist;
const rendererMenuLink = new marked.Renderer();
let cur_file = "";
// 重写链接的渲染方法
rendererMenuLink.link = function (_obj) {
// console.log(_obj, cur_file);
let _htmlHref = _obj.href + ".html";
let _tempCurFile = cur_file.replaceAll(path.sep, "/");
cur_file = _tempCurFile;
let _class_a = "doc-menu-a";
if (_htmlHref == _tempCurFile) {
_class_a = "doc-menu-active-a"
}
return `<a href="${_htmlHref}" class="${_class_a}" title="${_obj.title || ''}">${_obj.text}</a>`;
};
/**
* 读取src 下的md文件
*/
function readDir(dir, _extname) {
fs.readdir(dir, (err, files) => {
if (err) {
console.error('无法读取文件夹:', err);
return;
}
files.forEach(file => {
const filePath = path.join(dir, file);
fs.stat(filePath, (err, stats) => {
if (err) {
console.error('无法获取文件状态:', err);
return;
}
if (stats.isDirectory()) {
readDir(filePath, _extname); // 递归读取子文件夹
} else if (path.extname(file).toLowerCase() === _extname) {
fs.readFile(filePath, 'utf8', (err, data) => {
let _fileName = filePath.replaceAll(config.src, "");
_fileName = _fileName.replaceAll('.md', '.html');
let level1Headings = data.match(/^#\s+(.*)$/gm);
if (!level1Headings) {
level1Headings = config.title;
} else {
level1Headings += ("|" + config.title);
level1Headings = level1Headings.replaceAll("#", "");
}
let html = marked.parse(data);
//todo 渲染html
html = readerHtml(html, _fileName, level1Headings);
createFile(_fileName, html)
});
}
});
});
});
}
//todo 创建文件
function createFile(fileName, content) {
const fullPath = path.join(dir_dist, fileName);
const directoryPath = path.dirname(fullPath);
// 检查目录是否存在,如果不存在则创建目录
if (!fs.existsSync(directoryPath)) {
fs.mkdirSync(directoryPath, { recursive: true });
}
// 创建文件
fs.writeFileSync(fullPath, content);
}
/**
* 拷贝目录
* @param {*} source
* @param {*} destination
*/
function copyDirectory(source, destination) {
if (destination.indexOf('pages') > 0) {
return;
}
// if (destination.indexOf('components') > 0) {
// return;
// }
// 创建目标目录
fs.mkdirSync(destination, { recursive: true });
// 读取源目录中的所有文件和子目录
const files = fs.readdirSync(source);
// 遍历文件列表
for (const file of files) {
// 构建源文件路径和目标文件路径
const sourcePath = path.join(source, file);
const destinationPath = path.join(destination, file);
// 如果是文件,则拷贝文件内容
if (fs.lstatSync(sourcePath).isFile()) {
fs.writeFileSync(destinationPath, fs.readFileSync(sourcePath));
} else if (fs.lstatSync(sourcePath).isDirectory()) {
// 如果是目录,则递归拷贝子目录
copyDirectory(sourcePath, destinationPath);
}
}
}
// 拷贝文件
function copyFile(source, destination) {
// 读取源目录中的所有文件和子目录
const files = fs.readdirSync(source);
// 遍历文件列表
for (const file of files) {
// 构建源文件路径和目标文件路径
const sourcePath = path.join(source, file);
const destinationPath = path.join(destination, file);
// 如果是文件,则拷贝文件内容
if (fs.lstatSync(sourcePath).isFile()) {
if (sourcePath.endsWith('.md')) {
continue;
}
fs.writeFileSync(destinationPath, fs.readFileSync(sourcePath));
}
}
}
/**
* 读取src 下的md文件
*/
function copyImage(source, destination, _extname) {
// 读取源目录中的所有文件和子目录
const files = fs.readdirSync(source);
// 遍历文件列表
for (const file of files) {
// 构建源文件路径和目标文件路径
const sourcePath = path.join(source, file);
const destinationPath = path.join(destination, file);
// 如果是文件,则拷贝文件内容
if (fs.lstatSync(sourcePath).isFile()) {
if (!sourcePath.endsWith(_extname)) {
continue;
}
let directoryPath = path.dirname(destinationPath);
// 检查目录是否存在,如果不存在则创建目录
if (!fs.existsSync(directoryPath)) {
fs.mkdirSync(directoryPath, { recursive: true });
}
fs.writeFileSync(destinationPath, fs.readFileSync(sourcePath));
} else {
copyImage(sourcePath, destinationPath, _extname);
}
}
}
// 渲染html
function readerHtml(html, _curlPath, _level1Headings) {
let templateHtml = fs.readFileSync(md_template_path, { encoding: 'utf8' });
cur_file = _curlPath;
let _positon = config.src + cur_file.replaceAll(path.sep, "/").replaceAll('.html', '.md');
//todo 替换位置
templateHtml = templateHtml.replaceAll("{{positon}}", _positon);
templateHtml = templateHtml.replaceAll("{{positonHref}}", config.docUrl + "/" + _positon);
//todo 替换 标题
templateHtml = templateHtml.replaceAll("{{title}}", _level1Headings);
//todo 替换 logo
templateHtml = templateHtml.replaceAll("{{logo}}", config.title);
//todo 替换 描述
templateHtml = templateHtml.replaceAll("{{description}}", _level1Headings + config.description);
//todo 替换 内容
templateHtml = templateHtml.replaceAll("<md-content></md-content>", html);
const fileNameWithoutExt = path.basename(_curlPath, path.extname(_curlPath));
if (fileNameWithoutExt.indexOf('_') < 0) {
return templateHtml;
}
let _menuFile = fileNameWithoutExt.split("_")[1];
let mdMenu = fs.readFileSync(_menuFile + ".md", { encoding: 'utf8' });
let menuHtml = marked.parse(mdMenu, { renderer: rendererMenuLink });
//todo 替换 菜单
templateHtml = templateHtml.replaceAll("<md-menu></md-menu>", menuHtml);
//todo 替换nav内容
let _tempNavs = config[_menuFile];
let _navHtml = "";
let _navHref = "";
_tempNavs.forEach(_n => {
_navHref = _n.href.replaceAll('.md', '.html')
if (_n.target) {
_navHtml += ("<li><a href='" + _navHref + "' target='_blank'>" + _n.title + "</a></li>");
} else {
_navHtml += ("<li><a href='" + _navHref + "'>" + _n.title + "</a></li>");
}
});
templateHtml = templateHtml.replaceAll("<md-nav></md-nav>", _navHtml);
return templateHtml;
}
async function uploadDirectory(localDirPath, ossDirPrefix, client) {
try {
const files = fs.readdirSync(localDirPath);
for (let file of files) {
const localFilePath = path.join(localDirPath, file);
const stats = fs.statSync(localFilePath);
console.log(`file: ${file} `);
if (stats.isDirectory()) {
// 如果是子目录,递归上传
await uploadDirectory(localFilePath, ossDirPrefix + file + '/', client);
} else {
const ossFilePath = ossDirPrefix + file;
await client.put(ossFilePath, localFilePath);
console.log(`已成功上传文件: ${localFilePath} 到 ${ossFilePath}`);
}
}
console.log(`已成功上传目录: ${localDirPath} 到OSS`);
} catch (err) {
console.error('上传目录时出错', err);
}
}
//todo 将dist 目录保存到oss 下
async function saveToOss() {
const client = new OSS({
accessKeyId: ossConfig.accessKeyId,
accessKeySecret: ossConfig.accessKeySecret,
bucket: ossConfig.bucket,
endpoint: ossConfig.endpoint
});
// for (let i = 0; i < ossConfig.maxFile/1000; i++) {
// let result = await client.list({
// prefix: "dist",
// 'max-keys': 1000 // 可根据实际情况调整每次列举的最大数量
// });
// for (let object of result.objects) {
// console.log(`正在OSS删除文件: ${object.name} `);
// await client.delete(object.name);
// }
// }
uploadDirectory(config.dist, '/', client);
}
// 同步删除 目标文件夹
if (fs.existsSync(dir_dist)) {
fs.removeSync(dir_dist);
}
copyDirectory(dir_src + "/css", dir_dist + "/css");
copyDirectory(dir_src + "/fonts", dir_dist + "/fonts");
copyDirectory(dir_src + "/images", dir_dist + "/images");
copyFile(dir_src, dir_dist);
copyImage(dir_src, dir_dist, '.jpg');
copyImage(dir_src, dir_dist, '.png');
// todo 复制 样式文件
if (fs.lstatSync("md-doc.css").isFile()) {
fs.writeFileSync(dir_dist + "/css/style.css", fs.readFileSync("md-doc.css"));
}
readDir(dir_src, ".md");
if (has_open == 'ON') {
// 创建服务器实例
const server = http.createServer((req, res) => {
// 解析URL
const parsedUrl = url.parse(req.url, true);
// 获取不包含参数的路径部分
const pathWithoutParams = parsedUrl.pathname;
// 假设静态文件目录为
const staticDir = path.join(__dirname, config.dist);
let filePath = path.join(staticDir, pathWithoutParams);
if (filePath === path.join(staticDir, '/')) {
filePath = path.join(staticDir, 'index.html');
}
// 检查文件是否存在
fs.stat(filePath, (err, stats) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.write('404 Not Found');
res.end();
return;
}
if (stats.isDirectory()) {
filePath = path.join(filePath, 'index.html');
}
// 读取文件并返回内容
fs.readFile(filePath, (readErr, data) => {
if (readErr) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.write('500 Internal Server Error');
res.end();
return;
}
const extname = path.extname(filePath);
let contentType;
switch (extname) {
case '.html':
contentType = 'text/html';
break;
case '.css':
contentType = 'text/css';
break;
case '.js':
contentType = 'application/javascript';
break;
// 可以根据需要添加更多文件类型的处理
default:
contentType = 'text/plain';
break;
}
res.writeHead(200, { 'Content-Type': contentType });
res.write(data);
res.end();
});
});
});
server.listen(config.serverPort, () => {
console.log(`服务已启动,访问地址为 http:://localhost:${config.serverPort} ,请打开浏览器访问`);
});
const openFile = "http://localhost:" + config.serverPort;
//open(openFile);
}
if (push_oss == "ON") {
setTimeout(function(){
saveToOss();
},5000);
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。