nc.str
String helpers: case conversion, slugs, truncation, templates, wrapping, fuzzy matching, plurals. Nothing is mutated, any value is accepted, and lengths are counted the way you see them, so 👨👩👧 is one character and is never cut in half.
const { str } = require("@ix-xs/node-comfort");
import { capitalize } from "@ix-xs/node-comfort/str";str.slugify("Héllo, Wörld!"); // "hello-world"
str.camelCase("user_first-name"); // "userFirstName"
str.plural(3, { one: "file", other: "files" }); // "3 files"nc.str.Functions
nc.str.capitalize()
capitalize(input: unknown): stringUppercases the first character and lowercases the rest.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.capitalize("hELLO wORLD"); // "Hello world"nc.str.titleCase()
titleCase(input: unknown): stringUppercases the first letter of each word and leaves the rest alone.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.titleCase("the quick brown fox"); // "The Quick Brown Fox"
str.titleCase("élodie o'neil"); // "Élodie O'neil"nc.str.sentenceCase()
sentenceCase(input: unknown): stringLowercases everything, then capitalizes the start of each sentence.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.sentenceCase("hELLO WORLD. how ARE you?"); // "Hello world. How are you?"nc.str.camelCase()
camelCase(input: unknown): stringConverts to camelCase.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.camelCase("user_first-name"); // "userFirstName"
str.camelCase("XMLHttpRequest"); // "xmlHttpRequest"nc.str.pascalCase()
pascalCase(input: unknown): stringConverts to PascalCase.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.pascalCase("hello world"); // "HelloWorld"nc.str.snakeCase()
snakeCase(input: unknown): stringConverts to snake_case.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.snakeCase("helloWorld"); // "hello_world"nc.str.kebabCase()
kebabCase(input: unknown): stringConverts to kebab-case.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.kebabCase("helloWorld"); // "hello-world"nc.str.constantCase()
constantCase(input: unknown): stringConverts to CONSTANT_CASE.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.constantCase("helloWorld"); // "HELLO_WORLD"nc.str.dotCase()
dotCase(input: unknown): stringConverts to dot.case.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.dotCase("userFirstName"); // "user.first.name"nc.str.words()
words(input: unknown): string[]Splits text into words. Understands camelCase, snake_case, kebab-case, dots, spaces and punctuation.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string[]
Example
str.words("helloWorld-foo_bar"); // ["hello", "World", "foo", "bar"]nc.str.deburr()
deburr(input: unknown): stringRemoves accents (é becomes e) and spells out special Latin letters (ß becomes ss, æ becomes ae).
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.deburr("Crème brûlée"); // "Creme brulee"
str.deburr("Straße"); // "Strasse"nc.str.slugify()
slugify(input: unknown, options?: SlugifyOptions): stringTurns text into a URL slug: no accents, lowercase, words joined by dashes.
Parameters
| Name | Type |
|---|---|
input | unknown |
optionsoptional | SlugifyOptions |
Returns string: The slug, possibly empty.
Example
str.slugify("Héllo, World!"); // "hello-world"
str.slugify("Crème Brûlée", { separator: "_" }); // "creme_brulee"
str.slugify("A very long title", { maxLength: 8 }); // "a-very"nc.str.squish()
squish(input: unknown): stringCollapses runs of whitespace into single spaces and trims the ends.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.squish(" hello \n\t world "); // "hello world"nc.str.stripTags()
stripTags(input: unknown): stringRemoves HTML tags and keeps the text. This is not a sanitizer: to show untrusted text in HTML, use escapeHTML().
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.stripTags("<p>Hello <b>world</b></p>"); // "Hello world"nc.str.escapeHTML()
escapeHTML(input: unknown): stringEscapes & < > " ' so the text is safe inside HTML content and attributes.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.escapeHTML('<a href="x">Tom & Jerry</a>');
// "<a href="x">Tom & Jerry</a>"nc.str.unescapeHTML()
unescapeHTML(input: unknown): stringDecodes HTML entities: named ones like & and , and numeric ones like é.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.unescapeHTML("Tom & Jerry 😀"); // "Tom & Jerry 😀"nc.str.escapeRegExp()
escapeRegExp(input: unknown): stringEscapes regex special characters so the text matches literally.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
new RegExp(str.escapeRegExp("1+1=2?")).test("1+1=2?"); // truenc.str.length()
length(input: unknown): numberCounts visible characters. Unlike .length, an emoji or an accented letter counts as one.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns number
Example
"👨👩👧".length; // 8
str.length("👨👩👧"); // 1nc.str.byteLength()
byteLength(input: unknown, encoding?: BufferEncoding): numberSize of the text in bytes once encoded, UTF-8 by default. Useful when a limit is in bytes, like a database column or an HTTP header.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
encodingoptional | BufferEncoding | Default: "utf8" |
Returns number
Example
str.byteLength("é"); // 2
str.byteLength("😀"); // 4nc.str.count()
count(input: unknown, search: string): numberCounts how many times search appears, without overlaps.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
search | string | An empty string gives 0. |
Returns number
Example
str.count("banana", "a"); // 3
str.count("aaaa", "aa"); // 2nc.str.truncate()
truncate(input: unknown, length: number, options?: TruncateOptions): stringShortens text to length visible characters, ending with … when cut.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
length | number | Maximum length, omission included. |
optionsoptional | TruncateOptions |
Returns string
Example
str.truncate("Hello world", 8); // "Hello w…"
str.truncate("Hello world", 8, { omission: "..." }); // "Hello..."
str.truncate("Hello big world", 12, { words: true }); // "Hello big…"nc.str.between()
between(input: unknown, start: string, end: string): string | undefinedReturns the text between start and the next end, or undefined if a marker is missing.
Parameters
| Name | Type |
|---|---|
input | unknown |
start | string |
end | string |
Returns string | undefined
Example
str.between("Hello [world]!", "[", "]"); // "world"nc.str.splitOnce()
splitOnce(input: unknown, separator: string): [string, string | undefined]Splits at the first occurrence of separator only.
Parameters
| Name | Type |
|---|---|
input | unknown |
separator | string |
Returns [string, string | undefined]
Example
str.splitOnce("key=value=more", "="); // ["key", "value=more"]
str.splitOnce("novalue", "="); // ["novalue", undefined]nc.str.lines()
lines(input: unknown): string[]Splits text into lines, whatever the line endings.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string[]
Example
str.lines("a\r\nb\nc"); // ["a", "b", "c"]nc.str.padStart()
padStart(input: unknown, length: number, char?: string): stringPads the start until the text is length characters long.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
length | number | |
charoptional | string | Default: " " |
Returns string
Example
str.padStart("7", 3, "0"); // "007"nc.str.padEnd()
padEnd(input: unknown, length: number, char?: string): stringPads the end until the text is length characters long.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
length | number | |
charoptional | string | Default: " " |
Returns string
Example
str.padEnd("ab", 5, "."); // "ab..."nc.str.center()
center(input: unknown, length: number, char?: string): stringCenters text within length characters. An odd leftover goes to the right.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
length | number | |
charoptional | string | Default: " " |
Returns string
Example
str.center("hi", 7, "*"); // "**hi***"nc.str.indent()
indent(input: unknown, prefix?: string | number): stringIndents every non-empty line.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
prefixoptional | number | string | A number of spaces, or the prefix itself.Default: 2 |
Returns string
Example
str.indent("a\nb", 2); // " a\n b"
str.indent("a\nb", "> "); // "> a\n> b"nc.str.dedent()
dedent(input: unknown, ...values: unknown[]): stringRemoves the indentation shared by all lines, and blank first and last lines. Works as a template tag, so multi-line strings can follow your code's indentation.
Parameters
| Name | Type |
|---|---|
input | unknown |
...values | ...unknown |
Returns string
Example
const sql = str.dedent`
SELECT *
FROM users
WHERE id = ${id}
`;
// "SELECT *\n FROM users\n WHERE id = 42"nc.str.wrap()
wrap(input: unknown, options?: number | WrapOptions): stringWraps text so no line is longer than width visible characters. Existing line breaks are kept.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
optionsoptional | WrapOptions | number | Options, or just the width. |
Returns string
Example
str.wrap("The quick brown fox jumps over the lazy dog", 16);
// "The quick brown\nfox jumps over\nthe lazy dog"nc.str.reverse()
reverse(input: unknown): stringReverses text without breaking emoji or accents.
Parameters
| Name | Type |
|---|---|
input | unknown |
Returns string
Example
str.reverse("añ👍🏽"); // "👍🏽ña"nc.str.mask()
mask(input: unknown, options?: MaskOptions): stringHides part of a string, like a card number or a token.
Parameters
| Name | Type |
|---|---|
input | unknown |
optionsoptional | MaskOptions |
Returns string
Example
str.mask("4242424242424242"); // "************4242"
str.mask("4242 4242 4242 4242", { keepSpaces: true }); // "**** **** **** 4242"
str.mask("secret-token", { start: 2, end: 2, char: "•" }); // "se••••••••en"nc.str.initials()
initials(input: unknown, max?: number): stringThe initials of a name, in uppercase.
Parameters
| Name | Type | Description |
|---|---|---|
input | unknown | |
maxoptional | number | Maximum number of letters.Default: 2 |
Returns string
Example
str.initials("Ada Lovelace"); // "AL"
str.initials("jean-luc picard", 3); // "JLP"nc.str.plural()
plural(value: number, forms: PluralForms, options?: PluralOptions): stringPicks the right plural for a count, following the rules of the language, and puts the formatted count in front.
Parameters
| Name | Type |
|---|---|
value | number |
forms | PluralForms |
optionsoptional | PluralOptions |
Returns string
Example
str.plural(1, { one: "file", other: "files" }); // "1 file"
str.plural(1234, { one: "item", other: "items" }); // "1,234 items"
str.plural(0, { zero: "no files", one: "file", other: "files" }); // "no files"
str.plural(0, { one: "fichier", other: "fichiers" }, { locale: "fr" }); // "0 fichier"nc.str.template()
template(input: unknown, data: Record<string, any>, options?: TemplateOptions): stringFills {placeholders} with values. Dotted paths like {user.name} work, and missing values are left alone unless you give a fallback.
Parameters
| Name | Type |
|---|---|
input | unknown |
data | Record<string, any> |
optionsoptional | TemplateOptions |
Returns string
Example
str.template("Hi {name}, you have {count} messages", { name: "Jo", count: 3 });
// "Hi Jo, you have 3 messages"
str.template("Hello {{ user.name }}", { user: { name: "Ada" } }, { open: "{{", close: "}}" });
// "Hello Ada"nc.str.ensurePrefix()
ensurePrefix(input: unknown, prefix: string): stringAdds prefix unless the text already starts with it.
Parameters
| Name | Type |
|---|---|
input | unknown |
prefix | string |
Returns string
Example
str.ensurePrefix("example.com", "https://"); // "https://example.com"nc.str.ensureSuffix()
ensureSuffix(input: unknown, suffix: string): stringAdds suffix unless the text already ends with it.
Parameters
| Name | Type |
|---|---|
input | unknown |
suffix | string |
Returns string
Example
str.ensureSuffix("path/to", "/"); // "path/to/"nc.str.removePrefix()
removePrefix(input: unknown, prefix: string): stringRemoves prefix if the text starts with it.
Parameters
| Name | Type |
|---|---|
input | unknown |
prefix | string |
Returns string
Example
str.removePrefix("https://example.com", "https://"); // "example.com"nc.str.removeSuffix()
removeSuffix(input: unknown, suffix: string): stringRemoves suffix if the text ends with it.
Parameters
| Name | Type |
|---|---|
input | unknown |
suffix | string |
Returns string
Example
str.removeSuffix("report.pdf", ".pdf"); // "report"nc.str.compare()
compare(a: unknown, b: unknown, options?: CompareOptions): numberCompares two strings the way people sort them: numbers in natural order and accents in the right place. Pass it straight to sort().
Parameters
| Name | Type |
|---|---|
a | unknown |
b | unknown |
optionsoptional | CompareOptions |
Returns number: Negative if a comes first, positive if b does, 0 if equal.
Example
["file10", "file2", "File1"].sort(str.compare); // ["File1", "file2", "file10"]
str.compare("a", "A", { sensitivity: "base" }); // 0nc.str.levenshtein()
levenshtein(a: unknown, b: unknown): numberThe number of single-character edits needed to turn a into b.
Parameters
| Name | Type |
|---|---|
a | unknown |
b | unknown |
Returns number
Example
str.levenshtein("kitten", "sitting"); // 3nc.str.similarity()
similarity(a: unknown, b: unknown): numberHow alike two strings are, from 0 (nothing in common) to 1 (identical).
Parameters
| Name | Type |
|---|---|
a | unknown |
b | unknown |
Returns number
Example
str.similarity("hello", "hallo"); // 0.8nc.str.closest()
closest(input: unknown, candidates: Iterable<string>, options?: ClosestOptions): string | undefinedFinds the candidate closest to input. Made for "Did you mean...?" suggestions.
Parameters
| Name | Type |
|---|---|
input | unknown |
candidates | Iterable<string> |
optionsoptional | ClosestOptions |
Returns string | undefined: undefined when nothing is close enough.
Example
str.closest("instal", ["install", "uninstall", "list"]); // "install"
str.closest("xyz", ["install", "list"]); // undefinednc.str.random()
random(size?: number, options?: string | RandomStringOptions): stringA random string. It relies on Math.random, so don't use it for secrets: nc.id.token() and nc.id.nano() are made for that.
Parameters
| Name | Type | Description |
|---|---|---|
sizeoptional | number | Default: 16 |
optionsoptional | RandomStringOptions | string | Options, or the charset itself. |
Returns string
Example
str.random(); // "aZ3kP9qL0xYb7TcW"
str.random(6, { charset: "0123456789" }); // "402917"Types
Import any of them in TypeScript with import type { ClosestOptions } from "@ix-xs/node-comfort", or in JavaScript with import("@ix-xs/node-comfort").ClosestOptions.
ClosestOptions
Options for closest().
| Property | Type | Description |
|---|---|---|
thresholdoptional | number | Minimum similarity (0 to 1) to accept a match. Defaults to 0.4. |
caseSensitiveoptional | boolean | Take case into account. |
CompareOptions
Options for compare().
| Property | Type | Description |
|---|---|---|
localeoptional | string | Language used for alphabetical order. Defaults to the system's. |
numericoptional | boolean | Sort numbers naturally, "file2" before "file10". Defaults to true. |
sensitivityoptional | "base" | "accent" | "case" | "variant" | Which differences count. "base" ignores accents and case. Defaults to "variant". |
MaskOptions
Options for mask().
| Property | Type | Description |
|---|---|---|
startoptional | number | Characters left visible at the start. Defaults to 0. |
endoptional | number | Characters left visible at the end. Defaults to 4. |
charoptional | string | Mask character. Defaults to "*". |
keepSpacesoptional | boolean | Leave spaces and dashes visible, nice for card numbers. |
PluralForms
The word forms for plural(). Only other is required; add the others when your language needs them.
| Property | Type | Description |
|---|---|---|
other | string | The general plural, like "files". |
zerooptional | string | Used for 0 in any language, like "no files". |
oneoptional | string | The singular, like "file". French also uses it for 0. |
twooptional | string | Dual form (Arabic, Hebrew, Slovenian...). |
fewoptional | string | "Few" form (Polish, Czech, Russian...). |
manyoptional | string | "Many" form (Polish, Russian, Arabic...). |
PluralOptions
Options for plural().
| Property | Type | Description |
|---|---|---|
localeoptional | string | Language whose plural rules apply. Defaults to "en". |
includeCountoptional | boolean | Put the formatted count before the word. Defaults to true. |
ordinaloptional | boolean | Use ordinal rules (1st, 2nd, 3rd). |
RandomStringOptions
Options for random().
| Property | Type | Description |
|---|---|---|
charsetoptional | string | Characters to pick from. Defaults to letters and digits. |
SlugifyOptions
Options for slugify().
| Property | Type | Description |
|---|---|---|
separatoroptional | string | Placed between words. Defaults to "-". |
loweroptional | boolean | Lowercase the result. Defaults to true. |
maxLengthoptional | number | Maximum length, cut on a word boundary when possible. |
TemplateOptions
Options for template().
| Property | Type | Description |
|---|---|---|
openoptional | string | Opening delimiter. Defaults to "{". |
closeoptional | string | Closing delimiter. Defaults to "}". |
fallbackoptional | string | Used for missing values. Without it, their placeholders stay as they are. |
TruncateOptions
Options for truncate().
| Property | Type | Description |
|---|---|---|
omissionoptional | string | Added where the text is cut, and counted in the length. Defaults to "…". |
wordsoptional | boolean | Cut at the previous space rather than inside a word. |
WrapOptions
Options for wrap().
| Property | Type | Description |
|---|---|---|
widthoptional | number | Maximum visible characters per line. Defaults to 80. |
indentoptional | string | Added at the start of every line. |
cutoptional | boolean | Break words longer than width instead of letting them overflow. |
newlineoptional | string | Line separator. Defaults to "\n". |