properties.js (13271B)
1 (function(root){ 2 3 /* 4 * General Value Types definition 5 * they return an object of arrays of type { <name>: [<start-value>, <end-value>], ... } 6 */ 7 var values = { 8 'length' : function() { 9 // http://www.w3.org/TR/css3-values/#lengths 10 return { 11 // CSS Values and Module Level 3 12 // ch: ['1ch', '10ch'], 13 // rem: ['1rem', '10rem'], 14 // vw: ['1vw', '10vw'], 15 // vh: ['1vh', '10vh'], 16 // vmin: ['1vmin', '10vmin'], 17 // vmax: ['1vmax', '10vmax'], 18 // CSS Values and Module Level 2 19 pt: ['1pt', '10pt'], 20 pc: ['1pc', '10pc'], 21 px: ['1px', '10px'], 22 // CSS Values and Module Level 1 23 em: ['1em', '10em'], 24 ex: ['1ex', '10ex'], 25 mm: ['1mm', '10mm'], 26 cm: ['1cm', '10cm'], 27 'in': ['1in', '10in'] 28 }; 29 }, 30 'length-em': function() { 31 return { 32 em: ['1.1em', '1.5em'] 33 }; 34 }, 35 'percentage': function() { 36 // http://www.w3.org/TR/css3-values/#percentages 37 return { 38 '%': ['33%', '80%'] 39 }; 40 }, 41 'color': function() { 42 // http://www.w3.org/TR/css3-values/#colors 43 // http://www.w3.org/TR/css3-color/ 44 return { 45 rgba: ['rgba(100,100,100,1)', 'rgba(10,10,10,0.4)'] 46 }; 47 }, 48 'rectangle': function() { 49 // http://www.w3.org/TR/CSS2/visufx.html#value-def-shape 50 return { 51 rectangle: ['rect(10px,10px,10px,10px)', 'rect(15px,15px,5px,5px)'] 52 }; 53 }, 54 'font-weight': function() { 55 // http://www.w3.org/TR/css3-fonts/#font-weight-prop 56 return { 57 keyword: ["normal", "bold"], 58 numeric: ["100", "900"] 59 }; 60 }, 61 'number': function() { 62 // http://www.w3.org/TR/css3-values/#number 63 return { 64 integer: ["1", "10"], 65 decimal: ["1.1", "9.55"] 66 }; 67 }, 68 'number[0,1]': function() { 69 // http://www.w3.org/TR/css3-values/#number 70 // applies to [0,1]-ranged properties like opacity 71 return { 72 "zero-to-one": ["0.2", "0.9"] 73 }; 74 }, 75 'integer': function() { 76 // http://www.w3.org/TR/css3-values/#integer 77 return { 78 integer: ["1", "10"] 79 }; 80 }, 81 'shadow': function() { 82 // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property 83 return { 84 shadow: ['rgba(0,0,0,0.1) 5px 6px 7px', 'rgba(10,10,10,0.9) 5px 6px 7px'] 85 }; 86 }, 87 'visibility': function() { 88 // http://www.w3.org/TR/CSS2/visufx.html#visibility 89 return { 90 keyword: ['visible', 'hidden', {discrete: true}] 91 }; 92 }, 93 // types reqired for non-specified properties 94 'border-radius': function() { 95 return { 96 px: ['1px', '10px'], 97 "px-px": ['1px 3px', '10px 13px'] 98 }; 99 }, 100 'image' : function() { 101 var prefix = getValueVendorPrefix('background-image', 'linear-gradient(top, hsl(0, 80%, 70%), #bada55)'); 102 return { 103 // Chrome implements this 104 url: ['url(support/one.gif)', 'url(support/two.gif)'], 105 data: ['url(data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=)', 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==)'], 106 // A hunch, as from the spec: 107 // http://www.w3.org/TR/css3-transitions/#animatable-types 108 // gradient: interpolated via the positions and colors of each stop. They must have the same type (radial or linear) and same number of stops in order to be animated. Note: [CSS3-IMAGES] may extend this definition. 109 gradient: [prefix + 'linear-gradient(top, hsl(0, 80%, 70%), #bada55)', prefix + 'linear-gradient(top, #bada55, hsl(0, 80%, 70%))'] 110 }; 111 }, 112 'background-size': function() { 113 return { 114 keyword: ['cover', 'contain'] 115 }; 116 }, 117 'box-shadow': function() { 118 // http://www.w3.org/TR/css3-background/#ltshadowgt 119 return { 120 shadow: ['60px -16px teal', '60px -16px red'] 121 }; 122 }, 123 'vertical': function() { 124 return { 125 keyword: ['top', 'bottom'] 126 }; 127 }, 128 'horizontal': function() { 129 return { 130 keyword: ['left', 'right'] 131 }; 132 }, 133 'font-stretch': function() { 134 return { 135 keyword: ['condensed', 'expanded'] 136 }; 137 }, 138 'transform': function() { 139 return { 140 rotate: ['rotate(10deg)', 'rotate(20deg)'] 141 }; 142 }, 143 'position': function() { 144 return { 145 'static to absolute': ['static', 'absolute', {discrete: true}], 146 'relative to absolute': ['relative', 'absolute', {discrete: true}], 147 'absolute to fixed': ['absolute', 'fixed', {discrete: true}] 148 }; 149 }, 150 'display': function() { 151 return { 152 'static to absolute': ['none', 'block', {discrete: true}], 153 'block to inline-block': ['block', 'inline-block', {discrete: true}] 154 }; 155 }, 156 'object-view-box': function() { 157 return { 158 inset: ['inset(10% 10% 20% 20%)', 'inset(20% 20% 30% 30%)'], 159 rect: ['rect(10px 20px 30px 40px)', 'rect(20px 30px 40px 50px)'], 160 xywh: ['xywh(10px 20px 30px 40px)', 'xywh(20px 30px 40px 50px)'], 161 }; 162 } 163 }; 164 165 /* 166 * Property to Type table 167 * (as stated in specification) 168 */ 169 var properties = { 170 'background-color': ['color'], 171 'background-position-x': ['length', 'percentage'], 172 173 'border-top-width': ['length'], 174 'border-right-width': ['length'], 175 'border-bottom-width': ['length'], 176 'border-left-width': ['length'], 177 178 'border-top-color': ['color'], 179 'border-right-color': ['color'], 180 'border-bottom-color': ['color'], 181 'border-left-color': ['color'], 182 183 'padding-bottom': ['length'], 184 'padding-left': ['length'], 185 'padding-right': ['length'], 186 'padding-top': ['length'], 187 188 'margin-bottom': ['length'], 189 'margin-left': ['length'], 190 'margin-right': ['length'], 191 'margin-top': ['length'], 192 193 'height': ['length', 'percentage'], 194 'width': ['length', 'percentage'], 195 'min-height': ['length', 'percentage'], 196 'min-width': ['length', 'percentage'], 197 'max-height': ['length', 'percentage'], 198 'max-width': ['length', 'percentage'], 199 200 'top': ['length', 'percentage'], 201 'right': ['length', 'percentage'], 202 'bottom': ['length', 'percentage'], 203 'left': ['length', 'percentage'], 204 205 'color': ['color'], 206 'font-size': ['length', 'percentage'], 207 'font-weight': ['font-weight'], 208 'line-height': ['number', 'length', 'percentage'], 209 'letter-spacing': ['length'], 210 // Note: percentage is Level3 and not implemented anywhere yet 211 // https://drafts.csswg.org/css3-text/#word-spacing 212 'word-spacing': ['length', 'percentage'], 213 'text-indent': ['length', 'percentage'], 214 'text-shadow': ['shadow'], 215 216 'outline-color': ['color'], 217 // outline-offset <integer> used to be an error in the spec 218 'outline-offset': ['length'], 219 'outline-width': ['length'], 220 221 'clip': ['rectangle'], 222 223 'vertical-align': ['length', 'percentage'], 224 'opacity': ['number[0,1]'], 225 'visibility': ['visibility'], 226 'z-index': ['integer'] 227 }; 228 229 /* 230 * Property to Type table 231 * (missing value-types of specified properties) 232 */ 233 var missing_properties = { 234 'margin-bottom': ['percentage'], 235 'margin-left': ['percentage'], 236 'margin-right': ['percentage'], 237 'margin-top': ['percentage'], 238 'padding-bottom': ['percentage'], 239 'padding-left': ['percentage'], 240 'padding-right': ['percentage'], 241 'padding-top': ['percentage'], 242 'vertical-align': ['vertical'] 243 }; 244 245 /* 246 * Property to Type table 247 * (properties that haven't been specified but implemented) 248 */ 249 var unspecified_properties = { 250 // http://oli.jp/2010/css-animatable-properties/ 251 'border-top-left-radius': ['border-radius'], 252 'border-top-right-radius': ['border-radius'], 253 'border-bottom-left-radius': ['border-radius'], 254 'border-bottom-right-radius': ['border-radius'], 255 'background-image': ['image'], 256 'background-size': ['background-size'], 257 // https://drafts.csswg.org/css3-background/#the-box-shadow 258 // Animatable: yes, except between inner and outer shadows (Transition to/from an absent shadow is a transition to/from ‘0 0 transparent’ or ‘0 0 transparent inset’, as appropriate.) 259 'box-shadow': ['box-shadow'], 260 'font-size-adjust': ['number'], 261 'font-stretch': ['font-stretch'], 262 'text-decoration-color': ['color'], 263 'column-count': ['integer'], 264 'column-gap': ['length'], 265 'column-rule-color': ['color'], 266 'column-rule-width': ['length'], 267 'column-width': ['length'], 268 'column-height': ['length'], 269 'transform': ['transform'], 270 'transform-origin': ['horizontal'], 271 'display': ['display'], 272 'position': ['position'], 273 'object-view-box': ['object-view-box'] 274 }; 275 276 /* 277 * additional styles required to actually render 278 * (different browsers expect different environment) 279 */ 280 var additional_styles = { 281 // all browsers 282 'border-top-width': {'border-top-style' : 'solid'}, 283 'border-right-width': {'border-right-style' : 'solid'}, 284 'border-bottom-width': {'border-bottom-style' : 'solid'}, 285 'border-left-width': {'border-left-style' : 'solid'}, 286 'top': {'position': 'absolute'}, 287 'right': {'position': 'absolute'}, 288 'bottom': {'position': 'absolute'}, 289 'left': {'position': 'absolute'}, 290 'z-index': {'position': 'absolute'}, 291 'outline-offset': {'outline-style': 'solid'}, 292 'outline-width': {'outline-style': 'solid'}, 293 'word-spacing': {'width': '100px', 'height': '100px'}, 294 // unspecified properties 295 'column-rule-width': {'column-rule-style': 'solid'}, 296 'position': {'width': '50px', 'height': '50px', top: '10px', left: '50px'} 297 }; 298 299 /* 300 * additional styles required *on the parent* to actually render 301 * (different browsers expect different environment) 302 */ 303 var parent_styles = { 304 'border-top-width': {'border-top-style' : 'solid'}, 305 'border-right-width': {'border-right-style' : 'solid'}, 306 'border-bottom-width': {'border-bottom-style' : 'solid'}, 307 'border-left-width': {'border-left-style' : 'solid'}, 308 'height': {'width': '100px', 'height': '100px'}, 309 'min-height': {'width': '100px', 'height': '100px'}, 310 'max-height': {'width': '100px', 'height': '100px'}, 311 'width': {'width': '100px', 'height': '100px'}, 312 'min-width': {'width': '100px', 'height': '100px'}, 313 'max-width': {'width': '100px', 'height': '100px'}, 314 // unspecified properties 315 'position': {'position': 'relative', 'width': '100px', 'height': '100px'}, 316 // inheritance tests 317 'top': {'width': '100px', 'height': '100px', 'position': 'relative'}, 318 'right': {'width': '100px', 'height': '100px', 'position': 'relative'}, 319 'bottom': {'width': '100px', 'height': '100px', 'position': 'relative'}, 320 'left': {'width': '100px', 'height': '100px', 'position': 'relative'} 321 }; 322 323 324 function assemble(props) { 325 var tests = []; 326 327 // assemble tests 328 for (var property in props) { 329 props[property].forEach(function(type) { 330 var _values = values[type](property); 331 Object.keys(_values).forEach(function(unit) { 332 var data = { 333 name: property + ' ' + type + '(' + unit + ')', 334 property: property, 335 valueType : type, 336 unit : unit, 337 parentStyle: extend({}, parent_styles[property] || {}), 338 from: extend({}, additional_styles[property] || {}), 339 to: {} 340 }; 341 342 data.from[property] = _values[unit][0]; 343 data.to[property] = _values[unit][1]; 344 data.flags = _values[unit][2] || {}; 345 346 tests.push(data); 347 }); 348 }); 349 } 350 351 return tests; 352 } 353 354 root.getPropertyTests = function() { 355 return assemble(properties); 356 }; 357 358 root.getMissingPropertyTests = function() { 359 return assemble(missing_properties); 360 }; 361 362 root.getUnspecifiedPropertyTests = function() { 363 return assemble(unspecified_properties); 364 }; 365 366 root.getFontSizeRelativePropertyTests = function() { 367 var accepted = {}; 368 369 for (var key in properties) { 370 if (!Object.prototype.hasOwnProperty.call(properties, key) || key === "font-size") { 371 continue; 372 } 373 374 if (properties[key].indexOf('length') > -1) { 375 accepted[key] = ['length-em']; 376 } 377 } 378 379 return assemble(accepted); 380 }; 381 382 root.filterPropertyTests = function(tests, names) { 383 var allowed = {}; 384 var accepted = []; 385 386 if (typeof names === "string") { 387 names = [names]; 388 } 389 390 if (!(names instanceof RegExp)) { 391 names.forEach(function(name) { 392 allowed[name] = true; 393 }); 394 } 395 396 tests.forEach(function(test) { 397 if (names instanceof RegExp) { 398 if (!test.name.match(names)) { 399 return; 400 } 401 } else if (!allowed[test.name]) { 402 return; 403 } 404 405 accepted.push(test); 406 }); 407 408 return accepted; 409 }; 410 411 })(window);