Skip to content

Commit

Permalink
fix(parser-printer) call updateJSXElementsWithin when printing jsx at…
Browse files Browse the repository at this point in the history
…tributes (#5021)
  • Loading branch information
Rheeseyb authored Mar 12, 2024
1 parent cad07c8 commit 37aac68
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* eslint jest/expect-expect: ["error", { "assertFunctionNames": ["expect", "testParseModifyPrint"] }] */
import * as PP from '../../shared/property-path'
import type { ArbitraryJSBlock } from '../../shared/element-template'
import type { ArbitraryJSBlock, JSXAttributesEntry } from '../../shared/element-template'
import {
arbitraryJSBlock,
clearTopLevelElementUniqueIDs,
Expand All @@ -18,6 +19,7 @@ import {
emptyComments,
jsxMapExpression,
jsIdentifier,
isJSXAttributesEntry,
} from '../../shared/element-template'
import { setJSXValueAtPath } from '../../shared/jsx-attribute-utils'
import { forEachRight } from '../../shared/either'
Expand Down Expand Up @@ -107,7 +109,6 @@ export var ${BakedInStoryboardVariableName} = (props) => {
parseResult,
)
})
// eslint-disable-next-line jest/expect-expect
it('should write updated arbitrary elements back into code', () => {
const code = applyPrettier(
`import * as React from "react";
Expand Down Expand Up @@ -196,6 +197,92 @@ export var ${BakedInStoryboardVariableName} = (props) => {
})
})

it('should write updated JSX inside a prop back into code', () => {
const code = applyPrettier(
`import * as React from "react";
import { View, Storyboard, Scene } from 'utopia-api';
export var App = props => {
return (
<View thing={<div data-uid='bbb' />} data-uid='aaa' />
)
}
export var ${BakedInStoryboardVariableName} = (props) => {
return (
<Storyboard data-uid='${BakedInStoryboardUID}'>
<Scene
style={{ height: 200, left: 59, width: 200, top: 79 }}
data-uid='${TestSceneUID}'
>
<App
data-uid='${TestAppUID}'
style={{ height: '100%', width: '100%' }}
title='Hi there!'
/>
</Scene>
</Storyboard>
)
}
`,
false,
).formatted

const expectedCode = applyPrettier(
`import * as React from "react";
import { View, Storyboard, Scene } from 'utopia-api';
export var App = props => {
return (
<View thing={<div data-uid="bbb" style={{ left: 20, top: 300 }} />} data-uid="aaa" />
);
};
export var ${BakedInStoryboardVariableName} = (props) => {
return (
<Storyboard data-uid='${BakedInStoryboardUID}'>
<Scene
style={{ height: 200, left: 59, width: 200, top: 79 }}
data-uid='${TestSceneUID}'
>
<App
data-uid='${TestAppUID}'
style={{ height: '100%', width: '100%' }}
title='Hi there!'
/>
</Scene>
</Storyboard>
)
}
`,
false,
).formatted

testParseModifyPrint('/index.js', code, expectedCode, (success: ParseSuccess) => {
const firstComponent = success.topLevelElements.find(isUtopiaJSXComponent)
if (firstComponent != null) {
const view = firstComponent.rootElement
if (isJSXElement(view)) {
const jsxProp: JSXAttributesEntry | undefined = view.props
.filter(isJSXAttributesEntry)
.find((prop) => prop.key === 'thing')
if (jsxProp != null && isJSExpressionMapOrOtherJavaScript(jsxProp.value)) {
const elementWithin = jsxProp.value.elementsWithin['bbb']
const newAttributes = setJSXValueAtPath(
elementWithin.props,
PP.create('style'),
jsExpressionValue({ left: 20, top: 300 }, emptyComments),
)
forEachRight(newAttributes, (updated) => {
elementWithin.props = updated
})
}
}
}
return success
})
})

it('Supports using top level components inside an arbitrary block', () => {
const code = `import React from "react";
import { View } from "utopia-api";
Expand Down
7 changes: 6 additions & 1 deletion editor/src/core/workers/parser-printer/parser-printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,12 @@ function jsxAttributeToExpression(
attribute.javascriptWithUIDs,
).statement
if (TS.isExpressionStatement(maybeExpressionStatement)) {
const expression = maybeExpressionStatement.expression
const expression = updateJSXElementsWithin(
maybeExpressionStatement.expression,
attribute.elementsWithin,
imports,
stripUIDs,
)
addCommentsToNode(expression, attribute.comments)
return expression
} else {
Expand Down

0 comments on commit 37aac68

Please sign in to comment.