@visulima/string 3.0.0-alpha.7 → 3.0.0-alpha.9

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 (42) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/LICENSE.md +54 -0
  3. package/README.md +8 -2
  4. package/dist/align-text.js +7 -5
  5. package/dist/case/camel-case.js +7 -7
  6. package/dist/case/capital-case.js +3 -3
  7. package/dist/case/flip-case.js +1 -1
  8. package/dist/case/identify-case.js +2 -1
  9. package/dist/case/index.d.ts +1 -1
  10. package/dist/case/index.js +1 -1
  11. package/dist/case/kebab-case.js +3 -3
  12. package/dist/case/pascal-case.js +3 -3
  13. package/dist/case/sentence-case.js +7 -7
  14. package/dist/case/split-by-case.js +46 -30
  15. package/dist/case/title-case.js +3 -5
  16. package/dist/case/train-case.js +1 -1
  17. package/dist/closest-string.js +4 -5
  18. package/dist/compare-similarity.js +2 -2
  19. package/dist/get-string-truncated-width.js +2 -114
  20. package/dist/index.d.ts +7 -2
  21. package/dist/index.js +10 -5
  22. package/dist/outdent.js +6 -14
  23. package/dist/packem_shared/{closestN-Cvsw0Fue.js → closestN-DUsjgiXb.js} +4 -3
  24. package/dist/packem_shared/{constants-D5qaproB.js → constants-BsZS5f0z.js} +1 -1
  25. package/dist/packem_shared/direction-C9gfWWTK.js +16 -0
  26. package/dist/packem_shared/eastAsianWidthType-SD3YniiT.js +20 -0
  27. package/dist/packem_shared/indent-D3DSCa6s.js +33 -0
  28. package/dist/packem_shared/isFullwidthCodePoint-IFXZxNjq.js +10 -0
  29. package/dist/packem_shared/{joinSegments-BStLas0c.js → joinSegments-CvxSgKz0.js} +1 -1
  30. package/dist/packem_shared/lookup-BE8lEqy4.js +104 -0
  31. package/dist/packem_shared/{normalize-german-eszett-DEB8-ZPT.js → normalize-german-eszett-4p3yKEzn.js} +2 -1
  32. package/dist/packem_shared/redent-DSb1IJWn.js +8 -0
  33. package/dist/packem_shared/{replaceString-BVlxk27d.js → replaceString-Ce8X2ZQ-.js} +11 -9
  34. package/dist/packem_shared/stripIndent-D_TRjxZ_.js +20 -0
  35. package/dist/packem_shared/{transliterate-DGlx-woj.js → transliterate-CKt9VK7D.js} +10 -10
  36. package/dist/slice.js +9 -7
  37. package/dist/slugify.js +1 -1
  38. package/dist/truncate.js +28 -30
  39. package/dist/utilities.js +6 -8
  40. package/dist/word-wrap.js +20 -18
  41. package/package.json +1 -4
  42. package/dist/packem_shared/direction-BVhR8MOQ.js +0 -10
package/dist/slice.js CHANGED
@@ -1,9 +1,10 @@
1
- import { g as RE_VALID_ANSI_PAIRS, h as RE_VALID_HYPERLINKS, i as RE_ANSI } from './packem_shared/constants-D5qaproB.js';
1
+ import { j as RE_VALID_ANSI_PAIRS, k as RE_VALID_HYPERLINKS, g as RE_ANSI } from './packem_shared/constants-BsZS5f0z.js';
2
2
  import { getStringWidth } from './get-string-width.js';
3
3
  import LRUCache from './packem_shared/LRUCache-3r3SovvR.js';
4
4
 
5
5
  const segmentCache = new LRUCache(100);
6
6
  const defaultSegmenter = new Intl.Segmenter("en", { granularity: "grapheme" });
7
+ const RE_ASCII_ONLY = /^[\u0000-\u007F]*$/;
7
8
  const ANSI_RESET_CODES = /* @__PURE__ */ new Set([
8
9
  "0",
9
10
  // Full reset
@@ -70,8 +71,8 @@ const FORMAT_STYLES = [
70
71
  ];
71
72
  const findFirstPositionOfAny = (input, substrings) => {
72
73
  let firstPos = -1;
73
- for (const substring of substrings) {
74
- const pos = input.indexOf(substring);
74
+ for (const sub of substrings) {
75
+ const pos = input.indexOf(sub);
75
76
  if (pos !== -1 && (firstPos === -1 || pos < firstPos)) {
76
77
  firstPos = pos;
77
78
  }
@@ -271,10 +272,10 @@ const processIntoStyledSegments = (input, options) => {
271
272
  }
272
273
  if (needsForegroundClose && needsBackgroundClose && input.includes("\x1B[39m") && input.includes("\x1B[49m")) {
273
274
  if (input.indexOf("\x1B[39m") < input.indexOf("\x1B[49m")) {
274
- closingParts.length -= needsForegroundClose && needsBackgroundClose ? 2 : needsForegroundClose || needsBackgroundClose ? 1 : 0;
275
+ closingParts.length -= 2;
275
276
  closingParts.push("\x1B[39m", "\x1B[49m");
276
277
  } else if (input.indexOf("\x1B[49m") < input.indexOf("\x1B[39m")) {
277
- closingParts.length -= needsForegroundClose && needsBackgroundClose ? 2 : needsForegroundClose || needsBackgroundClose ? 1 : 0;
278
+ closingParts.length -= 2;
278
279
  closingParts.push("\x1B[49m", "\x1B[39m");
279
280
  }
280
281
  }
@@ -284,7 +285,8 @@ const processIntoStyledSegments = (input, options) => {
284
285
  style
285
286
  };
286
287
  }).filter((item) => item.position >= 0).toSorted((a, b) => b.position - a.position);
287
- for (const item of activeFormatStyles) {
288
+ for (const activeFormatStyle of activeFormatStyles) {
289
+ const item = activeFormatStyle;
288
290
  if (closingSequences.includes(item.style.close)) {
289
291
  closingParts.push(item.style.close);
290
292
  }
@@ -350,7 +352,7 @@ const slice = (inputString, startIndex = 0, endIndex = Number.MAX_SAFE_INTEGER,
350
352
  throw new RangeError("Negative indices aren't supported");
351
353
  }
352
354
  if (!inputString.includes("\x1B")) {
353
- if (/^[\u0000-\u007F]*$/.test(inputString)) {
355
+ if (RE_ASCII_ONLY.test(inputString)) {
354
356
  return inputString.slice(startIndex, endIndex);
355
357
  }
356
358
  return fastSlice(inputString, startIndex, endIndex, config);
package/dist/slugify.js CHANGED
@@ -1,4 +1,4 @@
1
- import transliterate from './packem_shared/transliterate-DGlx-woj.js';
1
+ import transliterate from './packem_shared/transliterate-CKt9VK7D.js';
2
2
  import { escapeRegExp } from './utilities.js';
3
3
 
4
4
  const removeDisallowedChars = (input, allowedChars, separator) => {
package/dist/truncate.js CHANGED
@@ -38,37 +38,35 @@ const truncate = (input, limit, options = {}) => {
38
38
  if (input === "" || limit <= 0) {
39
39
  return "";
40
40
  }
41
- input = input.normalize("NFC");
41
+ const normalizedInput = input.normalize("NFC");
42
42
  const { ellipsis = DEFAULT_ELLIPSIS, position = "end", preferTruncationOnSpace = false } = options;
43
43
  let ellipsisWidth = options.ellipsisWidth ?? ellipsis === DEFAULT_ELLIPSIS ? 1 : void 0;
44
- if (ellipsisWidth === void 0) {
45
- ellipsisWidth = getStringTruncatedWidth(ellipsis, {
46
- ...options.width,
47
- ellipsis: "",
48
- ellipsisWidth: 0,
49
- limit: Number.POSITIVE_INFINITY
50
- }).width;
51
- }
52
- const { width } = getStringTruncatedWidth(input, {
44
+ ellipsisWidth ??= getStringTruncatedWidth(ellipsis, {
45
+ ...options.width,
46
+ ellipsis: "",
47
+ ellipsisWidth: 0,
48
+ limit: Number.POSITIVE_INFINITY
49
+ }).width;
50
+ const { width } = getStringTruncatedWidth(normalizedInput, {
53
51
  ...options.width,
54
52
  ellipsis,
55
53
  ellipsisWidth
56
54
  });
57
55
  if (width <= limit) {
58
- return input;
56
+ return normalizedInput;
59
57
  }
60
58
  switch (position) {
61
59
  case "end": {
62
60
  if (preferTruncationOnSpace) {
63
61
  const targetWidth = limit - ellipsisWidth;
64
- const stringIndex = widthToIndex(input, targetWidth, options.width);
65
- const nearestSpace = findNearestSpace(input, stringIndex);
66
- const nearestSpaceWidth = indexToWidth(input, nearestSpace, options.width);
67
- return slice(input, 0, nearestSpaceWidth, {
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, {
68
66
  width: options.width
69
67
  }) + ellipsis;
70
68
  }
71
- return slice(input, 0, limit - ellipsisWidth, {
69
+ return slice(normalizedInput, 0, limit - ellipsisWidth, {
72
70
  width: options.width
73
71
  }) + ellipsis;
74
72
  }
@@ -78,30 +76,30 @@ const truncate = (input, limit, options = {}) => {
78
76
  const leftWidth = Math.min(half, totalTextWidth);
79
77
  const rightWidth = Math.max(0, totalTextWidth - leftWidth);
80
78
  if (preferTruncationOnSpace) {
81
- const firstBreakIndex = widthToIndex(input, leftWidth, options.width);
82
- const firstBreak = findNearestSpace(input, firstBreakIndex);
83
- const firstBreakWidth = indexToWidth(input, firstBreak, options.width);
79
+ const firstBreakIndex = widthToIndex(normalizedInput, leftWidth, options.width);
80
+ const firstBreak = findNearestSpace(normalizedInput, firstBreakIndex);
81
+ const firstBreakWidth = indexToWidth(normalizedInput, firstBreak, options.width);
84
82
  const secondBreakWidthTarget = width - rightWidth;
85
- const secondBreakIndex = widthToIndex(input, secondBreakWidthTarget, options.width);
86
- const secondBreak = findNearestSpace(input, secondBreakIndex, true);
87
- const secondBreakWidthActual = indexToWidth(input, secondBreak, options.width);
88
- return slice(input, 0, firstBreakWidth, { width: options.width }) + ellipsis + slice(input, secondBreakWidthActual, width, { width: options.width }).trim();
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();
89
87
  }
90
- return slice(input, 0, leftWidth, {
88
+ return slice(normalizedInput, 0, leftWidth, {
91
89
  width: options.width
92
- }) + ellipsis + slice(input, width - rightWidth, width, {
90
+ }) + ellipsis + slice(normalizedInput, width - rightWidth, width, {
93
91
  width: options.width
94
92
  });
95
93
  }
96
94
  case "start": {
97
95
  if (preferTruncationOnSpace) {
98
96
  const targetWidth = width - limit + ellipsisWidth;
99
- const stringIndex = widthToIndex(input, targetWidth, options.width);
100
- const nearestSpace = findNearestSpace(input, stringIndex, true);
101
- const nearestSpaceWidth = indexToWidth(input, nearestSpace, options.width);
102
- return ellipsis + slice(input, nearestSpaceWidth, width, { width: options.width }).trim();
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();
103
101
  }
104
- return ellipsis + slice(input, width - limit + ellipsisWidth, width, {
102
+ return ellipsis + slice(normalizedInput, width - limit + ellipsisWidth, width, {
105
103
  width: options.width
106
104
  });
107
105
  }
package/dist/utilities.js CHANGED
@@ -1,17 +1,15 @@
1
1
  export { default as LRUCache } from './packem_shared/LRUCache-3r3SovvR.js';
2
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;
3
6
  const escapeRegExp = (char) => (
4
7
  // $& means the whole matched string
5
- char.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)
8
+ char.replaceAll(RE_REGEXP_SPECIAL, String.raw`\$&`)
6
9
  );
7
10
  const inRange = (number_, ranges) => ranges.some((range) => number_ >= range[0] && number_ <= range[1]);
8
- const hasChinese = (char) => /[\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]/.test(
9
- char
10
- );
11
- const hasPunctuationOrSpace = (char) => (
12
- // Uses Unicode property escapes for Punctuation and general category for Space
13
- /[\p{P}\p{Z}]/u.test(char)
14
- );
11
+ const hasChinese = (char) => RE_CHINESE.test(char);
12
+ const hasPunctuationOrSpace = (char) => RE_PUNCTUATION_OR_SPACE.test(char);
15
13
  const findStringOccurrences = (source, needles) => {
16
14
  const ranges = [];
17
15
  if (!Array.isArray(needles)) {
package/dist/word-wrap.js CHANGED
@@ -1,6 +1,7 @@
1
- import { O as ESCAPES, P as ANSI_ESCAPE_LINK, Q as ANSI_SGR_TERMINATOR, S as ANSI_ESCAPE_BELL, T as ANSI_CSI, U as RE_ESCAPE_PATTERN, V as ANSI_RESET_CODES, W as END_CODE, X as RE_ZERO_WIDTH } from './packem_shared/constants-D5qaproB.js';
1
+ import { O as ESCAPES, P as ANSI_ESCAPE_LINK, Q as ANSI_SGR_TERMINATOR, S as ANSI_ESCAPE_BELL, T as ANSI_CSI, U as RE_ESCAPE_PATTERN, V as ANSI_RESET_CODES, W as END_CODE, X as RE_ZERO_WIDTH } from './packem_shared/constants-BsZS5f0z.js';
2
2
  import { getStringWidth } from './get-string-width.js';
3
3
 
4
+ const RE_ANSI_CODE = /\x1B\[(\d+)m/;
4
5
  class AnsiStateTracker {
5
6
  activeForeground = void 0;
6
7
  activeBackground = void 0;
@@ -11,7 +12,7 @@ class AnsiStateTracker {
11
12
  * @param sequence The escape sequence to process
12
13
  */
13
14
  processEscape(sequence) {
14
- const match = /\x1B\[(\d+)m/.exec(sequence);
15
+ const match = RE_ANSI_CODE.exec(sequence);
15
16
  if (!match) {
16
17
  return;
17
18
  }
@@ -62,7 +63,7 @@ class AnsiStateTracker {
62
63
  }
63
64
  }
64
65
  /**
65
- * Gets all active escape sequences to apply
66
+ * Gets all active escape sequences to apply.
66
67
  * @returns String with all active escapes
67
68
  */
68
69
  getStartEscapesForAllActiveAttributes() {
@@ -122,7 +123,6 @@ const processAnsiString = (string, options = {}) => {
122
123
  const stateTracker = new AnsiStateTracker();
123
124
  let currentText = "";
124
125
  let isInsideEscape = false;
125
- let isInsideLinkEscape = false;
126
126
  let escapeBuffer = "";
127
127
  let currentUrl = "";
128
128
  let isInHyperlink = false;
@@ -150,7 +150,7 @@ const processAnsiString = (string, options = {}) => {
150
150
  isInsideEscape = true;
151
151
  escapeBuffer = character;
152
152
  const escapeInfo = checkEscapeSequence(chars, index);
153
- isInsideLinkEscape = escapeInfo.isInsideLinkEscape;
153
+ const { isInsideLinkEscape } = escapeInfo;
154
154
  if (isInsideLinkEscape) {
155
155
  let urlEnd = index + 1;
156
156
  currentUrl = "";
@@ -177,7 +177,6 @@ const processAnsiString = (string, options = {}) => {
177
177
  index = urlEnd;
178
178
  isInHyperlink = true;
179
179
  isInsideEscape = false;
180
- isInsideLinkEscape = false;
181
180
  escapeBuffer = "";
182
181
  continue;
183
182
  }
@@ -264,7 +263,7 @@ const processAnsiString = (string, options = {}) => {
264
263
 
265
264
  const wrapAnsiCode = (code) => {
266
265
  const escapeChar = ESCAPES.values().next().value;
267
- return `${escapeChar}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
266
+ return `${escapeChar}${ANSI_CSI}${String(code)}${ANSI_SGR_TERMINATOR}`;
268
267
  };
269
268
 
270
269
  const wrapAnsiHyperlink = (url) => {
@@ -318,6 +317,8 @@ const preserveAnsi = (rawLines) => {
318
317
  return returnValue;
319
318
  };
320
319
 
320
+ const RE_SPLIT_WHITESPACE = /(?=\s)|(?<=\s)/;
321
+ const RE_WHITESPACE_ONLY = /^\s+$/;
321
322
  const resetAnsiAtLineBreak = (currentLine) => {
322
323
  if (!currentLine.includes("\x1B")) {
323
324
  return currentLine;
@@ -438,12 +439,13 @@ const wrapCharByChar = (string, width, trim) => {
438
439
  getWidth: getStringWidth,
439
440
  // eslint-disable-next-line sonarjs/cognitive-complexity,sonarjs/no-invariant-returns
440
441
  onSegment: (segment, stateTracker) => {
442
+ const segText = segment.text ?? "";
441
443
  if (segment.isEscapeSequence) {
442
- currentLine += segment.text;
444
+ currentLine += segText;
443
445
  } else {
444
- const isSpace = segment.text === " ";
446
+ const isSpace = segText === " ";
445
447
  if (segment.width === 0) {
446
- currentLine += segment.text;
448
+ currentLine += segText;
447
449
  return true;
448
450
  }
449
451
  if (currentWidth + segment.width > width) {
@@ -456,11 +458,11 @@ const wrapCharByChar = (string, width, trim) => {
456
458
  if (trim) {
457
459
  return true;
458
460
  }
459
- rows.push(stateTracker.getStartEscapesForAllActiveAttributes() + segment.text);
461
+ rows.push(stateTracker.getStartEscapesForAllActiveAttributes() + segText);
460
462
  return true;
461
463
  }
462
464
  }
463
- currentLine += segment.text;
465
+ currentLine += segText;
464
466
  currentWidth += segment.width;
465
467
  }
466
468
  return true;
@@ -479,14 +481,14 @@ const wrapWithWordBoundaries = (string, width, trim) => {
479
481
  if (inputToProcess.length === 0) {
480
482
  return [];
481
483
  }
482
- const tokens = inputToProcess.split(/(?=\s)|(?<=\s)/);
484
+ const tokens = inputToProcess.split(RE_SPLIT_WHITESPACE);
483
485
  const rows = [];
484
486
  let currentLine = "";
485
487
  let currentWidth = 0;
486
488
  let index = 0;
487
489
  while (index < tokens.length) {
488
490
  const token = tokens[index];
489
- const isSpace = /^\s+$/.test(token);
491
+ const isSpace = RE_WHITESPACE_ONLY.test(token);
490
492
  const tokenVisibleWidth = getStringWidth(token);
491
493
  if (token.length === 0) {
492
494
  index += 1;
@@ -527,14 +529,14 @@ const wrapAndBreakWords = (string, width, trim) => {
527
529
  if (inputToProcess.length === 0) {
528
530
  return [];
529
531
  }
530
- const tokens = inputToProcess.split(/(?=\s)|(?<=\s)/);
532
+ const tokens = inputToProcess.split(RE_SPLIT_WHITESPACE);
531
533
  const rows = [];
532
534
  let currentLine = "";
533
535
  let currentWidth = 0;
534
536
  let index = 0;
535
537
  while (index < tokens.length) {
536
538
  const token = tokens[index];
537
- const isSpace = /^\s+$/.test(token);
539
+ const isSpace = RE_WHITESPACE_ONLY.test(token);
538
540
  const tokenVisibleWidth = getStringWidth(token);
539
541
  if (token.length === 0) {
540
542
  index += 1;
@@ -553,7 +555,7 @@ const wrapAndBreakWords = (string, width, trim) => {
553
555
  for (let brokenLineIndex = 0; brokenLineIndex < brokenLines.length - 1; brokenLineIndex += 1) {
554
556
  rows.push(brokenLines[brokenLineIndex]);
555
557
  }
556
- currentLine = brokenLines[brokenLines.length - 1];
558
+ currentLine = brokenLines.at(-1);
557
559
  currentWidth = getStringWidth(currentLine);
558
560
  } else {
559
561
  currentLine = "";
@@ -603,7 +605,7 @@ const wordWrap = (string, options = {}) => {
603
605
  if (trim && string.trim() === "") {
604
606
  return "";
605
607
  }
606
- let normalizedString = String(string).normalize("NFC").replaceAll("\r\n", "\n");
608
+ let normalizedString = string.normalize("NFC").replaceAll("\r\n", "\n");
607
609
  if (removeZeroWidthCharacters) {
608
610
  normalizedString = normalizedString.replaceAll(RE_ZERO_WIDTH, "");
609
611
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visulima/string",
3
- "version": "3.0.0-alpha.7",
3
+ "version": "3.0.0-alpha.9",
4
4
  "description": "Functions for manipulating strings.",
5
5
  "keywords": [
6
6
  "visulima",
@@ -227,9 +227,6 @@
227
227
  "README.md",
228
228
  "CHANGELOG.md"
229
229
  ],
230
- "dependencies": {},
231
- "peerDependencies": {},
232
- "optionalDependencies": {},
233
230
  "engines": {
234
231
  "node": ">=22.13 <=25.x"
235
232
  },
@@ -1,10 +0,0 @@
1
- const rtlRange = "֑-߿יִ-﷽ﹰ-ﻼ";
2
- const ltrRange = "A-Za-zÀ-ÖØ-öø-ʸ̀-֐ࠀ-῿‎Ⰰ-﬜︀-﹯﻽-￿";
3
- const rtl = new RegExp("^[^" + ltrRange + "]*[" + rtlRange + "]");
4
- const ltr = new RegExp("^[^" + rtlRange + "]*[" + ltrRange + "]");
5
- const direction = (value) => {
6
- const source = String(value || "");
7
- return rtl.test(source) ? "rtl" : ltr.test(source) ? "ltr" : "neutral";
8
- };
9
-
10
- export { direction };