Skip to content

Commit

Permalink
Fixes expressjs#8 - Separate javascript and css from directory.html t…
Browse files Browse the repository at this point in the history
…o be compliant with content security policy
  • Loading branch information
jantimon committed May 28, 2014
1 parent 6e3f352 commit ae2db16
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 69 deletions.
55 changes: 53 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,28 @@ var defaultTemplate = join(__dirname, 'public', 'directory.html');

var defaultStylesheet = join(__dirname, 'public', 'style.css');

/*!
* Stylesheet.
*/

var defaultScript = join(__dirname, 'public', 'script.js');

/**
* Media types and the map for content negotiation.
*/

var mediaTypes = [
'text/css',
'text/html',
'text/javascript',
'text/plain',
'application/json'
];

var mediaType = {
'text/css': 'css',
'text/html': 'html',
'text/javascript': 'javascript',
'text/plain': 'plain',
'application/json': 'json'
};
Expand All @@ -81,7 +91,8 @@ exports = module.exports = function directory(root, options){
, filter = options.filter
, root = normalize(root + sep)
, template = options.template || defaultTemplate
, stylesheet = options.stylesheet || defaultStylesheet;
, stylesheet = options.stylesheet || defaultStylesheet
, script = options.script || defaultScript;

return function directory(req, res, next) {
if ('GET' != req.method && 'HEAD' != req.method) return next();
Expand Down Expand Up @@ -117,9 +128,14 @@ exports = module.exports = function directory(root, options){
// content-negotiation
var type = new Negotiator(req).preferredMediaType(mediaTypes);

// take custom types from the url
// e.g /?text/css
var mediaTypeFromUrl = req.url.replace(/^.+\?/, '');
if (mediaTypes.indexOf(mediaTypeFromUrl) !== -1) type = mediaTypeFromUrl;

// not acceptable
if (!type) return next(createError(406));
exports[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template, stylesheet);
exports[mediaType[type]](req, res, files, next, originalDir, showUp, icons, path, view, template, stylesheet, script);
});
});
};
Expand Down Expand Up @@ -152,6 +168,41 @@ exports.html = function(req, res, files, next, dir, showUp, icons, path, view, t
});
};

/**
* Respond with text/css.
*/

exports.css = function (req, res, files, next, dir, showUp, icons, path, view, template, stylesheet){
fs.readFile(stylesheet, 'utf8', function (err, style) {
if (err) return next(err);
stat(path, files, function (err, stats){
if (err) return next(err);
files = files.map(function (file, i){
return { name: file, stat: stats[i] };
});
files.sort(fileSort);
if (showUp) files.unshift({ name: '..' });
var str = style.concat(iconStyle(files, icons));
res.setHeader('Content-Type', 'text/css');
res.setHeader('Content-Length', str.length);
res.end(str);
});
});
};

/**
* Respond with text/javascript.
*/

exports.javascript = function (req, res, files, next, dir, showUp, icons, path, view, template, stylesheet, script){
fs.readFile(script, 'utf8', function (err, script){
if (err) return next(err);
res.setHeader('Content-Type', 'text/javascript');
res.setHeader('Content-Length', script.length);
res.end(script);
});
};

/**
* Respond with application/json.
*/
Expand Down
69 changes: 2 additions & 67 deletions public/directory.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,8 @@
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>listing directory {directory}</title>
<style>{style}</style>
<script>
function $(id){
var el = 'string' == typeof id
? document.getElementById(id)
: id;

el.on = function(event, fn){
if ('content loaded' == event) {
event = window.attachEvent ? "load" : "DOMContentLoaded";
}
el.addEventListener
? el.addEventListener(event, fn, false)
: el.attachEvent("on" + event, fn);
};

el.all = function(selector){
return $(el.querySelectorAll(selector));
};

el.each = function(fn){
for (var i = 0, len = el.length; i < len; ++i) {
fn($(el[i]), i);
}
};

el.getClasses = function(){
return this.getAttribute('class').split(/\s+/);
};

el.addClass = function(name){
var classes = this.getAttribute('class');
el.setAttribute('class', classes
? classes + ' ' + name
: name);
};

el.removeClass = function(name){
var classes = this.getClasses().filter(function(curr){
return curr != name;
});
this.setAttribute('class', classes.join(' '));
};

return el;
}

function search() {
var str = $('search').value
, links = $('files').all('a');

links.each(function(link){
var text = link.textContent;

if ('..' == text) return;
if (str.length && ~text.indexOf(str)) {
link.addClass('highlight');
} else {
link.removeClass('highlight');
}
});
}

$(window).on('content loaded', function(){
$('search').on('keyup', search);
});
</script>
<link rel="stylesheet" type="text/css" href="?text/css">
<script src="?text/javascript"></script>
</head>
<body class="directory">
<input id="search" type="text" placeholder="Search" autocomplete="off" />
Expand Down
64 changes: 64 additions & 0 deletions public/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
function $(id){
var el = 'string' == typeof id
? document.getElementById(id)
: id;

el.on = function(event, fn){
if ('content loaded' == event) {
event = window.attachEvent ? "load" : "DOMContentLoaded";
}
el.addEventListener
? el.addEventListener(event, fn, false)
: el.attachEvent("on" + event, fn);
};

el.all = function(selector){
return $(el.querySelectorAll(selector));
};

el.each = function(fn){
for (var i = 0, len = el.length; i < len; ++i) {
fn($(el[i]), i);
}
};

el.getClasses = function(){
return this.getAttribute('class').split(/\s+/);
};

el.addClass = function(name){
var classes = this.getAttribute('class');
el.setAttribute('class', classes
? classes + ' ' + name
: name);
};

el.removeClass = function(name){
var classes = this.getClasses().filter(function(curr){
return curr != name;
});
this.setAttribute('class', classes.join(' '));
};

return el;
}

function search() {
var str = $('search').value
, links = $('files').all('a');

links.each(function(link){
var text = link.textContent;

if ('..' == text) return;
if (str.length && ~text.indexOf(str)) {
link.addClass('highlight');
} else {
link.removeClass('highlight');
}
});
}

$(window).on('content loaded', function(){
$('search').on('keyup', search);
});

0 comments on commit ae2db16

Please sign in to comment.