@xaendar/compiler 0.6.18 → 0.6.20
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/xaendar-compiler.es.js +105 -104
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Stack, indent } from "@xaendar/common";
|
|
2
|
-
import ts from "typescript";
|
|
2
|
+
import ts, { ScriptTarget, SyntaxKind, createSourceFile, forEachChild, isExpressionStatement, isIdentifier } from "typescript";
|
|
3
3
|
//#region ../packages/compiler/src/lexer/types/lexer-state.enum.ts
|
|
4
4
|
/**
|
|
5
5
|
* Represents the set of states the lexer can be in while processing template input.
|
|
@@ -196,7 +196,8 @@ function consumeAttributeValue(cursor, _context) {
|
|
|
196
196
|
tokens: [{
|
|
197
197
|
type: TokenType.ATTRIBUTE_VALUE,
|
|
198
198
|
parts: [value]
|
|
199
|
-
}]
|
|
199
|
+
}],
|
|
200
|
+
popState: true
|
|
200
201
|
};
|
|
201
202
|
break;
|
|
202
203
|
default:
|
|
@@ -384,12 +385,19 @@ function consumeEventParameter(cursor, _context) {
|
|
|
384
385
|
parts: [eventParameter]
|
|
385
386
|
});
|
|
386
387
|
cursor.advance();
|
|
388
|
+
cursor.skipSpaces();
|
|
387
389
|
eventParameter = "";
|
|
388
390
|
} else eventParameter = addCharacter$2(cursor, eventParameter);
|
|
389
391
|
break;
|
|
390
392
|
case 41:
|
|
391
393
|
cursor.advance();
|
|
392
|
-
|
|
394
|
+
if (!charDelimiter) {
|
|
395
|
+
retVal.tokens.push({
|
|
396
|
+
type: TokenType.EVENT_PAREMETER,
|
|
397
|
+
parts: [eventParameter]
|
|
398
|
+
});
|
|
399
|
+
read = false;
|
|
400
|
+
}
|
|
393
401
|
default: eventParameter = addCharacter$2(cursor, eventParameter);
|
|
394
402
|
}
|
|
395
403
|
return retVal;
|
|
@@ -651,29 +659,6 @@ function addCharacter(cursor, interpolation) {
|
|
|
651
659
|
return `${interpolation}${cursor.currentChar.value}`;
|
|
652
660
|
}
|
|
653
661
|
//#endregion
|
|
654
|
-
//#region ../packages/compiler/src/utils/chars.utils.ts
|
|
655
|
-
/**
|
|
656
|
-
* Checks whether a string contains at least one non-whitespace character.
|
|
657
|
-
*
|
|
658
|
-
* Whitespace characters include space, `\n`, `\r`, `\t`, `\f`, and `\v`.
|
|
659
|
-
*
|
|
660
|
-
* @param str - The string to check.
|
|
661
|
-
* @returns `true` if the string is not blank, `false` if it consists entirely of whitespace.
|
|
662
|
-
*/
|
|
663
|
-
function isNotBlank(str) {
|
|
664
|
-
return /\S/.test(str);
|
|
665
|
-
}
|
|
666
|
-
/**
|
|
667
|
-
* Checks whether the given ASCII code is a valid first character for a
|
|
668
|
-
* JavaScript identifier (`A`–`Z`, `a`–`z`, `$`, `_`).
|
|
669
|
-
*
|
|
670
|
-
* @param code - The ASCII code to evaluate.
|
|
671
|
-
* @returns `true` if the code can start a JS identifier, `false` otherwise.
|
|
672
|
-
*/
|
|
673
|
-
function isJSIdentifierStart(code) {
|
|
674
|
-
return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 36 || code === 95;
|
|
675
|
-
}
|
|
676
|
-
//#endregion
|
|
677
662
|
//#region ../packages/compiler/src/lexer/states/interpolation.state.ts
|
|
678
663
|
/**
|
|
679
664
|
* Dispatches between an expression and a literal interpolation after the opening `{`.
|
|
@@ -685,14 +670,9 @@ function isJSIdentifierStart(code) {
|
|
|
685
670
|
* @returns Transition result with the appropriate interpolation sub-state.
|
|
686
671
|
*/
|
|
687
672
|
function consumeInterpolation(cursor, _context) {
|
|
688
|
-
let retVal;
|
|
689
673
|
cursor.advance();
|
|
690
674
|
cursor.skipSpaces();
|
|
691
|
-
|
|
692
|
-
if (nextChar === 96) retVal = { state: LexerState.INTERPOLATION_LITERAL };
|
|
693
|
-
else if (isJSIdentifierStart(nextChar)) retVal = { state: LexerState.INTERPOLATION_EXPRESSION };
|
|
694
|
-
else throw new Error(`Unrecognized First Character ${String.fromCharCode(nextChar)} in interpolation`);
|
|
695
|
-
return retVal;
|
|
675
|
+
return cursor.peek() === 96 ? { state: LexerState.INTERPOLATION_LITERAL } : { state: LexerState.INTERPOLATION_EXPRESSION };
|
|
696
676
|
}
|
|
697
677
|
//#endregion
|
|
698
678
|
//#region ../packages/compiler/src/lexer/states/tag-body.state.ts
|
|
@@ -835,6 +815,19 @@ function consumeTagOpenName(cursor, _context) {
|
|
|
835
815
|
return retVal;
|
|
836
816
|
}
|
|
837
817
|
//#endregion
|
|
818
|
+
//#region ../packages/compiler/src/utils/chars.utils.ts
|
|
819
|
+
/**
|
|
820
|
+
* Checks whether a string contains at least one non-whitespace character.
|
|
821
|
+
*
|
|
822
|
+
* Whitespace characters include space, `\n`, `\r`, `\t`, `\f`, and `\v`.
|
|
823
|
+
*
|
|
824
|
+
* @param str - The string to check.
|
|
825
|
+
* @returns `true` if the string is not blank, `false` if it consists entirely of whitespace.
|
|
826
|
+
*/
|
|
827
|
+
function isNotBlank(str) {
|
|
828
|
+
return /\S/.test(str);
|
|
829
|
+
}
|
|
830
|
+
//#endregion
|
|
838
831
|
//#region ../packages/compiler/src/lexer/states/text.state.ts
|
|
839
832
|
/**
|
|
840
833
|
* Consumes plain text content, accumulating characters until a structural boundary
|
|
@@ -1308,7 +1301,7 @@ var ASTNodeType = /* @__PURE__ */ function(ASTNodeType) {
|
|
|
1308
1301
|
* // "'await' is not allowed inside template expressions."
|
|
1309
1302
|
*/
|
|
1310
1303
|
function validateExpression(source) {
|
|
1311
|
-
const expression =
|
|
1304
|
+
const expression = createSourceFile("expression.ts", `const x = ${source}`, ScriptTarget.ESNext, true).statements[0].declarationList.declarations[0].initializer;
|
|
1312
1305
|
const diagnostics = new Array();
|
|
1313
1306
|
visitNode(expression, 10, diagnostics);
|
|
1314
1307
|
if (diagnostics.length) throw new Error(diagnostics.reduce((acc, d) => `${acc}${d.message}\n`, ""));
|
|
@@ -1328,7 +1321,7 @@ function validateExpression(source) {
|
|
|
1328
1321
|
*/
|
|
1329
1322
|
function visitNode(node, offset, diagnostics) {
|
|
1330
1323
|
if (!isAllowedNode(node)) throw new Error(buildDisallowedMessage(node));
|
|
1331
|
-
|
|
1324
|
+
forEachChild(node, (child) => visitNode(child, offset, diagnostics));
|
|
1332
1325
|
if (diagnostics.length) throw new Error(diagnostics[0].message);
|
|
1333
1326
|
}
|
|
1334
1327
|
/**
|
|
@@ -1341,62 +1334,63 @@ function visitNode(node, offset, diagnostics) {
|
|
|
1341
1334
|
*/
|
|
1342
1335
|
function isAllowedNode(node) {
|
|
1343
1336
|
switch (node.kind) {
|
|
1344
|
-
case
|
|
1345
|
-
case
|
|
1346
|
-
case
|
|
1347
|
-
case
|
|
1348
|
-
case
|
|
1349
|
-
case
|
|
1350
|
-
case
|
|
1351
|
-
case
|
|
1352
|
-
case
|
|
1353
|
-
case
|
|
1354
|
-
case
|
|
1355
|
-
case
|
|
1356
|
-
case
|
|
1357
|
-
case
|
|
1358
|
-
case
|
|
1359
|
-
case
|
|
1360
|
-
case
|
|
1361
|
-
case
|
|
1362
|
-
case
|
|
1363
|
-
case
|
|
1364
|
-
case
|
|
1365
|
-
case
|
|
1366
|
-
case
|
|
1367
|
-
case
|
|
1368
|
-
case
|
|
1369
|
-
case
|
|
1370
|
-
case
|
|
1371
|
-
case
|
|
1372
|
-
case
|
|
1373
|
-
case
|
|
1374
|
-
case
|
|
1375
|
-
case
|
|
1376
|
-
case
|
|
1377
|
-
case
|
|
1378
|
-
case
|
|
1379
|
-
case
|
|
1380
|
-
case
|
|
1381
|
-
case
|
|
1382
|
-
case
|
|
1383
|
-
case
|
|
1384
|
-
case
|
|
1385
|
-
case
|
|
1386
|
-
case
|
|
1387
|
-
case
|
|
1388
|
-
case
|
|
1389
|
-
case
|
|
1390
|
-
case
|
|
1391
|
-
case
|
|
1392
|
-
case
|
|
1393
|
-
case
|
|
1394
|
-
case
|
|
1395
|
-
case
|
|
1396
|
-
case
|
|
1397
|
-
case
|
|
1398
|
-
case
|
|
1399
|
-
case
|
|
1337
|
+
case SyntaxKind.StringLiteral:
|
|
1338
|
+
case SyntaxKind.NumericLiteral:
|
|
1339
|
+
case SyntaxKind.BigIntLiteral:
|
|
1340
|
+
case SyntaxKind.TrueKeyword:
|
|
1341
|
+
case SyntaxKind.FalseKeyword:
|
|
1342
|
+
case SyntaxKind.NullKeyword:
|
|
1343
|
+
case SyntaxKind.UndefinedKeyword:
|
|
1344
|
+
case SyntaxKind.Identifier:
|
|
1345
|
+
case SyntaxKind.PropertyAccessExpression:
|
|
1346
|
+
case SyntaxKind.ElementAccessExpression:
|
|
1347
|
+
case SyntaxKind.CallExpression:
|
|
1348
|
+
case SyntaxKind.BinaryExpression:
|
|
1349
|
+
case SyntaxKind.EqualsEqualsToken:
|
|
1350
|
+
case SyntaxKind.EqualsEqualsEqualsToken:
|
|
1351
|
+
case SyntaxKind.ExclamationEqualsToken:
|
|
1352
|
+
case SyntaxKind.ExclamationEqualsEqualsToken:
|
|
1353
|
+
case SyntaxKind.LessThanToken:
|
|
1354
|
+
case SyntaxKind.LessThanEqualsToken:
|
|
1355
|
+
case SyntaxKind.GreaterThanToken:
|
|
1356
|
+
case SyntaxKind.GreaterThanEqualsToken:
|
|
1357
|
+
case SyntaxKind.PlusToken:
|
|
1358
|
+
case SyntaxKind.MinusToken:
|
|
1359
|
+
case SyntaxKind.AsteriskToken:
|
|
1360
|
+
case SyntaxKind.SlashToken:
|
|
1361
|
+
case SyntaxKind.PercentToken:
|
|
1362
|
+
case SyntaxKind.AsteriskAsteriskToken:
|
|
1363
|
+
case SyntaxKind.AmpersandAmpersandToken:
|
|
1364
|
+
case SyntaxKind.BarBarToken:
|
|
1365
|
+
case SyntaxKind.QuestionQuestionToken:
|
|
1366
|
+
case SyntaxKind.QuestionDotToken:
|
|
1367
|
+
case SyntaxKind.AmpersandToken:
|
|
1368
|
+
case SyntaxKind.BarToken:
|
|
1369
|
+
case SyntaxKind.CaretToken:
|
|
1370
|
+
case SyntaxKind.LessThanLessThanToken:
|
|
1371
|
+
case SyntaxKind.GreaterThanGreaterThanToken:
|
|
1372
|
+
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
|
|
1373
|
+
case SyntaxKind.InstanceOfKeyword:
|
|
1374
|
+
case SyntaxKind.InKeyword:
|
|
1375
|
+
case SyntaxKind.PrefixUnaryExpression:
|
|
1376
|
+
case SyntaxKind.PostfixUnaryExpression:
|
|
1377
|
+
case SyntaxKind.TypeOfExpression:
|
|
1378
|
+
case SyntaxKind.VoidExpression:
|
|
1379
|
+
case SyntaxKind.ConditionalExpression:
|
|
1380
|
+
case SyntaxKind.ParenthesizedExpression:
|
|
1381
|
+
case SyntaxKind.TemplateExpression:
|
|
1382
|
+
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
1383
|
+
case SyntaxKind.TemplateHead:
|
|
1384
|
+
case SyntaxKind.TemplateMiddle:
|
|
1385
|
+
case SyntaxKind.TemplateTail:
|
|
1386
|
+
case SyntaxKind.TemplateSpan:
|
|
1387
|
+
case SyntaxKind.ArrayLiteralExpression:
|
|
1388
|
+
case SyntaxKind.ObjectLiteralExpression:
|
|
1389
|
+
case SyntaxKind.PropertyAssignment:
|
|
1390
|
+
case SyntaxKind.ShorthandPropertyAssignment:
|
|
1391
|
+
case SyntaxKind.SpreadAssignment:
|
|
1392
|
+
case SyntaxKind.SpreadElement:
|
|
1393
|
+
case SyntaxKind.SyntaxList: return true;
|
|
1400
1394
|
default: return false;
|
|
1401
1395
|
}
|
|
1402
1396
|
}
|
|
@@ -1409,25 +1403,25 @@ function isAllowedNode(node) {
|
|
|
1409
1403
|
*/
|
|
1410
1404
|
function buildDisallowedMessage(node) {
|
|
1411
1405
|
switch (node.kind) {
|
|
1412
|
-
case
|
|
1413
|
-
case
|
|
1414
|
-
case
|
|
1415
|
-
case
|
|
1416
|
-
case
|
|
1417
|
-
case
|
|
1418
|
-
case
|
|
1419
|
-
default: return `'${
|
|
1406
|
+
case SyntaxKind.AwaitExpression: return "'await' is not allowed inside template expressions.";
|
|
1407
|
+
case SyntaxKind.YieldExpression: return "'yield' is not allowed inside template expressions.";
|
|
1408
|
+
case SyntaxKind.NewExpression: return "'new' is not allowed inside template expressions.";
|
|
1409
|
+
case SyntaxKind.ArrowFunction:
|
|
1410
|
+
case SyntaxKind.FunctionExpression: return "Function expressions are not allowed inside template expressions.";
|
|
1411
|
+
case SyntaxKind.TaggedTemplateExpression: return "Tagged template expressions are not allowed inside template expressions.";
|
|
1412
|
+
case SyntaxKind.BinaryExpression: return isAssignmentOperator(node.operatorToken.kind) ? "Assignments are not allowed inside template expressions. Use @const to declare local template variables instead." : `'${SyntaxKind[node.kind]}' is not allowed inside template expressions.`;
|
|
1413
|
+
default: return `'${SyntaxKind[node.kind]}' is not allowed inside template expressions.`;
|
|
1420
1414
|
}
|
|
1421
1415
|
}
|
|
1422
1416
|
/**
|
|
1423
|
-
* Returns `true` if the given {@link
|
|
1417
|
+
* Returns `true` if the given {@link SyntaxKind} is an assignment operator.
|
|
1424
1418
|
*
|
|
1425
1419
|
* Covers simple assignment (`=`) as well as all compound assignment operators
|
|
1426
1420
|
* (`+=`, `-=`, `&&=`, `||=`, `??=`, etc.) as defined by the TypeScript
|
|
1427
1421
|
* `FirstAssignment`–`LastAssignment` range.
|
|
1428
1422
|
*/
|
|
1429
1423
|
function isAssignmentOperator(kind) {
|
|
1430
|
-
return kind >=
|
|
1424
|
+
return kind >= SyntaxKind.FirstAssignment && kind <= SyntaxKind.LastAssignment;
|
|
1431
1425
|
}
|
|
1432
1426
|
//#endregion
|
|
1433
1427
|
//#region ../packages/compiler/src/parser/states/parse-interpolation.state.ts
|
|
@@ -1749,8 +1743,8 @@ function splitForSections(source) {
|
|
|
1749
1743
|
*/
|
|
1750
1744
|
function isValidIdentifier(name) {
|
|
1751
1745
|
if (!name.length) return false;
|
|
1752
|
-
const statement =
|
|
1753
|
-
return !!statement &&
|
|
1746
|
+
const statement = createSourceFile("__id.ts", name, ScriptTarget.ESNext, false).statements[0];
|
|
1747
|
+
return !!statement && isExpressionStatement(statement) && isIdentifier(statement.expression) && statement.expression.text === name;
|
|
1754
1748
|
}
|
|
1755
1749
|
//#endregion
|
|
1756
1750
|
//#region ../packages/compiler/src/parser/states/parse-if.state.ts
|
|
@@ -2327,7 +2321,14 @@ function mapAttributes(attributes, compilerContext) {
|
|
|
2327
2321
|
function mapEvents(events, compilerContext) {
|
|
2328
2322
|
compilerContext.addIdentifier("$event");
|
|
2329
2323
|
const mappedEvents = events?.map((event) => {
|
|
2330
|
-
|
|
2324
|
+
let parsedEventParameter = false;
|
|
2325
|
+
const parameters = event.parameters.map((parameter) => {
|
|
2326
|
+
const resolvedParameter = resolveExpression(parameter, compilerContext);
|
|
2327
|
+
if (!parsedEventParameter && resolvedParameter === "$event") {
|
|
2328
|
+
parsedEventParameter = true;
|
|
2329
|
+
return `($event) => ${resolvedParameter},`;
|
|
2330
|
+
} else return `() => ${resolvedParameter},`;
|
|
2331
|
+
});
|
|
2331
2332
|
return [
|
|
2332
2333
|
"{",
|
|
2333
2334
|
...indent([
|
|
@@ -2412,7 +2413,7 @@ function processFor(node, nodeName, parentNode, compilerContext) {
|
|
|
2412
2413
|
counterName
|
|
2413
2414
|
]
|
|
2414
2415
|
});
|
|
2415
|
-
mainBlock.push(`_for(${parentNode}, context, () => ${iterableExpr}, this.${forKey}.bind(this));`);
|
|
2416
|
+
mainBlock.push(`_for(${parentNode}, context, () => ${iterableExpr}, (${node.itemAlias}) => ${resolveExpression(node.trackExpression, forContext)}, this.${forKey}.bind(this));`);
|
|
2416
2417
|
return {
|
|
2417
2418
|
mainBlock,
|
|
2418
2419
|
fns: functionsToProcess
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xaendar/compiler",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.20",
|
|
4
4
|
"description": "A library for transpiling Xaendar Templates into JavaScript code",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"type": "module",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@xaendar/common": "0.6.
|
|
20
|
-
"@xaendar/types": "0.6.
|
|
19
|
+
"@xaendar/common": "0.6.20",
|
|
20
|
+
"@xaendar/types": "0.6.20",
|
|
21
21
|
"typescript": "^6.0.3"
|
|
22
22
|
}
|
|
23
23
|
}
|