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.
function between(start: string, end: string, str: string): Option<string>function between(start: string, end: string): (str: string) => Option<string>// 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.
function camelCase(str: string): stringcamelCase('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.
function capitalize(str: string, options?: CaseOptions | undefined): stringcapitalize('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)
function escapeHtml(str: string, options?: EscapeHtmlOptions | undefined): stringfunction escapeHtml(options: EscapeHtmlOptions): (str: string) => string// Data-first
escapeHtml('<script>alert("XSS")</script>')
// => '<script>alert("XSS")</script>'
escapeHtml("It's a test", { escapeSingleQuote: true })
// => 'It'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.
function escapeRegex(str: string): stringescapeRegex('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.
function extract(str: string, pattern: RegExp): string[]function extract(pattern: RegExp): (str: string) => string[]// 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.
function highlight(text: string, query: string, options?: HighlightOptions | undefined): stringfunction highlight(query: string, options?: HighlightOptions | undefined): (text: string) => string// 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')
// => '<<mark>script</mark>>alert("xss")</<mark>script</mark>>'
// 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.
function initials(name: string, options?: InitialsOptions | undefined): stringfunction initials(options?: InitialsOptions | undefined): (name: string) => string// 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.
function isAlphanumeric(str: string): booleanisAlphanumeric('hello123')
// => true
isAlphanumeric('hello-world')
// => false
isAlphanumeric('123')
// => trueisBlank
Checks if a string is blank (empty or whitespace-only).
Alias for isEmpty.
function isBlank(str: string): booleanSee 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.
function isEmail(str: string): Option<string>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.
function isEmpty(str: string): booleanisEmpty('')
// => true
isEmpty(' ')
// => true
isEmpty('hello')
// => false
isEmpty(' hello ')
// => falseSee also isBlank.
isHexColor
Validates if a string is a valid hexadecimal color.
Supports 3, 6, and 8 character hex colors with optional # prefix.
function isHexColor(str: string): Option<string>isHexColor('#ff0000')
// => Some('#ff0000')
isHexColor('fff')
// => Some('fff')
isHexColor('#ff00ff80')
// => Some('#ff00ff80') (with alpha)
isHexColor('not-a-color')
// => NoneisNumeric
Validates if a string contains only numeric characters.
function isNumeric(str: string): booleanisNumeric('12345')
// => true
isNumeric('123.45')
// => false
isNumeric('12a34')
// => falseisUrl
Validates if a string is a valid URL.
Returns Some with the URL if valid, None otherwise. Supports http, https, and protocol-relative URLs.
function isUrl(str: string): Option<string>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.
function kebabCase(str: string): stringkebabCase('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).
function lines(str: string): string[]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.
function normalizeWhitespace(str: string): stringnormalizeWhitespace('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.
function parseTemplate(templateStr: string): string[]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.
function pascalCase(str: string): stringpascalCase('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.
function pluralize(word: string, count: number, options?: PluralizeOptions | undefined): stringfunction pluralize(count: number, options?: PluralizeOptions | undefined): (word: string) => string// 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
function slugify(str: string): stringslugify('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.
function snakeCase(str: string): stringsnakeCase('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.
function stripHtml(str: string): stringstripHtml('<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.
function template(templateStr: string, vars: TemplateVars): Result<string, TemplateError>function template(vars: TemplateVars): (templateStr: string) => Result<string, TemplateError>Fails with TemplateError.
// 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.
function titleCase(str: string, options?: CaseOptions | undefined): stringtitleCase('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.
function trim(str: string): stringtrim(' 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.
function trimEnd(str: string): stringtrimEnd(' hello ')
// => ' hello'
trimEnd('test\n\t ')
// => 'test'See also trim, trimStart.
trimStart
Trims whitespace from the start of a string.
function trimStart(str: string): stringtrimStart(' 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.
function truncate(str: string, options: TruncateOptions): stringfunction truncate(options: TruncateOptions): (str: string) => string// 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.
function truncateWords(str: string, maxWords: number, options?: TruncateWordsOptions | undefined): stringfunction truncateWords(maxWords: number, options?: TruncateWordsOptions | undefined): (str: string) => string// 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.
function unescapeHtml(str: string): stringunescapeHtml('<script>')
// => '<script>'
unescapeHtml('"Hello"')
// => '"Hello"'
unescapeHtml('& < >')
// => '& < >'See also escapeHtml.
words
Splits a string into an array of words.
By default, splits on non-alphanumeric characters. Custom pattern can be provided.
function words(str: string, options?: WordsOptions | undefined): string[]function words(options: WordsOptions): (str: string) => string[]// 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.
interface CaseOptions {
readonly locale?: string | string[]
}EscapeHtmlOptions
Options for HTML escaping.
interface EscapeHtmlOptions {
readonly escapeSingleQuote?: boolean
}HighlightOptions
Options for highlight function.
interface HighlightOptions {
readonly tag?: string
readonly className?: string
readonly caseInsensitive?: boolean
readonly escapeHtml?: boolean
}InitialsOptions
Options for initials function.
interface InitialsOptions {
readonly maxInitials?: number
readonly uppercase?: boolean
}PluralizeOptions
Options for pluralize function.
interface PluralizeOptions {
readonly plural?: string
readonly wordOnly?: boolean
}TemplateError
Template interpolation error types.
type TemplateError =
| { readonly type: 'missing_variable'; readonly variable: string }
| { readonly type: 'invalid_template'; readonly message: string }TemplateVars
Variable map for template interpolation.
type TemplateVars = Record<string, string | number | boolean | null | undefined>TruncateOptions
Options for truncating a string.
interface TruncateOptions {
readonly length: number
readonly ellipsis?: string
readonly words?: boolean
}TruncateWordsOptions
Options for truncateWords function.
interface TruncateWordsOptions {
readonly suffix?: string
}WordsOptions
Options for splitting text into words.
interface WordsOptions {
readonly pattern?: RegExp
}