diff --git a/lxljs/display.js b/lxljs/display.js index 554ed6c88..5a50c1a74 100644 --- a/lxljs/display.js +++ b/lxljs/display.js @@ -67,7 +67,7 @@ function tryGetValueByLang(item, propertyId, langCode, context) { } if (typeof propertyId === 'string' && propertyId.startsWith('@reverse/') && propertyId !== '@reverse/itemOf') { - return get(item, propertyId.replaceAll('/', '.')); + return get(item, propertyId.replace(/\//g, '.')); } const byLangKey = VocabUtil.getMappedPropertyByContainer(propertyId, '@language', context); @@ -171,12 +171,14 @@ export function translateObjectProp(object) { function formatLabel(item, type, resources) { const label = []; const formatters = resources.display.lensGroups.formatters; - const replaceInnerDot = s => s.replaceAll(' • ', ', '); // TODO: handle nested chips properly + const replaceInnerDot = s => s.replace(/ • /g, ', '); // TODO: handle nested chips properly // FIXME: this should be driven by display.jsonld // We don't want Library and Bibliography. Could do isSubclassOf('Agent') && !isSubclassOf('Collection') but hardcode the list for now const isAgent = ['Person', 'Organization', 'Jurisdiction', 'Meeting', 'Family'].includes(type); - const separator = isAgent ? ', ' : ' • '; + // We don't want to touch commas inside property values when doing the final cleanup. + // Use a private use character as a temporary stand in for comma. + const separator = isAgent ? '\uE000 ' : ' • '; const objKeys = Object.keys(item); for (let i = 0; i < objKeys.length; i++) { @@ -195,7 +197,7 @@ function formatLabel(item, type, resources) { label.push(formatter['fresnel:contentLast']); } } else { - label.push(value.map(replaceInnerDot).join(', ')); + label.push(value.map(replaceInnerDot).join('\uE000 ')); } } else { label.push(replaceInnerDot(value)); @@ -204,8 +206,9 @@ function formatLabel(item, type, resources) { } let labelStr = label.join(''); // TODO: lots of punctuation for MARC going on inside some of these fields - labelStr = labelStr.replace(/([:.,]),/g, '$1'); - labelStr = labelStr.replace(/\(,\s?/g, '(') + labelStr = labelStr.replace(/([:.\uE000])\uE000/g, '$1'); + labelStr = labelStr.replace(/\(\uE000\s?/g, '('); + labelStr = labelStr.replace(/\uE000/g, ','); return labelStr; } @@ -458,7 +461,7 @@ export function getDisplayObject(item, level, resources, quoted, settings) { } } } - const str = s => JSON.stringify(s || '').replaceAll('"', ''); + const str = s => JSON.stringify(s || '').replace(/"/g, ''); lxlLog(`Computed alternateProperties for ${trueItem['@type']}. Looked for: ${property.alternateProperties.map(str).join(', ')} | Settled on: ${str(foundProperty)}`); } } diff --git a/nuxt-app/modules/vocab-cache.js b/nuxt-app/modules/vocab-cache.js new file mode 100644 index 000000000..783ade1a5 --- /dev/null +++ b/nuxt-app/modules/vocab-cache.js @@ -0,0 +1,54 @@ +import fetch from "node-fetch"; +import {CONTEXT, DISPLAY, translateAliasedUri, VOCAB} from "../plugins/env"; +import * as VocabUtil from "lxljs/vocab"; +import * as DisplayUtil from "lxljs/display"; + +const toJson = response => { + if (response.ok) { + return response.json() + } + else { + throw { statusCode: response.status } + } +} + +async function fetchVocab() { + const vocabCache = {}; + + await Promise.all([ + fetch(translateAliasedUri(CONTEXT)).then(toJson), + fetch(translateAliasedUri(VOCAB)).then(toJson), + fetch(translateAliasedUri(DISPLAY)).then(toJson) + ]) + .then(v => { + let context, vocab, display; + [context, vocab, display] = v; + + vocabCache.context = VocabUtil.preprocessContext(context)['@context']; + vocabCache.vocab = vocab; + vocabCache.display = DisplayUtil.expandInherited(display); + }) + .catch(err => { + vocabCache.error = { statusCode: err.statusCode || 500, 'message': err.message || ''} + }); + + return vocabCache; +} + +export default function (_moduleOptions) { + // shared by all requests + let cache; + + async function getVocab() { + if (!cache || cache.error) { + cache = await fetchVocab(); + } + + return cache; + } + + // called before server-side rendering + this.nuxt.hook("vue-renderer:ssr:prepareContext", async (ssrContext) => { + ssrContext.$vocab = await getVocab(); + }); +} diff --git a/nuxt-app/nuxt.config.js b/nuxt-app/nuxt.config.js index 3744c8b28..e3d051721 100644 --- a/nuxt-app/nuxt.config.js +++ b/nuxt-app/nuxt.config.js @@ -65,6 +65,7 @@ export default { modules: [ '@nuxtjs/style-resources', '@nuxt/http', + '~/modules/vocab-cache' ], styleResources: { diff --git a/nuxt-app/store/index.js b/nuxt-app/store/index.js index 9df45af1a..f435eba6b 100644 --- a/nuxt-app/store/index.js +++ b/nuxt-app/store/index.js @@ -222,51 +222,22 @@ export const mutations = { }, } -const toJson = response => { - if (response.ok) { - return response.json() - } - else { - throw { statusCode: response.status } - } -} - -function catcher(error) { - return err => { - error({ statusCode: err.statusCode || 500, 'message': err.message || ''}) - } -} - export const actions = { - async nuxtServerInit({ commit, dispatch }, { req, error }) { + async nuxtServerInit({ commit, dispatch }, { req, error, ssrContext }) { dispatch('setAppState', { property: 'domain', value: activeSite(req.headers['x-forwarded-host']) }); - await Promise.all([ - fetch(translateAliasedUri(CONTEXT)) - .then(toJson) - .then(contextData => { - const processed = VocabUtil.preprocessContext(contextData); - commit('SET_VOCAB_CONTEXT', processed['@context']); - }) - .catch(catcher(error)), - - fetch(translateAliasedUri(VOCAB)) - .then(toJson) - .then(vocab => { - commit('SET_VOCAB', vocab); - commit('SET_VOCAB_CLASSES', vocab); - commit('SET_VOCAB_PROPERTIES', vocab); - }) - .catch(catcher(error)), - - fetch(translateAliasedUri(DISPLAY)) - .then(toJson) - .then(display => { - const expanded = DisplayUtil.expandInherited(display); - commit('SET_DISPLAY', expanded); - }) - .catch(catcher(error)) - ]); + const vocab = ssrContext.$vocab; + if (vocab.error) { + console.error(`Error getting vocab resources: ${JSON.stringify(vocab.error)}`) + error(vocab.error); + } + else { + commit('SET_VOCAB_CONTEXT', vocab.context); + commit('SET_VOCAB', vocab.vocab); + commit('SET_VOCAB_CLASSES', vocab.vocab); + commit('SET_VOCAB_PROPERTIES', vocab.vocab); + commit('SET_DISPLAY', vocab.display); + } }, setMarcframe({ commit }, data) { commit('SET_MARCFRAME_DATA', data); diff --git a/vue-client/package.json b/vue-client/package.json index 9790ad474..76e03f570 100644 --- a/vue-client/package.json +++ b/vue-client/package.json @@ -1,6 +1,6 @@ { "name": "vue-client", - "version": "1.27.5", + "version": "1.27.6", "private": true, "scripts": { "serve": "vue-cli-service serve",