@style-this/core 0.2.0 → 0.2.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/atomic.d.mts +5 -0
- package/dist/atomic.d.mts.map +1 -0
- package/dist/atomic.mjs +10 -0
- package/dist/atomic.mjs.map +1 -0
- package/dist/cssSourceMap.d.mts +31 -0
- package/dist/cssSourceMap.d.mts.map +1 -0
- package/dist/cssSourceMap.mjs +106 -0
- package/dist/cssSourceMap.mjs.map +1 -0
- package/package.json +8 -10
- package/src/atomic.ts +0 -13
- package/src/cssSourceMap.ts +0 -170
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic.d.mts","names":[],"sources":["../src/atomic.ts"],"sourcesContent":[],"mappings":";cAOa,0BAAA"}
|
package/dist/atomic.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
//#region src/atomic.ts
|
|
2
|
+
(function() {
|
|
3
|
+
if (typeof __style_this_atomic_init === "undefined") globalThis.__style_this_atomic_init = true;
|
|
4
|
+
})();
|
|
5
|
+
const __style_this_atomic_marker = true;
|
|
6
|
+
throw new Error("@style-this/core/atomic should not be imported directly. The transformer converts this import into a virtual module.");
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
export { __style_this_atomic_marker };
|
|
10
|
+
//# sourceMappingURL=atomic.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic.mjs","names":[],"sources":["../src/atomic.ts"],"sourcesContent":["// This code runs as a side effect during module load, preventing tree-shaking\n(function () {\n if (typeof __style_this_atomic_init === 'undefined') {\n (globalThis as any).__style_this_atomic_init = true;\n }\n})();\n\nexport const __style_this_atomic_marker = true;\n\nthrow new Error(\n '@style-this/core/atomic should not be imported directly. ' +\n 'The transformer converts this import into a virtual module.'\n);\n"],"mappings":";CACC,WAAY;AACX,KAAI,OAAO,6BAA6B,YACtC,CAAC,WAAmB,2BAA2B;IAE/C;AAEJ,MAAa,6BAA6B;AAE1C,MAAM,IAAI,MACR,uHAED"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/compiler.d.ts
|
|
2
|
+
|
|
3
|
+
type CssSourceMapData = Array<{
|
|
4
|
+
className: string;
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
}>;
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/cssSourceMap.d.ts
|
|
10
|
+
interface SourceMapSegment {
|
|
11
|
+
generatedLine: number;
|
|
12
|
+
generatedColumn: number;
|
|
13
|
+
originalLine: number;
|
|
14
|
+
originalColumn: number;
|
|
15
|
+
source: string;
|
|
16
|
+
}
|
|
17
|
+
interface SourceMap {
|
|
18
|
+
version: number;
|
|
19
|
+
file?: string;
|
|
20
|
+
sources: string[];
|
|
21
|
+
sourcesContent: string[];
|
|
22
|
+
names: string[];
|
|
23
|
+
mappings: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Generate a CSS source map that maps generated CSS classes back to original source locations
|
|
27
|
+
*/
|
|
28
|
+
declare function generateCssSourceMap(cssContent: string, sourcemapData: CssSourceMapData, originalFilepath: string, originalSource: string, generatedFilepath?: string): SourceMap;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { SourceMap, SourceMapSegment, generateCssSourceMap };
|
|
31
|
+
//# sourceMappingURL=cssSourceMap.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cssSourceMap.d.mts","names":[],"sources":["../src/compiler.ts","../src/cssSourceMap.ts"],"sourcesContent":[],"mappings":";;KA2BY,gBAAA,GAAmB;;;;;;;AAAnB,UCzBK,gBAAA,CDyBW;;;;ECzBX,cAAA,EAAA,MAAgB;EAQhB,MAAA,EAAA,MAAS;AAY1B;UAZiB,SAAA;;;;;;;;;;;iBAYD,oBAAA,oCAEC,iGAId"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
//#region src/cssSourceMap.ts
|
|
2
|
+
/**
|
|
3
|
+
* Generate a CSS source map that maps generated CSS classes back to original source locations
|
|
4
|
+
*/
|
|
5
|
+
function generateCssSourceMap(cssContent, sourcemapData, originalFilepath, originalSource, generatedFilepath) {
|
|
6
|
+
const segments = [];
|
|
7
|
+
for (const entry of sourcemapData) {
|
|
8
|
+
const position = findSelectorInCss(cssContent, `.${entry.className}`);
|
|
9
|
+
if (position) {
|
|
10
|
+
const originalPos = getLineAndColumn(originalSource, entry.start);
|
|
11
|
+
segments.push({
|
|
12
|
+
generatedLine: position.line,
|
|
13
|
+
generatedColumn: position.column,
|
|
14
|
+
originalLine: originalPos.line,
|
|
15
|
+
originalColumn: originalPos.column,
|
|
16
|
+
source: originalFilepath
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const mappings = segmentsToVLQ(segments);
|
|
21
|
+
return {
|
|
22
|
+
version: 3,
|
|
23
|
+
file: generatedFilepath,
|
|
24
|
+
sources: [originalFilepath],
|
|
25
|
+
sourcesContent: [originalSource],
|
|
26
|
+
names: [],
|
|
27
|
+
mappings
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function findSelectorInCss(css, selector) {
|
|
31
|
+
const index = css.indexOf(selector);
|
|
32
|
+
if (index === -1) return null;
|
|
33
|
+
const beforeSelector = css.substring(0, index);
|
|
34
|
+
return {
|
|
35
|
+
line: (beforeSelector.match(/\n/g) || []).length,
|
|
36
|
+
column: index - beforeSelector.lastIndexOf("\n") - 1
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function getLineAndColumn(source, offset) {
|
|
40
|
+
const beforeOffset = source.substring(0, offset);
|
|
41
|
+
const line = (beforeOffset.match(/\n/g) || []).length;
|
|
42
|
+
const column = offset - beforeOffset.lastIndexOf("\n") - 1;
|
|
43
|
+
return {
|
|
44
|
+
line,
|
|
45
|
+
column: Math.max(0, column)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Convert segments to VLQ-encoded mappings string
|
|
50
|
+
* This is a simplified implementation - for production, consider using a library
|
|
51
|
+
*/
|
|
52
|
+
function segmentsToVLQ(segments) {
|
|
53
|
+
if (segments.length === 0) return "";
|
|
54
|
+
segments.sort((a, b) => {
|
|
55
|
+
if (a.generatedLine !== b.generatedLine) return a.generatedLine - b.generatedLine;
|
|
56
|
+
return a.generatedColumn - b.generatedColumn;
|
|
57
|
+
});
|
|
58
|
+
const lines = [];
|
|
59
|
+
let currentLine = 0;
|
|
60
|
+
let previousGeneratedColumn = 0;
|
|
61
|
+
let previousOriginalLine = 0;
|
|
62
|
+
let previousOriginalColumn = 0;
|
|
63
|
+
let previousSourceIndex = 0;
|
|
64
|
+
for (const segment of segments) {
|
|
65
|
+
while (currentLine < segment.generatedLine) {
|
|
66
|
+
lines.push("");
|
|
67
|
+
currentLine++;
|
|
68
|
+
previousGeneratedColumn = 0;
|
|
69
|
+
}
|
|
70
|
+
const values = [
|
|
71
|
+
segment.generatedColumn - previousGeneratedColumn,
|
|
72
|
+
0 - previousSourceIndex,
|
|
73
|
+
segment.originalLine - previousOriginalLine,
|
|
74
|
+
segment.originalColumn - previousOriginalColumn
|
|
75
|
+
];
|
|
76
|
+
lines[currentLine] = (lines[currentLine] ? lines[currentLine] + "," : "") + values.map(encodeVLQ).join("");
|
|
77
|
+
previousGeneratedColumn = segment.generatedColumn;
|
|
78
|
+
previousOriginalLine = segment.originalLine;
|
|
79
|
+
previousOriginalColumn = segment.originalColumn;
|
|
80
|
+
previousSourceIndex = 0;
|
|
81
|
+
}
|
|
82
|
+
return lines.join(";");
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Encode a value as VLQ (Variable Length Quantity)
|
|
86
|
+
*/
|
|
87
|
+
function encodeVLQ(value) {
|
|
88
|
+
const VLQ_BASE_SHIFT = 5;
|
|
89
|
+
const VLQ_BASE = 1 << VLQ_BASE_SHIFT;
|
|
90
|
+
const VLQ_BASE_MASK = VLQ_BASE - 1;
|
|
91
|
+
const VLQ_CONTINUATION_BIT = VLQ_BASE;
|
|
92
|
+
const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
93
|
+
let encoded = value < 0 ? -value << 1 | 1 : value << 1;
|
|
94
|
+
let result = "";
|
|
95
|
+
do {
|
|
96
|
+
let digit = encoded & VLQ_BASE_MASK;
|
|
97
|
+
encoded >>>= VLQ_BASE_SHIFT;
|
|
98
|
+
if (encoded > 0) digit |= VLQ_CONTINUATION_BIT;
|
|
99
|
+
result += BASE64_CHARS[digit];
|
|
100
|
+
} while (encoded > 0);
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
105
|
+
export { generateCssSourceMap };
|
|
106
|
+
//# sourceMappingURL=cssSourceMap.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cssSourceMap.mjs","names":["segments: SourceMapSegment[]","lines: string[]"],"sources":["../src/cssSourceMap.ts"],"sourcesContent":["import type { CssSourceMapData } from \"./compiler.js\";\n\nexport interface SourceMapSegment {\n generatedLine: number;\n generatedColumn: number;\n originalLine: number;\n originalColumn: number;\n source: string;\n}\n\nexport interface SourceMap {\n version: number;\n file?: string;\n sources: string[];\n sourcesContent: string[];\n names: string[];\n mappings: string;\n}\n\n/**\n * Generate a CSS source map that maps generated CSS classes back to original source locations\n */\nexport function generateCssSourceMap(\n cssContent: string,\n sourcemapData: CssSourceMapData,\n originalFilepath: string,\n originalSource: string,\n generatedFilepath?: string,\n): SourceMap {\n const segments: SourceMapSegment[] = [];\n\n // For each CSS class, find its position in the generated CSS and map it back\n for (const entry of sourcemapData) {\n const selector = `.${entry.className}`;\n const position = findSelectorInCss(cssContent, selector);\n\n if (position) {\n // Calculate line and column from byte offset in original source\n const originalPos = getLineAndColumn(originalSource, entry.start);\n\n segments.push({\n generatedLine: position.line,\n generatedColumn: position.column,\n originalLine: originalPos.line,\n originalColumn: originalPos.column,\n source: originalFilepath,\n });\n }\n }\n\n // Convert segments to VLQ mappings\n const mappings = segmentsToVLQ(segments);\n\n return {\n version: 3,\n file: generatedFilepath,\n sources: [originalFilepath],\n sourcesContent: [originalSource],\n names: [],\n mappings,\n };\n}\n\nfunction findSelectorInCss(\n css: string,\n selector: string,\n): { line: number; column: number } | null {\n const index = css.indexOf(selector);\n if (index === -1) return null;\n\n const beforeSelector = css.substring(0, index);\n const line = (beforeSelector.match(/\\n/g) || []).length;\n const lastNewline = beforeSelector.lastIndexOf(\"\\n\");\n const column = index - lastNewline - 1;\n\n return { line, column };\n}\n\nfunction getLineAndColumn(\n source: string,\n offset: number,\n): { line: number; column: number } {\n const beforeOffset = source.substring(0, offset);\n const line = (beforeOffset.match(/\\n/g) || []).length;\n const lastNewline = beforeOffset.lastIndexOf(\"\\n\");\n const column = offset - lastNewline - 1;\n\n return { line, column: Math.max(0, column) };\n}\n\n/**\n * Convert segments to VLQ-encoded mappings string\n * This is a simplified implementation - for production, consider using a library\n */\nfunction segmentsToVLQ(segments: SourceMapSegment[]): string {\n if (segments.length === 0) return \"\";\n\n // Sort segments by generated position\n segments.sort((a, b) => {\n if (a.generatedLine !== b.generatedLine) {\n return a.generatedLine - b.generatedLine;\n }\n return a.generatedColumn - b.generatedColumn;\n });\n\n const lines: string[] = [];\n let currentLine = 0;\n let previousGeneratedColumn = 0;\n let previousOriginalLine = 0;\n let previousOriginalColumn = 0;\n let previousSourceIndex = 0;\n\n for (const segment of segments) {\n // Add empty line segments for skipped lines\n while (currentLine < segment.generatedLine) {\n lines.push(\"\");\n currentLine++;\n previousGeneratedColumn = 0;\n }\n\n // Encode this segment\n const values = [\n segment.generatedColumn - previousGeneratedColumn,\n 0 - previousSourceIndex, // source index (always 0 for us)\n segment.originalLine - previousOriginalLine,\n segment.originalColumn - previousOriginalColumn,\n ];\n\n lines[currentLine] =\n (lines[currentLine] ? lines[currentLine] + \",\" : \"\") +\n values.map(encodeVLQ).join(\"\");\n\n previousGeneratedColumn = segment.generatedColumn;\n previousOriginalLine = segment.originalLine;\n previousOriginalColumn = segment.originalColumn;\n previousSourceIndex = 0;\n }\n\n return lines.join(\";\");\n}\n\n/**\n * Encode a value as VLQ (Variable Length Quantity)\n */\nfunction encodeVLQ(value: number): string {\n const VLQ_BASE_SHIFT = 5;\n const VLQ_BASE = 1 << VLQ_BASE_SHIFT;\n const VLQ_BASE_MASK = VLQ_BASE - 1;\n const VLQ_CONTINUATION_BIT = VLQ_BASE;\n\n const BASE64_CHARS =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n // Convert to sign-magnitude representation\n let encoded = value < 0 ? ((-value) << 1) | 1 : value << 1;\n\n let result = \"\";\n do {\n let digit = encoded & VLQ_BASE_MASK;\n encoded >>>= VLQ_BASE_SHIFT;\n\n if (encoded > 0) {\n digit |= VLQ_CONTINUATION_BIT;\n }\n\n result += BASE64_CHARS[digit];\n } while (encoded > 0);\n\n return result;\n}\n"],"mappings":";;;;AAsBA,SAAgB,qBACd,YACA,eACA,kBACA,gBACA,mBACW;CACX,MAAMA,WAA+B,EAAE;AAGvC,MAAK,MAAM,SAAS,eAAe;EAEjC,MAAM,WAAW,kBAAkB,YADlB,IAAI,MAAM,YAC6B;AAExD,MAAI,UAAU;GAEZ,MAAM,cAAc,iBAAiB,gBAAgB,MAAM,MAAM;AAEjE,YAAS,KAAK;IACZ,eAAe,SAAS;IACxB,iBAAiB,SAAS;IAC1B,cAAc,YAAY;IAC1B,gBAAgB,YAAY;IAC5B,QAAQ;IACT,CAAC;;;CAKN,MAAM,WAAW,cAAc,SAAS;AAExC,QAAO;EACL,SAAS;EACT,MAAM;EACN,SAAS,CAAC,iBAAiB;EAC3B,gBAAgB,CAAC,eAAe;EAChC,OAAO,EAAE;EACT;EACD;;AAGH,SAAS,kBACP,KACA,UACyC;CACzC,MAAM,QAAQ,IAAI,QAAQ,SAAS;AACnC,KAAI,UAAU,GAAI,QAAO;CAEzB,MAAM,iBAAiB,IAAI,UAAU,GAAG,MAAM;AAK9C,QAAO;EAAE,OAJK,eAAe,MAAM,MAAM,IAAI,EAAE,EAAE;EAIlC,QAFA,QADK,eAAe,YAAY,KAAK,GACf;EAEd;;AAGzB,SAAS,iBACP,QACA,QACkC;CAClC,MAAM,eAAe,OAAO,UAAU,GAAG,OAAO;CAChD,MAAM,QAAQ,aAAa,MAAM,MAAM,IAAI,EAAE,EAAE;CAE/C,MAAM,SAAS,SADK,aAAa,YAAY,KAAK,GACZ;AAEtC,QAAO;EAAE;EAAM,QAAQ,KAAK,IAAI,GAAG,OAAO;EAAE;;;;;;AAO9C,SAAS,cAAc,UAAsC;AAC3D,KAAI,SAAS,WAAW,EAAG,QAAO;AAGlC,UAAS,MAAM,GAAG,MAAM;AACtB,MAAI,EAAE,kBAAkB,EAAE,cACxB,QAAO,EAAE,gBAAgB,EAAE;AAE7B,SAAO,EAAE,kBAAkB,EAAE;GAC7B;CAEF,MAAMC,QAAkB,EAAE;CAC1B,IAAI,cAAc;CAClB,IAAI,0BAA0B;CAC9B,IAAI,uBAAuB;CAC3B,IAAI,yBAAyB;CAC7B,IAAI,sBAAsB;AAE1B,MAAK,MAAM,WAAW,UAAU;AAE9B,SAAO,cAAc,QAAQ,eAAe;AAC1C,SAAM,KAAK,GAAG;AACd;AACA,6BAA0B;;EAI5B,MAAM,SAAS;GACb,QAAQ,kBAAkB;GAC1B,IAAI;GACJ,QAAQ,eAAe;GACvB,QAAQ,iBAAiB;GAC1B;AAED,QAAM,gBACH,MAAM,eAAe,MAAM,eAAe,MAAM,MACjD,OAAO,IAAI,UAAU,CAAC,KAAK,GAAG;AAEhC,4BAA0B,QAAQ;AAClC,yBAAuB,QAAQ;AAC/B,2BAAyB,QAAQ;AACjC,wBAAsB;;AAGxB,QAAO,MAAM,KAAK,IAAI;;;;;AAMxB,SAAS,UAAU,OAAuB;CACxC,MAAM,iBAAiB;CACvB,MAAM,WAAW,KAAK;CACtB,MAAM,gBAAgB,WAAW;CACjC,MAAM,uBAAuB;CAE7B,MAAM,eACJ;CAGF,IAAI,UAAU,QAAQ,IAAM,CAAC,SAAU,IAAK,IAAI,SAAS;CAEzD,IAAI,SAAS;AACb,IAAG;EACD,IAAI,QAAQ,UAAU;AACtB,eAAa;AAEb,MAAI,UAAU,EACZ,UAAS;AAGX,YAAU,aAAa;UAChB,UAAU;AAEnB,QAAO"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@style-this/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "CSS-in-JS library for the modern web - core module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
|
-
"dist"
|
|
8
|
-
"src/cssSourceMap.ts",
|
|
9
|
-
"src/atomic.ts"
|
|
7
|
+
"dist"
|
|
10
8
|
],
|
|
11
9
|
"main": "./dist/index.mjs",
|
|
12
10
|
"module": "./dist/index.mjs",
|
|
@@ -24,14 +22,14 @@
|
|
|
24
22
|
"default": "./dist/compiler.cjs"
|
|
25
23
|
},
|
|
26
24
|
"./cssSourceMap": {
|
|
27
|
-
"types": "./
|
|
28
|
-
"import": "./
|
|
29
|
-
"default": "./
|
|
25
|
+
"types": "./dist/cssSourceMap.d.mts",
|
|
26
|
+
"import": "./dist/cssSourceMap.mjs",
|
|
27
|
+
"default": "./dist/cssSourceMap.mjs"
|
|
30
28
|
},
|
|
31
29
|
"./atomic": {
|
|
32
|
-
"types": "./
|
|
33
|
-
"import": "./
|
|
34
|
-
"default": "./
|
|
30
|
+
"types": "./dist/atomic.d.mts",
|
|
31
|
+
"import": "./dist/atomic.mjs",
|
|
32
|
+
"default": "./dist/atomic.mjs"
|
|
35
33
|
},
|
|
36
34
|
"./package.json": "./package.json"
|
|
37
35
|
},
|
package/src/atomic.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// This code runs as a side effect during module load, preventing tree-shaking
|
|
2
|
-
(function () {
|
|
3
|
-
if (typeof __style_this_atomic_init === 'undefined') {
|
|
4
|
-
(globalThis as any).__style_this_atomic_init = true;
|
|
5
|
-
}
|
|
6
|
-
})();
|
|
7
|
-
|
|
8
|
-
export const __style_this_atomic_marker = true;
|
|
9
|
-
|
|
10
|
-
throw new Error(
|
|
11
|
-
'@style-this/core/atomic should not be imported directly. ' +
|
|
12
|
-
'The transformer converts this import into a virtual module.'
|
|
13
|
-
);
|
package/src/cssSourceMap.ts
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import type { CssSourceMapData } from "./compiler.js";
|
|
2
|
-
|
|
3
|
-
export interface SourceMapSegment {
|
|
4
|
-
generatedLine: number;
|
|
5
|
-
generatedColumn: number;
|
|
6
|
-
originalLine: number;
|
|
7
|
-
originalColumn: number;
|
|
8
|
-
source: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface SourceMap {
|
|
12
|
-
version: number;
|
|
13
|
-
file?: string;
|
|
14
|
-
sources: string[];
|
|
15
|
-
sourcesContent: string[];
|
|
16
|
-
names: string[];
|
|
17
|
-
mappings: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Generate a CSS source map that maps generated CSS classes back to original source locations
|
|
22
|
-
*/
|
|
23
|
-
export function generateCssSourceMap(
|
|
24
|
-
cssContent: string,
|
|
25
|
-
sourcemapData: CssSourceMapData,
|
|
26
|
-
originalFilepath: string,
|
|
27
|
-
originalSource: string,
|
|
28
|
-
generatedFilepath?: string,
|
|
29
|
-
): SourceMap {
|
|
30
|
-
const segments: SourceMapSegment[] = [];
|
|
31
|
-
|
|
32
|
-
// For each CSS class, find its position in the generated CSS and map it back
|
|
33
|
-
for (const entry of sourcemapData) {
|
|
34
|
-
const selector = `.${entry.className}`;
|
|
35
|
-
const position = findSelectorInCss(cssContent, selector);
|
|
36
|
-
|
|
37
|
-
if (position) {
|
|
38
|
-
// Calculate line and column from byte offset in original source
|
|
39
|
-
const originalPos = getLineAndColumn(originalSource, entry.start);
|
|
40
|
-
|
|
41
|
-
segments.push({
|
|
42
|
-
generatedLine: position.line,
|
|
43
|
-
generatedColumn: position.column,
|
|
44
|
-
originalLine: originalPos.line,
|
|
45
|
-
originalColumn: originalPos.column,
|
|
46
|
-
source: originalFilepath,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// Convert segments to VLQ mappings
|
|
52
|
-
const mappings = segmentsToVLQ(segments);
|
|
53
|
-
|
|
54
|
-
return {
|
|
55
|
-
version: 3,
|
|
56
|
-
file: generatedFilepath,
|
|
57
|
-
sources: [originalFilepath],
|
|
58
|
-
sourcesContent: [originalSource],
|
|
59
|
-
names: [],
|
|
60
|
-
mappings,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function findSelectorInCss(
|
|
65
|
-
css: string,
|
|
66
|
-
selector: string,
|
|
67
|
-
): { line: number; column: number } | null {
|
|
68
|
-
const index = css.indexOf(selector);
|
|
69
|
-
if (index === -1) return null;
|
|
70
|
-
|
|
71
|
-
const beforeSelector = css.substring(0, index);
|
|
72
|
-
const line = (beforeSelector.match(/\n/g) || []).length;
|
|
73
|
-
const lastNewline = beforeSelector.lastIndexOf("\n");
|
|
74
|
-
const column = index - lastNewline - 1;
|
|
75
|
-
|
|
76
|
-
return { line, column };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function getLineAndColumn(
|
|
80
|
-
source: string,
|
|
81
|
-
offset: number,
|
|
82
|
-
): { line: number; column: number } {
|
|
83
|
-
const beforeOffset = source.substring(0, offset);
|
|
84
|
-
const line = (beforeOffset.match(/\n/g) || []).length;
|
|
85
|
-
const lastNewline = beforeOffset.lastIndexOf("\n");
|
|
86
|
-
const column = offset - lastNewline - 1;
|
|
87
|
-
|
|
88
|
-
return { line, column: Math.max(0, column) };
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Convert segments to VLQ-encoded mappings string
|
|
93
|
-
* This is a simplified implementation - for production, consider using a library
|
|
94
|
-
*/
|
|
95
|
-
function segmentsToVLQ(segments: SourceMapSegment[]): string {
|
|
96
|
-
if (segments.length === 0) return "";
|
|
97
|
-
|
|
98
|
-
// Sort segments by generated position
|
|
99
|
-
segments.sort((a, b) => {
|
|
100
|
-
if (a.generatedLine !== b.generatedLine) {
|
|
101
|
-
return a.generatedLine - b.generatedLine;
|
|
102
|
-
}
|
|
103
|
-
return a.generatedColumn - b.generatedColumn;
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const lines: string[] = [];
|
|
107
|
-
let currentLine = 0;
|
|
108
|
-
let previousGeneratedColumn = 0;
|
|
109
|
-
let previousOriginalLine = 0;
|
|
110
|
-
let previousOriginalColumn = 0;
|
|
111
|
-
let previousSourceIndex = 0;
|
|
112
|
-
|
|
113
|
-
for (const segment of segments) {
|
|
114
|
-
// Add empty line segments for skipped lines
|
|
115
|
-
while (currentLine < segment.generatedLine) {
|
|
116
|
-
lines.push("");
|
|
117
|
-
currentLine++;
|
|
118
|
-
previousGeneratedColumn = 0;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Encode this segment
|
|
122
|
-
const values = [
|
|
123
|
-
segment.generatedColumn - previousGeneratedColumn,
|
|
124
|
-
0 - previousSourceIndex, // source index (always 0 for us)
|
|
125
|
-
segment.originalLine - previousOriginalLine,
|
|
126
|
-
segment.originalColumn - previousOriginalColumn,
|
|
127
|
-
];
|
|
128
|
-
|
|
129
|
-
lines[currentLine] =
|
|
130
|
-
(lines[currentLine] ? lines[currentLine] + "," : "") +
|
|
131
|
-
values.map(encodeVLQ).join("");
|
|
132
|
-
|
|
133
|
-
previousGeneratedColumn = segment.generatedColumn;
|
|
134
|
-
previousOriginalLine = segment.originalLine;
|
|
135
|
-
previousOriginalColumn = segment.originalColumn;
|
|
136
|
-
previousSourceIndex = 0;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return lines.join(";");
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Encode a value as VLQ (Variable Length Quantity)
|
|
144
|
-
*/
|
|
145
|
-
function encodeVLQ(value: number): string {
|
|
146
|
-
const VLQ_BASE_SHIFT = 5;
|
|
147
|
-
const VLQ_BASE = 1 << VLQ_BASE_SHIFT;
|
|
148
|
-
const VLQ_BASE_MASK = VLQ_BASE - 1;
|
|
149
|
-
const VLQ_CONTINUATION_BIT = VLQ_BASE;
|
|
150
|
-
|
|
151
|
-
const BASE64_CHARS =
|
|
152
|
-
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
153
|
-
|
|
154
|
-
// Convert to sign-magnitude representation
|
|
155
|
-
let encoded = value < 0 ? ((-value) << 1) | 1 : value << 1;
|
|
156
|
-
|
|
157
|
-
let result = "";
|
|
158
|
-
do {
|
|
159
|
-
let digit = encoded & VLQ_BASE_MASK;
|
|
160
|
-
encoded >>>= VLQ_BASE_SHIFT;
|
|
161
|
-
|
|
162
|
-
if (encoded > 0) {
|
|
163
|
-
digit |= VLQ_CONTINUATION_BIT;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
result += BASE64_CHARS[digit];
|
|
167
|
-
} while (encoded > 0);
|
|
168
|
-
|
|
169
|
-
return result;
|
|
170
|
-
}
|