mirror of
https://github.com/aljazceru/awesome-nostr.git
synced 2025-02-23 07:09:00 +00:00
added mark.js and now it looks and works even better
This commit is contained in:
parent
e390d63ba4
commit
4a5bfedd1f
@ -49,6 +49,8 @@
|
|||||||
<div id="resources-container"></div>
|
<div id="resources-container"></div>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Add marked.js before your script -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
248
script.js
248
script.js
@ -201,6 +201,7 @@ function parseResources(content) {
|
|||||||
if (line.startsWith('## ')) {
|
if (line.startsWith('## ')) {
|
||||||
currentMainSection = line.slice(3).trim();
|
currentMainSection = line.slice(3).trim();
|
||||||
currentSubSection = '';
|
currentSubSection = '';
|
||||||
|
console.log('Processing section:', currentMainSection); // Debug log
|
||||||
} else if (currentMainSection.toLowerCase() === 'contributors') {
|
} else if (currentMainSection.toLowerCase() === 'contributors') {
|
||||||
const match = line.match(repoRegex);
|
const match = line.match(repoRegex);
|
||||||
if (match) {
|
if (match) {
|
||||||
@ -228,9 +229,13 @@ function parseResources(content) {
|
|||||||
.replace(/[^a-z0-9]+/g, '-')
|
.replace(/[^a-z0-9]+/g, '-')
|
||||||
.replace(/(^-|-$)/g, '');
|
.replace(/(^-|-$)/g, '');
|
||||||
|
|
||||||
|
console.log('Parsed resource:', categoryId, resource); // Debug log
|
||||||
|
|
||||||
// Add resource to appropriate category if it exists
|
// Add resource to appropriate category if it exists
|
||||||
if (resources[categoryId]) {
|
if (resources[categoryId]) {
|
||||||
resources[categoryId].push(resource);
|
resources[categoryId].push(resource);
|
||||||
|
} else {
|
||||||
|
console.warn('Category not found:', categoryId); // Debug log
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,29 +259,33 @@ function parseResources(content) {
|
|||||||
|
|
||||||
// Function to parse a single resource line
|
// Function to parse a single resource line
|
||||||
function parseResourceLine(line) {
|
function parseResourceLine(line) {
|
||||||
// Regular expressions to extract information
|
// Updated regex patterns to better handle various markdown formats
|
||||||
const nameRegex = /\[(.*?)\]/;
|
const nameRegex = /\[(.*?)\]/;
|
||||||
const linkRegex = /\((.*?)\)/;
|
const linkRegex = /\((.*?)\)/;
|
||||||
const starsRegex = /!\[stars\].*?stars\/(.*?)\/.*?style=social/;
|
const starsRegex = /!\[stars\].*?stars\/(.*?)\/.*?style=social/;
|
||||||
const descriptionRegex = /\) - (.*?)(?=\[|$)/;
|
// Updated description regex to handle descriptions after stars badge
|
||||||
|
const descriptionRegex = /style=social\) - (.*?)(?=(?:\[|\n|$))|(?:\) - )(.*?)(?=(?:\[|\n|$))/;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const name = nameRegex.exec(line)?.[1];
|
const name = nameRegex.exec(line)?.[1];
|
||||||
const link = linkRegex.exec(line)?.[1];
|
const link = linkRegex.exec(line)?.[1];
|
||||||
const stars = starsRegex.exec(line)?.[1];
|
const stars = starsRegex.exec(line)?.[1];
|
||||||
const description = descriptionRegex.exec(line)?.[1]?.trim();
|
|
||||||
|
|
||||||
if (name && (link || description)) {
|
// More robust description extraction
|
||||||
|
const descMatch = descriptionRegex.exec(line);
|
||||||
|
const description = (descMatch?.[1] || descMatch?.[2] || '').trim();
|
||||||
|
|
||||||
|
if (name && link) {
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
link,
|
link,
|
||||||
stars: stars || 0,
|
stars: stars || 0,
|
||||||
description: description || '',
|
description: description || '',
|
||||||
raw: line.trim() // Keep the original markdown line
|
raw: line.trim()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error parsing resource line:', error);
|
console.error('Error parsing resource line:', error, line);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -287,7 +296,6 @@ function createResourceCard(resource) {
|
|||||||
card.className = 'resource-card';
|
card.className = 'resource-card';
|
||||||
card.dataset.stars = resource.stars || 0;
|
card.dataset.stars = resource.stars || 0;
|
||||||
|
|
||||||
// Create a formatted version of the markdown content
|
|
||||||
const formattedContent = `
|
const formattedContent = `
|
||||||
<div class="resource-title"><strong>${resource.name}</strong></div>
|
<div class="resource-title"><strong>${resource.name}</strong></div>
|
||||||
${resource.link ? `
|
${resource.link ? `
|
||||||
@ -421,74 +429,194 @@ function getCategoryIcon(category) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to generate navigation from content
|
// Function to generate navigation from content
|
||||||
function generateNavigation(content) {
|
function generateNavigation(sectionNames) {
|
||||||
const navList = document.querySelector('.nav-links');
|
const navList = document.querySelector('.nav-links');
|
||||||
const categories = [];
|
navList.innerHTML = ''; // Clear existing navigation
|
||||||
let currentCategory = '';
|
|
||||||
|
|
||||||
// Split content by lines and find all ## headers
|
sectionNames.forEach(section => {
|
||||||
const lines = content.split('\n');
|
// Create URL-friendly ID
|
||||||
lines.forEach(line => {
|
const sectionId = section
|
||||||
if (line.startsWith('## ')) {
|
.toLowerCase()
|
||||||
currentCategory = line.slice(3).trim();
|
.replace(/[^a-z0-9]+/g, '-')
|
||||||
const categoryId = currentCategory.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
.replace(/(^-|-$)/g, '');
|
||||||
const icon = getCategoryIcon(currentCategory.toLowerCase());
|
|
||||||
|
|
||||||
categories.push({
|
const li = document.createElement('li');
|
||||||
id: categoryId,
|
li.innerHTML = `
|
||||||
name: currentCategory,
|
<a href="#${sectionId}" data-section="${section}">
|
||||||
icon: icon
|
<i class="fas fa-chevron-right"></i>
|
||||||
});
|
${section}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generate navigation HTML
|
|
||||||
navList.innerHTML = categories.map(category => `
|
|
||||||
<li>
|
|
||||||
<a href="#${category.id}">
|
|
||||||
<i class="fas ${category.icon}"></i>
|
|
||||||
${category.name}
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
`;
|
||||||
`).join('');
|
|
||||||
|
|
||||||
// Add click event listeners to the new navigation items
|
// Add click handler
|
||||||
document.querySelectorAll('.nav-links a').forEach(link => {
|
li.querySelector('a').addEventListener('click', (e) => {
|
||||||
link.addEventListener('click', (e) => {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const categoryId = e.target.getAttribute('href').replace('#', '');
|
// Remove active class from all links
|
||||||
populateResources(categoryId, window.parsedResources);
|
document.querySelectorAll('.nav-links a').forEach(a =>
|
||||||
});
|
a.classList.remove('active')
|
||||||
|
);
|
||||||
|
// Add active class to clicked link
|
||||||
|
e.target.classList.add('active');
|
||||||
|
// Display the section
|
||||||
|
displaySection(section, window.parsedResources);
|
||||||
});
|
});
|
||||||
|
|
||||||
return categories;
|
navList.appendChild(li);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set first item as active
|
||||||
|
const firstLink = navList.querySelector('a');
|
||||||
|
if (firstLink) {
|
||||||
|
firstLink.classList.add('active');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the fetch call to generate navigation
|
// Remove the old fetch call and replace with this initialization
|
||||||
fetch('./README.md')
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
.then(response => {
|
// Test if marked is loaded
|
||||||
|
if (typeof marked === 'undefined') {
|
||||||
|
console.error('marked.js is not loaded!');
|
||||||
|
document.getElementById('resources-container').innerHTML = `
|
||||||
|
<div class="error-message">
|
||||||
|
Error: marked.js library is not loaded properly.
|
||||||
|
</div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test marked with a simple markdown string
|
||||||
|
console.log('marked.js test:', marked.parse('# Test\nThis is a *test* of **marked.js**'));
|
||||||
|
|
||||||
|
// If everything is working, proceed with main functionality
|
||||||
|
parseAndDisplayContent()
|
||||||
|
.then(() => console.log('Content successfully parsed and displayed'))
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error in main content processing:', error);
|
||||||
|
document.getElementById('resources-container').innerHTML = `
|
||||||
|
<div class="error-message">
|
||||||
|
Error loading content: ${error.message}
|
||||||
|
</div>`;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function parseAndDisplayContent() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('./README.md');
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
}
|
}
|
||||||
return response.text();
|
const content = await response.text();
|
||||||
})
|
|
||||||
.then(content => {
|
|
||||||
console.log('README content loaded:', content.substring(0, 200) + '...');
|
|
||||||
|
|
||||||
// Generate navigation first
|
// Parse the markdown into HTML
|
||||||
const categories = generateNavigation(content);
|
const htmlContent = marked.parse(content);
|
||||||
|
|
||||||
// Then parse and populate resources
|
// Create a temporary element to parse the HTML
|
||||||
window.parsedResources = parseResources(content);
|
const tempDiv = document.createElement('div');
|
||||||
console.log('Parsed resources:', window.parsedResources);
|
tempDiv.innerHTML = htmlContent;
|
||||||
|
|
||||||
// Load initial category (first one in the list)
|
// Get all sections (h2 headers and their content)
|
||||||
if (categories.length > 0) {
|
const sections = {};
|
||||||
populateResources(categories[0].id, window.parsedResources);
|
let currentSection = null;
|
||||||
|
let currentSectionContent = [];
|
||||||
|
|
||||||
|
Array.from(tempDiv.children).forEach(element => {
|
||||||
|
if (element.tagName === 'H2') {
|
||||||
|
// If we have a previous section, save it
|
||||||
|
if (currentSection) {
|
||||||
|
sections[currentSection] = currentSectionContent;
|
||||||
}
|
}
|
||||||
})
|
// Start new section
|
||||||
.catch(error => {
|
currentSection = element.textContent.trim();
|
||||||
console.error('Error loading README:', error);
|
currentSectionContent = [];
|
||||||
document.getElementById('resources-container').innerHTML =
|
} else if (currentSection) {
|
||||||
`<div class="error-message">Error loading resources: ${error.message}</div>`;
|
currentSectionContent.push({
|
||||||
|
type: element.tagName === 'UL' ? 'resources' : 'content',
|
||||||
|
element: element
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save the last section
|
||||||
|
if (currentSection) {
|
||||||
|
sections[currentSection] = currentSectionContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store sections globally
|
||||||
|
window.parsedResources = sections;
|
||||||
|
|
||||||
|
// Generate navigation
|
||||||
|
const sectionNames = Object.keys(sections);
|
||||||
|
generateNavigation(sectionNames);
|
||||||
|
|
||||||
|
// Display initial section
|
||||||
|
if (sectionNames.length > 0) {
|
||||||
|
displaySection(sectionNames[0], sections);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error processing markdown:', error);
|
||||||
|
throw error; // Re-throw to be caught by the main error handler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function displaySection(sectionName, sections) {
|
||||||
|
const container = document.getElementById('resources-container');
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
// Add section header
|
||||||
|
const header = document.createElement('h2');
|
||||||
|
header.textContent = sectionName;
|
||||||
|
container.appendChild(header);
|
||||||
|
|
||||||
|
// Display section content
|
||||||
|
sections[sectionName].forEach(item => {
|
||||||
|
if (item.type === 'content') {
|
||||||
|
// Regular markdown content
|
||||||
|
const contentDiv = document.createElement('div');
|
||||||
|
contentDiv.className = 'markdown-content';
|
||||||
|
contentDiv.innerHTML = item.element.outerHTML;
|
||||||
|
container.appendChild(contentDiv);
|
||||||
|
} else if (item.type === 'resources') {
|
||||||
|
// Resource list
|
||||||
|
Array.from(item.element.children).forEach(li => {
|
||||||
|
const card = createResourceCard({
|
||||||
|
name: li.querySelector('a')?.textContent || '',
|
||||||
|
link: li.querySelector('a')?.href || '',
|
||||||
|
description: li.textContent.split('- ')[1]?.trim() || '',
|
||||||
|
stars: li.querySelector('img[alt="stars"]')
|
||||||
|
? parseInt(li.querySelector('img[alt="stars"]').src.match(/stars\/(\d+)/)?.[1]) || 0
|
||||||
|
: 0
|
||||||
|
});
|
||||||
|
container.appendChild(card);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createResourceCard(resource) {
|
||||||
|
const card = document.createElement('div');
|
||||||
|
card.className = 'resource-card';
|
||||||
|
|
||||||
|
card.innerHTML = `
|
||||||
|
<div class="resource-header">
|
||||||
|
<h3 class="resource-title">
|
||||||
|
<a href="${resource.link}" target="_blank">
|
||||||
|
${resource.name}
|
||||||
|
<i class="fas fa-external-link-alt"></i>
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
${resource.stars ? `
|
||||||
|
<div class="resource-stars">
|
||||||
|
<i class="fas fa-star"></i>
|
||||||
|
${resource.stars}
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
|
${resource.description ? `
|
||||||
|
<div class="resource-description">
|
||||||
|
${resource.description}
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
`;
|
||||||
|
|
||||||
|
return card;
|
||||||
|
}
|
21
styles.css
21
styles.css
@ -146,7 +146,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.resource-link a {
|
.resource-link a {
|
||||||
color: var(--link-color);
|
color: var(--primary-color);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -159,12 +159,14 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.resource-description {
|
.resource-description {
|
||||||
color: var(--text-secondary);
|
color: var(--text-color);
|
||||||
margin-bottom: 12px;
|
margin: 12px 0;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-size: 0.95em;
|
font-size: 0.95em;
|
||||||
padding-left: 8px;
|
padding: 8px 12px;
|
||||||
border-left: 3px solid var(--border-color);
|
background: rgba(110, 84, 148, 0.05);
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 3px solid var(--primary-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.resource-stars {
|
.resource-stars {
|
||||||
@ -313,3 +315,12 @@ body {
|
|||||||
background-color: var(--primary-color);
|
background-color: var(--primary-color);
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem;
|
||||||
|
background-color: #fff3f3;
|
||||||
|
border-left: 4px solid #ff4444;
|
||||||
|
color: #dc3545;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user