node安装好http-server模块后,通过http-server .
命令浏览器默认展示效果如下:

个人觉得挺丑的,忍不了一点,我想改一改其CSS样式,优化下展示效果,但是找了半天网上竟然没有教程。。。。没办法,硬着头皮找了半天代码,终于找到了在哪里修改
第一步:找到http-server安装目录
我使用的nvm管理多个node版本,使用nvm root
命令可以看到nvm的安装目录,全局安装的node module都在对应的版本下的node文件夹中。

若是直接安装的node,可以使用命令npm root -g
查看全局package安装的位置。
第二步:修改css样式
打开node_modules\http-server\lib\core\show-dir
文件夹,修改styles.js
文件,复制如下内容覆盖styles.js
文件
'use strict';
const icons = require('./icons.json');
const IMG_SIZE = 16;
let css = `i.icon { display: block; height: ${IMG_SIZE}px; width: ${IMG_SIZE}px; }\n`;
css += 'table tr { white-space: nowrap; line-height: 30px;color:rgb(68, 68, 68);}\n';
css += 'td.perms {}\n';
css += 'td.file-size { text-align: right; padding-left: 1em; }\n';
css += 'td.display-name { padding-left: 1em; }\n';
css += '.displayName{text-decoration: none;cursor: pointer;}';
css += 'a{color:rgb(68, 68, 68);}';
css += 'a:hover{color:black;font-weight:bold;}';
Object.keys(icons).forEach((key) => {
css += `i.icon-${key} {\n`;
css += ` background-image: url("data:image/png;base64,${icons[key]}");\n`;
css += '}\n\n';
});
exports.icons = icons;
exports.css = css;
第三步:修改默认显示模板
打开node_modules\http-server\lib\core\show-dir
文件夹,修改index.js
文件,复制如下内容覆盖index.js
文件
'use strict';
const styles = require('./styles');
const lastModifiedToString = require('./last-modified-to-string');
const permsToString = require('./perms-to-string');
const sizeToString = require('./size-to-string');
const sortFiles = require('./sort-files');
const fs = require('fs');
const path = require('path');
const he = require('he');
const etag = require('../etag');
const url = require('url');
const status = require('../status-handlers');
const supportedIcons = styles.icons;
const css = styles.css;
module.exports = (opts) => {
// opts are parsed by opts.js, defaults already applied
const cache = opts.cache;
const root = path.resolve(opts.root);
const baseDir = opts.baseDir;
const humanReadable = opts.humanReadable;
const hidePermissions = opts.hidePermissions;
const handleError = opts.handleError;
const showDotfiles = opts.showDotfiles;
const si = opts.si;
const weakEtags = opts.weakEtags;
return function middleware(req, res, next) {
// Figure out the path for the file from the given url
const parsed = url.parse(req.url);
const pathname = decodeURIComponent(parsed.pathname);
const dir = path.normalize(
path.join(
root,
path.relative(
path.join('/', baseDir),
pathname
)
)
);
fs.stat(dir, (statErr, stat) => {
if (statErr) {
if (handleError) {
status[500](res, next, { error: statErr });
} else {
next();
}
return;
}
// files are the listing of dir
fs.readdir(dir, (readErr, _files) => {
let files = _files;
if (readErr) {
if (handleError) {
status[500](res, next, { error: readErr });
} else {
next();
}
return;
}
// Optionally exclude dotfiles from directory listing.
if (!showDotfiles) {
files = files.filter(filename => filename.slice(0, 1) !== '.');
}
res.setHeader('content-type', 'text/html');
res.setHeader('etag', etag(stat, weakEtags));
res.setHeader('last-modified', (new Date(stat.mtime)).toUTCString());
res.setHeader('cache-control', cache);
function render(dirs, renderFiles, lolwuts) {
// each entry in the array is a [name, stat] tuple
var dispayPathname = pathname;
if(dispayPathname.length>=3){
dispayPathname = pathname.substring(1,pathname.length-1)
}
let html = `${[
'<!doctype html>',
'<html>',
' <head>',
' <meta charset="utf-8">',
' <meta name="viewport" content="width=device-width">',
` <title>${he.encode(dispayPathname)}</title>`,
` <style type="text/css">${css}</style>`,
' </head>',
' <body>',
`<h1>${he.encode(dispayPathname)}</h1>`,
].join('\n')}\n`;
html += '<table>';
const failed = false;
const writeRow = (file) => {
// render a row given a [name, stat] tuple
const isDir = file[1].isDirectory && file[1].isDirectory();
let href = `./${encodeURIComponent(file[0])}`;
// append trailing slash and query for dir entry
if (isDir) {
href += `/${he.encode((parsed.search) ? parsed.search : '')}`;
}
const displayName = he.encode(file[0]) + ((isDir) ? '/' : '');
const ext = file[0].split('.').pop();
const classForNonDir = supportedIcons[ext] ? ext : '_page';
const iconClass = `icon-${isDir ? '_blank' : classForNonDir}`;
// TODO: use stylessheets?
html += `${'<tr class="customTr">' +
'<td><i class="icon '}${iconClass}"></i></td>`;
if (!hidePermissions) {
html += `<td class="perms"><code>(${permsToString(file[1])})</code></td>`;
}
html +=
`<td class="last-modified">${lastModifiedToString(file[1])}</td>` +
`<td class="file-size"><code>${sizeToString(file[1], humanReadable, si)}</code></td>`;
if(isDir){
html+=`<td class="display-name"><a class="displayName" href="${href}">${displayName}</a></td>`;
}else{
var displayName1 = displayName;
if(validationEnd(displayName,".html")){
displayName1= displayName.substring(0,displayName.length-5);
}
html+=`<td class="display-name"><a class="displayName" href="${href}" target="_blank">${displayName1}</a></td>`;
}
html +='</tr>\n';
};
dirs.sort((a, b) => a[0].toString().localeCompare(b[0].toString())).forEach(writeRow);
renderFiles.sort((a, b) => a.toString().localeCompare(b.toString())*-1).forEach(writeRow);
lolwuts.sort((a, b) => a[0].toString().localeCompare(b[0].toString())).forEach(writeRow);
if (!failed) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(html);
}
}
function validationEnd (str, appoint) {
str=str.toLowerCase(); //不区分大小写:全部转为小写后进行判断
var start = str.length-appoint.length; //相差长度=字符串长度-特定字符长度
var char= str.substr(start,appoint.length);//将相差长度作为开始下标,特定字符长度为截取长度
if(char== appoint){ //两者相同,则代表验证通过
return true;
}
return false;
}
sortFiles(dir, files, (lolwuts, dirs, sortedFiles) => {
// It's possible to get stat errors for all sorts of reasons here.
// Unfortunately, our two choices are to either bail completely,
// or just truck along as though everything's cool. In this case,
// I decided to just tack them on as "??!?" items along with dirs
// and files.
//
// Whatever.
// if it makes sense to, add a .. link
if (path.resolve(dir, '..').slice(0, root.length) === root) {
fs.stat(path.join(dir, '..'), (err, s) => {
if (err) {
if (handleError) {
status[500](res, next, { error: err });
} else {
next();
}
return;
}
dirs.unshift(['..', s]);
render(dirs, sortedFiles, lolwuts);
});
} else {
render(dirs, sortedFiles, lolwuts);
}
});
});
});
};
};
第四步:修改日期展示
打开node_modules\http-server\lib\core\show-dir
文件夹,修改last-modified-to-string.js
文件,复制如下内容覆盖last-modified-to-string.js
文件
'use strict';
Date.prototype.format = function(format)
{
var o = {
"M+" : this.getMonth()+1, //month
"d+" : this.getDate(), //day
"h+" : this.getHours(), //hour
"m+" : this.getMinutes(), //minute
"s+" : this.getSeconds(), //second
"q+" : Math.floor((this.getMonth()+3)/3), //quarter
"S" : this.getMilliseconds() //millisecond
}
if(/(y+)/.test(format)) format=format.replace(RegExp.$1,
(this.getFullYear()+"").substr(4 - RegExp.$1.length));
for(var k in o)if(new RegExp("("+ k +")").test(format))
format = format.replace(RegExp.$1,
RegExp.$1.length==1 ? o[k] :
("00"+ o[k]).substr((""+ o[k]).length));
return format;
}
module.exports = function lastModifiedToString(stat) {
const t = new Date(stat.mtime);
return t.format('yyyy-MM-dd hh:mm:ss');
};
最后:效果展示
首页:

点击进入子目录:

END.
注意:本文归作者所有,未经作者允许,不得转载