(function (window, undefined) { "use strict"; // test for REM unit support var cssremunit = function() { var div = document.createElement( 'div' ); div.style.cssText = 'font-size: 1rem;'; return (/rem/).test(div.style.fontSize); }, // filter returned links for stylesheets isStyleSheet = function () { var styles = document.getElementsByTagName('link'), filteredLinks = []; for ( var i = 0; i < styles.length; i++) { if ( styles[i].rel.toLowerCase() === 'stylesheet' && styles[i].getAttribute('data-norem') === null ) { filteredLinks.push( styles[i].href ); } } return filteredLinks; }, processLinks = function () { //prepare to match each link for( var i = 0; i < links.length; i++ ){ xhr( links[i], storeCSS ); } }, storeCSS = function ( response, link ) { preCSS.push(response.responseText); CSSLinks.push(link); if( CSSLinks.length === links.length ){ for( var j = 0; j < CSSLinks.length; j++ ){ matchCSS( preCSS[j], CSSLinks[j] ); } if( ( links = importLinks.slice(0) ).length > 0 ){ //after finishing all current links, set links equal to the new imports found CSSLinks = []; preCSS = []; importLinks = []; processLinks(); } else { buildCSS(); } } }, matchCSS = function ( sheetCSS, link ) { // collect all of the rules from the xhr response texts and match them to a pattern var clean = removeMediaQueries( sheetCSS ).replace(/\/\*[\s\S]*?\*\//g, ''), // remove MediaQueries and comments pattern = /[\w\d\s\-\/\\\[\]:,.'"*()<>+~%#^$_=|@]+\{[\w\d\s\-\/\\%#:!;,.'"*()]+\d*\.?\d+rem[\w\d\s\-\/\\%#:!;,.'"*()]*\}/g, //find selectors that use rem in one or more of their rules current = clean.match(pattern), remPattern =/\d*\.?\d+rem/g, remCurrent = clean.match(remPattern), sheetPathPattern = /(.*\/)/, sheetPath = sheetPathPattern.exec(link)[0], //relative path to css file specified in @import importPattern = /@import (?:url\()?['"]?([^'\)"]*)['"]?\)?[^;]*/gm, //matches all @import variations outlined at: https://developer.mozilla.org/en-US/docs/Web/CSS/@import importStatement; while( (importStatement = importPattern.exec(sheetCSS)) !== null ){ if( importStatement[1].indexOf("/") === 0 ) { // check if the value of importStatement[1] is a root relative path, in which case it shouldn't be concatenated with sheetPath importLinks.push( importStatement[1] ); } else { importLinks.push( sheetPath + importStatement[1] ); } } if( current !== null && current.length !== 0 ){ found = found.concat( current ); // save all of the blocks of rules with rem in a property foundProps = foundProps.concat( remCurrent ); // save all of the properties with rem } }, buildCSS = function () { // first build each individual rule from elements in the found array and then add it to the string of rules. var pattern = /[\w\d\s\-\/\\%#:,.'"*()]+\d*\.?\d+rem[\w\d\s\-\/\\%#:!,.'"*()]*[;}]/g; // find properties with rem values in them for( var i = 0; i < found.length; i++ ){ rules = rules + found[i].substr(0,found[i].indexOf("{")+1); // save the selector portion of each rule with a rem value var current = found[i].match( pattern ); for( var j = 0; j