commit: fd1e3f65a86be1dc1c1fb7252c2b9de7bf7ed6c7
parent 507824224fc7fdd88d4624d8157b9f4a44318df7
Author: Henry Jameson <me@hjkos.com>
Date:   Tue, 19 Nov 2024 22:19:11 +0200
Added fetching of *.custom.* indexes that aren't part of source tree
Diffstat:
3 files changed, 50 insertions(+), 27 deletions(-)
diff --git a/changelog.d/custom.add 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
@@ -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
@@ -0,0 +1 @@
+*.custom.*