remeda
Version:
A utility library for JavaScript and Typescript.
119 lines (117 loc) • 6.96 kB
TypeScript
import { ClampedIntegerSubtract } from "./ClampedIntegerSubtract-BmNra3Vv.js";
import { And, IsEqual, IsNever, IsStringLiteral, NonNegativeInteger } from "type-fest";
//#region src/internal/types/StringLength.d.ts
/**
* Returns a literal number for literal strings.
*
* Although TypeScript provides literal length for tuples via the `length`
* property, it doesn't do so for strings.
*/
type StringLength<S extends string, Characters extends ReadonlyArray<string> = []> = IsStringLiteral<S> extends true ? S extends `${infer Character}${infer Rest}` ? StringLength<Rest, [...Characters, Character]> : Characters["length"] : number;
//#endregion
//#region src/truncate.d.ts
type TruncateOptions = {
readonly omission?: string;
readonly separator?: string | RegExp;
};
declare const DEFAULT_OMISSION = "...";
type Truncate<S extends string, N extends number, Options extends TruncateOptions> = IsNever<NonNegativeInteger<N>> extends true ? string : TruncateWithOptions<S, N, Options extends Pick<Required<TruncateOptions>, "omission"> ? Options["omission"] : typeof DEFAULT_OMISSION, Options extends Pick<Required<TruncateOptions>, "separator"> ? Options["separator"] : undefined>;
type TruncateWithOptions<S extends string, N extends number, Omission extends string, Separator extends string | RegExp | undefined> = N extends unknown ? IsEqual<N, 0> extends true ? "" : Omission extends unknown ? IsStringLiteral<Omission> extends true ? IsEqual<ClampedIntegerSubtract<N, StringLength<Omission>>, 0> extends true ? TruncateLiterals<Omission, N, ""> : And<IsStringLiteral<S>, IsEqual<Separator, undefined>> extends true ? TruncateLiterals<S, N, Omission> : string : string : never : never;
/**
* This is the actual implementation of the truncation logic. It assumes all
* its params are literals and valid.
*/
type TruncateLiterals<S extends string, N extends number, Omission extends string, Iteration extends ReadonlyArray<unknown> = []> = S extends `${infer Character}${infer Rest}` ? Iteration["length"] extends ClampedIntegerSubtract<N, StringLength<Omission>> ? IsLongerThan<S, Omission> extends true ? Omission : S : `${Character}${TruncateLiterals<Rest, N, Omission, [...Iteration, unknown]>}` : "";
/**
* An optimized check that efficiently checks if the string A is longer than B.
*/
type IsLongerThan<A extends string, B extends string> = A extends `${string}${infer RestA}` ? B extends `${string}${infer RestB}` ? IsLongerThan<RestA, RestB> : true : false;
/**
* Truncates strings longer than `n`, appending an `omission` marker to them
* (which defaults to '...'); shorter strings are returned as-is. The total
* length of the output will never exceed `n` (in the rare case where the
* `omission` itself is too long, it will be truncated too).
*
* The `separator` argument provides more control by optimistically searching
* for a matching cutoff point, which could be used to avoid truncating in the
* middle of a word or other semantic boundary.
*
* If you just need to limit the total length of the string, without adding an
* `omission` or optimizing the cutoff point via `separator`, prefer
* `sliceString` instead, which runs more efficiently.
*
* **IMPORTANT**: Prefer using CSS [`text-overflow: ellipsis`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow#ellipsis) when
* the output is rendered in a browser; this function doesn't handle
* diacritics, emojis, and any sort of semantic understanding of the string
* contents.
*
* @param data - The input string.
* @param n - The maximum length of the output string. The output will **never**
* exceed this length.
* @param options - An optional options object.
* @param options.omission - The string that is appended to the end of the
* output *whenever the input string is truncated*. Default: '...'.
* @param options.separator - A string or regular expression that defines a
* cutoff point for the truncation. If multiple cutoff points are found, the one
* closest to `n` will be used, and if no cutoff point is found then the
* function will fallback to the trivial cutoff point. Regular expressions are
* also supported. Default: <none> (which is equivalent to `""` or the regular
* expression `/./`).
* @signature
* R.truncate(data, n, { omission, separator });
* @example
* R.truncate("Hello, world!", 8); //=> "Hello..."
* R.truncate(
* "cat, dog, mouse",
* 12,
* { omission: "__", separator: ","},
* ); //=> "cat, dog__"
* @dataFirst
* @category String
*/
declare function truncate<S extends string, N extends number, const Options extends TruncateOptions>(data: S, n: N, options?: Options): Truncate<S, N, Options>;
/**
* Truncates strings longer than `n`, appending an `omission` marker to them
* (which defaults to '...'); shorter strings are returned as-is. The total
* length of the output will never exceed `n` (in the rare case where the
* `omission` itself is too long, it will be truncated too).
*
* The `separator` argument provides more control by optimistically searching
* for a matching cutoff point, which could be used to avoid truncating in the
* middle of a word or other semantic boundary.
*
* If you just need to limit the total length of the string, without adding an
* `omission` or optimizing the cutoff point via `separator`, prefer
* `sliceString` instead, which runs more efficiently.
*
* **IMPORTANT**: Prefer using CSS [`text-overflow: ellipsis`](https://developer.mozilla.org/en-US/docs/Web/CSS/text-overflow#ellipsis) when
* the output is rendered in a browser; this function doesn't handle
* diacritics, emojis, and any sort of semantic understanding of the string
* contents.
*
* @param n - The maximum length of the output string. The output will **never**
* exceed this length.
* @param options - An optional options object.
* @param options.omission - The string that is appended to the end of the
* output *whenever the input string is truncated*. Default: '...'.
* @param options.separator - A string or regular expression that defines a
* cutoff point for the truncation. If multiple cutoff points are found, the one
* closest to `n` will be used, and if no cutoff point is found then the
* function will fallback to the trivial cutoff point. Regular expressions are
* also supported. Default: <none> (which is equivalent to `""` or the regular
* expression `/./`).
* @signature
* R.truncate(n, { omission, separator })(data);
* @example
* R.pipe("Hello, world!" as const, R.truncate(8)); //=> "Hello..."
* R.pipe(
* "cat, dog, mouse" as const,
* R.truncate(12, { omission: "__", separator: ","}),
* ); //=> "cat, dog__"
* @dataLast
* @category String
*/
declare function truncate<N extends number, const Options extends TruncateOptions>(n: N, options?: Options): <S extends string>(data: S) => Truncate<S, N, Options>;
//#endregion
export { truncate };
//# sourceMappingURL=truncate-yONlUNTA.d.ts.map