refactoring
This commit is contained in:
@@ -8,6 +8,7 @@ const ignoredFolderNames = new Set(["template", "templates", "example", "example
|
||||
const tarotSuits = ["wands", "cups", "swords", "disks"];
|
||||
const majorTrumpNumbers = Array.from({ length: 22 }, (_, index) => index);
|
||||
const expectedMinorCardCount = 56;
|
||||
const cardBackCandidateExtensions = ["webp", "png", "jpg", "jpeg", "avif", "gif"];
|
||||
|
||||
function isPlainObject(value) {
|
||||
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
||||
@@ -29,6 +30,10 @@ function asNonEmptyString(value) {
|
||||
return normalized || null;
|
||||
}
|
||||
|
||||
function isRemoteAssetPath(value) {
|
||||
return /^(https?:)?\/\//i.test(String(value || "").trim());
|
||||
}
|
||||
|
||||
function toTitleCase(value) {
|
||||
const normalized = String(value || "").trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
@@ -241,6 +246,10 @@ function validateDeckManifest(manifest) {
|
||||
errors.push("majorNameOverridesByTrump must be an object when provided");
|
||||
}
|
||||
|
||||
if (manifest.cardBack != null && !asNonEmptyString(manifest.cardBack)) {
|
||||
errors.push("cardBack must be a non-empty string when provided");
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -358,6 +367,15 @@ function getReferencedMinorFiles(manifest) {
|
||||
return [];
|
||||
}
|
||||
|
||||
function getReferencedCardBackFiles(manifest) {
|
||||
const cardBack = asNonEmptyString(manifest?.cardBack);
|
||||
if (!cardBack || isRemoteAssetPath(cardBack)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [cardBack];
|
||||
}
|
||||
|
||||
function summarizeMissingFiles(fileList) {
|
||||
const maxPreview = 8;
|
||||
const preview = fileList.slice(0, maxPreview).join(", ");
|
||||
@@ -368,11 +386,30 @@ function summarizeMissingFiles(fileList) {
|
||||
return `${preview}, ... (+${fileList.length - maxPreview} more)`;
|
||||
}
|
||||
|
||||
function detectDeckCardBackRelativePath(folderName, manifest) {
|
||||
const explicitCardBack = asNonEmptyString(manifest?.cardBack);
|
||||
if (explicitCardBack) {
|
||||
return explicitCardBack;
|
||||
}
|
||||
|
||||
const deckFolderPath = path.join(decksRoot, folderName);
|
||||
for (let index = 0; index < cardBackCandidateExtensions.length; index += 1) {
|
||||
const extension = cardBackCandidateExtensions[index];
|
||||
const candidateName = `back.${extension}`;
|
||||
if (fs.existsSync(path.join(deckFolderPath, candidateName))) {
|
||||
return candidateName;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function auditDeckFiles(folderName, manifest) {
|
||||
const deckFolderPath = path.join(decksRoot, folderName);
|
||||
const referencedFiles = [
|
||||
...getReferencedMajorFiles(manifest),
|
||||
...getReferencedMinorFiles(manifest)
|
||||
...getReferencedMinorFiles(manifest),
|
||||
...getReferencedCardBackFiles(manifest)
|
||||
]
|
||||
.map((relativePath) => String(relativePath || "").trim())
|
||||
.filter(Boolean);
|
||||
@@ -453,6 +490,7 @@ function compileDeckRegistry() {
|
||||
const id = (idFromManifest || fallbackId).toLowerCase();
|
||||
const label = labelFromManifest || folderName;
|
||||
const basePath = `asset/tarot deck/${folderName}`;
|
||||
const cardBackPath = detectDeckCardBackRelativePath(folderName, manifest);
|
||||
|
||||
if (seenIds.has(id)) {
|
||||
warnings.push(`Skipped '${folderName}': duplicate deck id '${id}'`);
|
||||
@@ -465,7 +503,8 @@ function compileDeckRegistry() {
|
||||
id,
|
||||
label,
|
||||
basePath,
|
||||
manifestPath: `${basePath}/deck.json`
|
||||
manifestPath: `${basePath}/deck.json`,
|
||||
...(cardBackPath ? { cardBackPath } : {})
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user