Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: contentstack/contentstack-utils-javascript
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.3.17
Choose a base ref
...
head repository: contentstack/contentstack-utils-javascript
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.3.18
Choose a head ref
  • 12 commits
  • 10 files changed
  • 5 contributors

Commits on Feb 8, 2025

  1. chore: Added support of \n after just enter (#133)

    * chore: Added support of \n after just enter
    
    * chore: Updated changelog
    sunil-lakshman authored Feb 8, 2025
    Copy the full SHA
    2e8970f View commit details

Commits on Feb 12, 2025

  1. Merge pull request #137 from contentstack/master

    back merge (master to staging)
    harshithad0703 authored Feb 12, 2025
    Copy the full SHA
    c81c13c View commit details
  2. Merge pull request #138 from contentstack/staging

    back merge (staging to development)
    harshithad0703 authored Feb 12, 2025
    Copy the full SHA
    52b7d0d View commit details
  3. Copy the full SHA
    38cca9f View commit details
  4. Copy the full SHA
    665b422 View commit details
  5. chore: update version to 1.3.18 and document html injection fix in ch…

    …angelog
    harshithad0703 committed Feb 12, 2025
    Copy the full SHA
    031e7cd View commit details
  6. Merge pull request #139 from contentstack/fix/dx-1771-html-injection-fix

    dx 1771 html injection fix
    harshithad0703 authored Feb 12, 2025
    Copy the full SHA
    53ec08e View commit details
  7. Merge pull request #140 from contentstack/development

    DX | 17-02-2025 | Release
    harshithad0703 authored Feb 12, 2025
    Copy the full SHA
    29f3ffc View commit details

Commits on Feb 13, 2025

  1. fix: update test for asset url method for gql

    nadeem-cs committed Feb 13, 2025
    Copy the full SHA
    a384722 View commit details
  2. Merge pull request #142 from contentstack/hotfix/updateAssetURLForGQL…

    …-enhancement
    
    fix: update test for asset url method for gql
    nadeem-cs authored Feb 13, 2025
    Copy the full SHA
    60e794a View commit details
  3. Merge pull request #143 from contentstack/development

    Staging | DX-2186
    harshithad0703 authored Feb 13, 2025
    Copy the full SHA
    d880132 View commit details

Commits on Feb 14, 2025

  1. Merge pull request #141 from contentstack/staging

    DX | 17-02-2025 | Hotfix
    harshithad0703 authored Feb 14, 2025
    1
    Copy the full SHA
    ca4b919 View commit details
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## [1.3.18](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.17) (2025-02-17)
- Fix: Added fix for html injection

## [1.3.17](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.3.17) (2025-02-11)
- Enh: updateAssetURLForGQL update for multilpe entries
- Fix: Added support of br tag (\n) after just enter
15 changes: 13 additions & 2 deletions __test__/json-to-html.test.ts
Original file line number Diff line number Diff line change
@@ -33,7 +33,8 @@ import {
orderListJson2,
testJsonRte,
testJsonAsset,
embeddedAssetAsLinkJsonEntry} from './mock/json-element-mock'
embeddedAssetAsLinkJsonEntry,
escapeJsonHtml } from './mock/json-element-mock'
import {
blockquoteHtml,
codeHtml,
@@ -60,7 +61,8 @@ import {
styleObjHtml,
referenceObjHtml,
referenceObjHtmlBlock,
imagetags} from './mock/json-element-mock-result'
imagetags,
escapeHtml } from './mock/json-element-mock-result'
describe('Node parser paragraph content', () => {
it('Should accept proper values', done => {
const entry = { uid: 'uid'}
@@ -122,6 +124,15 @@ describe('Node parser paragraph content', () => {
expect(entry.rich_text_editor).toEqual([paragraphHtml])
done()
})

it('Should render Json To html', done => {
const entry = {...escapeJsonHtml}

jsonToHTML({entry, paths: ['rich_text_editor']})

expect(entry.rich_text_editor).toEqual(escapeHtml)
done()
})
})


23 changes: 9 additions & 14 deletions __test__/mock/gql-asset-url-update-mock.ts
Original file line number Diff line number Diff line change
@@ -264,21 +264,13 @@ export const gqlResponseForAssetUpdateMultipleEntries = {
"title": "merry-marketplace.png",
"url": "actual_asset_url.png",
"content_type": "image/png",
"description": null,
"description": "null",
"file_size": 273858,
"filename": "merry-marketplace.png",
"permanent_url": "Permanent URL Not Defined!"
}
},
{
"node": {
"title": "Screenshot.png",
"url": "https://azure-na-images.contentstack.com/v3/assets/folder_uid/asset_uid_2/folder_uid_4/Screenshot_2024-12-09_at_7.28.28_PM.png?branch=test2",
"content_type": "image/png",
"description": "",
"file_size": 287954,
"filename": "Screenshot_2024-12-09_at_7.28.28_PM.png",
"permanent_url": "Permanent URL Not Defined!"
"permanent_url": "Permanent URL Not Defined!",
"system" : {
"uid": "asset_uid_1"
}
}
},
{
@@ -289,7 +281,10 @@ export const gqlResponseForAssetUpdateMultipleEntries = {
"description": "",
"file_size": 1050317,
"filename": "Aadhaar.pdf",
"permanent_url": "Permanent URL Not Defined!"
"permanent_url": "Permanent URL Not Defined!",
"system" : {
"uid": "asset_uid_2"
}
}
}
]
4 changes: 2 additions & 2 deletions __test__/mock/json-element-mock-result.ts
Original file line number Diff line number Diff line change
@@ -23,8 +23,8 @@ const classAndIdAttrsHtml = "<a class=\"class_a\" id=\"id_p\" href=\"LINK.com\">
const styleObjHtml = "<h1 style=\"text-align:justify;\">heading1</h1><h2 style=\"text-align:left;\">heading2</h2><h3 style=\"text-align:right;\">heading3</h3><h4 style=\"text-align:justify;\">heading4</h4><h5 style=\"text-align:justify;\">heading5</h5><h6 style=\"text-align:justify;\">heading6</h6>"
const referenceObjHtml = "<p><a class=\"embedded-entry redactor-component block-entry\" href=\"/test\" target=\"_self\">Embed entry as a link</a></p><p><a class=\"embedded-entry redactor-component block-entry\" href=\"/entry-3\" target=\"_blank\">Open entry as a link in new tab</a></p><p><a class=\"embedded-entry redactor-component block-entry\" href=\"/entry-2\" target=\"_self\">Bold entry</a></p><p><a class=\"embedded-entry redactor-component block-entry\" href=\"/entry-4\" target=\"_blank\"><strong>Bold entry open in new tab</strong></a></p>"
const referenceObjHtmlBlock = "<p><a class=\"embedded-entry redactor-component block-entry\" href=\"/Test\" target=\"_self\">Embed entry as a link</a></p><p><a class=\"embedded-entry redactor-component block-entry\" href=\"undefined\" target=\"_blank\">Embed entry as a link open in new tab</a></p><ul><li><a class=\"embedded-entry redactor-component block-entry\" href=\"undefined\" target=\"_self\">Entry as a link</a></li><li><a class=\"embedded-entry redactor-component block-entry\" href=\"undefined\" target=\"_blank\">Open entry as a link in new tab</a></li><li><a class=\"embedded-entry redactor-component block-entry\" href=\"undefined\" target=\"_self\"><strong><u>Entry as a link bold</u></strong></a></li><li><a class=\"embedded-entry redactor-component block-entry\" href=\"khjgf\" target=\"_blank\"><strong><u>Open bold entry as a link in new tab </u></strong></a></li><li><a href=\"https://\" target=\"_self\"><strong><u>Link URL</u></strong></a></li><li><a href=\"https://\" target=\"_blank\"><strong><u>Open link in new tab</u></strong></a></li></ul>"

const imagetags = "<figure style=\"text-align:right;max-width:137px;float:right;width:137px;max-height:257px;height:257px;\"><a href=\"https://batman.com\" target=\"_blank\"><img asset_uid=\"asset-UID\" class=\"embedded-asset\" src=\"https://images.contentstack.io/v3/assets/api-key/asset-UID/random-uid/batman.png\" alt=\"batman\" target=\"_blank\" style=\"text-align:right;max-width:137px;float:right;width:137px;max-height:257px;height:257px;\" /></a><figcaption>The Batman</figcaption></figure>"
const escapeHtml = "<p>&lt;p&gt;Welcome to Contentstack! &lt;script&gt;console.log(/\"Hello from Contentstack!/\");&lt;/script&gt; Explore our platform to create, manage, and publish content seamlessly.&lt;/p&gt;</p>"

export {
h1Html,
@@ -53,5 +53,5 @@ export {
referenceObjHtmlBlock,
imagetags,
paragraphHtmlWithNewLine,

escapeHtml
}
30 changes: 29 additions & 1 deletion __test__/mock/json-element-mock.ts
Original file line number Diff line number Diff line change
@@ -2394,6 +2394,33 @@ const testJsonAsset={
"_version": 22
}
}

const escapeJsonHtml = {
title: 'entry and assets',
url: '/entry-and-assets',
rich_text_editor: {
uid: "uid",
_version: 13,
attrs: {},
children: [
{
type: "p",
attrs: {},
uid: "0a1b5676aa510e5a",
children: [
{
text: '<p>Welcome to Contentstack! <script>console.log(/"Hello from Contentstack!/");</script> Explore our platform to create, manage, and publish content seamlessly.</p>'
}
]
}
],
type: "doc"
},
locale: 'en-us',
_in_progress: false,
uid: 'asset_uid_10',
}

export {
h1Json,
h2Json,
@@ -2432,5 +2459,6 @@ export {
orderListJson2,
testJsonRte,
testJsonAsset,
paragraphEntryWithNewline
paragraphEntryWithNewline,
escapeJsonHtml
}
8 changes: 4 additions & 4 deletions __test__/updateAssetURLForGQL.test.ts
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ import { gqlResponseForAssetUpdate, gqlResponseForAssetUpdateWithoutSystemUid, g

describe('updateAssetURLForGQL test', () => {

it.skip('should update the asset URL in the GQL response when proper response is passed', done => {
it('should update the asset URL in the GQL response when proper response is passed', done => {
const testResponse = { ...gqlResponseForAssetUpdate };
updateAssetURLForGQL(testResponse);

@@ -15,19 +15,19 @@ describe('updateAssetURLForGQL test', () => {
done();
});

it.skip('should update the asset URL in the GQL response when proper response is passed', done => {
it('should update the asset URL in the GQL response with multiple entries when proper response is passed', done => {
const testResponse = { ...gqlResponseForAssetUpdateMultipleEntries };
updateAssetURLForGQL(testResponse);

const rteField = testResponse.data.page_json_rte.items[0].body_new[0].body.body_12;
const assetLink = rteField.json.children[0].attrs['asset-link'];
const expectedUrl = rteField.embedded_itemsConnection.edges[0].node.url;

expect(assetLink).toBe(expectedUrl);
done();
});

it.skip('should throw error when system.uid is not present', done => {
it('should throw error when system.uid is not present', done => {
jest.spyOn(console, 'error').mockImplementation(() => {});

const testResponse = { ...gqlResponseForAssetUpdateWithoutSystemUid };
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentstack/utils",
"version": "1.3.17",
"version": "1.3.18",
"description": "Contentstack utilities for Javascript",
"main": "dist/index.es.js",
"types": "dist/types/index.d.ts",
9 changes: 8 additions & 1 deletion src/helper/enumerate-entries.ts
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ export function enumerateContents(
}

export function textNodeToHTML(node: TextNode, renderOption: RenderOption): string {
let text = node.text;
let text = escapeHtml(node.text);
if (node.classname || node.id) {
text = (renderOption[MarkType.CLASSNAME_OR_ID] as RenderMark)(text, node.classname, node.id);
}
@@ -158,3 +158,10 @@ function nodeToHTML(
}
}
}

function escapeHtml(text: string): string {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
}
35 changes: 24 additions & 11 deletions src/updateAssetURLForGQL.ts
Original file line number Diff line number Diff line change
@@ -20,21 +20,34 @@ export function updateAssetURLForGQL(gqlResponse:any) {
function processEntry(entry:any) {
for (let field in entry) {
const fieldData = entry[field];
const rteField = findRTEField(fieldData)
const edges = rteField?.embedded_itemsConnection?.edges;
edges.forEach((edge:any) => {
const node = edge.node;
if (node?.url && node?.filename) {

if (!node?.system?.uid) throw new Error('Asset UID not found in the response');

const correspondingAsset = rteField?.json?.children?.find((child:any) => child.attrs['asset-uid'] === node.system.uid);
correspondingAsset.attrs['asset-link'] = node.url;
}
if (fieldData instanceof Array) {
fieldData.forEach((data:any) => {
findRTEFieldAndUpdateURL(data);
});
} else if (fieldData && typeof fieldData === 'object') {
findRTEFieldAndUpdateURL(fieldData);
}
}
}

function findRTEFieldAndUpdateURL(fieldData:any) {
const rteField = findRTEField(fieldData);

if (!rteField) return;

const edges = rteField?.embedded_itemsConnection?.edges;
edges.forEach((edge:any) => {
const node = edge.node;
if (node?.url && node?.filename) {

if (!node?.system?.uid) throw new Error('Asset UID not found in the response');

const correspondingAsset = rteField?.json?.children?.find((child:any) => child.attrs['asset-uid'] === node.system.uid);
correspondingAsset.attrs['asset-link'] = node.url;
}
});
}

function findRTEField(fieldData: any): any {
if (fieldData && fieldData.embedded_itemsConnection) {
return fieldData;