Str.Text
Str / Text
Import
import { Str } from '@wollybeard/kit'
// Access via namespace
Str.Text.someFunction()
import * as Str from '@wollybeard/kit/str'
// Access via namespace
Str.Text.someFunction()
Text Formatting
[C]
defaultIndentCharacter
' '
Default character used for indentation (non-breaking space).
[C]
defaultLineSeparator
'\n'
Default line separator character (newline).
[T]
Column
type Column = string[]
A column is a vertical stack of lines.
[C]
lines
(value: string) => string[]
Split text into an array of lines. Pre-configured splitWith using newline separator.
Examples:
Str.Text.lines('hello\nworld\n!') // ['hello', 'world', '!']
Str.Text.lines('single line') // ['single line']
[C]
unlines
;((value: string[]) => string)
Join an array of lines into text. Pre-configured joinWith using newline separator.
Examples:
Str.Text.unlines(['hello', 'world', '!']) // 'hello\nworld\n!'
Str.Text.unlines(['single line']) // 'single line'
[F]
indent
(text: string, size?: number | undefined): string
Parameters:
text
- The text to indentsize
- Number of spaces to indent (default: defaultIndentSize)
Returns: The indented text
Indent each line of text by a specified number of spaces.
Examples:
Str.Text.indent('hello\nworld') // ' hello\n world'
Str.Text.indent('line1\nline2', 4) // ' line1\n line2'
[C]
indentOn
;((text: string) => (size?: number | undefined) => string)
Curried version of indent with text first.
[C]
indentWith
;((size?: number | undefined) => (text: string) => string)
Curried version of indent with size first.
Examples:
const indent4 = Str.Text.indentWith(4)
indent4('hello\nworld') // ' hello\n world'
[F]
indentBy
(text: string, prefixOrFn: string | ((line: string, lineIndex: number) => string)): string
Parameters:
text
- The text to indentprefixOrFn
- String to prepend to each line, or function(line: string, lineIndex: number) => string
Returns: The indented text
Indent each line using a custom prefix string or function. When given a function, it receives both the line content and index, allowing for content-aware indentation.
Examples:
// Fixed string prefix
Str.Text.indentBy('hello\nworld', '>>> ') // '>>> hello\n>>> world'
// Dynamic prefix based on line index (ignore line content with _)
Str.Text.indentBy('line1\nline2\nline3', (_, i) => `${i + 1}. `)
// '1. line1\n2. line2\n3. line3'
// Content-aware indentation
Str.Text.indentBy('title\nitem', (line, i) => line === 'title' ? '' : ' ')
// 'title\n item'
[C]
indentByOn
;((text: string) =>
(prefixOrFn: string | ((line: string, lineIndex: number) => string)) => string)
Curried version of indentBy with text first.
[C]
indentByWith
;((prefixOrFn: string | ((line: string, lineIndex: number) => string)) =>
(text: string) => string)
Curried version of indentBy with prefix first.
Examples:
const addArrow = Str.Text.indentByWith('→ ')
addArrow('hello\nworld') // '→ hello\n→ world'
const numbered = Str.Text.indentByWith((_, i) => `${i}. `)
numbered('first\nsecond') // '0. first\n1. second'
const conditionalIndent = Str.Text.indentByWith((line, i) =>
line.startsWith('#') ? '' : ' '
)
conditionalIndent('# Title\nContent') // '# Title\n Content'
[F]
stripIndent
(text: string): string
Parameters:
text
- The text to dedent
Returns: The dedented text
Remove common leading whitespace from all lines. Finds the minimum indentation across all non-empty lines and removes that amount from every line. This is useful for dedenting code blocks or template strings while preserving relative indentation.
Examples:
Str.Text.stripIndent(' line1\n line2\n line3')
// 'line1\n line2\nline3'
Str.Text.stripIndent(' code\n nested\n code')
// 'code\n nested\ncode'
// Empty lines are ignored when calculating minimum indent
Str.Text.stripIndent(' line1\n\n line2')
// 'line1\n\nline2'
[C]
defaultPadCharacter
' '
Default character used for padding.
[F]
pad
(text: string, size: number, side?: "left" | "right" = `left`, char?: string = defaultPadCharacter): string
Parameters:
text
- The text to padsize
- Number of padding characters to addside
- Which side to add padding ('left' or 'right')char
- Character to use for padding (default: space)
Returns: The padded text
Add padding characters to text.
Examples:
Str.Text.pad('hello', 3, 'left') // ' hello'
Str.Text.pad('hello', 3, 'right') // 'hello '
Str.Text.pad('hello', 2, 'left', '-') // '--hello'
[C]
padOn
;((text: string) =>
(size: number) =>
(side?: 'left' | 'right' | undefined) =>
(char?: string | undefined) => string)
Curried version of pad with text first.
[C]
padWith
;((size: number) =>
(text: string) =>
(side?: 'left' | 'right' | undefined) =>
(char?: string | undefined) => string)
Curried version of pad with size first.
[F]
padLeft
(text: string, size: number, char?: string = defaultPadCharacter): string
Parameters:
text
- The text to padsize
- Number of padding characters to addchar
- Character to use for padding (default: space)
Returns: The left-padded text
Add left padding to text.
Examples:
Str.Text.padLeft('hello', 3) // ' hello'
Str.Text.padLeft('hello', 2, '0') // '00hello'
[C]
padLeftOn
;((text: string) => (size: number) => (char?: string | undefined) => string)
Curried version of padLeft with text first.
[C]
padLeftWith
;((size: number) => (text: string) => (char?: string | undefined) => string)
Curried version of padLeft with size first.
Examples:
const pad3 = Str.Text.padLeftWith(3)
pad3('hi') // ' hi'
[F]
padRight
(text: string, size: number, char?: string = defaultPadCharacter): string
Parameters:
text
- The text to padsize
- Number of padding characters to addchar
- Character to use for padding (default: space)
Returns: The right-padded text
Add right padding to text.
Examples:
Str.Text.padRight('hello', 3) // 'hello '
Str.Text.padRight('hello', 2, '.') // 'hello..'
[C]
padRightOn
;((text: string) => (size: number) => (char?: string | undefined) => string)
Curried version of padRight with text first.
[C]
padRightWith
;((size: number) => (text: string) => (char?: string | undefined) => string)
Curried version of padRight with size first.
Examples:
const pad3 = Str.Text.padRightWith(3)
pad3('hi') // 'hi '
[F]
span
(text: string, width: number, align?: "left" | "right" = `left`, char?: string = defaultPadCharacter): string
Parameters:
text
- The text to alignwidth
- Target width (in characters)align
- Content alignment ('left' or 'right')char
- Character to use for padding (default: space)
Returns: The aligned text
Align text within a specified width by adding padding.
This ensures text spans exactly the target width, aligning content to the left or right. If the text is already wider than the target width, no padding is added.
Examples:
// Left-align (pad right)
Str.span('hi', 5, 'left') // 'hi '
// Right-align (pad left)
Str.span('hi', 5, 'right') // ' hi'
// Text already wider - no padding added
Str.span('hello world', 5, 'left') // 'hello world' (unchanged)
[C]
spanOn
;((text: string) =>
(width: number) =>
(align?: 'left' | 'right' | undefined) =>
(char?: string | undefined) => string)
Curried version of span with text first.
[C]
spanWith
;((width: number) =>
(text: string) =>
(align?: 'left' | 'right' | undefined) =>
(char?: string | undefined) => string)
Curried version of span with width first.
Examples:
const span8 = Str.spanWith(8)
span8('Name', 'left') // 'Name '
span8('Age', 'right') // ' Age'
[F]
fit
(text: string, width: number, align?: "left" | "right" = `left`, char?: string = defaultPadCharacter): string
Parameters:
text
- The text to constrainwidth
- Exact target width (in characters)align
- Content alignment ('left' or 'right')char
- Character to use for padding (default: space)
Returns: Text constrained to exact width
Constrain text to exact width by cropping and/or padding.
Unlike span which only pads (leaving text unchanged if too long), this function guarantees the exact width by:
- Cropping text if it exceeds the target width
- Padding text if it's shorter than the target width
This is useful for fixed-width layouts where column widths must be exact, such as table columns, CSV files, and fixed-format text files.
Examples:
// Text too long - gets cropped
Str.fit('hello world', 5, 'left') // 'hello'
// Text too short - gets padded
Str.fit('hi', 5, 'left') // 'hi '
Str.fit('hi', 5, 'right') // ' hi'
// Perfect fit - unchanged
Str.fit('exact', 5, 'left') // 'exact'
// Use case: Fixed-width table columns
const columns = ['Name', 'Email', 'Status'].map(
(header, i) => Str.fit(header, [10, 20, 8][i], 'left'),
)
// ['Name ', 'Email ', 'Status ']
// CSV formatting with fixed columns
const row = [name, email, status].map((val, i) =>
Str.fit(val, [20, 30, 10][i], 'left')
).join(',')
[C]
fitOn
;((text: string) =>
(width: number) =>
(align?: 'left' | 'right' | undefined) =>
(char?: string | undefined) => string)
Curried version of fit with text first.
[C]
fitWith
;((width: number) =>
(text: string) =>
(align?: 'left' | 'right' | undefined) =>
(char?: string | undefined) => string)
Curried version of fit with width first.
Examples:
// Create fixed-width formatters
const nameColumn = Str.fitWith(20)
const statusColumn = Str.fitWith(10)
nameColumn('John Doe', 'left') // 'John Doe '
statusColumn('Active', 'left') // 'Active '
statusColumn('Very Long Status', 'left') // 'Very Long '
[F]
mapLines
(text: string, fn: (line: string, index: number) => string): string
Parameters:
text
- The text to transformfn
- Function to apply to each line, receiving the line and its index
Returns: The transformed text
Map a transformation function over each line of text.
Examples:
Str.Text.mapLines('hello\nworld', (line) => line.toUpperCase())
// 'HELLO\nWORLD'
Str.Text.mapLines('a\nb\nc', (line, i) => `${i}: ${line}`)
// '0: a\n1: b\n2: c'
[C]
mapLinesOn
;((text: string) => (fn: (line: string, index: number) => string) => string)
Curried version of mapLines with text first.
[C]
mapLinesWith
;((fn: (line: string, index: number) => string) => (text: string) => string)
Curried version of mapLines with function first.
Examples:
const uppercase = Str.Text.mapLinesWith((line) => line.toUpperCase())
uppercase('hello\nworld') // 'HELLO\nWORLD'
[T]
StyledPrefix
type StyledPrefix = {
/**
* The prefix text/symbol to display.
*/
symbol: string
/**
* Optional function to colorize the prefix.
*/
color?: (text: string) => string
}
Styled prefix that can have an optional color function. Used with formatBlock for colored line prefixes.
[F]
formatBlock
(block: string, opts: { prefix?: string | StyledPrefix; indent?: number; excludeFirstLine?: boolean; }): string
Parameters:
block
- The text block to formatopts
- Formatting options
Returns: Formatted text block
Format a multi-line text block with line-by-line transformations.
Processes each line of text, adding a prefix and optional indentation. Supports excluding the first line and styled prefixes with colors.
Examples:
// Simple string prefix
Str.Text.formatBlock('line1\nline2\nline3', { prefix: '> ' })
// '> line1\n> line2\n> line3'
// With indentation
Str.Text.formatBlock('line1\nline2', { prefix: '| ', indent: 2 })
// '| line1\n| line2'
// Exclude first line (useful for continuing indentation)
Str.Text.formatBlock('header\nline1\nline2', {
prefix: ' ',
excludeFirstLine: true,
})
// 'header\n line1\n line2'
// Single line - returned as-is
Str.Text.formatBlock('single', { prefix: '> ' })
// 'single'
// Styled prefix with color function
Str.Text.formatBlock('data\nmore data', {
prefix: {
symbol: '│ ',
color: (text) => `\x1b[90m${text}\x1b[0m`, // gray color
},
indent: 2,
})
// '\x1b[90m│ \x1b[0m data\n\x1b[90m│ \x1b[0m more data'
[C]
formatBlockOn
;((block: string) =>
(
opts: {
prefix?: string | StyledPrefix
indent?: number
excludeFirstLine?: boolean
},
) => string)
Curried version of formatBlock with block first.
[C]
formatBlockWith
;((
opts: {
prefix?: string | StyledPrefix
indent?: number
excludeFirstLine?: boolean
},
) =>
(block: string) => string)
Curried version of formatBlock with options first.
Examples:
const addSpine = Str.Text.formatBlockWith({ prefix: '│ ', indent: 2 })
addSpine('line1\nline2\nline3')
// '│ line1\n│ line2\n│ line3'
Text Formatting 2
[C]
defaultIndentSize
2
Default indentation size in characters.