a zip code crypto-currency system good for red ONLY

override-properties.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. var hasInherit = require('./has-inherit');
  2. var everyValuesPair = require('./every-values-pair');
  3. var findComponentIn = require('./find-component-in');
  4. var isComponentOf = require('./is-component-of');
  5. var isMergeableShorthand = require('./is-mergeable-shorthand');
  6. var overridesNonComponentShorthand = require('./overrides-non-component-shorthand');
  7. var sameVendorPrefixesIn = require('./vendor-prefixes').same;
  8. var compactable = require('../compactable');
  9. var deepClone = require('../clone').deep;
  10. var deepClone = require('../clone').deep;
  11. var restoreWithComponents = require('../restore-with-components');
  12. var shallowClone = require('../clone').shallow;
  13. var restoreFromOptimizing = require('../../restore-from-optimizing');
  14. var Token = require('../../../tokenizer/token');
  15. var Marker = require('../../../tokenizer/marker');
  16. var serializeProperty = require('../../../writer/one-time').property;
  17. function wouldBreakCompatibility(property, validator) {
  18. for (var i = 0; i < property.components.length; i++) {
  19. var component = property.components[i];
  20. var descriptor = compactable[component.name];
  21. var canOverride = descriptor && descriptor.canOverride || canOverride.sameValue;
  22. var _component = shallowClone(component);
  23. _component.value = [[Token.PROPERTY_VALUE, descriptor.defaultValue]];
  24. if (!everyValuesPair(canOverride.bind(null, validator), _component, component)) {
  25. return true;
  26. }
  27. }
  28. return false;
  29. }
  30. function overrideIntoMultiplex(property, by) {
  31. by.unused = true;
  32. turnIntoMultiplex(by, multiplexSize(property));
  33. property.value = by.value;
  34. }
  35. function overrideByMultiplex(property, by) {
  36. by.unused = true;
  37. property.multiplex = true;
  38. property.value = by.value;
  39. }
  40. function overrideSimple(property, by) {
  41. by.unused = true;
  42. property.value = by.value;
  43. }
  44. function override(property, by) {
  45. if (by.multiplex)
  46. overrideByMultiplex(property, by);
  47. else if (property.multiplex)
  48. overrideIntoMultiplex(property, by);
  49. else
  50. overrideSimple(property, by);
  51. }
  52. function overrideShorthand(property, by) {
  53. by.unused = true;
  54. for (var i = 0, l = property.components.length; i < l; i++) {
  55. override(property.components[i], by.components[i], property.multiplex);
  56. }
  57. }
  58. function turnIntoMultiplex(property, size) {
  59. property.multiplex = true;
  60. if (compactable[property.name].shorthand) {
  61. turnShorthandValueIntoMultiplex(property, size);
  62. } else {
  63. turnLonghandValueIntoMultiplex(property, size);
  64. }
  65. }
  66. function turnShorthandValueIntoMultiplex(property, size) {
  67. var component;
  68. var i, l;
  69. for (i = 0, l = property.components.length; i < l; i++) {
  70. component = property.components[i];
  71. if (!component.multiplex) {
  72. turnLonghandValueIntoMultiplex(component, size);
  73. }
  74. }
  75. }
  76. function turnLonghandValueIntoMultiplex(property, size) {
  77. var withRealValue = compactable[property.name].intoMultiplexMode == 'real';
  78. var withValue = withRealValue ?
  79. property.value.slice(0) :
  80. compactable[property.name].defaultValue;
  81. var i = multiplexSize(property);
  82. var j;
  83. var m = withValue.length;
  84. for (; i < size; i++) {
  85. property.value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
  86. if (Array.isArray(withValue)) {
  87. for (j = 0; j < m; j++) {
  88. property.value.push(withRealValue ? withValue[j] : [Token.PROPERTY_VALUE, withValue[j]]);
  89. }
  90. } else {
  91. property.value.push(withRealValue ? withValue : [Token.PROPERTY_VALUE, withValue]);
  92. }
  93. }
  94. }
  95. function multiplexSize(component) {
  96. var size = 0;
  97. for (var i = 0, l = component.value.length; i < l; i++) {
  98. if (component.value[i][1] == Marker.COMMA)
  99. size++;
  100. }
  101. return size + 1;
  102. }
  103. function lengthOf(property) {
  104. var fakeAsArray = [
  105. Token.PROPERTY,
  106. [Token.PROPERTY_NAME, property.name]
  107. ].concat(property.value);
  108. return serializeProperty([fakeAsArray], 0).length;
  109. }
  110. function moreSameShorthands(properties, startAt, name) {
  111. // Since we run the main loop in `compactOverrides` backwards, at this point some
  112. // properties may not be marked as unused.
  113. // We should consider reverting the order if possible
  114. var count = 0;
  115. for (var i = startAt; i >= 0; i--) {
  116. if (properties[i].name == name && !properties[i].unused)
  117. count++;
  118. if (count > 1)
  119. break;
  120. }
  121. return count > 1;
  122. }
  123. function overridingFunction(shorthand, validator) {
  124. for (var i = 0, l = shorthand.components.length; i < l; i++) {
  125. if (!anyValue(validator.isUrl, shorthand.components[i]) && anyValue(validator.isFunction, shorthand.components[i])) {
  126. return true;
  127. }
  128. }
  129. return false;
  130. }
  131. function anyValue(fn, property) {
  132. for (var i = 0, l = property.value.length; i < l; i++) {
  133. if (property.value[i][1] == Marker.COMMA)
  134. continue;
  135. if (fn(property.value[i][1]))
  136. return true;
  137. }
  138. return false;
  139. }
  140. function wouldResultInLongerValue(left, right) {
  141. if (!left.multiplex && !right.multiplex || left.multiplex && right.multiplex)
  142. return false;
  143. var multiplex = left.multiplex ? left : right;
  144. var simple = left.multiplex ? right : left;
  145. var component;
  146. var multiplexClone = deepClone(multiplex);
  147. restoreFromOptimizing([multiplexClone], restoreWithComponents);
  148. var simpleClone = deepClone(simple);
  149. restoreFromOptimizing([simpleClone], restoreWithComponents);
  150. var lengthBefore = lengthOf(multiplexClone) + 1 + lengthOf(simpleClone);
  151. if (left.multiplex) {
  152. component = findComponentIn(multiplexClone, simpleClone);
  153. overrideIntoMultiplex(component, simpleClone);
  154. } else {
  155. component = findComponentIn(simpleClone, multiplexClone);
  156. turnIntoMultiplex(simpleClone, multiplexSize(multiplexClone));
  157. overrideByMultiplex(component, multiplexClone);
  158. }
  159. restoreFromOptimizing([simpleClone], restoreWithComponents);
  160. var lengthAfter = lengthOf(simpleClone);
  161. return lengthBefore <= lengthAfter;
  162. }
  163. function isCompactable(property) {
  164. return property.name in compactable;
  165. }
  166. function noneOverrideHack(left, right) {
  167. return !left.multiplex &&
  168. (left.name == 'background' || left.name == 'background-image') &&
  169. right.multiplex &&
  170. (right.name == 'background' || right.name == 'background-image') &&
  171. anyLayerIsNone(right.value);
  172. }
  173. function anyLayerIsNone(values) {
  174. var layers = intoLayers(values);
  175. for (var i = 0, l = layers.length; i < l; i++) {
  176. if (layers[i].length == 1 && layers[i][0][1] == 'none')
  177. return true;
  178. }
  179. return false;
  180. }
  181. function intoLayers(values) {
  182. var layers = [];
  183. for (var i = 0, layer = [], l = values.length; i < l; i++) {
  184. var value = values[i];
  185. if (value[1] == Marker.COMMA) {
  186. layers.push(layer);
  187. layer = [];
  188. } else {
  189. layer.push(value);
  190. }
  191. }
  192. layers.push(layer);
  193. return layers;
  194. }
  195. function overrideProperties(properties, withMerging, compatibility, validator) {
  196. var mayOverride, right, left, component;
  197. var overriddenComponents;
  198. var overriddenComponent;
  199. var overridingComponent;
  200. var overridable;
  201. var i, j, k;
  202. propertyLoop:
  203. for (i = properties.length - 1; i >= 0; i--) {
  204. right = properties[i];
  205. if (!isCompactable(right))
  206. continue;
  207. if (right.block)
  208. continue;
  209. mayOverride = compactable[right.name].canOverride;
  210. traverseLoop:
  211. for (j = i - 1; j >= 0; j--) {
  212. left = properties[j];
  213. if (!isCompactable(left))
  214. continue;
  215. if (left.block)
  216. continue;
  217. if (left.unused || right.unused)
  218. continue;
  219. if (left.hack && !right.hack && !right.important || !left.hack && !left.important && right.hack)
  220. continue;
  221. if (left.important == right.important && left.hack[0] != right.hack[0])
  222. continue;
  223. if (left.important == right.important && (left.hack[0] != right.hack[0] || (left.hack[1] && left.hack[1] != right.hack[1])))
  224. continue;
  225. if (hasInherit(right))
  226. continue;
  227. if (noneOverrideHack(left, right))
  228. continue;
  229. if (right.shorthand && isComponentOf(right, left)) {
  230. // maybe `left` can be overridden by `right` which is a shorthand?
  231. if (!right.important && left.important)
  232. continue;
  233. if (!sameVendorPrefixesIn([left], right.components))
  234. continue;
  235. if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator))
  236. continue;
  237. if (!isMergeableShorthand(right)) {
  238. left.unused = true;
  239. continue;
  240. }
  241. component = findComponentIn(right, left);
  242. mayOverride = compactable[left.name].canOverride;
  243. if (everyValuesPair(mayOverride.bind(null, validator), left, component)) {
  244. left.unused = true;
  245. }
  246. } else if (right.shorthand && overridesNonComponentShorthand(right, left)) {
  247. // `right` is a shorthand while `left` can be overriden by it, think `border` and `border-top`
  248. if (!right.important && left.important) {
  249. continue;
  250. }
  251. if (!sameVendorPrefixesIn([left], right.components)) {
  252. continue;
  253. }
  254. if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator)) {
  255. continue;
  256. }
  257. overriddenComponents = left.shorthand ?
  258. left.components:
  259. [left];
  260. for (k = overriddenComponents.length - 1; k >= 0; k--) {
  261. overriddenComponent = overriddenComponents[k];
  262. overridingComponent = findComponentIn(right, overriddenComponent);
  263. mayOverride = compactable[overriddenComponent.name].canOverride;
  264. if (!everyValuesPair(mayOverride.bind(null, validator), left, overridingComponent)) {
  265. continue traverseLoop;
  266. }
  267. }
  268. left.unused = true;
  269. } else if (withMerging && left.shorthand && !right.shorthand && isComponentOf(left, right, true)) {
  270. // maybe `right` can be pulled into `left` which is a shorthand?
  271. if (right.important && !left.important)
  272. continue;
  273. if (!right.important && left.important) {
  274. right.unused = true;
  275. continue;
  276. }
  277. // Pending more clever algorithm in #527
  278. if (moreSameShorthands(properties, i - 1, left.name))
  279. continue;
  280. if (overridingFunction(left, validator))
  281. continue;
  282. if (!isMergeableShorthand(left))
  283. continue;
  284. component = findComponentIn(left, right);
  285. if (everyValuesPair(mayOverride.bind(null, validator), component, right)) {
  286. var disabledBackgroundMerging =
  287. !compatibility.properties.backgroundClipMerging && component.name.indexOf('background-clip') > -1 ||
  288. !compatibility.properties.backgroundOriginMerging && component.name.indexOf('background-origin') > -1 ||
  289. !compatibility.properties.backgroundSizeMerging && component.name.indexOf('background-size') > -1;
  290. var nonMergeableValue = compactable[right.name].nonMergeableValue === right.value[0][1];
  291. if (disabledBackgroundMerging || nonMergeableValue)
  292. continue;
  293. if (!compatibility.properties.merging && wouldBreakCompatibility(left, validator))
  294. continue;
  295. if (component.value[0][1] != right.value[0][1] && (hasInherit(left) || hasInherit(right)))
  296. continue;
  297. if (wouldResultInLongerValue(left, right))
  298. continue;
  299. if (!left.multiplex && right.multiplex)
  300. turnIntoMultiplex(left, multiplexSize(right));
  301. override(component, right);
  302. left.dirty = true;
  303. }
  304. } else if (withMerging && left.shorthand && right.shorthand && left.name == right.name) {
  305. // merge if all components can be merged
  306. if (!left.multiplex && right.multiplex)
  307. continue;
  308. if (!right.important && left.important) {
  309. right.unused = true;
  310. continue propertyLoop;
  311. }
  312. if (right.important && !left.important) {
  313. left.unused = true;
  314. continue;
  315. }
  316. if (!isMergeableShorthand(right)) {
  317. left.unused = true;
  318. continue;
  319. }
  320. for (k = left.components.length - 1; k >= 0; k--) {
  321. var leftComponent = left.components[k];
  322. var rightComponent = right.components[k];
  323. mayOverride = compactable[leftComponent.name].canOverride;
  324. if (!everyValuesPair(mayOverride.bind(null, validator), leftComponent, rightComponent))
  325. continue propertyLoop;
  326. }
  327. overrideShorthand(left, right);
  328. left.dirty = true;
  329. } else if (withMerging && left.shorthand && right.shorthand && isComponentOf(left, right)) {
  330. // border is a shorthand but any of its components is a shorthand too
  331. if (!left.important && right.important)
  332. continue;
  333. component = findComponentIn(left, right);
  334. mayOverride = compactable[right.name].canOverride;
  335. if (!everyValuesPair(mayOverride.bind(null, validator), component, right))
  336. continue;
  337. if (left.important && !right.important) {
  338. right.unused = true;
  339. continue;
  340. }
  341. var rightRestored = compactable[right.name].restore(right, compactable);
  342. if (rightRestored.length > 1)
  343. continue;
  344. component = findComponentIn(left, right);
  345. override(component, right);
  346. right.dirty = true;
  347. } else if (left.name == right.name) {
  348. // two non-shorthands should be merged based on understandability
  349. overridable = true;
  350. if (right.shorthand) {
  351. for (k = right.components.length - 1; k >= 0 && overridable; k--) {
  352. overriddenComponent = left.components[k];
  353. overridingComponent = right.components[k];
  354. mayOverride = compactable[overridingComponent.name].canOverride;
  355. overridable = overridable && everyValuesPair(mayOverride.bind(null, validator), overriddenComponent, overridingComponent);
  356. }
  357. } else {
  358. mayOverride = compactable[right.name].canOverride;
  359. overridable = everyValuesPair(mayOverride.bind(null, validator), left, right);
  360. }
  361. if (left.important && !right.important && overridable) {
  362. right.unused = true;
  363. continue;
  364. }
  365. if (!left.important && right.important && overridable) {
  366. left.unused = true;
  367. continue;
  368. }
  369. if (!overridable) {
  370. continue;
  371. }
  372. left.unused = true;
  373. }
  374. }
  375. }
  376. }
  377. module.exports = overrideProperties;