diff --git a/README.md b/README.md index 521221b..a93da36 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,11 @@ The detected prefix of the current browser (like `'-moz-'` or `'-webkit-'`) The detected prefix of the current browser in camelCase format (like `'Moz'` or `'Webkit'`) PrefixFree.properties - PrefixFree.values + PrefixFree.functions + PrefixFree.keywords PrefixFree.selectors PrefixFree.atrules -Properties/values/etc that are **only** available with a prefix in the current browser. +Properties/functions/keywords/etc that are **only** available with a prefix in the current browser. ### Methods PrefixFree.prefixCSS(code [, raw]) diff --git a/prefixfree.js b/prefixfree.js index 1e84d78..daae4cd 100644 --- a/prefixfree.js +++ b/prefixfree.js @@ -12,41 +12,42 @@ if(!window.getComputedStyle || !window.addEventListener) { var self = window.PrefixFree = { prefixCSS: function(css, raw) { - var regex, prefix = self.prefix; + var prefix = self.prefix; - if (self.values.length) { - regex = RegExp('\\b(' + self.values.join('|') + ')\\b', 'gi'); + function fix(what, replacement, after, before) { + what = self[what]; - css = css.replace(regex, prefix + "$1"); + before = before || ''; + after = after || ''; + + replacement = replacement || before + prefix + '$1' + after; + + before = before || '\\b'; + after = after || '\\b'; + + if(what.length) { + var regex = RegExp(before + '(' + what.join('|') + ')' + after, 'gi'); + + css = css.replace(regex, replacement); + } } + fix('functions', prefix + "$1(", '\\s*\\('); + fix('keywords'); + fix('properties', prefix + '$1:', '\\s*:'); + + // Prefix properties *inside* values (issue #8) if (self.properties.length) { - regex = RegExp('\\b(' + self.properties.join('|') + '):', 'gi'); - - css = css.replace(regex, prefix + "$1:"); + var regex = RegExp('\\b(' + self.properties.join('|') + ')(?!:)', 'gi'); - // Prefix properties *inside* values (issue #8) - regex = RegExp('\\b(' + self.valueProperties.join('|') + '):(.+?);\s*$', 'gim'); - - var vpRegex = RegExp('\\b(' + self.properties.join('|') + ')(?!:)', 'gi'); - - css = css.replace(regex, function($0) { - return $0.replace(vpRegex, prefix + "$1") - }); + fix('valueProperties', function($0) { + return $0.replace(regex, prefix + "$1") + }, ':(.+?);'); } if(raw) { - if(self.selectors.length) { - regex = RegExp('\\b(' + self.selectors.join('|') + ')\\b', 'gi'); - - css = css.replace(regex, self.prefixSelector); - } - - if(self.atrules.length) { - regex = RegExp('@(' + self.atrules.join('|') + ')\\b', 'gi'); - - css = css.replace(regex, '@' + prefix + "$1"); - } + fix('selectors', self.prefixSelector); + fix('atrules', null, null, '@'); } // Fix double prefixing @@ -229,8 +230,8 @@ var self = window.PrefixFree = { * Values **************************************/ (function() { -// Values that *might* need prefixing -var values = { +// Values that might need prefixing +var functions = { 'linear-gradient': { property: 'backgroundImage', params: 'red, teal' @@ -239,30 +240,34 @@ var values = { property: 'width', params: '1px + 5%' }, - 'initial': { - property: 'color' - }, 'element': { property: 'backgroundImage', params: '#foo' } +}, + +keywords = { + 'initial': 'color', + 'zoom-in': 'cursor', + 'zoom-out': 'cursor' }; -values['repeating-linear-gradient'] = -values['repeating-radial-gradient'] = -values['radial-gradient'] = -values['linear-gradient']; +functions['repeating-linear-gradient'] = +functions['repeating-radial-gradient'] = +functions['radial-gradient'] = +functions['linear-gradient']; -self.values = []; +self.functions = []; +self.keywords = []; var style = document.createElement('div').style; -for (var val in values) { +for (var func in functions) { // Try if prefix-less version is supported - var test = values[val], + var test = functions[func], property = test.property, - value = val + (test.params? '(' + test.params + ')' : ''); - + value = func + '(' + test.params + ')'; + style[property] = ''; style[property] = value; @@ -279,7 +284,30 @@ for (var val in values) { } // If we're here, it is supported, but with a prefix - self.values.push(val); + self.functions.push(func); +} + +for (var keyword in keywords) { + // Try if prefix-less version is supported + var property = keywords[keyword]; + + style[property] = ''; + style[property] = keyword; + + if (style[property]) { + continue; + } + + // Now try with a prefix + style[property] = ''; + style[property] = self.prefix + keyword; + + if (!style[property]) { + continue; + } + + // If we're here, it is supported, but with a prefix + self.keywords.push(keyword); } })(); diff --git a/prefixfree.min.js b/prefixfree.min.js index 37b0512..b88ec90 100644 --- a/prefixfree.min.js +++ b/prefixfree.min.js @@ -3,12 +3,12 @@ * @author Lea Verou * MIT license */ -(function(k){function i(a,b){return[].slice.call((b||document).querySelectorAll(a))}if(window.getComputedStyle&&window.addEventListener){var b=window.PrefixFree={prefixCSS:function(a,f){var d,e=b.prefix;b.values.length&&(d=RegExp("\\b("+b.values.join("|")+")\\b","gi"),a=a.replace(d,e+"$1"));if(b.properties.length){d=RegExp("\\b("+b.properties.join("|")+"):","gi");a=a.replace(d,e+"$1:");d=RegExp("\\b("+b.valueProperties.join("|")+"):(.+?);s*$","gim");var c=RegExp("\\b("+b.properties.join("|")+")(?!:)", -"gi"),a=a.replace(d,function(a){return a.replace(c,e+"$1")})}f&&(b.selectors.length&&(d=RegExp("\\b("+b.selectors.join("|")+")\\b","gi"),a=a.replace(d,b.prefixSelector)),b.atrules.length&&(d=RegExp("@("+b.atrules.join("|")+")\\b","gi"),a=a.replace(d,"@"+e+"$1")));return a=a.replace(RegExp("-"+e,"g"),"-")},process:{link:function(a){try{if(!/\bstylesheet\b/i.test(a.rel)||!a.sheet.cssRules)return}catch(f){return}var d=a.getAttribute("href")||a.getAttribute("data-href"),e=d.replace(/[^\/]+$/,""),c=a.parentNode, -h=new XMLHttpRequest;h.open("GET",d);h.onreadystatechange=function(){if(h.readyState===4){var d=h.responseText;if(d&&a.parentNode){var d=b.prefixCSS(d,true),d=d.replace(/url\((?:'|")?(.+?)(?:'|")?\)/gi,function(a,b){return!/^([a-z]{3,10}:|\/)/i.test(b)?'url("'+e+b+'")':a}),f=document.createElement("style");f.textContent=d;c.insertBefore(f,a);c.removeChild(a)}}};h.send(null)},styleElement:function(a){a.textContent=b.prefixCSS(a.textContent,true)},styleAttribute:function(a){var f=a.getAttribute("style"), -f=b.prefixCSS(f);a.setAttribute("style",f)}},prefixSelector:function(a){return a.replace(/^:{1,2}/,function(a){return a+b.prefix})},prefixProperty:function(a,f){var d=b.prefix+a;return f?b.camelCase(d):d},camelCase:function(a){return a.replace(/-([a-z])/g,function(a,b){return b.toUpperCase()}).replace("-","")},deCamelCase:function(a){return a.replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})}};(function(){var a={},f="",d=0,e=[],c=getComputedStyle(document.documentElement,null),h=document.createElement("div").style, -i=function(c){e.indexOf(c)===-1&&e.push(c);if(c.indexOf("-")>-1){var i=c.split("-");if(c.charAt(0)==="-"){var c=i[1],g=++a[c]||1;a[c]=g;for(d3;)i.pop(),g=i.join("-"),b.camelCase(g)in h&&(c=e,c.indexOf(g)===-1&&c.push(g))}}};if(c.length>0)for(var g=0;g-1&&b.selectors.push(e)}for(var h in f)if(c=h+" "+(f[h]||"")+"{}",d.textContent="@"+c,d.sheet.cssRules.length===0)d.textContent="@"+b.prefix+c,d.sheet.cssRules.length>0&&b.atrules.push(h);k.removeChild(d)})();b.valueProperties=["transition","transition-property"];i('link[rel~="stylesheet"]').forEach(b.process.link);k.className+=" "+b.prefix;document.addEventListener("DOMContentLoaded",function(){i('link[rel~="stylesheet"]').forEach(b.process.link); -i("style").forEach(b.process.styleElement);i("[style]").forEach(b.process.styleAttribute)},false)}})(document.documentElement); \ No newline at end of file +(function(l){function k(b,f){return[].slice.call((f||document).querySelectorAll(b))}if(window.getComputedStyle&&window.addEventListener){var b=window.PrefixFree={prefixCSS:function(d,f){function a(a,c,f,i){a=b[a];i=i||"";f=f||"";c=c||i+g+"$1"+f;a.length&&(a=RegExp((i||"\\b")+"("+a.join("|")+")"+(f||"\\b"),"gi"),d=d.replace(a,c))}var g=b.prefix;a("functions",g+"$1(","\\s*\\(");a("keywords");a("properties",g+"$1:","\\s*:");if(b.properties.length){var c=RegExp("\\b("+b.properties.join("|")+")(?!:)", +"gi");a("valueProperties",function(a){return a.replace(c,g+"$1")},":(.+?);")}f&&(a("selectors",b.prefixSelector),a("atrules",null,null,"@"));return d=d.replace(RegExp("-"+g,"g"),"-")},process:{link:function(d){try{if(!/\bstylesheet\b/i.test(d.rel)||!d.sheet.cssRules)return}catch(f){return}var a=d.getAttribute("href")||d.getAttribute("data-href"),g=a.replace(/[^\/]+$/,""),c=d.parentNode,e=new XMLHttpRequest;e.open("GET",a);e.onreadystatechange=function(){if(e.readyState===4){var a=e.responseText;if(a&& +d.parentNode){var a=b.prefixCSS(a,true),a=a.replace(/url\((?:'|")?(.+?)(?:'|")?\)/gi,function(a,b){return!/^([a-z]{3,10}:|\/)/i.test(b)?'url("'+g+b+'")':a}),f=document.createElement("style");f.textContent=a;c.insertBefore(f,d);c.removeChild(d)}}};e.send(null)},styleElement:function(d){d.textContent=b.prefixCSS(d.textContent,true)},styleAttribute:function(d){var f=d.getAttribute("style"),f=b.prefixCSS(f);d.setAttribute("style",f)}},prefixSelector:function(d){return d.replace(/^:{1,2}/,function(d){return d+ +b.prefix})},prefixProperty:function(d,f){var a=b.prefix+d;return f?b.camelCase(a):a},camelCase:function(b){return b.replace(/-([a-z])/g,function(b,a){return a.toUpperCase()}).replace("-","")},deCamelCase:function(b){return b.replace(/[A-Z]/g,function(b){return"-"+b.toLowerCase()})}};(function(){var d={},f="",a=0,g=[],c=getComputedStyle(document.documentElement,null),e=document.createElement("div").style,h=function(c){g.indexOf(c)===-1&&g.push(c);if(c.indexOf("-")>-1){var i=c.split("-");if(c.charAt(0)=== +"-"){var c=i[1],h=++d[c]||1;d[c]=h;for(a3;)i.pop(),h=i.join("-"),b.camelCase(h)in e&&(c=g,c.indexOf(h)===-1&&c.push(h))}}};if(c.length>0)for(var j=0;j-1&&b.selectors.push(g)}for(var e in f)if(c=e+" "+(f[e]||"")+"{}",a.textContent="@"+c,a.sheet.cssRules.length===0)a.textContent="@"+b.prefix+c,a.sheet.cssRules.length>0&&b.atrules.push(e);l.removeChild(a)})();b.valueProperties=["transition","transition-property"];k('link[rel~="stylesheet"]').forEach(b.process.link);l.className+=" "+b.prefix;document.addEventListener("DOMContentLoaded", +function(){k('link[rel~="stylesheet"]').forEach(b.process.link);k("style").forEach(b.process.styleElement);k("[style]").forEach(b.process.styleAttribute)},false)}})(document.documentElement); \ No newline at end of file