utils.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. "use strict";
  2. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
  3. if (k2 === undefined) k2 = k;
  4. Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
  5. }) : (function(o, m, k, k2) {
  6. if (k2 === undefined) k2 = k;
  7. o[k2] = m[k];
  8. }));
  9. var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
  10. Object.defineProperty(o, "default", { enumerable: true, value: v });
  11. }) : function(o, v) {
  12. o["default"] = v;
  13. });
  14. var __importStar = (this && this.__importStar) || function (mod) {
  15. if (mod && mod.__esModule) return mod;
  16. var result = {};
  17. if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
  18. __setModuleDefault(result, mod);
  19. return result;
  20. };
  21. var __importDefault = (this && this.__importDefault) || function (mod) {
  22. return (mod && mod.__esModule) ? mod : { "default": mod };
  23. };
  24. Object.defineProperty(exports, "__esModule", { value: true });
  25. exports.transformJSXSpreadAttribute = exports.isConstant = exports.dedupeProperties = exports.isOn = exports.buildIIFE = exports.walksScope = exports.transformJSXSpreadChild = exports.transformJSXExpressionContainer = exports.transformJSXText = exports.getJSXAttributeName = exports.getTag = exports.transformJSXMemberExpression = exports.checkIsComponent = exports.shouldTransformedToSlots = exports.isDirective = exports.createIdentifier = exports.KEEP_ALIVE = exports.FRAGMENT = exports.JSX_HELPER_KEY = void 0;
  26. const t = __importStar(require("@babel/types"));
  27. const html_tags_1 = __importDefault(require("html-tags"));
  28. const svg_tags_1 = __importDefault(require("svg-tags"));
  29. exports.JSX_HELPER_KEY = 'JSX_HELPER_KEY';
  30. exports.FRAGMENT = 'Fragment';
  31. exports.KEEP_ALIVE = 'KeepAlive';
  32. /**
  33. * create Identifier
  34. * @param path NodePath
  35. * @param state
  36. * @param name string
  37. * @returns MemberExpression
  38. */
  39. const createIdentifier = (state, name) => state.get(name)();
  40. exports.createIdentifier = createIdentifier;
  41. /**
  42. * Checks if string is describing a directive
  43. * @param src string
  44. */
  45. const isDirective = (src) => src.startsWith('v-')
  46. || (src.startsWith('v') && src.length >= 2 && src[1] >= 'A' && src[1] <= 'Z');
  47. exports.isDirective = isDirective;
  48. /**
  49. * Should transformed to slots
  50. * @param tag string
  51. * @returns boolean
  52. */
  53. // if _Fragment is already imported, it will end with number
  54. const shouldTransformedToSlots = (tag) => !(tag.match(RegExp(`^_?${exports.FRAGMENT}\\d*$`)) || tag === exports.KEEP_ALIVE);
  55. exports.shouldTransformedToSlots = shouldTransformedToSlots;
  56. /**
  57. * Check if a Node is a component
  58. *
  59. * @param t
  60. * @param path JSXOpeningElement
  61. * @returns boolean
  62. */
  63. const checkIsComponent = (path, state) => {
  64. var _a, _b;
  65. const namePath = path.get('name');
  66. if (namePath.isJSXMemberExpression()) {
  67. return (0, exports.shouldTransformedToSlots)(namePath.node.property.name); // For withCtx
  68. }
  69. const tag = namePath.node.name;
  70. return !((_b = (_a = state.opts).isCustomElement) === null || _b === void 0 ? void 0 : _b.call(_a, tag)) && (0, exports.shouldTransformedToSlots)(tag) && !html_tags_1.default.includes(tag) && !svg_tags_1.default.includes(tag);
  71. };
  72. exports.checkIsComponent = checkIsComponent;
  73. /**
  74. * Transform JSXMemberExpression to MemberExpression
  75. * @param path JSXMemberExpression
  76. * @returns MemberExpression
  77. */
  78. const transformJSXMemberExpression = (path) => {
  79. const objectPath = path.node.object;
  80. const propertyPath = path.node.property;
  81. const transformedObject = t.isJSXMemberExpression(objectPath)
  82. ? (0, exports.transformJSXMemberExpression)(path.get('object'))
  83. : t.isJSXIdentifier(objectPath)
  84. ? t.identifier(objectPath.name)
  85. : t.nullLiteral();
  86. const transformedProperty = t.identifier(propertyPath.name);
  87. return t.memberExpression(transformedObject, transformedProperty);
  88. };
  89. exports.transformJSXMemberExpression = transformJSXMemberExpression;
  90. /**
  91. * Get tag (first attribute for h) from JSXOpeningElement
  92. * @param path JSXElement
  93. * @param state State
  94. * @returns Identifier | StringLiteral | MemberExpression | CallExpression
  95. */
  96. const getTag = (path, state) => {
  97. var _a, _b;
  98. const namePath = path.get('openingElement').get('name');
  99. if (namePath.isJSXIdentifier()) {
  100. const { name } = namePath.node;
  101. if (!html_tags_1.default.includes(name) && !svg_tags_1.default.includes(name)) {
  102. return (name === exports.FRAGMENT
  103. ? (0, exports.createIdentifier)(state, exports.FRAGMENT)
  104. : path.scope.hasBinding(name)
  105. ? t.identifier(name)
  106. : ((_b = (_a = state.opts).isCustomElement) === null || _b === void 0 ? void 0 : _b.call(_a, name))
  107. ? t.stringLiteral(name)
  108. : t.callExpression((0, exports.createIdentifier)(state, 'resolveComponent'), [t.stringLiteral(name)]));
  109. }
  110. return t.stringLiteral(name);
  111. }
  112. if (namePath.isJSXMemberExpression()) {
  113. return (0, exports.transformJSXMemberExpression)(namePath);
  114. }
  115. throw new Error(`getTag: ${namePath.type} is not supported`);
  116. };
  117. exports.getTag = getTag;
  118. const getJSXAttributeName = (path) => {
  119. const nameNode = path.node.name;
  120. if (t.isJSXIdentifier(nameNode)) {
  121. return nameNode.name;
  122. }
  123. return `${nameNode.namespace.name}:${nameNode.name.name}`;
  124. };
  125. exports.getJSXAttributeName = getJSXAttributeName;
  126. /**
  127. * Transform JSXText to StringLiteral
  128. * @param path JSXText
  129. * @returns StringLiteral | null
  130. */
  131. const transformJSXText = (path) => {
  132. const { node } = path;
  133. const lines = node.value.split(/\r\n|\n|\r/);
  134. let lastNonEmptyLine = 0;
  135. for (let i = 0; i < lines.length; i++) {
  136. if (lines[i].match(/[^ \t]/)) {
  137. lastNonEmptyLine = i;
  138. }
  139. }
  140. let str = '';
  141. for (let i = 0; i < lines.length; i++) {
  142. const line = lines[i];
  143. const isFirstLine = i === 0;
  144. const isLastLine = i === lines.length - 1;
  145. const isLastNonEmptyLine = i === lastNonEmptyLine;
  146. // replace rendered whitespace tabs with spaces
  147. let trimmedLine = line.replace(/\t/g, ' ');
  148. // trim whitespace touching a newline
  149. if (!isFirstLine) {
  150. trimmedLine = trimmedLine.replace(/^[ ]+/, '');
  151. }
  152. // trim whitespace touching an endline
  153. if (!isLastLine) {
  154. trimmedLine = trimmedLine.replace(/[ ]+$/, '');
  155. }
  156. if (trimmedLine) {
  157. if (!isLastNonEmptyLine) {
  158. trimmedLine += ' ';
  159. }
  160. str += trimmedLine;
  161. }
  162. }
  163. return str !== '' ? t.stringLiteral(str) : null;
  164. };
  165. exports.transformJSXText = transformJSXText;
  166. /**
  167. * Transform JSXExpressionContainer to Expression
  168. * @param path JSXExpressionContainer
  169. * @returns Expression
  170. */
  171. const transformJSXExpressionContainer = (path) => path.get('expression').node;
  172. exports.transformJSXExpressionContainer = transformJSXExpressionContainer;
  173. /**
  174. * Transform JSXSpreadChild
  175. * @param path JSXSpreadChild
  176. * @returns SpreadElement
  177. */
  178. const transformJSXSpreadChild = (path) => t.spreadElement(path.get('expression').node);
  179. exports.transformJSXSpreadChild = transformJSXSpreadChild;
  180. const walksScope = (path, name, slotFlag) => {
  181. if (path.scope.hasBinding(name) && path.parentPath) {
  182. if (t.isJSXElement(path.parentPath.node)) {
  183. path.parentPath.setData('slotFlag', slotFlag);
  184. }
  185. (0, exports.walksScope)(path.parentPath, name, slotFlag);
  186. }
  187. };
  188. exports.walksScope = walksScope;
  189. const buildIIFE = (path, children) => {
  190. const { parentPath } = path;
  191. if (t.isAssignmentExpression(parentPath)) {
  192. const { left } = parentPath.node;
  193. if (t.isIdentifier(left)) {
  194. return children.map((child) => {
  195. if (t.isIdentifier(child) && child.name === left.name) {
  196. const insertName = path.scope.generateUidIdentifier(child.name);
  197. parentPath.insertBefore(t.variableDeclaration('const', [
  198. t.variableDeclarator(insertName, t.callExpression(t.functionExpression(null, [], t.blockStatement([t.returnStatement(child)])), [])),
  199. ]));
  200. return insertName;
  201. }
  202. return child;
  203. });
  204. }
  205. }
  206. return children;
  207. };
  208. exports.buildIIFE = buildIIFE;
  209. const onRE = /^on[^a-z]/;
  210. const isOn = (key) => onRE.test(key);
  211. exports.isOn = isOn;
  212. const mergeAsArray = (existing, incoming) => {
  213. if (t.isArrayExpression(existing.value)) {
  214. existing.value.elements.push(incoming.value);
  215. }
  216. else {
  217. existing.value = t.arrayExpression([
  218. existing.value,
  219. incoming.value,
  220. ]);
  221. }
  222. };
  223. const dedupeProperties = (properties = [], mergeProps) => {
  224. if (!mergeProps) {
  225. return properties;
  226. }
  227. const knownProps = new Map();
  228. const deduped = [];
  229. properties.forEach((prop) => {
  230. if (t.isStringLiteral(prop.key)) {
  231. const { value: name } = prop.key;
  232. const existing = knownProps.get(name);
  233. if (existing) {
  234. if (name === 'style' || name === 'class' || name.startsWith('on')) {
  235. mergeAsArray(existing, prop);
  236. }
  237. }
  238. else {
  239. knownProps.set(name, prop);
  240. deduped.push(prop);
  241. }
  242. }
  243. else {
  244. // v-model target with variable
  245. deduped.push(prop);
  246. }
  247. });
  248. return deduped;
  249. };
  250. exports.dedupeProperties = dedupeProperties;
  251. /**
  252. * Check if an attribute value is constant
  253. * @param node
  254. * @returns boolean
  255. */
  256. const isConstant = (node) => {
  257. if (t.isIdentifier(node)) {
  258. return node.name === 'undefined';
  259. }
  260. if (t.isArrayExpression(node)) {
  261. const { elements } = node;
  262. return elements.every((element) => element && (0, exports.isConstant)(element));
  263. }
  264. if (t.isObjectExpression(node)) {
  265. return node.properties.every((property) => (0, exports.isConstant)(property.value));
  266. }
  267. if (t.isLiteral(node)) {
  268. return true;
  269. }
  270. return false;
  271. };
  272. exports.isConstant = isConstant;
  273. const transformJSXSpreadAttribute = (nodePath, path, mergeProps, args) => {
  274. const argument = path.get('argument');
  275. const properties = t.isObjectExpression(argument.node) ? argument.node.properties : undefined;
  276. if (!properties) {
  277. if (argument.isIdentifier()) {
  278. (0, exports.walksScope)(nodePath, argument.node.name, 2 /* DYNAMIC */);
  279. }
  280. args.push(mergeProps ? argument.node : t.spreadElement(argument.node));
  281. }
  282. else if (mergeProps) {
  283. args.push(t.objectExpression(properties));
  284. }
  285. else {
  286. args.push(...properties);
  287. }
  288. };
  289. exports.transformJSXSpreadAttribute = transformJSXSpreadAttribute;
  290. //# sourceMappingURL=utils.js.map