transformClass.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.createVirtualHostClass = exports.rewriteClass = exports.findStaticClassIndex = exports.isClassBinding = void 0;
  4. const types_1 = require("@babel/types");
  5. const compiler_core_1 = require("@vue/compiler-core");
  6. const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
  7. const ast_1 = require("../ast");
  8. const codegen_1 = require("../codegen");
  9. const runtimeHelpers_1 = require("../runtimeHelpers");
  10. const utils_1 = require("./utils");
  11. function isClassBinding({ arg }) {
  12. return (arg && arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && arg.content === 'class');
  13. }
  14. exports.isClassBinding = isClassBinding;
  15. function findStaticClassIndex(props) {
  16. return props.findIndex((prop) => prop.name === 'class');
  17. }
  18. exports.findStaticClassIndex = findStaticClassIndex;
  19. function rewriteClass(index, classBindingProp, props, virtualHost, context) {
  20. const expr = classBindingProp.exp
  21. ? (0, ast_1.parseExpr)(classBindingProp.exp, context)
  22. : undefined;
  23. let classBindingExpr;
  24. if (expr) {
  25. classBindingExpr = expr;
  26. if ((0, types_1.isObjectExpression)(expr)) {
  27. classBindingExpr = createClassBindingByObjectExpression(rewriteClassObjectExpression(expr, classBindingProp.loc, context));
  28. }
  29. else if ((0, types_1.isArrayExpression)(expr)) {
  30. classBindingExpr = createClassBindingByArrayExpression(rewriteClassArrayExpression(expr, context));
  31. }
  32. else {
  33. classBindingExpr = (0, ast_1.parseExpr)(rewriteClassExpression(classBindingProp.exp, context).content, context);
  34. }
  35. }
  36. else if (virtualHost) {
  37. classBindingExpr = (0, types_1.arrayExpression)([]);
  38. }
  39. else {
  40. return;
  41. }
  42. const staticClassPropIndex = findStaticClassIndex(props);
  43. if (staticClassPropIndex > -1) {
  44. const staticClass = props[staticClassPropIndex].value
  45. .content;
  46. if (staticClass) {
  47. if (!(0, types_1.isArrayExpression)(classBindingExpr)) {
  48. classBindingExpr = (0, types_1.arrayExpression)([classBindingExpr]);
  49. }
  50. const staticClassLiterals = parseStaticClass(staticClass);
  51. if (index > staticClassPropIndex) {
  52. classBindingExpr.elements.unshift(...staticClassLiterals);
  53. }
  54. else {
  55. classBindingExpr.elements.push(...staticClassLiterals);
  56. }
  57. }
  58. }
  59. if (virtualHost) {
  60. if (!(0, types_1.isArrayExpression)(classBindingExpr)) {
  61. classBindingExpr = (0, types_1.arrayExpression)([classBindingExpr]);
  62. }
  63. classBindingExpr.elements.push((0, types_1.identifier)(utils_1.VIRTUAL_HOST_CLASS));
  64. }
  65. if (!context.miniProgram.class.array) {
  66. classBindingExpr = parseClassBindingArrayExpr(classBindingExpr);
  67. }
  68. classBindingProp.exp = (0, compiler_core_1.createSimpleExpression)((0, codegen_1.genBabelExpr)(classBindingExpr));
  69. }
  70. exports.rewriteClass = rewriteClass;
  71. function createVirtualHostClass(props, context) {
  72. const classBindingProp = (0, uni_cli_shared_1.createBindDirectiveNode)('class', '');
  73. delete classBindingProp.exp;
  74. rewriteClass(0, classBindingProp, props, true, context);
  75. return classBindingProp;
  76. }
  77. exports.createVirtualHostClass = createVirtualHostClass;
  78. /**
  79. * 目前 mp-toutiao, mp-alipay, mp-lark 不支持数组绑定class,故统一转换为字符串相加
  80. * @param classBindingExpr
  81. * @returns
  82. */
  83. function parseClassBindingArrayExpr(classBindingExpr) {
  84. if (!(0, types_1.isArrayExpression)(classBindingExpr)) {
  85. return classBindingExpr;
  86. }
  87. let binaryExpr;
  88. classBindingExpr.elements.forEach((expr) => {
  89. if ((0, types_1.isArrayExpression)(expr)) {
  90. expr = parseClassBindingArrayExpr(expr);
  91. }
  92. if (!binaryExpr) {
  93. binaryExpr = (0, types_1.parenthesizedExpression)(expr);
  94. }
  95. else {
  96. binaryExpr = (0, types_1.binaryExpression)('+', (0, types_1.binaryExpression)('+', binaryExpr, (0, types_1.stringLiteral)(' ')), expr);
  97. }
  98. });
  99. return binaryExpr;
  100. }
  101. function parseStaticClass(staticClass) {
  102. // 已经在 parse 阶段格式化了多余空格等
  103. return staticClass.split(' ').map((clazz) => (0, types_1.stringLiteral)(clazz));
  104. }
  105. function rewriteClassExpression(expr, context) {
  106. return (0, utils_1.rewriteExpression)((0, compiler_core_1.createCompoundExpression)([
  107. context.helperString(runtimeHelpers_1.NORMALIZE_CLASS) + '(',
  108. expr,
  109. ')',
  110. ]), context);
  111. }
  112. function rewriteClassArrayExpression(expr, context) {
  113. expr.elements.forEach((prop, index) => {
  114. if (!(0, types_1.isStringLiteral)(prop)) {
  115. const code = (0, codegen_1.genBabelExpr)((0, types_1.arrayExpression)([(0, types_1.isSpreadElement)(prop) ? prop.argument : prop]));
  116. expr.elements[index] = (0, types_1.identifier)(rewriteClassExpression((0, compiler_core_1.createSimpleExpression)(code.slice(1, -1), false), context).content);
  117. }
  118. });
  119. return expr;
  120. }
  121. function rewriteClassObjectExpression(expr, loc, context) {
  122. expr.properties.forEach((prop, index) => {
  123. if ((0, types_1.isSpreadElement)(prop)) {
  124. // <view :class="{...obj}"/>
  125. // <view class="{{[a]}}"/>
  126. const newExpr = (0, utils_1.rewriteSpreadElement)(runtimeHelpers_1.NORMALIZE_CLASS, prop, loc, context);
  127. if (newExpr) {
  128. expr.properties[index] = (0, types_1.objectProperty)(newExpr, (0, types_1.booleanLiteral)(true), true);
  129. }
  130. }
  131. else if ((0, types_1.isObjectProperty)(prop)) {
  132. const { key, value, computed } = prop;
  133. if (computed) {
  134. // {[handle(computedKey)]:1} => {[a]:1}
  135. prop.key = (0, utils_1.parseExprWithRewrite)((0, codegen_1.genBabelExpr)(key), loc, context, key);
  136. }
  137. if ((0, utils_1.isStaticLiteral)(value)) {
  138. return;
  139. }
  140. else {
  141. const newExpr = (0, utils_1.parseExprWithRewriteClass)((0, codegen_1.genBabelExpr)(value), loc, context, value);
  142. if (newExpr) {
  143. prop.value = newExpr;
  144. }
  145. }
  146. }
  147. });
  148. return expr;
  149. }
  150. function createClassBindingByArrayExpression(expr) {
  151. const elements = [];
  152. expr.elements.forEach((prop) => {
  153. if ((0, types_1.isStringLiteral)(prop) || (0, types_1.isIdentifier)(prop)) {
  154. elements.push(prop);
  155. }
  156. });
  157. return (0, types_1.arrayExpression)(elements);
  158. }
  159. function createClassBindingByObjectExpression(expr) {
  160. const elements = [];
  161. expr.properties.forEach((prop) => {
  162. if ((0, types_1.isObjectProperty)(prop)) {
  163. const { value } = prop;
  164. if ((0, ast_1.isUndefined)(value) || (0, types_1.isPrivateName)(prop.key)) {
  165. // remove {a:undefined}
  166. return;
  167. }
  168. if ((0, types_1.isLiteral)(value)) {
  169. // {a:true,b:1,c:0} => ['a','b']
  170. if ((0, ast_1.isTrueExpr)(value)) {
  171. elements.push(prop.computed
  172. ? prop.key
  173. : (0, ast_1.parseStringLiteral)(prop.key));
  174. }
  175. return;
  176. }
  177. elements.push((0, types_1.logicalExpression)('&&', value, prop.computed ? prop.key : (0, ast_1.parseStringLiteral)(prop.key)));
  178. }
  179. });
  180. return (0, types_1.arrayExpression)(elements);
  181. }