@boperators/webpack-loader 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/toRawSourceMap.js +121 -0
- package/package.json +2 -2
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toRawSourceMap = toRawSourceMap;
|
|
4
|
+
/**
|
|
5
|
+
* Convert boperators EditRecord[] into a V3 RawSourceMap.
|
|
6
|
+
*
|
|
7
|
+
* Generates line-level mappings: unchanged regions map 1:1, and edit
|
|
8
|
+
* boundaries map back to the start of the original edit region.
|
|
9
|
+
*/
|
|
10
|
+
function toRawSourceMap(edits, originalText, transformedText, fileName) {
|
|
11
|
+
const origLineStarts = buildLineStarts(originalText);
|
|
12
|
+
const transLineStarts = buildLineStarts(transformedText);
|
|
13
|
+
// Each segment is [transCol, sourceIndex, origLine, origCol]
|
|
14
|
+
// We only have one source (index 0), so sourceIndex is always 0.
|
|
15
|
+
const mappingLines = [];
|
|
16
|
+
const transLineCount = transLineStarts.length;
|
|
17
|
+
// Initialise empty lines
|
|
18
|
+
for (let i = 0; i < transLineCount; i++) {
|
|
19
|
+
mappingLines.push([]);
|
|
20
|
+
}
|
|
21
|
+
// For positions outside any edit, the mapping is identity + accumulated delta.
|
|
22
|
+
// For positions inside an edit's transformed region, map to the original edit start.
|
|
23
|
+
// We generate one segment per transformed line start.
|
|
24
|
+
for (let transLine = 0; transLine < transLineCount; transLine++) {
|
|
25
|
+
const transOffset = transLineStarts[transLine];
|
|
26
|
+
const origOffset = transformedToOriginal(edits, transOffset);
|
|
27
|
+
const { line: origLine, col: origCol } = offsetToLineCol(origLineStarts, origOffset);
|
|
28
|
+
mappingLines[transLine].push([0, 0, origLine, origCol]);
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
version: 3,
|
|
32
|
+
file: fileName,
|
|
33
|
+
sources: [fileName],
|
|
34
|
+
sourcesContent: [originalText],
|
|
35
|
+
names: [],
|
|
36
|
+
mappings: encodeMappings(mappingLines),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Map a transformed-source offset back to the original source. */
|
|
40
|
+
function transformedToOriginal(edits, pos) {
|
|
41
|
+
let delta = 0;
|
|
42
|
+
for (const edit of edits) {
|
|
43
|
+
if (pos < edit.transStart) {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
if (pos < edit.transEnd) {
|
|
47
|
+
return edit.origStart;
|
|
48
|
+
}
|
|
49
|
+
delta = edit.origEnd - edit.transEnd;
|
|
50
|
+
}
|
|
51
|
+
return pos + delta;
|
|
52
|
+
}
|
|
53
|
+
/** Build an array where index i is the character offset of line i. */
|
|
54
|
+
function buildLineStarts(text) {
|
|
55
|
+
const starts = [0];
|
|
56
|
+
for (let i = 0; i < text.length; i++) {
|
|
57
|
+
if (text[i] === "\n") {
|
|
58
|
+
starts.push(i + 1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return starts;
|
|
62
|
+
}
|
|
63
|
+
/** Convert a character offset to 0-based line and column. */
|
|
64
|
+
function offsetToLineCol(lineStarts, offset) {
|
|
65
|
+
// Binary search for the line containing this offset
|
|
66
|
+
let lo = 0;
|
|
67
|
+
let hi = lineStarts.length - 1;
|
|
68
|
+
while (lo < hi) {
|
|
69
|
+
const mid = (lo + hi + 1) >>> 1;
|
|
70
|
+
if (lineStarts[mid] <= offset) {
|
|
71
|
+
lo = mid;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
hi = mid - 1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { line: lo, col: offset - lineStarts[lo] };
|
|
78
|
+
}
|
|
79
|
+
/** Encode segment arrays into a VLQ mappings string. */
|
|
80
|
+
function encodeMappings(lines) {
|
|
81
|
+
let prevTransCol = 0;
|
|
82
|
+
let prevOrigLine = 0;
|
|
83
|
+
let prevOrigCol = 0;
|
|
84
|
+
let prevSourceIdx = 0;
|
|
85
|
+
const lineStrings = [];
|
|
86
|
+
for (const segments of lines) {
|
|
87
|
+
prevTransCol = 0; // reset column tracking per line
|
|
88
|
+
const segStrings = [];
|
|
89
|
+
for (const seg of segments) {
|
|
90
|
+
const [transCol, sourceIdx, origLine, origCol] = seg;
|
|
91
|
+
segStrings.push(encodeVLQ(transCol - prevTransCol) +
|
|
92
|
+
encodeVLQ(sourceIdx - prevSourceIdx) +
|
|
93
|
+
encodeVLQ(origLine - prevOrigLine) +
|
|
94
|
+
encodeVLQ(origCol - prevOrigCol));
|
|
95
|
+
prevTransCol = transCol;
|
|
96
|
+
prevSourceIdx = sourceIdx;
|
|
97
|
+
prevOrigLine = origLine;
|
|
98
|
+
prevOrigCol = origCol;
|
|
99
|
+
}
|
|
100
|
+
lineStrings.push(segStrings.join(","));
|
|
101
|
+
}
|
|
102
|
+
return lineStrings.join(";");
|
|
103
|
+
}
|
|
104
|
+
const VLQ_BASE = 32;
|
|
105
|
+
const VLQ_BASE_MASK = VLQ_BASE - 1;
|
|
106
|
+
const VLQ_CONTINUATION = VLQ_BASE;
|
|
107
|
+
const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
108
|
+
/** Encode a single integer as a VLQ base64 string. */
|
|
109
|
+
function encodeVLQ(value) {
|
|
110
|
+
let vlq = value < 0 ? (-value << 1) | 1 : value << 1;
|
|
111
|
+
let result = "";
|
|
112
|
+
do {
|
|
113
|
+
let digit = vlq & VLQ_BASE_MASK;
|
|
114
|
+
vlq >>>= 5;
|
|
115
|
+
if (vlq > 0) {
|
|
116
|
+
digit |= VLQ_CONTINUATION;
|
|
117
|
+
}
|
|
118
|
+
result += BASE64_CHARS[digit];
|
|
119
|
+
} while (vlq > 0);
|
|
120
|
+
return result;
|
|
121
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boperators/webpack-loader",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "webpack loader for boperators",
|
|
6
6
|
"repository": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dist"
|
|
38
38
|
],
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"boperators": "0.3.
|
|
40
|
+
"boperators": "0.3.1",
|
|
41
41
|
"typescript": ">=5.0.0 <5.10.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|