@uniweb/core 0.4.2 → 0.4.4
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/package.json +1 -1
- package/src/uniweb.js +45 -9
- package/src/website.js +7 -12
package/package.json
CHANGED
package/src/uniweb.js
CHANGED
|
@@ -16,6 +16,7 @@ export default class Uniweb {
|
|
|
16
16
|
this.foundation = null // The loaded foundation module
|
|
17
17
|
this.foundationConfig = {} // Configuration from foundation (capabilities)
|
|
18
18
|
this.meta = {} // Per-component runtime metadata (from meta.js)
|
|
19
|
+
this.extensions = [] // Array of { foundation, meta } objects
|
|
19
20
|
this.language = 'en'
|
|
20
21
|
|
|
21
22
|
// Icon resolver: (library, name) => Promise<string|null>
|
|
@@ -67,13 +68,30 @@ export default class Uniweb {
|
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
/**
|
|
72
|
+
* Register an extension (secondary foundation)
|
|
73
|
+
* @param {Object} foundation - The loaded ESM extension module
|
|
74
|
+
*/
|
|
75
|
+
registerExtension(foundation) {
|
|
76
|
+
const meta = foundation.meta || {}
|
|
77
|
+
this.extensions.push({ foundation, meta })
|
|
78
|
+
}
|
|
79
|
+
|
|
70
80
|
/**
|
|
71
81
|
* Get runtime metadata for a component
|
|
72
82
|
* @param {string} componentName
|
|
73
83
|
* @returns {Object|null} Meta with defaults, context, initialState, background, data
|
|
74
84
|
*/
|
|
75
85
|
getComponentMeta(componentName) {
|
|
76
|
-
|
|
86
|
+
const primary = this.meta[componentName]
|
|
87
|
+
if (primary) return primary
|
|
88
|
+
|
|
89
|
+
for (const ext of this.extensions) {
|
|
90
|
+
const meta = ext.meta[componentName]
|
|
91
|
+
if (meta) return meta
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return null
|
|
77
95
|
}
|
|
78
96
|
|
|
79
97
|
/**
|
|
@@ -82,7 +100,7 @@ export default class Uniweb {
|
|
|
82
100
|
* @returns {Object} Default values (empty object if none)
|
|
83
101
|
*/
|
|
84
102
|
getComponentDefaults(componentName) {
|
|
85
|
-
return this.
|
|
103
|
+
return this.getComponentMeta(componentName)?.defaults || {}
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
/**
|
|
@@ -96,8 +114,17 @@ export default class Uniweb {
|
|
|
96
114
|
return undefined
|
|
97
115
|
}
|
|
98
116
|
|
|
99
|
-
//
|
|
100
|
-
|
|
117
|
+
// Primary foundation first
|
|
118
|
+
const primary = this.foundation.components?.[name] || this.foundation[name]
|
|
119
|
+
if (primary) return primary
|
|
120
|
+
|
|
121
|
+
// Fall through to extensions (declared order)
|
|
122
|
+
for (const ext of this.extensions) {
|
|
123
|
+
const component = ext.foundation.components?.[name] || ext.foundation[name]
|
|
124
|
+
if (component) return component
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return undefined
|
|
101
128
|
}
|
|
102
129
|
|
|
103
130
|
/**
|
|
@@ -105,14 +132,23 @@ export default class Uniweb {
|
|
|
105
132
|
* @returns {string[]}
|
|
106
133
|
*/
|
|
107
134
|
listComponents() {
|
|
108
|
-
|
|
135
|
+
const names = new Set()
|
|
136
|
+
|
|
137
|
+
if (this.foundation?.components) {
|
|
138
|
+
for (const name of Object.keys(this.foundation.components)) {
|
|
139
|
+
names.add(name)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
109
142
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
143
|
+
for (const ext of this.extensions) {
|
|
144
|
+
if (ext.foundation.components) {
|
|
145
|
+
for (const name of Object.keys(ext.foundation.components)) {
|
|
146
|
+
names.add(name)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
113
149
|
}
|
|
114
150
|
|
|
115
|
-
return []
|
|
151
|
+
return [...names]
|
|
116
152
|
}
|
|
117
153
|
|
|
118
154
|
/**
|
package/src/website.js
CHANGED
|
@@ -18,21 +18,19 @@ export default class Website {
|
|
|
18
18
|
this.description = config.description || ''
|
|
19
19
|
this.url = config.url || ''
|
|
20
20
|
|
|
21
|
-
// Store
|
|
21
|
+
// Store layout panels (header, footer, left, right)
|
|
22
22
|
// These come from top-level properties set by content-collector
|
|
23
|
-
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
26
|
-
this.
|
|
27
|
-
this.rightPage = right || pages.find((p) => p.route === '/@right') || null
|
|
23
|
+
this.headerPage = header || null
|
|
24
|
+
this.footerPage = footer || null
|
|
25
|
+
this.leftPage = left || null
|
|
26
|
+
this.rightPage = right || null
|
|
28
27
|
|
|
29
28
|
// Store 404 page (for SPA routing)
|
|
30
29
|
// Convention: pages/404/ directory
|
|
31
30
|
this.notFoundPage = notFound || pages.find((p) => p.route === '/404') || null
|
|
32
31
|
|
|
33
|
-
// Filter out
|
|
34
|
-
const
|
|
35
|
-
const regularPages = pages.filter((page) => !specialRoutes.includes(page.route))
|
|
32
|
+
// Filter out 404 from regular pages array
|
|
33
|
+
const regularPages = pages.filter((page) => page.route !== '/404')
|
|
36
34
|
|
|
37
35
|
// Store original page data for dynamic pages (needed to create instances on-demand)
|
|
38
36
|
this._dynamicPageData = new Map()
|
|
@@ -792,9 +790,6 @@ export default class Website {
|
|
|
792
790
|
|
|
793
791
|
// Filter pages based on navigation type and visibility
|
|
794
792
|
const isPageVisible = (page) => {
|
|
795
|
-
// Always exclude special pages (header/footer are already separated)
|
|
796
|
-
if (page.route.startsWith('/@')) return false
|
|
797
|
-
|
|
798
793
|
// Always exclude dynamic route template pages (e.g., /blog/:slug)
|
|
799
794
|
// These are templates for generating pages, not actual navigable pages
|
|
800
795
|
if (page.route.includes(':')) return false
|