summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormayx <mayx@outlook.com>2025-07-15 05:43:20 +0200
committermayx <mayx@outlook.com>2025-07-15 05:43:20 +0200
commit3ef5ec378d020844af7d7be99731afc1357a2175 (patch)
tree141d72270dd2c7f57ef04a2cd1f5be51b58c7ab9
parente3cf4e5b9ef18a49b8d0f1d6cc5a7a37be5c6929 (diff)
Update 5 files
- /.github/PULL_REQUEST_TEMPLATE.yml - /assets/js/rss-feed-preview.js - /links.md - /sitemap.xsl - /.github/PULL_REQUEST_TEMPLATE.md
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md (renamed from .github/PULL_REQUEST_TEMPLATE.yml)0
-rw-r--r--assets/js/rss-feed-preview.js397
-rw-r--r--links.md4
-rw-r--r--sitemap.xsl2
4 files changed, 181 insertions, 222 deletions
diff --git a/.github/PULL_REQUEST_TEMPLATE.yml b/.github/PULL_REQUEST_TEMPLATE.md
index f595bc4..f595bc4 100644
--- a/.github/PULL_REQUEST_TEMPLATE.yml
+++ b/.github/PULL_REQUEST_TEMPLATE.md
diff --git a/assets/js/rss-feed-preview.js b/assets/js/rss-feed-preview.js
index 2929622..30af324 100644
--- a/assets/js/rss-feed-preview.js
+++ b/assets/js/rss-feed-preview.js
@@ -2,235 +2,196 @@
* 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) => ({
+(function () {
+ if (window.rssFeedPreviewInitialized)
+ return;
+ window.rssFeedPreviewInitialized = true;
+
+ var CORS_PROXY = 'https://cors-anywhere.mayx.eu.org/?';
+
+ var $previewEl = $('<div>', {
+ id: 'rss-feed-preview'
+ }).css({
+ position: 'fixed',
+ display: 'none',
+ width: '300px',
+ maxHeight: '400px',
+ overflowY: 'auto',
+ backgroundColor: 'white',
+ border: '1px solid #ccc',
+ borderRadius: '5px',
+ padding: '10px',
+ fontSize: '14px',
+ lineHeight: '1.4',
+ zIndex: 1000,
+ boxShadow: '0 2px 10px rgba(0,0,0,0.1)'
+ });
+
+ $('body').append($previewEl);
+
+ function escapeHTML(str) {
+ return String(str).replace(/[&<>"']/g, function (c) {
+ return {
'&': '&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>
- `;
+ "'": '&#39;'
+ }[c];
+ });
+ }
+
+ function parseRSS(xmlText) {
+ var xml;
+ try {
+ xml = $.parseXML(xmlText);
+ } catch (e) {
+ return [];
+ }
+
+ var $xml = $(xml);
+ var $items = $xml.find('item');
+ if (!$items.length)
+ $items = $xml.find('entry');
+
+ var result = [];
+ $items.slice(0, 5).each(function () {
+ var $el = $(this);
+ result.push({
+ title: $el.find('title').text() || 'No title',
+ date: $el.find('pubDate, updated').text() || 'No date'
});
-
- 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;
+ });
+
+ return result;
+ }
+
+ function checkFeed(url, callback) {
+ $.ajax({
+ url: CORS_PROXY + url,
+ type: 'GET',
+ dataType: 'text',
+ success: function (data) {
+ var items = parseRSS(data);
+ callback(items);
+ },
+ error: function () {
+ callback(null);
}
-
- 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);
+ });
+ }
+
+ function renderFeedItems(items, siteName) {
+ if (!items || !items.length) {
+ $previewEl.html('<p>No feed items found.</p>');
+ return;
+ }
+
+ var html = '<h3>Latest from ' + escapeHTML(siteName) + '</h3><ul style="list-style:none; padding:0; margin:0;">';
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ var dateStr = 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;">' + escapeHTML(item.title) + '</div>' +
+ '<div style="color:#586069; font-size:12px; margin:3px 0;">' + escapeHTML(dateStr) + '</div>' +
+ '</li>';
+ }
+ html += '</ul>';
+ $previewEl.html(html);
+ }
+
+ function positionPreview(e) {
+ e = e || window.event;
+
+ var x = e.clientX;
+ var y = e.clientY;
+
+ var offsetWidth = $previewEl.outerWidth();
+ var offsetHeight = $previewEl.outerHeight();
+
+ var left = x + 20;
+ var top = y + 20;
+
+ if (left + offsetWidth > $(window).width()) {
+ left = x - offsetWidth - 20;
+ }
+ if (top + offsetHeight > $(window).height()) {
+ top = y - offsetHeight - 20;
+ }
+
+ $previewEl.css({
+ left: Math.max(10, left),
+ top: Math.max(10, top)
+ });
+ }
+
+
+ function init() {
+ var cache = {};
+ var currentLink = null;
+ var timeout = null;
+
+ $('main table tbody tr td a').each(function () {
+ var $link = $(this);
+
+ $link.on('mouseenter', function (e) {
+ currentLink = this;
+ var siteName = $link.text();
+ var url = $link.attr('data-feed');
+ if (!url)
+ return;
+
+ $previewEl.html('<p>Checking for RSS/Atom feed...</p>').show();
+ positionPreview(e);
+
+ if (timeout)
+ clearTimeout(timeout);
+ timeout = setTimeout(function () {
+ if (cache[url]) {
+ renderFeedItems(cache[url], siteName);
+ positionPreview(e);
+ return;
}
-
- 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
+
+ if (url) {
+ checkFeed(url, function (items) {
+ if (currentLink === $link[0] && items) {
+ cache[url] = items;
+ renderFeedItems(items, siteName);
+ positionPreview(e);
} else {
- previewEl.style.display = 'none';
+ $previewEl.hide();
}
- }
- }, 300);
- });
-
- link.addEventListener('mousemove', (event) => {
- if (previewEl.style.display === 'block') {
- window.requestAnimationFrame(() => {
- positionPreview(previewEl, event);
});
+ } else {
+ $previewEl.hide();
}
- });
-
- link.addEventListener('mouseleave', () => {
- if (loadingTimeout) {
- clearTimeout(loadingTimeout);
- loadingTimeout = null;
- }
-
- currentLink = null;
- previewEl.style.display = 'none';
- });
+ }, 300);
});
-
- document.addEventListener('click', (event) => {
- if (!previewEl.contains(event.target)) {
- previewEl.style.display = 'none';
- }
+
+ $link.on('mousemove', function (e) {
+ if ($previewEl.is(':visible'))
+ positionPreview(e);
});
- };
-
- if (!window.rssFeedPreviewInitialized) {
- window.rssFeedPreviewInitialized = true;
-
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', initFeedPreview);
- } else {
- initFeedPreview();
+
+ $link.on('mouseleave', function () {
+ clearTimeout(timeout);
+ timeout = null;
+ currentLink = null;
+ $previewEl.hide();
+ });
+ });
+
+ $(document).on('click', function (e) {
+ if (!$(e.target).closest('#rss-feed-preview').length) {
+ $previewEl.hide();
}
- }
- })();
- \ No newline at end of file
+ });
+ }
+
+ if (document.readyState === 'complete' || document.readyState === 'interactive') {
+ init();
+ } else {
+ $(document).ready(init);
+ }
+})();
diff --git a/links.md b/links.md
index 6a9c5d3..8d07260 100644
--- a/links.md
+++ b/links.md
@@ -29,6 +29,4 @@ tags: [links]
头像:<https://avatars0.githubusercontent.com/u/17966333>
Logo:<https://mabbs.github.io/favicon.ico>
-<!--[if !IE]> -->
-<script src="/assets/js/rss-feed-preview.js"></script>
-<!-- <![endif]--> \ No newline at end of file
+<script src="/assets/js/rss-feed-preview.js"></script> \ No newline at end of file
diff --git a/sitemap.xsl b/sitemap.xsl
index 256704b..4485c3b 100644
--- a/sitemap.xsl
+++ b/sitemap.xsl
@@ -11,7 +11,7 @@ title: Sitemap
<li>
<a>
<xsl:attribute name="href"><xsl:value-of select="sm:loc" /></xsl:attribute>
- <xsl:value-of select="sm:loc" />
+ <xsl:value-of select="sm:loc" />
</a>
</li>
</xsl:for-each>