@uniweb/core 0.2.3 → 0.2.5
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 +2 -2
- package/src/block.js +0 -3
- package/src/page.js +2 -6
- package/src/website.js +14 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "Core classes for the Uniweb platform - Uniweb, Website, Page, Block",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"jest": "^29.7.0"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@uniweb/semantic-parser": "1.0.
|
|
33
|
+
"@uniweb/semantic-parser": "1.0.15"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
|
package/src/block.js
CHANGED
|
@@ -52,9 +52,6 @@ export default class Block {
|
|
|
52
52
|
? blockData.subsections.map((block, i) => new Block(block, `${id}_${i}`))
|
|
53
53
|
: []
|
|
54
54
|
|
|
55
|
-
// Input data
|
|
56
|
-
this.input = blockData.input || null
|
|
57
|
-
|
|
58
55
|
// Fetch configuration (from section frontmatter)
|
|
59
56
|
// Supports local files (path) or remote URLs (url)
|
|
60
57
|
this.fetch = blockData.fetch || null
|
package/src/page.js
CHANGED
|
@@ -26,7 +26,6 @@ export default class Page {
|
|
|
26
26
|
this.description = pageData.description || ''
|
|
27
27
|
this.label = pageData.label || null // Short label for navigation (null = use title)
|
|
28
28
|
this.keywords = pageData.keywords || null
|
|
29
|
-
this.order = pageData.order ?? 0
|
|
30
29
|
this.lastModified = pageData.lastModified || null
|
|
31
30
|
|
|
32
31
|
// Navigation visibility options
|
|
@@ -38,11 +37,8 @@ export default class Page {
|
|
|
38
37
|
this.layout = {
|
|
39
38
|
header: pageData.layout?.header !== false,
|
|
40
39
|
footer: pageData.layout?.footer !== false,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// Aliases for backwards compatibility
|
|
44
|
-
leftPanel: pageData.layout?.left !== false,
|
|
45
|
-
rightPanel: pageData.layout?.right !== false,
|
|
40
|
+
leftPanel: pageData.layout?.leftPanel !== false,
|
|
41
|
+
rightPanel: pageData.layout?.rightPanel !== false,
|
|
46
42
|
}
|
|
47
43
|
|
|
48
44
|
// SEO configuration
|
package/src/website.js
CHANGED
|
@@ -167,12 +167,8 @@ export default class Website {
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
if (page.children.length > 0) {
|
|
173
|
-
page.children.sort((a, b) => (a.order || 0) - (b.order || 0))
|
|
174
|
-
}
|
|
175
|
-
}
|
|
170
|
+
// Note: Pages arrive pre-sorted from build time.
|
|
171
|
+
// The hierarchy is hydrated from that order - no runtime sorting needed.
|
|
176
172
|
|
|
177
173
|
// Build page ID map for makeHref() resolution
|
|
178
174
|
// Supports both explicit IDs and route-based lookup
|
|
@@ -201,18 +197,22 @@ export default class Website {
|
|
|
201
197
|
* @returns {Page|undefined}
|
|
202
198
|
*/
|
|
203
199
|
getPage(route) {
|
|
200
|
+
// Normalize trailing slashes for consistent matching
|
|
201
|
+
// '/about/' and '/about' should match the same page
|
|
202
|
+
const normalizedRoute = route === '/' ? '/' : route.replace(/\/$/, '')
|
|
203
|
+
|
|
204
204
|
// Priority 1: Exact match on actual route
|
|
205
|
-
const exactMatch = this.pages.find((page) => page.route ===
|
|
205
|
+
const exactMatch = this.pages.find((page) => page.route === normalizedRoute)
|
|
206
206
|
if (exactMatch) return exactMatch
|
|
207
207
|
|
|
208
208
|
// Priority 2: Index page nav route match
|
|
209
|
-
const indexMatch = this.pages.find((page) => page.isIndex && page.getNavRoute() ===
|
|
209
|
+
const indexMatch = this.pages.find((page) => page.isIndex && page.getNavRoute() === normalizedRoute)
|
|
210
210
|
if (indexMatch) return indexMatch
|
|
211
211
|
|
|
212
212
|
// Priority 3: Dynamic route pattern matching
|
|
213
213
|
// Check cache first
|
|
214
|
-
if (this._dynamicPageCache.has(
|
|
215
|
-
return this._dynamicPageCache.get(
|
|
214
|
+
if (this._dynamicPageCache.has(normalizedRoute)) {
|
|
215
|
+
return this._dynamicPageCache.get(normalizedRoute)
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
// Try to match against dynamic route patterns
|
|
@@ -220,13 +220,13 @@ export default class Website {
|
|
|
220
220
|
// Check if this is a dynamic page (has :param in route)
|
|
221
221
|
if (!page.route.includes(':')) continue
|
|
222
222
|
|
|
223
|
-
const match = this._matchDynamicRoute(page.route,
|
|
223
|
+
const match = this._matchDynamicRoute(page.route, normalizedRoute)
|
|
224
224
|
if (match) {
|
|
225
225
|
// Create a dynamic page instance with the concrete route and params
|
|
226
|
-
const dynamicPage = this._createDynamicPage(page,
|
|
226
|
+
const dynamicPage = this._createDynamicPage(page, normalizedRoute, match.params)
|
|
227
227
|
if (dynamicPage) {
|
|
228
228
|
// Cache for future requests
|
|
229
|
-
this._dynamicPageCache.set(
|
|
229
|
+
this._dynamicPageCache.set(normalizedRoute, dynamicPage)
|
|
230
230
|
return dynamicPage
|
|
231
231
|
}
|
|
232
232
|
}
|
|
@@ -739,7 +739,7 @@ export default class Website {
|
|
|
739
739
|
*
|
|
740
740
|
* // Custom filtering
|
|
741
741
|
* const topLevel = website.getPageHierarchy({
|
|
742
|
-
* filter: (page) => page.
|
|
742
|
+
* filter: (page) => !page.route.startsWith('/admin')
|
|
743
743
|
* })
|
|
744
744
|
*/
|
|
745
745
|
getPageHierarchy(options = {}) {
|
|
@@ -795,7 +795,6 @@ export default class Website {
|
|
|
795
795
|
title: page.title,
|
|
796
796
|
label: page.getLabel(),
|
|
797
797
|
description: page.description,
|
|
798
|
-
order: page.order,
|
|
799
798
|
hasContent: page.hasContent(),
|
|
800
799
|
children: nested && page.hasChildren()
|
|
801
800
|
? page.children.filter(isPageVisible).map(buildPageInfo)
|