UNPKG

@builder.io/mitosis

Version:

Write components once, run everywhere. Compiles to Vue, React, Solid, and Liquid. Import code from Figma and Builder.io

131 lines (130 loc) 6.31 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertTypeScriptToJS = exports.babelTransformExpression = exports.babelTransformCode = void 0; const babel = __importStar(require("@babel/core")); const plugin_syntax_decorators_1 = __importDefault(require("@babel/plugin-syntax-decorators")); const plugin_syntax_typescript_1 = __importDefault(require("@babel/plugin-syntax-typescript")); const preset_typescript_1 = __importDefault(require("@babel/preset-typescript")); const function_1 = require("fp-ts/lib/function"); const patterns_1 = require("./patterns"); const handleErrorOrExpression = ({ code, useCode, result, visitor, stripTypes, }) => { try { // If it can't, e.g. this is an expression or code fragment, modify the code below and try again // Detect method fragments. These get passed sometimes and otherwise // generate compile errors. They are of the form `foo() { ... }` const isMethod = Boolean(!code.trim().startsWith('function') && code.trim().match(/^[a-z0-9_]+\s*\([^\)]*\)\s*[\{:]/i)); const isGetter = (0, patterns_1.checkIsGetter)(code); const isMethodOrGetter = isMethod || isGetter; if (isMethodOrGetter) { useCode = `function ${useCode}`; } result = (0, function_1.pipe)( // Parse the code as an expression (instead of the default, a block) by giving it a fake variable assignment // e.g. if the code parsed is { ... } babel will treat that as a block by deafult, unless processed as an expression // that is an object `let _ = ${useCode}`, (code) => (0, exports.babelTransformCode)(code, visitor, stripTypes), trimSemicolons, // Remove our fake variable assignment (str) => str.replace(/let _ =\s/, '')); if (isMethodOrGetter) { return result.replace('function', ''); } return result; } catch (err) { console.error('Error parsing code:\n', { code, result, useCode }); throw err; } }; const babelTransform = ({ code, visitor, stripTypes, }) => { return babel.transform(code, { sourceFileName: 'file.tsx', configFile: false, babelrc: false, parserOpts: { allowReturnOutsideFunction: true }, ...(stripTypes ? { presets: [[preset_typescript_1.default, { isTSX: true, allExtensions: true }]] } : {}), plugins: [ [plugin_syntax_typescript_1.default, { isTSX: true }], [plugin_syntax_decorators_1.default, { legacy: true }], ...(visitor ? [() => ({ visitor })] : []), ], }); }; const babelTransformCode = (code, visitor, stripTypes = false) => { var _a; return ((_a = babelTransform({ code, visitor, stripTypes })) === null || _a === void 0 ? void 0 : _a.code) || ''; }; exports.babelTransformCode = babelTransformCode; // Babel adds trailing semicolons, but for expressions we need those gone // TODO: maybe detect if the original code ended with one, and keep it if so, for the case // of appending several fragements const trimSemicolons = (code) => code.replace(/;$/, ''); const trimExpression = (type) => (code) => { switch (type) { case 'functionBody': return code.replace(/^function\s*\(\)\s*\{/, '').replace(/\};?$/, ''); default: return trimSemicolons(code); } }; const getType = (code, initialType) => { // match for object literal like { foo: ... } if (initialType === 'unknown' && code.trim().match(/^\s*{\s*[a-z0-9]+:/i)) { return 'expression'; } // For Builder content if (initialType === 'unknown' && (code.includes('return _virtual_index') || code.trim().startsWith('return ')) && !code.trim().startsWith('function')) { return 'functionBody'; } return initialType; }; const babelTransformExpression = (code, visitor, initialType = 'unknown', stripTypes = false) => { if (!code) { return ''; } const isGetter = code.trim().startsWith('get '); return (0, function_1.pipe)(code, isGetter ? patterns_1.replaceGetterWithFunction : function_1.identity, (code) => { const type = getType(code, initialType); const useCode = type === 'functionBody' ? `function(){${code}}` : code; return { type, useCode }; }, ({ type, useCode }) => { if (type !== 'expression') { try { return (0, function_1.pipe)((0, exports.babelTransformCode)(useCode, visitor, stripTypes), trimExpression(type)); } catch (error) { return handleErrorOrExpression({ code, useCode, result: null, visitor, stripTypes }); } } else { return handleErrorOrExpression({ code, useCode, result: null, visitor, stripTypes }); } }, isGetter ? patterns_1.replaceFunctionWithGetter : function_1.identity); }; exports.babelTransformExpression = babelTransformExpression; const convertTypeScriptToJS = (code) => (0, exports.babelTransformExpression)(code, {}, 'unknown', true); exports.convertTypeScriptToJS = convertTypeScriptToJS;