0
# Source Manipulation
1
2
Classes for combining, modifying, and transforming sources while preserving source map information.
3
4
## Capabilities
5
6
### ConcatSource
7
8
Concatenates multiple sources or strings into a single source, preserving source map information from all components.
9
10
```typescript { .api }
11
/**
12
* Concatenates multiple sources or strings
13
* @param items - Sources, strings, or source-like objects to concatenate
14
*/
15
class ConcatSource extends Source {
16
constructor(...items: ConcatSourceChild[]);
17
18
/** Adds an item to the end of the concatenated source */
19
add(item: ConcatSourceChild): void;
20
21
/** Adds multiple items efficiently without optimization checks */
22
addAllSkipOptimizing(items: ConcatSourceChild[]): void;
23
24
/** Returns array of child sources */
25
getChildren(): Source[];
26
27
/** Streams chunks from all concatenated sources */
28
streamChunks(
29
options: StreamChunksOptions,
30
onChunk: OnChunk,
31
onSource: OnSource,
32
onName: OnName
33
): GeneratedSourceInfo;
34
}
35
36
/** Items that can be concatenated */
37
type ConcatSourceChild = string | Source | SourceLike;
38
```
39
40
**Usage Examples:**
41
42
```javascript
43
const { ConcatSource, RawSource, OriginalSource } = require("webpack-sources");
44
45
// Concatenate mixed content
46
const concat = new ConcatSource(
47
"// Header comment\n",
48
new OriginalSource("const x = 1;", "module.js"),
49
"\n",
50
new RawSource("console.log(x);")
51
);
52
53
console.log(concat.source());
54
// Output:
55
// // Header comment
56
// const x = 1;
57
// console.log(x);
58
59
// Add more content dynamically
60
concat.add("\n// Footer");
61
concat.add(new RawSource("module.exports = x;"));
62
63
// Check children
64
const children = concat.getChildren();
65
console.log(children.length); // Number of child sources
66
67
// Efficient bulk addition
68
const moreItems = [
69
"\n// More code",
70
new RawSource("console.log('done');")
71
];
72
concat.addAllSkipOptimizing(moreItems);
73
```
74
75
### ReplaceSource
76
77
Decorates a source with replacements and insertions, preserving source map information with identity mappings support.
78
79
```typescript { .api }
80
/**
81
* Source with replacements and insertions
82
* @param source - The source to decorate with replacements
83
* @param name - Optional name for the source
84
*/
85
class ReplaceSource extends Source {
86
constructor(source: Source, name?: string);
87
88
/**
89
* Replaces characters from start to end with replacement text
90
* @param start - Start position (0-indexed, inclusive)
91
* @param end - End position (0-indexed, inclusive)
92
* @param newValue - Replacement text
93
* @param name - Optional name for the replacement
94
*/
95
replace(start: number, end: number, newValue: string, name?: string): void;
96
97
/**
98
* Inserts text before the specified position
99
* @param pos - Position to insert before (0-indexed)
100
* @param newValue - Text to insert
101
* @param name - Optional name for the insertion
102
*/
103
insert(pos: number, newValue: string, name?: string): void;
104
105
/** Returns the original decorated source */
106
original(): Source;
107
108
/** Returns the name if provided */
109
getName(): string | undefined;
110
111
/** Returns array of all replacements */
112
getReplacements(): Replacement[];
113
114
/** Streams chunks with replacement and insertion processing */
115
streamChunks(
116
options: StreamChunksOptions,
117
onChunk: OnChunk,
118
onSource: OnSource,
119
onName: OnName
120
): GeneratedSourceInfo;
121
122
/** Replacement class constructor */
123
static Replacement: typeof Replacement;
124
}
125
```
126
127
**Usage Examples:**
128
129
```javascript
130
const { ReplaceSource, OriginalSource } = require("webpack-sources");
131
132
const original = new OriginalSource(
133
"function hello(name) {\n console.log('Hello ' + name);\n}",
134
"hello.js"
135
);
136
137
const modified = new ReplaceSource(original, "modified-hello.js");
138
139
// Replace function name
140
modified.replace(9, 13, "greet"); // Replace "hello" with "greet"
141
142
// Insert parameter validation
143
modified.insert(23, "if (!name) return; ");
144
145
// Replace string concatenation with template literal
146
modified.replace(45, 63, "`Hello ${name}`");
147
148
console.log(modified.source());
149
// Output:
150
// function greet(name) {
151
// if (!name) return; console.log(`Hello ${name}`);
152
// }
153
154
console.log(modified.getName()); // "modified-hello.js"
155
console.log(modified.original() === original); // true
156
157
// Get all modifications
158
const replacements = modified.getReplacements();
159
console.log(replacements.length); // Number of replacements/insertions
160
```
161
162
### PrefixSource
163
164
Prefixes every line of a source with a provided string, useful for indentation or commenting.
165
166
```typescript { .api }
167
/**
168
* Prefixes every line with a string
169
* @param prefix - String to prefix each line with
170
* @param source - Source to prefix (string, Buffer, or Source)
171
*/
172
class PrefixSource extends Source {
173
constructor(prefix: string, source: string | Source | Buffer);
174
175
/** Returns the prefix string */
176
getPrefix(): string;
177
178
/** Returns the original source */
179
original(): Source;
180
181
/** Streams chunks with line prefixing */
182
streamChunks(
183
options: StreamChunksOptions,
184
onChunk: OnChunk,
185
onSource: OnSource,
186
onName: OnName
187
): GeneratedSourceInfo;
188
}
189
```
190
191
**Usage Examples:**
192
193
```javascript
194
const { PrefixSource, RawSource } = require("webpack-sources");
195
196
// Add indentation
197
const code = "console.log('test');\nconsole.log('done');";
198
const indented = new PrefixSource(" ", code);
199
200
console.log(indented.source());
201
// Output:
202
// console.log('test');
203
// console.log('done');
204
205
// Add comment prefix
206
const commented = new PrefixSource("// ", new RawSource(code));
207
console.log(commented.source());
208
// Output:
209
// // console.log('test');
210
// // console.log('done');
211
212
console.log(commented.getPrefix()); // "// "
213
console.log(commented.original().source()); // Original uncommented code
214
215
// Complex prefixing
216
const numbered = new PrefixSource("/* Line */ ", code);
217
console.log(numbered.source());
218
// Output:
219
// /* Line */ console.log('test');
220
// /* Line */ console.log('done');
221
```
222
223
### Replacement Class
224
225
Represents a single replacement operation in ReplaceSource.
226
227
```typescript { .api }
228
/**
229
* Represents a replacement operation
230
* @param start - Start position (0-indexed, inclusive)
231
* @param end - End position (0-indexed, inclusive)
232
* @param content - Replacement content
233
* @param name - Optional name for the replacement
234
*/
235
class Replacement {
236
constructor(start: number, end: number, content: string, name?: string);
237
238
/** Start position of replacement */
239
start: number;
240
241
/** End position of replacement */
242
end: number;
243
244
/** Replacement content */
245
content: string;
246
247
/** Optional replacement name */
248
name?: string;
249
250
/** Optional index for ordering */
251
index?: number;
252
}
253
```
254
255
**Usage Example:**
256
257
```javascript
258
const { ReplaceSource } = require("webpack-sources");
259
260
// Access Replacement class
261
const ReplacementClass = ReplaceSource.Replacement;
262
263
// Create replacement manually (usually not needed)
264
const replacement = new ReplacementClass(0, 4, "const", "var-to-const");
265
console.log(replacement.start); // 0
266
console.log(replacement.end); // 4
267
console.log(replacement.content); // "const"
268
console.log(replacement.name); // "var-to-const"
269
```
270
271
### Source-Like Interface
272
273
Interface for objects that can be used as sources in concatenation and other operations.
274
275
```typescript { .api }
276
/**
277
* Interface for source-like objects that can be converted to Sources
278
*/
279
interface SourceLike {
280
/** Returns source content */
281
source(): string | Buffer;
282
/** Optional method to return content as Buffer */
283
buffer?(): Buffer;
284
/** Optional method to return size */
285
size?(): number;
286
/** Optional method to return source map */
287
map?(options?: MapOptions): RawSourceMap | null;
288
/** Optional method to return both source and map */
289
sourceAndMap?(options?: MapOptions): SourceAndMap;
290
/** Optional method to update hash */
291
updateHash?(hash: HashLike): void;
292
}
293
```