Skip to content

Commit

Permalink
more options for caching, prettier frontend, refresh all link,
Browse files Browse the repository at this point in the history
safe cache as .png in git-like folders
  • Loading branch information
juliangruber committed Jan 18, 2013
1 parent b087611 commit 145dcab
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 92 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ Configure the resolutions to use for screenshots. Defaults to `["1200x800"]`

PhantomJS will wait for `x` milliseconds after loading the page before it takes the screenshot, so you can make sure your page is completely loaded. Defaults to `0`.

### review#cache(x)
### review#cache({ dir : 'directory', expires : 60 })

Cache rendered snapshots for `x` seconds.
Cache rendered snapshots for `expires` seconds in `dir`.

### review#listen(port)

Expand Down
9 changes: 6 additions & 3 deletions bin/review.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ var review = require('..')
var optimist = require('optimist')

var argv = optimist
.usage('Host review\nUsage: $0 [options]\n\nExample: review --sites=\'{"google":"http://google.com"}\'')
.usage(
'Host review\nUsage: $0 [options]\n\n'+
'Examples: review --sites=\'{"google":"http://google.com"}\' --cache=\'{"dir":"cache","expires":100}\'')
.demand(['sites'])

.describe('port', 'Port to listen on')
Expand All @@ -26,8 +28,8 @@ var argv = optimist
.default('wait', 0)
.alias('w', 'wait')

.describe('cache', 'Cache snapshots for x seconds')
.default('cache', false)
.describe('cache', 'Cache snapshots for x milliseconds')
.default('cache', 'false')
.alias('c', 'cache')

.describe('help', 'Print usage instructions')
Expand All @@ -41,6 +43,7 @@ review()
.sites(JSON.parse(argv.sites))
.resolutions(JSON.parse(argv.resolutions))
.wait(argv.wait)
.cache(argv.cache? { dir : __dirname + '/cache', expires : argv.cache } : false)
.listen(argv.port, function () {
console.log('-> Review on port ' + argv.port)
})
Empty file removed cache/.gitkeep
Empty file.
11 changes: 7 additions & 4 deletions example/cache.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
var review = require('..')

review()
.title('Cached Review')
.sites({ localhost : 'http://localhost:3000/' })
.resolutions(['1280x1024', '800x600'])
.cache(5)
.title('Review')
.sites({ 'github' : 'https://github.com/' })
.resolutions(['1440x900', '1200x800', '640x480'])
.cache({
dir : __dirname + '/cache/',
expires : 86400
})
.listen(5000, function () {
console.log('-> Review on port 5000')
})
4 changes: 3 additions & 1 deletion lib/review.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var express = require('express')
var span = require('span')

module.exports = review

Expand Down Expand Up @@ -101,7 +102,8 @@ function review () {
sites : _sites,
resolutions : _resolutions,
wait : wait,
cache : cache
cache : cache,
expires : cache? span(cache.expires * 1000) : null
})
}
})
Expand Down
16 changes: 8 additions & 8 deletions lib/snapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var fs = require('fs')
var path = require('path')
var EventEmitter = require('events').EventEmitter
var crypto = require('crypto')
var mkdirp = require('mkdirp')

var app = module.exports = express()

Expand All @@ -27,7 +28,6 @@ app.cache = function (_cache) {
*/

var script = __dirname + '/../script/rasterize.js'
var cacheDir = path.join(__dirname, '/../cache/')

/**
* cache handling
Expand Down Expand Up @@ -55,15 +55,15 @@ app.get('/:url/:resolution/:wait', function (req, res, next) {
.update(req.params['resolution'])
.digest('hex')

var dir = hash.slice(0, 2)
var filename = cacheDir + dir + '/' + hash
var dir = path.join(cache.dir, hash.slice(0, 2))
var filename = path.join(dir, hash + '.png')

function createCash () {
function createCache () {
caching[hash] = true
snapshot(req.params, function (err, rasterized) {
if (err) return caching[hash] = false, next(err)

fs.mkdir(cacheDir + dir, function () {
mkdirp(dir, function () {
fs.writeFile(filename, rasterized, function (err) {
caching[hash] = false
if (err) return next(err)
Expand All @@ -76,12 +76,12 @@ app.get('/:url/:resolution/:wait', function (req, res, next) {
}

// refresh
if ('refresh' in req.query) return createCash()
if ('refresh' in req.query) return createCache()

// choose action based on cache file stat
fs.stat(filename, function (err, stat) {
// serve cache
if (!err && stat.mtime >= (Date.now() - cache * 1000)) {
if (!err && stat.mtime >= (Date.now() - cache.expires * 1000)) {
return res.sendfile(filename)
}

Expand All @@ -90,7 +90,7 @@ app.get('/:url/:resolution/:wait', function (req, res, next) {
return caches.once(hash, res.sendfile.bind(res, filename))
}

createCash()
createCache()
})
})

Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"dependencies": {
"optimist": "~0.3.5",
"jade": "~0.28.1",
"express": "~3.0.6"
"express": "~3.0.6",
"mkdirp": "~0.3.4",
"span": "0.0.5"
}
}
96 changes: 37 additions & 59 deletions public/app.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,49 @@
var images = Array.prototype.slice.apply(document.querySelectorAll('img'))
var info = document.querySelector('#info')
var loading = document.querySelector('#loading')

var loaded = 0
var reloads = 0
var allLoaded = false
var links = Array.prototype.slice.apply(document.querySelectorAll('.refresh'))
var refreshAll = document.querySelector('.refresh-all')

/**
* loading indicator
* refresh all
*/

var iv = setInterval(function () {
if (loaded == images.length) return clearInterval(iv)

loading.innerHTML += '.'
if (loading.innerHTML == '....') loading.innerHTML = ''
}, 500)

info.innerHTML = '0 / ' + images.length + ' loaded'
refreshAll.addEventListener('click', function () {
var msg = "You're about to refresh " + images.length + " snapshots. Are you sure?"
if (images.length > 10 && !confirm(msg)) return
images.forEach(refresh)
})

/**
* reload
* refresh
*/

images.forEach(function (image) {
image.addEventListener('click', function () {
reloads++

// show gray placeholder in same dimensions
var oldSrc = image.src + ''
var oldHeight = image.height

image.src = '/empty.jpg'
image.style.height = oldHeight + 'px'

setTimeout(function () {
// force reload
var newSrc = oldSrc
newSrc += newSrc.match(/\?/)
? '&reload'
: '?reload'

image.src = newSrc

function onLoad () {
image.style.height = 'auto'
image.removeEventListener('load', onLoad)
}

image.addEventListener('load', onLoad)
}, 500)

links.forEach(function (link) {
link.addEventListener('click', function () {
refresh(link.parentNode.nextSibling.childNodes[0])
})
})

/**
* loading status
*/

images.forEach(function (image) {
image.addEventListener('load', function () {
if (allLoaded) return
loaded++
info.innerHTML = (loaded-reloads) + ' / ' + images.length + ' loaded'
if ((loaded-reloads) == images.length) {
allLoaded = true
info.innerHTML = 'all loaded'
loading.innerHTML = ''
function refresh (image) {
// show gray placeholder in same dimensions
var oldSrc = image.src + ''
var oldHeight = image.height

image.src = '/empty.jpg'
image.style.height = oldHeight + 'px'

setTimeout(function () {
// force refresh
var newSrc = oldSrc
newSrc += newSrc.match(/\?/)
? '&refresh'
: '?refresh'

image.src = newSrc

function onLoad () {
image.style.height = 'auto'
image.removeEventListener('load', onLoad)
}
})
})

image.addEventListener('load', onLoad)
}, 500)
}
23 changes: 18 additions & 5 deletions public/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,33 @@ body {
padding : 20px 40px;
}

a {
cursor : pointer;
}

a.refresh-all {
color : lightblue;
font-weight : bold;
margin-left : 0.5ex;
position : relative;
top : -0.2ex;
}

a.refresh {
position : relative;
top : -0.2ex;
color : lightblue;
}

h1 span, h2 span {
color : lightgray;
}

h1 span {
font-weight : normal;
font-size : 40%;
color : lightblue;
}

#info {
margin-left : 1em;
}

img {
box-shadow: 2px 2px 25px rgba(0, 0, 0, 0.80);
-moz-box-shadow: 2px 2px 25px rgba(0, 0, 0, 0.80);
Expand Down
20 changes: 11 additions & 9 deletions views/index.jade
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,23 @@ html
link(rel='stylesheet',href='/style.css')
body
h1= title
span#info be patient
span#loading
a.refresh-all

if cache
p Serving potentially cached screenshots. Click an image to refresh.
p Images are cached for #{expires}. Refresh at will.
else
p Be patient, images will start appearing after #{wait/1000}s. Click an image to refresh.
if wait
p Be patient, images will start appearing after #{wait/1000}s. Refresh at will.

each url, title in sites
each resolution in resolutions
h2= title
span #{resolution.name}
img(
src='/snapshot/#{url}/#{resolution.name}/#{wait}',
style="width:#{resolution.width}; max-width:#{resolution.maxWidth}"
)
span #{resolution.name}
a.refresh
a(href="#{decodeURIComponent(url)}",target="_blank")
img(
src='/snapshot/#{url}/#{resolution.name}/#{wait}',
style="width:#{resolution.width}; max-width:#{resolution.maxWidth}"
)

script(src="/app.js")

0 comments on commit 145dcab

Please sign in to comment.