| 'use strict'; | |
| var SourceMapGenerator = require('source-map').SourceMapGenerator; | |
| function offsetMapping(mapping, offset) { | |
| return { line: offset.line + mapping.line, column: offset.column + mapping.column }; | |
| } | |
| function newlinesIn(src) { | |
| if (!src) return 0; | |
| var newlines = src.match(/\n/g); | |
| return newlines ? newlines.length : 0; | |
| } | |
| function Generator(opts) { | |
| opts = opts || {}; | |
| this.generator = new SourceMapGenerator({ file: opts.file || '', sourceRoot: opts.sourceRoot || '' }); | |
| this.sourcesContent = undefined; | |
| this.opts = opts; | |
| } | |
| /** | |
| * Adds the given mappings to the generator and offsets them if offset is given | |
| * | |
| * @name addMappings | |
| * @function | |
| * @param sourceFile {String} name of the source file | |
| * @param mappings {Array{{Object}} each object has the form { original: { line: _, column: _ }, generated: { line: _, column: _ } } | |
| * @param offset {Object} offset to apply to each mapping. Has the form { line: _, column: _ } | |
| * @return {Object} the generator to allow chaining | |
| */ | |
| Generator.prototype.addMappings = function (sourceFile, mappings, offset) { | |
| var generator = this.generator; | |
| offset = offset || {}; | |
| offset.line = offset.hasOwnProperty('line') ? offset.line : 0; | |
| offset.column = offset.hasOwnProperty('column') ? offset.column : 0; | |
| mappings.forEach(function (m) { | |
| // only set source if we have original position to handle edgecase (see inline-source-map tests) | |
| generator.addMapping({ | |
| source : m.original ? sourceFile : undefined | |
| , original : m.original | |
| , generated : offsetMapping(m.generated, offset) | |
| }); | |
| }); | |
| return this; | |
| }; | |
| /** | |
| * Generates mappings for the given source, assuming that no translation from original to generated is necessary. | |
| * | |
| * @name addGeneratedMappings | |
| * @function | |
| * @param sourceFile {String} name of the source file | |
| * @param source {String} source of the file | |
| * @param offset {Object} offset to apply to each mapping. Has the form { line: _, column: _ } | |
| * @return {Object} the generator to allow chaining | |
| */ | |
| Generator.prototype.addGeneratedMappings = function (sourceFile, source, offset) { | |
| var mappings = [] | |
| , linesToGenerate = newlinesIn(source) + 1; | |
| for (var line = 1; line <= linesToGenerate; line++) { | |
| var location = { line: line, column: 0 }; | |
| mappings.push({ original: location, generated: location }); | |
| } | |
| return this.addMappings(sourceFile, mappings, offset); | |
| }; | |
| /** | |
| * Adds source content for the given source file. | |
| * | |
| * @name addSourceContent | |
| * @function | |
| * @param sourceFile {String} The source file for which a mapping is included | |
| * @param sourcesContent {String} The content of the source file | |
| * @return {Object} The generator to allow chaining | |
| */ | |
| Generator.prototype.addSourceContent = function (sourceFile, sourcesContent) { | |
| this.sourcesContent = this.sourcesContent || {}; | |
| this.sourcesContent[sourceFile] = sourcesContent; | |
| return this; | |
| }; | |
| /** | |
| * @name base64Encode | |
| * @function | |
| * @return {String} bas64 encoded representation of the added mappings | |
| */ | |
| Generator.prototype.base64Encode = function () { | |
| var map = this.toString(); | |
| return new Buffer(map).toString('base64'); | |
| }; | |
| /** | |
| * @name inlineMappingUrl | |
| * @function | |
| * @return {String} comment with base64 encoded representation of the added mappings. Can be inlined at the end of the generated file. | |
| */ | |
| Generator.prototype.inlineMappingUrl = function () { | |
| var charset = this.opts.charset || 'utf-8'; | |
| return '//# sourceMappingURL=data:application/json;charset=' + charset + ';base64,' + this.base64Encode(); | |
| }; | |
| Generator.prototype.toJSON = function () { | |
| var map = this.generator.toJSON(); | |
| if (!this.sourcesContent) return map; | |
| var toSourcesContent = (function (s) { | |
| if (typeof this.sourcesContent[s] === 'string') { | |
| return this.sourcesContent[s]; | |
| } else { | |
| return null; | |
| } | |
| }).bind(this); | |
| map.sourcesContent = map.sources.map(toSourcesContent); | |
| return map; | |
| }; | |
| Generator.prototype.toString = function () { | |
| return JSON.stringify(this); | |
| }; | |
| Generator.prototype._mappings = function () { | |
| return this.generator._mappings._array; | |
| }; | |
| Generator.prototype.gen = function () { | |
| return this.generator; | |
| }; | |
| module.exports = function (opts) { return new Generator(opts); }; | |
| module.exports.Generator = Generator; |