commit a874a96592535ba0110af897ccca65112e13e1ef Author: Kiritow <1362050620@qq.com> Date: Sat Jan 19 22:23:25 2019 +0800 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0245614 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +bin/*.exe +site/ +blog/ +config/*.json \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..aace81b --- /dev/null +++ b/app.js @@ -0,0 +1,178 @@ +const http=require('http') +const spawn=require('child_process').spawn +const promisify=require('util').promisify +const path=require('path') +const url=require('url') +const fs=require('fs') +const mime=require('mime') + +let _configObj=JSON.parse(fs.readFileSync("config/config.json")) +const SOURCE_DIR=_configObj.source +const ROOT_DIR=_configObj.dist +const LISTEN_PORT=_configObj.port + +async function RemoveSingleFile(filename) { + try { + let stats=await promisify(fs.stat)(filename) + if(stats.isFile()) { + console.log(`Deleting: ${filename}`) + await promisify(fs.unlink)(filename) + } else { + await RemoveDirStep(filename) + await promisify(fs.rmdir)(filename) + } + } catch (e) { + console.log(`[Error] RemoveSingleFile: ${e.toString()}`) + } +} + +async function RemoveDirStep(dir) { + try { + let files=await promisify(fs.readdir)(dir) + if(files && files.length>0) { + let pArr=new Array + files.forEach((val)=>{ + pArr.push(RemoveSingleFile(path.join(dir,val))) + }) + return Promise.all(pArr) + } + } catch (e) { + console.log(`[Error] RemoveDirStep: ${e.toString()}`) + } +} + +async function ClearSite() { + console.log("Clearing site...") + await RemoveDirStep(ROOT_DIR) + console.log("[Done] Site cleaned.") +} + +async function GenerateSingle(val) { + try { + let stat=await promisify(fs.stat)(path.join(SOURCE_DIR,val)) + if(stat && stat.isFile()) { + if(path.extname(val).toLowerCase()==".md") { + return new Promise((resolve,reject)=>{ + console.log(`Generating: ${val}`) + let child=spawn('bin/pandoc',['-f','markdown','-t','html',path.join(SOURCE_DIR,val),'-o',path.join(ROOT_DIR,path.dirname(val),path.basename(val,path.extname(val)) + '.html')]) + child.on('close',()=>{ + resolve() + }) + }) + } else { + console.log(`Copying: ${val}`) + await promisify(fs.copy)(path.join(SOURCE_DIR,val),path.join(ROOT_DIR,val)) + } + } else if(stat && stat.isDirectory()) { + await promisify(fs.mkdir)(path.join(ROOT_DIR,val)) + await GenerateStep(val) + } + } catch (e) { + console.log(`[Error] GenerateSingle: ${e.toString()}`) + } +} + +async function GenerateStep(dir) { + try { + let files=await promisify(fs.readdir)(path.join(SOURCE_DIR,dir)) + if(files && files.length>0) { + let pArr=new Array + files.forEach((val)=>{ + pArr.push(GenerateSingle(path.join(dir,val))) + }) + await Promise.all(pArr) + } + } catch (e) { + console.log(`[Error] GenerateStep: ${e.toString()}`) + } +} + +async function BuildSite() { + console.log("Building site...") + try { + await GenerateStep("") + } catch (e) { + console.log(`[Error] BuildSite: ${e.toString()}`) + } + console.log("[Done] Site building done.") +} + +async function RebuildSite() { + await ClearSite() + await BuildSite() +} + +async function request_handler(req,res) { + let obj=url.parse(req.url,true) + if(req.method=="GET") { + let normPath=path.normalize(obj.pathname) + let localPath=path.join(ROOT_DIR,normPath) + try { + let stats=await promisify(fs.stat)(localPath) + if(stats && stats.isFile()) { + let mimeType=mime.getType(localPath) + if(mimeType=="text/html") { + res.setHeader('Content-Type',mimeType + ";charset=utf-8") + } else { + res.setHeader('Content-Type',mimeType) + } + fs.createReadStream(localPath).pipe(res) + } else { + let files=await promisify(fs.readdir)(localPath) + res.writeHead(200,"OK") + res.write(` + + + + Index of ${normPath} + + +

Index of ${normPath}

+ +`) + let pArr=new Array + files.forEach((val)=>{ + pArr.push(new Promise((resolve,reject)=>{ + fs.stat(path.join(localPath,val),(err,stats)=>{ + if(err) return reject(err) + else if(!stats) return reject("no stats returned.") + else { + return resolve({ + name:val, + isfile:stats.isFile() + }) + } + }) + })) + }) + for(let i=0;i${path.basename(j.name,path.extname(j.name))}`) + } else { + res.write(`
  • Directory ${path.basename(j.name,path.extname(j.name))}
  • `) + } + } + res.write(` +
    + + +`) + res.end() + } + } catch (e) { + res.writeHead(500,"Server error") + res.end(`Error: ${e.toString()}`) + } + } +} + +async function main() { + await RebuildSite() + http.createServer(request_handler).listen(LISTEN_PORT) +} + +let _tmBefore=new Date() +main().then(()=>{ + console.log(`Server started in ${(new Date()-_tmBefore)/1000}s.`) +}) \ No newline at end of file diff --git a/bin/readme.md b/bin/readme.md new file mode 100644 index 0000000..265d77e --- /dev/null +++ b/bin/readme.md @@ -0,0 +1,3 @@ +# Binary files + +Place `pandoc` executable binary file in this directory. \ No newline at end of file diff --git a/config/config.json.example b/config/config.json.example new file mode 100644 index 0000000..2ea610e --- /dev/null +++ b/config/config.json.example @@ -0,0 +1,5 @@ +{ + "source":"blog", + "dist":"site", + "port":12345 +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..6be8a1f --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "kblog", + "version": "1.0.0", + "description": "Kiritow's Blog Backend", + "main": "app.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "http://kiritow.com:3000/Kiritow/kblog" + }, + "keywords": [ + "blog" + ], + "author": "Kiritow", + "license": "MIT", + "dependencies": { + "mime": "^2.4.0" + } +}