diff --git a/README.md b/README.md new file mode 100644 index 0000000..fe824d0 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# HTTP文件浏览 Version2 + +## 改进 +之前做的[HTTP浏览](http://moyuyc.github.io/2016/05/28/node-express-jade%E5%AE%9E%E7%8E%B0HTTP%E6%96%87%E4%BB%B6%E6%B5%8F%E8%A7%88%E5%99%A8/)是使用express2.x版本做的...,因为参考书比较旧了。 +1. `express2.x`中没有`express4.x`中的`res.sendFile()`方法,之前发送文件是使用的`stream.pipe()`方法,导致不支持继续下载,而且用户不能知道下载进度,在线音乐视频播放也不能选择时间跳跃欣赏。`res.sendFile()`方法可以将本地文件以静态资源发送给用户,所有问题迎刃而解。 +2. 旧版本不支持`java/c/cpp/js/css/html`等代码文件和`md/markdown`文件在线查看,所以进行改进。 +3. 利用`Bootstrap responsive utils`和`Bootstrap grid system`进行响应式布局。 +4. 监控`root.txt`文件,改变root后无需重启服务器。 +5. 去除对`q.js`依赖,使用原生`Promise` + +## 说明 +- `root.txt` :共享文件夹路径 +- `app.js` :入口 + +## 使用 +1. npm install +2. npm start +3. http://localhost:3500/ \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..bfce63e --- /dev/null +++ b/app.js @@ -0,0 +1,68 @@ +var express = require('express'); +var path = require('path'); +var favicon = require('serve-favicon'); +var logger = require('morgan'); +var cookieParser = require('cookie-parser'); +var bodyParser = require('body-parser'); + +var routes = require('./routes/index'); +var users = require('./routes/users'); + +var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'jade'); + +// uncomment after placing your favicon in /public +//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); +app.use(logger('dev')); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); +// app.use(express.static(path.join('/'))); +var fs = require('fs'); + +global.root = fs.readFileSync('./root.txt').toString().split(/\s+/)[0]; +fs.watchFile('./root.txt',function () { + global.root = fs.readFileSync('./root.txt').toString().split(/\s+/)[0]; +}); +app.use('/users', users); +app.use('/*', routes.index); + +app.listen(3500); + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); +}); + +// error handlers + +// development error handler +// will print stacktrace +if (app.get('env') === 'development') { + app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + }); +} + +// production error handler +// no stacktraces leaked to user +app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); +}); + + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100644 index 0000000..0bf9691 --- /dev/null +++ b/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('4.x:server'); +var http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/npm-debug.log b/npm-debug.log new file mode 100644 index 0000000..9da96c9 --- /dev/null +++ b/npm-debug.log @@ -0,0 +1,42 @@ +0 info it worked if it ends with ok +1 verbose cli [ '/usr/local/node-v4.4.7-linux-x64/bin/node', +1 verbose cli '/usr/local/node-v4.4.7-linux-x64/bin/npm', +1 verbose cli 'start' ] +2 info using npm@2.15.8 +3 info using node@v4.4.7 +4 verbose run-script [ 'prestart', 'start', 'poststart' ] +5 info prestart http-file-express4.x@0.0.0 +6 info start http-file-express4.x@0.0.0 +7 verbose unsafe-perm in lifecycle true +8 info http-file-express4.x@0.0.0 Failed to exec start script +9 verbose stack Error: http-file-express4.x@0.0.0 start: `node ./bin/www` +9 verbose stack Exit status 1 +9 verbose stack at EventEmitter. (/usr/local/node-v4.4.7-linux-x64/lib/node_modules/npm/lib/utils/lifecycle.js:217:16) +9 verbose stack at emitTwo (events.js:87:13) +9 verbose stack at EventEmitter.emit (events.js:172:7) +9 verbose stack at ChildProcess. (/usr/local/node-v4.4.7-linux-x64/lib/node_modules/npm/lib/utils/spawn.js:24:14) +9 verbose stack at emitTwo (events.js:87:13) +9 verbose stack at ChildProcess.emit (events.js:172:7) +9 verbose stack at maybeClose (internal/child_process.js:827:16) +9 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:211:5) +10 verbose pkgid http-file-express4.x@0.0.0 +11 verbose cwd /mnt/www/tarns_app/http_file +12 error Linux 2.6.32-642.3.1.el6.x86_64 +13 error argv "/usr/local/node-v4.4.7-linux-x64/bin/node" "/usr/local/node-v4.4.7-linux-x64/bin/npm" "start" +14 error node v4.4.7 +15 error npm v2.15.8 +16 error code ELIFECYCLE +17 error http-file-express4.x@0.0.0 start: `node ./bin/www` +17 error Exit status 1 +18 error Failed at the http-file-express4.x@0.0.0 start script 'node ./bin/www'. +18 error This is most likely a problem with the http-file-express4.x package, +18 error not with npm itself. +18 error Tell the author that this fails on your system: +18 error node ./bin/www +18 error You can get information on how to open an issue for this project with: +18 error npm bugs http-file-express4.x +18 error Or if that isn't available, you can get their info via: +18 error +18 error npm owner ls http-file-express4.x +18 error There is likely additional logging output above. +19 verbose exit [ 1, true ] diff --git a/package.json b/package.json new file mode 100644 index 0000000..160fd29 --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "http-file-express4.x", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "archiver": "^1.0.0", + "body-parser": "~1.13.2", + "cookie-parser": "~1.3.5", + "debug": "~2.2.0", + "express": "^4.13.4", + "highlight.js": "^9.4.0", + "jade": "~1.11.0", + "marked": "^0.3.5", + "morgan": "~1.6.1", + "serve-favicon": "~2.3.0" + }, + "description": "之前做的[HTTP浏览](http://moyuyc.github.io/2016/05/28/node-express-jade%E5%AE%9E%E7%8E%B0HTTP%E6%96%87%E4%BB%B6%E6%B5%8F%E8%A7%88%E5%99%A8/)是使用express2.x版本做的...,因为参考书比较旧了。\r 1. `express2.x`中没有`express4.x`中的`res.sendFile()`方法,之前发送文件是使用的`stream.pipe()`方法,导致不支持继续下载,而且用户不能知道下载进度,在线音乐视频播放也不能选择时间跳跃欣赏。`res.sendFile()`方法可以将本地文件以静态资源发送给用户,所有问题迎刃而解。\r 2. 旧版本不支持`java/c/cpp/js/css/html`等代码文件和`md/markdown`文件在线查看,所以进行改进。\r 3. 利用`Bootstrap responsive utils`和`Bootstrap grid system`进行响应式布局。\r 4. 监控`root.txt`文件,改变root后无需重启服务器。\r 5. 去除对`q.js`依赖,使用原生`Promise`", + "main": "app.js", + "devDependencies": {}, + "repository": { + "type": "git", + "url": "git+https://github.com/moyuyc/http-file-explorer-express4.x.git" + }, + "keywords": [ + "node", + "express", + "http-explorer" + ], + "author": "moyu", + "license": "ISC", + "bugs": { + "url": "https://github.com/moyuyc/http-file-explorer-express4.x/issues" + }, + "homepage": "https://github.com/moyuyc/http-file-explorer-express4.x#readme" +} diff --git a/public/javascripts/html.js b/public/javascripts/html.js new file mode 100644 index 0000000..c639581 --- /dev/null +++ b/public/javascripts/html.js @@ -0,0 +1,12 @@ +/** + * Created by Yc on 2016/6/9. + */ +!function () { + hljs.initHighlightingOnLoad(); + var i =document.getElementById('html-show'); + i.contentWindow.onload = function(){ + var h= 30+i.contentDocument.body.clientHeight; + if(i.clientHeight' + + text + ''; + }; +}(); diff --git a/public/stylesheets/bootstrap.min.css b/public/stylesheets/bootstrap.min.css new file mode 100644 index 0000000..fba8a59 --- /dev/null +++ b/public/stylesheets/bootstrap.min.css @@ -0,0 +1,14 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! + * Generated using the Bootstrap Customizer (http://v3.bootcss.com/customize/?id=3e67b81f792957f181e0ddcb74fbabde) + * Config saved to config.json and https://gist.github.com/3e67b81f792957f181e0ddcb74fbabde + *//*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role="button"]{cursor:pointer}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:0.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table !important}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (max-width:767px){.visible-xs-block{display:block !important}}@media (max-width:767px){.visible-xs-inline{display:inline !important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table !important}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline !important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table !important}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline !important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table !important}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (min-width:1200px){.visible-lg-block{display:block !important}}@media (min-width:1200px){.visible-lg-inline{display:inline !important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table !important}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}.visible-print-block{display:none !important}@media print{.visible-print-block{display:block !important}}.visible-print-inline{display:none !important}@media print{.visible-print-inline{display:inline !important}}.visible-print-inline-block{display:none !important}@media print{.visible-print-inline-block{display:inline-block !important}}@media print{.hidden-print{display:none !important}} \ No newline at end of file diff --git a/public/stylesheets/github-markdown.css b/public/stylesheets/github-markdown.css new file mode 100644 index 0000000..f36bef0 --- /dev/null +++ b/public/stylesheets/github-markdown.css @@ -0,0 +1,704 @@ +@font-face { + font-family: octicons-anchor; + src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAYcAA0AAAAACjQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAca8vGTk9TLzIAAAFMAAAARAAAAFZG1VHVY21hcAAAAZAAAAA+AAABQgAP9AdjdnQgAAAB0AAAAAQAAAAEACICiGdhc3AAAAHUAAAACAAAAAj//wADZ2x5ZgAAAdwAAADRAAABEKyikaNoZWFkAAACsAAAAC0AAAA2AtXoA2hoZWEAAALgAAAAHAAAACQHngNFaG10eAAAAvwAAAAQAAAAEAwAACJsb2NhAAADDAAAAAoAAAAKALIAVG1heHAAAAMYAAAAHwAAACABEAB2bmFtZQAAAzgAAALBAAAFu3I9x/Nwb3N0AAAF/AAAAB0AAAAvaoFvbwAAAAEAAAAAzBdyYwAAAADP2IQvAAAAAM/bz7t4nGNgZGFgnMDAysDB1Ml0hoGBoR9CM75mMGLkYGBgYmBlZsAKAtJcUxgcPsR8iGF2+O/AEMPsznAYKMwIkgMA5REMOXicY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+h5j//yEk/3KoSgZGNgYYk4GRCUgwMaACRoZhDwCs7QgGAAAAIgKIAAAAAf//AAJ4nHWMMQrCQBBF/0zWrCCIKUQsTDCL2EXMohYGSSmorScInsRGL2DOYJe0Ntp7BK+gJ1BxF1stZvjz/v8DRghQzEc4kIgKwiAppcA9LtzKLSkdNhKFY3HF4lK69ExKslx7Xa+vPRVS43G98vG1DnkDMIBUgFN0MDXflU8tbaZOUkXUH0+U27RoRpOIyCKjbMCVejwypzJJG4jIwb43rfl6wbwanocrJm9XFYfskuVC5K/TPyczNU7b84CXcbxks1Un6H6tLH9vf2LRnn8Ax7A5WQAAAHicY2BkYGAA4teL1+yI57f5ysDNwgAC529f0kOmWRiYVgEpDgYmEA8AUzEKsQAAAHicY2BkYGB2+O/AEMPCAAJAkpEBFbAAADgKAe0EAAAiAAAAAAQAAAAEAAAAAAAAKgAqACoAiAAAeJxjYGRgYGBhsGFgYgABEMkFhAwM/xn0QAIAD6YBhwB4nI1Ty07cMBS9QwKlQapQW3VXySvEqDCZGbGaHULiIQ1FKgjWMxknMfLEke2A+IJu+wntrt/QbVf9gG75jK577Lg8K1qQPCfnnnt8fX1NRC/pmjrk/zprC+8D7tBy9DHgBXoWfQ44Av8t4Bj4Z8CLtBL9CniJluPXASf0Lm4CXqFX8Q84dOLnMB17N4c7tBo1AS/Qi+hTwBH4rwHHwN8DXqQ30XXAS7QaLwSc0Gn8NuAVWou/gFmnjLrEaEh9GmDdDGgL3B4JsrRPDU2hTOiMSuJUIdKQQayiAth69r6akSSFqIJuA19TrzCIaY8sIoxyrNIrL//pw7A2iMygkX5vDj+G+kuoLdX4GlGK/8Lnlz6/h9MpmoO9rafrz7ILXEHHaAx95s9lsI7AHNMBWEZHULnfAXwG9/ZqdzLI08iuwRloXE8kfhXYAvE23+23DU3t626rbs8/8adv+9DWknsHp3E17oCf+Z48rvEQNZ78paYM38qfk3v/u3l3u3GXN2Dmvmvpf1Srwk3pB/VSsp512bA/GG5i2WJ7wu430yQ5K3nFGiOqgtmSB5pJVSizwaacmUZzZhXLlZTq8qGGFY2YcSkqbth6aW1tRmlaCFs2016m5qn36SbJrqosG4uMV4aP2PHBmB3tjtmgN2izkGQyLWprekbIntJFing32a5rKWCN/SdSoga45EJykyQ7asZvHQ8PTm6cslIpwyeyjbVltNikc2HTR7YKh9LBl9DADC0U/jLcBZDKrMhUBfQBvXRzLtFtjU9eNHKin0x5InTqb8lNpfKv1s1xHzTXRqgKzek/mb7nB8RZTCDhGEX3kK/8Q75AmUM/eLkfA+0Hi908Kx4eNsMgudg5GLdRD7a84npi+YxNr5i5KIbW5izXas7cHXIMAau1OueZhfj+cOcP3P8MNIWLyYOBuxL6DRylJ4cAAAB4nGNgYoAALjDJyIAOWMCiTIxMLDmZedkABtIBygAAAA==) format('woff'); +} + + + +.markdown-body { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + color: #333; + overflow: hidden; + font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif; + font-size: 16px; + line-height: 1.6; + word-wrap: break-word; +} + +.markdown-body a { + background: transparent; +} + +.markdown-body a:active, +.markdown-body a:hover { + outline: 0; +} + +.markdown-body strong { + font-weight: bold; +} + +.markdown-body h1 { + font-size: 2em; + margin: 0.67em 0; +} + +.markdown-body img { + border: 0; +} + +.markdown-body hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +.markdown-body pre { + overflow: auto; +} + +.markdown-body code, +.markdown-body kbd, +.markdown-body pre { + font-family: monospace, monospace; + font-size: 1em; +} + +.markdown-body input { + color: inherit; + font: inherit; + margin: 0; +} + +.markdown-body html input[disabled] { + cursor: default; +} + +.markdown-body input { + line-height: normal; +} + +.markdown-body input[type="checkbox"] { + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} + +.markdown-body table { + border-collapse: collapse; + border-spacing: 0; +} + +.markdown-body td, +.markdown-body th { + padding: 0; +} + +.markdown-body * { + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.markdown-body input { + font: 13px/1.4 Helvetica, arial, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"; +} + +.markdown-body a { + color: #4183c4; + text-decoration: none; +} + +.markdown-body a:hover, +.markdown-body a:focus, +.markdown-body a:active { + text-decoration: underline; +} + +.markdown-body hr { + height: 0; + margin: 15px 0; + overflow: hidden; + background: transparent; + border: 0; + border-bottom: 1px solid #ddd; +} + +.markdown-body hr:before { + display: table; + content: ""; +} + +.markdown-body hr:after { + display: table; + clear: both; + content: ""; +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + margin-top: 15px; + margin-bottom: 15px; + line-height: 1.1; +} + +.markdown-body h1 { + font-size: 30px; +} + +.markdown-body h2 { + font-size: 21px; +} + +.markdown-body h3 { + font-size: 16px; +} + +.markdown-body h4 { + font-size: 14px; +} + +.markdown-body h5 { + font-size: 12px; +} + +.markdown-body h6 { + font-size: 11px; +} + +.markdown-body blockquote { + margin: 0; +} + +.markdown-body ul, +.markdown-body ol { + padding: 0; + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body ol ol, +.markdown-body ul ol { + list-style-type: lower-roman; +} + +.markdown-body ul ul ol, +.markdown-body ul ol ol, +.markdown-body ol ul ol, +.markdown-body ol ol ol { + list-style-type: lower-alpha; +} + +.markdown-body dd { + margin-left: 0; +} + +.markdown-body code { + font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace; +} + +.markdown-body pre { + margin-top: 0; + margin-bottom: 0; + font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace; +} + +.markdown-body kbd { + background-color: #e7e7e7; + background-image: -webkit-linear-gradient(#fefefe, #e7e7e7); + background-image: linear-gradient(#fefefe, #e7e7e7); + background-repeat: repeat-x; + border-radius: 2px; + border: 1px solid #cfcfcf; + color: #000; + padding: 3px 5px; + line-height: 10px; + font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; + display: inline-block; +} + +.markdown-body>*:first-child { + margin-top: 0 !important; +} + +.markdown-body>*:last-child { + margin-bottom: 0 !important; +} + +.markdown-body .anchor { + position: absolute; + top: 0; + bottom: 0; + left: 0; + display: block; + padding-right: 6px; + padding-left: 30px; + margin-left: -30px; +} + +.markdown-body .anchor:focus { + outline: none; +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + position: relative; + margin-top: 1em; + margin-bottom: 16px; + font-weight: bold; + line-height: 1.4; +} + +.markdown-body h1 .octicon-link, +.markdown-body h2 .octicon-link, +.markdown-body h3 .octicon-link, +.markdown-body h4 .octicon-link, +.markdown-body h5 .octicon-link, +.markdown-body h6 .octicon-link { + display: none; + color: #000; + vertical-align: middle; +} + +.markdown-body h1:hover .anchor, +.markdown-body h2:hover .anchor, +.markdown-body h3:hover .anchor, +.markdown-body h4:hover .anchor, +.markdown-body h5:hover .anchor, +.markdown-body h6:hover .anchor { + height: 1em; + padding-left: 8px; + margin-left: -30px; + line-height: 1; + text-decoration: none; +} + +.markdown-body h1:hover .anchor .octicon-link, +.markdown-body h2:hover .anchor .octicon-link, +.markdown-body h3:hover .anchor .octicon-link, +.markdown-body h4:hover .anchor .octicon-link, +.markdown-body h5:hover .anchor .octicon-link, +.markdown-body h6:hover .anchor .octicon-link { + display: inline-block; +} + +.markdown-body h1 { + padding-bottom: 0.3em; + font-size: 2.25em; + line-height: 1.2; + border-bottom: 1px solid #eee; +} + +.markdown-body h2 { + padding-bottom: 0.3em; + font-size: 1.75em; + line-height: 1.225; + border-bottom: 1px solid #eee; +} + +.markdown-body h3 { + font-size: 1.5em; + line-height: 1.43; +} + +.markdown-body h4 { + font-size: 1.25em; +} + +.markdown-body h5 { + font-size: 1em; +} + +.markdown-body h6 { + font-size: 1em; + color: #777; +} + +.markdown-body p, +.markdown-body blockquote, +.markdown-body ul, +.markdown-body ol, +.markdown-body dl, +.markdown-body table, +.markdown-body pre { + margin-top: 0; + margin-bottom: 16px; +} + +.markdown-body hr { + height: 4px; + padding: 0; + margin: 16px 0; + background-color: #e7e7e7; + border: 0 none; +} + +.markdown-body ul, +.markdown-body ol { + padding-left: 2em; +} + +.markdown-body ul ul, +.markdown-body ul ol, +.markdown-body ol ol, +.markdown-body ol ul { + margin-top: 0; + margin-bottom: 0; +} + +.markdown-body li>p { + margin-top: 16px; +} + +.markdown-body dl { + padding: 0; +} + +.markdown-body dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: bold; +} + +.markdown-body dl dd { + padding: 0 16px; + margin-bottom: 16px; +} + +.markdown-body blockquote { + padding: 0 15px; + color: #777; + border-left: 4px solid #ddd; +} + +.markdown-body blockquote>:first-child { + margin-top: 0; +} + +.markdown-body blockquote>:last-child { + margin-bottom: 0; +} + +.markdown-body table { + display: block; + width: 100%; + overflow: auto; + word-break: normal; + word-break: keep-all; +} + +.markdown-body table th { + font-weight: bold; +} + +.markdown-body table th, +.markdown-body table td { + padding: 6px 13px; + border: 1px solid #ddd; +} + +.markdown-body table tr { + background-color: #fff; + border-top: 1px solid #ccc; +} + +.markdown-body table tr:nth-child(2n) { + background-color: #f8f8f8; +} + +.markdown-body img { + max-width: 100%; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +.markdown-body code { + padding: 0; + padding-top: 0.2em; + padding-bottom: 0.2em; + margin: 0; + font-size: 85%; + background-color: rgba(0,0,0,0.04); + border-radius: 3px; +} + +.markdown-body code:before, +.markdown-body code:after { + letter-spacing: -0.2em; + content: "\00a0"; +} + +.markdown-body pre>code { + padding: 0; + margin: 0; + font-size: 100%; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} + +.markdown-body .highlight { + margin-bottom: 16px; +} + +.markdown-body .highlight pre, +.markdown-body pre { + padding: 16px; + overflow: auto; + font-size: 85%; + line-height: 1.45; + background-color: #f7f7f7; + border-radius: 3px; +} + +.markdown-body .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.markdown-body pre { + word-wrap: normal; +} + +.markdown-body pre code { + display: inline; + max-width: initial; + padding: 0; + margin: 0; + overflow: initial; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; +} + +.markdown-body pre code:before, +.markdown-body pre code:after { + content: normal; +} + +.markdown-body .highlight { + background: #fff; +} + +.markdown-body .highlight .mf, +.markdown-body .highlight .mh, +.markdown-body .highlight .mi, +.markdown-body .highlight .mo, +.markdown-body .highlight .il, +.markdown-body .highlight .m { + color: #945277; +} + +.markdown-body .highlight .s, +.markdown-body .highlight .sb, +.markdown-body .highlight .sc, +.markdown-body .highlight .sd, +.markdown-body .highlight .s2, +.markdown-body .highlight .se, +.markdown-body .highlight .sh, +.markdown-body .highlight .si, +.markdown-body .highlight .sx, +.markdown-body .highlight .s1 { + color: #df5000; +} + +.markdown-body .highlight .kc, +.markdown-body .highlight .kd, +.markdown-body .highlight .kn, +.markdown-body .highlight .kp, +.markdown-body .highlight .kr, +.markdown-body .highlight .kt, +.markdown-body .highlight .k, +.markdown-body .highlight .o { + font-weight: bold; +} + +.markdown-body .highlight .kt { + color: #458; +} + +.markdown-body .highlight .c, +.markdown-body .highlight .cm, +.markdown-body .highlight .c1 { + color: #998; + font-style: italic; +} + +.markdown-body .highlight .cp, +.markdown-body .highlight .cs { + color: #999; + font-weight: bold; +} + +.markdown-body .highlight .cs { + font-style: italic; +} + +.markdown-body .highlight .n { + color: #333; +} + +.markdown-body .highlight .na, +.markdown-body .highlight .nv, +.markdown-body .highlight .vc, +.markdown-body .highlight .vg, +.markdown-body .highlight .vi { + color: #008080; +} + +.markdown-body .highlight .nb { + color: #0086B3; +} + +.markdown-body .highlight .nc { + color: #458; + font-weight: bold; +} + +.markdown-body .highlight .no { + color: #094e99; +} + +.markdown-body .highlight .ni { + color: #800080; +} + +.markdown-body .highlight .ne { + color: #990000; + font-weight: bold; +} + +.markdown-body .highlight .nf { + color: #945277; + font-weight: bold; +} + +.markdown-body .highlight .nn { + color: #555; +} + +.markdown-body .highlight .nt { + color: #000080; +} + +.markdown-body .highlight .err { + color: #a61717; + background-color: #e3d2d2; +} + +.markdown-body .highlight .gd { + color: #000; + background-color: #fdd; +} + +.markdown-body .highlight .gd .x { + color: #000; + background-color: #faa; +} + +.markdown-body .highlight .ge { + font-style: italic; +} + +.markdown-body .highlight .gr { + color: #aa0000; +} + +.markdown-body .highlight .gh { + color: #999; +} + +.markdown-body .highlight .gi { + color: #000; + background-color: #dfd; +} + +.markdown-body .highlight .gi .x { + color: #000; + background-color: #afa; +} + +.markdown-body .highlight .go { + color: #888; +} + +.markdown-body .highlight .gp { + color: #555; +} + +.markdown-body .highlight .gs { + font-weight: bold; +} + +.markdown-body .highlight .gu { + color: #800080; + font-weight: bold; +} + +.markdown-body .highlight .gt { + color: #aa0000; +} + +.markdown-body .highlight .ow { + font-weight: bold; +} + +.markdown-body .highlight .w { + color: #bbb; +} + +.markdown-body .highlight .sr { + color: #017936; +} + +.markdown-body .highlight .ss { + color: #8b467f; +} + +.markdown-body .highlight .bp { + color: #999; +} + +.markdown-body .highlight .gc { + color: #999; + background-color: #EAF2F5; +} + +.markdown-body .octicon { + font: normal normal 16px octicons-anchor; + line-height: 1; + display: inline-block; + text-decoration: none; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.markdown-body .octicon-link:before { + content: '\f05c'; +} + +.markdown-body .task-list-item { + list-style-type: none; +} + +.markdown-body .task-list-item+.task-list-item { + margin-top: 3px; +} + +.markdown-body .task-list-item input { + float: left; + margin: 0.3em 0 0.25em -1.6em; + vertical-align: middle; +} + +@media (min-width: 43.75em) { + body { + padding: 30px; + } +} diff --git a/public/stylesheets/hljs-github.min.css b/public/stylesheets/hljs-github.min.css new file mode 100644 index 0000000..9b4f3aa --- /dev/null +++ b/public/stylesheets/hljs-github.min.css @@ -0,0 +1,124 @@ +/* + +github.com style (c) Vasily Polovnyov + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #333; + background: #f8f8f8; + -webkit-text-size-adjust: none; +} + +.hljs-comment, +.diff .hljs-header, +.hljs-javadoc { + color: #998; + font-style: italic; +} + +.hljs-keyword, +.css .rule .hljs-keyword, +.hljs-winutils, +.nginx .hljs-title, +.hljs-subst, +.hljs-request, +.hljs-status { + color: #333; + font-weight: bold; +} + +.hljs-number, +.hljs-hexcolor, +.ruby .hljs-constant { + color: #008080; +} + +.hljs-string, +.hljs-tag .hljs-value, +.hljs-phpdoc, +.hljs-dartdoc, +.tex .hljs-formula { + color: #d14; +} + +.hljs-title, +.hljs-id, +.scss .hljs-preprocessor { + color: #900; + font-weight: bold; +} + +.hljs-list .hljs-keyword, +.hljs-subst { + font-weight: normal; +} + +.hljs-class .hljs-title, +.hljs-type, +.vhdl .hljs-literal, +.tex .hljs-command { + color: #458; + font-weight: bold; +} + +.hljs-tag, +.hljs-tag .hljs-title, +.hljs-rules .hljs-property, +.django .hljs-tag .hljs-keyword { + color: #000080; + font-weight: normal; +} + +.hljs-attribute, +.hljs-variable, +.lisp .hljs-body { + color: #008080; +} + +.hljs-regexp { + color: #009926; +} + +.hljs-symbol, +.ruby .hljs-symbol .hljs-string, +.lisp .hljs-keyword, +.clojure .hljs-keyword, +.scheme .hljs-keyword, +.tex .hljs-special, +.hljs-prompt { + color: #990073; +} + +.hljs-built_in { + color: #0086b3; +} + +.hljs-preprocessor, +.hljs-pragma, +.hljs-pi, +.hljs-doctype, +.hljs-shebang, +.hljs-cdata { + color: #999; + font-weight: bold; +} + +.hljs-deletion { + background: #fdd; +} + +.hljs-addition { + background: #dfd; +} + +.diff .hljs-change { + background: #0086b3; +} + +.hljs-chunk { + color: #aaa; +} diff --git a/public/stylesheets/pilcrow.css b/public/stylesheets/pilcrow.css new file mode 100644 index 0000000..b29d663 --- /dev/null +++ b/public/stylesheets/pilcrow.css @@ -0,0 +1,47 @@ +/* needed because the container has overflow: hidden, but the pilcrows overflow */ +.markdown-body { + padding-left: 30px; +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + position: relative; +} + +.markdown-body h1:hover .header-link:before, +.markdown-body h2:hover .header-link:before, +.markdown-body h3:hover .header-link:before, +.markdown-body h4:hover .header-link:before, +.markdown-body h5:hover .header-link:before, +.markdown-body h6:hover .header-link:before { + content: "#";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.markdown-body .header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + /*left: -0.7em;*/ + display: block; + padding-right: 1em; +} + +.markdown-body h1:hover .header-link, +.markdown-body h2:hover .header-link, +.markdown-body h3:hover .header-link, +.markdown-body h4:hover .header-link, +.markdown-body h5:hover .header-link, +.markdown-body h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 0000000..cdc18f3 --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,28 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + margin-right:10px; + color: #00B7FF; +} +.text-center{ + text-align: center; +} +.text-info{ + color: #00B7FF; +} +.text-right{ + text-align: right; +} +footer{ + margin-top:80px; +} +.text-primary{ + color: crimson; +} +iframe[id=html-show] { + border:1px solid #bbbbbb; + padding:10px;width:100%;height:400px; +} \ No newline at end of file diff --git a/root.txt b/root.txt new file mode 100644 index 0000000..9cd45a7 --- /dev/null +++ b/root.txt @@ -0,0 +1 @@ +/mnt/file \ No newline at end of file diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..7a7cf5a --- /dev/null +++ b/routes/index.js @@ -0,0 +1,217 @@ + +/* + * GET home page. + */ +var fs = require('fs'); +var url = require('url'); +var archiver = require('archiver'); +var marked = require('marked'); +var hl = require('highlight.js'); + +function loadZip(file,rela,req,res) { + var state = fs.statSync(file); + var filename = rela.substring(rela.lastIndexOf('/')+1); + console.log('zip',filename) + var archive = archiver('zip'); + archive.on('error', function(err){throw err;}); + archive.pipe(res); + if(state.isDirectory()) archive.directory(file,filename); + else archive.file(file,{name:filename}); + archive.finalize(); +} + +var statPr = function (root,file) { + var deferred = Q.defer(); + fs.stat(root+'/'+file,function (err, stats) { + if(err) deferred.reject(err); + else { + stats.name = file; + stats.type = stats.isDirectory()?'文件夹':'文件'; + deferred.resolve(stats, root); + } + }); + return deferred.promise; +}; +var statP = function(root,file){ + return new Promise(function(resolve){ + fs.stat(root+'/'+file,function (err, stats) { + var t = {}; + if(err){ + t.reason=err; + resolve(t); + } + else { + t.state='ok'; + stats.name = file; + stats.type = stats.isDirectory()?'文件夹':'文件'; + t.value=stats; + resolve(t); + } + }); + }) +} + + +function loadDir(r,rela,req,res) { + fs.readdir(r,function (err,files) { + if(err) throw err; + if(r!==root){ + var d = r.substring(0,r.lastIndexOf('/')); + Promise.resolve(d).then(v=>{ + fs.readdir(v,function (err, files) { + if(err) throw err; + fn(files,r.substring(r.lastIndexOf('/')+1)); + }) + }) + }else { + fn(); + } + function fn(list,f) { + var o ={}; + if(list){ + var i = list.indexOf(f); + if(i>=0) { + o.prev = list[i - 1]; + o.next = list[i + 1]; + } + } + Promise.all(files.map((x,i,a)=>{return statP(r,x);})) + .then(function (results) { + var values=[]; + results.forEach(x=>{ + if(x.state==='ok'){ + values.push(x.value); + }else + console.error(x.reason); + }); + res.render('file',Object.extend(o, + { + title:'HTTP文件查看', + dirname:rela, + files : values.map(x=> { + return { + type: x.type, + name: x.name, + time: x.mtime.format(), + size: x.size.toSize() + }; + }) + }) + ); + },console.error) + } + }); +} +Number.prototype.toSize = function () { + if(this<1024){ + return this+"B"; + }else if(this<1024<<10){ + return (this/1024).toFixed(2)+"KB"; + }else if(this<1024<<20){ + return (this/(1024<<10)).toFixed(2)+"MB"; + }else{ + return (this/(1024<<20)).toFixed(2)+"GB"; + } +} +Object.extend = function (src) { + Array.prototype.slice.call(arguments,1) + .forEach(x=>{ + for(var k in x) + src[k]=x[k]; + }) + return src; +} +function loadFile(file,rela,noraw,res){ + if(!!noraw){ + if(file!==root){ + var d = file.substring(0,file.lastIndexOf('/')); + Promise.resolve(d).then(v=>{ + fs.readdir(v,(err,files)=>{ + fn(files,file.substring(file.lastIndexOf('/')+1)); + }) + }); + }else fn(); + function fn(list,f) { + var o ={}; + if(list){ + var i = list.indexOf(f); + if(i>=0) { + o.prev = list[i - 1]; + o.next = list[i + 1]; + } + } + o = Object.extend(o,{ + dirname:rela, + title:f, + src:f + }); + + if(f.match(/\.(avi|mp4|mkv|rmvb|mpg|rm|wma)$/i)){ + res.render('video',o); + }else if(f.match(/\.(jpg|png|bmp|jpeg|gif)$/i)){ + res.render('img',o); + }else if(f.match(/\.(mp3|wma|aac)$/i)){ + res.render('audio',o); + }else if(f.match(/\.(md|markdown)$/i)){ + fs.readFile(file,(error,data) => { + if(error) throw error; + o.content = data.toString(); + res.render('md',o); + }); + }else if(f.match(/\.(java|c|cpp|js|css|jsp|php|json|txt)$/i)){ + fs.readFile(file,(error,data) => { + if(error) throw error; + o.content = data.toString(); + res.render('code',o); + }); + }else if(f.match(/\.(html|htm)$/i)){ + fs.readFile(file,(error,data) => { + if(error) throw error; + o.content = data.toString(); + res.render('html',o); + }); + }else{ + res.sendFile(rela,{root:global.root}); + } + } + }else{ + res.sendFile(rela,{root:global.root}); + } +} + +exports.index = function(req, res){ + var arg = url.parse(req.originalUrl,true), + query = arg.query; + var root = global.root; + var r = decodeURIComponent(arg.pathname); + r=r==='/'?'':r; + + var t = r.replace(/(\/$)/g,''); + console.info(r,t,query); + if(!query.compress){ + var state = fs.statSync(root+r); + if(state.isDirectory()) + loadDir(root+t,t, req, res); + else + loadFile(root+t,t,query.noraw,res); + }else{ + loadZip(root+t,t,req,res); + } +}; + +Date.prototype.format = function (fmt) { //author: meizz + fmt = fmt || 'yyyy/MM/dd hh:mm'; + var o = { + "M+": this.getMonth() + 1, //月份 + "d+": this.getDate(), //日 + "h+": this.getHours(), //小时 + "m+": this.getMinutes(), //分 + "s+": this.getSeconds(), //秒 + "q+": Math.floor((this.getMonth() + 3) / 3), //季度 + "S": this.getMilliseconds() //毫秒 + }; + if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); + for (var k in o) + if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); + return fmt; +} \ No newline at end of file diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..623e430 --- /dev/null +++ b/routes/users.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +router.get('/', function(req, res, next) { + res.send('respond with a resource'); +}); + +module.exports = router; diff --git a/views/audio.jade b/views/audio.jade new file mode 100644 index 0000000..c1a7597 --- /dev/null +++ b/views/audio.jade @@ -0,0 +1,15 @@ +// + Created by Yc on 2016/5/28. +extends layout + +block content + div.container-fluid + h1=title + p.text-primary 若不能播放,则不支持该格式在线播放,请 + a(href=src,style="margin:0px") 下载 + 欣赏。 + include btns + audio(src=src controls="controls" autoplay="autoplay") 您的浏览器不支持 audio 标签。 + + footer + p.text-center.text-info Running on node with Express, Jade. By Moyu. \ No newline at end of file diff --git a/views/btns.jade b/views/btns.jade new file mode 100644 index 0000000..4222bbf --- /dev/null +++ b/views/btns.jade @@ -0,0 +1,11 @@ +// + Created by Yc on 2016/5/29. + +-var d = dirname.substring(0,dirname.lastIndexOf('/')) +p + -if(dirname!=='') + a(href=(d===''?'/':d)) 上一层 + -if(prev) + a(href=d+'/'+prev+'?noraw=true' style="margin-left:20px;")<< #{prev} + -if(next) + a(href=d+'/'+next+'?noraw=true',style="margin-left:20px;")=next+" >>" diff --git a/views/code.jade b/views/code.jade new file mode 100644 index 0000000..fa14de0 --- /dev/null +++ b/views/code.jade @@ -0,0 +1,15 @@ +// + Created by Yc on 2016/6/9. +extends layout + +block content + script(src="http://cdn.bootcss.com/highlight.js/8.0/highlight.min.js") + div.container-fluid + h1=title + include btns + div.markdown-body + pre + code!=content + script hljs.initHighlightingOnLoad(); + footer + p.text-center.text-info Running on node with Express, Jade. By Moyu. diff --git a/views/error.jade b/views/error.jade new file mode 100644 index 0000000..51ec12c --- /dev/null +++ b/views/error.jade @@ -0,0 +1,6 @@ +extends layout + +block content + h1= message + h2= error.status + pre #{error.stack} diff --git a/views/file.jade b/views/file.jade new file mode 100644 index 0000000..09ed5f9 --- /dev/null +++ b/views/file.jade @@ -0,0 +1,33 @@ +// + Created by Yc on 2016/5/27. +extends layout + +block content + -dirname=dirname.replace(/\/*$/,''); + div.container-fluid + h1=dirname===''?'/':dirname + include btns + div.table-responsive + table.table.table-striped + thead + tr + td 类型 + td 文件名 + td 操作 + td 修改时间 + td 大小 + tbody + each obj in files + tr + td= obj.type + td + a(href=dirname+'/'+obj.name+'?noraw=true')= obj.name + td + -if(obj.type!=='文件') + a(href=dirname+'/'+obj.name+'/?compress=true',download=obj.name+'.zip') 打包下载 + -if(obj.type==='文件') + a(href=dirname+'/'+obj.name,download=obj.name) 下载 + td= obj.time + td= obj.size + footer + p.text-center.text-info Running on node with Express, Jade. By Moyu. \ No newline at end of file diff --git a/views/html.jade b/views/html.jade new file mode 100644 index 0000000..9b35739 --- /dev/null +++ b/views/html.jade @@ -0,0 +1,23 @@ +// + Created by Yc on 2016/6/9. +extends layout + +block content + script(src="http://cdn.bootcss.com/highlight.js/8.0/highlight.min.js") + div.container-fluid + h1=title + include btns + div.row + div.col-lg-6.visible-lg + h2 解析前 + div.markdown-body + pre + code(id='html-raw')=content + div.col-lg-6 + h2.clearfix 解析后 + small + a.pull-right(href=src,target='_blank')点击预览 + iframe(id='html-show',src=src) + script(src='/javascripts/html.js') + footer + p.text-center.text-info Running on node with Express, Jade. By Moyu. \ No newline at end of file diff --git a/views/img.jade b/views/img.jade new file mode 100644 index 0000000..2be7956 --- /dev/null +++ b/views/img.jade @@ -0,0 +1,12 @@ +// + Created by Yc on 2016/5/28. +extends layout + +block content + div.container-fluid + h1=title + include btns + div + img.img-responsive(src=src) + footer + p.text-center.text-info Running on node with Express, Jade. By Moyu. \ No newline at end of file diff --git a/views/index.jade b/views/index.jade new file mode 100644 index 0000000..3d63b9a --- /dev/null +++ b/views/index.jade @@ -0,0 +1,5 @@ +extends layout + +block content + h1= title + p Welcome to #{title} diff --git a/views/layout.jade b/views/layout.jade new file mode 100644 index 0000000..8cbe529 --- /dev/null +++ b/views/layout.jade @@ -0,0 +1,14 @@ +doctype +html(lang="zh") + head + title= title + meta(name="renderer",content="webkit") + meta(http-equiv="X-UA-Compatible",content="IE=edge") + meta(name="viewport" content="width=device-width, initial-scale=1") + link(rel='stylesheet', href='/stylesheets/bootstrap.min.css') + link(rel='stylesheet', href='/stylesheets/style.css') + link(rel='stylesheet', href='/stylesheets/hljs-github.min.css') + link(rel='stylesheet', href='/stylesheets/pilcrow.css') + link(rel='stylesheet', href='/stylesheets/github-markdown.css') + body + block content \ No newline at end of file diff --git a/views/md.jade b/views/md.jade new file mode 100644 index 0000000..f4699ca --- /dev/null +++ b/views/md.jade @@ -0,0 +1,24 @@ +// + Created by Yc on 2016/6/9. +extends layout + +block content + script(src="http://cdn.bootcss.com/marked/0.3.5/marked.min.js") + script(src="http://cdn.bootcss.com/highlight.js/8.0/highlight.min.js") + div.container-fluid + h1=title + include btns + div.row + div.col-lg-6.visible-lg + h2 解析前 + div.markdown-body + pre + code(id='markdown-raw')=content + div.col-lg-6 + h2 解析后 + div.markdown-body(id='markdown-show') + script(src="/javascripts/md.js") + script document.getElementById('markdown-show').innerHTML = marked(document.getElementById('markdown-raw').innerText,{renderer:renderer}); + + footer + p.text-center.text-info Running on node with Express, Jade. By Moyu. \ No newline at end of file diff --git a/views/text.jade b/views/text.jade new file mode 100644 index 0000000..a8fb899 --- /dev/null +++ b/views/text.jade @@ -0,0 +1,6 @@ +// + Created by Yc on 2016/6/6. +extends layout + +block content + pre diff --git a/views/video.jade b/views/video.jade new file mode 100644 index 0000000..331d7b9 --- /dev/null +++ b/views/video.jade @@ -0,0 +1,14 @@ +// + Created by Yc on 2016/5/28. +extends layout + +block content + div.container-fluid + h1=title + p.text-primary 若不能播放,则不支持该格式在线播放,请 + a(href=src,style="margin:0px") 下载 + 欣赏。 + include btns + video(src=src controls="controls" width='70%') 您的浏览器不支持 video 标签。 + footer + p.text-center.text-info Running on node with Express, Jade. By Moyu. \ No newline at end of file