diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..6a214ee --- /dev/null +++ b/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "usage" + } + ] + ] +} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..8f952e8 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "standard", + "rules": { + "semi": ["error", "always"] + } +} diff --git a/.gitignore b/.gitignore index fb98761..facf85e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ .DS_Store -lib/*.js -lib/*/*.js node_modules/ *.tgz npm-debug.log diff --git a/.npmignore b/.npmignore index 4f0af4f..d5ec1fc 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,3 @@ -/lib-cov/ /src/ /test/ /bower.json -/Rakefile -/Gruntfile.js diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 14a632d..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,47 +0,0 @@ -module.exports = function(grunt) { - - grunt.initConfig({ - coffee: { - src: { - expand: true, - cwd: 'src', - src: '*.coffee', - dest: 'lib', - ext: '.js' - } - }, - - browserify: { - dist: { - options: { - transform: ['envify'] - }, - src: ['lib/startup.js'], - dest: 'dist/livereload.js' - }, - - test: { - src: ['test/html/browserified/main.js'], - dest: 'test/html/browserified/bundle.js' - } - }, - - mochaTest: { - test: { - options: { - reporter: 'spec' - }, - src: ['test/*.js'] - } - } - }); - - grunt.loadNpmTasks('grunt-contrib-coffee'); - grunt.loadNpmTasks('grunt-browserify'); - grunt.loadNpmTasks('grunt-mocha-test'); - - grunt.registerTask('build', ['coffee', 'browserify:dist']); - grunt.registerTask('test', ['mochaTest']); - grunt.registerTask('default', ['build', 'test']); - -}; diff --git a/README.md b/README.md index ff9865b..36fb6e4 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,6 @@ Hacking on LiveReload.js Requirements: * Node.js with npm -* Grunt (`npm install grunt-cli`) To install additional prerequisites: @@ -195,31 +194,27 @@ To install additional prerequisites: To build: - grunt build + npm run build To run tests: - grunt + npm test Manual testing: open files in `test/html/*` in various browsers, make some changes and make sure they are applied. -Testing the Browserify usage scenario: `grunt browserify:test`, then perform manual testing of `test/html/browserified/`. +Testing the Browserify usage scenario: `npm run test-manual`, then perform manual testing of `test/html/browserified/`. Releasing a new version ----------------------- -1. Update the version number in `package.json`. - -1. Run `rake version` to update the version numbers in all other files, using the one from `package.json`. - -1. Run `grunt`. +1. Run `npm version` with the applicable identifier (`major`/`minor`/`patch`/...). 1. Do some manual testing. -1. Tag the version in Git: `rake tag` then `git push --tags`. +1. Create a release on GitHub. -1. `npm publish` +1. Run `npm publish`. License diff --git a/Rakefile b/Rakefile deleted file mode 100644 index db3fe86..0000000 --- a/Rakefile +++ /dev/null @@ -1,51 +0,0 @@ -VERSION_FILES = %w( - src/connector.coffee - bower.json -) - -def version - content = File.read('package.json') - if content =~ /"version": "(\d+\.\d+\.\d+)"/ - return $1 - else - raise "Failed to get version info from package.json" - end -end - -def subst_version_refs_in_file file, ver - puts file - orig = File.read(file) - prev_line = "" - anything_matched = false - data = orig.lines.map do |line| - if line =~ /\d\.\d\.\d/ && (line =~ /version/i || prev_line =~ /CFBundleShortVersionString|CFBundleVersion/) - anything_matched = true - new_line = line.gsub /\d\.\d\.\d/, ver - puts " #{new_line.strip}" - else - new_line = line - end - prev_line = line - new_line - end.join('') - - raise "Error: no substitutions made in #{file}" unless anything_matched - - File.open(file, 'w') { |f| f.write data } -end - -desc "Embed version number where it belongs" -task :version do - ver = version - VERSION_FILES.each { |file| subst_version_refs_in_file(file, ver) } - sh 'grunt' -end - -desc "Tag the current version" -task :tag do - sh 'git', 'tag', "v#{version}" -end -desc "Move (git tag -f) the tag for the current version" -task :retag do - sh 'git', 'tag', '-f', "v#{version}" -end diff --git a/bower.json b/bower.json index 5210f3d..792831c 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "livereload-js", - "version": "2.2.2", + "version": "2.4.0", "main": "dist/livereload.js", "homepage": "http://livereload.com", "authors": [ @@ -14,9 +14,6 @@ ], "license": "MIT", "ignore": [ - "Rakefile", - "lib", - "lib-cov", "src", "test", "**/.*", diff --git a/dist/livereload.js b/dist/livereload.js index 3c24b5d..419de25 100644 --- a/dist/livereload.js +++ b/dist/livereload.js @@ -1,1204 +1,1951 @@ (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i Array#indexOf +// true -> Array#includes +var toIObject = require('./_to-iobject'); +var toLength = require('./_to-length'); +var toAbsoluteIndex = require('./_to-absolute-index'); +module.exports = function (IS_INCLUDES) { + return function ($this, el, fromIndex) { + var O = toIObject($this); + var length = toLength(O.length); + var index = toAbsoluteIndex(fromIndex, length); + var value; + // Array#includes uses SameValueZero equality algorithm + // eslint-disable-next-line no-self-compare + if (IS_INCLUDES && el != el) while (length > index) { + value = O[index++]; + // eslint-disable-next-line no-self-compare + if (value != value) return true; + // Array#indexOf ignores holes, Array#includes - not + } else for (;length > index; index++) if (IS_INCLUDES || index in O) { + if (O[index] === el) return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; +}; - Connector.prototype._isSocketConnected = function() { - return this.socket && this.socket.readyState === this.WebSocket.OPEN; - }; +},{"./_to-absolute-index":37,"./_to-iobject":39,"./_to-length":40}],5:[function(require,module,exports){ +var toString = {}.toString; - Connector.prototype.connect = function() { - this._connectionDesired = true; - if (this._isSocketConnected()) { - return; - } - this._reconnectTimer.stop(); - this._disconnectionReason = 'cannot-connect'; - this.protocolParser.reset(); - this.handlers.connecting(); - this.socket = new this.WebSocket(this._uri); - this.socket.onopen = (function(_this) { - return function(e) { - return _this._onopen(e); - }; - })(this); - this.socket.onclose = (function(_this) { - return function(e) { - return _this._onclose(e); - }; - })(this); - this.socket.onmessage = (function(_this) { - return function(e) { - return _this._onmessage(e); - }; - })(this); - return this.socket.onerror = (function(_this) { - return function(e) { - return _this._onerror(e); - }; - })(this); - }; +module.exports = function (it) { + return toString.call(it).slice(8, -1); +}; + +},{}],6:[function(require,module,exports){ +var core = module.exports = { version: '2.6.0' }; +if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef - Connector.prototype.disconnect = function() { - this._connectionDesired = false; - this._reconnectTimer.stop(); +},{}],7:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function (fn, that, length) { + aFunction(fn); + if (that === undefined) return fn; + switch (length) { + case 1: return function (a) { + return fn.call(that, a); + }; + case 2: return function (a, b) { + return fn.call(that, a, b); + }; + case 3: return function (a, b, c) { + return fn.call(that, a, b, c); + }; + } + return function (/* ...args */) { + return fn.apply(that, arguments); + }; +}; + +},{"./_a-function":1}],8:[function(require,module,exports){ +// 7.2.1 RequireObjectCoercible(argument) +module.exports = function (it) { + if (it == undefined) throw TypeError("Can't call method on " + it); + return it; +}; + +},{}],9:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function () { + return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; +}); + +},{"./_fails":13}],10:[function(require,module,exports){ +var isObject = require('./_is-object'); +var document = require('./_global').document; +// typeof document.createElement is 'object' in old IE +var is = isObject(document) && isObject(document.createElement); +module.exports = function (it) { + return is ? document.createElement(it) : {}; +}; + +},{"./_global":14,"./_is-object":20}],11:[function(require,module,exports){ +// IE 8- don't enum bug keys +module.exports = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' +).split(','); + +},{}],12:[function(require,module,exports){ +var global = require('./_global'); +var core = require('./_core'); +var hide = require('./_hide'); +var redefine = require('./_redefine'); +var ctx = require('./_ctx'); +var PROTOTYPE = 'prototype'; + +var $export = function (type, name, source) { + var IS_FORCED = type & $export.F; + var IS_GLOBAL = type & $export.G; + var IS_STATIC = type & $export.S; + var IS_PROTO = type & $export.P; + var IS_BIND = type & $export.B; + var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE]; + var exports = IS_GLOBAL ? core : core[name] || (core[name] = {}); + var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {}); + var key, own, out, exp; + if (IS_GLOBAL) source = name; + for (key in source) { + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + // export native or passed + out = (own ? target : source)[key]; + // bind timers to global for call from export context + exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // extend global + if (target) redefine(target, key, out, type & $export.U); + // export + if (exports[key] != out) hide(exports, key, exp); + if (IS_PROTO && expProto[key] != out) expProto[key] = out; + } +}; +global.core = core; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; + +},{"./_core":6,"./_ctx":7,"./_global":14,"./_hide":16,"./_redefine":33}],13:[function(require,module,exports){ +module.exports = function (exec) { + try { + return !!exec(); + } catch (e) { + return true; + } +}; + +},{}],14:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self + // eslint-disable-next-line no-new-func + : Function('return this')(); +if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef + +},{}],15:[function(require,module,exports){ +var hasOwnProperty = {}.hasOwnProperty; +module.exports = function (it, key) { + return hasOwnProperty.call(it, key); +}; + +},{}],16:[function(require,module,exports){ +var dP = require('./_object-dp'); +var createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function (object, key, value) { + return dP.f(object, key, createDesc(1, value)); +} : function (object, key, value) { + object[key] = value; + return object; +}; + +},{"./_descriptors":9,"./_object-dp":27,"./_property-desc":32}],17:[function(require,module,exports){ +var document = require('./_global').document; +module.exports = document && document.documentElement; + +},{"./_global":14}],18:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function () { + return Object.defineProperty(require('./_dom-create')('div'), 'a', { get: function () { return 7; } }).a != 7; +}); + +},{"./_descriptors":9,"./_dom-create":10,"./_fails":13}],19:[function(require,module,exports){ +// fallback for non-array-like ES3 and non-enumerable old V8 strings +var cof = require('./_cof'); +// eslint-disable-next-line no-prototype-builtins +module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) { + return cof(it) == 'String' ? it.split('') : Object(it); +}; + +},{"./_cof":5}],20:[function(require,module,exports){ +module.exports = function (it) { + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; + +},{}],21:[function(require,module,exports){ +'use strict'; +var create = require('./_object-create'); +var descriptor = require('./_property-desc'); +var setToStringTag = require('./_set-to-string-tag'); +var IteratorPrototype = {}; + +// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() +require('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function () { return this; }); + +module.exports = function (Constructor, NAME, next) { + Constructor.prototype = create(IteratorPrototype, { next: descriptor(1, next) }); + setToStringTag(Constructor, NAME + ' Iterator'); +}; + +},{"./_hide":16,"./_object-create":26,"./_property-desc":32,"./_set-to-string-tag":34,"./_wks":44}],22:[function(require,module,exports){ +'use strict'; +var LIBRARY = require('./_library'); +var $export = require('./_export'); +var redefine = require('./_redefine'); +var hide = require('./_hide'); +var Iterators = require('./_iterators'); +var $iterCreate = require('./_iter-create'); +var setToStringTag = require('./_set-to-string-tag'); +var getPrototypeOf = require('./_object-gpo'); +var ITERATOR = require('./_wks')('iterator'); +var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next` +var FF_ITERATOR = '@@iterator'; +var KEYS = 'keys'; +var VALUES = 'values'; + +var returnThis = function () { return this; }; + +module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) { + $iterCreate(Constructor, NAME, next); + var getMethod = function (kind) { + if (!BUGGY && kind in proto) return proto[kind]; + switch (kind) { + case KEYS: return function keys() { return new Constructor(this, kind); }; + case VALUES: return function values() { return new Constructor(this, kind); }; + } return function entries() { return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator'; + var DEF_VALUES = DEFAULT == VALUES; + var VALUES_BUG = false; + var proto = Base.prototype; + var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT]; + var $default = $native || getMethod(DEFAULT); + var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined; + var $anyNative = NAME == 'Array' ? proto.entries || $native : $native; + var methods, key, IteratorPrototype; + // Fix native + if ($anyNative) { + IteratorPrototype = getPrototypeOf($anyNative.call(new Base())); + if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) { + // Set @@toStringTag to native iterators + setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if (DEF_VALUES && $native && $native.name !== VALUES) { + VALUES_BUG = true; + $default = function values() { return $native.call(this); }; + } + // Define iterator + if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) { + hide(proto, ITERATOR, $default); + } + // Plug for library + Iterators[NAME] = $default; + Iterators[TAG] = returnThis; + if (DEFAULT) { + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if (FORCED) for (key in methods) { + if (!(key in proto)) redefine(proto, key, methods[key]); + } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; +}; + +},{"./_export":12,"./_hide":16,"./_iter-create":21,"./_iterators":24,"./_library":25,"./_object-gpo":29,"./_redefine":33,"./_set-to-string-tag":34,"./_wks":44}],23:[function(require,module,exports){ +module.exports = function (done, value) { + return { value: value, done: !!done }; +}; + +},{}],24:[function(require,module,exports){ +module.exports = {}; + +},{}],25:[function(require,module,exports){ +module.exports = false; + +},{}],26:[function(require,module,exports){ +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +var anObject = require('./_an-object'); +var dPs = require('./_object-dps'); +var enumBugKeys = require('./_enum-bug-keys'); +var IE_PROTO = require('./_shared-key')('IE_PROTO'); +var Empty = function () { /* empty */ }; +var PROTOTYPE = 'prototype'; + +// Create object with fake `null` prototype: use iframe Object with cleared prototype +var createDict = function () { + // Thrash, waste and sodomy: IE GC bug + var iframe = require('./_dom-create')('iframe'); + var i = enumBugKeys.length; + var lt = '<'; + var gt = '>'; + var iframeDocument; + iframe.style.display = 'none'; + require('./_html').appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt); + iframeDocument.close(); + createDict = iframeDocument.F; + while (i--) delete createDict[PROTOTYPE][enumBugKeys[i]]; + return createDict(); +}; + +module.exports = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + Empty[PROTOTYPE] = anObject(O); + result = new Empty(); + Empty[PROTOTYPE] = null; + // add "__proto__" for Object.getPrototypeOf polyfill + result[IE_PROTO] = O; + } else result = createDict(); + return Properties === undefined ? result : dPs(result, Properties); +}; + +},{"./_an-object":3,"./_dom-create":10,"./_enum-bug-keys":11,"./_html":17,"./_object-dps":28,"./_shared-key":35}],27:[function(require,module,exports){ +var anObject = require('./_an-object'); +var IE8_DOM_DEFINE = require('./_ie8-dom-define'); +var toPrimitive = require('./_to-primitive'); +var dP = Object.defineProperty; + +exports.f = require('./_descriptors') ? Object.defineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPrimitive(P, true); + anObject(Attributes); + if (IE8_DOM_DEFINE) try { + return dP(O, P, Attributes); + } catch (e) { /* empty */ } + if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); + if ('value' in Attributes) O[P] = Attributes.value; + return O; +}; + +},{"./_an-object":3,"./_descriptors":9,"./_ie8-dom-define":18,"./_to-primitive":42}],28:[function(require,module,exports){ +var dP = require('./_object-dp'); +var anObject = require('./_an-object'); +var getKeys = require('./_object-keys'); + +module.exports = require('./_descriptors') ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var keys = getKeys(Properties); + var length = keys.length; + var i = 0; + var P; + while (length > i) dP.f(O, P = keys[i++], Properties[P]); + return O; +}; + +},{"./_an-object":3,"./_descriptors":9,"./_object-dp":27,"./_object-keys":31}],29:[function(require,module,exports){ +// 19.1.2.9 / 15.2.3.2 Object.getPrototypeOf(O) +var has = require('./_has'); +var toObject = require('./_to-object'); +var IE_PROTO = require('./_shared-key')('IE_PROTO'); +var ObjectProto = Object.prototype; + +module.exports = Object.getPrototypeOf || function (O) { + O = toObject(O); + if (has(O, IE_PROTO)) return O[IE_PROTO]; + if (typeof O.constructor == 'function' && O instanceof O.constructor) { + return O.constructor.prototype; + } return O instanceof Object ? ObjectProto : null; +}; + +},{"./_has":15,"./_shared-key":35,"./_to-object":41}],30:[function(require,module,exports){ +var has = require('./_has'); +var toIObject = require('./_to-iobject'); +var arrayIndexOf = require('./_array-includes')(false); +var IE_PROTO = require('./_shared-key')('IE_PROTO'); + +module.exports = function (object, names) { + var O = toIObject(object); + var i = 0; + var result = []; + var key; + for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key); + // Don't enum bug & hidden keys + while (names.length > i) if (has(O, key = names[i++])) { + ~arrayIndexOf(result, key) || result.push(key); + } + return result; +}; + +},{"./_array-includes":4,"./_has":15,"./_shared-key":35,"./_to-iobject":39}],31:[function(require,module,exports){ +// 19.1.2.14 / 15.2.3.14 Object.keys(O) +var $keys = require('./_object-keys-internal'); +var enumBugKeys = require('./_enum-bug-keys'); + +module.exports = Object.keys || function keys(O) { + return $keys(O, enumBugKeys); +}; + +},{"./_enum-bug-keys":11,"./_object-keys-internal":30}],32:[function(require,module,exports){ +module.exports = function (bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value: value + }; +}; + +},{}],33:[function(require,module,exports){ +var global = require('./_global'); +var hide = require('./_hide'); +var has = require('./_has'); +var SRC = require('./_uid')('src'); +var TO_STRING = 'toString'; +var $toString = Function[TO_STRING]; +var TPL = ('' + $toString).split(TO_STRING); + +require('./_core').inspectSource = function (it) { + return $toString.call(it); +}; + +(module.exports = function (O, key, val, safe) { + var isFunction = typeof val == 'function'; + if (isFunction) has(val, 'name') || hide(val, 'name', key); + if (O[key] === val) return; + if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key))); + if (O === global) { + O[key] = val; + } else if (!safe) { + delete O[key]; + hide(O, key, val); + } else if (O[key]) { + O[key] = val; + } else { + hide(O, key, val); + } +// add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative +})(Function.prototype, TO_STRING, function toString() { + return typeof this == 'function' && this[SRC] || $toString.call(this); +}); + +},{"./_core":6,"./_global":14,"./_has":15,"./_hide":16,"./_uid":43}],34:[function(require,module,exports){ +var def = require('./_object-dp').f; +var has = require('./_has'); +var TAG = require('./_wks')('toStringTag'); + +module.exports = function (it, tag, stat) { + if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, { configurable: true, value: tag }); +}; + +},{"./_has":15,"./_object-dp":27,"./_wks":44}],35:[function(require,module,exports){ +var shared = require('./_shared')('keys'); +var uid = require('./_uid'); +module.exports = function (key) { + return shared[key] || (shared[key] = uid(key)); +}; + +},{"./_shared":36,"./_uid":43}],36:[function(require,module,exports){ +var core = require('./_core'); +var global = require('./_global'); +var SHARED = '__core-js_shared__'; +var store = global[SHARED] || (global[SHARED] = {}); + +(module.exports = function (key, value) { + return store[key] || (store[key] = value !== undefined ? value : {}); +})('versions', []).push({ + version: core.version, + mode: require('./_library') ? 'pure' : 'global', + copyright: '© 2018 Denis Pushkarev (zloirock.ru)' +}); + +},{"./_core":6,"./_global":14,"./_library":25}],37:[function(require,module,exports){ +var toInteger = require('./_to-integer'); +var max = Math.max; +var min = Math.min; +module.exports = function (index, length) { + index = toInteger(index); + return index < 0 ? max(index + length, 0) : min(index, length); +}; + +},{"./_to-integer":38}],38:[function(require,module,exports){ +// 7.1.4 ToInteger +var ceil = Math.ceil; +var floor = Math.floor; +module.exports = function (it) { + return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); +}; + +},{}],39:[function(require,module,exports){ +// to indexed object, toObject with fallback for non-array-like ES3 strings +var IObject = require('./_iobject'); +var defined = require('./_defined'); +module.exports = function (it) { + return IObject(defined(it)); +}; + +},{"./_defined":8,"./_iobject":19}],40:[function(require,module,exports){ +// 7.1.15 ToLength +var toInteger = require('./_to-integer'); +var min = Math.min; +module.exports = function (it) { + return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 +}; + +},{"./_to-integer":38}],41:[function(require,module,exports){ +// 7.1.13 ToObject(argument) +var defined = require('./_defined'); +module.exports = function (it) { + return Object(defined(it)); +}; + +},{"./_defined":8}],42:[function(require,module,exports){ +// 7.1.1 ToPrimitive(input [, PreferredType]) +var isObject = require('./_is-object'); +// instead of the ES6 spec version, we didn't implement @@toPrimitive case +// and the second argument - flag - preferred type is a string +module.exports = function (it, S) { + if (!isObject(it)) return it; + var fn, val; + if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; + if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val; + if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; + throw TypeError("Can't convert object to primitive value"); +}; + +},{"./_is-object":20}],43:[function(require,module,exports){ +var id = 0; +var px = Math.random(); +module.exports = function (key) { + return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); +}; + +},{}],44:[function(require,module,exports){ +var store = require('./_shared')('wks'); +var uid = require('./_uid'); +var Symbol = require('./_global').Symbol; +var USE_SYMBOL = typeof Symbol == 'function'; + +var $exports = module.exports = function (name) { + return store[name] || (store[name] = + USE_SYMBOL && Symbol[name] || (USE_SYMBOL ? Symbol : uid)('Symbol.' + name)); +}; + +$exports.store = store; + +},{"./_global":14,"./_shared":36,"./_uid":43}],45:[function(require,module,exports){ +'use strict'; +var addToUnscopables = require('./_add-to-unscopables'); +var step = require('./_iter-step'); +var Iterators = require('./_iterators'); +var toIObject = require('./_to-iobject'); + +// 22.1.3.4 Array.prototype.entries() +// 22.1.3.13 Array.prototype.keys() +// 22.1.3.29 Array.prototype.values() +// 22.1.3.30 Array.prototype[@@iterator]() +module.exports = require('./_iter-define')(Array, 'Array', function (iterated, kind) { + this._t = toIObject(iterated); // target + this._i = 0; // next index + this._k = kind; // kind +// 22.1.5.2.1 %ArrayIteratorPrototype%.next() +}, function () { + var O = this._t; + var kind = this._k; + var index = this._i++; + if (!O || index >= O.length) { + this._t = undefined; + return step(1); + } + if (kind == 'keys') return step(0, index); + if (kind == 'values') return step(0, O[index]); + return step(0, [index, O[index]]); +}, 'values'); + +// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) +Iterators.Arguments = Iterators.Array; + +addToUnscopables('keys'); +addToUnscopables('values'); +addToUnscopables('entries'); + +},{"./_add-to-unscopables":2,"./_iter-define":22,"./_iter-step":23,"./_iterators":24,"./_to-iobject":39}],46:[function(require,module,exports){ +var $iterators = require('./es6.array.iterator'); +var getKeys = require('./_object-keys'); +var redefine = require('./_redefine'); +var global = require('./_global'); +var hide = require('./_hide'); +var Iterators = require('./_iterators'); +var wks = require('./_wks'); +var ITERATOR = wks('iterator'); +var TO_STRING_TAG = wks('toStringTag'); +var ArrayValues = Iterators.Array; + +var DOMIterables = { + CSSRuleList: true, // TODO: Not spec compliant, should be false. + CSSStyleDeclaration: false, + CSSValueList: false, + ClientRectList: false, + DOMRectList: false, + DOMStringList: false, + DOMTokenList: true, + DataTransferItemList: false, + FileList: false, + HTMLAllCollection: false, + HTMLCollection: false, + HTMLFormElement: false, + HTMLSelectElement: false, + MediaList: true, // TODO: Not spec compliant, should be false. + MimeTypeArray: false, + NamedNodeMap: false, + NodeList: true, + PaintRequestList: false, + Plugin: false, + PluginArray: false, + SVGLengthList: false, + SVGNumberList: false, + SVGPathSegList: false, + SVGPointList: false, + SVGStringList: false, + SVGTransformList: false, + SourceBufferList: false, + StyleSheetList: true, // TODO: Not spec compliant, should be false. + TextTrackCueList: false, + TextTrackList: false, + TouchList: false +}; + +for (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) { + var NAME = collections[i]; + var explicit = DOMIterables[NAME]; + var Collection = global[NAME]; + var proto = Collection && Collection.prototype; + var key; + if (proto) { + if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues); + if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME); + Iterators[NAME] = ArrayValues; + if (explicit) for (key in $iterators) if (!proto[key]) redefine(proto, key, $iterators[key], true); + } +} + +},{"./_global":14,"./_hide":16,"./_iterators":24,"./_object-keys":31,"./_redefine":33,"./_wks":44,"./es6.array.iterator":45}],47:[function(require,module,exports){ +"use strict"; + +const { + Parser, + PROTOCOL_6, + PROTOCOL_7 +} = require('./protocol'); + +const VERSION = "2.4.0"; + +class Connector { + constructor(options, WebSocket, Timer, handlers) { + this.options = options; + this.WebSocket = WebSocket; + this.Timer = Timer; + this.handlers = handlers; + const path = this.options.path ? `${this.options.path}` : 'livereload'; + this._uri = `ws${this.options.https ? 's' : ''}://${this.options.host}:${this.options.port}/${path}`; + this._nextDelay = this.options.mindelay; + this._connectionDesired = false; + this.protocol = 0; + this.protocolParser = new Parser({ + connected: protocol => { + this.protocol = protocol; + + this._handshakeTimeout.stop(); + + this._nextDelay = this.options.mindelay; + this._disconnectionReason = 'broken'; + return this.handlers.connected(this.protocol); + }, + error: e => { + this.handlers.error(e); + return this._closeOnError(); + }, + message: message => { + return this.handlers.message(message); + } + }); + this._handshakeTimeout = new this.Timer(() => { if (!this._isSocketConnected()) { return; } - this._disconnectionReason = 'manual'; - return this.socket.close(); - }; - Connector.prototype._scheduleReconnection = function() { + this._disconnectionReason = 'handshake-timeout'; + return this.socket.close(); + }); + this._reconnectTimer = new this.Timer(() => { if (!this._connectionDesired) { return; - } - if (!this._reconnectTimer.running) { - this._reconnectTimer.start(this._nextDelay); - return this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2); - } - }; + } // shouldn't hit this, but just in case - Connector.prototype.sendCommand = function(command) { - if (this.protocol == null) { - return; - } - return this._sendCommand(command); - }; - Connector.prototype._sendCommand = function(command) { - return this.socket.send(JSON.stringify(command)); - }; + return this.connect(); + }); + this.connect(); + } - Connector.prototype._closeOnError = function() { - this._handshakeTimeout.stop(); - this._disconnectionReason = 'error'; - return this.socket.close(); - }; + _isSocketConnected() { + return this.socket && this.socket.readyState === this.WebSocket.OPEN; + } - Connector.prototype._onopen = function(e) { - var hello; - this.handlers.socketConnected(); - this._disconnectionReason = 'handshake-failed'; - hello = { - command: 'hello', - protocols: [PROTOCOL_6, PROTOCOL_7] - }; - hello.ver = Version; - if (this.options.ext) { - hello.ext = this.options.ext; - } - if (this.options.extver) { - hello.extver = this.options.extver; - } - if (this.options.snipver) { - hello.snipver = this.options.snipver; - } - this._sendCommand(hello); - return this._handshakeTimeout.start(this.options.handshake_timeout); - }; + connect() { + this._connectionDesired = true; - Connector.prototype._onclose = function(e) { - this.protocol = 0; - this.handlers.disconnected(this._disconnectionReason, this._nextDelay); - return this._scheduleReconnection(); - }; + if (this._isSocketConnected()) { + return; + } // prepare for a new connection + + + this._reconnectTimer.stop(); + + this._disconnectionReason = 'cannot-connect'; + this.protocolParser.reset(); + this.handlers.connecting(); + this.socket = new this.WebSocket(this._uri); + + this.socket.onopen = e => this._onopen(e); + + this.socket.onclose = e => this._onclose(e); + + this.socket.onmessage = e => this._onmessage(e); + + this.socket.onerror = e => this._onerror(e); + } + + disconnect() { + this._connectionDesired = false; + + this._reconnectTimer.stop(); // in case it was running - Connector.prototype._onerror = function(e) {}; - Connector.prototype._onmessage = function(e) { - return this.protocolParser.process(e.data); + if (!this._isSocketConnected()) { + return; + } + + this._disconnectionReason = 'manual'; + return this.socket.close(); + } + + _scheduleReconnection() { + if (!this._connectionDesired) { + return; + } // don't reconnect after manual disconnection + + + if (!this._reconnectTimer.running) { + this._reconnectTimer.start(this._nextDelay); + + this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2); + } + } + + sendCommand(command) { + if (!this.protocol) { + return; + } + + return this._sendCommand(command); + } + + _sendCommand(command) { + return this.socket.send(JSON.stringify(command)); + } + + _closeOnError() { + this._handshakeTimeout.stop(); + + this._disconnectionReason = 'error'; + return this.socket.close(); + } + + _onopen(e) { + this.handlers.socketConnected(); + this._disconnectionReason = 'handshake-failed'; // start handshake + + const hello = { + command: 'hello', + protocols: [PROTOCOL_6, PROTOCOL_7] }; + hello.ver = VERSION; - return Connector; + if (this.options.ext) { + hello.ext = this.options.ext; + } - })(); + if (this.options.extver) { + hello.extver = this.options.extver; + } -}).call(this); + if (this.options.snipver) { + hello.snipver = this.options.snipver; + } -},{"./protocol":6}],2:[function(require,module,exports){ -(function() { - var CustomEvents; + this._sendCommand(hello); - CustomEvents = { - bind: function(element, eventName, handler) { - if (element.addEventListener) { - return element.addEventListener(eventName, handler, false); - } else if (element.attachEvent) { - element[eventName] = 1; - return element.attachEvent('onpropertychange', function(event) { - if (event.propertyName === eventName) { - return handler(); - } - }); - } else { - throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement"); - } - }, - fire: function(element, eventName) { - var event; - if (element.addEventListener) { - event = document.createEvent('HTMLEvents'); - event.initEvent(eventName, true, true); - return document.dispatchEvent(event); - } else if (element.attachEvent) { - if (element[eventName]) { - return element[eventName]++; + return this._handshakeTimeout.start(this.options.handshake_timeout); + } + + _onclose(e) { + this.protocol = 0; + this.handlers.disconnected(this._disconnectionReason, this._nextDelay); + return this._scheduleReconnection(); + } + + _onerror(e) {} + + _onmessage(e) { + return this.protocolParser.process(e.data); + } + +} + +; +exports.Connector = Connector; + +},{"./protocol":52}],48:[function(require,module,exports){ +"use strict"; + +const CustomEvents = { + bind(element, eventName, handler) { + if (element.addEventListener) { + return element.addEventListener(eventName, handler, false); + } else if (element.attachEvent) { + element[eventName] = 1; + return element.attachEvent('onpropertychange', function (event) { + if (event.propertyName === eventName) { + return handler(); } - } else { - throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement"); + }); + } else { + throw new Error(`Attempt to attach custom event ${eventName} to something which isn't a DOMElement`); + } + }, + + fire(element, eventName) { + if (element.addEventListener) { + const event = document.createEvent('HTMLEvents'); + event.initEvent(eventName, true, true); + return document.dispatchEvent(event); + } else if (element.attachEvent) { + if (element[eventName]) { + return element[eventName]++; } + } else { + throw new Error(`Attempt to fire custom event ${eventName} on something which isn't a DOMElement`); } - }; + } + +}; +exports.bind = CustomEvents.bind; +exports.fire = CustomEvents.fire; - exports.bind = CustomEvents.bind; +},{}],49:[function(require,module,exports){ +"use strict"; - exports.fire = CustomEvents.fire; +class LessPlugin { + constructor(window, host) { + this.window = window; + this.host = host; + } -}).call(this); + reload(path, options) { + if (this.window.less && this.window.less.refresh) { + if (path.match(/\.less$/i)) { + return this.reloadLess(path); + } -},{}],3:[function(require,module,exports){ -(function() { - var LessPlugin; + if (options.originalPath.match(/\.less$/i)) { + return this.reloadLess(options.originalPath); + } + } - module.exports = LessPlugin = (function() { - LessPlugin.identifier = 'less'; + return false; + } - LessPlugin.version = '1.0'; + reloadLess(path) { + let link; - function LessPlugin(window, host) { - this.window = window; - this.host = host; - } + const links = (() => { + const result = []; - LessPlugin.prototype.reload = function(path, options) { - if (this.window.less && this.window.less.refresh) { - if (path.match(/\.less$/i)) { - return this.reloadLess(path); - } - if (options.originalPath.match(/\.less$/i)) { - return this.reloadLess(options.originalPath); + for (link of Array.from(document.getElementsByTagName('link'))) { + if (link.href && link.rel.match(/^stylesheet\/less$/i) || link.rel.match(/stylesheet/i) && link.type.match(/^text\/(x-)?less$/i)) { + result.push(link); } } + + return result; + })(); + + if (links.length === 0) { return false; - }; + } - LessPlugin.prototype.reloadLess = function(path) { - var i, len, link, links; - links = (function() { - var i, len, ref, results; - ref = document.getElementsByTagName('link'); - results = []; - for (i = 0, len = ref.length; i < len; i++) { - link = ref[i]; - if (link.href && link.rel.match(/^stylesheet\/less$/i) || (link.rel.match(/stylesheet/i) && link.type.match(/^text\/(x-)?less$/i))) { - results.push(link); - } - } - return results; - })(); - if (links.length === 0) { - return false; - } - for (i = 0, len = links.length; i < len; i++) { - link = links[i]; - link.href = this.host.generateCacheBustUrl(link.href); - } - this.host.console.log("LiveReload is asking LESS to recompile all stylesheets"); - this.window.less.refresh(true); - return true; - }; + for (link of Array.from(links)) { + link.href = this.host.generateCacheBustUrl(link.href); + } - LessPlugin.prototype.analyze = function() { - return { - disable: !!(this.window.less && this.window.less.refresh) - }; + this.host.console.log('LiveReload is asking LESS to recompile all stylesheets'); + this.window.less.refresh(true); + return true; + } + + analyze() { + return { + disable: !!(this.window.less && this.window.less.refresh) }; + } - return LessPlugin; +} - })(); +; +LessPlugin.identifier = 'less'; +LessPlugin.version = '1.0'; +module.exports = LessPlugin; -}).call(this); +},{}],50:[function(require,module,exports){ +"use strict"; -},{}],4:[function(require,module,exports){ -(function() { - var Connector, LiveReload, Options, ProtocolError, Reloader, Timer, - hasProp = {}.hasOwnProperty; +require("core-js/modules/web.dom.iterable"); - Connector = require('./connector').Connector; +/* global alert */ +const { + Connector +} = require('./connector'); - Timer = require('./timer').Timer; +const { + Timer +} = require('./timer'); - Options = require('./options').Options; +const { + Options +} = require('./options'); - Reloader = require('./reloader').Reloader; +const { + Reloader +} = require('./reloader'); - ProtocolError = require('./protocol').ProtocolError; +const { + ProtocolError +} = require('./protocol'); - exports.LiveReload = LiveReload = (function() { - function LiveReload(window1) { - var k, ref, v; - this.window = window1; - this.listeners = {}; - this.plugins = []; - this.pluginIdentifiers = {}; - this.console = this.window.console && this.window.console.log && this.window.console.error ? this.window.location.href.match(/LR-verbose/) ? this.window.console : { - log: function() {}, - error: this.window.console.error.bind(this.window.console) - } : { - log: function() {}, - error: function() {} - }; - if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) { - this.console.error("LiveReload disabled because the browser does not seem to support web sockets"); +class LiveReload { + constructor(window) { + this.window = window; + this.listeners = {}; + this.plugins = []; + this.pluginIdentifiers = {}; // i can haz console? + + this.console = this.window.console && this.window.console.log && this.window.console.error ? this.window.location.href.match(/LR-verbose/) ? this.window.console : { + log() {}, + + error: this.window.console.error.bind(this.window.console) + } : { + log() {}, + + error() {} + + }; // i can haz sockets? + + if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) { + this.console.error('LiveReload disabled because the browser does not seem to support web sockets'); + return; + } // i can haz options? + + + if ('LiveReloadOptions' in window) { + this.options = new Options(); + + for (let k of Object.keys(window['LiveReloadOptions'] || {})) { + const v = window['LiveReloadOptions'][k]; + this.options.set(k, v); + } + } else { + this.options = Options.extract(this.window.document); + + if (!this.options) { + this.console.error('LiveReload disabled because it could not find its own """) - - options = Options.extract(dom.window.document) - assert.ok options? - assert.equal 'somewhere.com', options.host - assert.equal 9876, options.port - - - it "should recognize zlivereload.js as a valid SCRIPT tag for dev testing purposes", -> - dom = new JSDOM("""""") - - options = Options.extract(dom.window.document) - assert.ok options? - assert.equal 'somewhere.com', options.host - assert.equal 9876, options.port - - - it "should pick the correct SCRIPT tag", -> - dom = new JSDOM(""" """) - - options = Options.extract(dom.window.document) - assert.ok options? - assert.equal 'somewhere.com', options.host - assert.equal 9876, options.port - - - it "should extract additional options", -> - dom = new JSDOM("""""") - - options = Options.extract(dom.window.document) - assert.equal '1', options.snipver - assert.equal 'Safari', options.ext - assert.equal '2.0', options.extver - - - it "should be cool with a strange URL", -> - dom = new JSDOM("""""") - - options = Options.extract(dom.window.document) - assert.equal 'somewhere.com', options.host - assert.equal 35729, options.port - - it "should accept when livereload is not being served domain root", -> - dom = new JSDOM("""""") - options = Options.extract(dom.window.document) - assert.equal 'somewhere.com', options.host - assert.equal 9876, options.port - - it "should set https when using an https URL ", -> - dom = new JSDOM("""""") - - options = Options.extract(dom.window.document) - assert.ok options? - assert.equal true, options.https diff --git a/test/options_test.js b/test/options_test.js new file mode 100644 index 0000000..dc69029 --- /dev/null +++ b/test/options_test.js @@ -0,0 +1,65 @@ +const assert = require('assert'); +const { JSDOM } = require('jsdom'); + +const { Options } = require('../src/options'); + +describe('Options', function () { + it('should extract host and port from a SCRIPT tag', function () { + const dom = new JSDOM(''); + + const options = Options.extract(dom.window.document); + assert.ok(options); + assert.strictEqual('somewhere.com', options.host); + return assert.strictEqual(9876, options.port); + }); + + it('should recognize zlivereload.js as a valid SCRIPT tag for dev testing purposes', function () { + const dom = new JSDOM(''); + + const options = Options.extract(dom.window.document); + assert.ok(options); + assert.strictEqual('somewhere.com', options.host); + return assert.strictEqual(9876, options.port); + }); + + it('should pick the correct SCRIPT tag', function () { + const dom = new JSDOM(' '); + + const options = Options.extract(dom.window.document); + assert.ok(options); + assert.strictEqual('somewhere.com', options.host); + return assert.strictEqual(9876, options.port); + }); + + it('should extract additional options', function () { + const dom = new JSDOM(''); + + const options = Options.extract(dom.window.document); + assert.strictEqual(1, options.snipver); + assert.strictEqual('Safari', options.ext); + return assert.strictEqual(2, options.extver); + }); + + it('should be cool with a strange URL', function () { + const dom = new JSDOM(''); + + const options = Options.extract(dom.window.document); + assert.strictEqual('somewhere.com', options.host); + return assert.strictEqual(35729, options.port); + }); + + it('should accept when livereload is not being served domain root', function () { + const dom = new JSDOM(''); + const options = Options.extract(dom.window.document); + assert.strictEqual('somewhere.com', options.host); + return assert.strictEqual(9876, options.port); + }); + + return it('should set https when using an https URL ', function () { + const dom = new JSDOM(''); + + const options = Options.extract(dom.window.document); + assert.ok(options); + return assert.strictEqual(true, options.https); + }); +}); diff --git a/test/protocol_test.coffee b/test/protocol_test.coffee deleted file mode 100644 index dc3e877..0000000 --- a/test/protocol_test.coffee +++ /dev/null @@ -1,49 +0,0 @@ -assert = require 'assert' -{ Parser } = require '../src/protocol' - -class MockHandler - constructor: -> - @_log = [] - @gotError = no - - obtainLog: -> result = @_log.join("\n"); @_log = []; result - log: (message) -> @_log.push message - - connected: (@protocol) -> - error: (@error) -> @gotError = yes - - message: (msg) -> - switch msg.command - when 'reload' then @log "reload(#{msg.path})" - else @log msg.commmand - -describe "Protocol", -> - it "should reject a bogus handshake", -> - handler = new MockHandler() - parser = new Parser(handler) - - parser.process 'boo' - assert.ok handler.gotError - - - it "should speak protocol 6", -> - handler = new MockHandler() - parser = new Parser(handler) - - parser.process '!!ver:1.6' - assert.equal 6, parser.protocol - - parser.process '[ "refresh", { "path": "foo.css" } ]' - assert.equal "reload(foo.css)", handler.obtainLog() - - - it "should speak protocol 7", -> - handler = new MockHandler() - parser = new Parser(handler) - - parser.process '{ "command": "hello", "protocols": [ "http://livereload.com/protocols/official-7" ] }' - assert.equal null, handler.error?.message - assert.equal 7, parser.protocol - - parser.process '{ "command": "reload", "path": "foo.css" }' - assert.equal "reload(foo.css)", handler.obtainLog() diff --git a/test/protocol_test.js b/test/protocol_test.js new file mode 100644 index 0000000..58b8247 --- /dev/null +++ b/test/protocol_test.js @@ -0,0 +1,60 @@ +const assert = require('assert'); +const { Parser } = require('../src/protocol'); + +class MockHandler { + constructor () { + this._log = []; + this.gotError = false; + } + + obtainLog () { const result = this._log.join('\n'); this._log = []; return result; } + log (message) { return this._log.push(message); } + + connected (protocol) { + this.protocol = protocol; + } + error (error) { + this.error = error; + this.gotError = true; + } + + message (msg) { + switch (msg.command) { + case 'reload': return this.log(`reload(${msg.path})`); + default: return this.log(msg.commmand); + } + } +} + +describe('Protocol', function () { + it('should reject a bogus handshake', function () { + const handler = new MockHandler(); + const parser = new Parser(handler); + + parser.process('boo'); + return assert.ok(handler.gotError); + }); + + it('should speak protocol 6', function () { + const handler = new MockHandler(); + const parser = new Parser(handler); + + parser.process('!!ver:1.6'); + assert.strictEqual(6, parser.protocol); + + parser.process('[ "refresh", { "path": "foo.css" } ]'); + return assert.strictEqual('reload(foo.css)', handler.obtainLog()); + }); + + return it('should speak protocol 7', function () { + const handler = new MockHandler(); + const parser = new Parser(handler); + + parser.process('{ "command": "hello", "protocols": [ "http://livereload.com/protocols/official-7" ] }'); + assert.strictEqual(undefined, (handler.error || {}).message); + assert.strictEqual(7, parser.protocol); + + parser.process('{ "command": "reload", "path": "foo.css" }'); + return assert.strictEqual('reload(foo.css)', handler.obtainLog()); + }); +}); diff --git a/test/timer_test.coffee b/test/timer_test.coffee deleted file mode 100644 index 34ccb14..0000000 --- a/test/timer_test.coffee +++ /dev/null @@ -1,48 +0,0 @@ -assert = require 'assert' -{ Timer } = require '../src/timer' - -describe "Timer", -> - it "should fire an event once in due time", (done) -> - fired = 0 - timer = new Timer -> - ++fired - - assert.equal no, timer.running - timer.start(20) - assert.equal yes, timer.running - - setTimeout -> - assert.equal 1, fired - done() - , 50 - - - it "shouldn't fire after it is stopped", (done) -> - fired = 0 - timer = new Timer -> - ++fired - - timer.start(20) - setTimeout((-> timer.stop()), 10) - - setTimeout -> - assert.equal 0, fired - done() - , 50 - - - it "should restart interval on each start() call", (done) -> - okToFire = no - fired = 0 - timer = new Timer -> - assert.equal yes, okToFire - ++fired - - timer.start(10) - setTimeout((-> timer.start(50)), 5) - setTimeout((-> okToFire = yes), 15) - - setTimeout -> - assert.equal 1, fired - done() - , 100 diff --git a/test/timer_test.js b/test/timer_test.js new file mode 100644 index 0000000..1d8668d --- /dev/null +++ b/test/timer_test.js @@ -0,0 +1,56 @@ +const assert = require('assert'); +const { Timer } = require('../src/timer'); + +describe('Timer', function () { + it('should fire an event once in due time', function (done) { + let fired = 0; + const timer = new Timer(function () { + return ++fired; + }); + + assert.strictEqual(false, timer.running); + timer.start(20); + assert.strictEqual(true, timer.running); + + return setTimeout(function () { + assert.strictEqual(1, fired); + return done(); + } + , 50); + }); + + it("shouldn't fire after it is stopped", function (done) { + let fired = 0; + const timer = new Timer(function () { + return ++fired; + }); + + timer.start(20); + setTimeout(() => timer.stop(), 10); + + return setTimeout(function () { + assert.strictEqual(0, fired); + return done(); + } + , 50); + }); + + return it('should restart interval on each start() call', function (done) { + let okToFire = false; + let fired = 0; + const timer = new Timer(function () { + assert.strictEqual(true, okToFire); + return ++fired; + }); + + timer.start(10); + setTimeout(() => timer.start(50), 5); + setTimeout(() => { okToFire = true; }, 15); + + return setTimeout(function () { + assert.strictEqual(1, fired); + return done(); + } + , 100); + }); +}); diff --git a/version-bower.js b/version-bower.js new file mode 100755 index 0000000..7eccc10 --- /dev/null +++ b/version-bower.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node +const { promisify } = require('util'); +const writeFile = promisify(require('fs').writeFile); + +const { version } = require('./package.json'); +const bwr = require('./bower.json'); + +writeFile('./bower.json', `${JSON.stringify({ ...bwr, version }, null, 2)}\n`, 'utf8') + .catch(err => { + throw err; + });