Skip to content

Commit 9cea2b8

Browse files
committed
feat: improve performance and reduce package size, plus added a latin only mode
1 parent 70967a6 commit 9cea2b8

134 files changed

Lines changed: 735 additions & 76 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,56 @@
11
# Changelog
22

3+
## 2.5.0
4+
5+
- **Performance**: Switched to 2D array lookup for ~26% faster transliteration
6+
- **New Feature**: Added Latin-only build (`transliteration/latin`) for minimal bundle size (~5 KB vs ~186 KB)
7+
- **Optimization**: Korean Hangul characters now computed algorithmically at runtime (saves 11,172 entries)
8+
- **Internal**: Refactored charmap data structure into chunked files for better tree-shaking
9+
310
## 2.4.0
411

5-
- Modernized toolchain: migrated from Rollup/Babel to tsup/Bun for faster builds
6-
- Added comprehensive test suites with 100% code coverage
7-
- Fixed slugify to collapse consecutive separators (e.g., `hello---world``hello-world`)
8-
- Fixed slugify to properly strip leading/trailing separators
9-
- Replaced TSLint/Prettier with Biome for linting
10-
- Minimum Node.js requirement is now v20.0.0
11-
- Refactored utilities and added edge case handling
12-
- Added Vitest as modern test runner with jsdom environment for browser tests
12+
- **Tooling**: Migrated from Rollup/Babel to tsup/Bun for faster builds
13+
- **Testing**: Added comprehensive test suites with 100% code coverage
14+
- **Fix**: Slugify now collapses consecutive separators (e.g., `hello---world``hello-world`)
15+
- **Fix**: Slugify now properly strips leading/trailing separators
16+
- **Tooling**: Replaced TSLint/Prettier with Biome for linting
17+
- **Breaking**: Minimum Node.js requirement is now v20.0.0
18+
- **Internal**: Refactored utilities and added edge case handling
19+
- **Testing**: Added Vitest as modern test runner with jsdom environment for browser tests
1320

1421
## 2.2.0
1522

16-
- Fixed data issue (#229)
17-
- Added `fixChineseSpacing` option for improving performance with non-Chinese languages
18-
- Fixed replace-related issues (#202)
19-
- Updated dependencies
23+
- **Fix**: Fixed data issue (#229)
24+
- **New Feature**: Added `fixChineseSpacing` option for improving performance with non-Chinese languages
25+
- **Fix**: Fixed replace-related issues (#202)
26+
- **Internal**: Updated dependencies
2027

2128
## 2.1.0
2229

23-
- Added `transliterate` as a global variable for browser builds (kept `transl` for backward compatibility)
30+
- **New Feature**: Added `transliterate` as a global variable for browser builds (kept `transl` for backward compatibility)
2431

2532
## 2.0.0
2633

2734
- **Breaking**: CDN file structure changed — see [jsDelivr](https://www.jsdelivr.com/package/npm/transliteration)
28-
- Refactored entire module in TypeScript with significant performance improvements and reduced package size
29-
- Improved code quality with 100% unit test coverage
30-
- Dropped `bower` support — use CDN or bundlers like webpack/rollup instead
31-
- Per RFC 3986, more characters (`a-zA-Z0-9-_.~`) are now allowed in `slugify` output (configurable)
32-
- Added `uppercase` option for `slugify` to convert output to uppercase
33-
- Unknown characters are now transliterated as empty string by default (previously `[?]`)
35+
- **Performance**: Refactored entire module in TypeScript with significant performance improvements and reduced package size
36+
- **Testing**: Improved code quality with 100% unit test coverage
37+
- **Breaking**: Dropped `bower` support — use CDN or bundlers like webpack/rollup instead
38+
- **New Feature**: Per RFC 3986, more characters (`a-zA-Z0-9-_.~`) are now allowed in `slugify` output (configurable)
39+
- **New Feature**: Added `uppercase` option for `slugify` to convert output to uppercase
40+
- **Breaking**: Unknown characters are now transliterated as empty string by default (previously `[?]`)
3441

3542
## 1.6.6
3643

37-
- Added TypeScript support (#77)
44+
- **New Feature**: Added TypeScript support (#77)
3845

3946
## 1.5.0
4047

41-
- Minimum Node.js requirement: v6.0+
48+
- **Breaking**: Minimum Node.js requirement: v6.0+
4249

4350
## 1.0.0
4451

4552
- **Breaking**: Entire codebase refactored — upgrade carefully from v0.1.x or v0.2.x
46-
- The `options` parameter of `transliterate` is now an object (previously a string for `unknown`)
47-
- Added `transliterate.config()` and `slugify.config()` methods
48-
- Unknown characters are now transliterated as `[?]` instead of `?`
49-
- Browser global variables changed to `window.transl` and `window.slugify` (other globals removed)
53+
- **Breaking**: The `options` parameter of `transliterate` is now an object (previously a string for `unknown`)
54+
- **New Feature**: Added `transliterate.config()` and `slugify.config()` methods
55+
- **Breaking**: Unknown characters are now transliterated as `[?]` instead of `?`
56+
- **Breaking**: Browser global variables changed to `window.transl` and `window.slugify` (other globals removed)

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ A universal Unicode to Latin transliteration and slug generation library. Design
2222
- [transliterate()](#transliteratestr-options)
2323
- [slugify()](#slugifystr-options)
2424
- [CLI](#cli-usage)
25+
- [Latin-Only Mode](#latin-only-mode)
2526
- [Known Issues](#known-issues)
2627
- [License](#license)
2728

@@ -267,6 +268,27 @@ Examples:
267268
slugify "你好,世界!" -i 你好 -i ,
268269
```
269270

271+
## Latin-Only Mode
272+
273+
For applications that only need to transliterate Latin-based scripts (Western European languages), you can use the lightweight Latin-only build for significantly smaller bundle size:
274+
275+
```javascript
276+
// Full build: ~186 KB (all scripts including CJK, Korean, etc.)
277+
import { transliterate, slugify } from 'transliteration';
278+
279+
// Latin-only build: ~5 KB (Basic Latin + Latin Extended only)
280+
import { transliterate, slugify } from 'transliteration/latin';
281+
```
282+
283+
The Latin-only build supports:
284+
285+
- Basic ASCII (U+0000-U+007F)
286+
- Latin-1 Supplement (U+0080-U+00FF)
287+
- Latin Extended-A (U+0100-U+017F)
288+
- Latin Extended-B (U+0180-U+024F)
289+
290+
This is ideal for applications that only handle Western European languages and want to minimize bundle size.
291+
270292
## Known Issues
271293

272294
This library uses 1-to-1 Unicode code point mapping, which provides broad language coverage but has inherent limitations with context-dependent characters (e.g., polyphonic characters where pronunciation varies by context). Thorough testing with your target languages is recommended before production use.

biome.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
"suspicious": {
1515
"noConsole": "off",
1616
"noBitwiseOperators": "off"
17+
},
18+
"style": {
19+
"useForOf": "off"
1720
}
1821
}
1922
},

data/charmap-latin.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Latin-only charmap - minimal bundle for Latin scripts
2+
// Only includes 0x00-0x02 (Basic Latin + Latin Extended)
3+
4+
import x00 from './chunks/x00';
5+
import x01 from './chunks/x01';
6+
import x02 from './chunks/x02';
7+
8+
export interface Charmap {
9+
[key: string]: string;
10+
}
11+
12+
// 2D array: _[high][low]
13+
const _: (string | null)[][] = [];
14+
_[0x00] = x00;
15+
_[0x01] = x01;
16+
_[0x02] = x02;
17+
18+
// Fast lookup function - Latin only
19+
export function lookup(char: string): string {
20+
const code = char.charCodeAt(0);
21+
const high = code >> 8;
22+
const low = code & 0xff;
23+
24+
const chunk = _[high];
25+
if (chunk) {
26+
return chunk[low] ?? '';
27+
}
28+
return '';
29+
}
30+
31+
// Backwards-compatible charmap object
32+
export const charmap: Charmap = new Proxy({} as Charmap, {
33+
get(_, prop: string) {
34+
if (typeof prop === 'string' && prop.length > 0) {
35+
return lookup(prop) || undefined;
36+
}
37+
return undefined;
38+
},
39+
has(_, prop: string) {
40+
if (typeof prop === 'string' && prop.length > 0) {
41+
return lookup(prop) !== '';
42+
}
43+
return false;
44+
}
45+
});

data/charmap.ts

Lines changed: 309 additions & 10 deletions
Large diffs are not rendered by default.

data/chunks/x00.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default ["\u0000","\u0001","\u0002","\u0003","\u0004","\u0005","\u0006","\u0007","\b","\t","\n","\u000b","\f","\r","\u000e","\u000f","\u0010","\u0011","\u0012","\u0013","\u0014","\u0015","\u0016","\u0017","\u0018","\u0019","\u001a","\u001b","\u001c","\u001d","\u001e","\u001f"," ","!","\"","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","",null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null," ","!","C/","PS","$?","Y=","|","SS","\"","(c)","a","<<","!",null,"(r)","-","deg","+-","2","3","'","u","P","*",",","1","o",">>","1/4","1/2","3/4","?","A","A","A","A","A","A","AE","C","E","E","E","E","I","I","I","I","D","N","O","O","O","O","O","x","O","U","U","U","U","U","Th","ss","a","a","a","a","a","a","ae","c","e","e","e","e","i","i","i","i","d","n","o","o","o","o","o","/","o","u","u","u","u","y","th","y"];

data/chunks/x01.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default ["A","a","A","a","A","a","C","c","C","c","C","c","C","c","D","d","D","d","E","e","E","e","E","e","E","e","E","e","G","g","G","g","G","g","G","g","H","h","H","h","I","i","I","i","I","i","I","i","I","i","IJ","ij","J","j","K","k","k","L","l","L","l","L","l","L","l","L","l","N","n","N","n","N","n","'n","NG","ng","O","o","O","o","O","o","OE","oe","R","r","R","r","R","r","S","s","S","s","S","s","S","s","T","t","T","t","T","t","U","u","U","u","U","u","U","u","U","u","U","u","W","w","Y","y","Y","Z","z","Z","z","Z","z","s","b","B","B","b","6","6","O","C","c","D","D","D","d","d","3","@","E","F","f","G","G","hv","I","I","K","k","l","l","W","N","n","O","O","o","OI","oi","P","p","YR","2","2","SH","sh","t","T","t","T","U","u","Y","V","Y","y","Z","z","ZH","ZH","zh","zh","2","5","5","ts","w","|","||","|=","!","DZ","Dz","dz","LJ","Lj","lj","NJ","Nj","nj","A","a","I","i","O","o","U","u","U","u","U","u","U","u","U","u","@","A","a","A","a","AE","ae","G","g","G","g","K","k","O","o","O","o","ZH","zh","j","DZ","D","dz","G","g","HV","W","N","n","A","a","AE","ae","O","o"];

data/chunks/x02.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default ["A","a","A","a","E","e","E","e","I","i","I","i","O","o","O","o","R","r","R","r","U","u","U","u","S","s","T","t","Y","y","H","h","N","d","OU","ou","Z","z","A","a","E","e","O","o","O","o","O","o","O","o","Y","y","l","n","t","j","db","qp","A","C","c","L","T","s","z","?","?","B","U","V","E","e","J","j","Q","q","R","r","Y","y","a","a","a","b","o","c","d","d","e","@","@","e","e","e","e","j","g","g","g","g","u","Y","h","h","i","i","I","l","l","l","lZ","W","W","m","n","n","n","o","OE","O","F","R","R","R","R","r","r","R","R","R","s","S","j","S","S","t","t","U","U","v","^","W","Y","Y","z","z","Z","Z","?","?","?","C","@","B","E","G","H","j","k","L","q","?","?","dz","dZ","dz","ts","tS","tC","fN","ls","lz","WW","]]","h","h","k","h","j","r","r","r","r","w","y","'","\"","`","'","`","`","'","?","?","<",">","^","V","^","V","'","-","/","\\",",","_","\\","/",":",".","`","'","^","V","+","-","V",".","@",",","~","\"","R","X","G","l","s","x","?",null,null,null,null,null,null,null,"V","=","\""];

data/chunks/x03.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default [null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,"'",",",null,null,null,null,null,null,null,null,"?",null,null,null,null,null,null,null,"A",";","E","I","I",null,"O",null,"U","O","I","A","V","G","D","E","Z","I","Th","I","K","L","M","N","X","O","P","R",null,"S","T","Y","F","H","Ps","O","I","Y","a","e","i","i","y","a","v","g","d","e","z","i","th","i","k","l","m","n","x","o","p","r","s","s","t","y","f","h","ps","o","i","y","o","y","o",null,"b","th","U","U","U","ph","p","&",null,null,"St","st","W","w","Q","q","Sp","sp","Sh","sh","F","f","Kh","kh","H","h","G","g","CH","ch","Ti","ti","k","r","c","j"];

data/chunks/x04.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default ["Jo","Yo","Dj","Gj","Ie","Dz","I","Yi","J","Lj","Nj","Tsh","Kj","I","U","Dzh","A","B","V","G","D","E","Zh","Z","I","Y","K","L","M","N","O","P","R","S","T","U","F","H","C","Ch","Sh","Shch",null,"Y",null,"E","Yu","Ya","a","b","v","g","d","e","zh","z","i","y","k","l","m","n","o","p","r","s","t","u","f","h","c","ch","sh","shch",null,"y",null,"e","yu","ya","je","yo","dj","gj","ie","dz","i","yi","j","lj","nj","tsh","kj","i","u","dzh","O","o","E","e","Ie","ie","E","e","Ie","ie","O","o","Io","io","Ks","ks","Ps","ps","F","f","Y","y","Y","y","u","u","O","o","O","o","Ot","ot","Q","q","*1000*",null,null,null,null,null,"*100.000*","*1.000.000*",null,null,"\"","\"","R'","r'","G'","g'","G'","g'","G'","g'","Zh'","zh'","Z'","z'","K'","k'","K'","k'","K'","k'","K'","k'","N'","n'","Ng","ng","P'","p'","Kh","kh","S'","s'","T'","t'","U","u","U'","u'","Kh'","kh'","Tts","tts","Ch'","ch'","Ch'","ch'","H","h","Ch","ch","Ch'","ch'","`","Zh","zh","K'","k'",null,null,"N'","n'",null,null,"Ch","ch",null,null,null,"a","a","A","a","Ae","ae","Ie","ie","@","@","@","@","Zh","zh","Z","z","Dz","dz","I","i","I","i","O","o","O","o","O","o","E","e","U","u","U","u","U","u","Ch","ch",null,null,"Y","y"];

0 commit comments

Comments
 (0)