From e1551025f9b23e0e93e1b4d3f32786af0f82349a Mon Sep 17 00:00:00 2001 From: Nadeem Patwekar Date: Wed, 14 Aug 2024 16:55:57 +0530 Subject: [PATCH 1/4] fix: reference-to-html method fix for asset reference --- CHANGELOG.md | 3 ++ __test__/json-to-html.test.ts | 13 ++++++ __test__/mock/json-element-mock.ts | 73 ++++++++++++++++++------------ package.json | 2 +- src/helper/enumerate-entries.ts | 12 +++-- 5 files changed, 69 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 475f660..98a4ea1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Changelog +## [1.3.11](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.11) (2024-08-21) + - Fix: Reference to HTML fixed to support assets that are referenced + ## [1.3.10](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.10) (2024-07-08) - Enhancement: Update default node options diff --git a/__test__/json-to-html.test.ts b/__test__/json-to-html.test.ts index 51cb753..c3d1549 100644 --- a/__test__/json-to-html.test.ts +++ b/__test__/json-to-html.test.ts @@ -167,6 +167,19 @@ describe('Node parser reference content', () => { expect(entry.json_rte[0]).toEqual(referenceObjHtml) done() }) + + it('should convert to html when asset embedded as link in json_rte', done => { + const entry = { + uid: 'entry_uid', + rte_data: {...embeddedAssetAsLinkJsonEntry}, + } + const paths = ["rte_data"] + const result = `

asdasdasdas

` + jsonToHTML({ entry: entry, paths }) + + expect(entry.rte_data).toBe(result) + done() + }) }) describe('Node parse text Content', () => { diff --git a/__test__/mock/json-element-mock.ts b/__test__/mock/json-element-mock.ts index 94c0540..7da793e 100644 --- a/__test__/mock/json-element-mock.ts +++ b/__test__/mock/json-element-mock.ts @@ -1139,38 +1139,51 @@ const paragraphJsonArrayEntry = { } const embeddedAssetAsLinkJsonEntry = { - uid: 'entry_uid', - rte_data: { - type: 'doc', - attrs: {}, - uid: 'rte_uid', - children: [ + "type": "doc", + "attrs": {}, + "uid": "1b212916f2784af4bcf9a0af5018364e", + "children": [ { - type: 'p', - uid: 'p_uid', - attrs: {}, - children: [ - { text: '' }, - { - uid: 'ref_uid', - type: 'reference', - attrs: { - 'display-type': 'link', - type: 'asset', - 'class-name': 'embedded-entry redactor-component undefined-entry', - 'asset-uid': 'asset_uid_2', - 'content-type-uid': 'sys_assets', - target: '_self', - href: 'https://picsum.photos/200' - }, - children: [ { text: 'Door matching', bold: true, underline: true } ] - }, - { text: '' } - ] + "type": "p", + "attrs": {}, + "uid": "3f3a84966368435388b7b9948283be2e", + "children": [ + { + "text": "asda" + }, + { + "uid": "c2384ca128a64ee89e82b7aaab77e7b1", + "type": "reference", + "attrs": { + "display-type": "link", + "type": "asset", + "class-name": "embedded-entry redactor-component undefined-entry", + "asset-uid": "bltbcfce09569234229", + "content-type-uid": "sys_assets", + "target": "_self", + "href": "https://images.contentstack.io/v3/assets/blt144f0e44ce32a42f/bltbcfce09569234229/657304603ed4d5773c01feed/Screenshot_2023-03-01_at_1.09.39_PM.png" + }, + "children": [ + { + "text": "s" + }, + { + "text": "das", + "bold": true + } + ] + }, + { + "text": "d", + "bold": true + }, + { + "text": "as" + } + ] } - ], - _version: 4 - } + ], + "_version": 1 } const embeddedAssetJsonEntry = { diff --git a/package.json b/package.json index 68d003e..0dcc8d8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/utils", - "version": "1.3.10", + "version": "1.3.11", "description": "Contentstack utilities for Javascript", "main": "dist/index.es.js", "types": "dist/types/index.d.ts", diff --git a/src/helper/enumerate-entries.ts b/src/helper/enumerate-entries.ts index d6f0906..5e3fd90 100644 --- a/src/helper/enumerate-entries.ts +++ b/src/helper/enumerate-entries.ts @@ -77,12 +77,18 @@ export function referenceToHTML( renderOption: RenderOption, renderEmbed?: (metadata: Metadata) => EmbeddedItem | EntryNode, ): string { - if (node.attrs.type === 'entry' && node.attrs['display-type'] === 'link') { + if ((node.attrs.type === 'entry' || node.attrs.type === 'asset') && node.attrs['display-type'] === 'link') { const entryText = node.children ? nodeChildrenToHTML(node.children, renderOption, renderEmbed) : ''; + + let aTagAttrs = `${node.attrs.style ? ` style="${node.attrs.style}"` : ``}${node.attrs['class-name'] ? ` class="${node.attrs['class-name']}"` : ``}${node.attrs.id ? ` id="${node.attrs.id}"` : ``} href="${node.attrs.href || node.attrs.url}"`; if (node.attrs.target) { - return `${entryText}` + aTagAttrs +=` target="${node.attrs.target}"`; + } + if(node.attrs.type == 'asset') { + aTagAttrs += ` type="asset" content-type-uid="sys_assets" ${node.attrs['asset-uid'] ? `data-sys-asset-uid="${node.attrs['asset-uid']}"` : ``} sys-style-type="download"` } - return `${entryText}`; + const aTag = `${entryText}`; + return aTag; } function sendToRenderOption(referenceNode: Node): string { From 80eeeff75730935e1efbd70122fc3535d6ba664c Mon Sep 17 00:00:00 2001 From: Mridul Sharma Date: Wed, 14 Aug 2024 18:28:14 +0530 Subject: [PATCH 2/4] fix: live preview: added variant support in data cslp tag function --- src/entry-editable.ts | 216 +++++++++++++++++++++++------------------- 1 file changed, 116 insertions(+), 100 deletions(-) diff --git a/src/entry-editable.ts b/src/entry-editable.ts index 0a6a111..6a5b4e4 100644 --- a/src/entry-editable.ts +++ b/src/entry-editable.ts @@ -1,105 +1,121 @@ -import { EntryModel } from "."; +import { EntryModel } from "." -export function addTags(entry: EntryModel, contentTypeUid: string, tagsAsObject: boolean, locale: string = 'en-us') : void { - if (entry) - entry.$ = getTag(entry, `${contentTypeUid}.${entry.uid}.${locale}`, tagsAsObject, locale) -} - -function getTag(content: object, prefix: string, tagsAsObject: boolean, locale: string): object { - const tags: any = {} - Object.entries(content).forEach(([key, value]) => { - if (key === '$') return + export function addTags(entry: EntryModel, contentTypeUid: string, tagsAsObject: boolean, locale: string = 'en-us') : void { + if (entry) { + const appliedVariants = entry._applied_variants || null; + entry.$ = getTag(entry, `${contentTypeUid}.${entry.uid}.${locale}`, tagsAsObject, locale, {_applied_variants: appliedVariants, shouldApplyVariant: !!appliedVariants, metaKey: ''}) } + } + + function getTag(content: object, prefix: string, tagsAsObject: boolean, locale: string, appliedVariants: {_applied_variants:{[key: string]: any}, shouldApplyVariant: boolean, metaKey: string}): object { + const tags: any = {} + const { metaKey, shouldApplyVariant, _applied_variants } = appliedVariants + Object.entries(content).forEach(([key, value]) => { + if (key === '$') return + let metaUID = value && typeof value === 'object' && value._metadata && value._metadata.uid ? value._metadata.uid : ''; + let updatedMetakey = appliedVariants.shouldApplyVariant ? `${appliedVariants.metaKey ? appliedVariants.metaKey + '.' : '' }${key}` : ''; + if(metaUID && updatedMetakey) updatedMetakey = updatedMetakey + '.' + metaUID; + switch (typeof value) { + case "object": + if (Array.isArray(value)) { + value.forEach((obj, index) => { + const childKey = `${key}__${index}` + const parentKey = `${key}__parent` + metaUID = value && typeof value === 'object' && obj._metadata && obj._metadata.uid ? obj._metadata.uid : ''; + updatedMetakey = appliedVariants.shouldApplyVariant ? `${appliedVariants.metaKey ? appliedVariants.metaKey + '.' : '' }${key}` : ''; + if(metaUID && updatedMetakey) updatedMetakey = updatedMetakey + '.' + metaUID; + /** + * Indexes of array are handled here + * { + * "array": ["hello", "world"], + * "$": { + * "array": {"data-cslp": "content_type_uid.entry_uid.locale.array"} + * "array__0": {"data-cslp": "content_type_uid.entry_uid.locale.array.0"} + * "array__1": {"data-cslp": "content_type_uid.entry_uid.locale.array.1"} + * } + * } + */ + tags[childKey] = getTagsValue(`${prefix}.${key}.${index}`, tagsAsObject, { _applied_variants, shouldApplyVariant, metaKey: updatedMetakey }) + tags[parentKey] = getParentTagsValue(`${prefix}.${key}`, tagsAsObject) + if (typeof obj !== 'undefined' && obj !== null && obj._content_type_uid !== undefined && obj.uid !== undefined) { + /** + * References are handled here + * { + * "reference": [{ + * "title": "title", + * "uid": "ref_uid", + * "_content_type_uid": "ref_content_type_uid", + * "$": {"title": {"data-cslp": "ref_content_type_uid.ref_uid.locale.title"}} + * }] + * } + */ + const newAppliedVariants = obj._applied_variants || _applied_variants; + const newShouldApplyVariant = !!newAppliedVariants + value[index].$ = getTag(obj, `${obj._content_type_uid}.${obj.uid}.${obj.locale || locale}`, tagsAsObject, locale, {_applied_variants:newAppliedVariants, shouldApplyVariant:newShouldApplyVariant, metaKey: updatedMetakey}) + }else if (typeof obj === "object") { + /** + * Objects inside Array like modular blocks are handled here + * { + * "array": [{ + * "title": "title", + * "$": {"title": {"data-cslp": "content_type_uid.entry_uid.locale.array.0.title"}} + * }] + * } + */ + obj.$ = getTag(obj,`${prefix}.${key}.${index}`, tagsAsObject, locale, {_applied_variants, shouldApplyVariant, metaKey: updatedMetakey}) + } + }) + }else { + if (value) { + /** + * Objects are handled here + * { + * "object": { + * "title": "title", + * "$": { + * "title": {"data-cslp": "content_type_uid.entry_uid.locale.object.title"} + * } + * }, + * } + */ + value.$ = getTag(value, `${prefix}.${key}`, tagsAsObject, locale, {_applied_variants, shouldApplyVariant, metaKey: updatedMetakey}) + } + } + /** + * { + * "object": { + * "title": "title", + * }, + * "array": ["hello", "world"] + * "$": { + * "object": {"data-cslp": "content_type_uid.entry_uid.locale.object"}, + * "array": {"data-cslp": "content_type_uid.entry_uid.locale.array"} + * } + * } + */ - switch (typeof value) { - case "object": - if (Array.isArray(value)) { - value.forEach((obj, index) => { - const childKey = `${key}__${index}` - const parentKey = `${key}__parent` - /** - * Indexes of array are handled here - * { - * "array": ["hello", "world"], - * "$": { - * "array": {"data-cslp": "content_type_uid.entry_uid.locale.array"} - * "array__0": {"data-cslp": "content_type_uid.entry_uid.locale.array.0"} - * "array__1": {"data-cslp": "content_type_uid.entry_uid.locale.array.1"} - * } - * } - */ - tags[childKey] = getTagsValue(`${prefix}.${key}.${index}`, tagsAsObject) - tags[parentKey] = getParentTagsValue(`${prefix}.${key}`, tagsAsObject) - if (typeof obj !== 'undefined' && obj !== null && obj._content_type_uid !== undefined && obj.uid !== undefined) { - /** - * References are handled here - * { - * "reference": [{ - * "title": "title", - * "uid": "ref_uid", - * "_content_type_uid": "ref_content_type_uid", - * "$": {"title": {"data-cslp": "ref_content_type_uid.ref_uid.locale.title"}} - * }] - * } - */ - value[index].$ = getTag(obj, `${obj._content_type_uid}.${obj.uid}.${obj.locale || locale}`, tagsAsObject, locale) - }else if (typeof obj === "object") { - /** - * Objects inside Array like modular blocks are handled here - * { - * "array": [{ - * "title": "title", - * "$": {"title": {"data-cslp": "content_type_uid.entry_uid.locale.array.0.title"}} - * }] - * } - */ - obj.$ = getTag(obj,`${prefix}.${key}.${index}`, tagsAsObject, locale) - } - }) - }else { - if (value) { - /** - * Objects are handled here - * { - * "object": { - * "title": "title", - * "$": { - * "title": {"data-cslp": "content_type_uid.entry_uid.locale.object.title"} - * } - * }, - * } - */ - value.$ = getTag(value, `${prefix}.${key}`, tagsAsObject, locale) - } - } - /** - * { - * "object": { - * "title": "title", - * }, - * "array": ["hello", "world"] - * "$": { - * "object": {"data-cslp": "content_type_uid.entry_uid.locale.object"}, - * "array": {"data-cslp": "content_type_uid.entry_uid.locale.array"} - * } - * } - */ - tags[key] = getTagsValue(`${prefix}.${key}`, tagsAsObject) - break; - default: - /** - * All primitive values are handled here - * { - * "title": "title", - * "$": {title: {"data-cslp": "content_type_uid.entry_uid.locale.title"}} - * } - */ - tags[key] = getTagsValue(`${prefix}.${key}`, tagsAsObject) - } - }) - return tags -} - -function getTagsValue (dataValue:string, tagsAsObject: boolean): any { + tags[key] = getTagsValue(`${prefix}.${key}`, tagsAsObject, { _applied_variants, shouldApplyVariant, metaKey: updatedMetakey }) + break; + default: + /** + * All primitive values are handled here + * { + * "title": "title", + * "$": {title: {"data-cslp": "content_type_uid.entry_uid.locale.title"}} + * } + */ + tags[key] = getTagsValue(`${prefix}.${key}`, tagsAsObject, { _applied_variants, shouldApplyVariant, metaKey: updatedMetakey }) + } + }) + return tags + } + +function getTagsValue (dataValue:string, tagsAsObject: boolean, appliedVariants: {_applied_variants: {[key: string]: any}, shouldApplyVariant: boolean, metaKey: string}): any { + if(appliedVariants.shouldApplyVariant && appliedVariants._applied_variants && appliedVariants._applied_variants[appliedVariants.metaKey]) { + const variant = appliedVariants._applied_variants[appliedVariants.metaKey] + const newDataValueArray = dataValue.split('.'); + newDataValueArray[1] = newDataValueArray[1] + '_' + variant; + dataValue = newDataValueArray.join('.'); + } if (tagsAsObject) { return { "data-cslp": dataValue }; } else { From fa3433334c04cffe23fd1a27ea97fc17b79f925a Mon Sep 17 00:00:00 2001 From: Mridul Sharma Date: Thu, 22 Aug 2024 19:50:48 +0530 Subject: [PATCH 3/4] fix: live preview: resolve bug for non-variant field --- src/entry-editable.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/entry-editable.ts b/src/entry-editable.ts index 6a5b4e4..cc4f70c 100644 --- a/src/entry-editable.ts +++ b/src/entry-editable.ts @@ -112,7 +112,8 @@ import { EntryModel } from "." function getTagsValue (dataValue:string, tagsAsObject: boolean, appliedVariants: {_applied_variants: {[key: string]: any}, shouldApplyVariant: boolean, metaKey: string}): any { if(appliedVariants.shouldApplyVariant && appliedVariants._applied_variants && appliedVariants._applied_variants[appliedVariants.metaKey]) { const variant = appliedVariants._applied_variants[appliedVariants.metaKey] - const newDataValueArray = dataValue.split('.'); + // Adding v2 prefix to the cslp tag. New cslp tags are in v2 format. ex: v2:content_type_uid.entry_uid.locale.title + const newDataValueArray = ('v2:' + dataValue).split('.'); newDataValueArray[1] = newDataValueArray[1] + '_' + variant; dataValue = newDataValueArray.join('.'); } From ecfbfd37c8d1eda88795f0e89cd6552e06dde24e Mon Sep 17 00:00:00 2001 From: Mridul Sharma Date: Tue, 27 Aug 2024 20:54:49 +0530 Subject: [PATCH 4/4] fix: live preview: resolve cslp variant issue for reference entry --- src/entry-editable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entry-editable.ts b/src/entry-editable.ts index cc4f70c..12f1723 100644 --- a/src/entry-editable.ts +++ b/src/entry-editable.ts @@ -50,7 +50,7 @@ import { EntryModel } from "." */ const newAppliedVariants = obj._applied_variants || _applied_variants; const newShouldApplyVariant = !!newAppliedVariants - value[index].$ = getTag(obj, `${obj._content_type_uid}.${obj.uid}.${obj.locale || locale}`, tagsAsObject, locale, {_applied_variants:newAppliedVariants, shouldApplyVariant:newShouldApplyVariant, metaKey: updatedMetakey}) + value[index].$ = getTag(obj, `${obj._content_type_uid}.${obj.uid}.${obj.locale || locale}`, tagsAsObject, locale, {_applied_variants:newAppliedVariants, shouldApplyVariant:newShouldApplyVariant, metaKey: ""}) }else if (typeof obj === "object") { /** * Objects inside Array like modular blocks are handled here