Skip to content

Commit

Permalink
Refactoring .add method
Browse files Browse the repository at this point in the history
  • Loading branch information
Krasimir Tsonev committed Dec 22, 2013
1 parent 07f3268 commit 2a350e3
Show file tree
Hide file tree
Showing 14 changed files with 235 additions and 327 deletions.
181 changes: 84 additions & 97 deletions client-side/build/absurd.js
@@ -1,4 +1,4 @@
/* version: 0.1.21 */
/* version: 0.2.0 */
var Absurd = (function(w) {
var lib = {
api: {},
Expand Down Expand Up @@ -455,140 +455,127 @@ var client = function() {
lib.api.add = function(API) {
var extend = require("../helpers/Extend");
var clone = require("../helpers/Clone");
var checkAndExecutePlugin = function(selector, prop, value, stylesheet) {
var toRegister = [];
var checkAndExecutePlugin = function(selector, prop, value, stylesheet, parentSelector) {
var plugin = API.getPlugins()[prop];
if(typeof plugin !== 'undefined') {
var pluginResponse = plugin(API, value);
if(pluginResponse) {
addRule(selector, pluginResponse, stylesheet);
addRule(selector, pluginResponse, stylesheet, parentSelector);
}
return true;
} else {
return false;
}
}
var clearing = function(props) {
// plugins
var plugins = API.getPlugins();
for(var prop in props) {
if(typeof plugins[prop] !== 'undefined') {
props[prop] = false;
}
}
// pseudo classes
for(var prop in props) {
if(prop.charAt(0) === ":") {
props[prop] = false;
}
}
// ampersand
for(var prop in props) {
if(/&/g.test(prop)) {
props[prop] = false;
}
}
}
var checkForNesting = function(selector, props, stylesheet) {
for(var prop in props) {
if(typeof props[prop] === 'object') {
// check for pseudo classes
if(prop.charAt(0) === ":") {
addRule(selector + prop, props[prop], stylesheet);
// check for ampersand operator
} else if(/&/g.test(prop)) {
addRule(prop.replace(/&/g, selector), props[prop], stylesheet);
// check for media query
} else if(prop.indexOf("@media") === 0 || prop.indexOf("@supports") === 0) {
addRule(selector, props[prop], prop);
// check for media query
} else if(selector.indexOf("@media") === 0 || prop.indexOf("@supports") === 0) {
addRule(prop, props[prop], selector);
// check for plugins
} else if(checkAndExecutePlugin(selector, prop, props[prop], stylesheet) === false) {
addRule(selector + " " + prop, props[prop], stylesheet);
}
props[prop] = false;
} else if(typeof props[prop] === 'function') {
props[prop] = props[prop]();
checkForNesting(selector, props, stylesheet);
} else {
if(checkAndExecutePlugin(selector, prop, props[prop], stylesheet)) {
props[prop] = false;
}
var addRule = function(selector, props, stylesheet, parentSelector) {
// console.log("\n---------- addRule ---------", selector, ".........", parentSelector, "\n", props);

stylesheet = stylesheet || "mainstream";

if(/, ?/g.test(selector)) {
var parts = selector.replace(/, /g, ',').split(',');
for(var i=0; i<parts.length, p=parts[i]; i++) {
addRule(p, props, stylesheet, parentSelector);
}
return;
}
}
var addRule = function(selector, props, stylesheet) {

// if array is passed as props
if(typeof props.length !== 'undefined' && typeof props === "object") {
for(var i=0; prop=props[i]; i++) {
addRule(selector, prop, stylesheet);
for(var i=0; i<props.length, prop=props[i]; i++) {
addRule(selector, prop, stylesheet, parentSelector);
}
return;
}

// check for plugin
if(checkAndExecutePlugin(null, selector, props, stylesheet)) {
if(checkAndExecutePlugin(null, selector, props, stylesheet, parentSelector)) {
return;
}

// if the selector is already there
if(typeof API.getRules(stylesheet || "mainstream")[selector] == 'object') {
var current = API.getRules(stylesheet || "mainstream")[selector];
for(var propNew in props) {
// overwrite already added value
if(typeof props[propNew] != 'object') {
current[propNew] = props[propNew];
var _props = {},
_selector = selector,
_objects = {},
_functions = {};

// processing props
for(var prop in props) {
var type = typeof props[prop];
if(type !== 'object' && type !== 'function') {
if(checkAndExecutePlugin(selector, prop, props[prop], stylesheet, parentSelector) === false) {
_selector = typeof parentSelector !== "undefined" ? parentSelector + " " + selector : selector;
_props[prop] = props[prop];
}
} else if(type === 'object') {
_objects[prop] = props[prop];
} else if(type === 'function') {
_functions[prop] = props[prop];
}
// no, the selector is still not added
} else {
API.getRules(stylesheet || "mainstream")[selector] = props;
}

checkForNesting(selector, props, stylesheet || "mainstream");
clearing(props);

}
var prepareRules = function(obj) {
if(obj instanceof Array) {
for(var i=0; i<obj.length; i++) {
prepareRules(obj[i]);
toRegister.push({
selector: _selector,
props: _props,
stylesheet: stylesheet
});

for(var prop in _objects) {
// check for pseudo classes
if(prop.charAt(0) === ":") {
addRule(selector + prop, _objects[prop], stylesheet, parentSelector);
// check for ampersand operator
} else if(/&/g.test(prop)) {
addRule(prop.replace(/&/g, selector), _objects[prop], stylesheet, parentSelector);
// check for media query
} else if(prop.indexOf("@media") === 0 || prop.indexOf("@supports") === 0) {
addRule(selector, _objects[prop], prop, parentSelector);
// check for media query
} else if(selector.indexOf("@media") === 0 || prop.indexOf("@supports") === 0) {
addRule(prop, _objects[prop], selector, parentSelector);
// check for plugins
} else if(checkAndExecutePlugin(selector, prop, _objects[prop], stylesheet, parentSelector) === false) {
addRule(prop, _objects[prop], stylesheet, (parentSelector ? parentSelector + " " : "") + selector);
}
return;
}
for(var prop in obj) {
var value = obj[prop];
if(typeof value == 'object') {
prepareRules(value);
}
if(/, ?/g.test(prop)) {
var parts = prop.replace(/, /g, ',').split(',');
for(var i=0; i<parts.length, p=parts[i]; i++) {
if(obj[p]) {
obj[p] = extend({}, obj[p], value);
} else {
obj[p] = extend({}, value);
}
}
delete obj[prop];
}

for(var prop in _functions) {
var o = {};
o[prop] = _functions[prop]();
addRule(selector, o, stylesheet, parentSelector);
}

}
var add = function(rules, stylesheet) {
rules = clone(rules);

toRegister = [];
API.numOfAddedRules += 1;
prepareRules(rules);

for(var selector in rules) {
if(rules[selector] instanceof Array) {
for(var i=0; i<rules[selector].length, r=rules[selector][i]; i++) {
addRule(selector, r, stylesheet || "mainstream");
addRule(selector, rules[selector], stylesheet || "mainstream");
}

// if the selector is already there
for(var i=0; i<toRegister.length; i++) {
var stylesheet = toRegister[i].stylesheet,
selector = toRegister[i].selector,
props = toRegister[i].props,
allRules = API.getRules(stylesheet);
// console.log(selector, props);
if(typeof allRules[selector] == 'object') {
var current = allRules[selector];
for(var propNew in props) {
// overwrite already added value
if(typeof props[propNew] != 'object') {
current[propNew] = props[propNew];
}
}
// no, the selector is still not added
} else {
addRule(selector, rules[selector], stylesheet || "mainstream");
allRules[selector] = props;
}
}

return API;
}
return add;
Expand Down
2 changes: 1 addition & 1 deletion client-side/build/absurd.min.js

Large diffs are not rendered by default.

18 changes: 10 additions & 8 deletions client-side/tests/tests.from.node.js
Expand Up @@ -202,9 +202,9 @@ describe("Media queries", function() {
}).compile(function(err, css) {
expect(err).toBe(null);
expect(css).toBeDefined();
expect(css).toContain("body {\n line-height: 20px;\n}\nbody p {\n margin: 10px;\n padding: 4px;\n}\n@media all (max-width: 950px) {\nbody {\n line-height: 40px;\n color: #BADA55;\n}\nbody p {\n color: #9fA;\n padding: 12px;\n}\n}\n@media all (min-width: 550px) {\nbody {\n line-height: 32px;\n}\n}\n");
expect(css).toBe('body{line-height: 20px;}body p{margin: 10px;padding: 4px;}@media all (max-width: 950px) {body{line-height: 40px;color: #BADA55;}body p{color: #9fA;padding: 12px;}}@media all (min-width: 550px) {body{line-height: 32px;}}');
done();
});
}, {minify: true});
});

});
Expand Down Expand Up @@ -291,7 +291,10 @@ describe("Nested selectors", function() {
'font-size': '16px',
'text-shadow': '2px 2px #00F',
a: {
'text-decoration': 'none'
'text-decoration': 'none',
span: {
fontSize: '10px'
}
}
}
}
Expand All @@ -300,10 +303,9 @@ describe("Nested selectors", function() {
}).compile(function(err, css) {
expect(err).toBe(null);
expect(css).toBeDefined();
expect(css).toContain('.content p');
expect(css).toContain('.content p a');
expect(css).toContain('.content p{font-size: 16px;text-shadow: 2px 2px #00F;}.content p a{text-decoration: none;}.content p a span{font-size: 10px;}');
done();
});
}, {minify: true});
});

});
Expand Down Expand Up @@ -595,7 +597,7 @@ describe("Use ampersand operator", function() {
}).compile(function(err, css) {
expect(err).toBe(null);
expect(css).toBeDefined();
expect(css).toBe("a{color: red;}a:hover{color: blue;}a.fancy{color: green;}.ie6 a.fancy{color: yellow;}.ie7 a.fancy{color: black;}.ie6 a:hover,.ie7 a:hover{color: orange;}");
expect(css).toBe('a{color: red;}a:hover{color: blue;}a.fancy{color: green;}.ie6 a:hover,.ie7 a:hover{color: orange;}.ie6 a.fancy{color: yellow;}.ie7 a.fancy{color: black;}');
done();
}, { minify: true })
});
Expand Down Expand Up @@ -904,7 +906,7 @@ describe("Multiple selectors per rule overwrite all individual selectors", funct
}).compile(function(err, css) {
expect(err).toBe(null);
expect(css).toBeDefined();
expect(css).toBe("body{background: blue;}html{background: pink;}body,html{color: red;}");
expect(css).toBe("html,body{color: red;}html{background: pink;}body{background: blue;}");
done();
}, { minify: true });
});
Expand Down

0 comments on commit 2a350e3

Please sign in to comment.