olova 2.0.72 → 2.0.74
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/compiler.js +158 -148
- package/dist/compiler.js.map +1 -1
- package/dist/index.js +158 -148
- package/dist/index.js.map +1 -1
- package/dist/vite.js +158 -148
- package/dist/vite.js.map +1 -1
- package/package.json +2 -1
package/dist/compiler.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parse } from '@babel/parser';
|
|
1
|
+
import { parse, parseExpression } from '@babel/parser';
|
|
2
2
|
import generatorModule from '@babel/generator';
|
|
3
3
|
import traverseModule from '@babel/traverse';
|
|
4
4
|
import * as t from '@babel/types';
|
|
@@ -655,6 +655,33 @@ function parseModule(code) {
|
|
|
655
655
|
plugins: ["typescript", "jsx"]
|
|
656
656
|
});
|
|
657
657
|
}
|
|
658
|
+
function parseStandaloneExpression(code) {
|
|
659
|
+
return parseExpression(code, {
|
|
660
|
+
plugins: ["typescript", "jsx"]
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
function createExpressionFile(expression) {
|
|
664
|
+
return t.file(
|
|
665
|
+
t.program([
|
|
666
|
+
t.expressionStatement(t.cloneNode(expression, true))
|
|
667
|
+
])
|
|
668
|
+
);
|
|
669
|
+
}
|
|
670
|
+
function nodeHasJsx(node) {
|
|
671
|
+
if (!node) {
|
|
672
|
+
return false;
|
|
673
|
+
}
|
|
674
|
+
let found = false;
|
|
675
|
+
t.traverseFast(node, (child) => {
|
|
676
|
+
if (found) {
|
|
677
|
+
return;
|
|
678
|
+
}
|
|
679
|
+
if (t.isJSXElement(child) || t.isJSXFragment(child)) {
|
|
680
|
+
found = true;
|
|
681
|
+
}
|
|
682
|
+
});
|
|
683
|
+
return found;
|
|
684
|
+
}
|
|
658
685
|
function runCompilePhase(phase, fn) {
|
|
659
686
|
try {
|
|
660
687
|
return fn();
|
|
@@ -1022,25 +1049,7 @@ function collectScriptInfo(script) {
|
|
|
1022
1049
|
});
|
|
1023
1050
|
addNestedMutationNotify(ast, stateNames);
|
|
1024
1051
|
const nodeContainsJsx = (node) => {
|
|
1025
|
-
|
|
1026
|
-
return false;
|
|
1027
|
-
}
|
|
1028
|
-
let found = false;
|
|
1029
|
-
try {
|
|
1030
|
-
const generated = generate2(node).code;
|
|
1031
|
-
const code = t.isBlockStatement(node) ? `(() => ${generated})` : `(${generated})`;
|
|
1032
|
-
traverse(parseModule(code), {
|
|
1033
|
-
JSXElement() {
|
|
1034
|
-
found = true;
|
|
1035
|
-
},
|
|
1036
|
-
JSXFragment() {
|
|
1037
|
-
found = true;
|
|
1038
|
-
}
|
|
1039
|
-
});
|
|
1040
|
-
} catch {
|
|
1041
|
-
found = false;
|
|
1042
|
-
}
|
|
1043
|
-
return found;
|
|
1052
|
+
return nodeHasJsx(node);
|
|
1044
1053
|
};
|
|
1045
1054
|
traverse(ast, {
|
|
1046
1055
|
FunctionDeclaration(path) {
|
|
@@ -1062,12 +1071,8 @@ function collectScriptInfo(script) {
|
|
|
1062
1071
|
allSignalNames,
|
|
1063
1072
|
jsxFunctionNames
|
|
1064
1073
|
);
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
if (statement && t.isExpressionStatement(statement)) {
|
|
1068
|
-
path.replaceWith(statement.expression);
|
|
1069
|
-
path.skip();
|
|
1070
|
-
}
|
|
1074
|
+
path.replaceWith(parseStandaloneExpression(transformed.code));
|
|
1075
|
+
path.skip();
|
|
1071
1076
|
},
|
|
1072
1077
|
JSXFragment(path) {
|
|
1073
1078
|
const transformed = transformExpression(
|
|
@@ -1076,12 +1081,8 @@ function collectScriptInfo(script) {
|
|
|
1076
1081
|
allSignalNames,
|
|
1077
1082
|
jsxFunctionNames
|
|
1078
1083
|
);
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
if (statement && t.isExpressionStatement(statement)) {
|
|
1082
|
-
path.replaceWith(statement.expression);
|
|
1083
|
-
path.skip();
|
|
1084
|
-
}
|
|
1084
|
+
path.replaceWith(parseStandaloneExpression(transformed.code));
|
|
1085
|
+
path.skip();
|
|
1085
1086
|
}
|
|
1086
1087
|
});
|
|
1087
1088
|
if (needsGlobalRuntime) {
|
|
@@ -1115,7 +1116,7 @@ function collectScriptInfo(script) {
|
|
|
1115
1116
|
};
|
|
1116
1117
|
}
|
|
1117
1118
|
function transformExpression(expr, stateNames, allSignalNames, jsxFunctionNames = /* @__PURE__ */ new Set(), scopeId) {
|
|
1118
|
-
const ast =
|
|
1119
|
+
const ast = createExpressionFile(parseStandaloneExpression(expr));
|
|
1119
1120
|
let containsJsx = false;
|
|
1120
1121
|
const jsxScopeAttr = createScopeAttr(scopeId);
|
|
1121
1122
|
traverse(ast, {
|
|
@@ -1177,16 +1178,7 @@ function transformExpression(expr, stateNames, allSignalNames, jsxFunctionNames
|
|
|
1177
1178
|
const toStringCall = (input) => t.callExpression(t.identifier("__olovaToString"), [input]);
|
|
1178
1179
|
const escapeCall = (input) => t.callExpression(t.identifier("__olovaEscape"), [input]);
|
|
1179
1180
|
const expressionContainsJsx = (input) => {
|
|
1180
|
-
|
|
1181
|
-
traverse(parseModule(`(${generate2(input).code})`), {
|
|
1182
|
-
JSXElement() {
|
|
1183
|
-
found = true;
|
|
1184
|
-
},
|
|
1185
|
-
JSXFragment() {
|
|
1186
|
-
found = true;
|
|
1187
|
-
}
|
|
1188
|
-
});
|
|
1189
|
-
return found;
|
|
1181
|
+
return nodeHasJsx(input);
|
|
1190
1182
|
};
|
|
1191
1183
|
const expressionProducesHtml = (input) => {
|
|
1192
1184
|
if (!input) {
|
|
@@ -1196,19 +1188,18 @@ function transformExpression(expr, stateNames, allSignalNames, jsxFunctionNames
|
|
|
1196
1188
|
return true;
|
|
1197
1189
|
}
|
|
1198
1190
|
let found = false;
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1191
|
+
t.traverseFast(input, (child) => {
|
|
1192
|
+
if (found || !t.isCallExpression(child)) {
|
|
1193
|
+
return;
|
|
1194
|
+
}
|
|
1195
|
+
if (t.isIdentifier(child.callee) && jsxFunctionNames.has(child.callee.name)) {
|
|
1196
|
+
found = true;
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
if (t.isMemberExpression(child.callee) && t.isIdentifier(child.callee.property) && (child.callee.property.name === "map" || child.callee.property.name === "flatMap")) {
|
|
1200
|
+
const [firstArg] = child.arguments;
|
|
1201
|
+
if (t.isIdentifier(firstArg) && jsxFunctionNames.has(firstArg.name) || nodeContainsRenderableFunction(firstArg, jsxFunctionNames)) {
|
|
1202
1202
|
found = true;
|
|
1203
|
-
path.stop();
|
|
1204
|
-
return;
|
|
1205
|
-
}
|
|
1206
|
-
if (t.isMemberExpression(path.node.callee) && t.isIdentifier(path.node.callee.property) && (path.node.callee.property.name === "map" || path.node.callee.property.name === "flatMap")) {
|
|
1207
|
-
const [firstArg] = path.node.arguments;
|
|
1208
|
-
if (t.isIdentifier(firstArg) && jsxFunctionNames.has(firstArg.name) || nodeContainsRenderableFunction(firstArg, jsxFunctionNames)) {
|
|
1209
|
-
found = true;
|
|
1210
|
-
path.stop();
|
|
1211
|
-
}
|
|
1212
1203
|
}
|
|
1213
1204
|
}
|
|
1214
1205
|
});
|
|
@@ -1251,7 +1242,7 @@ function transformExpression(expr, stateNames, allSignalNames, jsxFunctionNames
|
|
|
1251
1242
|
return walkMember(name);
|
|
1252
1243
|
};
|
|
1253
1244
|
const transformEmbeddedJsxExpression = (input) => {
|
|
1254
|
-
const wrapped =
|
|
1245
|
+
const wrapped = createExpressionFile(input);
|
|
1255
1246
|
let containsNestedJsx = false;
|
|
1256
1247
|
traverse(wrapped, {
|
|
1257
1248
|
JSXElement(path) {
|
|
@@ -1434,17 +1425,16 @@ function transformExpression(expr, stateNames, allSignalNames, jsxFunctionNames
|
|
|
1434
1425
|
}
|
|
1435
1426
|
});
|
|
1436
1427
|
const statement = ast.program.body[0];
|
|
1437
|
-
|
|
1428
|
+
const expression = statement && t.isExpressionStatement(statement) ? statement.expression : null;
|
|
1429
|
+
if (!expression) {
|
|
1438
1430
|
return { code: expr.trim(), containsJsx };
|
|
1439
1431
|
}
|
|
1440
|
-
containsJsx = containsJsx || expressionProducesHtml(
|
|
1441
|
-
return { code: generate2(
|
|
1432
|
+
containsJsx = containsJsx || expressionProducesHtml(expression);
|
|
1433
|
+
return { code: generate2(expression).code, containsJsx };
|
|
1442
1434
|
}
|
|
1443
1435
|
function parseExpressionNode(expr) {
|
|
1444
1436
|
try {
|
|
1445
|
-
|
|
1446
|
-
const statement = ast.program.body[0];
|
|
1447
|
-
return statement && t.isExpressionStatement(statement) ? statement.expression : null;
|
|
1437
|
+
return parseStandaloneExpression(expr);
|
|
1448
1438
|
} catch {
|
|
1449
1439
|
return null;
|
|
1450
1440
|
}
|
|
@@ -1514,11 +1504,41 @@ function jsxToTemplateHtml(node) {
|
|
|
1514
1504
|
return "";
|
|
1515
1505
|
}
|
|
1516
1506
|
function replaceTemplateExpressions(input, replacer) {
|
|
1507
|
+
const rawTextTags = /* @__PURE__ */ new Set(["pre", "code", "textarea", "kbd", "samp"]);
|
|
1517
1508
|
let output = "";
|
|
1518
1509
|
let index = 0;
|
|
1519
1510
|
let inTag = false;
|
|
1520
1511
|
let tagQuote = null;
|
|
1521
1512
|
let tagBraceDepth = 0;
|
|
1513
|
+
let tagStart = -1;
|
|
1514
|
+
const rawTextStack = [];
|
|
1515
|
+
const updateRawTextStack = (rawTag) => {
|
|
1516
|
+
const trimmed = rawTag.trim();
|
|
1517
|
+
if (!trimmed || trimmed.startsWith("!") || trimmed.startsWith("?")) {
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
const closing = trimmed.startsWith("/");
|
|
1521
|
+
const content = closing ? trimmed.slice(1).trim() : trimmed;
|
|
1522
|
+
const selfClosing = /\/\s*$/.test(content);
|
|
1523
|
+
const nameMatch = content.match(/^([A-Za-z][A-Za-z0-9:-]*)/);
|
|
1524
|
+
if (!nameMatch) {
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
const tagName = nameMatch[1].toLowerCase();
|
|
1528
|
+
if (!rawTextTags.has(tagName)) {
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
if (closing) {
|
|
1532
|
+
const stackIndex = rawTextStack.lastIndexOf(tagName);
|
|
1533
|
+
if (stackIndex >= 0) {
|
|
1534
|
+
rawTextStack.splice(stackIndex, 1);
|
|
1535
|
+
}
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
if (!selfClosing) {
|
|
1539
|
+
rawTextStack.push(tagName);
|
|
1540
|
+
}
|
|
1541
|
+
};
|
|
1522
1542
|
while (index < input.length) {
|
|
1523
1543
|
const char = input[index];
|
|
1524
1544
|
const prev = index > 0 ? input[index - 1] : "";
|
|
@@ -1539,12 +1559,19 @@ function replaceTemplateExpressions(input, replacer) {
|
|
|
1539
1559
|
tagBraceDepth -= 1;
|
|
1540
1560
|
} else if (char === ">" && tagBraceDepth === 0) {
|
|
1541
1561
|
inTag = false;
|
|
1562
|
+
updateRawTextStack(input.slice(tagStart + 1, index));
|
|
1542
1563
|
}
|
|
1543
1564
|
index += 1;
|
|
1544
1565
|
continue;
|
|
1545
1566
|
}
|
|
1546
1567
|
if (char === "<") {
|
|
1547
1568
|
inTag = true;
|
|
1569
|
+
tagStart = index;
|
|
1570
|
+
output += char;
|
|
1571
|
+
index += 1;
|
|
1572
|
+
continue;
|
|
1573
|
+
}
|
|
1574
|
+
if (rawTextStack.length > 0) {
|
|
1548
1575
|
output += char;
|
|
1549
1576
|
index += 1;
|
|
1550
1577
|
continue;
|
|
@@ -1632,90 +1659,75 @@ function transformTemplate(template, stateNames, allSignalNames, jsxFunctionName
|
|
|
1632
1659
|
const ifBindings = [];
|
|
1633
1660
|
html = replaceTemplateExpressions(html, (expr) => {
|
|
1634
1661
|
try {
|
|
1635
|
-
const
|
|
1636
|
-
const
|
|
1637
|
-
if (t.
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1662
|
+
const node = parseStandaloneExpression(expr);
|
|
1663
|
+
const containsJsxNode = (n) => nodeHasJsx(n);
|
|
1664
|
+
if (t.isLogicalExpression(node) && node.operator === "&&") {
|
|
1665
|
+
if (containsJsxNode(node.right)) {
|
|
1666
|
+
const id = `i${counters.if++}`;
|
|
1667
|
+
const condition = generate2(node.left).code;
|
|
1668
|
+
const trueBranchHtml = jsxToTemplateHtml(node.right);
|
|
1669
|
+
ifBindings.push({
|
|
1670
|
+
id,
|
|
1671
|
+
expr: transformExpression(
|
|
1672
|
+
condition,
|
|
1673
|
+
stateNames,
|
|
1674
|
+
allSignalNames,
|
|
1675
|
+
jsxFunctionNames,
|
|
1676
|
+
scopeId
|
|
1677
|
+
).code,
|
|
1678
|
+
trueBranch: transformTemplate(
|
|
1679
|
+
trueBranchHtml,
|
|
1680
|
+
stateNames,
|
|
1681
|
+
allSignalNames,
|
|
1682
|
+
jsxFunctionNames,
|
|
1683
|
+
componentNames,
|
|
1684
|
+
counters,
|
|
1685
|
+
scopeId,
|
|
1686
|
+
devWarnings,
|
|
1687
|
+
filename
|
|
1688
|
+
)
|
|
1648
1689
|
});
|
|
1649
|
-
return
|
|
1650
|
-
}
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
allSignalNames,
|
|
1691
|
-
jsxFunctionNames,
|
|
1692
|
-
scopeId
|
|
1693
|
-
).code,
|
|
1694
|
-
trueBranch: transformTemplate(
|
|
1695
|
-
trueBranchHtml,
|
|
1696
|
-
stateNames,
|
|
1697
|
-
allSignalNames,
|
|
1698
|
-
jsxFunctionNames,
|
|
1699
|
-
componentNames,
|
|
1700
|
-
counters,
|
|
1701
|
-
scopeId,
|
|
1702
|
-
devWarnings,
|
|
1703
|
-
filename
|
|
1704
|
-
),
|
|
1705
|
-
falseBranch: transformTemplate(
|
|
1706
|
-
falseBranchHtml,
|
|
1707
|
-
stateNames,
|
|
1708
|
-
allSignalNames,
|
|
1709
|
-
jsxFunctionNames,
|
|
1710
|
-
componentNames,
|
|
1711
|
-
counters,
|
|
1712
|
-
scopeId,
|
|
1713
|
-
devWarnings,
|
|
1714
|
-
filename
|
|
1715
|
-
)
|
|
1716
|
-
});
|
|
1717
|
-
return `__O_IF_${id}__`;
|
|
1718
|
-
}
|
|
1690
|
+
return `__O_IF_${id}__`;
|
|
1691
|
+
}
|
|
1692
|
+
} else if (t.isConditionalExpression(node)) {
|
|
1693
|
+
if (containsJsxNode(node.consequent) || containsJsxNode(node.alternate)) {
|
|
1694
|
+
const id = `i${counters.if++}`;
|
|
1695
|
+
const condition = generate2(node.test).code;
|
|
1696
|
+
const trueBranchHtml = containsJsxNode(node.consequent) ? jsxToTemplateHtml(node.consequent) : `{${generate2(node.consequent).code}}`;
|
|
1697
|
+
const falseBranchHtml = containsJsxNode(node.alternate) ? jsxToTemplateHtml(node.alternate) : `{${generate2(node.alternate).code}}`;
|
|
1698
|
+
ifBindings.push({
|
|
1699
|
+
id,
|
|
1700
|
+
expr: transformExpression(
|
|
1701
|
+
condition,
|
|
1702
|
+
stateNames,
|
|
1703
|
+
allSignalNames,
|
|
1704
|
+
jsxFunctionNames,
|
|
1705
|
+
scopeId
|
|
1706
|
+
).code,
|
|
1707
|
+
trueBranch: transformTemplate(
|
|
1708
|
+
trueBranchHtml,
|
|
1709
|
+
stateNames,
|
|
1710
|
+
allSignalNames,
|
|
1711
|
+
jsxFunctionNames,
|
|
1712
|
+
componentNames,
|
|
1713
|
+
counters,
|
|
1714
|
+
scopeId,
|
|
1715
|
+
devWarnings,
|
|
1716
|
+
filename
|
|
1717
|
+
),
|
|
1718
|
+
falseBranch: transformTemplate(
|
|
1719
|
+
falseBranchHtml,
|
|
1720
|
+
stateNames,
|
|
1721
|
+
allSignalNames,
|
|
1722
|
+
jsxFunctionNames,
|
|
1723
|
+
componentNames,
|
|
1724
|
+
counters,
|
|
1725
|
+
scopeId,
|
|
1726
|
+
devWarnings,
|
|
1727
|
+
filename
|
|
1728
|
+
)
|
|
1729
|
+
});
|
|
1730
|
+
return `__O_IF_${id}__`;
|
|
1719
1731
|
}
|
|
1720
1732
|
}
|
|
1721
1733
|
} catch {
|
|
@@ -1861,9 +1873,7 @@ function transformTemplate(template, stateNames, allSignalNames, jsxFunctionName
|
|
|
1861
1873
|
const rawValue = node.attrs.fallback;
|
|
1862
1874
|
if (rawValue.startsWith("{") && rawValue.endsWith("}")) {
|
|
1863
1875
|
const fallbackExpression = rawValue.slice(1, -1).trim();
|
|
1864
|
-
const
|
|
1865
|
-
const fallbackStatement = fallbackAst.program.body[0];
|
|
1866
|
-
const fallbackNode = fallbackStatement && t.isExpressionStatement(fallbackStatement) ? fallbackStatement.expression : null;
|
|
1876
|
+
const fallbackNode = parseExpressionNode(fallbackExpression);
|
|
1867
1877
|
if (fallbackNode && (t.isJSXElement(fallbackNode) || t.isJSXFragment(fallbackNode))) {
|
|
1868
1878
|
slotFactories.push({
|
|
1869
1879
|
varName: `__slot_${id}_fallback`,
|