forked from mozilla/source-map
/
char-props.js
118 lines (102 loc) · 3.33 KB
/
char-props.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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;
});