├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE.md ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | reports 4 | *.tgz -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "strict": true 4 | } 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "10" 5 | - "9" 6 | - "8" 7 | - "6" 8 | - "4" 9 | - "0.10" 10 | after_script: 11 | - npm run coveralls 12 | branches: 13 | except: 14 | - /^v[0-9]/ 15 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## ISC License 2 | 3 | Copyright (c) 2014, Florian Reiterer 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Concat with source maps [![NPM version][npm-image]][npm-url] [![build status][travis-image]][travis-url] [![Test coverage][coveralls-image]][coveralls-url] 2 | 3 | NPM module for concatenating files and generating source maps. 4 | 5 | ### Usage example 6 | ```js 7 | var concat = new Concat(true, 'all.js', '\n'); 8 | concat.add(null, "// (c) John Doe"); 9 | concat.add('file1.js', file1Content); 10 | concat.add('file2.js', file2Content, file2SourceMap); 11 | 12 | var concatenatedContent = concat.content; 13 | var sourceMapForContent = concat.sourceMap; 14 | ``` 15 | 16 | ### API 17 | 18 | #### new Concat(generateSourceMap, outFileName, separator) 19 | Initialize a new concat object. 20 | 21 | Parameters: 22 | - generateSourceMap: whether or not to generate a source map (default: false) 23 | - outFileName: the file name/path of the output file (for the source map) 24 | - separator: the string that should separate files (default: no separator) 25 | 26 | #### concat.add(fileName, content, sourceMap) 27 | Add a file to the output file. 28 | 29 | Parameters: 30 | - fileName: file name of the input file (can be null for content without a file reference, e.g. a license comment) 31 | - content: content (Buffer or string) of the input file 32 | - sourceMap: optional source map of the input file (string). Will be merged into the output source map. 33 | 34 | #### concat.content 35 | The resulting concatenated file content (Buffer). 36 | 37 | #### concat.sourceMap 38 | The resulting source map of the concatenated files (string). 39 | 40 | [npm-image]: https://img.shields.io/npm/v/concat-with-sourcemaps.svg 41 | [npm-url]: https://www.npmjs.com/package/concat-with-sourcemaps 42 | [travis-image]: https://img.shields.io/travis/floridoo/concat-with-sourcemaps.svg 43 | [travis-url]: https://travis-ci.org/floridoo/concat-with-sourcemaps 44 | [coveralls-image]: https://img.shields.io/coveralls/floridoo/concat-with-sourcemaps.svg 45 | [coveralls-url]: https://coveralls.io/r/floridoo/concat-with-sourcemaps?branch=master 46 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | import { RawSourceMap } from "source-map"; 2 | 3 | declare module "concat-with-sourcemaps" { 4 | 5 | export default class Concat { 6 | constructor(generateSourceMap: boolean, fileName: string, separator?: string); 7 | add(filePath: string | null, content: string | Buffer, sourceMap?: string | RawSourceMap): void; 8 | readonly content: Buffer; 9 | readonly sourceMap: string | undefined; 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var SourceMapGenerator = require('source-map').SourceMapGenerator; 3 | var SourceMapConsumer = require('source-map').SourceMapConsumer; 4 | 5 | function unixStylePath(filePath) { 6 | return filePath.replace(/\\/g, '/'); 7 | } 8 | 9 | function Concat(generateSourceMap, fileName, separator) { 10 | this.lineOffset = 0; 11 | this.columnOffset = 0; 12 | this.sourceMapping = generateSourceMap; 13 | this.contentParts = []; 14 | 15 | if (separator === undefined) { 16 | this.separator = bufferFrom(''); 17 | } else { 18 | this.separator = bufferFrom(separator); 19 | } 20 | 21 | if (this.sourceMapping) { 22 | this._sourceMap = new SourceMapGenerator({file: unixStylePath(fileName)}); 23 | this.separatorLineOffset = 0; 24 | this.separatorColumnOffset = 0; 25 | var separatorString = this.separator.toString(); 26 | for (var i = 0; i < separatorString.length; i++) { 27 | this.separatorColumnOffset++; 28 | if (separatorString[i] === '\n') { 29 | this.separatorLineOffset++; 30 | this.separatorColumnOffset = 0; 31 | } 32 | } 33 | } 34 | } 35 | 36 | Concat.prototype.add = function(filePath, content, sourceMap) { 37 | filePath = filePath && unixStylePath(filePath); 38 | 39 | if (!Buffer.isBuffer(content)) { 40 | content = bufferFrom(content); 41 | } 42 | 43 | if (this.contentParts.length !== 0) { 44 | this.contentParts.push(this.separator); 45 | } 46 | this.contentParts.push(content); 47 | 48 | if (this.sourceMapping) { 49 | var contentString = content.toString(); 50 | var lines = contentString.split('\n').length; 51 | 52 | if (Object.prototype.toString.call(sourceMap) === '[object String]') 53 | sourceMap = JSON.parse(sourceMap); 54 | 55 | if (sourceMap && sourceMap.mappings && sourceMap.mappings.length > 0) { 56 | var upstreamSM = new SourceMapConsumer(sourceMap); 57 | var _this = this; 58 | upstreamSM.eachMapping(function(mapping) { 59 | if (mapping.source) { 60 | _this._sourceMap.addMapping({ 61 | generated: { 62 | line: _this.lineOffset + mapping.generatedLine, 63 | column: (mapping.generatedLine === 1 ? _this.columnOffset : 0) + mapping.generatedColumn 64 | }, 65 | original: mapping.originalLine == null ? null : { 66 | line: mapping.originalLine, 67 | column: mapping.originalColumn 68 | }, 69 | source: mapping.originalLine != null ? mapping.source : null, 70 | name: mapping.name 71 | }); 72 | } 73 | }); 74 | if (upstreamSM.sourcesContent) { 75 | upstreamSM.sourcesContent.forEach(function(sourceContent, i) { 76 | _this._sourceMap.setSourceContent(upstreamSM.sources[i], sourceContent); 77 | }); 78 | } 79 | } else { 80 | if (sourceMap && sourceMap.sources && sourceMap.sources.length > 0) 81 | filePath = sourceMap.sources[0]; 82 | if (filePath) { 83 | for (var i = 1; i <= lines; i++) { 84 | this._sourceMap.addMapping({ 85 | generated: { 86 | line: this.lineOffset + i, 87 | column: (i === 1 ? this.columnOffset : 0) 88 | }, 89 | original: { 90 | line: i, 91 | column: 0 92 | }, 93 | source: filePath 94 | }); 95 | } 96 | if (sourceMap && sourceMap.sourcesContent) 97 | this._sourceMap.setSourceContent(filePath, sourceMap.sourcesContent[0]); 98 | } 99 | } 100 | if (lines > 1) 101 | this.columnOffset = 0; 102 | if (this.separatorLineOffset === 0) 103 | this.columnOffset += contentString.length - Math.max(0, contentString.lastIndexOf('\n')+1); 104 | this.columnOffset += this.separatorColumnOffset; 105 | this.lineOffset += lines - 1 + this.separatorLineOffset; 106 | } 107 | }; 108 | 109 | Object.defineProperty(Concat.prototype, 'content', { 110 | get: function content() { 111 | return Buffer.concat(this.contentParts); 112 | } 113 | }); 114 | 115 | Object.defineProperty(Concat.prototype, 'sourceMap', { 116 | get: function sourceMap() { 117 | return this._sourceMap ? this._sourceMap.toString() : undefined; 118 | } 119 | }); 120 | 121 | function bufferFrom(content) { 122 | try { 123 | return Buffer.from(content); 124 | } catch(e) { 125 | if (Object.prototype.toString.call(content) !== '[object String]') { 126 | throw new TypeError("separator must be a string"); 127 | } 128 | return new Buffer(content); 129 | } 130 | } 131 | Concat.bufferFrom = bufferFrom; 132 | Concat.default = Concat; 133 | 134 | module.exports = Concat; 135 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "concat-with-sourcemaps", 3 | "version": "1.1.0", 4 | "description": "Concatenate file contents with a custom separator and generate a source map", 5 | "homepage": "http://github.com/floridoo/concat-with-sourcemaps", 6 | "repository": "git://github.com/floridoo/concat-with-sourcemaps.git", 7 | "main": "index.js", 8 | "types": "index.d.ts", 9 | "scripts": { 10 | "test": "jshint *.js test/*.js && faucet test/*.js", 11 | "tap": "tape test/*.js", 12 | "cover": "istanbul cover --dir reports/coverage tape test/*.js", 13 | "coveralls": "istanbul cover tape test/*.js --report lcovonly && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage" 14 | }, 15 | "keywords": [ 16 | "concat", 17 | "source map" 18 | ], 19 | "author": "Florian Reiterer ", 20 | "license": "ISC", 21 | "dependencies": { 22 | "source-map": "^0.6.1" 23 | }, 24 | "devDependencies": { 25 | "coveralls": "^3.0.0", 26 | "faucet": "0.0.1", 27 | "istanbul": "^0.4.5", 28 | "jshint": "^2.9.5", 29 | "tape": "^4.9.0" 30 | }, 31 | "files": [ 32 | "index.js", 33 | "index.d.ts", 34 | "package.json", 35 | "README.md", 36 | "LICENSE.md" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var test = require('tape'); 4 | var Concat = require('..'); 5 | 6 | function testCase(description, options) { 7 | test(description, function(t) { 8 | // content as Buffer 9 | var concat = new Concat(options.sourceMapping, options.outFile, options.separator); 10 | options.input.forEach(function(input, i) { 11 | concat.add((input.fileName !== undefined ? input.fileName : 'test'+(i+1)), Concat.bufferFrom(input.content), input.sourceMap); 12 | }); 13 | t.equal(concat.content.toString(), options.output.content, 'should produce the right output'); 14 | if (options.output.sourceMap) 15 | t.deepEqual(JSON.parse(concat.sourceMap), JSON.parse(options.output.sourceMap), 'should produce the right source map'); 16 | else 17 | t.equal(concat.sourceMap, undefined, 'should not produce a source map'); 18 | 19 | // content as string 20 | concat = new Concat(options.sourceMapping, options.outFile, options.separator); 21 | options.input.forEach(function(input, i) { 22 | concat.add((input.fileName !== undefined ? input.fileName : 'test'+(i+1)), input.content, input.sourceMap); 23 | }); 24 | t.equal(concat.content.toString(), options.output.content, 'should produce the right output'); 25 | if (options.output.sourceMap) 26 | t.deepEqual(JSON.parse(concat.sourceMap), JSON.parse(options.output.sourceMap), 'should produce the right source map'); 27 | else 28 | t.equal(concat.sourceMap, undefined, 'should not produce a source map'); 29 | t.end(); 30 | }); 31 | } 32 | 33 | testCase('should concatenate with "\\n"', { 34 | separator: '\n', 35 | sourceMapping: false, 36 | outFile: 'out.js', 37 | input: [ 38 | { content: 'AAA' }, 39 | { content: 'BBB' }, 40 | { content: 'CCC' } 41 | ], 42 | output: { 43 | content: 'AAA\nBBB\nCCC' 44 | } 45 | }); 46 | 47 | testCase('should concatenate with "\\n\\n"', { 48 | separator: '\n\n', 49 | sourceMapping: false, 50 | outFile: 'out.js', 51 | input: [ 52 | { content: 'AAA' }, 53 | { content: 'BBB' }, 54 | { content: 'CCC' } 55 | ], 56 | output: { 57 | content: 'AAA\n\nBBB\n\nCCC' 58 | } 59 | }); 60 | 61 | testCase('should concatenate with "\\nXXXX\\n"', { 62 | separator: '\nXXXX\n', 63 | sourceMapping: false, 64 | outFile: 'out.js', 65 | input: [ 66 | { content: 'AAA' }, 67 | { content: 'BBB' }, 68 | { content: 'CCC' } 69 | ], 70 | output: { 71 | content: 'AAA\nXXXX\nBBB\nXXXX\nCCC' 72 | } 73 | }); 74 | 75 | testCase('should concatenate with "XXXX"', { 76 | separator: 'XXXX', 77 | sourceMapping: false, 78 | outFile: 'out.js', 79 | input: [ 80 | { content: 'AAA' }, 81 | { content: 'BBB' }, 82 | { content: 'CCC' } 83 | ], 84 | output: { 85 | content: 'AAAXXXXBBBXXXXCCC' 86 | } 87 | }); 88 | 89 | testCase('should concatenate without separator specified', { 90 | separator: undefined, 91 | sourceMapping: false, 92 | outFile: 'out.js', 93 | input: [ 94 | { content: 'AAA' }, 95 | { content: 'BBB' }, 96 | { content: 'CCC' } 97 | ], 98 | output: { 99 | content: 'AAABBBCCC' 100 | } 101 | }); 102 | 103 | testCase('should concatenate with "\\n" and produce source map', { 104 | separator: '\n', 105 | sourceMapping: true, 106 | outFile: 'out.js', 107 | input: [ 108 | { content: 'AAA' }, 109 | { content: 'BBB' }, 110 | { content: 'CCC' } 111 | ], 112 | output: { 113 | content: 'AAA\nBBB\nCCC', 114 | sourceMap: '{"version":3,"file":"out.js","sources":["test1","test2","test3"],"names":[],"mappings":"AAAA;ACAA;ACAA"}' 115 | } 116 | }); 117 | 118 | testCase('should concatenate with "\\n\\n" and produce source map', { 119 | separator: '\n\n', 120 | sourceMapping: true, 121 | outFile: 'out.js', 122 | input: [ 123 | { content: 'AAA' }, 124 | { content: 'BBB' }, 125 | { content: 'CCC' } 126 | ], 127 | output: { 128 | content: 'AAA\n\nBBB\n\nCCC', 129 | sourceMap: '{"version":3,"file":"out.js","sources":["test1","test2","test3"],"names":[],"mappings":"AAAA;;ACAA;;ACAA"}' 130 | } 131 | }); 132 | 133 | testCase('should concatenate with "XXXX" and produce source map', { 134 | separator: 'XXXX', 135 | sourceMapping: true, 136 | outFile: 'out.js', 137 | input: [ 138 | { content: 'AAA' }, 139 | { content: 'BBB' }, 140 | { content: 'CCC' } 141 | ], 142 | output: { 143 | content: 'AAAXXXXBBBXXXXCCC', 144 | sourceMap: '{"version":3,"file":"out.js","sources":["test1","test2","test3"],"names":[],"mappings":"AAAA,OCAA,OCAA"}' 145 | } 146 | }); 147 | 148 | testCase('should concatenate with "\\nXXXX" and produce source map', { 149 | separator: '\nXXXX', 150 | sourceMapping: true, 151 | outFile: 'out.js', 152 | input: [ 153 | { content: 'AAA' }, 154 | { content: 'BBB' }, 155 | { content: 'CCC' } 156 | ], 157 | output: { 158 | content: 'AAA\nXXXXBBB\nXXXXCCC', 159 | sourceMap: '{"version":3,"file":"out.js","sources":["test1","test2","test3"],"names":[],"mappings":"AAAA;ICAA;QCAA"}' 160 | } 161 | }); 162 | 163 | testCase('should concatenate with "XXXX\\n" and produce source map', { 164 | separator: 'XXXX\n', 165 | sourceMapping: true, 166 | outFile: 'out.js', 167 | input: [ 168 | { content: 'AAA' }, 169 | { content: 'BBB' }, 170 | { content: 'CCC' } 171 | ], 172 | output: { 173 | content: 'AAAXXXX\nBBBXXXX\nCCC', 174 | sourceMap: '{"version":3,"file":"out.js","sources":["test1","test2","test3"],"names":[],"mappings":"AAAA;ACAA;ACAA"}' 175 | } 176 | }); 177 | 178 | testCase('should concatenate mulitline content with "\\n" and produce source map', { 179 | separator: '\n', 180 | sourceMapping: true, 181 | outFile: 'out.js', 182 | input: [ 183 | { content: 'AA\nA' }, 184 | { content: 'BBB' }, 185 | { content: 'CC\nC' } 186 | ], 187 | output: { 188 | content: 'AA\nA\nBBB\nCC\nC', 189 | sourceMap: '{"version":3,"file":"out.js","sources":["test1","test2","test3"],"names":[],"mappings":"AAAA;AACA;ACDA;ACAA;AACA"}' 190 | } 191 | }); 192 | 193 | testCase('should concatenate content with source maps with "\\n" and produce combined source map', { 194 | separator: '\n', 195 | sourceMapping: true, 196 | outFile: 'out.js', 197 | input: [ 198 | { 199 | content: 'AAA\nBBB\nCCC', 200 | sourceMap: '{"version":3,"file":"intermediate.js","sources":["test11","test12","test13"],"names":[],"mappings":"AAAA;ACAA;ACAA"}', 201 | fileName: 'intermediate.js' 202 | }, 203 | { content: 'EEE' }, 204 | { content: 'FFF' } 205 | ], 206 | output: { 207 | content: 'AAA\nBBB\nCCC\nEEE\nFFF', 208 | sourceMap: '{"version":3,"file":"out.js","sources":["test11","test12","test13","test2","test3"],"names":[],"mappings":"AAAA;ACAA;ACAA;ACAA;ACAA"}' 209 | } 210 | }); 211 | 212 | testCase('should pass on source content', { 213 | separator: '\n', 214 | sourceMapping: true, 215 | outFile: 'out.js', 216 | input: [ 217 | { 218 | content: 'AAA\nBBB\nCCC', 219 | sourceMap: '{"version":3,"file":"intermediate.js","sources":["test11","test12","test13"], "sourcesContent": ["AAA", "BBB", "CCC"], "names":[],"mappings":"AAAA;ACAA;ACAA"}', 220 | fileName: 'intermediate.js' 221 | }, 222 | { content: 'EEE' }, 223 | { content: 'FFF' } 224 | ], 225 | output: { 226 | content: 'AAA\nBBB\nCCC\nEEE\nFFF', 227 | sourceMap: '{"version":3,"file":"out.js","sources":["test11","test12","test13","test2","test3"],"names":[],"mappings":"AAAA;ACAA;ACAA;ACAA;ACAA","sourcesContent":["AAA","BBB","CCC",null,null]}' 228 | } 229 | }); 230 | 231 | testCase('should pass on source content when mappings is empty', { 232 | separator: '\n', 233 | sourceMapping: true, 234 | outFile: 'out.js', 235 | input: [ 236 | { 237 | content: 'AAA', 238 | sourceMap: '{"version":3,"file":"intermediate.js","sources":["test11"], "sourcesContent": ["AAA"], "names":[],"mappings":""}', 239 | fileName: 'intermediate.js' 240 | }, 241 | { content: 'EEE' }, 242 | { content: 'FFF' } 243 | ], 244 | output: { 245 | content: 'AAA\nEEE\nFFF', 246 | sourceMap: '{"version":3,"file":"out.js","sources":["test11","test2","test3"],"names":[],"mappings":"AAAA;ACAA;ACAA","sourcesContent":["AAA",null,null]}' 247 | } 248 | }); 249 | 250 | testCase('should ignore invalid mappings', { 251 | separator: '\n', 252 | sourceMapping: true, 253 | outFile: 'out.js', 254 | input: [ 255 | { 256 | content: 'AAA\nBBB\nCCC', 257 | sourceMap: '{"version":3,"file":"intermediate.js","sources":["test11","test12","test13"], "sourcesContent": ["AAA", "BBB", "CCC"], "names":[],"mappings":"A;ACAA;ACAA"}', 258 | fileName: 'intermediate.js' 259 | }, 260 | { content: 'EEE' }, 261 | { content: 'FFF' } 262 | ], 263 | output: { 264 | content: 'AAA\nBBB\nCCC\nEEE\nFFF', 265 | sourceMap: '{"version":3,"file":"out.js","sources":["test12","test13","test2","test3"],"names":[],"mappings":"A;AAAA;ACAA;ACAA;ACAA","sourcesContent":["BBB","CCC",null,null]}' 266 | } 267 | }); 268 | 269 | testCase('should output unix style paths on Windows', { 270 | separator: '\n', 271 | sourceMapping: true, 272 | outFile: 'test\\test\\out.js', 273 | input: [ 274 | { 275 | content: 'AAA', 276 | fileName: 'test\\test1' 277 | }, 278 | { 279 | content: 'BBB', 280 | fileName: 'test\\test2' 281 | }, 282 | { 283 | content: 'CCC', 284 | fileName: 'test\\test3' 285 | } 286 | ], 287 | output: { 288 | content: 'AAA\nBBB\nCCC', 289 | sourceMap: '{"version":3,"file":"test/test/out.js","sources":["test/test1","test/test2","test/test3"],"names":[],"mappings":"AAAA;ACAA;ACAA"}' 290 | } 291 | }); 292 | 293 | testCase('should keep source in sources with empty mappings', { 294 | separator: '\n', 295 | sourceMapping: true, 296 | outFile: 'out.js', 297 | input: [ 298 | { 299 | content: 'AAA', 300 | sourceMap: '{"version":3,"file":"test1","sources":["testXXX"], "names":[],"mappings":""}' 301 | }, 302 | { content: 'BBB' }, 303 | { content: 'CCC' } 304 | ], 305 | output: { 306 | content: 'AAA\nBBB\nCCC', 307 | sourceMap: '{"version":3,"file":"out.js","sources":["testXXX","test2","test3"],"names":[],"mappings":"AAAA;ACAA;ACAA"}' 308 | } 309 | }); 310 | 311 | testCase('should not crash with an input source map with no mappings', { 312 | separator: '\n', 313 | sourceMapping: true, 314 | outFile: 'out.js', 315 | input: [ 316 | { 317 | content: 'AAA\nBBB\nCCC', 318 | sourceMap: '{"version":3,"file":"intermediate.js","sources":[],"names":[],"mappings":""}', 319 | fileName: 'intermediate.js' 320 | }, 321 | { content: 'EEE' }, 322 | { content: 'FFF' } 323 | ], 324 | output: { 325 | content: 'AAA\nBBB\nCCC\nEEE\nFFF', 326 | sourceMap: '{"version":3,"file":"out.js","sources":["intermediate.js", "test2", "test3"],"names":[],"mappings":"AAAA;AACA;AACA;ACFA;ACAA"}' 327 | } 328 | }); 329 | 330 | testCase('should allow content without filename and produce no mapping for it', { 331 | separator: '\n', 332 | sourceMapping: true, 333 | outFile: 'out.js', 334 | input: [ 335 | { content: '// Header', fileName: null }, 336 | { content: 'AA\nA' }, 337 | { content: 'BBB' }, 338 | { content: '// inbetween', fileName: null }, 339 | { content: 'CC\nC' }, 340 | { content: '// Footer', fileName: null } 341 | ], 342 | output: { 343 | content: '// Header\nAA\nA\nBBB\n// inbetween\nCC\nC\n// Footer', 344 | sourceMap: '{"version":3,"file":"out.js","sources":["test2","test3","test5"],"names":[],"mappings":";AAAA;AACA;ACDA;;ACAA;AACA"}' 345 | } 346 | }); 347 | 348 | test('should not allocate an uninitialized buffer when passing a number', function(t) { 349 | t.throws(function() { 350 | new Concat(true, 'all.js', 234); 351 | }, "passing a number as separator should throw"); 352 | t.end(); 353 | }); --------------------------------------------------------------------------------