@museumwnf/viewer-core 1.14.0 → 1.15.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/LICENSE.md +44 -44
- package/README.md +658 -635
- package/package.json +50 -50
- package/src/AppRoot.vue +58 -58
- package/src/catalogue/dates.js +209 -209
- package/src/catalogue/facets.js +61 -61
- package/src/catalogue/keywordIndex.js +289 -289
- package/src/catalogue/listQuery.js +100 -100
- package/src/catalogue/pagination.js +57 -57
- package/src/catalogue/searchLanguage.js +32 -32
- package/src/catalogue/timeline.js +220 -220
- package/src/composables/useCatalogueData.js +141 -141
- package/src/composables/useDataPackage.js +98 -98
- package/src/composables/useEntities.js +100 -100
- package/src/composables/useRecordLanguage.js +71 -71
- package/src/conventions.js +252 -148
- package/src/createViewer.js +29 -29
- package/src/i18n/I18nText.vue +17 -17
- package/src/i18n/I18nTextInline.vue +17 -17
- package/src/i18n/index.js +88 -88
- package/src/i18n/language.js +127 -127
- package/src/i18n/markdown.js +265 -265
- package/src/index.js +51 -50
- package/src/injectionKeys.js +1 -1
- package/src/languages.js +49 -49
- package/src/legacy/index.js +58 -58
- package/src/record/collectionTree.js +307 -307
- package/src/record/derivations.js +154 -154
- package/src/record/partners.js +87 -87
- package/src/record/recordSheet.js +231 -231
- package/src/rights.js +53 -53
- package/src/router/index.js +138 -138
- package/src/siteConfig.js +37 -37
- package/src/styles/base.css +49 -49
- package/src/testing/checkOfferedLanguages.js +67 -67
- package/src/testing/index.js +3 -3
- package/src/testing/smoke.js +103 -103
- package/src/testing/viteConfig.js +90 -90
- package/src/views/DetailView.vue +53 -53
- package/src/views/HomeView.vue +20 -20
- package/src/views/ListView.vue +61 -61
- package/src/views/NotFoundView.vue +8 -8
- package/src/vite.js +8 -8
package/src/languages.js
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import { useDataPackage } from './composables/useDataPackage.js'
|
|
2
|
-
|
|
3
|
-
// Which languages a website offers, decided by one rule for every website: the
|
|
4
|
-
// languages the package declares for the site, in the package's order, kept
|
|
5
|
-
// only where the site's items actually have content.
|
|
6
|
-
|
|
7
|
-
export function declaredSiteLanguages(manifest) {
|
|
8
|
-
const declared = manifest?.site?.languages
|
|
9
|
-
if (!Array.isArray(declared)) return null
|
|
10
|
-
return declared.map((entry) => (typeof entry === 'string' ? entry : entry?.code)).filter(Boolean)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* `declared ∩ availableLanguages(entity)`, in the declared order. `declared`
|
|
15
|
-
* defaults to `manifest.site.languages`; a package that carries no such list
|
|
16
|
-
* offers every language its items have content in, alphabetically.
|
|
17
|
-
*
|
|
18
|
-
* A website may pass its own `declared` list to narrow what the package
|
|
19
|
-
* declares — a language that covers a handful of item sheets is worse than no
|
|
20
|
-
* switcher — but never to widen it: a code the package does not declare for
|
|
21
|
-
* this site is dropped even where some items carry it. That keeps the
|
|
22
|
-
* decision of which languages a site *can* offer in the package, and only the
|
|
23
|
-
* decision of which of those it *does* offer in the site.
|
|
24
|
-
*/
|
|
25
|
-
export function offeredLanguages({ declared, entity = 'items', manifest, availableLanguages } = {}) {
|
|
26
|
-
const pkg = useDataPackage()
|
|
27
|
-
const withContent = (availableLanguages ?? pkg.availableLanguages)(entity)
|
|
28
|
-
const fromPackage = declaredSiteLanguages(manifest ?? pkg.manifest)
|
|
29
|
-
if (!declared && !fromPackage) return [...withContent].sort()
|
|
30
|
-
const list = declared
|
|
31
|
-
? fromPackage
|
|
32
|
-
? declared.filter((code) => fromPackage.includes(code))
|
|
33
|
-
: declared
|
|
34
|
-
: fromPackage
|
|
35
|
-
return list.filter((code) => withContent.includes(code))
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* `[{ code, label }]` for the language switcher: the native label the package
|
|
40
|
-
* declares for each code, the code itself in capitals where it declares none.
|
|
41
|
-
*/
|
|
42
|
-
export function languageLabels(codes, manifest) {
|
|
43
|
-
const declared = (manifest ?? useDataPackage().manifest)?.site?.languages
|
|
44
|
-
const labels = new Map()
|
|
45
|
-
for (const entry of Array.isArray(declared) ? declared : []) {
|
|
46
|
-
if (entry && typeof entry === 'object' && entry.code) labels.set(entry.code, entry.label)
|
|
47
|
-
}
|
|
48
|
-
return codes.map((code) => ({ code, label: labels.get(code) || code.toUpperCase() }))
|
|
49
|
-
}
|
|
1
|
+
import { useDataPackage } from './composables/useDataPackage.js'
|
|
2
|
+
|
|
3
|
+
// Which languages a website offers, decided by one rule for every website: the
|
|
4
|
+
// languages the package declares for the site, in the package's order, kept
|
|
5
|
+
// only where the site's items actually have content.
|
|
6
|
+
|
|
7
|
+
export function declaredSiteLanguages(manifest) {
|
|
8
|
+
const declared = manifest?.site?.languages
|
|
9
|
+
if (!Array.isArray(declared)) return null
|
|
10
|
+
return declared.map((entry) => (typeof entry === 'string' ? entry : entry?.code)).filter(Boolean)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* `declared ∩ availableLanguages(entity)`, in the declared order. `declared`
|
|
15
|
+
* defaults to `manifest.site.languages`; a package that carries no such list
|
|
16
|
+
* offers every language its items have content in, alphabetically.
|
|
17
|
+
*
|
|
18
|
+
* A website may pass its own `declared` list to narrow what the package
|
|
19
|
+
* declares — a language that covers a handful of item sheets is worse than no
|
|
20
|
+
* switcher — but never to widen it: a code the package does not declare for
|
|
21
|
+
* this site is dropped even where some items carry it. That keeps the
|
|
22
|
+
* decision of which languages a site *can* offer in the package, and only the
|
|
23
|
+
* decision of which of those it *does* offer in the site.
|
|
24
|
+
*/
|
|
25
|
+
export function offeredLanguages({ declared, entity = 'items', manifest, availableLanguages } = {}) {
|
|
26
|
+
const pkg = useDataPackage()
|
|
27
|
+
const withContent = (availableLanguages ?? pkg.availableLanguages)(entity)
|
|
28
|
+
const fromPackage = declaredSiteLanguages(manifest ?? pkg.manifest)
|
|
29
|
+
if (!declared && !fromPackage) return [...withContent].sort()
|
|
30
|
+
const list = declared
|
|
31
|
+
? fromPackage
|
|
32
|
+
? declared.filter((code) => fromPackage.includes(code))
|
|
33
|
+
: declared
|
|
34
|
+
: fromPackage
|
|
35
|
+
return list.filter((code) => withContent.includes(code))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* `[{ code, label }]` for the language switcher: the native label the package
|
|
40
|
+
* declares for each code, the code itself in capitals where it declares none.
|
|
41
|
+
*/
|
|
42
|
+
export function languageLabels(codes, manifest) {
|
|
43
|
+
const declared = (manifest ?? useDataPackage().manifest)?.site?.languages
|
|
44
|
+
const labels = new Map()
|
|
45
|
+
for (const entry of Array.isArray(declared) ? declared : []) {
|
|
46
|
+
if (entry && typeof entry === 'object' && entry.code) labels.set(entry.code, entry.label)
|
|
47
|
+
}
|
|
48
|
+
return codes.map((code) => ({ code, label: labels.get(code) || code.toUpperCase() }))
|
|
49
|
+
}
|
package/src/legacy/index.js
CHANGED
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
// The legacy URL mappings the four DXA sites decode from `backward_compatibility`
|
|
2
|
-
// — near-identically, because nothing shared did it before this. Pure, no Vue:
|
|
3
|
-
// a site's own composable stays the reactive wrapper around its own
|
|
4
|
-
// `partners` / `countries` / `items` refs, and hands this module plain lists.
|
|
5
|
-
// It is a separate entry point rather than part of the package root because
|
|
6
|
-
// only a site built against DXA's legacy URL shapes needs it — the standalone
|
|
7
|
-
// sites never import it.
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* A partner's legacy identity, `{ legacyId, countryCode }`, read from its
|
|
11
|
-
* `backward_compatibility`.
|
|
12
|
-
*
|
|
13
|
-
* The DXA sites carry `mwnf3:museums:Mus21:ua` — the third and fourth
|
|
14
|
-
* colon-separated segments are the legacy id and the two-letter country
|
|
15
|
-
* code. Sharing History keys its partners differently —
|
|
16
|
-
* `mwnf3_sharing_history:sh_partners:at_01_d` has no country segment at
|
|
17
|
-
* all; the country is the key's own prefix, so that shape is decoded apart
|
|
18
|
-
* rather than by segment index. `countries` (a country's own `code`, its
|
|
19
|
-
* `backward_compatibility`) is the fallback for a partner carrying no
|
|
20
|
-
* `backward_compatibility` at all: its `country_id` resolved to the same
|
|
21
|
-
* two-letter code, so a package still missing the legacy key can be routed
|
|
22
|
-
* by the country a visitor is already on.
|
|
23
|
-
*/
|
|
24
|
-
export function partnerKey(partner, countries = []) {
|
|
25
|
-
const parts = String(partner?.backward_compatibility ?? '').split(':')
|
|
26
|
-
if (parts[0] === 'mwnf3_sharing_history') {
|
|
27
|
-
const key = parts[2] ?? partner?.id ?? ''
|
|
28
|
-
return { legacyId: key, countryCode: key.split('_')[0] ?? '' }
|
|
29
|
-
}
|
|
30
|
-
if (parts.length > 1) {
|
|
31
|
-
return { legacyId: parts[2] ?? partner?.id ?? '', countryCode: parts[3] ?? '' }
|
|
32
|
-
}
|
|
33
|
-
const country = countries.find((c) => c.id === partner?.country_id)
|
|
34
|
-
return { legacyId: partner?.id ?? '', countryCode: country?.code ?? '' }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The partner a legacy `/partner/:country/:id` route names, or null — the
|
|
39
|
-
* reverse of `partnerKey`, scanning `partners` for the one whose key
|
|
40
|
-
* matches both parts.
|
|
41
|
-
*/
|
|
42
|
-
export function partnerFromKey(partners, countries, countryCode, legacyId) {
|
|
43
|
-
return (partners ?? []).find((partner) => {
|
|
44
|
-
const key = partnerKey(partner, countries)
|
|
45
|
-
return key.legacyId === legacyId && key.countryCode === countryCode
|
|
46
|
-
}) ?? null
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* The item a legacy dbUid *path* names, or null. The public item URL keeps
|
|
51
|
-
* the dbUid path, which is exactly `backward_compatibility` with `:`
|
|
52
|
-
* swapped for `/` — matched case-insensitively, because Sharing History
|
|
53
|
-
* stores its keys lowercase.
|
|
54
|
-
*/
|
|
55
|
-
export function itemFromUidPath(items, path) {
|
|
56
|
-
const needle = String(path ?? '').split('/').join(':').toLowerCase()
|
|
57
|
-
return (items ?? []).find((item) => item?.backward_compatibility?.toLowerCase() === needle) ?? null
|
|
58
|
-
}
|
|
1
|
+
// The legacy URL mappings the four DXA sites decode from `backward_compatibility`
|
|
2
|
+
// — near-identically, because nothing shared did it before this. Pure, no Vue:
|
|
3
|
+
// a site's own composable stays the reactive wrapper around its own
|
|
4
|
+
// `partners` / `countries` / `items` refs, and hands this module plain lists.
|
|
5
|
+
// It is a separate entry point rather than part of the package root because
|
|
6
|
+
// only a site built against DXA's legacy URL shapes needs it — the standalone
|
|
7
|
+
// sites never import it.
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A partner's legacy identity, `{ legacyId, countryCode }`, read from its
|
|
11
|
+
* `backward_compatibility`.
|
|
12
|
+
*
|
|
13
|
+
* The DXA sites carry `mwnf3:museums:Mus21:ua` — the third and fourth
|
|
14
|
+
* colon-separated segments are the legacy id and the two-letter country
|
|
15
|
+
* code. Sharing History keys its partners differently —
|
|
16
|
+
* `mwnf3_sharing_history:sh_partners:at_01_d` has no country segment at
|
|
17
|
+
* all; the country is the key's own prefix, so that shape is decoded apart
|
|
18
|
+
* rather than by segment index. `countries` (a country's own `code`, its
|
|
19
|
+
* `backward_compatibility`) is the fallback for a partner carrying no
|
|
20
|
+
* `backward_compatibility` at all: its `country_id` resolved to the same
|
|
21
|
+
* two-letter code, so a package still missing the legacy key can be routed
|
|
22
|
+
* by the country a visitor is already on.
|
|
23
|
+
*/
|
|
24
|
+
export function partnerKey(partner, countries = []) {
|
|
25
|
+
const parts = String(partner?.backward_compatibility ?? '').split(':')
|
|
26
|
+
if (parts[0] === 'mwnf3_sharing_history') {
|
|
27
|
+
const key = parts[2] ?? partner?.id ?? ''
|
|
28
|
+
return { legacyId: key, countryCode: key.split('_')[0] ?? '' }
|
|
29
|
+
}
|
|
30
|
+
if (parts.length > 1) {
|
|
31
|
+
return { legacyId: parts[2] ?? partner?.id ?? '', countryCode: parts[3] ?? '' }
|
|
32
|
+
}
|
|
33
|
+
const country = countries.find((c) => c.id === partner?.country_id)
|
|
34
|
+
return { legacyId: partner?.id ?? '', countryCode: country?.code ?? '' }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* The partner a legacy `/partner/:country/:id` route names, or null — the
|
|
39
|
+
* reverse of `partnerKey`, scanning `partners` for the one whose key
|
|
40
|
+
* matches both parts.
|
|
41
|
+
*/
|
|
42
|
+
export function partnerFromKey(partners, countries, countryCode, legacyId) {
|
|
43
|
+
return (partners ?? []).find((partner) => {
|
|
44
|
+
const key = partnerKey(partner, countries)
|
|
45
|
+
return key.legacyId === legacyId && key.countryCode === countryCode
|
|
46
|
+
}) ?? null
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The item a legacy dbUid *path* names, or null. The public item URL keeps
|
|
51
|
+
* the dbUid path, which is exactly `backward_compatibility` with `:`
|
|
52
|
+
* swapped for `/` — matched case-insensitively, because Sharing History
|
|
53
|
+
* stores its keys lowercase.
|
|
54
|
+
*/
|
|
55
|
+
export function itemFromUidPath(items, path) {
|
|
56
|
+
const needle = String(path ?? '').split('/').join(':').toLowerCase()
|
|
57
|
+
return (items ?? []).find((item) => item?.backward_compatibility?.toLowerCase() === needle) ?? null
|
|
58
|
+
}
|