Skip to content

Commit

Permalink
Merge pull request #32 from papandreou/morekeyframes
Browse files Browse the repository at this point in the history
Support for @Keyframes and @-moz-keyframes rules.
  • Loading branch information
Nikita Vasilyev authored and Nikita Vasilyev committed Feb 17, 2012
2 parents dc430dd + f63659b commit fdc11b8
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 12 deletions.
2 changes: 1 addition & 1 deletion lib/CSSKeyframesRule.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ CSSOM.CSSKeyframesRule.prototype.__defineGetter__("cssText", function() {
for (var i=0, length=this.cssRules.length; i < length; i++) {
cssTexts.push(" " + this.cssRules[i].cssText);
}
return "@-webkit-keyframes " + this.name + " { \n" + cssTexts.join("\n") + "\n}";
return "@" + (this._vendorPrefix || '') + "keyframes " + this.name + " { \n" + cssTexts.join("\n") + "\n}";
});


Expand Down
25 changes: 16 additions & 9 deletions lib/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ CSSOM.parse = function parse(token) {

var selector, name, value, priority="", styleRule, mediaRule, importRule, keyframesRule, keyframeRule;

var atKeyframesRegExp = /@(-(?:\w+-)+)?keyframes/g;

for (var character; character = token.charAt(i); i++) {

switch (character) {
Expand Down Expand Up @@ -134,15 +136,20 @@ CSSOM.parse = function parse(token) {
i += "import".length;
buffer += "@import";
break;
} else if (token.indexOf("@-webkit-keyframes", i) === i) {
state = "keyframesRule-begin";
keyframesRule = new CSSOM.CSSKeyframesRule;
keyframesRule.__starts = i;
i += "-webkit-keyframes".length;
buffer = "";
break;
} else if (state === "selector") {
state = "atRule";
} else {
atKeyframesRegExp.lastIndex = i;
var matchKeyframes = atKeyframesRegExp.exec(token);
if (matchKeyframes && matchKeyframes.index === i) {
state = "keyframesRule-begin";
keyframesRule = new CSSOM.CSSKeyframesRule;
keyframesRule.__starts = i;
keyframesRule._vendorPrefix = matchKeyframes[1]; // Will come out as undefined if no prefix was found
i += matchKeyframes[0].length - 1;
buffer = "";
break;
} else if (state == "selector") {
state = "atRule";
}
}
buffer += character;
break;
Expand Down
126 changes: 124 additions & 2 deletions spec/parse.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -707,13 +707,134 @@ var TESTS = [
return result;
})()
},
{
// Non-vendor prefixed @keyframes rule, from Twitter Bootstrap (progress-bars):
input: '@keyframes progress-bar-stripes {\n from { background-position: 0 0; }\n to { background-position: 40px 0; }\n}',
result: (function () {
var result = {
cssRules: [
{
name: "progress-bar-stripes",
_vendorPrefix: undefined,
cssRules: [
{
keyText: "from",
style: {
0: "background-position",
'background-position': "0 0",
length: 1
}
},
{
keyText: "to",
style: {
0: "background-position",
'background-position': "40px 0",
length: 1
}
}
],
parentRule: null
}
],
parentStyleSheet: null
};
result.cssRules[0].parentStyleSheet = result.cssRules[0].cssRules[0].parentStyleSheet = result.cssRules[0].cssRules[1].parentStyleSheet = result;
result.cssRules[0].cssRules[0].parentRule = result.cssRules[0].cssRules[1].parentRule = result.cssRules[0];
result.cssRules[0].cssRules[0].style.parentRule = result.cssRules[0].cssRules[0];
result.cssRules[0].cssRules[1].style.parentRule = result.cssRules[0].cssRules[1];
return result;
})()
},
{
// @keyframes with invalid vendor prefix followed by a valid one (make sure that the RegExp.lastIndex trick works as expected):
input: '@-moz-keyframes foo {} @--keyframes bar {} @-webkit-keyframes quux {}',
result: (function () {
var result = {
cssRules: [
{
name: "foo",
_vendorPrefix: "-moz-",
cssRules: [],
parentRule: null
},
{
selectorText: "@--keyframes bar",
style: {
length: 0
},
parentRule: null,
__starts: 0,
__ends: 14
},
{
name: "quux",
_vendorPrefix: "-webkit-",
cssRules: [],
parentRule: null
}
],
parentStyleSheet: null
};
result.cssRules[0].parentStyleSheet = result.cssRules[1].parentStyleSheet = result.cssRules[2].parentStyleSheet = result;
result.cssRules[1].style.parentRule = result.cssRules[1];
return result;
})()
},
{
input: "@-some-ridiculously-long-vendor-prefix-that-must-be-supported-keyframes therulename /*comment*/{0%{top:0px; left:0px; background:red;}100% {top:4em; left:40px; background:maroon;}}",
result: (function() {
var result = {
cssRules: [
{
name: "therulename",
_vendorPrefix: '-some-ridiculously-long-vendor-prefix-that-must-be-supported-',
cssRules: [
{
keyText: "0%",
style: {
0: "top",
1: "left",
2: "background",
top: "0px",
left: "0px",
background: "red",
length: 3
}
},
{
keyText: "100%",
style: {
0: "top",
1: "left",
2: "background",
top: "4em",
left: "40px",
background: "maroon",
length: 3
}
}
],
parentRule: null
}
],
parentStyleSheet: null
};
result.cssRules[0].parentStyleSheet = result.cssRules[0].cssRules[0].parentStyleSheet = result.cssRules[0].cssRules[1].parentStyleSheet = result;
result.cssRules[0].cssRules[0].parentRule = result.cssRules[0].cssRules[1].parentRule = result.cssRules[0];
result.cssRules[0].cssRules[0].style.parentRule = result.cssRules[0].cssRules[0];
result.cssRules[0].cssRules[1].style.parentRule = result.cssRules[0].cssRules[1];
return result;
})()
},
{
input: "@-webkit-keyframes mymove {\nfrom {top:0px}\nto {top:200px}\n}",
result: (function() {
var result = {
cssRules: [
{
name: "mymove",
_vendorPrefix: '-webkit-',
cssRules: [
{
keyText: "from",
Expand Down Expand Up @@ -751,6 +872,7 @@ var TESTS = [
cssRules: [
{
name: "mymovepercent",
_vendorPrefix: '-webkit-',
cssRules: [
{
keyText: "0%",
Expand Down Expand Up @@ -813,7 +935,7 @@ describe('parse', function() {
});

/**
* Recurcively remove all keys which start with '_'
* Recursively remove all keys which start with '_', except "_vendorPrefix", which needs to be tested against.
* @param {Object} object
*/
function removeUnderscored(object) {
Expand All @@ -823,7 +945,7 @@ function removeUnderscored(object) {
var keys = Object.keys(object);
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i];
if (key[0] === '_') {
if (key[0] === '_' && key !== '_vendorPrefix') {
delete object[key];
} else {
var value = object[key];
Expand Down

0 comments on commit fdc11b8

Please sign in to comment.