Skip to content

Instantly share code, notes, and snippets.

@tomazy
Last active November 24, 2017 18:16
Show Gist options
  • Save tomazy/73ede5d75a19244d36fb2030aea5bde4 to your computer and use it in GitHub Desktop.
Save tomazy/73ede5d75a19244d36fb2030aea5bde4 to your computer and use it in GitHub Desktop.
extract bundle contents
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');
const request = require('request-promise-native');
const { SourceMapConsumer } = require('source-map');
const usage = `
usage:
node map-source.js <bundle js url>
`
function extractSourceMappingURL(content) {
const lines = content.split("\n");
const last = lines.pop();
const [, url] = /sourceMappingURL=(.+)$/.exec(last);
return url;
}
function get(url) {
return request({
url,
method: 'GET',
gzip: true,
headers: {
'Accept': '*/*',
'Accept-Encoding': 'gzip',
'Accept-Language': 'en-US,en;q=0.9',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3221.0 Safari/537.36',
}
});
}
function replaceLastUrlPart(url, newLastPart) {
const parts = url.split('/');
parts.pop();
return [...parts, newLastPart].join('/');
}
function targetFilePath(rootDir, mapSource) {
const [, relPath] = /^.+:\/\/\/?(.+)$/.exec(mapSource);
return path.join(rootDir, relPath.replace(/\?.+$/, ''));
}
async function main([bundleUrl]) {
if (!bundleUrl) {
console.log(usage);
return process.exit(1);
}
const bundle = await get(bundleUrl);
const sourceMappingRelativeURL = extractSourceMappingURL(bundle);
if (!sourceMappingRelativeURL) {
throw new Error('source mapping url not found!');
}
const sourceMappingURL = replaceLastUrlPart(bundleUrl, sourceMappingRelativeURL)
const mapContent = await get(sourceMappingURL);
const consumer = new SourceMapConsumer(JSON.parse(mapContent));
const targetDir = bundleUrl.split('/').pop();
const seen = {};
consumer.eachMapping(mapping => {
const { source } = mapping;
if (!seen[source]) {
seen[source] = 1;
const content = consumer.sourceContentFor(source, true);
if (content) {
console.log('extracting', source);
const target = targetFilePath(targetDir, source);
mkdirp(path.dirname(target), err => {
if (err) throw err;
fs.writeFile(target, content, 'utf-8', err => {
if (err) throw err;
})
});
}
}
});
}
main(process.argv.slice(2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment