Code Monkey home page Code Monkey logo

combine-source-map's Introduction

combine-source-map build status

Add source maps of multiple files, offset them and then combine them into one source map.

var convert = require('convert-source-map');
var combine = require('combine-source-map');

var fooComment = '//# sourceMappingURL=data:application/json;base64,eyJ2Z [..] pzJylcbiJdfQ==';
var barComment = '//# sourceMappingURL=data:application/json;base64,eyJ2Z [..] VjaycpXG4iXX0=';

var fooFile = {
    source: '(function() {\n\n  console.log(require(\'./bar.js\'));\n\n}).call(this);\n' + '\n' + fooComment
  , sourceFile: 'foo.js'
};
var barFile = {
    source: '(function() {\n\n  console.log(alert(\'alerts suck\'));\n\n}).call(this);\n' + '\n' + barComment
  , sourceFile: 'bar.js'
};

var offset = { line: 2 };
var base64 = combine
  .create('bundle.js')
  .addFile(fooFile, offset)
  .addFile(barFile, { line: offset.line + 8 })
  .base64();

var sm = convert.fromBase64(base64).toObject();
console.log(sm);
{ version: 3,
  file: 'bundle.js',
  sources: [ 'foo.coffee', 'bar.coffee' ],
  names: [],
  mappings: ';;;AAAA;CAAA;CAAA,CAAA,CAAA,IAAO,GAAK;CAAZ;;;;;ACAA;CAAA;CAAA,CAAA,CAAA,IAAO,GAAK;CAAZ',
  sourcesContent:
   [ 'console.log(require \'./bar.js\')\n',
     'console.log(alert \'alerts suck\')\n' ] }

Installation

npm install combine-source-map

API

create()

/**
 * @name create
 * @function
 * @param file {String} optional name of the generated file
 * @param sourceRoot { String} optional sourceRoot of the map to be generated
 * @return {Object} Combiner instance to which source maps can be added and later combined
 */

Combiner.prototype.addFile(opts, offset)

/**
 * Adds map to underlying source map.
 * If source contains a source map comment that has the source of the original file inlined it will offset these
 * mappings and include them.
 * If no source map comment is found or it has no source inlined, mappings for the file will be generated and included
 * 
 * @name addMap
 * @function
 * @param opts {Object} { sourceFile: {String}, source: {String} }
 * @param offset {Object} { line: {Number}, column: {Number} }
 */

Combiner.prototype.base64()

/**
* @name base64
* @function
* @return {String} base64 encoded combined source map
*/

Combiner.prototype.comment()

/**
 * @name comment
 * @function
 * @return {String} base64 encoded sourceMappingUrl comment of the combined source map
 */

removeComments(src)

/**
 * @name removeComments
 * @function
 * @param src 
 * @return {String} src with all sourceMappingUrl comments removed
 */

Example

Read and run the more elaborate example in order to get a better idea how things work.

combine-source-map's People

Contributors

aarononeal avatar brettz9 avatar jasonslyvia avatar jscissr avatar kylepdavis avatar loganfsmyth avatar thlorenz avatar zertosh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

combine-source-map's Issues

Handling inline source map files

I have the following scenario:

  • I have a file which may or may not include source map comment (either inline or as a map file)
  • I want to wrap this file with a closure that injects some global values
  • I want source maps to work nicely so that Chrome DevTools hides this ugly closure function (header / footer)

Is this possible using this module? I am currently using something like this, but Chrome DevTools is not handling source maps for content with a relative sourceMappingURL map file. Those with inline base64 data are working fine.

var combineSourceMap = require('combine-source-map');

var prelude = [
  '(function (__blah) {',
  '\n});'
];

var originalSource = fs.readFileSync(...);
var wrappedSource = prelude[0] + originalSource + prelude[1];

var sourceFile = path.relative(basedir, currentFile).replace(/\\/g, '/');
var sourceFileName = path.basename(sourceFile);
var sourceFileDir = path.dirname(sourceFile);

var sourceMap = combineSourceMap.create(sourceFileName, sourceFileDir)
    .addFile({ sourceFile: sourceFile, source: originalSourceContent });

// replace existing comments with new base64 data
var finalSource = [
  combineSourceMap.removeComments(wrappedSource),
  sourceMap.comment()
].join('\n');

Thanks for the great module. ๐Ÿ˜„

Offset Line

Hi @thlorenz I am wondering about your use of offset line.

I've taken your code and tried to add a third file to the map:

var convert = require('convert-source-map');
var combine = require('combine-source-map');

var foo = {
  version        :  3,
  file           :  'foo.js',
  sourceRoot     :  '',
  sources        :  [ 'foo.coffee' ],
  names          :  [],
  mappings       :  ';AAAA;CAAA;CAAA,CAAA,CAAA,IAAO,GAAK;CAAZ',
  sourcesContent :  [ 'console.log(require \'./bar.js\')\n' ]
};

var bar = {
  version        :  3,
  file           :  'bar.js',
  sourceRoot     :  '',
  sources        :  [ 'bar.coffee' ],
  names          :  [],
  mappings       :  ';AAAA;CAAA;CAAA,CAAA,CAAA,IAAO,GAAK;CAAZ',
  sourcesContent :  [ 'console.log(alert \'alerts suck\')\n' ]
};


var bar3 = {
  version        :  3,
  file           :  'bar3.js',
  sourceRoot     :  '',
  sources        :  [ 'bar3.coffee' ],
  names          :  [],
  mappings       :  ';AAAA;CAAA;CAAA,CAAA,CAAA,IAAO,GAAK;CAAZ',
  sourcesContent :  [ 'console.log(alert \'alerts suck3\')\n' ]
};


var fooComment = convert.fromObject(foo).toComment();
var barComment = convert.fromObject(bar).toComment();
var bar3Comment = convert.fromObject(bar3).toComment();

var fooFile = {
    source: '(function() {\n\n  console.log(require(\'./bar.js\'));\n\n}).call(this);\n' + '\n' + fooComment
  , sourceFile: 'foo.js'
};
var barFile = {
    source: '(function() {\n\n  console.log(alert(\'alerts suck\'));\n\n}).call(this);\n' + '\n' + barComment
  , sourceFile: 'bar.js'
};
var barFile3 = {
    source: '(function() {\n\n  console.log(alert(\'alerts suck 3\'));\n\n}).call(this);\n' + '\n' + bar3Comment
  , sourceFile: 'bar3.js'
};

var offset = { line: 2 };
var base64 = combine
  .create('bundle.js')
  .addFile(fooFile, offset)
  .addFile(barFile, { line: offset.line + 8 })
  .addFile(barFile3, { line: offset.line + 8 })
  .base64();

var sm = convert.fromBase64(base64).toObject();
console.log('Combined source maps:\n', sm);
console.log('\nMappings:\n', sm.mappings);

This seems to work fine, but what I would like to check with you... is if .addFile(barFile3, { line: offset.line + 8 }) will work for adding the third file (all all subsequent files)?

//@sourceMappingURL is getting replaced with //#sourceMappingURL

Didn't want to file this with all your source mapping related repos, and it's probably too early to make the switch, but thought it'd be worth tracking.

Invalid JSON output when source contains HTML entity '"'

Hey, I'm using browserify and have recently upgraded to v2. Since the upgrade, I've not seen sourcemaps working.

In tracking this down, I decoded the base64 JSON source map to make sure it was valid. I stuck in my editor with syntax highlighting on and quickly found where the JSON was malformed:

Screen Shot 2013-04-18 at 14 11 04

We are using lodash on our project, and it looks like the error stems from here where there is this string in the comment:

`&`, `<`, `>`, `"`, and `'` in `string` to their

It looks like somewhere down the line (after the source has been escaped), it's being converted into a quote and spoiling the JSON.

If I run just that file from lodash though addFile() I get malformed JSON back. I hope this is the right repo for the issue โ€“ apologies if not!

I would love to add a test and try to fix the bug but I've been unable to get your tests running:

 $  combine-source-map master - npm test

> [email protected] test /Users/bengourley/Projects/combine-source-map
> node-trap test/*.js


path.js:313
        throw new TypeError('Arguments to path.resolve must be strings');
              ^
TypeError: Arguments to path.resolve must be strings
    at exports.resolve (path.js:313:15)
    at Array.map (native)
    at /Users/bengourley/Projects/combine-source-map/node_modules/trap/lib/fileRunner.js:55:10
    at Glob.<anonymous> (/Users/bengourley/Projects/combine-source-map/node_modules/trap/node_modules/glob/glob.js:90:7)
    at Glob.EventEmitter.emit (events.js:117:20)
    at Glob._processEmitQueue (/Users/bengourley/Projects/combine-source-map/node_modules/trap/node_modules/glob/glob.js:280:10)
    at Glob.emitMatch (/Users/bengourley/Projects/combine-source-map/node_modules/trap/node_modules/glob/glob.js:265:8)
    at Glob._finish (/Users/bengourley/Projects/combine-source-map/node_modules/trap/node_modules/glob/glob.js:227:8)
    at Glob.<anonymous> (/Users/bengourley/Projects/combine-source-map/node_modules/trap/node_modules/glob/glob.js:168:27)
    at Glob.cb (/Users/bengourley/Projects/combine-source-map/node_modules/trap/node_modules/glob/glob.js:301:11)
npm ERR! Test failed.  See above for more details.
npm ERR! not ok code 0

support non-inline sourcemaps

My use case: I'm trying to use spine with browserify, and resulting bundle contains multiple original non-inline sourcemap comments instead of expected one combined inline. Example compiled js and map files: spine/lib

My current workaround - preprocess generated files and convert non-inline maps to inline. I'm using https://github.com/sidorares/embed-source-map
Ideally this should be handled by combine-source-map without external preprocessing

input source maps only have their first sources considered

At https://github.com/thlorenz/combine-source-map/blob/master/index.js#L30 it's clear that only the first source is considered.

When using combine-source-map to try to take already bundled/transpiled source and add new code, updating the source map, it's helpful to process the mappings for all sources.

See here for an example of using the source-map module directly to port all mappings with a fixed offset: https://github.com/okfn/annotator/blob/browserify/tools/bundle#L145

`sourcesContent` only has first character of source file.

When combining several minified Coffee files, the sourcesContent has only a single character.

Given the output from Coffee as

{ content: '(function() {  angular.module(\'stassets.main\', [\'stassets.main.controller\', \'main.template\']);}).call(this);',
  sourceMap:
   { version: 3,
     file: '',
     sourceRoot: '',
     sources: [ 'main/main.coffee' ],
     names: [],
     mappings: 'AAAA;AAAA,EAAA,OAAO,CAAC,MAAR,CAAe,eAAf,EAAgC,CAC5B,0BAD4B,EAE5B,eAF4B,CAAhC,CAAA,CAAA;AAAA',
     sourcesContent: 'angular.module(\'stassets.main\', [\n    \'stassets.main.controller\'\n    \'main.template\'\n])\n' } }
{ content: '(function() {  var MainCtrl;  MainCtrl = (function() {    function MainCtrl() {}    return MainCtrl;  })();  angular.module(\'stassets.main.controller\', []).controller(\'MainCtrl\', MainCtrl);}).call(this);',
  sourceMap:
   { version: 3,
     file: '',
     sourceRoot: '',
     sources: [ 'main/controller.coffee' ],
     names: [],
     mappings: 'AAAA;AAAA,MAAA,QAAA;;AAAA,EAAM;AACW,IAAA,kBAAA,GAAA,CAAb;;oBAAA;;MADJ,CAAA;;AAAA,EAGA,OAAO,CAAC,MAAR,CAAe,0BAAf,EAA2C,EAA3C,CACA,CAAC,UADD,CACY,UADZ,EACwB,QADxB,CAHA,CAAA;AAAA',
     sourcesContent: 'class MainCtrl\n    constructor: ->\n\nangular.module(\'stassets.main.controller\', [])\n.controller \'MainCtrl\', MainCtrl\n' } }
{ content: '(function() {  angular.module(\'stassets.main.nav.directive\', [\'main.nav.template\']);}).call(this);',
  sourceMap:
   { version: 3,
     file: '',
     sourceRoot: '',
     sources: [ 'main/nav/directive.coffee' ],
     names: [],
     mappings: 'AAAA;AAAA,EAAA,OAAO,CAAC,MAAR,CAAe,6BAAf,EAA8C,CAC1C,mBAD0C,CAA9C,CAAA,CAAA;AAAA',
     sourcesContent: 'angular.module(\'stassets.main.nav.directive\', [\n    \'main.nav.template\'\n])\n' } }

I take the content (the original source), append the sourceMap (using convert.fromObject(f.sourceMap).toComment()), and pass each to the bundle.

bundle.addFile( { source: '(function() {  angular.module(\'stassets.main\', [\'stassets.main.controller\', \'main.template\']);}).call(this);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWFpbi9tYWluLmNvZmZlZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUFBLEVBQUEsT0FBTyxDQUFDLE1BQVIsQ0FBZSxlQUFmLEVBQWdDLENBQzVCLDBCQUQ0QixFQUU1QixlQUY0QixDQUFoQyxDQUFBLENBQUE7QUFBQSIsInNvdXJjZXNDb250ZW50IjoiYW5ndWxhci5tb2R1bGUoJ3N0YXNzZXRzLm1haW4nLCBbXG4gICAgJ3N0YXNzZXRzLm1haW4uY29udHJvbGxlcidcbiAgICAnbWFpbi50ZW1wbGF0ZSdcbl0pXG4ifQ==',
  sourceFile: 'main/main.coffee' } ,  { line: 1 } )
bundle.addFile( { source: '(function() {  var MainCtrl;  MainCtrl = (function() {    function MainCtrl() {}    return MainCtrl;  })();  angular.module(\'stassets.main.controller\', []).controller(\'MainCtrl\', MainCtrl);}).call(this);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWFpbi9jb250cm9sbGVyLmNvZmZlZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUFBLE1BQUEsUUFBQTs7QUFBQSxFQUFNO0FBQ1csSUFBQSxrQkFBQSxHQUFBLENBQWI7O29CQUFBOztNQURKLENBQUE7O0FBQUEsRUFHQSxPQUFPLENBQUMsTUFBUixDQUFlLDBCQUFmLEVBQTJDLEVBQTNDLENBQ0EsQ0FBQyxVQURELENBQ1ksVUFEWixFQUN3QixRQUR4QixDQUhBLENBQUE7QUFBQSIsInNvdXJjZXNDb250ZW50IjoiY2xhc3MgTWFpbkN0cmxcbiAgICBjb25zdHJ1Y3RvcjogLT5cblxuYW5ndWxhci5tb2R1bGUoJ3N0YXNzZXRzLm1haW4uY29udHJvbGxlcicsIFtdKVxuLmNvbnRyb2xsZXIgJ01haW5DdHJsJywgTWFpbkN0cmxcbiJ9',
  sourceFile: 'main/controller.coffee' } ,  { line: 2 } )
bundle.addFile( { source: '(function() {  angular.module(\'stassets.main.nav.directive\', [\'main.nav.template\']);}).call(this);\n//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWFpbi9uYXYvZGlyZWN0aXZlLmNvZmZlZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUFBLEVBQUEsT0FBTyxDQUFDLE1BQVIsQ0FBZSw2QkFBZixFQUE4QyxDQUMxQyxtQkFEMEMsQ0FBOUMsQ0FBQSxDQUFBO0FBQUEiLCJzb3VyY2VzQ29udGVudCI6ImFuZ3VsYXIubW9kdWxlKCdzdGFzc2V0cy5tYWluLm5hdi5kaXJlY3RpdmUnLCBbXG4gICAgJ21haW4ubmF2LnRlbXBsYXRlJ1xuXSlcbiJ9',
  sourceFile: 'main/nav/directive.coffee' } ,  { line: 3 } )

Using the same object structure as above, the actual file is concated with .join('\n').

(function() {  angular.module('stassets.main', ['stassets.main.controller', 'main.template']);}).call(this);
(function() {  var MainCtrl;  MainCtrl = (function() {    function MainCtrl() {}    return MainCtrl;  })();  angular.module('stassets.main.controller', []).controller('MainCtrl', MainCtrl);}).call(this);
(function() {  angular.module('stassets.main.nav.directive', ['main.nav.template']);}).call(this);

The final source map has an incorrect sourceContent array.

{ version: 3,
  file: '/app.js',
  sources:
   [ 'main/main.coffee',
     'main/controller.coffee',
     'main/nav/directive.coffee' ],
  names: [],
  mappings: ';AAAA;ACAA,ADAA,EAAA,OAAO,CAAC,MAAR,CAAe,eAAf,EAAgC,CAC5B,0BAD4B,EAE5B,eAF4B,CAAhC,CAAA,CAAA;ACAA,ADAA,AEAA,MDAA,QAAA;ACAA,EAAA,OAAO,CAAC,MAAR,CAAe,6BAAf,EAA8C,CAC1C,mBAD0C,CAA9C,CAAA,CAAA;ADAA,ACAA,EDAM;AACW,IAAA,kBAAA,GAAA,CAAb;;oBAAA;;MADJ,CAAA;;AAAA,EAGA,OAAO,CAAC,MAAR,CAAe,0BAAf,EAA2C,EAA3C,CACA,CAAC,UADD,CACY,UADZ,EACwB,QADxB,CAHA,CAAA;AAAA',
  sourcesContent: [ 'a', 'c', 'a' ] }

Conflict with latest react and react-native versions

When I try to launch react-native project it throws me an error "error: unknown command 'start'"
It only proceeds with "start" command - all other commands work well(run-android, run-ios, etc.)
I have no idea what the problem is as there are no detailed logs, but when I delete this library and try to launch project without it - everything goes well.

That's my package.json configuration

{
"name": "********",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"lint": "eslint .",
"start": "react-native start",
"test": "jest"
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.17.11",
"@react-native-community/cli": "^10.1.3",
"@react-native-community/netinfo": "^9.3.7",
"@react-navigation/native": "^6.1.2",
"@react-navigation/native-stack": "^6.9.8",
"axios": "^1.2.3",
"convert-source-map": "^2.0.0",
"fs-extra": "^11.1.0",
"javascript-obfuscator": "^4.0.0",
"lottie-react-native": "^5.1.4",
"query-string": "^8.1.0",
"react": "18.2.0",
"react-native": "0.71.1",
"react-native-animated-loader": "^1.0.0",
"react-native-bootsplash": "^4.4.1",
"react-native-device-info": "^10.3.0",
"react-native-onesignal": "^4.5.0",
"react-native-play-install-referrer": "^1.1.8",
"react-native-safe-area-context": "^4.5.0",
"react-native-screens": "^3.19.0",
"react-native-webview": "^11.26.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native-community/eslint-config": "^3.0.0",
"@tsconfig/react-native": "^2.0.2",
"@types/jest": "^29.2.1",
"@types/react": "^18.0.24",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.2.1",
"eslint": "^8.19.0",
"jest": "^29.2.1",
"metro-react-native-babel-preset": "0.73.7",
"prettier": "^2.4.1",
"react-test-renderer": "18.2.0",
"typescript": "4.8.4"
},
"jest": {
"preset": "react-native"
}
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.