abyss internal link shortening, removal of # for ids and external preview

This commit is contained in:
2026-05-17 14:16:13 +02:00
parent 832f97970e
commit 82574466ee
5 changed files with 70 additions and 16 deletions

View File

@@ -1668,7 +1668,14 @@ class CommentSystem {
}
);
// Build regex for allowed media hosters (video/audio)
// Abyss label replacement
md = md.replace(
/<a\s[^>]*href="(?:https?:\/\/[^\/]+)?\/abyss(?:#|\/)(\d+)"[^>]*>([\s\S]*?)<\/a>/gi,
(match, abyssId) => {
return `<a href="/abyss/${abyssId}" class="abyss-link" data-abyss-id="${abyssId}"><i class="fa-solid fa-dice-d6"></i> /abyss/${abyssId}</a>`;
}
);
const mediaHosts = [escapedSiteHost];
if (window.f0ckAllowedImages && Array.isArray(window.f0ckAllowedImages)) {
window.f0ckAllowedImages.forEach(h => {

View File

@@ -1678,7 +1678,7 @@ window.cancelAnimFrame = (function () {
(parts.length >= 3 && (parts[0] === 'tag' || parts[0] === 'user' || parts[0] === 'h') && /^\d+$/.test(parts[parts.length - 1]))
);
const isMessages = !!pathname.match(/^\/messages(\/|$)/);
const isAbyss = !!pathname.match(/^\/abyss(\/?$|\?|#)/) || pathname === '/abyss';
const isAbyss = !!pathname.match(/^\/abyss(\/|$|\?|#)/) || pathname === '/abyss';
const isGrid = !isProfile && !isUserHall && !isUserHalls && !isHall && !isHalls && !isTags && !isComments && !isNotifs && !isItem && !isAdmin && !isMod && !isSettings && !isStatic && !isUpload && !isMessages && !isAbyss;
if (isItem) {

View File

@@ -229,28 +229,32 @@
return ago(fmt(y === 1 ? i.ta_year : i.ta_years, y, 'year'));
}
function hashId() {
// Strip the leading '#' and allow numeric IDs or board/postid format
// Check path first /abyss/1234
const pathMatch = location.pathname.match(/\/abyss\/(\d+)$/);
if (pathMatch) return pathMatch[1];
// Fallback to hash
const raw = location.hash.replace(/^#/, '').trim();
if (/^\d+$/.test(raw)) return raw;
if (/^[a-z0-9]+\/\d+$/.test(raw)) return raw;
return '';
}
let lastPushedHash = location.hash;
let lastPushedUrl = location.pathname + location.hash;
function pushHash(id) {
if (!id) return;
const newHash = '#' + id;
if (newHash === lastPushedHash) return;
lastPushedHash = newHash;
history.pushState({ scrollerId: id }, '', '/abyss' + newHash);
const newUrl = '/abyss/' + id;
if (newUrl === lastPushedUrl) return;
lastPushedUrl = newUrl;
history.pushState({ scrollerId: id }, '', newUrl);
updateCacheActiveId(id);
}
// Handle back/forward within abyss — scroll to the target slide
window.addEventListener('popstate', (e) => {
if (!document.body.classList.contains('scroller-active')) return;
const id = e.state?.scrollerId || location.hash.replace('#', '');
const id = e.state?.scrollerId || hashId();
if (!id) return;
lastPushedHash = '#' + id;
lastPushedUrl = '/abyss/' + id;
const slide = feed.querySelector(`.scroll-slide[data-id="${id}"], .scroll-slide[data-local-id="${id}"]`);
if (slide) {
slide.scrollIntoView({ behavior: 'smooth', block: 'start' });

View File

@@ -40,6 +40,7 @@
const ytOembedCache = new Map(); // videoId -> meta object
const ytOembedPending = new Map(); // videoId -> Promise
const fetchSidebarYoutubeTitles = async (container) => {
const links = container.querySelectorAll('.sidebar-video-link[data-yt-id]');
if (links.length === 0) return;
@@ -290,6 +291,14 @@
}
);
// Abyss label replacement
md = md.replace(
/<a\s[^>]*href="(?:https?:\/\/[^\/]+)?\/abyss(?:#|\/)(\d+)"[^>]*>([\s\S]*?)<\/a>/gi,
(match, abyssId) => {
return `<a href="/abyss/${abyssId}" class="sidebar-abyss-link" data-abyss-id="${abyssId}"><i class="fa-solid fa-dice-d6"></i> /abyss/${abyssId}</a>`;
}
);
// Build regex for allowed media hosters (video/audio)
const escapedSiteHost = window.location.host.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const mediaHosts = [escapedSiteHost];