diff --git a/packages/teleport-component-generator-angular/src/angular-mapping.ts b/packages/teleport-component-generator-angular/src/angular-mapping.ts index 3520bbfe5..04f3da0bc 100644 --- a/packages/teleport-component-generator-angular/src/angular-mapping.ts +++ b/packages/teleport-component-generator-angular/src/angular-mapping.ts @@ -1,5 +1,18 @@ -export const AngularMapping = { - elements: {}, +import { Mapping } from '@teleporthq/teleport-types' + +export const AngularMapping: Mapping = { + elements: { + fragment: { + elementType: 'div', + name: 'custom-fragment', + style: { + display: { + type: 'static', + content: 'contents', + }, + }, + }, + }, events: {}, attributes: {}, } diff --git a/packages/teleport-component-generator-vue/src/vue-mapping.ts b/packages/teleport-component-generator-vue/src/vue-mapping.ts index a4f430268..7fb07a8b0 100644 --- a/packages/teleport-component-generator-vue/src/vue-mapping.ts +++ b/packages/teleport-component-generator-vue/src/vue-mapping.ts @@ -27,6 +27,16 @@ export const VueMapping: Mapping = { 'lottie-node': { elementType: 'lottie-vue-player', }, + fragment: { + elementType: 'div', + name: 'custom-fragment', + style: { + display: { + type: 'static', + content: 'contents', + }, + }, + }, }, events: {}, attributes: {}, diff --git a/packages/teleport-project-generator-html/__tests__/end2end/index.ts b/packages/teleport-project-generator-html/__tests__/end2end/index.ts index 2d1384805..d067431c5 100644 --- a/packages/teleport-project-generator-html/__tests__/end2end/index.ts +++ b/packages/teleport-project-generator-html/__tests__/end2end/index.ts @@ -59,7 +59,7 @@ describe('Html Project Generator', () => { expect(aboutCSS?.content).toContain('public/playground_assets/kitten.png') }) - it('creates a next project and generates the named-slot for passing components', async () => { + it('creates a html project and generates the named-slot for passing components', async () => { const generator = createHTMLProjectGenerator() const { subFolders, files } = await generator.generateProject(uidlSample) const components = subFolders.find((folder) => folder.name === 'components') diff --git a/packages/teleport-project-generator-next/__tests__/end2end/index.ts b/packages/teleport-project-generator-next/__tests__/end2end/index.ts index f9cb5ad01..16e1d268c 100644 --- a/packages/teleport-project-generator-next/__tests__/end2end/index.ts +++ b/packages/teleport-project-generator-next/__tests__/end2end/index.ts @@ -102,7 +102,9 @@ describe('React Next Project Generator', () => { const pages = subFolders.find((folder) => folder.name === 'pages') const components = subFolders.find((folder) => folder.name === 'components') const indexPage = pages?.files.find((file) => file.name === 'index') - const heroComponent = components?.files.find((file) => file.name === 'hero') + const heroComponent = components?.files.find( + (file) => file.name === 'hero' && file.fileType === FileType.JS + ) expect(indexPage).toMatchSnapshot() expect(heroComponent).toMatchSnapshot() diff --git a/packages/teleport-project-generator-next/src/next-project-mapping.ts b/packages/teleport-project-generator-next/src/next-project-mapping.ts index 248bcc2e0..288c93f7f 100644 --- a/packages/teleport-project-generator-next/src/next-project-mapping.ts +++ b/packages/teleport-project-generator-next/src/next-project-mapping.ts @@ -101,9 +101,5 @@ export const NextProjectMapping: Mapping = { }, }, }, - fragment: { - elementType: ' ', - semanticType: '', - }, }, } diff --git a/packages/teleport-uidl-resolver/src/resolver.ts b/packages/teleport-uidl-resolver/src/resolver.ts index 47c594f68..4dd8722e3 100644 --- a/packages/teleport-uidl-resolver/src/resolver.ts +++ b/packages/teleport-uidl-resolver/src/resolver.ts @@ -63,7 +63,10 @@ export default class Resolver { resolveReferencedStyle(uidl, newOptions) resolveHtmlNode(uidl, newOptions) // TODO: Rename into apply mappings - utils.resolveNode(uidl.node, newOptions) + utils.resolveNode(uidl.node, { + ...newOptions, + propDefinitions: uidl.propDefinitions, + }) utils.resolveNodeInPropDefinitions(uidl, newOptions) utils.createNodesLookup(uidl, nodesLookup) diff --git a/packages/teleport-uidl-resolver/src/utils.ts b/packages/teleport-uidl-resolver/src/utils.ts index a60fc7d65..5e84ea536 100644 --- a/packages/teleport-uidl-resolver/src/utils.ts +++ b/packages/teleport-uidl-resolver/src/utils.ts @@ -15,6 +15,7 @@ import { UIDLDynamicReference, UIDLConditionalNode, ElementsLookup, + UIDLPropDefinition, } from '@teleporthq/teleport-types' import deepmerge from 'deepmerge' @@ -60,8 +61,40 @@ export const resolveMetaTags = (uidl: ComponentUIDL, options: GeneratorOptions) }) } -export const resolveNode = (uidlNode: UIDLNode, options: GeneratorOptions) => { +export const resolveNode = ( + uidlNode: UIDLNode, + options: GeneratorOptions & { propDefinitions: Record } +) => { UIDLUtils.traverseNodes(uidlNode, (node, parentNode) => { + // When a prop is of type element, we need to replace the parent node with a fragment + // This is because, the defaultValue for the prop is alaready sending the elementType of the same. + // This will make sure, we are not nesting the same tags. + if ( + node.type === 'dynamic' && + node.content.referenceType === 'prop' && + options.mapping.elements?.fragment !== undefined && + parentNode.type === 'element' + ) { + const prop = options.propDefinitions[node.content.id] + if (prop?.type !== 'element' || (prop?.defaultValue as UIDLElementNode)?.type !== 'element') { + return + } + + const fragmentMapping = options.mapping.elements.fragment + const propElement = prop.defaultValue as UIDLElementNode + // We change the parent node to a fragment only if the defaultValue is also a fragment. + // This is to make sure we are not changing the parent node to a fragment when it is not needed. + // Like `named-slot`. Named slot's defaultValue is also an element. + if (propElement.type === 'element' && propElement.content.elementType !== 'fragment') { + return + } + + parentNode.content = { + ...parentNode.content, + ...fragmentMapping, + } + } + if (node.type === 'element') { resolveElement(node.content, options) } @@ -712,7 +745,10 @@ export const resolveNodeInPropDefinitions = (uidl: ComponentUIDL, options: Gener for (const propKey of Object.keys(uidl.propDefinitions)) { const prop = uidl.propDefinitions[propKey] if (prop.type === 'element' && typeof prop.defaultValue === 'object') { - resolveNode(prop.defaultValue as UIDLElementNode, options) + resolveNode(prop.defaultValue as UIDLElementNode, { + ...options, + propDefinitions: uidl.propDefinitions, + }) } } }