node-comfortv2.0.0

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"
GuideExplanations and examples for nc.str.
Read the guide →

Functions

nc.str.capitalize()

capitalize(input: unknown): string

Uppercases the first character and lowercases the rest.

Parameters

NameType
inputunknown

Returns string

Example

str.capitalize("hELLO wORLD"); // "Hello world"

nc.str.titleCase()

titleCase(input: unknown): string

Uppercases the first letter of each word and leaves the rest alone.

Parameters

NameType
inputunknown

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): string

Lowercases everything, then capitalizes the start of each sentence.

Parameters

NameType
inputunknown

Returns string

Example

str.sentenceCase("hELLO WORLD. how ARE you?"); // "Hello world. How are you?"

nc.str.camelCase()

camelCase(input: unknown): string

Converts to camelCase.

Parameters

NameType
inputunknown

Returns string

Example

str.camelCase("user_first-name"); // "userFirstName"
str.camelCase("XMLHttpRequest");  // "xmlHttpRequest"

nc.str.pascalCase()

pascalCase(input: unknown): string

Converts to PascalCase.

Parameters

NameType
inputunknown

Returns string

Example

str.pascalCase("hello world"); // "HelloWorld"

nc.str.snakeCase()

snakeCase(input: unknown): string

Converts to snake_case.

Parameters

NameType
inputunknown

Returns string

Example

str.snakeCase("helloWorld"); // "hello_world"

nc.str.kebabCase()

kebabCase(input: unknown): string

Converts to kebab-case.

Parameters

NameType
inputunknown

Returns string

Example

str.kebabCase("helloWorld"); // "hello-world"

nc.str.constantCase()

constantCase(input: unknown): string

Converts to CONSTANT_CASE.

Parameters

NameType
inputunknown

Returns string

Example

str.constantCase("helloWorld"); // "HELLO_WORLD"

nc.str.dotCase()

dotCase(input: unknown): string

Converts to dot.case.

Parameters

NameType
inputunknown

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

NameType
inputunknown

Returns string[]

Example

str.words("helloWorld-foo_bar"); // ["hello", "World", "foo", "bar"]

nc.str.deburr()

deburr(input: unknown): string

Removes accents (é becomes e) and spells out special Latin letters (ß becomes ss, æ becomes ae).

Parameters

NameType
inputunknown

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): string

Turns text into a URL slug: no accents, lowercase, words joined by dashes.

Parameters

NameType
inputunknown
optionsoptionalSlugifyOptions

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): string

Collapses runs of whitespace into single spaces and trims the ends.

Parameters

NameType
inputunknown

Returns string

Example

str.squish("  hello \n\t world  "); // "hello world"

nc.str.stripTags()

stripTags(input: unknown): string

Removes HTML tags and keeps the text. This is not a sanitizer: to show untrusted text in HTML, use escapeHTML().

Parameters

NameType
inputunknown

Returns string

Example

str.stripTags("<p>Hello <b>world</b></p>"); // "Hello world"

nc.str.escapeHTML()

escapeHTML(input: unknown): string

Escapes & < > " ' so the text is safe inside HTML content and attributes.

Parameters

NameType
inputunknown

Returns string

Example

str.escapeHTML('<a href="x">Tom & Jerry</a>');
// "&lt;a href=&quot;x&quot;&gt;Tom &amp; Jerry&lt;/a&gt;"

nc.str.unescapeHTML()

unescapeHTML(input: unknown): string

Decodes HTML entities: named ones like &amp; and &nbsp;, and numeric ones like &#233;.

Parameters

NameType
inputunknown

Returns string

Example

str.unescapeHTML("Tom &amp; Jerry &#x1F600;"); // "Tom & Jerry 😀"

nc.str.escapeRegExp()

escapeRegExp(input: unknown): string

Escapes regex special characters so the text matches literally.

Parameters

NameType
inputunknown

Returns string

Example

new RegExp(str.escapeRegExp("1+1=2?")).test("1+1=2?"); // true

nc.str.length()

length(input: unknown): number

Counts visible characters. Unlike .length, an emoji or an accented letter counts as one.

Parameters

NameType
inputunknown

Returns number

Example

"👨‍👩‍👧".length;         // 8
str.length("👨‍👩‍👧");     // 1

nc.str.byteLength()

byteLength(input: unknown, encoding?: BufferEncoding): number

Size 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

NameTypeDescription
inputunknown
encodingoptionalBufferEncodingDefault: "utf8"

Returns number

Example

str.byteLength("é");  // 2
str.byteLength("😀"); // 4

nc.str.count()

count(input: unknown, search: string): number

Counts how many times search appears, without overlaps.

Parameters

NameTypeDescription
inputunknown
searchstringAn empty string gives 0.

Returns number

Example

str.count("banana", "a"); // 3
str.count("aaaa", "aa");  // 2

nc.str.truncate()

truncate(input: unknown, length: number, options?: TruncateOptions): string

Shortens text to length visible characters, ending with when cut.

Parameters

NameTypeDescription
inputunknown
lengthnumberMaximum length, omission included.
optionsoptionalTruncateOptions

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 | undefined

Returns the text between start and the next end, or undefined if a marker is missing.

Parameters

NameType
inputunknown
startstring
endstring

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

NameType
inputunknown
separatorstring

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

NameType
inputunknown

Returns string[]

Example

str.lines("a\r\nb\nc"); // ["a", "b", "c"]

nc.str.padStart()

padStart(input: unknown, length: number, char?: string): string

Pads the start until the text is length characters long.

Parameters

NameTypeDescription
inputunknown
lengthnumber
charoptionalstringDefault: " "

Returns string

Example

str.padStart("7", 3, "0"); // "007"

nc.str.padEnd()

padEnd(input: unknown, length: number, char?: string): string

Pads the end until the text is length characters long.

Parameters

NameTypeDescription
inputunknown
lengthnumber
charoptionalstringDefault: " "

Returns string

Example

str.padEnd("ab", 5, "."); // "ab..."

nc.str.center()

center(input: unknown, length: number, char?: string): string

Centers text within length characters. An odd leftover goes to the right.

Parameters

NameTypeDescription
inputunknown
lengthnumber
charoptionalstringDefault: " "

Returns string

Example

str.center("hi", 7, "*"); // "**hi***"

nc.str.indent()

indent(input: unknown, prefix?: string | number): string

Indents every non-empty line.

Parameters

NameTypeDescription
inputunknown
prefixoptionalnumber | stringA 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[]): string

Removes 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

NameType
inputunknown
...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): string

Wraps text so no line is longer than width visible characters. Existing line breaks are kept.

Parameters

NameTypeDescription
inputunknown
optionsoptionalWrapOptions | numberOptions, 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): string

Reverses text without breaking emoji or accents.

Parameters

NameType
inputunknown

Returns string

Example

str.reverse("añ👍🏽"); // "👍🏽ña"

nc.str.mask()

mask(input: unknown, options?: MaskOptions): string

Hides part of a string, like a card number or a token.

Parameters

NameType
inputunknown
optionsoptionalMaskOptions

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): string

The initials of a name, in uppercase.

Parameters

NameTypeDescription
inputunknown
maxoptionalnumberMaximum 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): string

Picks the right plural for a count, following the rules of the language, and puts the formatted count in front.

Parameters

NameType
valuenumber
formsPluralForms
optionsoptionalPluralOptions

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): string

Fills {placeholders} with values. Dotted paths like {user.name} work, and missing values are left alone unless you give a fallback.

Parameters

NameType
inputunknown
dataRecord<string, any>
optionsoptionalTemplateOptions

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): string

Adds prefix unless the text already starts with it.

Parameters

NameType
inputunknown
prefixstring

Returns string

Example

str.ensurePrefix("example.com", "https://"); // "https://example.com"

nc.str.ensureSuffix()

ensureSuffix(input: unknown, suffix: string): string

Adds suffix unless the text already ends with it.

Parameters

NameType
inputunknown
suffixstring

Returns string

Example

str.ensureSuffix("path/to", "/"); // "path/to/"

nc.str.removePrefix()

removePrefix(input: unknown, prefix: string): string

Removes prefix if the text starts with it.

Parameters

NameType
inputunknown
prefixstring

Returns string

Example

str.removePrefix("https://example.com", "https://"); // "example.com"

nc.str.removeSuffix()

removeSuffix(input: unknown, suffix: string): string

Removes suffix if the text ends with it.

Parameters

NameType
inputunknown
suffixstring

Returns string

Example

str.removeSuffix("report.pdf", ".pdf"); // "report"

nc.str.compare()

compare(a: unknown, b: unknown, options?: CompareOptions): number

Compares two strings the way people sort them: numbers in natural order and accents in the right place. Pass it straight to sort().

Parameters

NameType
aunknown
bunknown
optionsoptionalCompareOptions

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" }); // 0

nc.str.levenshtein()

levenshtein(a: unknown, b: unknown): number

The number of single-character edits needed to turn a into b.

Parameters

NameType
aunknown
bunknown

Returns number

Example

str.levenshtein("kitten", "sitting"); // 3

nc.str.similarity()

similarity(a: unknown, b: unknown): number

How alike two strings are, from 0 (nothing in common) to 1 (identical).

Parameters

NameType
aunknown
bunknown

Returns number

Example

str.similarity("hello", "hallo"); // 0.8

nc.str.closest()

closest(input: unknown, candidates: Iterable<string>, options?: ClosestOptions): string | undefined

Finds the candidate closest to input. Made for "Did you mean...?" suggestions.

Parameters

NameType
inputunknown
candidatesIterable<string>
optionsoptionalClosestOptions

Returns string | undefined: undefined when nothing is close enough.

Example

str.closest("instal", ["install", "uninstall", "list"]); // "install"
str.closest("xyz", ["install", "list"]);                 // undefined

nc.str.random()

random(size?: number, options?: string | RandomStringOptions): string

A 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

NameTypeDescription
sizeoptionalnumberDefault: 16
optionsoptionalRandomStringOptions | stringOptions, 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().

PropertyTypeDescription
thresholdoptionalnumberMinimum similarity (0 to 1) to accept a match. Defaults to 0.4.
caseSensitiveoptionalbooleanTake case into account.

CompareOptions

Options for compare().

PropertyTypeDescription
localeoptionalstringLanguage used for alphabetical order. Defaults to the system's.
numericoptionalbooleanSort 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().

PropertyTypeDescription
startoptionalnumberCharacters left visible at the start. Defaults to 0.
endoptionalnumberCharacters left visible at the end. Defaults to 4.
charoptionalstringMask character. Defaults to "*".
keepSpacesoptionalbooleanLeave 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.

PropertyTypeDescription
otherstringThe general plural, like "files".
zerooptionalstringUsed for 0 in any language, like "no files".
oneoptionalstringThe singular, like "file". French also uses it for 0.
twooptionalstringDual form (Arabic, Hebrew, Slovenian...).
fewoptionalstring"Few" form (Polish, Czech, Russian...).
manyoptionalstring"Many" form (Polish, Russian, Arabic...).

PluralOptions

Options for plural().

PropertyTypeDescription
localeoptionalstringLanguage whose plural rules apply. Defaults to "en".
includeCountoptionalbooleanPut the formatted count before the word. Defaults to true.
ordinaloptionalbooleanUse ordinal rules (1st, 2nd, 3rd).

RandomStringOptions

Options for random().

PropertyTypeDescription
charsetoptionalstringCharacters to pick from. Defaults to letters and digits.

SlugifyOptions

Options for slugify().

PropertyTypeDescription
separatoroptionalstringPlaced between words. Defaults to "-".
loweroptionalbooleanLowercase the result. Defaults to true.
maxLengthoptionalnumberMaximum length, cut on a word boundary when possible.

TemplateOptions

Options for template().

PropertyTypeDescription
openoptionalstringOpening delimiter. Defaults to "{".
closeoptionalstringClosing delimiter. Defaults to "}".
fallbackoptionalstringUsed for missing values. Without it, their placeholders stay as they are.

TruncateOptions

Options for truncate().

PropertyTypeDescription
omissionoptionalstringAdded where the text is cut, and counted in the length. Defaults to "…".
wordsoptionalbooleanCut at the previous space rather than inside a word.

WrapOptions

Options for wrap().

PropertyTypeDescription
widthoptionalnumberMaximum visible characters per line. Defaults to 80.
indentoptionalstringAdded at the start of every line.
cutoptionalbooleanBreak words longer than width instead of letting them overflow.
newlineoptionalstringLine separator. Defaults to "\n".
node-comfort v2.0.0View the source