Skip to content

Commit 30b3261

Browse files
committed
Validate fill, stroke, and opacity properties.
Originally based on PR #162 by Onno van der Zee <[email protected]>. Fixes: #162
1 parent 42cee20 commit 30b3261

File tree

3 files changed

+179
-3
lines changed

3 files changed

+179
-3
lines changed

src/css/Properties.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ var Properties = {
285285
"empty-cells" : "show | hide | inherit",
286286

287287
//F
288-
"fill" : "<color> | inherit",
288+
"fill" : "<paint> | inherit",
289+
"fill-opacity" : "<opacity-value> | inherit",
290+
"fill-rule" : "nonzero | evenodd | inherit",
289291
"filter" : "<filter-function-list> | none",
290292
"fit" : "fill | hidden | meet | slice",
291293
"fit-position" : 1,
@@ -421,7 +423,7 @@ var Properties = {
421423
//O
422424
"object-fit" : "fill | contain | cover | none | scale-down",
423425
"object-position" : "<position> | inherit",
424-
"opacity" : "<number> | inherit",
426+
"opacity" : "<opacity-value> | inherit",
425427
"order" : "<integer>",
426428
"-webkit-order" : "<integer>",
427429
"orphans" : "<integer> | inherit",
@@ -489,6 +491,14 @@ var Properties = {
489491
"src" : 1,
490492
"stress" : 1,
491493
"string-set" : 1,
494+
"stroke" : "<paint> | inherit",
495+
"stroke-dasharray" : "none | <dasharray> | inherit",
496+
"stroke-dashoffset" : "<percentage> | <length> | inherit",
497+
"stroke-linecap" : "butt | round | square | inherit",
498+
"stroke-linejoin" : "miter | round | bevel | inherit",
499+
"stroke-miterlimit" : "<miterlimit> | inherit",
500+
"stroke-opacity" : "<opacity-value> | inherit",
501+
"stroke-width" : "<percentage> | <length> | inherit",
492502

493503
"table-layout" : "auto | fixed | inherit",
494504
"tab-size" : "<integer> | <length>",

src/css/ValidationTypes.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,39 @@ ValidationTypes = {
387387
return part.type === "color" || part == "transparent" || part == "currentColor";
388388
},
389389

390+
// The SVG <color> spec doesn't include "currentColor" or "transparent" as a color.
391+
"<color-svg>": function(part) {
392+
return part.type === "color";
393+
},
394+
395+
"<icccolor>": function(part){
396+
/* ex.:
397+
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/local
398+
icc-color(acmecmyk, 0.11, 0.48, 0.83, 0.00)
399+
cielab(62.253188, 23.950124, 48.410653)
400+
cielch(62.253188, 54.011108, 63.677091)
401+
icc-color(FooColors, Sandy23C)
402+
http://www.w3.org/TR/2009/WD-SVGColor12-20091001/#iccnamedcolor
403+
~"icc-color(" name (comma-wsp number)+ ")"
404+
~"icc-named-color(" name comma-wsp namedColor ")"
405+
~"cielab(" lightness comma-wsp a-value comma-wsp b-value ")"
406+
~"cielchab(" lightness comma-wsp chroma comma-wsp hue ")"
407+
*/
408+
return ValidationTypes.isLiteral(part, "cielab() | cielch() | cielchab() | icc-color() | icc-named-color()");
409+
},
410+
390411
"<number>": function(part){
391412
return part.type === "number" || this["<integer>"](part);
392413
},
393414

415+
"<miterlimit>": function(part){
416+
return this["<number>"](part) && part.value >= 1;
417+
},
418+
419+
"<opacity-value>": function(part){
420+
return this["<number>"](part) && part.value >= 0 && part.value <= 1;
421+
},
422+
394423
"<integer>": function(part){
395424
return part.type === "integer";
396425
},
@@ -515,10 +544,31 @@ ValidationTypes = {
515544
// <basic-shape> || <geometry-box>
516545
Matcher.cast("<basic-shape>").oror("<geometry-box>"),
517546

547+
"<dasharray>":
548+
// "list of comma and/or white space separated <length>s and
549+
// <percentage>s". We use <padding-width> to enforce the
550+
// nonnegative constraint.
551+
Matcher.cast("<padding-width>")
552+
.braces(1, Infinity, "#", Matcher.cast(",").question()),
553+
518554
"<filter-function-list>":
519555
// [ <filter-function> | <uri> ]+
520556
Matcher.cast("<filter-function> | <uri>").plus(),
521557

558+
"<paint>":
559+
// none | currentColor | <color> [<icccolor>]? |
560+
// <funciri> [ none | currentColor | <color> [<icccolor>]? ]?
561+
562+
// Note that <color> here is "as defined in the SVG spec", which
563+
// is more restrictive that the <color> defined in the CSS spec.
564+
Matcher.alt("<paint-basic>",
565+
Matcher.seq("<uri>", Matcher.cast("<paint-basic>").question())),
566+
// Helper definition for <paint> above.
567+
"<paint-basic>":
568+
Matcher.alt("none", "currentColor",
569+
Matcher.seq("<color-svg>",
570+
Matcher.cast("<icccolor>").question())),
571+
522572
"<position>":
523573
// <position> = [
524574
// [ left | center | right | top | bottom | <percentage> | <length> ]

tests/css/Validation.js

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,46 @@
729729
}
730730
}));
731731

732+
// test <paint>
733+
suite.add(new ValidationTestCase({
734+
property: "fill",
735+
736+
valid: [
737+
"url('myGradient')",
738+
"url('myGradient') darkred",
739+
"url('myGradient') darkred icc-color(myCmykDarkRed)",
740+
"currentColor",
741+
"darkred icc-color(myCmykDarkRed)",
742+
"none",
743+
"inherit"
744+
],
745+
746+
invalid: {
747+
"url('myGradient') inherit" : "Expected end of value but found 'inherit'.",
748+
"url('myGradient') icc-color(myCmykDarkRed)" : "Expected end of value but found 'icc-color(myCmykDarkRed)'.",
749+
"currentColor icc-color(myCmykDarkRed)" : "Expected end of value but found 'icc-color(myCmykDarkRed)'.",
750+
"icc-color(myCmykDarkRed) darkred" : "Expected (<paint> | inherit) but found 'icc-color(myCmykDarkRed) darkred'.",
751+
"icc-color(myCmykDarkRed)" : "Expected (<paint> | inherit) but found 'icc-color(myCmykDarkRed)'.",
752+
"icc-color(myCmykDarkRed) inherit" : "Expected (<paint> | inherit) but found 'icc-color(myCmykDarkRed) inherit'.",
753+
"inherit icc-color(myCmykDarkRed)" : "Expected end of value but found 'icc-color(myCmykDarkRed)'.",
754+
"none inherit" : "Expected end of value but found 'inherit'."
755+
}
756+
}));
757+
758+
suite.add(new ValidationTestCase({
759+
property: "fill-rule",
760+
761+
valid: [
762+
"nonzero",
763+
"evenodd",
764+
"inherit"
765+
],
766+
767+
invalid: {
768+
"foo" : "Expected (nonzero | evenodd | inherit) but found 'foo'."
769+
}
770+
}));
771+
732772
suite.add(new ValidationTestCase({
733773
property: "filter",
734774

@@ -1040,11 +1080,15 @@
10401080
property: "opacity",
10411081

10421082
valid: [
1083+
"0",
1084+
"0.5",
10431085
"1"
10441086
],
10451087

10461088
invalid: {
1047-
"foo" : "Expected (<number> | inherit) but found 'foo'."
1089+
"-0.75" : "Expected (<opacity-value> | inherit) but found '-0.75'.",
1090+
"12" : "Expected (<opacity-value> | inherit) but found '12'.",
1091+
"foo" : "Expected (<opacity-value> | inherit) but found 'foo'."
10481092
}
10491093
}));
10501094

@@ -1070,6 +1114,78 @@
10701114
}
10711115
}));
10721116

1117+
suite.add(new ValidationTestCase({
1118+
property: "stroke-dasharray",
1119+
1120+
valid: [
1121+
"0",
1122+
"4",
1123+
"20px",
1124+
"20px 40px 30px",
1125+
"20px, 40px, 30px",
1126+
"calc(1px + 2px) calc(3px + 1em)",
1127+
"none",
1128+
"inherit"
1129+
],
1130+
1131+
invalid: {
1132+
"-20px" : "Expected (none | <dasharray> | inherit) but found '-20px'.",
1133+
"20px," : "Expected end of value but found ','.",
1134+
"20px, -20px": "Expected end of value but found ','.",
1135+
"auto" : "Expected (none | <dasharray> | inherit) but found 'auto'."
1136+
}
1137+
}));
1138+
1139+
suite.add(new ValidationTestCase({
1140+
property: "stroke-linecap",
1141+
1142+
valid: [
1143+
"butt",
1144+
"round",
1145+
"square",
1146+
"inherit"
1147+
],
1148+
1149+
invalid: {
1150+
"auto" : "Expected (butt | round | square | inherit) but found 'auto'.",
1151+
"none" : "Expected (butt | round | square | inherit) but found 'none'."
1152+
}
1153+
}));
1154+
1155+
suite.add(new ValidationTestCase({
1156+
property: "stroke-linejoin",
1157+
1158+
valid: [
1159+
"miter",
1160+
"round",
1161+
"bevel",
1162+
"inherit"
1163+
],
1164+
1165+
invalid: {
1166+
"auto" : "Expected (miter | round | bevel | inherit) but found 'auto'.",
1167+
"none" : "Expected (miter | round | bevel | inherit) but found 'none'."
1168+
}
1169+
}));
1170+
1171+
suite.add(new ValidationTestCase({
1172+
property: "stroke-miterlimit",
1173+
1174+
valid: [
1175+
"1",
1176+
"1.4",
1177+
"20",
1178+
"10",
1179+
"inherit"
1180+
],
1181+
1182+
invalid: {
1183+
"-10" : "Expected (<miterlimit> | inherit) but found '-10'.",
1184+
"0.5" : "Expected (<miterlimit> | inherit) but found '0.5'.",
1185+
"foo" : "Expected (<miterlimit> | inherit) but found 'foo'."
1186+
}
1187+
}));
1188+
10731189
suite.add(new ValidationTestCase({
10741190
property: "-ms-touch-action",
10751191

0 commit comments

Comments
 (0)