Compare commits

..

27 Commits

Author SHA1 Message Date
f17cb52c2e use this, and add reaction counter 2023-12-29 11:24:33 -06:00
a7c56f8d43 rework test to have reaction counts 2023-12-29 11:24:16 -06:00
25a86c634c rename cards to this 2023-12-29 11:23:58 -06:00
b675961b9c move call to action vars to be scoped 2023-12-29 10:18:03 -06:00
04f860e06a only show card footer if there are reactions 2023-12-28 23:39:18 -06:00
ba8935a3d3 color reactions the same as body text 2023-12-28 23:37:47 -06:00
41157d5205 fix color mode js 2023-12-28 23:36:56 -06:00
1876732d56 and this one 2023-12-28 23:28:17 -06:00
e6150c8ae6 forgot this one 2023-12-28 23:27:45 -06:00
4cabbe2013 adjust comments 2023-12-28 23:25:35 -06:00
25a3373f2b Format test script, and strip whitespace 2023-12-28 23:22:23 -06:00
61dcf7caae sync vscode settings 2023-12-28 23:15:03 -06:00
1042957ca4 ignore all logs 2023-12-28 23:14:35 -06:00
572036a292 don't ignore the gallery template 2023-12-28 23:13:28 -06:00
226cd3438e Change license to BSD-3 Clause from MIT 2023-12-28 23:08:00 -06:00
39042d2526 card data 2023-12-28 22:40:44 -06:00
c846c8e789 Fix rendering of the cards 2023-12-28 22:40:33 -06:00
50a67a5491 ignore test.html 2023-12-28 22:09:55 -06:00
7cbfe6e346 Create test render script 2023-12-28 22:09:37 -06:00
df7042942b put footer text into own dict 2023-12-28 22:08:20 -06:00
d6c66161a5 update header docs, remove commented meta tags 2023-12-28 22:08:02 -06:00
26acdaf66a use different way for bootstrap icons 2023-12-28 22:07:38 -06:00
8a28bd5ce2 ignore venv 2023-12-28 22:06:17 -06:00
4edd2fb59d Create a bunch of templates 2023-12-28 21:14:10 -06:00
0ed2e1ee7b ignore examples 2023-12-28 21:13:59 -06:00
03b9bf6e63 delete original templates 2023-12-28 21:12:38 -06:00
0f75811000 Update license to my new name 2023-12-27 19:32:17 -06:00
17 changed files with 556 additions and 291 deletions

8
.gitignore vendored
View File

@@ -1,6 +1,8 @@
pathlist*.txt pathlist*.txt
thumbs/* thumbs/*
GenThumb.log *.log
index*.html index*.html
.vscode **/example/**
gallery.html **/*venv/**
test.html

6
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"license.author": "Code Fox <c0de@c0de.dev>",
"license.filename": "license",
"license.extension": ".txt",
"license.default": "bsd-3-clause"
}

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2019 David Todd (c0de@c0defox.es)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

28
license.txt Normal file
View File

@@ -0,0 +1,28 @@
BSD 3-Clause License
Copyright (c) 2023, Code Fox <c0de@c0de.dev>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

13
templates/base.html Normal file
View File

@@ -0,0 +1,13 @@
{% include 'header.html' %}
{% include 'body_top.html' %}
{% include 'navbar.html' %}
<main>
{% include 'call_to_action.html' %}
{% include 'gallery.html' %}
</main>
{% include 'footer.html' %}
{% include 'body_bottom.html' %}

View File

@@ -0,0 +1,9 @@
{% if static.scripts.bootstrap %}
<script
src="{{ static.scripts.bootstrap.src | default('') }}"
integrity="{{ static.scripts.bootstrap.integrity | default('') }}"
crossorigin="{{ static.scripts.bootstrap.crossorigin | default('anonymous' if static.scripts.bootstrap.integrity else '') }}"
></script>
{% endif %}
</body>
</html>

53
templates/body_top.html Normal file
View File

@@ -0,0 +1,53 @@
<body>
<!-- Bootstrap Color Picker -->
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
<symbol id="check2" viewBox="0 0 16 16">
<path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/>
</symbol>
<symbol id="circle-half" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/>
</symbol>
<symbol id="moon-stars-fill" viewBox="0 0 16 16">
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/>
<path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z"/>
</symbol>
<symbol id="sun-fill" viewBox="0 0 16 16">
<path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/>
</symbol>
</svg>
<div class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle">
<button class="btn btn-bd-primary py-2 dropdown-toggle d-flex align-items-center"
id="bd-theme"
type="button"
aria-expanded="false"
data-bs-toggle="dropdown"
aria-label="Toggle theme (auto)">
<svg class="bi my-1 theme-icon-active" width="1em" height="1em"><use href="#circle-half"></use></svg>
<span class="visually-hidden" id="bd-theme-text">Toggle theme</span>
</button>
<ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="bd-theme-text">
<li>
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="light" aria-pressed="false">
<svg class="bi me-2 opacity-50 theme-icon" width="1em" height="1em"><use href="#sun-fill"></use></svg>
Light
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
</button>
</li>
<li>
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="dark" aria-pressed="false">
<svg class="bi me-2 opacity-50 theme-icon" width="1em" height="1em"><use href="#moon-stars-fill"></use></svg>
Dark
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
</button>
</li>
<li>
<button type="button" class="dropdown-item d-flex align-items-center active" data-bs-theme-value="auto" aria-pressed="true">
<svg class="bi me-2 opacity-50 theme-icon" width="1em" height="1em"><use href="#circle-half"></use></svg>
Auto
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
</button>
</li>
</ul>
</div>
<!-- End Bootstrap Color Picker -->

View File

@@ -0,0 +1,39 @@
<!--{#
#~ Var | Required | Default ~#
active | no | false
header | yes | none
lead_text | yes | none
action_buttons (list, optional)
n. (list index)
- href | no | #
- theme | no | primary
- icon | no | none
- text | yes | none
... (etc)
#}-->
{% if call_to_action.active | default(false) %}
<section class="py-5 text-center container">
<div class="row py-lg-5">
<div class="col-lg-6 col-md-8 mx-auto">
<h1 class="fw-light">{{ call_to_action.header }}</h1>
<p class="lead text-body-secondary">{{ call_to_action.lead_text }}</p>
{% if call_to_action.buttons %}
<p>
{% for button in call_to_action.buttons %}
<a
href="{{ button.href | default('#') }}"
class="btn btn-{{ button.theme | default('primary') }} my-2 d-inline-flex"
>
{% if button.icon %}
<i class="bi-{{ button.icon }}"></i>
{% endif %}
{{ button.text }}
</a>
{% endfor %}
</p>
{% endif %}
</div>
</div>
</section>
{% endif %}

View File

@@ -1,8 +1,61 @@
<div class="col-md-3"> <div class="col">
<a href="{{FULLLINK}}" target="{{FULLLINK}}"> <div class="card shadow-sm">
<div class="card mb-3 bg-dark text-white"> <div class="card-header">
<div class="card-header">{{TITLE}}</div> <span class="flex">{{ this.title }}</span>
<img class="card-img" width="250" src="{{THUMBNAIL}}" /> <a
</div> href="#"
class="btn btn-link float-end"
data-bs-toggle="tooltip"
data-bs-placement="top"
data-bs-title="Add a reaction"
>
<i class="bi-heart-fill text-end" style="font-size: 1rem; color: pink;"></i>
</a> </a>
</div>
<img
class="card-image-top"
width="{{ this.width | default('100%') }}"
height="{{ this.height | default('225') }}"
src="{{ this.src }}"
alt="{{ this.alt_text if this.alt_text else this.title }}"
/>
<div class="card-body">
<p class="card-text">{{ this.description | default('') }}</p>
</div>
{% if this.reactions and gallery.max_reactions_per_card|int >= 1 %}
<div class="card-footer text-body-secondary text-end">
{% set reaction_iterations = namespace(value=0) %}
{% for reaction, reaction_count in this.reactions|dictsort(by="value") %}
{# Don't render reaction if we've reached the max number, or its counter is 0 (or lower) #}
{% if reaction_iterations != gallery.max_reactions_per_card|int and reaction_count >= 1 %}
<button class="btn btn-link btn-sm disabled text-body position-relative">
{# TODO: Enable the button, and make clicking it toggle adding/removing that reaction to the counter, also color reaction button #}
<i class="bi-{{ reaction }}"></i>
{# Only show counter if more than 2 people gave the same reaction #}
{% if reaction_count|int >= 2 %}
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-dark">
{# Don't render reaction counts larger than 1000 #}
{{ reaction_count if reaction_count <= 999 else '1K+' }}
<span class="visually-hidden">
{{ reaction_count }} people reacted with {{ reaction }}
</span>
</span>
{% endif %}
</button>
{% set reaction_iterations.value = reaction_iterations.value + 1 %}
{% endif %}
{% endfor %}
{% set reaction_iterations = none %}
</div>
{% endif %}
</div>
</div> </div>

View File

@@ -0,0 +1,23 @@
<div class="col">
<div class="card" aria-hidden="true">
<div class="card-header">
<div class="d-flex align-items-center">
<strong role="status">Loading...</strong>
<div class="spinner-border ms-auto" aria-hidden="true"></div>
</div>
</div>
<svg class="bd-placeholder-img card-img-top" width="100%" height="225" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Placeholder: Loading..." preserveAspectRatio="xMidYMid slice" focusable="false"><title>Placeholder</title><rect width="100%" height="100%" fill="#55595c"/><text x="50%" y="50%" fill="#eceeef" dy=".3em">Loading...</text></svg>
<div class="card-body">
<h5 class="card-title placeholder-glow">
<span class="placeholder col-6"></span>
</h5>
<p class="card-text placeholder-glow">
<span class="placeholder col-7"></span>
<span class="placeholder col-4"></span>
<span class="placeholder col-4"></span>
<span class="placeholder col-6"></span>
<span class="placeholder col-8"></span>
</p>
</div>
</div>
</div>

23
templates/footer.html Normal file
View File

@@ -0,0 +1,23 @@
<!--{#
#~ Var | Required | Default ~#
main_line | no | none
extra_lines (list)
- (text to print) | no | none
#}-->
<footer class="text-body-secondary py-5">
<div class="container">
<p class="float-end mb-1">
<a href="#">Back to top</a>
</p>
<p class="mb-1">{{ footer.main_line | default('') }}</p>
{% if footer.extra_lines %}
{% for line in footer.extra_lines %}
{% if line %}
<p class="mb-0">{{ line }}</p>
{% endif %}
{% endfor %}
{% endif %}
</div>
</footer>

12
templates/gallery.html Normal file
View File

@@ -0,0 +1,12 @@
<div class="album py-5 bg-body-tertiary">
<div class="container">
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
{% for this in gallery_items %}
{% include 'card.html' %}
{# include 'card_loading.html' #}
{% endfor %}
</div>
</div>
</div>

122
templates/header.html Normal file
View File

@@ -0,0 +1,122 @@
<!--{#
#~ Var | Required | Default ~#
language | no | en
css_theme_name | no | auto
canonical_url | yes | none
page_title | yes | none
static (dict)
- scripts (dict)
- bootstrap (used in footer.html)
- src | yes | none
- integrity | no | empty
- crossorigin | no | empty if no integrity, anonymous otherwise
- theme
- src | yes | none
- integrity | no | empty
- crossorigin | no | empty if no integrity, anonymous otherwise
- css (dict)
- bootstrap
- src | yes | none
- integrity | no | empty
- crossorigin | no | empty if no integrity, anonymous otherwise
- theme
- src | yes | none
- integrity | no | empty
- crossorigin | no | empty if no integrity, anonymous otherwise
- icons
- src | yes | none
- integrity | no | empty
- crossorigin | no | empty if no integrity, anonymous otherwise
meta_list
n. (list index)
- name | yes | none
- content | yes | none
... (etc)
favicon_list (list of dicts)
n. (list index)
- rel | no | icon
- src | yes | none
- sizes | no | none
- type | no | none
- color | no | none
... (etc)
#}-->
<!doctype html>
<html
lang="{{ language | default('en') }}"
data-bs-theme="{{ css_theme_name | default('auto') }}"
>
<head>
{% if static.scripts.theme %}
<script
src="{{ static.scripts.theme.src | default('') }}"
integrity="{{ static.scripts.theme.integrity | default('') }}"
crossorigin="{{ static.scripts.theme.crossorigin | default('anonymous' if static.scripts.theme.integrity else '') }}"
></script>
{% endif %}
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="{{ charset | default('utf-8') }}" />
<link rel="canonical" href="{{ canonical_url }}" />
<title>{{ page_title }}</title>
{% if meta_list %}
<!-- meta-tags -->
{% for meta in meta_list %}
<meta name="{{ meta.name }}" content="{{ meta.content }}" />
{% endfor %}
{% endif %}
{% if favicon_list %}
<!-- Favicons -->
{% for icon in favicon_list %}
<link
rel="{{ icon.rel | default('icon') }}"
href="{{ icon.src }}"
sizes="{{ icon.sizes | default('') }}"
type="{{ icon.type | default('') }}"
color="{{ icon.color | default('') }}"
/>
{% endfor %}
{% endif %}
<!--
#~ These are to be provided by the favicon_list above ~#
<link rel="apple-touch-icon" href="/docs/5.3/assets/img/favicons/apple-touch-icon.png" sizes="180x180">
<link rel="icon" href="/docs/5.3/assets/img/favicons/favicon-32x32.png" sizes="32x32" type="image/png">
<link rel="icon" href="/docs/5.3/assets/img/favicons/favicon-16x16.png" sizes="16x16" type="image/png">
<link rel="manifest" href="/docs/5.3/assets/img/favicons/manifest.json">
<link rel="mask-icon" href="/docs/5.3/assets/img/favicons/safari-pinned-tab.svg" color="#712cf9">
<link rel="icon" href="/docs/5.3/assets/img/favicons/favicon.ico">
-->
{% if static.css.bootstrap %}
<link
rel="stylesheet"
href="{{ static.css.bootstrap.src }}"
integrity="{{ static.css.bootstrap.integrity | default('') }}"
crossorigin="{{ static.css.bootstrap.crossorigin | default('anonymous' if static.css.bootstrap.integrity else '') }}"
/>
{% endif %}
{% if static.css.theme %}
<link
rel="stylesheet"
href="{{ static.css.theme.src }}"
integrity="{{ static.css.theme.integrity | default('') }}"
crossorigin="{{ static.css.theme.crossorigin | default('anonymous' if static.css.theme.integrity else '') }}"
/>
{% endif %}
{% if static.css.icons %}
<link
rel="stylesheet"
href="{{ static.css.icons.src }}"
integrity="{{ static.css.icons.integrity | default('') }}"
crossorigin="{{ static.css.icons.crossorigin | default('anonymous' if static.css.icons.integrity else '') }}"
/>
{% endif %}
</head>

57
templates/navbar.html Normal file
View File

@@ -0,0 +1,57 @@
<!--{#
#~ Var | Required | Default ~#
theme | no | dark
text_theme | no | white
page_title | yes | none
left_header | no | About
left_text | no | none
right_header | no | none
link_list
n. (list index)
- href | yes | none
- text | yes | none
- icon | no | none
... (etc)
#}-->
<header data-bs-theme="{{ theme | default('dark') }}">
<div class="collapse text-bg-{{ theme | default('dark') }}" id="navbarHeader">
<div class="container">
<div class="row">
<div class="col-sm-8 col-md-7 py-4">
<h4>{{ left_header | default('About') }}</h4>
<p class="text-body-secondary">{{ left_text | default('') }}</p>
</div>
<div class="col-sm-4 offset-md-1 py-4">
<h4>{{ right_header | default('') }}</h4>
{% if link_list %}
<ul class="list-unstyled">
{% for link in link_list %}
{% if link.href and link.text %}
<li><a href={{ link.href }} class="text-{{ text_theme | default('white') }}">
{% if link.icon %}
<i class="bi-{{ link.icon }}"></i>
{% endif %}
{{ link.text }}
</a></li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
</div>
</div>
</div>
</div>
<div class="navbar navbar-{{ theme | default('dark') }} bg-{{ theme | default('dark') }} shadow-sm">
<div class="container">
<a href="#" class="navbar-brand d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" aria-hidden="true" class="me-2" viewBox="0 0 24 24"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
<strong>{{ page_title }}</strong>
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
</header>

View File

@@ -1,123 +0,0 @@
<html>
<head>
<title>Simple S3 Gallery</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="David Todd" />
<link rel="icon" type="image/png" href="https://secure.gravatar.com/avatar/1e346a54257cf0a9932fcfc1e61c015d" />
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
.jumbotron {
padding-top: 3rem;
padding-bottom: 3rem;
margin-bottom: 0;
background-color: #fff;
}
@media (min-width: 768px) {
.jumbotron {
padding-top: 6rem;
padding-bottom: 6rem;
}
}
.jumbotron p:last-child {
margin-bottom: 0;
}
.jumbotron-heading {
font-weight: 300;
}
.jumbotron .container {
max-width: 40rem;
}
.card-header {
text-align: center;
padding: 0.25rem 0rem;
}
footer {
padding-top: 3rem;
padding-bottom: 3rem;
}
footer p {
margin-bottom: .25rem;
}
</style>
</head>
<body>
<header>
<div class="collapse bg-dark" id="navbarHeader">
<div class="container">
<div class="row">
<div class="col-sm-8 col-md-7 py-4">
<h4 class="text-white">About</h4>
<p class="text-muted">This was a small gallery that I put together to make my photography available to the world. Images are grouped in folders for what I've done.</p>
</div>
<div class="col-sm-4 offset-md-1 py-4">
<h4 class="text-white">Contact</h4>
<ul class="list-unstyled">
<li><a href="https://c0defox.es" class="text-white">My contact site</a></li>
<li><a href="https://t.me/c0defox" class="text-white">Hit me up on Telegram</a></li>
<li><a href="c0de#0689" class="text-white">My Discord is c0de#0689</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="navbar navbar-dark bg-dark shadow-sm">
<div class="container d-flex justify-content-between">
<a href="#" class="navbar-brand d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" aria-hidden="true" class="mr-2" viewBox="0 0 24 24" focusable="false"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
<strong>Simple S3 Gallery</strong>
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
</header>
<main role="main">
<!-- Optional for creating a notification -->
<!--
<section class="jumbotron text-center">
<div class="container">
<h1 class="jumbotron-heading">Album example</h1>
<p class="lead text-muted">Something short and leading about the collection below—its contents, the creator, etc. Make it short and sweet, but not too short so folks dont simply skip over it entirely.</p>
<p>
<a href="#" class="btn btn-primary my-2">Main call to action</a>
<a href="#" class="btn btn-secondary my-2">Secondary action</a>
</p>
</div>
</section>
-->
<div class="album py-4 bg-dark">
<div class="container">
<div class="row">
{{THUMBROW}}
</div>
</div>
</div>
</main>
<footer class="text-muted">
<div class="container">
<p class="float-right"><a href="#">Back to top</a></p>
<p><a href="https://github.com/alopexc0de/simple-s3-gallery"></a>Simple S3 Gallery</a> &copy; 2019 <a href="https://c0defox.es">David Todd</a> - All photos are &copy; David Todd</p>
</div>
</footer>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>

View File

@@ -1,137 +0,0 @@
<html>
<head>
<title>Simple S3 Gallery</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="David Todd" />
<link rel="icon" type="image/png" href="https://secure.gravatar.com/avatar/1e346a54257cf0a9932fcfc1e61c015d" />
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<style>
.bg-dark {
background-color: #343a40cc !important;
}
nav.bcrumb {
margin-left: 1rem;
margin-top: 0.5rem;
}
.jumbotron {
padding-top: 3rem;
padding-bottom: 3rem;
margin-bottom: 0;
background-color: #fff;
}
@media (min-width: 768px) {
.jumbotron {
padding-top: 6rem;
padding-bottom: 6rem;
}
}
.jumbotron p:last-child {
margin-bottom: 0;
}
.jumbotron-heading {
font-weight: 300;
}
.jumbotron .container {
max-width: 40rem;
}
.card-header {
text-align: center;
padding: 0.25rem 0rem;
}
footer {
padding-top: 3rem;
padding-bottom: 3rem;
}
footer p {
margin-bottom: .25rem;
}
</style>
</head>
<body>
<header>
<div class="collapse bg-dark" id="navbarHeader">
<div class="container">
<div class="row">
<div class="col-sm-8 col-md-7 py-4">
<h4 class="text-white">About</h4>
<p class="text-white">This is a small gallery to represent images that I have taken over the past few years. Most of these are unsorted and unedited, and thus a lot are blurry or have lighting issues. I have taken, and thereby own all photos on this site.</p>
</div>
<div class="col-sm-4 offset-md-1 py-4">
<h4 class="text-white">Contact</h4>
<ul class="list-unstyled">
<li><a href="https://c0defox.es" class="text-white">My contact site</a></li>
<li><a href="https://t.me/c0defox" class="text-white">Hit me up on Telegram</a></li>
<li><a href="c0de#0689" class="text-white">My Discord is c0de#0689</a></li>
</ul>
</div>
</div>
</div>
</div>
<div class="navbar navbar-dark bg-dark shadow-sm">
<div class="container d-flex justify-content-between">
<span class="navbar-brand d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" aria-hidden="true" class="mr-2" viewBox="0 0 24 24" focusable="false"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
<strong>Simple S3 Gallery</strong>
<nav class="text-dark bcrumb" aria-label="breadcrumb">
<ol class="breadcrumb">
{{BREADCRUMBS}}
</ol>
</nav>
</span>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
</header>
<main role="main">
<!-- Optional for creating a notification -->
<!--
<section class="jumbotron text-center">
<div class="container">
<h1 class="jumbotron-heading">Album example</h1>
<p class="lead text-muted">Something short and leading about the collection below—its contents, the creator, etc. Make it short and sweet, but not too short so folks dont simply skip over it entirely.</p>
<p>
<a href="#" class="btn btn-primary my-2">Main call to action</a>
<a href="#" class="btn btn-secondary my-2">Secondary action</a>
</p>
</div>
</section>
-->
<div class="album py-3 bg-dark">
<div class="container">
<div class="row">
{{THUMBROW}}
</div>
</div>
</div>
</main>
<footer class="text-muted">
<div class="container">
<p class="float-right"><a href="#">Back to top</a></p>
<p><a href="https://github.com/alopexc0de/simple-s3-gallery">Simple S3 Gallery</a> &copy; 2019 <a href="https://c0defox.es">David Todd</a> - All photos are &copy; David Todd</p>
</div>
</footer>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>

106
test.py Normal file
View File

@@ -0,0 +1,106 @@
#!/usr/bin/python3
"""
test template rendering
python3 test.py | tee test.html
python3 -m http.server
"""
from jinja2 import Environment, FileSystemLoader, select_autoescape
template_vars = {
"charset": "utf-8",
"language": "en",
"css_theme_name": "auto",
"canonical_url": "http://example.com",
"page_title": "This is a title",
"theme": "dark",
"text_theme": "white",
"static": {
"scripts": {
"bootstrap": {
"src": "./templates/example/bootstrap.bundle.min.js",
},
"theme": {"src": "./templates/example/color-modes.js"},
},
"css": {
"bootstrap": {"src": "./templates/example/bootstrap.min.css"},
"theme": {"src": "./templates/example/gallery.css"},
"icons": {
"src": "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.min.css"
},
},
},
"meta_list": [
{"name": "description", "content": "This is a description"},
{"name": "generator", "content": "simple-s3-gallery v.2023.12"},
{"name": "author", "content": "Code Fox"},
{"name": "theme-color", "content": "#712cf9"},
],
"left_header": "About the gallery",
"left_text": "This is an example gallery that is generated via a template",
"right_header": "Contact",
"link_list": [
{"href": "https://c0defox.es", "text": "Fox :3"},
{"href": "https://furry.engineer/c0de", "text": "Mastodon", "icon": "mastodon"},
],
"footer": {
"main_line": "Copyright 2024 Code Fox",
"extra_lines": ["This is another line", "This is yet another line"],
},
"call_to_action": {
"active": True,
"header": "This is a call to action",
"lead_text": "Some interesting text for the user",
"buttons": [
{"href": "1"},
{"href": "2", "theme": "danger"},
{"href": "3", "theme": "warning", "icon": "exclamation-diamond-fill"},
{
"href": "3",
"theme": "warning",
"icon": "exclamation-diamond-fill",
"text": "some text",
},
],
},
"gallery": {
"max_reactions_per_card": 10,
},
"gallery_items": [
{
"src": "https://files.c0defox.es/Pictures/arctic-fox.jpg",
"description": "An arctic fox :3",
"title": "fox",
"reactions": {"heart-fill":4, "backpack4":1, "balloon-fill":45, "bag-x-fill":0},
},
{
"src": "https://files.c0defox.es/Pictures/arctic-fox.jpg",
"description": "An arctic fox :3",
"title": "fox",
"reactions": {"heart-fill":1024, "bag-x-fill":50},
},
{
"src": "https://files.c0defox.es/Pictures/arctic-fox.jpg",
"description": "An arctic fox :3",
"title": "fox",
},
],
}
def main():
"""main method"""
env = Environment(
loader=FileSystemLoader("templates"),
autoescape=select_autoescape(),
trim_blocks=True,
lstrip_blocks=True,
)
template = env.get_template("base.html")
print(template.render(**template_vars))
if __name__ == "__main__":
main()