@uniweb/projections 0.3.1 → 0.3.2
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 +3 -3
- package/src/search/collections.js +34 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/projections",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Projections of a Uniweb site's content — agent index, per-page markdown, search index. Pure JS, runs anywhere.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"node": ">=20.19"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@uniweb/
|
|
35
|
-
"@uniweb/
|
|
34
|
+
"@uniweb/core": "^0.9.0",
|
|
35
|
+
"@uniweb/content-writer": "^0.3.3"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"vitest": "^4.1.7",
|
|
@@ -6,26 +6,57 @@
|
|
|
6
6
|
* per-record detail files into each item before calling this function.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Compose a record's route the way the build does, for the sources that have
|
|
11
|
+
* not already done it.
|
|
12
|
+
*
|
|
13
|
+
* `collections[name].route` is authored in `site.yml` (see the blog and
|
|
14
|
+
* international templates). When it is set, the build's collection processor
|
|
15
|
+
* already stamps `item.route` on every record — so the route below is a
|
|
16
|
+
* *fallback* for records that arrived without one (an API-backed collection a
|
|
17
|
+
* host assembled itself), never a second opinion about records that have one.
|
|
18
|
+
*
|
|
19
|
+
* The trailing-slash strip matches `collectItems` in
|
|
20
|
+
* `@uniweb/build`'s `site/collection-processor.js`. Without it a `route:
|
|
21
|
+
* /blog/` authored with a slash yields `/blog//my-post` here and
|
|
22
|
+
* `/blog/my-post` there — two answers to one question, on a value nobody
|
|
23
|
+
* checks until a visitor clicks it.
|
|
24
|
+
*/
|
|
25
|
+
function composeRoute(configRoute, slug) {
|
|
26
|
+
if (typeof configRoute !== 'string' || configRoute === '') return undefined
|
|
27
|
+
return `${configRoute.replace(/\/$/, '')}/${slug}`
|
|
28
|
+
}
|
|
29
|
+
|
|
9
30
|
/**
|
|
10
31
|
* @param {string} name - Collection name (e.g. "articles")
|
|
11
32
|
* @param {Object} config - Collection config from site.yml (config.collections[name])
|
|
12
|
-
* @param {Object} collectionData - Parsed cascade JSON (`data/{name}.json`)
|
|
33
|
+
* @param {Object[]|Object} collectionData - Parsed cascade JSON (`data/{name}.json`),
|
|
34
|
+
* which the build writes as a bare array. The `{ items: [...] }` envelope is
|
|
35
|
+
* accepted too, since a host fetching the collection from a backend may carry one.
|
|
13
36
|
* @param {string} locale - Locale code (e.g. "en")
|
|
14
37
|
* @returns {Object} Collection search index
|
|
15
38
|
*/
|
|
16
39
|
export function generateCollectionIndex(name, config, collectionData, locale) {
|
|
17
40
|
const fields = config.search?.fields || ['title']
|
|
18
41
|
const weight = config.search?.weight ?? 0.7
|
|
19
|
-
const items = collectionData
|
|
42
|
+
const items = Array.isArray(collectionData)
|
|
43
|
+
? collectionData
|
|
44
|
+
: collectionData?.items || []
|
|
20
45
|
|
|
21
46
|
const entries = items.map(item => {
|
|
22
47
|
const content = fields.map(f => item[f] || '').filter(Boolean).join(' ')
|
|
23
48
|
const slug = item.slug || item.id || String(item.title || '').toLowerCase().replace(/\s+/g, '-')
|
|
49
|
+
// The record's own route wins: the build already resolved it against the
|
|
50
|
+
// same config, so recomputing here could only disagree. `route` is omitted
|
|
51
|
+
// entirely when neither source can supply one — a missing key is detectable
|
|
52
|
+
// by a consumer, where the string "undefined/my-post" is a link that ranks
|
|
53
|
+
// correctly, looks plausible, and 404s on click.
|
|
54
|
+
const route = item.route || composeRoute(config.route, slug)
|
|
24
55
|
return {
|
|
25
56
|
id: `collection:${name}:${slug}`,
|
|
26
57
|
type: 'collection',
|
|
27
58
|
collection: name,
|
|
28
|
-
route
|
|
59
|
+
...(route ? { route } : {}),
|
|
29
60
|
title: item.title || item.name || slug,
|
|
30
61
|
content,
|
|
31
62
|
excerpt: content.length > 160
|