index.js
4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
'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;