✨ permalink option
This commit is contained in:
5
app.py
5
app.py
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
84
static/js/permalink.js
Normal 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -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>
|
||||||
@@ -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 %}
|
||||||
|
|
||||||
|
|||||||
@@ -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 %}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user