@boperators/webpack-loader 0.2.1 → 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/README.md CHANGED
@@ -119,7 +119,7 @@ The loader runs as a webpack pre-loader, executing before TypeScript compilation
119
119
 
120
120
  1. Creates a [ts-morph](https://ts-morph.com) Project from your tsconfig
121
121
  2. Scans all source files for operator overload definitions
122
- 3. Transforms expressions in the current file (e.g. `v1 + v2` becomes `Vector3["+"][0](v1, v2)`)
122
+ 3. Transforms expressions in the current file (e.g. `v1 + v2` becomes `Vector3["+"](v1, v2)`)
123
123
  4. Generates a V3 source map so stack traces and debugger breakpoints map back to your original source
124
124
  5. Passes the transformed code to the next loader (e.g. `ts-loader`)
125
125
 
@@ -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.2.1",
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.2.1",
40
+ "boperators": "0.3.1",
41
41
  "typescript": ">=5.0.0 <5.10.0"
42
42
  },
43
43
  "devDependencies": {