lineputscript 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 YIYuNCU
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,347 @@
1
+ # LinePutScript
2
+
3
+ TypeScript SDK for the LinePutScript (LPS) data format — a text-based hierarchical key-value storage format.
4
+
5
+ LPS is a simple, human-readable structured data format used by the [VPet](https://github.com/LorisYounger/VPet) virtual pet simulator and other applications. It represents nested key-value pairs, typed values, multi-line text, and comments in a compact line-oriented syntax.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install lineputscript
11
+ ```
12
+
13
+ Requires Node.js >= 18.
14
+
15
+ ## LPS Format Overview
16
+
17
+ A LinePutScript document consists of **Lines**, each containing an optional **Info** value, zero or more **Subs** (nested key-value pairs), and optional **Text** content.
18
+
19
+ ```
20
+ Name#Info:||Sub1#Val1:||Sub2#Val2:||TextContent
21
+ ```
22
+
23
+ - `#` separates the line name from its info value
24
+ - `:|` separates subs within a line, and precedes the text content
25
+ - Subs have the same `Name#Value` structure as lines
26
+ - Lines are separated by newlines
27
+
28
+ ### Example
29
+
30
+ ```
31
+ note#greeting:|sub#hello:|world
32
+ config#settings:|timeout#30:|enabled#true:|production
33
+ ```
34
+
35
+ This document has two lines:
36
+ - `note` with info `greeting`, one sub (`sub` = `hello`), and text `world`
37
+ - `config` with info `settings`, two subs (`timeout` = `30`, `enabled` = `true`), and text `production`
38
+
39
+ ### Escape Sequences
40
+
41
+ Characters with special meaning in LPS are escaped in storage and unescaped on display:
42
+
43
+ | Character | Stored As |
44
+ |-----------|-----------|
45
+ | `\|` | `/\|` |
46
+ | `/` | `/!` |
47
+ | `:\|` | `/stop` |
48
+ | `\t` | `/tab` |
49
+ | `\n` | `/n` |
50
+ | `\r` | `/r` |
51
+ | `#` | `/id` |
52
+ | `,` | `/com` |
53
+
54
+ Use `textReplace()` to convert display text → storage format, and `textDeReplace()` to convert storage → display format.
55
+
56
+ ## Quick Start
57
+
58
+ ```typescript
59
+ import { LPS, Line, Sub } from 'lineputscript';
60
+
61
+ // Parse a document
62
+ const doc = new LPS(`name#value:|subkey#subval:|extra text`);
63
+
64
+ // Read values
65
+ const line = doc.findLine('name');
66
+ console.log(line?.infoDisplay); // 'value'
67
+ console.log(line?.textDisplay); // 'extra text'
68
+ console.log(line?.find('subkey')?.infoDisplay); // 'subval'
69
+
70
+ // Typed access
71
+ doc.setLineInt('count', 42);
72
+ console.log(doc.getLineInt('count')); // 42
73
+
74
+ doc.setLineBool('flag', true);
75
+ console.log(doc.getLineBool('flag')); // true
76
+
77
+ // Modify
78
+ const vupmod = doc.findorAddLine('vupmod');
79
+ vupmod.findorAdd('author').infoDisplay = 'LorisYounger';
80
+
81
+ // Serialize back to string
82
+ const output = doc.toString();
83
+ ```
84
+
85
+ ## API Reference
86
+
87
+ ### `Sub`
88
+
89
+ The base unit — a named value pair.
90
+
91
+ ```typescript
92
+ new Sub() // Empty sub
93
+ new Sub('name#value') // Parse from LPS string
94
+ new Sub('name', 'value') // Name + info
95
+ new Sub('tags', 'a', 'b', 'c') // Multiple infos (comma-joined, escape-aware)
96
+
97
+ // Properties
98
+ sub.name // string
99
+ sub.info // Raw storage-escaped info string
100
+ sub.infoDisplay // Display-unescaped info string
101
+ sub.infoToInt // number
102
+ sub.infoToInt64 // bigint
103
+ sub.infoToDouble // number
104
+ sub.infoToBoolean // boolean
105
+ sub.infos // StringStructure (comma-separated values as key-value pairs)
106
+
107
+ // Methods
108
+ sub.getString() // Display-unescaped string
109
+ sub.getInteger() // Parse as int
110
+ sub.getInteger64() // Parse as bigint
111
+ sub.getDouble() // Parse as float
112
+ sub.getBoolean() // Parse as bool ('true'/'t'/'1' → true)
113
+ sub.getDateTime() // Parse as Date (.NET ticks or ISO string)
114
+ sub.getFloat() // Parse as FInt64
115
+ sub.setString(val) // Set from display string (auto-escapes)
116
+ sub.setInteger(val) // Set from number
117
+ sub.setInteger64(val) // Set from bigint
118
+ sub.setDouble(val) // Set from number
119
+ sub.setBoolean(val) // Set from boolean
120
+ sub.setDateTime(val) // Set from Date (.NET ticks)
121
+ sub.setFloat(val) // Set from FInt64
122
+ sub.getInfos() // Get comma-separated values as string[]
123
+ sub.first() // First comma-separated value or null
124
+ sub.last() // Last comma-separated value or null
125
+ sub.load(lpsString) // Parse from LPS string
126
+ sub.set(other) // Copy from another ISub
127
+ sub.toString() // Serialize to 'name#info:|' format
128
+ ```
129
+
130
+ ### `Line` (extends `Sub`)
131
+
132
+ A Sub with child subs, text content, and comments.
133
+
134
+ ```typescript
135
+ new Line() // Empty line
136
+ new Line('name#info:||sub#val:||text') // Parse from LPS string
137
+ new Line('name', 'info', 'text', [sub1, sub2])
138
+
139
+ // Properties (in addition to Sub)
140
+ line.text // Raw storage-escaped text
141
+ line.textDisplay // Display-unescaped text
142
+ line.textToInt // number
143
+ line.textToInt64 // bigint
144
+ line.textToDouble // number
145
+ line.comments // String after /// marker
146
+ line.texts // StringStructure over text content
147
+ line.subs // ISub[] — ordered list of child subs
148
+
149
+ // Sub management
150
+ line.addSub(sub)
151
+ line.addorReplaceSub(sub)
152
+ line.addRange([sub1, sub2])
153
+ line.insertSub(index, sub)
154
+ line.remove(sub) // boolean
155
+ line.removeByName(name) // boolean
156
+ line.removeAll(name)
157
+ line.removeAt(index)
158
+ line.contains(sub) // boolean
159
+ line.containsByName(name) // boolean
160
+ line.find(name) // ISub | null
161
+ line.find(name, info) // ISub | null (match name + info)
162
+ line.findInfo(info) // ISub | null (match info only)
163
+ line.findAll(name) // ISub[]
164
+ line.findorAdd(name) // Find existing or create new
165
+ line.search(value) // ISub | null (substring match on name)
166
+ line.searchAll(value) // ISub[] (substring match on name)
167
+ line.indexOf(name) // number
168
+ line.indexsOf(name) // number[] (all indices)
169
+
170
+ // Typed shorthands on subs (find-or-create, then get/set typed value)
171
+ line.getSubBool(name) // boolean
172
+ line.setSubBool(name, val)
173
+ line.getSubInt(name, default?) // number
174
+ line.setSubInt(name, val)
175
+ line.getSubInt64(name, default?) // bigint
176
+ line.setSubInt64(name, val)
177
+ line.getSubDouble(name, default?) // number
178
+ line.setSubDouble(name, val)
179
+ line.getSubString(name, default?) // string | null
180
+ line.setSubString(name, val)
181
+ line.getSubFloat(name, default?) // FInt64
182
+ line.setSubFloat(name, val)
183
+ line.getSubDateTime(name, default?) // Date | null
184
+ line.setSubDateTime(name, val)
185
+ ```
186
+
187
+ ### `LineDict` (extends `Sub`)
188
+
189
+ Same interface as `Line` but backed by a `Map<string, ISub>` for unique-name fast O(1) lookup. When duplicate names are added, the last one wins.
190
+
191
+ ### `LPS` / `LpsDocument`
192
+
193
+ A document containing an ordered collection of lines.
194
+
195
+ ```typescript
196
+ new LPS() // Empty document
197
+ new LPS(lpsString) // Parse from LPS string
198
+ new LPS([line1, line2]) // From array of lines
199
+
200
+ // Properties
201
+ doc.assemblage // ILine[]
202
+ doc.count // number of lines
203
+ doc.length // Estimated serialized byte length
204
+
205
+ // Line management
206
+ doc.addLine(line)
207
+ doc.addorReplaceLine(line)
208
+ doc.addRange([line1, line2])
209
+ doc.insertLine(index, line)
210
+ doc.remove(line) // boolean (by reference or name)
211
+ doc.removeAll(target) // by reference or name
212
+ doc.removeAt(index)
213
+ doc.contains(line) // boolean (line or sub)
214
+ doc.containsLine(name) // boolean
215
+ doc.containsSub(name) // boolean
216
+
217
+ // Querying
218
+ doc.findLine(name) // ILine | null
219
+ doc.findLine(name, info) // ILine | null (match name + info)
220
+ doc.findLineInfo(info) // ILine | null
221
+ doc.findorAddLine(name) // Find existing or create new
222
+ doc.findAllLine(name) // ILine[]
223
+ doc.findAllLineInfo(info) // ILine[]
224
+
225
+ // Cross-line sub search
226
+ doc.findSub(name) // ISub | null (first match across all lines)
227
+ doc.findSub(name, info) // ISub | null
228
+ doc.findSubInfo(info) // ISub | null
229
+ doc.findAllSub(name) // ISub[]
230
+
231
+ // Text search (substring match on name)
232
+ doc.searchLine(value) // ILine | null
233
+ doc.searchAllLine(value) // ILine[]
234
+ doc.searchSub(value) // ISub | null
235
+ doc.searchAllSub(value) // ISub[]
236
+
237
+ doc.indexOf(name) // number
238
+ doc.first() // ILine | null
239
+ doc.last() // ILine | null
240
+ doc.load(lpsString) // Parse/replace content
241
+ doc.toString() // Serialize to LPS string
242
+
243
+ // Typed shorthands on lines (find-or-add-line, then get/set typed info)
244
+ doc.getLineBool(name)
245
+ doc.setLineBool(name, val)
246
+ doc.getLineInt(name, default?)
247
+ doc.setLineInt(name, val)
248
+ doc.getLineInt64(name, default?)
249
+ doc.setLineInt64(name, val)
250
+ doc.getLineDouble(name, default?)
251
+ doc.setLineDouble(name, val)
252
+ doc.getLineString(name, default?)
253
+ doc.setLineString(name, val)
254
+ doc.getLineFloat(name, default?)
255
+ doc.setLineFloat(name, val)
256
+ doc.getLineDateTime(name, default?)
257
+ doc.setLineDateTime(name, val)
258
+ ```
259
+
260
+ #### `LpsDocument` extends `LPS` — adds cursor operations
261
+
262
+ ```typescript
263
+ const doc = new LpsDocument(lpsString);
264
+
265
+ doc.readNext() // ILine | null — reads and advances cursor
266
+ doc.read() // ILine | null — reads without advancing
267
+ doc.append(line) // Inserts line after current cursor position
268
+ doc.append(name, info, text, ...subs) // Create and insert
269
+ doc.appendSub(...subs) // Add subs to current line
270
+ doc.appendSubByName(name, info)
271
+ doc.readReset() // Reset cursor to start
272
+ doc.readEnd() // Move cursor past end
273
+ doc.readCanNext() // boolean
274
+ doc.lineNode // get/set cursor position (0-based, clamped)
275
+ ```
276
+
277
+ ### `StringStructure`
278
+
279
+ A dictionary view over a string encoded as `/n`-delimited `key=value` pairs, with caching.
280
+
281
+ ```typescript
282
+ const ss = new StringStructure(
283
+ (val) => { /* setter — called when cache flushes */ },
284
+ () => /* getter — returns raw string */
285
+ );
286
+
287
+ ss.setString('key', 'value')
288
+ ss.getString('key') // string | null
289
+ ss.getBool('key') // boolean
290
+ ss.setBool('key', true)
291
+ ss.getInt('key', default?) // number
292
+ ss.setInt('key', 42)
293
+ ss.getInt64('key') // bigint
294
+ ss.getDouble('key') // number
295
+ ss.getFloat('key') // FInt64
296
+ ss.getDateTime('key') // Date | null
297
+ ss.containsKey('key') // boolean
298
+ ss.remove('key') // boolean
299
+ ss.clear()
300
+ ss.keys, ss.values, ss.count
301
+ ss[Symbol.iterator]() // Iterate [key, value] pairs
302
+ ```
303
+
304
+ ### `FInt64`
305
+
306
+ Fixed-precision 64-bit decimal using `bigint` internally (Anchor = 1e9). Provides exact decimal arithmetic without floating-point rounding errors.
307
+
308
+ ```typescript
309
+ FInt64.fromInt(42) // Integer → FInt64
310
+ FInt64.fromDouble(3.14) // Double → FInt64
311
+ FInt64.fromLong(1000000000n) // Raw bigint
312
+ FInt64.parse('3.14') // Parse string
313
+
314
+ a.add(b) // a + b
315
+ a.sub(b) // a - b
316
+ a.mul(b) // a * b
317
+ a.div(b) // a / b
318
+ a.compareTo(b) // -1, 0, or 1
319
+ a.equals(b) // boolean
320
+ a.toDouble() // number
321
+ a.toInt32() // number (truncated)
322
+ a.toInt64() // bigint (truncated)
323
+
324
+ FInt64.Zero, FInt64.One, FInt64.NaN
325
+ FInt64.MinValue, FInt64.MaxValue
326
+ FInt64.PositiveInfinity, FInt64.NegativeInfinity
327
+ ```
328
+
329
+ ### Utility Functions
330
+
331
+ ```typescript
332
+ import { textReplace, textDeReplace, getHashCode, getHashCode32, splitLimited } from 'lineputscript';
333
+
334
+ textReplace('hello|world') // → 'hello/!|world' (display → storage)
335
+ textDeReplace('hello/!|world') // → 'hello|world' (storage → display)
336
+ getHashCode('text') // → bigint (SHA-512 based, 64-bit LE)
337
+ getHashCode32('text') // → number (32-bit)
338
+ splitLimited('a:b:c', ':', 1) // → ['a', 'b:c']
339
+ ```
340
+
341
+ ## TypeScript
342
+
343
+ This package is written in TypeScript and ships with type declarations. All public APIs are fully typed.
344
+
345
+ ## License
346
+
347
+ MIT
@@ -0,0 +1,2 @@
1
+ 'use strict';
2
+
@@ -0,0 +1,233 @@
1
+ // src/utils/escaping.ts
2
+ function textReplace(text) {
3
+ if (text === null || text === void 0) return "";
4
+ let result = text;
5
+ result = result.replace(/\|/g, "/|");
6
+ result = result.replace(/\//g, "/!");
7
+ result = result.replace(/:\|/g, "/stop");
8
+ result = result.replace(/\t/g, "/tab");
9
+ result = result.replace(/\n/g, "/n");
10
+ result = result.replace(/\r/g, "/r");
11
+ result = result.replace(/#/g, "/id");
12
+ result = result.replace(/,/g, "/com");
13
+ return result;
14
+ }
15
+ function textDeReplace(text) {
16
+ if (text === null || text === void 0) return "";
17
+ let result = text;
18
+ result = result.replace(/\/stop/g, ":|");
19
+ result = result.replace(/\/equ/g, "=");
20
+ result = result.replace(/\/tab/g, " ");
21
+ result = result.replace(/\/n/g, "\n");
22
+ result = result.replace(/\/r/g, "\r");
23
+ result = result.replace(/\/id/g, "#");
24
+ result = result.replace(/\/com/g, ",");
25
+ result = result.replace(/\/!/g, "/");
26
+ result = result.replace(/\/\|/g, "|");
27
+ return result;
28
+ }
29
+
30
+ // src/utils/fint64.ts
31
+ var Anchor = 1000000000n;
32
+ var Anchord = 1e9;
33
+ var NaNValue = 9223372036854775807n - 1n;
34
+ var NegativeInfinityValue = -9223372036854775807n + 1n;
35
+ var PositiveInfinityValue = 9223372036854775807n;
36
+ var _FInt64 = class _FInt64 {
37
+ constructor(value) {
38
+ this.m_value = value;
39
+ }
40
+ static fromLong(value) {
41
+ return new _FInt64(value);
42
+ }
43
+ static fromDouble(value) {
44
+ return new _FInt64(BigInt(Math.round(value * Anchord)));
45
+ }
46
+ static fromNumber(value) {
47
+ return _FInt64.fromDouble(value);
48
+ }
49
+ static fromInt(value) {
50
+ return new _FInt64(BigInt(value) * Anchor);
51
+ }
52
+ static fromObject(value) {
53
+ if (value instanceof _FInt64) return value;
54
+ if (typeof value === "bigint") return new _FInt64(value);
55
+ if (typeof value === "number") {
56
+ if (Number.isInteger(value)) return _FInt64.fromInt(value);
57
+ return _FInt64.fromDouble(value);
58
+ }
59
+ if (typeof value === "string") return _FInt64.parse(value);
60
+ return _FInt64.NaN;
61
+ }
62
+ toDouble() {
63
+ if (this.isNaN()) return NaN;
64
+ return Number(this.m_value) / Anchord;
65
+ }
66
+ toStoreString() {
67
+ return this.m_value.toString();
68
+ }
69
+ toString() {
70
+ return this.toDouble().toString();
71
+ }
72
+ isNaN() {
73
+ return this.m_value === NaNValue;
74
+ }
75
+ isNegativeInfinity() {
76
+ return this.m_value === NegativeInfinityValue;
77
+ }
78
+ isPositiveInfinity() {
79
+ return this.m_value === PositiveInfinityValue;
80
+ }
81
+ isFinite() {
82
+ return !this.isNaN() && !this.isNegativeInfinity() && !this.isPositiveInfinity();
83
+ }
84
+ isInfinity() {
85
+ return this.isPositiveInfinity() || this.isNegativeInfinity();
86
+ }
87
+ isNegative() {
88
+ return this.m_value < 0n;
89
+ }
90
+ isNormal() {
91
+ return this.m_value !== 0n && this.isFinite();
92
+ }
93
+ toBoolean() {
94
+ return this.m_value > Anchor;
95
+ }
96
+ toInt32() {
97
+ return Math.trunc(this.toDouble());
98
+ }
99
+ toInt64() {
100
+ return this.m_value / Anchor;
101
+ }
102
+ // Arithmetic
103
+ add(other) {
104
+ return new _FInt64(this.m_value + other.m_value);
105
+ }
106
+ sub(other) {
107
+ return new _FInt64(this.m_value - other.m_value);
108
+ }
109
+ mul(other) {
110
+ return new _FInt64(this.m_value / 1000n * (other.m_value / 1000n) / 1000n);
111
+ }
112
+ div(other) {
113
+ return new _FInt64(this.m_value * 100000n / other.m_value * 10000n);
114
+ }
115
+ addDouble(other) {
116
+ return new _FInt64(this.m_value + BigInt(Math.round(other * Anchord)));
117
+ }
118
+ subDouble(other) {
119
+ return new _FInt64(this.m_value - BigInt(Math.round(other * Anchord)));
120
+ }
121
+ mulDouble(other) {
122
+ return new _FInt64(BigInt(Math.round(Number(this.m_value) * other)));
123
+ }
124
+ divDouble(other) {
125
+ return new _FInt64(BigInt(Math.round(Number(this.m_value) / other)));
126
+ }
127
+ negate() {
128
+ return new _FInt64(-this.m_value);
129
+ }
130
+ increment() {
131
+ return new _FInt64(this.m_value + Anchor);
132
+ }
133
+ decrement() {
134
+ return new _FInt64(this.m_value - Anchor);
135
+ }
136
+ // Bitwise
137
+ and(other) {
138
+ return new _FInt64(this.m_value & other.m_value);
139
+ }
140
+ or(other) {
141
+ return new _FInt64(this.m_value | other.m_value);
142
+ }
143
+ xor(other) {
144
+ return new _FInt64(this.m_value ^ other.m_value);
145
+ }
146
+ not() {
147
+ return new _FInt64(~this.m_value);
148
+ }
149
+ // Comparison
150
+ compareTo(other) {
151
+ if (this.isNaN()) return -1;
152
+ if (other.isNaN()) return 1;
153
+ if (this.m_value < other.m_value) return -1;
154
+ if (this.m_value > other.m_value) return 1;
155
+ return 0;
156
+ }
157
+ equals(other) {
158
+ if (this.isNaN() || other.isNaN()) return false;
159
+ return this.m_value === other.m_value;
160
+ }
161
+ // Parse
162
+ static parse(s) {
163
+ if (s === null || s === void 0) return _FInt64.NaN;
164
+ const longMatch = /^-?\d+$/.test(s);
165
+ if (longMatch) {
166
+ try {
167
+ const bi = BigInt(s);
168
+ return new _FInt64(bi);
169
+ } catch {
170
+ }
171
+ }
172
+ const d = Number(s);
173
+ if (!isNaN(d)) {
174
+ return _FInt64.fromDouble(d);
175
+ }
176
+ return _FInt64.NaN;
177
+ }
178
+ static tryParse(s) {
179
+ if (s === null || s === void 0) return { result: _FInt64.Zero, success: false };
180
+ const parsed = _FInt64.parse(s);
181
+ if (parsed.isNaN()) return { result: _FInt64.Zero, success: false };
182
+ return { result: parsed, success: true };
183
+ }
184
+ // Static helpers
185
+ static isFinite(d) {
186
+ return d.isFinite();
187
+ }
188
+ static isInfinity(d) {
189
+ return d.isInfinity();
190
+ }
191
+ static isNaNStatic(d) {
192
+ return d.isNaN();
193
+ }
194
+ static isNegative(d) {
195
+ return d.isNegative();
196
+ }
197
+ static isNormal(d) {
198
+ return d.isNormal();
199
+ }
200
+ };
201
+ // Constants
202
+ _FInt64.Anchor = Anchor;
203
+ _FInt64.Anchord = Anchord;
204
+ _FInt64.MinValue = new _FInt64(-9223372036854775807n - 1n);
205
+ _FInt64.MaxValue = new _FInt64(9223372036854775807n);
206
+ _FInt64.NaN = new _FInt64(NaNValue);
207
+ _FInt64.NegativeInfinity = new _FInt64(NegativeInfinityValue);
208
+ _FInt64.PositiveInfinity = new _FInt64(PositiveInfinityValue);
209
+ _FInt64.Zero = new _FInt64(0n);
210
+ _FInt64.One = new _FInt64(Anchor);
211
+ _FInt64.NegativeOne = _FInt64.fromDouble(-1);
212
+ _FInt64.AdditiveIdentity = new _FInt64(0n);
213
+ _FInt64.MultiplicativeIdentity = new _FInt64(Anchor);
214
+ var FInt64 = _FInt64;
215
+
216
+ // src/utils/parsing.ts
217
+ function splitLimited(text, separator, count = -1) {
218
+ if (count === -1) {
219
+ return text.split(separator);
220
+ }
221
+ const result = [];
222
+ let remaining = text;
223
+ for (let i = 0; i < count; i++) {
224
+ const idx = remaining.indexOf(separator);
225
+ if (idx === -1) break;
226
+ result.push(remaining.substring(0, idx));
227
+ remaining = remaining.substring(idx + separator.length);
228
+ }
229
+ result.push(remaining);
230
+ return result;
231
+ }
232
+
233
+ export { FInt64, splitLimited, textDeReplace, textReplace };