backgroundPosition.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. "use strict";
  2. const parsers = require("../parsers");
  3. const property = "background-position";
  4. const shorthand = "background";
  5. const keyX = ["left", "right"];
  6. const keyY = ["top", "bottom"];
  7. const keywordsX = ["center", ...keyX];
  8. const keywordsY = ["center", ...keyY];
  9. const keywords = ["center", ...keyX, ...keyY];
  10. module.exports.parse = (v, opt = {}) => {
  11. const { globalObject } = opt;
  12. if (v === "") {
  13. return v;
  14. }
  15. const { AST_TYPES } = parsers;
  16. const values = parsers.splitValue(v, {
  17. delimiter: ","
  18. });
  19. const parsedValues = [];
  20. for (const val of values) {
  21. const value = parsers.parsePropertyValue(property, val, {
  22. globalObject,
  23. inArray: true
  24. });
  25. if (Array.isArray(value) && value.length) {
  26. const [part1, part2, part3, part4] = value;
  27. let parsedValue = "";
  28. switch (value.length) {
  29. case 1: {
  30. const val1 =
  31. part1.type === AST_TYPES.IDENTIFIER
  32. ? part1.name
  33. : parsers.resolveNumericValue([part1], { type: "length" });
  34. if (val1) {
  35. if (val1 === "center") {
  36. parsedValue = `${val1} ${val1}`;
  37. } else if (val1 === "top" || val1 === "bottom") {
  38. parsedValue = `center ${val1}`;
  39. } else {
  40. parsedValue = `${val1} center`;
  41. }
  42. }
  43. break;
  44. }
  45. case 2: {
  46. const val1 =
  47. part1.type === AST_TYPES.IDENTIFIER
  48. ? part1.name
  49. : parsers.resolveNumericValue([part1], { type: "length" });
  50. const val2 =
  51. part2.type === AST_TYPES.IDENTIFIER
  52. ? part2.name
  53. : parsers.resolveNumericValue([part2], { type: "length" });
  54. if (val1 && val2) {
  55. if (keywordsX.includes(val1) && keywordsY.includes(val2)) {
  56. parsedValue = `${val1} ${val2}`;
  57. } else if (keywordsY.includes(val1) && keywordsX.includes(val2)) {
  58. parsedValue = `${val2} ${val1}`;
  59. } else if (keywordsX.includes(val1)) {
  60. if (val2 === "center" || !keywordsX.includes(val2)) {
  61. parsedValue = `${val1} ${val2}`;
  62. }
  63. } else if (keywordsY.includes(val2)) {
  64. if (!keywordsY.includes(val1)) {
  65. parsedValue = `${val1} ${val2}`;
  66. }
  67. } else if (!keywordsY.includes(val1) && !keywordsX.includes(val2)) {
  68. parsedValue = `${val1} ${val2}`;
  69. }
  70. }
  71. break;
  72. }
  73. case 3: {
  74. const val1 = part1.type === AST_TYPES.IDENTIFIER && part1.name;
  75. const val2 =
  76. part2.type === AST_TYPES.IDENTIFIER
  77. ? part2.name
  78. : parsers.resolveNumericValue([part2], { type: "length" });
  79. const val3 =
  80. part3.type === AST_TYPES.IDENTIFIER
  81. ? part3.name
  82. : parsers.resolveNumericValue([part3], { type: "length" });
  83. if (val1 && val2 && val3) {
  84. let posX = "";
  85. let offX = "";
  86. let posY = "";
  87. let offY = "";
  88. if (keywordsX.includes(val1)) {
  89. if (keyY.includes(val2)) {
  90. if (!keywords.includes(val3)) {
  91. posX = val1;
  92. posY = val2;
  93. offY = val3;
  94. }
  95. } else if (keyY.includes(val3)) {
  96. if (!keywords.includes(val2)) {
  97. posX = val1;
  98. offX = val2;
  99. posY = val3;
  100. }
  101. }
  102. } else if (keywordsY.includes(val1)) {
  103. if (keyX.includes(val2)) {
  104. if (!keywords.includes(val3)) {
  105. posX = val2;
  106. offX = val3;
  107. posY = val1;
  108. }
  109. } else if (keyX.includes(val3)) {
  110. if (!keywords.includes(val2)) {
  111. posX = val3;
  112. posY = val1;
  113. offY = val2;
  114. }
  115. }
  116. }
  117. if (posX && posY) {
  118. if (offX) {
  119. parsedValue = `${posX} ${offX} ${posY}`;
  120. } else if (offY) {
  121. parsedValue = `${posX} ${posY} ${offY}`;
  122. }
  123. }
  124. }
  125. break;
  126. }
  127. case 4: {
  128. const val1 = part1.type === AST_TYPES.IDENTIFIER && part1.name;
  129. const val2 = parsers.resolveNumericValue([part2], { type: "length" });
  130. const val3 = part3.type === AST_TYPES.IDENTIFIER && part3.name;
  131. const val4 = parsers.resolveNumericValue([part4], { type: "length" });
  132. if (val1 && val2 && val3 && val4) {
  133. let posX = "";
  134. let offX = "";
  135. let posY = "";
  136. let offY = "";
  137. if (keywordsX.includes(val1) && keyY.includes(val3)) {
  138. posX = val1;
  139. offX = val2;
  140. posY = val3;
  141. offY = val4;
  142. } else if (keyX.includes(val1) && keywordsY.includes(val3)) {
  143. posX = val1;
  144. offX = val2;
  145. posY = val3;
  146. offY = val4;
  147. } else if (keyY.includes(val1) && keywordsX.includes(val3)) {
  148. posX = val3;
  149. offX = val4;
  150. posY = val1;
  151. offY = val2;
  152. }
  153. if (posX && offX && posY && offY) {
  154. parsedValue = `${posX} ${offX} ${posY} ${offY}`;
  155. }
  156. }
  157. break;
  158. }
  159. default:
  160. }
  161. if (parsedValue) {
  162. parsedValues.push(parsedValue);
  163. } else {
  164. return;
  165. }
  166. } else if (typeof value === "string") {
  167. parsedValues.push(value);
  168. }
  169. }
  170. if (parsedValues.length) {
  171. return parsedValues.join(", ");
  172. }
  173. };
  174. module.exports.definition = {
  175. set(v) {
  176. v = parsers.prepareValue(v);
  177. if (parsers.hasVarFunc(v)) {
  178. this._setProperty(shorthand, "");
  179. this._setProperty(property, v);
  180. } else {
  181. const val = module.exports.parse(v, {
  182. globalObject: this._global
  183. });
  184. if (typeof val === "string") {
  185. const priority =
  186. !this._priorities.get(shorthand) && this._priorities.has(property)
  187. ? this._priorities.get(property)
  188. : "";
  189. this._setProperty(property, val, priority);
  190. }
  191. }
  192. },
  193. get() {
  194. return this.getPropertyValue(property);
  195. },
  196. enumerable: true,
  197. configurable: true
  198. };
  199. module.exports.property = property;