@visulima/string
Version:
Functions for manipulating strings.
101 lines (96 loc) • 3.53 kB
JavaScript
;
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;