@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
- return exp.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
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
- return exp.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
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.20260228085805",
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
- return exp.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
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
- return exp.replace(/\b([a-zA-Z_$][\w$]*)\b/g, (match, id, offset, str) => {
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 ---