diff --git a/src/pages/list/group/group.service.test.ts b/src/pages/list/group/group.service.test.ts new file mode 100644 index 0000000..18b0604 --- /dev/null +++ b/src/pages/list/group/group.service.test.ts @@ -0,0 +1,99 @@ +import { expect, describe, it } from 'vitest'; + +import { groupList, SplitOperatorType } from './service'; + +describe('groupList', () => { + it('splits by symbol, groups, pads, and formats correctly', () => { + const input = "a,b,c,d,e,f,g,h,i,j"; + const splitOperatorType: SplitOperatorType = 'symbol'; + const splitSeparator = ','; + const groupNumber = 3; + const itemSeparator = '-'; + const leftWrap = '['; + const rightWrap = ']'; + const groupSeparator = ' | '; + const deleteEmptyItems = false; + const padNonFullGroup = true; + const paddingChar = 'x'; + + const expectedOutput = "[a-b-c] | [d-e-f] | [g-h-i] | [j-x-x]"; + + const result = groupList( + splitOperatorType, + splitSeparator, + input, + groupNumber, + itemSeparator, + leftWrap, + rightWrap, + groupSeparator, + deleteEmptyItems, + padNonFullGroup, + paddingChar + ); + + expect(result).toBe(expectedOutput); + }); + + it('handles regex split, no padding, and formats correctly', () => { + const input = "a1b2c3d4e5f6g7h8i9j"; + const splitOperatorType: SplitOperatorType = 'regex'; + const splitSeparator = '\\d'; + const groupNumber = 4; + const itemSeparator = ','; + const leftWrap = '('; + const rightWrap = ')'; + const groupSeparator = ' / '; + const deleteEmptyItems = true; + const padNonFullGroup = false; + + const expectedOutput = "(a,b,c,d) / (e,f,g,h) / (i,j)"; + + const result = groupList( + splitOperatorType, + splitSeparator, + input, + groupNumber, + itemSeparator, + leftWrap, + rightWrap, + groupSeparator, + deleteEmptyItems, + padNonFullGroup + ); + + expect(result).toBe(expectedOutput); + }); + + it('handles empty items removal and padd the last group with a z', () => { + const input = "a,,b,,c,,d,,e,,"; + const splitOperatorType: SplitOperatorType = 'symbol'; + const splitSeparator = ','; + const groupNumber = 2; + const itemSeparator = ':'; + const leftWrap = '<'; + const rightWrap = '>'; + const groupSeparator = ' & '; + const deleteEmptyItems = true; + const padNonFullGroup = true; + const paddingChar = 'z'; + + const expectedOutput = " & & "; + + const result = groupList( + splitOperatorType, + splitSeparator, + input, + groupNumber, + itemSeparator, + leftWrap, + rightWrap, + groupSeparator, + deleteEmptyItems, + padNonFullGroup, + paddingChar + ); + + expect(result).toBe(expectedOutput); + }); +}); \ No newline at end of file diff --git a/src/pages/list/group/index.tsx b/src/pages/list/group/index.tsx new file mode 100644 index 0000000..3134478 --- /dev/null +++ b/src/pages/list/group/index.tsx @@ -0,0 +1,11 @@ +import { Box } from '@mui/material'; +import React from 'react'; +import * as Yup from 'yup'; + +const initialValues = {}; +const validationSchema = Yup.object({ + // splitSeparator: Yup.string().required('The separator is required') +}); +export default function Group() { + return Lorem ipsum; +} \ No newline at end of file diff --git a/src/pages/list/group/meta.ts b/src/pages/list/group/meta.ts new file mode 100644 index 0000000..70d482e --- /dev/null +++ b/src/pages/list/group/meta.ts @@ -0,0 +1,13 @@ +import { defineTool } from '@tools/defineTool'; +import { lazy } from 'react'; +// import image from '@assets/text.png'; + +export const tool = defineTool('list', { + name: 'Group', + path: 'group', + // image, + description: '', + shortDescription: '', + keywords: ['group'], + component: lazy(() => import('./index')) +}); \ No newline at end of file diff --git a/src/pages/list/group/service.ts b/src/pages/list/group/service.ts new file mode 100644 index 0000000..245a564 --- /dev/null +++ b/src/pages/list/group/service.ts @@ -0,0 +1,92 @@ +export type SplitOperatorType = 'symbol' | 'regex'; + + +// function that split the array into an array of subarray of desired length +function groupMaker( + array: string[], + groupNumber: number, +): string[][] { + const result: string[][] = []; + for (let i = 0; i < array.length; i += groupNumber) { + result.push(array.slice(i, i + groupNumber)); + } + return result; +} + +// function use to handle the case paddingNonFullGroup is enable +function groupFiller( + array: string[][], + groupNumber: number, + padNonFullGroup: boolean, + paddingChar: string = '', +): string[][] { + if (padNonFullGroup) { + const lastSubArray: string[] = array[array.length - 1]; + if (lastSubArray.length < groupNumber) { + for (let i = lastSubArray.length; i < groupNumber; i++) { + lastSubArray.push(paddingChar); + } + } + array[array.length - 1] = lastSubArray; + } + return array; + +} + +// function that join with the item separator and wrap with left and right each subArray of the Array +function groupJoinerAndWrapper( + array: string[][], + itemSeparator: string = '', + leftWrap: string = '', + rightWrap: string = '', +): string[] { + return array.map(subArray => { + return leftWrap + subArray.join(itemSeparator) + rightWrap; + }); +} + + +export function groupList( + splitOperatorType: SplitOperatorType, + splitSeparator: string, + input: string, + groupNumber: number, + itemSeparator: string = '', + leftWrap: string = '', + rightWrap: string = '', + groupSeparator: string, + deleteEmptyItems: boolean, + padNonFullGroup: boolean, + paddingChar: string = '', + +): string { + let array: string[]; + let splitedArray: string[][]; + let fullSplitedArray: string[][]; + let result: string[]; + switch (splitOperatorType) { + case 'symbol': + array = input.split(splitSeparator); + break; + case 'regex': + array = input.split(new RegExp(splitSeparator)); + break; + } + // delete empty items after intial split + if (deleteEmptyItems) { + array = array.filter(item => item !== ''); + } + + // split the input into an array of subArray with the desired length + splitedArray = groupMaker(array, groupNumber); + + // fill the last subArray is PadNonFullGroup is enabled + fullSplitedArray = groupFiller(splitedArray, groupNumber, padNonFullGroup, paddingChar); + + // get the list of formated subArray with the item separator and left and right wrapper + result = groupJoinerAndWrapper(fullSplitedArray, itemSeparator, leftWrap, rightWrap); + + // finnaly join the group separator before returning + return result.join(groupSeparator); +} + diff --git a/src/pages/list/index.ts b/src/pages/list/index.ts index a98cbb6..d265dd7 100644 --- a/src/pages/list/index.ts +++ b/src/pages/list/index.ts @@ -1,3 +1,4 @@ +import { tool as listGroup } from './group/meta'; import { tool as listWrap } from './wrap/meta'; import { tool as listRotate } from './rotate/meta'; import { tool as listTruncate } from './truncate/meta';