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] };