115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
import { z } from "zod";
|
|
|
|
export const videoDetails = {
|
|
width: "1008",
|
|
height: "567",
|
|
minDim: "100",
|
|
maxDim: "1008",
|
|
};
|
|
|
|
/**
|
|
* Extract YouTube video ID from a URL or a raw ID.
|
|
*/
|
|
export const extractYoutubeId = (input: string): string | null => {
|
|
const trimmed = input.trim();
|
|
// Direct ID (11 chars)
|
|
if (/^[a-zA-Z0-9_-]{11}$/.test(trimmed)) return trimmed;
|
|
// youtube.com/watch?v=ID
|
|
const watchMatch = trimmed.match(/[?&]v=([a-zA-Z0-9_-]{11})/);
|
|
if (watchMatch) return watchMatch[1];
|
|
// youtu.be/ID
|
|
const shortMatch = trimmed.match(/youtu\.be\/([a-zA-Z0-9_-]{11})/);
|
|
if (shortMatch) return shortMatch[1];
|
|
// youtube.com/embed/ID
|
|
const embedMatch = trimmed.match(/youtube\.com\/embed\/([a-zA-Z0-9_-]{11})/);
|
|
if (embedMatch) return embedMatch[1];
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Extract Vimeo video ID from a URL or a raw ID.
|
|
*/
|
|
export const extractVimeoId = (input: string): string | null => {
|
|
const trimmed = input.trim();
|
|
// Direct numeric ID
|
|
if (/^\d+$/.test(trimmed)) return trimmed;
|
|
// vimeo.com/ID or vimeo.com/video/ID
|
|
const match = trimmed.match(/vimeo\.com\/(?:video\/)?(\d+)/);
|
|
if (match) return match[1];
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Build the iframe src URL for YouTube or Vimeo with options.
|
|
*/
|
|
export const buildVideoSrc = (attrs: {
|
|
videoId?: string | null;
|
|
isMuted?: boolean;
|
|
hasControls?: boolean;
|
|
provider: number;
|
|
}): string => {
|
|
const params = new URLSearchParams();
|
|
const query = params.toString();
|
|
if (attrs.provider == 1) {
|
|
if (attrs.isMuted) params.set("mute", "1");
|
|
params.set("controls", attrs.hasControls ? "1" : "0");
|
|
return `https://www.youtube.com/embed/${attrs.videoId}${query ? `?${query}` : ""}`;
|
|
}
|
|
|
|
if (attrs.provider == 2) {
|
|
if (attrs.isMuted) params.set("muted", "1");
|
|
if (!attrs.hasControls) params.set("controls", "0");
|
|
return `https://player.vimeo.com/video/${attrs.videoId}${query ? `?${query}` : ""}`;
|
|
}
|
|
|
|
return "";
|
|
};
|
|
|
|
/**
|
|
* Zod schema for video caption input.
|
|
*/
|
|
export const videoTextSchema = ({
|
|
hasCaption,
|
|
transValidationCaption,
|
|
transValidationAlt,
|
|
}: {
|
|
hasCaption: boolean;
|
|
transValidationCaption: { min: string; max: string; string: string, boolean: string };
|
|
transValidationAlt: {
|
|
min: string;
|
|
max: string;
|
|
string: string;
|
|
};
|
|
}) => {
|
|
const altRules = z
|
|
.string({ message: transValidationAlt.string })
|
|
.min(3, transValidationAlt.min)
|
|
.max(255, transValidationAlt.max);
|
|
|
|
const captionRules = z
|
|
.string({ message: transValidationCaption.string })
|
|
.min(3, transValidationCaption.min)
|
|
.max(255, transValidationCaption.max);
|
|
|
|
const isBool = z.boolean({ message: transValidationCaption.boolean });
|
|
|
|
return z.object({
|
|
caption: hasCaption ? captionRules : z.null(),
|
|
isMuted: isBool,
|
|
hasControls: isBool,
|
|
canFullScreen: isBool,
|
|
alt: altRules
|
|
});
|
|
};
|
|
|
|
export const isBoolsSchema = (transValidation: { isMuted: string; hasControls: string; canFullScreen: string }) => {
|
|
const isMuted = z.boolean({ message: transValidation.isMuted });
|
|
const hasControls = z.boolean({ message: transValidation.hasControls });
|
|
const canFullScreen = z.boolean({ message: transValidation.canFullScreen });
|
|
|
|
return z.object({
|
|
isMuted: isMuted,
|
|
hasControls: hasControls,
|
|
canFullScreen: canFullScreen,
|
|
});
|
|
};
|