Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changelog/20260522160634_ck_9933.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
type: Feature
---

Added `mapObjectKeys` for transforming object keys and `kebabToCamelCase` for converting strings from kebab-case to camelCase, along with their unit tests.
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export { filterObjectValues } from './utils/filterObjectValues.js';
export { filterBlankObjectValues } from './utils/filterBlankObjectValues.js';
export { mapObjectValues } from './utils/mapObjectValues.js';
export { without } from './utils/without.js';
export { mapObjectKeys } from './utils/mapObjectKeys.js';
export { kebabToCamelCase } from './utils/kebabToCamelCase.js';
export { isSemanticVersion, type SemanticVersion } from './utils/version/isSemanticVersion.js';
export { compareSemanticVersions, type VersionCompareResult } from './utils/version/compareSemanticVersions.js';
export { destructureSemanticVersion, type DestructuredSemanticVersion } from './utils/version/destructureSemanticVersion.js';
Expand Down
13 changes: 13 additions & 0 deletions src/utils/kebabToCamelCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/

/**
* Converts a kebab-case string to camelCase.
* @param str - The kebab-case string (e.g., "font-size").
* @returns The camelCase string (e.g., "fontSize").
*/
export function kebabToCamelCase( str: string ): string {
return str.replace( /-([a-z])/g, ( match: string, letter: string ) => letter.toUpperCase() );
Comment thread
Mati365 marked this conversation as resolved.
}
21 changes: 21 additions & 0 deletions src/utils/mapObjectKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/

/**
* Creates a new object with keys mapped using the provided function.
* @param obj - The input object.
* @param fn - The mapping function (takes the original key, returns the new one).
* @returns A new object with the mapped keys.
*/
export function mapObjectKeys<T>(
Comment thread
Mati365 marked this conversation as resolved.
obj: Record<string, T>,
fn: ( key: string ) => string
): Record<string, T> {
return Object.keys( obj ).reduce( ( acc: Record<string, T>, key: string ) => {
const newKey = fn( key );
acc[ newKey ] = obj[ key ];
return acc;
}, Object.create( null ) );
}
22 changes: 22 additions & 0 deletions tests/utils/kebabToCamelCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/

import { describe, it, expect } from 'vitest';
import { kebabToCamelCase } from '../../src/utils/kebabToCamelCase.js';

describe( 'kebabToCamelCase', () => {
it( 'should convert "font-size" to "fontSize"', () => {
expect( kebabToCamelCase( 'font-size' ) ).toBe( 'fontSize' );
} );

it( 'should convert properties with multiple dashes', () => {
expect( kebabToCamelCase( 'border-bottom-width' ) ).toBe( 'borderBottomWidth' );
} );

it( 'should not change words without dashes', () => {
expect( kebabToCamelCase( 'color' ) ).toBe( 'color' );
expect( kebabToCamelCase( 'margin' ) ).toBe( 'margin' );
} );
} );
44 changes: 44 additions & 0 deletions tests/utils/mapObjectKeys.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
*/

import { describe, it, expect } from 'vitest';
import { mapObjectKeys } from '../../src/utils/mapObjectKeys.js';

describe( 'mapObjectKeys', () => {
it( 'should correctly map keys using a simple uppercase function', () => {
const obj: Record<string, number> = { a: 1, b: 2 };
const result = mapObjectKeys( obj, function( key: string ) {
return key.toUpperCase();
} );

expect( result ).toEqual( { A: 1, B: 2 } );
} );

it( 'should add a prefix to all keys in the object', () => {
const data: Record<string, string> = {
name: 'Alice',
role: 'Admin'
};

const prefixedData = mapObjectKeys( data, function( key: string ) {
return 'user_' + key;
} );

expect( prefixedData ).toEqual( {
user_name: 'Alice',
user_role: 'Admin'
} );
} );

it( 'should not mutate the original object', () => {
const obj: Record<string, string> = { originalKey: 'value' };

mapObjectKeys( obj, function( key: string ) {
return 'new_' + key;
} );

expect( obj ).toEqual( { originalKey: 'value' } );
} );
} );