POWR/utils/contentParser.ts
DocNR 6c7c54a54e feat(social): implement link and image rendering in social posts
- Create contentParser utility to detect URLs and images in text
- Enhance EnhancedSocialPost to render links as clickable and images as embedded
- Archive unused SocialPost component following project conventions
- Update CHANGELOG.md to document the enhancement

This fixes the issue where links and images weren't properly rendered in the social feeds, improving the user experience by making content more interactive and visual.
2025-04-09 21:50:47 -04:00

91 lines
2.2 KiB
TypeScript

// 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;
}