Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance by removing map/filter/join methods in hot path (failed) #20

Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 2 additions & 2 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ change-title-escapes: '\<*_&'
no-changes-template: 'No changes'
categories:
- title: '⚠️ Needs Changelog Edit'
label: 'needs-changelog-edit'
label: 'needs changelog edit'
- title: 'Breaking Changes'
label: 'breaking'
- title: 'Features'
Expand All @@ -18,7 +18,7 @@ categories:
- title: 'Other'
label: 'other'
exclude-labels:
- 'skip-changelog'
- 'skip changelog'
version-resolver:
major:
labels:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
!/.yarn/sdks/
!/.yarn/versions/
/dist/
/node_modules/
node_modules/
.DS_Store
*.local
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,20 @@ twMerge('p-5 p-2 my-non-tailwind-class p-4') // → 'my-non-tailwind-class p-4'
twMerge('text-red text-secret-sauce') // → 'text-secret-sauce'
```

### Ignores `undefined` and `null` values

```ts
twMerge('some-class', undefined, null) // → 'some-class'
```

## API reference

Reference to all exports of tailwind-merge.

### `twMerge`

```ts
function twMerge(...classLists: Array<string | undefined>): string
function twMerge(...classLists: Array<string | undefined | null>): string
```

Default function to use if you're using the default Tailwind config or are close enough to the default config. You can use this function if all of the following points apply to your Tailwind config:
Expand Down
14 changes: 7 additions & 7 deletions src/tailwind-merge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Config } from './types'
import { mergeClassList } from './merge-classlist'

type CreateConfig = (getDefault: typeof getDefaultConfig) => Config
type ClassLists = Array<string | undefined>
type ClassLists = ClassListElement[]
type ClassListElement = string | undefined | null
type TailwindMerge = (...classLists: ClassLists) => string
type ConfigUtils = ReturnType<typeof createConfigUtils>

Expand All @@ -14,17 +15,16 @@ export function createTailwindMerge(createConfig: CreateConfig): TailwindMerge {
let cacheSet: ConfigUtils['cache']['set']
let functionToCall = initTailwindMerge

function initTailwindMerge(classLists: ClassLists) {
function initTailwindMerge(classList: string) {
configUtils = createConfigUtils(createConfig(getDefaultConfig))
cacheGet = configUtils.cache.get
cacheSet = configUtils.cache.set
functionToCall = tailwindMerge

return tailwindMerge(classLists)
return tailwindMerge(classList)
}

function tailwindMerge(classLists: ClassLists) {
const classList = classLists.filter(Boolean).join(' ')
function tailwindMerge(classList: string) {
const cachedResult = cacheGet(classList)

if (cachedResult) {
Expand All @@ -37,7 +37,7 @@ export function createTailwindMerge(createConfig: CreateConfig): TailwindMerge {
return result
}

return function callTailwindMerge(...classLists) {
return functionToCall(classLists)
return function callTailwindMerge(...classLists: ClassLists) {
return functionToCall(classLists.join(' '))
}
}
6 changes: 2 additions & 4 deletions tests/public-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test('twMerge() has correct inputs and outputs', () => {
expect.any(String)
)
expect(twMerge('hello world', undefined)).toStrictEqual(expect.any(String))
expect(twMerge('hello world', undefined, null)).toStrictEqual(expect.any(String))

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const noRun = () => {
Expand All @@ -22,8 +23,6 @@ test('twMerge() has correct inputs and outputs', () => {
// @ts-expect-error
twMerge(123)
// @ts-expect-error
twMerge(null)
// @ts-expect-error
twMerge(true)
// @ts-expect-error
twMerge({})
Expand Down Expand Up @@ -68,6 +67,7 @@ test('createTailwindMerge() has correct inputs and outputs', () => {
expect.any(String)
)
expect(tailwindMerge('hello world', undefined)).toStrictEqual(expect.any(String))
expect(tailwindMerge('hello world', undefined, null)).toStrictEqual(expect.any(String))

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const noRun = () => {
Expand All @@ -76,8 +76,6 @@ test('createTailwindMerge() has correct inputs and outputs', () => {
// @ts-expect-error
tailwindMerge(123)
// @ts-expect-error
tailwindMerge(null)
// @ts-expect-error
tailwindMerge(true)
// @ts-expect-error
tailwindMerge({})
Expand Down
2 changes: 1 addition & 1 deletion tests/readme-examples.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const twMergeExampleRegex =
/twMerge\((?<arguments>[\w\s\-:[\]#(),!\n'"]+?)\)(?!.*(?<!\/\/.*)')\s*\n?\s*\/\/\s*→\s*['"](?<result>.+)['"]/g

test('readme examples', () => {
expect.assertions(16)
expect.assertions(17)

return fs.promises
.readFile(`${__dirname}/../README.md`, { encoding: 'utf-8' })
Expand Down