UNPKG

@visulima/string

Version:

Functions for manipulating strings.

101 lines (96 loc) 3.53 kB
'use strict'; Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } }); const getStringTruncatedWidth = require('./get-string-truncated-width.cjs'); const slice = require('./slice.cjs'); var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); const DEFAULT_ELLIPSIS = "…"; const MAX_SPACE_SEARCH_DISTANCE = 3; const findNearestSpace = /* @__PURE__ */ __name((string_, startIndex, searchRight = false) => { if (string_.charAt(startIndex) === " ") { return startIndex; } const direction = searchRight ? 1 : -1; const limit = Math.min(MAX_SPACE_SEARCH_DISTANCE, searchRight ? string_.length - startIndex : startIndex); for (let offset = 1; offset <= limit; offset++) { const index = startIndex + offset * direction; if (string_.charAt(index) === " ") { return index; } } return startIndex; }, "findNearestSpace"); const truncate = /* @__PURE__ */ __name((input, limit, options = {}) => { if (typeof input !== "string") { throw new TypeError(`Expected \`input\` to be a string, got ${typeof input}`); } if (typeof limit !== "number") { throw new TypeError(`Expected \`limit\` to be a number, got ${typeof limit}`); } if (input === "" || limit <= 0) { return ""; } const { ellipsis = DEFAULT_ELLIPSIS, position = "end", preferTruncationOnSpace = false } = options; let ellipsisWidth = options.ellipsisWidth ?? ellipsis === DEFAULT_ELLIPSIS ? 1 : void 0; if (ellipsisWidth === void 0) { ellipsisWidth = getStringTruncatedWidth.getStringTruncatedWidth(ellipsis, { ...options.width, ellipsis: "", ellipsisWidth: 0, limit: Number.POSITIVE_INFINITY }).width; } if (limit === 1 && ellipsisWidth === 1) { return ellipsis; } if (limit === 1) { return ""; } const { width } = getStringTruncatedWidth.getStringTruncatedWidth(input, { ...options.width, ellipsis, ellipsisWidth }); if (width <= limit) { return input; } switch (position) { case "start": { if (preferTruncationOnSpace) { const nearestSpace = findNearestSpace(input, width - limit + 1, true); return ellipsis + slice.slice(input, nearestSpace, width).trim(); } return ellipsis + slice.slice(input, width - limit + ellipsisWidth, width, { width: options.width }); } case "middle": { const half = Math.floor(limit / 2); if (preferTruncationOnSpace) { const firstBreak = findNearestSpace(input, half); const secondBreak = findNearestSpace(input, width - (limit - half) + 1, true); return slice.slice(input, 0, firstBreak) + ellipsis + slice.slice(input, secondBreak, width).trim(); } return slice.slice(input, 0, half, { width: options.width }) + ellipsis + slice.slice(input, width - (limit - half) + ellipsisWidth, width, { width: options.width }); } case "end": { if (preferTruncationOnSpace) { const nearestSpace = findNearestSpace(input, limit - 1); return slice.slice(input, 0, nearestSpace, { width: options.width }) + ellipsis; } return slice.slice(input, 0, limit - ellipsisWidth, { width: options.width }) + ellipsis; } default: { throw new Error(`Invalid position: expected 'start', 'middle' or 'end', got '${position}'`); } } }, "truncate"); exports.truncate = truncate;