Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helper for adding index based mappings from files #25

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,40 @@ should have the following properties:

Renders the source map being generated to a string.

### SourceMapFileCollector

An instance of the SourceMapFileCollector represents a source map which is being built in files.

#### new SourceMapFileCollector(startOfSourceMap)

To create a new one, you must pass an object with the following properties:

* `file`: The filename of the generated source that this source map is
associated with.

* `sourceRoot`: An optional root for all relative URLs in this source map.

#### SourceMapFileCollector.prototype.addIndexMapping(mapping)

Add code with an index based mapping to the file collection.

The mapping object
should have the following properties:

* `src`: Filepath to original src.

* `input`: Unminified JavaScript.

* `output`: Minified JavaScript.

* `map`: Map of character index to character index (number -> number)

* `lineOffset`: An optional line offset to add to mappings.

#### SourceMapFileCollector.prototype.toString()

Renders the source map being generated to a string.

### SourceNode

SourceNodes provide a way to abstract over interpolating and/or concatenating
Expand Down
4 changes: 3 additions & 1 deletion lib/source-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ requirejs.config({
requirejs([
'source-map/source-map-generator',
'source-map/source-map-consumer',
'source-map/source-map-file-collector',
'source-map/source-node'
], function (generatorModule, consumerModule, sourceNodeModule) {
], function (generatorModule, consumerModule, fileCollectorModule, sourceNodeModule) {
exports.SourceMapGenerator = generatorModule.SourceMapGenerator;
exports.SourceMapConsumer = consumerModule.SourceMapConsumer;
exports.SourceMapFileCollector = fileCollectorModule.SourceMapFileCollector;
exports.SourceNode = sourceNodeModule.SourceNode;
});
118 changes: 118 additions & 0 deletions lib/source-map/char-props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* char-props from https://github.com/twolfson/char-props
* with slimmed down for source-map
*/
define(function (require, exports, module) {
/**
* Indexer constructor (takes index and performs pre-emptive caching)
* @constructor
* @param {String} input Content to index
*/
function Indexer(input) {
this.input = input;

// Break up lines by line breaks
var lines = input.split('\n');

// Iterate over the lines until we reach the end or we hit our index
var i = 0,
len = lines.length,
line,
lineStart = 0,
lineEnd,
lineMap = {'length': len};
for (; i < len; i++) {
// Grab the line
line = lines[i];

// Calculate the line end (includes \n we removed)
lineEnd = lineStart + line.length + 1;

// Save the line to its map
lineMap[i] = {'start': lineStart, 'end': lineEnd};

// Overwrite lineStart with lineEnd
lineStart = lineEnd;
}

// Save the lineMap to this
this.lineMap = lineMap;
}
Indexer.prototype = {
/**
* Get the line of the character at a certain index
* @param {Number} index Index of character to retrieve line of
* @param {Object} [options] Options to use for search
* @param {Number} [options.minLine=0] Minimum line for us to search on
* TODO: The following still have to be built/implemented
* @param {Number} [options.maxLine=lines.length] Maximum line for us to search on
* @param {String} [options.guess="average"] Affects searching pattern -- can be "high", "low", or "average" (linear top-down, linear bottom-up, or binary)
* @returns {Number} Line number of character
*/
'lineAt': function (index, options) {
// Fallback options
options = options || {};

// TODO: We can binary search here
// Grab the line map and iterate over it
var lineMap = this.lineMap,
i = options.minLine || 0,
len = lineMap.length,
lineItem;

for (; i < len; i++) {
// TODO: If binary searching, this requires both above and below
// If the index is under end of the lineItem, stop
lineItem = lineMap[i];
if (index < lineItem.end) {
break;
}
}

// Return the line we stopped on
return i;
},
/**
* Get the column of the character at a certain index
* @param {Number} index Index of character to retrieve column of
* @returns {Number} Column number of character
*/
'columnAt': function (index) {
// Start at the index - 1
var input = this.input,
char,
i = index - 1;

// If the index is negative, return now
if (index < 0) {
return 0;
}

// Continue left until index < 0 or we hit a line break
for (; i >= 0; i--) {
char = input.charAt(i);
if (char === '\n') {
break;
}
}

// Return the col of our index - 1 (line break is not in the column count)
var col = index - i - 1;
return col;
}
};

function charProps(input) {
// Create and return a new Indexer with the content
var indexer = new Indexer(input);
return indexer;
}

// Expose Indexer to charProps
charProps.Indexer = Indexer;

// Export charProps
exports['char-props'] = charProps;

});
96 changes: 96 additions & 0 deletions lib/source-map/source-map-file-collector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2011 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
define(function (require, exports, module) {

var SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator;
var charPropsObj = require('source-map/char-props');
var charProps = charPropsObj['char-props'];

/**
* Collect multiple files into a source map
*
* - file: The filename of the generated source.
* - sourceRoot: An optional root for all URLs in this source map.
*/
function SourceMapFileCollector(params) {
// Create and save a new SourceMapGenerator
var srcMapGenerator = new SourceMapGenerator(params);
this.srcMapGenerator = srcMapGenerator;
}

/**
* Add code with an index based mapping to our srcMapGenerator
* - params Object holding multiple parameters
* - params.src Filepath to original src
* - params.input Unminified JavaScript
* - params.output Minified JavaScript
* - params.map Map of character index to character index (number -> number)
* - params.lineOffset (OPTIONAL) Line offset to add to mappings
*/
SourceMapFileCollector.prototype.addIndexMapping = function (params) {
// Localize items from params
var srcFile = params.src,
srcProps = charProps(params.input),
destProps = charProps(params.output),
codeMap = params.map,
lineOffset = params.lineOffset || 0;

// Grab the keys of the codeMap
// DEV: If columnAt starts to be the slow part, create a map which memoizes each of the indicies it `while` loops over -- an LRU is probably best here.
var srcMapGenerator = this.srcMapGenerator,
lastSrcLine = 0,
lastDestLine = 0,
srcPoints = Object.getOwnPropertyNames(codeMap);
srcPoints.forEach(function (srcPoint) {
// Get the line and col of the src
var srcLine = srcProps.lineAt(srcPoint, {'minLine': lastSrcLine}),
srcCol = srcProps.columnAt(srcPoint);

// Save the srcLine as our next guess
lastSrcLine = srcLine;

// Get the line and col of the dest
var destPoint = codeMap[srcPoint],
destLine = destProps.lineAt(destPoint, {'minLine': lastDestLine}),
destCol = destProps.columnAt(destPoint);

// Save the destLine for our next guess
lastDestLine = destLine;

// Create our mapping
var mapping = {
'original': {
'line': srcLine + 1,
'column': srcCol
},
'generated': {
'line': destLine + 1 + lineOffset,
'column': destCol
},
'source': srcFile
};

// Add the mapping to our generator
srcMapGenerator.addMapping(mapping);
});

// Return this for a fluent interface
return this;
};

/**
* Export the current collection as a sourcemap
*/
SourceMapFileCollector.prototype.toString = function () {
var srcMapGenerator = this.srcMapGenerator;
return srcMapGenerator.toString();
};

// Export SourceMapFileCollector
exports.SourceMapFileCollector = SourceMapFileCollector;

});
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "source-map",
"description": "Generates and consumes source maps",
"version": "0.1.2",
"version": "0.1.3",
"homepage": "https://github.com/mozilla/source-map",
"author": "Nick Fitzgerald <nfitzgerald@mozilla.com>",
"contributors": [ ],
Expand All @@ -17,5 +17,8 @@
],
"dependencies": {
"requirejs": "==0.26.0"
},
"scripts": {
"test": "node test/run-tests.js"
}
}
Loading