muggle-string 0.4.1 → 1.0.0-alpha.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.
@@ -0,0 +1,362 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSourceRewrite = createSourceRewrite;
4
+ function createSourceRewrite(source, text) {
5
+ return new Rewrite(source, text);
6
+ }
7
+ const coreRank = 0x7fffffff;
8
+ // Before: outermost (highest rank) first; Slot and After: innermost first
9
+ function compareEdits(a, b) {
10
+ if (a.at !== b.at) {
11
+ return a.at - b.at;
12
+ }
13
+ if (a.side !== b.side) {
14
+ return a.side - b.side;
15
+ }
16
+ if (a.rank !== b.rank) {
17
+ return a.side === 0 /* Side.Before */ ? b.rank - a.rank : a.rank - b.rank;
18
+ }
19
+ if (a.order !== b.order) {
20
+ return a.order < b.order ? -1 : 1;
21
+ }
22
+ return a.seq - b.seq;
23
+ }
24
+ class Edits {
25
+ constructor() {
26
+ this.records = [];
27
+ // the sorted records by column, filled when frozen
28
+ this.at = new Int32Array(0);
29
+ this.side = new Uint8Array(0);
30
+ this.code = [];
31
+ }
32
+ push(at, side, rank, order, code) {
33
+ this.records.push({ at, side, rank, order, seq: this.records.length, code });
34
+ }
35
+ freeze() {
36
+ const records = this.records;
37
+ // every writer's edits usually arrive in order; the sort is linear on such runs
38
+ for (let i = 1; i < records.length; i++) {
39
+ if (compareEdits(records[i - 1], records[i]) > 0) {
40
+ records.sort(compareEdits);
41
+ break;
42
+ }
43
+ }
44
+ const size = records.length;
45
+ this.at = new Int32Array(size);
46
+ this.side = new Uint8Array(size);
47
+ this.code = new Array(size);
48
+ for (let i = 0; i < size; i++) {
49
+ const record = records[i];
50
+ this.at[i] = record.at;
51
+ this.side[i] = record.side;
52
+ this.code[i] = record.code;
53
+ }
54
+ }
55
+ /** The first index from `low` whose anchor is at or after `offset`. */
56
+ lowerBound(offset, low) {
57
+ let high = this.at.length;
58
+ while (low < high) {
59
+ const mid = (low + high) >>> 1;
60
+ if (this.at[mid] < offset) {
61
+ low = mid + 1;
62
+ }
63
+ else {
64
+ high = mid;
65
+ }
66
+ }
67
+ return low;
68
+ }
69
+ }
70
+ class Rewrite {
71
+ constructor(source, text) {
72
+ this.source = source;
73
+ this.text = text;
74
+ this.edits = new Edits();
75
+ /** `insertAfter(0)`: before all text. */
76
+ this.head = new Edits();
77
+ /** `insertBefore(length)`: after all text. */
78
+ this.tail = new Edits();
79
+ /** Removed ranges as flat start, end pairs; merged when frozen. */
80
+ this.removals = [];
81
+ /** The top-level cuts, sorted and disjoint. */
82
+ this.roots = [];
83
+ this.frozen = false;
84
+ const core = this.createWriter(coreRank);
85
+ core.cut = (start, end, { data, placeholder }) => {
86
+ this.check(start, end);
87
+ const cut = new Cut(this, start, end, data, placeholder);
88
+ if (start === end) {
89
+ if (placeholder !== undefined) {
90
+ throw new RangeError(`The empty cut ${start}..${end} cannot have a placeholder.`);
91
+ }
92
+ if (!this.text.length) {
93
+ this.firstEmpty ??= cut;
94
+ }
95
+ }
96
+ else {
97
+ this.insertCut(cut);
98
+ }
99
+ return cut;
100
+ };
101
+ this.core = core;
102
+ }
103
+ writer(rank) {
104
+ if (!Number.isInteger(rank) || rank < 0 || rank >= coreRank) {
105
+ throw new RangeError(`The rank ${rank} is not a non-negative integer below the rank of core.`);
106
+ }
107
+ return this.createWriter(rank);
108
+ }
109
+ createWriter(rank) {
110
+ return {
111
+ insertBefore: (offset, code, options) => {
112
+ this.check(offset, offset);
113
+ const order = getOrder(options);
114
+ if (offset === this.text.length) {
115
+ this.tail.push(offset, 2 /* Side.After */, rank, order, code);
116
+ }
117
+ else {
118
+ this.edits.push(offset, 0 /* Side.Before */, rank, order, code);
119
+ }
120
+ },
121
+ insertAfter: (offset, code, options) => {
122
+ this.check(offset, offset);
123
+ const order = getOrder(options);
124
+ if (offset === 0) {
125
+ this.head.push(0, 0 /* Side.Before */, rank, order, code);
126
+ }
127
+ else {
128
+ this.edits.push(offset - 1, 2 /* Side.After */, rank, order, code);
129
+ }
130
+ },
131
+ replace: (start, end, code, options) => {
132
+ this.check(start, end);
133
+ if (start === end) {
134
+ throw new RangeError(`The replace at ${start}..${end} removes no char.`);
135
+ }
136
+ this.edits.push(start, 1 /* Side.Slot */, rank, getOrder(options), code);
137
+ this.removals.push(start, end);
138
+ },
139
+ };
140
+ }
141
+ check(start, end) {
142
+ if (this.frozen) {
143
+ throw new Error('The rewrite is already rendered.');
144
+ }
145
+ if (!Number.isInteger(start) || !Number.isInteger(end) || start < 0 || start > end || end > this.text.length) {
146
+ throw new RangeError(`${start}..${end} is out of 0..${this.text.length}.`);
147
+ }
148
+ }
149
+ // A cut that crosses `cut` intersects it, so it lies inside every cut that contains `cut`: the descent only checks
150
+ // the siblings that `cut` intersects, of the innermost cut that contains it.
151
+ insertCut(cut) {
152
+ const { start, end } = cut;
153
+ const last = this.lastCut;
154
+ let siblings = last && last.start <= start && end <= last.end ? last.children : this.roots;
155
+ while (true) {
156
+ let first = 0;
157
+ let after = siblings.length;
158
+ for (let high = after; first < high;) {
159
+ const mid = (first + high) >>> 1;
160
+ if (siblings[mid].end <= start) {
161
+ first = mid + 1;
162
+ }
163
+ else {
164
+ high = mid;
165
+ }
166
+ }
167
+ for (let low = first; low < after;) {
168
+ const mid = (low + after) >>> 1;
169
+ if (siblings[mid].start < end) {
170
+ low = mid + 1;
171
+ }
172
+ else {
173
+ after = mid;
174
+ }
175
+ }
176
+ if (after - first === 1 && siblings[first].start <= start && end <= siblings[first].end) {
177
+ siblings = siblings[first].children;
178
+ continue;
179
+ }
180
+ if (after > first) {
181
+ // the siblings in between lie strictly inside `cut`
182
+ for (const sibling of [siblings[first], siblings[after - 1]]) {
183
+ if (sibling.start < start || sibling.end > end) {
184
+ throw new RangeError(`The cut ${start}..${end} crosses the cut ${sibling.start}..${sibling.end}; cuts are nested or disjoint.`);
185
+ }
186
+ }
187
+ cut.children = siblings.splice(first, after - first, cut);
188
+ }
189
+ else {
190
+ siblings.splice(first, 0, cut);
191
+ }
192
+ this.lastCut = cut;
193
+ return;
194
+ }
195
+ }
196
+ freeze() {
197
+ if (this.frozen) {
198
+ return;
199
+ }
200
+ this.frozen = true;
201
+ this.edits.freeze();
202
+ this.head.freeze();
203
+ this.tail.freeze();
204
+ const removals = this.removals;
205
+ const pairs = removals.length >> 1;
206
+ for (let pair = 1; pair < pairs; pair++) {
207
+ if (removals[2 * pair - 2] > removals[2 * pair]) {
208
+ const sorted = Array.from({ length: pairs }, (_, index) => [removals[2 * index], removals[2 * index + 1]])
209
+ .sort((a, b) => a[0] - b[0]);
210
+ for (let index = 0; index < pairs; index++) {
211
+ removals[2 * index] = sorted[index][0];
212
+ removals[2 * index + 1] = sorted[index][1];
213
+ }
214
+ break;
215
+ }
216
+ }
217
+ let merged = 0;
218
+ for (let pair = 0; pair < pairs; pair++) {
219
+ const start = removals[2 * pair];
220
+ const end = removals[2 * pair + 1];
221
+ if (merged && start <= removals[merged - 1]) {
222
+ if (end > removals[merged - 1]) {
223
+ removals[merged - 1] = end;
224
+ }
225
+ }
226
+ else {
227
+ removals[merged++] = start;
228
+ removals[merged++] = end;
229
+ }
230
+ }
231
+ removals.length = merged;
232
+ for (const root of this.roots) {
233
+ root.isRoot = true;
234
+ }
235
+ }
236
+ }
237
+ function getOrder(options) {
238
+ const order = options?.order ?? 0;
239
+ if (typeof order !== 'number' || Number.isNaN(order)) {
240
+ throw new TypeError(`The order ${order} is not a number.`);
241
+ }
242
+ return order;
243
+ }
244
+ class Cut {
245
+ constructor(rewrite, start, end, data, placeholder) {
246
+ this.rewrite = rewrite;
247
+ this.start = start;
248
+ this.end = end;
249
+ this.data = data;
250
+ this.placeholder = placeholder;
251
+ /** The cuts directly inside, sorted and disjoint. */
252
+ this.children = [];
253
+ this.isRoot = false;
254
+ this.placed = false;
255
+ }
256
+ render(sink) {
257
+ if (this.placed) {
258
+ throw new Error(`The cut ${this.start}..${this.end} is placed twice.`);
259
+ }
260
+ this.placed = true;
261
+ const rewrite = this.rewrite;
262
+ rewrite.freeze();
263
+ const { edits, removals, head, tail } = rewrite;
264
+ const { start, end, children, data } = this;
265
+ if (start === end) {
266
+ if (this === rewrite.firstEmpty) {
267
+ renderAll(head, sink);
268
+ renderAll(tail, sink);
269
+ }
270
+ return;
271
+ }
272
+ if (this.isRoot && start === 0) {
273
+ renderAll(head, sink);
274
+ }
275
+ const removalsEnd = removals.length;
276
+ let pos = start;
277
+ let removal = 0;
278
+ // the first removal that ends after `pos`, from `removal` on
279
+ const seekRemoval = () => {
280
+ let low = removal >> 1;
281
+ let high = removalsEnd >> 1;
282
+ while (low < high) {
283
+ const mid = (low + high) >>> 1;
284
+ if (removals[2 * mid + 1] <= pos) {
285
+ low = mid + 1;
286
+ }
287
+ else {
288
+ high = mid;
289
+ }
290
+ }
291
+ removal = low * 2;
292
+ };
293
+ // the kept chars from `pos` to `to`, as runs between the removals
294
+ const renderText = (to) => {
295
+ while (pos < to) {
296
+ while (removal < removalsEnd && removals[removal + 1] <= pos) {
297
+ removal += 2;
298
+ }
299
+ if (removal < removalsEnd && removals[removal] <= pos) {
300
+ pos = Math.min(removals[removal + 1], to);
301
+ continue;
302
+ }
303
+ const stop = removal < removalsEnd ? Math.min(removals[removal], to) : to;
304
+ sink.source(rewrite, pos, stop, data);
305
+ pos = stop;
306
+ }
307
+ };
308
+ seekRemoval();
309
+ const { at, side, code } = edits;
310
+ const size = at.length;
311
+ let edit = edits.lowerBound(start, 0);
312
+ for (let index = 0;; index++) {
313
+ const child = children[index];
314
+ const until = child ? child.start : end;
315
+ for (; edit < size && at[edit] < until; edit++) {
316
+ renderText(side[edit] === 2 /* Side.After */ ? at[edit] + 1 : at[edit]);
317
+ renderCode(code[edit], sink);
318
+ }
319
+ if (!child) {
320
+ break;
321
+ }
322
+ renderText(child.start);
323
+ if (child.placeholder !== undefined) {
324
+ renderCode(child.placeholder, sink);
325
+ }
326
+ pos = child.end;
327
+ seekRemoval();
328
+ edit = edits.lowerBound(child.end, edit);
329
+ }
330
+ renderText(end);
331
+ if (this.isRoot && end === rewrite.text.length) {
332
+ renderAll(tail, sink);
333
+ }
334
+ }
335
+ }
336
+ function renderAll(edits, sink) {
337
+ for (const code of edits.code) {
338
+ renderCode(code, sink);
339
+ }
340
+ }
341
+ function renderCode(code, sink) {
342
+ if (typeof code === 'string') {
343
+ if (code) {
344
+ sink.text(code);
345
+ }
346
+ return;
347
+ }
348
+ for (const item of code()) {
349
+ if (typeof item === 'string') {
350
+ if (item) {
351
+ sink.text(item);
352
+ }
353
+ }
354
+ else if (Array.isArray(item)) {
355
+ sink.segment(item);
356
+ }
357
+ else {
358
+ item.render(sink);
359
+ }
360
+ }
361
+ }
362
+ //# sourceMappingURL=sourceRewrite.js.map
package/out/types.d.ts CHANGED
@@ -1,16 +1,4 @@
1
- declare const NO_DATA_SYMBOL: unique symbol;
2
- export type Segment<T = typeof NO_DATA_SYMBOL> = string | (T extends typeof NO_DATA_SYMBOL ? [
3
- text: string,
4
- source: string | undefined,
5
- sourceOffset: number
6
- ] : [
7
- text: string,
8
- source: string | undefined,
9
- sourceOffset: number,
10
- data: T
11
- ]);
12
- export interface StackNode {
13
- length: number;
14
- stack: string;
15
- }
16
- export {};
1
+ /** Generated code: plain text, or text that maps to `sourceOffset` of `source`. */
2
+ export type Segment<Source, Data> = string | [text: string, source: Source, sourceOffset: number, data: Data];
3
+ /** A segment of generated code that maps to a source. */
4
+ export type MappedSegment<Source, Data> = Exclude<Segment<Source, Data>, string>;
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "muggle-string",
3
- "version": "0.4.1",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "Ranked, conflict-free rewrites of a source text, rendered as format-neutral segments",
4
5
  "main": "out/index.js",
6
+ "types": "out/index.d.ts",
5
7
  "license": "MIT",
6
8
  "files": [
7
9
  "out/**/*.js",
@@ -12,11 +14,12 @@
12
14
  "url": "https://github.com/johnsoncodehk/muggle-string.git"
13
15
  },
14
16
  "scripts": {
17
+ "build": "tsc",
15
18
  "test": "vitest run"
16
19
  },
17
20
  "devDependencies": {
18
- "typescript": "latest",
19
- "vitest": "latest",
20
- "vite": "latest"
21
+ "@types/node": "^26.0.1",
22
+ "typescript": "7.1.0-beta",
23
+ "vitest": "latest"
21
24
  }
22
25
  }
package/out/base.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import { Range, Segment } from './types';
2
- export declare function getLength(segments: Segment<any>[]): number;
3
- export declare function toString<T extends Segment<any>>(segments: T[]): string;
4
- export declare function replace<T extends Segment<any>>(segments: T[], pattern: string | RegExp, ...replacers: (T | ((match: string) => T))[]): void;
5
- export declare function replaceAll<T extends Segment<any>>(segments: T[], pattern: RegExp, ...replacers: (T | ((match: string) => T))[]): void;
6
- export declare function overwrite<T extends Segment<any>>(segments: T[], range: number | Range, ...inserts: T[]): T[];
package/out/base.js DELETED
@@ -1,119 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.overwrite = exports.replaceAll = exports.replace = exports.toString = exports.getLength = void 0;
4
- const binarySearch_1 = require("./binarySearch");
5
- const track_1 = require("./track");
6
- function getLength(segments) {
7
- let length = 0;
8
- for (const segment of segments) {
9
- length += typeof segment == 'string' ? segment.length : segment[0].length;
10
- }
11
- return length;
12
- }
13
- exports.getLength = getLength;
14
- function toString(segments) {
15
- return segments.map(s => typeof s === 'string' ? s : s[0]).join('');
16
- }
17
- exports.toString = toString;
18
- function replace(segments, pattern, ...replacers) {
19
- const str = toString(segments);
20
- const match = str.match(pattern);
21
- if (match && match.index !== undefined) {
22
- const start = match.index;
23
- const end = start + match[0].length;
24
- (0, track_1.offsetStack)();
25
- overwrite(segments, [start, end], ...replacers.map(replacer => typeof replacer === 'function' ? replacer(match[0]) : replacer));
26
- (0, track_1.resetOffsetStack)();
27
- }
28
- }
29
- exports.replace = replace;
30
- function replaceAll(segments, pattern, ...replacers) {
31
- const str = toString(segments);
32
- const allMatch = str.matchAll(pattern);
33
- let length = str.length;
34
- let lengthDiff = 0;
35
- for (const match of allMatch) {
36
- if (match.index !== undefined) {
37
- const start = match.index + lengthDiff;
38
- const end = start + match[0].length;
39
- (0, track_1.offsetStack)();
40
- overwrite(segments, [start, end], ...replacers.map(replacer => typeof replacer === 'function' ? replacer(match[0]) : replacer));
41
- (0, track_1.resetOffsetStack)();
42
- const newLength = getLength(segments);
43
- lengthDiff += newLength - length;
44
- length = newLength;
45
- }
46
- }
47
- }
48
- exports.replaceAll = replaceAll;
49
- function overwrite(segments, range, ...inserts) {
50
- const offsets = toOffsets(segments);
51
- const [start, end] = typeof range === 'number' ? [range, range] : range;
52
- const startIndex = (0, binarySearch_1.binarySearch)(offsets, start);
53
- const endIndex = (0, binarySearch_1.binarySearch)(offsets, end);
54
- const startSegment = segments[startIndex];
55
- const endSegment = segments[endIndex];
56
- const startSegmentStart = offsets[startIndex];
57
- const endSegmentStart = offsets[endIndex];
58
- const endSegmentEnd = offsets[endIndex] + (typeof endSegment === 'string' ? endSegment.length : endSegment[0].length);
59
- if (start > startSegmentStart) {
60
- inserts.unshift(trimSegmentEnd(startSegment, start - startSegmentStart));
61
- }
62
- if (end < endSegmentEnd) {
63
- inserts.push(trimSegmentStart(endSegment, end - endSegmentStart));
64
- }
65
- (0, track_1.offsetStack)();
66
- const deleted = segments.splice(startIndex, endIndex - startIndex + 1, ...inserts);
67
- (0, track_1.resetOffsetStack)();
68
- if (end < endSegmentEnd) {
69
- deleted[deleted.length - 1] = trimSegmentEnd(deleted[deleted.length - 1], end - endSegmentStart);
70
- }
71
- if (start > startSegmentStart) {
72
- deleted[0] = trimSegmentStart(deleted[0], start - startSegmentStart);
73
- }
74
- return deleted;
75
- }
76
- exports.overwrite = overwrite;
77
- function trimSegmentEnd(segment, trimEnd) {
78
- if (typeof segment === 'string') {
79
- return segment.slice(0, trimEnd);
80
- }
81
- const originalString = segment[0];
82
- const originalRange = segment[2];
83
- const newString = originalString.slice(0, trimEnd);
84
- const newRange = typeof originalRange === 'number' ? originalRange : [originalRange[0], originalRange[1] - (originalString.length - newString.length)];
85
- return [
86
- newString,
87
- segment[1],
88
- newRange,
89
- ...segment.slice(3),
90
- ];
91
- }
92
- function trimSegmentStart(segment, trimStart) {
93
- if (typeof segment === 'string') {
94
- return segment.slice(trimStart);
95
- }
96
- const originalString = segment[0];
97
- const originalRange = segment[2];
98
- const newString = originalString.slice(trimStart);
99
- if (trimStart < 0) {
100
- trimStart += originalString.length;
101
- }
102
- const newRange = typeof originalRange === 'number' ? originalRange + trimStart : [originalRange[0] + trimStart, originalRange[1]];
103
- return [
104
- newString,
105
- segment[1],
106
- newRange,
107
- ...segment.slice(3),
108
- ];
109
- }
110
- function toOffsets(segments) {
111
- const offsets = [];
112
- let offset = 0;
113
- for (const segment of segments) {
114
- offsets.push(offset);
115
- offset += typeof segment == 'string' ? segment.length : segment[0].length;
116
- }
117
- return offsets;
118
- }
119
- //# sourceMappingURL=base.js.map
package/out/basic.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import { Range, Segment } from './types';
2
- export declare function getLength(segments: Segment<any>[]): number;
3
- export declare function toString<T extends Segment<any>>(segments: T[]): string;
4
- export declare function replace<T extends Segment<any>>(segments: T[], pattern: string | RegExp, ...replacers: (T | ((match: string) => T))[]): void;
5
- export declare function replaceAll<T extends Segment<any>>(segments: T[], pattern: RegExp, ...replacers: (T | ((match: string) => T))[]): void;
6
- export declare function overwrite<T extends Segment<any>>(segments: T[], range: number | Range, ...inserts: T[]): T[];
package/out/basic.js DELETED
@@ -1,119 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.overwrite = exports.replaceAll = exports.replace = exports.toString = exports.getLength = void 0;
4
- const binarySearch_1 = require("./binarySearch");
5
- const track_1 = require("./track");
6
- function getLength(segments) {
7
- let length = 0;
8
- for (const segment of segments) {
9
- length += typeof segment == 'string' ? segment.length : segment[0].length;
10
- }
11
- return length;
12
- }
13
- exports.getLength = getLength;
14
- function toString(segments) {
15
- return segments.map(s => typeof s === 'string' ? s : s[0]).join('');
16
- }
17
- exports.toString = toString;
18
- function replace(segments, pattern, ...replacers) {
19
- const str = toString(segments);
20
- const match = str.match(pattern);
21
- if (match && match.index !== undefined) {
22
- const start = match.index;
23
- const end = start + match[0].length;
24
- (0, track_1.offsetStack)();
25
- overwrite(segments, [start, end], ...replacers.map(replacer => typeof replacer === 'function' ? replacer(match[0]) : replacer));
26
- (0, track_1.resetOffsetStack)();
27
- }
28
- }
29
- exports.replace = replace;
30
- function replaceAll(segments, pattern, ...replacers) {
31
- const str = toString(segments);
32
- const allMatch = str.matchAll(pattern);
33
- let length = str.length;
34
- let lengthDiff = 0;
35
- for (const match of allMatch) {
36
- if (match.index !== undefined) {
37
- const start = match.index + lengthDiff;
38
- const end = start + match[0].length;
39
- (0, track_1.offsetStack)();
40
- overwrite(segments, [start, end], ...replacers.map(replacer => typeof replacer === 'function' ? replacer(match[0]) : replacer));
41
- (0, track_1.resetOffsetStack)();
42
- const newLength = getLength(segments);
43
- lengthDiff += newLength - length;
44
- length = newLength;
45
- }
46
- }
47
- }
48
- exports.replaceAll = replaceAll;
49
- function overwrite(segments, range, ...inserts) {
50
- const offsets = toOffsets(segments);
51
- const [start, end] = typeof range === 'number' ? [range, range] : range;
52
- const startIndex = (0, binarySearch_1.binarySearch)(offsets, start);
53
- const endIndex = (0, binarySearch_1.binarySearch)(offsets, end);
54
- const startSegment = segments[startIndex];
55
- const endSegment = segments[endIndex];
56
- const startSegmentStart = offsets[startIndex];
57
- const endSegmentStart = offsets[endIndex];
58
- const endSegmentEnd = offsets[endIndex] + (typeof endSegment === 'string' ? endSegment.length : endSegment[0].length);
59
- if (start > startSegmentStart) {
60
- inserts.unshift(trimSegmentEnd(startSegment, start - startSegmentStart));
61
- }
62
- if (end < endSegmentEnd) {
63
- inserts.push(trimSegmentStart(endSegment, end - endSegmentStart));
64
- }
65
- (0, track_1.offsetStack)();
66
- const deleted = segments.splice(startIndex, endIndex - startIndex + 1, ...inserts);
67
- (0, track_1.resetOffsetStack)();
68
- if (end < endSegmentEnd) {
69
- deleted[deleted.length - 1] = trimSegmentEnd(deleted[deleted.length - 1], end - endSegmentStart);
70
- }
71
- if (start > startSegmentStart) {
72
- deleted[0] = trimSegmentStart(deleted[0], start - startSegmentStart);
73
- }
74
- return deleted;
75
- }
76
- exports.overwrite = overwrite;
77
- function trimSegmentEnd(segment, trimEnd) {
78
- if (typeof segment === 'string') {
79
- return segment.slice(0, trimEnd);
80
- }
81
- const originalString = segment[0];
82
- const originalRange = segment[2];
83
- const newString = originalString.slice(0, trimEnd);
84
- const newRange = typeof originalRange === 'number' ? originalRange : [originalRange[0], originalRange[1] - (originalString.length - newString.length)];
85
- return [
86
- newString,
87
- segment[1],
88
- newRange,
89
- ...segment.slice(3),
90
- ];
91
- }
92
- function trimSegmentStart(segment, trimStart) {
93
- if (typeof segment === 'string') {
94
- return segment.slice(trimStart);
95
- }
96
- const originalString = segment[0];
97
- const originalRange = segment[2];
98
- const newString = originalString.slice(trimStart);
99
- if (trimStart < 0) {
100
- trimStart += originalString.length;
101
- }
102
- const newRange = typeof originalRange === 'number' ? originalRange + trimStart : [originalRange[0] + trimStart, originalRange[1]];
103
- return [
104
- newString,
105
- segment[1],
106
- newRange,
107
- ...segment.slice(3),
108
- ];
109
- }
110
- function toOffsets(segments) {
111
- const offsets = [];
112
- let offset = 0;
113
- for (const segment of segments) {
114
- offsets.push(offset);
115
- offset += typeof segment == 'string' ? segment.length : segment[0].length;
116
- }
117
- return offsets;
118
- }
119
- //# sourceMappingURL=basic.js.map
@@ -1 +0,0 @@
1
- export declare function binarySearch(offsets: number[], start: number): number;
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.binarySearch = void 0;
4
- function binarySearch(offsets, start) {
5
- let low = 0;
6
- let high = offsets.length - 1;
7
- while (low <= high) {
8
- const mid = Math.floor((low + high) / 2);
9
- const midValue = offsets[mid];
10
- if (midValue < start) {
11
- low = mid + 1;
12
- }
13
- else if (midValue > start) {
14
- high = mid - 1;
15
- }
16
- else {
17
- low = mid;
18
- high = mid;
19
- break;
20
- }
21
- }
22
- return Math.max(Math.min(low, high, offsets.length - 1), 0);
23
- }
24
- exports.binarySearch = binarySearch;
25
- //# sourceMappingURL=binarySearch.js.map