source: node_modules/magic-string/README.md@ 3a74959

Last change on this file since 3a74959 was 57e58a3, checked in by ste08 <sjovanoska@…>, 4 months ago

Initial commit

  • Property mode set to 100644
File size: 12.3 KB
Line 
1# magic-string
2
3<a href="https://github.com/Rich-Harris/magic-string/actions/workflows/test.yml">
4 <img src="https://img.shields.io/github/actions/workflow/status/Rich-Harris/magic-string/test.yml"
5 alt="build status">
6</a>
7<a href="https://npmjs.org/package/magic-string">
8 <img src="https://img.shields.io/npm/v/magic-string.svg"
9 alt="npm version">
10</a>
11<a href="https://github.com/Rich-Harris/magic-string/blob/master/LICENSE.md">
12 <img src="https://img.shields.io/npm/l/magic-string.svg"
13 alt="license">
14</a>
15
16Suppose you have some source code. You want to make some light modifications to it - replacing a few characters here and there, wrapping it with a header and footer, etc - and ideally you'd like to generate a [source map](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/) at the end of it. You've thought about using something like [recast](https://github.com/benjamn/recast) (which allows you to generate an AST from some JavaScript, manipulate it, and reprint it with a sourcemap without losing your comments and formatting), but it seems like overkill for your needs (or maybe the source code isn't JavaScript).
17
18Your requirements are, frankly, rather niche. But they're requirements that I also have, and for which I made magic-string. It's a small, fast utility for manipulating strings and generating sourcemaps.
19
20## Installation
21
22magic-string works in both node.js and browser environments. For node, install with npm:
23
24```bash
25npm i magic-string
26```
27
28To use in browser, grab the [magic-string.umd.js](https://unpkg.com/magic-string/dist/magic-string.umd.js) file and add it to your page:
29
30```html
31<script src="magic-string.umd.js"></script>
32```
33
34(It also works with various module systems, if you prefer that sort of thing - it has a dependency on [vlq](https://github.com/Rich-Harris/vlq).)
35
36## Usage
37
38These examples assume you're in node.js, or something similar:
39
40```js
41import MagicString from 'magic-string';
42import fs from 'fs';
43
44const s = new MagicString('problems = 99');
45
46s.update(0, 8, 'answer');
47s.toString(); // 'answer = 99'
48
49s.update(11, 13, '42'); // character indices always refer to the original string
50s.toString(); // 'answer = 42'
51
52s.prepend('var ').append(';'); // most methods are chainable
53s.toString(); // 'var answer = 42;'
54
55const map = s.generateMap({
56 source: 'source.js',
57 file: 'converted.js.map',
58 includeContent: true,
59}); // generates a v3 sourcemap
60
61fs.writeFileSync('converted.js', s.toString());
62fs.writeFileSync('converted.js.map', map.toString());
63```
64
65You can pass an options argument:
66
67```js
68const s = new MagicString(someCode, {
69 // these options will be used if you later call `bundle.addSource( s )` - see below
70 filename: 'foo.js',
71 indentExclusionRanges: [
72 /*...*/
73 ],
74 // mark source as ignore in DevTools, see below #Bundling
75 ignoreList: false,
76 // adjust the incoming position - see below
77 offset: 0,
78});
79```
80
81## Properties
82
83### s.offset
84
85Sets the offset property to adjust the incoming position for the following APIs: `slice`, `update`, `overwrite`, `appendLeft`, `prependLeft`, `appendRight`, `prependRight`, `move`, `reset`, and `remove`.
86
87Example usage:
88
89```ts
90const s = new MagicString('hello world', { offset: 0 });
91s.offset = 6;
92s.slice() === 'world';
93```
94
95## Methods
96
97### s.addSourcemapLocation( index )
98
99Adds the specified character index (with respect to the original string) to sourcemap mappings, if `hires` is `false` (see below).
100
101### s.append( content )
102
103Appends the specified content to the end of the string. Returns `this`.
104
105### s.appendLeft( index, content )
106
107Appends the specified `content` at the `index` in the original string. If a range _ending_ with `index` is subsequently moved, the insert will be moved with it. Returns `this`. See also `s.prependLeft(...)`.
108
109### s.appendRight( index, content )
110
111Appends the specified `content` at the `index` in the original string. If a range _starting_ with `index` is subsequently moved, the insert will be moved with it. Returns `this`. See also `s.prependRight(...)`.
112
113### s.clone()
114
115Does what you'd expect.
116
117### s.generateDecodedMap( options )
118
119Generates a sourcemap object with raw mappings in array form, rather than encoded as a string. See `generateMap` documentation below for options details. Useful if you need to manipulate the sourcemap further, but most of the time you will use `generateMap` instead.
120
121### s.generateMap( options )
122
123Generates a [version 3 sourcemap](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit). All options are, well, optional:
124
125- `file` - the filename where you plan to write the sourcemap
126- `source` - the filename of the file containing the original source
127- `includeContent` - whether to include the original content in the map's `sourcesContent` array
128- `hires` - whether the mapping should be high-resolution. Hi-res mappings map every single character, meaning (for example) your devtools will always be able to pinpoint the exact location of function calls and so on. With lo-res mappings, devtools may only be able to identify the correct line - but they're quicker to generate and less bulky. You can also set `"boundary"` to generate a semi-hi-res mappings segmented per word boundary instead of per character, suitable for string semantics that are separated by words. If sourcemap locations have been specified with `s.addSourcemapLocation()`, they will be used here.
129
130The returned sourcemap has two (non-enumerable) methods attached for convenience:
131
132- `toString` - returns the equivalent of `JSON.stringify(map)`
133- `toUrl` - returns a DataURI containing the sourcemap. Useful for doing this sort of thing:
134
135```js
136code += '\n//# sourceMappingURL=' + map.toUrl();
137```
138
139### s.hasChanged()
140
141Indicates if the string has been changed.
142
143### s.indent( prefix[, options] )
144
145Prefixes each line of the string with `prefix`. If `prefix` is not supplied, the indentation will be guessed from the original content, falling back to a single tab character. Returns `this`.
146
147The `options` argument can have an `exclude` property, which is an array of `[start, end]` character ranges. These ranges will be excluded from the indentation - useful for (e.g.) multiline strings.
148
149### s.insertLeft( index, content )
150
151**DEPRECATED** since 0.17 – use `s.appendLeft(...)` instead
152
153### s.insertRight( index, content )
154
155**DEPRECATED** since 0.17 – use `s.prependRight(...)` instead
156
157### s.isEmpty()
158
159Returns true if the resulting source is empty (disregarding white space).
160
161### s.locate( index )
162
163**DEPRECATED** since 0.10 – see [#30](https://github.com/Rich-Harris/magic-string/pull/30)
164
165### s.locateOrigin( index )
166
167**DEPRECATED** since 0.10 – see [#30](https://github.com/Rich-Harris/magic-string/pull/30)
168
169### s.move( start, end, index )
170
171Moves the characters from `start` and `end` to `index`. Returns `this`.
172
173### s.overwrite( start, end, content[, options] )
174
175Replaces the characters from `start` to `end` with `content`, along with the appended/prepended content in that range. The same restrictions as `s.remove()` apply. Returns `this`.
176
177The fourth argument is optional. It can have a `storeName` property — if `true`, the original name will be stored for later inclusion in a sourcemap's `names` array — and a `contentOnly` property which determines whether only the content is overwritten, or anything that was appended/prepended to the range as well.
178
179It may be preferred to use `s.update(...)` instead if you wish to avoid overwriting the appended/prepended content.
180
181### s.prepend( content )
182
183Prepends the string with the specified content. Returns `this`.
184
185### s.prependLeft ( index, content )
186
187Same as `s.appendLeft(...)`, except that the inserted content will go _before_ any previous appends or prepends at `index`
188
189### s.prependRight ( index, content )
190
191Same as `s.appendRight(...)`, except that the inserted content will go _before_ any previous appends or prepends at `index`
192
193### s.replace( regexpOrString, substitution )
194
195String replacement with RegExp or string. When using a RegExp, replacer function is also supported. Returns `this`.
196
197```ts
198import MagicString from 'magic-string';
199
200const s = new MagicString(source);
201
202s.replace('foo', 'bar');
203s.replace(/foo/g, 'bar');
204s.replace(/(\w)(\d+)/g, (_, $1, $2) => $1.toUpperCase() + $2);
205```
206
207The differences from [`String.replace`](<(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace)>):
208
209- It will always match against the **original string**
210- It mutates the magic string state (use `.clone()` to be immutable)
211
212### s.replaceAll( regexpOrString, substitution )
213
214Same as `s.replace`, but replace all matched strings instead of just one.
215If `regexpOrString` is a regex, then it must have the global (`g`) flag set, or a `TypeError` is thrown. Matches the behavior of the builtin [`String.property.replaceAll`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll). Returns `this`.
216
217### s.remove( start, end )
218
219Removes the characters from `start` to `end` (of the original string, **not** the generated string). Removing the same content twice, or making removals that partially overlap, will cause an error. Returns `this`.
220
221### s.reset( start, end )
222
223Resets the characters from `start` to `end` (of the original string, **not** the generated string).
224It can be used to restore previously removed characters and discard unwanted changes.
225
226### s.slice( start, end )
227
228Returns the content of the generated string that corresponds to the slice between `start` and `end` of the original string. Throws error if the indices are for characters that were already removed.
229
230### s.snip( start, end )
231
232Returns a clone of `s`, with all content before the `start` and `end` characters of the original string removed.
233
234### s.toString()
235
236Returns the generated string.
237
238### s.trim([ charType ])
239
240Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start and end. Returns `this`.
241
242### s.trimStart([ charType ])
243
244Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the start. Returns `this`.
245
246### s.trimEnd([ charType ])
247
248Trims content matching `charType` (defaults to `\s`, i.e. whitespace) from the end. Returns `this`.
249
250### s.trimLines()
251
252Removes empty lines from the start and end. Returns `this`.
253
254### s.update( start, end, content[, options] )
255
256Replaces the characters from `start` to `end` with `content`. The same restrictions as `s.remove()` apply. Returns `this`.
257
258The fourth argument is optional. It can have a `storeName` property — if `true`, the original name will be stored for later inclusion in a sourcemap's `names` array — and an `overwrite` property which defaults to `false` and determines whether anything that was appended/prepended to the range will be overwritten along with the original content.
259
260`s.update(start, end, content)` is equivalent to `s.overwrite(start, end, content, { contentOnly: true })`.
261
262## Bundling
263
264To concatenate several sources, use `MagicString.Bundle`:
265
266```js
267const bundle = new MagicString.Bundle();
268
269bundle.addSource({
270 filename: 'foo.js',
271 content: new MagicString('var answer = 42;'),
272});
273
274bundle.addSource({
275 filename: 'bar.js',
276 content: new MagicString('console.log( answer )'),
277});
278
279// Sources can be marked as ignore-listed, which provides a hint to debuggers
280// to not step into this code and also don't show the source files depending
281// on user preferences.
282bundle.addSource({
283 filename: 'some-3rdparty-library.js',
284 content: new MagicString('function myLib(){}'),
285 ignoreList: false, // <--
286});
287
288// Advanced: a source can include an `indentExclusionRanges` property
289// alongside `filename` and `content`. This will be passed to `s.indent()`
290// - see documentation above
291
292bundle
293 .indent() // optionally, pass an indent string, otherwise it will be guessed
294 .prepend('(function () {\n')
295 .append('}());');
296
297bundle.toString();
298// (function () {
299// var answer = 42;
300// console.log( answer );
301// }());
302
303// options are as per `s.generateMap()` above
304const map = bundle.generateMap({
305 file: 'bundle.js',
306 includeContent: true,
307 hires: true,
308});
309```
310
311As an alternative syntax, if you a) don't have `filename` or `indentExclusionRanges` options, or b) passed those in when you used `new MagicString(...)`, you can simply pass the `MagicString` instance itself:
312
313```js
314const bundle = new MagicString.Bundle();
315const source = new MagicString(someCode, {
316 filename: 'foo.js',
317});
318
319bundle.addSource(source);
320```
321
322## License
323
324MIT
Note: See TracBrowser for help on using the repository browser.