-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathwebpack-sourcemap-unpacker.js
executable file
·93 lines (82 loc) · 3.63 KB
/
webpack-sourcemap-unpacker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/env node
const path = require('path');
const fse = require('fs-extra');
const glob = require('glob');
const SourceMapConsumer = require('source-map').SourceMapConsumer;
const program = require('commander');
const config = require('./package.json');
const dataUriToBuffer = require('data-uri-to-buffer');
program.version(config.version, '-v, --version').description('Unpack the sourcemaps generated by Webpack to a project folder').usage('[options]').option('-p, --prefix [webpack:///]', 'filter the path with certain prefix').option('-i, --input [glob-pattern]',
'a glob patterns to describe sourcemap files to be unpacked, default to *.map').option('-o, --output [folder]', 'set the output folder, default to current folder');
program.action((options) => {
options.input = options.input || '*.map';
options.output = options.output || '.';
options.prefix = options.prefix || 'webpack:///';
let files = glob.sync(options.input);
if (!files.length) {
console.warn(`There is no ${options.input} in current directory`);
return;
}
console.info(`output src to ${options.output}`);
files.forEach(async function(filepath) {
console.info(`extract sourcemap: ${filepath}`);
const mapSource = fse.readFileSync(path.resolve(filepath));
const consumer = await new SourceMapConsumer(mapSource.toString());
const paths = consumer._absoluteSources;
const sources = consumer.sourcesContent;
paths.forEach((p, idx) => {
const relativePath = path.relative(options.prefix, p).replace(/\\/g, '/');
const parts = relativePath.match(/([0-9a-zA-Z_/.\-@]+?)(\?\w{4})?$/);
if (!parts) {
// ignore special path
console.log(`ignore file: ${p}`);
return;
}
// handle filename ends with hash
const folder = path.resolve(path.join(options.output, path.dirname(parts[1])));
const basename = path.basename(parts[1]);
const extname = path.extname(basename);
const filename = (parts[2] ? path.basename(basename, extname) + parts[2] + extname : basename);
let absPath = path.resolve(path.join(folder, filename));
if (path.relative(path.resolve(), absPath).startsWith('..')) {
console.error(`Do not write files to ancestor folder: ${p}. Please check the prefix option: ${options.prefix}`);
process.exit(1);
}
console.info(`output to file: ${absPath}`);
let source;
switch (extname) {
// plain text files
case '.glsl':
source = evalModule(sources[idx]).exports;
break;
// base64 files
case '.jpg':
case '.gif':
case '.png':
case '.obj':
try {
const exports = evalModule(sources[idx]).exports;
source = dataUriToBuffer(exports);
} catch (e) {
console.info(`It's not a binary file: ${absPath}`);
source = sources[idx];
absPath += '.js';
}
break;
default:
source = sources[idx];
}
fse.ensureDirSync(folder);
fse.writeFileSync(absPath, source);
});
});
});
program.parse(process.argv);
function evalModule(source) {
return eval(`
let module = {};
let __webpack_public_path__ = '';
${source}
module;
`);
}