prithivMLmods commited on
Commit
730e8a2
·
verified ·
1 Parent(s): 0d61c5a

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +7 -106
index.html CHANGED
@@ -171,7 +171,7 @@
171
  .input-line {
172
  display: flex;
173
  gap: 10px;
174
- margin-bottom: 12px;
175
  flex-wrap: wrap;
176
  }
177
 
@@ -242,51 +242,6 @@
242
  .exec-btn:hover { opacity: 0.85; }
243
  .exec-btn:disabled { opacity: 0.4; cursor: wait; }
244
 
245
- /* ── Quick Examples Bar ── */
246
- .quick-bar {
247
- display: flex;
248
- align-items: center;
249
- gap: 6px;
250
- flex-wrap: wrap;
251
- margin-bottom: 18px;
252
- padding-bottom: 14px;
253
- border-bottom: 1px solid #141414;
254
- }
255
-
256
- .quick-label {
257
- font-size: 0.68rem;
258
- color: #555555;
259
- text-transform: uppercase;
260
- letter-spacing: 1px;
261
- font-weight: 600;
262
- margin-right: 4px;
263
- }
264
-
265
- .quick-chip {
266
- background: #080808;
267
- border: 1px solid #1f1f1f;
268
- color: #888888;
269
- padding: 4px 10px;
270
- border-radius: 3px;
271
- cursor: pointer;
272
- font-size: 0.7rem;
273
- font-weight: 500;
274
- transition: all 0.15s;
275
- display: inline-flex;
276
- align-items: center;
277
- gap: 5px;
278
- }
279
- .quick-chip:hover {
280
- border-color: #ffffff;
281
- color: #ffffff;
282
- background: #111111;
283
- }
284
- .quick-chip .chip-tag {
285
- font-size: 0.6rem;
286
- color: #555555;
287
- text-transform: uppercase;
288
- }
289
-
290
  /* ── Status ── */
291
  #statusMsg {
292
  padding: 10px 14px;
@@ -302,7 +257,7 @@
302
  /* ── Empty / Home State ── */
303
  .empty-state {
304
  text-align: center;
305
- padding-top: 28px;
306
  }
307
 
308
  .empty-title {
@@ -1068,29 +1023,6 @@
1068
  </button>
1069
  </div>
1070
 
1071
- <!-- Always-visible Quick Examples Bar -->
1072
- <div class="quick-bar">
1073
- <span class="quick-label">examples:</span>
1074
- <button class="quick-chip" data-query="prithivMLmods/Qwen-Image-Edit-2511-Unblur-Upscale">
1075
- <span class="chip-tag">[model]</span> prithivMLmods/Qwen-Image-Edit-2511-Unblur-Upscale
1076
- </button>
1077
- <button class="quick-chip" data-query="autotrust/JEV-27B-VL">
1078
- <span class="chip-tag">[org-model]</span> autotrust/JEV-27B-VL
1079
- </button>
1080
- <button class="quick-chip" data-query="prithivMLmods/Qwen-Image-Edit-2511-LoRAs-Fast">
1081
- <span class="chip-tag">[space]</span> prithivMLmods/Qwen-Image-Edit-2511-LoRAs-Fast
1082
- </button>
1083
- <button class="quick-chip" data-query="prithivMLmods/FireRed-Image-Edit-1.0-Fast">
1084
- <span class="chip-tag">[space]</span> prithivMLmods/FireRed-Image-Edit-1.0-Fast
1085
- </button>
1086
- <button class="quick-chip" data-query="autotrust">
1087
- <span class="chip-tag">[org]</span> autotrust
1088
- </button>
1089
- <button class="quick-chip" data-query="prithivMLmods">
1090
- <span class="chip-tag">[user]</span> prithivMLmods
1091
- </button>
1092
- </div>
1093
-
1094
  <div id="statusMsg"></div>
1095
 
1096
  <!-- Empty State -->
@@ -1238,7 +1170,7 @@
1238
  repoData: null, // single repo metadata
1239
  likers: [], // array of likers if repo
1240
  ownerRepos: [], // all models, datasets, spaces for owner/org
1241
- dailySeries: [], // [{ date, total, cumulative, models, datasets, spaces, reposPolled }]
1242
  exactTimestamps: false,
1243
  chartMode: 'combined', // 'combined' | 'daily' | 'cumulative' | 'breakdown'
1244
  chartRange: 'all', // 'all' | '90' | '30' | '7'
@@ -1353,10 +1285,8 @@
1353
  let s = (rawInput || '').trim();
1354
  if (!s) return null;
1355
 
1356
- // Strip URL wrapper if user pasted full https://huggingface.co/... link
1357
  s = s.replace(/^https?:\/\/(www\.)?(huggingface\.co|hf\.co)\//i, '');
1358
  s = s.replace(/^@/, '').replace(/\/+$/, '');
1359
- // Strip tree/blob suffixes if pasted from browser bar
1360
  s = s.replace(/\/(tree|blob|discussions|settings)\/.*$/i, '');
1361
 
1362
  let forcedType = selectedType !== 'auto' ? selectedType : null;
@@ -1528,7 +1458,6 @@
1528
  const days = getDayList(startIso, nowIso);
1529
  const totalLikes = Math.max(repoData.likes || 0, likers.length);
1530
 
1531
- // Check if likers array includes explicit timestamps
1532
  const timestampedLikers = likers.filter(l => l.at || l.likedAt || l.createdAt || l.date);
1533
  const hasExactTimestamps = timestampedLikers.length > 0;
1534
 
@@ -1548,7 +1477,6 @@
1548
  }
1549
  });
1550
  } else if (totalLikes > 0) {
1551
- // Distribute totalLikes across days since published, anchored on launch spike + commit activity dates
1552
  const rng = createRng(repoData.id || repoData.modelId || 'hf');
1553
  const commitDaySet = new Set();
1554
  if (Array.isArray(commits)) {
@@ -1563,7 +1491,6 @@
1563
 
1564
  const weights = days.map((d, idx) => {
1565
  const progress = idx / Math.max(1, days.length - 1);
1566
- // Launch surge during first 14 days + steady community discovery + commit release spikes
1567
  const launchBoost = idx < 3 ? 4.2 : idx < 10 ? 2.6 : idx < 25 ? 1.5 : 1.0;
1568
  const commitBoost = commitDaySet.has(d) ? 2.4 : 1.0;
1569
  const recencyWave = 0.7 + 0.5 * Math.sin(progress * Math.PI * 3 + rng() * 1.8);
@@ -1571,15 +1498,14 @@
1571
  });
1572
 
1573
  const weightSum = weights.reduce((a, b) => a + b, 0);
1574
- let allocated = 0;
1575
  const exactQuotas = weights.map(w => (w / weightSum) * totalLikes);
1576
  const floors = exactQuotas.map(q => Math.floor(q));
1577
- allocated = floors.reduce((a, b) => a + b, 0);
1578
 
1579
  const remainders = exactQuotas.map((q, idx) => ({ idx, rem: q - floors[idx] }));
1580
  remainders.sort((a, b) => b.rem - a.rem);
1581
 
1582
- let diff = totalLikes - allocated;
1583
  for (let i = 0; i < diff && i < remainders.length; i++) {
1584
  floors[remainders[i].idx]++;
1585
  }
@@ -1589,7 +1515,6 @@
1589
  });
1590
  }
1591
 
1592
- // Assign estimated date to each liker in chronological order if not explicitly present
1593
  if (!hasExactTimestamps && likers.length > 0) {
1594
  const expandedDates = [];
1595
  days.forEach(d => {
@@ -1646,10 +1571,9 @@
1646
 
1647
  const dayBuckets = {};
1648
  days.forEach(d => {
1649
- dayBuckets[d] = { models: 0, datasets: 0, spaces: 0, repos: [] };
1650
  });
1651
 
1652
- // For each repo, distribute its likes from its createdAt to today (with launch surge on its publish week)
1653
  allRepos.forEach(repo => {
1654
  const likes = typeof repo.likes === 'number' ? repo.likes : 0;
1655
  const rCreated = repo.createdAt || repo.lastModified;
@@ -1670,7 +1594,7 @@
1670
  const wSum = weights.reduce((a, b) => a + b, 0);
1671
  const quotas = weights.map(w => (w / wSum) * likes);
1672
  const floors = quotas.map(q => Math.floor(q));
1673
- let rem = likes - floors.reduce((a, b) => a + b, 0);
1674
 
1675
  const order = quotas.map((q, i) => ({ i, r: q - floors[i] })).sort((a, b) => b.r - a.r);
1676
  for (let k = 0; k < rem && k < order.length; k++) {
@@ -1781,7 +1705,6 @@
1781
  els.tabLikersBtn.classList.remove('hidden');
1782
 
1783
  } else {
1784
- // Organization or User mode
1785
  const owner = parsed.owner;
1786
  showMsg(`<span class="spinner"></span> fetching organization / user profile &amp; all repositories for ${escapeHtml(owner)}...`, 'loading');
1787
 
@@ -1913,7 +1836,6 @@
1913
  }
1914
  els.pulseSection.style.display = 'block';
1915
 
1916
- // Show up to the last 365 days in the matrix
1917
  const slice = series.slice(-365);
1918
  const maxDaily = Math.max(1, ...slice.map(d => d.total));
1919
  const activeDays = slice.filter(d => d.total > 0).length;
@@ -2066,7 +1988,6 @@
2066
  const W = rect.width;
2067
  const H = rect.height;
2068
 
2069
- // Clear background
2070
  ctx.fillStyle = '#000000';
2071
  ctx.fillRect(0, 0, W, H);
2072
 
@@ -2087,14 +2008,12 @@
2087
 
2088
  state.chartGeom = { padL, padR, padT, padB, plotW, plotH, W, H, data };
2089
 
2090
- // Header subtitle & legend
2091
  const firstDate = data[0].date;
2092
  const lastDate = data[data.length - 1].date;
2093
  const windowLikes = data.reduce((s, d) => s + d.total, 0);
2094
  els.graphHeaderTitle.textContent = `${state.targetId} — like polling graph`;
2095
  els.graphHeaderSub.textContent = `[${firstDate} → ${lastDate}] (${data.length}d, +${formatNumFull(windowLikes)} likes polled)`;
2096
 
2097
- // Horizontal grid lines & Y-axis labels
2098
  ctx.font = '500 10px "JetBrains Mono", monospace';
2099
  const gridSteps = 4;
2100
 
@@ -2109,7 +2028,6 @@
2109
  ctx.lineTo(padL + plotW, y);
2110
  ctx.stroke();
2111
 
2112
- // Left Y-axis label
2113
  const leftVal = state.chartMode === 'cumulative'
2114
  ? Math.round(minCum + frac * cumSpan)
2115
  : Math.round(frac * maxDaily);
@@ -2118,7 +2036,6 @@
2118
  ctx.textBaseline = 'middle';
2119
  ctx.fillText(formatNum(leftVal), padL - 8, y);
2120
 
2121
- // Right Y-axis label for combined mode (Cumulative)
2122
  if (state.chartMode === 'combined') {
2123
  const rightVal = Math.round(minCum + frac * cumSpan);
2124
  ctx.fillStyle = '#888888';
@@ -2127,7 +2044,6 @@
2127
  }
2128
  }
2129
 
2130
- // X-axis date ticks
2131
  const tickCount = Math.min(data.length, Math.max(2, Math.floor(plotW / 110)));
2132
  ctx.fillStyle = '#666666';
2133
  ctx.textAlign = 'center';
@@ -2143,7 +2059,6 @@
2143
  const stepX = n > 1 ? plotW / (n - 1) : plotW;
2144
  const barW = Math.max(1.5, Math.min(18, (plotW / n) * 0.72));
2145
 
2146
- // 1. Render Daily Bars (Combined, Daily, or Breakdown modes)
2147
  if (state.chartMode === 'combined' || state.chartMode === 'daily') {
2148
  data.forEach((d, idx) => {
2149
  if (d.total <= 0) return;
@@ -2157,7 +2072,6 @@
2157
  ctx.fillRect(cx - barW / 2, by, barW, bh);
2158
  });
2159
  } else if (state.chartMode === 'breakdown') {
2160
- // Stacked bars for Models (#ffffff), Spaces (#888888), Datasets (#444444)
2161
  data.forEach((d, idx) => {
2162
  if (d.total <= 0) return;
2163
  const cx = padL + (n === 1 ? plotW / 2 : idx * stepX);
@@ -2179,7 +2093,6 @@
2179
  });
2180
  }
2181
 
2182
- // 2. Render Cumulative Growth Curve (Combined or Cumulative modes)
2183
  if (state.chartMode === 'combined' || state.chartMode === 'cumulative') {
2184
  const pts = data.map((d, idx) => ({
2185
  x: padL + (n === 1 ? plotW / 2 : idx * stepX),
@@ -2212,7 +2125,6 @@
2212
  }
2213
  }
2214
 
2215
- // 3. Hover Crosshair & Highlight Dot
2216
  if (state.hoverIndex >= 0 && state.hoverIndex < data.length) {
2217
  const hi = state.hoverIndex;
2218
  const hd = data[hi];
@@ -2239,7 +2151,6 @@
2239
  }
2240
  }
2241
 
2242
- // Update Legend Bar
2243
  renderGraphLegend();
2244
  }
2245
 
@@ -2672,14 +2583,12 @@
2672
 
2673
  let y = doc.lastAutoTable.finalY + 8;
2674
 
2675
- // Embed Graph Canvas Image
2676
  const chartImg = els.likeCanvas.toDataURL('image/png');
2677
  doc.setFontSize(11);
2678
  doc.text('Daily & Cumulative Likes Graph:', 14, y);
2679
  doc.addImage(chartImg, 'PNG', 14, y + 3, 182, 62);
2680
  y += 72;
2681
 
2682
- // Top Daily Spikes Table
2683
  const topDays = [...series].sort((a, b) => b.total - a.total).slice(0, 35);
2684
  doc.autoTable({
2685
  startY: y,
@@ -2782,14 +2691,6 @@
2782
  els.fetchBtn.addEventListener('click', executeQuery);
2783
  els.targetInput.addEventListener('keypress', e => { if (e.key === 'Enter') executeQuery(); });
2784
 
2785
- document.querySelectorAll('.quick-chip').forEach(chip => {
2786
- chip.addEventListener('click', () => {
2787
- els.targetInput.value = chip.dataset.query;
2788
- els.typeSelect.value = 'auto';
2789
- executeQuery();
2790
- });
2791
- });
2792
-
2793
  document.querySelectorAll('[data-mode]').forEach(btn => {
2794
  btn.addEventListener('click', () => {
2795
  state.chartMode = btn.dataset.mode;
 
171
  .input-line {
172
  display: flex;
173
  gap: 10px;
174
+ margin-bottom: 20px;
175
  flex-wrap: wrap;
176
  }
177
 
 
242
  .exec-btn:hover { opacity: 0.85; }
243
  .exec-btn:disabled { opacity: 0.4; cursor: wait; }
244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
  /* ── Status ── */
246
  #statusMsg {
247
  padding: 10px 14px;
 
257
  /* ── Empty / Home State ── */
258
  .empty-state {
259
  text-align: center;
260
+ padding-top: 40px;
261
  }
262
 
263
  .empty-title {
 
1023
  </button>
1024
  </div>
1025
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1026
  <div id="statusMsg"></div>
1027
 
1028
  <!-- Empty State -->
 
1170
  repoData: null, // single repo metadata
1171
  likers: [], // array of likers if repo
1172
  ownerRepos: [], // all models, datasets, spaces for owner/org
1173
+ dailySeries: [], // [{ date, total, cumulative, models, datasets, spaces }]
1174
  exactTimestamps: false,
1175
  chartMode: 'combined', // 'combined' | 'daily' | 'cumulative' | 'breakdown'
1176
  chartRange: 'all', // 'all' | '90' | '30' | '7'
 
1285
  let s = (rawInput || '').trim();
1286
  if (!s) return null;
1287
 
 
1288
  s = s.replace(/^https?:\/\/(www\.)?(huggingface\.co|hf\.co)\//i, '');
1289
  s = s.replace(/^@/, '').replace(/\/+$/, '');
 
1290
  s = s.replace(/\/(tree|blob|discussions|settings)\/.*$/i, '');
1291
 
1292
  let forcedType = selectedType !== 'auto' ? selectedType : null;
 
1458
  const days = getDayList(startIso, nowIso);
1459
  const totalLikes = Math.max(repoData.likes || 0, likers.length);
1460
 
 
1461
  const timestampedLikers = likers.filter(l => l.at || l.likedAt || l.createdAt || l.date);
1462
  const hasExactTimestamps = timestampedLikers.length > 0;
1463
 
 
1477
  }
1478
  });
1479
  } else if (totalLikes > 0) {
 
1480
  const rng = createRng(repoData.id || repoData.modelId || 'hf');
1481
  const commitDaySet = new Set();
1482
  if (Array.isArray(commits)) {
 
1491
 
1492
  const weights = days.map((d, idx) => {
1493
  const progress = idx / Math.max(1, days.length - 1);
 
1494
  const launchBoost = idx < 3 ? 4.2 : idx < 10 ? 2.6 : idx < 25 ? 1.5 : 1.0;
1495
  const commitBoost = commitDaySet.has(d) ? 2.4 : 1.0;
1496
  const recencyWave = 0.7 + 0.5 * Math.sin(progress * Math.PI * 3 + rng() * 1.8);
 
1498
  });
1499
 
1500
  const weightSum = weights.reduce((a, b) => a + b, 0);
 
1501
  const exactQuotas = weights.map(w => (w / weightSum) * totalLikes);
1502
  const floors = exactQuotas.map(q => Math.floor(q));
1503
+ const allocated = floors.reduce((a, b) => a + b, 0);
1504
 
1505
  const remainders = exactQuotas.map((q, idx) => ({ idx, rem: q - floors[idx] }));
1506
  remainders.sort((a, b) => b.rem - a.rem);
1507
 
1508
+ const diff = totalLikes - allocated;
1509
  for (let i = 0; i < diff && i < remainders.length; i++) {
1510
  floors[remainders[i].idx]++;
1511
  }
 
1515
  });
1516
  }
1517
 
 
1518
  if (!hasExactTimestamps && likers.length > 0) {
1519
  const expandedDates = [];
1520
  days.forEach(d => {
 
1571
 
1572
  const dayBuckets = {};
1573
  days.forEach(d => {
1574
+ dayBuckets[d] = { models: 0, datasets: 0, spaces: 0 };
1575
  });
1576
 
 
1577
  allRepos.forEach(repo => {
1578
  const likes = typeof repo.likes === 'number' ? repo.likes : 0;
1579
  const rCreated = repo.createdAt || repo.lastModified;
 
1594
  const wSum = weights.reduce((a, b) => a + b, 0);
1595
  const quotas = weights.map(w => (w / wSum) * likes);
1596
  const floors = quotas.map(q => Math.floor(q));
1597
+ const rem = likes - floors.reduce((a, b) => a + b, 0);
1598
 
1599
  const order = quotas.map((q, i) => ({ i, r: q - floors[i] })).sort((a, b) => b.r - a.r);
1600
  for (let k = 0; k < rem && k < order.length; k++) {
 
1705
  els.tabLikersBtn.classList.remove('hidden');
1706
 
1707
  } else {
 
1708
  const owner = parsed.owner;
1709
  showMsg(`<span class="spinner"></span> fetching organization / user profile &amp; all repositories for ${escapeHtml(owner)}...`, 'loading');
1710
 
 
1836
  }
1837
  els.pulseSection.style.display = 'block';
1838
 
 
1839
  const slice = series.slice(-365);
1840
  const maxDaily = Math.max(1, ...slice.map(d => d.total));
1841
  const activeDays = slice.filter(d => d.total > 0).length;
 
1988
  const W = rect.width;
1989
  const H = rect.height;
1990
 
 
1991
  ctx.fillStyle = '#000000';
1992
  ctx.fillRect(0, 0, W, H);
1993
 
 
2008
 
2009
  state.chartGeom = { padL, padR, padT, padB, plotW, plotH, W, H, data };
2010
 
 
2011
  const firstDate = data[0].date;
2012
  const lastDate = data[data.length - 1].date;
2013
  const windowLikes = data.reduce((s, d) => s + d.total, 0);
2014
  els.graphHeaderTitle.textContent = `${state.targetId} — like polling graph`;
2015
  els.graphHeaderSub.textContent = `[${firstDate} → ${lastDate}] (${data.length}d, +${formatNumFull(windowLikes)} likes polled)`;
2016
 
 
2017
  ctx.font = '500 10px "JetBrains Mono", monospace';
2018
  const gridSteps = 4;
2019
 
 
2028
  ctx.lineTo(padL + plotW, y);
2029
  ctx.stroke();
2030
 
 
2031
  const leftVal = state.chartMode === 'cumulative'
2032
  ? Math.round(minCum + frac * cumSpan)
2033
  : Math.round(frac * maxDaily);
 
2036
  ctx.textBaseline = 'middle';
2037
  ctx.fillText(formatNum(leftVal), padL - 8, y);
2038
 
 
2039
  if (state.chartMode === 'combined') {
2040
  const rightVal = Math.round(minCum + frac * cumSpan);
2041
  ctx.fillStyle = '#888888';
 
2044
  }
2045
  }
2046
 
 
2047
  const tickCount = Math.min(data.length, Math.max(2, Math.floor(plotW / 110)));
2048
  ctx.fillStyle = '#666666';
2049
  ctx.textAlign = 'center';
 
2059
  const stepX = n > 1 ? plotW / (n - 1) : plotW;
2060
  const barW = Math.max(1.5, Math.min(18, (plotW / n) * 0.72));
2061
 
 
2062
  if (state.chartMode === 'combined' || state.chartMode === 'daily') {
2063
  data.forEach((d, idx) => {
2064
  if (d.total <= 0) return;
 
2072
  ctx.fillRect(cx - barW / 2, by, barW, bh);
2073
  });
2074
  } else if (state.chartMode === 'breakdown') {
 
2075
  data.forEach((d, idx) => {
2076
  if (d.total <= 0) return;
2077
  const cx = padL + (n === 1 ? plotW / 2 : idx * stepX);
 
2093
  });
2094
  }
2095
 
 
2096
  if (state.chartMode === 'combined' || state.chartMode === 'cumulative') {
2097
  const pts = data.map((d, idx) => ({
2098
  x: padL + (n === 1 ? plotW / 2 : idx * stepX),
 
2125
  }
2126
  }
2127
 
 
2128
  if (state.hoverIndex >= 0 && state.hoverIndex < data.length) {
2129
  const hi = state.hoverIndex;
2130
  const hd = data[hi];
 
2151
  }
2152
  }
2153
 
 
2154
  renderGraphLegend();
2155
  }
2156
 
 
2583
 
2584
  let y = doc.lastAutoTable.finalY + 8;
2585
 
 
2586
  const chartImg = els.likeCanvas.toDataURL('image/png');
2587
  doc.setFontSize(11);
2588
  doc.text('Daily & Cumulative Likes Graph:', 14, y);
2589
  doc.addImage(chartImg, 'PNG', 14, y + 3, 182, 62);
2590
  y += 72;
2591
 
 
2592
  const topDays = [...series].sort((a, b) => b.total - a.total).slice(0, 35);
2593
  doc.autoTable({
2594
  startY: y,
 
2691
  els.fetchBtn.addEventListener('click', executeQuery);
2692
  els.targetInput.addEventListener('keypress', e => { if (e.key === 'Enter') executeQuery(); });
2693
 
 
 
 
 
 
 
 
 
2694
  document.querySelectorAll('[data-mode]').forEach(btn => {
2695
  btn.addEventListener('click', () => {
2696
  state.chartMode = btn.dataset.mode;