Find your way through the chain of sourcemaps to the original source, like magic sourcery
npm install sourcery-mapThis package is a JavaScript source map management toolset
- fork of sorcery
- including exorcist
- implementing webpack loader and plugin
- implementing esbuild plugin
The purpose is to be consistent, have the same implementation and the same options for managing these different purposes.
We merged pull requests
* Adjust delimiter used to detect the end of source map URLs in JS files
* chore(deps-dev): bump eslint from 2.13.1 to 6.6.0
* Handle file:// paths to source files
* Ignore missing / unavailable files
* Single character segment compatibility (needed for traceur)
* chore(deps-dev): bump eslint from 2.13.1 to 6.6.0
New features
* Flatten is optional and can be limited to existing physical files only (ease the debugging)
* source path can be customized, relative or absolute.
* Provide a source root resolution fallback when map has been generated from another path (browserify)
* sourceMappingURL can be inline content, absolute, relative...
Beware, some features are still experimental and not fully covered by tests, if you find an issue, do not hesitate to create a bug or contribute ;-)
First, install sourcery-map globally:
``bash`
npm install -g sourcery-map
| Input file
Input folder |
| content | --- | a map of filename: contents pairs. | filename will be resolved against the current working directory if needs be |
| sourcemaps | --- | a map of filename: sourcemap pairs | where filename is the name of the file the sourcemap is related to. This will override any sourceMappingURL comments in the file itself |
| sourceRootResolution | --sourceRootResolution | | base path of the relative sources path in the map |$3
| API | Command line | Value | Description |
| ------------------------ | -------------------- | ----------- | ----------- |
| --- | -o, --output | | Output file (if absent, will use input) |
| excludeContent | -x, --excludeContent | flag | Don't populate the sourcesContent array |
| sourceMappingURLTemplate | --sourceMappingURLTemplate | [relative-path] (default)
[resource-path]
[absolute-path]
inline
none
| SourceMapping path is relative to the file map location or sourceMappingURLBase
relative-path without root ([drive]:/ or /)
SourceMapping path is absoluteAppend map as a data URI rather than separate fileRemove map reference
TBD|
| sourceMappingURLBase | --sourceMappingURLBase | | allows the base to be specified as something other than the map file, used by [relative-path]/[resource-path] |
| sourcePathTemplate | --sourcePathTemplate | [relative-path] (default)
[resource-path]
[absolute-path]
| Source paths are relative to the file location or sourcePathBase
relative-path without root ([drive]:/ or /)
Source paths are absolute
Customize the relative path, can contain [relative-path] or [absolute-path]
for instance `webpack://[resource-path]` |
| sourcePathBase | --sourcePathBase | | Base path for calculating relative source paths, used by [relative-path]/[resource-path] |
| sourceRoot | --sourceRoot | | Root URL for loading relative source paths. Set as sourceRoot in the source map |
| flatten | -f, --flatten | full (default)
existing
| flatten source map until the original file is reached
flatten source map as long as the file (content) exists
do not flatten the map |$3
| API | Command line | Value | Description |
| ------------------------ | -------------------- | ----------- | ----------- |
| inline | -d, --datauri | flag | equivalent to sourceMappingURLTemplate=inline |
| absolutePath | --- | flag | equivalent to sourceMappingURLTemplate=[absolute-path] |
| sourceMappingURL | --sourceMappingURL | | see sourceMappingURLTemplate |$3
| Command line | Description |
| ------------- |----------- |
| -h, --help | Show help message |
| -v, --version | Show version |
Sourcery-map
$3
`
Usage:
sourcery-map [options] Resolve a chain of sourcemaps back to the original source.
Options:
-h, --help Show help message
-v, --version Show version
-i, --input Input file (option will override default provided value)
-o, --output Output file (if absent, will overwrite input)
-d, --datauri Append map as a data URI, rather than separate file
-x, --excludeContent Do not populate the sourcesContent array
Examples:
# overwrite sourcemap in place (will write map to
# some/generated/code.min.js.map, and update
# sourceMappingURL comment if necessary
sourcery-map -i some/generated/code.min.js
# append flattened sourcemap as an inline data URI
# (will delete existing .map file, if applicable)
sourcery-map -d -i some/generated/code.min.js
# write to a new file (will create newfile.js and
# newfile.js.map)
sourcery-map -i some/generated/code.min.js -o newfile.js
`$3
`js
interface SourceMap {
version: 3;
file: string;
sources: string[];
sourcesContent: string[];
names: string[];
mappings: string;
sourceRoot: string;
toString(): string;
toUrl(): string;
}interface Chain {
apply ( apply_options: Options ): SourceMap | null;
trace ( oneBasedLineIndex: number, zeroBasedColumnIndex: number, trace_options: Options ): Trace;
write ( write_options?: Options ): Promise;
write ( dest: string, write_options?: Options ): Promise;
writeSync ( write_options?: Options ): void;
writeSync ( dest: string, write_options?: Options ): void;
}
function load(file: string, options: Options): Promise;
function loadSync(file: string, options: Options): Chain | null;
``js
var sourcery_map = require( 'sourcery-map' );sourcery_map.load( 'some/generated/code.min.js' ).then( ( chain ) => {
// generate a flattened sourcemap
var map = chain.apply(); // { version: 3, file: 'code.min.js', ... }
// get a JSON representation of the sourcemap
map.toString(); // '{"version":3,"file":"code.min.js",...}'
// get a data URI representation
map.toUrl(); // 'data:application/json;charset=utf-8;base64,eyJ2ZXJ...'
// write to a new file - this will create
output.js and
// output.js.map, and will preserve relative paths. It
// returns a Promise
chain.write( 'output.js' ); // write to a new file but use an absolute path for the
// sourceMappingURL
chain.write( 'output.js', { absolutePath: true });
// write to a new file, but append the flattened sourcemap as a data URI
chain.write( 'output.js', { inline: true });
// overwrite the existing file
chain.write();
chain.write({ inline: true });
// find the origin of line x, column y. Returns an object with
//
source, line, column and (if applicable) name properties.
// Note - for consistency with other tools, line numbers are always
// one-based, column numbers are always zero-based. It's daft, I know.
var loc = chain.trace( x, y );
});// You can also use sourcery-map synchronously:
var chain = sourcery_map.loadSync( 'some/generated/code.min.js' );
var map = chain.apply();
var loc = chain.trace( x, y );
chain.writeSync();
`You can pass an optional second argument to sorcery.load() and sorcery.loadSync(), with zero or more of the following properties:
content - a map of filename: contents pairs. filename will be resolved against the current working directory if needs be
sourcemaps - a map of filename: sourcemap pairs, where filename is the name of the file the sourcemap is related to. This will override any sourceMappingURL comments in the file itself.
`js
sourcery_map.load( 'some/generated/code.min.js', {
content: {
'some/minified/code.min.js': '...',
'some/transpiled/code.js': '...',
'some/original/code.js': '...'
},
sourcemaps: {
'some/minified/code.min.js': {...},
'some/transpiled/code.js': {...}
},
existingContentOnly: false
}).then( chain => {
/ ... /
});
`
Any files not found will be read from the filesystem as normal.Sourcery-exorcist
Can replace exorcist$3
`
Usage:
sourcery-exorcist `$3
`js
function transform(mapFileOrStream: string | Writable, options?: Options): Transform;
``js
const basedir = process.cwd();
const browserify_options = {
debug: true,
basedir,
...options
}; browserify(inputFile, browserify_options)
.bundle()
.pipe(exorcist(mapFile, undefined, undefined, path.dirname(inputFile)))
.pipe(fse.createWriteStream(bundleFile));
`
by such code
`js
.pipe(sourcery_map.transform(mapFile, { flatten: false, sourcePathBase: path.dirname(inputFile) }))]
.pipe(fse.createWriteStream(bundleFile));
`you can flatten the map at the same time
`js
.pipe(sourcery_map.transform(mapFile, {
flatten: 'existing',
sourcePathBase: path.dirname(inputFile),
excludeContent: true
}))]
.pipe(fse.createWriteStream(bundleFile));
`Webpack >= 5.x
$3
If you are happy with source maps generated by Webpack but would like to have them flattened, this is the good way to do this.
Can replace source-map-loader. On our side, this plugin is in trouble when reaching content not present on the machine.`js
module.exports = {
...
module: {
rules: [
{
test: /\.js$/,
use: [
{ loader : 'sourcery-map/webpack-loader',
options: {
excludeContent: true
}
},
// { loader : "source-map-loader" },
]
},
]
`$3
If the Webpack source maps are not properly generated, problem of paths, roots, ... this plugin could help to fix/normalize them. Here, webpack will generated map files using absolute paths, our plugin will normalize paths and flattern them.
`js
const SourceryMapperPlugin = require('sourcery-map/webpack-plugin');module.exports = {
...
module: {
devtool: "source-map",
plugins: [new SourceryMapperPlugin( { excludeContent: true } )],
output: {
sourceMapFilename:
[file].map,
devtoolModuleFilenameTemplate: "[absolute-resource-path]",
devtoolFallbackModuleFilenameTemplate: "[absolute-resource-path]?[hash]
},`esbuild
$3
`js
const sourcery_map_esbuild = require('sourcery-map/esbuild-plugin'); const options = {
target: 'es2020',
entryPoints: 'main.js',
bundle: true,
external: ['electron'],
plugins: [ sourcery_map_esbuild({
sourcePathBase: path.dirname(config.name),
excludeContent: true,
flatten: 'existing',
})],
sourcemap: true,
sourcesContent: false,
loader: {
".node": "file",
".json": "file"
},
logLevel: 'info'
}
``MIT