Spaces:
Running
Running
File size: 4,069 Bytes
f31a721 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | import uFuzzy from "@leeoniya/ufuzzy";
/**
* Extracts hostname from a URL, removing www. prefix
* @param url - The URL to extract hostname from
* @returns The hostname without www. prefix, or the original string if parsing fails
*/
export function getHostname(url: string) {
try {
return new URL(url).hostname.replace("www.", "");
} catch {
return url;
}
}
/**
* Converts a date to semantic version format (YYYY.MM.DD)
* @param date - The date to convert
* @returns Semantic version string
*/
export function getSemanticVersion(date: number | string | Date) {
const targetDate = new Date(date);
return `${targetDate.getFullYear()}.${targetDate.getMonth() + 1}.${targetDate.getDate()}`;
}
/**
* Formats a timestamp as relative time (e.g., "2h ago", "3d ago")
* @param timestamp - The timestamp to format
* @returns Relative time string
*/
export function formatRelativeTime(timestamp: number): string {
const now = Date.now();
const diff = now - timestamp;
const minutes = Math.floor(diff / 60000);
const hours = Math.floor(diff / 3600000);
const days = Math.floor(diff / 86400000);
if (minutes < 1) return "Just now";
if (minutes < 60) return `${minutes}m ago`;
if (hours < 24) return `${hours}h ago`;
if (days < 7) return `${days}d ago`;
return new Date(timestamp).toLocaleDateString();
}
const uf = new uFuzzy({
intraMode: 1,
intraIns: 1,
intraSub: 1,
intraDel: 1,
intraTrn: 1,
intraChars: "[\\w-]",
interChars: "[^a-z\\d]",
});
const infoThresh = 1000;
/**
* Fuzzy search implementation using uFuzzy library
* @param items - Array of items to search through
* @param query - Search query string
* @param extractText - Function to extract searchable text from each item
* @param limit - Maximum number of results to return
* @returns Array of items with their search scores
*/
export function searchWithFuzzy<T>(
items: T[],
query: string,
extractText: (item: T) => string,
limit?: number,
): Array<{ item: T; score: number }> {
if (!query.trim()) {
return items.slice(0, limit).map((item) => ({ item, score: 0 }));
}
const haystack = items.map(extractText);
const needle = query.trim();
const [idxs, info, order] = uf.search(haystack, needle, 0, infoThresh);
if (!idxs || idxs.length === 0) {
return [];
}
let orderedIdxs: number[] = [];
if (info && order) {
orderedIdxs = order.map((i) => info.idx[i]);
} else {
orderedIdxs = idxs;
}
const finalIdxs = orderedIdxs.slice(0, limit ?? orderedIdxs.length);
return finalIdxs.map((idx, rank) => ({
item: items[idx],
score: 1 - rank / finalIdxs.length,
}));
}
/**
* Groups search results by date categories (Today, Yesterday, This Week, etc.)
* @param items - Array of items with timestamps to group
* @returns Object with date group keys as properties and arrays of items as values
*/
export function groupSearchResultsByDate<T>(
items: Array<{ item: T; timestamp: number }>,
): Record<string, Array<{ item: T; timestamp: number }>> {
const groups: Record<string, Array<{ item: T; timestamp: number }>> = {};
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);
const weekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
for (const result of items) {
const date = new Date(result.timestamp);
let groupKey: string;
if (date >= today) {
groupKey = "Today";
} else if (date >= yesterday) {
groupKey = "Yesterday";
} else if (date >= weekAgo) {
groupKey = "This Week";
} else {
const monthNames = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
groupKey = `${monthNames[date.getMonth()]} ${date.getFullYear()}`;
}
if (!groups[groupKey]) {
groups[groupKey] = [];
}
groups[groupKey].push(result);
}
return groups;
}
|