Skip to content

Commit 88f8652

Browse files
committed
Merge pull request #137 from jawshooah/at-document
Add support for @document, @-moz-document
2 parents 936f5b8 + 12b1af3 commit 88f8652

File tree

7 files changed

+390
-3
lines changed

7 files changed

+390
-3
lines changed

src/css/Parser.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ Parser.prototype = function(){
127127
this._viewport();
128128
this._skipCruft();
129129
break;
130+
case Tokens.DOCUMENT_SYM:
131+
this._document();
132+
this._skipCruft();
133+
break;
130134
case Tokens.UNKNOWN_SYM: //unknown @ rule
131135
tokenStream.get();
132136
if (!this.options.strict){
@@ -368,6 +372,8 @@ Parser.prototype = function(){
368372
this._font_face();
369373
} else if (tokenStream.peek() == Tokens.VIEWPORT_SYM){
370374
this._viewport();
375+
} else if (tokenStream.peek() == Tokens.DOCUMENT_SYM){
376+
this._document();
371377
} else if (!this._ruleset()){
372378
break;
373379
}
@@ -751,6 +757,92 @@ Parser.prototype = function(){
751757

752758
},
753759

760+
_document: function(){
761+
/*
762+
* document
763+
* : DOCUMENT_SYM S*
764+
* _document_function [ ',' S* _document_function ]* S*
765+
* '{' S* ruleset* '}'
766+
* ;
767+
*/
768+
769+
var tokenStream = this._tokenStream,
770+
token,
771+
tt,
772+
functions = [],
773+
prefix = "";
774+
775+
tokenStream.mustMatch(Tokens.DOCUMENT_SYM);
776+
token = tokenStream.token();
777+
if (/^@\-([^\-]+)\-/.test(token.value)) {
778+
prefix = RegExp.$1;
779+
}
780+
781+
this._readWhitespace();
782+
functions.push(this._document_function());
783+
784+
while(tokenStream.match(Tokens.COMMA)) {
785+
this._readWhitespace();
786+
functions.push(this._document_function());
787+
}
788+
789+
tokenStream.mustMatch(Tokens.LBRACE);
790+
this._readWhitespace();
791+
792+
this.fire({
793+
type: "startdocument",
794+
functions: functions,
795+
prefix: prefix,
796+
line: token.startLine,
797+
col: token.startCol
798+
});
799+
800+
while(true) {
801+
if (tokenStream.peek() == Tokens.PAGE_SYM){
802+
this._page();
803+
} else if (tokenStream.peek() == Tokens.FONT_FACE_SYM){
804+
this._font_face();
805+
} else if (tokenStream.peek() == Tokens.VIEWPORT_SYM){
806+
this._viewport();
807+
} else if (tokenStream.peek() == Tokens.MEDIA_SYM){
808+
this._media();
809+
} else if (!this._ruleset()){
810+
break;
811+
}
812+
}
813+
814+
tokenStream.mustMatch(Tokens.RBRACE);
815+
this._readWhitespace();
816+
817+
this.fire({
818+
type: "enddocument",
819+
functions: functions,
820+
prefix: prefix,
821+
line: token.startLine,
822+
col: token.startCol
823+
});
824+
},
825+
826+
_document_function: function(){
827+
/*
828+
* document_function
829+
* : function | URI S*
830+
* ;
831+
*/
832+
833+
var tokenStream = this._tokenStream,
834+
value;
835+
836+
if (tokenStream.match(Tokens.URI)) {
837+
value = tokenStream.token().value;
838+
this._readWhitespace();
839+
} else {
840+
value = this._function();
841+
}
842+
843+
return value;
844+
},
845+
754846
_operator: function(inFunction){
755847

756848
/*

src/css/TokenStream.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -510,17 +510,18 @@ TokenStream.prototype = mix(new TokenStreamBase(), {
510510
identOrFunctionToken: function(first, startLine, startCol){
511511
var reader = this._reader,
512512
ident = this.readName(first),
513-
tt = Tokens.IDENT;
513+
tt = Tokens.IDENT,
514+
uriFns = ["url(", "url-prefix(", "domain("];
514515

515516
//if there's a left paren immediately after, it's a URI or function
516517
if (reader.peek() == "("){
517518
ident += reader.read();
518-
if (ident.toLowerCase() == "url("){
519+
if (uriFns.indexOf(ident.toLowerCase()) > -1){
519520
tt = Tokens.URI;
520521
ident = this.readURI(ident);
521522

522523
//didn't find a valid URL or there's no closing paren
523-
if (ident.toLowerCase() == "url("){
524+
if (uriFns.indexOf(ident.toLowerCase()) > -1){
524525
tt = Tokens.FUNCTION;
525526
}
526527
} else {

src/css/Tokens.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ var Tokens = [
3232
{ name: "CHARSET_SYM", text: "@charset"},
3333
{ name: "NAMESPACE_SYM", text: "@namespace"},
3434
{ name: "VIEWPORT_SYM", text: ["@viewport", "@-ms-viewport", "@-o-viewport"]},
35+
{ name: "DOCUMENT_SYM", text: ["@document", "@-moz-document"]},
3536
{ name: "UNKNOWN_SYM" },
3637
//{ name: "ATKEYWORD"},
3738

tests/css/CSSParserTests.htm

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,148 @@ <h1>CSS Parser Tests</h1>
14461446
assert.isTrue(true); //just don't want an error
14471447
},
14481448

1449+
testDocumentUrl: function(){
1450+
var parser = new Parser({ strict: true}),
1451+
valid = true;
1452+
1453+
parser.addListener("error", function(event) {
1454+
valid = false;
1455+
});
1456+
1457+
var result = parser.parse("@document url(http://www.w3.org/) { p { color: red; } }");
1458+
assert.isTrue(valid);
1459+
},
1460+
1461+
testDocumentUrlPrefix: function(){
1462+
var parser = new Parser({ strict: true}),
1463+
valid = true;
1464+
1465+
parser.addListener("error", function(event) {
1466+
valid = false;
1467+
});
1468+
1469+
var result = parser.parse("@document url-prefix(http://www.w3.org/) { p { color: red; } }");
1470+
assert.isTrue(valid);
1471+
},
1472+
1473+
testDocumentDomain: function(){
1474+
var parser = new Parser({ strict: true}),
1475+
valid = true;
1476+
1477+
parser.addListener("error", function(event) {
1478+
valid = false;
1479+
});
1480+
1481+
var result = parser.parse("@document domain(w3.org) { p { color: red; } }");
1482+
assert.isTrue(valid);
1483+
},
1484+
1485+
testDocumentRegexp: function(){
1486+
var parser = new Parser({ strict: true}),
1487+
valid = true;
1488+
1489+
parser.addListener("error", function(event) {
1490+
valid = false;
1491+
});
1492+
1493+
var result = parser.parse("@document regexp('https:.*') { p { color: red; } }");
1494+
assert.isTrue(valid);
1495+
},
1496+
1497+
testDocumentMultipleFunctions: function(){
1498+
var parser = new Parser({ strict: true}),
1499+
valid = true;
1500+
1501+
parser.addListener("error", function(event) {
1502+
valid = false;
1503+
});
1504+
1505+
var result = parser.parse("@document url-prefix(http://www.w3.org/), domain(w3.org) { p { color: red; } }");
1506+
assert.isTrue(valid);
1507+
},
1508+
1509+
testMozDocument: function(){
1510+
var parser = new Parser({ strict: true}),
1511+
valid = true;
1512+
1513+
parser.addListener("error", function(event) {
1514+
valid = false;
1515+
});
1516+
1517+
var result = parser.parse("@-moz-document url-prefix() { p { color: red; } }");
1518+
assert.isTrue(valid);
1519+
},
1520+
1521+
testDocumentWithPage: function(){
1522+
var parser = new Parser({ strict: true}),
1523+
valid = true;
1524+
1525+
parser.addListener("error", function(event) {
1526+
valid = false;
1527+
});
1528+
1529+
var result = parser.parse("@document url-prefix() { @page {} p { color: red; } }");
1530+
assert.isTrue(valid);
1531+
},
1532+
1533+
testDocumentWithMedia: function(){
1534+
var parser = new Parser({ strict: true}),
1535+
valid = true;
1536+
1537+
parser.addListener("error", function(event) {
1538+
valid = false;
1539+
});
1540+
1541+
var result = parser.parse("@document url-prefix() { @media {} p { color: red; } }");
1542+
assert.isTrue(valid);
1543+
},
1544+
1545+
testDocumentWithFontFace: function(){
1546+
var parser = new Parser({ strict: true}),
1547+
valid = true;
1548+
1549+
parser.addListener("error", function(event) {
1550+
valid = false;
1551+
});
1552+
1553+
var result = parser.parse("@document url-prefix() { @font-face {} p { color: red; } }");
1554+
assert.isTrue(valid);
1555+
},
1556+
1557+
testDocumentWithViewport: function(){
1558+
var parser = new Parser({ strict: true}),
1559+
valid = true;
1560+
1561+
parser.addListener("error", function(event) {
1562+
valid = false;
1563+
});
1564+
1565+
var result = parser.parse("@document url-prefix() { @viewport {} p { color: red; } }");
1566+
assert.isTrue(valid);
1567+
},
1568+
1569+
testDocumentEventFires: function(){
1570+
var parser = new Parser({ strict:true}),
1571+
calledStart = false,
1572+
calledEnd = false;
1573+
1574+
parser.addListener("startdocument", function(event) {
1575+
assert.areEqual(1, event.line, "Line should be 1");
1576+
assert.areEqual(1, event.col, "Column should be 1");
1577+
calledStart = true;
1578+
});
1579+
1580+
parser.addListener("enddocument", function(event) {
1581+
assert.areEqual(1, event.line, "Line should be 1");
1582+
assert.areEqual(1, event.col, "Column should be 1");
1583+
calledEnd = true;
1584+
});
1585+
1586+
var result = parser.parse("@document url-prefix() {}");
1587+
assert.isTrue(calledStart); //just don't want an error
1588+
assert.isTrue(calledEnd); //just don't want an error
1589+
},
1590+
14491591
testClassesWithEscapes: function(){
14501592
var parser = new Parser({strict:true});
14511593
var result = parser.parseSelector("#\\31 a2b3c");

tests/css/CSSTokensTests.htm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ <h1>CSS Tokens Tests</h1>
186186
"@-ms-viewport" : CSSTokens.VIEWPORT_SYM,
187187
"@viewport" : CSSTokens.VIEWPORT_SYM,
188188

189+
"@-moz-document" : CSSTokens.DOCUMENT_SYM,
190+
"@document" : CSSTokens.DOCUMENT_SYM,
191+
189192
//animation
190193
"@-webkit-keyframes": CSSTokens.KEYFRAMES_SYM,
191194
"@-moz-keyframes" : CSSTokens.KEYFRAMES_SYM,

0 commit comments

Comments
 (0)