:lightning: CDN option
This commit is contained in:
60
README.md
60
README.md
@@ -44,6 +44,7 @@ A Flask-based webcomic website with server-side rendering using Jinja2 templates
|
|||||||
- [Option 1: Docker (Recommended)](#option-1-docker-recommended)
|
- [Option 1: Docker (Recommended)](#option-1-docker-recommended)
|
||||||
- [Option 2: Manual Deployment with Gunicorn](#option-2-manual-deployment-with-gunicorn)
|
- [Option 2: Manual Deployment with Gunicorn](#option-2-manual-deployment-with-gunicorn)
|
||||||
- [Using a Reverse Proxy (Recommended)](#using-a-reverse-proxy-recommended)
|
- [Using a Reverse Proxy (Recommended)](#using-a-reverse-proxy-recommended)
|
||||||
|
- [Using a CDN for Static Assets](#using-a-cdn-for-static-assets)
|
||||||
- [Additional Production Considerations](#additional-production-considerations)
|
- [Additional Production Considerations](#additional-production-considerations)
|
||||||
- [Upgrading to a Database](#upgrading-to-a-database)
|
- [Upgrading to a Database](#upgrading-to-a-database)
|
||||||
- [Customization](#customization)
|
- [Customization](#customization)
|
||||||
@@ -172,6 +173,7 @@ Don't have a server? No problem! Here are beginner-friendly options to get your
|
|||||||
- JSON API for programmatic access
|
- JSON API for programmatic access
|
||||||
- Open Graph and Twitter Card metadata for social sharing
|
- Open Graph and Twitter Card metadata for social sharing
|
||||||
- Server-side rendering with Jinja2
|
- Server-side rendering with Jinja2
|
||||||
|
- **Built-in CDN support** for static assets (images, CSS, JavaScript)
|
||||||
- **Comprehensive accessibility features** (WCAG compliant)
|
- **Comprehensive accessibility features** (WCAG compliant)
|
||||||
- **Search engine optimized** (sitemap, robots.txt, meta tags, canonical URLs)
|
- **Search engine optimized** (sitemap, robots.txt, meta tags, canonical URLs)
|
||||||
|
|
||||||
@@ -724,6 +726,7 @@ The `comics_data.py` file contains global configuration options for your comic s
|
|||||||
COMIC_NAME = 'Sunday Comics' # Your comic/website name
|
COMIC_NAME = 'Sunday Comics' # Your comic/website name
|
||||||
COPYRIGHT_NAME = None # Name for copyright (defaults to COMIC_NAME)
|
COPYRIGHT_NAME = None # Name for copyright (defaults to COMIC_NAME)
|
||||||
SITE_URL = 'http://localhost:3000' # Your domain (update for production)
|
SITE_URL = 'http://localhost:3000' # Your domain (update for production)
|
||||||
|
CDN_URL = None # CDN URL for static assets (None = use local)
|
||||||
FULL_WIDTH_DEFAULT = False # Make all comics full-width by default
|
FULL_WIDTH_DEFAULT = False # Make all comics full-width by default
|
||||||
PLAIN_DEFAULT = False # Hide header/remove borders by default
|
PLAIN_DEFAULT = False # Hide header/remove borders by default
|
||||||
LOGO_IMAGE = 'logo.png' # Path to logo (relative to static/images/)
|
LOGO_IMAGE = 'logo.png' # Path to logo (relative to static/images/)
|
||||||
@@ -1035,12 +1038,67 @@ Set up Nginx or another reverse proxy in front of your app for:
|
|||||||
- Load balancing
|
- Load balancing
|
||||||
- Better security
|
- Better security
|
||||||
|
|
||||||
|
### Using a CDN for Static Assets
|
||||||
|
|
||||||
|
For better performance, especially with high traffic or global audiences, you can serve static assets (images, CSS, JavaScript) from a Content Delivery Network (CDN).
|
||||||
|
|
||||||
|
**How it works:**
|
||||||
|
|
||||||
|
Sunday Comics includes built-in CDN support through the `CDN_URL` configuration option. When set, all static assets (comic images, CSS, JavaScript, icons, etc.) are served from your CDN instead of your application server.
|
||||||
|
|
||||||
|
**Setup Steps:**
|
||||||
|
|
||||||
|
1. **Upload your static files to a CDN:**
|
||||||
|
- Upload the entire `static/` directory to your CDN provider
|
||||||
|
- Popular CDN options: Cloudflare, AWS CloudFront, BunnyCDN, KeyCDN
|
||||||
|
- Maintain the same directory structure (e.g., `static/css/style.css` → `your-cdn.com/static/css/style.css`)
|
||||||
|
|
||||||
|
2. **Configure Sunday Comics:**
|
||||||
|
```python
|
||||||
|
# In comics_data.py
|
||||||
|
CDN_URL = 'https://cdn.example.com' # No trailing slash!
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Deploy and test:**
|
||||||
|
- Restart your application
|
||||||
|
- Verify images and CSS load from the CDN by checking network requests in browser DevTools
|
||||||
|
|
||||||
|
**Benefits:**
|
||||||
|
- ⚡ **Faster loading** - Static assets served from edge servers closer to your readers
|
||||||
|
- 📉 **Reduced server load** - Your application server only handles dynamic content
|
||||||
|
- 💰 **Lower bandwidth costs** - CDN bandwidth is often cheaper than server bandwidth
|
||||||
|
- 🌍 **Global performance** - Readers worldwide get fast load times
|
||||||
|
- 🛡️ **DDoS protection** - Many CDNs include built-in protection
|
||||||
|
|
||||||
|
**Example Configuration:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Local development (no CDN)
|
||||||
|
CDN_URL = None
|
||||||
|
|
||||||
|
# Production with CDN
|
||||||
|
CDN_URL = 'https://d1abc123xyz.cloudfront.net' # AWS CloudFront example
|
||||||
|
CDN_URL = 'https://cdn.yourcomic.com' # Custom domain example
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important Notes:**
|
||||||
|
- When using a CDN, update your static files on the CDN whenever you make changes
|
||||||
|
- Consider using cache-busting techniques for CSS/JS updates (version query parameters)
|
||||||
|
- Test thoroughly after enabling CDN to ensure all assets load correctly
|
||||||
|
- The `cdn_static` template filter automatically handles URL generation
|
||||||
|
- When `CDN_URL` is `None`, Sunday Comics falls back to local static file serving
|
||||||
|
|
||||||
|
**Free CDN Options:**
|
||||||
|
- **Cloudflare** - Free tier includes CDN and DDoS protection
|
||||||
|
- **jsDelivr** - Free CDN for GitHub repositories
|
||||||
|
- **BunnyCDN** - Low-cost pay-as-you-go pricing
|
||||||
|
|
||||||
### Additional Production Considerations
|
### Additional Production Considerations
|
||||||
|
|
||||||
- Use a process manager (systemd, supervisor) for non-Docker deployments
|
- Use a process manager (systemd, supervisor) for non-Docker deployments
|
||||||
- Set appropriate file permissions
|
- Set appropriate file permissions
|
||||||
- Enable HTTPS with Let's Encrypt
|
- Enable HTTPS with Let's Encrypt
|
||||||
- Consider using a CDN for static assets
|
- Use a CDN for static assets (see [Using a CDN](#using-a-cdn-for-static-assets) above)
|
||||||
- Monitor logs and performance
|
- Monitor logs and performance
|
||||||
- Set up automated backups of `comics_data.py`
|
- Set up automated backups of `comics_data.py`
|
||||||
|
|
||||||
|
|||||||
21
app.py
21
app.py
@@ -7,7 +7,7 @@ import logging
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import Flask, render_template, abort, jsonify, request
|
from flask import Flask, render_template, abort, jsonify, request
|
||||||
from comics_data import (
|
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, CDN_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, USE_SHARE_ICONS, NEWSLETTER_ENABLED,
|
USE_COMIC_NAV_ICONS, USE_HEADER_NAV_ICONS, USE_FOOTER_SOCIAL_ICONS, USE_SHARE_ICONS, NEWSLETTER_ENABLED,
|
||||||
SOCIAL_INSTAGRAM, SOCIAL_YOUTUBE, SOCIAL_EMAIL, API_SPEC_LINK, EMBED_ENABLED, PERMALINK_ENABLED
|
SOCIAL_INSTAGRAM, SOCIAL_YOUTUBE, SOCIAL_EMAIL, API_SPEC_LINK, EMBED_ENABLED, PERMALINK_ENABLED
|
||||||
@@ -32,6 +32,24 @@ def add_ai_blocking_headers(response):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
@app.template_filter('cdn_static')
|
||||||
|
def cdn_static(filename):
|
||||||
|
"""Generate URL for static assets with CDN support
|
||||||
|
|
||||||
|
When CDN_URL is set, returns CDN URL. Otherwise returns local static URL.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename: Path to static file (e.g., 'css/style.css')
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Full URL to the static asset
|
||||||
|
"""
|
||||||
|
from flask import url_for
|
||||||
|
if CDN_URL:
|
||||||
|
return f"{CDN_URL}/static/{filename}"
|
||||||
|
return url_for('static', filename=filename)
|
||||||
|
|
||||||
|
|
||||||
@app.context_processor
|
@app.context_processor
|
||||||
def inject_global_settings():
|
def inject_global_settings():
|
||||||
"""Make global settings available to all templates"""
|
"""Make global settings available to all templates"""
|
||||||
@@ -40,6 +58,7 @@ def inject_global_settings():
|
|||||||
'copyright_name': COPYRIGHT_NAME if COPYRIGHT_NAME else COMIC_NAME,
|
'copyright_name': COPYRIGHT_NAME if COPYRIGHT_NAME else COMIC_NAME,
|
||||||
'current_year': datetime.now().year,
|
'current_year': datetime.now().year,
|
||||||
'site_url': SITE_URL,
|
'site_url': SITE_URL,
|
||||||
|
'cdn_url': CDN_URL,
|
||||||
'logo_image': LOGO_IMAGE,
|
'logo_image': LOGO_IMAGE,
|
||||||
'logo_mode': LOGO_MODE,
|
'logo_mode': LOGO_MODE,
|
||||||
'header_image': HEADER_IMAGE,
|
'header_image': HEADER_IMAGE,
|
||||||
|
|||||||
@@ -15,6 +15,12 @@ COPYRIGHT_NAME = None # e.g., 'Your Name' or 'Your Studio Name'
|
|||||||
# Update this to your production domain when deploying
|
# Update this to your production domain when deploying
|
||||||
SITE_URL = 'http://localhost:3000'
|
SITE_URL = 'http://localhost:3000'
|
||||||
|
|
||||||
|
# Global setting: CDN URL for static assets (set to None to use local assets)
|
||||||
|
# When set, all static assets will be served from this CDN
|
||||||
|
# Example: CDN_URL = 'https://cdn.example.com' (no trailing slash)
|
||||||
|
# Leave as None for local development or if not using a CDN
|
||||||
|
CDN_URL = None
|
||||||
|
|
||||||
# Global setting: Set to True to make all comics full-width by default
|
# Global setting: Set to True to make all comics full-width by default
|
||||||
# Individual comics can override this with 'full_width': False
|
# Individual comics can override this with 'full_width': False
|
||||||
FULL_WIDTH_DEFAULT = False
|
FULL_WIDTH_DEFAULT = False
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
{% for comic in section_comics %}
|
{% for comic in section_comics %}
|
||||||
<div class="archive-item{% if archive_full_width %} archive-item-fullwidth{% endif %}">
|
<div class="archive-item{% if archive_full_width %} archive-item-fullwidth{% endif %}">
|
||||||
<a href="{{ url_for('comic', comic_id=comic.number) }}">
|
<a href="{{ url_for('comic', comic_id=comic.number) }}">
|
||||||
<img src="{{ url_for('static', filename='images/thumbs/' + comic.filename) }}"
|
<img src="{{ ('images/thumbs/' + comic.filename) | cdn_static }}"
|
||||||
onerror="this.onerror=null; this.src='{{ url_for('static', filename='images/thumbs/default.jpg') }}';"
|
onerror="this.onerror=null; this.src='{{ 'images/thumbs/default.jpg' | cdn_static }}';"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
loading="lazy">
|
loading="lazy">
|
||||||
<div class="archive-info">
|
<div class="archive-info">
|
||||||
@@ -47,5 +47,5 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
<script src="{{ url_for('static', filename='js/archive-lazy-load.js') }}"></script>
|
<script src="{{ 'js/archive-lazy-load.js' | cdn_static }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -31,13 +31,13 @@
|
|||||||
<meta property="twitter:image" content="{% block twitter_image %}{{ self.og_image() }}{% endblock %}">
|
<meta property="twitter:image" content="{% block twitter_image %}{{ self.og_image() }}{% endblock %}">
|
||||||
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
<link rel="icon" type="image/x-icon" href="{{ 'favicon.ico' | cdn_static }}">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('static', filename='favicon-32x32.png') }}">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ 'favicon-32x32.png' | cdn_static }}">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon-16x16.png') }}">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ 'favicon-16x16.png' | cdn_static }}">
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='apple-touch-icon.png') }}">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ 'apple-touch-icon.png' | cdn_static }}">
|
||||||
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
|
<link rel="stylesheet" href="{{ 'css/style.css' | cdn_static }}">
|
||||||
<link rel="alternate" type="application/rss+xml" title="{{ comic_name }} RSS Feed" href="{{ url_for('static', filename='feed.rss') }}">
|
<link rel="alternate" type="application/rss+xml" title="{{ comic_name }} RSS Feed" href="{{ 'feed.rss' | cdn_static }}">
|
||||||
{% block extra_css %}{% endblock %}
|
{% block extra_css %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body data-site-url="{{ site_url }}">
|
<body data-site-url="{{ site_url }}">
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
{% if header_image %}
|
{% if header_image %}
|
||||||
<div class="site-header-image">
|
<div class="site-header-image">
|
||||||
<img src="{{ url_for('static', filename='images/' + header_image) }}" alt="{{ comic_name }} Header">
|
<img src="{{ ('images/' + header_image) | cdn_static }}" alt="{{ comic_name }} Header">
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -57,10 +57,10 @@
|
|||||||
<div class="nav-brand">
|
<div class="nav-brand">
|
||||||
<a href="{{ url_for('index') }}">
|
<a href="{{ url_for('index') }}">
|
||||||
{% if logo_image and logo_mode == 'beside' %}
|
{% if logo_image and logo_mode == 'beside' %}
|
||||||
<img src="{{ url_for('static', filename='images/' + logo_image) }}" alt="{{ comic_name }} Logo" class="nav-logo nav-logo-beside">
|
<img src="{{ ('images/' + logo_image) | cdn_static }}" alt="{{ comic_name }} Logo" class="nav-logo nav-logo-beside">
|
||||||
<span class="nav-title">{{ comic_name }}</span>
|
<span class="nav-title">{{ comic_name }}</span>
|
||||||
{% elif logo_image and logo_mode == 'replace' %}
|
{% elif logo_image and logo_mode == 'replace' %}
|
||||||
<img src="{{ url_for('static', filename='images/' + logo_image) }}" alt="{{ comic_name }}" class="nav-logo nav-logo-replace">
|
<img src="{{ ('images/' + logo_image) | cdn_static }}" alt="{{ comic_name }}" class="nav-logo nav-logo-replace">
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ comic_name }}
|
{{ comic_name }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -70,17 +70,17 @@
|
|||||||
<ul class="nav-links">
|
<ul class="nav-links">
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url_for('index') }}" {% if request.endpoint == 'index' %}class="active"{% endif %}>
|
<a href="{{ url_for('index') }}" {% if request.endpoint == 'index' %}class="active"{% endif %}>
|
||||||
{% if use_header_nav_icons %}<img src="{{ url_for('static', filename='images/icons/alert.png') }}" alt="" class="nav-icon" aria-hidden="true">{% endif %}Latest
|
{% if use_header_nav_icons %}<img src="{{ 'images/icons/alert.png' | cdn_static }}" alt="" class="nav-icon" aria-hidden="true">{% endif %}Latest
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url_for('archive') }}" {% if request.endpoint == 'archive' %}class="active"{% endif %}>
|
<a href="{{ url_for('archive') }}" {% if request.endpoint == 'archive' %}class="active"{% endif %}>
|
||||||
{% if use_header_nav_icons %}<img src="{{ url_for('static', filename='images/icons/archive.png') }}" alt="" class="nav-icon" aria-hidden="true">{% endif %}Archive
|
{% if use_header_nav_icons %}<img src="{{ 'images/icons/archive.png' | cdn_static }}" alt="" class="nav-icon" aria-hidden="true">{% endif %}Archive
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url_for('about') }}" {% if request.endpoint == 'about' %}class="active"{% endif %}>
|
<a href="{{ url_for('about') }}" {% if request.endpoint == 'about' %}class="active"{% endif %}>
|
||||||
{% if use_header_nav_icons %}<img src="{{ url_for('static', filename='images/icons/info.png') }}" alt="" class="nav-icon" aria-hidden="true">{% endif %}About
|
{% if use_header_nav_icons %}<img src="{{ 'images/icons/info.png' | cdn_static }}" alt="" class="nav-icon" aria-hidden="true">{% endif %}About
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
{% if social_instagram %}
|
{% if social_instagram %}
|
||||||
<a href="{{ social_instagram }}" target="_blank" rel="noopener noreferrer" aria-label="Instagram">
|
<a href="{{ social_instagram }}" target="_blank" rel="noopener noreferrer" aria-label="Instagram">
|
||||||
{% if use_footer_social_icons %}
|
{% if use_footer_social_icons %}
|
||||||
<img src="{{ url_for('static', filename='images/icons/instagram.png') }}" alt="" class="social-icon">
|
<img src="{{ 'images/icons/instagram.png' | cdn_static }}" alt="" class="social-icon">
|
||||||
{% else %}
|
{% else %}
|
||||||
Instagram
|
Instagram
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
{% if social_youtube %}
|
{% if social_youtube %}
|
||||||
<a href="{{ social_youtube }}" target="_blank" rel="noopener noreferrer" aria-label="YouTube">
|
<a href="{{ social_youtube }}" target="_blank" rel="noopener noreferrer" aria-label="YouTube">
|
||||||
{% if use_footer_social_icons %}
|
{% if use_footer_social_icons %}
|
||||||
<img src="{{ url_for('static', filename='images/icons/youtube.png') }}" alt="" class="social-icon">
|
<img src="{{ 'images/icons/youtube.png' | cdn_static }}" alt="" class="social-icon">
|
||||||
{% else %}
|
{% else %}
|
||||||
YouTube
|
YouTube
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -121,21 +121,21 @@
|
|||||||
{% if social_email %}
|
{% if social_email %}
|
||||||
<a href="{{ social_email }}" aria-label="Email">
|
<a href="{{ social_email }}" aria-label="Email">
|
||||||
{% if use_footer_social_icons %}
|
{% if use_footer_social_icons %}
|
||||||
<img src="{{ url_for('static', filename='images/icons/mail .png') }}" alt="" class="social-icon">
|
<img src="{{ 'images/icons/mail .png' | cdn_static }}" alt="" class="social-icon">
|
||||||
{% else %}
|
{% else %}
|
||||||
Email
|
Email
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ url_for('static', filename='feed.rss') }}" aria-label="RSS Feed">
|
<a href="{{ 'feed.rss' | cdn_static }}" aria-label="RSS Feed">
|
||||||
{% if use_footer_social_icons %}
|
{% if use_footer_social_icons %}
|
||||||
<img src="{{ url_for('static', filename='images/icons/rss.png') }}" alt="" class="social-icon">
|
<img src="{{ 'images/icons/rss.png' | cdn_static }}" alt="" class="social-icon">
|
||||||
{% else %}
|
{% else %}
|
||||||
RSS Feed
|
RSS Feed
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</a>
|
</a>
|
||||||
{% if api_spec_link %}
|
{% if api_spec_link %}
|
||||||
<a href="{{ url_for('static', filename=api_spec_link) }}" aria-label="API">API</a>
|
<a href="{{ api_spec_link | cdn_static }}" aria-label="API">API</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -157,11 +157,11 @@
|
|||||||
<h3>Share A Link</h3>
|
<h3>Share A Link</h3>
|
||||||
<div class="shareable-banner">
|
<div class="shareable-banner">
|
||||||
<a href="{{ site_url }}" target="_blank" rel="noopener noreferrer" aria-label="Link to {{ comic_name }} home page">
|
<a href="{{ site_url }}" target="_blank" rel="noopener noreferrer" aria-label="Link to {{ comic_name }} home page">
|
||||||
<img src="{{ url_for('static', filename='images/' + banner_image) }}" alt="{{ comic_name }}" class="banner-image">
|
<img src="{{ ('images/' + banner_image) | cdn_static }}" alt="{{ comic_name }}" class="banner-image">
|
||||||
</a>
|
</a>
|
||||||
<details class="banner-code">
|
<details class="banner-code">
|
||||||
<summary>Get code</summary>
|
<summary>Get code</summary>
|
||||||
<textarea readonly onfocus="this.select()" onclick="this.select()" aria-label="HTML code for linking to {{ comic_name }}"><a href="{{ site_url }}"><img src="{{ site_url }}/static/images/{{ banner_image }}" alt="{{ comic_name }}"></a></textarea>
|
<textarea readonly onfocus="this.select()" onclick="this.select()" aria-label="HTML code for linking to {{ comic_name }}"><a href="{{ site_url }}"><img src="{% if cdn_url %}{{ cdn_url }}/static/images/{{ banner_image }}{% else %}{{ site_url }}/static/images/{{ banner_image }}{% endif %}" alt="{{ comic_name }}"></a></textarea>
|
||||||
</details>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
<span class="footer-divider" aria-hidden="true">|</span>
|
<span class="footer-divider" aria-hidden="true">|</span>
|
||||||
<div class="site-credit">
|
<div class="site-credit">
|
||||||
<a href="https://git.puercito.net/mi/sunday" target="_blank" rel="noopener noreferrer" aria-label="Sunday Comics - Webcomic platform">
|
<a href="https://git.puercito.net/mi/sunday" target="_blank" rel="noopener noreferrer" aria-label="Sunday Comics - Webcomic platform">
|
||||||
<img src="{{ url_for('static', filename='images/sunday.jpg') }}" alt="Sunday Comics" class="credit-image">
|
<img src="{{ 'images/sunday.jpg' | cdn_static }}" alt="Sunday Comics" class="credit-image">
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -184,7 +184,7 @@
|
|||||||
|
|
||||||
{% if footer_image %}
|
{% if footer_image %}
|
||||||
<div class="site-footer-image">
|
<div class="site-footer-image">
|
||||||
<img src="{{ url_for('static', filename='images/' + footer_image) }}" alt="{{ comic_name }} Footer">
|
<img src="{{ ('images/' + footer_image) | cdn_static }}" alt="{{ comic_name }} Footer">
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -206,12 +206,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<script src="{{ url_for('static', filename='js/comic-nav.js') }}"></script>
|
<script src="{{ 'js/comic-nav.js' | cdn_static }}"></script>
|
||||||
{% if embed_enabled %}
|
{% if embed_enabled %}
|
||||||
<script src="{{ url_for('static', filename='js/embed.js') }}"></script>
|
<script src="{{ 'js/embed.js' | cdn_static }}"></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if permalink_enabled %}
|
{% if permalink_enabled %}
|
||||||
<script src="{{ url_for('static', filename='js/permalink.js') }}"></script>
|
<script src="{{ 'js/permalink.js' | cdn_static }}"></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% block extra_js %}{% endblock %}
|
{% block extra_js %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
{% block meta_description %}{{ comic.alt_text }}{% if comic.author_note %} - {{ comic.author_note }}{% endif %}{% endblock %}
|
{% block meta_description %}{{ comic.alt_text }}{% if comic.author_note %} - {{ comic.author_note }}{% endif %}{% endblock %}
|
||||||
|
|
||||||
{% block og_image %}{{ site_url }}/static/images/thumbs/{{ comic.filename }}{% endblock %}
|
{% block og_image %}{% if cdn_url %}{{ cdn_url }}/static/images/thumbs/{{ comic.filename }}{% else %}{{ site_url }}/static/images/thumbs/{{ comic.filename }}{% endif %}{% endblock %}
|
||||||
|
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<script type="application/ld+json">
|
<script type="application/ld+json">
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
"@type": "ComicStory",
|
"@type": "ComicStory",
|
||||||
"name": "{{ comic.title if comic.title else '#' ~ comic.number }}",
|
"name": "{{ comic.title if comic.title else '#' ~ comic.number }}",
|
||||||
"datePublished": "{{ comic.date }}",
|
"datePublished": "{{ comic.date }}",
|
||||||
"image": "{{ site_url }}/static/images/comics/{{ comic.filename }}",
|
"image": "{% if cdn_url %}{{ cdn_url }}/static/images/comics/{{ comic.filename }}{% else %}{{ site_url }}/static/images/comics/{{ comic.filename }}{% endif %}",
|
||||||
"thumbnailUrl": "{{ site_url }}/static/images/thumbs/{{ comic.filename }}",
|
"thumbnailUrl": "{% if cdn_url %}{{ cdn_url }}/static/images/thumbs/{{ comic.filename }}{% else %}{{ site_url }}/static/images/thumbs/{{ comic.filename }}{% endif %}",
|
||||||
"description": "{{ comic.alt_text }}",
|
"description": "{{ comic.alt_text }}",
|
||||||
"isPartOf": {
|
"isPartOf": {
|
||||||
"@type": "ComicSeries",
|
"@type": "ComicSeries",
|
||||||
@@ -41,8 +41,8 @@
|
|||||||
{% if comic.is_multi_image %}
|
{% if comic.is_multi_image %}
|
||||||
{# Multi-image layout (webtoon style) - no click-through on individual images #}
|
{# Multi-image layout (webtoon style) - no click-through on individual images #}
|
||||||
{% for i in range(comic.filenames|length) %}
|
{% for i in range(comic.filenames|length) %}
|
||||||
<img src="{% if loop.first %}{{ url_for('static', filename='images/comics/' + comic.filenames[i]) }}{% endif %}"
|
<img src="{% if loop.first %}{{ ('images/comics/' + comic.filenames[i]) | cdn_static }}{% endif %}"
|
||||||
{% if not loop.first %}data-src="{{ url_for('static', filename='images/comics/' + comic.filenames[i]) }}" class="lazy-load"{% endif %}
|
{% if not loop.first %}data-src="{{ ('images/comics/' + comic.filenames[i]) | cdn_static }}" class="lazy-load"{% endif %}
|
||||||
alt="{{ comic.alt_texts[i] }}"
|
alt="{{ comic.alt_texts[i] }}"
|
||||||
title="{{ comic.alt_texts[i] }}"
|
title="{{ comic.alt_texts[i] }}"
|
||||||
loading="{% if loop.first %}eager{% else %}lazy{% endif %}">
|
loading="{% if loop.first %}eager{% else %}lazy{% endif %}">
|
||||||
@@ -53,13 +53,13 @@
|
|||||||
<a href="{{ url_for('comic', comic_id=comic.number + 1) }}" aria-label="Click to view next comic">
|
<a href="{{ url_for('comic', comic_id=comic.number + 1) }}" aria-label="Click to view next comic">
|
||||||
{% if comic.mobile_filename %}
|
{% if comic.mobile_filename %}
|
||||||
<picture>
|
<picture>
|
||||||
<source media="(max-width: 768px)" srcset="{{ url_for('static', filename='images/comics/' + comic.mobile_filename) }}">
|
<source media="(max-width: 768px)" srcset="{{ ('images/comics/' + comic.mobile_filename) | cdn_static }}">
|
||||||
<img src="{{ url_for('static', filename='images/comics/' + comic.filename) }}"
|
<img src="{{ ('images/comics/' + comic.filename) | cdn_static }}"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
title="{{ comic.alt_text }}">
|
title="{{ comic.alt_text }}">
|
||||||
</picture>
|
</picture>
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{ url_for('static', filename='images/comics/' + comic.filename) }}"
|
<img src="{{ ('images/comics/' + comic.filename) | cdn_static }}"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
title="{{ comic.alt_text }}"
|
title="{{ comic.alt_text }}"
|
||||||
loading="eager">
|
loading="eager">
|
||||||
@@ -68,13 +68,13 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
{% if comic.mobile_filename %}
|
{% if comic.mobile_filename %}
|
||||||
<picture>
|
<picture>
|
||||||
<source media="(max-width: 768px)" srcset="{{ url_for('static', filename='images/comics/' + comic.mobile_filename) }}">
|
<source media="(max-width: 768px)" srcset="{{ ('images/comics/' + comic.mobile_filename) | cdn_static }}">
|
||||||
<img src="{{ url_for('static', filename='images/comics/' + comic.filename) }}"
|
<img src="{{ ('images/comics/' + comic.filename) | cdn_static }}"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
title="{{ comic.alt_text }}">
|
title="{{ comic.alt_text }}">
|
||||||
</picture>
|
</picture>
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{ url_for('static', filename='images/comics/' + comic.filename) }}"
|
<img src="{{ ('images/comics/' + comic.filename) | cdn_static }}"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
title="{{ comic.alt_text }}"
|
title="{{ comic.alt_text }}"
|
||||||
loading="eager">
|
loading="eager">
|
||||||
@@ -89,17 +89,17 @@
|
|||||||
{# Icon-based navigation #}
|
{# Icon-based navigation #}
|
||||||
{% if comic.number > 1 %}
|
{% if comic.number > 1 %}
|
||||||
<a href="{{ url_for('comic', comic_id=1) }}" class="btn-icon-nav" aria-label="First">
|
<a href="{{ url_for('comic', comic_id=1) }}" class="btn-icon-nav" aria-label="First">
|
||||||
<img src="{{ url_for('static', filename='images/icons/first.png') }}" alt="">
|
<img src="{{ 'images/icons/first.png' | cdn_static }}" alt="">
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url_for('comic', comic_id=comic.number - 1) }}" class="btn-icon-nav" aria-label="Previous">
|
<a href="{{ url_for('comic', comic_id=comic.number - 1) }}" class="btn-icon-nav" aria-label="Previous">
|
||||||
<img src="{{ url_for('static', filename='images/icons/previous.png') }}" alt="">
|
<img src="{{ 'images/icons/previous.png' | cdn_static }}" alt="">
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="First" aria-disabled="true">
|
<span class="btn-icon-nav btn-icon-disabled" aria-label="First" aria-disabled="true">
|
||||||
<img src="{{ url_for('static', filename='images/icons/first.png') }}" alt="">
|
<img src="{{ 'images/icons/first.png' | cdn_static }}" alt="">
|
||||||
</span>
|
</span>
|
||||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Previous" aria-disabled="true">
|
<span class="btn-icon-nav btn-icon-disabled" aria-label="Previous" aria-disabled="true">
|
||||||
<img src="{{ url_for('static', filename='images/icons/previous.png') }}" alt="">
|
<img src="{{ 'images/icons/previous.png' | cdn_static }}" alt="">
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -107,17 +107,17 @@
|
|||||||
|
|
||||||
{% if comic.number < total_comics %}
|
{% if comic.number < total_comics %}
|
||||||
<a href="{{ url_for('comic', comic_id=comic.number + 1) }}" class="btn-icon-nav" aria-label="Next">
|
<a href="{{ url_for('comic', comic_id=comic.number + 1) }}" class="btn-icon-nav" aria-label="Next">
|
||||||
<img src="{{ url_for('static', filename='images/icons/next.png') }}" alt="">
|
<img src="{{ 'images/icons/next.png' | cdn_static }}" alt="">
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url_for('comic', comic_id=total_comics) }}" class="btn-icon-nav" aria-label="Latest">
|
<a href="{{ url_for('comic', comic_id=total_comics) }}" class="btn-icon-nav" aria-label="Latest">
|
||||||
<img src="{{ url_for('static', filename='images/icons/latest.png') }}" alt="">
|
<img src="{{ 'images/icons/latest.png' | cdn_static }}" alt="">
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Next" aria-disabled="true">
|
<span class="btn-icon-nav btn-icon-disabled" aria-label="Next" aria-disabled="true">
|
||||||
<img src="{{ url_for('static', filename='images/icons/next.png') }}" alt="">
|
<img src="{{ 'images/icons/next.png' | cdn_static }}" alt="">
|
||||||
</span>
|
</span>
|
||||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Latest" aria-disabled="true">
|
<span class="btn-icon-nav btn-icon-disabled" aria-label="Latest" aria-disabled="true">
|
||||||
<img src="{{ url_for('static', filename='images/icons/latest.png') }}" alt="">
|
<img src="{{ 'images/icons/latest.png' | cdn_static }}" alt="">
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -147,12 +147,12 @@
|
|||||||
<div class="comic-share-section">
|
<div class="comic-share-section">
|
||||||
{% if permalink_enabled %}
|
{% if permalink_enabled %}
|
||||||
<button class="btn-permalink{% if use_share_icons %} btn-with-icon{% endif %}" id="permalink-button" data-comic-number="{{ comic.number }}" aria-label="Copy permalink to this comic">
|
<button class="btn-permalink{% if use_share_icons %} btn-with-icon{% endif %}" id="permalink-button" data-comic-number="{{ comic.number }}" aria-label="Copy permalink to this comic">
|
||||||
{% if use_share_icons %}<img src="{{ url_for('static', filename='images/icons/link.png') }}" alt="" class="btn-icon" aria-hidden="true">{% endif %}Copy Permalink
|
{% if use_share_icons %}<img src="{{ 'images/icons/link.png' | cdn_static }}" alt="" class="btn-icon" aria-hidden="true">{% endif %}Copy Permalink
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if embed_enabled %}
|
{% if embed_enabled %}
|
||||||
<button class="btn-embed{% if use_share_icons %} btn-with-icon{% endif %}" id="embed-button" data-comic-number="{{ comic.number }}" aria-label="Get embed code for this comic">
|
<button class="btn-embed{% if use_share_icons %} btn-with-icon{% endif %}" id="embed-button" data-comic-number="{{ comic.number }}" aria-label="Get embed code for this comic">
|
||||||
{% if use_share_icons %}<img src="{{ url_for('static', filename='images/icons/embed.png') }}" alt="" class="btn-icon" aria-hidden="true">{% endif %}Share/Embed
|
{% if use_share_icons %}<img src="{{ 'images/icons/embed.png' | cdn_static }}" alt="" class="btn-icon" aria-hidden="true">{% endif %}Share/Embed
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -127,21 +127,21 @@
|
|||||||
<p class="embed-date">{{ comic.formatted_date }}</p>
|
<p class="embed-date">{{ comic.formatted_date }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% if logo_image %}
|
{% if logo_image %}
|
||||||
<img src="{{ site_url }}/static/images/{{ logo_image }}" alt="{{ comic_name }}" class="embed-logo">
|
<img src="{% if cdn_url %}{{ cdn_url }}/static/images/{{ logo_image }}{% else %}{{ site_url }}/static/images/{{ logo_image }}{% endif %}" alt="{{ comic_name }}" class="embed-logo">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="embed-image-wrapper">
|
<div class="embed-image-wrapper">
|
||||||
<a href="{{ site_url }}/comic/{{ comic.number }}" class="embed-image-link" target="_blank" rel="noopener noreferrer" aria-label="View {{ comic.title if comic.title else 'comic #' ~ comic.number }} on {{ comic_name }}">
|
<a href="{{ site_url }}/comic/{{ comic.number }}" class="embed-image-link" target="_blank" rel="noopener noreferrer" aria-label="View {{ comic.title if comic.title else 'comic #' ~ comic.number }} on {{ comic_name }}">
|
||||||
{% if comic.mobile_filename %}
|
{% if comic.mobile_filename %}
|
||||||
<picture>
|
<picture>
|
||||||
<source media="(max-width: 768px)" srcset="{{ url_for('static', filename='images/comics/' + comic.mobile_filename) }}">
|
<source media="(max-width: 768px)" srcset="{{ ('images/comics/' + comic.mobile_filename) | cdn_static }}">
|
||||||
<img src="{{ url_for('static', filename='images/comics/' + comic.filename) }}"
|
<img src="{{ ('images/comics/' + comic.filename) | cdn_static }}"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
title="{{ comic.alt_text }}"
|
title="{{ comic.alt_text }}"
|
||||||
class="embed-image">
|
class="embed-image">
|
||||||
</picture>
|
</picture>
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{ url_for('static', filename='images/comics/' + comic.filename) }}"
|
<img src="{{ ('images/comics/' + comic.filename) | cdn_static }}"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
title="{{ comic.alt_text }}"
|
title="{{ comic.alt_text }}"
|
||||||
class="embed-image">
|
class="embed-image">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
{% if comic %}
|
{% if comic %}
|
||||||
{% block meta_description %}{{ comic.alt_text }}{% if comic.author_note %} - {{ comic.author_note }}{% endif %}{% endblock %}
|
{% block meta_description %}{{ comic.alt_text }}{% if comic.author_note %} - {{ comic.author_note }}{% endif %}{% endblock %}
|
||||||
|
|
||||||
{% block og_image %}{{ site_url }}/static/images/thumbs/{{ comic.filename }}{% endblock %}
|
{% block og_image %}{% if cdn_url %}{{ cdn_url }}/static/images/thumbs/{{ comic.filename }}{% else %}{{ site_url }}/static/images/thumbs/{{ comic.filename }}{% endif %}{% endblock %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
@@ -20,8 +20,8 @@
|
|||||||
{% if comic.is_multi_image %}
|
{% if comic.is_multi_image %}
|
||||||
{# Multi-image layout (webtoon style) - no click-through on individual images #}
|
{# Multi-image layout (webtoon style) - no click-through on individual images #}
|
||||||
{% for i in range(comic.filenames|length) %}
|
{% for i in range(comic.filenames|length) %}
|
||||||
<img src="{% if loop.first %}{{ url_for('static', filename='images/comics/' + comic.filenames[i]) }}{% endif %}"
|
<img src="{% if loop.first %}{{ ('images/comics/' + comic.filenames[i]) | cdn_static }}{% endif %}"
|
||||||
{% if not loop.first %}data-src="{{ url_for('static', filename='images/comics/' + comic.filenames[i]) }}" class="lazy-load"{% endif %}
|
{% if not loop.first %}data-src="{{ ('images/comics/' + comic.filenames[i]) | cdn_static }}" class="lazy-load"{% endif %}
|
||||||
alt="{{ comic.alt_texts[i] }}"
|
alt="{{ comic.alt_texts[i] }}"
|
||||||
title="{{ comic.alt_texts[i] }}"
|
title="{{ comic.alt_texts[i] }}"
|
||||||
loading="{% if loop.first %}eager{% else %}lazy{% endif %}">
|
loading="{% if loop.first %}eager{% else %}lazy{% endif %}">
|
||||||
@@ -29,13 +29,13 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
{% if comic.mobile_filename %}
|
{% if comic.mobile_filename %}
|
||||||
<picture>
|
<picture>
|
||||||
<source media="(max-width: 768px)" srcset="{{ url_for('static', filename='images/comics/' + comic.mobile_filename) }}">
|
<source media="(max-width: 768px)" srcset="{{ ('images/comics/' + comic.mobile_filename) | cdn_static }}">
|
||||||
<img src="{{ url_for('static', filename='images/comics/' + comic.filename) }}"
|
<img src="{{ ('images/comics/' + comic.filename) | cdn_static }}"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
title="{{ comic.alt_text }}">
|
title="{{ comic.alt_text }}">
|
||||||
</picture>
|
</picture>
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{ url_for('static', filename='images/comics/' + comic.filename) }}"
|
<img src="{{ ('images/comics/' + comic.filename) | cdn_static }}"
|
||||||
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
alt="{{ comic.title if comic.title else '#' ~ comic.number }}"
|
||||||
title="{{ comic.alt_text }}">
|
title="{{ comic.alt_text }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -48,17 +48,17 @@
|
|||||||
{# Icon-based navigation #}
|
{# Icon-based navigation #}
|
||||||
{% if comic.number > 1 %}
|
{% if comic.number > 1 %}
|
||||||
<a href="{{ url_for('comic', comic_id=1) }}" class="btn-icon-nav" aria-label="First">
|
<a href="{{ url_for('comic', comic_id=1) }}" class="btn-icon-nav" aria-label="First">
|
||||||
<img src="{{ url_for('static', filename='images/icons/first.png') }}" alt="">
|
<img src="{{ 'images/icons/first.png' | cdn_static }}" alt="">
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url_for('comic', comic_id=comic.number - 1) }}" class="btn-icon-nav" aria-label="Previous">
|
<a href="{{ url_for('comic', comic_id=comic.number - 1) }}" class="btn-icon-nav" aria-label="Previous">
|
||||||
<img src="{{ url_for('static', filename='images/icons/previous.png') }}" alt="">
|
<img src="{{ 'images/icons/previous.png' | cdn_static }}" alt="">
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="First" aria-disabled="true">
|
<span class="btn-icon-nav btn-icon-disabled" aria-label="First" aria-disabled="true">
|
||||||
<img src="{{ url_for('static', filename='images/icons/first.png') }}" alt="">
|
<img src="{{ 'images/icons/first.png' | cdn_static }}" alt="">
|
||||||
</span>
|
</span>
|
||||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Previous" aria-disabled="true">
|
<span class="btn-icon-nav btn-icon-disabled" aria-label="Previous" aria-disabled="true">
|
||||||
<img src="{{ url_for('static', filename='images/icons/previous.png') }}" alt="">
|
<img src="{{ 'images/icons/previous.png' | cdn_static }}" alt="">
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@@ -66,17 +66,17 @@
|
|||||||
|
|
||||||
{% if comic.number < total_comics %}
|
{% if comic.number < total_comics %}
|
||||||
<a href="{{ url_for('comic', comic_id=comic.number + 1) }}" class="btn-icon-nav" aria-label="Next">
|
<a href="{{ url_for('comic', comic_id=comic.number + 1) }}" class="btn-icon-nav" aria-label="Next">
|
||||||
<img src="{{ url_for('static', filename='images/icons/next.png') }}" alt="">
|
<img src="{{ 'images/icons/next.png' | cdn_static }}" alt="">
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url_for('comic', comic_id=total_comics) }}" class="btn-icon-nav" aria-label="Latest">
|
<a href="{{ url_for('comic', comic_id=total_comics) }}" class="btn-icon-nav" aria-label="Latest">
|
||||||
<img src="{{ url_for('static', filename='images/icons/latest.png') }}" alt="">
|
<img src="{{ 'images/icons/latest.png' | cdn_static }}" alt="">
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Next" aria-disabled="true">
|
<span class="btn-icon-nav btn-icon-disabled" aria-label="Next" aria-disabled="true">
|
||||||
<img src="{{ url_for('static', filename='images/icons/next.png') }}" alt="">
|
<img src="{{ 'images/icons/next.png' | cdn_static }}" alt="">
|
||||||
</span>
|
</span>
|
||||||
<span class="btn-icon-nav btn-icon-disabled" aria-label="Latest" aria-disabled="true">
|
<span class="btn-icon-nav btn-icon-disabled" aria-label="Latest" aria-disabled="true">
|
||||||
<img src="{{ url_for('static', filename='images/icons/latest.png') }}" alt="">
|
<img src="{{ 'images/icons/latest.png' | cdn_static }}" alt="">
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -106,12 +106,12 @@
|
|||||||
<div class="comic-share-section">
|
<div class="comic-share-section">
|
||||||
{% if permalink_enabled %}
|
{% if permalink_enabled %}
|
||||||
<button class="btn-permalink{% if use_share_icons %} btn-with-icon{% endif %}" id="permalink-button" data-comic-number="{{ comic.number }}" aria-label="Copy permalink to this comic">
|
<button class="btn-permalink{% if use_share_icons %} btn-with-icon{% endif %}" id="permalink-button" data-comic-number="{{ comic.number }}" aria-label="Copy permalink to this comic">
|
||||||
{% if use_share_icons %}<img src="{{ url_for('static', filename='images/icons/link.png') }}" alt="" class="btn-icon" aria-hidden="true">{% endif %}Copy Permalink
|
{% if use_share_icons %}<img src="{{ 'images/icons/link.png' | cdn_static }}" alt="" class="btn-icon" aria-hidden="true">{% endif %}Copy Permalink
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if embed_enabled %}
|
{% if embed_enabled %}
|
||||||
<button class="btn-embed{% if use_share_icons %} btn-with-icon{% endif %}" id="embed-button" data-comic-number="{{ comic.number }}" aria-label="Get embed code for this comic">
|
<button class="btn-embed{% if use_share_icons %} btn-with-icon{% endif %}" id="embed-button" data-comic-number="{{ comic.number }}" aria-label="Get embed code for this comic">
|
||||||
{% if use_share_icons %}<img src="{{ url_for('static', filename='images/icons/embed.png') }}" alt="" class="btn-icon" aria-hidden="true">{% endif %}Share/Embed
|
{% if use_share_icons %}<img src="{{ 'images/icons/embed.png' | cdn_static }}" alt="" class="btn-icon" aria-hidden="true">{% endif %}Share/Embed
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user