diff --git a/src/fromRedactor.tsx b/src/fromRedactor.tsx index 555ce99..64fe860 100644 --- a/src/fromRedactor.tsx +++ b/src/fromRedactor.tsx @@ -15,7 +15,7 @@ const isInline = ['span', 'a', 'inlineCode', 'reference'] const isVoid = ['img', 'embed'] -const ELEMENT_TAGS: IHtmlToJsonElementTags = { +export const ELEMENT_TAGS: IHtmlToJsonElementTags = { A: (el: HTMLElement) => { const attrs: Record = {} const target = el.getAttribute('target'); @@ -49,7 +49,11 @@ const ELEMENT_TAGS: IHtmlToJsonElementTags = { const assetName = splittedUrl[splittedUrl?.length - 1] return { type: 'reference', attrs: { "asset-name": assetName,"content-type-uid" : "sys_assets", "asset-link": el.getAttribute('src'), "asset-type": `image/${imageType}`, "display-type": "display", "type": "asset", "asset-uid": assetUid } } } - return { type: 'img', attrs: { url: el.getAttribute('src') } } + const imageAttrs : any = { type: 'img', attrs: { url: el.getAttribute('src') } } + if (el.getAttribute('width')) { + imageAttrs.attrs['width'] = el.getAttribute('width') + } + return imageAttrs }, LI: () => ({ type: 'li', attrs: {} }), OL: () => ({ type: 'ol', attrs: {} }), @@ -98,7 +102,8 @@ const ELEMENT_TAGS: IHtmlToJsonElementTags = { SCRIPT: (el: HTMLElement) => { return { type: 'script', attrs: {} } }, - HR: () => ({ type: 'hr', attrs: {} }) + HR: () => ({ type: 'hr', attrs: {} }), + FIGCAPTION: () => ({ type: 'figcaption', attrs: {} }), } const TEXT_TAGS: IHtmlToJsonTextTags = { @@ -437,7 +442,11 @@ export const fromRedactor = (el: any, options?:IHtmlToJsonOptions) : IAnyObject } } elementAttrs.attrs["redactor-attributes"] = redactor - return jsx('element', { attrs: { ...elementAttrs?.attrs, type, "asset-caption": caption, "link": link, "asset-alt": alt, target, position, "asset-link": fileLink, "asset-uid": uid, "display-type": displayType, "asset-name": fileName, "asset-type": contentType, "content-type-uid": contentTypeUid }, type: "reference", uid: generateId() }, children) + const assetAttrs = { ...elementAttrs?.attrs, type, "asset-caption": caption, "link": link, "asset-alt": alt, target, position, "asset-link": fileLink, "asset-uid": uid, "display-type": displayType, "asset-name": fileName, "asset-type": contentType, "content-type-uid": contentTypeUid } + if(assetAttrs.target === "_self"){ + delete assetAttrs.target + } + return jsx('element', { attrs: assetAttrs, type: "reference", uid: generateId() }, children) } } if (nodeName === 'FIGCAPTION') { @@ -626,11 +635,14 @@ export const fromRedactor = (el: any, options?:IHtmlToJsonOptions) : IAnyObject const { href, target } = newChildren[0].attrs?.["redactor-attributes"] extraAttrs['anchorLink'] = href; if (target && target !== '') { - extraAttrs['target'] = true; + extraAttrs['target'] = target === "_blank"; } const imageAttrs = newChildren[0].children; if(imageAttrs[0].type === 'img'){ + if(imageAttrs[0].attrs.width){ + sizeAttrs.width = imageAttrs[0].attrs.width + } elementAttrs = getFinalImageAttributes({elementAttrs, newChildren : imageAttrs, extraAttrs, sizeAttrs}) } @@ -655,6 +667,16 @@ export const fromRedactor = (el: any, options?:IHtmlToJsonOptions) : IAnyObject elementAttrs = getImageAttributes(imageAttrs, imageAttrs.attrs || {}, extraAttrs) return jsx('element', elementAttrs, [{ text: '' }]) } + if (newChildren[0]?.type === 'img'){ + let extraAttrs: { [key: string]: any } = {} + const imageAttrs = newChildren[0] + elementAttrs = getImageAttributes(imageAttrs, imageAttrs.attrs || {}, extraAttrs) + elementAttrs.attrs['anchorLink'] = el.getAttribute('href') + if(el.getAttribute('target')) + elementAttrs.attrs['target'] = el.getAttribute('target') + return jsx('element', elementAttrs, [{ text: '' }]) + + } } if (nodeName === 'IMG' || nodeName === 'IFRAME' || nodeName === 'VIDEO') { if (elementAttrs?.attrs?.["redactor-attributes"]?.width) { @@ -670,6 +692,10 @@ export const fromRedactor = (el: any, options?:IHtmlToJsonOptions) : IAnyObject if (elementAttrs?.attrs?.["redactor-attributes"]?.inline) { elementAttrs.attrs.inline = Boolean(elementAttrs?.attrs?.["redactor-attributes"]?.inline) } + if(nodeName === "IMG" && elementAttrs.attrs.width){ + elementAttrs.attrs.style.width = `${elementAttrs.attrs.width}px` + elementAttrs.attrs.style['max-width'] = `${elementAttrs.attrs.width}px` + } return jsx('element', elementAttrs, [{ text: '' }]) } if (nodeName === 'BLOCKQUOTE') { @@ -928,6 +954,13 @@ const getFinalImageAttributes = ({elementAttrs, newChildren, extraAttrs, sizeAtt sizeAttrs.width = newChildren[0].attrs.width.toString(); } + if(!isNaN(parseInt(sizeAttrs.width))){ + sizeAttrs.style = { + width: `${sizeAttrs.width}px`, + "max-width": `${sizeAttrs.width}px` + } + } + const childAttrs = { ...newChildren[0].attrs, ...sizeAttrs, style: { 'text-align': style?.['text-align'] }, caption: extraAttrs['caption'] } extraAttrs = { ...extraAttrs, ...sizeAttrs } @@ -935,7 +968,10 @@ const getFinalImageAttributes = ({elementAttrs, newChildren, extraAttrs, sizeAtt delete childAttrs.caption } - const imageAttrs = getImageAttributes(elementAttrs, childAttrs, extraAttrs); + const imageAttrs = getImageAttributes(elementAttrs, childAttrs, extraAttrs); + + delete imageAttrs?.attrs?.['redactor-attributes']?.['anchorlink']; + delete imageAttrs?.attrs?.['redactor-attributes']?.['style']; return imageAttrs } diff --git a/src/toRedactor.tsx b/src/toRedactor.tsx index 5a200fb..ce486b6 100644 --- a/src/toRedactor.tsx +++ b/src/toRedactor.tsx @@ -482,6 +482,14 @@ export const toRedactor = (jsonValue: any,options?:IJsonToHtmlOptions) : string } if(jsonValue['type'] === 'img'){ attrsJson['src'] = allattrs['url'] + + if(allattrs['caption']) figureStyles.caption = allattrs['caption'] + if(allattrs['position']) figureStyles.position = allattrs['position'] + if(allattrs['anchorLink']) figureStyles.anchorLink = `href="${allattrs['anchorLink']}"` + if(allattrs['target']){ + figureStyles.anchorLink += ` target="${allattrs['target']}"` + } + figureStyles.fieldsEdited.push(figureStyles.caption) } if(!(options?.customElementTypes && !isEmpty(options.customElementTypes) && options.customElementTypes[jsonValue['type']])) { delete attrsJson['url'] diff --git a/test/expectedJson.ts b/test/expectedJson.ts index 2a2e482..241b1b2 100644 --- a/test/expectedJson.ts +++ b/test/expectedJson.ts @@ -1346,7 +1346,6 @@ export default { "sys-style-type": "display" }, "type": "asset", - "target": "_self", "asset-link": "https://images.contentstack.io/v3/assets/bltbdb397c7cc18a214/blt9fedd0336c2f7f0d/61fe9fb699c8a84a577b9f40/crop_area.jpeg", "asset-uid": "blt9fedd0336c2f7f0d", "display-type": "display", @@ -1701,7 +1700,7 @@ export default {
Landscape
`, - "json": {"type":"doc","uid":"d6cd7b938dcc41a8a75fb8bad29aa2e9","attrs":{},"children":[{"type":"p","attrs":{},"uid":"c17f2b982464422aaa58499b9525b437","children":[{"text":""}]},{"type":"img","attrs":{"style":{"text-align":"center"},"redactor-attributes":{"src":"https://images.contentstack.io/v3/assets/blt858e12437ac2679e/bltfea8157ddfb8e776/6329f1106a7f7364973c028c/landscape-3.jpg","position":"center","captionAttrs":{"style":"text-align: center;"},"caption":"Landscape","anchorLink":"https://app.contentstack.com/","width":204},"url":"https://images.contentstack.io/v3/assets/blt858e12437ac2679e/bltfea8157ddfb8e776/6329f1106a7f7364973c028c/landscape-3.jpg","width":204,"caption":"Landscape","link":"https://app.contentstack.com/"},"children":[{"text":""}]}]} + "json": {"type":"doc","attrs":{},"children":[{"type":"p","attrs":{},"children":[{"text":""}]},{"type":"img","attrs":{"style":{"text-align":"center"},"redactor-attributes":{"src":"https://images.contentstack.io/v3/assets/blt858e12437ac2679e/bltfea8157ddfb8e776/6329f1106a7f7364973c028c/landscape-3.jpg","position":"center","captionAttrs":{"style":"text-align: center;"},"caption":"Landscape","width":204},"url":"https://images.contentstack.io/v3/assets/blt858e12437ac2679e/bltfea8157ddfb8e776/6329f1106a7f7364973c028c/landscape-3.jpg","anchorLink":"https://app.contentstack.com/","width":204,"caption":"Landscape"},"children":[{"text":""}]}]} }, "'\n' to
": { "html": '

This is test for break element
This is text on the next line.

', diff --git a/test/fromRedactor.test.ts b/test/fromRedactor.test.ts index 0c5f484..dd5b899 100644 --- a/test/fromRedactor.test.ts +++ b/test/fromRedactor.test.ts @@ -1,5 +1,5 @@ // @ts-nocheck -import { fromRedactor, getNestedValueIfAvailable } from "../src/fromRedactor" +import { ELEMENT_TAGS, fromRedactor, getNestedValueIfAvailable } from "../src/fromRedactor" import { JSDOM } from "jsdom" import isEqual from "lodash.isequal" import omitdeep from "omit-deep-lodash" @@ -295,6 +295,16 @@ describe("Testing html to json conversion", () => { const json = htmlToJson(html) expect(json).toStrictEqual({"type":"doc","uid":"uid","attrs":{},"children":[{"type":"reference","attrs":{"style":{"text-align":"right"},"redactor-attributes":{"src":"https://picsum.photos/200","height":"141","alt":"image_(9).png","caption":"ss","type":"asset","asset-alt":"image_(9).png","max-height":"141","max-width":"148","sys-style-type":"display","position":"right","captionAttrs":{"style":"text-align:center"},"anchorLink":"ss.com","target":true,"asset-caption":"ss"},"class-name":"embedded-asset","width":148,"type":"asset","asset-caption":"ss","link":"ss.com","asset-alt":"image_(9).png","target":"_blank","position":"right","asset-link":"https://picsum.photos/200","asset-uid":"blt137d845621ef8168","display-type":"display","asset-name":"image_(9).png","asset-type":"image/png","content-type-uid":"sys_assets"},"uid":"uid","children":[{"text":""}]},{"type":"p","attrs":{},"uid":"uid","children":[{"text":""}]}] }) }) + test("should convert asset to reference with non standard tags", () => { + const html = `
+
image_(9).png +
ss
+
+
+

` + const json = htmlToJson(html, { allowNonStandardTags: true }) + expect(json).toStrictEqual({"type":"doc","uid":"uid","attrs":{},"children":[{"type":"reference","attrs":{"style":{"text-align":"right"},"redactor-attributes":{"src":"https://picsum.photos/200","height":"141","alt":"image_(9).png","caption":"ss","type":"asset","asset-alt":"image_(9).png","max-height":"141","max-width":"148","sys-style-type":"display","position":"right","captionAttrs":{"style":"text-align:center"},"anchorLink":"ss.com","target":true,"asset-caption":"ss"},"class-name":"embedded-asset","width":148,"type":"asset","asset-caption":"ss","link":"ss.com","asset-alt":"image_(9).png","target":"_blank","position":"right","asset-link":"https://picsum.photos/200","asset-uid":"blt137d845621ef8168","display-type":"display","asset-name":"image_(9).png","asset-type":"image/png","content-type-uid":"sys_assets"},"uid":"uid","children":[{"text":""}]},{"type":"p","attrs":{},"uid":"uid","children":[{"text":""}]}] }) + }) }) @@ -372,14 +382,16 @@ describe("CS-41001", () =>{ }) }) - - - +describe("ELEMENT_TAGS", () => { + test("should have FIGCAPTION as a standard element tag", () => { + const standardElementTags = Object.keys(ELEMENT_TAGS); + expect(standardElementTags).toContain("FIGCAPTION"); + }) +}) function htmlToJson (html: string, options: IHtmlToJsonOptions) { const dom = new JSDOM(html); let htmlDoc = dom.window.document.querySelector("body"); return fromRedactor(htmlDoc, options); -} - +} \ No newline at end of file diff --git a/test/toRedactor.test.ts b/test/toRedactor.test.ts index 85608a1..dccbfe4 100644 --- a/test/toRedactor.test.ts +++ b/test/toRedactor.test.ts @@ -228,7 +228,7 @@ describe("Testing json to html conversion", () => { test("RT-253 - should convert to proper HTML image code", () => { const json = {"type":"doc","attrs":{},"children":[{"type":"img","attrs":{"url":"https://picsum.photos/200","width":100},"children":[{"text":""}]}],"_version":3 } const html = toRedactor(json); - expect(html).toBe(''); + expect(html).toBe(''); }); test("RT-264 - reference asset should have proper unit in the converted image", () => { @@ -236,5 +236,11 @@ describe("Testing json to html conversion", () => { const html = toRedactor(json); expect(html).toBe(`
`); }) + + test("RT-292", () => { + const json = {"type":"doc","uid":"41870a48806348eb866c1944d37d3a5d","attrs":{},"children":[{"type":"img","attrs":{"url":"https://picsum.photos/536/354","style":{},"redactor-attributes":{"position":"none","caption":"caption","inline":"true","width":"243","dirty":"true","max-width":"243","src":"https://picsum.photos/536/354","alt":"alt","anchorLink":"link","target":true},"width":"217","inline":"true","caption":"caption","alt":"alt","anchorLink":"link","target":"_blank"},"uid":"bedc4931f5aa4fd59fd6411665f931e2","children":[{"text":""}]}] } + const html = toRedactor(json); + expect(html).toBe(`
alt
caption
`) + }) })