compactable.js 25 KB

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