1// Contains the interpretation of CSS properties, as used by the property optimizer 2 3var breakUp = require('./break-up'); 4var canOverride = require('./can-override'); 5var restore = require('./restore'); 6 7var override = require('../../utils/override'); 8 9// Properties to process 10// Extend this object in order to add support for more properties in the optimizer. 11// 12// Each key in this object represents a CSS property and should be an object. 13// Such an object contains properties that describe how the represented CSS property should be handled. 14// Possible options: 15// 16// * components: array (Only specify for shorthand properties.) 17// Contains the names of the granular properties this shorthand compacts. 18// 19// * canOverride: function 20// Returns whether two tokens of this property can be merged with each other. 21// This property has no meaning for shorthands. 22// 23// * defaultValue: string 24// Specifies the default value of the property according to the CSS standard. 25// For shorthand, this is used when every component is set to its default value, therefore it should be the shortest possible default value of all the components. 26// 27// * shortestValue: string 28// Specifies the shortest possible value the property can possibly have. 29// (Falls back to defaultValue if unspecified.) 30// 31// * breakUp: function (Only specify for shorthand properties.) 32// Breaks the shorthand up to its components. 33// 34// * restore: function (Only specify for shorthand properties.) 35// Puts the shorthand together from its components. 36// 37var compactable = { 38 'animation': { 39 canOverride: canOverride.generic.components([ 40 canOverride.generic.time, 41 canOverride.generic.timingFunction, 42 canOverride.generic.time, 43 canOverride.property.animationIterationCount, 44 canOverride.property.animationDirection, 45 canOverride.property.animationFillMode, 46 canOverride.property.animationPlayState, 47 canOverride.property.animationName 48 ]), 49 components: [ 50 'animation-duration', 51 'animation-timing-function', 52 'animation-delay', 53 'animation-iteration-count', 54 'animation-direction', 55 'animation-fill-mode', 56 'animation-play-state', 57 'animation-name' 58 ], 59 breakUp: breakUp.multiplex(breakUp.animation), 60 defaultValue: 'none', 61 restore: restore.multiplex(restore.withoutDefaults), 62 shorthand: true, 63 vendorPrefixes: [ 64 '-moz-', 65 '-o-', 66 '-webkit-' 67 ] 68 }, 69 'animation-delay': { 70 canOverride: canOverride.generic.time, 71 componentOf: [ 72 'animation' 73 ], 74 defaultValue: '0s', 75 intoMultiplexMode: 'real', 76 vendorPrefixes: [ 77 '-moz-', 78 '-o-', 79 '-webkit-' 80 ] 81 }, 82 'animation-direction': { 83 canOverride: canOverride.property.animationDirection, 84 componentOf: [ 85 'animation' 86 ], 87 defaultValue: 'normal', 88 intoMultiplexMode: 'real', 89 vendorPrefixes: [ 90 '-moz-', 91 '-o-', 92 '-webkit-' 93 ] 94 }, 95 'animation-duration': { 96 canOverride: canOverride.generic.time, 97 componentOf: [ 98 'animation' 99 ], 100 defaultValue: '0s', 101 intoMultiplexMode: 'real', 102 keepUnlessDefault: 'animation-delay', 103 vendorPrefixes: [ 104 '-moz-', 105 '-o-', 106 '-webkit-' 107 ] 108 }, 109 'animation-fill-mode': { 110 canOverride: canOverride.property.animationFillMode, 111 componentOf: [ 112 'animation' 113 ], 114 defaultValue: 'none', 115 intoMultiplexMode: 'real', 116 vendorPrefixes: [ 117 '-moz-', 118 '-o-', 119 '-webkit-' 120 ] 121 }, 122 'animation-iteration-count': { 123 canOverride: canOverride.property.animationIterationCount, 124 componentOf: [ 125 'animation' 126 ], 127 defaultValue: '1', 128 intoMultiplexMode: 'real', 129 vendorPrefixes: [ 130 '-moz-', 131 '-o-', 132 '-webkit-' 133 ] 134 }, 135 'animation-name': { 136 canOverride: canOverride.property.animationName, 137 componentOf: [ 138 'animation' 139 ], 140 defaultValue: 'none', 141 intoMultiplexMode: 'real', 142 vendorPrefixes: [ 143 '-moz-', 144 '-o-', 145 '-webkit-' 146 ] 147 }, 148 'animation-play-state': { 149 canOverride: canOverride.property.animationPlayState, 150 componentOf: [ 151 'animation' 152 ], 153 defaultValue: 'running', 154 intoMultiplexMode: 'real', 155 vendorPrefixes: [ 156 '-moz-', 157 '-o-', 158 '-webkit-' 159 ] 160 }, 161 'animation-timing-function': { 162 canOverride: canOverride.generic.timingFunction, 163 componentOf: [ 164 'animation' 165 ], 166 defaultValue: 'ease', 167 intoMultiplexMode: 'real', 168 vendorPrefixes: [ 169 '-moz-', 170 '-o-', 171 '-webkit-' 172 ] 173 }, 174 'background': { 175 canOverride: canOverride.generic.components([ 176 canOverride.generic.image, 177 canOverride.property.backgroundPosition, 178 canOverride.property.backgroundSize, 179 canOverride.property.backgroundRepeat, 180 canOverride.property.backgroundAttachment, 181 canOverride.property.backgroundOrigin, 182 canOverride.property.backgroundClip, 183 canOverride.generic.color 184 ]), 185 components: [ 186 'background-image', 187 'background-position', 188 'background-size', 189 'background-repeat', 190 'background-attachment', 191 'background-origin', 192 'background-clip', 193 'background-color' 194 ], 195 breakUp: breakUp.multiplex(breakUp.background), 196 defaultValue: '0 0', 197 restore: restore.multiplex(restore.background), 198 shortestValue: '0', 199 shorthand: true 200 }, 201 'background-attachment': { 202 canOverride: canOverride.property.backgroundAttachment, 203 componentOf: [ 204 'background' 205 ], 206 defaultValue: 'scroll', 207 intoMultiplexMode: 'real' 208 }, 209 'background-clip': { 210 canOverride: canOverride.property.backgroundClip, 211 componentOf: [ 212 'background' 213 ], 214 defaultValue: 'border-box', 215 intoMultiplexMode: 'real', 216 shortestValue: 'border-box' 217 }, 218 'background-color': { 219 canOverride: canOverride.generic.color, 220 componentOf: [ 221 'background' 222 ], 223 defaultValue: 'transparent', 224 intoMultiplexMode: 'real', // otherwise real color will turn into default since color appears in last multiplex only 225 multiplexLastOnly: true, 226 nonMergeableValue: 'none', 227 shortestValue: 'red' 228 }, 229 'background-image': { 230 canOverride: canOverride.generic.image, 231 componentOf: [ 232 'background' 233 ], 234 defaultValue: 'none', 235 intoMultiplexMode: 'default' 236 }, 237 'background-origin': { 238 canOverride: canOverride.property.backgroundOrigin, 239 componentOf: [ 240 'background' 241 ], 242 defaultValue: 'padding-box', 243 intoMultiplexMode: 'real', 244 shortestValue: 'border-box' 245 }, 246 'background-position': { 247 canOverride: canOverride.property.backgroundPosition, 248 componentOf: [ 249 'background' 250 ], 251 defaultValue: ['0', '0'], 252 doubleValues: true, 253 intoMultiplexMode: 'real', 254 shortestValue: '0' 255 }, 256 'background-repeat': { 257 canOverride: canOverride.property.backgroundRepeat, 258 componentOf: [ 259 'background' 260 ], 261 defaultValue: ['repeat'], 262 doubleValues: true, 263 intoMultiplexMode: 'real' 264 }, 265 'background-size': { 266 canOverride: canOverride.property.backgroundSize, 267 componentOf: [ 268 'background' 269 ], 270 defaultValue: ['auto'], 271 doubleValues: true, 272 intoMultiplexMode: 'real', 273 shortestValue: '0 0' 274 }, 275 'bottom': { 276 canOverride: canOverride.property.bottom, 277 defaultValue: 'auto' 278 }, 279 'border': { 280 breakUp: breakUp.border, 281 canOverride: canOverride.generic.components([ 282 canOverride.generic.unit, 283 canOverride.property.borderStyle, 284 canOverride.generic.color 285 ]), 286 components: [ 287 'border-width', 288 'border-style', 289 'border-color' 290 ], 291 defaultValue: 'none', 292 overridesShorthands: [ 293 'border-bottom', 294 'border-left', 295 'border-right', 296 'border-top' 297 ], 298 restore: restore.withoutDefaults, 299 shorthand: true, 300 shorthandComponents: true 301 }, 302 'border-bottom': { 303 breakUp: breakUp.border, 304 canOverride: canOverride.generic.components([ 305 canOverride.generic.unit, 306 canOverride.property.borderStyle, 307 canOverride.generic.color 308 ]), 309 components: [ 310 'border-bottom-width', 311 'border-bottom-style', 312 'border-bottom-color' 313 ], 314 defaultValue: 'none', 315 restore: restore.withoutDefaults, 316 shorthand: true 317 }, 318 'border-bottom-color': { 319 canOverride: canOverride.generic.color, 320 componentOf: [ 321 'border-bottom', 322 'border-color' 323 ], 324 defaultValue: 'none' 325 }, 326 'border-bottom-left-radius': { 327 canOverride: canOverride.generic.unit, 328 componentOf: [ 329 'border-radius' 330 ], 331 defaultValue: '0', 332 vendorPrefixes: [ 333 '-moz-', 334 '-o-' 335 ] 336 }, 337 'border-bottom-right-radius': { 338 canOverride: canOverride.generic.unit, 339 componentOf: [ 340 'border-radius' 341 ], 342 defaultValue: '0', 343 vendorPrefixes: [ 344 '-moz-', 345 '-o-' 346 ] 347 }, 348 'border-bottom-style': { 349 canOverride: canOverride.property.borderStyle, 350 componentOf: [ 351 'border-bottom', 352 'border-style' 353 ], 354 defaultValue: 'none' 355 }, 356 'border-bottom-width': { 357 canOverride: canOverride.generic.unit, 358 componentOf: [ 359 'border-bottom', 360 'border-width' 361 ], 362 defaultValue: 'medium', 363 oppositeTo: 'border-top-width', 364 shortestValue: '0' 365 }, 366 'border-collapse': { 367 canOverride: canOverride.property.borderCollapse, 368 defaultValue: 'separate' 369 }, 370 'border-color': { 371 breakUp: breakUp.fourValues, 372 canOverride: canOverride.generic.components([ 373 canOverride.generic.color, 374 canOverride.generic.color, 375 canOverride.generic.color, 376 canOverride.generic.color 377 ]), 378 componentOf: [ 379 'border' 380 ], 381 components: [ 382 'border-top-color', 383 'border-right-color', 384 'border-bottom-color', 385 'border-left-color' 386 ], 387 defaultValue: 'none', 388 restore: restore.fourValues, 389 shortestValue: 'red', 390 shorthand: true 391 }, 392 'border-left': { 393 breakUp: breakUp.border, 394 canOverride: canOverride.generic.components([ 395 canOverride.generic.unit, 396 canOverride.property.borderStyle, 397 canOverride.generic.color 398 ]), 399 components: [ 400 'border-left-width', 401 'border-left-style', 402 'border-left-color' 403 ], 404 defaultValue: 'none', 405 restore: restore.withoutDefaults, 406 shorthand: true 407 }, 408 'border-left-color': { 409 canOverride: canOverride.generic.color, 410 componentOf: [ 411 'border-color', 412 'border-left' 413 ], 414 defaultValue: 'none' 415 }, 416 'border-left-style': { 417 canOverride: canOverride.property.borderStyle, 418 componentOf: [ 419 'border-left', 420 'border-style' 421 ], 422 defaultValue: 'none' 423 }, 424 'border-left-width': { 425 canOverride: canOverride.generic.unit, 426 componentOf: [ 427 'border-left', 428 'border-width' 429 ], 430 defaultValue: 'medium', 431 oppositeTo: 'border-right-width', 432 shortestValue: '0' 433 }, 434 'border-radius': { 435 breakUp: breakUp.borderRadius, 436 canOverride: canOverride.generic.components([ 437 canOverride.generic.unit, 438 canOverride.generic.unit, 439 canOverride.generic.unit, 440 canOverride.generic.unit 441 ]), 442 components: [ 443 'border-top-left-radius', 444 'border-top-right-radius', 445 'border-bottom-right-radius', 446 'border-bottom-left-radius' 447 ], 448 defaultValue: '0', 449 restore: restore.borderRadius, 450 shorthand: true, 451 vendorPrefixes: [ 452 '-moz-', 453 '-o-' 454 ] 455 }, 456 'border-right': { 457 breakUp: breakUp.border, 458 canOverride: canOverride.generic.components([ 459 canOverride.generic.unit, 460 canOverride.property.borderStyle, 461 canOverride.generic.color 462 ]), 463 components: [ 464 'border-right-width', 465 'border-right-style', 466 'border-right-color' 467 ], 468 defaultValue: 'none', 469 restore: restore.withoutDefaults, 470 shorthand: true 471 }, 472 'border-right-color': { 473 canOverride: canOverride.generic.color, 474 componentOf: [ 475 'border-color', 476 'border-right' 477 ], 478 defaultValue: 'none' 479 }, 480 'border-right-style': { 481 canOverride: canOverride.property.borderStyle, 482 componentOf: [ 483 'border-right', 484 'border-style' 485 ], 486 defaultValue: 'none' 487 }, 488 'border-right-width': { 489 canOverride: canOverride.generic.unit, 490 componentOf: [ 491 'border-right', 492 'border-width' 493 ], 494 defaultValue: 'medium', 495 oppositeTo: 'border-left-width', 496 shortestValue: '0' 497 }, 498 'border-style': { 499 breakUp: breakUp.fourValues, 500 canOverride: canOverride.generic.components([ 501 canOverride.property.borderStyle, 502 canOverride.property.borderStyle, 503 canOverride.property.borderStyle, 504 canOverride.property.borderStyle 505 ]), 506 componentOf: [ 507 'border' 508 ], 509 components: [ 510 'border-top-style', 511 'border-right-style', 512 'border-bottom-style', 513 'border-left-style' 514 ], 515 defaultValue: 'none', 516 restore: restore.fourValues, 517 shorthand: true 518 }, 519 'border-top': { 520 breakUp: breakUp.border, 521 canOverride: canOverride.generic.components([ 522 canOverride.generic.unit, 523 canOverride.property.borderStyle, 524 canOverride.generic.color 525 ]), 526 components: [ 527 'border-top-width', 528 'border-top-style', 529 'border-top-color' 530 ], 531 defaultValue: 'none', 532 restore: restore.withoutDefaults, 533 shorthand: true 534 }, 535 'border-top-color': { 536 canOverride: canOverride.generic.color, 537 componentOf: [ 538 'border-color', 539 'border-top' 540 ], 541 defaultValue: 'none' 542 }, 543 'border-top-left-radius': { 544 canOverride: canOverride.generic.unit, 545 componentOf: [ 546 'border-radius' 547 ], 548 defaultValue: '0', 549 vendorPrefixes: [ 550 '-moz-', 551 '-o-' 552 ] 553 }, 554 'border-top-right-radius': { 555 canOverride: canOverride.generic.unit, 556 componentOf: [ 557 'border-radius' 558 ], 559 defaultValue: '0', 560 vendorPrefixes: [ 561 '-moz-', 562 '-o-' 563 ] 564 }, 565 'border-top-style': { 566 canOverride: canOverride.property.borderStyle, 567 componentOf: [ 568 'border-style', 569 'border-top' 570 ], 571 defaultValue: 'none' 572 }, 573 'border-top-width': { 574 canOverride: canOverride.generic.unit, 575 componentOf: [ 576 'border-top', 577 'border-width' 578 ], 579 defaultValue: 'medium', 580 oppositeTo: 'border-bottom-width', 581 shortestValue: '0' 582 }, 583 'border-width': { 584 breakUp: breakUp.fourValues, 585 canOverride: canOverride.generic.components([ 586 canOverride.generic.unit, 587 canOverride.generic.unit, 588 canOverride.generic.unit, 589 canOverride.generic.unit 590 ]), 591 componentOf: [ 592 'border' 593 ], 594 components: [ 595 'border-top-width', 596 'border-right-width', 597 'border-bottom-width', 598 'border-left-width' 599 ], 600 defaultValue: 'medium', 601 restore: restore.fourValues, 602 shortestValue: '0', 603 shorthand: true 604 }, 605 'clear': { 606 canOverride: canOverride.property.clear, 607 defaultValue: 'none' 608 }, 609 'color': { 610 canOverride: canOverride.generic.color, 611 defaultValue: 'transparent', 612 shortestValue: 'red' 613 }, 614 'cursor': { 615 canOverride: canOverride.property.cursor, 616 defaultValue: 'auto' 617 }, 618 'display': { 619 canOverride: canOverride.property.display, 620 }, 621 'float': { 622 canOverride: canOverride.property.float, 623 defaultValue: 'none' 624 }, 625 'font': { 626 breakUp: breakUp.font, 627 canOverride: canOverride.generic.components([ 628 canOverride.property.fontStyle, 629 canOverride.property.fontVariant, 630 canOverride.property.fontWeight, 631 canOverride.property.fontStretch, 632 canOverride.generic.unit, 633 canOverride.generic.unit, 634 canOverride.property.fontFamily 635 ]), 636 components: [ 637 'font-style', 638 'font-variant', 639 'font-weight', 640 'font-stretch', 641 'font-size', 642 'line-height', 643 'font-family' 644 ], 645 restore: restore.font, 646 shorthand: true 647 }, 648 'font-family': { 649 canOverride: canOverride.property.fontFamily, 650 defaultValue: 'user|agent|specific' 651 }, 652 'font-size': { 653 canOverride: canOverride.generic.unit, 654 defaultValue: 'medium', 655 shortestValue: '0' 656 }, 657 'font-stretch': { 658 canOverride: canOverride.property.fontStretch, 659 defaultValue: 'normal' 660 }, 661 'font-style': { 662 canOverride: canOverride.property.fontStyle, 663 defaultValue: 'normal' 664 }, 665 'font-variant': { 666 canOverride: canOverride.property.fontVariant, 667 defaultValue: 'normal' 668 }, 669 'font-weight': { 670 canOverride: canOverride.property.fontWeight, 671 defaultValue: 'normal', 672 shortestValue: '400' 673 }, 674 'height': { 675 canOverride: canOverride.generic.unit, 676 defaultValue: 'auto', 677 shortestValue: '0' 678 }, 679 'left': { 680 canOverride: canOverride.property.left, 681 defaultValue: 'auto' 682 }, 683 'line-height': { 684 canOverride: canOverride.generic.unitOrNumber, 685 defaultValue: 'normal', 686 shortestValue: '0' 687 }, 688 'list-style': { 689 canOverride: canOverride.generic.components([ 690 canOverride.property.listStyleType, 691 canOverride.property.listStylePosition, 692 canOverride.property.listStyleImage 693 ]), 694 components: [ 695 'list-style-type', 696 'list-style-position', 697 'list-style-image' 698 ], 699 breakUp: breakUp.listStyle, 700 restore: restore.withoutDefaults, 701 defaultValue: 'outside', // can't use 'disc' because that'd override default 'decimal' for <ol> 702 shortestValue: 'none', 703 shorthand: true 704 }, 705 'list-style-image' : { 706 canOverride: canOverride.generic.image, 707 componentOf: [ 708 'list-style' 709 ], 710 defaultValue: 'none' 711 }, 712 'list-style-position' : { 713 canOverride: canOverride.property.listStylePosition, 714 componentOf: [ 715 'list-style' 716 ], 717 defaultValue: 'outside', 718 shortestValue: 'inside' 719 }, 720 'list-style-type' : { 721 canOverride: canOverride.property.listStyleType, 722 componentOf: [ 723 'list-style' 724 ], 725 // NOTE: we can't tell the real default value here, it's 'disc' for <ul> and 'decimal' for <ol> 726 // this is a hack, but it doesn't matter because this value will be either overridden or 727 // it will disappear at the final step anyway 728 defaultValue: 'decimal|disc', 729 shortestValue: 'none' 730 }, 731 'margin': { 732 breakUp: breakUp.fourValues, 733 canOverride: canOverride.generic.components([ 734 canOverride.generic.unit, 735 canOverride.generic.unit, 736 canOverride.generic.unit, 737 canOverride.generic.unit 738 ]), 739 components: [ 740 'margin-top', 741 'margin-right', 742 'margin-bottom', 743 'margin-left' 744 ], 745 defaultValue: '0', 746 restore: restore.fourValues, 747 shorthand: true 748 }, 749 'margin-bottom': { 750 canOverride: canOverride.generic.unit, 751 componentOf: [ 752 'margin' 753 ], 754 defaultValue: '0', 755 oppositeTo: 'margin-top' 756 }, 757 'margin-left': { 758 canOverride: canOverride.generic.unit, 759 componentOf: [ 760 'margin' 761 ], 762 defaultValue: '0', 763 oppositeTo: 'margin-right' 764 }, 765 'margin-right': { 766 canOverride: canOverride.generic.unit, 767 componentOf: [ 768 'margin' 769 ], 770 defaultValue: '0', 771 oppositeTo: 'margin-left' 772 }, 773 'margin-top': { 774 canOverride: canOverride.generic.unit, 775 componentOf: [ 776 'margin' 777 ], 778 defaultValue: '0', 779 oppositeTo: 'margin-bottom' 780 }, 781 'outline': { 782 canOverride: canOverride.generic.components([ 783 canOverride.generic.color, 784 canOverride.property.outlineStyle, 785 canOverride.generic.unit 786 ]), 787 components: [ 788 'outline-color', 789 'outline-style', 790 'outline-width' 791 ], 792 breakUp: breakUp.outline, 793 restore: restore.withoutDefaults, 794 defaultValue: '0', 795 shorthand: true 796 }, 797 'outline-color': { 798 canOverride: canOverride.generic.color, 799 componentOf: [ 800 'outline' 801 ], 802 defaultValue: 'invert', 803 shortestValue: 'red' 804 }, 805 'outline-style': { 806 canOverride: canOverride.property.outlineStyle, 807 componentOf: [ 808 'outline' 809 ], 810 defaultValue: 'none' 811 }, 812 'outline-width': { 813 canOverride: canOverride.generic.unit, 814 componentOf: [ 815 'outline' 816 ], 817 defaultValue: 'medium', 818 shortestValue: '0' 819 }, 820 'overflow': { 821 canOverride: canOverride.property.overflow, 822 defaultValue: 'visible' 823 }, 824 'overflow-x': { 825 canOverride: canOverride.property.overflow, 826 defaultValue: 'visible' 827 }, 828 'overflow-y': { 829 canOverride: canOverride.property.overflow, 830 defaultValue: 'visible' 831 }, 832 'padding': { 833 breakUp: breakUp.fourValues, 834 canOverride: canOverride.generic.components([ 835 canOverride.generic.unit, 836 canOverride.generic.unit, 837 canOverride.generic.unit, 838 canOverride.generic.unit 839 ]), 840 components: [ 841 'padding-top', 842 'padding-right', 843 'padding-bottom', 844 'padding-left' 845 ], 846 defaultValue: '0', 847 restore: restore.fourValues, 848 shorthand: true 849 }, 850 'padding-bottom': { 851 canOverride: canOverride.generic.unit, 852 componentOf: [ 853 'padding' 854 ], 855 defaultValue: '0', 856 oppositeTo: 'padding-top' 857 }, 858 'padding-left': { 859 canOverride: canOverride.generic.unit, 860 componentOf: [ 861 'padding' 862 ], 863 defaultValue: '0', 864 oppositeTo: 'padding-right' 865 }, 866 'padding-right': { 867 canOverride: canOverride.generic.unit, 868 componentOf: [ 869 'padding' 870 ], 871 defaultValue: '0', 872 oppositeTo: 'padding-left' 873 }, 874 'padding-top': { 875 canOverride: canOverride.generic.unit, 876 componentOf: [ 877 'padding' 878 ], 879 defaultValue: '0', 880 oppositeTo: 'padding-bottom' 881 }, 882 'position': { 883 canOverride: canOverride.property.position, 884 defaultValue: 'static' 885 }, 886 'right': { 887 canOverride: canOverride.property.right, 888 defaultValue: 'auto' 889 }, 890 'text-align': { 891 canOverride: canOverride.property.textAlign, 892 // NOTE: we can't tell the real default value here, as it depends on default text direction 893 // this is a hack, but it doesn't matter because this value will be either overridden or 894 // it will disappear anyway 895 defaultValue: 'left|right' 896 }, 897 'text-decoration': { 898 canOverride: canOverride.property.textDecoration, 899 defaultValue: 'none' 900 }, 901 'text-overflow': { 902 canOverride: canOverride.property.textOverflow, 903 defaultValue: 'none' 904 }, 905 'text-shadow': { 906 canOverride: canOverride.property.textShadow, 907 defaultValue: 'none' 908 }, 909 'top': { 910 canOverride: canOverride.property.top, 911 defaultValue: 'auto' 912 }, 913 'transform': { 914 canOverride: canOverride.property.transform, 915 vendorPrefixes: [ 916 '-moz-', 917 '-ms-', 918 '-webkit-' 919 ] 920 }, 921 'transition': { 922 breakUp: breakUp.multiplex(breakUp.transition), 923 canOverride: canOverride.generic.components([ 924 canOverride.property.transitionProperty, 925 canOverride.generic.time, 926 canOverride.generic.timingFunction, 927 canOverride.generic.time 928 ]), 929 components: [ 930 'transition-property', 931 'transition-duration', 932 'transition-timing-function', 933 'transition-delay' 934 ], 935 defaultValue: 'none', 936 restore: restore.multiplex(restore.withoutDefaults), 937 shorthand: true, 938 vendorPrefixes: [ 939 '-moz-', 940 '-o-', 941 '-webkit-' 942 ] 943 }, 944 'transition-delay': { 945 canOverride: canOverride.generic.time, 946 componentOf: [ 947 'transition' 948 ], 949 defaultValue: '0s', 950 intoMultiplexMode: 'real', 951 vendorPrefixes: [ 952 '-moz-', 953 '-o-', 954 '-webkit-' 955 ] 956 }, 957 'transition-duration': { 958 canOverride: canOverride.generic.time, 959 componentOf: [ 960 'transition' 961 ], 962 defaultValue: '0s', 963 intoMultiplexMode: 'real', 964 vendorPrefixes: [ 965 '-moz-', 966 '-o-', 967 '-webkit-' 968 ] 969 }, 970 'transition-property': { 971 canOverride: canOverride.generic.propertyName, 972 componentOf: [ 973 'transition' 974 ], 975 defaultValue: 'all', 976 intoMultiplexMode: 'placeholder', 977 placeholderValue: '_', // it's a short value that won't match any property and still be a valid `transition-property` 978 vendorPrefixes: [ 979 '-moz-', 980 '-o-', 981 '-webkit-' 982 ] 983 }, 984 'transition-timing-function': { 985 canOverride: canOverride.generic.timingFunction, 986 componentOf: [ 987 'transition' 988 ], 989 defaultValue: 'ease', 990 intoMultiplexMode: 'real', 991 vendorPrefixes: [ 992 '-moz-', 993 '-o-', 994 '-webkit-' 995 ] 996 }, 997 'vertical-align': { 998 canOverride: canOverride.property.verticalAlign, 999 defaultValue: 'baseline' 1000 }, 1001 'visibility': { 1002 canOverride: canOverride.property.visibility, 1003 defaultValue: 'visible' 1004 }, 1005 'white-space': { 1006 canOverride: canOverride.property.whiteSpace, 1007 defaultValue: 'normal' 1008 }, 1009 'width': { 1010 canOverride: canOverride.generic.unit, 1011 defaultValue: 'auto', 1012 shortestValue: '0' 1013 }, 1014 'z-index': { 1015 canOverride: canOverride.property.zIndex, 1016 defaultValue: 'auto' 1017 } 1018}; 1019 1020function cloneDescriptor(propertyName, prefix) { 1021 var clonedDescriptor = override(compactable[propertyName], {}); 1022 1023 if ('componentOf' in clonedDescriptor) { 1024 clonedDescriptor.componentOf = clonedDescriptor.componentOf.map(function (shorthandName) { 1025 return prefix + shorthandName; 1026 }); 1027 } 1028 1029 if ('components' in clonedDescriptor) { 1030 clonedDescriptor.components = clonedDescriptor.components.map(function (longhandName) { 1031 return prefix + longhandName; 1032 }); 1033 } 1034 1035 if ('keepUnlessDefault' in clonedDescriptor) { 1036 clonedDescriptor.keepUnlessDefault = prefix + clonedDescriptor.keepUnlessDefault; 1037 } 1038 1039 return clonedDescriptor; 1040} 1041 1042// generate vendor-prefixed properties 1043var vendorPrefixedCompactable = {}; 1044 1045for (var propertyName in compactable) { 1046 var descriptor = compactable[propertyName]; 1047 1048 if (!('vendorPrefixes' in descriptor)) { 1049 continue; 1050 } 1051 1052 for (var i = 0; i < descriptor.vendorPrefixes.length; i++) { 1053 var prefix = descriptor.vendorPrefixes[i]; 1054 var clonedDescriptor = cloneDescriptor(propertyName, prefix); 1055 delete clonedDescriptor.vendorPrefixes; 1056 1057 vendorPrefixedCompactable[prefix + propertyName] = clonedDescriptor; 1058 } 1059 1060 delete descriptor.vendorPrefixes; 1061} 1062 1063module.exports = override(compactable, vendorPrefixedCompactable); 1064