@thi.ng/strings 3.7.2 → 3.7.4
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 +8 -1
- package/README.md +1 -1
- package/ansi.js +12 -37
- package/api.js +4 -5
- package/case.js +24 -56
- package/center.js +12 -32
- package/currency.js +16 -8
- package/cursor.js +16 -37
- package/entities.js +136 -149
- package/escape.js +39 -62
- package/float.js +26 -45
- package/format.js +19 -27
- package/groups.js +42 -53
- package/hollerith.js +4 -16
- package/initials.js +6 -27
- package/int.js +8 -2
- package/interpolate.js +9 -36
- package/join.js +6 -21
- package/package.json +11 -8
- package/pad-left.js +18 -25
- package/pad-right.js +12 -13
- package/parse.js +10 -6
- package/percent.js +4 -7
- package/radix.js +32 -54
- package/range.js +13 -18
- package/repeat.js +6 -5
- package/ruler.js +12 -63
- package/slugify.js +12 -48
- package/splice.js +15 -29
- package/split.d.ts +3 -0
- package/split.js +24 -28
- package/stringify.js +4 -12
- package/tabs.js +40 -81
- package/trim.js +7 -22
- package/truncate-left.js +6 -3
- package/truncate.js +8 -5
- package/units.js +77 -44
- package/utf8.js +72 -130
- package/uuid.js +4 -14
- package/vector.js +25 -28
- package/word-wrap.js +78 -141
- package/wrap.js +6 -5
package/word-wrap.js
CHANGED
|
@@ -1,154 +1,91 @@
|
|
|
1
1
|
import { lengthAnsi } from "./ansi.js";
|
|
2
2
|
import { split } from "./split.js";
|
|
3
|
-
/**
|
|
4
|
-
* Internal representation of a single line (for word wrapping purposes). A thin
|
|
5
|
-
* wrapper of individual word and the _logical_ line length (rather than the
|
|
6
|
-
* actualy string width).
|
|
7
|
-
*
|
|
8
|
-
* @internal
|
|
9
|
-
*/
|
|
10
3
|
class Line {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
4
|
+
n = 0;
|
|
5
|
+
w = [];
|
|
6
|
+
constructor(word, n) {
|
|
7
|
+
word != null && this.add(word, n);
|
|
8
|
+
}
|
|
9
|
+
add(word, n = word.length) {
|
|
10
|
+
this.w.push(word);
|
|
11
|
+
this.n += n + ~~(this.n > 0);
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
toString() {
|
|
15
|
+
return this.w.join(" ");
|
|
16
|
+
}
|
|
24
17
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
export const SPLIT_PLAIN = {
|
|
29
|
-
length: (x) => x.length,
|
|
30
|
-
split: (_, max) => max,
|
|
18
|
+
const SPLIT_PLAIN = {
|
|
19
|
+
length: (x) => x.length,
|
|
20
|
+
split: (_, max) => max
|
|
31
21
|
};
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
return i;
|
|
49
|
-
},
|
|
22
|
+
const SPLIT_ANSI = {
|
|
23
|
+
length: lengthAnsi,
|
|
24
|
+
split: (x, max) => {
|
|
25
|
+
const re = /\x1b\[[0-9;]+m/g;
|
|
26
|
+
let i = max;
|
|
27
|
+
let match;
|
|
28
|
+
while (match = re.exec(x)) {
|
|
29
|
+
if (match.index >= max)
|
|
30
|
+
break;
|
|
31
|
+
const n = match[0].length;
|
|
32
|
+
i += n;
|
|
33
|
+
max += n;
|
|
34
|
+
}
|
|
35
|
+
return i;
|
|
36
|
+
}
|
|
50
37
|
};
|
|
51
|
-
/**
|
|
52
|
-
* Attempts to append given word to current line or else creates a new line.
|
|
53
|
-
*
|
|
54
|
-
* @internal
|
|
55
|
-
*/
|
|
56
38
|
const append = (acc, word, wordLen, width) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
? curr.add(word, wordLen)
|
|
60
|
-
: acc.push(new Line(word, wordLen));
|
|
39
|
+
const curr = acc[acc.length - 1];
|
|
40
|
+
curr && width - curr.n > wordLen ? curr.add(word, wordLen) : acc.push(new Line(word, wordLen));
|
|
61
41
|
};
|
|
62
|
-
/**
|
|
63
|
-
* Depending on wrap mode (hard/soft), splits too long words into multiple lines
|
|
64
|
-
* and appends them to `acc`.
|
|
65
|
-
*
|
|
66
|
-
* @remarks
|
|
67
|
-
* Splitting uses the provided {@link IWordSplit} impl (or, if missing,
|
|
68
|
-
* {@link SPLIT_PLAIN}). If the current start line only has less than
|
|
69
|
-
* {@link WordWrapOpts.min} chars available and the word is longer than that, it
|
|
70
|
-
* will be placed into a new line (thus minimizing legibility issues).
|
|
71
|
-
*
|
|
72
|
-
* @param word -
|
|
73
|
-
* @param opts -
|
|
74
|
-
* @param offset -
|
|
75
|
-
* @param acc -
|
|
76
|
-
*
|
|
77
|
-
* @internal
|
|
78
|
-
*/
|
|
79
42
|
const wrapWord = (word, { width, min, hard, splitter }, offset = 0, acc = []) => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
append(acc, word, len, width);
|
|
97
|
-
return acc;
|
|
43
|
+
let len = splitter.length(word);
|
|
44
|
+
let free = width - offset;
|
|
45
|
+
if (free < min && free < len) {
|
|
46
|
+
free = width;
|
|
47
|
+
}
|
|
48
|
+
while (hard && len > free) {
|
|
49
|
+
const split2 = splitter.split(word, free);
|
|
50
|
+
const chunk = word.substring(0, split2);
|
|
51
|
+
append(acc, chunk, free, width);
|
|
52
|
+
word = word.substring(split2);
|
|
53
|
+
free = width;
|
|
54
|
+
len = splitter.length(word);
|
|
55
|
+
}
|
|
56
|
+
append(acc, word, len, width);
|
|
57
|
+
return acc;
|
|
98
58
|
};
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* into text.
|
|
103
|
-
*
|
|
104
|
-
* @see {@link wordWrap} for main user facing alternative.
|
|
105
|
-
*
|
|
106
|
-
* @param line -
|
|
107
|
-
* @param opts -
|
|
108
|
-
* @param acc -
|
|
109
|
-
*
|
|
110
|
-
* @internal
|
|
111
|
-
*/
|
|
112
|
-
export const wordWrapLine = (line, opts, acc = []) => {
|
|
113
|
-
if (!line.length) {
|
|
114
|
-
acc.push(new Line());
|
|
115
|
-
return acc;
|
|
116
|
-
}
|
|
117
|
-
const $opts = {
|
|
118
|
-
width: 80,
|
|
119
|
-
min: 4,
|
|
120
|
-
hard: false,
|
|
121
|
-
splitter: SPLIT_PLAIN,
|
|
122
|
-
...opts,
|
|
123
|
-
};
|
|
124
|
-
for (let word of split(line, opts.delimWord || /\s/g)) {
|
|
125
|
-
const curr = acc[acc.length - 1];
|
|
126
|
-
wrapWord(word, $opts, curr && curr.n > 0 ? curr.n + 1 : 0, acc);
|
|
127
|
-
}
|
|
59
|
+
const wordWrapLine = (line, opts, acc = []) => {
|
|
60
|
+
if (!line.length) {
|
|
61
|
+
acc.push(new Line());
|
|
128
62
|
return acc;
|
|
63
|
+
}
|
|
64
|
+
const $opts = {
|
|
65
|
+
width: 80,
|
|
66
|
+
min: 4,
|
|
67
|
+
hard: false,
|
|
68
|
+
splitter: SPLIT_PLAIN,
|
|
69
|
+
...opts
|
|
70
|
+
};
|
|
71
|
+
for (let word of split(line, opts.delimWord || /\s/g)) {
|
|
72
|
+
const curr = acc[acc.length - 1];
|
|
73
|
+
wrapWord(word, $opts, curr && curr.n > 0 ? curr.n + 1 : 0, acc);
|
|
74
|
+
}
|
|
75
|
+
return acc;
|
|
129
76
|
};
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
return acc;
|
|
77
|
+
const wordWrapLines = (lines, opts) => {
|
|
78
|
+
let acc = [];
|
|
79
|
+
for (let line of split(lines, opts.delimLine)) {
|
|
80
|
+
acc = acc.concat(wordWrapLine(line, opts));
|
|
81
|
+
}
|
|
82
|
+
return acc;
|
|
83
|
+
};
|
|
84
|
+
const wordWrap = (str, opts) => wordWrapLines(str, opts).join("\n");
|
|
85
|
+
export {
|
|
86
|
+
SPLIT_ANSI,
|
|
87
|
+
SPLIT_PLAIN,
|
|
88
|
+
wordWrap,
|
|
89
|
+
wordWrapLine,
|
|
90
|
+
wordWrapLines
|
|
146
91
|
};
|
|
147
|
-
/**
|
|
148
|
-
* Same as {@link wordWrapLines}, but returns wordwrapped result as string. See
|
|
149
|
-
* {@link WordWrapOpts} for options.
|
|
150
|
-
*
|
|
151
|
-
* @param str -
|
|
152
|
-
* @param opts -
|
|
153
|
-
*/
|
|
154
|
-
export const wordWrap = (str, opts) => wordWrapLines(str, opts).join("\n");
|
package/wrap.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { memoizeJ } from "@thi.ng/memoize/memoizej";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
const wrap = memoizeJ(
|
|
3
|
+
(pad) => (x) => pad + x + pad
|
|
4
|
+
);
|
|
5
|
+
export {
|
|
6
|
+
wrap
|
|
7
|
+
};
|