utils.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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.JSX_HELPER_KEY = exports.buildIIFE = exports.walksScope = exports.FRAGMENT = exports.isFragment = exports.transformJSXExpressionContainer = exports.transformJSXSpreadChild = exports.transformJSXText = exports.getJSXAttributeName = exports.getTag = exports.transformJSXMemberExpression = exports.checkIsComponent = exports.isDirective = exports.createIdentifier = 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. const JSX_HELPER_KEY = 'JSX_HELPER_KEY';
  30. exports.JSX_HELPER_KEY = JSX_HELPER_KEY;
  31. const FRAGMENT = 'Fragment';
  32. exports.FRAGMENT = FRAGMENT;
  33. /**
  34. * create Identifier
  35. * @param path NodePath
  36. * @param state
  37. * @param id string
  38. * @returns MemberExpression
  39. */
  40. const createIdentifier = (state, id) => {
  41. if (!state.get(JSX_HELPER_KEY)) {
  42. state.set(JSX_HELPER_KEY, new Set());
  43. }
  44. const helpers = state.get(JSX_HELPER_KEY);
  45. helpers.add(id);
  46. return t.identifier(id);
  47. };
  48. exports.createIdentifier = createIdentifier;
  49. /**
  50. * Checks if string is describing a directive
  51. * @param src string
  52. */
  53. const isDirective = (src) => src.startsWith('v-')
  54. || (src.startsWith('v') && src.length >= 2 && src[1] >= 'A' && src[1] <= 'Z');
  55. exports.isDirective = isDirective;
  56. /**
  57. * Check if a Node is fragment
  58. * @param {*} path JSXIdentifier | JSXMemberExpression | JSXNamespacedName
  59. * @returns boolean
  60. */
  61. const isFragment = (path) => {
  62. if (path.isJSXIdentifier()) {
  63. return path.node.name === FRAGMENT;
  64. }
  65. if (path.isJSXMemberExpression()) {
  66. return path.node.property.name === FRAGMENT;
  67. }
  68. return false;
  69. };
  70. exports.isFragment = isFragment;
  71. /**
  72. * Check if a Node is a component
  73. *
  74. * @param t
  75. * @param path JSXOpeningElement
  76. * @returns boolean
  77. */
  78. const checkIsComponent = (path) => {
  79. const namePath = path.get('name');
  80. if (t.isJSXMemberExpression(namePath)) {
  81. return !isFragment(namePath); // For withCtx
  82. }
  83. const tag = namePath.node.name;
  84. return tag !== FRAGMENT && !html_tags_1.default.includes(tag) && !svg_tags_1.default.includes(tag);
  85. };
  86. exports.checkIsComponent = checkIsComponent;
  87. /**
  88. * Transform JSXMemberExpression to MemberExpression
  89. * @param path JSXMemberExpression
  90. * @returns MemberExpression
  91. */
  92. const transformJSXMemberExpression = (path) => {
  93. const objectPath = path.node.object;
  94. const propertyPath = path.node.property;
  95. const transformedObject = t.isJSXMemberExpression(objectPath)
  96. ? transformJSXMemberExpression(path.get('object'))
  97. : t.isJSXIdentifier(objectPath)
  98. ? t.identifier(objectPath.name)
  99. : t.nullLiteral();
  100. const transformedProperty = t.identifier(propertyPath.name);
  101. return t.memberExpression(transformedObject, transformedProperty);
  102. };
  103. exports.transformJSXMemberExpression = transformJSXMemberExpression;
  104. /**
  105. * Get tag (first attribute for h) from JSXOpeningElement
  106. * @param path JSXElement
  107. * @param state State
  108. * @returns Identifier | StringLiteral | MemberExpression | CallExpression
  109. */
  110. const getTag = (path, state) => {
  111. var _a, _b;
  112. const namePath = path.get('openingElement').get('name');
  113. if (namePath.isJSXIdentifier()) {
  114. const { name } = namePath.node;
  115. if (!html_tags_1.default.includes(name) && !svg_tags_1.default.includes(name)) {
  116. return (name === FRAGMENT
  117. ? createIdentifier(state, FRAGMENT)
  118. : path.scope.hasBinding(name)
  119. ? t.identifier(name)
  120. : ((_b = (_a = state.opts).isCustomElement) === null || _b === void 0 ? void 0 : _b.call(_a, name)) ? t.stringLiteral(name)
  121. : t.callExpression(createIdentifier(state, 'resolveComponent'), [t.stringLiteral(name)]));
  122. }
  123. return t.stringLiteral(name);
  124. }
  125. if (namePath.isJSXMemberExpression()) {
  126. return transformJSXMemberExpression(namePath);
  127. }
  128. throw new Error(`getTag: ${namePath.type} is not supported`);
  129. };
  130. exports.getTag = getTag;
  131. const getJSXAttributeName = (path) => {
  132. const nameNode = path.node.name;
  133. if (t.isJSXIdentifier(nameNode)) {
  134. return nameNode.name;
  135. }
  136. return `${nameNode.namespace.name}:${nameNode.name.name}`;
  137. };
  138. exports.getJSXAttributeName = getJSXAttributeName;
  139. /**
  140. * Transform JSXText to StringLiteral
  141. * @param path JSXText
  142. * @returns StringLiteral | null
  143. */
  144. const transformJSXText = (path) => {
  145. const { node } = path;
  146. const lines = node.value.split(/\r\n|\n|\r/);
  147. let lastNonEmptyLine = 0;
  148. for (let i = 0; i < lines.length; i++) {
  149. if (lines[i].match(/[^ \t]/)) {
  150. lastNonEmptyLine = i;
  151. }
  152. }
  153. let str = '';
  154. for (let i = 0; i < lines.length; i++) {
  155. const line = lines[i];
  156. const isFirstLine = i === 0;
  157. const isLastLine = i === lines.length - 1;
  158. const isLastNonEmptyLine = i === lastNonEmptyLine;
  159. // replace rendered whitespace tabs with spaces
  160. let trimmedLine = line.replace(/\t/g, ' ');
  161. // trim whitespace touching a newline
  162. if (!isFirstLine) {
  163. trimmedLine = trimmedLine.replace(/^[ ]+/, '');
  164. }
  165. // trim whitespace touching an endline
  166. if (!isLastLine) {
  167. trimmedLine = trimmedLine.replace(/[ ]+$/, '');
  168. }
  169. if (trimmedLine) {
  170. if (!isLastNonEmptyLine) {
  171. trimmedLine += ' ';
  172. }
  173. str += trimmedLine;
  174. }
  175. }
  176. return str !== '' ? t.stringLiteral(str) : null;
  177. };
  178. exports.transformJSXText = transformJSXText;
  179. /**
  180. * Transform JSXExpressionContainer to Expression
  181. * @param path JSXExpressionContainer
  182. * @returns Expression
  183. */
  184. const transformJSXExpressionContainer = (path) => path.get('expression').node;
  185. exports.transformJSXExpressionContainer = transformJSXExpressionContainer;
  186. /**
  187. * Transform JSXSpreadChild
  188. * @param path JSXSpreadChild
  189. * @returns SpreadElement
  190. */
  191. const transformJSXSpreadChild = (path) => t.spreadElement(path.get('expression').node);
  192. exports.transformJSXSpreadChild = transformJSXSpreadChild;
  193. const walksScope = (path, name, slotFlag) => {
  194. if (path.scope.hasBinding(name) && path.parentPath) {
  195. if (t.isJSXElement(path.parentPath.node)) {
  196. path.parentPath.setData('slotFlag', slotFlag);
  197. }
  198. walksScope(path.parentPath, name, slotFlag);
  199. }
  200. };
  201. exports.walksScope = walksScope;
  202. const createInsertName = (path, name) => {
  203. if (path.scope.hasBinding(name)) {
  204. return createInsertName(path, `_${name}`);
  205. }
  206. return t.identifier(name);
  207. };
  208. const buildIIFE = (path, children) => {
  209. const { parentPath } = path;
  210. if (t.isAssignmentExpression(parentPath)) {
  211. const { left } = parentPath.node;
  212. if (t.isIdentifier(left)) {
  213. return children.map((child) => {
  214. if (t.isIdentifier(child) && child.name === left.name) {
  215. const insertName = createInsertName(parentPath, `_${child.name}`);
  216. parentPath.insertBefore(t.variableDeclaration('const', [
  217. t.variableDeclarator(insertName, t.callExpression(t.functionExpression(null, [], t.blockStatement([t.returnStatement(child)])), [])),
  218. ]));
  219. return insertName;
  220. }
  221. return child;
  222. });
  223. }
  224. }
  225. return children;
  226. };
  227. exports.buildIIFE = buildIIFE;