From dcd5a994cbd6de4c317edd22104701e1250b493f Mon Sep 17 00:00:00 2001 From: Joe Pettersson Date: Wed, 16 Jul 2014 11:44:42 +0100 Subject: [PATCH 1/9] Remove implicit config folder structure Remove the need for an implicit config folder structure (which is badly documented, in the original Wraith Ruby project as well). Now you pass a full relative path e.g. `./config/my_config.json` --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 7c309f6..3fa8837 100644 --- a/index.js +++ b/index.js @@ -13,7 +13,7 @@ function run(configFile) { outputFolder = '', baseFolder = process.cwd() + '/'; - var config = require(baseFolder + 'config/' + configFile + '.json'); + var config = require(baseFolder + configFile); outputFolder = typeof config.outputDir === 'undefined' ? baseFolder + 'shots/' : baseFolder + 'shots/' + config.outputDir; @@ -52,4 +52,4 @@ function run(configFile) { wraith(config, config.engines, domains, config.sizes, domainLabels, outputFolder, cb); } } -} \ No newline at end of file +} From e45109ace695d3ffb2d7fd1448b3440cf34a2526 Mon Sep 17 00:00:00 2001 From: Joe Pettersson Date: Wed, 16 Jul 2014 11:47:39 +0100 Subject: [PATCH 2/9] Update README.md to reflect new config changes --- readme.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index ef407cd..fe9196b 100644 --- a/readme.md +++ b/readme.md @@ -20,11 +20,13 @@ Based on the Ruby version available at [http://github.com/BBC-News/wraith](http: --v, --version Output version information Examples: - wraith --config chrome + wraith --config ./config/chrome.json ### Configuration file -Wraith uses a json based configuration file that allows you specfify a large number of options. You can create as many configurations files as you need and call them from the cli using the --config flag. All congiguration files must be stored within the config folder. +Wraith uses a json based configuration file that allows you specfify a large number of options. You can create as many configurations files as you need and call them from the cli using the --config flag. These configuration files can live anywhere that is addressable by a local path and they are passed as an argument like this: + + wraith --config ./path/to/my_config.json Below is an example configuration file: @@ -71,4 +73,4 @@ Below is an example configuration file: ## License -MIT © [James Bell](http://james-bell.co.uk) \ No newline at end of file +MIT © [James Bell](http://james-bell.co.uk) From 124bad7fae57864769a9b512104b3de19b7ec8ef Mon Sep 17 00:00:00 2001 From: David Byrd Date: Tue, 26 Aug 2014 11:10:04 -0400 Subject: [PATCH 3/9] ability to specify output directory --- index.js | 5 +++-- lib/gallery.js | 5 +++-- package.json | 4 ++-- readme.md | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 3fa8837..374f34a 100644 --- a/index.js +++ b/index.js @@ -2,7 +2,8 @@ var fs = require('fs'), wraith = require('./lib/wraith'), - spider = require('./lib/spider'); + spider = require('./lib/spider'), + path = require('path'); module.exports.run = run; @@ -15,7 +16,7 @@ function run(configFile) { var config = require(baseFolder + configFile); - outputFolder = typeof config.outputDir === 'undefined' ? baseFolder + 'shots/' : baseFolder + 'shots/' + config.outputDir; + outputFolder = path.join(baseFolder, config.outputDir || 'shots/'); for(var domain in config.domains) { domains.push(config.domains[domain].replace(/\/+$/, '')); diff --git a/lib/gallery.js b/lib/gallery.js index aa4cdb9..75bc7f9 100644 --- a/lib/gallery.js +++ b/lib/gallery.js @@ -3,6 +3,7 @@ var fs = require('fs'); var helpers = require('./helpers'); var mustache = require('mustache'); +var path = require('path') module.exports.generate = generate; @@ -31,7 +32,7 @@ function generate(dirs, compareList, outputDir, project, cb) { fs.readFile(template, function (err, data) { if (err) { throw err; } var output = mustache.render(data.toString(), view); - fs.writeFile(outputDir + 'gallery.html', output, function(err) { + fs.writeFile(path.join(outputDir, 'gallery.html'), output, function(err) { if(err) { console.log(err); } else { @@ -40,4 +41,4 @@ function generate(dirs, compareList, outputDir, project, cb) { } }); }); -} \ No newline at end of file +} diff --git a/package.json b/package.json index 998b66a..3258a70 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "wraith", - "version": "1.0.0", + "version": "1.0.1", "description": "A responsive screenshot comparison tool. Based on the Ruby version available at http://github.comm/BBC-News/wraith", "license": "MIT", - "repository": "jamesryanbell/node-wraith", + "repository": "thebyrd/node-wraith", "bin": { "wraith": "cli.js" }, diff --git a/readme.md b/readme.md index fe9196b..db6ab56 100644 --- a/readme.md +++ b/readme.md @@ -24,7 +24,7 @@ Based on the Ruby version available at [http://github.com/BBC-News/wraith](http: ### Configuration file -Wraith uses a json based configuration file that allows you specfify a large number of options. You can create as many configurations files as you need and call them from the cli using the --config flag. These configuration files can live anywhere that is addressable by a local path and they are passed as an argument like this: +Wraith uses a json based configuration file that allows you specify a large number of options. You can create as many configurations files as you need and call them from the cli using the --config flag. These configuration files can live anywhere that is addressable by a local path and they are passed as an argument like this: wraith --config ./path/to/my_config.json @@ -51,7 +51,7 @@ Below is an example configuration file: "1440" ], - "outputDir": "test/chrome/", (Output directory within the /shots directory) + "outputDir": "test/chrome/", (defaults to "shots") You can choose to specfiy a list of paths to be used or you can crawl the site. If paths are provided they will take precident and the spider file will be ignored. From 5fa34178df6defc1bf8252d261e4a76d44dcfa69 Mon Sep 17 00:00:00 2001 From: David Byrd Date: Tue, 26 Aug 2014 11:34:05 -0400 Subject: [PATCH 4/9] updated README --- readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.md b/readme.md index db6ab56..a464712 100644 --- a/readme.md +++ b/readme.md @@ -71,6 +71,9 @@ Below is an example configuration file: "maxConnections": 20 (Limit the amount of concurrent processes) } +## External Dependencies +Wraith requires [phantomjs](http://phantomjs.org/) & [imagemagick](http://www.imagemagick.org/) to be installed. On OS X this can easily be done with `npm install phantomjs` and `brew install imagemagick`. + ## License MIT © [James Bell](http://james-bell.co.uk) From 38ca44c1539150194c5521c4d9e61e8bbba474e8 Mon Sep 17 00:00:00 2001 From: David Byrd Date: Tue, 26 Aug 2014 14:53:45 -0400 Subject: [PATCH 5/9] got it working --- cli.js | 0 index.js | 5 +++-- lib/gallery.js | 4 +++- lib/wraith.js | 13 ++++++++----- package.json | 19 +++++++++++++++++-- 5 files changed, 31 insertions(+), 10 deletions(-) mode change 100644 => 100755 cli.js diff --git a/cli.js b/cli.js old mode 100644 new mode 100755 diff --git a/index.js b/index.js index 374f34a..03e04b4 100644 --- a/index.js +++ b/index.js @@ -14,10 +14,11 @@ function run(configFile) { outputFolder = '', baseFolder = process.cwd() + '/'; - var config = require(baseFolder + configFile); + var config = require(path.join(baseFolder, configFile)); - outputFolder = path.join(baseFolder, config.outputDir || 'shots/'); + outputFolder = path.join(baseFolder, config.outputDir || 'shots/'); + console.log('$$$$5', outputFolder, baseFolder, config.outputDir) for(var domain in config.domains) { domains.push(config.domains[domain].replace(/\/+$/, '')); domainLabels.push(domain); diff --git a/lib/gallery.js b/lib/gallery.js index 75bc7f9..a10ea01 100644 --- a/lib/gallery.js +++ b/lib/gallery.js @@ -9,7 +9,7 @@ module.exports.generate = generate; function generate(dirs, compareList, outputDir, project, cb) { compareList = compareList.sort(helpers.sortByProp('sort')); - var template = __dirname + '/../gallery.html', + var template = path.join(__dirname, '/../gallery.html'), view = { 'images' : compareList, 'dirs': dirs.sort(), @@ -29,9 +29,11 @@ function generate(dirs, compareList, outputDir, project, cb) { } }; + console.log('read tmpl') fs.readFile(template, function (err, data) { if (err) { throw err; } var output = mustache.render(data.toString(), view); + console.log('write out', path.join(outputDir, 'gallery.html')) fs.writeFile(path.join(outputDir, 'gallery.html'), output, function(err) { if(err) { console.log(err); diff --git a/lib/wraith.js b/lib/wraith.js index f583bcc..fa1fedf 100644 --- a/lib/wraith.js +++ b/lib/wraith.js @@ -1,6 +1,7 @@ 'use strict'; var fs = require('fs'), + path = require('path'), async = require('async'), mkdirp = require('mkdirp'), gallery = require('./gallery'), @@ -30,6 +31,7 @@ function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) console.log('Cleaned up old folders and files'); var foldersQueue = async.queue(function(folder, callback) { + console.log('$$$1folder', folder) mkdirp(folder, function (err) { if (err) { throw err; } callback(); @@ -37,7 +39,8 @@ function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) }); for(var url in urls) { - folder = outputFolder + urls[url].substring(1).replace(/\/+$/,'') + '/'; + folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/,'') + '/'); + console.log('$$$$2', folder, outputFolder) foldersQueue.push(folder); dirs.push(folder); } @@ -55,7 +58,7 @@ function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) for(var domain in domains) { for(url in urls) { imageUrls.push(domains[domain] + urls[url]); - folder = outputFolder + urls[url].substring(1).replace(/\/+$/,'') + '/'; + folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/,'') + '/'); for(size in sizes) { image = folder + domainLabels[domain] + '_' + sizes[size] + '.png'; screenshotQueue.push({ @@ -72,7 +75,7 @@ function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) for(url in urls) { for(var engine in engines) { imageUrls.push(domains[0] + urls[url]); - folder = outputFolder + urls[url].substring(1).replace(/\/+$/,'') + '/'; + folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/,'') + '/'); for(size in sizes) { image = folder + engines[engine] + '_' + sizes[size] + '.png'; screenshotQueue.push({ @@ -105,7 +108,7 @@ function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) for(var url in urls) { var dir = urls[url].substring(1).replace(/\/+$/,'') + '/'; - folder = outputFolder + dir; + folder = path.join(outputFolder, dir); for(var size in sizes) { item = { 'dir': ( size > 0 ? false : folder), @@ -133,4 +136,4 @@ function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) console.log('No url(s) provided'); return false; } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 3258a70..4ddb29c 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,10 @@ "version": "1.0.1", "description": "A responsive screenshot comparison tool. Based on the Ruby version available at http://github.comm/BBC-News/wraith", "license": "MIT", - "repository": "thebyrd/node-wraith", + "repository": { + "type": "git", + "url": "git://github.com/thebyrd/node-wraith" + }, "bin": { "wraith": "cli.js" }, @@ -49,5 +52,17 @@ "mustache": "~0.8.1", "rimraf": "~2.2.6" }, - "devDependencies": {} + "devDependencies": {}, + "readme": "# Wraith\nA responsive screenshot comparison tool.\nBased on the Ruby version available at [http://github.com/BBC-News/wraith](http://github.com/BBC-News/wraith)\n\n## CLI app\n\n### Install\n\n```\n\tnpm install --global wraith\n```\n\n###Usage\n\n\tUsage:\n\twraith --config \n\n\tOptions:\n\t-h, --help\t\tOutput help information\n\t--v, --version\tOutput version information\n\n\tExamples:\n\twraith --config ./config/chrome.json\n\n### Configuration file\n\nWraith uses a json based configuration file that allows you specify a large number of options. You can create as many configurations files as you need and call them from the cli using the --config flag. These configuration files can live anywhere that is addressable by a local path and they are passed as an argument like this:\n\n wraith --config ./path/to/my_config.json\n\nBelow is an example configuration file:\n\n\t{\n\t\t\"project\": \"Test\", (Optional name for the project, if supplied it will be used within the generated gallery only)\n\n\t\tSpecify one or two domains\n\t\t\"domains\": {\n\t\t\t\"bbb.co.uk\": \"http://www.bbc.co.uk\",\n\t\t\t\"live.bbc.co.uk\": \"http://live.bbc.co.uk\"\n\t\t},\n\n\t\tEngines supported are phantomjs, slimerjs and triflejs but in theory any phantomjs based headless browser can be supported via a custom snap.js file\n\t\t\"engines\" : [\n\t\t\t\"phantomjs\"\n\t\t],\n\n\t\tSpecify as many sizes as you wish\n\t\t\"sizes\": [\n\t\t\t\"320\",\n\t\t\t\"768\",\n\t\t\t\"1440\"\n\t\t],\n\n\t\t\"outputDir\": \"test/chrome/\", (defaults to \"shots\")\n\n\t\tYou can choose to specfiy a list of paths to be used or you can crawl the site. If paths are provided they will take precident and the spider file will be ignored.\n\n\t\t\"paths\": [\n\t\t\t\"/\",\n\t\t\t\"/news/\",\n\t\t\t\"/news/local/\",\n\t\t\t\"/news/england/york_and_north_yorkshire/\",\n\t\t\t\"/weather/\"\n\t\t],\n\n\t\tIf no paths are specified then a site crawl will take place and the results will be save in the location specified within this option\n\t\t\"spider\": \"spider/test.txt\", (Specify which file should be used for the spider txt file)\n\n\t\t\"snap\": \"snap/test/chrome.js\", (Specify snap.js which is used to take the screenshots)\n\t\t\"fuzz\": \"20%\", (Adjusts the sensitivity of the image comparison)\n\t\t\"maxConnections\": 20 (Limit the amount of concurrent processes)\n\t}\n\n## External Dependencies\nWraith requires [phantomjs](http://phantomjs.org/) & [imagemagick](http://www.imagemagick.org/) to be installed. On OS X this can easily be done with `npm install phantomjs` and `brew install imagemagick`.\n\n## License\n\nMIT © [James Bell](http://james-bell.co.uk)\n", + "readmeFilename": "readme.md", + "bugs": { + "url": "https://github.com/thebyrd/node-wraith/issues" + }, + "homepage": "https://github.com/thebyrd/node-wraith", + "_id": "wraith@1.0.1", + "dist": { + "shasum": "6fe7dcbc35f8d4e3d5df72d796dd500ae8a84591" + }, + "_resolved": "git+https://github.com/thebyrd/node-wraith.git#96e70c3c85256859c240b99ffa648ddfec8870c1", + "_from": "wraith@git+https://github.com/thebyrd/node-wraith.git#master" } From 3afded4af1f7b09660fab043dc2337a09fea2af1 Mon Sep 17 00:00:00 2001 From: David Byrd Date: Tue, 26 Aug 2014 14:56:30 -0400 Subject: [PATCH 6/9] added .gitignore and remove debug --- .gitignore | 2 ++ index.js | 1 - lib/wraith.js | 2 -- 3 files changed, 2 insertions(+), 3 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d9308f4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +bbc diff --git a/index.js b/index.js index 03e04b4..9e10c02 100644 --- a/index.js +++ b/index.js @@ -18,7 +18,6 @@ function run(configFile) { outputFolder = path.join(baseFolder, config.outputDir || 'shots/'); - console.log('$$$$5', outputFolder, baseFolder, config.outputDir) for(var domain in config.domains) { domains.push(config.domains[domain].replace(/\/+$/, '')); domainLabels.push(domain); diff --git a/lib/wraith.js b/lib/wraith.js index fa1fedf..f518586 100644 --- a/lib/wraith.js +++ b/lib/wraith.js @@ -31,7 +31,6 @@ function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) console.log('Cleaned up old folders and files'); var foldersQueue = async.queue(function(folder, callback) { - console.log('$$$1folder', folder) mkdirp(folder, function (err) { if (err) { throw err; } callback(); @@ -40,7 +39,6 @@ function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) for(var url in urls) { folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/,'') + '/'); - console.log('$$$$2', folder, outputFolder) foldersQueue.push(folder); dirs.push(folder); } From c826ff3f5ba228ba1838736ccfba80254758ff33 Mon Sep 17 00:00:00 2001 From: David Byrd Date: Tue, 26 Aug 2014 14:58:43 -0400 Subject: [PATCH 7/9] change example from bbc to google --- .gitignore | 2 +- config/chrome.json | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index d9308f4..f05b1f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ node_modules -bbc +test diff --git a/config/chrome.json b/config/chrome.json index 22c20a4..0cbf831 100644 --- a/config/chrome.json +++ b/config/chrome.json @@ -1,25 +1,21 @@ { "project": "Test", "domains": { - "bbc.co.uk": "http://www.bbc.co.uk", - "live.bbc.co.uk": "http://www.live.bbc.co.uk" + "usa": "http://www.google.com", + "canada": "http://www.google.ca" }, "engines" : [ "phantomjs" ], "sizes": [ - "320", "768", "1440" ], "paths": [ "/", - "/news", - "/weather", - "/tv", - "/aboutthebbc" + "/404" ], - "outputDir": "bbc", + "outputDir": "test", "fuzz": "20%", "maxConnections": 20 -} \ No newline at end of file +} From 64f83e6347d0d3d3d66ad40be836cc0c65ce07bb Mon Sep 17 00:00:00 2001 From: David Byrd Date: Tue, 26 Aug 2014 14:59:30 -0400 Subject: [PATCH 8/9] remove debug --- config/chrome.json | 2 +- lib/gallery.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/config/chrome.json b/config/chrome.json index 0cbf831..66478af 100644 --- a/config/chrome.json +++ b/config/chrome.json @@ -1,5 +1,5 @@ { - "project": "Test", + "project": "Google Test", "domains": { "usa": "http://www.google.com", "canada": "http://www.google.ca" diff --git a/lib/gallery.js b/lib/gallery.js index a10ea01..2510c22 100644 --- a/lib/gallery.js +++ b/lib/gallery.js @@ -29,11 +29,9 @@ function generate(dirs, compareList, outputDir, project, cb) { } }; - console.log('read tmpl') fs.readFile(template, function (err, data) { if (err) { throw err; } var output = mustache.render(data.toString(), view); - console.log('write out', path.join(outputDir, 'gallery.html')) fs.writeFile(path.join(outputDir, 'gallery.html'), output, function(err) { if(err) { console.log(err); From c5f4d048724c68e7ad9161c0407485d6b8a3980e Mon Sep 17 00:00:00 2001 From: Ryan Cline Date: Wed, 12 Nov 2014 16:05:23 -0700 Subject: [PATCH 9/9] Added a default configs file instead of defaults being inline. Added other example config files. Linted code. --- .gitignore | 2 +- .jshintrc | 34 ++--- cli.js | 90 ++++++------- config/bbc.json | 25 ++++ config/chrome.json | 21 --- config/config.example.json | 47 +++++++ config/defaults.json | 16 +++ config/google.json | 21 +++ gallery.html | 143 ++++++++++---------- index.js | 85 ++++++------ lib/gallery.js | 66 +++++----- lib/helpers.js | 36 ++--- lib/screenshot.js | 6 +- lib/spider.js | 96 +++++++------- lib/wraith.js | 260 +++++++++++++++++++------------------ package.json | 132 +++++++++---------- readme.md | 43 +----- snap.js | 84 ++++++------ 18 files changed, 630 insertions(+), 577 deletions(-) create mode 100644 config/bbc.json delete mode 100644 config/chrome.json create mode 100644 config/config.example.json create mode 100644 config/defaults.json create mode 100644 config/google.json diff --git a/.gitignore b/.gitignore index f05b1f2..7a1537b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ +.idea node_modules -test diff --git a/.jshintrc b/.jshintrc index 39a8579..0f62563 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,19 +1,19 @@ { - "node": true, - "esnext": true, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "indent": 4, - "newcap": true, - "noarg": true, - "quotmark": "single", - "regexp": true, - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "smarttabs": true + "node": true, + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "indent": 4, + "newcap": true, + "noarg": true, + "quotmark": "single", + "regexp": true, + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + "smarttabs": true } diff --git a/cli.js b/cli.js index 04e5478..03e2ab7 100755 --- a/cli.js +++ b/cli.js @@ -5,72 +5,72 @@ var chalk = require('chalk'); var wraith = require('./index'); function showHelp() { - console.log('A responsive screenshot comparison tool.'); - console.log('Based on the Ruby version available at http://github.comm/BBC-News/wraith'); - console.log(''); - console.log(chalk.underline('Usage')); - console.log(' wraith --config '); - console.log(''); - console.log(chalk.underline('Example')); - console.log(' wraith --config chrome'); - console.log(''); + console.log('A responsive screenshot comparison tool.'); + console.log('Based on the Ruby version available at http://github.comm/BBC-News/wraith'); + console.log(''); + console.log(chalk.underline('Usage')); + console.log(' wraith --config '); + console.log(''); + console.log(chalk.underline('Example')); + console.log(' wraith --config chrome'); + console.log(''); } function getStdin(cb) { - var ret = ''; + var ret = ''; - process.stdin.resume(); - process.stdin.setEncoding('utf8'); + process.stdin.resume(); + process.stdin.setEncoding('utf8'); - process.stdin.on('data', function (data) { - ret += data; - }); + process.stdin.on('data', function (data) { + ret += data; + }); - process.stdin.on('end', function () { - cb(ret); - }); + process.stdin.on('end', function () { + cb(ret); + }); } function init(args) { - if (opts.help) { - return showHelp(); - } + if (opts.help) { + return showHelp(); + } - if (opts.version) { - return console.log(require('./package').version); - } + if (opts.version) { + return console.log(require('./package').version); + } - var config = args; - if( opts.config && args[0]) { - if (config.length === 0) { - console.error(chalk.yellow('You must specifiy a configuration file')); - return showHelp(); - } else { - return wraith.run(args[0]); - } - } + var config = args; + if (opts.config && args[0]) { + if (config.length === 0) { + console.error(chalk.yellow('You must specifiy a configuration file')); + return showHelp(); + } else { + return wraith.run(args[0]); + } + } - return showHelp(); + return showHelp(); } var opts = nopt({ - help: Boolean, - version: Boolean, - config: Boolean + help: Boolean, + version: Boolean, + config: Boolean }, { - h: '--help', - v: '--version', - c: '--config' + h: '--help', + v: '--version', + c: '--config' }); var args = opts.argv.remain; if (process.stdin.isTTY) { - init(args); + init(args); } else { - getStdin(function (data) { - [].push.apply(args, data.trim().split('\n')); - init(args); - }); + getStdin(function (data) { + [].push.apply(args, data.trim().split('\n')); + init(args); + }); } diff --git a/config/bbc.json b/config/bbc.json new file mode 100644 index 0000000..d7e89fb --- /dev/null +++ b/config/bbc.json @@ -0,0 +1,25 @@ +{ + "project": "Test", + "domains": { + "bbc.co.uk": "http://www.bbc.co.uk", + "live.bbc.co.uk": "http://www.live.bbc.co.uk" + }, + "engines": [ + "phantomjs" + ], + "sizes": [ + "320", + "768", + "1440" + ], + "outputDir": "bbc", + "paths": [ + "/", + "/news", + "/weather", + "/tv", + "/aboutthebbc" + ], + "fuzz": "20%", + "maxConnections": 20 +} diff --git a/config/chrome.json b/config/chrome.json deleted file mode 100644 index 66478af..0000000 --- a/config/chrome.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "project": "Google Test", - "domains": { - "usa": "http://www.google.com", - "canada": "http://www.google.ca" - }, - "engines" : [ - "phantomjs" - ], - "sizes": [ - "768", - "1440" - ], - "paths": [ - "/", - "/404" - ], - "outputDir": "test", - "fuzz": "20%", - "maxConnections": 20 -} diff --git a/config/config.example.json b/config/config.example.json new file mode 100644 index 0000000..a5cbb33 --- /dev/null +++ b/config/config.example.json @@ -0,0 +1,47 @@ +{ + "#": "(Optional name for the project, if supplied it will be used within the generated gallery only)", + "project": "Test", + + "#": "Specify one or two domains", + "domains": { + "bbb.co.uk": "http://www.bbc.co.uk", + "live.bbc.co.uk": "http://live.bbc.co.uk" + }, + + "#": "Engines supported are phantomjs, slimerjs and triflejs but in theory any phantomjs based headless browser can be supported via a custom snap.js file", + "engines": [ + "phantomjs" + ], + + "#": "Specify as many sizes as you wish", + "sizes": [ + "320", + "768", + "1440" + ], + + "#": "(Defaults to 'shots' directory)", + "outputDir": "test/chrome/", + + "#": "You can choose to specify a list of paths to be used or you can crawl the site. If paths are provided they will take precedent and the spider file will be ignored.", + "paths": [ + "/", + "/news/", + "/news/local/", + "/news/england/york_and_north_yorkshire/", + "/weather/" + ], + + "#": "If no paths are specified then a site crawl will take place and the results will be save in the location specified within this option", + "#": "(Specify which file should be used for the spider txt file)", + "spider": "spider/test.txt", + + "#": "(Specify snap.js which is used to take the screenshots. Defaults to 'snap.js')", + "snap": "snap/test/chrome.js", + + "#": "(Adjusts the sensitivity of the image comparison)", + "fuzz": "20%", + + "#": "(Limit the amount of concurrent processes)", + "maxConnections": 20 +} diff --git a/config/defaults.json b/config/defaults.json new file mode 100644 index 0000000..2ff2b87 --- /dev/null +++ b/config/defaults.json @@ -0,0 +1,16 @@ +{ + "project": "", + "engines": [ + "phantomjs" + ], + "sizes": [ + "720" + ], + "outputDir": "shots/", + "paths": [ + "/" + ], + "snap": "snap.js", + "fuzz": "20%", + "maxConnections": 20 +} diff --git a/config/google.json b/config/google.json new file mode 100644 index 0000000..2c15cd4 --- /dev/null +++ b/config/google.json @@ -0,0 +1,21 @@ +{ + "project": "Google Test", + "domains": { + "usa": "http://www.google.com", + "canada": "http://www.google.ca" + }, + "engines": [ + "phantomjs" + ], + "sizes": [ + "768", + "1440" + ], + "outputDir": "test", + "paths": [ + "/", + "/404" + ], + "fuzz": "20%", + "maxConnections": 20 +} diff --git a/gallery.html b/gallery.html index 1a016d8..f259c66 100644 --- a/gallery.html +++ b/gallery.html @@ -1,70 +1,77 @@ - - - - Screenshots - {{project}} - - -
- -
-
-
-

Screenshots:

- -
-
-
- {{#images}} - {{#dir}} -
- -

/{{#resolve}}{{dir}}{{/resolve}}

-
- {{/dir}} -
-

{{size}}px

-
- - - -

{{#resolve}}{{base}}{{/resolve}}

-
-
- - - -

{{#resolve}}{{compare}}{{/resolve}}

-
-
- - - -

diff

-

{{#contents}}{{diff}}{{/contents}} bytes

-
-
- {{/images}} -
-
-
- - \ No newline at end of file + + + + Screenshots - {{project}} + + +
+ +
+
+
+

Screenshots:

+ +
+
+
+ {{#images}} + {{#dir}} +
+ + +

/{{#resolve}}{{dir}}{{/resolve}}

+
+ {{/dir}} +
+

{{size}}px

+ +
+ + + + +

{{#resolve}}{{base}}{{/resolve}}

+
+
+ + + + +

{{#resolve}}{{compare}}{{/resolve}}

+
+
+ + + + +

diff

+ +

{{#contents}}{{diff}}{{/contents}} bytes

+
+
+ {{/images}} +
+
+
+ + diff --git a/index.js b/index.js index 9e10c02..505d068 100644 --- a/index.js +++ b/index.js @@ -1,56 +1,45 @@ 'use strict'; -var fs = require('fs'), - wraith = require('./lib/wraith'), - spider = require('./lib/spider'), - path = require('path'); +var fs = require('fs'); +var wraith = require('./lib/wraith'); +var spider = require('./lib/spider'); +var path = require('path'); +var extend = require('util')._extend; module.exports.run = run; function run(configFile) { - var domains = [], - domainLabels = [], - outputFolder = '', - baseFolder = process.cwd() + '/'; - - var config = require(path.join(baseFolder, configFile)); - - - outputFolder = path.join(baseFolder, config.outputDir || 'shots/'); - for(var domain in config.domains) { - domains.push(config.domains[domain].replace(/\/+$/, '')); - domainLabels.push(domain); - } - - if( !config.fuzz ) { - config.fuzz = '20%'; - } - - if( !config.maxConnections ) { - config.maxConnections = 20; - } - - if(config.snap) { - config.snap = baseFolder + config.snap; - } else { - config.snap = __dirname + '/snap.js'; - } - - var cb = function() { - console.log('Done'); - }; - - if( config.paths && config.paths.length > 0 ) { - wraith(config, config.engines, domains, config.sizes, domainLabels, outputFolder, cb); - } else if( config.spider ) { - config.spider = baseFolder + config.spider; - if (!fs.existsSync(config.spider)) { - spider(domains[0], config.spider, function() { - wraith(config, config.engines, domains, config.sizes, domainLabels, outputFolder, cb); - }); - } else { - wraith(config, config.engines, domains, config.sizes, domainLabels, outputFolder, cb); - } - } + var domains = []; + var domainLabels = []; + var outputFolder = ''; + var baseFolder = process.cwd() + '/'; + + var defaults = require(path.join(baseFolder, "config/defaults.json")); + var config = require(path.join(baseFolder, configFile)); + extend(defaults, config); + + outputFolder = path.join(baseFolder, config.outputDir); + + for (var domain in config.domains) { + domains.push(config.domains[domain].replace(/\/+$/, '')); + domainLabels.push(domain); + } + + var cb = function () { + console.log('Done'); + }; + + if (config.paths && config.paths.length > 0) { + wraith(config, config.engines, domains, config.sizes, domainLabels, outputFolder, cb); + } else if (config.spider) { + config.spider = baseFolder + config.spider; + if (!fs.existsSync(config.spider)) { + spider(domains[0], config.spider, function () { + wraith(config, config.engines, domains, config.sizes, domainLabels, outputFolder, cb); + }); + } else { + wraith(config, config.engines, domains, config.sizes, domainLabels, outputFolder, cb); + } + } } diff --git a/lib/gallery.js b/lib/gallery.js index 2510c22..fd82241 100644 --- a/lib/gallery.js +++ b/lib/gallery.js @@ -8,37 +8,39 @@ var path = require('path') module.exports.generate = generate; function generate(dirs, compareList, outputDir, project, cb) { - compareList = compareList.sort(helpers.sortByProp('sort')); - var template = path.join(__dirname, '/../gallery.html'), - view = { - 'images' : compareList, - 'dirs': dirs.sort(), - 'project': project, - 'resolve': function() { - return function(text, render) { - var rendered = render(text); - return rendered.replace(///g, '/').replace(outputDir, '').replace(/^\//, ''); - }; - }, - 'contents': function() { - return function(text, render) { - var rendered = render(text); - var output = fs.readFileSync(rendered.replace(///g, '/').replace(/\/\//g,'/'),'utf8'); - return output ? output : 0; - }; - } - }; + compareList = compareList.sort(helpers.sortByProp('sort')); + var template = path.join(__dirname, '/../gallery.html'), + view = { + 'images': compareList, + 'dirs': dirs.sort(), + 'project': project, + 'resolve': function () { + return function (text, render) { + var rendered = render(text); + return rendered.replace(///g, '/').replace(outputDir, '').replace(/^\//, ''); + }; + }, + 'contents': function () { + return function (text, render) { + var rendered = render(text); + var output = fs.readFileSync(rendered.replace(///g, '/').replace(/\/\//g, '/'), 'utf8'); + return output ? output : 0; + }; + } + }; - fs.readFile(template, function (err, data) { - if (err) { throw err; } - var output = mustache.render(data.toString(), view); - fs.writeFile(path.join(outputDir, 'gallery.html'), output, function(err) { - if(err) { - console.log(err); - } else { - console.log('Gallery generated'); - cb(); - } - }); - }); + fs.readFile(template, function (err, data) { + if (err) { + throw err; + } + var output = mustache.render(data.toString(), view); + fs.writeFile(path.join(outputDir, 'gallery.html'), output, function (err) { + if (err) { + console.log(err); + } else { + console.log('Gallery generated'); + cb(); + } + }); + }); } diff --git a/lib/helpers.js b/lib/helpers.js index 57c9250..861750e 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -4,26 +4,30 @@ var rimraf = require('rimraf'); module.exports.sortByProp = sortByProp; -function sortByProp(prop){ - return function(a,b){ - if( a[prop] > b[prop]){ - return 1; - } else if( a[prop] < b[prop] ) { - return -1; - } - return 0; - }; +function sortByProp(prop) { + return function (a, b) { + if (a[prop] > b[prop]) { + return 1; + } else if (a[prop] < b[prop]) { + return -1; + } + return 0; + }; } module.exports.emptyFolder = emptyFolder; function emptyFolder(folder, cb) { - if( typeof(folder) === 'undefined' ) { return false; } + if (typeof(folder) === 'undefined') { + return false; + } - rimraf(folder, function(err) { - if( err ) { throw err; } - cb(); - }); + rimraf(folder, function (err) { + if (err) { + throw err; + } + cb(); + }); - return true; -} \ No newline at end of file + return true; +} diff --git a/lib/screenshot.js b/lib/screenshot.js index aeab6f9..51151de 100644 --- a/lib/screenshot.js +++ b/lib/screenshot.js @@ -6,9 +6,9 @@ module.exports.compare = compare; module.exports.take = take; function take(engine, snapFile, url, size, output, callback) { - exec(engine + ' ' + snapFile + ' ' + url + ' ' + size + ' ' + output, callback); + exec(engine + ' ' + snapFile + ' ' + url + ' ' + size + ' ' + output, callback); } function compare(base, compare, output, info, fuzz, callback) { - exec('compare -quiet -fuzz ' + fuzz + ' -metric AE -highlight-color blue ' + base + ' ' + compare + ' ' + output + ' 2>' + info, callback); -} \ No newline at end of file + exec('compare -quiet -fuzz ' + fuzz + ' -metric AE -highlight-color blue ' + base + ' ' + compare + ' ' + output + ' 2>' + info, callback); +} diff --git a/lib/spider.js b/lib/spider.js index cc2a04e..5e8c327 100644 --- a/lib/spider.js +++ b/lib/spider.js @@ -1,54 +1,56 @@ 'use strict'; -var fs = require('fs'), - mkdirp = require('mkdirp'), - crawl = require('crawl'); +var fs = require('fs'); +var mkdirp = require('mkdirp'); +var crawl = require('crawl'); module.exports = spider; function spider(url, file, callback) { - console.log('Crawl of ' + url + ' started'); - - crawl.crawl(url, { headers: false, body: false }, function(err, pages) { - - if (err) { - console.error('An error occured', err); - return; - } - - var txt = '', - pagesLength = pages.length, - link = ''; - - for(var i = 0; i 0 ) { - - var folders = file.split('/'); - folders.pop(); - folders = folders.join('/'); - - mkdirp(folders, function (err) { - if (err) { throw err; } - fs.writeFile(file, txt, function(err) { - if(err) { - console.log(err); - } else { - console.log('Spider file saved to ' + file); - callback(); - } - }); - }); - } else { - console.log('No urls found'); - } - }); -} \ No newline at end of file + console.log('Crawl of ' + url + ' started'); + + crawl.crawl(url, {headers: false, body: false}, function (err, pages) { + + if (err) { + console.error('An error occured', err); + return; + } + + var txt = '', + pagesLength = pages.length, + link = ''; + + for (var i = 0; i < pagesLength; i++) { + link = pages[i].url; + var excPattern = new RegExp('.(css|js|jpg|jpeg|png|pdf|doc|xls|xlsx|ppt|txt|gif|swf|svg|ttf|otf|woff|json|xml)+$'); + if (link.indexOf(url) === 0 && !link.match(excPattern)) { + txt += link.replace(url, '') + '\n'; + } + } + txt = txt.trim(); + + if (txt.length > 0) { + + var folders = file.split('/'); + folders.pop(); + folders = folders.join('/'); + + mkdirp(folders, function (err) { + if (err) { + throw err; + } + fs.writeFile(file, txt, function (err) { + if (err) { + console.log(err); + } else { + console.log('Spider file saved to ' + file); + callback(); + } + }); + }); + } else { + console.log('No urls found'); + } + }); +} diff --git a/lib/wraith.js b/lib/wraith.js index f518586..33b7ea9 100644 --- a/lib/wraith.js +++ b/lib/wraith.js @@ -1,137 +1,139 @@ 'use strict'; -var fs = require('fs'), - path = require('path'), - async = require('async'), - mkdirp = require('mkdirp'), - gallery = require('./gallery'), - screenshot = require('./screenshot'), - helpers = require('./helpers'); +var fs = require('fs'); +var path = require('path'); +var async = require('async'); +var mkdirp = require('mkdirp'); +var gallery = require('./gallery'); +var screenshot = require('./screenshot'); +var helpers = require('./helpers'); module.exports = wraith; function wraith(config, engines, domains, sizes, domainLabels, outputFolder, cb) { - var imageUrls = [], - image = '', - folder = '', - dirs = [], - urls; - - if( typeof config.paths !== 'undefined' && config.paths.length > 0 ) { - urls = config.paths; - } else { - urls = fs.readFileSync(config.spider, 'utf8').split('\n'); - } - - if( urls.length > 0 ) { - - helpers.emptyFolder(outputFolder, function () { - - console.log('Cleaned up old folders and files'); - - var foldersQueue = async.queue(function(folder, callback) { - mkdirp(folder, function (err) { - if (err) { throw err; } - callback(); - }); - }); - - for(var url in urls) { - folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/,'') + '/'); - foldersQueue.push(folder); - dirs.push(folder); - } - - foldersQueue.drain = function() { - console.log('New folders created'); - - var screenshotQueue = async.queue(function (task, callback) { - screenshot.take(task.engine, task.snapFile, task.url, task.size, task.output, callback); - }, config.maxConnections); - - var url, size; - - if( engines.length === 1 ) { - for(var domain in domains) { - for(url in urls) { - imageUrls.push(domains[domain] + urls[url]); - folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/,'') + '/'); - for(size in sizes) { - image = folder + domainLabels[domain] + '_' + sizes[size] + '.png'; - screenshotQueue.push({ - engine: engines[0], - snapFile: config.snap, - url: domains[domain] + urls[url], - size: sizes[size], - output: image - }); - } - } - } - } else { - for(url in urls) { - for(var engine in engines) { - imageUrls.push(domains[0] + urls[url]); - folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/,'') + '/'); - for(size in sizes) { - image = folder + engines[engine] + '_' + sizes[size] + '.png'; - screenshotQueue.push({ - engine: engines[engine], - snapFile: config.snap, - url: domains[0] + urls[url], - size: sizes[size], - output: image - }); - } - } - } - } - - screenshotQueue.drain = function() { - console.log('Screenshots done'); - - var compareQueue = async.queue(function(task, callback) { - screenshot.compare(task.base, task.compare, task.output, task.diff, task.fuzz, callback); - }, config.maxConnections); - - folder = ''; - var fileLabels = [], compareList = [], item; - - if( engines.length === 1 ) { - fileLabels = [domainLabels[0], domainLabels[1]]; - } else { - fileLabels = [engines[0], engines[1]]; - } - - for(var url in urls) { - var dir = urls[url].substring(1).replace(/\/+$/,'') + '/'; - folder = path.join(outputFolder, dir); - for(var size in sizes) { - item = { - 'dir': ( size > 0 ? false : folder), - 'sort': folder + size, - 'base': folder + fileLabels[0] + '_' + sizes[size] + '.png', - 'compare': folder + fileLabels[1] + '_' + sizes[size] + '.png', - 'output': folder + sizes[size] + '_diff.png', - 'diff': folder + sizes[size] + '_diff.txt', - 'fuzz': config.fuzz, - 'size': sizes[size] - }; - compareQueue.push(item); - compareList.push(item); - } - } - - compareQueue.drain = function(){ - console.log('Image comparison done'); - gallery.generate(dirs, compareList, outputFolder, config.project, cb); - }; - }; - }; - }); - } else { - console.log('No url(s) provided'); - return false; - } + var imageUrls = [], + image = '', + folder = '', + dirs = [], + urls; + + if (typeof config.paths !== 'undefined' && config.paths.length > 0) { + urls = config.paths; + } else { + urls = fs.readFileSync(config.spider, 'utf8').split('\n'); + } + + if (urls.length > 0) { + + helpers.emptyFolder(outputFolder, function () { + + console.log('Cleaned up old folders and files'); + + var foldersQueue = async.queue(function (folder, callback) { + mkdirp(folder, function (err) { + if (err) { + throw err; + } + callback(); + }); + }); + + for (var url in urls) { + folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/, '') + '/'); + foldersQueue.push(folder); + dirs.push(folder); + } + + foldersQueue.drain = function () { + console.log('New folders created'); + + var screenshotQueue = async.queue(function (task, callback) { + screenshot.take(task.engine, task.snapFile, task.url, task.size, task.output, callback); + }, config.maxConnections); + + var url, size; + + if (engines.length === 1) { + for (var domain in domains) { + for (url in urls) { + imageUrls.push(domains[domain] + urls[url]); + folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/, '') + '/'); + for (size in sizes) { + image = folder + domainLabels[domain] + '_' + sizes[size] + '.png'; + screenshotQueue.push({ + engine: engines[0], + snapFile: config.snap, + url: domains[domain] + urls[url], + size: sizes[size], + output: image + }); + } + } + } + } else { + for (url in urls) { + for (var engine in engines) { + imageUrls.push(domains[0] + urls[url]); + folder = path.join(outputFolder, urls[url].substring(1).replace(/\/+$/, '') + '/'); + for (size in sizes) { + image = folder + engines[engine] + '_' + sizes[size] + '.png'; + screenshotQueue.push({ + engine: engines[engine], + snapFile: config.snap, + url: domains[0] + urls[url], + size: sizes[size], + output: image + }); + } + } + } + } + + screenshotQueue.drain = function () { + console.log('Screenshots done'); + + var compareQueue = async.queue(function (task, callback) { + screenshot.compare(task.base, task.compare, task.output, task.diff, task.fuzz, callback); + }, config.maxConnections); + + folder = ''; + var fileLabels = [], compareList = [], item; + + if (engines.length === 1) { + fileLabels = [domainLabels[0], domainLabels[1]]; + } else { + fileLabels = [engines[0], engines[1]]; + } + + for (var url in urls) { + var dir = urls[url].substring(1).replace(/\/+$/, '') + '/'; + folder = path.join(outputFolder, dir); + for (var size in sizes) { + item = { + 'dir': ( size > 0 ? false : folder), + 'sort': folder + size, + 'base': folder + fileLabels[0] + '_' + sizes[size] + '.png', + 'compare': folder + fileLabels[1] + '_' + sizes[size] + '.png', + 'output': folder + sizes[size] + '_diff.png', + 'diff': folder + sizes[size] + '_diff.txt', + 'fuzz': config.fuzz, + 'size': sizes[size] + }; + compareQueue.push(item); + compareList.push(item); + } + } + + compareQueue.drain = function () { + console.log('Image comparison done'); + gallery.generate(dirs, compareList, outputFolder, config.project, cb); + }; + }; + }; + }); + } else { + console.log('No url(s) provided'); + return false; + } } diff --git a/package.json b/package.json index 4ddb29c..e28ea45 100644 --- a/package.json +++ b/package.json @@ -1,68 +1,68 @@ { - "name": "wraith", - "version": "1.0.1", - "description": "A responsive screenshot comparison tool. Based on the Ruby version available at http://github.comm/BBC-News/wraith", - "license": "MIT", - "repository": { - "type": "git", - "url": "git://github.com/thebyrd/node-wraith" - }, - "bin": { - "wraith": "cli.js" - }, - "author": { - "name": "James Bell", - "email": "james@james-bell.co.uk", - "url": "http://james-bell.co.uk" - }, - "engines": { - "node": ">=0.10.0" - }, - "scripts": {}, - "files": [ - "index.js", - "cli.js", - "lib/*", - "gallery.html", - "snap.js" - ], - "keywords": [ - "page", - "website", - "site", - "web", - "url", - "resolution", - "size", - "screenshot", - "screen", - "responsive", - "cli", - "wraith", - "phantomjs", - "triflejs", - "slimerjs" - ], - "dependencies": { - "chalk": "~0.4.0", - "nopt": "~2.1.2", - "crawl": "~0.3.1", - "async": "~0.2.10", - "mkdirp": "~0.3.5", - "mustache": "~0.8.1", - "rimraf": "~2.2.6" - }, - "devDependencies": {}, - "readme": "# Wraith\nA responsive screenshot comparison tool.\nBased on the Ruby version available at [http://github.com/BBC-News/wraith](http://github.com/BBC-News/wraith)\n\n## CLI app\n\n### Install\n\n```\n\tnpm install --global wraith\n```\n\n###Usage\n\n\tUsage:\n\twraith --config \n\n\tOptions:\n\t-h, --help\t\tOutput help information\n\t--v, --version\tOutput version information\n\n\tExamples:\n\twraith --config ./config/chrome.json\n\n### Configuration file\n\nWraith uses a json based configuration file that allows you specify a large number of options. You can create as many configurations files as you need and call them from the cli using the --config flag. These configuration files can live anywhere that is addressable by a local path and they are passed as an argument like this:\n\n wraith --config ./path/to/my_config.json\n\nBelow is an example configuration file:\n\n\t{\n\t\t\"project\": \"Test\", (Optional name for the project, if supplied it will be used within the generated gallery only)\n\n\t\tSpecify one or two domains\n\t\t\"domains\": {\n\t\t\t\"bbb.co.uk\": \"http://www.bbc.co.uk\",\n\t\t\t\"live.bbc.co.uk\": \"http://live.bbc.co.uk\"\n\t\t},\n\n\t\tEngines supported are phantomjs, slimerjs and triflejs but in theory any phantomjs based headless browser can be supported via a custom snap.js file\n\t\t\"engines\" : [\n\t\t\t\"phantomjs\"\n\t\t],\n\n\t\tSpecify as many sizes as you wish\n\t\t\"sizes\": [\n\t\t\t\"320\",\n\t\t\t\"768\",\n\t\t\t\"1440\"\n\t\t],\n\n\t\t\"outputDir\": \"test/chrome/\", (defaults to \"shots\")\n\n\t\tYou can choose to specfiy a list of paths to be used or you can crawl the site. If paths are provided they will take precident and the spider file will be ignored.\n\n\t\t\"paths\": [\n\t\t\t\"/\",\n\t\t\t\"/news/\",\n\t\t\t\"/news/local/\",\n\t\t\t\"/news/england/york_and_north_yorkshire/\",\n\t\t\t\"/weather/\"\n\t\t],\n\n\t\tIf no paths are specified then a site crawl will take place and the results will be save in the location specified within this option\n\t\t\"spider\": \"spider/test.txt\", (Specify which file should be used for the spider txt file)\n\n\t\t\"snap\": \"snap/test/chrome.js\", (Specify snap.js which is used to take the screenshots)\n\t\t\"fuzz\": \"20%\", (Adjusts the sensitivity of the image comparison)\n\t\t\"maxConnections\": 20 (Limit the amount of concurrent processes)\n\t}\n\n## External Dependencies\nWraith requires [phantomjs](http://phantomjs.org/) & [imagemagick](http://www.imagemagick.org/) to be installed. On OS X this can easily be done with `npm install phantomjs` and `brew install imagemagick`.\n\n## License\n\nMIT © [James Bell](http://james-bell.co.uk)\n", - "readmeFilename": "readme.md", - "bugs": { - "url": "https://github.com/thebyrd/node-wraith/issues" - }, - "homepage": "https://github.com/thebyrd/node-wraith", - "_id": "wraith@1.0.1", - "dist": { - "shasum": "6fe7dcbc35f8d4e3d5df72d796dd500ae8a84591" - }, - "_resolved": "git+https://github.com/thebyrd/node-wraith.git#96e70c3c85256859c240b99ffa648ddfec8870c1", - "_from": "wraith@git+https://github.com/thebyrd/node-wraith.git#master" + "name": "wraith", + "version": "1.0.2", + "description": "A responsive screenshot comparison tool. Based on the Ruby version available at http://github.comm/BBC-News/wraith", + "license": "MIT", + "repository": { + "type": "git", + "url": "git://github.com/rcline/node-wraith" + }, + "bin": { + "wraith": "cli.js" + }, + "author": { + "name": "James Bell", + "email": "james@james-bell.co.uk", + "url": "http://james-bell.co.uk" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": {}, + "files": [ + "index.js", + "cli.js", + "lib/*", + "gallery.html", + "snap.js" + ], + "keywords": [ + "page", + "website", + "site", + "web", + "url", + "resolution", + "size", + "screenshot", + "screen", + "responsive", + "cli", + "wraith", + "phantomjs", + "triflejs", + "slimerjs" + ], + "dependencies": { + "chalk": "~0.4.0", + "nopt": "~2.1.2", + "crawl": "~0.3.1", + "async": "~0.2.10", + "mkdirp": "~0.3.5", + "mustache": "~0.8.1", + "rimraf": "~2.2.6" + }, + "devDependencies": {}, + "readme": "# Wraith\nA responsive screenshot comparison tool.\nBased on the Ruby version available at [http://github.com/BBC-News/wraith](http://github.com/BBC-News/wraith)\n\n## CLI app\n\n### Install\n\n```\n\tnpm install --global wraith\n```\n\n###Usage\n\n\tUsage:\n\twraith --config \n\n\tOptions:\n\t-h, --help\t\tOutput help information\n\t--v, --version\tOutput version information\n\n\tExamples:\n\twraith --config ./config/chrome.json\n\n### Configuration file\n\nWraith uses a json based configuration file that allows you specify a large number of options. You can create as many configurations files as you need and call them from the cli using the --config flag. These configuration files can live anywhere that is addressable by a local path and they are passed as an argument like this:\n\n wraith --config ./path/to/my_config.json\n\nBelow is an example configuration file:\n\n\t{\n\t\t\"project\": \"Test\", (Optional name for the project, if supplied it will be used within the generated gallery only)\n\n\t\tSpecify one or two domains\n\t\t\"domains\": {\n\t\t\t\"bbb.co.uk\": \"http://www.bbc.co.uk\",\n\t\t\t\"live.bbc.co.uk\": \"http://live.bbc.co.uk\"\n\t\t},\n\n\t\tEngines supported are phantomjs, slimerjs and triflejs but in theory any phantomjs based headless browser can be supported via a custom snap.js file\n\t\t\"engines\" : [\n\t\t\t\"phantomjs\"\n\t\t],\n\n\t\tSpecify as many sizes as you wish\n\t\t\"sizes\": [\n\t\t\t\"320\",\n\t\t\t\"768\",\n\t\t\t\"1440\"\n\t\t],\n\n\t\t\"outputDir\": \"test/chrome/\", (defaults to \"shots\")\n\n\t\tYou can choose to specfiy a list of paths to be used or you can crawl the site. If paths are provided they will take precident and the spider file will be ignored.\n\n\t\t\"paths\": [\n\t\t\t\"/\",\n\t\t\t\"/news/\",\n\t\t\t\"/news/local/\",\n\t\t\t\"/news/england/york_and_north_yorkshire/\",\n\t\t\t\"/weather/\"\n\t\t],\n\n\t\tIf no paths are specified then a site crawl will take place and the results will be save in the location specified within this option\n\t\t\"spider\": \"spider/test.txt\", (Specify which file should be used for the spider txt file)\n\n\t\t\"snap\": \"snap/test/chrome.js\", (Specify snap.js which is used to take the screenshots)\n\t\t\"fuzz\": \"20%\", (Adjusts the sensitivity of the image comparison)\n\t\t\"maxConnections\": 20 (Limit the amount of concurrent processes)\n\t}\n\n## External Dependencies\nWraith requires [phantomjs](http://phantomjs.org/) & [imagemagick](http://www.imagemagick.org/) to be installed. On OS X this can easily be done with `npm install phantomjs` and `brew install imagemagick`.\n\n## License\n\nMIT © [James Bell](http://james-bell.co.uk)\n", + "readmeFilename": "readme.md", + "bugs": { + "url": "https://github.com/rcline/node-wraith/issues" + }, + "homepage": "https://github.com/rcline/node-wraith", + "_id": "wraith@1.0.2", + "dist": { + "shasum": "6fe7dcbc35f8d4e3d5df72d796dd500ae8a84591" + }, + "_resolved": "git+https://github.com/rcline/node-wraith.git#96e70c3c85256859c240b99ffa648ddfec8870c1", + "_from": "wraith@git+https://github.com/rcline/node-wraith.git#master" } diff --git a/readme.md b/readme.md index a464712..7098fa2 100644 --- a/readme.md +++ b/readme.md @@ -28,48 +28,7 @@ Wraith uses a json based configuration file that allows you specify a large numb wraith --config ./path/to/my_config.json -Below is an example configuration file: - - { - "project": "Test", (Optional name for the project, if supplied it will be used within the generated gallery only) - - Specify one or two domains - "domains": { - "bbb.co.uk": "http://www.bbc.co.uk", - "live.bbc.co.uk": "http://live.bbc.co.uk" - }, - - Engines supported are phantomjs, slimerjs and triflejs but in theory any phantomjs based headless browser can be supported via a custom snap.js file - "engines" : [ - "phantomjs" - ], - - Specify as many sizes as you wish - "sizes": [ - "320", - "768", - "1440" - ], - - "outputDir": "test/chrome/", (defaults to "shots") - - You can choose to specfiy a list of paths to be used or you can crawl the site. If paths are provided they will take precident and the spider file will be ignored. - - "paths": [ - "/", - "/news/", - "/news/local/", - "/news/england/york_and_north_yorkshire/", - "/weather/" - ], - - If no paths are specified then a site crawl will take place and the results will be save in the location specified within this option - "spider": "spider/test.txt", (Specify which file should be used for the spider txt file) - - "snap": "snap/test/chrome.js", (Specify snap.js which is used to take the screenshots) - "fuzz": "20%", (Adjusts the sensitivity of the image comparison) - "maxConnections": 20 (Limit the amount of concurrent processes) - } +Here is an example configuration file: [config.example.json](https://github.com/rcline/node-wraith/blob/master/config/config.example.json) ## External Dependencies Wraith requires [phantomjs](http://phantomjs.org/) & [imagemagick](http://www.imagemagick.org/) to be installed. On OS X this can easily be done with `npm install phantomjs` and `brew install imagemagick`. diff --git a/snap.js b/snap.js index 65c1992..8be4811 100644 --- a/snap.js +++ b/snap.js @@ -14,8 +14,8 @@ var current_requests = 0; var last_request_timeout; var final_timeout; -page.viewportSize = { width: view_port_width, height: 2000}; -page.settings = { loadImages: true, javascriptEnabled: true }; +page.viewportSize = {width: view_port_width, height: 2000}; +page.settings = {loadImages: true, javascriptEnabled: true}; // If you want to use additional phantomjs commands, place them here //page.settings.userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.17'; @@ -40,55 +40,55 @@ page.settings = { loadImages: true, javascriptEnabled: true }; // 'domain': '.bbc.co.uk' // }); -page.onResourceRequested = function(req) { - current_requests += 1; +page.onResourceRequested = function (req) { + current_requests += 1; }; //TrifleJS only /*page.onLoadFinished = function(status) { - if (status == 'success') { - current_requests -= 1; - debounced_render(); - } -};*/ + if (status == 'success') { + current_requests -= 1; + debounced_render(); + } + };*/ //SlimerJS or PhantomJS -page.onResourceReceived = function(res) { - if (res.stage === 'end') { - current_requests -= 1; - debounced_render(); - } +page.onResourceReceived = function (res) { + if (res.stage === 'end') { + current_requests -= 1; + debounced_render(); + } }; -page.open(url, function(status) { - if (status !== 'success') { - console.log('Error with page ' + url); - phantom.exit(); - } else { - } +page.open(url, function (status) { + if (status !== 'success') { + console.log('Error with page ' + url); + phantom.exit(); + } else { + } }); function debounced_render() { - clearTimeout(last_request_timeout); - clearTimeout(final_timeout); - - // If there's no more ongoing resource requests, wait for 1 second before - // rendering, just in case the page kicks off another request - if (current_requests < 1) { - clearTimeout(final_timeout); - last_request_timeout = setTimeout(function() { - console.log('Snapping ' + url + ' at width ' + view_port_width); - page.render(image_name); - phantom.exit(); - }, 1000); - } - - // Sometimes, straggling requests never make it back, in which - // case, timeout after 5 seconds and render the page anyway - final_timeout = setTimeout(function() { - console.log('Snapping ' + url + ' at width ' + view_port_width); - page.render(image_name); - phantom.exit(); - }, 5000); -} \ No newline at end of file + clearTimeout(last_request_timeout); + clearTimeout(final_timeout); + + // If there's no more ongoing resource requests, wait for 1 second before + // rendering, just in case the page kicks off another request + if (current_requests < 1) { + clearTimeout(final_timeout); + last_request_timeout = setTimeout(function () { + console.log('Snapping ' + url + ' at width ' + view_port_width); + page.render(image_name); + phantom.exit(); + }, 1000); + } + + // Sometimes, straggling requests never make it back, in which + // case, timeout after 5 seconds and render the page anyway + final_timeout = setTimeout(function () { + console.log('Snapping ' + url + ' at width ' + view_port_width); + page.render(image_name); + phantom.exit(); + }, 5000); +}