diff --git a/tasks/filerev.js b/tasks/filerev.js index b57b795..eed8c4f 100644 --- a/tasks/filerev.js +++ b/tasks/filerev.js @@ -62,23 +62,57 @@ module.exports = function (grunt) { // Source maps var sourceMap = false; if (ext === '.js' || ext === '.css') { - var map = file + '.map'; - resultPath += '.map'; - if (grunt.file.exists(map)) { - if (move) { - fs.renameSync(map, resultPath); - } else { - grunt.file.copy(map, resultPath); - } - sourceMap = true; - } + var map = file + '.map'; + var resultPathMap = resultPath + '.map'; + var fileContents = grunt.file.read(resultPath); + var srcMapRegex = /(sourceMappingURL\=)([\w\-\/\.]+(?![\b\w\.]+[\.js|\.css]\.map)\/)?([\w\.\-]+\b\w+[\.js|\.css]\.map)/gi; + var regexResult; + var srcRelativePath; + var srcRelativePathExists; + + try { + regexResult = srcMapRegex.exec(fileContents); + srcRelativePath = path.dirname(resultPath) + '/' + regexResult[2] + regexResult[3]; + srcRelativePathExists = true; + } catch (err) { + srcRelativePathExists = false; + } + + if (grunt.file.exists(map) || srcRelativePathExists) { + if (move) { + try { + fs.renameSync(map, resultPathMap); + } catch (err) { + // if map is not in the same directory, must be relative path + grunt.verbose.writeln('Source Map not found in: ' + map); + grunt.verbose.writeln('Trying Relative Path: : ' + srcRelativePath); + resultPathMap = srcRelativePath; + fs.renameSync(srcRelativePath, srcRelativePath); + } + } else { + grunt.file.copy(map, resultPathMap); + } + + // rewrite the sourceMappingURL in files + var newSrcMapUrl = fileContents.replace(srcMapRegex, '$1' + ('$2' || '') + path.basename(resultPath) + '.map'); + // update file reference inside source map file + var srcFileReference = grunt.file.readJSON(resultPathMap); + srcFileReference.file = path.basename(resultPath); + + if (grunt.file.exists(srcRelativePath)) { + grunt.file.delete(srcRelativePath); + } + grunt.file.write(resultPath, newSrcMapUrl); + grunt.file.write(path.dirname(srcRelativePath) + '/' + path.basename(resultPath) + '.map', JSON.stringify(srcFileReference)); + sourceMap = true; + } } filerev.summary[path.normalize(file)] = path.join(dirname, newName); grunt.verbose.writeln(chalk.green('✔ ') + file + chalk.gray(' changed to ') + newName); if (sourceMap) { - filerev.summary[path.normalize(file + '.map')] = path.join(dirname, newName + '.map'); - grunt.verbose.writeln(chalk.green('✔ ') + file + '.map' + chalk.gray(' changed to ') + newName + '.map'); + filerev.summary[path.normalize(file + '.map')] = path.join(dirname, newName + '.map'); + grunt.verbose.writeln(chalk.green('✔ ') + file + '.map' + chalk.gray(' changed to ') + newName + '.map'); } }); diff --git a/test/test.js b/test/test.js index 1692408..375b2f1 100644 --- a/test/test.js +++ b/test/test.js @@ -1,5 +1,6 @@ 'use strict'; var fs = require('fs'); +var path = require('path'); var assert = require('assert'); var hashes = { @@ -40,11 +41,18 @@ it('should allow sources defined with expand', function () { it('should use same revision as .js source for the .map', function () { var file = 'test/fixtures/math.js.map'; - var original = fs.statSync(file).size; - var revisioned = fs.statSync(hashes[file]).size; + var original = path.basename(hashes[file]); + var revisioned = path.basename(hashes[file] + '.map', '.map'); assert(revisioned === original); }); +it('should point the .js sourceMappingURL to the revisioned .map', function() { + var file = 'test/fixtures/math.js'; + var map = 'math.2f56179e.js.map'; + var revisioned = fs.readFileSync(hashes[file], {encoding: 'utf8'}); + assert.notStrictEqual(revisioned.indexOf('//# sourceMappingURL=' + map), -1); +}); + it('should revision .js file ok without any .map', function () { var file = 'test/fixtures/physics.js'; var original = fs.statSync(file).size;