feat: serve the atlas data from XOOPS-style paths

v2.0.0 put every atlas under /data/<atlas>/, which broke the original
/<atlas>/static/ download links and kept the data out of the modules/
layout the other sites use.

- read tree.json and items.json from /<atlas>/modules/xoonips/ and
  link the files under /<atlas>/modules/xoonips/file/
- redirect download.php, the v2.0.0 /data/ paths and the older
  /<atlas>/file/ paths with a 301
- send directories without an index.html to the SPA as well: the
  atlas directories now exist on disk, and the old rule served them
  as a 404
This commit is contained in:
2026-09-14 13:19:50 +09:00
parent 00f375cd9e
commit 20dd4f2a72
4 changed files with 15 additions and 13 deletions
+10 -8
View File
@@ -2,20 +2,22 @@
RewriteEngine On
RewriteBase /
# XOOPS download URLs point at the file directory, whose own .htaccess serves the file.
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
RewriteRule ^degu/modules/xoonips/download.php /data/degu/file/%2? [R=301,L]
RewriteRule ^(degu|jm|marmoset)/modules/xoonips/download\.php$ /$1/modules/xoonips/file/%2? [R=301,L]
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
RewriteRule ^jm/modules/xoonips/download.php /data/jm/file/%2? [R=301,L]
RewriteCond %{QUERY_STRING} (^|&)file_id=([0-9]+)($|&)
RewriteRule ^marmoset/modules/xoonips/download.php /data/marmoset/file/%2? [R=301,L]
# The v2.0.0 layout served everything under /data/; keep those links alive.
RewriteRule ^data/(degu|jm|marmoset)/file/(.*)$ /$1/modules/xoonips/file/$2 [R=301,L]
RewriteRule ^data/(degu|jm|marmoset)/static/(.*)$ /$1/static/$2 [R=301,L]
# An older static layout put the files at /<atlas>/file/.
RewriteRule ^(degu|jm|marmoset)/file/(.*)$ /$1/modules/xoonips/file/$2 [R=301,L]
RewriteRule ^index\.html$ - [L]
# Anything that is not a real file goes to the SPA -- including the atlas
# directories themselves, which now exist on disk as data roots.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l [OR]
RewriteCond %{REQUEST_FILENAME} !-d [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}index.html !-f
RewriteRule . /index.html [L]
+1 -1
View File
@@ -49,7 +49,7 @@ class IndexUtil {
this.indexes.set(type, collection);
this.loading.set(type, true);
this.callbacks.set(type, []);
ky.get(new URL(`${Config.BASE_URL}/data/${type}/tree.json`, window.location.href))
ky.get(new URL(`${Config.BASE_URL}/${type}/modules/xoonips/tree.json`, window.location.href))
.json<IndexData[]>()
.then((data) => {
const store = (indexesData: IndexesData, parentId: number) => {
+3 -3
View File
@@ -425,7 +425,7 @@ class ItemUtil {
this.items.set(type, collection);
this.loading.set(type, true);
this.callbacks.set(type, []);
ky.get(new URL(`${Config.BASE_URL}/data/${type}/items.json`, window.location.href))
ky.get(new URL(`${Config.BASE_URL}/${type}/modules/xoonips/items.json`, window.location.href))
.json<Item[]>()
.then((data) => {
const itemsJson = data;
@@ -492,11 +492,11 @@ class ItemUtil {
}
getFileUrl(type: BrainAtlasType, file: ItemBasicFile): string {
return `${Config.BASE_URL}/data/${type}/file/${file.file_id}/${Functions.escapeUrl(file.original_file_name)}`;
return `${Config.BASE_URL}/${type}/modules/xoonips/file/${file.file_id}/${Functions.escapeUrl(file.original_file_name)}`;
}
getPreviewFileUrl(type: BrainAtlasType, file: ItemBasicFile): string {
return `${Config.BASE_URL}/data/${type}/file/${file.file_id}/.png`;
return `${Config.BASE_URL}/${type}/modules/xoonips/file/${file.file_id}.png`;
}
getSearchByKeywordUrl(type: BrainAtlasType, ksType: KeywordSearchType, keyword: string): string {
+1 -1
View File
@@ -6,7 +6,7 @@ import type { Connect, Plugin, ResolvedConfig } from 'vite';
import { defineConfig } from 'vite';
/**
* `static-contents/` holds the dumped atlas data (`data/<atlas>/`).
* `static-contents/` holds the dumped atlas data (`<atlas>/modules/xoonips/`, `<atlas>/static/`).
* It sits next to the repository and is served from the site root next to
* `public/`, but it is deliberately kept out of the bundle: it runs to
* gigabytes of frozen data that the web server maps in directly. The dev and