mirror of
https://github.com/Pandipipas/scoreko-dev.git
synced 2026-06-06 03:32:06 +00:00
Support custom character image folders and document structure
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
# Character image catalog
|
||||||
|
|
||||||
|
Put custom character images here using this structure:
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/shared/character-images/
|
||||||
|
street-fighter-6/
|
||||||
|
ryu.png
|
||||||
|
ken.png
|
||||||
|
tekken-8/
|
||||||
|
jin.png
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- Folder name = game slug (`toLowerCase`, replace non alphanumeric with `-`).
|
||||||
|
- Example: `Guilty Gear -Strive-` -> `guilty-gear-strive`
|
||||||
|
- File name = character slug with the same rule.
|
||||||
|
- Example: `Chun-Li` -> `chun-li`
|
||||||
|
- Supported extensions: `.png`, `.jpg`, `.jpeg`, `.webp`, `.avif`, `.svg`.
|
||||||
|
- If an image is missing, the dashboard shows a generated placeholder preview.
|
||||||
@@ -24,11 +24,11 @@ const paletteByGame: Record<string, [string, string]> = {
|
|||||||
'2XKO': ['#22d3ee', '#0f766e'],
|
'2XKO': ['#22d3ee', '#0f766e'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const toCharacterValue = (character: string) => character.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
|
const toSlug = (value: string) => value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '');
|
||||||
|
|
||||||
const toDataUrl = (svg: string) => `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
const toDataUrl = (svg: string) => `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
|
||||||
|
|
||||||
const buildCharacterImage = (game: string, character: string) => {
|
const buildCharacterPlaceholder = (game: string, character: string) => {
|
||||||
const [startColor, endColor] = paletteByGame[game] ?? ['#334155', '#0f172a'];
|
const [startColor, endColor] = paletteByGame[game] ?? ['#334155', '#0f172a'];
|
||||||
const initials = character
|
const initials = character
|
||||||
.split(/\s+/)
|
.split(/\s+/)
|
||||||
@@ -55,14 +55,42 @@ const buildCharacterImage = (game: string, character: string) => {
|
|||||||
return toDataUrl(svg.trim());
|
return toDataUrl(svg.trim());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const characterImageModules = import.meta.glob('/src/shared/character-images/**/*.{png,jpg,jpeg,webp,avif,svg}', {
|
||||||
|
eager: true,
|
||||||
|
import: 'default',
|
||||||
|
query: '?url',
|
||||||
|
}) as Record<string, string>;
|
||||||
|
|
||||||
|
const characterImageByKey = Object.entries(characterImageModules).reduce<Record<string, string>>((acc, [path, url]) => {
|
||||||
|
const segments = path.split('/');
|
||||||
|
const gameFolder = segments.at(-2);
|
||||||
|
const filename = segments.at(-1);
|
||||||
|
if (!gameFolder || !filename) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const characterSlug = filename.replace(/\.[^.]+$/, '');
|
||||||
|
acc[`${gameFolder}/${characterSlug}`] = url;
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const getCharacterImage = (game: string, character: string, characterValue: string) => {
|
||||||
|
const gameSlug = toSlug(game);
|
||||||
|
const key = `${gameSlug}/${characterValue}`;
|
||||||
|
return characterImageByKey[key] ?? buildCharacterPlaceholder(game, character);
|
||||||
|
};
|
||||||
|
|
||||||
export const fightingCharactersByGame: Record<string, FightingCharacterOption[]> = Object.fromEntries(
|
export const fightingCharactersByGame: Record<string, FightingCharacterOption[]> = Object.fromEntries(
|
||||||
Object.entries(characterNamesByGame).map(([game, characterNames]) => [
|
Object.entries(characterNamesByGame).map(([game, characterNames]) => [
|
||||||
game,
|
game,
|
||||||
characterNames.map((character) => ({
|
characterNames.map((character) => {
|
||||||
|
const value = toSlug(character);
|
||||||
|
return {
|
||||||
label: character,
|
label: character,
|
||||||
value: toCharacterValue(character),
|
value,
|
||||||
image: buildCharacterImage(game, character),
|
image: getCharacterImage(game, character, value),
|
||||||
})),
|
};
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user