browser-sync
Advanced tools
Comparing version 0.6.0 to 0.6.1
var browserSync = require("./lib/index"); | ||
var bs = browserSync.init("test/fixtures/**/*.css", { | ||
var files = ["test/fixtures/**/*.css", "test/fixtures/**/*.html"]; | ||
var bs = browserSync.init(files, { | ||
server: { | ||
baseDir: "test/fixtures" | ||
} | ||
}).on("init", function (api) { | ||
}).on("file:reload", function (file) { | ||
console.log("FILE INJECTED: " + file.assetFileName); | ||
}); | ||
//setInterval(function () { | ||
// bs.emit("file:changed", {path: "style.css"}); | ||
//}, 5000); | ||
}); |
@@ -25,4 +25,2 @@ "use strict"; | ||
var clients = []; | ||
browserSync.prototype = { | ||
@@ -34,2 +32,12 @@ cwd: cwd, | ||
}, | ||
clientEvents: [ | ||
"scroll", | ||
"input:text", | ||
"input:select", | ||
"input:radio", | ||
"input:checkbox", | ||
"form:submit", | ||
"form:reset", | ||
"click" | ||
], | ||
/** | ||
@@ -118,3 +126,2 @@ * @param {Array} files | ||
var ioLocal = this.setupSocket(ports); | ||
var callbacks = this.getSocketCallbacks(); | ||
@@ -127,3 +134,3 @@ // register internal events | ||
// Handle socket connections | ||
this.handleSocketConnection(callbacks, options, this.handleClientSocketEvent); | ||
this.handleSocketConnection(this.clientEvents, options); | ||
@@ -171,8 +178,2 @@ // Start file watcher | ||
/** | ||
* @returns {*} | ||
*/ | ||
getSocketCallbacks: function () { | ||
return _.union(this.ghostModeCallbacks, controlPanel.controlPanelEvents); | ||
}, | ||
/** | ||
* Set up the socket.io server | ||
@@ -194,5 +195,4 @@ * @param {Object} ports | ||
* @param {Object} userOptions | ||
* @param {function} handle | ||
*/ | ||
handleSocketConnection: function (events, userOptions, handle) { | ||
handleSocketConnection: function (events, userOptions) { | ||
@@ -206,5 +206,5 @@ var _this = this; | ||
if (userOptions.ghostMode) { | ||
for (var i = 0, n = events.length; i < n; i += 1) { | ||
handle(client, events[i], userOptions, _this); | ||
} | ||
events.forEach(function (evt) { | ||
_this.handleClientSocketEvent(client, evt); | ||
}); | ||
} | ||
@@ -216,9 +216,3 @@ | ||
clients.push(client); | ||
_this.logConnection(ua, userOptions); | ||
client.on("disconnect", function () { | ||
clients.splice(clients.indexOf(client), 1); | ||
}); | ||
}); | ||
@@ -230,8 +224,6 @@ }, | ||
* @param {String} event | ||
* @param {Object} userOptions | ||
* @param {Object} _this | ||
*/ | ||
handleClientSocketEvent: function (client, event, userOptions, _this) { | ||
client.on(event.name, function (data) { | ||
event.callback(client, data, _this); | ||
handleClientSocketEvent: function (client, event) { | ||
client.on(event, function (data) { | ||
client.broadcast.emit(event, data); | ||
}); | ||
@@ -254,57 +246,2 @@ }, | ||
/** | ||
* ghostMode Callbacks (responses to client events) | ||
*/ | ||
ghostModeCallbacks: [ | ||
{ | ||
name: "scroll", | ||
callback: function (client, data) { | ||
client.broadcast.emit("scroll:update", { position: data.pos, ghostId: data.ghostId, url: data.url}); | ||
} | ||
}, | ||
{ | ||
name: "input:type", | ||
callback: function (client, data) { | ||
client.broadcast.emit("input:update", { id: data.id, value: data.value }); | ||
} | ||
}, | ||
{ | ||
name: "input:select", | ||
callback: function (client, data) { | ||
client.broadcast.emit("input:update", { id: data.id, value: data.value }); | ||
} | ||
}, | ||
{ | ||
name: "input:radio", | ||
callback: function (client, data) { | ||
client.broadcast.emit("input:update:radio", { id: data.id, value: data.value }); | ||
} | ||
}, | ||
{ | ||
name: "input:checkbox", | ||
callback: function (client, data) { | ||
client.broadcast.emit("input:update:checkbox", { id: data.id, checked: data.checked }); | ||
} | ||
}, | ||
{ | ||
name: "form:submit", | ||
callback: function (client, data) { | ||
client.broadcast.emit("form:submit", { id: data.id }); | ||
} | ||
}, | ||
{ | ||
name: "form:reset", | ||
callback: function (client, data) { | ||
client.broadcast.emit("form:submit", { id: data.id }); | ||
} | ||
}, | ||
{ | ||
name: "click", | ||
callback: function (client, data) { | ||
client.broadcast.emit("click", data); | ||
} | ||
} | ||
], | ||
/** | ||
* Helper to try to retrieve the correct external IP for host | ||
* Defaults to localhost (0.0.0.0) if no network ip's are accessible. | ||
* @param {Object} options | ||
@@ -350,14 +287,15 @@ * @param {String|Array} [devIp] | ||
var suffix = ""; | ||
var validRoots = ["./", "/", "."]; | ||
if (!baseDir || baseDir === "./" || baseDir === "/" || baseDir === ".") { | ||
if (!baseDir || _.contains(validRoots, baseDir)) { | ||
return process.cwd(); | ||
} | ||
if (baseDir.charAt(0) === "/") { | ||
suffix = baseDir; | ||
} else { | ||
if (baseDir[0] === "/") { | ||
suffix = baseDir; | ||
if (/^.\//.test(baseDir)) { | ||
suffix = baseDir.replace(".", ""); | ||
} else { | ||
if (baseDir[0] === "." && baseDir[1] === "/") { | ||
suffix = baseDir.replace(".", ""); | ||
} else { | ||
suffix = "/" + baseDir; | ||
} | ||
suffix = "/" + baseDir; | ||
} | ||
@@ -404,3 +342,2 @@ } | ||
* @param {Object} options | ||
* @param _this - context | ||
* @returns {{assetFileName: String}} | ||
@@ -447,2 +384,3 @@ */ | ||
var server = options.server || false; | ||
var baseDir = this.getBaseDir(server.baseDir || "./"); | ||
var open = false; | ||
@@ -454,3 +392,3 @@ var msg; | ||
if (server) { | ||
msg = messages.initServer(host, ports.server, this.getBaseDir(options.server.baseDir || "./")); | ||
msg = messages.initServer(host, ports.server, baseDir); | ||
open = "server"; | ||
@@ -467,3 +405,2 @@ } | ||
if (open) { | ||
// Add test for this! | ||
this.openBrowser(options.url, options); | ||
@@ -470,0 +407,0 @@ } |
/*global window*/ | ||
/*global document*/ | ||
/*global location*/ | ||
/*global ___socket___*/ | ||
@@ -59,2 +58,3 @@ (function (window, socket) { | ||
notifyElem = this.createNotifyElem(styles || null); | ||
this.notify("Connected to BrowserSync", notifyElem); | ||
} | ||
@@ -119,2 +119,7 @@ }, | ||
var yPos = browserSyncActions.getScrollFromHref(window.location.href); | ||
if (yPos) { | ||
window.scrollTo(0, yPos); | ||
} | ||
if (ghostMode.forms) { | ||
@@ -229,3 +234,2 @@ | ||
/** | ||
* The actions for the style injector | ||
* @type {{reloadBrowser: Function, swapFile: Function}} | ||
@@ -239,6 +243,36 @@ */ | ||
if (confirm) { | ||
location.reload(); | ||
window.location.href = this.getPath(window.location.href, ghost.getScrollTop()); | ||
} | ||
}, | ||
/** | ||
* Retrieve y scroll from href | ||
* @param {String} href | ||
* @returns {String|Boolean} | ||
*/ | ||
getScrollFromHref: function (href) { | ||
var match = /bs_page_y=(\d{1,10})/.exec(href); | ||
if (match) { | ||
return match[1]; | ||
} | ||
return false; | ||
}, | ||
/** | ||
* @param {String} current | ||
* @param {Number} scrollTop | ||
* @returns {String} | ||
*/ | ||
getPath: function (current, scrollTop) { | ||
var regex = /(bs_page_y=\d{1,5})/; | ||
var prefix = "?"; | ||
if (current.match(regex)) { | ||
return current.replace(regex, function () { | ||
return "bs_page_y=" + scrollTop; | ||
}); | ||
} | ||
if (current.match(/\?/)) { | ||
prefix = "&"; | ||
} | ||
return current + prefix + "bs_page_y=" + scrollTop; | ||
}, | ||
/** | ||
* @param {HTMLElement} elem | ||
@@ -442,2 +476,6 @@ * @param {String} attr | ||
if (socket && socket.emit) { | ||
// send relative path of where the event is sent | ||
data.url = window.location.pathname; | ||
socket.emit(name, data); | ||
@@ -463,56 +501,2 @@ } | ||
/** | ||
* Get a href value from a clicked element | ||
* @param {HTMLElement} elem | ||
* @param {HTMLElement} [thisElem] | ||
* @returns {String} | ||
*/ | ||
getHref: function (elem, thisElem) { | ||
var tagName = elem.tagName; | ||
var href; | ||
if (thisElem && thisElem.href) { | ||
href = thisElem.href; | ||
} else { | ||
if (tagName === "A") { | ||
href = elem.href; | ||
} else { | ||
// IE 7/8 find the parent Anchor element | ||
href = this.getParentHref(elem, 5); | ||
} | ||
} | ||
return href; | ||
}, | ||
/** | ||
* Walk backwards up the dom until you find the HREF attr of a link. | ||
* @param {HTMLElement} elem | ||
* @param {Number} limit | ||
* @returns {String|Boolean} | ||
*/ | ||
getParentHref: function (elem, limit) { | ||
var getHref = function (elem) { | ||
if (elem.parentNode.tagName === "A") { | ||
return elem.parentNode.href; | ||
} else { | ||
return elem.parentNode; | ||
} | ||
}; | ||
var looperElem; | ||
var currentElem = elem; | ||
for (var i = 0; i < limit; i += 1) { | ||
looperElem = getHref(currentElem); | ||
if (typeof looperElem === "string") { | ||
return looperElem; | ||
} else { | ||
currentElem = looperElem; | ||
} | ||
} | ||
return false; | ||
}, | ||
/** | ||
* @returns {{texts: Array, radios: Array, checkboxes: Array}} | ||
@@ -559,4 +543,2 @@ */ | ||
var pos, url; | ||
var scrollTop = { | ||
@@ -566,6 +548,6 @@ raw: ghost.getScrollTop(), // Get px of y axis of scroll | ||
}; | ||
var newScroll = new Date().getTime(); | ||
var scrollThrottle = 0; | ||
if (scope.options && scope.options.scrollThrottle) { | ||
@@ -585,12 +567,4 @@ scrollThrottle = scope.options.scrollThrottle; | ||
if (scope.options.scrollProportionally) { | ||
pos = scrollTop.proportional; | ||
} else { | ||
pos = scrollTop.raw; | ||
} | ||
url = window.location.host + window.location.pathname; | ||
ghost.emitEvent("scroll", { | ||
pos: scrollTop, | ||
url: url | ||
position: scrollTop | ||
}); | ||
@@ -604,10 +578,20 @@ } | ||
* Handle aLL click events by indexing the dom element that was clicked | ||
* @param event | ||
* @param {Event} event | ||
* @param {Object} localScope | ||
*/ | ||
click: function (event) { | ||
click: function (event, localScope) { | ||
if (scope.ghostMode.enabled) { | ||
if (!localScope) { | ||
localScope = scope; | ||
} | ||
if (localScope.ghostMode.enabled) { | ||
var elem = event.target || event.srcElement; | ||
var tagName = elem.tagName; | ||
if (elem.type === "checkbox" || elem.type === "radio") { | ||
return; | ||
} | ||
var allElems = document.getElementsByTagName(tagName); | ||
@@ -624,3 +608,3 @@ var index = Array.prototype.indexOf.call(allElems, elem); | ||
} else { | ||
scope.ghostMode.enabled = true; | ||
localScope.ghostMode.enabled = true; | ||
} | ||
@@ -633,3 +617,3 @@ }, | ||
} | ||
ghost.emitEvent("input:type", { | ||
ghost.emitEvent("input:text", { | ||
id: target.id, | ||
@@ -651,2 +635,5 @@ value: target.value | ||
checkboxChange: function (event) { | ||
if (!scope.ghostMode.enabled) { | ||
return; | ||
} | ||
var target = event.target || event.srcElement; | ||
@@ -657,3 +644,3 @@ ghost.emitEvent("input:checkbox", { id: target.id, checked: target.checked }); | ||
var target = event.target || event.srcElement; | ||
ghost.emitEvent("input:select", { id: target.id, value: target.value }); | ||
ghost.emitEvent("input:text", { id: target.id, value: target.value }); | ||
}, | ||
@@ -669,2 +656,5 @@ formSubmit: function (event) { | ||
}, | ||
/** | ||
* Cross-browser event helpers | ||
*/ | ||
utils: { | ||
@@ -674,2 +664,14 @@ eventListener: (window.addEventListener) ? "addEventListener" : "attachEvent", | ||
prefix: (window.addEventListener) ? "" : "on" | ||
}, | ||
/** | ||
* @returns {string} | ||
*/ | ||
getCurrentPath: function () { | ||
return window.location.pathname; | ||
}, | ||
/** | ||
* @returns {boolean} | ||
*/ | ||
canSync: function (url) { | ||
return url === this.getCurrentPath(); | ||
} | ||
@@ -700,2 +702,7 @@ }; | ||
// ensure synchronization occurs only between same pages | ||
if (!ghost.canSync(data.url)) { | ||
return; | ||
} | ||
var elems = document.getElementsByTagName(data.tagName); | ||
@@ -711,3 +718,3 @@ var elem = elems[data.index]; | ||
socket.on("location:update", function (data) { | ||
socket.on("location", function (data) { | ||
if (data.url) { | ||
@@ -718,15 +725,25 @@ window.location = data.url; | ||
socket.on("scroll:update", function (data) { | ||
if (data.url === window.location.host + window.location.pathname) { | ||
scope.ghostMode.enabled = false; | ||
if (scope.options.scrollProportionally) { | ||
var scrollSpace = ghost.getScrollSpace(); | ||
window.scrollTo(0, scrollSpace[1] * data.position.proportional); // % of y axis of scroll to px | ||
} else { | ||
window.scrollTo(0, data.position.raw); | ||
} | ||
socket.on("scroll", function (data) { | ||
// ensure synchronization occurs only between same pages | ||
if (!ghost.canSync(data.url)) { | ||
return; | ||
} | ||
scope.ghostMode.enabled = false; | ||
if (scope.options.scrollProportionally) { | ||
var scrollSpace = ghost.getScrollSpace(); | ||
window.scrollTo(0, scrollSpace[1] * data.position.proportional); // % of y axis of scroll to px | ||
} else { | ||
window.scrollTo(0, data.position.raw); | ||
} | ||
}); | ||
socket.on("input:update", function (data) { | ||
socket.on("input:text", function (data) { | ||
// ensure synchronization occurs only between same pages | ||
if (!ghost.canSync(data.url)) { | ||
return; | ||
} | ||
scope.ghostMode.enabled = false; | ||
@@ -737,3 +754,9 @@ var elem = ghost.checkCache(scope.ghostMode.cache, data.id); | ||
socket.on("input:update:radio", function (data) { | ||
socket.on("input:radio", function (data) { | ||
// ensure synchronization occurs only between same pages | ||
if (!ghost.canSync(data.url)) { | ||
return; | ||
} | ||
scope.ghostMode.enabled = false; | ||
@@ -744,3 +767,10 @@ var elem = ghost.checkCache(scope.ghostMode.cache, data.id); | ||
socket.on("input:update:checkbox", function (data) { | ||
socket.on("input:checkbox", function (data) { | ||
// ensure synchronization occurs only between same pages | ||
if (!ghost.canSync(data.url)) { | ||
return; | ||
} | ||
scope.ghostMode.enabled = false; | ||
@@ -752,6 +782,19 @@ var elem = ghost.checkCache(scope.ghostMode.cache, data.id); | ||
socket.on("form:submit", function (data) { | ||
// ensure synchronization occurs only between same pages | ||
if (!ghost.canSync(data.url)) { | ||
return; | ||
} | ||
scope.ghostMode.enabled = false; | ||
document.forms[data.id].submit(); | ||
}); | ||
socket.on("form:reset", function (data) { | ||
// ensure synchronization occurs only between same pages | ||
if (!ghost.canSync(data.url)) { | ||
return; | ||
} | ||
scope.ghostMode.enabled = false; | ||
@@ -758,0 +801,0 @@ document.forms[data.id].reset(); |
"use strict"; | ||
var messages = require("./messages"); | ||
var snippetUtils = require("./snippet").utils; | ||
var connect = require("connect"); | ||
var http = require("http"); | ||
var loadSnippet = require("./loadSnippet"); | ||
var fs = require("fs"); | ||
@@ -41,5 +41,6 @@ var filePath = require("path"); | ||
var baseDir = __dirname + "/control-panel"; | ||
var scriptTags = messages.scriptTags(host, ports, options, "controlPanel"); | ||
var app = connect() | ||
.use(loadSnippet(host, ports, options, "controlPanel")) | ||
.use(snippetUtils.getSnippetMiddleware(scriptTags)) | ||
.use(clientScripts.versioned, modifySnippet) | ||
@@ -46,0 +47,0 @@ .use(connect.static(filePath.resolve(baseDir))); |
@@ -5,3 +5,2 @@ "use strict"; | ||
var messages = require("./messages"); | ||
var write = require("./snippet").write; | ||
var snippetUtils = require("./snippet").utils; | ||
@@ -17,23 +16,20 @@ | ||
/** | ||
* @param {String} html | ||
*/ | ||
return function (html) { | ||
var string = ""; | ||
var host = userServer.host; | ||
var port = userServer.port; | ||
var string = ""; | ||
var host = userServer.host; | ||
var port = userServer.port; | ||
var regex; | ||
if (host && port) { | ||
if (host && port) { | ||
string = host; | ||
if (parseInt(port, 10) !== 80) { | ||
string = host + ":" + port; | ||
} else { | ||
string = host; | ||
} | ||
} else { | ||
string = host; | ||
} | ||
regex = new RegExp(string, "g"); | ||
return html.replace(regex, function () { | ||
return { | ||
match: new RegExp(string, "g"), | ||
fn: function () { | ||
return proxyUrl; | ||
}); | ||
} | ||
}; | ||
@@ -52,2 +48,11 @@ }, | ||
}); | ||
}, | ||
/** | ||
* Get the proxy host with optional port | ||
*/ | ||
getProxyHost: function (opts) { | ||
if (opts.port && opts.port !== 80) { | ||
return opts.host + ":" + opts.port; | ||
} | ||
return opts.host; | ||
} | ||
@@ -67,4 +72,6 @@ }; | ||
var proxyUrl = host + ":" + ports.proxy; | ||
var rewriteLinks = utils.rewriteLinks(proxyOptions, proxyUrl); | ||
var scriptTags = messages.scriptTags(host, ports, options); | ||
var proxy = httpProxy.createProxyServer({}); | ||
var snippetMw = snippetUtils.getSnippetMiddleware(scriptTags, rewriteLinks); | ||
@@ -82,3 +89,3 @@ var server = require("http").createServer(function(req, res) { | ||
headers: { | ||
host: proxyOptions.host | ||
host: utils.getProxyHost(proxyOptions) | ||
} | ||
@@ -88,16 +95,9 @@ }); | ||
if (snippetUtils.isExcluded(req.url, options.excludedFileTypes)) { | ||
return next(); | ||
} | ||
req = snippetUtils.isOldIe(req); | ||
var tags = messages.scriptTags(host, ports, options); | ||
reqCallback(req, res); | ||
snippetMw(req, res, next); | ||
res.write = write(res, tags, null, utils.rewriteLinks(proxyOptions, proxyUrl)); | ||
}).listen(ports.proxy); | ||
reqCallback(req, res, next); | ||
}); | ||
server.listen(ports.proxy); | ||
// | ||
@@ -104,0 +104,0 @@ // Remove content-length to allow snippets to inserted to any body length |
@@ -5,4 +5,4 @@ "use strict"; | ||
var http = require("http"); | ||
var loadSnippet = require("./loadSnippet"); | ||
var proxyModule = require("./proxy"); | ||
var messages = require("./messages"); | ||
var filePath = require("path"); | ||
@@ -35,3 +35,3 @@ var snippetUtils = require("./snippet").utils; | ||
io.sockets.emit("location:update", { | ||
io.sockets.emit("location", { | ||
url: req.url | ||
@@ -49,3 +49,5 @@ }); | ||
} | ||
next(); | ||
if (typeof next === "function") { | ||
next(); | ||
} | ||
}; | ||
@@ -100,2 +102,3 @@ }, | ||
var navCallback = utils.navigateCallback(io, options); | ||
var scriptTags = messages.scriptTags(host, ports, options); | ||
@@ -110,5 +113,9 @@ if (proxy) { | ||
app = connect() | ||
.use(navCallback) | ||
.use(loadSnippet(host, ports, options)) | ||
.use(connect.static(filePath.resolve(baseDir), { index: index })); | ||
.use(function (req, res, next) { | ||
req = snippetUtils.isOldIe(req); | ||
return next(); | ||
}) | ||
.use(navCallback) | ||
.use(snippetUtils.getSnippetMiddleware(scriptTags)) | ||
.use(connect.static(filePath.resolve(baseDir), { index: index })); | ||
@@ -115,0 +122,0 @@ staticServer = http.createServer(app).listen(ports.server); |
@@ -5,2 +5,3 @@ "use strict"; | ||
var _ = require("lodash"); | ||
var lrSnippet = require("resp-modifier"); | ||
@@ -15,16 +16,3 @@ /** | ||
var utils = { | ||
bodyPattern: /<body[^>]*>/i, | ||
/** | ||
* Check if HTML body exists | ||
* @param {String} body | ||
* @returns {*} | ||
*/ | ||
bodyExists: function (body) { | ||
if (!body) { | ||
return false; | ||
} | ||
return (body.match(this.bodyPattern)); | ||
}, | ||
/** | ||
* @param {String} url | ||
@@ -46,52 +34,48 @@ * @param {Array} excludeList | ||
} | ||
return false; | ||
} | ||
}; | ||
module.exports.utils = utils; | ||
}, | ||
/** | ||
* @param {String} snippet | ||
* @returns {Function} | ||
*/ | ||
appendSnippet: function (snippet) { | ||
return function (w) { | ||
return w + snippet; | ||
}; | ||
}, | ||
/** | ||
* @param {String} snippet | ||
* @param {Object} extraRules | ||
* @returns {Function} | ||
*/ | ||
getSnippetMiddleware: function (snippet, extraRules) { | ||
/** | ||
* Write function for injecting script tags | ||
* @param {Object} res | ||
* @param {String} tags | ||
* @param {Boolean} rewriteHeaders | ||
* @param {Function} callback - any more actions on the parsed body | ||
* @returns {Function} | ||
*/ | ||
module.exports.write = function (res, tags, rewriteHeaders, callback) { | ||
var rules = [{ | ||
match: /<body[^>]*>/i, | ||
fn: this.appendSnippet(snippet) | ||
}]; | ||
var write = res.write; | ||
return function (string, encoding) { | ||
var body = string instanceof Buffer ? string.toString() : string; | ||
if (utils.bodyExists(body)) { | ||
body = body.replace(utils.bodyPattern, function (w) { | ||
return w + tags; | ||
}); | ||
if (extraRules) { | ||
rules.push(extraRules); | ||
} | ||
if (typeof callback === "function") { | ||
body = callback(body); | ||
} | ||
if (string instanceof Buffer) { | ||
string = new Buffer(body); | ||
} else { | ||
string = body; | ||
} | ||
if (rewriteHeaders) { | ||
// Remove content-length to allow snippets to inserted to any body length | ||
if (!this.headerSent) { | ||
if (this._headers.hasOwnProperty("content-length")) { | ||
delete this._headers["content-length"]; | ||
return lrSnippet({rules:rules}); | ||
}, | ||
/** | ||
* @param {Object} req | ||
* @returns {Object} | ||
*/ | ||
isOldIe: function (req, excludeList) { | ||
var ua = req.headers["user-agent"]; | ||
var match = /MSIE (\d)\.\d/.exec(ua); | ||
if (match) { | ||
if (parseInt(match[1], 10) < 9) { | ||
if (!utils.isExcluded(req.url, excludeList)) { | ||
req.headers["accept"] = "text/html"; | ||
} | ||
this._implicitHeader(); | ||
} | ||
} | ||
write.call(res, string, encoding); | ||
}; | ||
return req; | ||
} | ||
}; | ||
module.exports.utils = utils; |
{ | ||
"name": "browser-sync", | ||
"description": "Live CSS Reload & Browser Syncing", | ||
"version": "0.6.0", | ||
"version": "0.6.1", | ||
"homepage": "https://github.com/shakyshane/browser-sync", | ||
@@ -42,3 +42,4 @@ "author": { | ||
"http-proxy": "~1.0.2", | ||
"cl-strings": "~0.0.5" | ||
"cl-strings": "~0.0.5", | ||
"resp-modifier": "~0.0.2" | ||
}, | ||
@@ -45,0 +46,0 @@ "devDependencies": { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1552070
14
19258
+ Addedresp-modifier@~0.0.2
+ Addedresp-modifier@0.0.5(transitive)