From 321bec0d0cdf7947cb700bf77eeb1e3947016fe8 Mon Sep 17 00:00:00 2001 From: Samuel Mortenson Date: Wed, 22 Jul 2015 12:55:44 -0700 Subject: [PATCH 01/28] Updated cssKeyframeRegex to support css that includes the keyword "keyframes" in another context. --- css.js | 6 +++--- css.min.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/css.js b/css.js index b35458f..c2fea0f 100755 --- a/css.js +++ b/css.js @@ -9,7 +9,7 @@ this.cssRegex = new RegExp('([\\s\\S]*?){([\\s\\S]*?)}', 'gi'); this.cssMediaQueryRegex = '((@media [\\s\\S]*?){([\\s\\S]*?}\\s*?)})'; - this.cssKeyframeRegex = '((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})'; + this.cssKeyframeRegex = '((@(-webkit-)?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})'; this.combinedCSSRegex = '((\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})'; //to match css & media queries together this.cssCommentsRegex = '(\\/\\*[\\s\\S]*?\\*\\/)'; this.cssImportStatementRegex = new RegExp('@import .*?;', 'gi'); @@ -289,7 +289,7 @@ returns the changed(new,removed,updated) values on css1 parameter, on same structure if two css objects are the same, then returns false - + if a css directive exists in css1 and css2, and its value is different, it is included in diff if a css directive exists in css1 and not css2, it is then included in diff if a css directive exists in css2 but not css1, then it is deleted in css1, it would be included in diff but will be marked as type='DELETED' @@ -649,7 +649,7 @@ var __el = document.getElementById( id ); if(__el){ - __el.parentNode.removeChild( __el ); + __el.parentNode.removeChild( __el ); } var head = document.head || document.getElementsByTagName('head')[0], diff --git a/css.min.js b/css.min.js index 3478253..fc10f7d 100644 --- a/css.min.js +++ b/css.min.js @@ -1,2 +1,2 @@ -/*! css.js 16-01-2015 */ -!function(){"use strict";var a=function(){this.cssImportStatements=[],this.cssKeyframeStatements=[],this.cssRegex=new RegExp("([\\s\\S]*?){([\\s\\S]*?)}","gi"),this.cssMediaQueryRegex="((@media [\\s\\S]*?){([\\s\\S]*?}\\s*?)})",this.cssKeyframeRegex="((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})",this.combinedCSSRegex="((\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})",this.cssCommentsRegex="(\\/\\*[\\s\\S]*?\\*\\/)",this.cssImportStatementRegex=new RegExp("@import .*?;","gi")};a.prototype.stripComments=function(a){var b=new RegExp(this.cssCommentsRegex,"gi");return a.replace(b,"")},a.prototype.parseCSS=function(a){if(void 0===a)return[];for(var b=[];;){var c=this.cssImportStatementRegex.exec(a);if(null===c)break;this.cssImportStatements.push(c[0]),b.push({selector:"@imports",type:"imports",styles:c[0]})}a=a.replace(this.cssImportStatementRegex,"");for(var d,e=new RegExp(this.cssKeyframeRegex,"gi");;){if(d=e.exec(a),null===d)break;b.push({selector:"@keyframes",type:"keyframes",styles:d[0]})}a=a.replace(e,"");for(var f=new RegExp(this.combinedCSSRegex,"gi");;){if(d=f.exec(a),null===d)break;var g="";g=void 0===d[2]?d[5].split("\r\n").join("\n").trim():d[2].split("\r\n").join("\n").trim();var h=new RegExp(this.cssCommentsRegex,"gi"),i=h.exec(g);if(null!==i&&(g=g.replace(h,"").trim()),-1!==g.indexOf("@media")){var j={selector:g,type:"media",subStyles:this.parseCSS(d[3]+"\n}")};null!==i&&(j.comments=i[0]),b.push(j)}else{var k=this.parseRules(d[6]),l={selector:g,rules:k};"@font-face"===g&&(l.type="font-face"),null!==i&&(l.comments=i[0]),b.push(l)}}return b},a.prototype.parseRules=function(a){a=a.split("\r\n").join("\n");var b=[];a=a.split(";");for(var c=0;c0&&b.push({directive:"",value:d,defective:!0})}return b},a.prototype.findCorrespondingRule=function(a,b,c){void 0===c&&(c=!1);for(var d=!1,e=0;e-1;f--)if(a[f].selector===b.selector){d=a[f];break}if(d===!1)a.push(b);else if("media"!==b.type)for(var g=0;gc;c++)b+=" ";return b},a.prototype.applyNamespacing=function(a,b){var c=a,d="."+this.cssPreviewNamespace;void 0!==b&&(d=b),"string"==typeof a&&(c=this.parseCSS(a));for(var e=0;e-1||f.selector.indexOf("keyframes")>-1||f.selector.indexOf("@import")>-1||f.selector.indexOf(".form-all")>-1||f.selector.indexOf("#stage")>-1))if("media"!==f.type){for(var g=f.selector.split(","),h=[],i=0;i0&&b.push({directive:"",value:d,defective:!0})}return b},b.prototype.findCorrespondingRule=function(a,b,c){void 0===c&&(c=!1);for(var d=!1,e=0;e-1;f--)if(a[f].selector===b.selector){d=a[f];break}if(d===!1)a.push(b);else if("media"!==b.type)for(var g=0;gc;c++)b+=" ";return b},b.prototype.applyNamespacing=function(a,b){var c=a,d="."+this.cssPreviewNamespace;void 0!==b&&(d=b),"string"==typeof a&&(c=this.parseCSS(a));for(var e=0;e-1||f.selector.indexOf("keyframes")>-1||f.selector.indexOf("@import")>-1||f.selector.indexOf(".form-all")>-1||f.selector.indexOf("#stage")>-1))if("media"!==f.type){for(var g=f.selector.split(","),h=[],i=0;i Date: Mon, 24 Aug 2015 17:16:43 +0100 Subject: [PATCH 02/28] Removed unused $ parameter from outer closure and injected global context to allow for it to run server side --- README.md | 16 ++++++++++++++++ css.js | 6 +++--- css.min.js | 4 ++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c3728e6..5fe945b 100755 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ And to execute unit tests and produce css.min.js, execute How To Use ====== +On the browser +------ Simply parse css string, and log the output @@ -52,4 +54,18 @@ Simply parse css string, and log the output ``` +On the server +------ + +``` + var cssString = ' .someSelector { margin:40px 10px; padding:5px}'; + //require parser constructor + var cssjs = require("./css.js"); + //initialize parser object + var parser = new cssjs.cssjs(); + //parse css string + var parsed = parser.parseCSS(cssString); + + console.log(parsed); +``` diff --git a/css.js b/css.js index b35458f..0318ef8 100755 --- a/css.js +++ b/css.js @@ -1,6 +1,6 @@ /* jshint unused:false */ /* global base64_decode, CSSWizardView, window, console, jQuery */ -(function($) { +(function(global) { 'use strict'; var fi = function() { @@ -667,6 +667,6 @@ } }; - window.cssjs = fi; + global.cssjs = fi; -})(); \ No newline at end of file +})(this); \ No newline at end of file diff --git a/css.min.js b/css.min.js index 3478253..2cbdac8 100644 --- a/css.min.js +++ b/css.min.js @@ -1,2 +1,2 @@ -/*! css.js 16-01-2015 */ -!function(){"use strict";var a=function(){this.cssImportStatements=[],this.cssKeyframeStatements=[],this.cssRegex=new RegExp("([\\s\\S]*?){([\\s\\S]*?)}","gi"),this.cssMediaQueryRegex="((@media [\\s\\S]*?){([\\s\\S]*?}\\s*?)})",this.cssKeyframeRegex="((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})",this.combinedCSSRegex="((\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})",this.cssCommentsRegex="(\\/\\*[\\s\\S]*?\\*\\/)",this.cssImportStatementRegex=new RegExp("@import .*?;","gi")};a.prototype.stripComments=function(a){var b=new RegExp(this.cssCommentsRegex,"gi");return a.replace(b,"")},a.prototype.parseCSS=function(a){if(void 0===a)return[];for(var b=[];;){var c=this.cssImportStatementRegex.exec(a);if(null===c)break;this.cssImportStatements.push(c[0]),b.push({selector:"@imports",type:"imports",styles:c[0]})}a=a.replace(this.cssImportStatementRegex,"");for(var d,e=new RegExp(this.cssKeyframeRegex,"gi");;){if(d=e.exec(a),null===d)break;b.push({selector:"@keyframes",type:"keyframes",styles:d[0]})}a=a.replace(e,"");for(var f=new RegExp(this.combinedCSSRegex,"gi");;){if(d=f.exec(a),null===d)break;var g="";g=void 0===d[2]?d[5].split("\r\n").join("\n").trim():d[2].split("\r\n").join("\n").trim();var h=new RegExp(this.cssCommentsRegex,"gi"),i=h.exec(g);if(null!==i&&(g=g.replace(h,"").trim()),-1!==g.indexOf("@media")){var j={selector:g,type:"media",subStyles:this.parseCSS(d[3]+"\n}")};null!==i&&(j.comments=i[0]),b.push(j)}else{var k=this.parseRules(d[6]),l={selector:g,rules:k};"@font-face"===g&&(l.type="font-face"),null!==i&&(l.comments=i[0]),b.push(l)}}return b},a.prototype.parseRules=function(a){a=a.split("\r\n").join("\n");var b=[];a=a.split(";");for(var c=0;c0&&b.push({directive:"",value:d,defective:!0})}return b},a.prototype.findCorrespondingRule=function(a,b,c){void 0===c&&(c=!1);for(var d=!1,e=0;e-1;f--)if(a[f].selector===b.selector){d=a[f];break}if(d===!1)a.push(b);else if("media"!==b.type)for(var g=0;gc;c++)b+=" ";return b},a.prototype.applyNamespacing=function(a,b){var c=a,d="."+this.cssPreviewNamespace;void 0!==b&&(d=b),"string"==typeof a&&(c=this.parseCSS(a));for(var e=0;e-1||f.selector.indexOf("keyframes")>-1||f.selector.indexOf("@import")>-1||f.selector.indexOf(".form-all")>-1||f.selector.indexOf("#stage")>-1))if("media"!==f.type){for(var g=f.selector.split(","),h=[],i=0;i0&&b.push({directive:"",value:d,defective:!0})}return b},b.prototype.findCorrespondingRule=function(a,b,c){void 0===c&&(c=!1);for(var d=!1,e=0;e-1;f--)if(a[f].selector===b.selector){d=a[f];break}if(d===!1)a.push(b);else if("media"!==b.type)for(var g=0;gc;c++)b+=" ";return b},b.prototype.applyNamespacing=function(a,b){var c=a,d="."+this.cssPreviewNamespace;void 0!==b&&(d=b),"string"==typeof a&&(c=this.parseCSS(a));for(var e=0;e-1||f.selector.indexOf("keyframes")>-1||f.selector.indexOf("@import")>-1||f.selector.indexOf(".form-all")>-1||f.selector.indexOf("#stage")>-1))if("media"!==f.type){for(var g=f.selector.split(","),h=[],i=0;i Date: Mon, 9 Nov 2015 19:40:17 +0200 Subject: [PATCH 03/28] Typo fixes. More consistent style. --- css.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/css.js b/css.js index b35458f..b36bffe 100755 --- a/css.js +++ b/css.js @@ -116,7 +116,7 @@ } css.push(cssObject); } else { - //we have standart css + //we have standard css var rules = this.parseRules(arr[6]); var style = { selector: selector, @@ -368,7 +368,7 @@ } for (i = 0; i < cssObjectArray.length; i++) { var cobj = cssObjectArray[i]; - if (cobj.type === 'media' ||  (cobj.type === 'keyframes')) { + if (cobj.type === 'media' || (cobj.type === 'keyframes')) { continue; } cobj.rules = this.compactRules(cobj.rules); @@ -377,7 +377,7 @@ /* inserts new css objects into a bigger css object - with same selectors groupped together + with same selectors grouped together @param cssObjectArray, array of bigger css object to be pushed into @param minimalObject, single css object @@ -439,7 +439,7 @@ @param rules, array of rules - @returns rules array, compacted by deleting all unneccessary rules + @returns rules array, compacted by deleting all unnecessary rules */ fi.prototype.compactRules = function(rules) { var newRules = []; @@ -520,7 +520,7 @@ continue; } if (rules[i].defective === undefined) { - ret += this.getSpaces(depth) + rules[i].directive + ' : ' + rules[i].value + ';\n'; + ret += this.getSpaces(depth) + rules[i].directive + ': ' + rules[i].value + ';\n'; } else { ret += this.getSpaces(depth) + rules[i].value + ';\n'; } @@ -630,7 +630,7 @@ format = false; } - if (this.testMode === false && format!=='nonamespace') { + if (this.testMode === false && format !== 'nonamespace') { //apply namespacing classes css = this.applyNamespacing(css); } @@ -647,9 +647,9 @@ return this.testMode('create style #' + id, css); //if test mode, just pass result to callback } - var __el = document.getElementById( id ); - if(__el){ - __el.parentNode.removeChild( __el ); + var __el = document.getElementById(id); + if (__el) { + __el.parentNode.removeChild(__el); } var head = document.head || document.getElementsByTagName('head')[0], From 90378d6bc5990fcfd7ef3f34b1c35cde523d01b9 Mon Sep 17 00:00:00 2001 From: Braam Genis Date: Mon, 9 Nov 2015 19:48:44 +0200 Subject: [PATCH 04/28] Use strict equality. --- css.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/css.js b/css.js index b36bffe..2b12c6d 100755 --- a/css.js +++ b/css.js @@ -174,7 +174,7 @@ }); } else { //if there is no ':', but what if it was mis splitted value which starts with base64 - if (line.trim().substr(0, 7) == 'base64,') { //hack :) + if (line.trim().substr(0, 7) === 'base64,') { //hack :) ret[ret.length - 1].value += line.trim(); } else { //add rule, even if it is defective @@ -201,7 +201,7 @@ } var ret = false; for (var i = 0; i < rules.length; i++) { - if (rules[i].directive == directive) { + if (rules[i].directive === directive) { ret = rules[i]; if (value === rules[i].value) { break; @@ -419,7 +419,7 @@ var oldRule = this.findCorrespondingRule(cssObject.rules, rule.directive); if (oldRule === false) { cssObject.rules.push(rule); - } else if (rule.type == 'DELETED') { + } else if (rule.type === 'DELETED') { oldRule.type = 'DELETED'; } else { //rule found just update value @@ -465,7 +465,7 @@ } //append imports for (var i = 0; i < cssBase.length; i++) { - if (cssBase[i].type == 'imports') { + if (cssBase[i].type === 'imports') { ret += cssBase[i].styles + '\n\n'; } } @@ -479,7 +479,7 @@ comments = tmp.comments + '\n'; } - if (tmp.type == 'media') { //also put media queries to output + if (tmp.type === 'media') { //also put media queries to output ret += comments + tmp.selector + '{\n'; ret += this.getCSSForEditor(tmp.subStyles, depth + 1); ret += '}\n\n'; @@ -492,7 +492,7 @@ //append keyFrames for (i = 0; i < cssBase.length; i++) { - if (cssBase[i].type == 'keyframes') { + if (cssBase[i].type === 'keyframes') { ret += cssBase[i].styles + '\n\n'; } } @@ -503,7 +503,7 @@ fi.prototype.getImports = function(cssObjectArray) { var imps = []; for (var i = 0; i < cssObjectArray.length; i++) { - if (cssObjectArray[i].type == 'imports') { + if (cssObjectArray[i].type === 'imports') { imps.push(cssObjectArray[i].styles); } } @@ -635,7 +635,7 @@ css = this.applyNamespacing(css); } - if (typeof css != 'string') { + if (typeof css !== 'string') { css = this.getCSSForEditor(css); } //apply formatting for css From 92c57ec6abffb9c173af7f8e559b77b33d92d60e Mon Sep 17 00:00:00 2001 From: Braam Genis Date: Mon, 9 Nov 2015 19:52:02 +0200 Subject: [PATCH 05/28] Remove multiple consecutive line breaks. --- css.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/css.js b/css.js index 2b12c6d..d638563 100755 --- a/css.js +++ b/css.js @@ -103,6 +103,9 @@ selector = selector.replace(commentsRegex, '').trim(); } + // Never have more than a single line break in a row + selector = selector.replace(/\n+/, "\n"); + //determine the type if (selector.indexOf('@media') !== -1) { //we have a media query From 7a65e1425cfb52d6c79ad92f3e4bbb1eedf1f248 Mon Sep 17 00:00:00 2001 From: Braam Genis Date: Mon, 9 Nov 2015 19:53:53 +0200 Subject: [PATCH 06/28] Don't overwrite media queries sub styles. Rather just append them. --- css.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css.js b/css.js index d638563..4245829 100755 --- a/css.js +++ b/css.js @@ -431,7 +431,7 @@ } } } else { - cssObject.subStyles = minimalObject.subStyles; //TODO, make this intelligent too + cssObject.subStyles = cssObject.subStyles.concat(minimalObject.subStyles); //TODO, make this intelligent too } } From e25e6cf57f76d810e19afde7308fb64d4f226732 Mon Sep 17 00:00:00 2001 From: Braam Genis Date: Mon, 9 Nov 2015 19:55:26 +0200 Subject: [PATCH 07/28] Combined CSS regex matches optional comments before media query. --- css.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css.js b/css.js index 4245829..a06de27 100755 --- a/css.js +++ b/css.js @@ -10,7 +10,7 @@ this.cssRegex = new RegExp('([\\s\\S]*?){([\\s\\S]*?)}', 'gi'); this.cssMediaQueryRegex = '((@media [\\s\\S]*?){([\\s\\S]*?}\\s*?)})'; this.cssKeyframeRegex = '((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})'; - this.combinedCSSRegex = '((\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})'; //to match css & media queries together + this.combinedCSSRegex = '((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})'; //to match css & media queries together this.cssCommentsRegex = '(\\/\\*[\\s\\S]*?\\*\\/)'; this.cssImportStatementRegex = new RegExp('@import .*?;', 'gi'); }; From 63e6e9408c5485b47c66ac7f33e8f68d2958dbc1 Mon Sep 17 00:00:00 2001 From: Braam Genis Date: Tue, 10 Nov 2015 18:17:47 +0200 Subject: [PATCH 08/28] Added test case for media query with comment above. --- tests/cssParsing.test.js | 4 ++++ tests/data.js | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/tests/cssParsing.test.js b/tests/cssParsing.test.js index 843c318..9e0f73f 100755 --- a/tests/cssParsing.test.js +++ b/tests/cssParsing.test.js @@ -89,6 +89,10 @@ QUnit.test('Advanced CSS Parsing(support for media queries)', function(assert) { expected = $.parseJSON(testData.advCSS5.output); parsed = fullInspector.parseCSS(testData.advCSS5.input); assert.deepEqual(parsed, expected, 'Simple @font-face with multiline value containing css'); + + expected = $.parseJSON(testData.advCSS6.output); + parsed = fullInspector.parseCSS(testData.advCSS6.input); + assert.deepEqual(parsed, expected, 'Media query with a comment above it.'); }); /* diff --git a/tests/data.js b/tests/data.js index 353db96..54f1abb 100755 --- a/tests/data.js +++ b/tests/data.js @@ -42,6 +42,10 @@ var testData = { advCSS5: { input: '@font-face {\nfont-family: myFirstFont;\nsrc: url(sansation_light.woff) format(woff)\nurl(sansation_light.otf) format(opentype);\n}', output: '[{"selector":"@font-face","type":"font-face","rules":[{"directive":"font-family","value":"myFirstFont"},{"directive":"src","value":"url(sansation_light.woff) format(woff)\\nurl(sansation_light.otf) format(opentype)" }] }]' + }, + advCSS6: { + input: '/*--------------------------------------------------------------\nA big comment\n--------------------------------------------------------------*/@media screen and (min-width: 780px) {\n .supernova {\n background-color: #fafafa;\n }\n}', + output: '[{"comments": "/*--------------------------------------------------------------\\nA big comment\\n--------------------------------------------------------------*/","selector":"@media screen and (min-width: 780px)","type":"media","subStyles":[{"selector":".supernova","rules":[{"directive":"background-color","value":"#fafafa"}]}]}]' } }; From 136f885c4d3e2c7bc65377f151b3334d471658e5 Mon Sep 17 00:00:00 2001 From: Braam Genis Date: Tue, 10 Nov 2015 17:58:07 +0200 Subject: [PATCH 09/28] Added test case for intelligent push on media query object containing existing sub style. --- tests/cssParsing.test.js | 10 ++++++++-- tests/data.js | 5 +++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/cssParsing.test.js b/tests/cssParsing.test.js index 9e0f73f..e312b5f 100755 --- a/tests/cssParsing.test.js +++ b/tests/cssParsing.test.js @@ -150,12 +150,18 @@ QUnit.test('Intelligent CSS Push Tests', function(assert) { var styles = $.parseJSON(cssIntelligentPushData.pushBasic.styles); var newStyle = $.parseJSON(cssIntelligentPushData.pushBasic.newStyle); fullInspector.intelligentCSSPush(styles, newStyle); - var expected = $.parseJSON(cssIntelligentPushData.pushBasic.result) + var expected = $.parseJSON(cssIntelligentPushData.pushBasic.result); assert.deepEqual(styles, expected, 'Push CSS into empty CSS object'); styles = $.parseJSON(cssIntelligentPushData.pushBasic2.styles); newStyle = $.parseJSON(cssIntelligentPushData.pushBasic2.newStyle); fullInspector.intelligentCSSPush(styles, newStyle); - expected = $.parseJSON(cssIntelligentPushData.pushBasic2.result) + expected = $.parseJSON(cssIntelligentPushData.pushBasic2.result); assert.deepEqual(styles, expected, 'Push CSS containing a new css directive to an existing CSS object'); + + styles = $.parseJSON(cssIntelligentPushData.pushBasic3.styles); + newStyle = $.parseJSON(cssIntelligentPushData.pushBasic3.newStyle); + fullInspector.intelligentCSSPush(styles, newStyle); + expected = $.parseJSON(cssIntelligentPushData.pushBasic3.result); + assert.deepEqual(styles, expected, 'Push media query CSS containing a new css directive to an existing media query CSS object'); }); \ No newline at end of file diff --git a/tests/data.js b/tests/data.js index 54f1abb..52b4342 100755 --- a/tests/data.js +++ b/tests/data.js @@ -74,6 +74,11 @@ var cssIntelligentPushData = { styles: '[{"selector":".first","rules":[{"directive":"color","value":"blue"},{"directive":"margin","value":"10px"}]},{"selector":".second","rules":[{"directive":"color","value":"red"},{"directive":"margin","value":"20px"}]}]', newStyle: '{"selector":".first","rules":[{"directive":"padding","value":"5px"}]}', result: '[{"selector":".first","rules":[{"directive":"color","value":"blue"},{"directive":"margin","value":"10px"},{"directive":"padding","value":"5px"}]},{"selector":".second","rules":[{"directive":"color","value":"red"},{"directive":"margin","value":"20px"}]}]' + }, + pushBasic3: { + styles: '[{"selector":"@media screen and (min-width: 780px)","type":"media","subStyles":[{"selector":".supernova","rules":[{"directive":"background-color","value":"#fafafa"}]}]}]', + newStyle: '{"selector":"@media screen and (min-width: 780px)","type":"media","subStyles":[{"selector":".supernova","rules":[{"directive":"background-color","value":"#bada55"}]}]}', + result: '[{"selector":"@media screen and (min-width: 780px)","type":"media","subStyles":[{"selector":".supernova","rules":[{"directive":"background-color","value":"#fafafa"}]},{"selector":".supernova","rules":[{"directive":"background-color","value":"#bada55"}]}]}]' } }; From 97ddeb9f2feaac0e8d39907831517cfd4a004f32 Mon Sep 17 00:00:00 2001 From: Kemal Dag Date: Mon, 30 Nov 2015 12:45:18 +0200 Subject: [PATCH 10/28] Add npm test script --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ee0e5a..8b0b19d 100755 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "grunt-contrib-uglify": "^0.7.0" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "grunt" }, "repository": { "type": "git", From 98704cc49e1da588fbec31e1f8d33a7815b73926 Mon Sep 17 00:00:00 2001 From: Kemal Dag Date: Mon, 30 Nov 2015 12:47:37 +0200 Subject: [PATCH 11/28] Add .travis.yml file --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6fcadf4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "4.2.1" \ No newline at end of file From 406ba89210f4cb9068678928319ec3aa0d607703 Mon Sep 17 00:00:00 2001 From: Kemal Dag Date: Mon, 30 Nov 2015 12:49:29 +0200 Subject: [PATCH 12/28] Add global npm dependencies to travis.yml --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6fcadf4..b9a894a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ language: node_js node_js: - - "4.2.1" \ No newline at end of file + - "4.2.1" +before_install: npm install -g grunt-cli bower \ No newline at end of file From 023d10a815cbd4d779b504ccdfc142a62f9cf511 Mon Sep 17 00:00:00 2001 From: Kemal Dag Date: Mon, 30 Nov 2015 12:51:13 +0200 Subject: [PATCH 13/28] Travis: do a bower install before testing --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b9a894a..787fb70 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: node_js node_js: - "4.2.1" -before_install: npm install -g grunt-cli bower \ No newline at end of file +before_install: npm install -g grunt-cli bower +before_script: bower install \ No newline at end of file From fd07cd3a68779435e202d4573aa1fac2d49a694a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kemal=20Da=C4=9F?= Date: Mon, 30 Nov 2015 14:16:30 +0200 Subject: [PATCH 14/28] Add travis badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5fe945b..892952c 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -css.js +css.js [![Build Status](https://travis-ci.org/jotform/css.js.svg)](https://travis-ci.org/jotform/css.js) ====== A lightweight, battle tested, fast, css parser in JavaScript From 1664623ed031c15e6a159494fa5a1105cdbe52d7 Mon Sep 17 00:00:00 2001 From: Thomas Reggi Date: Fri, 4 Dec 2015 23:31:50 -0500 Subject: [PATCH 15/28] fix main & add grunt-cli dep --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8b0b19d..94f3e29 100755 --- a/package.json +++ b/package.json @@ -1,14 +1,15 @@ { "name": "css.js", "version": "1.0.0", - "description": "css.js ======", - "main": "Gruntfile.js", + "description": "A lightweight, battle tested, fast, CSS parser in JavaScript.", + "main": "css.js", "directories": { "test": "tests" }, "dependencies": {}, "devDependencies": { "grunt": "^0.4.5", + "grunt-cli": "^0.1.13", "grunt-contrib-concat": "^0.5.0", "grunt-contrib-jshint": "^0.10.0", "grunt-contrib-qunit": "^0.5.2", From 6e2149882c01505559a9e3550fd4e236a7fa476e Mon Sep 17 00:00:00 2001 From: Kemal DAG Date: Tue, 19 Apr 2016 17:14:20 +0300 Subject: [PATCH 16/28] Ditch bower, migrate jQuery dependency into npm and link qunit statically --- bower.json | 29 - css.min.js | 2 +- ext/qunit-1.21.1.css | 305 +++ ext/qunit-1.23.1.js | 4334 +++++++++++++++++++++++++++++++++++++++++ package.json | 4 +- tests/cssParsing.html | 6 +- 6 files changed, 4646 insertions(+), 34 deletions(-) delete mode 100755 bower.json create mode 100644 ext/qunit-1.21.1.css create mode 100644 ext/qunit-1.23.1.js mode change 100755 => 100644 package.json diff --git a/bower.json b/bower.json deleted file mode 100755 index 5dda10a..0000000 --- a/bower.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "css.js", - "main": "css.js", - "version": "0.0.1", - "homepage": "https://github.com/cettox/css.js", - "authors": [ - "Kemal DAG " - ], - "description": "A lightweight, fast, stable css parser and utility library", - "keywords": [ - "css", - "css", - "parser", - "css", - "utility" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - "dependencies": { - "jquery": "~2.1.3", - "qunit": "~1.16.0" - } -} diff --git a/css.min.js b/css.min.js index 8a2fdaf..b0e02da 100644 --- a/css.min.js +++ b/css.min.js @@ -1,2 +1,2 @@ -/*! css.js 30-11-2015 */ +/*! css.js 19-04-2016 */ !function(a){"use strict";var b=function(){this.cssImportStatements=[],this.cssKeyframeStatements=[],this.cssRegex=new RegExp("([\\s\\S]*?){([\\s\\S]*?)}","gi"),this.cssMediaQueryRegex="((@media [\\s\\S]*?){([\\s\\S]*?}\\s*?)})",this.cssKeyframeRegex="((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})",this.combinedCSSRegex="((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})",this.cssCommentsRegex="(\\/\\*[\\s\\S]*?\\*\\/)",this.cssImportStatementRegex=new RegExp("@import .*?;","gi")};b.prototype.stripComments=function(a){var b=new RegExp(this.cssCommentsRegex,"gi");return a.replace(b,"")},b.prototype.parseCSS=function(a){if(void 0===a)return[];for(var b=[];;){var c=this.cssImportStatementRegex.exec(a);if(null===c)break;this.cssImportStatements.push(c[0]),b.push({selector:"@imports",type:"imports",styles:c[0]})}a=a.replace(this.cssImportStatementRegex,"");for(var d,e=new RegExp(this.cssKeyframeRegex,"gi");;){if(d=e.exec(a),null===d)break;b.push({selector:"@keyframes",type:"keyframes",styles:d[0]})}a=a.replace(e,"");for(var f=new RegExp(this.combinedCSSRegex,"gi");;){if(d=f.exec(a),null===d)break;var g="";g=void 0===d[2]?d[5].split("\r\n").join("\n").trim():d[2].split("\r\n").join("\n").trim();var h=new RegExp(this.cssCommentsRegex,"gi"),i=h.exec(g);if(null!==i&&(g=g.replace(h,"").trim()),g=g.replace(/\n+/,"\n"),-1!==g.indexOf("@media")){var j={selector:g,type:"media",subStyles:this.parseCSS(d[3]+"\n}")};null!==i&&(j.comments=i[0]),b.push(j)}else{var k=this.parseRules(d[6]),l={selector:g,rules:k};"@font-face"===g&&(l.type="font-face"),null!==i&&(l.comments=i[0]),b.push(l)}}return b},b.prototype.parseRules=function(a){a=a.split("\r\n").join("\n");var b=[];a=a.split(";");for(var c=0;c0&&b.push({directive:"",value:d,defective:!0})}return b},b.prototype.findCorrespondingRule=function(a,b,c){void 0===c&&(c=!1);for(var d=!1,e=0;e-1;f--)if(a[f].selector===b.selector){d=a[f];break}if(d===!1)a.push(b);else if("media"!==b.type)for(var g=0;gc;c++)b+=" ";return b},b.prototype.applyNamespacing=function(a,b){var c=a,d="."+this.cssPreviewNamespace;void 0!==b&&(d=b),"string"==typeof a&&(c=this.parseCSS(a));for(var e=0;e-1||f.selector.indexOf("keyframes")>-1||f.selector.indexOf("@import")>-1||f.selector.indexOf(".form-all")>-1||f.selector.indexOf("#stage")>-1))if("media"!==f.type){for(var g=f.selector.split(","),h=[],i=0;i