README.md
1 # Source Map 2 3 [](https://travis-ci.org/mozilla/source-map) 4 5 [](https://www.npmjs.com/package/source-map) 6 7 This is a library to generate and consume the source map format 8 [described here][format]. 9 10 [format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit 11 12 ## Use with Node 13 14 $ npm install source-map 15 16 ## Use on the Web 17 18 <script src="https://raw.githubusercontent.com/mozilla/source-map/master/dist/source-map.min.js" defer></script> 19 20 -------------------------------------------------------------------------------- 21 22 <!-- `npm run toc` to regenerate the Table of Contents --> 23 24 <!-- START doctoc generated TOC please keep comment here to allow auto update --> 25 <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> 26 ## Table of Contents 27 28 - [Examples](#examples) 29 - [Consuming a source map](#consuming-a-source-map) 30 - [Generating a source map](#generating-a-source-map) 31 - [With SourceNode (high level API)](#with-sourcenode-high-level-api) 32 - [With SourceMapGenerator (low level API)](#with-sourcemapgenerator-low-level-api) 33 - [API](#api) 34 - [SourceMapConsumer](#sourcemapconsumer) 35 - [new SourceMapConsumer(rawSourceMap)](#new-sourcemapconsumerrawsourcemap) 36 - [SourceMapConsumer.prototype.computeColumnSpans()](#sourcemapconsumerprototypecomputecolumnspans) 37 - [SourceMapConsumer.prototype.originalPositionFor(generatedPosition)](#sourcemapconsumerprototypeoriginalpositionforgeneratedposition) 38 - [SourceMapConsumer.prototype.generatedPositionFor(originalPosition)](#sourcemapconsumerprototypegeneratedpositionfororiginalposition) 39 - [SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition)](#sourcemapconsumerprototypeallgeneratedpositionsfororiginalposition) 40 - [SourceMapConsumer.prototype.hasContentsOfAllSources()](#sourcemapconsumerprototypehascontentsofallsources) 41 - [SourceMapConsumer.prototype.sourceContentFor(source[, returnNullOnMissing])](#sourcemapconsumerprototypesourcecontentforsource-returnnullonmissing) 42 - [SourceMapConsumer.prototype.eachMapping(callback, context, order)](#sourcemapconsumerprototypeeachmappingcallback-context-order) 43 - [SourceMapGenerator](#sourcemapgenerator) 44 - [new SourceMapGenerator([startOfSourceMap])](#new-sourcemapgeneratorstartofsourcemap) 45 - [SourceMapGenerator.fromSourceMap(sourceMapConsumer)](#sourcemapgeneratorfromsourcemapsourcemapconsumer) 46 - [SourceMapGenerator.prototype.addMapping(mapping)](#sourcemapgeneratorprototypeaddmappingmapping) 47 - [SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent)](#sourcemapgeneratorprototypesetsourcecontentsourcefile-sourcecontent) 48 - [SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]])](#sourcemapgeneratorprototypeapplysourcemapsourcemapconsumer-sourcefile-sourcemappath) 49 - [SourceMapGenerator.prototype.toString()](#sourcemapgeneratorprototypetostring) 50 - [SourceNode](#sourcenode) 51 - [new SourceNode([line, column, source[, chunk[, name]]])](#new-sourcenodeline-column-source-chunk-name) 52 - [SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath])](#sourcenodefromstringwithsourcemapcode-sourcemapconsumer-relativepath) 53 - [SourceNode.prototype.add(chunk)](#sourcenodeprototypeaddchunk) 54 - [SourceNode.prototype.prepend(chunk)](#sourcenodeprototypeprependchunk) 55 - [SourceNode.prototype.setSourceContent(sourceFile, sourceContent)](#sourcenodeprototypesetsourcecontentsourcefile-sourcecontent) 56 - [SourceNode.prototype.walk(fn)](#sourcenodeprototypewalkfn) 57 - [SourceNode.prototype.walkSourceContents(fn)](#sourcenodeprototypewalksourcecontentsfn) 58 - [SourceNode.prototype.join(sep)](#sourcenodeprototypejoinsep) 59 - [SourceNode.prototype.replaceRight(pattern, replacement)](#sourcenodeprototypereplacerightpattern-replacement) 60 - [SourceNode.prototype.toString()](#sourcenodeprototypetostring) 61 - [SourceNode.prototype.toStringWithSourceMap([startOfSourceMap])](#sourcenodeprototypetostringwithsourcemapstartofsourcemap) 62 63 <!-- END doctoc generated TOC please keep comment here to allow auto update --> 64 65 ## Examples 66 67 ### Consuming a source map 68 69 ```js 70 var rawSourceMap = { 71 version: 3, 72 file: 'min.js', 73 names: ['bar', 'baz', 'n'], 74 sources: ['one.js', 'two.js'], 75 sourceRoot: 'http://example.com/www/js/', 76 mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' 77 }; 78 79 var smc = new SourceMapConsumer(rawSourceMap); 80 81 console.log(smc.sources); 82 // [ 'http://example.com/www/js/one.js', 83 // 'http://example.com/www/js/two.js' ] 84 85 console.log(smc.originalPositionFor({ 86 line: 2, 87 column: 28 88 })); 89 // { source: 'http://example.com/www/js/two.js', 90 // line: 2, 91 // column: 10, 92 // name: 'n' } 93 94 console.log(smc.generatedPositionFor({ 95 source: 'http://example.com/www/js/two.js', 96 line: 2, 97 column: 10 98 })); 99 // { line: 2, column: 28 } 100 101 smc.eachMapping(function (m) { 102 // ... 103 }); 104 ``` 105 106 ### Generating a source map 107 108 In depth guide: 109 [**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/) 110 111 #### With SourceNode (high level API) 112 113 ```js 114 function compile(ast) { 115 switch (ast.type) { 116 case 'BinaryExpression': 117 return new SourceNode( 118 ast.location.line, 119 ast.location.column, 120 ast.location.source, 121 [compile(ast.left), " + ", compile(ast.right)] 122 ); 123 case 'Literal': 124 return new SourceNode( 125 ast.location.line, 126 ast.location.column, 127 ast.location.source, 128 String(ast.value) 129 ); 130 // ... 131 default: 132 throw new Error("Bad AST"); 133 } 134 } 135 136 var ast = parse("40 + 2", "add.js"); 137 console.log(compile(ast).toStringWithSourceMap({ 138 file: 'add.js' 139 })); 140 // { code: '40 + 2', 141 // map: [object SourceMapGenerator] } 142 ``` 143 144 #### With SourceMapGenerator (low level API) 145 146 ```js 147 var map = new SourceMapGenerator({ 148 file: "source-mapped.js" 149 }); 150 151 map.addMapping({ 152 generated: { 153 line: 10, 154 column: 35 155 }, 156 source: "foo.js", 157 original: { 158 line: 33, 159 column: 2 160 }, 161 name: "christopher" 162 }); 163 164 console.log(map.toString()); 165 // '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}' 166 ``` 167 168 ## API 169 170 Get a reference to the module: 171 172 ```js 173 // Node.js 174 var sourceMap = require('source-map'); 175 176 // Browser builds 177 var sourceMap = window.sourceMap; 178 179 // Inside Firefox 180 const sourceMap = require("devtools/toolkit/sourcemap/source-map.js"); 181 ``` 182 183 ### SourceMapConsumer 184 185 A SourceMapConsumer instance represents a parsed source map which we can query 186 for information about the original file positions by giving it a file position 187 in the generated source. 188 189 #### new SourceMapConsumer(rawSourceMap) 190 191 The only parameter is the raw source map (either as a string which can be 192 `JSON.parse`'d, or an object). According to the spec, source maps have the 193 following attributes: 194 195 * `version`: Which version of the source map spec this map is following. 196 197 * `sources`: An array of URLs to the original source files. 198 199 * `names`: An array of identifiers which can be referenced by individual 200 mappings. 201 202 * `sourceRoot`: Optional. The URL root from which all sources are relative. 203 204 * `sourcesContent`: Optional. An array of contents of the original source files. 205 206 * `mappings`: A string of base64 VLQs which contain the actual mappings. 207 208 * `file`: Optional. The generated filename this source map is associated with. 209 210 ```js 211 var consumer = new sourceMap.SourceMapConsumer(rawSourceMapJsonData); 212 ``` 213 214 #### SourceMapConsumer.prototype.computeColumnSpans() 215 216 Compute the last column for each generated mapping. The last column is 217 inclusive. 218 219 ```js 220 // Before: 221 consumer.allGeneratedPositionsFor({ line: 2, source: "foo.coffee" }) 222 // [ { line: 2, 223 // column: 1 }, 224 // { line: 2, 225 // column: 10 }, 226 // { line: 2, 227 // column: 20 } ] 228 229 consumer.computeColumnSpans(); 230 231 // After: 232 consumer.allGeneratedPositionsFor({ line: 2, source: "foo.coffee" }) 233 // [ { line: 2, 234 // column: 1, 235 // lastColumn: 9 }, 236 // { line: 2, 237 // column: 10, 238 // lastColumn: 19 }, 239 // { line: 2, 240 // column: 20, 241 // lastColumn: Infinity } ] 242 243 ``` 244 245 #### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) 246 247 Returns the original source, line, and column information for the generated 248 source's line and column positions provided. The only argument is an object with 249 the following properties: 250 251 * `line`: The line number in the generated source. Line numbers in 252 this library are 1-based (note that the underlying source map 253 specification uses 0-based line numbers -- this library handles the 254 translation). 255 256 * `column`: The column number in the generated source. Column numbers 257 in this library are 0-based. 258 259 * `bias`: Either `SourceMapConsumer.GREATEST_LOWER_BOUND` or 260 `SourceMapConsumer.LEAST_UPPER_BOUND`. Specifies whether to return the closest 261 element that is smaller than or greater than the one we are searching for, 262 respectively, if the exact element cannot be found. Defaults to 263 `SourceMapConsumer.GREATEST_LOWER_BOUND`. 264 265 and an object is returned with the following properties: 266 267 * `source`: The original source file, or null if this information is not 268 available. 269 270 * `line`: The line number in the original source, or null if this information is 271 not available. The line number is 1-based. 272 273 * `column`: The column number in the original source, or null if this 274 information is not available. The column number is 0-based. 275 276 * `name`: The original identifier, or null if this information is not available. 277 278 ```js 279 consumer.originalPositionFor({ line: 2, column: 10 }) 280 // { source: 'foo.coffee', 281 // line: 2, 282 // column: 2, 283 // name: null } 284 285 consumer.originalPositionFor({ line: 99999999999999999, column: 999999999999999 }) 286 // { source: null, 287 // line: null, 288 // column: null, 289 // name: null } 290 ``` 291 292 #### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) 293 294 Returns the generated line and column information for the original source, 295 line, and column positions provided. The only argument is an object with 296 the following properties: 297 298 * `source`: The filename of the original source. 299 300 * `line`: The line number in the original source. The line number is 301 1-based. 302 303 * `column`: The column number in the original source. The column 304 number is 0-based. 305 306 and an object is returned with the following properties: 307 308 * `line`: The line number in the generated source, or null. The line 309 number is 1-based. 310 311 * `column`: The column number in the generated source, or null. The 312 column number is 0-based. 313 314 ```js 315 consumer.generatedPositionFor({ source: "example.js", line: 2, column: 10 }) 316 // { line: 1, 317 // column: 56 } 318 ``` 319 320 #### SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition) 321 322 Returns all generated line and column information for the original source, line, 323 and column provided. If no column is provided, returns all mappings 324 corresponding to a either the line we are searching for or the next closest line 325 that has any mappings. Otherwise, returns all mappings corresponding to the 326 given line and either the column we are searching for or the next closest column 327 that has any offsets. 328 329 The only argument is an object with the following properties: 330 331 * `source`: The filename of the original source. 332 333 * `line`: The line number in the original source. The line number is 334 1-based. 335 336 * `column`: Optional. The column number in the original source. The 337 column number is 0-based. 338 339 and an array of objects is returned, each with the following properties: 340 341 * `line`: The line number in the generated source, or null. The line 342 number is 1-based. 343 344 * `column`: The column number in the generated source, or null. The 345 column number is 0-based. 346 347 ```js 348 consumer.allGeneratedpositionsfor({ line: 2, source: "foo.coffee" }) 349 // [ { line: 2, 350 // column: 1 }, 351 // { line: 2, 352 // column: 10 }, 353 // { line: 2, 354 // column: 20 } ] 355 ``` 356 357 #### SourceMapConsumer.prototype.hasContentsOfAllSources() 358 359 Return true if we have the embedded source content for every source listed in 360 the source map, false otherwise. 361 362 In other words, if this method returns `true`, then 363 `consumer.sourceContentFor(s)` will succeed for every source `s` in 364 `consumer.sources`. 365 366 ```js 367 // ... 368 if (consumer.hasContentsOfAllSources()) { 369 consumerReadyCallback(consumer); 370 } else { 371 fetchSources(consumer, consumerReadyCallback); 372 } 373 // ... 374 ``` 375 376 #### SourceMapConsumer.prototype.sourceContentFor(source[, returnNullOnMissing]) 377 378 Returns the original source content for the source provided. The only 379 argument is the URL of the original source file. 380 381 If the source content for the given source is not found, then an error is 382 thrown. Optionally, pass `true` as the second param to have `null` returned 383 instead. 384 385 ```js 386 consumer.sources 387 // [ "my-cool-lib.clj" ] 388 389 consumer.sourceContentFor("my-cool-lib.clj") 390 // "..." 391 392 consumer.sourceContentFor("this is not in the source map"); 393 // Error: "this is not in the source map" is not in the source map 394 395 consumer.sourceContentFor("this is not in the source map", true); 396 // null 397 ``` 398 399 #### SourceMapConsumer.prototype.eachMapping(callback, context, order) 400 401 Iterate over each mapping between an original source/line/column and a 402 generated line/column in this source map. 403 404 * `callback`: The function that is called with each mapping. Mappings have the 405 form `{ source, generatedLine, generatedColumn, originalLine, originalColumn, 406 name }` 407 408 * `context`: Optional. If specified, this object will be the value of `this` 409 every time that `callback` is called. 410 411 * `order`: Either `SourceMapConsumer.GENERATED_ORDER` or 412 `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over 413 the mappings sorted by the generated file's line/column order or the 414 original's source/line/column order, respectively. Defaults to 415 `SourceMapConsumer.GENERATED_ORDER`. 416 417 ```js 418 consumer.eachMapping(function (m) { console.log(m); }) 419 // ... 420 // { source: 'illmatic.js', 421 // generatedLine: 1, 422 // generatedColumn: 0, 423 // originalLine: 1, 424 // originalColumn: 0, 425 // name: null } 426 // { source: 'illmatic.js', 427 // generatedLine: 2, 428 // generatedColumn: 0, 429 // originalLine: 2, 430 // originalColumn: 0, 431 // name: null } 432 // ... 433 ``` 434 ### SourceMapGenerator 435 436 An instance of the SourceMapGenerator represents a source map which is being 437 built incrementally. 438 439 #### new SourceMapGenerator([startOfSourceMap]) 440 441 You may pass an object with the following properties: 442 443 * `file`: The filename of the generated source that this source map is 444 associated with. 445 446 * `sourceRoot`: A root for all relative URLs in this source map. 447 448 * `skipValidation`: Optional. When `true`, disables validation of mappings as 449 they are added. This can improve performance but should be used with 450 discretion, as a last resort. Even then, one should avoid using this flag when 451 running tests, if possible. 452 453 ```js 454 var generator = new sourceMap.SourceMapGenerator({ 455 file: "my-generated-javascript-file.js", 456 sourceRoot: "http://example.com/app/js/" 457 }); 458 ``` 459 460 #### SourceMapGenerator.fromSourceMap(sourceMapConsumer) 461 462 Creates a new `SourceMapGenerator` from an existing `SourceMapConsumer` instance. 463 464 * `sourceMapConsumer` The SourceMap. 465 466 ```js 467 var generator = sourceMap.SourceMapGenerator.fromSourceMap(consumer); 468 ``` 469 470 #### SourceMapGenerator.prototype.addMapping(mapping) 471 472 Add a single mapping from original source line and column to the generated 473 source's line and column for this source map being created. The mapping object 474 should have the following properties: 475 476 * `generated`: An object with the generated line and column positions. 477 478 * `original`: An object with the original line and column positions. 479 480 * `source`: The original source file (relative to the sourceRoot). 481 482 * `name`: An optional original token name for this mapping. 483 484 ```js 485 generator.addMapping({ 486 source: "module-one.scm", 487 original: { line: 128, column: 0 }, 488 generated: { line: 3, column: 456 } 489 }) 490 ``` 491 492 #### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) 493 494 Set the source content for an original source file. 495 496 * `sourceFile` the URL of the original source file. 497 498 * `sourceContent` the content of the source file. 499 500 ```js 501 generator.setSourceContent("module-one.scm", 502 fs.readFileSync("path/to/module-one.scm")) 503 ``` 504 505 #### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]]) 506 507 Applies a SourceMap for a source file to the SourceMap. 508 Each mapping to the supplied source file is rewritten using the 509 supplied SourceMap. Note: The resolution for the resulting mappings 510 is the minimum of this map and the supplied map. 511 512 * `sourceMapConsumer`: The SourceMap to be applied. 513 514 * `sourceFile`: Optional. The filename of the source file. 515 If omitted, sourceMapConsumer.file will be used, if it exists. 516 Otherwise an error will be thrown. 517 518 * `sourceMapPath`: Optional. The dirname of the path to the SourceMap 519 to be applied. If relative, it is relative to the SourceMap. 520 521 This parameter is needed when the two SourceMaps aren't in the same 522 directory, and the SourceMap to be applied contains relative source 523 paths. If so, those relative source paths need to be rewritten 524 relative to the SourceMap. 525 526 If omitted, it is assumed that both SourceMaps are in the same directory, 527 thus not needing any rewriting. (Supplying `'.'` has the same effect.) 528 529 #### SourceMapGenerator.prototype.toString() 530 531 Renders the source map being generated to a string. 532 533 ```js 534 generator.toString() 535 // '{"version":3,"sources":["module-one.scm"],"names":[],"mappings":"...snip...","file":"my-generated-javascript-file.js","sourceRoot":"http://example.com/app/js/"}' 536 ``` 537 538 ### SourceNode 539 540 SourceNodes provide a way to abstract over interpolating and/or concatenating 541 snippets of generated JavaScript source code, while maintaining the line and 542 column information associated between those snippets and the original source 543 code. This is useful as the final intermediate representation a compiler might 544 use before outputting the generated JS and source map. 545 546 #### new SourceNode([line, column, source[, chunk[, name]]]) 547 548 * `line`: The original line number associated with this source node, or null if 549 it isn't associated with an original line. The line number is 1-based. 550 551 * `column`: The original column number associated with this source node, or null 552 if it isn't associated with an original column. The column number 553 is 0-based. 554 555 * `source`: The original source's filename; null if no filename is provided. 556 557 * `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see 558 below. 559 560 * `name`: Optional. The original identifier. 561 562 ```js 563 var node = new SourceNode(1, 2, "a.cpp", [ 564 new SourceNode(3, 4, "b.cpp", "extern int status;\n"), 565 new SourceNode(5, 6, "c.cpp", "std::string* make_string(size_t n);\n"), 566 new SourceNode(7, 8, "d.cpp", "int main(int argc, char** argv) {}\n"), 567 ]); 568 ``` 569 570 #### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath]) 571 572 Creates a SourceNode from generated code and a SourceMapConsumer. 573 574 * `code`: The generated code 575 576 * `sourceMapConsumer` The SourceMap for the generated code 577 578 * `relativePath` The optional path that relative sources in `sourceMapConsumer` 579 should be relative to. 580 581 ```js 582 var consumer = new SourceMapConsumer(fs.readFileSync("path/to/my-file.js.map", "utf8")); 583 var node = SourceNode.fromStringWithSourceMap(fs.readFileSync("path/to/my-file.js"), 584 consumer); 585 ``` 586 587 #### SourceNode.prototype.add(chunk) 588 589 Add a chunk of generated JS to this source node. 590 591 * `chunk`: A string snippet of generated JS code, another instance of 592 `SourceNode`, or an array where each member is one of those things. 593 594 ```js 595 node.add(" + "); 596 node.add(otherNode); 597 node.add([leftHandOperandNode, " + ", rightHandOperandNode]); 598 ``` 599 600 #### SourceNode.prototype.prepend(chunk) 601 602 Prepend a chunk of generated JS to this source node. 603 604 * `chunk`: A string snippet of generated JS code, another instance of 605 `SourceNode`, or an array where each member is one of those things. 606 607 ```js 608 node.prepend("/** Build Id: f783haef86324gf **/\n\n"); 609 ``` 610 611 #### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) 612 613 Set the source content for a source file. This will be added to the 614 `SourceMap` in the `sourcesContent` field. 615 616 * `sourceFile`: The filename of the source file 617 618 * `sourceContent`: The content of the source file 619 620 ```js 621 node.setSourceContent("module-one.scm", 622 fs.readFileSync("path/to/module-one.scm")) 623 ``` 624 625 #### SourceNode.prototype.walk(fn) 626 627 Walk over the tree of JS snippets in this node and its children. The walking 628 function is called once for each snippet of JS and is passed that snippet and 629 the its original associated source's line/column location. 630 631 * `fn`: The traversal function. 632 633 ```js 634 var node = new SourceNode(1, 2, "a.js", [ 635 new SourceNode(3, 4, "b.js", "uno"), 636 "dos", 637 [ 638 "tres", 639 new SourceNode(5, 6, "c.js", "quatro") 640 ] 641 ]); 642 643 node.walk(function (code, loc) { console.log("WALK:", code, loc); }) 644 // WALK: uno { source: 'b.js', line: 3, column: 4, name: null } 645 // WALK: dos { source: 'a.js', line: 1, column: 2, name: null } 646 // WALK: tres { source: 'a.js', line: 1, column: 2, name: null } 647 // WALK: quatro { source: 'c.js', line: 5, column: 6, name: null } 648 ``` 649 650 #### SourceNode.prototype.walkSourceContents(fn) 651 652 Walk over the tree of SourceNodes. The walking function is called for each 653 source file content and is passed the filename and source content. 654 655 * `fn`: The traversal function. 656 657 ```js 658 var a = new SourceNode(1, 2, "a.js", "generated from a"); 659 a.setSourceContent("a.js", "original a"); 660 var b = new SourceNode(1, 2, "b.js", "generated from b"); 661 b.setSourceContent("b.js", "original b"); 662 var c = new SourceNode(1, 2, "c.js", "generated from c"); 663 c.setSourceContent("c.js", "original c"); 664 665 var node = new SourceNode(null, null, null, [a, b, c]); 666 node.walkSourceContents(function (source, contents) { console.log("WALK:", source, ":", contents); }) 667 // WALK: a.js : original a 668 // WALK: b.js : original b 669 // WALK: c.js : original c 670 ``` 671 672 #### SourceNode.prototype.join(sep) 673 674 Like `Array.prototype.join` except for SourceNodes. Inserts the separator 675 between each of this source node's children. 676 677 * `sep`: The separator. 678 679 ```js 680 var lhs = new SourceNode(1, 2, "a.rs", "my_copy"); 681 var operand = new SourceNode(3, 4, "a.rs", "="); 682 var rhs = new SourceNode(5, 6, "a.rs", "orig.clone()"); 683 684 var node = new SourceNode(null, null, null, [ lhs, operand, rhs ]); 685 var joinedNode = node.join(" "); 686 ``` 687 688 #### SourceNode.prototype.replaceRight(pattern, replacement) 689 690 Call `String.prototype.replace` on the very right-most source snippet. Useful 691 for trimming white space from the end of a source node, etc. 692 693 * `pattern`: The pattern to replace. 694 695 * `replacement`: The thing to replace the pattern with. 696 697 ```js 698 // Trim trailing white space. 699 node.replaceRight(/\s*$/, ""); 700 ``` 701 702 #### SourceNode.prototype.toString() 703 704 Return the string representation of this source node. Walks over the tree and 705 concatenates all the various snippets together to one string. 706 707 ```js 708 var node = new SourceNode(1, 2, "a.js", [ 709 new SourceNode(3, 4, "b.js", "uno"), 710 "dos", 711 [ 712 "tres", 713 new SourceNode(5, 6, "c.js", "quatro") 714 ] 715 ]); 716 717 node.toString() 718 // 'unodostresquatro' 719 ``` 720 721 #### SourceNode.prototype.toStringWithSourceMap([startOfSourceMap]) 722 723 Returns the string representation of this tree of source nodes, plus a 724 SourceMapGenerator which contains all the mappings between the generated and 725 original sources. 726 727 The arguments are the same as those to `new SourceMapGenerator`. 728 729 ```js 730 var node = new SourceNode(1, 2, "a.js", [ 731 new SourceNode(3, 4, "b.js", "uno"), 732 "dos", 733 [ 734 "tres", 735 new SourceNode(5, 6, "c.js", "quatro") 736 ] 737 ]); 738 739 node.toStringWithSourceMap({ file: "my-output-file.js" }) 740 // { code: 'unodostresquatro', 741 // map: [object SourceMapGenerator] } 742 ```