mirror of https://gitlab.com/mayx/mayx.gitlab.io
parent
8c26bc57d5
commit
3bfbd78385
|
@ -1,14 +1,14 @@
|
||||||
title,link,description
|
title,link,feed_url,description
|
||||||
花火学园,https://www.sayhanabi.net/,和谐融洽的ACG交流以及资源聚集地
|
花火学园,https://www.sayhanabi.net/,,和谐融洽的ACG交流以及资源聚集地
|
||||||
资源统筹局,https://gkdworld.com/,统筹保管用户分享的资源
|
资源统筹局,https://gkdworld.com/,,统筹保管用户分享的资源
|
||||||
贫困的蚊子,https://mozz.ie/,*No description*
|
贫困的蚊子,https://mozz.ie/,https://mozz.ie/index.xml,*No description*
|
||||||
极客兔兔,https://geektutu.com/,致力于分享有趣的技术实践
|
极客兔兔,https://geektutu.com/,https://geektutu.com/atom.xml,致力于分享有趣的技术实践
|
||||||
维基萌,https://www.wikimoe.com/,萌即是正义!一名热爱acg的前端设计师的小站!
|
维基萌,https://www.wikimoe.com/,https://www.wikimoe.com/rss,萌即是正义!一名热爱acg的前端设计师的小站!
|
||||||
7gugu's blog,https://www.7gugu.com/,"一个用来存放我爱好的地方,编程,摄影之类的空间"
|
7gugu's blog,https://www.7gugu.com/,https://7gugu.com/index.php/feed/,"一个用来存放我爱好的地方,编程,摄影之类的空间"
|
||||||
云游君,https://www.yunyoujun.cn/,希望能成为一个有趣的人。
|
云游君,https://www.yunyoujun.cn/,https://www.yunyoujun.cn/atom.xml,希望能成为一个有趣的人。
|
||||||
Kingfish404,https://blog.kingfish404.cn/,"Stay curious,stay naive. WUT. Jin Yu's Blog"
|
Kingfish404,https://blog.kingfish404.cn/,https://blog.kingfish404.cn/index.xml,"Stay curious,stay naive. WUT. Jin Yu's Blog"
|
||||||
FKUN,https://blog.fkun.tech/,*No description*
|
FKUN,https://blog.fkun.tech/,https://blog.fkun.tech/feed/,*No description*
|
||||||
Sinofine,https://sinofine.me/,*No description*
|
Sinofine,https://sinofine.me/,https://sinofine.me/atom.xml,*No description*
|
||||||
JiaoYuan's blog,https://yuanj.top/,思绪来得快去得也快,偶尔会在这里停留
|
JiaoYuan's blog,https://yuanj.top/,https://yuanj.top/index.xml,思绪来得快去得也快,偶尔会在这里停留
|
||||||
花生莲子粥,https://blog.hslzz.cn/,与世无争,不染于泥
|
花生莲子粥,https://blog.hslzz.cn/,https://blog.hslzz.cn/atom.xml,与世无争,不染于泥
|
||||||
南蛮子懋和,https://www.dao.js.cn/,李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。
|
南蛮子懋和,https://www.dao.js.cn/,https://www.dao.js.cn/feed.php,李懋和,俗名李栋梁。书法、国画爱好者,互联网安全与前端建设者。
|
|
|
@ -0,0 +1,223 @@
|
||||||
|
/**
|
||||||
|
* 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 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 => {
|
||||||
|
html += `
|
||||||
|
<li style="margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid #eee;">
|
||||||
|
<div style="color: #24292e; font-weight: bold;">
|
||||||
|
${item.title}
|
||||||
|
</div>
|
||||||
|
<div style="color: #586069; font-size: 12px; margin: 3px 0;">
|
||||||
|
${new Date(item.date).toLocaleDateString()}
|
||||||
|
</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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
4
links.md
4
links.md
|
@ -8,7 +8,7 @@ tags: [links]
|
||||||
|
|
||||||
| Link | Description |
|
| Link | Description |
|
||||||
| - | - |
|
| - | - |
|
||||||
{% for item in site.data.links %}| [{{ item.title }}]({{ item.link }}) | {{ item.description }} |
|
{% for item in site.data.links %}| <a href="{{ item.link }}" data-feed="{{ item.feed_url }}">{{ item.title }}</a> | {{ item.description }} |
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
## Links申请
|
## Links申请
|
||||||
|
@ -25,3 +25,5 @@ tags: [links]
|
||||||
链接:<https://mabbs.github.io>
|
链接:<https://mabbs.github.io>
|
||||||
头像:<https://avatars0.githubusercontent.com/u/17966333>
|
头像:<https://avatars0.githubusercontent.com/u/17966333>
|
||||||
Logo:<https://mabbs.github.io/favicon.ico>
|
Logo:<https://mabbs.github.io/favicon.ico>
|
||||||
|
|
||||||
|
<script src="/js/rss-feed-preview.js"></script>
|
Loading…
Reference in New Issue