Skip to content

Commit

Permalink
feat: introduce offset (#297)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiyuanzmj authored Dec 16, 2024
1 parent 24cb8ea commit 29f260e
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 2 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,25 @@ const s = new MagicString(someCode, {
],
// mark source as ignore in DevTools, see below #Bundling
ignoreList: false,
// adjust the incoming position - see below
offset: 0,
});
```

## Properties

### s.offset

Sets the offset property to adjust the incoming position for the following APIs: `slice`, `update`, `overwrite`, `appendLeft`, `prependLeft`, `appendRight`, `prependRight`, `move`, `reset`, and `remove`.

Example usage:

```ts
const s = new MagicString('hello world', { offset: 0 });
s.offset = 6;
s.slice() === 'world';
```

## Methods

### s.addSourcemapLocation( index )
Expand Down
29 changes: 27 additions & 2 deletions src/MagicString.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default class MagicString {
storedNames: { writable: true, value: {} },
indentStr: { writable: true, value: undefined },
ignoreList: { writable: true, value: options.ignoreList },
offset: { writable: true, value: options.offset || 0 },
});

if (DEBUG) {
Expand All @@ -57,6 +58,8 @@ export default class MagicString {
}

appendLeft(index, content) {
index = index + this.offset;

if (typeof content !== 'string') throw new TypeError('inserted content must be a string');

if (DEBUG) this.stats.time('appendLeft');
Expand All @@ -76,6 +79,8 @@ export default class MagicString {
}

appendRight(index, content) {
index = index + this.offset;

if (typeof content !== 'string') throw new TypeError('inserted content must be a string');

if (DEBUG) this.stats.time('appendRight');
Expand All @@ -95,7 +100,7 @@ export default class MagicString {
}

clone() {
const cloned = new MagicString(this.original, { filename: this.filename });
const cloned = new MagicString(this.original, { filename: this.filename, offset: this.offset });

let originalChunk = this.firstChunk;
let clonedChunk = (cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone());
Expand Down Expand Up @@ -312,6 +317,10 @@ export default class MagicString {
}

move(start, end, index) {
start = start + this.offset;
end = end + this.offset;
index = index + this.offset;

if (index >= start && index <= end) throw new Error('Cannot move a selection inside itself');

if (DEBUG) this.stats.time('move');
Expand Down Expand Up @@ -358,6 +367,9 @@ export default class MagicString {
}

update(start, end, content, options) {
start = start + this.offset;
end = end + this.offset;

if (typeof content !== 'string') throw new TypeError('replacement content must be a string');

if (this.original.length !== 0) {
Expand Down Expand Up @@ -433,6 +445,8 @@ export default class MagicString {
}

prependLeft(index, content) {
index = index + this.offset;

if (typeof content !== 'string') throw new TypeError('inserted content must be a string');

if (DEBUG) this.stats.time('insertRight');
Expand All @@ -452,6 +466,8 @@ export default class MagicString {
}

prependRight(index, content) {
index = index + this.offset;

if (typeof content !== 'string') throw new TypeError('inserted content must be a string');

if (DEBUG) this.stats.time('insertRight');
Expand All @@ -471,6 +487,9 @@ export default class MagicString {
}

remove(start, end) {
start = start + this.offset;
end = end + this.offset;

if (this.original.length !== 0) {
while (start < 0) start += this.original.length;
while (end < 0) end += this.original.length;
Expand Down Expand Up @@ -501,6 +520,9 @@ export default class MagicString {
}

reset(start, end) {
start = start + this.offset;
end = end + this.offset;

if (this.original.length !== 0) {
while (start < 0) start += this.original.length;
while (end < 0) end += this.original.length;
Expand Down Expand Up @@ -569,7 +591,10 @@ export default class MagicString {
return this.intro + lineStr;
}

slice(start = 0, end = this.original.length) {
slice(start = 0, end = this.original.length - this.offset) {
start = start + this.offset;
end = end + this.offset;

if (this.original.length !== 0) {
while (start < 0) start += this.original.length;
while (end < 0) end += this.original.length;
Expand Down
3 changes: 3 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export type ExclusionRange = [number, number];
export interface MagicStringOptions {
filename?: string;
indentExclusionRanges?: ExclusionRange | Array<ExclusionRange>;
offset?: number;
}

export interface IndentOptions {
Expand Down Expand Up @@ -283,4 +284,6 @@ export default class MagicString {
* Returns the generated string.
*/
toString(): string;

offset: number;
}
18 changes: 18 additions & 0 deletions test/MagicString.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1902,5 +1902,23 @@ describe('MagicString', () => {
message: 'MagicString.prototype.replaceAll called with a non-global RegExp argument',
});
});

it('with offset', () => {
const s = new MagicString('hello world', { offset: 6 });
assert.equal(s.slice(0, 5), 'world');
assert.equal(s.remove(0, 5).toString(), 'hello ');
assert.equal(s.prependLeft(0, 'w').toString(), 'hello w');
assert.equal(s.appendLeft(0, 'o').toString(), 'hello wo');
assert.equal(s.prependRight(0, 'r').toString(), 'hello wor');
assert.equal(s.appendRight(0, 'l').toString(), 'hello worl');
assert.equal(s.reset(4, 5).toString(), 'hello world');
assert.equal(s.update(0, 5, 'd').toString(), 'hello world');
assert.equal(s.overwrite(0, 5, 'rld').toString(), 'hello world');

s.offset = 1;
const s1 = s.clone();
assert.strictEqual(s1.slice(), 'ello world');
assert.equal(s1.move(0, 1, 2).slice(0), 'elo world');
});
});
});

0 comments on commit 29f260e

Please sign in to comment.