compactable.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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. // Properties to process
  6. // Extend this object in order to add support for more properties in the optimizer.
  7. //
  8. // Each key in this object represents a CSS property and should be an object.
  9. // Such an object contains properties that describe how the represented CSS property should be handled.
  10. // Possible options:
  11. //
  12. // * components: array (Only specify for shorthand properties.)
  13. // Contains the names of the granular properties this shorthand compacts.
  14. //
  15. // * canOverride: function (Default is canOverride.sameValue - meaning that they'll only be merged if they have the same value.)
  16. // Returns whether two tokens of this property can be merged with each other.
  17. // This property has no meaning for shorthands.
  18. //
  19. // * defaultValue: string
  20. // Specifies the default value of the property according to the CSS standard.
  21. // 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.
  22. //
  23. // * shortestValue: string
  24. // Specifies the shortest possible value the property can possibly have.
  25. // (Falls back to defaultValue if unspecified.)
  26. //
  27. // * breakUp: function (Only specify for shorthand properties.)
  28. // Breaks the shorthand up to its components.
  29. //
  30. // * restore: function (Only specify for shorthand properties.)
  31. // Puts the shorthand together from its components.
  32. //
  33. var compactable = {
  34. 'color': {
  35. canOverride: canOverride.color,
  36. defaultValue: 'transparent',
  37. shortestValue: 'red'
  38. },
  39. 'background': {
  40. components: [
  41. 'background-image',
  42. 'background-position',
  43. 'background-size',
  44. 'background-repeat',
  45. 'background-attachment',
  46. 'background-origin',
  47. 'background-clip',
  48. 'background-color'
  49. ],
  50. breakUp: breakUp.multiplex(breakUp.background),
  51. defaultValue: '0 0',
  52. restore: restore.multiplex(restore.background),
  53. shortestValue: '0',
  54. shorthand: true
  55. },
  56. 'background-clip': {
  57. canOverride: canOverride.always,
  58. defaultValue: 'border-box',
  59. shortestValue: 'border-box'
  60. },
  61. 'background-color': {
  62. canOverride: canOverride.color,
  63. defaultValue: 'transparent',
  64. multiplexLastOnly: true,
  65. nonMergeableValue: 'none',
  66. shortestValue: 'red'
  67. },
  68. 'background-image': {
  69. canOverride: canOverride.backgroundImage,
  70. defaultValue: 'none'
  71. },
  72. 'background-origin': {
  73. canOverride: canOverride.always,
  74. defaultValue: 'padding-box',
  75. shortestValue: 'border-box'
  76. },
  77. 'background-repeat': {
  78. canOverride: canOverride.always,
  79. defaultValue: ['repeat'],
  80. doubleValues: true
  81. },
  82. 'background-position': {
  83. canOverride: canOverride.alwaysButIntoFunction,
  84. defaultValue: ['0', '0'],
  85. doubleValues: true,
  86. shortestValue: '0'
  87. },
  88. 'background-size': {
  89. canOverride: canOverride.alwaysButIntoFunction,
  90. defaultValue: ['auto'],
  91. doubleValues: true,
  92. shortestValue: '0 0'
  93. },
  94. 'background-attachment': {
  95. canOverride: canOverride.always,
  96. defaultValue: 'scroll'
  97. },
  98. 'border': {
  99. breakUp: breakUp.border,
  100. canOverride: canOverride.border,
  101. components: [
  102. 'border-width',
  103. 'border-style',
  104. 'border-color'
  105. ],
  106. defaultValue: 'none',
  107. restore: restore.withoutDefaults,
  108. shorthand: true
  109. },
  110. 'border-color': {
  111. canOverride: canOverride.color,
  112. defaultValue: 'none',
  113. shorthand: true
  114. },
  115. 'border-style': {
  116. canOverride: canOverride.always,
  117. defaultValue: 'none',
  118. shorthand: true
  119. },
  120. 'border-width': {
  121. canOverride: canOverride.unit,
  122. defaultValue: 'medium',
  123. shortestValue: '0',
  124. shorthand: true
  125. },
  126. 'list-style': {
  127. components: [
  128. 'list-style-type',
  129. 'list-style-position',
  130. 'list-style-image'
  131. ],
  132. canOverride: canOverride.always,
  133. breakUp: breakUp.listStyle,
  134. restore: restore.withoutDefaults,
  135. defaultValue: 'outside', // can't use 'disc' because that'd override default 'decimal' for <ol>
  136. shortestValue: 'none',
  137. shorthand: true
  138. },
  139. 'list-style-type' : {
  140. canOverride: canOverride.always,
  141. defaultValue: '__hack',
  142. // NOTE: we can't tell the real default value here, it's 'disc' for <ul> and 'decimal' for <ol>
  143. // -- this is a hack, but it doesn't matter because this value will be either overridden or it will disappear at the final step anyway
  144. shortestValue: 'none'
  145. },
  146. 'list-style-position' : {
  147. canOverride: canOverride.always,
  148. defaultValue: 'outside',
  149. shortestValue: 'inside'
  150. },
  151. 'list-style-image' : {
  152. canOverride: canOverride.always,
  153. defaultValue: 'none'
  154. },
  155. 'outline': {
  156. components: [
  157. 'outline-color',
  158. 'outline-style',
  159. 'outline-width'
  160. ],
  161. breakUp: breakUp.outline,
  162. restore: restore.withoutDefaults,
  163. defaultValue: '0',
  164. shorthand: true
  165. },
  166. 'outline-color': {
  167. canOverride: canOverride.color,
  168. defaultValue: 'invert',
  169. shortestValue: 'red'
  170. },
  171. 'outline-style': {
  172. canOverride: canOverride.always,
  173. defaultValue: 'none'
  174. },
  175. 'outline-width': {
  176. canOverride: canOverride.unit,
  177. defaultValue: 'medium',
  178. shortestValue: '0'
  179. },
  180. '-moz-transform': {
  181. canOverride: canOverride.sameFunctionOrValue
  182. },
  183. '-ms-transform': {
  184. canOverride: canOverride.sameFunctionOrValue
  185. },
  186. '-webkit-transform': {
  187. canOverride: canOverride.sameFunctionOrValue
  188. },
  189. 'transform': {
  190. canOverride: canOverride.sameFunctionOrValue
  191. }
  192. };
  193. var addFourValueShorthand = function (prop, components, options) {
  194. options = options || {};
  195. compactable[prop] = {
  196. canOverride: options.canOverride,
  197. components: components,
  198. breakUp: options.breakUp || breakUp.fourValues,
  199. defaultValue: options.defaultValue || '0',
  200. restore: options.restore || restore.fourValues,
  201. shortestValue: options.shortestValue,
  202. shorthand: true
  203. };
  204. for (var i = 0; i < components.length; i++) {
  205. compactable[components[i]] = {
  206. breakUp: options.breakUp || breakUp.fourValues,
  207. canOverride: options.canOverride || canOverride.unit,
  208. defaultValue: options.defaultValue || '0',
  209. shortestValue: options.shortestValue
  210. };
  211. }
  212. };
  213. ['', '-moz-', '-o-'].forEach(function (prefix) {
  214. addFourValueShorthand(prefix + 'border-radius', [
  215. prefix + 'border-top-left-radius',
  216. prefix + 'border-top-right-radius',
  217. prefix + 'border-bottom-right-radius',
  218. prefix + 'border-bottom-left-radius'
  219. ], {
  220. breakUp: breakUp.borderRadius,
  221. restore: restore.borderRadius
  222. });
  223. });
  224. addFourValueShorthand('border-color', [
  225. 'border-top-color',
  226. 'border-right-color',
  227. 'border-bottom-color',
  228. 'border-left-color'
  229. ], {
  230. breakUp: breakUp.fourValues,
  231. canOverride: canOverride.color,
  232. defaultValue: 'none',
  233. shortestValue: 'red'
  234. });
  235. addFourValueShorthand('border-style', [
  236. 'border-top-style',
  237. 'border-right-style',
  238. 'border-bottom-style',
  239. 'border-left-style'
  240. ], {
  241. breakUp: breakUp.fourValues,
  242. canOverride: canOverride.always,
  243. defaultValue: 'none'
  244. });
  245. addFourValueShorthand('border-width', [
  246. 'border-top-width',
  247. 'border-right-width',
  248. 'border-bottom-width',
  249. 'border-left-width'
  250. ], {
  251. defaultValue: 'medium',
  252. shortestValue: '0'
  253. });
  254. addFourValueShorthand('padding', [
  255. 'padding-top',
  256. 'padding-right',
  257. 'padding-bottom',
  258. 'padding-left'
  259. ]);
  260. addFourValueShorthand('margin', [
  261. 'margin-top',
  262. 'margin-right',
  263. 'margin-bottom',
  264. 'margin-left'
  265. ]);
  266. // Adds `componentOf` field to all longhands
  267. for (var property in compactable) {
  268. if (compactable[property].shorthand) {
  269. for (var i = 0, l = compactable[property].components.length; i < l; i++) {
  270. compactable[compactable[property].components[i]].componentOf = property;
  271. }
  272. }
  273. }
  274. module.exports = compactable;