@litsx/jsx-authoring 0.1.0

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/src/parser.js ADDED
@@ -0,0 +1,181 @@
1
+ import {
2
+ createVirtualLitsxJsxSource,
3
+ decodeVirtualAttributeName,
4
+ mapVirtualPositionToOriginal,
5
+ } from "./index.js";
6
+
7
+ const VIRTUALIZATION_METADATA = Symbol.for("litsx.babelParser.virtualization");
8
+
9
+ function ensureJsxPlugin(plugins = []) {
10
+ const hasJsx = plugins.some((plugin) => {
11
+ if (typeof plugin === "string") {
12
+ return plugin === "jsx";
13
+ }
14
+
15
+ return Array.isArray(plugin) && plugin[0] === "jsx";
16
+ });
17
+
18
+ return hasJsx ? plugins : [...plugins, "jsx"];
19
+ }
20
+
21
+ function normalizeOptions(options = {}) {
22
+ const {
23
+ plugins = [],
24
+ sourceFileName,
25
+ sourceFilename,
26
+ litsxSourceMap,
27
+ ...rest
28
+ } = options;
29
+
30
+ return {
31
+ parserOptions: {
32
+ sourceType: "module",
33
+ ...rest,
34
+ plugins: ensureJsxPlugin(plugins),
35
+ },
36
+ virtualizationOptions: {
37
+ sourceFileName: sourceFileName ?? sourceFilename,
38
+ sourceMap: litsxSourceMap !== false,
39
+ },
40
+ };
41
+ }
42
+
43
+ function walk(node, visitor) {
44
+ if (!node || typeof node !== "object") {
45
+ return;
46
+ }
47
+
48
+ visitor(node);
49
+
50
+ for (const value of Object.values(node)) {
51
+ if (Array.isArray(value)) {
52
+ for (const item of value) {
53
+ walk(item, visitor);
54
+ }
55
+ continue;
56
+ }
57
+
58
+ walk(value, visitor);
59
+ }
60
+ }
61
+
62
+ function createIndexToPosition(source) {
63
+ const lineStarts = [0];
64
+
65
+ for (let index = 0; index < source.length; index += 1) {
66
+ if (source[index] === "\n") {
67
+ lineStarts.push(index + 1);
68
+ }
69
+ }
70
+
71
+ return (index) => {
72
+ let low = 0;
73
+ let high = lineStarts.length - 1;
74
+
75
+ while (low <= high) {
76
+ const mid = Math.floor((low + high) / 2);
77
+ if (lineStarts[mid] <= index) {
78
+ low = mid + 1;
79
+ } else {
80
+ high = mid - 1;
81
+ }
82
+ }
83
+
84
+ const lineIndex = Math.max(0, high);
85
+ return {
86
+ line: lineIndex + 1,
87
+ column: index - lineStarts[lineIndex],
88
+ index,
89
+ };
90
+ };
91
+ }
92
+
93
+ function remapAstPositions(ast, source, replacements) {
94
+ if (!replacements?.length) {
95
+ return ast;
96
+ }
97
+
98
+ const indexToPosition = createIndexToPosition(source);
99
+
100
+ walk(ast, (node) => {
101
+ if (!node || typeof node !== "object") {
102
+ return;
103
+ }
104
+
105
+ if (typeof node.start === "number") {
106
+ node.start = mapVirtualPositionToOriginal(node.start, replacements);
107
+ }
108
+
109
+ if (typeof node.end === "number") {
110
+ node.end = mapVirtualPositionToOriginal(node.end, replacements);
111
+ }
112
+
113
+ if (node.loc) {
114
+ const startIndex =
115
+ typeof node.start === "number"
116
+ ? node.start
117
+ : mapVirtualPositionToOriginal(node.loc.start.index, replacements);
118
+ const endIndex =
119
+ typeof node.end === "number"
120
+ ? node.end
121
+ : mapVirtualPositionToOriginal(node.loc.end.index, replacements);
122
+
123
+ node.loc = {
124
+ ...node.loc,
125
+ start: indexToPosition(startIndex),
126
+ end: indexToPosition(endIndex),
127
+ };
128
+ }
129
+ });
130
+
131
+ return ast;
132
+ }
133
+
134
+ function restoreVirtualAttributeNames(ast) {
135
+ walk(ast, (node) => {
136
+ if (
137
+ node?.type === "JSXAttribute" &&
138
+ node.name?.type === "JSXIdentifier" &&
139
+ typeof node.name.name === "string"
140
+ ) {
141
+ const decoded = decodeVirtualAttributeName(node.name.name);
142
+ if (decoded) {
143
+ node.name.name = decoded;
144
+ }
145
+ }
146
+ });
147
+
148
+ return ast;
149
+ }
150
+
151
+ function attachVirtualizationMetadata(ast, virtualSource) {
152
+ if (!ast || !virtualSource) {
153
+ return ast;
154
+ }
155
+
156
+ Object.defineProperty(ast, VIRTUALIZATION_METADATA, {
157
+ configurable: true,
158
+ enumerable: false,
159
+ writable: false,
160
+ value: {
161
+ code: virtualSource.code,
162
+ map: virtualSource.map ?? null,
163
+ replacements: virtualSource.replacements ?? [],
164
+ },
165
+ });
166
+
167
+ return ast;
168
+ }
169
+
170
+ export function getLitsxVirtualizationMetadata(ast) {
171
+ return ast?.[VIRTUALIZATION_METADATA] ?? null;
172
+ }
173
+
174
+ export function parseWithLitsxVirtualization(parseFn, code, options) {
175
+ const { parserOptions, virtualizationOptions } = normalizeOptions(options);
176
+ const virtualSource = createVirtualLitsxJsxSource(code, virtualizationOptions);
177
+ const ast = parseFn(virtualSource.code, parserOptions);
178
+ remapAstPositions(ast, code, virtualSource.replacements);
179
+ restoreVirtualAttributeNames(ast);
180
+ return attachVirtualizationMetadata(ast, virtualSource);
181
+ }