POWR/utils/contentParser.ts

91 lines
2.2 KiB
TypeScript
Raw Normal View History

// utils/contentParser.ts
/**
* Utility functions for parsing content in social posts, including URL detection,
* image URL detection, and content segmentation for rendering.
*/
/**
* Regular expression for detecting URLs
* Matches common URL patterns with or without protocol
*/
const URL_REGEX = /(https?:\/\/[^\s]+)|(www\.[^\s]+)/gi;
/**
* Regular expression for detecting image URLs
* Matches URLs ending with common image extensions
*/
const IMAGE_URL_REGEX = /\.(gif|jpe?g|tiff?|png|webp|bmp)(\?.*)?$/i;
/**
* Interface for content segments
*/
export interface ContentSegment {
type: 'text' | 'url' | 'image';
content: string;
}
/**
* Check if a URL is an image URL based on its extension
*
* @param url URL to check
* @returns Boolean indicating if URL is an image
*/
export function isImageUrl(url: string): boolean {
return IMAGE_URL_REGEX.test(url);
}
/**
* Extract URLs from text
*
* @param text Text to extract URLs from
* @returns Array of URLs found in the text
*/
export function extractUrls(text: string): string[] {
return text.match(URL_REGEX) || [];
}
/**
* Parse text content into segments for rendering
* Each segment is either plain text, a URL, or an image URL
*
* @param content Text content to parse
* @returns Array of content segments
*/
export function parseContent(content: string): ContentSegment[] {
if (!content) return [];
const segments: ContentSegment[] = [];
const urls = extractUrls(content);
// If no URLs, return whole content as text
if (urls.length === 0) {
return [{ type: 'text', content }];
}
// Split content by URLs and create segments for each part
let remainingContent = content;
urls.forEach(url => {
const parts = remainingContent.split(url);
// Add text before URL if exists
if (parts[0]) {
segments.push({ type: 'text', content: parts[0] });
}
// Add URL (as image or link)
const type = isImageUrl(url) ? 'image' : 'url';
segments.push({ type, content: url });
// Update remaining content
remainingContent = parts.slice(1).join(url);
});
// Add any remaining text
if (remainingContent) {
segments.push({ type: 'text', content: remainingContent });
}
return segments;
}