// get url of current tab chrome.tabs.query({ active: true, currentWindow: true }, async function (tabs) { const tab = tabs[0]; const url = tab.url; const prefix = 'https://huggingface.co./'; if (!url.startsWith(prefix)) { // show error message in .message const message = document.querySelector('.container'); message.innerHTML = '

Not a Hugging Face page.

'; return; } // get project type and path const [type, path] = getProjectTypeAndPath(url); if (type === null) { // show error message in .message const message = document.querySelector('.container'); message.innerHTML = '

No project found.

'; return; } // get project info const res = await fetch(`https://huggingface.co./api/${type}/${path}/likers?expand[]=likeAt`) const likers = await res.json() let likeHistory = transformLikesData(likers) if (likeHistory.length > 40) { // sample 20 points const sampledLikeHistory = [] const step = Math.floor(likeHistory.length / 20) for (let i = 0; i < likeHistory.length; i += step) { sampledLikeHistory.push(likeHistory[i]) } // Add the last point if it's not included if (sampledLikeHistory[sampledLikeHistory.length - 1].x !== likeHistory[likeHistory.length - 1].x) { sampledLikeHistory.push(likeHistory[likeHistory.length - 1]) } likeHistory = sampledLikeHistory } // if likeHistory is empty, show error message if (likeHistory.length === 0) { const message = document.querySelector('.container'); message.innerHTML = '

No likes found.

'; return } const svg = document.querySelector('.line-chart'); new chartXkcd.XY(svg, { title: 'Like History', xLabel: 'Time', yLabel: 'Likes', data: { datasets: [{ label: path, data: likeHistory, }], }, options: { // unxkcdify: true, showLegend: false, xTickCount: 3, yTickCount: 4, legendPosition: chartXkcd.config.positionType.upLeft, showLine: true, timeFormat: 'MM/DD/YYYY', dotSize: 0.5, dataColors: [ "#FBBF24", // Warm Yellow "#60A5FA", // Light Blue "#14B8A6", // Teal "#A78BFA", // Soft Purple "#FF8C00", // Orange "#64748B", // Slate Gray "#FB7185", // Coral Pink "#6EE7B7", // Mint Green "#2563EB", // Deep Blue "#374151" // Charcoal ] }, }); }); function getProjectTypeAndPath(url) { // Define the possible project types // Create a URL object to parse the given url const parsedUrl = new URL(url); // Extract the pathname from the URL and split it into parts const pathParts = parsedUrl.pathname.split('/').filter(part => part.length > 0); if (pathParts.length < 2) { return [null, null]; } // The project type should be the first part of the path const type = pathParts[0]; console.log(type); if (type !== 'spaces' && type !== 'datasets') { // If the type is not spaces or datasets, it should be models const actualType = 'models'; const path = pathParts.slice(0, 2).join('/'); return [actualType, path]; } else { const path = pathParts.slice(1, 3).join('/'); return [type, path]; } } function transformLikesData(likesData) { // Step 1 likesData.sort((a, b) => new Date(a.likedAt) - new Date(b.likedAt)); // Step 2 const cumulativeLikes = {}; let cumulativeCount = 0; // Step 3 likesData.forEach(like => { const date = like.likedAt cumulativeCount++; cumulativeLikes[date] = cumulativeCount; }); // Step 4 const transformedData = Object.keys(cumulativeLikes).map(date => ({ x: date, y: cumulativeLikes[date].toString() })); return transformedData; }