permalink option

This commit is contained in:
mi
2025-11-15 18:04:49 +10:00
parent 742ff0e553
commit 866bfe4d6d
7 changed files with 143 additions and 9 deletions

5
app.py
View File

@@ -9,7 +9,7 @@ from comics_data import (
COMICS, COMIC_NAME, COPYRIGHT_NAME, SITE_URL, FULL_WIDTH_DEFAULT, PLAIN_DEFAULT, LOGO_IMAGE, LOGO_MODE, COMICS, COMIC_NAME, COPYRIGHT_NAME, SITE_URL, FULL_WIDTH_DEFAULT, PLAIN_DEFAULT, LOGO_IMAGE, LOGO_MODE,
HEADER_IMAGE, FOOTER_IMAGE, BANNER_IMAGE, COMPACT_FOOTER, ARCHIVE_FULL_WIDTH, SECTIONS_ENABLED, HEADER_IMAGE, FOOTER_IMAGE, BANNER_IMAGE, COMPACT_FOOTER, ARCHIVE_FULL_WIDTH, SECTIONS_ENABLED,
USE_COMIC_NAV_ICONS, USE_HEADER_NAV_ICONS, USE_FOOTER_SOCIAL_ICONS, NEWSLETTER_ENABLED, USE_COMIC_NAV_ICONS, USE_HEADER_NAV_ICONS, USE_FOOTER_SOCIAL_ICONS, NEWSLETTER_ENABLED,
SOCIAL_INSTAGRAM, SOCIAL_YOUTUBE, SOCIAL_EMAIL, API_SPEC_LINK, EMBED_ENABLED SOCIAL_INSTAGRAM, SOCIAL_YOUTUBE, SOCIAL_EMAIL, API_SPEC_LINK, EMBED_ENABLED, PERMALINK_ENABLED
) )
import markdown import markdown
@@ -50,7 +50,8 @@ def inject_global_settings():
'social_youtube': SOCIAL_YOUTUBE, 'social_youtube': SOCIAL_YOUTUBE,
'social_email': SOCIAL_EMAIL, 'social_email': SOCIAL_EMAIL,
'api_spec_link': API_SPEC_LINK, 'api_spec_link': API_SPEC_LINK,
'embed_enabled': EMBED_ENABLED 'embed_enabled': EMBED_ENABLED,
'permalink_enabled': PERMALINK_ENABLED
} }

View File

@@ -89,6 +89,10 @@ API_SPEC_LINK = None # Set to 'openapi.yml' to enable
# When enabled, users can get embed codes to display comics on other websites # When enabled, users can get embed codes to display comics on other websites
EMBED_ENABLED = True EMBED_ENABLED = True
# Global setting: Set to True to enable permalink copy button
# When enabled, users can easily copy a direct link to the current comic
PERMALINK_ENABLED = True
COMICS = [ COMICS = [
{ {
'number': 1, 'number': 1,

View File

@@ -1070,13 +1070,45 @@ footer.compact-footer .footer-section:not(:last-child)::after {
} }
/* ============================================================ /* ============================================================
EMBED FEATURE STYLES SHARE/EMBED FEATURE STYLES
============================================================ */ ============================================================ */
/* Embed button section */ /* Share section (contains permalink and embed buttons) */
.comic-embed-section { .comic-share-section {
margin-top: var(--space-lg); margin-top: var(--space-lg);
text-align: center; text-align: center;
display: flex;
justify-content: center;
gap: var(--space-md);
flex-wrap: wrap;
}
/* Permalink button */
.btn-permalink {
padding: var(--space-sm) var(--space-lg);
background-color: var(--color-background);
border: var(--border-width-thin) solid var(--color-border);
color: var(--color-text);
font-family: var(--font-family);
font-size: var(--font-size-md);
cursor: pointer;
text-transform: uppercase;
letter-spacing: var(--letter-spacing-tight);
transition: background-color var(--transition-speed);
}
.btn-permalink:hover {
background-color: var(--color-hover-bg);
}
.btn-permalink:focus {
outline: 3px solid var(--color-primary);
outline-offset: 2px;
}
.btn-permalink.copied {
background-color: var(--color-primary);
color: var(--color-background);
} }
/* Embed button */ /* Embed button */

84
static/js/permalink.js Normal file
View File

@@ -0,0 +1,84 @@
// Permalink functionality for Sunday Comics
// Handles copying comic permalinks to clipboard
(function() {
'use strict';
const permalinkButton = document.getElementById('permalink-button');
if (!permalinkButton) {
// Permalink feature not enabled or button not found
return;
}
// Get the site URL from the page
const siteUrl = document.body.getAttribute('data-site-url') || window.location.origin;
// Copy permalink when button is clicked
permalinkButton.addEventListener('click', function() {
const comicNumber = this.getAttribute('data-comic-number');
if (!comicNumber) return;
// Generate permalink URL
const permalink = `${siteUrl}/comic/${comicNumber}`;
// Copy to clipboard
copyToClipboard(permalink);
});
// Copy text to clipboard
function copyToClipboard(text) {
// Modern clipboard API
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(function() {
showCopyFeedback();
}).catch(function() {
// Fallback for older browsers
fallbackCopy(text);
});
} else {
// Fallback for older browsers
fallbackCopy(text);
}
}
// Fallback copy method for older browsers
function fallbackCopy(text) {
// Create temporary textarea
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.opacity = '0';
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
try {
document.execCommand('copy');
showCopyFeedback();
} catch (err) {
alert('Failed to copy. Please copy manually: ' + text);
}
document.body.removeChild(textarea);
}
// Show visual feedback that the permalink was copied
function showCopyFeedback() {
const originalText = permalinkButton.textContent;
permalinkButton.textContent = 'Copied!';
permalinkButton.classList.add('copied');
setTimeout(function() {
permalinkButton.textContent = originalText;
permalinkButton.classList.remove('copied');
}, 2000);
}
// Update permalink button when comic changes via client-side navigation
window.addEventListener('comicUpdated', function(event) {
if (event.detail && event.detail.comicNumber && permalinkButton) {
permalinkButton.setAttribute('data-comic-number', event.detail.comicNumber);
}
});
})();

View File

@@ -207,6 +207,9 @@
{% if embed_enabled %} {% if embed_enabled %}
<script src="{{ url_for('static', filename='js/embed.js') }}"></script> <script src="{{ url_for('static', filename='js/embed.js') }}"></script>
{% endif %} {% endif %}
{% if permalink_enabled %}
<script src="{{ url_for('static', filename='js/permalink.js') }}"></script>
{% endif %}
{% block extra_js %}{% endblock %} {% block extra_js %}{% endblock %}
</body> </body>
</html> </html>

View File

@@ -131,9 +131,14 @@
</div> </div>
</div> </div>
{% if embed_enabled or permalink_enabled %}
<div class="comic-share-section">
{% if permalink_enabled %}
<button class="btn-permalink" id="permalink-button" data-comic-number="{{ comic.number }}" aria-label="Copy permalink to this comic">Copy Permalink</button>
{% endif %}
{% if embed_enabled %} {% if embed_enabled %}
<div class="comic-embed-section">
<button class="btn-embed" id="embed-button" data-comic-number="{{ comic.number }}" aria-label="Get embed code for this comic">Share/Embed</button> <button class="btn-embed" id="embed-button" data-comic-number="{{ comic.number }}" aria-label="Get embed code for this comic">Share/Embed</button>
{% endif %}
</div> </div>
{% endif %} {% endif %}

View File

@@ -91,9 +91,14 @@
</div> </div>
</div> </div>
{% if embed_enabled or permalink_enabled %}
<div class="comic-share-section">
{% if permalink_enabled %}
<button class="btn-permalink" id="permalink-button" data-comic-number="{{ comic.number }}" aria-label="Copy permalink to this comic">Copy Permalink</button>
{% endif %}
{% if embed_enabled %} {% if embed_enabled %}
<div class="comic-embed-section">
<button class="btn-embed" id="embed-button" data-comic-number="{{ comic.number }}" aria-label="Get embed code for this comic">Share/Embed</button> <button class="btn-embed" id="embed-button" data-comic-number="{{ comic.number }}" aria-label="Get embed code for this comic">Share/Embed</button>
{% endif %}
</div> </div>
{% endif %} {% endif %}