SkateSpots/.agents/skills/note-content/files/lib/mediaUrls.ts
shakespeare.diy 06fae294b8 New project created with Shakespeare
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
2026-06-15 19:49:07 +07:00

93 lines
3.1 KiB
TypeScript

/** Image extensions rendered inline. */
export const IMAGE_EXTS = 'jpg|jpeg|png|gif|webp|svg|avif';
/** Video extensions rendered as players. */
export const VIDEO_EXTS = 'mp4|webm|mov|qt|avi|mkv|flv';
/** Audio extensions rendered as players. */
export const AUDIO_EXTS = 'mp3|wav|ogg|flac|m4a|aac|opus';
/** All media extensions (image + video + audio + webxdc). */
export const ALL_MEDIA_EXTS = `${IMAGE_EXTS}|${VIDEO_EXTS}|${AUDIO_EXTS}|xdc`;
/** Matches image URLs. */
export const IMAGE_URL_REGEX = new RegExp(
`https?:\\/\\/[^\\s]+\\.(${IMAGE_EXTS})(\\?[^\\s]*)?`,
'i',
);
/** Matches video URLs. */
export const VIDEO_URL_REGEX = new RegExp(
`https?:\\/\\/[^\\s]+\\.(${VIDEO_EXTS})(\\?[^\\s]*)?`,
'gi',
);
/** Matches audio URLs. */
export const AUDIO_URL_REGEX = new RegExp(
`https?:\\/\\/[^\\s]+\\.(${AUDIO_EXTS})(\\?[^\\s]*)?`,
'gi',
);
/** Matches any media URL (video, audio, webxdc) that is rendered as an embed — not a link preview. */
export const EMBED_MEDIA_URL_REGEX = new RegExp(
`https?:\\/\\/[^\\s]+\\.(${VIDEO_EXTS}|${AUDIO_EXTS}|xdc)(\\?[^\\s]*)?`,
'i',
);
/** Matches all NIP-92 media URLs for imeta tag generation (images + video + audio + webxdc). */
export const IMETA_MEDIA_URL_REGEX = new RegExp(
`https?:\\/\\/[^\\s]+\\.(${ALL_MEDIA_EXTS})(\\?[^\\s]*)?`,
'gi',
);
/**
* Non-global variant of IMETA_MEDIA_URL_REGEX, safe for `.test()` calls.
*
* IMPORTANT: Never use the global (`g`) IMETA_MEDIA_URL_REGEX with `.test()` —
* the global flag makes `lastIndex` stateful, so repeated `.test()` calls
* (e.g. inside `.find()` or `.filter()`) will alternate between matching and
* not matching, causing every other URL to be misclassified.
*/
export const IMETA_MEDIA_URL_TEST_REGEX = new RegExp(
IMETA_MEDIA_URL_REGEX.source,
'i',
);
/** Infers a MIME type from a file extension string (lowercase). */
export function mimeFromExt(ext: string): string {
switch (ext) {
case 'jpg': case 'jpeg': return 'image/jpeg';
case 'png': return 'image/png';
case 'gif': return 'image/gif';
case 'webp': return 'image/webp';
case 'svg': return 'image/svg+xml';
case 'avif': return 'image/avif';
case 'mp4': return 'video/mp4';
case 'webm': return 'video/webm';
case 'mov': return 'video/quicktime';
case 'qt': return 'video/quicktime';
case 'avi': return 'video/x-msvideo';
case 'mkv': return 'video/x-matroska';
case 'flv': return 'video/x-flv';
case 'mp3': return 'audio/mpeg';
case 'wav': return 'audio/wav';
case 'ogg': return 'audio/ogg';
case 'flac': return 'audio/flac';
case 'm4a': return 'audio/mp4';
case 'aac': return 'audio/aac';
case 'opus': return 'audio/opus';
case 'xdc': return 'application/x-webxdc';
default: return 'application/octet-stream';
}
}
/** Extracts all video URLs from a string. */
export function extractVideoUrls(content: string): string[] {
return content.match(new RegExp(VIDEO_URL_REGEX.source, 'gi')) ?? [];
}
/** Extracts all audio URLs from a string. */
export function extractAudioUrls(content: string): string[] {
return content.match(new RegExp(AUDIO_URL_REGEX.source, 'gi')) ?? [];
}