From 425ece09678c30c53fc3033fc274caf5d979e23f Mon Sep 17 00:00:00 2001 From: "harshitha.d" Date: Tue, 14 Oct 2025 12:29:18 +0530 Subject: [PATCH 1/3] fix: handle null and undefined values in get tag function --- src/entry-editable.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/entry-editable.ts b/src/entry-editable.ts index 5cf9bd1..06f833e 100644 --- a/src/entry-editable.ts +++ b/src/entry-editable.ts @@ -29,6 +29,9 @@ function getTag(content: object, prefix: string, tagsAsObject: boolean, locale: case "object": if (Array.isArray(value)) { value.forEach((obj, index) => { + if (obj === null || obj === undefined) { + return; + } const childKey = `${key}__${index}` const parentKey = `${key}__parent` metaUID = value && typeof value === 'object' && obj !== null && obj._metadata && obj._metadata.uid ? obj._metadata.uid : ''; From 870d1bf97228ac73edac3e093abc3646b1b30299 Mon Sep 17 00:00:00 2001 From: "harshitha.d" Date: Tue, 14 Oct 2025 12:37:59 +0530 Subject: [PATCH 2/3] chore: release version 1.4.5 --- CHANGELOG.md | 6 ++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96ffa4d..4f79625 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.4.5](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.4.5) (2025-10-23) + - handle null and undefined values in getTag function + +## [1.4.4](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.4.4) (2025-09-24) + -Enhance break and newline handling, update dependencies + ## [1.4.3](https://github.com/contentstack/contentstack-utils-javascript/tree/v1.4.3) (2025-09-22) - Fix data-cslp generation logic in case of applied_variants diff --git a/package-lock.json b/package-lock.json index c4c2d75..9a194cf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/utils", - "version": "1.4.4", + "version": "1.4.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/utils", - "version": "1.4.4", + "version": "1.4.5", "license": "MIT", "devDependencies": { "@commitlint/cli": "^17.8.1", diff --git a/package.json b/package.json index 15f0031..ce31428 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/utils", - "version": "1.4.4", + "version": "1.4.5", "description": "Contentstack utilities for Javascript", "main": "dist/index.es.js", "types": "dist/types/index.d.ts", From 50e560091cc3165a2ec6360379436d33629dd278 Mon Sep 17 00:00:00 2001 From: "harshitha.d" Date: Tue, 14 Oct 2025 12:49:52 +0530 Subject: [PATCH 3/3] test: add test cases --- __test__/entry-editable.test.ts | 104 ++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/__test__/entry-editable.test.ts b/__test__/entry-editable.test.ts index 39d72e4..dc6fdc7 100644 --- a/__test__/entry-editable.test.ts +++ b/__test__/entry-editable.test.ts @@ -232,6 +232,110 @@ describe('Entry editable test', () => { done() }) + it('Entry with array containing null values should skip null elements', done => { + const entryWithNullInArray = { + "locale": "en-us", + "uid": "uid", + "items": [ + null, + { "title": "valid item" }, + null + ] + } + + expect(() => addTags(entryWithNullInArray, 'content_type', false)).not.toThrow() + expect((entryWithNullInArray as any)['items'][1]['$']['title']).toEqual('data-cslp=content_type.uid.en-us.items.1.title') + + done() + }) + + it('Entry with array containing undefined values should skip undefined elements', done => { + const entryWithUndefinedInArray = { + "locale": "en-us", + "uid": "uid", + "items": [ + undefined, + { "title": "valid item" }, + undefined + ] + } + + expect(() => addTags(entryWithUndefinedInArray, 'content_type', false)).not.toThrow() + expect((entryWithUndefinedInArray as any)['items'][1]['$']['title']).toEqual('data-cslp=content_type.uid.en-us.items.1.title') + + done() + }) + + it('Entry with array containing mixed null and undefined values should skip both', done => { + const entryWithMixedNullUndefined = { + "locale": "en-us", + "uid": "uid", + "items": [ + null, + undefined, + { "title": "valid item 1" }, + null, + { "title": "valid item 2" }, + undefined + ] + } + + expect(() => addTags(entryWithMixedNullUndefined, 'content_type', true)).not.toThrow() + expect((entryWithMixedNullUndefined as any)['items'][2]['$']['title']).toEqual({'data-cslp': 'content_type.uid.en-us.items.2.title'}) + expect((entryWithMixedNullUndefined as any)['items'][4]['$']['title']).toEqual({'data-cslp': 'content_type.uid.en-us.items.4.title'}) + + done() + }) + + it('Entry with _embedded_items containing null values should handle gracefully', done => { + const entryWithEmbeddedNull: any = { + "locale": "en-us", + "uid": "uid", + "blocks": [ + { + "items": [ + { "heading": "Item heading" } + ] + } + ], + "_embedded_items": { + "blocks.items.description": [null] + } + } + + expect(() => addTags(entryWithEmbeddedNull, 'content_type', false)).not.toThrow() + expect((entryWithEmbeddedNull as any)['blocks'][0]['items'][0]['$']['heading']).toEqual('data-cslp=content_type.uid.en-us.blocks.0.items.0.heading') + expect((entryWithEmbeddedNull as any)['_embedded_items']['blocks.items.description'][0]).toBeNull() + + done() + }) + + it('Entry with nested arrays containing nulls in complex structure should work', done => { + const entryWithComplexNulls: any = { + "locale": "en-us", + "uid": "uid", + "blocks": [ + { + "hero": { + "title": "Hero title", + "items": [null, { "name": "Item name" }, undefined] + } + }, + null, + { + "content": "Content text" + } + ] + } + + expect(() => addTags(entryWithComplexNulls, 'content_type', true)).not.toThrow() + expect((entryWithComplexNulls as any)['blocks'][0]['hero']['$']['title']).toEqual({'data-cslp': 'content_type.uid.en-us.blocks.0.hero.title'}) + expect((entryWithComplexNulls as any)['blocks'][0]['hero']['items'][1]['$']['name']).toEqual({'data-cslp': 'content_type.uid.en-us.blocks.0.hero.items.1.name'}) + expect((entryWithComplexNulls as any)['blocks'][2]['$']['content']).toEqual({'data-cslp': 'content_type.uid.en-us.blocks.2.content'}) + + done() + }) + it('Variant path sorting should work correctly for nested paths', done => { const entryWithComplexVariants = { "_version": 10,