meno-core 1.0.19 → 1.0.21
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/.claude/settings.local.json +7 -0
- package/lib/client/core/ComponentBuilder.test.ts +68 -56
- package/lib/client/core/ComponentBuilder.ts +6 -4
- package/lib/client/core/builders/embedBuilder.ts +10 -1
- package/lib/client/core/builders/index.ts +6 -2
- package/lib/client/core/builders/{cmsListBuilder.ts → listBuilder.ts} +227 -95
- package/lib/client/responsiveStyleResolver.test.ts +12 -12
- package/lib/client/responsiveStyleResolver.ts +19 -7
- package/lib/client/routing/Router.tsx +35 -7
- package/lib/client/templateEngine.test.ts +126 -0
- package/lib/client/templateEngine.ts +53 -13
- package/lib/server/jsonLoader.test.ts +4 -1
- package/lib/server/jsonLoader.ts +64 -15
- package/lib/server/services/configService.ts +68 -13
- package/lib/server/ssr/attributeBuilder.ts +8 -0
- package/lib/server/ssr/index.ts +1 -1
- package/lib/server/ssr/ssrRenderer.ts +245 -111
- package/lib/server/ssrRenderer.test.ts +197 -3
- package/lib/server/validateStyleCoverage.ts +14 -17
- package/lib/shared/breakpoints.test.ts +210 -23
- package/lib/shared/breakpoints.ts +124 -17
- package/lib/shared/constants.test.ts +1 -1
- package/lib/shared/constants.ts +5 -1
- package/lib/shared/cssGeneration.test.ts +17 -0
- package/lib/shared/cssGeneration.ts +49 -12
- package/lib/shared/index.ts +3 -0
- package/lib/shared/itemTemplateUtils.test.ts +44 -2
- package/lib/shared/itemTemplateUtils.ts +15 -2
- package/lib/shared/nodeUtils.ts +23 -4
- package/lib/shared/registry/BaseNodeTypeRegistry.test.ts +2 -2
- package/lib/shared/registry/nodeTypes/ListNodeType.ts +186 -0
- package/lib/shared/registry/nodeTypes/SlotMarkerType.ts +6 -0
- package/lib/shared/registry/nodeTypes/index.ts +6 -5
- package/lib/shared/responsiveScaling.test.ts +87 -0
- package/lib/shared/responsiveScaling.ts +33 -29
- package/lib/shared/responsiveStyleUtils.test.ts +7 -7
- package/lib/shared/responsiveStyleUtils.ts +22 -16
- package/lib/shared/styleNodeUtils.ts +5 -5
- package/lib/shared/styleValueRegistry.ts +60 -5
- package/lib/shared/tree/PathBuilder.ts +3 -3
- package/lib/shared/treePathUtils.ts +7 -5
- package/lib/shared/types/cms.ts +4 -57
- package/lib/shared/types/components.ts +45 -4
- package/lib/shared/types/index.ts +13 -0
- package/lib/shared/utilityClassConfig.ts +14 -0
- package/lib/shared/utilityClassMapper.ts +43 -2
- package/lib/shared/validation/propValidator.ts +9 -1
- package/lib/shared/validation/schemas.ts +60 -14
- package/package.json +1 -1
- package/lib/shared/registry/nodeTypes/CMSListNodeType.ts +0 -109
|
@@ -2,7 +2,7 @@ import { test, expect, describe, beforeEach, mock } from "bun:test";
|
|
|
2
2
|
import { ComponentBuilder } from "./ComponentBuilder";
|
|
3
3
|
import { ComponentRegistry } from "../componentRegistry";
|
|
4
4
|
import { ElementRegistry } from "../elementRegistry";
|
|
5
|
-
import type { ComponentNode,
|
|
5
|
+
import type { ComponentNode, ListNode, CMSItem } from "../../shared/types";
|
|
6
6
|
import { NODE_TYPE } from "../../shared/constants";
|
|
7
7
|
import { createMockElementRegistry } from "../../test-utils/mocks";
|
|
8
8
|
|
|
@@ -677,7 +677,7 @@ describe("ComponentBuilder", () => {
|
|
|
677
677
|
});
|
|
678
678
|
});
|
|
679
679
|
|
|
680
|
-
describe("buildComponent -
|
|
680
|
+
describe("buildComponent - List (Collection Mode)", () => {
|
|
681
681
|
// Helper to create mock CMS items
|
|
682
682
|
const createMockCMSItems = (count: number): CMSItem[] => {
|
|
683
683
|
return Array.from({ length: count }, (_, i) => ({
|
|
@@ -688,21 +688,22 @@ describe("ComponentBuilder", () => {
|
|
|
688
688
|
}));
|
|
689
689
|
};
|
|
690
690
|
|
|
691
|
-
// Helper to create a
|
|
692
|
-
const
|
|
693
|
-
|
|
691
|
+
// Helper to create a List node with sourceType: 'collection'
|
|
692
|
+
const createCollectionListNode = (
|
|
693
|
+
source: string,
|
|
694
694
|
children: ComponentNode[],
|
|
695
695
|
options: { limit?: number; offset?: number } = {}
|
|
696
|
-
):
|
|
697
|
-
type: NODE_TYPE.
|
|
698
|
-
collection,
|
|
696
|
+
): ListNode => ({
|
|
697
|
+
type: NODE_TYPE.LIST,
|
|
698
|
+
sourceType: 'collection',
|
|
699
|
+
source,
|
|
699
700
|
children,
|
|
700
701
|
...options,
|
|
701
702
|
});
|
|
702
703
|
|
|
703
704
|
test("should render children for each CMS item", () => {
|
|
704
705
|
const items = createMockCMSItems(3);
|
|
705
|
-
const node =
|
|
706
|
+
const node = createCollectionListNode("posts", [
|
|
706
707
|
{ type: "node", tag: "div", children: ["Item content"] },
|
|
707
708
|
]);
|
|
708
709
|
|
|
@@ -721,7 +722,7 @@ describe("ComponentBuilder", () => {
|
|
|
721
722
|
|
|
722
723
|
test("should add data-cms-item-index attribute to each item wrapper", () => {
|
|
723
724
|
const items = createMockCMSItems(3);
|
|
724
|
-
const node =
|
|
725
|
+
const node = createCollectionListNode("posts", [
|
|
725
726
|
{ type: "node", tag: "div", children: ["Item content"] },
|
|
726
727
|
]);
|
|
727
728
|
|
|
@@ -749,7 +750,7 @@ describe("ComponentBuilder", () => {
|
|
|
749
750
|
const items: CMSItem[] = [
|
|
750
751
|
{ _id: "1", _slug: "test", title: "Hello World" },
|
|
751
752
|
];
|
|
752
|
-
const node =
|
|
753
|
+
const node = createCollectionListNode("posts", [
|
|
753
754
|
{ type: "node", tag: "h1", children: ["{{item.title}}"] },
|
|
754
755
|
]);
|
|
755
756
|
|
|
@@ -765,7 +766,7 @@ describe("ComponentBuilder", () => {
|
|
|
765
766
|
|
|
766
767
|
test("should interpolate {{itemIndex}}, {{itemFirst}}, {{itemLast}}", () => {
|
|
767
768
|
const items = createMockCMSItems(3);
|
|
768
|
-
const node =
|
|
769
|
+
const node = createCollectionListNode("posts", [
|
|
769
770
|
{ type: "node", tag: "span", children: ["Index: {{itemIndex}}, First: {{itemFirst}}, Last: {{itemLast}}"] },
|
|
770
771
|
]);
|
|
771
772
|
|
|
@@ -782,7 +783,7 @@ describe("ComponentBuilder", () => {
|
|
|
782
783
|
});
|
|
783
784
|
|
|
784
785
|
test("should show empty state when no items", () => {
|
|
785
|
-
const node =
|
|
786
|
+
const node = createCollectionListNode("posts", [
|
|
786
787
|
{ type: "node", tag: "div", children: ["Item"] },
|
|
787
788
|
]);
|
|
788
789
|
|
|
@@ -799,7 +800,7 @@ describe("ComponentBuilder", () => {
|
|
|
799
800
|
});
|
|
800
801
|
|
|
801
802
|
test("should show empty state when collection not in map", () => {
|
|
802
|
-
const node =
|
|
803
|
+
const node = createCollectionListNode("posts", [
|
|
803
804
|
{ type: "node", tag: "div", children: ["Item"] },
|
|
804
805
|
]);
|
|
805
806
|
|
|
@@ -814,7 +815,7 @@ describe("ComponentBuilder", () => {
|
|
|
814
815
|
|
|
815
816
|
test("should apply limit to items", () => {
|
|
816
817
|
const items = createMockCMSItems(5);
|
|
817
|
-
const node =
|
|
818
|
+
const node = createCollectionListNode("posts", [
|
|
818
819
|
{ type: "node", tag: "div", children: ["Item"] },
|
|
819
820
|
], { limit: 2 });
|
|
820
821
|
|
|
@@ -831,7 +832,7 @@ describe("ComponentBuilder", () => {
|
|
|
831
832
|
|
|
832
833
|
test("should apply offset to items", () => {
|
|
833
834
|
const items = createMockCMSItems(5);
|
|
834
|
-
const node =
|
|
835
|
+
const node = createCollectionListNode("posts", [
|
|
835
836
|
{ type: "node", tag: "div", children: ["Item"] },
|
|
836
837
|
], { offset: 2 });
|
|
837
838
|
|
|
@@ -848,7 +849,7 @@ describe("ComponentBuilder", () => {
|
|
|
848
849
|
|
|
849
850
|
test("should apply both limit and offset", () => {
|
|
850
851
|
const items = createMockCMSItems(5);
|
|
851
|
-
const node =
|
|
852
|
+
const node = createCollectionListNode("posts", [
|
|
852
853
|
{ type: "node", tag: "div", children: ["Item"] },
|
|
853
854
|
], { offset: 1, limit: 2 });
|
|
854
855
|
|
|
@@ -870,9 +871,10 @@ describe("ComponentBuilder", () => {
|
|
|
870
871
|
{ _id: "3", _slug: "post3", featured: true, title: "Another Featured" },
|
|
871
872
|
{ _id: "4", _slug: "post4", featured: false, title: "Regular Post 2" },
|
|
872
873
|
];
|
|
873
|
-
const node:
|
|
874
|
-
type: NODE_TYPE.
|
|
875
|
-
|
|
874
|
+
const node: ListNode = {
|
|
875
|
+
type: NODE_TYPE.LIST,
|
|
876
|
+
sourceType: 'collection',
|
|
877
|
+
source: "posts",
|
|
876
878
|
filter: { featured: true },
|
|
877
879
|
children: [{ type: "node", tag: "div", children: ["Item"] }],
|
|
878
880
|
};
|
|
@@ -895,9 +897,10 @@ describe("ComponentBuilder", () => {
|
|
|
895
897
|
{ _id: "3", _slug: "post3", price: 200, title: "Expensive 2" },
|
|
896
898
|
{ _id: "4", _slug: "post4", price: 75, title: "Mid" },
|
|
897
899
|
];
|
|
898
|
-
const node:
|
|
899
|
-
type: NODE_TYPE.
|
|
900
|
-
|
|
900
|
+
const node: ListNode = {
|
|
901
|
+
type: NODE_TYPE.LIST,
|
|
902
|
+
sourceType: 'collection',
|
|
903
|
+
source: "posts",
|
|
901
904
|
filter: { field: "price", operator: "gt", value: 100 },
|
|
902
905
|
children: [{ type: "node", tag: "div", children: ["Item"] }],
|
|
903
906
|
};
|
|
@@ -919,9 +922,10 @@ describe("ComponentBuilder", () => {
|
|
|
919
922
|
{ _id: "2", _slug: "post2", category: "news", title: "News Post" },
|
|
920
923
|
{ _id: "3", _slug: "post3", category: "tech", title: "Tech Post 2" },
|
|
921
924
|
];
|
|
922
|
-
const node:
|
|
923
|
-
type: NODE_TYPE.
|
|
924
|
-
|
|
925
|
+
const node: ListNode = {
|
|
926
|
+
type: NODE_TYPE.LIST,
|
|
927
|
+
sourceType: 'collection',
|
|
928
|
+
source: "posts",
|
|
925
929
|
filter: { category: "{{cms.category}}" },
|
|
926
930
|
children: [{ type: "node", tag: "div", children: ["Item"] }],
|
|
927
931
|
};
|
|
@@ -944,9 +948,10 @@ describe("ComponentBuilder", () => {
|
|
|
944
948
|
{ _id: "2", _slug: "a", title: "A" },
|
|
945
949
|
{ _id: "3", _slug: "b", title: "B" },
|
|
946
950
|
];
|
|
947
|
-
const node:
|
|
948
|
-
type: NODE_TYPE.
|
|
949
|
-
|
|
951
|
+
const node: ListNode = {
|
|
952
|
+
type: NODE_TYPE.LIST,
|
|
953
|
+
sourceType: 'collection',
|
|
954
|
+
source: "posts",
|
|
950
955
|
sort: { field: "title", order: "asc" },
|
|
951
956
|
children: [{ type: "node", tag: "div", children: ["{{item.title}}"] }],
|
|
952
957
|
};
|
|
@@ -969,9 +974,10 @@ describe("ComponentBuilder", () => {
|
|
|
969
974
|
{ _id: "2", _slug: "p2", date: 300 },
|
|
970
975
|
{ _id: "3", _slug: "p3", date: 200 },
|
|
971
976
|
];
|
|
972
|
-
const node:
|
|
973
|
-
type: NODE_TYPE.
|
|
974
|
-
|
|
977
|
+
const node: ListNode = {
|
|
978
|
+
type: NODE_TYPE.LIST,
|
|
979
|
+
sourceType: 'collection',
|
|
980
|
+
source: "posts",
|
|
975
981
|
sort: { field: "date", order: "desc" },
|
|
976
982
|
children: [{ type: "node", tag: "div", children: ["Item"] }],
|
|
977
983
|
};
|
|
@@ -996,9 +1002,10 @@ describe("ComponentBuilder", () => {
|
|
|
996
1002
|
{ _id: "4", _slug: "p4", featured: true, title: "Featured 2" },
|
|
997
1003
|
{ _id: "5", _slug: "p5", featured: false, title: "Regular 3" },
|
|
998
1004
|
];
|
|
999
|
-
const node:
|
|
1000
|
-
type: NODE_TYPE.
|
|
1001
|
-
|
|
1005
|
+
const node: ListNode = {
|
|
1006
|
+
type: NODE_TYPE.LIST,
|
|
1007
|
+
sourceType: 'collection',
|
|
1008
|
+
source: "posts",
|
|
1002
1009
|
filter: { featured: true },
|
|
1003
1010
|
limit: 3, // Without proper order, this would limit before filtering
|
|
1004
1011
|
children: [{ type: "node", tag: "div", children: ["Item"] }],
|
|
@@ -1024,9 +1031,10 @@ describe("ComponentBuilder", () => {
|
|
|
1024
1031
|
{ _id: "4", _slug: "p4", date: 400 },
|
|
1025
1032
|
{ _id: "5", _slug: "p5", date: 50 },
|
|
1026
1033
|
];
|
|
1027
|
-
const node:
|
|
1028
|
-
type: NODE_TYPE.
|
|
1029
|
-
|
|
1034
|
+
const node: ListNode = {
|
|
1035
|
+
type: NODE_TYPE.LIST,
|
|
1036
|
+
sourceType: 'collection',
|
|
1037
|
+
source: "posts",
|
|
1030
1038
|
sort: { field: "date", order: "desc" },
|
|
1031
1039
|
limit: 2, // Should get 2 most recent (highest date)
|
|
1032
1040
|
children: [{ type: "node", tag: "div", children: ["Item"] }],
|
|
@@ -1050,9 +1058,10 @@ describe("ComponentBuilder", () => {
|
|
|
1050
1058
|
{ _id: "3", _slug: "p3", featured: true, price: 50 },
|
|
1051
1059
|
{ _id: "4", _slug: "p4", featured: true, price: 200 },
|
|
1052
1060
|
];
|
|
1053
|
-
const node:
|
|
1054
|
-
type: NODE_TYPE.
|
|
1055
|
-
|
|
1061
|
+
const node: ListNode = {
|
|
1062
|
+
type: NODE_TYPE.LIST,
|
|
1063
|
+
sourceType: 'collection',
|
|
1064
|
+
source: "posts",
|
|
1056
1065
|
filter: [
|
|
1057
1066
|
{ field: "featured", value: true },
|
|
1058
1067
|
{ field: "price", operator: "gte", value: 100 }
|
|
@@ -1531,7 +1540,7 @@ describe("ComponentBuilder", () => {
|
|
|
1531
1540
|
});
|
|
1532
1541
|
});
|
|
1533
1542
|
|
|
1534
|
-
describe("Edge Case 7:
|
|
1543
|
+
describe("Edge Case 7: List Paths Tracking (Collection Mode)", () => {
|
|
1535
1544
|
const createMockCMSItems = (count: number): CMSItem[] => {
|
|
1536
1545
|
return Array.from({ length: count }, (_, i) => ({
|
|
1537
1546
|
_id: `item-${i}`,
|
|
@@ -1540,11 +1549,12 @@ describe("ComponentBuilder", () => {
|
|
|
1540
1549
|
}));
|
|
1541
1550
|
};
|
|
1542
1551
|
|
|
1543
|
-
test("should pass
|
|
1544
|
-
// Create a simple
|
|
1545
|
-
const node:
|
|
1546
|
-
type: NODE_TYPE.
|
|
1547
|
-
|
|
1552
|
+
test("should pass listPaths through buildChildren", () => {
|
|
1553
|
+
// Create a simple list with items
|
|
1554
|
+
const node: ListNode = {
|
|
1555
|
+
type: NODE_TYPE.LIST,
|
|
1556
|
+
sourceType: 'collection',
|
|
1557
|
+
source: "posts",
|
|
1548
1558
|
children: [{ type: "node", tag: "div", children: ["Item"] }],
|
|
1549
1559
|
};
|
|
1550
1560
|
|
|
@@ -1555,21 +1565,23 @@ describe("ComponentBuilder", () => {
|
|
|
1555
1565
|
elementPath: [0],
|
|
1556
1566
|
});
|
|
1557
1567
|
|
|
1558
|
-
// If
|
|
1568
|
+
// If listPaths tracking works, the result should render without errors
|
|
1559
1569
|
expect(result).not.toBeNull();
|
|
1560
1570
|
const element = result as { props?: { children?: unknown[] } };
|
|
1561
1571
|
expect(element?.props?.children?.length).toBe(2);
|
|
1562
1572
|
});
|
|
1563
1573
|
|
|
1564
|
-
test("should track
|
|
1565
|
-
// Outer
|
|
1566
|
-
const outerNode:
|
|
1567
|
-
type: NODE_TYPE.
|
|
1568
|
-
|
|
1574
|
+
test("should track listPaths in nested lists", () => {
|
|
1575
|
+
// Outer list with inner list
|
|
1576
|
+
const outerNode: ListNode = {
|
|
1577
|
+
type: NODE_TYPE.LIST,
|
|
1578
|
+
sourceType: 'collection',
|
|
1579
|
+
source: "categories",
|
|
1569
1580
|
children: [
|
|
1570
1581
|
{
|
|
1571
|
-
type: NODE_TYPE.
|
|
1572
|
-
|
|
1582
|
+
type: NODE_TYPE.LIST,
|
|
1583
|
+
sourceType: 'collection',
|
|
1584
|
+
source: "posts",
|
|
1573
1585
|
children: [{ type: "node", tag: "span", children: ["Post"] }],
|
|
1574
1586
|
} as any,
|
|
1575
1587
|
],
|
|
@@ -1584,7 +1596,7 @@ describe("ComponentBuilder", () => {
|
|
|
1584
1596
|
elementPath: [0],
|
|
1585
1597
|
});
|
|
1586
1598
|
|
|
1587
|
-
// Nested
|
|
1599
|
+
// Nested lists should render correctly with path tracking
|
|
1588
1600
|
expect(result).not.toBeNull();
|
|
1589
1601
|
});
|
|
1590
1602
|
});
|
|
@@ -13,7 +13,7 @@ import { processStructure } from "../templateEngine";
|
|
|
13
13
|
import { NODE_TYPE } from "../../shared/constants";
|
|
14
14
|
import { ErrorBoundary } from "../ErrorBoundary";
|
|
15
15
|
import type { ComponentNode, StyleValue } from "../../shared/types";
|
|
16
|
-
import { isComponentNode, extractNodeProperties, isSlotMarker, isEmbedNode, isLinkNode, isLocaleListNode,
|
|
16
|
+
import { isComponentNode, extractNodeProperties, isSlotMarker, isEmbedNode, isLinkNode, isLocaleListNode, isListNode, markAsSlotContent, evaluateNodeIf, isBooleanMapping } from "../../shared/nodeUtils";
|
|
17
17
|
import { mergeNodeStyles } from "../../shared/styleNodeUtils";
|
|
18
18
|
import { extractAttributesFromNode } from "../../shared/attributeNodeUtils";
|
|
19
19
|
import { resolvePropsFromDefinition } from "../../shared/propResolver";
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
buildEmbed,
|
|
42
42
|
buildLinkNode,
|
|
43
43
|
buildLocaleList,
|
|
44
|
-
|
|
44
|
+
buildList,
|
|
45
45
|
buildLink,
|
|
46
46
|
} from "./builders";
|
|
47
47
|
|
|
@@ -346,8 +346,10 @@ export class ComponentBuilder {
|
|
|
346
346
|
return buildLocaleList(node, ctx, builderDeps);
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
-
|
|
350
|
-
|
|
349
|
+
// Handle List nodes (unified - handles both prop and collection source types)
|
|
350
|
+
// isListNode() also matches legacy 'cms-list' type for migration
|
|
351
|
+
if (isListNode(node)) {
|
|
352
|
+
return buildList(node, children, ctx, builderDeps);
|
|
351
353
|
}
|
|
352
354
|
|
|
353
355
|
// Extract node properties
|
|
@@ -15,6 +15,7 @@ import { hasInteractiveStyleMappings, extractInteractiveStyleMappings, resolveEx
|
|
|
15
15
|
import DOMPurify from "isomorphic-dompurify";
|
|
16
16
|
import type { ElementRegistry } from "../../elementRegistry";
|
|
17
17
|
import type { BuilderContext } from "./types";
|
|
18
|
+
import { hasItemTemplates, processItemTemplate } from "../../../shared/itemTemplateUtils";
|
|
18
19
|
|
|
19
20
|
export interface EmbedBuilderDeps {
|
|
20
21
|
elementRegistry: ElementRegistry;
|
|
@@ -49,8 +50,16 @@ export function buildEmbed(
|
|
|
49
50
|
): ReactElement {
|
|
50
51
|
const { key, elementPath, parentComponentName, componentContext, componentRootPath, cmsItemIndexPath } = ctx;
|
|
51
52
|
|
|
53
|
+
// Process templates in html property before sanitization (matching SSR behavior)
|
|
54
|
+
let htmlContent = node.html;
|
|
55
|
+
|
|
56
|
+
// Process item template strings (for List context) - e.g., {{item.icon}}, {{feature.title}}
|
|
57
|
+
if (ctx.templateContext && hasItemTemplates(htmlContent)) {
|
|
58
|
+
htmlContent = processItemTemplate(htmlContent, ctx.templateContext);
|
|
59
|
+
}
|
|
60
|
+
|
|
52
61
|
// Sanitize HTML with allowlist
|
|
53
|
-
const sanitizedHtml = DOMPurify.sanitize(
|
|
62
|
+
const sanitizedHtml = DOMPurify.sanitize(htmlContent, SANITIZE_CONFIG);
|
|
54
63
|
const effectiveParentComponentName = deps.getEffectiveParentComponentName(componentContext, parentComponentName);
|
|
55
64
|
|
|
56
65
|
// Extract attributes from node
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* - embedBuilder: Embed nodes (HTML content like SVGs)
|
|
6
6
|
* - linkNodeBuilder: Link nodes (links as div in editor)
|
|
7
7
|
* - localeListBuilder: Locale list nodes (language switchers)
|
|
8
|
-
* -
|
|
8
|
+
* - listBuilder: Unified list nodes (prop and collection item rendering)
|
|
9
9
|
* - linkBuilder: Link components with navigation/prefetch
|
|
10
10
|
*/
|
|
11
11
|
|
|
@@ -22,5 +22,9 @@ export type {
|
|
|
22
22
|
export { buildEmbed, type EmbedBuilderDeps } from './embedBuilder';
|
|
23
23
|
export { buildLinkNode, type LinkNodeBuilderDeps } from './linkNodeBuilder';
|
|
24
24
|
export { buildLocaleList, type LocaleListBuilderDeps } from './localeListBuilder';
|
|
25
|
-
export {
|
|
25
|
+
export { buildList, type ListBuilderDeps } from './listBuilder';
|
|
26
26
|
export { buildLink, type LinkBuilderDeps } from './linkBuilder';
|
|
27
|
+
|
|
28
|
+
// Legacy alias for backward compatibility during migration
|
|
29
|
+
export { buildList as buildCMSList } from './listBuilder';
|
|
30
|
+
export type { ListBuilderDeps as CMSListBuilderDeps } from './listBuilder';
|