Biome reported 229 diagnostics after aligning the config with
bsi-ni.brain.riken.jp. Fix them all so `biome check` passes clean
without per-rule overrides.
- replace `any` in LokiJS queries with an `ItemFilter` interface and
a single `asLokiQuery()` cast, matching bsi-ni
- type the XOOPS redirect maps as
`Record<string, { key: string; isNumber: boolean }>`
- use `ItemSubTypes<string>` instead of `any` for sub item types
- join author lists with `.join(', ')` instead of index-keyed nodes
- give list elements stable keys derived from their own data
- return `React.ReactNode` from `ListBase.renderBody()`
- drop the temporary `noArrayIndexKey` override from biome.json
149 lines
6.2 KiB
TypeScript
149 lines
6.2 KiB
TypeScript
import { Navigate, useLocation } from 'react-router';
|
|
import PageNotFound from '../common/lib/PageNotFound';
|
|
import type { MultiLang } from '../config';
|
|
import Functions from '../functions';
|
|
|
|
interface Props {
|
|
lang: MultiLang;
|
|
}
|
|
|
|
const getRedirectUrl = (location: { pathname: string; search: string }): string => {
|
|
{
|
|
const pathname = location.pathname || '';
|
|
const query = new URLSearchParams(location.search);
|
|
const search = /^\/modules\/xoonips(?:\/+(.*))?$/;
|
|
const matches = pathname.match(search);
|
|
if (matches === null) {
|
|
return '';
|
|
}
|
|
const path = matches[1] || '';
|
|
switch (path) {
|
|
case '':
|
|
case 'index.php': {
|
|
return '/database';
|
|
}
|
|
case 'detail.php': {
|
|
const id = query.get('id');
|
|
if (id !== null) {
|
|
return `/database/item/id/${Functions.escape(id)}`;
|
|
}
|
|
const itemId = query.get('item_id');
|
|
if (itemId !== null && itemId.match(/^\d+$/) !== null) {
|
|
return `/database/item/${Functions.escape(itemId)}`;
|
|
}
|
|
return '';
|
|
}
|
|
case 'listitem.php': {
|
|
const indexId = query.get('index_id');
|
|
if (indexId !== null && indexId.match(/^\d+$/) !== null) {
|
|
const params = new URLSearchParams();
|
|
const map: Record<string, { key: string; isNumber: boolean }> = {
|
|
orderby: { key: 'orderby', isNumber: false },
|
|
order_dir: { key: 'order_dir', isNumber: true },
|
|
itemcount: { key: 'itemcount', isNumber: true },
|
|
page: { key: 'page', isNumber: true },
|
|
};
|
|
for (const k in map) {
|
|
const v = query.get(k);
|
|
if (v === null || v.length === 0) {
|
|
continue;
|
|
}
|
|
if (map[k].isNumber && v.match(/^\d+$/) !== null) {
|
|
continue;
|
|
}
|
|
params.set(map[k].key, v);
|
|
}
|
|
const paramStr = params.toString();
|
|
return `/database/list/${Functions.escape(indexId)}${paramStr.length > 0 ? `?${paramStr}` : ''}`;
|
|
}
|
|
break;
|
|
}
|
|
case 'itemselect.php': {
|
|
const op = query.get('op');
|
|
if (op === null) {
|
|
break;
|
|
}
|
|
switch (op) {
|
|
case 'quicksearch': {
|
|
const keyword = query.get('keyword');
|
|
const itemType = query.get('search_itemtype');
|
|
if (keyword === null || itemType === null || keyword === '') {
|
|
return '';
|
|
}
|
|
const type = itemType.replace('xnp', '');
|
|
if (itemType !== 'basic' && itemType !== 'all' && itemType.match(/^xnp.+/) === null) {
|
|
return '';
|
|
}
|
|
const params = new URLSearchParams({ type, keyword });
|
|
const map: Record<string, { key: string; isNumber: boolean }> = {
|
|
orderby: { key: 'orderby', isNumber: false },
|
|
orderdir: { key: 'order_dir', isNumber: true },
|
|
item_per_page: { key: 'itemcount', isNumber: true },
|
|
page: { key: 'page', isNumber: true },
|
|
};
|
|
for (const k in map) {
|
|
const v = query.get(k);
|
|
if (v === null || v.length === 0) {
|
|
continue;
|
|
}
|
|
if (map[k].isNumber && v.match(/^\d+$/) !== null) {
|
|
continue;
|
|
}
|
|
params.set(map[k].key, v);
|
|
}
|
|
return `/database/search?${params.toString()}`;
|
|
}
|
|
case 'itemtypesearch': {
|
|
const itemType = query.get('search_itemtype');
|
|
if (itemType === null || itemType.match(/^xnp.+/) === null) {
|
|
return '';
|
|
}
|
|
const type = itemType.replace('xnp', '');
|
|
return `/database/search/itemtype/${Functions.escape(type)}`;
|
|
}
|
|
case 'itemsubtypesearch': {
|
|
let type = '';
|
|
let subtype = '';
|
|
query.forEach((v, k) => {
|
|
if (k.match(/^xnp[a-z]+$/) !== null && v) {
|
|
type = k.replace('xnp', '');
|
|
return;
|
|
}
|
|
});
|
|
if (type === '') {
|
|
return '';
|
|
}
|
|
query.forEach((v, k) => {
|
|
if (k.match(`^xnp${type}_.+$`) !== null && v) {
|
|
subtype = v;
|
|
return;
|
|
}
|
|
});
|
|
if (subtype === '') {
|
|
return '';
|
|
}
|
|
return `/database/search/itemtype/${Functions.escape(type)}/${Functions.escape(subtype)}`;
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
case 'advanced_search.php': {
|
|
return '/database/advanced';
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
};
|
|
|
|
const DatabaseXoopsPathRedirect = (props: Props) => {
|
|
const { lang } = props;
|
|
const location = useLocation();
|
|
const url = getRedirectUrl(location);
|
|
if (url === '') {
|
|
return <PageNotFound lang={lang} />;
|
|
}
|
|
return <Navigate to={url} replace />;
|
|
};
|
|
|
|
export default DatabaseXoopsPathRedirect;
|