| var fs = require('graceful-fs'); |
| var path = require('path'); |
| |
| var sourcemapUrlRegeExp = /^\/\/#\s*sourceMappingURL=/; |
| |
| var createSourceMapLocatorPreprocessor = function(args, logger) { |
| var log = logger.create('preprocessor.sourcemap'); |
| var charsetRegex = /^;charset=([^;]+);/; |
| |
| return function(content, file, done) { |
| function sourceMapData(data){ |
| file.sourceMap = JSON.parse(data); |
| done(content); |
| } |
| |
| function inlineMap(inlineData){ |
| |
| var charset = 'utf-8'; |
| |
| if (charsetRegex.test(inlineData)) { |
| var matches = inlineData.match(charsetRegex); |
| |
| if (matches.length === 2) { |
| charset = matches[1]; |
| inlineData = inlineData.slice(matches[0].length -1); |
| } |
| } |
| |
| if (/^;base64,/.test(inlineData)) { |
| // base64-encoded JSON string |
| log.debug('base64-encoded source map for', file.originalPath); |
| var buffer = Buffer.from(inlineData.slice(';base64,'.length), 'base64'); |
| sourceMapData(buffer.toString(charset)); |
| } else { |
| // straight-up URL-encoded JSON string |
| log.debug('raw inline source map for', file.originalPath); |
| sourceMapData(decodeURIComponent(inlineData)); |
| } |
| } |
| |
| function fileMap(mapPath){ |
| fs.exists(mapPath, function(exists) { |
| if (!exists) { |
| done(content); |
| return; |
| } |
| fs.readFile(mapPath, function(err, data) { |
| if (err){ throw err; } |
| |
| log.debug('external source map exists for', file.originalPath); |
| sourceMapData(data); |
| }); |
| }); |
| } |
| |
| var lines = content.split(/\n/); |
| var lastLine = lines.pop(); |
| while (/^\s*$/.test(lastLine)) { |
| lastLine = lines.pop(); |
| } |
| |
| var mapUrl; |
| |
| if (sourcemapUrlRegeExp.test(lastLine)) { |
| mapUrl = lastLine.replace(sourcemapUrlRegeExp, ''); |
| } |
| |
| if (!mapUrl) { |
| fileMap(file.path + ".map"); |
| } else if (/^data:application\/json/.test(mapUrl)) { |
| inlineMap(mapUrl.slice('data:application/json'.length)); |
| } else { |
| fileMap(path.resolve(path.dirname(file.path), mapUrl)); |
| } |
| }; |
| }; |
| |
| createSourceMapLocatorPreprocessor.$inject = ['args', 'logger']; |
| |
| // PUBLISH DI MODULE |
| module.exports = { |
| 'preprocessor:sourcemap': ['factory', createSourceMapLocatorPreprocessor] |
| }; |