Skip to content

Commit ea26144

Browse files
committed
Specify Properties as Matcher rule strings.
This allows us to use the "Formal Syntax" from the CSS spec. It also lets us simplify the code by removing the multiProperty and groupProperty methods from Validation.
1 parent 0b2a4ac commit ea26144

File tree

3 files changed

+63
-166
lines changed

3 files changed

+63
-166
lines changed

src/css/Properties.js

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,59 +12,59 @@ var Properties = {
1212
"alignment-adjust" : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | <percentage> | <length>",
1313
"alignment-baseline" : "auto | baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical",
1414
"animation" : 1,
15-
"animation-delay" : { multi: "<time>", comma: true },
16-
"animation-direction" : { multi: "normal | alternate", comma: true },
17-
"animation-duration" : { multi: "<time>", comma: true },
18-
"animation-fill-mode" : { multi: "none | forwards | backwards | both", comma: true },
19-
"animation-iteration-count" : { multi: "<number> | infinite", comma: true },
20-
"animation-name" : { multi: "none | <single-animation-name>", comma: true },
21-
"animation-play-state" : { multi: "running | paused", comma: true },
15+
"animation-delay" : "<time>#",
16+
"animation-direction" : "[ normal | alternate ]#",
17+
"animation-duration" : "<time>#",
18+
"animation-fill-mode" : "[ none | forwards | backwards | both ]#",
19+
"animation-iteration-count" : "[ <number> | infinite ]#",
20+
"animation-name" : "[ none | <single-animation-name> ]#",
21+
"animation-play-state" : "[ running | paused ]#",
2222
"animation-timing-function" : 1,
2323

2424
//vendor prefixed
25-
"-moz-animation-delay" : { multi: "<time>", comma: true },
26-
"-moz-animation-direction" : { multi: "normal | alternate", comma: true },
27-
"-moz-animation-duration" : { multi: "<time>", comma: true },
28-
"-moz-animation-iteration-count" : { multi: "<number> | infinite", comma: true },
29-
"-moz-animation-name" : { multi: "none | <single-animation-name>", comma: true },
30-
"-moz-animation-play-state" : { multi: "running | paused", comma: true },
25+
"-moz-animation-delay" : "<time>#",
26+
"-moz-animation-direction" : "[ normal | alternate ]#",
27+
"-moz-animation-duration" : "<time>#",
28+
"-moz-animation-iteration-count" : "[ <number> | infinite ]#",
29+
"-moz-animation-name" : "[ none | <single-animation-name> ]#",
30+
"-moz-animation-play-state" : "[ running | paused ]#",
3131

32-
"-ms-animation-delay" : { multi: "<time>", comma: true },
33-
"-ms-animation-direction" : { multi: "normal | alternate", comma: true },
34-
"-ms-animation-duration" : { multi: "<time>", comma: true },
35-
"-ms-animation-iteration-count" : { multi: "<number> | infinite", comma: true },
36-
"-ms-animation-name" : { multi: "none | <single-animation-name>", comma: true },
37-
"-ms-animation-play-state" : { multi: "running | paused", comma: true },
32+
"-ms-animation-delay" : "<time>#",
33+
"-ms-animation-direction" : "[ normal | alternate ]#",
34+
"-ms-animation-duration" : "<time>#",
35+
"-ms-animation-iteration-count" : "[ <number> | infinite ]#",
36+
"-ms-animation-name" : "[ none | <single-animation-name> ]#",
37+
"-ms-animation-play-state" : "[ running | paused ]#",
3838

39-
"-webkit-animation-delay" : { multi: "<time>", comma: true },
40-
"-webkit-animation-direction" : { multi: "normal | alternate", comma: true },
41-
"-webkit-animation-duration" : { multi: "<time>", comma: true },
42-
"-webkit-animation-fill-mode" : { multi: "none | forwards | backwards | both", comma: true },
43-
"-webkit-animation-iteration-count" : { multi: "<number> | infinite", comma: true },
44-
"-webkit-animation-name" : { multi: "none | <single-animation-name>", comma: true },
45-
"-webkit-animation-play-state" : { multi: "running | paused", comma: true },
39+
"-webkit-animation-delay" : "<time>#",
40+
"-webkit-animation-direction" : "[ normal | alternate ]#",
41+
"-webkit-animation-duration" : "<time>#",
42+
"-webkit-animation-fill-mode" : "[ none | forwards | backwards | both ]#",
43+
"-webkit-animation-iteration-count" : "[ <number> | infinite ]#",
44+
"-webkit-animation-name" : "[ none | <single-animation-name> ]#",
45+
"-webkit-animation-play-state" : "[ running | paused ]#",
4646

47-
"-o-animation-delay" : { multi: "<time>", comma: true },
48-
"-o-animation-direction" : { multi: "normal | alternate", comma: true },
49-
"-o-animation-duration" : { multi: "<time>", comma: true },
50-
"-o-animation-iteration-count" : { multi: "<number> | infinite", comma: true },
51-
"-o-animation-name" : { multi: "none | <single-animation-name>", comma: true },
52-
"-o-animation-play-state" : { multi: "running | paused", comma: true },
47+
"-o-animation-delay" : "<time>#",
48+
"-o-animation-direction" : "[ normal | alternate ]#",
49+
"-o-animation-duration" : "<time>#",
50+
"-o-animation-iteration-count" : "[ <number> | infinite ]#",
51+
"-o-animation-name" : "[ none | <single-animation-name> ]#",
52+
"-o-animation-play-state" : "[ running | paused ]#",
5353

5454
"appearance" : "icon | window | desktop | workspace | document | tooltip | dialog | button | push-button | hyperlink | radio | radio-button | checkbox | menu-item | tab | menu | menubar | pull-down-menu | pop-up-menu | list-menu | radio-group | checkbox-group | outline-tree | range | field | combo-box | signature | password | normal | none",
5555
"azimuth" : "<azimuth>",
5656

5757
//B
5858
"backface-visibility" : "visible | hidden",
5959
"background" : 1,
60-
"background-attachment" : { multi: "<attachment>", comma: true },
61-
"background-clip" : { multi: "<box>", comma: true },
60+
"background-attachment" : "<attachment>#",
61+
"background-clip" : "<box>#",
6262
"background-color" : "<color>",
63-
"background-image" : { multi: "<bg-image>", comma: true },
64-
"background-origin" : { multi: "<box>", comma: true },
63+
"background-image" : "<bg-image>#",
64+
"background-origin" : "<box>#",
6565
"background-position" : "<bg-position>",
66-
"background-repeat" : { multi: "<repeat-style>", comma: true },
67-
"background-size" : { multi: "<bg-size>", comma: true },
66+
"background-repeat" : "<repeat-style>#",
67+
"background-size" : "<bg-size>#",
6868
"baseline-shift" : "baseline | sub | super | <percentage> | <length>",
6969
"behavior" : 1,
7070
"binding" : 1,
@@ -81,13 +81,13 @@ var Properties = {
8181
"border-bottom-style" : "<border-style>",
8282
"border-bottom-width" : "<border-width>",
8383
"border-collapse" : "collapse | separate",
84-
"border-color" : { multi: "<color>", max: 4 },
84+
"border-color" : "<color>{1,4}",
8585
"border-image" : 1,
86-
"border-image-outset" : { multi: "<length> | <number>", max: 4 },
87-
"border-image-repeat" : { multi: "stretch | repeat | round", max: 2 },
86+
"border-image-outset" : "[ <length> | <number> ]{1,4}",
87+
"border-image-repeat" : "[ stretch | repeat | round ]{1,2}",
8888
"border-image-slice" : "<border-image-slice>",
8989
"border-image-source" : "<image> | none",
90-
"border-image-width" : { multi: "<length> | <percentage> | <number> | auto", max: 4 },
90+
"border-image-width" : "[ <length> | <percentage> | <number> | auto ]{1,4}",
9191
"border-left" : "<border-width> || <border-style> || <color>",
9292
"border-left-color" : "<color>",
9393
"border-left-style" : "<border-style>",
@@ -97,15 +97,15 @@ var Properties = {
9797
"border-right-color" : "<color>",
9898
"border-right-style" : "<border-style>",
9999
"border-right-width" : "<border-width>",
100-
"border-spacing" : { multi: "<length>", max: 2 },
101-
"border-style" : { multi: "<border-style>", max: 4 },
100+
"border-spacing" : "<length>{1,2}",
101+
"border-style" : "<border-style>{1,4}",
102102
"border-top" : "<border-width> || <border-style> || <color>",
103103
"border-top-color" : "<color>",
104104
"border-top-left-radius" : "<x-one-radius>",
105105
"border-top-right-radius" : "<x-one-radius>",
106106
"border-top-style" : "<border-style>",
107107
"border-top-width" : "<border-width>",
108-
"border-width" : { multi: "<border-width>", max: 4 },
108+
"border-width" : "<border-width>{1,4}",
109109
"bottom" : "<margin-width>",
110110
"-moz-box-align" : "start | end | center | baseline | stretch",
111111
"-moz-box-decoration-break" : "slice |clone",
@@ -290,7 +290,7 @@ var Properties = {
290290
"list-style-type" : "disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none",
291291

292292
//M
293-
"margin" : { multi: "<margin-width>", max: 4 },
293+
"margin" : "<margin-width>{1,4}",
294294
"margin-bottom" : "<margin-width>",
295295
"margin-left" : "<margin-width>",
296296
"margin-right" : "<margin-width>",
@@ -335,7 +335,7 @@ var Properties = {
335335
"overflow-y" : 1,
336336

337337
//P
338-
"padding" : { multi: "<padding-width>", max: 4 },
338+
"padding" : "<padding-width>{1,4}",
339339
"padding-bottom" : "<padding-width>",
340340
"padding-left" : "<padding-width>",
341341
"padding-right" : "<padding-width>",

src/css/Validation.js

Lines changed: 3 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//This file will likely change a lot! Very experimental!
2-
/*global Properties, ValidationTypes, ValidationError, PropertyValueIterator */
2+
/*global Matcher, Properties, ValidationTypes, ValidationError, PropertyValueIterator */
33
/*exported Validation */
44
var Validation = {
55

@@ -28,18 +28,7 @@ var Validation = {
2828
}
2929

3030
// Property-specific validation.
31-
if (typeof spec === "string"){
32-
if (spec.indexOf("||") > -1) {
33-
this.groupProperty(spec, expression);
34-
} else {
35-
this.singleProperty(spec, expression);
36-
}
37-
38-
} else if (spec.multi) {
39-
this.multiProperty(spec.multi, expression, spec.comma, spec.max || Infinity);
40-
} else if (typeof spec === "function") {
41-
spec(expression);
42-
}
31+
this.singleProperty(spec, expression);
4332

4433
}
4534

@@ -51,7 +40,7 @@ var Validation = {
5140
value = expression.value,
5241
part;
5342

54-
result = ValidationTypes.isAny(expression, types);
43+
result = Matcher.parse(types).match(expression);
5544

5645
if (!result) {
5746
if (expression.hasNext() && !expression.isFirst()) {
@@ -65,98 +54,6 @@ var Validation = {
6554
throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
6655
}
6756

68-
},
69-
70-
multiProperty: function (types, expression, comma, max) {
71-
72-
var result = false,
73-
value = expression.value,
74-
count = 0,
75-
part;
76-
77-
while(expression.hasNext() && !result && count < max) {
78-
if (ValidationTypes.isAny(expression, types)) {
79-
count++;
80-
if (!expression.hasNext()) {
81-
result = true;
82-
83-
} else if (comma) {
84-
if (String(expression.peek()) === ",") {
85-
part = expression.next();
86-
} else {
87-
break;
88-
}
89-
}
90-
} else {
91-
break;
92-
93-
}
94-
}
95-
96-
if (!result) {
97-
if (expression.hasNext() && !expression.isFirst()) {
98-
part = expression.peek();
99-
throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
100-
} else {
101-
part = expression.previous();
102-
if (comma && String(part) === ",") {
103-
throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
104-
} else {
105-
throw new ValidationError("Expected (" + types + ") but found '" + value + "'.", value.line, value.col);
106-
}
107-
}
108-
109-
} else if (expression.hasNext()) {
110-
part = expression.next();
111-
throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
112-
}
113-
114-
},
115-
116-
groupProperty: function (types, expression, comma) {
117-
118-
var result = false,
119-
value = expression.value,
120-
typeCount = types.split("||").length,
121-
groups = { count: 0 },
122-
partial = false,
123-
name,
124-
part;
125-
126-
while(expression.hasNext() && !result) {
127-
name = ValidationTypes.isAnyOfGroup(expression, types);
128-
if (name) {
129-
130-
//no dupes
131-
if (groups[name]) {
132-
break;
133-
} else {
134-
groups[name] = 1;
135-
groups.count++;
136-
partial = true;
137-
138-
if (groups.count === typeCount || !expression.hasNext()) {
139-
result = true;
140-
}
141-
}
142-
} else {
143-
break;
144-
}
145-
}
146-
147-
if (!result) {
148-
if (partial && expression.hasNext()) {
149-
part = expression.peek();
150-
throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
151-
} else {
152-
throw new ValidationError("Expected (" + types + ") but found '" + value + "'.", value.line, value.col);
153-
}
154-
} else if (expression.hasNext()) {
155-
part = expression.next();
156-
throw new ValidationError("Expected end of value but found '" + part + "'.", part.line, part.col);
157-
}
15857
}
15958

160-
161-
16259
};

tests/css/Validation.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
],
9393

9494
invalid: {
95-
"1px" : "Expected (none | forwards | backwards | both) but found '1px'."
95+
"1px" : "Expected ([ none | forwards | backwards | both ]#) but found '1px'."
9696
}
9797
}));
9898

@@ -116,8 +116,8 @@
116116
],
117117

118118
invalid: {
119-
"1px" : "Expected (none | <single-animation-name>) but found '1px'.",
120-
"--invalid" : "Expected (none | <single-animation-name>) but found '--invalid'."
119+
"1px" : "Expected ([ none | <single-animation-name> ]#) but found '1px'.",
120+
"--invalid" : "Expected ([ none | <single-animation-name> ]#) but found '--invalid'."
121121
},
122122

123123
error: {
@@ -134,8 +134,8 @@
134134
],
135135

136136
invalid: {
137-
"0" : "Expected (<time>) but found '0'.",
138-
"1px" : "Expected (<time>) but found '1px'."
137+
"0" : "Expected (<time>#) but found '0'.",
138+
"1px" : "Expected (<time>#) but found '1px'."
139139
}
140140
}));
141141

@@ -167,7 +167,7 @@
167167
],
168168

169169
invalid: {
170-
"foo" : "Expected (<attachment>) but found 'foo'."
170+
"foo" : "Expected (<attachment>#) but found 'foo'."
171171
}
172172
}));
173173

@@ -204,7 +204,7 @@
204204
],
205205

206206
invalid: {
207-
"foo" : "Expected (<bg-image>) but found 'foo'.",
207+
"foo" : "Expected (<bg-image>#) but found 'foo'.",
208208
"url(foo.png)," : "Expected end of value but found ','."
209209
}
210210
}));
@@ -262,7 +262,7 @@
262262
],
263263

264264
invalid: {
265-
"foo" : "Expected (<bg-size>) but found 'foo'.",
265+
"foo" : "Expected (<bg-size>#) but found 'foo'.",
266266
"1px 1px 1px" : "Expected end of value but found '1px'."
267267

268268
}
@@ -286,7 +286,7 @@
286286
],
287287

288288
invalid: {
289-
"foo" : "Expected (<repeat-style>) but found 'foo'.",
289+
"foo" : "Expected (<repeat-style>#) but found 'foo'.",
290290
"repeat-x repeat-y" : "Expected end of value but found 'repeat-y'.",
291291
"no-repeat round 1px" : "Expected end of value but found '1px'."
292292

@@ -324,8 +324,8 @@
324324
],
325325

326326
invalid: {
327-
"foo" : "Expected (<color>) but found 'foo'.",
328-
"invert" : "Expected (<color>) but found 'invert'.",
327+
"foo" : "Expected (<color>{1,4}) but found 'foo'.",
328+
"invert" : "Expected (<color>{1,4}) but found 'invert'.",
329329
}
330330
}));
331331

@@ -468,7 +468,7 @@
468468

469469
invalid: {
470470
"1px 0.4em 1px" : "Expected end of value but found '1px'.",
471-
"foo" : "Expected (<length>) but found 'foo'."
471+
"foo" : "Expected (<length>{1,2}) but found 'foo'."
472472
}
473473
}));
474474

@@ -514,7 +514,7 @@
514514

515515
invalid: {
516516
"1px 1px 1px 1px 5px" : "Expected end of value but found '5px'.",
517-
"foo" : "Expected (<border-width>) but found 'foo'."
517+
"foo" : "Expected (<border-width>{1,4}) but found 'foo'."
518518
}
519519
}));
520520

0 commit comments

Comments
 (0)