Просмотр исходного кода

Define a new custom theme to match larlet.fr/david/

master
David Larlet 2 лет назад
Родитель
Сommit
6f3e3feabd
14 измененных файлов: 2485 добавлений и 0 удалений
  1. 2
    0
      .gitignore
  2. 41
    0
      theme/base.html.j2
  3. 45
    0
      theme/index.html.j2
  4. 158
    0
      theme/media.html.j2
  5. 6
    0
      theme/root/about.txt
  6. Двоичные данные
      theme/root/android-chrome-192x192.png
  7. Двоичные данные
      theme/root/android-chrome-512x512.png
  8. Двоичные данные
      theme/root/apple-touch-icon.png
  9. Двоичные данные
      theme/root/favicon-16x16.png
  10. Двоичные данные
      theme/root/favicon-32x32.png
  11. Двоичные данные
      theme/root/favicon.ico
  12. 1
    0
      theme/root/site.webmanifest
  13. 1944
    0
      theme/scripts/stimulus-3.0.1.js
  14. 288
    0
      theme/style/main.css

+ 2
- 0
.gitignore Просмотреть файл

@@ -1,7 +1,9 @@
/output
/.env
/theme/style/fonts

__pycache__

*.JPG
*.jpg
*.yml

+ 41
- 0
theme/base.html.j2 Просмотреть файл

@@ -0,0 +1,41 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="{% block lang %}fr{% endblock lang %}">
<head>
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>{% block title %}{% endblock %} — David Larlet</title>
<!-- Source : https://favicon.io/emoji-favicons/camera -->
<!-- The emoji graphics are from the open source project Twemoji.
The graphics are copyright 2020 Twitter, Inc and other contributors.
The graphics are licensed under CC-BY 4.0. -->
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
<link rel="manifest" href="/site.webmanifest">
<link rel="stylesheet" href="style/main.css">
{% block extra_head %}{% endblock %}
</head>
<body>
<main>
<div class="container">
{% block container %}{% endblock %}
</div>
</main>
<footer>
<hr>
<p class="u-center">
&copy;
<a href="https://larlet.fr/david/" title="Site principal">David Larlet</a>
-
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel">Demandez pour une réutilisation</a>, ça me permettra de vous fournir une meilleure qualité 🤗.
</p>
</footer>
{% block extra_bottom %}{% endblock %}
</body>

+ 45
- 0
theme/index.html.j2 Просмотреть файл

@@ -0,0 +1,45 @@
{% extends "base.html.j2" %}

{% block title %}Photos & vidéos{% endblock %}

{% block extra_head %}
<!-- CanIHazMoreComplexityPlease? https://htmlhead.dev/ -->
<meta
name="twitter:image" property="og:image" itemprop="image"
content="https://media.larlet.fr/2021--paysages/jpg/15_660x440.jpg"
>
{% endblock %}

{% block container %}
<div class="galleries">
{% for gallery in galleries -%}
{% if not gallery.private %}
<div class="gallery-cover">
<a href="{{ gallery.cover_photo.page_url }}">
<picture>
<source
srcset="
{%- for size in sizes %}
{{ gallery.cover_photo.gallery_slug }}/webp/{{ gallery.cover_photo.name }}_{{ size.0 }}x{{ size.1 }}.webp {{ size.0 }}w{% if not loop.last%},{% endif %}
{%- endfor -%}
"
sizes="min((100vw - 2rem), 330px)"
type="image/webp">
<img
src="{{ gallery.cover_photo.gallery_slug }}/jpg/{{ gallery.cover_photo.name }}_{{ sizes.0.0 }}x{{ sizes.0.1 }}.jpg"
width="{{ gallery.cover_photo.width }}" height="{{ gallery.cover_photo.height }}"
srcset="
{%- for size in sizes %}
{{ gallery.cover_photo.gallery_slug }}/jpg/{{ gallery.cover_photo.name }}_{{ size.0 }}x{{ size.1 }}.jpg {{ size.0 }}w{% if not loop.last%},{% endif %}
{%- endfor -%}
"
sizes="min((100vw - 2rem), 330px)"
alt="TODO" loading="lazy" decoding="async">
<figcaption>{{ gallery.name }}</figcaption>
</picture>
</a>
</div>
{% endif %}
{% endfor %}
</div>
{% endblock %}

+ 158
- 0
theme/media.html.j2 Просмотреть файл

@@ -0,0 +1,158 @@
{% extends "base.html.j2" %}

{% block title %}{{ gallery.name }}{% endblock %}

{% block extra_head %}
<!-- CanIHazMoreComplexityPlease? https://htmlhead.dev/ -->
<meta
name="twitter:image" property="og:image" itemprop="image"
content="https://media.larlet.fr/{{ photo.gallery_slug }}/jpg/{{ photo.name }}_{{ sizes.0.0 }}x{{ sizes.0.1 }}.jpg"
>
{% endblock %}

{% block container %}
<div class="hero u-center">
<picture>
<source
srcset="
{%- for size in sizes %}
{{ photo.gallery_slug }}/webp/{{ photo.name }}_{{ size.0 }}x{{ size.1 }}.webp {{ size.0 }}w{% if not loop.last%},{% endif %}
{%- endfor -%}
"
sizes="min(100vw, calc(100vh * {{ photo.width }} / {{ photo.height }}))"
type="image/webp">
<img
src="{{ photo.gallery_slug }}/jpg/{{ photo.name }}_{{ sizes.0.0 }}x{{ sizes.0.1 }}.jpg"
width="{{ photo.width }}" height="{{ photo.height }}"
srcset="
{%- for size in sizes %}
{{ photo.gallery_slug }}/jpg/{{ photo.name }}_{{ size.0 }}x{{ size.1 }}.jpg {{ size.0 }}w{% if not loop.last%},{% endif %}
{%- endfor -%}
"
sizes="min(100vw, calc(100vh * {{ photo.width }} / {{ photo.height }}))"
alt="TODO">
</picture>
</div>

<h1>{{ gallery.name }}{% if gallery.private %} (🔒 privé){% endif %}</h1>

<nav>
<p class="u-center">
{% if previous %}
<a href="{{ previous.page_url }}"
title="Photo précédente, vous pouvez utiliser la flèche du clavier ←"
>← Photo précédente</a>
{% endif %}
<a href="/"
title="Retour à l’accueil, vous pouvez utiliser la flèche du clavier ↑"
>↑ Retour aux albums{% if gallery.private %} publics{% endif %}</a>
{% if next %}
<a href="{{ next.page_url }}"
title="Photo suivante, vous pouvez utiliser la flèche du clavier →"
>Photo suivante →</a>
{% endif %}
</p>
</nav>

{# TODO: less manual! #}
{% if gallery.type == "video" %}
<div class="u-center">
<div class="iframe-container"><iframe src="https://player.vimeo.com/video/580086949?h=0833bc929c" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div>
<p><a href="https://vimeo.com/580086949/0833bc929c">Évasion (lire sur Vimeo)</a></p>
<hr>
<div class="iframe-container"><iframe src="https://player.vimeo.com/video/540447287?h=323e810be3" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div>
<p><a href="https://vimeo.com/540447287/323e810be3">Contemplation (lire sur Vimeo)</a></p>
<hr>
<div class="iframe-container"><iframe src="https://player.vimeo.com/video/516515235?h=45826baa92" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div>
<p><a href="https://vimeo.com/516515235/45826baa92">Précipitation (lire sur Vimeo)</a></p>
<hr>
<div class="iframe-container"><iframe src="https://player.vimeo.com/video/492686199?h=31ac11260c" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div>
<p><a href="https://vimeo.com/492686199/31ac11260c">Arrakice (lire sur Vimeo)</a></p>
<hr>
<div class="iframe-container"><iframe src="https://player.vimeo.com/video/473661570?h=46af2e921e" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen></iframe></div>
<p><a href="https://vimeo.com/473661570/46af2e921e">Chaos (lire sur Vimeo)</a></p>
</div>
{% endif %}
<div class="gallery">
{% for gallery_photo in gallery.photos %}
{% if not gallery_photo.url == photo.url %}
<div class="photo{% if gallery_photo.narrow %} narrow{% endif %}{% if gallery_photo.wide %} wide{% endif %}">
<a href="{{ gallery_photo.page_url }}">
<picture>
<source
srcset="
{%- for size in sizes %}
{{ gallery_photo.gallery_slug }}/webp/{{ gallery_photo.name }}_{{ size.0 }}x{{ size.1 }}.webp {{ size.0 }}w{% if not loop.last%},{% endif %}
{%- endfor -%}
"
sizes="{% if gallery_photo.narrow %}150px{% else %}310px{% endif %}"
type="image/webp">
<img
src="{{ gallery_photo.gallery_slug }}/jpg/{{ gallery_photo.name }}_{{ sizes.0.0 }}x{{ sizes.0.1 }}.jpg"
width="{{ gallery_photo.width }}" height="{{ gallery_photo.height }}"
srcset="
{%- for size in sizes %}
{{ gallery_photo.gallery_slug }}/jpg/{{ gallery_photo.name }}_{{ size.0 }}x{{ size.1 }}.jpg {{ size.0 }}w{% if not loop.last%},{% endif %}
{%- endfor -%}
"
sizes="{% if gallery_photo.narrow %}150px{% else %}310px{% endif %}"
alt="TODO" loading="lazy" decoding="async">
</picture>
</a>
</div>
{% endif %}
{% endfor %}
</div>
<nav>
<p class="u-center"
data-controller="navigation"
data-action="keydown@window->navigation#navigate"
>
{% if previous %}
<a href="{{ previous.page_url }}"
title="Photo précédente, vous pouvez utiliser la flèche du clavier ←"
data-navigation-target="previous"
>← Photo précédente</a>
{% endif %}
<a href="/"
title="Retour à l’accueil, vous pouvez utiliser la flèche du clavier ↑"
data-navigation-target="up"
>↑ Retour aux albums{% if gallery.private %} publics{% endif %}</a>
{% if next %}
<a href="{{ next.page_url }}"
title="Photo suivante, vous pouvez utiliser la flèche du clavier →"
data-navigation-target="next"
>Photo suivante →</a>
{% endif %}
</p>
</nav>
{% endblock %}

{% block extra_bottom %}
<script type="module">
import { Application, Controller } from "/scripts/stimulus-3.0.1.js"
window.Stimulus = Application.start()
// window.Stimulus.debug = true

Stimulus.register("navigation", class extends Controller {
static targets = [ "previous", "next", "up" ]

navigate(event) {
const key = event.key
if (key === "ArrowLeft" && this.hasPreviousTarget) {
this.previousTarget.click()
}
if (key === "ArrowRight" && this.hasNextTarget) {
this.nextTarget.click()
}
if (key === "ArrowUp" && this.hasUpTarget) {
this.upTarget.click()
}
}
})
</script>
{% endblock %}

+ 6
- 0
theme/root/about.txt Просмотреть файл

@@ -0,0 +1,6 @@
This favicon was generated using the following graphics from Twitter Twemoji:

- Graphics Title: 1f4f7.svg
- Graphics Author: Copyright 2020 Twitter, Inc and other contributors (https://github.com/twitter/twemoji)
- Graphics Source: https://github.com/twitter/twemoji/blob/master/assets/svg/1f4f7.svg
- Graphics License: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)

Двоичные данные
theme/root/android-chrome-192x192.png Просмотреть файл


Двоичные данные
theme/root/android-chrome-512x512.png Просмотреть файл


Двоичные данные
theme/root/apple-touch-icon.png Просмотреть файл


Двоичные данные
theme/root/favicon-16x16.png Просмотреть файл


Двоичные данные
theme/root/favicon-32x32.png Просмотреть файл


Двоичные данные
theme/root/favicon.ico Просмотреть файл


+ 1
- 0
theme/root/site.webmanifest Просмотреть файл

@@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#f7f7f7","background_color":"#f7f7f7","display":"standalone"}

+ 1944
- 0
theme/scripts/stimulus-3.0.1.js
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 288
- 0
theme/style/main.css Просмотреть файл

@@ -0,0 +1,288 @@
/* Section polices */

/* Fonts definition, a different font is in use between light and dark mode
in order to improve the readability of the text. */
@font-face {
font-family: 'triplicate_t4p';
src: url('fonts/triplicate_t4_poly_regular.woff2') format('woff2'),
url('fonts/triplicate_t4_poly_regular.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'triplicate_t4p';
src: url('fonts/triplicate_t4_poly_bold.woff2') format('woff2'),
url('fonts/triplicate_t4_poly_bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'triplicate_t4p';
src: url('fonts/triplicate_t4_poly_italic.woff2') format('woff2'),
url('fonts/triplicate_t4_poly_italic.woff') format('woff');
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: 'triplicate_t3';
src: url('fonts/triplicate_t3_regular.woff2') format('woff2'),
url('fonts/triplicate_t3_regular.woff') format('woff');
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'triplicate_t3';
src: url('fonts/triplicate_t3_bold.woff2') format('woff2'),
url('fonts/triplicate_t3_bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'triplicate_t3';
src: url('fonts/triplicate_t3_italic.woff2') format('woff2'),
url('fonts/triplicate_t3_italic.woff') format('woff');
font-weight: normal;
font-style: italic;
font-display: swap;
}

* {
box-sizing: border-box;
}

:root:not(.forced-dark),
.forced-light {
/* This tells the browser which color themes my app supports
See https://web.dev/prefers-color-scheme/#stylesheet-architecture */
color-scheme: light dark;

/* For a smooth transition between light/dark modes
See https://web.dev/prefers-color-scheme/#smooth-transitions-between-modes */
--duration: 0.5s;
--timing: ease;

--font-family: 'triplicate_t4p', Courier, Menlo, Monaco, 'DejaVu Sans Mono', Consolas, monospace;
--background-color: #f7f7f7;
--text-color: #07486c;
--remarkdown-color: SteelBlue;
--link-color: RoyalBlue;
--link-visited-color: RebeccaPurple;
--link-hover-color: var(--background-color);
--link-hover-background-color: var(--link-color);
--image-filter: none;
--target-after-color: #07486c;
--mark-background: LightGoldenRodYellow;
}
@media (prefers-color-scheme: dark) {
:root:not(.forced-light),
.forced-dark {
--font-family: 'triplicate_t3', 'Courier New', Menlo, Monaco, 'DejaVu Sans Mono', Consolas, monospace;
--background-color: #272727;
--text-color: Linen;
--remarkdown-color: Orange;
--link-color: #ffff2b;
--link-visited-color: Khaki;
--link-hover-color: var(--background-color);
--link-hover-background-color: var(--link-visited-color);
--image-filter: grayscale(.5) brightness(.8) contrast(1.2);
--target-after-color: DarkOrange;
--mark-background: Orange;
}
}

html {
/* Applying it to the html element will provide smooth scrolling to anchors
https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior */
scroll-behavior: smooth;
/* Only supported by Firefox, how fun? */
scrollbar-color: var(--background-color) var(--target-after-color);
}

/* General stuff. */
body {
margin: 0 auto;
padding: 0 .5rem;
font-family: var(--font-family);
background-color: var(--background-color);
color: var(--text-color);
transition:
color var(--duration) var(--timing),
background-color var(--duration) var(--timing);
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
}

a {
color: var(--text-color);
}

h1 {
margin-top: 0;
text-align: center;
word-wrap: break-word;
margin-bottom: 1.75rem;
font-size: 2rem;
line-height: 2.5rem;
}

img {
max-width: 100%;
max-height: 100%;
max-inline-size: 100%;
block-size: auto;
}
figcaption {
text-align: center;
}

hr {
height: 1.5em;
line-height: 1.5em;
margin: 1.5em 0 1.5em;
border: none;
color: inherit;
text-align: center;
}

hr::before {
content: "* * * *";
}

.container {
max-width: 70rem;
margin-left: auto;
margin-right: auto;
padding-left: .5rem;
padding-right: .5rem;
}

.galleries {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
margin-top: 1rem;
}

.gallery-cover {
width: 330px;
max-width: 100%;
margin-bottom: 2rem;
margin-right: .5rem;
}

.gallery-cover img {
border-radius: 0.25rem;
}

.photo {
width: 20rem;
max-width: 100%;
margin-right: .5rem;
margin-bottom: 2rem;
}

.hero img {
max-height: 100vh;
width: auto;
}
.u-center {
text-align: center;
}



/* See https://www.benmarshall.me/responsive-iframes/ */
.iframe-container {
overflow: hidden;
/* 16:9 aspect ratio */
padding-top: 56.25%;
position: relative;
}

.iframe-container iframe {
border: 0;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
@media only screen and (max-width: 600px) {
nav a {
display: block;
}
}

/* See https://sylvaindurand.org/masonry-photo-grid-in-pure-css/ */
@media only screen and (min-width: 600px) {
.gallery {
display: flex;
width: 100%;
flex-flow: row wrap;
margin-left: -4px;
}

.gallery div {
overflow: hidden;
margin: 0 0 8px 8px;
flex: auto;
height: 250px;
min-width: 150px;
}

.gallery div:nth-child(8n+1) {
width: 310px;
}

.gallery div:nth-child(8n+2) {
width: 270px;
}

.gallery div:nth-child(8n+3) {
width: 260px;
}

.gallery div:nth-child(8n+4) {
width: 310px;
}

.gallery div:nth-child(8n+5) {
width: 240px;
}

.gallery div:nth-child(8n+6) {
width: 190px;
}

.gallery div:nth-child(8n+7) {
width: 210px;
}

.gallery div:nth-child(8n+8) {
width: 170px;
}

.gallery div.wide {
width: 650px;
}

.gallery div.tall {
width: 650px;
height: 450px;
}

.gallery div.narrow {
width: 120px;
}

.gallery img {
object-fit: cover;
width: 100%;
height: 100%;
}
}

Загрузка…
Отмена
Сохранить