TypeScript/scripts/build/sourcemaps.js
2018-07-10 12:13:27 -07:00

143 lines
No EOL
5.1 KiB
TypeScript

// @ts-check
const path = require("path");
const Vinyl = require("./vinyl");
const convertMap = require("convert-source-map");
const applySourceMap = require("vinyl-sourcemaps-apply");
const through2 = require("through2");
/**
* @param {Vinyl} input
* @param {string | Buffer} contents
* @param {string | RawSourceMap} [sourceMap]
*/
function replaceContents(input, contents, sourceMap) {
const output = input.clone();
output.contents = typeof contents === "string" ? Buffer.from(contents, "utf8") : contents;
if (input.sourceMap) {
output.sourceMap = typeof input.sourceMap === "string" ? /**@type {RawSourceMap}*/(JSON.parse(input.sourceMap)) : input.sourceMap;
if (typeof sourceMap === "string") {
sourceMap = /**@type {RawSourceMap}*/(JSON.parse(sourceMap));
}
else if (sourceMap === undefined) {
const stringContents = typeof contents === "string" ? contents : contents.toString("utf8");
const newSourceMapConverter = convertMap.fromSource(stringContents);
if (newSourceMapConverter) {
sourceMap = /**@type {RawSourceMap}*/(newSourceMapConverter.toObject());
output.contents = new Buffer(convertMap.removeMapFileComments(stringContents), "utf8");
}
}
if (sourceMap) {
const cwd = input.cwd || process.cwd();
const base = input.base || cwd;
const sourceRoot = output.sourceMap.sourceRoot;
makeAbsoluteSourceMap(cwd, base, output.sourceMap);
makeAbsoluteSourceMap(cwd, base, sourceMap);
applySourceMap(output, sourceMap);
makeRelativeSourceMap(cwd, base, sourceRoot, output.sourceMap);
}
else {
output.sourceMap = undefined;
}
}
return output;
}
exports.replaceContents = replaceContents;
function removeSourceMaps() {
return through2.obj((/**@type {Vinyl}*/file, _, cb) => {
if (file.sourceMap && file.isBuffer()) {
file.contents = Buffer.from(convertMap.removeMapFileComments(file.contents.toString("utf8")), "utf8");
file.sourceMap = undefined;
}
cb(null, file);
});
}
exports.removeSourceMaps = removeSourceMaps;
/**
* @param {string | undefined} cwd
* @param {string | undefined} base
* @param {RawSourceMap} sourceMap
*
* @typedef RawSourceMap
* @property {string} version
* @property {string} file
* @property {string} [sourceRoot]
* @property {string[]} sources
* @property {string[]} [sourcesContent]
* @property {string} mappings
* @property {string[]} [names]
*/
function makeAbsoluteSourceMap(cwd = process.cwd(), base = "", sourceMap) {
const sourceRoot = sourceMap.sourceRoot || "";
const resolvedBase = path.resolve(cwd, base);
const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot);
sourceMap.file = path.resolve(resolvedBase, sourceMap.file).replace(/\\/g, "/");
sourceMap.sources = sourceMap.sources.map(source => path.resolve(resolvedSourceRoot, source).replace(/\\/g, "/"));
sourceMap.sourceRoot = "";
}
exports.makeAbsoluteSourceMap = makeAbsoluteSourceMap;
/**
* @param {string | undefined} cwd
* @param {string | undefined} base
* @param {string} sourceRoot
* @param {RawSourceMap} sourceMap
*/
function makeRelativeSourceMap(cwd = process.cwd(), base = "", sourceRoot, sourceMap) {
makeAbsoluteSourceMap(cwd, base, sourceMap);
const resolvedBase = path.resolve(cwd, base);
const resolvedSourceRoot = path.resolve(resolvedBase, sourceRoot);
sourceMap.file = path.relative(resolvedBase, sourceMap.file).replace(/\\/g, "/");
sourceMap.sources = sourceMap.sources.map(source => path.relative(resolvedSourceRoot, source).replace(/\\/g, "/"));
sourceMap.sourceRoot = sourceRoot;
}
exports.makeRelativeSourceMap = makeRelativeSourceMap;
/**
* @param {string} message
* @returns {never}
*/
function fail(message) {
throw new Error(message);
}
/**
* @param {number} value
*/
function base64FormatEncode(value) {
return value < 0 ? fail("Invalid value") :
value < 26 ? 0x41 /*A*/ + value :
value < 52 ? 0x61 /*a*/ + value - 26 :
value < 62 ? 0x30 /*0*/ + value - 52 :
value === 62 ? 0x2B /*+*/ :
value === 63 ? 0x2F /*/*/ :
fail("Invalid value");
}
/**
* @param {number} value
*/
function base64VLQFormatEncode(value) {
if (value < 0) {
value = ((-value) << 1) + 1;
}
else {
value = value << 1;
}
// Encode 5 bits at a time starting from least significant bits
let result = "";
do {
let currentDigit = value & 31; // 11111
value = value >> 5;
if (value > 0) {
// There are still more digits to decode, set the msb (6th bit)
currentDigit = currentDigit | 32;
}
result += String.fromCharCode(base64FormatEncode(currentDigit));
} while (value > 0);
return result;
}
exports.base64VLQFormatEncode = base64VLQFormatEncode;