@hyperfixi/core 2.2.1 → 2.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 +8 -11
- package/dist/bundle-generator/index.js +25 -4
- package/dist/bundle-generator/index.mjs +25 -4
- package/dist/chunks/{bridge-BELRwj7r.js → bridge-Clbh_xAj.js} +2 -2
- package/dist/chunks/browser-modular-DIOxQqhV.js +2 -0
- package/dist/chunks/{index-lsDi6izr.js → index-DcxoRUBe.js} +2 -2
- package/dist/commands/index.js +36 -6
- package/dist/commands/index.mjs +36 -6
- package/dist/core/base-expression-evaluator.d.ts +4 -0
- package/dist/expressions/index.js +10 -0
- package/dist/expressions/index.mjs +10 -0
- package/dist/hyperfixi-classic-i18n.js +1 -1
- package/dist/hyperfixi-hx.js +1 -1
- package/dist/hyperfixi-hybrid-complete.js +1 -1
- package/dist/hyperfixi-minimal.js +1 -1
- package/dist/hyperfixi-multilingual.js +1 -1
- package/dist/hyperfixi-standard.js +1 -1
- package/dist/hyperfixi.js +1 -1
- package/dist/hyperfixi.mjs +1 -1
- package/dist/index.js +175 -79
- package/dist/index.min.js +1 -1
- package/dist/index.mjs +175 -79
- package/dist/lokascript-browser-classic-i18n.js +1 -1
- package/dist/lokascript-browser-minimal.js +1 -1
- package/dist/lokascript-browser-standard.js +1 -1
- package/dist/lokascript-browser.js +1 -1
- package/dist/lokascript-hybrid-complete.js +1 -1
- package/dist/lokascript-hybrid-hx.js +1 -1
- package/dist/lokascript-multilingual.js +1 -1
- package/dist/parser/full-parser.js +119 -70
- package/dist/parser/full-parser.mjs +119 -70
- package/dist/parser/hybrid/index.js +7 -0
- package/dist/parser/hybrid/index.mjs +7 -0
- package/dist/parser/hybrid/parser-core.js +7 -0
- package/dist/parser/hybrid/parser-core.mjs +7 -0
- package/dist/parser/hybrid/tokenizer.js +7 -0
- package/dist/parser/hybrid/tokenizer.mjs +7 -0
- package/dist/parser/hybrid-parser.js +7 -0
- package/dist/parser/hybrid-parser.mjs +7 -0
- package/dist/registry/index.js +10 -0
- package/dist/registry/index.mjs +10 -0
- package/package.json +1 -1
- package/dist/chunks/browser-modular-B7Bb-ABs.js +0 -2
|
@@ -456,7 +456,9 @@ function tokenize(input) {
|
|
|
456
456
|
prevToken.value === ',' ||
|
|
457
457
|
prevToken.value === ';';
|
|
458
458
|
const isAdjacentToPrev = prevToken && prevToken.end === tokenizer.position;
|
|
459
|
-
if (isCSSSelectorContext &&
|
|
459
|
+
if (isCSSSelectorContext &&
|
|
460
|
+
!isAdjacentToPrev &&
|
|
461
|
+
(isAlpha(peek(tokenizer)) || peek(tokenizer) === '{')) {
|
|
460
462
|
tokenizeCSSSelector(tokenizer);
|
|
461
463
|
continue;
|
|
462
464
|
}
|
|
@@ -689,6 +691,17 @@ function tokenizeCSSSelector(tokenizer) {
|
|
|
689
691
|
const start = tokenizer.position;
|
|
690
692
|
const prefix = advance(tokenizer);
|
|
691
693
|
let value = prefix;
|
|
694
|
+
if (tokenizer.position < tokenizer.input.length && tokenizer.input[tokenizer.position] === '{') {
|
|
695
|
+
value += advance(tokenizer);
|
|
696
|
+
while (tokenizer.position < tokenizer.input.length) {
|
|
697
|
+
const ch = tokenizer.input[tokenizer.position];
|
|
698
|
+
value += advance(tokenizer);
|
|
699
|
+
if (ch === '}')
|
|
700
|
+
break;
|
|
701
|
+
}
|
|
702
|
+
addToken(tokenizer, TokenKind.SELECTOR, value, start);
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
692
705
|
while (tokenizer.position < tokenizer.input.length) {
|
|
693
706
|
const char = tokenizer.input[tokenizer.position];
|
|
694
707
|
if (isAlphaNumeric(char) || char === '-' || char === '_' || char === ':') {
|
|
@@ -2379,33 +2392,14 @@ function parseTriggerCommand(ctx, identifierNode) {
|
|
|
2379
2392
|
});
|
|
2380
2393
|
}
|
|
2381
2394
|
}
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
const arg = allArgs[i];
|
|
2389
|
-
const argRecord = arg;
|
|
2390
|
-
const argValue = argRecord.name || argRecord.value;
|
|
2391
|
-
if ((arg.type === 'identifier' || arg.type === 'literal' || arg.type === 'keyword') &&
|
|
2392
|
-
(argValue === 'on' || argValue === 'to')) {
|
|
2393
|
-
operationIndex = i;
|
|
2394
|
-
operationKeyword = argValue;
|
|
2395
|
-
break;
|
|
2395
|
+
const finalArgs = [...allArgs];
|
|
2396
|
+
if (ctx.check('on') || ctx.check('to')) {
|
|
2397
|
+
const keyword = ctx.advance().value;
|
|
2398
|
+
finalArgs.push(ctx.createIdentifier(keyword));
|
|
2399
|
+
while (!isCommandBoundary(ctx)) {
|
|
2400
|
+
finalArgs.push(ctx.parsePrimary());
|
|
2396
2401
|
}
|
|
2397
2402
|
}
|
|
2398
|
-
const finalArgs = [];
|
|
2399
|
-
if (operationIndex === -1) {
|
|
2400
|
-
finalArgs.push(...allArgs);
|
|
2401
|
-
}
|
|
2402
|
-
else {
|
|
2403
|
-
const eventArgs = allArgs.slice(0, operationIndex);
|
|
2404
|
-
const targetArgs = allArgs.slice(operationIndex + 1);
|
|
2405
|
-
finalArgs.push(...eventArgs);
|
|
2406
|
-
finalArgs.push(ctx.createIdentifier(operationKeyword));
|
|
2407
|
-
finalArgs.push(...targetArgs);
|
|
2408
|
-
}
|
|
2409
2403
|
return CommandNodeBuilder.fromIdentifier(identifierNode)
|
|
2410
2404
|
.withArgs(...finalArgs)
|
|
2411
2405
|
.endingAt(ctx.getPosition())
|
|
@@ -3125,8 +3119,13 @@ function parseSwapCommand(ctx, identifierNode) {
|
|
|
3125
3119
|
|
|
3126
3120
|
function parseWaitCommand(ctx, commandToken) {
|
|
3127
3121
|
const args = [];
|
|
3128
|
-
|
|
3129
|
-
|
|
3122
|
+
const isExpressionStart = ctx.checkTimeExpression() ||
|
|
3123
|
+
ctx.checkLiteral() ||
|
|
3124
|
+
ctx.checkContextVar() ||
|
|
3125
|
+
ctx.check('(') ||
|
|
3126
|
+
(ctx.checkIdentifierLike() && !ctx.check('for') && !isCommandBoundary(ctx));
|
|
3127
|
+
if (isExpressionStart) {
|
|
3128
|
+
const timeExpr = ctx.parseExpression();
|
|
3130
3129
|
args.push(timeExpr);
|
|
3131
3130
|
return CommandNodeBuilder.from(commandToken)
|
|
3132
3131
|
.withArgs(...args)
|
|
@@ -3312,43 +3311,24 @@ function parsePropertyOfTarget(ctx, startPosition) {
|
|
|
3312
3311
|
return null;
|
|
3313
3312
|
const thePosition = ctx.savePosition();
|
|
3314
3313
|
ctx.advance();
|
|
3315
|
-
const
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
const propertyToken = ctx.advance();
|
|
3319
|
-
if (ctx.check(KEYWORDS.OF)) {
|
|
3320
|
-
ctx.advance();
|
|
3321
|
-
const targetToken = ctx.advance();
|
|
3322
|
-
const isIdSelector = targetToken.value.startsWith('#');
|
|
3323
|
-
return {
|
|
3324
|
-
type: 'propertyOfExpression',
|
|
3325
|
-
property: {
|
|
3326
|
-
type: 'identifier',
|
|
3327
|
-
name: propertyToken.value,
|
|
3328
|
-
start: propertyToken.start,
|
|
3329
|
-
end: propertyToken.end,
|
|
3330
|
-
},
|
|
3331
|
-
target: {
|
|
3332
|
-
type: isIdSelector ? 'idSelector' : 'cssSelector',
|
|
3333
|
-
value: targetToken.value,
|
|
3334
|
-
start: targetToken.start,
|
|
3335
|
-
end: targetToken.end,
|
|
3336
|
-
},
|
|
3337
|
-
start: startPosition,
|
|
3338
|
-
end: ctx.savePosition(),
|
|
3339
|
-
};
|
|
3340
|
-
}
|
|
3341
|
-
ctx.restorePosition(startPosition);
|
|
3314
|
+
const propertyExpr = ctx.parseExpression();
|
|
3315
|
+
if (!propertyExpr) {
|
|
3316
|
+
ctx.restorePosition(thePosition);
|
|
3342
3317
|
return null;
|
|
3343
3318
|
}
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
start:
|
|
3350
|
-
end:
|
|
3351
|
-
|
|
3319
|
+
const exprAny = propertyExpr;
|
|
3320
|
+
if (exprAny.type === 'binaryExpression' && exprAny.operator === KEYWORDS.OF) {
|
|
3321
|
+
const property = exprAny.left;
|
|
3322
|
+
const target = exprAny.right;
|
|
3323
|
+
return createPropertyOfExpression(property, target, {
|
|
3324
|
+
start: property.start ?? 0,
|
|
3325
|
+
end: target.end ?? 0,
|
|
3326
|
+
line: property.line ?? 1,
|
|
3327
|
+
column: property.column ?? 1,
|
|
3328
|
+
});
|
|
3329
|
+
}
|
|
3330
|
+
if (ctx.check(KEYWORDS.TO)) {
|
|
3331
|
+
return propertyExpr;
|
|
3352
3332
|
}
|
|
3353
3333
|
ctx.restorePosition(thePosition);
|
|
3354
3334
|
return null;
|
|
@@ -3707,6 +3687,71 @@ function parseFetchNakedNamedArgs(ctx) {
|
|
|
3707
3687
|
column: startPos.column,
|
|
3708
3688
|
};
|
|
3709
3689
|
}
|
|
3690
|
+
function findJsEndBoundary(ctx, startPos) {
|
|
3691
|
+
const input = ctx.getInputSlice(startPos);
|
|
3692
|
+
if (!input) {
|
|
3693
|
+
return startPos;
|
|
3694
|
+
}
|
|
3695
|
+
let i = 0;
|
|
3696
|
+
while (i < input.length) {
|
|
3697
|
+
const ch = input[i];
|
|
3698
|
+
if (ch === "'" || ch === '\u2019' || ch === '\u2018') {
|
|
3699
|
+
i++;
|
|
3700
|
+
while (i < input.length && input[i] !== ch) {
|
|
3701
|
+
if (input[i] === '\\')
|
|
3702
|
+
i++;
|
|
3703
|
+
i++;
|
|
3704
|
+
}
|
|
3705
|
+
i++;
|
|
3706
|
+
continue;
|
|
3707
|
+
}
|
|
3708
|
+
if (ch === '"') {
|
|
3709
|
+
i++;
|
|
3710
|
+
while (i < input.length && input[i] !== '"') {
|
|
3711
|
+
if (input[i] === '\\')
|
|
3712
|
+
i++;
|
|
3713
|
+
i++;
|
|
3714
|
+
}
|
|
3715
|
+
i++;
|
|
3716
|
+
continue;
|
|
3717
|
+
}
|
|
3718
|
+
if (ch === '`') {
|
|
3719
|
+
i++;
|
|
3720
|
+
while (i < input.length && input[i] !== '`') {
|
|
3721
|
+
if (input[i] === '\\')
|
|
3722
|
+
i++;
|
|
3723
|
+
i++;
|
|
3724
|
+
}
|
|
3725
|
+
i++;
|
|
3726
|
+
continue;
|
|
3727
|
+
}
|
|
3728
|
+
if (ch === '/' && i + 1 < input.length && input[i + 1] === '/') {
|
|
3729
|
+
i += 2;
|
|
3730
|
+
while (i < input.length && input[i] !== '\n')
|
|
3731
|
+
i++;
|
|
3732
|
+
continue;
|
|
3733
|
+
}
|
|
3734
|
+
if (ch === '/' && i + 1 < input.length && input[i + 1] === '*') {
|
|
3735
|
+
i += 2;
|
|
3736
|
+
while (i < input.length &&
|
|
3737
|
+
!(input[i] === '*' && i + 1 < input.length && input[i + 1] === '/'))
|
|
3738
|
+
i++;
|
|
3739
|
+
i += 2;
|
|
3740
|
+
continue;
|
|
3741
|
+
}
|
|
3742
|
+
if ((ch === 'e' || ch === 'E') &&
|
|
3743
|
+
i + 3 <= input.length &&
|
|
3744
|
+
input.slice(i, i + 3).toLowerCase() === 'end') {
|
|
3745
|
+
const before = i === 0 || !/[a-zA-Z0-9_]/.test(input[i - 1]);
|
|
3746
|
+
const after = i + 3 >= input.length || !/[a-zA-Z0-9_]/.test(input[i + 3]);
|
|
3747
|
+
if (before && after) {
|
|
3748
|
+
return startPos + i;
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
i++;
|
|
3752
|
+
}
|
|
3753
|
+
return startPos + input.length;
|
|
3754
|
+
}
|
|
3710
3755
|
function parseJsCommand(ctx, identifierNode) {
|
|
3711
3756
|
const parameters = [];
|
|
3712
3757
|
if (ctx.match('(')) {
|
|
@@ -3719,11 +3764,12 @@ function parseJsCommand(ctx, identifierNode) {
|
|
|
3719
3764
|
ctx.consume(')', 'Expected ) after js parameters');
|
|
3720
3765
|
}
|
|
3721
3766
|
const jsCodeStart = ctx.peek().start;
|
|
3722
|
-
|
|
3767
|
+
const jsCodeEnd = findJsEndBoundary(ctx, jsCodeStart);
|
|
3768
|
+
while (!ctx.isAtEnd() && !ctx.check(KEYWORDS.END)) {
|
|
3769
|
+
if (ctx.peek().start >= jsCodeEnd)
|
|
3770
|
+
break;
|
|
3723
3771
|
ctx.advance();
|
|
3724
3772
|
}
|
|
3725
|
-
const endToken = ctx.peek();
|
|
3726
|
-
const jsCodeEnd = endToken.start;
|
|
3727
3773
|
ctx.consume(KEYWORDS.END, 'Expected end after js code body');
|
|
3728
3774
|
const rawSlice = ctx.getInputSlice(jsCodeStart, jsCodeEnd);
|
|
3729
3775
|
const code = rawSlice.trim();
|
|
@@ -4626,7 +4672,12 @@ class Parser {
|
|
|
4626
4672
|
}
|
|
4627
4673
|
else {
|
|
4628
4674
|
const commandName = expr.name.toLowerCase();
|
|
4629
|
-
if (commandName === 'wait' &&
|
|
4675
|
+
if (commandName === 'wait' &&
|
|
4676
|
+
(this.checkTimeExpression() ||
|
|
4677
|
+
this.checkNumber() ||
|
|
4678
|
+
this.checkIdentifier() ||
|
|
4679
|
+
this.checkContextVar() ||
|
|
4680
|
+
this.check('('))) {
|
|
4630
4681
|
const command = this.createCommandFromIdentifier(expr);
|
|
4631
4682
|
if (command) {
|
|
4632
4683
|
expr = command;
|
|
@@ -5845,9 +5896,7 @@ class Parser {
|
|
|
5845
5896
|
while (!this.isAtEnd() && !this.check('end')) {
|
|
5846
5897
|
if (this.match('on')) {
|
|
5847
5898
|
const handlerPos = this.getPosition();
|
|
5848
|
-
const
|
|
5849
|
-
const eventName = eventToken.value;
|
|
5850
|
-
this.advance();
|
|
5899
|
+
const eventName = this.parseEventNameWithNamespace("Expected event name after 'on'");
|
|
5851
5900
|
const eventArgs = [];
|
|
5852
5901
|
if (this.check('(')) {
|
|
5853
5902
|
this.advance();
|
|
@@ -454,7 +454,9 @@ function tokenize(input) {
|
|
|
454
454
|
prevToken.value === ',' ||
|
|
455
455
|
prevToken.value === ';';
|
|
456
456
|
const isAdjacentToPrev = prevToken && prevToken.end === tokenizer.position;
|
|
457
|
-
if (isCSSSelectorContext &&
|
|
457
|
+
if (isCSSSelectorContext &&
|
|
458
|
+
!isAdjacentToPrev &&
|
|
459
|
+
(isAlpha(peek(tokenizer)) || peek(tokenizer) === '{')) {
|
|
458
460
|
tokenizeCSSSelector(tokenizer);
|
|
459
461
|
continue;
|
|
460
462
|
}
|
|
@@ -687,6 +689,17 @@ function tokenizeCSSSelector(tokenizer) {
|
|
|
687
689
|
const start = tokenizer.position;
|
|
688
690
|
const prefix = advance(tokenizer);
|
|
689
691
|
let value = prefix;
|
|
692
|
+
if (tokenizer.position < tokenizer.input.length && tokenizer.input[tokenizer.position] === '{') {
|
|
693
|
+
value += advance(tokenizer);
|
|
694
|
+
while (tokenizer.position < tokenizer.input.length) {
|
|
695
|
+
const ch = tokenizer.input[tokenizer.position];
|
|
696
|
+
value += advance(tokenizer);
|
|
697
|
+
if (ch === '}')
|
|
698
|
+
break;
|
|
699
|
+
}
|
|
700
|
+
addToken(tokenizer, TokenKind.SELECTOR, value, start);
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
690
703
|
while (tokenizer.position < tokenizer.input.length) {
|
|
691
704
|
const char = tokenizer.input[tokenizer.position];
|
|
692
705
|
if (isAlphaNumeric(char) || char === '-' || char === '_' || char === ':') {
|
|
@@ -2377,33 +2390,14 @@ function parseTriggerCommand(ctx, identifierNode) {
|
|
|
2377
2390
|
});
|
|
2378
2391
|
}
|
|
2379
2392
|
}
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
const arg = allArgs[i];
|
|
2387
|
-
const argRecord = arg;
|
|
2388
|
-
const argValue = argRecord.name || argRecord.value;
|
|
2389
|
-
if ((arg.type === 'identifier' || arg.type === 'literal' || arg.type === 'keyword') &&
|
|
2390
|
-
(argValue === 'on' || argValue === 'to')) {
|
|
2391
|
-
operationIndex = i;
|
|
2392
|
-
operationKeyword = argValue;
|
|
2393
|
-
break;
|
|
2393
|
+
const finalArgs = [...allArgs];
|
|
2394
|
+
if (ctx.check('on') || ctx.check('to')) {
|
|
2395
|
+
const keyword = ctx.advance().value;
|
|
2396
|
+
finalArgs.push(ctx.createIdentifier(keyword));
|
|
2397
|
+
while (!isCommandBoundary(ctx)) {
|
|
2398
|
+
finalArgs.push(ctx.parsePrimary());
|
|
2394
2399
|
}
|
|
2395
2400
|
}
|
|
2396
|
-
const finalArgs = [];
|
|
2397
|
-
if (operationIndex === -1) {
|
|
2398
|
-
finalArgs.push(...allArgs);
|
|
2399
|
-
}
|
|
2400
|
-
else {
|
|
2401
|
-
const eventArgs = allArgs.slice(0, operationIndex);
|
|
2402
|
-
const targetArgs = allArgs.slice(operationIndex + 1);
|
|
2403
|
-
finalArgs.push(...eventArgs);
|
|
2404
|
-
finalArgs.push(ctx.createIdentifier(operationKeyword));
|
|
2405
|
-
finalArgs.push(...targetArgs);
|
|
2406
|
-
}
|
|
2407
2401
|
return CommandNodeBuilder.fromIdentifier(identifierNode)
|
|
2408
2402
|
.withArgs(...finalArgs)
|
|
2409
2403
|
.endingAt(ctx.getPosition())
|
|
@@ -3123,8 +3117,13 @@ function parseSwapCommand(ctx, identifierNode) {
|
|
|
3123
3117
|
|
|
3124
3118
|
function parseWaitCommand(ctx, commandToken) {
|
|
3125
3119
|
const args = [];
|
|
3126
|
-
|
|
3127
|
-
|
|
3120
|
+
const isExpressionStart = ctx.checkTimeExpression() ||
|
|
3121
|
+
ctx.checkLiteral() ||
|
|
3122
|
+
ctx.checkContextVar() ||
|
|
3123
|
+
ctx.check('(') ||
|
|
3124
|
+
(ctx.checkIdentifierLike() && !ctx.check('for') && !isCommandBoundary(ctx));
|
|
3125
|
+
if (isExpressionStart) {
|
|
3126
|
+
const timeExpr = ctx.parseExpression();
|
|
3128
3127
|
args.push(timeExpr);
|
|
3129
3128
|
return CommandNodeBuilder.from(commandToken)
|
|
3130
3129
|
.withArgs(...args)
|
|
@@ -3310,43 +3309,24 @@ function parsePropertyOfTarget(ctx, startPosition) {
|
|
|
3310
3309
|
return null;
|
|
3311
3310
|
const thePosition = ctx.savePosition();
|
|
3312
3311
|
ctx.advance();
|
|
3313
|
-
const
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
const propertyToken = ctx.advance();
|
|
3317
|
-
if (ctx.check(KEYWORDS.OF)) {
|
|
3318
|
-
ctx.advance();
|
|
3319
|
-
const targetToken = ctx.advance();
|
|
3320
|
-
const isIdSelector = targetToken.value.startsWith('#');
|
|
3321
|
-
return {
|
|
3322
|
-
type: 'propertyOfExpression',
|
|
3323
|
-
property: {
|
|
3324
|
-
type: 'identifier',
|
|
3325
|
-
name: propertyToken.value,
|
|
3326
|
-
start: propertyToken.start,
|
|
3327
|
-
end: propertyToken.end,
|
|
3328
|
-
},
|
|
3329
|
-
target: {
|
|
3330
|
-
type: isIdSelector ? 'idSelector' : 'cssSelector',
|
|
3331
|
-
value: targetToken.value,
|
|
3332
|
-
start: targetToken.start,
|
|
3333
|
-
end: targetToken.end,
|
|
3334
|
-
},
|
|
3335
|
-
start: startPosition,
|
|
3336
|
-
end: ctx.savePosition(),
|
|
3337
|
-
};
|
|
3338
|
-
}
|
|
3339
|
-
ctx.restorePosition(startPosition);
|
|
3312
|
+
const propertyExpr = ctx.parseExpression();
|
|
3313
|
+
if (!propertyExpr) {
|
|
3314
|
+
ctx.restorePosition(thePosition);
|
|
3340
3315
|
return null;
|
|
3341
3316
|
}
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
start:
|
|
3348
|
-
end:
|
|
3349
|
-
|
|
3317
|
+
const exprAny = propertyExpr;
|
|
3318
|
+
if (exprAny.type === 'binaryExpression' && exprAny.operator === KEYWORDS.OF) {
|
|
3319
|
+
const property = exprAny.left;
|
|
3320
|
+
const target = exprAny.right;
|
|
3321
|
+
return createPropertyOfExpression(property, target, {
|
|
3322
|
+
start: property.start ?? 0,
|
|
3323
|
+
end: target.end ?? 0,
|
|
3324
|
+
line: property.line ?? 1,
|
|
3325
|
+
column: property.column ?? 1,
|
|
3326
|
+
});
|
|
3327
|
+
}
|
|
3328
|
+
if (ctx.check(KEYWORDS.TO)) {
|
|
3329
|
+
return propertyExpr;
|
|
3350
3330
|
}
|
|
3351
3331
|
ctx.restorePosition(thePosition);
|
|
3352
3332
|
return null;
|
|
@@ -3705,6 +3685,71 @@ function parseFetchNakedNamedArgs(ctx) {
|
|
|
3705
3685
|
column: startPos.column,
|
|
3706
3686
|
};
|
|
3707
3687
|
}
|
|
3688
|
+
function findJsEndBoundary(ctx, startPos) {
|
|
3689
|
+
const input = ctx.getInputSlice(startPos);
|
|
3690
|
+
if (!input) {
|
|
3691
|
+
return startPos;
|
|
3692
|
+
}
|
|
3693
|
+
let i = 0;
|
|
3694
|
+
while (i < input.length) {
|
|
3695
|
+
const ch = input[i];
|
|
3696
|
+
if (ch === "'" || ch === '\u2019' || ch === '\u2018') {
|
|
3697
|
+
i++;
|
|
3698
|
+
while (i < input.length && input[i] !== ch) {
|
|
3699
|
+
if (input[i] === '\\')
|
|
3700
|
+
i++;
|
|
3701
|
+
i++;
|
|
3702
|
+
}
|
|
3703
|
+
i++;
|
|
3704
|
+
continue;
|
|
3705
|
+
}
|
|
3706
|
+
if (ch === '"') {
|
|
3707
|
+
i++;
|
|
3708
|
+
while (i < input.length && input[i] !== '"') {
|
|
3709
|
+
if (input[i] === '\\')
|
|
3710
|
+
i++;
|
|
3711
|
+
i++;
|
|
3712
|
+
}
|
|
3713
|
+
i++;
|
|
3714
|
+
continue;
|
|
3715
|
+
}
|
|
3716
|
+
if (ch === '`') {
|
|
3717
|
+
i++;
|
|
3718
|
+
while (i < input.length && input[i] !== '`') {
|
|
3719
|
+
if (input[i] === '\\')
|
|
3720
|
+
i++;
|
|
3721
|
+
i++;
|
|
3722
|
+
}
|
|
3723
|
+
i++;
|
|
3724
|
+
continue;
|
|
3725
|
+
}
|
|
3726
|
+
if (ch === '/' && i + 1 < input.length && input[i + 1] === '/') {
|
|
3727
|
+
i += 2;
|
|
3728
|
+
while (i < input.length && input[i] !== '\n')
|
|
3729
|
+
i++;
|
|
3730
|
+
continue;
|
|
3731
|
+
}
|
|
3732
|
+
if (ch === '/' && i + 1 < input.length && input[i + 1] === '*') {
|
|
3733
|
+
i += 2;
|
|
3734
|
+
while (i < input.length &&
|
|
3735
|
+
!(input[i] === '*' && i + 1 < input.length && input[i + 1] === '/'))
|
|
3736
|
+
i++;
|
|
3737
|
+
i += 2;
|
|
3738
|
+
continue;
|
|
3739
|
+
}
|
|
3740
|
+
if ((ch === 'e' || ch === 'E') &&
|
|
3741
|
+
i + 3 <= input.length &&
|
|
3742
|
+
input.slice(i, i + 3).toLowerCase() === 'end') {
|
|
3743
|
+
const before = i === 0 || !/[a-zA-Z0-9_]/.test(input[i - 1]);
|
|
3744
|
+
const after = i + 3 >= input.length || !/[a-zA-Z0-9_]/.test(input[i + 3]);
|
|
3745
|
+
if (before && after) {
|
|
3746
|
+
return startPos + i;
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
i++;
|
|
3750
|
+
}
|
|
3751
|
+
return startPos + input.length;
|
|
3752
|
+
}
|
|
3708
3753
|
function parseJsCommand(ctx, identifierNode) {
|
|
3709
3754
|
const parameters = [];
|
|
3710
3755
|
if (ctx.match('(')) {
|
|
@@ -3717,11 +3762,12 @@ function parseJsCommand(ctx, identifierNode) {
|
|
|
3717
3762
|
ctx.consume(')', 'Expected ) after js parameters');
|
|
3718
3763
|
}
|
|
3719
3764
|
const jsCodeStart = ctx.peek().start;
|
|
3720
|
-
|
|
3765
|
+
const jsCodeEnd = findJsEndBoundary(ctx, jsCodeStart);
|
|
3766
|
+
while (!ctx.isAtEnd() && !ctx.check(KEYWORDS.END)) {
|
|
3767
|
+
if (ctx.peek().start >= jsCodeEnd)
|
|
3768
|
+
break;
|
|
3721
3769
|
ctx.advance();
|
|
3722
3770
|
}
|
|
3723
|
-
const endToken = ctx.peek();
|
|
3724
|
-
const jsCodeEnd = endToken.start;
|
|
3725
3771
|
ctx.consume(KEYWORDS.END, 'Expected end after js code body');
|
|
3726
3772
|
const rawSlice = ctx.getInputSlice(jsCodeStart, jsCodeEnd);
|
|
3727
3773
|
const code = rawSlice.trim();
|
|
@@ -4624,7 +4670,12 @@ class Parser {
|
|
|
4624
4670
|
}
|
|
4625
4671
|
else {
|
|
4626
4672
|
const commandName = expr.name.toLowerCase();
|
|
4627
|
-
if (commandName === 'wait' &&
|
|
4673
|
+
if (commandName === 'wait' &&
|
|
4674
|
+
(this.checkTimeExpression() ||
|
|
4675
|
+
this.checkNumber() ||
|
|
4676
|
+
this.checkIdentifier() ||
|
|
4677
|
+
this.checkContextVar() ||
|
|
4678
|
+
this.check('('))) {
|
|
4628
4679
|
const command = this.createCommandFromIdentifier(expr);
|
|
4629
4680
|
if (command) {
|
|
4630
4681
|
expr = command;
|
|
@@ -5843,9 +5894,7 @@ class Parser {
|
|
|
5843
5894
|
while (!this.isAtEnd() && !this.check('end')) {
|
|
5844
5895
|
if (this.match('on')) {
|
|
5845
5896
|
const handlerPos = this.getPosition();
|
|
5846
|
-
const
|
|
5847
|
-
const eventName = eventToken.value;
|
|
5848
|
-
this.advance();
|
|
5897
|
+
const eventName = this.parseEventNameWithNamespace("Expected event name after 'on'");
|
|
5849
5898
|
const eventArgs = [];
|
|
5850
5899
|
if (this.check('(')) {
|
|
5851
5900
|
this.advance();
|
|
@@ -155,6 +155,13 @@ function tokenize(code) {
|
|
|
155
155
|
tokens.push({ type: 'globalVar', value: code.slice(start, pos), pos: start });
|
|
156
156
|
continue;
|
|
157
157
|
}
|
|
158
|
+
if (code[pos] === '@') {
|
|
159
|
+
pos++;
|
|
160
|
+
while (pos < code.length && /[\w-]/.test(code[pos]))
|
|
161
|
+
pos++;
|
|
162
|
+
tokens.push({ type: 'selector', value: code.slice(start, pos), pos: start });
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
158
165
|
if (code[pos] === '#' || code[pos] === '.') {
|
|
159
166
|
if (code[pos] === '.') {
|
|
160
167
|
const afterDot = code.slice(pos + 1).match(/^(once|prevent|stop|debounce|throttle)\b/i);
|
|
@@ -153,6 +153,13 @@ function tokenize(code) {
|
|
|
153
153
|
tokens.push({ type: 'globalVar', value: code.slice(start, pos), pos: start });
|
|
154
154
|
continue;
|
|
155
155
|
}
|
|
156
|
+
if (code[pos] === '@') {
|
|
157
|
+
pos++;
|
|
158
|
+
while (pos < code.length && /[\w-]/.test(code[pos]))
|
|
159
|
+
pos++;
|
|
160
|
+
tokens.push({ type: 'selector', value: code.slice(start, pos), pos: start });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
156
163
|
if (code[pos] === '#' || code[pos] === '.') {
|
|
157
164
|
if (code[pos] === '.') {
|
|
158
165
|
const afterDot = code.slice(pos + 1).match(/^(once|prevent|stop|debounce|throttle)\b/i);
|
|
@@ -155,6 +155,13 @@ function tokenize(code) {
|
|
|
155
155
|
tokens.push({ type: 'globalVar', value: code.slice(start, pos), pos: start });
|
|
156
156
|
continue;
|
|
157
157
|
}
|
|
158
|
+
if (code[pos] === '@') {
|
|
159
|
+
pos++;
|
|
160
|
+
while (pos < code.length && /[\w-]/.test(code[pos]))
|
|
161
|
+
pos++;
|
|
162
|
+
tokens.push({ type: 'selector', value: code.slice(start, pos), pos: start });
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
158
165
|
if (code[pos] === '#' || code[pos] === '.') {
|
|
159
166
|
if (code[pos] === '.') {
|
|
160
167
|
const afterDot = code.slice(pos + 1).match(/^(once|prevent|stop|debounce|throttle)\b/i);
|
|
@@ -153,6 +153,13 @@ function tokenize(code) {
|
|
|
153
153
|
tokens.push({ type: 'globalVar', value: code.slice(start, pos), pos: start });
|
|
154
154
|
continue;
|
|
155
155
|
}
|
|
156
|
+
if (code[pos] === '@') {
|
|
157
|
+
pos++;
|
|
158
|
+
while (pos < code.length && /[\w-]/.test(code[pos]))
|
|
159
|
+
pos++;
|
|
160
|
+
tokens.push({ type: 'selector', value: code.slice(start, pos), pos: start });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
156
163
|
if (code[pos] === '#' || code[pos] === '.') {
|
|
157
164
|
if (code[pos] === '.') {
|
|
158
165
|
const afterDot = code.slice(pos + 1).match(/^(once|prevent|stop|debounce|throttle)\b/i);
|
|
@@ -155,6 +155,13 @@ function tokenize(code) {
|
|
|
155
155
|
tokens.push({ type: 'globalVar', value: code.slice(start, pos), pos: start });
|
|
156
156
|
continue;
|
|
157
157
|
}
|
|
158
|
+
if (code[pos] === '@') {
|
|
159
|
+
pos++;
|
|
160
|
+
while (pos < code.length && /[\w-]/.test(code[pos]))
|
|
161
|
+
pos++;
|
|
162
|
+
tokens.push({ type: 'selector', value: code.slice(start, pos), pos: start });
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
158
165
|
if (code[pos] === '#' || code[pos] === '.') {
|
|
159
166
|
if (code[pos] === '.') {
|
|
160
167
|
const afterDot = code.slice(pos + 1).match(/^(once|prevent|stop|debounce|throttle)\b/i);
|
|
@@ -153,6 +153,13 @@ function tokenize(code) {
|
|
|
153
153
|
tokens.push({ type: 'globalVar', value: code.slice(start, pos), pos: start });
|
|
154
154
|
continue;
|
|
155
155
|
}
|
|
156
|
+
if (code[pos] === '@') {
|
|
157
|
+
pos++;
|
|
158
|
+
while (pos < code.length && /[\w-]/.test(code[pos]))
|
|
159
|
+
pos++;
|
|
160
|
+
tokens.push({ type: 'selector', value: code.slice(start, pos), pos: start });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
156
163
|
if (code[pos] === '#' || code[pos] === '.') {
|
|
157
164
|
if (code[pos] === '.') {
|
|
158
165
|
const afterDot = code.slice(pos + 1).match(/^(once|prevent|stop|debounce|throttle)\b/i);
|
|
@@ -155,6 +155,13 @@ function tokenize(code) {
|
|
|
155
155
|
tokens.push({ type: 'globalVar', value: code.slice(start, pos), pos: start });
|
|
156
156
|
continue;
|
|
157
157
|
}
|
|
158
|
+
if (code[pos] === '@') {
|
|
159
|
+
pos++;
|
|
160
|
+
while (pos < code.length && /[\w-]/.test(code[pos]))
|
|
161
|
+
pos++;
|
|
162
|
+
tokens.push({ type: 'selector', value: code.slice(start, pos), pos: start });
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
158
165
|
if (code[pos] === '#' || code[pos] === '.') {
|
|
159
166
|
if (code[pos] === '.') {
|
|
160
167
|
const afterDot = code.slice(pos + 1).match(/^(once|prevent|stop|debounce|throttle)\b/i);
|
|
@@ -153,6 +153,13 @@ function tokenize(code) {
|
|
|
153
153
|
tokens.push({ type: 'globalVar', value: code.slice(start, pos), pos: start });
|
|
154
154
|
continue;
|
|
155
155
|
}
|
|
156
|
+
if (code[pos] === '@') {
|
|
157
|
+
pos++;
|
|
158
|
+
while (pos < code.length && /[\w-]/.test(code[pos]))
|
|
159
|
+
pos++;
|
|
160
|
+
tokens.push({ type: 'selector', value: code.slice(start, pos), pos: start });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
156
163
|
if (code[pos] === '#' || code[pos] === '.') {
|
|
157
164
|
if (code[pos] === '.') {
|
|
158
165
|
const afterDot = code.slice(pos + 1).match(/^(once|prevent|stop|debounce|throttle)\b/i);
|
package/dist/registry/index.js
CHANGED
|
@@ -1647,6 +1647,8 @@ class BaseExpressionEvaluator {
|
|
|
1647
1647
|
return this.evaluateIdSelector(node, context);
|
|
1648
1648
|
case 'attributeAccess':
|
|
1649
1649
|
return this.evaluateAttributeAccess(node, context);
|
|
1650
|
+
case 'asExpression':
|
|
1651
|
+
return this.evaluateAsExpression(node, context);
|
|
1650
1652
|
default:
|
|
1651
1653
|
throw new Error(`Unsupported AST node type for evaluation: ${node.type}`);
|
|
1652
1654
|
}
|
|
@@ -1932,6 +1934,14 @@ class BaseExpressionEvaluator {
|
|
|
1932
1934
|
}
|
|
1933
1935
|
return `@${node.attributeName}`;
|
|
1934
1936
|
}
|
|
1937
|
+
async evaluateAsExpression(node, context) {
|
|
1938
|
+
const value = await this.evaluate(node.expression, context);
|
|
1939
|
+
const asExpr = this.expressionRegistry.get('as');
|
|
1940
|
+
if (asExpr) {
|
|
1941
|
+
return asExpr.evaluate(context, value, node.targetType);
|
|
1942
|
+
}
|
|
1943
|
+
throw new Error(`Conversion type 'as' not registered`);
|
|
1944
|
+
}
|
|
1935
1945
|
getAvailableExpressions() {
|
|
1936
1946
|
return Array.from(this.expressionRegistry.keys());
|
|
1937
1947
|
}
|