Skip to content

Commit 8c0a7b1

Browse files
authored
Merge pull request #28 from contentstack/development
Support for rendering image type assets while json to html conversion and fix empty fragment added between table
2 parents 06da814 + a5d6df4 commit 8c0a7b1

File tree

7 files changed

+1078
-5
lines changed

7 files changed

+1078
-5
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/json-rte-serializer",
3-
"version": "2.0.3",
3+
"version": "2.0.4",
44
"description": "This Package converts Html Document to Json and vice-versa.",
55
"main": "lib/index.js",
66
"types": "lib/index.d.ts",

src/fromRedactor.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,10 @@ const traverseChildAndWarpChild = (children: Array<Object>) => {
160160

161161
const whiteCharPattern = /^[\s ]{2,}$/
162162
export const fromRedactor = (el: any, options?:IHtmlToJsonOptions) : IAnyObject | null => {
163+
// If node is text node
163164
if (el.nodeType === 3) {
164165
if (whiteCharPattern.test(el.textContent)) return null
166+
if (["TABLE", "THEAD", "TBODY", "TR"].includes(el?.parentElement?.nodeName ?? "") && el?.textContent?.trim?.()?.length === 0) return null
165167
if (el.textContent === '\n') {
166168
return null
167169
}

src/toRedactor.tsx

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ const ELEMENT_TYPES: IJsonToHtmlElementTags = {
4949
return `<iframe${attrs}></iframe>`
5050
},
5151
p: (attrs: any, child: any) => {
52+
if(child.includes("<figure"))
53+
return `<div${attrs} style="overflow: hidden"><span>${child}</span></div>`
5254
return `<p${attrs}>${child}</p>`
5355
},
5456
ol: (attrs: any, child: any) => {
@@ -118,6 +120,53 @@ const ELEMENT_TYPES: IJsonToHtmlElementTags = {
118120
} else if (extraAttrs?.displayType === 'asset') {
119121
return `<figure${attrs}>${child}</figure>`
120122
}
123+
124+
else if (extraAttrs?.displayType === "display") {
125+
const anchor = jsonBlock?.["attrs"]?.["link"];
126+
127+
const caption = jsonBlock?.["attrs"]?.["asset-caption"];
128+
const position = jsonBlock?.["attrs"]?.["position"];
129+
const inline = jsonBlock?.["attrs"]?.["inline"]
130+
let figureAttrs = ""
131+
const figureStyles = {
132+
margin: "0",
133+
};
134+
attrs = ` src="${jsonBlock?.["attrs"]?.["asset-link"]}"` + attrs;
135+
let img = `<img${attrs}/>`;
136+
137+
if (anchor) {
138+
const target = jsonBlock?.["attrs"]?.["target"];
139+
let anchorAttrs = `href="${anchor}"`;
140+
if (target) {
141+
anchorAttrs = `${anchorAttrs} target="${target}"`;
142+
}
143+
img = `<a ${anchorAttrs}>${img}</a>`;
144+
}
145+
146+
if (caption || (position && position !== "none")) {
147+
const figcaption = caption
148+
? `<figcaption style="text-align:center">${caption}</figcaption>`
149+
: "";
150+
151+
if (inline && position !== "right" && position !== "left") {
152+
figureStyles["display"] = "inline-block";
153+
}
154+
if (position && position !== "none") {
155+
figureStyles[inline ? "float" : "text-align"] = position;
156+
}
157+
158+
if(figcaption){
159+
img = `<div style="display: inline-block">${img}${figcaption}</div>`;
160+
}
161+
}
162+
if(!isEmpty(figureStyles)){
163+
figureAttrs = ` style="${getStyleStringFromObject(figureStyles)}"`
164+
}
165+
if(inline && !caption && (!position ||position==='none')){
166+
return img
167+
}
168+
return `<figure${figureAttrs ? figureAttrs : ""}>${img}</figure>`;
169+
}
121170
return `<span${attrs}>${child}</span>`
122171
},
123172
inlineCode: (attrs: any, child: any) => {
@@ -362,7 +411,9 @@ export const toRedactor = (jsonValue: any,options?:IJsonToHtmlOptions) : string
362411
delete attrsJson['content-type-uid']
363412
attrsJson['sys-style-type'] = allattrs['display-type']
364413
delete attrsJson['display-type']
365-
} else if (attrsJson['type'] === "asset") {
414+
}
415+
416+
else if (attrsJson['type'] === "asset") {
366417
attrsJson['data-sys-asset-filelink'] = allattrs['asset-link']
367418
delete attrsJson['asset-link']
368419
attrsJson['data-sys-asset-uid'] = allattrs['asset-uid']
@@ -399,7 +450,16 @@ export const toRedactor = (jsonValue: any,options?:IJsonToHtmlOptions) : string
399450
if (!attrsJson['sys-style-type']) {
400451
attrsJson['sys-style-type'] = String(allattrs['asset-type']).indexOf('image') > -1 ? 'display' : 'download'
401452
}
402-
453+
if (attrsJson?.["display-type"] === "display") {
454+
const styleObj = jsonValue?.["attrs"]?.["style"] ?? {};
455+
if (!styleObj["width"]) {
456+
styleObj["width"] = "auto";
457+
}
458+
delete styleObj["float"];
459+
// (attrsJson["style"] && typeof attrsJson["style"] === 'string')
460+
// ? (attrsJson["style"] += getStyleStringFromObject(styleObj)) :
461+
(attrsJson["style"] = getStyleStringFromObject(styleObj));
462+
}
403463
delete attrsJson['display-type']
404464
}
405465
}
@@ -468,3 +528,10 @@ export const toRedactor = (jsonValue: any,options?:IJsonToHtmlOptions) : string
468528

469529
return children
470530
}
531+
532+
533+
function getStyleStringFromObject(styleObj: { [key: string]: string }) {
534+
return Object.keys(styleObj)
535+
.map((key) => `${key}: ${styleObj[key]}`)
536+
.join("; ");
537+
}

test/fromRedactor.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,38 @@ describe('getNestedValueIfAvailable', () => {
270270
});
271271

272272
});
273+
describe("CS-41001", () =>{
274+
test("should not add fragment for text nodes having white spaces", () => {
275+
const dom = new JSDOM();
276+
const document = dom.window.document;
277+
const body = document.createElement("body");
278+
const td1 = document.createElement("td");
279+
const td2 = document.createElement("td");
280+
const tr = document.createElement("tr");
281+
const text = document.createTextNode(` `)
282+
td1.textContent = "Hello";
283+
td2.textContent = "World";
284+
tr.appendChild(td1);
285+
tr.append(text)
286+
tr.appendChild(td2);
287+
body.append(tr)
288+
const jsonValue = fromRedactor(body);
289+
expect(jsonValue).toStrictEqual({"type":"doc","uid":"uid","attrs":{},"children":[{"type":"tr","attrs":{},"uid":"uid","children":[{"type":"td","attrs":{},"uid":"uid","children":[{"text":"Hello"}]},{"type":"td","attrs":{},"uid":"uid","children":[{"text":"World"}]}]}]})
290+
})
291+
test("should add fragment for text nodes between block nodes", () => {
292+
const dom = new JSDOM();
293+
const document = dom.window.document;
294+
const body = document.createElement("body");
295+
const p1 = document.createElement("p");
296+
const p2 = document.createElement("p");
297+
const text = document.createTextNode(` beautiful `)
298+
p1.textContent = "Hello";
299+
p2.textContent = "World";
300+
body.appendChild(p1);
301+
body.append(text)
302+
body.appendChild(p2);
303+
const jsonValue = fromRedactor(body);
304+
expect(jsonValue).toStrictEqual({"type":"doc","uid":"uid","attrs":{},"children":[{"type":"p","attrs":{},"uid":"uid","children":[{"text":"Hello"}]},{"type":"fragment","attrs":{},"uid":"uid","children":[{"text":" beautiful "}]},{"type":"p","attrs":{},"uid":"uid","children":[{"text":"World"}]}]})
305+
})
306+
})
307+

0 commit comments

Comments
 (0)