@visulima/string 3.0.0-alpha.11 → 3.0.0-alpha.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE.md +68 -3
  3. package/dist/align-text.d.ts +35 -0
  4. package/dist/align-text.js +2 -34
  5. package/dist/case/camel-case.d.ts +17 -2
  6. package/dist/case/camel-case.js +1 -55
  7. package/dist/case/capital-case.d.ts +14 -2
  8. package/dist/case/capital-case.js +1 -47
  9. package/dist/case/constant-case.d.ts +14 -2
  10. package/dist/case/constant-case.js +1 -7
  11. package/dist/case/dot-case.d.ts +14 -2
  12. package/dist/case/dot-case.js +1 -7
  13. package/dist/case/flat-case.d.ts +12 -2
  14. package/dist/case/flat-case.js +1 -7
  15. package/dist/case/flip-case.d.ts +16 -2
  16. package/dist/case/flip-case.js +1 -82
  17. package/dist/case/identify-case.d.ts +15 -2
  18. package/dist/case/identify-case.js +1 -66
  19. package/dist/case/index.d.ts +8 -2
  20. package/dist/case/index.js +1 -20
  21. package/dist/case/kebab-case.d.ts +25 -2
  22. package/dist/case/kebab-case.js +1 -55
  23. package/dist/case/lower-first.d.ts +13 -2
  24. package/dist/case/lower-first.js +1 -9
  25. package/dist/case/no-case.d.ts +14 -2
  26. package/dist/case/no-case.js +1 -7
  27. package/dist/case/pascal-case.d.ts +17 -2
  28. package/dist/case/pascal-case.js +1 -48
  29. package/dist/case/pascal-snake-case.d.ts +14 -2
  30. package/dist/case/pascal-snake-case.js +1 -28
  31. package/dist/case/path-case.d.ts +14 -2
  32. package/dist/case/path-case.js +1 -7
  33. package/dist/case/sentence-case.d.ts +14 -2
  34. package/dist/case/sentence-case.js +1 -54
  35. package/dist/case/snake-case.d.ts +14 -2
  36. package/dist/case/snake-case.js +1 -7
  37. package/dist/case/split-by-case.d.ts +29 -2
  38. package/dist/case/split-by-case.js +1 -763
  39. package/dist/case/title-case.d.ts +12 -2
  40. package/dist/case/title-case.js +1 -40
  41. package/dist/case/train-case.d.ts +14 -2
  42. package/dist/case/train-case.js +1 -40
  43. package/dist/case/upper-first.d.ts +13 -2
  44. package/dist/case/upper-first.js +1 -9
  45. package/dist/closest-string.d.ts +32 -0
  46. package/dist/closest-string.js +1 -22
  47. package/dist/compare-similarity.d.ts +38 -1
  48. package/dist/compare-similarity.js +1 -12
  49. package/dist/get-string-truncated-width.d.ts +151 -0
  50. package/dist/get-string-truncated-width.js +1 -332
  51. package/dist/get-string-width.d.ts +58 -0
  52. package/dist/get-string-width.js +1 -5
  53. package/dist/index.d.ts +194 -9
  54. package/dist/index.js +1 -44
  55. package/dist/native-string-types.d.ts +239 -0
  56. package/dist/outdent.d.ts +74 -0
  57. package/dist/outdent.js +1 -109
  58. package/dist/packem_shared/LRUCache-Bjo6gsbC.js +1 -0
  59. package/dist/packem_shared/closest-uarbVSbs.js +1 -0
  60. package/dist/packem_shared/closestN-Vd5oNJy_.js +1 -0
  61. package/dist/packem_shared/constants-DmzZF6_u.js +1 -0
  62. package/dist/packem_shared/countOccurrences-DIHSCdcG.js +1 -0
  63. package/dist/packem_shared/direction-dtczwUOE.js +1 -0
  64. package/dist/packem_shared/eastAsianWidthType-lcBsj7vg.js +1 -0
  65. package/dist/packem_shared/excerpt-DhV2yoHG.js +54 -0
  66. package/dist/packem_shared/generate-cache-key-DPByFaMH.js +1 -0
  67. package/dist/packem_shared/indent-CDlPQmpe.js +1 -0
  68. package/dist/packem_shared/isFullwidthCodePoint-Dmsf2-5L.js +1 -0
  69. package/dist/packem_shared/joinSegments-D27SxoCV.js +1 -0
  70. package/dist/packem_shared/lookup-ChWuUpyb.js +1 -0
  71. package/dist/packem_shared/normalize-german-eszett-AKfdw2MZ.js +1 -0
  72. package/dist/packem_shared/redent-BECVOaZp.js +1 -0
  73. package/dist/packem_shared/replaceString-aq-C7Wor.js +1 -0
  74. package/dist/packem_shared/stripIndent-Dt8hSxVM.js +1 -0
  75. package/dist/packem_shared/transliterate-D1p1yYE7.js +5 -0
  76. package/dist/packem_shared/types.d-FOLSY2Tc.d.ts +392 -0
  77. package/dist/packem_shared/types.d-NJ4vcG-A.d.ts +346 -0
  78. package/dist/slice.d.ts +42 -0
  79. package/dist/slice.js +1 -415
  80. package/dist/slugify.d.ts +10 -1
  81. package/dist/slugify.js +1 -46
  82. package/dist/test/utils.d.ts +17 -0
  83. package/dist/test/utils.js +13 -88
  84. package/dist/test/vitest.d.ts +3 -0
  85. package/dist/test/vitest.js +1 -5
  86. package/dist/truncate.d.ts +43 -0
  87. package/dist/truncate.js +1 -112
  88. package/dist/utilities.d.ts +28 -1
  89. package/dist/utilities.js +1 -52
  90. package/dist/word-similarity-sort.d.ts +34 -0
  91. package/dist/word-similarity-sort.js +1 -22
  92. package/dist/word-wrap.d.ts +44 -0
  93. package/dist/word-wrap.js +8 -639
  94. package/package.json +46 -46
  95. package/dist/packem_shared/LRUCache-3r3SovvR.js +0 -46
  96. package/dist/packem_shared/closest-IHuSvnSn.js +0 -139
  97. package/dist/packem_shared/closestN-DUsjgiXb.js +0 -25
  98. package/dist/packem_shared/constants-BsZS5f0z.js +0 -95
  99. package/dist/packem_shared/countOccurrences-CS9XprQN.js +0 -22
  100. package/dist/packem_shared/direction-C9gfWWTK.js +0 -16
  101. package/dist/packem_shared/eastAsianWidthType-SD3YniiT.js +0 -20
  102. package/dist/packem_shared/excerpt-COsVNttN.js +0 -1502
  103. package/dist/packem_shared/generate-cache-key-DdayDfjV.js +0 -6
  104. package/dist/packem_shared/indent-D3DSCa6s.js +0 -33
  105. package/dist/packem_shared/isFullwidthCodePoint-IFXZxNjq.js +0 -10
  106. package/dist/packem_shared/joinSegments-CvxSgKz0.js +0 -44
  107. package/dist/packem_shared/lookup-BE8lEqy4.js +0 -104
  108. package/dist/packem_shared/normalize-german-eszett-4p3yKEzn.js +0 -8
  109. package/dist/packem_shared/redent-DSb1IJWn.js +0 -8
  110. package/dist/packem_shared/replaceString-Ce8X2ZQ-.js +0 -192
  111. package/dist/packem_shared/stripIndent-D_TRjxZ_.js +0 -20
  112. package/dist/packem_shared/transliterate-CKt9VK7D.js +0 -47756
  113. package/dist/packem_shared/types.d-BVNv675q.d.ts +0 -61
  114. package/dist/packem_shared/types.d-DfgbcNKh.d.ts +0 -57
@@ -1,10 +1,53 @@
1
1
  import { StringTruncatedWidthOptions } from "./get-string-truncated-width.js";
2
2
  type TruncateOptions = {
3
+ /**
4
+ * Text appended to the string when it is truncated
5
+ * @default '…'
6
+ */
3
7
  ellipsis?: string;
8
+ /**
9
+ * Width of the ellipsis string
10
+ * If not provided, it will be calculated using getStringTruncatedWidth
11
+ */
4
12
  ellipsisWidth?: number;
13
+ /**
14
+ * The position to truncate the string.
15
+ * @default 'end'
16
+ */
5
17
  position?: "end" | "middle" | "start";
18
+ /**
19
+ * Truncate the string from a whitespace if it is within 3 characters from the actual breaking point.
20
+ * @default false
21
+ */
6
22
  preferTruncationOnSpace?: boolean;
23
+ /**
24
+ * Width calculation options
25
+ */
7
26
  width?: Omit<StringTruncatedWidthOptions, "ellipsis" | "ellipsisWidth" | "limit">;
8
27
  };
28
+ /**
29
+ * Truncates a string to a specified width limit, handling Unicode characters, ANSI escape codes,
30
+ * and adding an optional ellipsis.
31
+ *
32
+ * ANSI Sequence Handling:
33
+ * - Valid ANSI sequences (e.g. '\u001b[31m') are preserved and handled as styling
34
+ * - Incomplete sequences are preserved as-is
35
+ * - Missing terminators are preserved as-is
36
+ * @example
37
+ * ```typescript
38
+ * // Basic usage
39
+ * truncate('Hello World', 5); // 'Hello…'
40
+ *
41
+ * // With valid ANSI styling
42
+ * truncate('\u001b[31mRed\u001b[0m Text', 3); // '\u001b[31mRed\u001b[0m…'
43
+ *
44
+ * // With invalid ANSI sequence
45
+ * truncate('\u001b[abcText', 4); // '\u001b[abcText'
46
+ * ```
47
+ * @param input The string to truncate
48
+ * @param limit Maximum width of the returned string
49
+ * @param options Configuration options for truncation
50
+ * @returns The truncated string with ellipsis if applicable
51
+ */
9
52
  declare const truncate: (input: string, limit: number, options?: TruncateOptions) => string;
10
53
  export { TruncateOptions, truncate };
package/dist/truncate.js CHANGED
@@ -1,112 +1 @@
1
- import { getStringTruncatedWidth } from './get-string-truncated-width.js';
2
- import { getStringWidth } from './get-string-width.js';
3
- import { slice } from './slice.js';
4
-
5
- const DEFAULT_ELLIPSIS = "…";
6
- const MAX_SPACE_SEARCH_DISTANCE = 3;
7
- const findNearestSpace = (value, startIndex, searchRight = false) => {
8
- if (value.charAt(startIndex) === " ") {
9
- return startIndex;
10
- }
11
- const direction = searchRight ? 1 : -1;
12
- const limit = Math.min(MAX_SPACE_SEARCH_DISTANCE, searchRight ? value.length - startIndex : startIndex);
13
- for (let offset = 1; offset <= limit; offset++) {
14
- const index = startIndex + offset * direction;
15
- if (value.charAt(index) === " ") {
16
- return index;
17
- }
18
- }
19
- return startIndex;
20
- };
21
- const widthToIndex = (input, targetWidth, widthOptions) => {
22
- const result = getStringTruncatedWidth(input, {
23
- ...widthOptions,
24
- ellipsis: "",
25
- ellipsisWidth: 0,
26
- limit: targetWidth
27
- });
28
- return result.index;
29
- };
30
- const indexToWidth = (input, stringIndex, widthOptions) => getStringWidth(input.slice(0, stringIndex), widthOptions);
31
- const truncate = (input, limit, options = {}) => {
32
- if (typeof input !== "string") {
33
- throw new TypeError(`Expected \`input\` to be a string, got ${typeof input}`);
34
- }
35
- if (typeof limit !== "number") {
36
- throw new TypeError(`Expected \`limit\` to be a number, got ${typeof limit}`);
37
- }
38
- if (input === "" || limit <= 0) {
39
- return "";
40
- }
41
- const normalizedInput = input.normalize("NFC");
42
- const { ellipsis = DEFAULT_ELLIPSIS, position = "end", preferTruncationOnSpace = false } = options;
43
- let ellipsisWidth = options.ellipsisWidth ?? ellipsis === DEFAULT_ELLIPSIS ? 1 : void 0;
44
- ellipsisWidth ??= getStringTruncatedWidth(ellipsis, {
45
- ...options.width,
46
- ellipsis: "",
47
- ellipsisWidth: 0,
48
- limit: Number.POSITIVE_INFINITY
49
- }).width;
50
- const { width } = getStringTruncatedWidth(normalizedInput, {
51
- ...options.width,
52
- ellipsis,
53
- ellipsisWidth
54
- });
55
- if (width <= limit) {
56
- return normalizedInput;
57
- }
58
- switch (position) {
59
- case "end": {
60
- if (preferTruncationOnSpace) {
61
- const targetWidth = limit - ellipsisWidth;
62
- const stringIndex = widthToIndex(normalizedInput, targetWidth, options.width);
63
- const nearestSpace = findNearestSpace(normalizedInput, stringIndex);
64
- const nearestSpaceWidth = indexToWidth(normalizedInput, nearestSpace, options.width);
65
- return slice(normalizedInput, 0, nearestSpaceWidth, {
66
- width: options.width
67
- }) + ellipsis;
68
- }
69
- return slice(normalizedInput, 0, limit - ellipsisWidth, {
70
- width: options.width
71
- }) + ellipsis;
72
- }
73
- case "middle": {
74
- const half = Math.floor(limit / 2);
75
- const totalTextWidth = Math.max(0, limit - ellipsisWidth);
76
- const leftWidth = Math.min(half, totalTextWidth);
77
- const rightWidth = Math.max(0, totalTextWidth - leftWidth);
78
- if (preferTruncationOnSpace) {
79
- const firstBreakIndex = widthToIndex(normalizedInput, leftWidth, options.width);
80
- const firstBreak = findNearestSpace(normalizedInput, firstBreakIndex);
81
- const firstBreakWidth = indexToWidth(normalizedInput, firstBreak, options.width);
82
- const secondBreakWidthTarget = width - rightWidth;
83
- const secondBreakIndex = widthToIndex(normalizedInput, secondBreakWidthTarget, options.width);
84
- const secondBreak = findNearestSpace(normalizedInput, secondBreakIndex, true);
85
- const secondBreakWidthActual = indexToWidth(normalizedInput, secondBreak, options.width);
86
- return slice(normalizedInput, 0, firstBreakWidth, { width: options.width }) + ellipsis + slice(normalizedInput, secondBreakWidthActual, width, { width: options.width }).trim();
87
- }
88
- return slice(normalizedInput, 0, leftWidth, {
89
- width: options.width
90
- }) + ellipsis + slice(normalizedInput, width - rightWidth, width, {
91
- width: options.width
92
- });
93
- }
94
- case "start": {
95
- if (preferTruncationOnSpace) {
96
- const targetWidth = width - limit + ellipsisWidth;
97
- const stringIndex = widthToIndex(normalizedInput, targetWidth, options.width);
98
- const nearestSpace = findNearestSpace(normalizedInput, stringIndex, true);
99
- const nearestSpaceWidth = indexToWidth(normalizedInput, nearestSpace, options.width);
100
- return ellipsis + slice(normalizedInput, nearestSpaceWidth, width, { width: options.width }).trim();
101
- }
102
- return ellipsis + slice(normalizedInput, width - limit + ellipsisWidth, width, {
103
- width: options.width
104
- });
105
- }
106
- default: {
107
- throw new Error(`Invalid position: expected 'start', 'middle' or 'end', got '${position}'`);
108
- }
109
- }
110
- };
111
-
112
- export { truncate };
1
+ var N=Object.defineProperty;var T=(r,i)=>N(r,"name",{value:i,configurable:!0});import{getStringTruncatedWidth as x}from"./get-string-truncated-width.js";import{getStringWidth as O}from"./get-string-width.js";import{slice as h}from"./slice.js";var A=Object.defineProperty,g=T((r,i)=>A(r,"name",{value:i,configurable:!0}),"f");const b="…",$=3,u=g((r,i,t=!1)=>{if(r.charAt(i)===" ")return i;const e=t?1:-1,d=Math.min($,t?r.length-i:i);for(let w=1;w<=d;w++){const l=i+w*e;if(r.charAt(l)===" ")return l}return i},"findNearestSpace"),f=g((r,i,t)=>x(r,{...t,ellipsis:"",ellipsisWidth:0,limit:i}).index,"widthToIndex"),m=g((r,i,t)=>O(r.slice(0,i),t),"indexToWidth"),B=g((r,i,t={})=>{if(typeof r!="string")throw new TypeError(`Expected \`input\` to be a string, got ${typeof r}`);if(typeof i!="number")throw new TypeError(`Expected \`limit\` to be a number, got ${typeof i}`);if(r===""||i<=0)return"";const e=r.normalize("NFC"),{ellipsis:d=b,position:w="end",preferTruncationOnSpace:l=!1}=t;let o=t.ellipsisWidth??d===b?1:void 0;o??=x(d,{...t.width,ellipsis:"",ellipsisWidth:0,limit:Number.POSITIVE_INFINITY}).width;const{width:n}=x(e,{...t.width,ellipsis:d,ellipsisWidth:o});if(n<=i)return e;switch(w){case"end":{if(l){const p=i-o,a=f(e,p,t.width),s=u(e,a),c=m(e,s,t.width);return h(e,0,c,{width:t.width})+d}return h(e,0,i-o,{width:t.width})+d}case"middle":{const p=Math.floor(i/2),a=Math.max(0,i-o),s=Math.min(p,a),c=Math.max(0,a-s);if(l){const y=f(e,s,t.width),I=u(e,y),E=m(e,I,t.width),W=n-c,S=f(e,W,t.width),v=u(e,S,!0),M=m(e,v,t.width);return h(e,0,E,{width:t.width})+d+h(e,M,n,{width:t.width}).trim()}return h(e,0,s,{width:t.width})+d+h(e,n-c,n,{width:t.width})}case"start":{if(l){const p=n-i+o,a=f(e,p,t.width),s=u(e,a,!0),c=m(e,s,t.width);return d+h(e,c,n,{width:t.width}).trim()}return d+h(e,n-i+o,n,{width:t.width})}default:throw new Error(`Invalid position: expected 'start', 'middle' or 'end', got '${w}'`)}},"truncate");export{B as truncate};
@@ -1,8 +1,35 @@
1
- import { a as IntervalArray } from "./packem_shared/types.d-BVNv675q.js";
1
+ import { a as IntervalArray } from "./packem_shared/types.d-NJ4vcG-A.js";
2
2
  export { L as LRUCache } from "./packem_shared/lru-cache.d-BsP6kbVJ.js";
3
+ /**
4
+ * Escapes characters with special meaning in regular expressions.
5
+ * @param char The string to escape.
6
+ * @returns The escaped string.
7
+ */
3
8
  declare const escapeRegExp: (char: string) => string;
9
+ /**
10
+ * Checks if a number falls within any of the specified intervals.
11
+ * @param number_ The number to check.
12
+ * @param ranges An array of intervals [start, end].
13
+ * @returns True if the number is within any interval, false otherwise.
14
+ */
4
15
  declare const inRange: (number_: number, ranges: IntervalArray) => boolean;
16
+ /**
17
+ * Checks if a string contains Chinese characters (Han script).
18
+ * @param char The string to check.
19
+ * @returns True if the string contains Chinese characters, false otherwise.
20
+ */
5
21
  declare const hasChinese: (char: string) => boolean;
22
+ /**
23
+ * Checks if a string contains punctuation or space characters.
24
+ * @param char The string to check.
25
+ * @returns True if the string contains punctuation or space, false otherwise.
26
+ */
6
27
  declare const hasPunctuationOrSpace: (char: string) => boolean;
28
+ /**
29
+ * Finds all occurrences of a set of substrings within a source string and returns their start/end indices.
30
+ * @param source The string to search within.
31
+ * @param needles An array of strings to search for.
32
+ * @returns An array of intervals [start, end] for each occurrence.
33
+ */
7
34
  declare const findStringOccurrences: (source: string, needles: string[]) => IntervalArray;
8
35
  export { escapeRegExp, findStringOccurrences, hasChinese, hasPunctuationOrSpace, inRange };
package/dist/utilities.js CHANGED
@@ -1,52 +1 @@
1
- export { default as LRUCache } from './packem_shared/LRUCache-3r3SovvR.js';
2
-
3
- const RE_REGEXP_SPECIAL = /[.*+?^${}()|[\]\\]/g;
4
- const RE_CHINESE = /[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u3005\u3007\u3021-\u3029\u3038-\u303B\u3400-\u4DBF\u4E00-\u9FFC\uF900-\uFA6D\uFA70-\uFAD9]|\uD81B[\uDFF0\uDFF1]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A]/;
5
- const RE_PUNCTUATION_OR_SPACE = /[\p{P}\p{Z}]/u;
6
- const escapeRegExp = (char) => (
7
- // $& means the whole matched string
8
- char.replaceAll(RE_REGEXP_SPECIAL, String.raw`\$&`)
9
- );
10
- const inRange = (number_, ranges) => ranges.some((range) => number_ >= range[0] && number_ <= range[1]);
11
- const hasChinese = (char) => RE_CHINESE.test(char);
12
- const hasPunctuationOrSpace = (char) => RE_PUNCTUATION_OR_SPACE.test(char);
13
- const findStringOccurrences = (source, needles) => {
14
- const ranges = [];
15
- if (!Array.isArray(needles)) {
16
- return ranges;
17
- }
18
- needles.forEach((needle) => {
19
- if (typeof needle !== "string" || needle.length === 0) {
20
- return;
21
- }
22
- let startIndex = 0;
23
- let index;
24
- while ((index = source.indexOf(needle, startIndex)) > -1) {
25
- const end = index + needle.length - 1;
26
- ranges.push([index, end]);
27
- startIndex = index + 1;
28
- }
29
- });
30
- if (ranges.length === 0) {
31
- return [];
32
- }
33
- ranges.sort((a, b) => a[0] - b[0]);
34
- const merged = [];
35
- let currentRange;
36
- for (const range of ranges) {
37
- if (currentRange === void 0) {
38
- currentRange = [...range];
39
- } else if (range[0] <= currentRange[1] + 1) {
40
- currentRange[1] = Math.max(currentRange[1], range[1]);
41
- } else {
42
- merged.push(currentRange);
43
- currentRange = [...range];
44
- }
45
- }
46
- if (currentRange !== void 0) {
47
- merged.push(currentRange);
48
- }
49
- return merged;
50
- };
51
-
52
- export { escapeRegExp, findStringOccurrences, hasChinese, hasPunctuationOrSpace, inRange };
1
+ var i=Object.defineProperty;var c=(u,t)=>i(u,"name",{value:t,configurable:!0});import{default as B}from"./packem_shared/LRUCache-Bjo6gsbC.js";var p=Object.defineProperty,n=c((u,t)=>p(u,"name",{value:t,configurable:!0}),"D");const E=/[.*+?^${}()|[\]\\]/g,f=/[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u3005\u3007\u3021-\u3029\u3038-\u303B\u3400-\u4DBF\u4E00-\u9FFC\uF900-\uFA6D\uFA70-\uFAD9]|\uD81B[\uDFF0\uDFF1]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD869[\uDC00-\uDEDD\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A]/,h=/[\p{P}\p{Z}]/u,g=n(u=>u.replaceAll(E,String.raw`\$&`),"escapeRegExp"),l=n((u,t)=>t.some(F=>u>=F[0]&&u<=F[1]),"inRange"),A=n(u=>f.test(u),"hasChinese"),d=n(u=>h.test(u),"hasPunctuationOrSpace"),x=n((u,t)=>{const F=[];if(!Array.isArray(t))return F;if(t.forEach(D=>{if(typeof D!="string"||D.length===0)return;let r=0,a;for(;(a=u.indexOf(D,r))>-1;){const o=a+D.length-1;F.push([a,o]),r=a+1}}),F.length===0)return[];F.sort((D,r)=>D[0]-r[0]);const s=[];let e;for(const D of F)e===void 0?e=[...D]:D[0]<=e[1]+1?e[1]=Math.max(e[1],D[1]):(s.push(e),e=[...D]);return e!==void 0&&s.push(e),s},"findStringOccurrences");export{B as LRUCache,g as escapeRegExp,x as findStringOccurrences,A as hasChinese,d as hasPunctuationOrSpace,l as inRange};
@@ -1,6 +1,40 @@
1
+ /** Options for {@linkcode wordSimilaritySort}. */
1
2
  interface WordSimilaritySortOptions {
2
3
  caseSensitive?: boolean;
3
4
  compareFunction?: (a: string, b: string) => number;
4
5
  }
6
+ /**
7
+ * Sorts a string-array by similarity to a given string.
8
+ *
9
+ * By default, calculates the distance between words using the
10
+ * {@link https://en.wikipedia.org/wiki/Levenshtein_distance | Levenshtein distance}.
11
+ * @example Basic usage
12
+ *
13
+ * ```ts
14
+ * import { wordSimilaritySort } from "@visulima/string";
15
+ * import assert from "node:assert";
16
+ *
17
+ * const possibleWords = ["length", "size", "blah", "help"];
18
+ * const suggestions = wordSimilaritySort("hep", possibleWords);
19
+ *
20
+ * assert.deepStrictEqual(suggestions, ["help", "size", "blah", "length"]);
21
+ * ```
22
+ * @example Case-sensitive sorting
23
+ *
24
+ * ```ts
25
+ * import { wordSimilaritySort } from "@visulima/string";
26
+ * import assert from "node:assert";
27
+ *
28
+ * const possibleWords = ["length", "Size", "blah", "HELP"];
29
+ * const suggestions = wordSimilaritySort("hep", possibleWords, { caseSensitive: true });
30
+ *
31
+ * assert.deepStrictEqual(suggestions, ["Size", "blah", "HELP", "length"]);
32
+ * ```
33
+ * @param givenWord The string to measure distance against.
34
+ * @param possibleWords The string-array that will be sorted. This array will
35
+ * not be mutated, but the sorted copy will be returned.
36
+ * @param options Options for the sort.
37
+ * @returns A sorted copy of `possibleWords`.
38
+ */
5
39
  declare const wordSimilaritySort: (givenWord: string, possibleWords: ReadonlyArray<string>, options?: WordSimilaritySortOptions) => string[];
6
40
  export { WordSimilaritySortOptions, wordSimilaritySort };
@@ -1,22 +1 @@
1
- import { distance } from './packem_shared/closest-IHuSvnSn.js';
2
-
3
- const wordSimilaritySort = (givenWord, possibleWords, options) => {
4
- const { caseSensitive = false, compareFunction = distance } = options ?? {};
5
- const processedGivenWord = caseSensitive ? givenWord : givenWord.toLowerCase();
6
- const wordsWithDistances = possibleWords.map((word) => {
7
- const processedWord = caseSensitive ? word : word.toLowerCase();
8
- return {
9
- distance: compareFunction(processedGivenWord, processedWord),
10
- originalWord: word
11
- };
12
- });
13
- wordsWithDistances.sort((a, b) => {
14
- if (a.distance !== b.distance) {
15
- return a.distance - b.distance;
16
- }
17
- return a.originalWord.localeCompare(b.originalWord);
18
- });
19
- return wordsWithDistances.map((item) => item.originalWord);
20
- };
21
-
22
- export { wordSimilaritySort };
1
+ var l=Object.defineProperty;var n=(e,r)=>l(e,"name",{value:r,configurable:!0});import{distance as m}from"./packem_shared/closest-uarbVSbs.js";var p=Object.defineProperty,u=n((e,r)=>p(e,"name",{value:r,configurable:!0}),"s");const f=u((e,r,s)=>{const{caseSensitive:i=!1,compareFunction:c=m}=s??{},d=i?e:e.toLowerCase(),t=r.map(o=>{const a=i?o:o.toLowerCase();return{distance:c(d,a),originalWord:o}});return t.sort((o,a)=>o.distance!==a.distance?o.distance-a.distance:o.originalWord.localeCompare(a.originalWord)),t.map(o=>o.originalWord)},"wordSimilaritySort");export{f as wordSimilaritySort};
@@ -1,14 +1,58 @@
1
+ /**
2
+ * Enum representing different wrapping strategies for text
3
+ */
1
4
  declare const WrapMode: {
5
+ /**
6
+ * Breaks words at character boundaries to fit the width
7
+ */
2
8
  readonly BREAK_AT_CHARACTERS: "BREAK_AT_CHARACTERS";
9
+ /**
10
+ * Breaks lines at word boundaries. If a word is longer than the width, it will be broken.
11
+ */
3
12
  readonly BREAK_WORDS: "BREAK_WORDS";
13
+ /**
14
+ * Preserves word boundaries, words are kept intact even if they exceed width
15
+ */
4
16
  readonly PRESERVE_WORDS: "PRESERVE_WORDS";
17
+ /**
18
+ * Enforces strict adherence to the width limit by breaking at exact width
19
+ */
5
20
  readonly STRICT_WIDTH: "STRICT_WIDTH";
6
21
  };
22
+ /**
23
+ * Word wrap options interface with detailed documentation
24
+ */
7
25
  interface WordWrapOptions {
26
+ /**
27
+ * Whether to remove zero-width characters from the string.
28
+ * @default true
29
+ */
8
30
  removeZeroWidthCharacters?: boolean;
31
+ /**
32
+ * Whether to trim whitespace from wrapped lines.
33
+ * @default true
34
+ */
9
35
  trim?: boolean;
36
+ /**
37
+ * Maximum width of each line in visible characters.
38
+ * @default 80
39
+ */
10
40
  width?: number;
41
+ /**
42
+ * Controls how text wrapping is handled at width boundaries.
43
+ * - PRESERVE_WORDS: Words are kept intact even if they exceed width (default)
44
+ * - BREAK_AT_CHARACTERS: Words are broken at character boundaries to fit width
45
+ * - STRICT_WIDTH: Forces breaking exactly at width limit, always
46
+ * - BREAK_WORDS: Breaks at word boundaries, but breaks words if they are too long
47
+ * @default WrapMode.PRESERVE_WORDS
48
+ */
11
49
  wrapMode?: keyof typeof WrapMode;
12
50
  }
51
+ /**
52
+ * Wraps text using multiple wrapping strategies.
53
+ * @param string The string to wrap
54
+ * @param options Wrapping options
55
+ * @returns The wrapped string
56
+ */
13
57
  declare const wordWrap: (string: string, options?: WordWrapOptions) => string;
14
58
  export { WordWrapOptions, WrapMode, wordWrap };