summaryrefslogtreecommitdiff
path: root/js/rss-feed-preview.js
diff options
context:
space:
mode:
authormayx <mayx@outlook.com>2025-04-11 19:07:43 +0200
committermayx <mayx@outlook.com>2025-04-11 19:07:43 +0200
commit91dd8a34ea8487e21bdbfb25d906523ff627c926 (patch)
treedf434597e29784f71032a0f2046920b02f7399f7 /js/rss-feed-preview.js
parentc7cabd991a2ca69cf00f4daf9a663de53deaf5d6 (diff)
Update 24 files
- /css/gitalk.css - /js/aes.js - /js/gitalk.min.js - /js/jquery.min.js - /js/main.js - /js/rss-feed-preview.js - /js/simple-jekyll-search.min.js - /assets/css/gitalk.css - /assets/js/rss-feed-preview.js - /assets/js/main.js - /assets/js/jquery.min.js - /assets/js/simple-jekyll-search.min.js - /assets/js/aes.js - /assets/js/gitalk.min.js - /assets/js/instant.page.js - /_layouts/post.html - /_layouts/encrypt.html - /_layouts/default.html - /search.html - /aes.html - /_posts/2025-04-08-feed.md - /links.md - /blogroll.opml - /jump.html
Diffstat (limited to 'js/rss-feed-preview.js')
-rw-r--r--js/rss-feed-preview.js236
1 files changed, 0 insertions, 236 deletions
diff --git a/js/rss-feed-preview.js b/js/rss-feed-preview.js
deleted file mode 100644
index 2929622..0000000
--- a/js/rss-feed-preview.js
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
- * RSS/Atom Feed Preview for Links Table
- */
-
-(function() {
- const existingPreviews = document.querySelectorAll('#rss-feed-preview');
- existingPreviews.forEach(el => el.remove());
-
- const CORS_PROXY = 'https://cors-anywhere.mayx.eu.org/?';
-
- const createPreviewElement = () => {
- const existingPreview = document.getElementById('rss-feed-preview');
- if (existingPreview) {
- return existingPreview;
- }
-
- const previewEl = document.createElement('div');
- previewEl.id = 'rss-feed-preview';
- previewEl.style.cssText = `
- position: fixed;
- display: none;
- width: 300px;
- max-height: 400px;
- overflow-y: auto;
- background-color: white;
- border: 1px solid #ccc;
- border-radius: 5px;
- padding: 10px;
- box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
- z-index: 1000;
- font-size: 14px;
- line-height: 1.4;
- `;
- document.body.appendChild(previewEl);
- return previewEl;
- };
-
- const parseRSS = (xmlText) => {
- const parser = new DOMParser();
- const xml = parser.parseFromString(xmlText, 'text/xml');
-
- const rssItems = xml.querySelectorAll('item');
- if (rssItems.length > 0) {
- return Array.from(rssItems).slice(0, 5).map(item => {
- return {
- title: item.querySelector('title')?.textContent || 'No title',
- date: item.querySelector('pubDate')?.textContent || 'No date',
- };
- });
- }
-
- const atomItems = xml.querySelectorAll('entry');
- if (atomItems.length > 0) {
- return Array.from(atomItems).slice(0, 5).map(item => {
- return {
- title: item.querySelector('title')?.textContent || 'No title',
- date: item.querySelector('updated')?.textContent || 'No date',
- };
- });
- }
-
- return null;
- };
-
- const checkFeed = async (url) => {
- try {
- const response = await fetch(CORS_PROXY + url);
- if (!response.ok) {
- return null;
- }
-
- const text = await response.text();
- return parseRSS(text);
- } catch (error) {
- return null;
- }
- };
-
- const findFeedUrl = async (siteUrl, linkElement) => {
- if (linkElement && linkElement.hasAttribute('data-feed')) {
- const dataFeedUrl = linkElement.getAttribute('data-feed');
- if (dataFeedUrl) {
- const feedItems = await checkFeed(dataFeedUrl);
- if (feedItems) {
- return { url: dataFeedUrl, items: feedItems };
- }
- }
- }
-
- return null;
- };
-
- const escapeHTML = (str) => {
- return String(str).replace(/[&<>"'/]/g, (c) => ({
- '&': '&amp;',
- '<': '&lt;',
- '>': '&gt;',
- '"': '&quot;',
- "'": '&#39;',
- '/': '&#x2F;'
- }[c]));
- };
-
- const renderFeedItems = (previewEl, items, siteName) => {
- if (!items || items.length === 0) {
- previewEl.innerHTML = '<p>No feed items found.</p>';
- return;
- }
-
- let html = `<h3>Latest from ${siteName}</h3><ul style="list-style: none; padding: 0; margin: 0;">`;
-
- items.forEach(item => {
- const safeTitle = escapeHTML(item.title);
- const safeDate = escapeHTML(new Date(item.date).toLocaleDateString());
- html += `
- <li style="margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #eee;">
- <div style="color: #24292e; font-weight: bold;">
- ${safeTitle}
- </div>
- <div style="color: #586069; font-size: 12px; margin: 3px 0;">
- ${safeDate}
- </div>
- </li>
- `;
- });
-
- html += '</ul>';
- previewEl.innerHTML = html;
- };
-
- const positionPreview = (previewEl, event) => {
- const viewportWidth = window.innerWidth;
- const viewportHeight = window.innerHeight;
-
- let left = event.clientX + 20;
- let top = event.clientY + 20;
-
- const rect = previewEl.getBoundingClientRect();
-
- if (left + rect.width > viewportWidth) {
- left = event.clientX - rect.width - 20;
- }
-
- if (top + rect.height > viewportHeight) {
- top = event.clientY - rect.height - 20;
- }
-
- left = Math.max(10, left);
- top = Math.max(10, top);
-
- previewEl.style.left = `${left}px`;
- previewEl.style.top = `${top}px`;
- };
-
- const initFeedPreview = () => {
- const previewEl = createPreviewElement();
-
- const tableLinks = document.querySelectorAll('main table tbody tr td a');
-
- const feedCache = {};
-
- let currentLink = null;
- let loadingTimeout = null;
-
- tableLinks.forEach(link => {
- link.addEventListener('mouseenter', async (event) => {
- currentLink = link;
- const url = link.getAttribute('href');
- const siteName = link.textContent;
-
- previewEl.innerHTML = '<p>Checking for RSS/Atom feed...</p>';
- previewEl.style.display = 'block';
- positionPreview(previewEl, event);
-
- if (loadingTimeout) {
- clearTimeout(loadingTimeout);
- }
-
- loadingTimeout = setTimeout(async () => {
- if (feedCache[url]) {
- renderFeedItems(previewEl, feedCache[url].items, siteName);
- positionPreview(previewEl, event); // Reposition after content is loaded
- return;
- }
-
- const feedData = await findFeedUrl(url, link);
-
- if (currentLink === link) {
- if (feedData) {
- feedCache[url] = feedData;
- renderFeedItems(previewEl, feedData.items, siteName);
- positionPreview(previewEl, event); // Reposition after content is loaded
- } else {
- previewEl.style.display = 'none';
- }
- }
- }, 300);
- });
-
- link.addEventListener('mousemove', (event) => {
- if (previewEl.style.display === 'block') {
- window.requestAnimationFrame(() => {
- positionPreview(previewEl, event);
- });
- }
- });
-
- link.addEventListener('mouseleave', () => {
- if (loadingTimeout) {
- clearTimeout(loadingTimeout);
- loadingTimeout = null;
- }
-
- currentLink = null;
- previewEl.style.display = 'none';
- });
- });
-
- document.addEventListener('click', (event) => {
- if (!previewEl.contains(event.target)) {
- previewEl.style.display = 'none';
- }
- });
- };
-
- if (!window.rssFeedPreviewInitialized) {
- window.rssFeedPreviewInitialized = true;
-
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', initFeedPreview);
- } else {
- initFeedPreview();
- }
- }
- })();
- \ No newline at end of file