@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.
- package/CHANGELOG.md +39 -0
- package/LICENSE.md +54 -0
- package/README.md +8 -2
- package/dist/align-text.js +7 -5
- package/dist/case/camel-case.js +7 -7
- package/dist/case/capital-case.js +3 -3
- package/dist/case/flip-case.js +1 -1
- package/dist/case/identify-case.js +2 -1
- package/dist/case/index.d.ts +1 -1
- package/dist/case/index.js +1 -1
- package/dist/case/kebab-case.js +3 -3
- package/dist/case/pascal-case.js +3 -3
- package/dist/case/sentence-case.js +7 -7
- package/dist/case/split-by-case.js +46 -30
- package/dist/case/title-case.js +3 -5
- package/dist/case/train-case.js +1 -1
- package/dist/closest-string.js +4 -5
- package/dist/compare-similarity.js +2 -2
- package/dist/get-string-truncated-width.js +2 -114
- package/dist/index.d.ts +7 -2
- package/dist/index.js +10 -5
- package/dist/outdent.js +6 -14
- package/dist/packem_shared/{closestN-Cvsw0Fue.js → closestN-DUsjgiXb.js} +4 -3
- package/dist/packem_shared/{constants-D5qaproB.js → constants-BsZS5f0z.js} +1 -1
- package/dist/packem_shared/direction-C9gfWWTK.js +16 -0
- package/dist/packem_shared/eastAsianWidthType-SD3YniiT.js +20 -0
- package/dist/packem_shared/indent-D3DSCa6s.js +33 -0
- package/dist/packem_shared/isFullwidthCodePoint-IFXZxNjq.js +10 -0
- package/dist/packem_shared/{joinSegments-BStLas0c.js → joinSegments-CvxSgKz0.js} +1 -1
- package/dist/packem_shared/lookup-BE8lEqy4.js +104 -0
- package/dist/packem_shared/{normalize-german-eszett-DEB8-ZPT.js → normalize-german-eszett-4p3yKEzn.js} +2 -1
- package/dist/packem_shared/redent-DSb1IJWn.js +8 -0
- package/dist/packem_shared/{replaceString-BVlxk27d.js → replaceString-Ce8X2ZQ-.js} +11 -9
- package/dist/packem_shared/stripIndent-D_TRjxZ_.js +20 -0
- package/dist/packem_shared/{transliterate-DGlx-woj.js → transliterate-CKt9VK7D.js} +10 -10
- package/dist/slice.js +9 -7
- package/dist/slugify.js +1 -1
- package/dist/truncate.js +28 -30
- package/dist/utilities.js +6 -8
- package/dist/word-wrap.js +20 -18
- package/package.json +1 -4
- package/dist/packem_shared/direction-BVhR8MOQ.js +0 -10
package/dist/slice.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
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
|
|
74
|
-
const pos = input.indexOf(
|
|
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 -=
|
|
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 -=
|
|
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
|
|
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 (
|
|
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
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
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
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(
|
|
65
|
-
const nearestSpace = findNearestSpace(
|
|
66
|
-
const nearestSpaceWidth = indexToWidth(
|
|
67
|
-
return slice(
|
|
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(
|
|
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(
|
|
82
|
-
const firstBreak = findNearestSpace(
|
|
83
|
-
const firstBreakWidth = indexToWidth(
|
|
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(
|
|
86
|
-
const secondBreak = findNearestSpace(
|
|
87
|
-
const secondBreakWidthActual = indexToWidth(
|
|
88
|
-
return slice(
|
|
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(
|
|
88
|
+
return slice(normalizedInput, 0, leftWidth, {
|
|
91
89
|
width: options.width
|
|
92
|
-
}) + ellipsis + slice(
|
|
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(
|
|
100
|
-
const nearestSpace = findNearestSpace(
|
|
101
|
-
const nearestSpaceWidth = indexToWidth(
|
|
102
|
-
return ellipsis + slice(
|
|
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(
|
|
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(
|
|
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) =>
|
|
9
|
-
|
|
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-
|
|
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 =
|
|
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
|
|
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 +=
|
|
444
|
+
currentLine += segText;
|
|
443
445
|
} else {
|
|
444
|
-
const isSpace =
|
|
446
|
+
const isSpace = segText === " ";
|
|
445
447
|
if (segment.width === 0) {
|
|
446
|
-
currentLine +=
|
|
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() +
|
|
461
|
+
rows.push(stateTracker.getStartEscapesForAllActiveAttributes() + segText);
|
|
460
462
|
return true;
|
|
461
463
|
}
|
|
462
464
|
}
|
|
463
|
-
currentLine +=
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
|
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 =
|
|
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.
|
|
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 };
|