@aglyn/aglyn 1.0.0-beta.146 → 1.0.0-beta.147
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 +10 -10
- package/src/lib/app-utils/collection-entries.d.ts +43 -0
- package/src/lib/app-utils/collection-entries.js +48 -1
- package/src/lib/app-utils/collection-entries.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.js +1 -1
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/aglyn",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.147",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -33,15 +33,15 @@
|
|
|
33
33
|
"./package.json": "./package.json"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@aglyn/shared-data-enums": "1.0.0-beta.
|
|
37
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
38
|
-
"@aglyn/shared-data-types": "1.0.0-beta.
|
|
39
|
-
"@aglyn/shared-util-email": "1.0.0-beta.
|
|
40
|
-
"@aglyn/shared-util-http": "1.0.0-beta.
|
|
41
|
-
"@aglyn/shared-util-logger": "1.0.0-beta.
|
|
42
|
-
"@aglyn/shared-util-timestamp": "1.0.0-beta.
|
|
43
|
-
"@aglyn/shared-util-tools": "1.0.0-beta.
|
|
44
|
-
"@aglyn/shared-util-vendor": "1.0.0-beta.
|
|
36
|
+
"@aglyn/shared-data-enums": "1.0.0-beta.147",
|
|
37
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.147",
|
|
38
|
+
"@aglyn/shared-data-types": "1.0.0-beta.147",
|
|
39
|
+
"@aglyn/shared-util-email": "1.0.0-beta.147",
|
|
40
|
+
"@aglyn/shared-util-http": "1.0.0-beta.147",
|
|
41
|
+
"@aglyn/shared-util-logger": "1.0.0-beta.147",
|
|
42
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.147",
|
|
43
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.147",
|
|
44
|
+
"@aglyn/shared-util-vendor": "1.0.0-beta.147",
|
|
45
45
|
"@data-driven-forms/react-form-renderer": "^4.2.0",
|
|
46
46
|
"@msgpack/msgpack": "^3.1.3",
|
|
47
47
|
"@types/unist": "^3.0.3",
|
|
@@ -140,6 +140,38 @@ export declare const COLLECTION_LIST_PAGE_SIZE = 10;
|
|
|
140
140
|
* empty collection still has a page 1 (AGL-620).
|
|
141
141
|
*/
|
|
142
142
|
export declare function collectionTotalPages(total: number, perPage: number): number;
|
|
143
|
+
/**
|
|
144
|
+
* The slice of a listing's entries that the page named by `pagination`
|
|
145
|
+
* actually shows (AGL-3213).
|
|
146
|
+
*
|
|
147
|
+
* The loader hands the WHOLE narrowed set down to compose, because
|
|
148
|
+
* {@link expandCollectionEntries} does its own windowing off the block's
|
|
149
|
+
* props — a Collection entries block may carry its own `perPage`, its own
|
|
150
|
+
* pinned `page`, a `firstPageOnly` switch and its own filters, none of which
|
|
151
|
+
* this function can see. Slicing before compose would double-window and empty
|
|
152
|
+
* every page after the first.
|
|
153
|
+
*
|
|
154
|
+
* Everything the loader serializes into page PROPS is downstream of compose,
|
|
155
|
+
* and there the full set is not merely wasted bytes — it is a false
|
|
156
|
+
* statement. The `ItemList` JSON-LD numbers its items
|
|
157
|
+
* `(page - 1) * perPage + index + 1` on the premise that `entries` is the
|
|
158
|
+
* window; handed all one hundred, `/changelog/page/7` published
|
|
159
|
+
* `numberOfItems: 100` and positions 61 through 160, most of them past the
|
|
160
|
+
* end of the collection. The legacy fallback renderer read it the same way
|
|
161
|
+
* and rendered the whole list on every page.
|
|
162
|
+
*
|
|
163
|
+
* So: the loader keeps the full set until compose has had it, and narrows
|
|
164
|
+
* HERE on the way into props, where `pagination` is the route's own answer to
|
|
165
|
+
* which page this is.
|
|
166
|
+
*
|
|
167
|
+
* An unpaginated listing (an entry route, the RSS feed) passes no pagination
|
|
168
|
+
* and gets its entries back untouched.
|
|
169
|
+
*/
|
|
170
|
+
export declare function collectionEntriesPageWindow<T>(entries: readonly T[], pagination: {
|
|
171
|
+
page?: number;
|
|
172
|
+
perPage?: number;
|
|
173
|
+
windowStart?: number;
|
|
174
|
+
} | null | undefined): T[];
|
|
143
175
|
/** Default/most related posts a Related posts block renders (AGL-582). */
|
|
144
176
|
export declare const COLLECTION_RELATED_DEFAULT_LIMIT = 3;
|
|
145
177
|
export declare const COLLECTION_RELATED_MAX = 12;
|
|
@@ -334,6 +366,17 @@ export interface CollectionEntriesSource {
|
|
|
334
366
|
* wins: that is a deliberately pinned window, not a paginated list.
|
|
335
367
|
*/
|
|
336
368
|
page?: number;
|
|
369
|
+
/**
|
|
370
|
+
* The absolute index `entries[0]` holds in the collection's own order
|
|
371
|
+
* (AGL-3213). Zero everywhere except a listing page past the cached read's
|
|
372
|
+
* bound, which is served by a window read for that page alone.
|
|
373
|
+
*
|
|
374
|
+
* Without it a windowed source is silently empty: every consumer here
|
|
375
|
+
* slices `[(page - 1) * perPage, …)` on the premise that `entries` starts
|
|
376
|
+
* at the beginning of the collection, so page 11 of a windowed ten-entry
|
|
377
|
+
* source slices from 100 and renders nothing.
|
|
378
|
+
*/
|
|
379
|
+
windowStart?: number;
|
|
337
380
|
}
|
|
338
381
|
/**
|
|
339
382
|
* Display name of an entry's category (AGL-582): the `categoryId` lookup
|
|
@@ -133,6 +133,48 @@ export const COLLECTION_CATEGORY_ROUTE_SEGMENT = 'category';
|
|
|
133
133
|
if (perPage <= 0) return 1;
|
|
134
134
|
return Math.max(1, Math.ceil(total / perPage));
|
|
135
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* The slice of a listing's entries that the page named by `pagination`
|
|
138
|
+
* actually shows (AGL-3213).
|
|
139
|
+
*
|
|
140
|
+
* The loader hands the WHOLE narrowed set down to compose, because
|
|
141
|
+
* {@link expandCollectionEntries} does its own windowing off the block's
|
|
142
|
+
* props — a Collection entries block may carry its own `perPage`, its own
|
|
143
|
+
* pinned `page`, a `firstPageOnly` switch and its own filters, none of which
|
|
144
|
+
* this function can see. Slicing before compose would double-window and empty
|
|
145
|
+
* every page after the first.
|
|
146
|
+
*
|
|
147
|
+
* Everything the loader serializes into page PROPS is downstream of compose,
|
|
148
|
+
* and there the full set is not merely wasted bytes — it is a false
|
|
149
|
+
* statement. The `ItemList` JSON-LD numbers its items
|
|
150
|
+
* `(page - 1) * perPage + index + 1` on the premise that `entries` is the
|
|
151
|
+
* window; handed all one hundred, `/changelog/page/7` published
|
|
152
|
+
* `numberOfItems: 100` and positions 61 through 160, most of them past the
|
|
153
|
+
* end of the collection. The legacy fallback renderer read it the same way
|
|
154
|
+
* and rendered the whole list on every page.
|
|
155
|
+
*
|
|
156
|
+
* So: the loader keeps the full set until compose has had it, and narrows
|
|
157
|
+
* HERE on the way into props, where `pagination` is the route's own answer to
|
|
158
|
+
* which page this is.
|
|
159
|
+
*
|
|
160
|
+
* An unpaginated listing (an entry route, the RSS feed) passes no pagination
|
|
161
|
+
* and gets its entries back untouched.
|
|
162
|
+
*/ export function collectionEntriesPageWindow(entries, pagination) {
|
|
163
|
+
const perPage = Number(pagination == null ? void 0 : pagination.perPage);
|
|
164
|
+
if (!Number.isFinite(perPage) || perPage <= 0) return [
|
|
165
|
+
...entries
|
|
166
|
+
];
|
|
167
|
+
const pageRaw = Number(pagination == null ? void 0 : pagination.page);
|
|
168
|
+
const page = Number.isFinite(pageRaw) && pageRaw >= 1 ? Math.floor(pageRaw) : 1;
|
|
169
|
+
// `windowStart` is where `entries` begins in the collection's own order
|
|
170
|
+
// (AGL-3213). A listing past the cached read's bound is served by a window
|
|
171
|
+
// read for that page alone, and slicing it from the page's absolute offset
|
|
172
|
+
// would return nothing.
|
|
173
|
+
const startRaw = Number(pagination == null ? void 0 : pagination.windowStart);
|
|
174
|
+
const windowStart = Number.isFinite(startRaw) && startRaw > 0 ? Math.floor(startRaw) : 0;
|
|
175
|
+
const start = Math.max(0, (page - 1) * Math.floor(perPage) - windowStart);
|
|
176
|
+
return entries.slice(start, start + Math.floor(perPage));
|
|
177
|
+
}
|
|
136
178
|
/** Default/most related posts a Related posts block renders (AGL-582). */ export const COLLECTION_RELATED_DEFAULT_LIMIT = 3;
|
|
137
179
|
export const COLLECTION_RELATED_MAX = 12;
|
|
138
180
|
/** Most categories a collection's taxonomy holds (AGL-582). */ export const COLLECTION_CATEGORIES_MAX = 50;
|
|
@@ -779,7 +821,12 @@ const POSITIVE_INTEGER = /^[1-9]\d*$/;
|
|
|
779
821
|
// counting it, because the count cannot see a read that came back full
|
|
780
822
|
// and was then thinned by the liveness gate.
|
|
781
823
|
const sourceCapped = collectionSourceIsBounded(source);
|
|
782
|
-
|
|
824
|
+
// Where this source's first entry sits in the collection (AGL-3213):
|
|
825
|
+
// zero for a whole read, and the page's own offset for a windowed one.
|
|
826
|
+
const windowStartRaw = Number(source.windowStart);
|
|
827
|
+
const windowStart = Number.isFinite(windowStartRaw) && windowStartRaw > 0 ? Math.floor(windowStartRaw) : 0;
|
|
828
|
+
const pageStart = perPage ? Math.max(0, (page - 1) * perPage - windowStart) : 0;
|
|
829
|
+
const windowed = suppressedBeyondFirstPage ? [] : perPage ? filtered.slice(pageStart, pageStart + perPage) : filtered.slice(0, limit);
|
|
783
830
|
const childIds = [];
|
|
784
831
|
windowed.forEach((entry, index)=>{
|
|
785
832
|
const prefix = `${COLLECTION_ENTRIES_NODE_ID_PREFIX}${containerId}__${index}__`;
|