58 lines
2.0 KiB
JavaScript
58 lines
2.0 KiB
JavaScript
/**
|
|
* Parse onboarding media manifests into guide groups.
|
|
*
|
|
* WHY: keeping manifest shaping outside the view makes guide behavior
|
|
* testable without mounting the whole onboarding page.
|
|
*
|
|
* @param {string[]} files - Manifest file paths relative to the onboarding media root.
|
|
* @returns {object} Guide groups keyed by service, step, and variant.
|
|
*/
|
|
export function parseManifest(files) {
|
|
const grouped = {};
|
|
for (const path of files) {
|
|
if (typeof path !== "string") continue;
|
|
const cleaned = path.replace(/^\/+/, "").replace(/\\/g, "/");
|
|
const parts = cleaned.split("/");
|
|
if (parts.length < 3) continue;
|
|
const service = parts[0];
|
|
const step = parts[1];
|
|
const rest = parts.slice(2);
|
|
let variant = "default";
|
|
let filename = rest.join("/");
|
|
if (rest.length > 1) {
|
|
variant = rest[0];
|
|
filename = rest.slice(1).join("/");
|
|
}
|
|
const order = guideOrder(filename);
|
|
const label = guideLabel(filename);
|
|
const url = `/media/onboarding/${cleaned}`;
|
|
grouped[service] = grouped[service] || {};
|
|
grouped[service][step] = grouped[service][step] || {};
|
|
grouped[service][step][variant] = grouped[service][step][variant] || { id: variant, title: variant === "default" ? "" : variant, shots: [] };
|
|
grouped[service][step][variant].shots.push({ url, order, label, file: filename });
|
|
}
|
|
|
|
Object.values(grouped).forEach((serviceSteps) => {
|
|
Object.values(serviceSteps).forEach((variants) => {
|
|
Object.values(variants).forEach((group) => {
|
|
group.shots.sort((a, b) => (a.order - b.order) || a.file.localeCompare(b.file));
|
|
});
|
|
});
|
|
});
|
|
|
|
return grouped;
|
|
}
|
|
|
|
function guideOrder(filename) {
|
|
const prefix = filename.match(/^(\d{1,3})/);
|
|
if (prefix) return Number(prefix[1]);
|
|
const step = filename.match(/step[-_ ]?(\d{1,3})/i);
|
|
if (step) return Number(step[1]);
|
|
return Number.MAX_SAFE_INTEGER;
|
|
}
|
|
|
|
function guideLabel(filename) {
|
|
const base = filename.replace(/\.(png|jpe?g|webp)$/i, "");
|
|
return base.replace(/^\d+[-_]?/, "").replace(/[-_]/g, " ").trim();
|
|
}
|