Skip to content

Commit c691e5c

Browse files
committed
Simplify ValidationTypes using Matcher framework.
As a side-effect, we also pushed handling the `inherit` option out of most ValidationTypes and moved it into the specification in the Properties table. I expect to refactor this further in the future to make handling of inherit/initial/unset automatic and implicit.
1 parent d7f7d8c commit c691e5c

File tree

3 files changed

+55
-215
lines changed

3 files changed

+55
-215
lines changed

src/css/Properties.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ var Properties = {
104104
"border" : "<border-width> || <border-style> || <color>",
105105
"border-bottom" : "<border-width> || <border-style> || <color>",
106106
"border-bottom-color" : "<color> | inherit",
107-
"border-bottom-left-radius" : "<x-one-radius>",
108-
"border-bottom-right-radius" : "<x-one-radius>",
107+
"border-bottom-left-radius" : "<x-one-radius> | inherit",
108+
"border-bottom-right-radius" : "<x-one-radius> | inherit",
109109
"border-bottom-style" : "<border-style>",
110110
"border-bottom-width" : "<border-width>",
111111
"border-collapse" : "collapse | separate | inherit",
@@ -198,8 +198,8 @@ var Properties = {
198198
"border-style" : { multi: "<border-style>", max: 4 },
199199
"border-top" : "<border-width> || <border-style> || <color>",
200200
"border-top-color" : "<color> | inherit",
201-
"border-top-left-radius" : "<x-one-radius>",
202-
"border-top-right-radius" : "<x-one-radius>",
201+
"border-top-left-radius" : "<x-one-radius> | inherit",
202+
"border-top-right-radius" : "<x-one-radius> | inherit",
203203
"border-top-style" : "<border-style>",
204204
"border-top-width" : "<border-width>",
205205
"border-width" : { multi: "<border-width>", max: 4 },

src/css/ValidationTypes.js

Lines changed: 43 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -557,208 +557,48 @@ ValidationTypes = {
557557
return result;
558558
},
559559

560-
"<bg-size>": function(expression){
561-
//<bg-size> = [ <length> | <percentage> | auto ]{1,2} | cover | contain
562-
var result = false,
563-
numeric = "<percentage> | <length> | auto";
564-
565-
if (ValidationTypes.isAny(expression, "cover | contain")) {
566-
result = true;
567-
} else if (ValidationTypes.isAny(expression, numeric)) {
568-
result = true;
569-
ValidationTypes.isAny(expression, numeric);
570-
}
571-
572-
return result;
573-
},
574-
575-
"<clip-source>": function(expression){
576-
return ValidationTypes.isAny(expression, "<uri>");
577-
},
578-
579-
"<clip-path>": function(expression) {
580-
// <basic-shape> || <geometry-box>
581-
var result = false;
582-
583-
if (ValidationTypes.isType(expression, "<basic-shape>")) {
584-
result = true;
585-
if (expression.hasNext()) {
586-
result = ValidationTypes.isType(expression, "<geometry-box>");
587-
}
588-
} else if (ValidationTypes.isType(expression, "<geometry-box>")) {
589-
result = true;
590-
if (expression.hasNext()) {
591-
result = ValidationTypes.isType(expression, "<basic-shape>");
592-
}
593-
}
594-
595-
return result && !expression.hasNext();
596-
597-
},
598-
599-
"<filter-function-list>": function(expression){
600-
var result, part, i;
601-
for (i = 0, result = true; result && expression.hasNext(); i++) {
602-
result = ValidationTypes.isAny(expression, "<filter-function> | <uri>");
603-
}
604-
605-
if (i > 1 && !result) {
606-
// More precise error message if we fail after the first
607-
// parsed <filter-function>.
608-
part = expression.peek();
609-
throw new ValidationError("Expected (<filter-function> | <uri>) but found '" + part.text + "'.", part.line, part.col);
610-
}
611-
612-
return result;
613-
614-
},
615-
616-
"<repeat-style>": function(expression){
617-
//repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2}
618-
var result = false,
619-
values = "repeat | space | round | no-repeat",
620-
part;
621-
622-
if (expression.hasNext()){
623-
part = expression.next();
624-
625-
if (ValidationTypes.isLiteral(part, "repeat-x | repeat-y")) {
626-
result = true;
627-
} else if (ValidationTypes.isLiteral(part, values)) {
628-
result = true;
629-
630-
if (expression.hasNext() && ValidationTypes.isLiteral(expression.peek(), values)) {
631-
expression.next();
632-
}
633-
}
634-
}
635-
636-
return result;
637-
638-
},
639-
640-
"<shadow>": function(expression) {
641-
//inset? && [ <length>{2,4} && <color>? ]
642-
var result = false,
643-
count = 0,
644-
inset = false,
645-
color = false;
646-
647-
if (expression.hasNext()) {
648-
649-
if (ValidationTypes.isAny(expression, "inset")){
650-
inset = true;
651-
}
652-
653-
if (ValidationTypes.isAny(expression, "<color>")) {
654-
color = true;
655-
}
656-
657-
while (ValidationTypes.isAny(expression, "<length>") && count < 4) {
658-
count++;
659-
}
660-
661-
662-
if (expression.hasNext()) {
663-
if (!color) {
664-
ValidationTypes.isAny(expression, "<color>");
665-
}
666-
667-
if (!inset) {
668-
ValidationTypes.isAny(expression, "inset");
669-
}
670-
671-
}
672-
673-
result = (count >= 2 && count <= 4);
674-
675-
}
676-
677-
return result;
678-
},
679-
680-
"<x-one-radius>": function(expression) {
681-
//[ <length> | <percentage> ] [ <length> | <percentage> ]?
682-
var result = false,
683-
simple = "<length> | <percentage> | inherit";
684-
685-
if (ValidationTypes.isAny(expression, simple)){
686-
result = true;
687-
ValidationTypes.isAny(expression, simple);
688-
}
689-
690-
return result;
691-
},
692-
693-
"<flex>": function(expression) {
694-
// http://www.w3.org/TR/2014/WD-css-flexbox-1-20140325/#flex-property
695-
// none | [ <flex-grow> <flex-shrink>? || <flex-basis> ]
696-
// Valid syntaxes, according to https://developer.mozilla.org/en-US/docs/Web/CSS/flex#Syntax
697-
// * none
698-
// * <flex-grow>
699-
// * <flex-basis>
700-
// * <flex-grow> <flex-basis>
701-
// * <flex-grow> <flex-shrink>
702-
// * <flex-grow> <flex-shrink> <flex-basis>
703-
// * inherit
704-
var part,
705-
result = false;
706-
if (ValidationTypes.isAny(expression, "none | inherit")) {
707-
result = true;
708-
} else {
709-
if (ValidationTypes.isType(expression, "<flex-grow>")) {
710-
if (expression.peek()) {
711-
if (ValidationTypes.isType(expression, "<flex-shrink>")) {
712-
if (expression.peek()) {
713-
result = ValidationTypes.isType(expression, "<flex-basis>");
714-
} else {
715-
result = true;
716-
}
717-
} else if (ValidationTypes.isType(expression, "<flex-basis>")) {
718-
result = expression.peek() === null;
719-
}
720-
} else {
721-
result = true;
722-
}
723-
} else if (ValidationTypes.isType(expression, "<flex-basis>")) {
724-
result = true;
725-
}
726-
}
727-
728-
if (!result) {
729-
// Generate a more verbose error than "Expected <flex>..."
730-
part = expression.peek();
731-
throw new ValidationError("Expected (none | [ <flex-grow> <flex-shrink>? || <flex-basis> ]) but found '" + expression.value.text + "'.", part.line, part.col);
732-
}
733-
734-
return result;
735-
},
736-
737-
"<text-decoration>": function(expression) {
738-
// none | [ underline || overline || line-through || blink ] | inherit
739-
var part,
740-
result,
741-
someOf = "[ underline || overline || line-through || blink ]",
742-
identifiers = {},
743-
found;
744-
745-
do {
746-
part = expression.next();
747-
found = 0;
748-
if (someOf.indexOf(part) > -1) {
749-
if (!identifiers[part]) {
750-
identifiers[part] = 0;
751-
}
752-
identifiers[part]++;
753-
found = identifiers[part];
754-
}
755-
} while (found == 1 && expression.hasNext());
756-
757-
result = found == 1 && !expression.hasNext();
758-
if (found === 0 && JSON.stringify(identifiers) == '{}') {
759-
expression.previous();
760-
}
761-
return result;
762-
}
560+
"<bg-size>":
561+
//<bg-size> = [ <length> | <percentage> | auto ]{1,2} | cover | contain
562+
Matcher.alt("cover", "contain", Matcher.cast("<percentage> | <length> | auto").braces(1,2)),
563+
564+
"<clip-source>": Matcher.cast("<uri>"),
565+
566+
"<clip-path>":
567+
// <basic-shape> || <geometry-box>
568+
Matcher.cast("<basic-shape>").oror("<geometry-box>"),
569+
570+
"<filter-function-list>":
571+
// [ <filter-function> | <uri> ]+
572+
Matcher.cast("<filter-function> | <uri>").plus(),
573+
574+
"<repeat-style>":
575+
//repeat-x | repeat-y | [repeat | space | round | no-repeat]{1,2}
576+
Matcher.alt("repeat-x | repeat-y", Matcher.cast("repeat | space | round | no-repeat").braces(1,2)),
577+
578+
"<shadow>":
579+
//inset? && [ <length>{2,4} && <color>? ]
580+
Matcher.many([true /* length is required */],
581+
Matcher.cast("<length>").braces(2,4), "inset", "<color>"),
582+
583+
"<x-one-radius>":
584+
//[ <length> | <percentage> ] [ <length> | <percentage> ]?
585+
Matcher.cast("<length> | <percentage>").braces(1,2),
586+
587+
"<flex>":
588+
// http://www.w3.org/TR/2014/WD-css-flexbox-1-20140325/#flex-property
589+
// none | [ <flex-grow> <flex-shrink>? || <flex-basis> ]
590+
// Valid syntaxes, according to https://developer.mozilla.org/en-US/docs/Web/CSS/flex#Syntax
591+
// * none
592+
// * <flex-grow>
593+
// * <flex-basis>
594+
// * <flex-grow> <flex-basis>
595+
// * <flex-grow> <flex-shrink>
596+
// * <flex-grow> <flex-shrink> <flex-basis>
597+
// * inherit
598+
Matcher.alt("none", "inherit", Matcher.cast("<flex-grow>").then(Matcher.cast("<flex-shrink>").question()).oror("<flex-basis>")),
599+
600+
"<text-decoration>":
601+
// none | [ underline || overline || line-through || blink ] | inherit
602+
Matcher.oror("underline", "overline", "line-through", "blink")
763603
}
764604
};

tests/css/Validation.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@
372372
],
373373

374374
invalid: {
375-
"foo" : "Expected (<x-one-radius>) but found 'foo'.",
375+
"foo" : "Expected (<x-one-radius> | inherit) but found 'foo'.",
376376
"5px 5px 7px" : "Expected end of value but found '7px'.",
377377
}
378378
}));
@@ -388,7 +388,7 @@
388388
],
389389

390390
invalid: {
391-
"foo" : "Expected (<x-one-radius>) but found 'foo'.",
391+
"foo" : "Expected (<x-one-radius> | inherit) but found 'foo'.",
392392
"5px 5px 7px" : "Expected end of value but found '7px'.",
393393
}
394394
}));
@@ -457,7 +457,7 @@
457457
],
458458

459459
invalid: {
460-
"foo" : "Expected (<x-one-radius>) but found 'foo'.",
460+
"foo" : "Expected (<x-one-radius> | inherit) but found 'foo'.",
461461
"5px 5px 7px" : "Expected end of value but found '7px'.",
462462
}
463463
}));
@@ -472,7 +472,7 @@
472472
],
473473

474474
invalid: {
475-
"foo" : "Expected (<x-one-radius>) but found 'foo'.",
475+
"foo" : "Expected (<x-one-radius> | inherit) but found 'foo'.",
476476
"5px 5px 7px" : "Expected end of value but found '7px'.",
477477
}
478478
}));
@@ -743,7 +743,7 @@
743743
invalid: {
744744
"circle(50% at 0 0)" : "Expected (<filter-function-list> | none) but found 'circle(50% at 0 0)'.",
745745
"foo" : "Expected (<filter-function-list> | none) but found 'foo'.",
746-
"blur(30px 30px) none" : "Expected (<filter-function> | <uri>) but found 'none'."
746+
"blur(30px 30px) none" : "Expected end of value but found 'none'."
747747
}
748748
}));
749749

@@ -764,7 +764,7 @@
764764
],
765765

766766
invalid: {
767-
"foo": "Expected (none | [ <flex-grow> <flex-shrink>? || <flex-basis> ]) but found 'foo'."
767+
"foo": "Expected (none | inherit | <flex-grow> <flex-shrink>? || <flex-basis>) but found 'foo'."
768768
}
769769
}));
770770
});
@@ -965,9 +965,9 @@
965965

966966
invalid: {
967967
"none underline" : "Expected end of value but found 'underline'.",
968-
"line-through none" : "Expected (none | <text-decoration> | inherit) but found 'line-through none'.",
968+
"line-through none" : "Expected end of value but found 'none'.",
969969
"inherit blink" : "Expected end of value but found 'blink'.",
970-
"overline inherit" : "Expected (none | <text-decoration> | inherit) but found 'overline inherit'.",
970+
"overline inherit" : "Expected end of value but found 'inherit'.",
971971
"foo" : "Expected (none | <text-decoration> | inherit) but found 'foo'."
972972
}
973973
}));

0 commit comments

Comments
 (0)