{"_id":"@amiearth/truncate-smart","_rev":"7-a2e7427fc807cb3c50455eefba992e9e","name":"@amiearth/truncate-smart","dist-tags":{"latest":"0.1.9"},"versions":{"0.1.1":{"name":"@amiearth/truncate-smart","version":"0.1.1","keywords":["truncate","string","html","emoji","typescript","zero-dep"],"license":"MIT","_id":"@amiearth/truncate-smart@0.1.1","maintainers":[{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"}],"dist":{"shasum":"6d882fa39572d3893621cd783f4bcd2099dfd681","tarball":"https://registry.npmjs.org/@amiearth/truncate-smart/-/truncate-smart-0.1.1.tgz","fileCount":8,"integrity":"sha512-hDAshnZLw8RCTWYgYxR15fQQb78FnAAsnvLr5hDzVUQVV/e5tPt61dUfZlLvsHlZld5cVLsJR1+HFZmf66c1ow==","signatures":[{"sig":"MEUCIQC4c73uBL5Skvf/CPsm0JtjI+n4apqfhJqKf2gLY2wN5QIgSNT8iVrEuAs7VA+3vEV1nDQKcDGOiJ8287b3T9o5e18=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":40179},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","format":"prettier --write .","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"},"_npmVersion":"11.3.0","description":"Zero-dep, TypeScript-first string truncation with word boundary, HTML strip, and emoji safety","directories":{},"sideEffects":false,"_nodeVersion":"23.7.0","_hasShrinkwrap":false,"packageManager":"pnpm@10.28.0","devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","vitest":"^4.0.16","prettier":"^3.7.4","@eslint/js":"^9.39.2","typescript":"^5.9.3","@types/node":"^25.0.3","typescript-eslint":"^8.52.0","eslint-config-prettier":"^10.1.8","@typescript-eslint/parser":"^8.52.0","@typescript-eslint/eslint-plugin":"^8.52.0"},"_npmOperationalInternal":{"tmp":"tmp/truncate-smart_0.1.1_1776153457026_0.7540672523209075","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@amiearth/truncate-smart","version":"0.1.3","keywords":["truncate","string","html","emoji","typescript","zero-dep"],"license":"MIT","_id":"@amiearth/truncate-smart@0.1.3","maintainers":[{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"}],"homepage":"https://github.com/earth774/truncate-smart#readme","bugs":{"url":"https://github.com/earth774/truncate-smart/issues"},"dist":{"shasum":"d4427048641afc32586297893aeb5306210d0270","tarball":"https://registry.npmjs.org/@amiearth/truncate-smart/-/truncate-smart-0.1.3.tgz","fileCount":8,"integrity":"sha512-JjGXp5viZGe0M4gU0ToDLC+TFksQ7QJlogBotdN+LN4sfj0/pvpcjc88BFpazlnEORhmy9crI3laCL0HPj7K0Q==","signatures":[{"sig":"MEUCIQDJ/ip1/hRLimo5+rUkYNXmYV/xl5oAkRgBTORb+wGGqwIgWPQb/1uSs6MCzJqmKvXOp6tSw+UE1jnP0PMcJVqcHG4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amiearth%2ftruncate-smart@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40326},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"fccaf2fac986c42f2346fca172ff6fc6942e8ec9","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","format":"prettier --write .","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"},"repository":{"url":"git+https://github.com/earth774/truncate-smart.git","type":"git"},"_npmVersion":"10.8.2","description":"Zero-dep, TypeScript-first string truncation with word boundary, HTML strip, and emoji safety","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.0","devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","vitest":"^4.0.16","prettier":"^3.7.4","@eslint/js":"^9.39.2","typescript":"^5.9.3","@types/node":"^25.0.3","typescript-eslint":"^8.52.0","eslint-config-prettier":"^10.1.8","@typescript-eslint/parser":"^8.52.0","@typescript-eslint/eslint-plugin":"^8.52.0"},"_npmOperationalInternal":{"tmp":"tmp/truncate-smart_0.1.3_1776188382295_0.06389345353598741","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@amiearth/truncate-smart","version":"0.1.5","keywords":["truncate","string","html","emoji","typescript","zero-dep"],"license":"MIT","_id":"@amiearth/truncate-smart@0.1.5","maintainers":[{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"}],"homepage":"https://github.com/earth774/truncate-smart#readme","bugs":{"url":"https://github.com/earth774/truncate-smart/issues"},"dist":{"shasum":"dab1971f40381a05f7a792c331a69e49856af6be","tarball":"https://registry.npmjs.org/@amiearth/truncate-smart/-/truncate-smart-0.1.5.tgz","fileCount":8,"integrity":"sha512-loMAkjc9towH1gDfPgj9qzmFPZEcQTfFxD9hRPXS1AfSTjn9/k1KAnXB/FuKuzLJp85134gxHj3RGKzAHn7hWg==","signatures":[{"sig":"MEQCIETirO8+oI5IldB8SsDVohvTpv/MwOSng2OGAN4lLolVAiBiVuiOIigr//aQKdIjqxc4dJ62kBIUBIw2Eupc90Qptw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amiearth%2ftruncate-smart@0.1.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40470},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"1165be026a1973c3da0786be95d9a0761fa400e1","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","format":"prettier --write .","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","release:major":"bash ./release.sh major","release:minor":"bash ./release.sh minor","release:patch":"bash ./release.sh patch"},"_npmUser":{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"},"repository":{"url":"git+https://github.com/earth774/truncate-smart.git","type":"git"},"_npmVersion":"10.8.2","description":"Zero-dep, TypeScript-first string truncation with word boundary, HTML strip, and emoji safety","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.0","devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","vitest":"^4.0.16","prettier":"^3.7.4","@eslint/js":"^9.39.2","typescript":"^5.9.3","@types/node":"^25.0.3","typescript-eslint":"^8.52.0","eslint-config-prettier":"^10.1.8","@typescript-eslint/parser":"^8.52.0","@typescript-eslint/eslint-plugin":"^8.52.0"},"_npmOperationalInternal":{"tmp":"tmp/truncate-smart_0.1.5_1776188985105_0.05381518215097825","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@amiearth/truncate-smart","version":"0.1.6","keywords":["truncate","string","html","emoji","typescript","zero-dep"],"license":"MIT","_id":"@amiearth/truncate-smart@0.1.6","maintainers":[{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"}],"homepage":"https://github.com/earth774/truncate-smart#readme","bugs":{"url":"https://github.com/earth774/truncate-smart/issues"},"dist":{"shasum":"45c118263c7caf4a88332cd1539bc82ff75eeff3","tarball":"https://registry.npmjs.org/@amiearth/truncate-smart/-/truncate-smart-0.1.6.tgz","fileCount":8,"integrity":"sha512-PPEWeb5Qb5wpnN6ymvyjdYLwkfZjPUVoB5TUJBpKXKr9+KmnP8pn/DXXHirMyqlYX3vzeUacwMJnucXPxv90pQ==","signatures":[{"sig":"MEUCIBYr3pirHA5aiwdNsWcEC1X+XO13r/Uw7PvFwRD1ugARAiEA0Tt8rZXF5WLIwRi8UuaDhwnZZoltgwkgzpLQ5do/I+U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amiearth%2ftruncate-smart@0.1.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40623},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"0a5233f52ed9b40f23001d277174dad3f2adf38c","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","format":"prettier --write .","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","release:major":"bash ./release.sh major","release:minor":"bash ./release.sh minor","release:patch":"bash ./release.sh patch"},"_npmUser":{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"},"repository":{"url":"git+https://github.com/earth774/truncate-smart.git","type":"git"},"_npmVersion":"10.8.2","description":"Zero-dep, TypeScript-first string truncation with word boundary, HTML strip, and emoji safety","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.0","devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","vitest":"^4.0.16","prettier":"^3.7.4","@eslint/js":"^9.39.2","typescript":"^5.9.3","@types/node":"^25.0.3","typescript-eslint":"^8.52.0","eslint-config-prettier":"^10.1.8","@typescript-eslint/parser":"^8.52.0","@typescript-eslint/eslint-plugin":"^8.52.0"},"_npmOperationalInternal":{"tmp":"tmp/truncate-smart_0.1.6_1776227633017_0.8838783579796237","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@amiearth/truncate-smart","version":"0.1.7","keywords":["truncate","string","html","emoji","typescript","zero-dep"],"license":"MIT","_id":"@amiearth/truncate-smart@0.1.7","maintainers":[{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"}],"homepage":"https://github.com/earth774/truncate-smart#readme","bugs":{"url":"https://github.com/earth774/truncate-smart/issues"},"dist":{"shasum":"831b2c576043420d399bc0f36d4699e49d64aa6d","tarball":"https://registry.npmjs.org/@amiearth/truncate-smart/-/truncate-smart-0.1.7.tgz","fileCount":8,"integrity":"sha512-4aRtvz/cvdDdBnIEBHN46s9ashPCYTV+rWbYE9Q6o/dIFNcA8lRG6p6aXPbuCuWx+48mo1boILg6gzXk1wm7SA==","signatures":[{"sig":"MEUCIA+C0rVpgIK4DbJQlKL0Nn968D9uAyPep55myhnDQQenAiEAzlok6+xn95UDX1gDO4XiR7mIXJEOujMkScsKXzc21DQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amiearth%2ftruncate-smart@0.1.7","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40623},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"13fbd8e1aa0ff6892a1bd5a87298a2a190dd2179","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","format":"prettier --write .","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","release:major":"bash ./release.sh major","release:minor":"bash ./release.sh minor","release:patch":"bash ./release.sh patch"},"_npmUser":{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"},"repository":{"url":"git+https://github.com/earth774/truncate-smart.git","type":"git"},"_npmVersion":"10.8.2","description":"Zero-dep, TypeScript-first string truncation with word boundary, HTML strip, and emoji safety","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.0","devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","vitest":"^4.0.16","prettier":"^3.7.4","@eslint/js":"^9.39.2","typescript":"^5.9.3","@types/node":"^25.0.3","typescript-eslint":"^8.52.0","eslint-config-prettier":"^10.1.8","@typescript-eslint/parser":"^8.52.0","@typescript-eslint/eslint-plugin":"^8.52.0"},"_npmOperationalInternal":{"tmp":"tmp/truncate-smart_0.1.7_1776227677780_0.4818210823942384","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@amiearth/truncate-smart","version":"0.1.8","keywords":["truncate","string","html","emoji","typescript","zero-dep"],"license":"MIT","_id":"@amiearth/truncate-smart@0.1.8","maintainers":[{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"}],"homepage":"https://github.com/earth774/truncate-smart#readme","bugs":{"url":"https://github.com/earth774/truncate-smart/issues"},"dist":{"shasum":"52a4f0d65d2fdefbacb964014899e439a3402f44","tarball":"https://registry.npmjs.org/@amiearth/truncate-smart/-/truncate-smart-0.1.8.tgz","fileCount":8,"integrity":"sha512-55npZr19bt7SMKzlBOk/14byxsVeRZ5Xn2qVJlNKH2IVDZh9+63KuRIaPmoCQRVVFQ/7/tKYmKlq1ku9LftIrQ==","signatures":[{"sig":"MEUCIQCdsXdtGP/9Ox6NOnbW98ocQT7Sa73OQRj+g3MZfBDg2gIgHqeCX5LpOoCJ/etUvu95HNxJArQ9F6okXUZcCRX64yE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amiearth%2ftruncate-smart@0.1.8","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":40427},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"gitHead":"8f11efc0d41bb8fbd056c22701ad7f8a364a8b80","scripts":{"lint":"eslint src","test":"vitest run","build":"tsup","format":"prettier --write .","typecheck":"tsc --noEmit","test:watch":"vitest","format:check":"prettier --check .","release:major":"bash ./release.sh major","release:minor":"bash ./release.sh minor","release:patch":"bash ./release.sh patch","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"},"repository":{"url":"git+https://github.com/earth774/truncate-smart.git","type":"git"},"_npmVersion":"10.8.2","description":"Zero-dep, TypeScript-first string truncation with word boundary, HTML strip, and emoji safety","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.0","devDependencies":{"tsup":"^8.5.1","eslint":"^9.39.2","vitest":"^4.1.4","prettier":"^3.7.4","@eslint/js":"^9.39.2","typescript":"^5.9.3","@types/node":"^25.0.3","typescript-eslint":"^8.52.0","@vitest/coverage-v8":"^4.1.4","eslint-config-prettier":"^10.1.8","@typescript-eslint/parser":"^8.52.0","@typescript-eslint/eslint-plugin":"^8.52.0"},"_npmOperationalInternal":{"tmp":"tmp/truncate-smart_0.1.8_1776228047448_0.5387406465235598","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"@amiearth/truncate-smart","publishConfig":{"access":"public"},"version":"0.1.9","description":"Zero-dep, TypeScript-first string truncation with word boundary, HTML strip, and emoji safety","repository":{"type":"git","url":"git+https://github.com/earth774/truncate-smart.git"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"sideEffects":false,"keywords":["truncate","string","html","emoji","typescript","zero-dep"],"license":"MIT","scripts":{"build":"tsup","test":"vitest run","test:coverage":"vitest run --coverage","test:watch":"vitest","lint":"eslint src","typecheck":"tsc --noEmit","format":"prettier --write .","format:check":"prettier --check .","release:patch":"bash ./release.sh patch","release:minor":"bash ./release.sh minor","release:major":"bash ./release.sh major"},"devDependencies":{"@eslint/js":"^9.39.2","@types/node":"^25.0.3","@typescript-eslint/eslint-plugin":"^8.52.0","@typescript-eslint/parser":"^8.52.0","@vitest/coverage-v8":"^4.1.4","eslint":"^9.39.2","eslint-config-prettier":"^10.1.8","prettier":"^3.7.4","tsup":"^8.5.1","typescript":"^5.9.3","typescript-eslint":"^8.52.0","vitest":"^4.1.4"},"packageManager":"pnpm@10.28.0","engines":{"node":">=18"},"_id":"@amiearth/truncate-smart@0.1.9","gitHead":"395144477605b49625f0f6c642b195f39d60526f","bugs":{"url":"https://github.com/earth774/truncate-smart/issues"},"homepage":"https://github.com/earth774/truncate-smart#readme","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-9zB/+Tc2QVQNzm81sEujnZc+aGyZsZTO57w/40ywn5yz1IqHi7fUswH/TYFpWk5F/imazx43ip1tZVf3Pt7hXg==","shasum":"e4c162128d02438c0571e457a2d86c151d328fd6","tarball":"https://registry.npmjs.org/@amiearth/truncate-smart/-/truncate-smart-0.1.9.tgz","fileCount":8,"unpackedSize":40427,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amiearth%2ftruncate-smart@0.1.9","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCF/evD4CEWmWUUiLYZ/i1lIgZVzXUOFpvaIoT1JJ4nuQIhANi1qSYC82+4V4pcUlHj0r4PmE/gxLv34zHmeJgESO2L"}]},"_npmUser":{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"},"directories":{},"maintainers":[{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/truncate-smart_0.1.9_1776248674540_0.47398168372149185"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-14T07:57:36.883Z","modified":"2026-04-15T10:24:34.950Z","0.1.1":"2026-04-14T07:57:37.160Z","0.1.3":"2026-04-14T17:39:42.452Z","0.1.5":"2026-04-14T17:49:45.263Z","0.1.6":"2026-04-15T04:33:53.169Z","0.1.7":"2026-04-15T04:34:37.905Z","0.1.8":"2026-04-15T04:40:47.565Z","0.1.9":"2026-04-15T10:24:34.686Z"},"bugs":{"url":"https://github.com/earth774/truncate-smart/issues"},"license":"MIT","homepage":"https://github.com/earth774/truncate-smart#readme","keywords":["truncate","string","html","emoji","typescript","zero-dep"],"repository":{"type":"git","url":"git+https://github.com/earth774/truncate-smart.git"},"description":"Zero-dep, TypeScript-first string truncation with word boundary, HTML strip, and emoji safety","maintainers":[{"name":"amiearth","email":"sutthiphongnuanma@gmail.com"}],"readme":"# truncate-smart\n\nPublished on npm as **`@amiearth/truncate-smart`**. Zero-dependency, TypeScript-first string truncation. Handles word boundaries (including Thai/CJK via `Intl.Segmenter`), optional HTML tag stripping, grapheme-safe emoji boundaries, and protected substrings.\n\n## Install\n\n```bash\npnpm add @amiearth/truncate-smart\n# or\nyarn add @amiearth/truncate-smart\n# or\nnpm install @amiearth/truncate-smart\n```\n\n## Quick start\n\n```ts\nimport { truncate, createTruncator, truncateAll, stripHtml } from \"@amiearth/truncate-smart\"\n\ntruncate(\"Hello world today\", 14)\n// => \"Hello world...\"\n\ntruncate(\"<p>Hello <b>world</b></p>\", 10, { stripHtml: true })\n// => \"Hello...\"\n\ntruncate(\"👨‍👩‍👧 family\", 12)\n// Grapheme-safe: does not split the ZWJ family emoji\n\ntruncate(\"日本語の文章です\", 10, { locale: \"ja\" })\n// Word-aware when a BCP-47 locale is set\n\nconst t = createTruncator({ suffix: \"…\", locale: \"th\" })\nt(\"สวัสดีครับ\", 8)\n\ntruncateAll([\"one\", \"two three\"], 6)\n// => [\"one\", \"two...\"]\n```\n\n## API\n\n### `truncate(str, maxLength, options?)`\n\n- **`str`**: `string | null | undefined` — `null`/`undefined` are treated as empty.\n- **`maxLength`**: Non-negative integer length budget for the **entire returned string** (content + suffix). When `emojiSafe` is `true` (default), length is measured in **grapheme clusters** (via `Intl.Segmenter` when available).\n- **`options`**: See below.\n\nReturns the truncated string. If the input is only whitespace (after optional HTML strip), returns `\"\"`. If `maxLength` is less than or equal to the suffix length (in the same units as above), returns the suffix only (never throws).\n\n### `createTruncator(defaults)`\n\nReturns `(str, maxLength) => string` with fixed default options.\n\n### `truncateAll(strs, maxLength, options?)`\n\nMaps `truncate` over an array.\n\n### `stripHtml(str)`\n\nRemoves `<...>` tags with a small regex — not a full HTML parser.\n\n## Options\n\n| Option          | Type       | Default | Description                                                                     |\n| --------------- | ---------- | ------- | ------------------------------------------------------------------------------- |\n| `suffix`        | `string`   | `\"...\"` | Appended after truncated content                                                |\n| `wordBoundary`  | `boolean`  | `true`  | Prefer breaking at whitespace; with `locale`, uses word segments when supported |\n| `stripHtml`     | `boolean`  | `false` | Strip tags before measuring/truncating                                          |\n| `emojiSafe`     | `boolean`  | `true`  | Grapheme-aware counting and slicing                                             |\n| `locale`        | `string`   | —       | BCP-47 tag (e.g. `\"th\"`, `\"ja\"`) for `Intl.Segmenter`                           |\n| `preserveWords` | `string[]` | —       | Substrings that must not be cut in the middle                                   |\n\n### Word boundaries\n\nWithout `locale`, after fitting the content budget the result backs up to the last Unicode whitespace **only if** the cut would otherwise separate two word characters (letters or numbers). Newlines and tabs count as whitespace.\n\nWith `locale` and `wordBoundary`, word breaks use `Intl.Segmenter` with `granularity: \"word\"` when available; otherwise behavior falls back to grapheme slicing plus the whitespace rule above.\n\n### Runtime\n\n`Intl.Segmenter` is used when present (Node 18+). Older runtimes fall back to code-point iteration from the string iterator.\n\n## Scripts\n\n```bash\npnpm build        # tsup → dist (ESM + CJS + .d.ts)\npnpm test         # vitest run\npnpm typecheck    # tsc --noEmit\npnpm lint         # eslint src\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}