UNPKG

4.79 kBJavaScriptView Raw
1'use strict';
2
3const { SourceMapConsumer, SourceMapGenerator } = require('source-map');
4
5module.exports = {
6 create,
7 createFromMap,
8 clone,
9 append,
10 prepend,
11 insert
12};
13
14/**
15 * Create source map from 'content'
16 * @param {String} content
17 * @param {String} [url]
18 * @returns {SourceMapGenerator}
19 */
20function create(content, url) {
21 url = url || '<source>';
22 const map = new SourceMapGenerator({ file: url });
23 const lines = content.split('\n');
24
25 for (let l = 1, n = lines.length; l <= n; l++) {
26 // Skip empty
27 if (lines[l - 1]) {
28 map.addMapping({
29 source: url,
30 original: { line: l, column: 0 },
31 generated: { line: l, column: 0 }
32 });
33 }
34 }
35
36 map.setSourceContent(url, content);
37 return map;
38}
39
40/**
41 * Create source map from 'mapObject' and 'content'
42 * @param {Object} mapObject
43 * @param {String} content
44 * @param {String} [url]
45 * @returns {SourceMapGenerator}
46 */
47function createFromMap(mapObject, content, url) {
48 url = url || '<source>';
49 if ('string' == typeof mapObject) {
50 try {
51 mapObject = JSON.parse(mapObject);
52 } catch (err) {
53 mapObject = {
54 version: 3,
55 names: [],
56 mappings: '',
57 file: ''
58 };
59 }
60 }
61 if (emptySources(mapObject)) {
62 mapObject.sources = [url];
63 mapObject.sourcesContent = [content];
64 }
65
66 return SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapObject));
67}
68
69/**
70 * Clone 'map'
71 * @param {SourceMapGenerator} map
72 * @returns {SourceMapGenerator}
73 */
74function clone(map) {
75 return map instanceof SourceMapGenerator
76 ? SourceMapGenerator.fromSourceMap(new SourceMapConsumer(map.toJSON()))
77 : map;
78}
79
80/**
81 * Append 'inMap' to 'outMap' with line 'offset'
82 * @param {SourceMapGenerator} outMap
83 * @param {SourceMapGenerator} inMap
84 * @param {Number} offset
85 */
86function append(outMap, inMap, offset) {
87 if (inMap) {
88 const inConsumer = new SourceMapConsumer(inMap.toJSON());
89
90 inConsumer.eachMapping(mapping => {
91 outMap.addMapping({
92 source: mapping.source,
93 original: mapping.source == null
94 ? null
95 : {
96 line: mapping.originalLine,
97 column: mapping.originalColumn
98 },
99 generated: {
100 line: offset + mapping.generatedLine,
101 column: mapping.generatedColumn
102 }
103 });
104 });
105
106 inConsumer.sources.forEach((source, idx) => {
107 outMap.setSourceContent(source, inConsumer.sourcesContent[idx]);
108 });
109 }
110}
111
112/**
113 * Prepend 'inMap' to 'outMap' with line 'offset'
114 * @param {SourceMapGenerator} outMap
115 * @param {SourceMapGenerator} [inMap]
116 * @param {Number} offset
117 */
118function prepend(outMap, inMap, offset) {
119 // Move existing mappings
120 outMap._mappings.unsortedForEach(mapping => {
121 mapping.generatedLine += offset;
122 });
123
124 if (inMap) {
125 const inConsumer = new SourceMapConsumer(inMap.toJSON());
126
127 inConsumer.eachMapping(mapping => {
128 outMap.addMapping({
129 source: mapping.source,
130 original: mapping.source == null
131 ? null
132 : {
133 line: mapping.originalLine,
134 column: mapping.originalColumn
135 },
136 generated: {
137 line: mapping.generatedLine,
138 column: mapping.generatedColumn
139 }
140 });
141 });
142
143 inConsumer.sources.forEach((source, idx) => {
144 outMap.setSourceContent(source, inConsumer.sourcesContent[idx]);
145 });
146 }
147}
148
149/**
150 * Insert line in 'outMap' with 'inMap' at line 'index'
151 * @param {SourceMapGenerator} outMap
152 * @param {SourceMapGenerator} [inMap]
153 * @param {Number} length
154 * @param {Number} index
155 */
156function insert(outMap, inMap, length, index) {
157 // Move existing mappings
158 if (length) {
159 outMap._mappings.unsortedForEach(mapping => {
160 if (mapping.generatedLine > index) mapping.generatedLine += length;
161 });
162 }
163
164 // Add new mappings
165 if (inMap) {
166 const inConsumer = new SourceMapConsumer(inMap.toJSON());
167
168 inConsumer.eachMapping(mapping => {
169 outMap.addMapping({
170 source: mapping.source,
171 original: mapping.source == null
172 ? null
173 : {
174 line: mapping.originalLine,
175 column: mapping.originalColumn
176 },
177 generated: {
178 line: index + mapping.generatedLine - 1,
179 column: mapping.generatedColumn
180 }
181 });
182 });
183
184 inConsumer.sources.forEach((source, idx) => {
185 outMap.setSourceContent(source, inConsumer.sourcesContent[idx]);
186 });
187 }
188}
189
190/**
191 * Determine if 'map' has empty sources
192 * @param {Object} map
193 * @returns {Boolean}
194 */
195function emptySources(map) {
196 return !map.sources ||
197 !map.sources.length ||
198 !map.sourcesContent ||
199 !map.sourcesContent.length ||
200 map.sources.length != map.sourcesContent.length;
201}