@constela/start 1.2.16 → 1.2.18

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.
@@ -2462,8 +2462,31 @@ async function loadLayout2(layoutName, layoutsDir) {
2462
2462
  throw new Error(`Invalid JSON in layout file: ${layoutPath}`);
2463
2463
  }
2464
2464
  }
2465
- function applyLayout(pageView, layoutView) {
2466
- return replaceSlot(layoutView, pageView);
2465
+ function applyLayout(pageView, layoutView, namedSlots) {
2466
+ return replaceSlot(layoutView, pageView, namedSlots);
2467
+ }
2468
+ function extractMdxContentSlot2(loadedData, dataSourceName, routeParams) {
2469
+ const dataSource = loadedData[dataSourceName];
2470
+ if (dataSource && typeof dataSource === "object" && !Array.isArray(dataSource)) {
2471
+ if ("content" in dataSource) {
2472
+ return { "mdx-content": dataSource.content };
2473
+ }
2474
+ return void 0;
2475
+ }
2476
+ if (!Array.isArray(dataSource)) {
2477
+ return void 0;
2478
+ }
2479
+ const slug = routeParams["slug"] || "index";
2480
+ const item = dataSource.find(
2481
+ (entry) => typeof entry === "object" && entry !== null && "slug" in entry && entry.slug === slug
2482
+ );
2483
+ if (!item || typeof item !== "object" || !("content" in item)) {
2484
+ return void 0;
2485
+ }
2486
+ return { "mdx-content": item.content };
2487
+ }
2488
+ function isEventHandler(value) {
2489
+ return typeof value === "object" && value !== null && "event" in value && typeof value.event === "string" && "action" in value && typeof value.action === "string";
2467
2490
  }
2468
2491
  function normalizeProps(props) {
2469
2492
  if (!props || typeof props !== "object") {
@@ -2473,6 +2496,8 @@ function normalizeProps(props) {
2473
2496
  for (const [key, value] of Object.entries(props)) {
2474
2497
  if (value && typeof value === "object" && "expr" in value) {
2475
2498
  normalized[key] = value;
2499
+ } else if (isEventHandler(value)) {
2500
+ normalized[key] = value;
2476
2501
  } else if (value !== void 0 && value !== null) {
2477
2502
  normalized[key] = { expr: "lit", value };
2478
2503
  }
@@ -2579,18 +2604,25 @@ function substituteLayoutParamsInNode(node, layoutParams) {
2579
2604
  }
2580
2605
  return result;
2581
2606
  }
2582
- function replaceSlot(node, content) {
2607
+ function replaceSlot(node, content, namedSlots) {
2583
2608
  if (!node || typeof node !== "object") {
2584
2609
  return node;
2585
2610
  }
2586
2611
  const nodeObj = node;
2587
2612
  if (nodeObj["kind"] === "slot") {
2588
- return content;
2613
+ const slotName = nodeObj["name"];
2614
+ if (slotName && namedSlots && slotName in namedSlots) {
2615
+ return namedSlots[slotName];
2616
+ }
2617
+ if (!slotName || slotName === "default") {
2618
+ return content;
2619
+ }
2620
+ return node;
2589
2621
  }
2590
2622
  if (Array.isArray(nodeObj["children"])) {
2591
2623
  return {
2592
2624
  ...nodeObj,
2593
- children: nodeObj["children"].map((child) => replaceSlot(child, content))
2625
+ children: nodeObj["children"].map((child) => replaceSlot(child, content, namedSlots))
2594
2626
  };
2595
2627
  }
2596
2628
  return node;
@@ -2608,7 +2640,7 @@ async function collectLayoutChain(layoutName, layoutsDir, visited = /* @__PURE__
2608
2640
  }
2609
2641
  return chain;
2610
2642
  }
2611
- async function processLayouts(pageInfo, layoutsDir) {
2643
+ async function processLayouts(pageInfo, layoutsDir, routeParams = {}) {
2612
2644
  const layoutName = pageInfo.page.route?.layout;
2613
2645
  if (!layoutName || !layoutsDir) {
2614
2646
  return pageInfo;
@@ -2625,10 +2657,107 @@ async function processLayouts(pageInfo, layoutsDir) {
2625
2657
  };
2626
2658
  }
2627
2659
  }
2660
+ let mergedState = {};
2661
+ for (let i = layoutChain.length - 1; i >= 0; i--) {
2662
+ const layout = layoutChain[i];
2663
+ if (layout?.state) {
2664
+ mergedState = {
2665
+ ...mergedState,
2666
+ ...layout.state
2667
+ };
2668
+ }
2669
+ }
2670
+ if (pageInfo.page.state) {
2671
+ mergedState = {
2672
+ ...mergedState,
2673
+ ...pageInfo.page.state
2674
+ };
2675
+ }
2676
+ let mergedActionsMap = /* @__PURE__ */ new Map();
2677
+ for (let i = layoutChain.length - 1; i >= 0; i--) {
2678
+ const layout = layoutChain[i];
2679
+ if (layout?.actions && Array.isArray(layout.actions)) {
2680
+ for (const action of layout.actions) {
2681
+ const actionDef = action;
2682
+ mergedActionsMap.set(actionDef.name, action);
2683
+ }
2684
+ }
2685
+ }
2686
+ if (pageInfo.page.actions && Array.isArray(pageInfo.page.actions)) {
2687
+ for (const action of pageInfo.page.actions) {
2688
+ const actionDef = action;
2689
+ mergedActionsMap.set(actionDef.name, action);
2690
+ }
2691
+ }
2692
+ const mergedActions = Array.from(mergedActionsMap.values());
2693
+ let mergedLifecycle;
2694
+ for (let i = layoutChain.length - 1; i >= 0; i--) {
2695
+ const layout = layoutChain[i];
2696
+ if (layout?.lifecycle) {
2697
+ mergedLifecycle = {
2698
+ ...mergedLifecycle,
2699
+ ...layout.lifecycle
2700
+ };
2701
+ }
2702
+ }
2703
+ if (pageInfo.page.lifecycle) {
2704
+ mergedLifecycle = {
2705
+ ...mergedLifecycle,
2706
+ ...pageInfo.page.lifecycle
2707
+ };
2708
+ }
2709
+ let namedSlots;
2710
+ let effectiveRouteParams = routeParams;
2711
+ if (!routeParams["slug"] && pageInfo.page.route?.path) {
2712
+ const pathSegments = pageInfo.page.route.path.split("/").filter(Boolean);
2713
+ const lastSegment = pathSegments[pathSegments.length - 1];
2714
+ if (lastSegment && !lastSegment.startsWith(":")) {
2715
+ effectiveRouteParams = { ...routeParams, slug: lastSegment };
2716
+ }
2717
+ }
2718
+ if (pageInfo.loadedData && Object.keys(pageInfo.loadedData).length > 0) {
2719
+ for (const dataSourceName of Object.keys(pageInfo.loadedData)) {
2720
+ const slots = extractMdxContentSlot2(pageInfo.loadedData, dataSourceName, effectiveRouteParams);
2721
+ if (slots) {
2722
+ namedSlots = namedSlots ? { ...namedSlots, ...slots } : slots;
2723
+ break;
2724
+ }
2725
+ }
2726
+ }
2727
+ if (!namedSlots && pageInfo.resolvedImports && Object.keys(pageInfo.resolvedImports).length > 0) {
2728
+ for (const importName of Object.keys(pageInfo.resolvedImports)) {
2729
+ const slots = extractMdxContentSlot2(
2730
+ pageInfo.resolvedImports,
2731
+ importName,
2732
+ effectiveRouteParams
2733
+ );
2734
+ if (slots) {
2735
+ namedSlots = slots;
2736
+ break;
2737
+ }
2738
+ }
2739
+ }
2740
+ const pageWithImportData = pageInfo.page;
2741
+ if (!namedSlots && pageWithImportData.importData && Object.keys(pageWithImportData.importData).length > 0) {
2742
+ for (const importName of Object.keys(pageWithImportData.importData)) {
2743
+ const slots = extractMdxContentSlot2(
2744
+ pageWithImportData.importData,
2745
+ importName,
2746
+ effectiveRouteParams
2747
+ );
2748
+ if (slots) {
2749
+ namedSlots = slots;
2750
+ break;
2751
+ }
2752
+ }
2753
+ }
2628
2754
  let currentView = pageInfo.page.view;
2629
2755
  for (const layout of layoutChain) {
2630
2756
  const normalizedLayoutView = normalizeViewNode(structuredClone(layout.view));
2631
- currentView = applyLayout(currentView, normalizedLayoutView);
2757
+ currentView = applyLayout(currentView, normalizedLayoutView, namedSlots);
2758
+ }
2759
+ if (namedSlots && Object.keys(namedSlots).length > 0) {
2760
+ currentView = replaceSlot(currentView, currentView, namedSlots);
2632
2761
  }
2633
2762
  const layoutParams = pageInfo.page.route?.layoutParams;
2634
2763
  if (layoutParams && Object.keys(layoutParams).length > 0) {
@@ -2645,7 +2774,10 @@ async function processLayouts(pageInfo, layoutsDir) {
2645
2774
  page: {
2646
2775
  ...pageInfo.page,
2647
2776
  view: currentView,
2648
- route: updatedRoute
2777
+ route: updatedRoute,
2778
+ state: Object.keys(mergedState).length > 0 ? mergedState : void 0,
2779
+ actions: mergedActions.length > 0 ? mergedActions : void 0,
2780
+ lifecycle: mergedLifecycle
2649
2781
  }
2650
2782
  };
2651
2783
  return updatedPageInfo;
@@ -2773,13 +2905,29 @@ async function build2(options) {
2773
2905
  if (!staticPathsResult || staticPathsResult.length === 0) {
2774
2906
  continue;
2775
2907
  }
2776
- if (layoutsDir) {
2777
- pageInfo = await processLayouts(pageInfo, layoutsDir);
2778
- }
2779
2908
  for (const pathEntry of staticPathsResult) {
2780
2909
  const params = pathEntry.params;
2781
2910
  const outputPath = paramsToOutputPath(route.pattern, params, outDir);
2782
- const program = await convertToCompiledProgram(pageInfo);
2911
+ let boundPageInfo = pageInfo;
2912
+ if (pathEntry.data && pageInfo.page.getStaticPaths?.source) {
2913
+ const source = pageInfo.page.getStaticPaths.source;
2914
+ const sourceName = typeof source === "string" ? source : source.name;
2915
+ if (sourceName) {
2916
+ boundPageInfo = {
2917
+ ...pageInfo,
2918
+ loadedData: {
2919
+ ...pageInfo.loadedData,
2920
+ [sourceName]: pathEntry.data
2921
+ // Replace array with current item
2922
+ }
2923
+ };
2924
+ }
2925
+ }
2926
+ let processedPageInfo = boundPageInfo;
2927
+ if (layoutsDir) {
2928
+ processedPageInfo = await processLayouts(boundPageInfo, layoutsDir, params);
2929
+ }
2930
+ const program = await convertToCompiledProgram(processedPageInfo);
2783
2931
  const html = await renderPageToHtml(program, params, runtimePath, cssPath);
2784
2932
  await mkdir2(dirname5(outputPath), { recursive: true });
2785
2933
  await writeFile(outputPath, html, "utf-8");
@@ -2792,11 +2940,22 @@ async function build2(options) {
2792
2940
  routes.push(routePath);
2793
2941
  }
2794
2942
  } else {
2795
- const outputPath = getOutputPath(relPathFromRoutesDir, outDir);
2796
2943
  const loader = new JsonPageLoader(projectRoot, { routesDir: absoluteRoutesDir });
2797
2944
  let pageInfo = await loader.loadPage(relPathFromProjectRoot);
2945
+ let outputPath;
2946
+ if (pageInfo.page.route?.path) {
2947
+ const routePath = pageInfo.page.route.path;
2948
+ const relativePath = routePath.startsWith("/") ? routePath.slice(1) : routePath;
2949
+ if (relativePath === "" || relativePath === "/") {
2950
+ outputPath = join9(outDir, "index.html");
2951
+ } else {
2952
+ outputPath = join9(outDir, relativePath, "index.html");
2953
+ }
2954
+ } else {
2955
+ outputPath = getOutputPath(relPathFromRoutesDir, outDir);
2956
+ }
2798
2957
  if (layoutsDir) {
2799
- pageInfo = await processLayouts(pageInfo, layoutsDir);
2958
+ pageInfo = await processLayouts(pageInfo, layoutsDir, {});
2800
2959
  }
2801
2960
  const program = await convertToCompiledProgram(pageInfo);
2802
2961
  const html = await renderPageToHtml(program, {}, runtimePath, cssPath);
package/dist/cli/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createDevServer,
4
4
  loadConfig,
5
5
  resolveConfig
6
- } from "../chunk-RBEPA2Z2.js";
6
+ } from "../chunk-XOQABZYW.js";
7
7
  import "../chunk-PUTC5BCP.js";
8
8
 
9
9
  // src/cli/index.ts
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@ import {
23
23
  transformCsv,
24
24
  transformMdx,
25
25
  transformYaml
26
- } from "./chunk-RBEPA2Z2.js";
26
+ } from "./chunk-XOQABZYW.js";
27
27
  import {
28
28
  generateHydrationScript,
29
29
  renderPage,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constela/start",
3
- "version": "1.2.16",
3
+ "version": "1.2.18",
4
4
  "description": "Meta-framework for Constela applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -43,11 +43,11 @@
43
43
  "postcss": "^8.5.0",
44
44
  "@tailwindcss/postcss": "^4.0.0",
45
45
  "tailwindcss": "^4.0.0",
46
- "@constela/compiler": "0.7.1",
47
- "@constela/core": "0.7.0",
48
46
  "@constela/router": "8.0.0",
49
- "@constela/server": "3.0.1",
50
- "@constela/runtime": "0.10.2"
47
+ "@constela/core": "0.7.0",
48
+ "@constela/runtime": "0.10.2",
49
+ "@constela/compiler": "0.7.1",
50
+ "@constela/server": "3.0.1"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/mdast": "^4.0.4",