Skip to content

Commit

Permalink
Adding pascalCase transform to be used by brand (#1036)
Browse files Browse the repository at this point in the history
* adding pascalCase

* added changeset

* extracting function
  • Loading branch information
lukasoppermann authored Aug 29, 2024
1 parent 4ce3bcf commit 56ba227
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changeset/dry-walls-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/primitives': minor
---

Adding a pascalCase trasnformer
55 changes: 55 additions & 0 deletions src/transformers/namePathToPascalCase.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {getMockToken} from '../test-utilities'
import {namePathToPascalCase} from './namePathToPascalCase'

describe('Transformer: namePathToPascalCase', () => {
it('converts path elements to dot.notation and ignores name proprty', () => {
const input = [
getMockToken({
name: 'tokenName',
path: ['path', 'to', 'token'],
}),
getMockToken({
name: 'tokenName',
path: ['PATH', 'tO', 'Token'],
}),
getMockToken({
name: 'tokenName',
path: ['path', 'toToken'],
}),
getMockToken({
name: 'tokenName',
path: ['pathtoToken'],
}),
]
const expectedOutput = ['PathToToken', 'PATHTOToken', 'PathToToken', 'PathtoToken']

expect(input.map(item => namePathToPascalCase.transformer(item, {}))).toStrictEqual(expectedOutput)
})

it('removes `@`, so we can use it for the default hack', () => {
const input = [
getMockToken({
name: 'tokenName',
path: ['fgColor', 'accent', '@'],
}),
getMockToken({
name: 'tokenName',
path: ['fgColor', '@', 'muted'],
}),
]
const expectedOutput = ['FgColorAccent', 'FgColorMuted']
expect(input.map(item => namePathToPascalCase.transformer(item, {}))).toStrictEqual(expectedOutput)
})

it('adds prefix to token name', () => {
const platform = {
prefix: 'PRIMER',
}
const input = getMockToken({
name: 'tokenName',
path: ['start', 'pathTo', 'token'],
})
const expectedOutput = 'PRIMERStartPathToToken'
expect(namePathToPascalCase.transformer(input, platform)).toStrictEqual(expectedOutput)
})
})
13 changes: 13 additions & 0 deletions src/transformers/namePathToPascalCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type StyleDictionary from 'style-dictionary'
import {toPascalCase} from '../utilities/toPascalCase'
/**
* @description converts the [TransformedToken's](https://github.com/amzn/style-dictionary/blob/main/types/TransformedToken.d.ts) `.path` array to a PascalCase string, preserves casing of parts
* @type name transformer — [StyleDictionary.NameTransform](https://github.com/amzn/style-dictionary/blob/main/types/Transform.d.ts)
* @matcher omitted to match all tokens
* @transformer returns `string` PascalCase
*/
export const namePathToPascalCase: StyleDictionary.Transform = {
type: `name`,
transformer: (token: StyleDictionary.TransformedToken, options?: StyleDictionary.Platform): string =>
toPascalCase([options?.prefix || '', ...token.path]),
}
25 changes: 25 additions & 0 deletions src/utilities/filterStringArray.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {filterStringArray} from './filterStringArray'

describe('Utilities: filterStringArray', () => {
it('keeps words', () => {
expect(filterStringArray(['primer', 'test'])).toStrictEqual(['primer', 'test'])
})

it('it filters out undefined, etc.', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
expect(filterStringArray(['primer', false, null, undefined, ''])).toStrictEqual(['primer'])
})

it('remove special chars', () => {
expect(filterStringArray(['primer@test', 'Y_e-s', 'with space'])).toStrictEqual([
'primer',
'test',
'Y',
'e',
's',
'with',
'space',
])
})
})
14 changes: 14 additions & 0 deletions src/utilities/filterStringArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const filterStringArray = (string: string[]): string[] => {
// match unsupported characters
const regex = /[^a-zA-Z0-9]+/g
// replace any non-letter and non-number character and split into word array
const stringArray = string
.filter(Boolean)
.join(' ')
.replace(regex, ' ')
.split(' ')
// remove undefined if exists
.filter((part: unknown): part is string => Boolean(part) && typeof part === 'string')

return stringArray
}
15 changes: 3 additions & 12 deletions src/utilities/toCamelCase.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
import {filterStringArray} from './filterStringArray'
import {upperCaseFirstCharacter} from './upperCaseFirstCharacter'

export const toCamelCase = (string: string | string[]) => {
if (!Array.isArray(string)) {
string = [string]
}
// match unsupported characters
const regex = /[^a-zA-Z0-9]+/g
// replace any non-letter and non-number character and split into word array
const stringArray = string
.filter(part => part !== '@')
.filter(Boolean)
.join(' ')
.replace(regex, ' ')
.split(' ')

return (
stringArray
// remove undefined if exists
.filter((part: unknown): part is string => typeof part === 'string')
filterStringArray(string)
// ucFirst all but first part
.map((part: string, index: number) => {
if (index > 0) {
Expand Down
27 changes: 27 additions & 0 deletions src/utilities/toPascalCase.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {toPascalCase} from './toPascalCase'

describe('Utilities: toPascalCase', () => {
it('it transforms all lowercase word', () => {
expect(toPascalCase('primer')).toStrictEqual('Primer')
})

it('it transforms all lowercase sentence (words with spaces)', () => {
expect(toPascalCase('primer design token')).toStrictEqual('PrimerDesignToken')
})

it('it transforms all words with special chars', () => {
expect(toPascalCase('primer_design-token+edition')).toStrictEqual('PrimerDesignTokenEdition')
})

it('it preserves casing for words that are already all uppercased', () => {
expect(toPascalCase('PRIMER')).toStrictEqual('PRIMER')
})

it('it transforms all camelCase word', () => {
expect(toPascalCase('camelCase')).toStrictEqual('CamelCase')
})

it('it transforms array of words', () => {
expect(toPascalCase(['primer', 'design', 'token'])).toStrictEqual('PrimerDesignToken')
})
})
17 changes: 17 additions & 0 deletions src/utilities/toPascalCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {filterStringArray} from './filterStringArray'
import {upperCaseFirstCharacter} from './upperCaseFirstCharacter'

export const toPascalCase = (string: string | string[]) => {
if (!Array.isArray(string)) {
string = [string]
}

return (
filterStringArray(string)
// ucFirst all but first part
.map((part: string) => {
return upperCaseFirstCharacter(part)
})
.join('')
)
}

0 comments on commit 56ba227

Please sign in to comment.