Deploy to Production / pre-check (push) Successful in 2m0s
Deploy to Production / build (push) Successful in 9m9s
Deploy to Production / deploy-edgeone (push) Successful in 4m3s
Deploy to Production / finalize (push) Successful in 29s
Deploy to Production / notify-failure (push) Skipped
- 新增 [params.rssapi] base 配置,主题 7 处硬编码改为读配置: head(preconnect+window.rssApiBase)、footer(构建时拉 links/feeds)、 render-link(favicon)、circles/links 页 fetch、linkify.js(读 window.rssApiBase) - scripts/fetch_greetings.js 支持 RSS_API_BASE 环境变量,默认新地址 - scfapi.usj.cc(国内代理)保持不变
86 lines
3.2 KiB
JavaScript
86 lines
3.2 KiB
JavaScript
// linkify.js - Convert bare URLs to link cards, video URLs to players
|
|
(function() {
|
|
var URL_RE = /(https?:\/\/[^\s一-鿿 -〿-<>"')\]]+)/g;
|
|
var VIDEO_RE = /\.(mp4|webm|ogg|mov)(\?|$)/i;
|
|
var FAVICON_API = (window.rssApiBase || 'https://api.200181.xyz') + '/api/favicon?url=';
|
|
|
|
function getDomain(url) {
|
|
try { return new URL(url).hostname; } catch (e) { return url; }
|
|
}
|
|
|
|
function makeVideo(url) {
|
|
var video = document.createElement('video');
|
|
video.className = 'post-video';
|
|
video.controls = true;
|
|
video.preload = 'metadata';
|
|
video.playsInline = true;
|
|
var source = document.createElement('source');
|
|
source.src = url;
|
|
video.appendChild(source);
|
|
return video;
|
|
}
|
|
|
|
function makeCard(url) {
|
|
var domain = getDomain(url);
|
|
var card = document.createElement('a');
|
|
card.className = 'link-card';
|
|
card.href = '/tiaozhuan.html?target=' + btoa(url);
|
|
card.target = '_blank';
|
|
card.rel = 'noopener';
|
|
card.innerHTML = '<img class="link-card-icon" src="' + FAVICON_API + domain + '" alt="" loading="lazy" onerror="this.style.display=\'none\'">' +
|
|
'<span class="link-card-body"><span class="link-card-title">' + domain + '</span>' +
|
|
'<span class="link-card-url">' + url + '</span></span>' +
|
|
'<span class="link-card-arrow">↗</span>';
|
|
return card;
|
|
}
|
|
|
|
function linkify(root) {
|
|
var walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
|
|
var textNodes = [];
|
|
while (walker.nextNode()) {
|
|
var node = walker.currentNode;
|
|
if (node.parentElement && node.parentElement.closest('a, .link-card, code, pre, video, #szh')) continue;
|
|
if (URL_RE.test(node.textContent)) textNodes.push(node);
|
|
}
|
|
|
|
textNodes.forEach(function(node) {
|
|
URL_RE.lastIndex = 0;
|
|
var text = node.textContent;
|
|
var parts = [];
|
|
var lastIdx = 0;
|
|
var match;
|
|
while ((match = URL_RE.exec(text)) !== null) {
|
|
if (match.index > lastIdx) {
|
|
parts.push(document.createTextNode(text.slice(lastIdx, match.index)));
|
|
}
|
|
if (VIDEO_RE.test(match[1])) {
|
|
parts.push(makeVideo(match[1]));
|
|
} else {
|
|
parts.push(makeCard(match[1]));
|
|
}
|
|
lastIdx = match.index + match[0].length;
|
|
}
|
|
if (parts.length === 0) return;
|
|
if (lastIdx < text.length) {
|
|
parts.push(document.createTextNode(text.slice(lastIdx)));
|
|
}
|
|
var frag = document.createDocumentFragment();
|
|
parts.forEach(function(p) { frag.appendChild(p); });
|
|
node.parentNode.replaceChild(frag, node);
|
|
});
|
|
}
|
|
|
|
function run() {
|
|
var content = document.querySelector('.post-content');
|
|
if (content) linkify(content);
|
|
}
|
|
|
|
window.initLinkify = run;
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', run);
|
|
} else {
|
|
run();
|
|
}
|
|
})();
|