@museumwnf/viewer-core 1.14.0 → 1.15.1

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.
Files changed (43) hide show
  1. package/LICENSE.md +44 -44
  2. package/README.md +658 -635
  3. package/package.json +50 -50
  4. package/src/AppRoot.vue +58 -58
  5. package/src/catalogue/dates.js +209 -209
  6. package/src/catalogue/facets.js +61 -61
  7. package/src/catalogue/keywordIndex.js +289 -289
  8. package/src/catalogue/listQuery.js +100 -100
  9. package/src/catalogue/pagination.js +57 -57
  10. package/src/catalogue/searchLanguage.js +32 -32
  11. package/src/catalogue/timeline.js +220 -220
  12. package/src/composables/useCatalogueData.js +141 -141
  13. package/src/composables/useDataPackage.js +98 -98
  14. package/src/composables/useEntities.js +100 -100
  15. package/src/composables/useRecordLanguage.js +71 -71
  16. package/src/conventions.js +252 -148
  17. package/src/createViewer.js +29 -29
  18. package/src/i18n/I18nText.vue +17 -17
  19. package/src/i18n/I18nTextInline.vue +17 -17
  20. package/src/i18n/index.js +88 -88
  21. package/src/i18n/language.js +127 -127
  22. package/src/i18n/markdown.js +265 -265
  23. package/src/index.js +51 -50
  24. package/src/injectionKeys.js +1 -1
  25. package/src/languages.js +49 -49
  26. package/src/legacy/index.js +58 -58
  27. package/src/record/collectionTree.js +307 -307
  28. package/src/record/derivations.js +154 -154
  29. package/src/record/partners.js +87 -87
  30. package/src/record/recordSheet.js +231 -231
  31. package/src/rights.js +53 -53
  32. package/src/router/index.js +138 -138
  33. package/src/siteConfig.js +37 -37
  34. package/src/styles/base.css +49 -49
  35. package/src/testing/checkOfferedLanguages.js +67 -67
  36. package/src/testing/index.js +3 -3
  37. package/src/testing/smoke.js +103 -103
  38. package/src/testing/viteConfig.js +72 -90
  39. package/src/views/DetailView.vue +53 -53
  40. package/src/views/HomeView.vue +20 -20
  41. package/src/views/ListView.vue +61 -61
  42. package/src/views/NotFoundView.vue +8 -8
  43. 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
+ }
@@ -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
+ }