1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | var SourceMap = require('source-map').SourceMapGenerator;
|
7 | var SourceMapConsumer = require('source-map').SourceMapConsumer;
|
8 | var sourceMapResolve = require('source-map-resolve');
|
9 | var fs = require('fs');
|
10 | var path = require('path');
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | module.exports = mixin;
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | const makeFriendlyPath = function(aPath) {
|
23 | return path.sep === "\\" ? aPath.replace(/\\/g, "/").replace(/^[a-z]:\/?/i, "/") : aPath;
|
24 | }
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 | function mixin(compiler) {
|
34 | compiler._comment = compiler.comment;
|
35 | compiler.map = new SourceMap();
|
36 | compiler.position = { line: 1, column: 1 };
|
37 | compiler.files = {};
|
38 | for (var k in exports) compiler[k] = exports[k];
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 | exports.updatePosition = function(str) {
|
49 | var lines = str.match(/\n/g);
|
50 | if (lines) this.position.line += lines.length;
|
51 | var i = str.lastIndexOf('\n');
|
52 | this.position.column = ~i ? str.length - i : this.position.column + str.length;
|
53 | };
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | exports.emit = function(str, pos) {
|
65 | if (pos) {
|
66 | var sourceFile = makeFriendlyPath(pos.source || 'source.css');
|
67 |
|
68 | this.map.addMapping({
|
69 | source: sourceFile,
|
70 | generated: {
|
71 | line: this.position.line,
|
72 | column: Math.max(this.position.column - 1, 0)
|
73 | },
|
74 | original: {
|
75 | line: pos.start.line,
|
76 | column: pos.start.column - 1
|
77 | }
|
78 | });
|
79 |
|
80 | this.addFile(sourceFile, pos);
|
81 | }
|
82 |
|
83 | this.updatePosition(str);
|
84 |
|
85 | return str;
|
86 | };
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 | exports.addFile = function(file, pos) {
|
95 | if (typeof pos.content !== 'string') return;
|
96 | if (Object.prototype.hasOwnProperty.call(this.files, file)) return;
|
97 |
|
98 | this.files[file] = pos.content;
|
99 | };
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 | exports.applySourceMaps = function() {
|
107 | Object.keys(this.files).forEach(function(file) {
|
108 | var content = this.files[file];
|
109 | this.map.setSourceContent(file, content);
|
110 |
|
111 | if (this.options.inputSourcemaps !== false) {
|
112 | var originalMap = sourceMapResolve.resolveSync(
|
113 | content, file, fs.readFileSync);
|
114 | if (originalMap) {
|
115 | var map = new SourceMapConsumer(originalMap.map);
|
116 | var relativeTo = originalMap.sourcesRelativeTo;
|
117 | this.map.applySourceMap(map, file, makeFriendlyPath(path.dirname(relativeTo)));
|
118 | }
|
119 | }
|
120 | }, this);
|
121 | };
|
122 |
|
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 | exports.comment = function(node) {
|
129 | if (/^# sourceMappingURL=/.test(node.comment))
|
130 | return this.emit('', node.position);
|
131 | else
|
132 | return this._comment(node);
|
133 | };
|