fix: add copy-link button and hash deep-linking for blog articles
This commit is contained in:
+84
@@ -2083,6 +2083,35 @@
|
||||
color: var(--gold);
|
||||
}
|
||||
|
||||
#article-copy-link {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 58px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
background: rgba(93, 64, 55, 0.08);
|
||||
color: #8d6e63;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.2s, color 0.2s;
|
||||
z-index: 2;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
#article-copy-link:hover {
|
||||
background: rgba(230, 81, 0, 0.12);
|
||||
color: var(--gold);
|
||||
}
|
||||
|
||||
#article-copy-link.copied {
|
||||
color: var(--gold);
|
||||
}
|
||||
|
||||
/* ── Article actions row (schedule + trial) ──────────────────── */
|
||||
#article-actions {
|
||||
display: flex;
|
||||
@@ -2744,6 +2773,7 @@
|
||||
<div id="article-overlay">
|
||||
<div id="article-box">
|
||||
<button id="article-close" aria-label="Close article">×</button>
|
||||
<button id="article-copy-link" aria-label="Copy link to article" title="Copy link to this article">🔗</button>
|
||||
<div class="article-rule"></div>
|
||||
<div class="article-header">
|
||||
<div class="article-area" id="article-area"></div>
|
||||
@@ -3674,12 +3704,28 @@
|
||||
|
||||
var articleOverlay = document.getElementById('article-overlay');
|
||||
var articleClose = document.getElementById('article-close');
|
||||
var articleCopyLink = document.getElementById('article-copy-link');
|
||||
var articleTitle = document.getElementById('article-title');
|
||||
var articleArea = document.getElementById('article-area');
|
||||
var articleDate = document.getElementById('article-date');
|
||||
var articleBody = document.getElementById('article-body');
|
||||
var articleContent = document.getElementById('article-content');
|
||||
|
||||
function slugify(title) {
|
||||
return (title || '').toLowerCase()
|
||||
.replace(/[^a-z0-9\s-]/g, '')
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/-+/g, '-')
|
||||
.replace(/^-|-$/g, '');
|
||||
}
|
||||
|
||||
function findPostIndexBySlug(slug) {
|
||||
for (var i = 0; i < allPosts.length; i++) {
|
||||
if (slugify(allPosts[i].title) === slug) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function openArticle(index) {
|
||||
var post = allPosts[index];
|
||||
if (!post) return;
|
||||
@@ -3690,11 +3736,17 @@
|
||||
articleBody.scrollTop = 0;
|
||||
articleOverlay.classList.add('is-open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
history.replaceState(null, '', '#post-' + slugify(post.title));
|
||||
if (articleCopyLink) {
|
||||
articleCopyLink.innerHTML = '🔗';
|
||||
articleCopyLink.classList.remove('copied');
|
||||
}
|
||||
}
|
||||
|
||||
function closeArticle() {
|
||||
articleOverlay.classList.remove('is-open');
|
||||
document.body.style.overflow = '';
|
||||
history.replaceState(null, '', window.location.pathname + window.location.search);
|
||||
}
|
||||
|
||||
articleClose.addEventListener('click', closeArticle);
|
||||
@@ -3705,6 +3757,32 @@
|
||||
if (e.key === 'Escape' && articleOverlay.classList.contains('is-open')) closeArticle();
|
||||
});
|
||||
|
||||
if (articleCopyLink) {
|
||||
articleCopyLink.addEventListener('click', function() {
|
||||
var url = window.location.href;
|
||||
function showCopied() {
|
||||
articleCopyLink.textContent = '\u2713';
|
||||
articleCopyLink.classList.add('copied');
|
||||
setTimeout(function() {
|
||||
articleCopyLink.innerHTML = '🔗';
|
||||
articleCopyLink.classList.remove('copied');
|
||||
}, 2000);
|
||||
}
|
||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(url).then(showCopied, showCopied);
|
||||
} else {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = url;
|
||||
ta.style.cssText = 'position:fixed;opacity:0;pointer-events:none';
|
||||
document.body.appendChild(ta);
|
||||
ta.select();
|
||||
try { document.execCommand('copy'); } catch(e) {}
|
||||
document.body.removeChild(ta);
|
||||
showCopied();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
grid.addEventListener('click', function(e) {
|
||||
var btn = e.target.closest('.news-read-btn');
|
||||
if (!btn) return;
|
||||
@@ -3720,6 +3798,12 @@
|
||||
allPosts = Array.isArray(posts) ? posts : [];
|
||||
filteredPosts = allPosts.slice();
|
||||
render();
|
||||
var hash = window.location.hash;
|
||||
if (hash && hash.indexOf('#post-') === 0) {
|
||||
var slug = hash.slice(6);
|
||||
var idx = findPostIndexBySlug(slug);
|
||||
if (idx !== -1) openArticle(idx);
|
||||
}
|
||||
})
|
||||
.catch(function () {
|
||||
grid.innerHTML = emptyMarkup(
|
||||
|
||||
Reference in New Issue
Block a user