mirror of
https://github.com/aljazceru/awesome-nostr.git
synced 2025-02-22 06:39:00 +00:00
commit
bde289e5ac
@ -478,6 +478,7 @@ Websites with lists of relays and their performance/health:
|
||||
- [tostr](https://github.com/slaninas/tostr) - a twitter to nostr bot
|
||||
- [Undelete my Nostr](https://yonle.github.io/undelete-my-nostr) - 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
129
script.js
@ -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}"
|
||||
|
Loading…
Reference in New Issue
Block a user