legacyLogicalProperties.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. function splitValues(value) {
  2. if (typeof value === 'number') {
  3. return [value];
  4. }
  5. const splitStyle = String(value).split(/\s+/);
  6. // Combine styles split in brackets, like `calc(1px + 2px)`
  7. let temp = '';
  8. let brackets = 0;
  9. return splitStyle.reduce((list, item) => {
  10. if (item.includes('(')) {
  11. temp += item;
  12. brackets += item.split('(').length - 1;
  13. } else if (item.includes(')')) {
  14. temp += ` ${item}`;
  15. brackets -= item.split(')').length - 1;
  16. if (brackets === 0) {
  17. list.push(temp);
  18. temp = '';
  19. }
  20. } else if (brackets > 0) {
  21. temp += ` ${item}`;
  22. } else {
  23. list.push(item);
  24. }
  25. return list;
  26. }, []);
  27. }
  28. function noSplit(list) {
  29. list.notSplit = true;
  30. return list;
  31. }
  32. const keyMap = {
  33. // Inset
  34. inset: ['top', 'right', 'bottom', 'left'],
  35. insetBlock: ['top', 'bottom'],
  36. insetBlockStart: ['top'],
  37. insetBlockEnd: ['bottom'],
  38. insetInline: ['left', 'right'],
  39. insetInlineStart: ['left'],
  40. insetInlineEnd: ['right'],
  41. // Margin
  42. marginBlock: ['marginTop', 'marginBottom'],
  43. marginBlockStart: ['marginTop'],
  44. marginBlockEnd: ['marginBottom'],
  45. marginInline: ['marginLeft', 'marginRight'],
  46. marginInlineStart: ['marginLeft'],
  47. marginInlineEnd: ['marginRight'],
  48. // Padding
  49. paddingBlock: ['paddingTop', 'paddingBottom'],
  50. paddingBlockStart: ['paddingTop'],
  51. paddingBlockEnd: ['paddingBottom'],
  52. paddingInline: ['paddingLeft', 'paddingRight'],
  53. paddingInlineStart: ['paddingLeft'],
  54. paddingInlineEnd: ['paddingRight'],
  55. // Border
  56. borderBlock: noSplit(['borderTop', 'borderBottom']),
  57. borderBlockStart: noSplit(['borderTop']),
  58. borderBlockEnd: noSplit(['borderBottom']),
  59. borderInline: noSplit(['borderLeft', 'borderRight']),
  60. borderInlineStart: noSplit(['borderLeft']),
  61. borderInlineEnd: noSplit(['borderRight']),
  62. // Border width
  63. borderBlockWidth: ['borderTopWidth', 'borderBottomWidth'],
  64. borderBlockStartWidth: ['borderTopWidth'],
  65. borderBlockEndWidth: ['borderBottomWidth'],
  66. borderInlineWidth: ['borderLeftWidth', 'borderRightWidth'],
  67. borderInlineStartWidth: ['borderLeftWidth'],
  68. borderInlineEndWidth: ['borderRightWidth'],
  69. // Border style
  70. borderBlockStyle: ['borderTopStyle', 'borderBottomStyle'],
  71. borderBlockStartStyle: ['borderTopStyle'],
  72. borderBlockEndStyle: ['borderBottomStyle'],
  73. borderInlineStyle: ['borderLeftStyle', 'borderRightStyle'],
  74. borderInlineStartStyle: ['borderLeftStyle'],
  75. borderInlineEndStyle: ['borderRightStyle'],
  76. // Border color
  77. borderBlockColor: ['borderTopColor', 'borderBottomColor'],
  78. borderBlockStartColor: ['borderTopColor'],
  79. borderBlockEndColor: ['borderBottomColor'],
  80. borderInlineColor: ['borderLeftColor', 'borderRightColor'],
  81. borderInlineStartColor: ['borderLeftColor'],
  82. borderInlineEndColor: ['borderRightColor'],
  83. // Border radius
  84. borderStartStartRadius: ['borderTopLeftRadius'],
  85. borderStartEndRadius: ['borderTopRightRadius'],
  86. borderEndStartRadius: ['borderBottomLeftRadius'],
  87. borderEndEndRadius: ['borderBottomRightRadius']
  88. };
  89. function skipCheck(value) {
  90. return {
  91. _skip_check_: true,
  92. value
  93. };
  94. }
  95. /**
  96. * Convert css logical properties to legacy properties.
  97. * Such as: `margin-block-start` to `margin-top`.
  98. * Transform list:
  99. * - inset
  100. * - margin
  101. * - padding
  102. * - border
  103. */
  104. const transform = {
  105. visit: cssObj => {
  106. const clone = {};
  107. Object.keys(cssObj).forEach(key => {
  108. const value = cssObj[key];
  109. const matchValue = keyMap[key];
  110. if (matchValue && (typeof value === 'number' || typeof value === 'string')) {
  111. const values = splitValues(value);
  112. if (matchValue.length && matchValue.notSplit) {
  113. // not split means always give same value like border
  114. matchValue.forEach(matchKey => {
  115. clone[matchKey] = skipCheck(value);
  116. });
  117. } else if (matchValue.length === 1) {
  118. // Handle like `marginBlockStart` => `marginTop`
  119. clone[matchValue[0]] = skipCheck(value);
  120. } else if (matchValue.length === 2) {
  121. // Handle like `marginBlock` => `marginTop` & `marginBottom`
  122. matchValue.forEach((matchKey, index) => {
  123. var _a;
  124. clone[matchKey] = skipCheck((_a = values[index]) !== null && _a !== void 0 ? _a : values[0]);
  125. });
  126. } else if (matchValue.length === 4) {
  127. // Handle like `inset` => `top` & `right` & `bottom` & `left`
  128. matchValue.forEach((matchKey, index) => {
  129. var _a, _b;
  130. clone[matchKey] = skipCheck((_b = (_a = values[index]) !== null && _a !== void 0 ? _a : values[index - 2]) !== null && _b !== void 0 ? _b : values[0]);
  131. });
  132. } else {
  133. clone[key] = value;
  134. }
  135. } else {
  136. clone[key] = value;
  137. }
  138. });
  139. return clone;
  140. }
  141. };
  142. export default transform;