UNPKG

@builder.io/mitosis

Version:

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

203 lines (202 loc) 8.59 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.hashCode = exports.hashCodeAsString = exports.getJsxSymbolComponentName = exports.convertBuilderElementToMitosisComponent = exports.convertBuilderContentToSymbolHierarchy = exports.ensureAllSymbolsHaveIds = void 0; const minify_1 = require("../generators/helpers/minify"); const builder_1 = require("../parsers/builder"); const legacy_1 = __importDefault(require("neotraverse/legacy")); /** * Ensure every symbol in a BuilderContent tree has a unique ID. * Mutates the data tree directly. */ function ensureAllSymbolsHaveIds(content) { let counter = 0; const ids = new Set(); (0, legacy_1.default)(content).forEach(function (el) { var _a, _b, _c; if (this.key === 'jsCode' && isString(el) && el.endsWith('return _virtual_index')) { // Sometimes rollup adds a final `return _virtual_index` but that causes VM evaluation to fail. // Instead of a return on the last line, it needs a plain expression on the last line. Luckily // because the rollup compile behavior is consistent this works pretty reliably el = el.replace(/return _virtual_index$/, '_virtual_index'); this.parent && (this.parent.node.jsCode = el); } if ((0, builder_1.isBuilderElement)(el)) { if (((_a = el === null || el === void 0 ? void 0 : el.component) === null || _a === void 0 ? void 0 : _a.name) === 'Symbol') { const id = getIdFromSymbol(el); if (id) { if (ids.has(id)) { if ((_c = (_b = el.component) === null || _b === void 0 ? void 0 : _b.options) === null || _c === void 0 ? void 0 : _c.symbol) { const id = pad(counter++); el.component.options.symbol.entry = id; if (el.component.options.symbol.content) { el.component.options.symbol.content.id = id; } ids.add(id); } } else { ids.add(id); } } } } }); } exports.ensureAllSymbolsHaveIds = ensureAllSymbolsHaveIds; //TODO(misko): needs test function convertBuilderContentToSymbolHierarchy(content, { collectComponentStyles, collectComponentState, } = {}) { var _a, _b; if (collectComponentState && ((_a = content.data) === null || _a === void 0 ? void 0 : _a.state)) { const state = (_b = content.data) === null || _b === void 0 ? void 0 : _b.state; collectComponentState['ROOT_COMPONENT_STATE'] = state; } const path = [-1, content.id]; const hierarchy = { depthFirstSymbols: [], [content.id]: [], }; (0, legacy_1.default)(content).forEach(function (el) { var _a, _b, _c; let cssCode = el === null || el === void 0 ? void 0 : el.cssCode; if (cssCode) { collectComponentStyles && collectComponentStyles.push((0, minify_1.minify) `${cssCode}`); } while (path[0 /* Path.DEPTH */] >= this.path.length) { path.shift(); path.shift(); } if ((0, builder_1.isBuilderElement)(el)) { if (((_a = el === null || el === void 0 ? void 0 : el.component) === null || _a === void 0 ? void 0 : _a.name) === 'Symbol') { if (collectComponentState) { const symbol = el.component.options.symbol; const props = symbol.data || (symbol.data = {}); const state = (_c = (_b = symbol.content) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.state; if (state) { const id = hashCodeAsString(state); props['serverStateId'] = id; collectComponentState[id] = state; } } if (path[0 /* Path.DEPTH */] < this.path.length) { const id = getIdFromSymbol(el); hierarchy[id] = []; addIfMissing(hierarchy[path[1 /* Path.ID */]], id); path.unshift(this.path.length, id); } // TODO(misko): This should be `el.content` not `el` // Because we don't wante to take the `<Symbol>` with us. // TODO(misko): Do we really want to add ALL symbols? Even duplicates? hierarchy.depthFirstSymbols.unshift(el); } } }); return hierarchy; } exports.convertBuilderContentToSymbolHierarchy = convertBuilderContentToSymbolHierarchy; function convertBuilderElementToMitosisComponent(element) { var _a, _b; const symbolValue = (_b = (_a = element.component) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.symbol; const elContent = symbolValue === null || symbolValue === void 0 ? void 0 : symbolValue.content; if (!elContent) { console.warn('Symbol missing content', element.id); delete element.component; // TODO(misko): Should this be assign `undefined` for perf? element.children = []; return null; } const id = getIdFromSymbol(element); const componentName = getJsxSymbolComponentName(id); delete element.component; // TODO(misko): Should this be assign `undefined` for perf? element.children = [ (0, builder_1.createBuilderElement)({ component: { name: componentName, options: symbolValue.data, }, properties: { 'builder-content-id': id, }, }), ]; const mitosisComponent = { ...(0, builder_1.builderContentToMitosisComponent)(elContent, { includeBuilderExtras: true, preserveTextBlocks: true, }), name: componentName, }; mitosisComponent.meta.builderElId = element.id; return mitosisComponent; } exports.convertBuilderElementToMitosisComponent = convertBuilderElementToMitosisComponent; function getJsxSymbolComponentName(id) { return 'Component' + id.toUpperCase().replace(/-/g, ''); } exports.getJsxSymbolComponentName = getJsxSymbolComponentName; function getIdFromSymbol(el) { var _a, _b, _c; // TODO(misko): Don't use entry us el.id??? return (_c = (_b = (_a = el.component) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.symbol) === null || _c === void 0 ? void 0 : _c.entry; } function addIfMissing(array, value) { if (array.indexOf(value) == -1) { array.push(value); } } function isString(value) { return typeof value == 'string'; } function hashCodeAsString(obj) { return Number(Math.abs(hashCode(obj))).toString(36); } exports.hashCodeAsString = hashCodeAsString; function hashCode(obj, hash = 0) { let value = 0; switch (typeof obj) { case 'number': value = obj; break; case 'undefined': value = Number.MIN_SAFE_INTEGER; break; case 'string': for (let i = 0; i < obj.length; i++) { hash = hashCodeApply(hash, obj.charCodeAt(i)); } value = obj.length; case 'boolean': value = obj ? 1 : 0; break; case 'object': if (obj === null) { value = Number.MAX_SAFE_INTEGER; } else if (Array.isArray(obj)) { for (let i = 0; i < obj.length; i++) { hash = hashCode(obj[i], hash); } } else { for (const key of Object.keys(obj).sort()) { if (obj.hasOwnProperty(key)) { hash = hashCode(obj[key], hash); } } } break; } return hashCodeApply(hash, value); } exports.hashCode = hashCode; function hashCodeApply(hash, value) { hash = (hash << 5) - hash + value; hash |= 0; // Convert to 32bit integer return hash; } function pad(value) { const padding = '000000'; let result = padding + String(value); return result.substring(result.length - padding.length); }