@uniweb/core 0.4.4 → 0.4.6
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/block.js +5 -8
- package/src/index.js +0 -4
- package/src/page.js +51 -101
- package/src/website.js +35 -17
- package/src/input.js +0 -15
package/package.json
CHANGED
package/src/block.js
CHANGED
|
@@ -8,17 +8,14 @@
|
|
|
8
8
|
import { parseContent as parseSemanticContent } from '@uniweb/semantic-parser'
|
|
9
9
|
|
|
10
10
|
export default class Block {
|
|
11
|
-
constructor(blockData, id) {
|
|
11
|
+
constructor(blockData, id, page) {
|
|
12
12
|
this.id = id
|
|
13
13
|
this.stableId = blockData.stableId || null // Stable section ID for scroll targeting (from filename or frontmatter)
|
|
14
|
-
|
|
15
|
-
this.
|
|
14
|
+
this.page = page
|
|
15
|
+
this.website = page.website
|
|
16
|
+
this.type = blockData.type || this.website.getDefaultBlockType()
|
|
16
17
|
this.Component = null
|
|
17
18
|
|
|
18
|
-
// Back-references (set by Page when creating blocks)
|
|
19
|
-
this.page = null
|
|
20
|
-
this.website = null
|
|
21
|
-
|
|
22
19
|
// Content structure
|
|
23
20
|
// The content can be:
|
|
24
21
|
// 1. Raw ProseMirror content (from content collection)
|
|
@@ -77,7 +74,7 @@ export default class Block {
|
|
|
77
74
|
|
|
78
75
|
// Child blocks (subsections)
|
|
79
76
|
this.childBlocks = blockData.subsections
|
|
80
|
-
? blockData.subsections.map((block, i) => new Block(block, `${id}_${i}
|
|
77
|
+
? blockData.subsections.map((block, i) => new Block(block, `${id}_${i}`, this.page))
|
|
81
78
|
: []
|
|
82
79
|
|
|
83
80
|
// Fetch configuration (from section frontmatter)
|
package/src/index.js
CHANGED
|
@@ -12,11 +12,7 @@ export { Uniweb }
|
|
|
12
12
|
export { default as Website } from './website.js'
|
|
13
13
|
export { default as Page } from './page.js'
|
|
14
14
|
export { default as Block } from './block.js'
|
|
15
|
-
export { default as Input } from './input.js'
|
|
16
|
-
export { default as Analytics } from './analytics.js'
|
|
17
15
|
export { default as Theme } from './theme.js'
|
|
18
|
-
export { default as DataStore } from './datastore.js'
|
|
19
|
-
export { default as EntityStore } from './entity-store.js'
|
|
20
16
|
|
|
21
17
|
/**
|
|
22
18
|
* The singleton Uniweb instance.
|
package/src/page.js
CHANGED
|
@@ -8,15 +8,7 @@
|
|
|
8
8
|
import Block from './block.js'
|
|
9
9
|
|
|
10
10
|
export default class Page {
|
|
11
|
-
constructor(
|
|
12
|
-
pageData,
|
|
13
|
-
id,
|
|
14
|
-
website,
|
|
15
|
-
pageHeader,
|
|
16
|
-
pageFooter,
|
|
17
|
-
pageLeft,
|
|
18
|
-
pageRight,
|
|
19
|
-
) {
|
|
11
|
+
constructor(pageData, id, website) {
|
|
20
12
|
this.id = id
|
|
21
13
|
this.stableId = pageData.id || null // Stable page ID for page: links (from page.yml)
|
|
22
14
|
this.route = pageData.route
|
|
@@ -77,14 +69,25 @@ export default class Page {
|
|
|
77
69
|
this.versionMeta = pageData.versionMeta || null // { versions, latestId }
|
|
78
70
|
this.versionScope = pageData.versionScope || null // The route where versioning starts
|
|
79
71
|
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
72
|
+
// Store raw section data for lazy block building
|
|
73
|
+
// Blocks are created on first access (when page is rendered), not during Website init
|
|
74
|
+
// This ensures foundationConfig is available for getDefaultBlockType()
|
|
75
|
+
// Layout panels (header, footer, left, right) are shared at Website level
|
|
76
|
+
this._bodySections = pageData.sections
|
|
77
|
+
this._bodyBlocks = null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Lazy getter for body blocks
|
|
82
|
+
* Blocks are built on first access, ensuring foundation is loaded
|
|
83
|
+
*/
|
|
84
|
+
get bodyBlocks() {
|
|
85
|
+
if (!this._bodyBlocks) {
|
|
86
|
+
this._bodyBlocks = (this._bodySections || []).map(
|
|
87
|
+
(section, index) => new Block(section, index, this)
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
return this._bodyBlocks
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
/**
|
|
@@ -140,66 +143,18 @@ export default class Page {
|
|
|
140
143
|
return this.dynamicContext?.paramValue || null
|
|
141
144
|
}
|
|
142
145
|
|
|
143
|
-
/**
|
|
144
|
-
* Build the page block structure for all layout areas.
|
|
145
|
-
* Each area can have multiple sections/blocks.
|
|
146
|
-
*
|
|
147
|
-
* @param {Array} body - Body sections from page content
|
|
148
|
-
* @param {Array} header - Header sections from @header page
|
|
149
|
-
* @param {Array} footer - Footer sections from @footer page
|
|
150
|
-
* @param {Array} left - Left panel sections from @left page
|
|
151
|
-
* @param {Array} right - Right panel sections from @right page
|
|
152
|
-
* @returns {Object} Block groups for each layout area
|
|
153
|
-
*/
|
|
154
|
-
buildPageBlocks(body, header, footer, left, right) {
|
|
155
|
-
const buildBlocks = (sections, prefix) => {
|
|
156
|
-
if (!sections || sections.length === 0) return null
|
|
157
|
-
return sections.map((section, index) => {
|
|
158
|
-
const block = new Block(section, `${prefix}-${index}`)
|
|
159
|
-
this.initBlockReferences(block)
|
|
160
|
-
return block
|
|
161
|
-
})
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const bodyBlocks = (body || []).map((section, index) => {
|
|
165
|
-
const block = new Block(section, index)
|
|
166
|
-
this.initBlockReferences(block)
|
|
167
|
-
return block
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
return {
|
|
171
|
-
header: buildBlocks(header, 'header'),
|
|
172
|
-
body: bodyBlocks,
|
|
173
|
-
footer: buildBlocks(footer, 'footer'),
|
|
174
|
-
left: buildBlocks(left, 'left'),
|
|
175
|
-
right: buildBlocks(right, 'right'),
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Initialize block back-references to page and website.
|
|
181
|
-
* Also recursively sets references for child blocks.
|
|
182
|
-
*
|
|
183
|
-
* @param {Block} block - The block to initialize
|
|
184
|
-
*/
|
|
185
|
-
initBlockReferences(block) {
|
|
186
|
-
block.page = this
|
|
187
|
-
block.website = this.website
|
|
188
|
-
|
|
189
|
-
// Recursively set references for child blocks
|
|
190
|
-
if (block.childBlocks?.length) {
|
|
191
|
-
for (const childBlock of block.childBlocks) {
|
|
192
|
-
this.initBlockReferences(childBlock)
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
146
|
/**
|
|
198
147
|
* Get all block groups (for Layout component)
|
|
199
148
|
* @returns {Object} { header, body, footer, left, right }
|
|
200
149
|
*/
|
|
201
150
|
getBlockGroups() {
|
|
202
|
-
return
|
|
151
|
+
return {
|
|
152
|
+
header: this.getHeaderBlocks(),
|
|
153
|
+
body: this.bodyBlocks,
|
|
154
|
+
footer: this.getFooterBlocks(),
|
|
155
|
+
left: this.getLeftBlocks(),
|
|
156
|
+
right: this.getRightBlocks(),
|
|
157
|
+
}
|
|
203
158
|
}
|
|
204
159
|
|
|
205
160
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -238,8 +193,7 @@ export default class Page {
|
|
|
238
193
|
* @returns {Object|null} First body block's info or null
|
|
239
194
|
*/
|
|
240
195
|
getFirstBodyBlockInfo() {
|
|
241
|
-
|
|
242
|
-
return bodyBlocks?.[0]?.getBlockInfo() || null
|
|
196
|
+
return this.bodyBlocks?.[0]?.getBlockInfo() || null
|
|
243
197
|
}
|
|
244
198
|
|
|
245
199
|
/**
|
|
@@ -249,62 +203,58 @@ export default class Page {
|
|
|
249
203
|
*/
|
|
250
204
|
getPageBlocks() {
|
|
251
205
|
const blocks = []
|
|
206
|
+
const headerBlocks = this.getHeaderBlocks()
|
|
207
|
+
const footerBlocks = this.getFooterBlocks()
|
|
252
208
|
|
|
253
|
-
if (
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
blocks.push(...this.pageBlocks.body)
|
|
258
|
-
|
|
259
|
-
if (this.hasFooter() && this.pageBlocks.footer) {
|
|
260
|
-
blocks.push(...this.pageBlocks.footer)
|
|
261
|
-
}
|
|
209
|
+
if (headerBlocks) blocks.push(...headerBlocks)
|
|
210
|
+
blocks.push(...this.bodyBlocks)
|
|
211
|
+
if (footerBlocks) blocks.push(...footerBlocks)
|
|
262
212
|
|
|
263
213
|
return blocks
|
|
264
214
|
}
|
|
265
215
|
|
|
266
216
|
/**
|
|
267
|
-
* Get
|
|
217
|
+
* Get body blocks
|
|
268
218
|
* @returns {Block[]}
|
|
269
219
|
*/
|
|
270
220
|
getBodyBlocks() {
|
|
271
|
-
return this.
|
|
221
|
+
return this.bodyBlocks
|
|
272
222
|
}
|
|
273
223
|
|
|
274
224
|
/**
|
|
275
|
-
* Get header blocks (respects layout preference)
|
|
225
|
+
* Get header blocks (respects layout preference, delegates to website)
|
|
276
226
|
* @returns {Block[]|null}
|
|
277
227
|
*/
|
|
278
228
|
getHeaderBlocks() {
|
|
279
229
|
if (!this.hasHeader()) return null
|
|
280
|
-
return this.
|
|
230
|
+
return this.website.getHeaderBlocks()
|
|
281
231
|
}
|
|
282
232
|
|
|
283
233
|
/**
|
|
284
|
-
* Get footer blocks (respects layout preference)
|
|
234
|
+
* Get footer blocks (respects layout preference, delegates to website)
|
|
285
235
|
* @returns {Block[]|null}
|
|
286
236
|
*/
|
|
287
237
|
getFooterBlocks() {
|
|
288
238
|
if (!this.hasFooter()) return null
|
|
289
|
-
return this.
|
|
239
|
+
return this.website.getFooterBlocks()
|
|
290
240
|
}
|
|
291
241
|
|
|
292
242
|
/**
|
|
293
|
-
* Get left panel blocks (respects layout preference)
|
|
243
|
+
* Get left panel blocks (respects layout preference, delegates to website)
|
|
294
244
|
* @returns {Block[]|null}
|
|
295
245
|
*/
|
|
296
246
|
getLeftBlocks() {
|
|
297
247
|
if (!this.hasLeftPanel()) return null
|
|
298
|
-
return this.
|
|
248
|
+
return this.website.getLeftBlocks()
|
|
299
249
|
}
|
|
300
250
|
|
|
301
251
|
/**
|
|
302
|
-
* Get right panel blocks (respects layout preference)
|
|
252
|
+
* Get right panel blocks (respects layout preference, delegates to website)
|
|
303
253
|
* @returns {Block[]|null}
|
|
304
254
|
*/
|
|
305
255
|
getRightBlocks() {
|
|
306
256
|
if (!this.hasRightPanel()) return null
|
|
307
|
-
return this.
|
|
257
|
+
return this.website.getRightBlocks()
|
|
308
258
|
}
|
|
309
259
|
|
|
310
260
|
/**
|
|
@@ -313,7 +263,7 @@ export default class Page {
|
|
|
313
263
|
* @deprecated Use getHeaderBlocks() instead
|
|
314
264
|
*/
|
|
315
265
|
getHeader() {
|
|
316
|
-
return this.
|
|
266
|
+
return this.getHeaderBlocks()?.[0] || null
|
|
317
267
|
}
|
|
318
268
|
|
|
319
269
|
/**
|
|
@@ -322,7 +272,7 @@ export default class Page {
|
|
|
322
272
|
* @deprecated Use getFooterBlocks() instead
|
|
323
273
|
*/
|
|
324
274
|
getFooter() {
|
|
325
|
-
return this.
|
|
275
|
+
return this.getFooterBlocks()?.[0] || null
|
|
326
276
|
}
|
|
327
277
|
|
|
328
278
|
/**
|
|
@@ -330,11 +280,11 @@ export default class Page {
|
|
|
330
280
|
*/
|
|
331
281
|
resetBlockStates() {
|
|
332
282
|
const allBlocks = [
|
|
333
|
-
...(this.
|
|
334
|
-
...this.
|
|
335
|
-
...(this.
|
|
336
|
-
...(this.
|
|
337
|
-
...(this.
|
|
283
|
+
...(this.getHeaderBlocks() || []),
|
|
284
|
+
...this.bodyBlocks,
|
|
285
|
+
...(this.getFooterBlocks() || []),
|
|
286
|
+
...(this.getLeftBlocks() || []),
|
|
287
|
+
...(this.getRightBlocks() || []),
|
|
338
288
|
]
|
|
339
289
|
|
|
340
290
|
for (const block of allBlocks) {
|
|
@@ -435,7 +385,7 @@ export default class Page {
|
|
|
435
385
|
* @returns {boolean}
|
|
436
386
|
*/
|
|
437
387
|
hasContent() {
|
|
438
|
-
return this.
|
|
388
|
+
return this.bodyBlocks.length > 0
|
|
439
389
|
}
|
|
440
390
|
|
|
441
391
|
// ─────────────────────────────────────────────────────────────────
|
package/src/website.js
CHANGED
|
@@ -18,12 +18,12 @@ export default class Website {
|
|
|
18
18
|
this.description = config.description || ''
|
|
19
19
|
this.url = config.url || ''
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
this.headerPage = header
|
|
24
|
-
this.footerPage = footer
|
|
25
|
-
this.leftPage = left
|
|
26
|
-
this.rightPage = right
|
|
21
|
+
// Layout panels as Page objects (header, footer, left, right)
|
|
22
|
+
// They build their own blocks lazily, just like regular pages
|
|
23
|
+
this.headerPage = header ? new Page(header, 'header', this) : null
|
|
24
|
+
this.footerPage = footer ? new Page(footer, 'footer', this) : null
|
|
25
|
+
this.leftPage = left ? new Page(left, 'left', this) : null
|
|
26
|
+
this.rightPage = right ? new Page(right, 'right', this) : null
|
|
27
27
|
|
|
28
28
|
// Store 404 page (for SPA routing)
|
|
29
29
|
// Convention: pages/404/ directory
|
|
@@ -44,8 +44,7 @@ export default class Website {
|
|
|
44
44
|
this._dynamicPageCache = new Map()
|
|
45
45
|
|
|
46
46
|
this.pages = regularPages.map(
|
|
47
|
-
(page, index) =>
|
|
48
|
-
new Page(page, index, this, this.headerPage, this.footerPage, this.leftPage, this.rightPage)
|
|
47
|
+
(page, index) => new Page(page, index, this)
|
|
49
48
|
)
|
|
50
49
|
|
|
51
50
|
// Build parent-child relationships based on route structure
|
|
@@ -416,15 +415,7 @@ export default class Website {
|
|
|
416
415
|
}
|
|
417
416
|
|
|
418
417
|
// Create the page instance
|
|
419
|
-
const dynamicPage = new Page(
|
|
420
|
-
pageData,
|
|
421
|
-
`dynamic-${concreteRoute}`,
|
|
422
|
-
this,
|
|
423
|
-
this.headerPage,
|
|
424
|
-
this.footerPage,
|
|
425
|
-
this.leftPage,
|
|
426
|
-
this.rightPage
|
|
427
|
-
)
|
|
418
|
+
const dynamicPage = new Page(pageData, `dynamic-${concreteRoute}`, this)
|
|
428
419
|
|
|
429
420
|
// Copy parent reference from template
|
|
430
421
|
dynamicPage.parent = templatePage.parent
|
|
@@ -472,6 +463,33 @@ export default class Website {
|
|
|
472
463
|
return globalThis.uniweb?.foundationConfig?.Layout || null
|
|
473
464
|
}
|
|
474
465
|
|
|
466
|
+
/**
|
|
467
|
+
* Get default block type from foundation config
|
|
468
|
+
*/
|
|
469
|
+
getDefaultBlockType() {
|
|
470
|
+
return globalThis.uniweb?.foundationConfig?.defaultType || 'Section'
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// ─────────────────────────────────────────────────────────────────
|
|
474
|
+
// Layout Blocks (from layout panel pages)
|
|
475
|
+
// ─────────────────────────────────────────────────────────────────
|
|
476
|
+
|
|
477
|
+
getHeaderBlocks() {
|
|
478
|
+
return this.headerPage?.bodyBlocks || null
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
getFooterBlocks() {
|
|
482
|
+
return this.footerPage?.bodyBlocks || null
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
getLeftBlocks() {
|
|
486
|
+
return this.leftPage?.bodyBlocks || null
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
getRightBlocks() {
|
|
490
|
+
return this.rightPage?.bodyBlocks || null
|
|
491
|
+
}
|
|
492
|
+
|
|
475
493
|
/**
|
|
476
494
|
* Get remote props from foundation config
|
|
477
495
|
*/
|