Spaces:
Running
Running
// 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 = '<h2>Not a Hugging Face page.</h2>'; | |
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 = '<h2>No project found.</h2>'; | |
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 = '<h2>No likes found.</h2>'; | |
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; | |
} |