@mulanjs/mulanjs 1.0.1-dev.20260228085805 → 1.0.1-dev.20260301163040
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.
|
@@ -297,22 +297,39 @@ const JS_KEYWORDS = new Set(['true', 'false', 'null', 'undefined', 'this', 'wind
|
|
|
297
297
|
function processBindings(exp, bindings, localScope) {
|
|
298
298
|
const isOptionsAPI = !bindings || bindings.length === 0;
|
|
299
299
|
const bindingSet = new Set(bindings || []);
|
|
300
|
-
|
|
300
|
+
// 1. Temporarily replace string literals with placeholders
|
|
301
|
+
const literals = [];
|
|
302
|
+
let literalIndex = 0;
|
|
303
|
+
// Match ', ", and ` literals accurately ignoring escaped quotes inside
|
|
304
|
+
const expWithPlaceholders = exp.replace(/(["'`])(?:(?=(\\?))\2.)*?\1/g, (match) => {
|
|
305
|
+
const placeholder = `__MU_LITERAL_${literalIndex++}__`;
|
|
306
|
+
literals.push(match);
|
|
307
|
+
return placeholder;
|
|
308
|
+
});
|
|
309
|
+
// 2. Perform variable binding replacement on the expression without literals
|
|
310
|
+
const processedExp = expWithPlaceholders.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
|
|
301
311
|
if (offset > 0 && str[offset - 1] === '.')
|
|
302
312
|
return match;
|
|
303
313
|
let i = offset + match.length;
|
|
304
314
|
while (i < str.length && /\s/.test(str[i]))
|
|
305
315
|
i++;
|
|
306
|
-
if (str[i] === ':' && str[i + 1] !== '=')
|
|
316
|
+
if (str[i] === ':' && (i + 1 >= str.length || str[i + 1] !== '='))
|
|
307
317
|
return match;
|
|
308
318
|
if (JS_KEYWORDS.has(id) || localScope.includes(id))
|
|
309
319
|
return match;
|
|
320
|
+
// Skip our placeholders
|
|
321
|
+
if (id.startsWith('__MU_LITERAL_'))
|
|
322
|
+
return match;
|
|
310
323
|
if (isOptionsAPI)
|
|
311
324
|
return `this.${id}`;
|
|
312
325
|
if (bindingSet.has(id))
|
|
313
326
|
return `this.${id}`;
|
|
314
327
|
return match;
|
|
315
328
|
});
|
|
329
|
+
// 3. Restore the string literals into the processed expression
|
|
330
|
+
return processedExp.replace(/__MU_LITERAL_(\d+)__/g, (_, index) => {
|
|
331
|
+
return literals[parseInt(index, 10)];
|
|
332
|
+
});
|
|
316
333
|
}
|
|
317
334
|
function transform(node, scriptResult, scopedId, localScope = [], filename) {
|
|
318
335
|
if (node.type === 'Element') {
|
|
@@ -171,13 +171,22 @@ function transform(node, scriptResult, scopedId, localScope = [], filename) {
|
|
|
171
171
|
function processBindings(exp, bindings, localScope) {
|
|
172
172
|
const isOptionsAPI = !bindings || bindings.length === 0;
|
|
173
173
|
const bindingSet = new Set(bindings || []);
|
|
174
|
-
|
|
174
|
+
// 1. Temporarily replace string literals with placeholders
|
|
175
|
+
const literals = [];
|
|
176
|
+
let literalIndex = 0;
|
|
177
|
+
const expWithPlaceholders = exp.replace(/(["'`])(?:(?=(\\?))\2.)*?\1/g, (match) => {
|
|
178
|
+
const placeholder = `__MU_LITERAL_${literalIndex++}__`;
|
|
179
|
+
literals.push(match);
|
|
180
|
+
return placeholder;
|
|
181
|
+
});
|
|
182
|
+
// 2. Perform variable binding replacement on the expression without literals
|
|
183
|
+
const processedExp = expWithPlaceholders.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
|
|
175
184
|
if (offset > 0 && str[offset - 1] === '.')
|
|
176
185
|
return match;
|
|
177
186
|
let i = offset + match.length;
|
|
178
187
|
while (i < str.length && /\s/.test(str[i]))
|
|
179
188
|
i++;
|
|
180
|
-
if (str[i] === ':' && str[i + 1] !== '=')
|
|
189
|
+
if (str[i] === ':' && (i + 1 >= str.length || str[i + 1] !== '='))
|
|
181
190
|
return match;
|
|
182
191
|
if (JS_KEYWORDS.has(id))
|
|
183
192
|
return match;
|
|
@@ -185,6 +194,8 @@ function processBindings(exp, bindings, localScope) {
|
|
|
185
194
|
return match;
|
|
186
195
|
if (localScope.includes(id))
|
|
187
196
|
return match;
|
|
197
|
+
if (id.startsWith('__MU_LITERAL_'))
|
|
198
|
+
return match;
|
|
188
199
|
if (isOptionsAPI) {
|
|
189
200
|
return `this.${id}`;
|
|
190
201
|
}
|
|
@@ -195,6 +206,10 @@ function processBindings(exp, bindings, localScope) {
|
|
|
195
206
|
}
|
|
196
207
|
return match;
|
|
197
208
|
});
|
|
209
|
+
// 3. Restore string literals
|
|
210
|
+
return processedExp.replace(/__MU_LITERAL_(\d+)__/g, (_, index) => {
|
|
211
|
+
return literals[parseInt(index, 10)];
|
|
212
|
+
});
|
|
198
213
|
}
|
|
199
214
|
// --- Generator ---
|
|
200
215
|
function generate(node, bindings, localScope = []) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mulanjs/mulanjs",
|
|
3
|
-
"version": "1.0.1-dev.
|
|
3
|
+
"version": "1.0.1-dev.20260301163040",
|
|
4
4
|
"description": "A powerful, secure, and enterprise-grade JavaScript framework.",
|
|
5
5
|
"main": "dist/mulan.js",
|
|
6
6
|
"module": "dist/mulan.esm.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsc && tsc -p src/compiler/tsconfig.json && npm run bundle",
|
|
33
33
|
"bundle": "webpack",
|
|
34
|
-
"test": "jest",
|
|
34
|
+
"test": "jest --forceExit",
|
|
35
35
|
"prepublishOnly": "npm run build && npm run bundle && npm test",
|
|
36
36
|
"publish:dev": "node scripts/publish-dev.js"
|
|
37
37
|
},
|
|
@@ -354,16 +354,38 @@ const JS_KEYWORDS = new Set(['true', 'false', 'null', 'undefined', 'this', 'wind
|
|
|
354
354
|
function processBindings(exp: string, bindings: string[] | undefined, localScope: string[]) {
|
|
355
355
|
const isOptionsAPI = !bindings || bindings.length === 0;
|
|
356
356
|
const bindingSet = new Set(bindings || []);
|
|
357
|
-
|
|
357
|
+
|
|
358
|
+
// 1. Temporarily replace string literals with placeholders
|
|
359
|
+
const literals: string[] = [];
|
|
360
|
+
let literalIndex = 0;
|
|
361
|
+
|
|
362
|
+
// Match ', ", and ` literals accurately ignoring escaped quotes inside
|
|
363
|
+
const expWithPlaceholders = exp.replace(/(["'`])(?:(?=(\\?))\2.)*?\1/g, (match) => {
|
|
364
|
+
const placeholder = `__MU_LITERAL_${literalIndex++}__`;
|
|
365
|
+
literals.push(match);
|
|
366
|
+
return placeholder;
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// 2. Perform variable binding replacement on the expression without literals
|
|
370
|
+
const processedExp = expWithPlaceholders.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
|
|
358
371
|
if (offset > 0 && str[offset - 1] === '.') return match;
|
|
359
372
|
let i = offset + match.length;
|
|
360
373
|
while (i < str.length && /\s/.test(str[i])) i++;
|
|
361
|
-
if (str[i] === ':' && str[i + 1] !== '=') return match;
|
|
374
|
+
if (str[i] === ':' && (i + 1 >= str.length || str[i + 1] !== '=')) return match;
|
|
362
375
|
if (JS_KEYWORDS.has(id) || localScope.includes(id)) return match;
|
|
376
|
+
|
|
377
|
+
// Skip our placeholders
|
|
378
|
+
if (id.startsWith('__MU_LITERAL_')) return match;
|
|
379
|
+
|
|
363
380
|
if (isOptionsAPI) return `this.${id}`;
|
|
364
381
|
if (bindingSet.has(id)) return `this.${id}`;
|
|
365
382
|
return match;
|
|
366
383
|
});
|
|
384
|
+
|
|
385
|
+
// 3. Restore the string literals into the processed expression
|
|
386
|
+
return processedExp.replace(/__MU_LITERAL_(\d+)__/g, (_, index) => {
|
|
387
|
+
return literals[parseInt(index, 10)];
|
|
388
|
+
});
|
|
367
389
|
}
|
|
368
390
|
|
|
369
391
|
function transform(node: Node, scriptResult: ScriptCompileResult, scopedId?: string, localScope: string[] = [], filename?: string) {
|
|
@@ -199,17 +199,29 @@ function processBindings(exp: string, bindings: string[] | undefined, localScope
|
|
|
199
199
|
const isOptionsAPI = !bindings || bindings.length === 0;
|
|
200
200
|
const bindingSet = new Set(bindings || []);
|
|
201
201
|
|
|
202
|
-
|
|
202
|
+
// 1. Temporarily replace string literals with placeholders
|
|
203
|
+
const literals: string[] = [];
|
|
204
|
+
let literalIndex = 0;
|
|
205
|
+
const expWithPlaceholders = exp.replace(/(["'`])(?:(?=(\\?))\2.)*?\1/g, (match) => {
|
|
206
|
+
const placeholder = `__MU_LITERAL_${literalIndex++}__`;
|
|
207
|
+
literals.push(match);
|
|
208
|
+
return placeholder;
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// 2. Perform variable binding replacement on the expression without literals
|
|
212
|
+
const processedExp = expWithPlaceholders.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
|
|
203
213
|
if (offset > 0 && str[offset - 1] === '.') return match;
|
|
204
214
|
|
|
205
215
|
let i = offset + match.length;
|
|
206
216
|
while (i < str.length && /\s/.test(str[i])) i++;
|
|
207
|
-
if (str[i] === ':' && str[i + 1] !== '=') return match;
|
|
217
|
+
if (str[i] === ':' && (i + 1 >= str.length || str[i + 1] !== '=')) return match;
|
|
208
218
|
|
|
209
219
|
if (JS_KEYWORDS.has(id)) return match;
|
|
210
220
|
if (GLOBALS.has(id)) return match;
|
|
211
221
|
if (localScope.includes(id)) return match;
|
|
212
222
|
|
|
223
|
+
if (id.startsWith('__MU_LITERAL_')) return match;
|
|
224
|
+
|
|
213
225
|
if (isOptionsAPI) {
|
|
214
226
|
return `this.${id}`;
|
|
215
227
|
} else {
|
|
@@ -220,6 +232,11 @@ function processBindings(exp: string, bindings: string[] | undefined, localScope
|
|
|
220
232
|
|
|
221
233
|
return match;
|
|
222
234
|
});
|
|
235
|
+
|
|
236
|
+
// 3. Restore string literals
|
|
237
|
+
return processedExp.replace(/__MU_LITERAL_(\d+)__/g, (_, index) => {
|
|
238
|
+
return literals[parseInt(index, 10)];
|
|
239
|
+
});
|
|
223
240
|
}
|
|
224
241
|
|
|
225
242
|
// --- Generator ---
|