linux-command/build/compile.js

392 lines
12 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var exec = require('child_process').exec;
var fs = require('fs');
var ejs = require('ejs');
var path = require('path');
var marked = require('marked');
var watch = require('watch');
var stylus = require('stylus')
var highlight = require('highlight.js')
var UglifyJS = require("uglify-js");
var renderer = new marked.Renderer();
var color = require('colors-cli/safe');
var error = color.red.bold;
var warn = color.yellow;
var notice = color.blue;
var success = color.green;
// console.log("该行代码所在的目录::",__dirname);
// console.log("当前运行的的根目录::",path.dirname(__dirname));
// console.log("当前目录名字::",path.basename(process.cwd()));
// console.log("当前目录::",process.cwd());
renderer.heading = function (text, level) {
if(/[\u4E00-\u9FA5]/i.test(text)){
return '<h' + level + ' id="'+text.toLowerCase()+'">'+text+'</h' + level + '>';
}else{
var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
return '<h' + level + ' id="'+escapedText+'">'+text+'</h' + level + '>';
}
}
marked.setOptions({
renderer: renderer,
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: false,
smartLists: true,
smartypants: false,
highlight: function (code, lang, callback) {
lang = lang?lang:"bash";
return callback('',highlight.highlight(lang,code).value);
}
// highlight: function (code, lang, callback) {
// if(lang){
// return highlight.highlight(lang,code).value;
// // return callback('',highlight.highlight(lang,code).value);
// }else{
// return highlight.highlightAuto(code).value;
// // return callback('',highlight.highlightAuto(code).value);
// }
// }
});
// 根目录
// var path_root = path.dirname(__dirname);
var path_root = process.cwd();
// 删除文件夹
exec('rm -rf .deploy');
// .deploy
// 当前项目根目录
// 生成 项目所需的文件
CreateDatajs('./.deploy/js/dt.js',function(dt_path,arr){
// 拷贝 favicon.ico 文件 start
var filetopath = path.join(process.cwd(),'/template/img/favicon.ico');
var topath = '.deploy/img/favicon.ico'
mkdirsSync(path.join(process.cwd(),'.deploy/img/'));
// 创建读取流
readable = fs.createReadStream( filetopath );
// 创建写入流
writable = fs.createWriteStream(topath);
// 通过管道来传输流
readable.pipe( writable);
console.log(success(" → ")+topath + '');
// 拷贝 favicon.ico 文件 end
CreateJS('/template/js/index.js','/.deploy/js/index.js')
CreateStyl('/template/styl/index.styl','/.deploy/css/index.css')
// 首页生成
ReadTmpToHTML('/template/index.ejs','/.deploy/index.html',null,{
'p':'/index.html',
'n':'Linux命令搜索引擎',
'd':'最专业的Linux命令大全内容包含Linux命令手册、详解、学习值得收藏的Linux命令速查手册。',
'command_length':arr.length
});
ReadTmpToHTML('/template/list.ejs','/.deploy/list.html',null,{
p:'/list.html',
n:'搜索',
d:'最专业的Linux命令大全命令搜索引擎内容包含Linux命令手册、详解、学习值得收藏的Linux命令速查手册。'
});
ReadTmpToHTML('/template/hot.ejs','/.deploy/hot.html',null,{
p:'/hot.html',
n:'搜索',
d:'最专业的Linux命令大全命令搜索引擎内容包含Linux命令手册、详解、学习值得收藏的Linux命令速查手册。',
arr:arr
});
// 文章批量生成
arr.forEach(function(itm,idx){
var ejstpm = path.join('/template/',itm.p);
var md_path = path.join('/command',itm.p);
var dep = path.join('/.deploy/c',itm.p);
ReadTmpToHTML('/template/details.ejs', dep+'.html' ,md_path+'.md', itm ,arr)
});
console.log(success(" → "),arr.length)
})
function copy(src, dst) {
fs.createReadStream(src).pipe(fs.createWriteStream(dst));
}
// // 监听实时编译
// watch.watchTree(path.join(path.dirname(__dirname),'/'), function (f, curr, prev) {
// if (typeof f == "object" && prev === null && curr === null) {
// console.log(success(" → :watching ") + '/template/');
// // Finished walking the tree
// } else if (prev === null) {
// // f is a new file
// } else if (curr.nlink === 0) {
// // f was removed
// } else {
// if(/\.styl$/.test(f)){
// CreateStyl('/template/styl/index.styl','/.deploy/css/index.css')
// }else if(/\.js$/.test(f)){
// CreateJS('/template/js/index.js','/.deploy/js/index.js')
// }else if(/\.ejs$/.test(f)){
// // 首页生成
// ReadTmpToHTML('/template/index.ejs','/.deploy/index.html');
// ReadTmpToHTML('/template/list.ejs','/.deploy/list.html');
// }else if(/\.md$/.test(f)){
// var mdp = f.replace(path_root,'');
// var dep = path.join('/.deploy/',mdp);
// ReadTmpToHTML('/template/details.ejs',dep.replace('.md','.html'),mdp);
// }
// }
// })
function CreateJS(from_path,to_path){
// 生成到指定目录
var new_to_path = path.join(path.dirname(__dirname),to_path);
// 循环创建目录
mkdirsSync(path.dirname(new_to_path));
var js_code = UglifyJS.minify(path.join(path_root,from_path), { mangle: { toplevel: true } });
fs.writeFileSync(new_to_path, js_code.code);
console.log(success(" → ")+to_path + '');
}
/**
* [ReadTmpToHTML ejs 模板转换成HTML]
* @param {[type]} from_path [模版来源地址]
* @param {[type]} to_path [生成到指定的位置]
* @param {[type]} md_path [Markdown的路径] // 给md地址就生产详情页面
* @param {[type]} des_json [页面信息 json 格式]
* @param {[type]} arr []
*/
function ReadTmpToHTML(from_path,to_path,md_path,des_json, total_pages){
var tmp_path = path.join(path.dirname(__dirname),from_path);
if(!exists(tmp_path)) return console.log("\n → error: 模板文件 "+tmp_path+" 不存在")
var tmp_str = fs.readFileSync(tmp_path);
tmp_str = tmp_str.toString();
var relative_path = '';
var current_path = to_path.replace(/^\/\.deploy/,'');
if(md_path){
//CSS/JS 引用相对地址
relative_path = path.relative(md_path.toString(),'/');
relative_path = relative_path.replace(/\.\.$/,'');
}
// 生成 HTML
var html = ejs.render(tmp_str,{
filename: tmp_path,
relative_path:relative_path, // 当前文件相对于根目录的相对路径
md_path:md_path?md_path:'', // markdown 路径
current_path:current_path, // 当前 html 路径
describe:des_json?des_json:{}, // 当前 md 的描述
});
// 生成到指定目录
var new_to_path = path.join(path.dirname(__dirname),to_path);
// 循环创建目录
!exists(path.dirname(new_to_path)) && mkdirsSync(path.dirname(new_to_path));
if(md_path){
var new_md_path = path.join(path.dirname(__dirname),md_path);
var README_str = fs.readFileSync(new_md_path);
marked(README_str.toString(),function(err,md_html){
if (err) return console.log(error(' → '+md_path+" 转换成HTML失败!"));
html = html.split('{{content}}')
html.splice(1, 0, md_html);
html = html.join('')
// html = html.replace('{{content}}',md_html);
fs.writeFileSync(new_to_path,html);
console.log(success(" → ")+to_path + '');
})
}else{
html = html.toString();
fs.writeFileSync(new_to_path, html.replace(/\n/g,''));
console.log(success(" → ")+to_path + '');
}
}
/**
* [CreateStyl 生成CSS]
* @param {[type]} styl_path [description]
* @param {[type]} css_path [description]
*/
function CreateStyl(styl_path,css_path){
var new_css_path = path.join(path.dirname(__dirname),css_path);
styl_path = path.dirname(__dirname) + styl_path;
// var paths = [
// path.dirname(__dirname) , path.dirname(__dirname) + '/'
// ];
var styl_str = fs.readFileSync(styl_path, 'utf8');
stylus(styl_str.toString())
.set('filename', styl_path )
.set('compress', true)
.render(function(err, css){
if (err) throw err;
// 循环创建目录
mkdirsSync(path.dirname(new_css_path));
fs.writeFileSync(new_css_path, css);
// console.log(err,css);
console.log(success(" → ")+styl_path + '');
});
}
// 生成数据索引JS
function CreateDatajs(dt_path,callback){
// 获取 markdown文件所在的目录
var path_md = path.join(path.dirname(__dirname),'command');
var path_dist = path.join(path.dirname(__dirname),'dist');
if(!exists(path_md)) return console.log("\n → error: 文件夹 "+path_md+" 不存在 \n ")
// 获取 markdown 目录的集合
var path_arr = readMDSync(path_md);
path_arr = sortLength(path_arr);
var indexes = [];
var command_data={}
path_arr.forEach(function(md_path,i){
var json = {}
var con = fs.readFileSync(md_path);
var str = con.toString();
var title = str.match(/[^===]+(?=[===])/g);
title = title[0]?title[0].replace(/\n/g,''):title[0];
// 命令名称
json["n"] = title;
// 命令路径
json["p"] = md_path.replace(/\.md$/,'').replace(path_md,'');
// 命令描述
var des = str.match(/\n==={1,}([\s\S]*?)##/i);
des = des[1]?des[1].replace(/\n/g,''):des[1];
des = des.replace(/\r/g,'')
json["d"] = des;
indexes.push(json)
command_data[title] = json;
})
mkdirsSync(path.dirname(dt_path));
console.log("path.dirname(__dirname)",path.dirname(__dirname))
//生成数据文件
fs.writeFile(dt_path, 'var linux_commands='+JSON.stringify(indexes) , 'utf8',function(err){
console.log(success("\n → ")+"生成数据成功!"+dt_path+" \n ");
path_dist = path.join(path_dist,'data.json')
fs.writeFile(path_dist, JSON.stringify(command_data) , 'utf8',function(err){
console.log(success("\n → ")+"生成数据成功!"+path_dist+" \n ");
callback&&callback(dt_path,indexes);
});
});
}
// 按长度排序
function sortLength(arr){
var compare = function (x, y) {//比较函数
x = path.basename(x,'.md');
y = path.basename(y,'.md');
if (x.length < y.length) {
return -1;
} else if (x.length > y.length) {
return 1;
} else {
return 0;
}
}
return arr.sort(compare)
}
// 同步循环创建所有目录 resolvePath
function mkdirsSync(dirpath, mode, callback) {
if(fs.existsSync(dirpath)){
callback&&callback(dirpath);
return true;
}else{
if(mkdirsSync(path.dirname(dirpath), mode)){
fs.mkdirSync(dirpath, mode, callback);
callback&&callback(dirpath);
return true;
}else{
callback&&callback(dirpath);
}
}
};
var fixture = path.join.bind(path, __dirname, 'template');
function cp(src, dest, cb) {
// yield support
if ('function' != typeof cb) return thunk;
var complete = false;
var read = fs.createReadStream(src);
var write = fs.createWriteStream(dest);
write.on('error', done);
write.on('close', done);
read.on('error', done);
read.pipe(write);
// done callback
function done(err) {
if (!complete) {
complete = true;
read.destroy();
write.destroy();
cb(err);
}
}
// thunk-ified
function thunk(done) {
cp(src, dest, done);
}
}
//返回 MD 所有路径的 Array
function readMDSync(filepath){
if(!exists(filepath)) return [];
var str = '',files = fs.readdirSync(filepath);
for (var i = 0; i < files.length; i++) {
var path_c = path.join(filepath,files[i]);
if( isDir(path_c) ) {
str += readMDSync(path_c) + ',';
}
else if(/\.(md)$/.test(files[i])) str += path_c + ',';
};
str = str.replace(/^\*|\,*$/g,'');
return str.split(',');
}
//写文件
function writeSync(filepath, content, callback) {
mkdirsSync(path.dirname(filepath));
return fs.writeFileSync(filepath, content, callback);
};
//写文件
function write(filepath, content) {
return fs.writeFile(filepath, content);
};
//判断是不是目录
function isDir(_path){return exists(_path) && fs.statSync(_path).isDirectory();}
//检查指定路径的文件或者目录是否存在
function exists(_path){return fs.existsSync(_path);}