From fd1e3f65a86be1dc1c1fb7252c2b9de7bf7ed6c7 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 19 Nov 2024 22:19:11 +0200 Subject: [PATCH] Added fetching of *.custom.* indexes that aren't part of source tree --- changelog.d/custom.add | 1 + src/services/style_setter/style_setter.js | 75 +++++++++++++++-------- static/.gitignore | 1 + 3 files changed, 50 insertions(+), 27 deletions(-) create mode 100644 changelog.d/custom.add create mode 100644 static/.gitignore diff --git a/changelog.d/custom.add b/changelog.d/custom.add new file mode 100644 index 00000000..97848d7e --- /dev/null +++ b/changelog.d/custom.add @@ -0,0 +1 @@ +Added support for fetching /{resource}.custom.ext to allow adding instance-specific themes without altering sourcetree diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js index 7ea94764..1892c111 100644 --- a/src/services/style_setter/style_setter.js +++ b/src/services/style_setter/style_setter.js @@ -228,35 +228,56 @@ export const applyConfig = (input, i18n) => { export const getResourcesIndex = async (url, parser = JSON.parse) => { const cache = 'no-store' + const customUrl = url.replace(/\.(\w+)$/, '.custom.$1') + let builtin + let custom + + const resourceTransform = (resources) => { + return Object + .entries(resources) + .map(([k, v]) => { + if (typeof v === 'object') { + return [k, () => Promise.resolve(v)] + } else if (typeof v === 'string') { + return [ + k, + () => window + .fetch(v, { cache }) + .then(data => data.text()) + .then(text => parser(text)) + .catch(e => { + console.error(e) + return null + }) + ] + } else { + console.error(`Unknown resource format - ${k} is a ${typeof v}`) + return [k, null] + } + }) + } try { - const data = await window.fetch(url, { cache }) - const resources = await data.json() - return Object.fromEntries( - Object - .entries(resources) - .map(([k, v]) => { - if (typeof v === 'object') { - return [k, () => Promise.resolve(v)] - } else if (typeof v === 'string') { - return [ - k, - () => window - .fetch(v, { cache }) - .then(data => data.text()) - .then(text => parser(text)) - .catch(e => { - console.error(e) - return null - }) - ] - } else { - console.error(`Unknown resource format - ${k} is a ${typeof v}`) - return [k, null] - } - }) - ) + const builtinData = await window.fetch(url, { cache }) + const builtinResources = await builtinData.json() + builtin = resourceTransform(builtinResources) } catch (e) { - return Promise.reject(e) + builtin = [] + console.warn(`Builtin resources at ${url} unavailable`) } + + try { + const customData = await window.fetch(customUrl, { cache }) + const customResources = await customData.json() + custom = resourceTransform(customResources) + } catch (e) { + custom = [] + console.warn(`Custom resources at ${customUrl} unavailable`) + } + + const total = [...builtin, ...custom] + if (total.length === 0) { + return Promise.reject(new Error(`Resource at ${url} and ${customUrl} completely unavailable. Panicking`)) + } + return Promise.resolve(Object.fromEntries(total)) } diff --git a/static/.gitignore b/static/.gitignore new file mode 100644 index 00000000..3332292a --- /dev/null +++ b/static/.gitignore @@ -0,0 +1 @@ +*.custom.*