UNPKG

blanket

Version:
339 lines (324 loc) 14.9 kB
(function(_blanket){ _blanket.extend({ utils: { normalizeBackslashes: function(str) { return str.replace(/\\/g, '/'); }, matchPatternAttribute: function(filename,pattern){ if (typeof pattern === 'string'){ if (pattern.indexOf("[") === 0){ //treat as array var pattenArr = pattern.slice(1,pattern.length-1).split(","); return pattenArr.some(function(elem){ return _blanket.utils.matchPatternAttribute(filename,_blanket.utils.normalizeBackslashes(elem.slice(1,-1))); //return filename.indexOf(_blanket.utils.normalizeBackslashes(elem.slice(1,-1))) > -1; }); }else if ( pattern.indexOf("//") === 0){ var ex = pattern.slice(2,pattern.lastIndexOf('/')); var mods = pattern.slice(pattern.lastIndexOf('/')+1); var regex = new RegExp(ex,mods); return regex.test(filename); }else if (pattern.indexOf("#") === 0){ return window[pattern.slice(1)].call(window,filename); }else{ return filename.indexOf(_blanket.utils.normalizeBackslashes(pattern)) > -1; } }else if ( pattern instanceof Array ){ return pattern.some(function(elem){ return _blanket.utils.matchPatternAttribute(filename,elem); }); }else if (pattern instanceof RegExp){ return pattern.test(filename); }else if (typeof pattern === "function"){ return pattern.call(window,filename); } }, blanketEval: function(data){ _blanket._addScript(data); }, collectPageScripts: function(){ var toArray = Array.prototype.slice; var selectedScripts=[],scriptNames=[]; var filter = _blanket.options("filter"); function selectAllScripts() { var browserScripts = toArray.call(document.scripts); var blanketScripts = toArray.call(document.getElementsByTagName('blanket')); return browserScripts.concat(blanketScripts); } if(filter != null){ //global filter in place, data-cover-only var antimatch = _blanket.options("antifilter"); selectedScripts = selectAllScripts() .filter(function(s){ return toArray.call(s.attributes).filter(function(sn){ return sn.nodeName === "src" && _blanket.utils.matchPatternAttribute(sn.nodeValue,filter) && (typeof antimatch === "undefined" || !_blanket.utils.matchPatternAttribute(sn.nodeValue,antimatch)); }).length === 1; }); }else{ selectedScripts = toArray.call(document.querySelectorAll("script[data-cover], blanket")); } scriptNames = selectedScripts.map(function(s){ return _blanket.utils.qualifyURL( toArray.call(s.attributes).filter( function(sn){ return sn.nodeName === "src"; })[0].nodeValue); }); if (!filter){ _blanket.options("filter","['"+scriptNames.join("','")+"']"); } return scriptNames; }, loadAll: function(nextScript,cb,preprocessor){ /** * load dependencies * @param {nextScript} factory for priority level * @param {cb} the done callback */ var currScript=nextScript(); var isLoaded = _blanket.utils.scriptIsLoaded( currScript, _blanket.utils.ifOrdered, nextScript, cb ); if (!(_blanket.utils.cache[currScript] && _blanket.utils.cache[currScript].loaded)){ var attach = function(){ if (_blanket.options("debug")) {console.log("BLANKET-Mark script:"+currScript+", as loaded and move to next script.");} isLoaded(); }; var whenDone = function(result){ if (_blanket.options("debug")) {console.log("BLANKET-File loading finished");} if (typeof result !== 'undefined'){ if (_blanket.options("debug")) {console.log("BLANKET-Add file to DOM.");} _blanket._addScript(result); } attach(); }; _blanket.utils.attachScript( { url: currScript }, function (content){ _blanket.utils.processFile( content, currScript, whenDone, whenDone ); } ); }else{ isLoaded(); } }, attachScript: function(options,cb){ var timeout = _blanket.options("timeout") || 3000; setTimeout(function(){ if (!_blanket.utils.cache[options.url].loaded){ throw new Error("error (timeout=" + timeout + ") loading source script: " + options.url); } },timeout); _blanket.utils.getFile( options.url, cb, function(){ throw new Error("error loading source script: " + options.url);} ); }, ifOrdered: function(nextScript,cb){ /** * ordered loading callback * @param {nextScript} factory for priority level * @param {cb} the done callback */ var currScript = nextScript(true); if (currScript){ _blanket.utils.loadAll(nextScript,cb); }else{ cb(new Error("Error in loading chain.")); } }, scriptIsLoaded: function(url,orderedCb,nextScript,cb){ /** * returns a callback that checks a loading list to see if a script is loaded. * @param {orderedCb} callback if ordered loading is being done * @param {nextScript} factory for next priority level * @param {cb} the done callback */ if (_blanket.options("debug")) {console.log("BLANKET-Returning function");} return function(){ if (_blanket.options("debug")) {console.log("BLANKET-Marking file as loaded: "+url);} _blanket.utils.cache[url].loaded=true; if (_blanket.utils.allLoaded()){ if (_blanket.options("debug")) {console.log("BLANKET-All files loaded");} cb(); }else if (orderedCb){ //if it's ordered we need to //traverse down to the next //priority level if (_blanket.options("debug")) {console.log("BLANKET-Load next file.");} orderedCb(nextScript,cb); } }; }, cache: {}, allLoaded: function (){ /** * check if depdencies are loaded in cache */ var cached = Object.keys(_blanket.utils.cache); for (var i=0;i<cached.length;i++){ if (!_blanket.utils.cache[cached[i]].loaded){ return false; } } return true; }, processFile: function (content,url,cb,oldCb) { var match = _blanket.options("filter"); //we check the never matches first var antimatch = _blanket.options("antifilter"); if (typeof antimatch !== "undefined" && _blanket.utils.matchPatternAttribute(url,antimatch) ){ oldCb(content); if (_blanket.options("debug")) {console.log("BLANKET-File will never be instrumented:"+url);} _blanket.requiringFile(url,true); }else if (_blanket.utils.matchPatternAttribute(url,match)){ if (_blanket.options("debug")) {console.log("BLANKET-Attempting instrument of:"+url);} _blanket.instrument({ inputFile: content, inputFileName: url },function(instrumented){ try{ if (_blanket.options("debug")) {console.log("BLANKET-instrument of:"+url+" was successfull.");} _blanket.utils.blanketEval(instrumented); cb(); _blanket.requiringFile(url,true); } catch(err){ if (_blanket.options("ignoreScriptError")){ //we can continue like normal if //we're ignoring script errors, //but otherwise we don't want //to completeLoad or the error might be //missed. if (_blanket.options("debug")) { console.log("BLANKET-There was an error loading the file:"+url); } cb(content); _blanket.requiringFile(url,true); }else{ var e = new Error("Error parsing instrumented code: "+err); e.error = err; throw e; } } }); }else{ if (_blanket.options("debug")) { console.log("BLANKET-Loading (without instrumenting) the file:"+url);} oldCb(content); _blanket.requiringFile(url,true); } }, cacheXhrConstructor: function(){ var Constructor, createXhr, i, progId; if (typeof XMLHttpRequest !== "undefined") { Constructor = XMLHttpRequest; this.createXhr = function() { return new Constructor(); }; } else if (typeof ActiveXObject !== "undefined") { Constructor = ActiveXObject; for (i = 0; i < 3; i += 1) { progId = progIds[i]; try { new ActiveXObject(progId); break; } catch (e) {} } this.createXhr = function() { return new Constructor(progId); }; } }, craeteXhr: function () { throw new Error("cacheXhrConstructor is supposed to overwrite this function."); }, getFile: function(url, callback, errback, onXhr){ var foundInSession = false; if (_blanket.blanketSession){ var files = Object.keys(_blanket.blanketSession); for (var i=0; i<files.length;i++ ){ var key = files[i]; if (url.indexOf(key) > -1){ callback(_blanket.blanketSession[key]); foundInSession=true; return; } } } if (!foundInSession){ var xhr = _blanket.utils.createXhr(); xhr.open('GET', url, true); //Allow overrides specified in config if (onXhr) { onXhr(xhr, url); } xhr.onreadystatechange = function (evt) { var status, err; //Do not explicitly handle errors, those should be //visible via console output in the browser. if (xhr.readyState === 4) { status = xhr.status; if ((status > 399 && status < 600) /*|| (status === 0 && navigator.userAgent.toLowerCase().indexOf('firefox') > -1) */ ) { //An http 4xx or 5xx error. Signal an error. err = new Error(url + ' HTTP status: ' + status); err.xhr = xhr; errback(err); } else { callback(xhr.responseText); } } }; try{ xhr.send(null); }catch(e){ if (e.code && (e.code === 101 || e.code === 1012) && _blanket.options("ignoreCors") === false){ //running locally and getting error from browser _blanket.showManualLoader(); } else { throw e; } } } } } }); (function(){ var require = blanket.options("commonJS") ? blanket._commonjs.require : window.require; var requirejs = blanket.options("commonJS") ? blanket._commonjs.requirejs : window.requirejs; if (!_blanket.options("engineOnly") && _blanket.options("existingRequireJS")){ _blanket.utils.oldloader = requirejs.load; requirejs.load = function (context, moduleName, url) { _blanket.requiringFile(url); _blanket.utils.getFile(url, function(content){ _blanket.utils.processFile( content, url, function newLoader(){ context.completeLoad(moduleName); }, function oldLoader(){ _blanket.utils.oldloader(context, moduleName, url); } ); }, function (err) { _blanket.requiringFile(); throw err; }); }; } // Save the XHR constructor, just in case frameworks like Sinon would sandbox it. _blanket.utils.cacheXhrConstructor(); })(); })(blanket);