UNPKG

@oxog/string

Version:

Comprehensive string manipulation utilities with zero dependencies

138 lines (137 loc) 4.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.reverse = reverse; exports.shuffle = shuffle; exports.repeat = repeat; exports.truncate = truncate; exports.pad = pad; exports.wrap = wrap; exports.slugify = slugify; const unicode_1 = require("../utils/unicode"); const unicode_2 = require("../utils/unicode"); function reverse(str) { return (0, unicode_1.reverseUnicode)(str); } function shuffle(str) { const chars = (0, unicode_1.getGraphemes)(str); for (let i = chars.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [chars[i], chars[j]] = [chars[j], chars[i]]; } return chars.join(''); } function repeat(str, count, separator = '') { if (count < 0) { throw new Error('Count must be non-negative'); } if (count === 0) return ''; if (count === 1) return str; const parts = []; for (let i = 0; i < count; i++) { parts.push(str); } return parts.join(separator); } function truncate(str, length, options = {}) { const { suffix = '...', preserveWords = false } = options; if (str.length <= length) return str; if (preserveWords) { const words = str.split(/\s+/); let result = ''; for (const word of words) { const potential = result ? `${result} ${word}` : word; if (potential.length + suffix.length > length) { break; } result = potential; } return result ? result + suffix : str.slice(0, Math.max(0, length - suffix.length)) + suffix; } return str.slice(0, Math.max(0, length - suffix.length)) + suffix; } function pad(str, length, fillString = ' ', type = 'end') { if (str.length >= length) return str; const padLength = length - str.length; const fill = fillString.repeat(Math.ceil(padLength / fillString.length)).slice(0, padLength); switch (type) { case 'start': return fill + str; case 'end': return str + fill; case 'both': const leftPadLength = Math.floor(padLength / 2); const rightPadLength = padLength - leftPadLength; const leftFill = fillString.repeat(Math.ceil(leftPadLength / fillString.length)).slice(0, leftPadLength); const rightFill = fillString.repeat(Math.ceil(rightPadLength / fillString.length)).slice(0, rightPadLength); return leftFill + str + rightFill; default: return str + fill; } } function wrap(str, width, options = {}) { const { indent = '', cut = false } = options; if (width <= 0) return str; const words = str.split(/\s+/); const lines = []; let currentLine = ''; for (const word of words) { const potential = currentLine ? `${currentLine} ${word}` : word; const potentialWidth = (0, unicode_1.getStringWidth)(potential); if (potentialWidth <= width) { currentLine = potential; } else { if (currentLine) { lines.push(indent + currentLine); currentLine = word; } else { // Word is longer than width if (cut) { const chars = (0, unicode_1.getGraphemes)(word); let chunk = ''; for (const char of chars) { const chunkWidth = (0, unicode_1.getStringWidth)(chunk + char); if (chunkWidth > width && chunk) { lines.push(indent + chunk); chunk = char; } else { chunk += char; } } if (chunk) { currentLine = chunk; } } else { currentLine = word; } } } } if (currentLine) { lines.push(indent + currentLine); } return lines.join('\n'); } function slugify(str, options = {}) { const { separator = '-', lowercase = true, strict = false, locale } = options; let result = (0, unicode_2.removeAccents)(str); if (lowercase) { result = locale ? result.toLocaleLowerCase(locale) : result.toLowerCase(); } if (strict) { result = result.replace(/[^a-zA-Z0-9]+/g, separator); } else { result = result.replace(/[^\w\s-]/g, '').replace(/[\s_-]+/g, separator); } result = result.replace(new RegExp(`^\\${separator}+|\\${separator}+$`, 'g'), ''); return result; }