Skip to content

Commit 759bfeb

Browse files
authored
Merge pull request #91 from contentstack/next
Fix: Embedded asset reference to html
2 parents 22cd7c1 + af6f858 commit 759bfeb

File tree

6 files changed

+186
-134
lines changed

6 files changed

+186
-134
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Changelog
22

33

4+
## [1.3.11](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.11) (2024-08-21)
5+
- Fix: Reference to HTML fixed to support assets that are referenced
6+
47
## [1.3.10](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.10) (2024-07-08)
58
- Enhancement: Update default node options
69

__test__/json-to-html.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,19 @@ describe('Node parser reference content', () => {
167167
expect(entry.json_rte[0]).toEqual(referenceObjHtml)
168168
done()
169169
})
170+
171+
it('should convert to html when asset embedded as link in json_rte', done => {
172+
const entry = {
173+
uid: 'entry_uid',
174+
rte_data: {...embeddedAssetAsLinkJsonEntry},
175+
}
176+
const paths = ["rte_data"]
177+
const result = `<p>asda<a class="embedded-entry redactor-component undefined-entry" href="https://images.contentstack.io/v3/assets/***REMOVED***/***REMOVED***/657304603ed4d5773c01feed/Screenshot_2023-03-01_at_1.09.39_PM.png" target="_self" content-type-uid="sys_assets" data-sys-asset-uid="***REMOVED***" sys-style-type="download">s<strong>das</strong></a><strong>d</strong>as</p>`
178+
jsonToHTML({ entry: entry, paths })
179+
180+
expect(entry.rte_data).toBe(result)
181+
done()
182+
})
170183
})
171184

172185
describe('Node parse text Content', () => {

__test__/mock/json-element-mock.ts

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,38 +1139,51 @@ const paragraphJsonArrayEntry = {
11391139
}
11401140

11411141
const embeddedAssetAsLinkJsonEntry = {
1142-
uid: 'entry_uid',
1143-
rte_data: {
1144-
type: 'doc',
1145-
attrs: {},
1146-
uid: 'rte_uid',
1147-
children: [
1142+
"type": "doc",
1143+
"attrs": {},
1144+
"uid": "1b212916f2784af4bcf9a0af5018364e",
1145+
"children": [
11481146
{
1149-
type: 'p',
1150-
uid: 'p_uid',
1151-
attrs: {},
1152-
children: [
1153-
{ text: '' },
1154-
{
1155-
uid: 'ref_uid',
1156-
type: 'reference',
1157-
attrs: {
1158-
'display-type': 'link',
1159-
type: 'asset',
1160-
'class-name': 'embedded-entry redactor-component undefined-entry',
1161-
'asset-uid': 'asset_uid_2',
1162-
'content-type-uid': 'sys_assets',
1163-
target: '_self',
1164-
href: 'https://picsum.photos/200'
1165-
},
1166-
children: [ { text: 'Door matching', bold: true, underline: true } ]
1167-
},
1168-
{ text: '' }
1169-
]
1147+
"type": "p",
1148+
"attrs": {},
1149+
"uid": "3f3a84966368435388b7b9948283be2e",
1150+
"children": [
1151+
{
1152+
"text": "asda"
1153+
},
1154+
{
1155+
"uid": "c2384ca128a64ee89e82b7aaab77e7b1",
1156+
"type": "reference",
1157+
"attrs": {
1158+
"display-type": "link",
1159+
"type": "asset",
1160+
"class-name": "embedded-entry redactor-component undefined-entry",
1161+
"asset-uid": "***REMOVED***",
1162+
"content-type-uid": "sys_assets",
1163+
"target": "_self",
1164+
"href": "https://images.contentstack.io/v3/assets/***REMOVED***/***REMOVED***/657304603ed4d5773c01feed/Screenshot_2023-03-01_at_1.09.39_PM.png"
1165+
},
1166+
"children": [
1167+
{
1168+
"text": "s"
1169+
},
1170+
{
1171+
"text": "das",
1172+
"bold": true
1173+
}
1174+
]
1175+
},
1176+
{
1177+
"text": "d",
1178+
"bold": true
1179+
},
1180+
{
1181+
"text": "as"
1182+
}
1183+
]
11701184
}
1171-
],
1172-
_version: 4
1173-
}
1185+
],
1186+
"_version": 1
11741187
}
11751188

11761189
const embeddedAssetJsonEntry = {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@contentstack/utils",
3-
"version": "1.3.10",
3+
"version": "1.3.11",
44
"description": "Contentstack utilities for Javascript",
55
"main": "dist/index.es.js",
66
"types": "dist/types/index.d.ts",

src/entry-editable.ts

Lines changed: 117 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,122 @@
1-
import { EntryModel } from ".";
1+
import { EntryModel } from "."
22

3-
export function addTags(entry: EntryModel, contentTypeUid: string, tagsAsObject: boolean, locale: string = 'en-us') : void {
4-
if (entry)
5-
entry.$ = getTag(entry, `${contentTypeUid}.${entry.uid}.${locale}`, tagsAsObject, locale)
6-
}
7-
8-
function getTag(content: object, prefix: string, tagsAsObject: boolean, locale: string): object {
9-
const tags: any = {}
10-
Object.entries(content).forEach(([key, value]) => {
11-
if (key === '$') return
3+
export function addTags(entry: EntryModel, contentTypeUid: string, tagsAsObject: boolean, locale: string = 'en-us') : void {
4+
if (entry) {
5+
const appliedVariants = entry._applied_variants || null;
6+
entry.$ = getTag(entry, `${contentTypeUid}.${entry.uid}.${locale}`, tagsAsObject, locale, {_applied_variants: appliedVariants, shouldApplyVariant: !!appliedVariants, metaKey: ''}) }
7+
}
8+
9+
function getTag(content: object, prefix: string, tagsAsObject: boolean, locale: string, appliedVariants: {_applied_variants:{[key: string]: any}, shouldApplyVariant: boolean, metaKey: string}): object {
10+
const tags: any = {}
11+
const { metaKey, shouldApplyVariant, _applied_variants } = appliedVariants
12+
Object.entries(content).forEach(([key, value]) => {
13+
if (key === '$') return
14+
let metaUID = value && typeof value === 'object' && value._metadata && value._metadata.uid ? value._metadata.uid : '';
15+
let updatedMetakey = appliedVariants.shouldApplyVariant ? `${appliedVariants.metaKey ? appliedVariants.metaKey + '.' : '' }${key}` : '';
16+
if(metaUID && updatedMetakey) updatedMetakey = updatedMetakey + '.' + metaUID;
17+
switch (typeof value) {
18+
case "object":
19+
if (Array.isArray(value)) {
20+
value.forEach((obj, index) => {
21+
const childKey = `${key}__${index}`
22+
const parentKey = `${key}__parent`
23+
metaUID = value && typeof value === 'object' && obj._metadata && obj._metadata.uid ? obj._metadata.uid : '';
24+
updatedMetakey = appliedVariants.shouldApplyVariant ? `${appliedVariants.metaKey ? appliedVariants.metaKey + '.' : '' }${key}` : '';
25+
if(metaUID && updatedMetakey) updatedMetakey = updatedMetakey + '.' + metaUID;
26+
/**
27+
* Indexes of array are handled here
28+
* {
29+
* "array": ["hello", "world"],
30+
* "$": {
31+
* "array": {"data-cslp": "content_type_uid.entry_uid.locale.array"}
32+
* "array__0": {"data-cslp": "content_type_uid.entry_uid.locale.array.0"}
33+
* "array__1": {"data-cslp": "content_type_uid.entry_uid.locale.array.1"}
34+
* }
35+
* }
36+
*/
37+
tags[childKey] = getTagsValue(`${prefix}.${key}.${index}`, tagsAsObject, { _applied_variants, shouldApplyVariant, metaKey: updatedMetakey })
38+
tags[parentKey] = getParentTagsValue(`${prefix}.${key}`, tagsAsObject)
39+
if (typeof obj !== 'undefined' && obj !== null && obj._content_type_uid !== undefined && obj.uid !== undefined) {
40+
/**
41+
* References are handled here
42+
* {
43+
* "reference": [{
44+
* "title": "title",
45+
* "uid": "ref_uid",
46+
* "_content_type_uid": "ref_content_type_uid",
47+
* "$": {"title": {"data-cslp": "ref_content_type_uid.ref_uid.locale.title"}}
48+
* }]
49+
* }
50+
*/
51+
const newAppliedVariants = obj._applied_variants || _applied_variants;
52+
const newShouldApplyVariant = !!newAppliedVariants
53+
value[index].$ = getTag(obj, `${obj._content_type_uid}.${obj.uid}.${obj.locale || locale}`, tagsAsObject, locale, {_applied_variants:newAppliedVariants, shouldApplyVariant:newShouldApplyVariant, metaKey: ""})
54+
}else if (typeof obj === "object") {
55+
/**
56+
* Objects inside Array like modular blocks are handled here
57+
* {
58+
* "array": [{
59+
* "title": "title",
60+
* "$": {"title": {"data-cslp": "content_type_uid.entry_uid.locale.array.0.title"}}
61+
* }]
62+
* }
63+
*/
64+
obj.$ = getTag(obj,`${prefix}.${key}.${index}`, tagsAsObject, locale, {_applied_variants, shouldApplyVariant, metaKey: updatedMetakey})
65+
}
66+
})
67+
}else {
68+
if (value) {
69+
/**
70+
* Objects are handled here
71+
* {
72+
* "object": {
73+
* "title": "title",
74+
* "$": {
75+
* "title": {"data-cslp": "content_type_uid.entry_uid.locale.object.title"}
76+
* }
77+
* },
78+
* }
79+
*/
80+
value.$ = getTag(value, `${prefix}.${key}`, tagsAsObject, locale, {_applied_variants, shouldApplyVariant, metaKey: updatedMetakey})
81+
}
82+
}
83+
/**
84+
* {
85+
* "object": {
86+
* "title": "title",
87+
* },
88+
* "array": ["hello", "world"]
89+
* "$": {
90+
* "object": {"data-cslp": "content_type_uid.entry_uid.locale.object"},
91+
* "array": {"data-cslp": "content_type_uid.entry_uid.locale.array"}
92+
* }
93+
* }
94+
*/
1295

13-
switch (typeof value) {
14-
case "object":
15-
if (Array.isArray(value)) {
16-
value.forEach((obj, index) => {
17-
const childKey = `${key}__${index}`
18-
const parentKey = `${key}__parent`
19-
/**
20-
* Indexes of array are handled here
21-
* {
22-
* "array": ["hello", "world"],
23-
* "$": {
24-
* "array": {"data-cslp": "content_type_uid.entry_uid.locale.array"}
25-
* "array__0": {"data-cslp": "content_type_uid.entry_uid.locale.array.0"}
26-
* "array__1": {"data-cslp": "content_type_uid.entry_uid.locale.array.1"}
27-
* }
28-
* }
29-
*/
30-
tags[childKey] = getTagsValue(`${prefix}.${key}.${index}`, tagsAsObject)
31-
tags[parentKey] = getParentTagsValue(`${prefix}.${key}`, tagsAsObject)
32-
if (typeof obj !== 'undefined' && obj !== null && obj._content_type_uid !== undefined && obj.uid !== undefined) {
33-
/**
34-
* References are handled here
35-
* {
36-
* "reference": [{
37-
* "title": "title",
38-
* "uid": "ref_uid",
39-
* "_content_type_uid": "ref_content_type_uid",
40-
* "$": {"title": {"data-cslp": "ref_content_type_uid.ref_uid.locale.title"}}
41-
* }]
42-
* }
43-
*/
44-
value[index].$ = getTag(obj, `${obj._content_type_uid}.${obj.uid}.${obj.locale || locale}`, tagsAsObject, locale)
45-
}else if (typeof obj === "object") {
46-
/**
47-
* Objects inside Array like modular blocks are handled here
48-
* {
49-
* "array": [{
50-
* "title": "title",
51-
* "$": {"title": {"data-cslp": "content_type_uid.entry_uid.locale.array.0.title"}}
52-
* }]
53-
* }
54-
*/
55-
obj.$ = getTag(obj,`${prefix}.${key}.${index}`, tagsAsObject, locale)
56-
}
57-
})
58-
}else {
59-
if (value) {
60-
/**
61-
* Objects are handled here
62-
* {
63-
* "object": {
64-
* "title": "title",
65-
* "$": {
66-
* "title": {"data-cslp": "content_type_uid.entry_uid.locale.object.title"}
67-
* }
68-
* },
69-
* }
70-
*/
71-
value.$ = getTag(value, `${prefix}.${key}`, tagsAsObject, locale)
72-
}
73-
}
74-
/**
75-
* {
76-
* "object": {
77-
* "title": "title",
78-
* },
79-
* "array": ["hello", "world"]
80-
* "$": {
81-
* "object": {"data-cslp": "content_type_uid.entry_uid.locale.object"},
82-
* "array": {"data-cslp": "content_type_uid.entry_uid.locale.array"}
83-
* }
84-
* }
85-
*/
86-
tags[key] = getTagsValue(`${prefix}.${key}`, tagsAsObject)
87-
break;
88-
default:
89-
/**
90-
* All primitive values are handled here
91-
* {
92-
* "title": "title",
93-
* "$": {title: {"data-cslp": "content_type_uid.entry_uid.locale.title"}}
94-
* }
95-
*/
96-
tags[key] = getTagsValue(`${prefix}.${key}`, tagsAsObject)
97-
}
98-
})
99-
return tags
100-
}
101-
102-
function getTagsValue (dataValue:string, tagsAsObject: boolean): any {
96+
tags[key] = getTagsValue(`${prefix}.${key}`, tagsAsObject, { _applied_variants, shouldApplyVariant, metaKey: updatedMetakey })
97+
break;
98+
default:
99+
/**
100+
* All primitive values are handled here
101+
* {
102+
* "title": "title",
103+
* "$": {title: {"data-cslp": "content_type_uid.entry_uid.locale.title"}}
104+
* }
105+
*/
106+
tags[key] = getTagsValue(`${prefix}.${key}`, tagsAsObject, { _applied_variants, shouldApplyVariant, metaKey: updatedMetakey })
107+
}
108+
})
109+
return tags
110+
}
111+
112+
function getTagsValue (dataValue:string, tagsAsObject: boolean, appliedVariants: {_applied_variants: {[key: string]: any}, shouldApplyVariant: boolean, metaKey: string}): any {
113+
if(appliedVariants.shouldApplyVariant && appliedVariants._applied_variants && appliedVariants._applied_variants[appliedVariants.metaKey]) {
114+
const variant = appliedVariants._applied_variants[appliedVariants.metaKey]
115+
// Adding v2 prefix to the cslp tag. New cslp tags are in v2 format. ex: v2:content_type_uid.entry_uid.locale.title
116+
const newDataValueArray = ('v2:' + dataValue).split('.');
117+
newDataValueArray[1] = newDataValueArray[1] + '_' + variant;
118+
dataValue = newDataValueArray.join('.');
119+
}
103120
if (tagsAsObject) {
104121
return { "data-cslp": dataValue };
105122
} else {

src/helper/enumerate-entries.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,18 @@ export function referenceToHTML(
7777
renderOption: RenderOption,
7878
renderEmbed?: (metadata: Metadata) => EmbeddedItem | EntryNode,
7979
): string {
80-
if (node.attrs.type === 'entry' && node.attrs['display-type'] === 'link') {
80+
if ((node.attrs.type === 'entry' || node.attrs.type === 'asset') && node.attrs['display-type'] === 'link') {
8181
const entryText = node.children ? nodeChildrenToHTML(node.children, renderOption, renderEmbed) : '';
82+
83+
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}"`;
8284
if (node.attrs.target) {
83-
return `<a${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}" target="${node.attrs.target}">${entryText}</a>`
85+
aTagAttrs +=` target="${node.attrs.target}"`;
86+
}
87+
if(node.attrs.type == 'asset') {
88+
aTagAttrs += ` type="asset" content-type-uid="sys_assets" ${node.attrs['asset-uid'] ? `data-sys-asset-uid="${node.attrs['asset-uid']}"` : ``} sys-style-type="download"`
8489
}
85-
return `<a${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}">${entryText}</a>`;
90+
const aTag = `<a${aTagAttrs}>${entryText}</a>`;
91+
return aTag;
8692
}
8793

8894
function sendToRenderOption(referenceNode: Node): string {

0 commit comments

Comments
 (0)