···
justify-content: space-between;
···
background-color: var(--card-bg);
border: 1px solid var(--border-color);
95
-
margin-bottom: 15px;
97
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
98
-
transition: transform 0.2s ease, box-shadow 0.2s ease;
97
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
98
+
transition: background-color 0.2s ease;
102
-
transform: translateY(-2px);
103
-
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
102
+
background-color: #202930;
106
-
.feed-item-header {
107
-
padding: 10px 15px;
108
-
border-bottom: 1px solid var(--border-color);
109
-
background-color: rgba(77, 250, 123, 0.05);
107
+
align-items: center;
114
+
font-family: 'JetBrains Mono', monospace;
115
+
font-size: 0.75rem;
116
+
color: var(--text-muted);
118
+
margin-right: 10px;
121
+
.feed-item-author {
122
+
font-family: 'JetBrains Mono', monospace;
123
+
color: var(--accent-alt);
124
+
font-size: 0.85rem;
126
+
margin-right: 15px;
127
+
white-space: nowrap;
113
-
font-size: 1.15rem;
115
-
margin-bottom: 3px;
132
+
font-size: 0.95rem;
134
+
white-space: nowrap;
136
+
text-overflow: ellipsis;
137
+
margin-right: 15px;
···
color: var(--accent-color);
131
-
justify-content: space-between;
132
-
align-items: center;
134
-
color: var(--text-muted);
137
-
.feed-item-source {
138
-
font-family: 'JetBrains Mono', monospace;
139
-
color: var(--accent-alt);
143
-
padding: 10px 15px;
145
-
border-bottom: 1px solid var(--border-color);
155
+
color: var(--text-muted);
156
+
font-size: 0.85rem;
157
+
margin-right: 15px;
160
+
.feed-item-actions {
162
+
align-items: center;
171
+
border-top: 1px solid var(--border-color);
172
+
background-color: #1d252c;
···
color: var(--text-muted);
185
-
.feed-item-actions {
188
-
justify-content: space-between;
189
-
align-items: center;
background-color: transparent;
194
-
border: 1px solid var(--accent-color);
color: var(--accent-color);
197
-
border-radius: 4px;
font-family: 'JetBrains Mono', monospace;
211
+
border-radius: 3px;
transition: all 0.2s ease;
207
-
background-color: var(--accent-color);
208
-
color: var(--bg-color);
217
+
.read-more-btn:hover {
218
+
background-color: rgba(77, 250, 123, 0.1);
222
+
color: var(--text-muted);
224
+
display: inline-flex;
225
+
align-items: center;
226
+
text-decoration: none;
211
-
.read-more::after {
216
-
transition: transform 0.2s ease;
229
+
.external-link:hover {
230
+
color: var(--accent-alt);
219
-
.read-more.active::after {
220
-
transform: rotate(180deg);
···
font-family: 'JetBrains Mono', monospace;
260
-
font-family: 'JetBrains Mono', monospace;
261
-
font-size: 0.75rem;
265
-
display: inline-flex;
266
-
align-items: center;
267
-
color: var(--text-muted);
268
-
text-decoration: none;
270
-
transition: color 0.2s ease;
273
-
.external-link:hover {
274
-
color: var(--accent-alt);
277
-
.external-link::after {
274
+
@media (max-width: 900px) {
275
+
.feed-item-preview {
@media (max-width: 600px) {
281
+
.feed-item-author {
283
+
margin-right: 10px;
288
-
.feed-item-header, .feed-item-preview, .feed-item-content, .feed-item-actions {
294
-
font-size: 0.75rem;
288
+
margin-right: 10px;
···
const entryCountElement = document.getElementById('entry-count');
const sourceCountElement = document.getElementById('source-count');
326
-
// Function to format date
320
+
// Function to format date (only date, no time)
function formatDate(dateString) {
const date = new Date(dateString);
329
-
return date.toLocaleString('en-US', {
323
+
return date.toLocaleDateString('en-US', {
···
} else if (firstNewline !== -1) {
359
-
// If no period or newline, take first 100 chars
360
-
endIndex = Math.min(text.length, 100);
351
+
// If no period or newline, take first 80 chars
352
+
endIndex = Math.min(text.length, 80);
return text.substring(0, endIndex + 1).trim();
366
-
// Function to attach toggle handlers
367
-
function setupToggleHandlers() {
368
-
document.querySelectorAll('.read-more').forEach(button => {
369
-
button.addEventListener('click', function() {
370
-
const article = this.closest('article');
371
-
const content = article.querySelector('.feed-item-content');
373
-
if (content.style.display === 'block') {
374
-
content.style.display = 'none';
375
-
this.textContent = 'Read More';
376
-
this.classList.remove('active');
378
-
content.style.display = 'block';
379
-
this.textContent = 'Show Less';
380
-
this.classList.add('active');
358
+
// Function to toggle content visibility
359
+
function toggleContent(articleId) {
360
+
const article = document.getElementById(articleId);
361
+
const content = article.querySelector('.feed-item-content');
362
+
const button = article.querySelector('.read-more-btn');
364
+
if (content.style.display === 'block') {
365
+
content.style.display = 'none';
366
+
button.innerHTML = 'More <span class="icon">↓</span>';
368
+
content.style.display = 'block';
369
+
button.innerHTML = 'Less <span class="icon">↑</span>';
···
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
396
+
const articleId = `article-${i}`;
const title = entry.getElementsByTagName('title')[0]?.textContent || 'No Title';
···
const contentType = contentElement?.getAttribute('type') || 'text';
const published = entry.getElementsByTagName('published')[0]?.textContent ||
entry.getElementsByTagName('updated')[0]?.textContent || '';
406
+
const author = entry.getElementsByTagName('author')[0]?.getElementsByTagName('name')[0]?.textContent || 'Unknown';
const categories = entry.getElementsByTagName('category');
// Extract source from category (we're using category to store source name)
···
// Get the first line for preview
const firstLine = getFirstLine(contentHtml);
444
-
// Format the entry HTML
433
+
// Format the entry HTML - single line layout
446
-
<article class="feed-item">
447
-
<div class="feed-item-header">
448
-
<h2 class="feed-item-title"><a href="${link}" target="_blank">${title}</a></h2>
449
-
<div class="feed-item-meta">
450
-
<span class="feed-item-source">${source}</span>
451
-
<span class="timestamp">${formatDate(published)}</span>
435
+
<article id="${articleId}" class="feed-item">
436
+
<div class="feed-item-row">
437
+
<div class="feed-item-date">${formatDate(published)}</div>
438
+
<div class="feed-item-author">${author}</div>
439
+
<div class="feed-item-title"><a href="${link}" target="_blank">${title}</a></div>
440
+
<div class="feed-item-preview">${firstLine}</div>
441
+
<div class="feed-item-actions">
442
+
<button class="read-more-btn" onclick="toggleContent('${articleId}')">More <span class="icon">↓</span></button>
443
+
<a href="${link}" target="_blank" class="external-link">Link <span class="icon">↗</span></a>
454
-
<div class="feed-item-preview">${firstLine}</div>
455
-
<div class="feed-item-actions">
456
-
<button class="read-more">Read More</button>
457
-
<a href="${link}" target="_blank" class="external-link">View Original</a>
<div class="feed-item-content">${contentHtml}</div>
···
sourceCountElement.textContent = sources.size;
454
+
// Add the toggleContent function to the global scope
455
+
window.toggleContent = toggleContent;
// Hide loading, show content
loadingContainer.style.display = 'none';
feedItemsContainer.innerHTML = entriesHTML;
471
-
// Setup toggle handlers
472
-
setupToggleHandlers();
console.error('Error loading feed:', error);