diff --git a/.travis.yml b/.travis.yml index 8b95a9ff..5dc3337f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ language: node_js +sudo: false node_js: - - "0.10" + - "4" + - "5" after_script: - npm run coveralls diff --git a/lib/api/new.coffee b/lib/api/new.coffee index d5f2d0d6..8e7d75a5 100644 --- a/lib/api/new.coffee +++ b/lib/api/new.coffee @@ -77,10 +77,10 @@ class New W.promise (resolve, reject) -> qs = [] for question in questions - qs.push(question) unless _.contains(skip, question.name) + qs.push(question) unless _.includes(skip, question.name) inquirer.prompt qs, (answers) -> resolve(answers) - W.resolve(_.contains(_.keys(sprout.templates), base_tpl_name)) + W.resolve(_.includes(_.keys(sprout.templates), base_tpl_name)) .then (res) -> if not res sprout.add(base_tpl_name, base_tpl_url) diff --git a/lib/api/template.coffee b/lib/api/template.coffee index 6eaf1c55..45f41439 100644 --- a/lib/api/template.coffee +++ b/lib/api/template.coffee @@ -66,7 +66,7 @@ exports.default = (args = {}) -> if not args.name return W.reject(new Error('please provide a template name')) - if not _.contains(_.keys(sprout.templates), args.name) + if not _.includes(_.keys(sprout.templates), args.name) return W.reject(new Error "you do not have this template installed") config = global_config() diff --git a/lib/api/watch.coffee b/lib/api/watch.coffee index 1183e5ac..8bc93a39 100644 --- a/lib/api/watch.coffee +++ b/lib/api/watch.coffee @@ -1,6 +1,6 @@ -chokidar = require 'chokidar' -minimatch = require 'minimatch' -_ = require 'lodash' +chokidar = require 'chokidar' +mm = require 'micromatch' +_ = require 'lodash' ###* * @class Watcher @@ -42,7 +42,7 @@ class Watcher ignore = (p) -> f = p.replace(@roots.root, '').slice(1) @roots.config.watcher_ignores - .map (i) -> minimatch(f, i, { dot: true }) + .map (i) -> mm.isMatch(f, i, { dot: true }) .filter (i) -> i .length diff --git a/lib/cli/watch.coffee b/lib/cli/watch.coffee index ad4fd348..bc952a03 100644 --- a/lib/cli/watch.coffee +++ b/lib/cli/watch.coffee @@ -1,4 +1,5 @@ open = require 'open' +node = require 'when/node' Roots = require '../../lib' Server = require '../local_server' @@ -24,6 +25,7 @@ module.exports = (cli, args) -> project = new Roots args.path, env: args.env verbose: args.verbose + no_open: args.no_open app = new Server(project) port = process.env.port or args.port @@ -39,12 +41,8 @@ module.exports = (cli, args) -> project.watch() .then (w) -> res.watcher = w - res.server = app.start(port) - if project.config.open_browser and not args.no_open - if project.config.open_browser == true - open("http://localhost:#{port}/") - else - open(project.config.open_browser) + res.server = app + node.call(app.start.bind(app), port) .yield(res) ###* diff --git a/lib/compiler.coffee b/lib/compiler.coffee index 7f655cb1..475218bb 100644 --- a/lib/compiler.coffee +++ b/lib/compiler.coffee @@ -64,7 +64,7 @@ class CompileFile constructor: (@roots, @extensions, @compile_options, @category, @file) -> @adapters = get_adapters.call(@) - @is_compiled = !!_(@adapters).pluck('name').compact().value().length + @is_compiled = !!_(@adapters).map('name').compact().value().length @out_ext = _.last(@adapters).output @file_options = {filename: @file.path, _path: url_path.call(@)} @@ -157,7 +157,7 @@ class CompileFile process_write_hook_results = (results) -> if results.length < 1 then return [write_task.call(@)] - if _.contains(results, false) then return [] + if _.includes(results, false) then return [] write_tasks = [] normal_write_pushed = false @@ -258,7 +258,7 @@ class CompileFile for ext in _.clone(extensions).reverse() compiler = _.find @roots.config.compilers, (c) -> - _.contains(c.extensions, ext) + _.includes(c.extensions, ext) adapters.push(if compiler then compiler else { output: ext }) diff --git a/lib/config.coffee b/lib/config.coffee index fc331326..84913018 100644 --- a/lib/config.coffee +++ b/lib/config.coffee @@ -52,7 +52,7 @@ class Config @verbose = opts.verbose ? false @debug = false @live_reload = true - @open_browser = true + @open_browser = !opts.no_open ? true load_config.call(@) @@ -144,7 +144,7 @@ class Config out: (f, ext) -> res = f.relative.split(path.sep) - if _.contains(@dump_dirs, res[0]) then res.shift() + if _.includes(@dump_dirs, res[0]) then res.shift() res.unshift(@output_path()) res = res.join(path.sep) if ext diff --git a/lib/extensions/compiled.coffee b/lib/extensions/compiled.coffee index efdf5894..dcdd0e9c 100644 --- a/lib/extensions/compiled.coffee +++ b/lib/extensions/compiled.coffee @@ -28,4 +28,4 @@ module.exports = -> detect_fn = (f) -> exts = _(@roots.config.compilers).map((i)->i.extensions).flatten().value() - _.contains(exts, path.extname(f.relative).slice(1)) + _.includes(exts, path.extname(f.relative).slice(1)) diff --git a/lib/fs_parser.coffee b/lib/fs_parser.coffee index b2cb0876..f1511237 100644 --- a/lib/fs_parser.coffee +++ b/lib/fs_parser.coffee @@ -1,11 +1,11 @@ -fs = require 'graceful-fs' -path = require 'path' -W = require 'when' -readdirp = require 'readdirp' -_ = require 'lodash' -minimatch = require 'minimatch' -pipeline = require 'when/pipeline' -File = require 'vinyl' +fs = require 'graceful-fs' +path = require 'path' +W = require 'when' +readdirp = require 'readdirp' +_ = require 'lodash' +mm = require 'micromatch' +pipeline = require 'when/pipeline' +File = require 'vinyl' ###* * @class FS Parser @@ -150,7 +150,7 @@ class FSParser if not detected then return false cat = extfs.category ? ext.category @ast[cat] ?= [] - @ast[cat].push(file) unless _.contains(@ast[cat], file) + @ast[cat].push(file) unless _.includes(@ast[cat], file) return extfs.extract ###* @@ -175,8 +175,8 @@ class FSParser ignored = (f) -> @config.ignores - .map (i) -> minimatch(f, i, dot: true) - .filter (i) -> i + .map((i) -> mm.isMatch(f, i, dot: true)) + .filter((i) -> i) .length module.exports = FSParser diff --git a/lib/local_server.coffee b/lib/local_server.coffee index 94230f40..b4459c00 100644 --- a/lib/local_server.coffee +++ b/lib/local_server.coffee @@ -1,6 +1,8 @@ path = require 'path' serve_static = require 'serve-static' charge = require 'charge' +browsersync = require 'browser-sync' +_ = require 'lodash' ###* * @class Server @@ -17,6 +19,7 @@ class Server ### constructor: (@project) -> + @bs = browsersync.create() ###* * Start the local server on the given port. @@ -26,52 +29,70 @@ class Server ### start: (port, cb) -> - opts = @project.config.server ? {} - opts.log = false - - if @project.config.env is 'development' - opts.write = content: - " - - " - opts.cache_control = {'**': 'max-age=0, no-cache, no-store'} - - app = charge(@project.config.output_path(), opts) - - if @project.config.env is 'development' - app.stack.splice app.stack.length - 2, 0, - route: '/__roots__' - handle: serve_static(path.resolve(__dirname, 'browser')) - - @server = app.start(port, cb) + bs_options = + port: port + logLevel: 'silent' + open: @project.config.open_browser + server: + baseDir: @project.config.output_path() + + if @project.config.browser then _.merge(bs_options, @project.config.browser) + + # add charge middleware after merge to prevent errors + opts = @project.config.server or {} + middlewares = [] + + if opts.clean_urls + middlewares.push(charge.hygienist(@project.config.output_path())) + if opts.exclude + middlewares.push(charge.escapist(opts.exclude)) + if opts.auth + middlewares.push(charge.publicist(opts.auth)) + if opts.cache_control + middlewares.push(charge.archivist(opts.cache_control)) + if opts.gzip + middlewares.push(charge.minimist(opts.gzip)) + if opts.log + middlewares.push(charge.journalist(opts.log)) + if opts.error_page + middlewares.push(charge.apologist(opts.error_page)) + + bs_options.server.middleware = middlewares + + @bs.init(bs_options, cb) ###* * Close the server and remove it. ### stop: (cb) -> - @server.close(cb) - delete @server + @bs.exit() + cb() ###* - * Send a message through websockets to the browser. - * - * @param {String} k - message key - * @param {*} v - message value + * Reload the browser ### - send_msg: (k, v) -> - @server.send(type: k, data: v) + reload: -> + @bs.reload() + + ###* + * Inject loading spinner while compiling + ### + compiling: -> + @bs.notify('compiling...') ###* - * These three methods send 'reload', 'compiling', and 'error' messages - * through to the browser. + * Sanitize error message and inject into page + * @param {Error} err - an error object ### - reload: -> @send_msg('reload') - compiling: -> @send_msg('compiling') show_error: (err) -> err = err.toString() if err instanceof Error - @send_msg('error', err) + cleanError = if err.replace + err.replace(/(\r\n|\n|\r)/gm, '
') + else + "compile error!" + @bs.notify(cleanError, 100000) module.exports = Server diff --git a/package.json b/package.json index 1c640805..b2f95c2b 100644 --- a/package.json +++ b/package.json @@ -10,29 +10,30 @@ "Sam Saccone " ], "dependencies": { - "accord": "0.20.x", + "accord": "0.21.x", "argparse": "1.x", - "charge": "0.0.4", - "chokidar": "1.0.x", - "coffee-script": "1.9.x", + "browser-sync": "2.x", + "charge": "0.1.x", + "chokidar": "1.x", + "coffee-script": "1.10.x", "colors": "1.x", "configstore": "0.3.x", "graceful-fs": "4.x", - "inquirer": "0.9.x", + "inquirer": "0.11.x", "keen.io": "0.1.x", - "lodash": "3.x", - "minimatch": "2.x", + "lodash": "4.x", + "micromatch": "2.x", "mkdirp": "0.5.x", - "npm": "2.x", + "npm": "3.x", "open": "0.0.5", "osenv": "0.1.x", - "readdirp": "1.x", + "readdirp": "2.x", "rimraf": "2.x", "serve-static": "1.x", "ship": "0.2.x", "sprout": "0.4.x", - "update-notifier": "0.5.x", - "vinyl": "0.5.x", + "update-notifier": "0.6.x", + "vinyl": "1.x", "when": "3.x" }, "devDependencies": { @@ -46,7 +47,6 @@ "mocha": "2.x", "mocha-lcov-reporter": "0.0.2", "mockery": "1.x", - "phantomjs": "1.x", "roots-util": "0.1.x", "selenium-webdriver": "2.x", "sinon": "1.x", diff --git a/test/cli.coffee b/test/cli.coffee index 11c33d2c..86154afe 100644 --- a/test/cli.coffee +++ b/test/cli.coffee @@ -184,7 +184,7 @@ describe 'cli', -> cli.removeListener('inline', spy) cli.removeListener('data', spy) cli.removeListener('err', spy) - obj.server.close(done) + obj.server.stop(done) it 'should error when trying to compile invalid code' diff --git a/test/new.coffee b/test/new.coffee index a12f996d..cbd22cfe 100644 --- a/test/new.coffee +++ b/test/new.coffee @@ -7,7 +7,7 @@ new_path = path.join(base_path, 'new/testing') before -> @starting_templates = Roots.template.list() - if _.contains(@starting_templates, 'roots-base') + if _.includes(@starting_templates, 'roots-base') # remove roots-base to verify 'base template added' # functionality in lib/api/new.coffee Roots.template.remove(name: 'roots-base')