Skip to content

Commit a7ae18d

Browse files
authored
fix: deserialization - wrap each resulting non-empty child text node with a paragraph (#2236)
1 parent 63131b5 commit a7ae18d

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

.changeset/slow-bags-cheer.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@commercetools-uikit/rich-text-utils': patch
3+
---
4+
5+
Fix `deserializeElement` function by wrapping each resulting non-empty child text node with a paragraph

packages/components/inputs/localized-rich-text-input/src/localized-rich-text-input.visualroute.jsx

+18
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ const initialValue = {
1616
es: lorem,
1717
};
1818

19+
const complexMarkup =
20+
'<ol><li><span style="font-weight: bold; font-family: &quot;Comic Sans MS&quot;;">Computermouse for <span style="text-decoration-line: underline;">controlling</span></span></li></ol><span><table class="table table-bordered"><tbody><tr><td>hello</td></tr><tr><td><p>world<img src="https://www.rollingstone.com/wp-content/uploads/2019/01/shutterstock_10010937aj.jpg" style="width: 100%; float: right;" class="pull-right img-circle"></p></td></tr></tbody></table></span><ol><li><span style="font-weight: bold; font-family: &quot;Comic Sans MS&quot;;">';
21+
22+
const initialValueWithComplexMarkup = {
23+
en: complexMarkup,
24+
de: complexMarkup,
25+
es: complexMarkup,
26+
};
27+
1928
const emptyValue = '';
2029

2130
export const routePath = '/localized-rich-text-input';
@@ -267,6 +276,15 @@ const DefaultRoute = () => (
267276
onClickExpand={() => {}}
268277
/>
269278
</Spec>
279+
<Spec label="with complex markup" omitPropsList>
280+
<LocalizedRichTextInput
281+
onChange={() => {}}
282+
value={initialValueWithComplexMarkup}
283+
selectedLanguage="en"
284+
horizontalConstraint={7}
285+
defaultExpandMultilineText={true}
286+
/>
287+
</Spec>
270288
</Suite>
271289
);
272290

packages/components/inputs/rich-text-utils/src/html/html.spec.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ describe('html', () => {
106106
'<ol><li><span style="font-weight: bold; font-family: &quot;Comic Sans MS&quot;;">Computermouse for <span style="text-decoration-line: underline;">controlling</span></span></li></ol><table class="table table-bordered"><tbody><tr><td>hello</td></tr><tr><td><p>world<img src="https://www.rollingstone.com/wp-content/uploads/2019/01/shutterstock_10010937aj.jpg" style="width: 100%; float: right;" class="pull-right img-circle"></p></td></tr></tbody></table><ol><li><span style="font-weight: bold; font-family: &quot;Comic Sans MS&quot;;"><span style="text-decoration-line: underline;"><br></span></span></li></ol>';
107107

108108
expect(html.serialize(html.deserialize(htmlValue))).toEqual(
109-
'<ol><li><strong>Computermouse for </strong><u><strong>controlling</strong></u></li></ol>hello<p>world</p><ol><li><u><strong></strong></u></li></ol>'
109+
'<ol><li><strong>Computermouse for </strong><u><strong>controlling</strong></u></li></ol><p>hello</p><p>world</p><ol><li><u><strong></strong></u></li></ol>'
110110
);
111111
});
112112
});

packages/components/inputs/rich-text-utils/src/html/html.tsx

+9-2
Original file line numberDiff line numberDiff line change
@@ -175,12 +175,16 @@ const mapper: TMapper = {
175175
},
176176
};
177177

178+
const wrapWithParagraph = (
179+
textContent: TElement | TText | (TElement | TText)[]
180+
) => jsx('element', { type: 'paragraph' }, textContent);
181+
178182
const wrapWithParagraphIfRootElement = (
179183
el: HTMLElement | ChildNode,
180184
textContent: TElement | TText | (TElement | TText)[]
181185
) =>
182186
el.parentNode?.nodeName === 'BODY' // root element, because body is eventually turned to React fragment
183-
? jsx('element', { type: 'paragraph' }, textContent)
187+
? wrapWithParagraph(textContent)
184188
: textContent;
185189

186190
export type Deserialized = Descendant | null;
@@ -275,7 +279,10 @@ const deserializeElement = (
275279
return children.map((child) => jsx('text', attrs, child));
276280
}
277281

278-
return children;
282+
// each non-empty text node must be wrapped with a paragraph
283+
return children.map((child) =>
284+
Text.isText(child) && child.text ? wrapWithParagraph(child) : child
285+
);
279286
};
280287
const deserialize = (html: Html) => {
281288
const document = new DOMParser().parseFromString(

0 commit comments

Comments
 (0)