Constructor
new SourceMap(sourceText)
Construct a new source map with the given source text. The modified text will be initialized to the same text, and the initial mapping will map all characters in the source text to their corresponding position in the modified text, and vice versa.
Parameters
-
sourceText
*
the string to be used as the source text of this source map (although any object can be passed, and will be converted to a string)
See
Source
Classes
Methods
debugCode(code)
A debugging routine useful when working with code in which you care
about the specific character indices and/or line and column numbers.
Call this routine to print the code to the console, with a line and
character number added at the start of each line, using the format
L_C_:
with the blanks replaced by line and character numbers,
respectively.
For example, "function ( x ) {\n\treturn 3;\n}"
would be printed
as follows. Note that these are not line and column numbers,
but rather line numbers and character indices.
L1C0: function ( x ) {
L2C17: return 3;
L3C27: }
Parameters
-
code
string
arbitrary text to be displayed on the console (typically some kind of code, such as putdown notation or JSON)
Source
isMarker(text) → {boolean}
See the documentation for modify() and nextMarker() for an explanation of how markers can be useful. This function is a predicate for testing whether an arbitrary string contains a marker.
Parameters
-
text
string
the text to test whether it is a marker
Returns
-
boolean
whether the given text is a marker
Source
dataForMarker(marker) → {Object}
See the documentation for modify() for an explanation of how markers work. That explanation mentions that arbitrary data can be associated with a marker as part of a call to the modify() function. To later query the data associated with a given marker, use this function.
Parameters
-
marker
string
the text for the marker whose data should be looked up
Returns
-
Object
the data associated with the marker, as a JavaScript object amenable to JSON encoding
Source
modified() → {string}
Get the modified text for this source map. At construction time, this will be the same as the source text, but can change via calls to modify().
Returns
-
string
the modified text for this source map
Source
modifiedLineAndColumn(line, column) → {Array}
See the documentation for modifiedPosition(); this function behaves similarly, except that it takes as input a line number and column number in the source text, and returns a line number and column number in the modified text.
Unlike character indices, line and column numbers start counting at 1, so the first character in the text (at index 0) would be in line 1 and at column 1.
Parameters
-
line
integer
the line number in the source text whose position in the modified text should be looked up
-
column
integer
the column number in the modified text whose position in the source should be looked up
Returns
-
Array
a pair of integers, the line and column number in the modified text that correspond to the given line and column number in the source text
Source
modifiedPosition(sourcePosition) → {integer}
See the documentation for sourcePosition(); this function is (approximately) the inverse to that function. The only difference is, as documented in that function, we cannot map precisely each character within a section of modified text, and thus we map to the first charcter in the corresponding range. For example, in the source map mentioned at the top of this page, each character in the source text "5+9" would map to the first character in the modified text "14."
Parameters
-
sourcePosition
integer
the position in the source text for which a lookup should be done in the modified text
Returns
-
integer
the position in the modified text corresponding to the given position in the source text
Source
modify(start, length, replacement, Objectopt)
Source map objects contain both a source text and a modified text, which are equal at construction time. But through one or more calls to this function, the modified text can change, diverging from the source text. This function not only makes such modifications, but it records where they were made, and any data associated with them, so that queries can be made later about correspondences between the source and modified text, as documented at the top of this file.
The first three parameters are straightforward, as documented below. However, the fourth parameter (which is optional) requires additional explanation. When replacing a portion of the source text, it is sometimes convenient to replace it not with text, but with arbitrary data. We support this more advanced usage as follows.
- First, the newly inserted text cannot be arbitrary text, but should instead be a special marker that indicates the location where non-text data resides. To create such markers, use the nextMarker() function.
- Second, the fourth parameter (
data
) should be provided, and it can be any JavaScript object amenable to JSON encoding, which will be stored in this object for later querying. - Later, when the client processes the modified text, upon encountering a marker (see isMarker()) and desiring to know what data it represents, the client can find out with a call to dataForMarker().
For example, let's say our source text was "Get me employee #16" and
we wanted to replace "employee #16" with the full data for that
employee, which is not text data, but rather something more complex,
such as { name:'Henrietta', age:35, ... }
. Assuming we have that
data in an object obj
, we could make a call like the following.
sourcemap.modify( 7, 12, sourcemap.nextMarker(), obj )
Notes:
- When passing data as the optional fourth parameter, you must pass
sourcemap.nextMarker()
as the third parameter, because data is stored internally only associated with markers, and cannot be retrieved later otherwise. - The starting index documented below is in the modified text, not the source text, but if this is inconvenient for you, simply make use of the modifiedPosition() function to convert what you have to what you need.
- Modifications must be made in increasing order of index in the modified text. For example, if you have a replacement to do on characters 5 through 10 and another to do on characters 50 through 70, you must do them in that order, not the reverse. This class does not support modifications in arbitrary order.
Parameters
-
start
integer
the starting index, in the modified text, where this next modification should be recorded
-
length
integer
the length of the text to be replaced, starting at the index
start
-
replacement
string
the text with which to replace the chosen portion of the source text
-
Object
<optional>
data arbitrary JSON data to store in the modified text, as documented above
Source
nextMarker() → {string}
See the documentation for modify() for an
explanation of how markers work. That explanation mentions that it is
useful to have a sequence of markers, each of which is a unique snippet
of text that does not appear anywhere in the original source text.
This function can be used as a generator, returning a different string
each time it is called, none of which appeared in the original source
text. In that way it can be used to generate markers that can be
passed as the replacement
parameter to modfiy().
Returns
-
string
a new marker
Source
nextModificationPosition() → {integer}
As discussed in the documentation for modify(), modifications must be made in increasing order of position in the modified text. Thus at any point, we have a minimum index at which the next modification could take place, so that it falls after all modifications made so far. This function returns that minimum index.
For example, in the source map described at the top of this file (in which "5+9" became "14" inside the source text), the next viable index in the modified text where a modification could be made is immediately after the text "14," that is, at index 16.
If no modifications have been made to the source text, this function will return zero.
Returns
-
integer
the earliest index at which a modification could be added to this source map
Source
source() → {string}
Get the source text given at the time this source map was constructed. This class provides no API for altering the source text, so it should be the same any time this function is called.
Returns
-
string
the source text given at construction time
Source
sourceLineAndColumn(line, column) → {Array}
See the documentation for sourcePosition(); this function behaves similarly, except that it takes as input a line number and column number in the modified text, and returns a line number and column number in the source text.
Unlike character indices, line and column numbers start counting at 1, so the first character in the text (at index 0) would be in line 1 and at column 1.
Parameters
-
line
integer
the line number in the modified text whose position in the source text should be looked up
-
column
integer
the column number in the modified text whose position in the source text should be looked up
Returns
-
Array
a pair of integers, the line and column number in the source text that correspond to the given line and column number in the modified text
Source
sourcePosition(modifiedPosition) → {integer}
The major purpose of the SourceMap class is to track the correspondence of character positions between its source text and its modified text. This function can be used to do a lookup from the latter to the former; you provide a character position in the modified text and it returns the corresponding position in the source text.
If the character position sits inside a section of modified text, there may not be an exact correspondence of which character in the source text relates to it; for example, in the source map mentioned at the top of this documentation page, which characters in "5+9" correspond to each character in the text "14?" In such cases, the first character in the corresponding section is returned. So both characters in "14" would be said to correspond to the first character in "5+9."
If the character position sits inside a section of unmodified text, then there is an exact copy of that unmodified text in the source text, and thus the corresponding position with it will be returned.
If an invalid index is provided, undefined is returned. Indices into both the source and modified texts are zero-based, so the first valid index is 0 and the last is the length of the text minus 1.
Parameters
-
modifiedPosition
integer
the position in the modified text for which a lookup should be done in the source text
Returns
-
integer
the position in the source text corresponding to the given position in the modified text