@constela/start 1.0.0 → 1.1.0
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/index.js +152 -20
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -460,6 +460,38 @@ function isCustomComponent(name) {
|
|
|
460
460
|
if (!name) return false;
|
|
461
461
|
return /^[A-Z]/.test(name);
|
|
462
462
|
}
|
|
463
|
+
var DISALLOWED_PATTERNS = [
|
|
464
|
+
/\bfunction\b/i,
|
|
465
|
+
/\b(eval|Function|setTimeout|setInterval)\b/,
|
|
466
|
+
/\bimport\b/,
|
|
467
|
+
/\brequire\b/,
|
|
468
|
+
/\bfetch\b/,
|
|
469
|
+
/\bwindow\b/,
|
|
470
|
+
/\bdocument\b/,
|
|
471
|
+
/\bglobal\b/,
|
|
472
|
+
/\bprocess\b/,
|
|
473
|
+
/\b__proto__\b/,
|
|
474
|
+
/\bconstructor\b/,
|
|
475
|
+
/\bprototype\b/
|
|
476
|
+
];
|
|
477
|
+
function isSafeLiteral(value) {
|
|
478
|
+
return !DISALLOWED_PATTERNS.some((pattern) => pattern.test(value));
|
|
479
|
+
}
|
|
480
|
+
function safeEvalLiteral(value) {
|
|
481
|
+
try {
|
|
482
|
+
return JSON.parse(value);
|
|
483
|
+
} catch {
|
|
484
|
+
}
|
|
485
|
+
if (!isSafeLiteral(value)) {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
try {
|
|
489
|
+
const fn = new Function(`return (${value});`);
|
|
490
|
+
return fn();
|
|
491
|
+
} catch {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
463
495
|
function parseAttributeValue(attr) {
|
|
464
496
|
if (attr.value === null) {
|
|
465
497
|
return lit(true);
|
|
@@ -474,6 +506,12 @@ function parseAttributeValue(attr) {
|
|
|
474
506
|
if (exprValue === "null") return lit(null);
|
|
475
507
|
const num = Number(exprValue);
|
|
476
508
|
if (!Number.isNaN(num)) return lit(num);
|
|
509
|
+
if (exprValue.startsWith("[") || exprValue.startsWith("{")) {
|
|
510
|
+
const parsed = safeEvalLiteral(exprValue);
|
|
511
|
+
if (parsed !== null && parsed !== void 0) {
|
|
512
|
+
return lit(parsed);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
477
515
|
return lit(exprValue);
|
|
478
516
|
}
|
|
479
517
|
return lit(null);
|
|
@@ -610,36 +648,130 @@ function transformJsxElement(node, ctx) {
|
|
|
610
648
|
const children = transformChildren(node.children, ctx);
|
|
611
649
|
return elementNode(name, props, children);
|
|
612
650
|
}
|
|
651
|
+
function substituteExpression(expr, props) {
|
|
652
|
+
const exprAny = expr;
|
|
653
|
+
if (exprAny.expr === "param") {
|
|
654
|
+
const paramExpr = expr;
|
|
655
|
+
const propValue = props[paramExpr.name];
|
|
656
|
+
if (!propValue) {
|
|
657
|
+
return { expr: "lit", value: null };
|
|
658
|
+
}
|
|
659
|
+
if (paramExpr.path && propValue.expr === "var") {
|
|
660
|
+
const varExpr = propValue;
|
|
661
|
+
return {
|
|
662
|
+
expr: "var",
|
|
663
|
+
name: varExpr.name,
|
|
664
|
+
path: paramExpr.path
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
return propValue;
|
|
668
|
+
}
|
|
669
|
+
if (expr.expr === "bin") {
|
|
670
|
+
const binExpr = expr;
|
|
671
|
+
return {
|
|
672
|
+
expr: "bin",
|
|
673
|
+
op: binExpr.op,
|
|
674
|
+
left: substituteExpression(binExpr.left, props),
|
|
675
|
+
right: substituteExpression(binExpr.right, props)
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
if (expr.expr === "not") {
|
|
679
|
+
const notExpr = expr;
|
|
680
|
+
return {
|
|
681
|
+
expr: "not",
|
|
682
|
+
operand: substituteExpression(notExpr.operand, props)
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
if (expr.expr === "cond") {
|
|
686
|
+
const condExpr = expr;
|
|
687
|
+
return {
|
|
688
|
+
expr: "cond",
|
|
689
|
+
if: substituteExpression(condExpr.if, props),
|
|
690
|
+
then: substituteExpression(condExpr.then, props),
|
|
691
|
+
else: substituteExpression(condExpr.else, props)
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
if (expr.expr === "get") {
|
|
695
|
+
const getExpr = expr;
|
|
696
|
+
return {
|
|
697
|
+
expr: "get",
|
|
698
|
+
base: substituteExpression(getExpr.base, props),
|
|
699
|
+
path: getExpr.path
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
return expr;
|
|
703
|
+
}
|
|
613
704
|
function applyComponentView(view, props, children) {
|
|
614
705
|
return substituteInNode(view, props, children);
|
|
615
706
|
}
|
|
616
707
|
function substituteInNode(node, props, children) {
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
708
|
+
switch (node.kind) {
|
|
709
|
+
case "each": {
|
|
710
|
+
const eachNode = node;
|
|
711
|
+
const result = {
|
|
712
|
+
kind: "each",
|
|
713
|
+
items: substituteExpression(eachNode.items, props),
|
|
714
|
+
as: eachNode.as,
|
|
715
|
+
body: substituteInNode(eachNode.body, props, children)
|
|
716
|
+
};
|
|
717
|
+
if (eachNode.index) {
|
|
718
|
+
result.index = eachNode.index;
|
|
719
|
+
}
|
|
720
|
+
if (eachNode.key) {
|
|
721
|
+
result.key = substituteExpression(eachNode.key, props);
|
|
623
722
|
}
|
|
723
|
+
return result;
|
|
624
724
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
725
|
+
case "text": {
|
|
726
|
+
const textNode2 = node;
|
|
727
|
+
return {
|
|
728
|
+
kind: "text",
|
|
729
|
+
value: substituteExpression(textNode2.value, props)
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
case "if": {
|
|
733
|
+
const ifNode = node;
|
|
734
|
+
const result = {
|
|
735
|
+
kind: "if",
|
|
736
|
+
condition: substituteExpression(ifNode.condition, props),
|
|
737
|
+
then: substituteInNode(ifNode.then, props, children)
|
|
738
|
+
};
|
|
739
|
+
if (ifNode.else) {
|
|
740
|
+
result.else = substituteInNode(ifNode.else, props, children);
|
|
741
|
+
}
|
|
742
|
+
return result;
|
|
743
|
+
}
|
|
744
|
+
case "element": {
|
|
745
|
+
const elem = node;
|
|
746
|
+
const newProps = {};
|
|
747
|
+
if (elem.props) {
|
|
748
|
+
for (const [key, value] of Object.entries(elem.props)) {
|
|
749
|
+
newProps[key] = substituteExpression(value, props);
|
|
633
750
|
}
|
|
634
751
|
}
|
|
752
|
+
let newChildren;
|
|
753
|
+
if (elem.children) {
|
|
754
|
+
newChildren = [];
|
|
755
|
+
for (const child of elem.children) {
|
|
756
|
+
if (child.kind === "slot") {
|
|
757
|
+
newChildren.push(...children);
|
|
758
|
+
} else {
|
|
759
|
+
newChildren.push(substituteInNode(child, props, children));
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
return elementNode(
|
|
764
|
+
elem.tag,
|
|
765
|
+
Object.keys(newProps).length > 0 ? newProps : void 0,
|
|
766
|
+
newChildren && newChildren.length > 0 ? newChildren : void 0
|
|
767
|
+
);
|
|
635
768
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
769
|
+
case "markdown":
|
|
770
|
+
case "code":
|
|
771
|
+
return node;
|
|
772
|
+
default:
|
|
773
|
+
return node;
|
|
641
774
|
}
|
|
642
|
-
return node;
|
|
643
775
|
}
|
|
644
776
|
function transformChildren(children, ctx) {
|
|
645
777
|
const result = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@constela/start",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Meta-framework for Constela applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"remark-parse": "^11.0.0",
|
|
40
40
|
"unified": "^11.0.0",
|
|
41
41
|
"vite": "^6.0.0",
|
|
42
|
-
"@constela/compiler": "0.
|
|
43
|
-
"@constela/
|
|
44
|
-
"@constela/
|
|
45
|
-
"@constela/
|
|
46
|
-
"@constela/
|
|
42
|
+
"@constela/compiler": "0.7.0",
|
|
43
|
+
"@constela/server": "3.0.0",
|
|
44
|
+
"@constela/runtime": "0.9.2",
|
|
45
|
+
"@constela/router": "7.0.0",
|
|
46
|
+
"@constela/core": "0.7.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/mdast": "^4.0.4",
|