Skip to content

fix[deburr]: only deburr Latin letters like lodash - #2123

Merged
raon0211 merged 1 commit into
toss:mainfrom
Patrick-SCH03:fix/compat-deburr
Sep 30, 2026
Merged

raon0211 merged 1 commit into
toss:mainfrom
Patrick-SCH03:fix/compat-deburr

Conversation

@Patrick-SCH03

Copy link
Copy Markdown
Contributor

Summary

Compat deburr applies NFD normalization to the entire string, while Lodash replaces letters in U+00C0–U+017F and removes combining marks without normalizing the string. This decomposes Hangul syllables and alters Cyrillic and Vietnamese text, also affecting the six compat case-conversion functions. The following calls compile in strict mode with @types/lodash.

import { camelCase, deburr, kebabCase } from 'es-toolkit/compat';

kebabCase('한국어') === '한국어';
// lodash:           true  (3 characters)
// es-toolkit/compat: false (8 decomposed Hangul jamo, NFD)

kebabCase('Мой край');
// lodash:           'мой-край'
// es-toolkit/compat: 'мои-краи'

deburr('йогурт');
// lodash:           'йогурт'
// es-toolkit/compat: 'иогурт'

camelCase('Tiếng Việt');
// lodash:           'tiếngViệt'
// es-toolkit/compat: 'tiengViet'

Changes

  • Replace compat's delegation with a 192-entry lookup table generated once at module initialization using the existing main implementation. Leave the main es-toolkit implementation unchanged.
  • Use an ASCII fast path and a single loop to replace Latin letters and remove combining marks, without calling normalize() on each invocation.
  • Fix camelCase, kebabCase, lowerCase, snakeCase, startCase, and upperCase through their existing compat deburr imports.
  • Add regression tests in deburr.spec.ts, kebabCase.spec.ts, and camelCase.spec.ts that fail on main and pass on this branch.
  • Update the compat camelCase bundle-size snapshot from 2,161 to 2,471 bytes (+310 bytes).

Comparing all 194,560 non-surrogate code points in U+0000–U+2FFFF against Lodash found zero mismatches on this branch, down from 13,088 on main.

Unlike the NFC recomposition approach in #1905, this preserves characters whose combining marks would otherwise be removed.

Benchmark results

Measured on Windows with Node.js 22, alternating main and this branch in the same benchmark file; values are ops/sec (higher is better). Equivalent cases were run with vitest bench using direct src/compat imports because the benchmarks workspace failed with ERR_UNSUPPORTED_ESM_URL_SCHEME.

Case main This branch
deburr('déjà vu, Ærøskøbing') 1,962,075 5,777,000
deburr('hello world foo bar') (ASCII) 2,882,578 10,898,472
kebabCase('Foo Bar déjà vu') 550,893 696,225

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
es-toolkit Ready Ready Preview Sep 27, 2026 8:12am UTC

Request Review

@raon0211
raon0211 merged commit ebea440 into toss:main Sep 30, 2026
12 checks passed

This branch was successfully deployed

1 active deployment
Preview — 30505b19 Deployed Sep 27, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants