Merge pull request #525 from Yeghro/fineTuning

Fine tuning
This commit is contained in:
Aljaz Ceru 2025-01-26 06:34:19 -06:00 committed by GitHub
commit bde289e5ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 94 additions and 36 deletions

View File

@ -478,6 +478,7 @@ Websites with lists of relays and their performance/health:
- [tostr](https://github.com/slaninas/tostr)![stars](https://img.shields.io/github/stars/slaninas/tostr.svg?style=social) - a twitter to nostr bot
- [Undelete my Nostr](https://yonle.github.io/undelete-my-nostr)![stars](https://img.shields.io/github/stars/Yonle/undelete-my-nostr.svg?style=social) - Simple tool for restoring deleted nostr account.
- [Zapper](https://zapper.nostrapps.org) - Nostr micro-app for zapping
- [YEGHRO unFollow Tool](https://unfollow.yeghro.com) - A tool that allows you to unfollow inactive users on nostr.
## NIP-05 identity services

129
script.js
View File

@ -371,35 +371,8 @@ searchInput.addEventListener('input', (e) => {
Object.entries(window.parsedResources).forEach(([sectionName, sectionContent]) => {
sectionContent.forEach(item => {
if (item.type === 'resources') {
// Search through resource lists
Array.from(item.element.children).forEach(li => {
const resourceName = li.querySelector('a')?.textContent || '';
const resourceLink = li.querySelector('a')?.href || '';
const resourceDescription = li.textContent.split('- ')[1]?.trim() || '';
const searchableText = [resourceName, resourceDescription, resourceLink]
.join(' ')
.toLowerCase();
if (searchableText.includes(searchTerm)) {
const card = createResourceCard({
name: resourceName,
link: resourceLink,
description: resourceDescription,
stars: li.querySelector('img[alt="stars"]')
? parseInt(li.querySelector('img[alt="stars"]').src.match(/stars\/(\d+)/)?.[1]) || 0
: 0
});
// Add section label to card
const sectionLabel = document.createElement('div');
sectionLabel.className = 'category-label';
sectionLabel.textContent = sectionName;
card.insertBefore(sectionLabel, card.firstChild);
container.appendChild(card);
}
});
// Process both top-level and nested items for search
searchResourceList(item.element, container, searchTerm, sectionName);
} else if (item.type === 'content') {
// Search through regular content
const contentText = item.element.textContent.toLowerCase();
@ -430,6 +403,51 @@ searchInput.addEventListener('input', (e) => {
}
});
// New helper function to search through resource lists recursively
function searchResourceList(ulElement, container, searchTerm, sectionName) {
Array.from(ulElement.children).forEach(li => {
// Search in the main item if it has a link
if (li.querySelector(':scope > a')) {
const resourceName = li.querySelector(':scope > a')?.textContent || '';
const resourceLink = li.querySelector(':scope > a')?.href || '';
const description = li.textContent
.replace(resourceName, '') // Remove the resource name
.replace(/^\s*-\s*/, '') // Remove leading dash
.replace(/\s*\[!\[.*?\]\(.*?\)\]\(.*?\)\s*/, '') // Remove GitHub stars badge if present
.trim();
const searchableText = [resourceName, description, resourceLink]
.join(' ')
.toLowerCase();
if (searchableText.includes(searchTerm)) {
const card = createResourceCard({
name: resourceName,
link: resourceLink,
description: description,
stars: li.querySelector(':scope > img[alt="stars"]')
? parseInt(li.querySelector(':scope > img[alt="stars"]').src.match(/stars\/(\d+)/)?.[1]) || 0
: 0
});
// Add section label to card
const sectionLabel = document.createElement('div');
sectionLabel.className = 'category-label';
sectionLabel.textContent = sectionName;
card.insertBefore(sectionLabel, card.firstChild);
container.appendChild(card);
}
}
// Search in nested items if they exist
const nestedUl = li.querySelector(':scope > ul');
if (nestedUl) {
searchResourceList(nestedUl, container, searchTerm, sectionName);
}
});
}
// Add active class handling for navigation
document.querySelectorAll('.nav-links a').forEach(link => {
link.addEventListener('click', () => {
@ -579,11 +597,10 @@ function parseResources(content) {
// Function to parse a single resource line
function parseResourceLine(line) {
// Updated regex patterns to better handle various markdown formats
// Same regex patterns as before
const nameRegex = /\[(.*?)\]/;
const linkRegex = /\((.*?)\)/;
const starsRegex = /!\[stars\].*?stars\/(.*?)\/.*?style=social/;
// Updated description regex to handle descriptions after stars badge
const descriptionRegex = /style=social\) - (.*?)(?=(?:\[|\n|$))|(?:\) - )(.*?)(?=(?:\[|\n|$))/;
try {
@ -591,7 +608,6 @@ function parseResourceLine(line) {
const link = linkRegex.exec(line)?.[1];
const stars = starsRegex.exec(line)?.[1];
// More robust description extraction
const descMatch = descriptionRegex.exec(line);
const description = (descMatch?.[1] || descMatch?.[2] || '').trim();
@ -599,7 +615,7 @@ function parseResourceLine(line) {
return {
name,
link,
stars: stars || 0,
stars: stars ? parseInt(stars) : 0,
description: description || '',
raw: line.trim()
};
@ -619,18 +635,59 @@ function createResourceCard(resource) {
card.setAttribute('itemscope', '');
card.setAttribute('itemtype', 'https://schema.org/SoftwareApplication');
// Extract domain for favicon
// Extract domain and build multiple fallback favicon URLs
let faviconUrl = '';
try {
const url = new URL(resource.link);
faviconUrl = `https://www.google.com/s2/favicons?domain=${url.hostname}&sz=64`;
const domain = url.hostname;
// Try multiple favicon sources
const faviconSources = [
`https://www.google.com/s2/favicons?domain=${domain}&sz=64`,
`https://${domain}/favicon.ico`,
`https://${domain}/favicon.png`,
`https://${domain}/apple-touch-icon.png`,
`https://${domain}/apple-touch-icon-precomposed.png`
];
// Create image element with fallback chain
const img = document.createElement('img');
img.className = 'resource-favicon';
img.alt = '';
// Set first source as initial
img.src = faviconSources[0];
// Add error handling to try next source
let sourceIndex = 0;
img.onerror = () => {
sourceIndex++;
if (sourceIndex < faviconSources.length) {
img.src = faviconSources[sourceIndex];
} else {
// If all sources fail, use a default icon
img.src = 'data:image/svg+xml,' + encodeURIComponent(`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="32" height="32">
<circle cx="50" cy="50" r="40" fill="#ccc"/>
<text x="50" y="65" font-size="40" text-anchor="middle" fill="#fff">
${resource.name.charAt(0).toUpperCase()}
</text>
</svg>
`);
img.onerror = null; // Remove error handler once default is shown
}
};
faviconUrl = img.outerHTML;
} catch (e) {
console.warn('Invalid URL:', resource.link);
// Use default icon for invalid URLs
faviconUrl = `<div class="resource-favicon-fallback">${resource.name.charAt(0).toUpperCase()}</div>`;
}
card.innerHTML = `
<div class="resource-header">
${faviconUrl ? `<img src="${faviconUrl}" alt="" class="resource-favicon" />` : ''}
${faviconUrl}
<div class="resource-content">
<h3 class="resource-title">
<a href="${resource.link}"