receta

String

43 exports from @ontologyio/receta/string.

Everything exported from @ontologyio/receta/string.

Functions

between

Extracts text between two delimiters.

Returns Some with the extracted text if both delimiters are found, None otherwise.

Data-first
function between(start: string, end: string, str: string): Option<string>
Data-last
function between(start: string, end: string): (str: string) => Option<string>
Example
// Data-first
between('[', ']', 'Hello [world]!')
// => Some('world')

between('$', '.', 'Price: $99.99')
// => Some('99')

between('[', ']', 'No delimiters')
// => None

between('[', ']', '[first] and [second]')
// => Some('first') (only returns first match)

// Data-last (in pipe)
import { unwrapOr } from '@ontologyio/receta/option'

pipe(
  'User ID: {12345}',
  between('{', '}'),
  unwrapOr('unknown')
)
// => '12345'

See also words, lines.

camelCase

Converts a string to camelCase.

Signature
function camelCase(str: string): string
Example
camelCase('hello-world')
// => 'helloWorld'

camelCase('user_profile_page')
// => 'userProfilePage'

camelCase('API KEY VALUE')
// => 'apiKeyValue'

See also pascalCase, snakeCase.

capitalize

Capitalizes the first character of a string.

Signature
function capitalize(str: string, options?: CaseOptions | undefined): string
Example
capitalize('hello world')
// => 'Hello world'

capitalize('HELLO')
// => 'HELLO' (only capitalizes first char, doesn't lowercase rest)

capitalize('')
// => ''

See also titleCase.

escapeHtml

Escapes HTML special characters.

Converts characters that have special meaning in HTML to their entity equivalents:

  • & → &
  • < → <
  • → >

  • " → "
  • ' → ' (if escapeSingleQuote is true)
Data-first
function escapeHtml(str: string, options?: EscapeHtmlOptions | undefined): string
Data-last
function escapeHtml(options: EscapeHtmlOptions): (str: string) => string
Example
// Data-first
escapeHtml('<script>alert("XSS")</script>')
// => '&lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;'

escapeHtml("It's a test", { escapeSingleQuote: true })
// => 'It&#x27;s a test'

// Data-last (in pipe)
pipe(
  userInput,
  escapeHtml({ escapeSingleQuote: true })
)

// Use in user-generated content
const safeComment = escapeHtml(userComment)

See also stripHtml, unescapeHtml.

escapeRegex

Escapes special regex characters in a string to make it safe for use in RegExp.

Escapes all regex metacharacters: . * + ? ^ $ { } ( ) | [ ] \

This is useful when you need to use user input or arbitrary strings as literal patterns in regular expressions, preventing unintended regex behavior.

Signature
function escapeRegex(str: string): string
Example
escapeRegex('Hello.')
// => 'Hello\\.'

escapeRegex('$100 (USD)')
// => '\\$100 \\(USD\\)'

escapeRegex('[a-z]+')
// => '\\[a-z\\]\\+'

// Using in regex pattern
const userInput = 'example.com'
const pattern = new RegExp(escapeRegex(userInput))
pattern.test('example.com') // => true
pattern.test('exampleXcom') // => false (. is literal, not wildcard)

// Search and replace with user input
const searchTerm = '$100'
const text = 'Price is $100 today'
const regex = new RegExp(escapeRegex(searchTerm), 'g')
text.replace(regex, '$200') // => 'Price is $200 today'

See also highlight.

extract

Extracts all matches of a pattern from a string.

Returns an array of all matched strings.

Data-first
function extract(str: string, pattern: RegExp): string[]
Data-last
function extract(pattern: RegExp): (str: string) => string[]
Example
// Data-first
extract('Price: $10, Discount: $5', /\$(\d+)/g)
// => ['$10', '$5']

extract('user@example.com and admin@test.org', /\S+@\S+/g)
// => ['user@example.com', 'admin@test.org']

extract('No matches here', /\d+/g)
// => []

// Data-last (in pipe)
pipe(
  logText,
  extract(/\d{4}-\d{2}-\d{2}/g), // Extract dates
  R.unique
)

See also between.

highlight

Highlights matching substrings by wrapping them in HTML tags.

Searches for the query string within the text and wraps all matches in HTML tags (default: <mark>). Useful for search results, autocomplete, and text highlighting.

By default, escapes HTML to prevent XSS attacks. Set escapeHtml: false if the input is already trusted/sanitized.

Data-first
function highlight(text: string, query: string, options?: HighlightOptions | undefined): string
Data-last
function highlight(query: string, options?: HighlightOptions | undefined): (text: string) => string
Example
// Data-first
highlight('Hello world', 'world')
// => 'Hello <mark>world</mark>'

highlight('JavaScript and TypeScript', 'script')
// => 'Java<mark>Script</mark> and Type<mark>Script</mark>'

// Case-insensitive (default)
highlight('Hello WORLD', 'world')
// => 'Hello <mark>WORLD</mark>'

// Custom tag and class
highlight('Search term here', 'term', {
  tag: 'span',
  className: 'highlight'
})
// => 'Search <span class="highlight">term</span> here'

// Case-sensitive
highlight('Hello World', 'world', { caseInsensitive: false })
// => 'Hello World' (no match due to case)

// Empty query returns original text
highlight('Hello world', '')
// => 'Hello world'

// HTML escaping (default, prevents XSS)
highlight('<script>alert("xss")</script>', 'script')
// => '&lt;<mark>script</mark>&gt;alert(&quot;xss&quot;)&lt;/<mark>script</mark>&gt;'

// Data-last (in pipe)
pipe(
  searchResults.map(r => r.title),
  R.map(highlight(searchQuery, { className: 'search-highlight' }))
)

See also escapeRegex, escapeHtml.

initials

Extracts initials from a name or phrase.

Splits the input by whitespace and takes the first character of each word. Commonly used for user avatars, labels, and displays.

Data-first
function initials(name: string, options?: InitialsOptions | undefined): string
Data-last
function initials(options?: InitialsOptions | undefined): (name: string) => string
Example
// Data-first
initials('John Doe')
// => 'JD'

initials('Mary Jane Watson')
// => 'MJW'

initials('Mary Jane Watson', { maxInitials: 2 })
// => 'MJ'

initials('john doe', { uppercase: false })
// => 'jd'

initials('  Multiple   Spaces  ')
// => 'MS'

initials('')
// => ''

initials('Single')
// => 'S'

// Data-last (in pipe)
pipe(
  user.fullName,
  initials({ maxInitials: 2 })
)
// => 'JD'

// Common use case: Avatar labels
const avatarLabel = pipe(
  'Robert Downey Jr.',
  initials({ maxInitials: 2 })
) // => 'RD'

See also capitalize, words.

isAlphanumeric

Validates if a string contains only alphanumeric characters.

Signature
function isAlphanumeric(str: string): boolean
Example
isAlphanumeric('hello123')
// => true

isAlphanumeric('hello-world')
// => false

isAlphanumeric('123')
// => true

isBlank

Checks if a string is blank (empty or whitespace-only).

Alias for isEmpty.

Signature
function isBlank(str: string): boolean

See also isEmpty.

isEmail

Validates if a string is a valid email address.

Returns Some with the email if valid, None otherwise. Uses a practical regex that covers most common email formats.

Signature
function isEmail(str: string): Option<string>
Example
isEmail('user@example.com')
// => Some('user@example.com')

isEmail('invalid.email')
// => None

isEmail('user+tag@domain.co.uk')
// => Some('user+tag@domain.co.uk')

// Use in forms
const email = pipe(
  formData.email,
  isEmail,
  unwrapOr('Invalid email')
)

See also isUrl.

isEmpty

Checks if a string is empty or contains only whitespace.

Signature
function isEmpty(str: string): boolean
Example
isEmpty('')
// => true

isEmpty('   ')
// => true

isEmpty('hello')
// => false

isEmpty('  hello  ')
// => false

See also isBlank.

isHexColor

Validates if a string is a valid hexadecimal color.

Supports 3, 6, and 8 character hex colors with optional # prefix.

Signature
function isHexColor(str: string): Option<string>
Example
isHexColor('#ff0000')
// => Some('#ff0000')

isHexColor('fff')
// => Some('fff')

isHexColor('#ff00ff80')
// => Some('#ff00ff80') (with alpha)

isHexColor('not-a-color')
// => None

isNumeric

Validates if a string contains only numeric characters.

Signature
function isNumeric(str: string): boolean
Example
isNumeric('12345')
// => true

isNumeric('123.45')
// => false

isNumeric('12a34')
// => false

isUrl

Validates if a string is a valid URL.

Returns Some with the URL if valid, None otherwise. Supports http, https, and protocol-relative URLs.

Signature
function isUrl(str: string): Option<string>
Example
isUrl('https://example.com')
// => Some('https://example.com')

isUrl('not a url')
// => None

isUrl('http://localhost:3000/path')
// => Some('http://localhost:3000/path')

// Use in validation
const website = pipe(
  formData.website,
  isUrl,
  match({
    onSome: (url) => url,
    onNone: () => 'Invalid URL'
  })
)

See also isEmail.

kebabCase

Converts a string to kebab-case.

Signature
function kebabCase(str: string): string
Example
kebabCase('helloWorld')
// => 'hello-world'

kebabCase('UserProfilePage')
// => 'user-profile-page'

kebabCase('API_KEY_VALUE')
// => 'api-key-value'

See also slugify, snakeCase.

lines

Splits a string into an array of lines.

Handles different line ending styles (\n, \r\n, \r).

Signature
function lines(str: string): string[]
Example
lines('hello\nworld')
// => ['hello', 'world']

lines('line1\r\nline2\r\nline3')
// => ['line1', 'line2', 'line3']

lines('single line')
// => ['single line']

// Use with pipe
pipe(
  multilineText,
  lines,
  R.filter(line => !isEmpty(line)),
  R.map(trim)
)

See also words.

normalizeWhitespace

Normalizes whitespace in a string by replacing multiple consecutive whitespace characters with a single space and trimming leading/trailing whitespace.

This includes:

  • Multiple spaces → single space
  • Tabs → single space
  • Newlines → single space
  • Mixed whitespace → single space
  • Leading/trailing whitespace → removed

Useful for cleaning up user input, normalizing text for search/comparison, and formatting data from external sources.

Signature
function normalizeWhitespace(str: string): string
Example
normalizeWhitespace('Hello    world')
// => 'Hello world'

normalizeWhitespace('  foo\t\tbar  ')
// => 'foo bar'

normalizeWhitespace('line1\n\nline2\n\n\nline3')
// => 'line1 line2 line3'

normalizeWhitespace('mixed   \t\n  whitespace')
// => 'mixed whitespace'

normalizeWhitespace('')
// => ''

// Useful for search normalization
const searchQuery = normalizeWhitespace(userInput)

// Or data cleanup
const cleanedData = pipe(
  rawText,
  normalizeWhitespace,
  trim
)

See also trim, stripHtml.

parseTemplate

Extracts variable names from a template string.

Parses {{variable}} placeholders and returns an array of unique variable names.

Signature
function parseTemplate(templateStr: string): string[]
Example
parseTemplate('Hello {{name}}, you have {{count}} messages')
// => ['name', 'count']

parseTemplate('{{user}} sent {{user}} a message')
// => ['user'] (duplicates removed)

parseTemplate('No variables here')
// => []

See also template.

pascalCase

Converts a string to PascalCase.

Signature
function pascalCase(str: string): string
Example
pascalCase('hello-world')
// => 'HelloWorld'

pascalCase('user_profile_page')
// => 'UserProfilePage'

pascalCase('api key value')
// => 'ApiKeyValue'

See also camelCase, kebabCase.

pluralize

Pluralizes a word based on count, with smart English pluralization rules.

By default, applies standard English pluralization:

  • Words ending in 's', 'ss', 'sh', 'ch', 'x', 'z' → add 'es'
  • Words ending in consonant + 'y' → replace 'y' with 'ies'
  • Words ending in 'f' or 'fe' → replace with 'ves'
  • All others → add 's'

For irregular plurals, provide a custom plural form via options.

Data-first
function pluralize(word: string, count: number, options?: PluralizeOptions | undefined): string
Data-last
function pluralize(count: number, options?: PluralizeOptions | undefined): (word: string) => string
Example
// Data-first
pluralize('item', 1)
// => '1 item'

pluralize('item', 5)
// => '5 items'

pluralize('box', 3)
// => '3 boxes'

pluralize('story', 2)
// => '2 stories'

pluralize('knife', 4)
// => '4 knives'

// Custom plural
pluralize('person', 3, { plural: 'people' })
// => '3 people'

// Word only
pluralize('category', 2, { wordOnly: true })
// => 'categories'

// Data-last (in pipe)
pipe(
  users.length,
  (count) => pluralize('user', count)
)
// => '42 users'

See also toOrdinal.

slugify

Converts a string to a URL-safe slug.

Transforms the input by:

  • Converting to lowercase
  • Replacing spaces and special characters with hyphens
  • Removing consecutive hyphens
  • Trimming leading/trailing hyphens
Signature
function slugify(str: string): string
Example
slugify('Hello World!')
// => 'hello-world'

slugify('  TypeScript & JavaScript  ')
// => 'typescript-javascript'

slugify('10 Tips for Better Code')
// => '10-tips-for-better-code'

slugify('Café Münster')
// => 'cafe-munster'

See also kebabCase.

snakeCase

Converts a string to snake_case.

Signature
function snakeCase(str: string): string
Example
snakeCase('helloWorld')
// => 'hello_world'

snakeCase('UserProfilePage')
// => 'user_profile_page'

snakeCase('API-KEY-VALUE')
// => 'api_key_value'

See also kebabCase, camelCase.

stripHtml

Removes all HTML tags from a string.

Strips all HTML tags, leaving only the text content. Does not decode HTML entities - use unescapeHtml for that.

Signature
function stripHtml(str: string): string
Example
stripHtml('<p>Hello <strong>world</strong>!</p>')
// => 'Hello world!'

stripHtml('<script>alert("xss")</script>Safe text')
// => 'Safe text'

stripHtml('No tags here')
// => 'No tags here'

// Use for user-generated content
pipe(
  userComment,
  stripHtml,
  truncate({ length: 100 })
)

See also escapeHtml.

template

Safely interpolates variables into a template string.

Uses {{variable}} syntax for interpolation. Returns an error if any variables are missing from the provided values.

Data-first
function template(templateStr: string, vars: TemplateVars): Result<string, TemplateError>
Data-last
function template(vars: TemplateVars): (templateStr: string) => Result<string, TemplateError>

Fails with TemplateError.

Example
// Data-first
template('Hello {{name}}!', { name: 'Alice' })
// => Ok('Hello Alice!')

template('Hello {{name}}!', {})
// => Err({ type: 'missing_variable', variable: 'name' })

// Data-last (in pipe)
pipe(
  'Welcome {{user}}, you have {{count}} messages',
  template({ user: 'Bob', count: 5 })
)
// => Ok('Welcome Bob, you have 5 messages')

See also parseTemplate.

titleCase

Converts a string to Title Case.

Capitalizes the first letter of each word. Words are separated by spaces.

Signature
function titleCase(str: string, options?: CaseOptions | undefined): string
Example
titleCase('hello world')
// => 'Hello World'

titleCase('the quick brown fox')
// => 'The Quick Brown Fox'

titleCase('user-profile-page')
// => 'User-profile-page' (only capitalizes after spaces)

See also capitalize.

trim

Trims whitespace from both ends of a string.

Enhanced version of String.prototype.trim that's pipe-friendly.

Signature
function trim(str: string): string
Example
trim('  hello  ')
// => 'hello'

trim('\n\t  test  \n')
// => 'test'

// Use in pipes
pipe(
  userInput,
  trim,
  truncate({ length: 50 })
)

See also trimStart, trimEnd.

trimEnd

Trims whitespace from the end of a string.

Signature
function trimEnd(str: string): string
Example
trimEnd('  hello  ')
// => '  hello'

trimEnd('test\n\t  ')
// => 'test'

See also trim, trimStart.

trimStart

Trims whitespace from the start of a string.

Signature
function trimStart(str: string): string
Example
trimStart('  hello  ')
// => 'hello  '

trimStart('\n\t  test')
// => 'test'

See also trim, trimEnd.

truncate

Truncates a string to a maximum length.

If the string exceeds the maximum length, it's truncated and an ellipsis is appended. Can optionally truncate at word boundaries to avoid cutting words.

Data-first
function truncate(str: string, options: TruncateOptions): string
Data-last
function truncate(options: TruncateOptions): (str: string) => string
Example
// Data-first
truncate('Hello world', { length: 8 })
// => 'Hello...'

truncate('Hello world', { length: 8, ellipsis: '…' })
// => 'Hello w…'

truncate('The quick brown fox', { length: 15, words: true })
// => 'The quick...'

truncate('Short', { length: 10 })
// => 'Short' (unchanged if under limit)

// Data-last (in pipe)
pipe(
  'A very long string that needs truncation',
  truncate({ length: 20, words: true })
)
// => 'A very long...'

See also words.

truncateWords

Truncates a string to a maximum number of words.

Unlike character-based truncation, this preserves complete words and truncates at word boundaries. Words are determined by whitespace.

Data-first
function truncateWords(str: string, maxWords: number, options?: TruncateWordsOptions | undefined): string
Data-last
function truncateWords(maxWords: number, options?: TruncateWordsOptions | undefined): (str: string) => string
Example
// Data-first
truncateWords('The quick brown fox jumps', 3)
// => 'The quick brown...'

truncateWords('Hello world', 5)
// => 'Hello world' (unchanged if under limit)

truncateWords('One two three four', 2, { suffix: ' […]' })
// => 'One two […]'

truncateWords('Single', 3)
// => 'Single' (no suffix if not truncated)

// Data-last (in pipe)
pipe(
  'A long article preview with many words in it',
  truncateWords(5)
)
// => 'A long article preview with...'

See also truncate, words.

unescapeHtml

Decodes HTML entities to their character equivalents.

Signature
function unescapeHtml(str: string): string
Example
unescapeHtml('&lt;script&gt;')
// => '<script>'

unescapeHtml('&quot;Hello&quot;')
// => '"Hello"'

unescapeHtml('&amp; &lt; &gt;')
// => '& < >'

See also escapeHtml.

words

Splits a string into an array of words.

By default, splits on non-alphanumeric characters. Custom pattern can be provided.

Data-first
function words(str: string, options?: WordsOptions | undefined): string[]
Data-last
function words(options: WordsOptions): (str: string) => string[]
Example
// Data-first
words('hello world')
// => ['hello', 'world']

words('user-profile-page')
// => ['user', 'profile', 'page']

words('oneTwo three_four')
// => ['oneTwo', 'three', 'four']

words('hello, world!')
// => ['hello', 'world']

// Data-last (in pipe)
pipe(
  'The quick brown fox',
  (str) => words(str),
  R.map((word) => capitalize(word))
)
// => ['The', 'Quick', 'Brown', 'Fox']

See also lines, between.

Types

CaseOptions

Options for case conversion functions.

Signature
interface CaseOptions {
  readonly locale?: string | string[]
}

EscapeHtmlOptions

Options for HTML escaping.

Signature
interface EscapeHtmlOptions {
  readonly escapeSingleQuote?: boolean
}

HighlightOptions

Options for highlight function.

Signature
interface HighlightOptions {
  readonly tag?: string

  readonly className?: string

  readonly caseInsensitive?: boolean

  readonly escapeHtml?: boolean
}

InitialsOptions

Options for initials function.

Signature
interface InitialsOptions {
  readonly maxInitials?: number

  readonly uppercase?: boolean
}

PluralizeOptions

Options for pluralize function.

Signature
interface PluralizeOptions {
  readonly plural?: string

  readonly wordOnly?: boolean
}

TemplateError

Template interpolation error types.

Signature
type TemplateError =
  | { readonly type: 'missing_variable'; readonly variable: string }
  | { readonly type: 'invalid_template'; readonly message: string }

TemplateVars

Variable map for template interpolation.

Signature
type TemplateVars = Record<string, string | number | boolean | null | undefined>

TruncateOptions

Options for truncating a string.

Signature
interface TruncateOptions {
  readonly length: number

  readonly ellipsis?: string

  readonly words?: boolean
}

TruncateWordsOptions

Options for truncateWords function.

Signature
interface TruncateWordsOptions {
  readonly suffix?: string
}

WordsOptions

Options for splitting text into words.

Signature
interface WordsOptions {
  readonly pattern?: RegExp
}

On this page