Skip to content

Commit 04949cb

Browse files
authored
feat: wrap text with span element when droppping instances into it (#5237)
Ref #3632 Here changed insertion logic to wrap rich text with span element instead of Text component when drop into it. This is the last place which creates legacy components. Refactored tests with jsx to make them more readable.
1 parent 3d064f1 commit 04949cb

File tree

3 files changed

+154
-159
lines changed

3 files changed

+154
-159
lines changed

apps/builder/app/shared/instance-utils.test.tsx

Lines changed: 148 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import type {
1616
Asset,
1717
Breakpoint,
1818
Instance,
19-
Prop,
2019
StyleDecl,
2120
StyleDeclKey,
2221
StyleSource,
@@ -172,175 +171,186 @@ const createFontAsset = (id: string, family: string): Asset => {
172171

173172
describe("insert instance children", () => {
174173
test("insert instance children into empty target", () => {
175-
const instances = toMap([createInstance("body", "Body", [])]);
176-
const data = getWebstudioDataStub({ instances });
177-
insertInstanceChildrenMutable(data, [{ type: "id", value: "box" }], {
178-
parentSelector: ["body"],
174+
const data = renderData(
175+
<ws.element ws:tag="body" ws:id="bodyId"></ws.element>
176+
);
177+
const [div] = renderTemplate(
178+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
179+
).instances;
180+
data.instances.set(div.id, div);
181+
insertInstanceChildrenMutable(data, [{ type: "id", value: "divId" }], {
182+
parentSelector: ["bodyId"],
179183
position: "end",
180184
});
181-
expect(data.instances).toEqual(
182-
toMap([createInstance("body", "Body", [{ type: "id", value: "box" }])])
185+
expect(data).toEqual(
186+
renderData(
187+
<ws.element ws:tag="body" ws:id="bodyId">
188+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
189+
</ws.element>
190+
)
183191
);
184192
});
185193

186194
test("insert instance children into the end of target", () => {
187-
const instances = toMap([
188-
createInstance("body", "Body", [{ type: "id", value: "text" }]),
189-
]);
190-
const data = getWebstudioDataStub({ instances });
191-
insertInstanceChildrenMutable(data, [{ type: "id", value: "box" }], {
192-
parentSelector: ["body"],
195+
const data = renderData(
196+
<ws.element ws:tag="body" ws:id="bodyId">
197+
<ws.element ws:tag="div" ws:id="textId"></ws.element>
198+
</ws.element>
199+
);
200+
const [div] = renderTemplate(
201+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
202+
).instances;
203+
data.instances.set(div.id, div);
204+
insertInstanceChildrenMutable(data, [{ type: "id", value: "divId" }], {
205+
parentSelector: ["bodyId"],
193206
position: "end",
194207
});
195-
expect(data.instances).toEqual(
196-
toMap([
197-
createInstance("body", "Body", [
198-
{ type: "id", value: "text" },
199-
{ type: "id", value: "box" },
200-
]),
201-
])
208+
expect(data).toEqual(
209+
renderData(
210+
<ws.element ws:tag="body" ws:id="bodyId">
211+
<ws.element ws:tag="div" ws:id="textId"></ws.element>
212+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
213+
</ws.element>
214+
)
202215
);
203216
});
204217

205218
test("insert instance children into the start of target", () => {
206-
const instances = toMap([
207-
createInstance("body", "Body", [{ type: "id", value: "text" }]),
208-
]);
209-
const data = getWebstudioDataStub({ instances });
210-
insertInstanceChildrenMutable(data, [{ type: "id", value: "box" }], {
211-
parentSelector: ["body"],
219+
const data = renderData(
220+
<ws.element ws:tag="body" ws:id="bodyId">
221+
<ws.element ws:tag="div" ws:id="textId"></ws.element>
222+
</ws.element>
223+
);
224+
const [div] = renderTemplate(
225+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
226+
).instances;
227+
data.instances.set(div.id, div);
228+
insertInstanceChildrenMutable(data, [{ type: "id", value: "divId" }], {
229+
parentSelector: ["bodyId"],
212230
position: 0,
213231
});
214-
expect(data.instances).toEqual(
215-
toMap([
216-
createInstance("body", "Body", [
217-
{ type: "id", value: "box" },
218-
{ type: "id", value: "text" },
219-
]),
220-
])
232+
expect(data).toEqual(
233+
renderData(
234+
<ws.element ws:tag="body" ws:id="bodyId">
235+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
236+
<ws.element ws:tag="div" ws:id="textId"></ws.element>
237+
</ws.element>
238+
)
221239
);
222240
});
223241

224242
test("insert instance children at the start of text", () => {
225-
const instances = toMap([
226-
createInstance("body", "Body", [{ type: "id", value: "text" }]),
227-
createInstance("text", "Text", [{ type: "text", value: "text" }]),
228-
]);
229-
const data = getWebstudioDataStub({ instances });
230-
insertInstanceChildrenMutable(data, [{ type: "id", value: "box" }], {
231-
parentSelector: ["text", "body"],
243+
const data = renderData(
244+
<ws.element ws:tag="body" ws:id="bodyId">
245+
<ws.element ws:tag="div" ws:id="textId">
246+
text
247+
</ws.element>
248+
</ws.element>
249+
);
250+
const [div] = renderTemplate(
251+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
252+
).instances;
253+
data.instances.set(div.id, div);
254+
insertInstanceChildrenMutable(data, [{ type: "id", value: "divId" }], {
255+
parentSelector: ["textId", "bodyId"],
232256
position: 0,
233257
});
234-
const [_bodyId, _textId, spanId] = data.instances.keys();
235-
expect(data.instances).toEqual(
236-
toMap([
237-
createInstance("body", "Body", [{ type: "id", value: "text" }]),
238-
createInstance("text", "Text", [
239-
{ type: "id", value: "box" },
240-
{ type: "id", value: spanId },
241-
]),
242-
createInstance(spanId, "Text", [{ type: "text", value: "text" }]),
243-
])
244-
);
245-
expect(data.props).toEqual(
246-
toMap<Prop>([
247-
{
248-
id: expect.any(String) as unknown as string,
249-
instanceId: spanId,
250-
name: "tag",
251-
type: "string",
252-
value: "span",
253-
},
254-
])
258+
const [_bodyId, _textId, _divId, spanId] = data.instances.keys();
259+
expect(data).toEqual(
260+
renderData(
261+
<ws.element ws:tag="body" ws:id="bodyId">
262+
<ws.element ws:tag="div" ws:id="textId">
263+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
264+
<ws.element ws:tag="span" ws:id={spanId}>
265+
text
266+
</ws.element>
267+
</ws.element>
268+
</ws.element>
269+
)
255270
);
256271
});
257272

258273
test("insert instance children at the end of text", () => {
259-
const instances = toMap([
260-
createInstance("body", "Body", [{ type: "id", value: "text" }]),
261-
createInstance("text", "Text", [{ type: "text", value: "text" }]),
262-
]);
263-
const data = getWebstudioDataStub({ instances });
264-
insertInstanceChildrenMutable(data, [{ type: "id", value: "box" }], {
265-
parentSelector: ["text", "body"],
274+
const data = renderData(
275+
<ws.element ws:tag="body" ws:id="bodyId">
276+
<ws.element ws:tag="div" ws:id="textId">
277+
text
278+
</ws.element>
279+
</ws.element>
280+
);
281+
const [div] = renderTemplate(
282+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
283+
).instances;
284+
data.instances.set(div.id, div);
285+
insertInstanceChildrenMutable(data, [{ type: "id", value: "divId" }], {
286+
parentSelector: ["textId", "bodyId"],
266287
position: "end",
267288
});
268-
const [_bodyId, _textId, spanId] = data.instances.keys();
269-
expect(data.instances).toEqual(
270-
toMap([
271-
createInstance("body", "Body", [{ type: "id", value: "text" }]),
272-
createInstance("text", "Text", [
273-
{ type: "id", value: spanId },
274-
{ type: "id", value: "box" },
275-
]),
276-
createInstance(spanId, "Text", [{ type: "text", value: "text" }]),
277-
])
278-
);
279-
expect(data.props).toEqual(
280-
toMap<Prop>([
281-
{
282-
id: expect.any(String) as unknown as string,
283-
instanceId: spanId,
284-
name: "tag",
285-
type: "string",
286-
value: "span",
287-
},
288-
])
289+
const [_bodyId, _textId, _divId, spanId] = data.instances.keys();
290+
expect(data).toEqual(
291+
renderData(
292+
<ws.element ws:tag="body" ws:id="bodyId">
293+
<ws.element ws:tag="div" ws:id="textId">
294+
<ws.element ws:tag="span" ws:id={spanId}>
295+
text
296+
</ws.element>
297+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
298+
</ws.element>
299+
</ws.element>
300+
)
289301
);
290302
});
291303

292304
test("insert instance children between text children", () => {
293-
const instances = toMap([
294-
createInstance("body", "Body", [{ type: "id", value: "text" }]),
295-
createInstance("text", "Text", [
296-
{ type: "id", value: "bold" },
297-
{ type: "text", value: "text" },
298-
{ type: "id", value: "italic" },
299-
]),
300-
createInstance("bold", "Bold", [{ type: "text", value: "bold" }]),
301-
createInstance("italic", "Italic", [{ type: "text", value: "italic" }]),
302-
]);
303-
const data = getWebstudioDataStub({ instances });
304-
insertInstanceChildrenMutable(data, [{ type: "id", value: "box" }], {
305-
parentSelector: ["text", "body"],
305+
const data = renderData(
306+
<ws.element ws:tag="body" ws:id="bodyId">
307+
<ws.element ws:tag="div" ws:id="textId">
308+
<ws.element ws:tag="strong" ws:id="strongId">
309+
strong
310+
</ws.element>
311+
text
312+
<ws.element ws:tag="em" ws:id="emId">
313+
emphasis
314+
</ws.element>
315+
</ws.element>
316+
</ws.element>
317+
);
318+
const [div] = renderTemplate(
319+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
320+
).instances;
321+
data.instances.set(div.id, div);
322+
insertInstanceChildrenMutable(data, [{ type: "id", value: "divId" }], {
323+
parentSelector: ["textId", "bodyId"],
306324
position: 1,
307325
});
308-
const [_bodyId, _textId, _boldId, _italicId, leftSpanId, rightSpanId] =
309-
data.instances.keys();
310-
expect(data.instances).toEqual(
311-
toMap([
312-
createInstance("body", "Body", [{ type: "id", value: "text" }]),
313-
createInstance("text", "Text", [
314-
{ type: "id", value: leftSpanId },
315-
{ type: "id", value: "box" },
316-
{ type: "id", value: rightSpanId },
317-
]),
318-
createInstance("bold", "Bold", [{ type: "text", value: "bold" }]),
319-
createInstance("italic", "Italic", [{ type: "text", value: "italic" }]),
320-
createInstance(leftSpanId, "Text", [{ type: "id", value: "bold" }]),
321-
createInstance(rightSpanId, "Text", [
322-
{ type: "text", value: "text" },
323-
{ type: "id", value: "italic" },
324-
]),
325-
])
326-
);
327-
expect(data.props).toEqual(
328-
toMap<Prop>([
329-
{
330-
id: expect.any(String) as unknown as string,
331-
instanceId: leftSpanId,
332-
name: "tag",
333-
type: "string",
334-
value: "span",
335-
},
336-
{
337-
id: expect.any(String) as unknown as string,
338-
instanceId: rightSpanId,
339-
name: "tag",
340-
type: "string",
341-
value: "span",
342-
},
343-
])
326+
const [
327+
_bodyId,
328+
_textId,
329+
_strongId,
330+
_emId,
331+
_divId,
332+
leftSpanId,
333+
rightSpanId,
334+
] = data.instances.keys();
335+
expect(data).toEqual(
336+
renderData(
337+
<ws.element ws:tag="body" ws:id="bodyId">
338+
<ws.element ws:tag="div" ws:id="textId">
339+
<ws.element ws:tag="span" ws:id={leftSpanId}>
340+
<ws.element ws:tag="strong" ws:id="strongId">
341+
strong
342+
</ws.element>
343+
</ws.element>
344+
<ws.element ws:tag="div" ws:id="divId"></ws.element>
345+
<ws.element ws:tag="span" ws:id={rightSpanId}>
346+
text
347+
<ws.element ws:tag="em" ws:id="emId">
348+
emphasis
349+
</ws.element>
350+
</ws.element>
351+
</ws.element>
352+
</ws.element>
353+
)
344354
);
345355
});
346356
});

apps/builder/app/shared/instance-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ export const findAllEditableInstanceSelector = ({
207207
};
208208

209209
export const insertInstanceChildrenMutable = (
210-
data: WebstudioData,
210+
data: Omit<WebstudioData, "pages">,
211211
children: Instance["children"],
212212
insertTarget: Insertable
213213
) => {

0 commit comments

Comments
 (0)