Skip to content

Commit

Permalink
feat: support CSS imports - fixes #10
Browse files Browse the repository at this point in the history
  • Loading branch information
shakyShane committed Dec 23, 2017
1 parent 4c66bb8 commit fb26e82
Show file tree
Hide file tree
Showing 11 changed files with 5,505 additions and 4,592 deletions.
9,184 changes: 4,882 additions & 4,302 deletions client/dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/index.js.map

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion client/dist/index.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/index.min.js.map

Large diffs are not rendered by default.

193 changes: 16 additions & 177 deletions client/lib/code-sync.js
@@ -1,24 +1,15 @@
"use strict";
var events = require("./events");
var utils = require("./browser.utils");
var emitter = require("./emitter");
var sync = exports;

var options = {
tagNames: {
css: "link",
jpg: "img",
jpeg: "img",
png: "img",
svg: "img",
gif: "img",
js: "script"
},
attrs: {
link: "href",
img: "src",
script: "src"
},
import { Reloader } from "../vendor/Reloader";
import { Timer } from "../vendor/Timer";

const events = require("./events");
const utils = require("./browser.utils");
const emitter = require("./emitter");
const sync = exports;
const nanlogger = require("nanologger");
const log = nanlogger("Browsersync", { colors: { magenta: "#0F2634" } });
const reloader = new Reloader(window, log, Timer);

const options = {
blacklist: [
// never allow .map files through
function(incoming) {
Expand All @@ -27,21 +18,15 @@ var options = {
]
};

var hiddenElem;
var OPT_PATH = "codeSync";

var current = function() {
const OPT_PATH = "codeSync";
const current = function() {
return window.location.pathname;
};

/**
* @param {BrowserSync} bs
*/
sync.init = function(bs) {
if (bs.options.tagNames) {
options.tagNames = bs.options.tagNames;
}

if (bs.options.scrollRestoreTechnique === "window.name") {
sync.saveScrollInName(emitter);
} else {
Expand Down Expand Up @@ -138,77 +123,6 @@ sync.saveScrollInCookie = function($window, $document) {
emitter.on("browser:hardReload", utils.saveScrollPosition);
};

/**
* @param {string} search
* @param {string} key
* @param {string} suffix
*/
sync.updateSearch = function(search, key, suffix) {
if (search === "") {
return "?" + suffix;
}

return (
"?" +
search
.slice(1)
.split("&")
.map(function(item) {
return item.split("=");
})
.filter(function(tuple) {
return tuple[0] !== key;
})
.map(function(item) {
return [item[0], item[1]].join("=");
})
.concat(suffix)
.join("&")
);
};

/**
* @param elem
* @param attr
* @param options
* @returns {{elem: HTMLElement, timeStamp: number}}
*/
sync.swapFile = function(elem, attr, options) {
var currentValue = elem[attr];
var timeStamp = new Date().getTime();
var key = "rel";
var suffix = key + "=" + timeStamp;
var anchor = utils.getLocation(currentValue);
var search = sync.updateSearch(anchor.search, key, suffix);

if (options.timestamps === false) {
elem[attr] = anchor.href;
} else {
elem[attr] = anchor.href.split("?")[0] + search;
}

var body = document.body;

setTimeout(function() {
if (!hiddenElem) {
hiddenElem = document.createElement("DIV");
body.appendChild(hiddenElem);
} else {
hiddenElem.style.display = "none";
hiddenElem.style.display = "block";
}
}, 200);

return {
elem: elem,
timeStamp: timeStamp
};
};

sync.getFilenameOnly = function(url) {
return /^[^\?]+(?=\?)/.exec(url);
};

/**
* @param {BrowserSync} bs
* @returns {*}
Expand All @@ -221,9 +135,8 @@ sync.reload = function(bs) {
if (!bs.canSync({ url: current() }, OPT_PATH)) {
return;
}
var transformedElem;

var options = bs.options;
var emitter = bs.emitter;

if (data.url || !options.injectChanges) {
sync.reloadBrowser(true);
Expand All @@ -234,48 +147,11 @@ sync.reload = function(bs) {
return;
}

var domData = sync.getElems(data.ext);
var elems = sync.getMatches(
domData.elems,
data.basename,
domData.attr
);

if (elems.length && options.notify) {
emitter.emit("notify", {
message: "Injected: " + data.basename
});
}

for (var i = 0, n = elems.length; i < n; i += 1) {
transformedElem = sync.swapFile(
elems[i],
domData.attr,
options
);
}
reloader.reload(data.path, { liveCSS: true });
}

return transformedElem;
};
};

/**
* @param fileExtension
* @returns {*}
*/
sync.getTagName = function(fileExtension) {
return options.tagNames[fileExtension];
};

/**
* @param tagName
* @returns {*}
*/
sync.getAttr = function(tagName) {
return options.attrs[tagName];
};

/**
* @param incoming
* @returns {boolean}
Expand All @@ -286,43 +162,6 @@ sync.isBlacklisted = function(incoming) {
});
};

/**
* @param elems
* @param url
* @param attr
* @returns {Array}
*/
sync.getMatches = function(elems, url, attr) {
if (url[0] === "*") {
return elems;
}

var matches = [];
var urlMatcher = new RegExp("(^|/)" + url);

for (var i = 0, len = elems.length; i < len; i += 1) {
if (urlMatcher.test(elems[i][attr])) {
matches.push(elems[i]);
}
}

return matches;
};

/**
* @param fileExtension
* @returns {{elems: NodeList, attr: *}}
*/
sync.getElems = function(fileExtension) {
var tagName = sync.getTagName(fileExtension);
var attr = sync.getAttr(tagName);

return {
elems: document.getElementsByTagName(tagName),
attr: attr
};
};

/**
* @param confirm
*/
Expand Down
78 changes: 78 additions & 0 deletions client/lib/utils.ts
@@ -0,0 +1,78 @@
export function each(incoming) {
return [].slice.call(incoming || []);
}

export const splitUrl = function(url) {
let hash, index, params;
if ((index = url.indexOf("#")) >= 0) {
hash = url.slice(index);
url = url.slice(0, index);
} else {
hash = "";
}

if ((index = url.indexOf("?")) >= 0) {
params = url.slice(index);
url = url.slice(0, index);
} else {
params = "";
}

return { url, params, hash };
};

export const pathFromUrl = function(url) {
let path;
({ url } = splitUrl(url));
if (url.indexOf("file://") === 0) {
path = url.replace(new RegExp(`^file://(localhost)?`), "");
} else {
// http : // hostname :8080 /
path = url.replace(new RegExp(`^([^:]+:)?//([^:/]+)(:\\d*)?/`), "/");
}

// decodeURI has special handling of stuff like semicolons, so use decodeURIComponent
return decodeURIComponent(path);
};

export const pickBestMatch = function(path, objects, pathFunc): any {
let score;
let bestMatch = { score: 0, object: null };

objects.forEach(object => {
score = numberOfMatchingSegments(path, pathFunc(object));
if (score > bestMatch.score) {
bestMatch = { object, score };
}
});

if (bestMatch.score > 0) {
return bestMatch;
} else {
return null;
}
};

export const numberOfMatchingSegments = function(path1, path2) {
// get rid of leading slashes and normalize to lower case
path1 = path1.replace(/^\/+/, "").toLowerCase();
path2 = path2.replace(/^\/+/, "").toLowerCase();

if (path1 === path2) {
return 10000;
}

const comps1 = path1.split("/").reverse();
const comps2 = path2.split("/").reverse();
const len = Math.min(comps1.length, comps2.length);

let eqCount = 0;
while (eqCount < len && comps1[eqCount] === comps2[eqCount]) {
++eqCount;
}

return eqCount;
};

export const pathsMatch = (path1, path2) =>
numberOfMatchingSegments(path1, path2) > 0;

0 comments on commit fb26e82

Please sign in to comment.