UNPKG

@builder.io/mitosis

Version:

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

170 lines (169 loc) 6.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.renderPreComponent = exports.renderImport = exports.transformImportPath = exports.checkIsComponentImport = void 0; const component_file_extensions_1 = require("./component-file-extensions"); const DEFAULT_IMPORT = 'default'; const STAR_IMPORT = '*'; const getStarImport = ({ theImport }) => { for (const key in theImport.imports) { const value = theImport.imports[key]; if (value === STAR_IMPORT) { return key; } } return null; }; const getDefaultImport = ({ theImport }) => { for (const key in theImport.imports) { const value = theImport.imports[key]; if (value === DEFAULT_IMPORT) { return key; } } return null; }; const CONTEXT_IMPORTS = ['context.lite', 'context.lite.ts', 'context.lite.js']; const checkIsContextImport = (theImport) => CONTEXT_IMPORTS.some((contextPath) => theImport.path.endsWith(contextPath)); const checkIsComponentImport = (theImport) => !checkIsContextImport(theImport) && component_file_extensions_1.COMPONENT_IMPORT_EXTENSIONS.some((contextPath) => theImport.path.endsWith(contextPath)); exports.checkIsComponentImport = checkIsComponentImport; const transformImportPath = ({ theImport, target, preserveFileExtensions, explicitImportFileExtension, }) => { // We need to drop the `.lite` from context files, because the context generator does so as well. if (checkIsContextImport(theImport)) { let path = theImport.path; CONTEXT_IMPORTS.forEach((contextPath) => { if (path.endsWith(contextPath)) { path = path.replace(contextPath, 'context.js'); } }); return path; } if (preserveFileExtensions) return theImport.path; if ((0, exports.checkIsComponentImport)(theImport)) { return theImport.path.replace(component_file_extensions_1.INPUT_EXTENSION_REGEX, (0, component_file_extensions_1.getComponentFileExtensionForTarget)({ target, type: 'import', explicitImportFileExtension })); } return theImport.path; }; exports.transformImportPath = transformImportPath; const getNamedImports = ({ theImport }) => { const namedImports = Object.entries(theImport.imports) .filter(([, value]) => ![DEFAULT_IMPORT, STAR_IMPORT].includes(value)) .map(([key, value]) => { return key !== value ? `${value} as ${key}` : value; }); if (namedImports.length > 0) { return `{ ${namedImports.join(', ')} }`; } else { return null; } }; const getImportedValues = ({ theImport }) => { const starImport = getStarImport({ theImport }); const defaultImport = getDefaultImport({ theImport }); const namedImports = getNamedImports({ theImport }); return { starImport, defaultImport, namedImports }; }; const getImportValue = ({ defaultImport, namedImports, starImport }) => { if (starImport) { return ` * as ${starImport} `; } else { return [defaultImport, namedImports].filter(Boolean).join(', '); } }; const renderImport = ({ theImport, target, asyncComponentImports, preserveFileExtensions = false, component = undefined, componentsUsed = [], importMapper, explicitImportFileExtension = false, }) => { const importedValues = getImportedValues({ theImport }); const path = (0, exports.transformImportPath)({ theImport, target, preserveFileExtensions, explicitImportFileExtension, }); const importValue = getImportValue(importedValues); const isComponentImport = (0, exports.checkIsComponentImport)(theImport); const shouldBeAsyncImport = asyncComponentImports && isComponentImport; const isTypeImport = theImport.importKind === 'type'; // For lit (components) we just want to do a plain import // https://lit.dev/docs/components/rendering/#composing-templates if (isComponentImport && target === 'lit') { return `import '${path}';`; } if (shouldBeAsyncImport) { const isVueImport = target === 'vue'; if (isVueImport && importedValues.namedImports) { console.warn('Vue: Async Component imports cannot include named imports. Dropping async import. This might break your code.'); } else { return `const ${importValue} = () => import('${path}') .then(x => x.default) .catch(err => { console.error('Error while attempting to dynamically import component ${importValue} at ${path}', err); throw err; });`; } } if (importMapper) { const importMapperResult = importMapper(component, theImport, importedValues, componentsUsed); // If import mapper has no result we skip this if (importMapperResult) { return importMapperResult; } } return importValue ? `import ${isTypeImport ? 'type' : ''} ${importValue} from '${path}';` : `import '${path}';`; }; exports.renderImport = renderImport; const renderImports = ({ imports, target, asyncComponentImports, excludeMitosisComponents, preserveFileExtensions = false, component, componentsUsed, importMapper, explicitImportFileExtension, }) => imports .filter((theImport) => { if ( // Remove compile away components theImport.path === '@builder.io/components' || // TODO: Mitosis output needs this theImport.path.startsWith('@builder.io/mitosis')) { return false; } else if (excludeMitosisComponents && theImport.path.includes('.lite')) { return false; } else { return true; } }) .map((theImport) => (0, exports.renderImport)({ theImport, target, asyncComponentImports, preserveFileExtensions, component, componentsUsed, importMapper, explicitImportFileExtension, })) .join('\n'); const renderPreComponent = ({ component, target, excludeMitosisComponents, asyncComponentImports = false, preserveFileExtensions = false, componentsUsed = [], importMapper, explicitImportFileExtension = false, excludeExportAndLocal = false, }) => { var _a; return ` ${renderImports({ imports: component.imports, target, asyncComponentImports, excludeMitosisComponents, preserveFileExtensions, component, componentsUsed, importMapper, explicitImportFileExtension, })} ${excludeExportAndLocal ? '' : renderExportAndLocal(component)} ${((_a = component.hooks.preComponent) === null || _a === void 0 ? void 0 : _a.code) || ''} `; }; exports.renderPreComponent = renderPreComponent; const renderExportAndLocal = (component) => { return Object.keys(component.exports || {}) .map((key) => component.exports[key].code) .join('\n'); };