@uniweb/core 0.4.8 → 0.5.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/package.json +1 -1
- package/src/page.js +31 -90
- package/src/website.js +49 -43
package/package.json
CHANGED
package/src/page.js
CHANGED
|
@@ -26,13 +26,11 @@ export default class Page {
|
|
|
26
26
|
this.hideInHeader = pageData.hideInHeader || false
|
|
27
27
|
this.hideInFooter = pageData.hideInFooter || false
|
|
28
28
|
|
|
29
|
-
// Layout options (named layout + per-page overrides
|
|
29
|
+
// Layout options (named layout + per-page overrides)
|
|
30
30
|
this.layout = {
|
|
31
31
|
name: pageData.layout?.name || null,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
leftPanel: pageData.layout?.leftPanel !== false,
|
|
35
|
-
rightPanel: pageData.layout?.rightPanel !== false,
|
|
32
|
+
hide: pageData.layout?.hide || [],
|
|
33
|
+
params: pageData.layout?.params || {},
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
// SEO configuration
|
|
@@ -155,15 +153,12 @@ export default class Page {
|
|
|
155
153
|
|
|
156
154
|
/**
|
|
157
155
|
* Get all block groups (for Layout component)
|
|
158
|
-
* @returns {Object} {
|
|
156
|
+
* @returns {Object} { body, ...areas }
|
|
159
157
|
*/
|
|
160
158
|
getBlockGroups() {
|
|
161
159
|
return {
|
|
162
|
-
header: this.getHeaderBlocks(),
|
|
163
160
|
body: this.bodyBlocks,
|
|
164
|
-
|
|
165
|
-
left: this.getLeftBlocks(),
|
|
166
|
-
right: this.getRightBlocks(),
|
|
161
|
+
...this.getLayoutAreas(),
|
|
167
162
|
}
|
|
168
163
|
}
|
|
169
164
|
|
|
@@ -208,13 +203,14 @@ export default class Page {
|
|
|
208
203
|
|
|
209
204
|
/**
|
|
210
205
|
* Get all blocks (header, body, footer) as flat array
|
|
211
|
-
* Respects page layout preferences (
|
|
206
|
+
* Respects page layout preferences (hide list)
|
|
212
207
|
* @returns {Block[]}
|
|
213
208
|
*/
|
|
214
209
|
getPageBlocks() {
|
|
215
210
|
const blocks = []
|
|
216
|
-
const
|
|
217
|
-
const
|
|
211
|
+
const areas = this.getLayoutAreas()
|
|
212
|
+
const headerBlocks = areas.header
|
|
213
|
+
const footerBlocks = areas.footer
|
|
218
214
|
|
|
219
215
|
if (headerBlocks) blocks.push(...headerBlocks)
|
|
220
216
|
blocks.push(...this.bodyBlocks)
|
|
@@ -232,69 +228,46 @@ export default class Page {
|
|
|
232
228
|
}
|
|
233
229
|
|
|
234
230
|
/**
|
|
235
|
-
* Get
|
|
231
|
+
* Get blocks for a specific area, respecting hide list
|
|
232
|
+
* @param {string} areaName - Area name (e.g., 'header', 'footer', 'left')
|
|
236
233
|
* @returns {Block[]|null}
|
|
237
234
|
*/
|
|
238
|
-
|
|
239
|
-
if (
|
|
240
|
-
return this.website.
|
|
235
|
+
getAreaBlocks(areaName) {
|
|
236
|
+
if (this.layout.hide.includes(areaName)) return null
|
|
237
|
+
return this.website.getAreaBlocks(areaName, this.getLayoutName())
|
|
241
238
|
}
|
|
242
239
|
|
|
243
240
|
/**
|
|
244
|
-
* Get
|
|
245
|
-
* @returns {Block[]
|
|
246
|
-
*/
|
|
247
|
-
getFooterBlocks() {
|
|
248
|
-
if (!this.hasFooter()) return null
|
|
249
|
-
return this.website.getFooterBlocks(this.getLayoutName())
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Get left panel blocks (respects layout preference, delegates to website)
|
|
254
|
-
* @returns {Block[]|null}
|
|
241
|
+
* Get all areas for this page's layout, excluding hidden areas
|
|
242
|
+
* @returns {Object} Map of areaName -> Block[]
|
|
255
243
|
*/
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
getRightBlocks() {
|
|
266
|
-
if (!this.hasRightPanel()) return null
|
|
267
|
-
return this.website.getRightBlocks(this.getLayoutName())
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Get header block (legacy - returns first block)
|
|
272
|
-
* @returns {Block|null}
|
|
273
|
-
* @deprecated Use getHeaderBlocks() instead
|
|
274
|
-
*/
|
|
275
|
-
getHeader() {
|
|
276
|
-
return this.getHeaderBlocks()?.[0] || null
|
|
244
|
+
getLayoutAreas() {
|
|
245
|
+
const allAreas = this.website.getLayoutAreas(this.getLayoutName())
|
|
246
|
+
const result = {}
|
|
247
|
+
for (const [name, blocks] of Object.entries(allAreas)) {
|
|
248
|
+
if (!this.layout.hide.includes(name)) {
|
|
249
|
+
result[name] = blocks
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return result
|
|
277
253
|
}
|
|
278
254
|
|
|
279
255
|
/**
|
|
280
|
-
* Get
|
|
281
|
-
* @returns {
|
|
282
|
-
* @deprecated Use getFooterBlocks() instead
|
|
256
|
+
* Get layout params for this page (merged with defaults at render time)
|
|
257
|
+
* @returns {Object}
|
|
283
258
|
*/
|
|
284
|
-
|
|
285
|
-
return this.
|
|
259
|
+
getLayoutParams() {
|
|
260
|
+
return this.layout.params
|
|
286
261
|
}
|
|
287
262
|
|
|
288
263
|
/**
|
|
289
264
|
* Reset block states (for scroll restoration)
|
|
290
265
|
*/
|
|
291
266
|
resetBlockStates() {
|
|
267
|
+
const areas = this.getLayoutAreas()
|
|
292
268
|
const allBlocks = [
|
|
293
|
-
...(this.getHeaderBlocks() || []),
|
|
294
269
|
...this.bodyBlocks,
|
|
295
|
-
...(
|
|
296
|
-
...(this.getLeftBlocks() || []),
|
|
297
|
-
...(this.getRightBlocks() || []),
|
|
270
|
+
...Object.values(areas).flat(),
|
|
298
271
|
]
|
|
299
272
|
|
|
300
273
|
for (const block of allBlocks) {
|
|
@@ -350,38 +323,6 @@ export default class Page {
|
|
|
350
323
|
return !this.hidden && !this.hideInFooter
|
|
351
324
|
}
|
|
352
325
|
|
|
353
|
-
/**
|
|
354
|
-
* Check if header should be rendered on this page
|
|
355
|
-
* @returns {boolean}
|
|
356
|
-
*/
|
|
357
|
-
hasHeader() {
|
|
358
|
-
return this.layout.header
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
/**
|
|
362
|
-
* Check if footer should be rendered on this page
|
|
363
|
-
* @returns {boolean}
|
|
364
|
-
*/
|
|
365
|
-
hasFooter() {
|
|
366
|
-
return this.layout.footer
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Check if left panel should be rendered on this page
|
|
371
|
-
* @returns {boolean}
|
|
372
|
-
*/
|
|
373
|
-
hasLeftPanel() {
|
|
374
|
-
return this.layout.leftPanel
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Check if right panel should be rendered on this page
|
|
379
|
-
* @returns {boolean}
|
|
380
|
-
*/
|
|
381
|
-
hasRightPanel() {
|
|
382
|
-
return this.layout.rightPanel
|
|
383
|
-
}
|
|
384
|
-
|
|
385
326
|
/**
|
|
386
327
|
* Check if page has child pages
|
|
387
328
|
* @returns {boolean}
|
package/src/website.js
CHANGED
|
@@ -11,35 +11,26 @@ import singularize from './singularize.js'
|
|
|
11
11
|
|
|
12
12
|
export default class Website {
|
|
13
13
|
constructor(websiteData) {
|
|
14
|
-
const { pages = [], theme = {}, config = {}, layouts,
|
|
14
|
+
const { pages = [], theme = {}, config = {}, layouts, notFound, versionedScopes = {} } = websiteData
|
|
15
15
|
|
|
16
16
|
// Site metadata
|
|
17
17
|
this.name = config.name || ''
|
|
18
18
|
this.description = config.description || ''
|
|
19
19
|
this.url = config.url || ''
|
|
20
20
|
|
|
21
|
-
//
|
|
21
|
+
// General area storage: { layoutName: { areaName: Page } }
|
|
22
|
+
this._layoutSets = {}
|
|
22
23
|
if (layouts && typeof layouts === 'object') {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
rightPage: panelData.right ? new Page(panelData.right, `layout-${name}-right`, this) : null,
|
|
24
|
+
for (const [name, areaData] of Object.entries(layouts)) {
|
|
25
|
+
this._layoutSets[name] = {}
|
|
26
|
+
for (const [areaName, pageData] of Object.entries(areaData)) {
|
|
27
|
+
if (pageData) {
|
|
28
|
+
this._layoutSets[name][areaName] = new Page(pageData, `layout-${name}-${areaName}`, this)
|
|
29
|
+
}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
} else {
|
|
33
|
-
this._layoutSets = null
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
// Layout panels as Page objects (header, footer, left, right)
|
|
37
|
-
// Flat fields for backward compatibility (used when no named layouts)
|
|
38
|
-
this.headerPage = header ? new Page(header, 'header', this) : null
|
|
39
|
-
this.footerPage = footer ? new Page(footer, 'footer', this) : null
|
|
40
|
-
this.leftPage = left ? new Page(left, 'left', this) : null
|
|
41
|
-
this.rightPage = right ? new Page(right, 'right', this) : null
|
|
42
|
-
|
|
43
34
|
// Store 404 page (for SPA routing)
|
|
44
35
|
// Convention: pages/404/ directory
|
|
45
36
|
this.notFoundPage = notFound || pages.find((p) => p.route === '/404') || null
|
|
@@ -477,13 +468,11 @@ export default class Website {
|
|
|
477
468
|
*/
|
|
478
469
|
getRemoteLayout(layoutName) {
|
|
479
470
|
const config = globalThis.uniweb?.foundationConfig
|
|
480
|
-
if (!config) return null
|
|
481
|
-
|
|
482
|
-
if (layoutName && config.layouts?.[layoutName]) {
|
|
471
|
+
if (!config?.layouts) return null
|
|
472
|
+
if (layoutName && config.layouts[layoutName]) {
|
|
483
473
|
return config.layouts[layoutName]
|
|
484
474
|
}
|
|
485
|
-
|
|
486
|
-
return config.Layout || null
|
|
475
|
+
return null
|
|
487
476
|
}
|
|
488
477
|
|
|
489
478
|
/**
|
|
@@ -502,35 +491,52 @@ export default class Website {
|
|
|
502
491
|
}
|
|
503
492
|
|
|
504
493
|
// ─────────────────────────────────────────────────────────────────
|
|
505
|
-
// Layout
|
|
494
|
+
// Layout Areas (general named areas)
|
|
506
495
|
// ─────────────────────────────────────────────────────────────────
|
|
507
496
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
497
|
+
/**
|
|
498
|
+
* Get blocks for a specific area, with layout name resolution
|
|
499
|
+
* @param {string} areaName - Area name (e.g., 'header', 'footer', 'left', 'sidebar')
|
|
500
|
+
* @param {string} [layoutName] - Named layout to look in (falls back to 'default')
|
|
501
|
+
* @returns {Block[]|null}
|
|
502
|
+
*/
|
|
503
|
+
getAreaBlocks(areaName, layoutName) {
|
|
504
|
+
if (layoutName && this._layoutSets[layoutName]) {
|
|
505
|
+
return this._layoutSets[layoutName][areaName]?.bodyBlocks || null
|
|
511
506
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
getFooterBlocks(layoutName) {
|
|
516
|
-
if (layoutName && this._layoutSets?.[layoutName]) {
|
|
517
|
-
return this._layoutSets[layoutName].footerPage?.bodyBlocks || null
|
|
507
|
+
// Fallback to 'default' layout
|
|
508
|
+
if (this._layoutSets.default) {
|
|
509
|
+
return this._layoutSets.default[areaName]?.bodyBlocks || null
|
|
518
510
|
}
|
|
519
|
-
return
|
|
511
|
+
return null
|
|
520
512
|
}
|
|
521
513
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
514
|
+
/**
|
|
515
|
+
* Get all areas for a layout as { areaName: Block[] }
|
|
516
|
+
* @param {string} [layoutName] - Named layout (falls back to 'default')
|
|
517
|
+
* @returns {Object} Map of areaName -> Block[]
|
|
518
|
+
*/
|
|
519
|
+
getLayoutAreas(layoutName) {
|
|
520
|
+
const setName = layoutName || 'default'
|
|
521
|
+
const layoutSet = this._layoutSets[setName] || this._layoutSets.default
|
|
522
|
+
if (!layoutSet) return {}
|
|
523
|
+
|
|
524
|
+
const areas = {}
|
|
525
|
+
for (const [areaName, page] of Object.entries(layoutSet)) {
|
|
526
|
+
if (page?.bodyBlocks) {
|
|
527
|
+
areas[areaName] = page.bodyBlocks
|
|
528
|
+
}
|
|
525
529
|
}
|
|
526
|
-
return
|
|
530
|
+
return areas
|
|
527
531
|
}
|
|
528
532
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
533
|
+
/**
|
|
534
|
+
* Get layout metadata from foundation config
|
|
535
|
+
* @param {string} layoutName - Layout name
|
|
536
|
+
* @returns {Object|null} Layout meta { areas, transitions, defaults }
|
|
537
|
+
*/
|
|
538
|
+
getLayoutMeta(layoutName) {
|
|
539
|
+
return globalThis.uniweb?.foundationConfig?.layoutMeta?.[layoutName] || null
|
|
534
540
|
}
|
|
535
541
|
|
|
536
542
|
/**
|