@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Utilities for parsing VFX filenames into shot / task metadata.
|
||||
*
|
||||
* Expected naming convention (any separator count is fine):
|
||||
* {SHOW}_{EP}_{SCENE}_{CUT}_{TASK}_{ARTIST}_v{NNN}.{ext}
|
||||
* e.g. UNG_106_035_010_cmp_TT_v002.mp4
|
||||
*
|
||||
* The shot code is matched against the database – the parser itself
|
||||
* does NOT hard-code how many underscore segments belong to the shot.
|
||||
*/
|
||||
|
||||
export interface ParsedFilename {
|
||||
originalName: string;
|
||||
/** Filename without the extension */
|
||||
nameWithoutExt: string;
|
||||
/** Lowercased extension without the leading dot (e.g. "mp4", "mov") */
|
||||
ext: string;
|
||||
/**
|
||||
* Task name base – the full name without the version suffix.
|
||||
* e.g. "UNG_106_035_010_cmp_TT"
|
||||
*/
|
||||
taskNameBase: string;
|
||||
/**
|
||||
* Full task title including the version suffix (no extension).
|
||||
* This is what the task should be named after upload.
|
||||
* e.g. "UNG_106_035_010_cmp_TT_v002"
|
||||
*/
|
||||
taskNameWithVersion: string;
|
||||
/**
|
||||
* Version string extracted from the filename, e.g. "v002".
|
||||
* Empty string if no version pattern was found.
|
||||
*/
|
||||
version: string;
|
||||
type: "mp4" | "mov" | "other";
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a VFX filename into its constituent parts.
|
||||
*/
|
||||
export function parseFilename(filename: string): ParsedFilename {
|
||||
const lastDot = filename.lastIndexOf(".");
|
||||
const ext = lastDot >= 0 ? filename.slice(lastDot + 1).toLowerCase() : "";
|
||||
const nameWithoutExt = lastDot >= 0 ? filename.slice(0, lastDot) : filename;
|
||||
|
||||
// Version pattern: _v followed by one or more digits at the end (case insensitive)
|
||||
const versionMatch = nameWithoutExt.match(/_v(\d+)$/i);
|
||||
const version = versionMatch ? `v${versionMatch[1]}` : "";
|
||||
const taskNameBase = versionMatch
|
||||
? nameWithoutExt.slice(0, nameWithoutExt.length - versionMatch[0].length)
|
||||
: nameWithoutExt;
|
||||
|
||||
const type: "mp4" | "mov" | "other" =
|
||||
ext === "mp4" ? "mp4" : ext === "mov" ? "mov" : "other";
|
||||
|
||||
return {
|
||||
originalName: filename,
|
||||
nameWithoutExt,
|
||||
ext,
|
||||
taskNameBase,
|
||||
taskNameWithVersion: nameWithoutExt,
|
||||
version,
|
||||
type,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip a trailing version suffix (_v###) from a task title.
|
||||
* e.g. "UNG_106_035_010_cmp_TT_v001" → "UNG_106_035_010_cmp_TT"
|
||||
*/
|
||||
export function stripVersionFromTitle(title: string): string {
|
||||
return title.replace(/_v\d+$/i, "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a taskNameBase and a list of shot codes, return the shot code that
|
||||
* is a prefix of the task name base (shot code + "_" separator).
|
||||
*
|
||||
* e.g. taskNameBase "UNG_106_035_010_cmp_TT" matches shot "UNG_106_035_010"
|
||||
*/
|
||||
export function findMatchingShotCode(
|
||||
taskNameBase: string,
|
||||
shotCodes: string[]
|
||||
): string | null {
|
||||
// Sort by length descending so longer (more specific) codes are matched first
|
||||
const sorted = [...shotCodes].sort((a, b) => b.length - a.length);
|
||||
for (const code of sorted) {
|
||||
if (
|
||||
taskNameBase === code ||
|
||||
taskNameBase.toLowerCase().startsWith(code.toLowerCase() + "_")
|
||||
) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user