Compare commits

...

3 commits

Author SHA1 Message Date
7b9c07b83e init 2025-10-06 19:21:06 +02:00
2fe0c9a830 Merge commit 'ecdfa2f7c4' as 'temp-repo' 2025-10-06 19:14:58 +02:00
ecdfa2f7c4 Squashed 'temp-repo/' content from commit 6688605
git-subtree-dir: temp-repo
git-subtree-split: 6688605ad41f49d1eccead8d29421c658cad0100
2025-10-06 19:14:58 +02:00
190 changed files with 11476 additions and 0 deletions

View file

@ -0,0 +1,3 @@
# Todo
add recipes from pkb as submodule

39
archetypes/collection.md Executable file
View file

@ -0,0 +1,39 @@
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
draft: true
ShowToc: false
cover:
hidden: false # hide everywhere but not in structured data
hiddenInList: false # hide on list pages and home
hiddenInSingle: true # hide on single page
image: "images/<image>"
alt: "<alt text>"
caption: "<text>"
relative: true # To use relative path for cover image, used in hugo Page-bundles
ShowBreadCrumbs: true
ShowPostNavLinks: true
ShowReadingTime: false
tags:
- <tag>
machineSpecs:
make:
model:
image: "images/<image>"
linkTpdb:
type: ""
dateManufactured:
massKg:
widthCm:
serialNumber:
---
{{< load-photoswipe >}}
{{< figure src="images/20250414_153350_lmc_8.4.jpg" alt="" title="Title">}}
{{< gallery caption-effect="none">}}
{{< figure src="images/xxx" alt_text="" title="" caption="">}}
{{< figure src="images/xxx" alt_text="" title="" caption="">}}
{{< figure src="images/xxx" alt_text="" title="" caption="">}}
{{< /gallery >}}

27
archetypes/default.md Executable file
View file

@ -0,0 +1,27 @@
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
draft: true
ShowToc: false
cover:
hidden: false # hide everywhere but not in structured data
hiddenInList: false # hide on list pages and home
hiddenInSingle: true # hide on single page
image: "images/<image.jpg>"
alt: "<alt text>"
caption: "<text>"
relative: true # To use relative path for cover image, used in hugo Page-bundles
ShowBreadCrumbs: true
ShowPostNavLinks: true
ShowReadingTime: true
---
{{< load-photoswipe >}}
{{< figure align=center src="images/xxxx" alt="" title="Title">}}
{{< gallery caption-effect="none">}}
{{< figure src="images/" alt_text="" title="" caption="">}}
{{< figure src="images/" alt_text="" title="" caption="">}}
{{< figure src="images/" alt_text="" title="" caption="">}}
{{< /gallery >}}

26
archetypes/livres.md Executable file
View file

@ -0,0 +1,26 @@
---
title: '{{ replace .File.ContentBaseName "-" " " | title }}'
date: '{{ .Date }}'
draft: true
ShowToc: false
cover:
hidden: false # hide everywhere but not in structured data
hiddenInList: false # hide on list pages and home
hiddenInSingle: true # hide on single page
image: "images/cover.jpg"
alt: "Couverture du livre"
relative: true # To use relative path for cover image, used in hugo Page-bundles
ShowBreadCrumbs: true
ShowPostNavLinks: true
ShowReadingTime: true
tags:
- test
BookData:
title: ""
author: "T"
ISBN: ""
publishDate: "2"
worldCat : ""
starGrade:
cover : ""
---

11
assets/css/common/404.css Executable file
View file

@ -0,0 +1,11 @@
.not-found {
position: absolute;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
height: 80%;
font-size: 160px;
font-weight: 700;
}

36
assets/css/common/archive.css Executable file
View file

@ -0,0 +1,36 @@
.archive-posts {
width: 100%;
font-size: 16px;
}
.archive-year {
margin-top: 40px;
}
.archive-year:not(:last-of-type) {
border-bottom: 2px solid var(--border);
}
.archive-month {
display: flex;
align-items: flex-start;
padding: 10px 0;
}
.archive-month-header {
margin: 25px 0;
width: 200px;
}
.archive-month:not(:last-of-type) {
border-bottom: 1px solid var(--border);
}
.archive-entry {
position: relative;
padding: 5px;
margin: 10px 0;
}
.archive-entry-title {
margin: 5px 0;
font-weight: 400;
}
.archive-count,
.archive-meta {
color: var(--secondary);
font-size: 14px;
}

51
assets/css/common/footer.css Executable file
View file

@ -0,0 +1,51 @@
.footer,
.top-link {
font-size: 12px;
color: var(--secondary);
}
.footer {
max-width: calc(var(--main-width) + var(--gap) * 2);
margin: auto;
padding: calc((var(--footer-height) - var(--gap)) / 2) var(--gap);
text-align: center;
line-height: 24px;
}
.footer span {
margin-inline-start: 1px;
margin-inline-end: 1px;
}
.footer span:last-child {
white-space: nowrap;
}
.footer a {
color: inherit;
border-bottom: 1px solid var(--secondary);
}
.footer a:hover {
border-bottom: 1px solid var(--primary);
}
.top-link {
visibility: hidden;
position: fixed;
bottom: 60px;
right: 30px;
z-index: 99;
background: var(--tertiary);
width: 42px;
height: 42px;
padding: 12px;
border-radius: 64px;
transition: visibility 0.5s, opacity 0.8s linear;
}
.top-link,
.top-link svg {
filter: drop-shadow(0px 0px 0px var(--theme));
}
.footer a:hover,
.top-link:hover {
color: var(--primary);
}
.top-link:focus,
#theme-toggle:focus {
outline: 0;
}

203
assets/css/common/header.css Executable file
View file

@ -0,0 +1,203 @@
.nav {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
max-width: calc(var(--nav-width) + var(--gap) * 2);
margin-inline-start: auto;
margin-inline-end: auto;
line-height: var(--header-height);
}
.nav a {
display: block;
}
.logo,
#menu {
display: flex;
margin: auto var(--gap);
}
.logo {
flex-wrap: inherit;
}
.logo a {
font-size: 30px;
font-weight: 700;
}
.logo a img, .logo a svg {
display: inline;
vertical-align: middle;
pointer-events: none;
border-radius: 0px;
margin-inline-end: 8px;
margin: 0 0 0 10px;
height: 40px;
}
button.theme-toggle-button {
font-size: 26px;
margin: auto 4px;
cursor: pointer;
}
body.dark .moon-icon {
vertical-align: middle;
display: none;
}
body:not(.dark) .sun-icon {
display: none;
}
.lang-switch li,
.lang-switch ul,
.logo-switches {
display: inline-flex;
margin: auto 4px;
}
.lang-switch {
display: flex;
flex-wrap: inherit;
}
.lang-switch a {
margin: auto 3px;
font-size: 16px;
font-weight: 500;
}
.logo-switches {
flex-wrap: inherit;
}
/* Menu */
.menu {
display: flex;
flex-wrap: wrap;
list-style: none;
margin: 20px 0 0;
padding: 0;
justify-content: flex-end;
}
.menu li {
margin: 0 10px;
display: inline-flex;
align-items: center;
}
.menu li a {
text-decoration: none;
display: flex;
flex-direction: column;
align-items: center;
line-height: 1; /* Reduce line height */
}
.menu .icon {
border-radius: 0;
margin: 5px; /* Remove all margins */
}
.menu li a span {
margin-top: 0px;
padding-top: 0;
}
.menu li a:hover {
text-decoration: underline;
}
.mobile-menu .menu {
flex-direction: column;
align-items: left;
justify-content: left;
}
.mobile-menu .menu li {
margin: 0 0 0 0;
font-size: 1.2em;
}
.mobile-menu-close {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
color: var(--primary);
}
/* Hamburger Menu */
.hamburger-menu {
display: none; /* Hidden by default on desktop */
cursor: pointer;
position: absolute;
right: 20px;
top: 20px;
}
/* The toggle checkbox (hidden) */
#menu-toggle {
display: none;
}
/* Menu overlay styles */
.menu-overlay {
display: none; /* Hidden by default */
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8);
z-index: 999;
opacity: 0;
transition: opacity 0.3s ease;
}
/* When checkbox is checked, show the menu overlay with animation */
#menu-toggle:checked ~ .menu-overlay {
display: block;
opacity: 1;
}
/* Mobile menu styling */
.mobile-menu {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 85%;
max-width: 300px;
background-color: var(--entry, white);
padding: 30px 20px;
border-radius: 8px;
z-index: 1000;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
}
/* Mobile menu items */
.mobile-menu .menu {
display: flex;
flex-direction: column;
align-items: left;
}
.mobile-menu .menu li {
flex-direction: row;
margin: 10px 0;
font-size: 1.2rem;
}
.mobile-menu .menu li a {
flex-direction: row;
align-items: center;
}
.mobile-menu .menu li a .icon {
margin-right: 10px;
}
/* Mobile breakpoint */
@media (max-width: 700px) {
.hamburger-menu {
display: block;
}
/* Hide the regular menu */
.nav .menu-wrapper {
display: none;
}
/* Make sure the header positions correctly for the hamburger icon */
.header {
position: relative;
padding-right: 50px; /* Make room for hamburger icon */
}
/* Ensure the logo area does not overflow */
.logo {
max-width: calc(100% - 60px);
}
}

55
assets/css/common/main.css Executable file
View file

@ -0,0 +1,55 @@
.main {
position: relative;
min-height: calc(100vh - var(--header-height) - var(--footer-height));
max-width: calc(var(--main-width) + var(--gap) * 2);
margin: auto;
padding: var(--gap);
}
.page-header h1 {
font-size: 40px;
}
.pagination {
display: flex;
}
.pagination a {
color: var(--theme);
font-size: 13px;
line-height: 36px;
background: var(--primary);
border-radius: calc(36px / 2);
padding: 0 16px;
}
.pagination .next {
margin-inline-start: auto;
}
.social-icons a {
display: inline-flex;
padding: 10px;
}
.social-icons a svg {
height: 26px;
width: 26px;
}
code {
direction: ltr;
}
div.highlight,
pre {
position: relative;
}
.copy-code {
display: none;
position: absolute;
top: 4px;
right: 4px;
color: rgba(255, 255, 255, 0.8);
background: rgba(78, 78, 78, 0.8);
border-radius: var(--radius);
padding: 0 5px;
font-size: 14px;
user-select: none;
}
div.highlight:hover .copy-code,
pre:hover .copy-code {
display: block;
}

View file

@ -0,0 +1,91 @@
.first-entry {
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
min-height: 320px;
margin: var(--gap) 0 calc(var(--gap) * 2) 0;
}
.first-entry .entry-header {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
}
.first-entry .entry-header h1 {
font-size: 34px;
line-height: 1.3;
}
.first-entry .entry-content {
margin: 14px 0;
font-size: 16px;
-webkit-line-clamp: 3;
}
.first-entry .entry-footer {
font-size: 14px;
}
.home-info .entry-content {
-webkit-line-clamp: unset;
}
.post-entry {
position: relative;
margin-bottom: var(--gap);
padding: var(--gap);
background: var(--entry);
border-radius: var(--radius);
transition: transform 0.1s;
border: 1px solid var(--border);
}
.post-entry:active {
transform: scale(0.96);
}
.tag-entry .entry-cover {
display: flex;
}
/* changed "none" to "flex" : cf https://github.com/adityatelange/hugo-PaperMod/discussions/631 */
.entry-header h2 {
font-size: 24px;
line-height: 1.3;
}
.entry-content {
margin: 8px 0;
color: var(--secondary);
font-size: 14px;
line-height: 1.6;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.entry-footer {
color: var(--secondary);
font-size: 13px;
}
.entry-link {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.entry-hint {
color: var(--secondary);
}
.entry-hint-parent {
display: flex;
justify-content: space-between;
}
.entry-cover {
font-size: 14px;
margin-bottom: var(--gap);
text-align: center;
}
.entry-cover img {
border-radius: var(--radius);
width: 100%;
height: auto;
}
.entry-cover a {
color: var(--secondary);
box-shadow: 0 1px 0 var(--primary);
}

337
assets/css/common/post-single.css Executable file
View file

@ -0,0 +1,337 @@
.page-header,
.post-header {
margin: 24px auto var(--content-gap) auto;
}
.post-title {
margin-bottom: 2px;
font-size: 40px;
}
.post-description {
margin-top: 10px;
margin-bottom: 5px;
}
.post-meta,
.breadcrumbs {
color: var(--secondary);
font-size: 14px;
display: flex;
flex-wrap: wrap;
}
.post-meta .i18n_list li {
display: inline-flex;
list-style: none;
margin: auto 3px;
box-shadow: 0 1px 0 var(--secondary);
}
.breadcrumbs a {
font-size: 16px;
}
.post-content {
color: var(--content);
}
.post-content h3,
.post-content h4,
.post-content h5,
.post-content h6 {
margin: 24px 0 16px;
}
.post-content h1 {
margin: 40px auto 32px;
font-size: 40px;
}
.post-content h2 {
margin: 32px auto 24px;
font-size: 32px;
}
.post-content h3 {
font-size: 24px;
}
.post-content h4 {
font-size: 16px;
}
.post-content h5 {
font-size: 14px;
}
.post-content h6 {
font-size: 12px;
}
.post-content a,
.toc a:hover {
box-shadow: 0 1px 0;
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
}
.post-content a code {
margin: auto 0;
border-radius: 0;
box-shadow: 0 -1px 0 var(--primary) inset;
}
.post-content del {
text-decoration: line-through;
}
.post-content dl,
.post-content ol,
.post-content p,
.post-content figure,
.post-content ul {
margin-bottom: var(--content-gap);
}
.post-content ol,
.post-content ul {
padding-inline-start: 20px;
}
.post-content li {
margin-top: 5px;
}
.post-content li p {
margin-bottom: 0;
}
.post-content dl {
display: flex;
flex-wrap: wrap;
margin: 0;
}
.post-content dt {
width: 25%;
font-weight: 700;
}
.post-content dd {
width: 75%;
margin-inline-start: 0;
padding-inline-start: 10px;
}
.post-content dd ~ dd,
.post-content dt ~ dt {
margin-top: 10px;
}
.post-content table {
margin-bottom: var(--content-gap);
}
.post-content table th,
.post-content table:not(.highlighttable, .highlight table, .gist .highlight) td {
min-width: 80px;
padding: 8px 5px;
line-height: 1.5;
border-bottom: 1px solid var(--border);
}
.post-content table th {
text-align: start;
}
.post-content table:not(.highlighttable) td code:only-child {
margin: auto 0;
}
.post-content .highlight table {
border-radius: var(--radius);
}
.post-content .highlight:not(table) {
margin: 10px auto;
background: var(--code-block-bg) !important;
border-radius: var(--radius);
direction: ltr;
}
.post-content li > .highlight {
margin-inline-end: 0;
}
.post-content ul pre {
margin-inline-start: calc(var(--gap) * -2);
}
.post-content .highlight pre {
margin: 0;
}
.post-content .highlighttable {
table-layout: fixed;
}
.post-content .highlighttable td:first-child {
width: 40px;
}
.post-content .highlighttable td .linenodiv {
padding-inline-end: 0 !important;
}
.post-content .highlighttable td .highlight,
.post-content .highlighttable td .linenodiv pre {
margin-bottom: 0;
}
.post-content code {
margin: auto 4px;
padding: 4px 6px;
font-size: 0.78em;
line-height: 1.5;
background: var(--code-bg);
border-radius: 2px;
}
.post-content pre code {
display: grid;
margin: auto 0;
padding: 10px;
color: rgb(213, 213, 214);
background: var(--code-block-bg) !important;
border-radius: var(--radius);
overflow-x: auto;
word-break: break-all;
}
.post-content blockquote {
margin: 20px 0;
padding: 0 14px;
border-inline-start: 3px solid var(--primary);
}
.post-content hr {
margin: 30px 0;
height: 2px;
background: var(--tertiary);
border: 0;
}
.post-content iframe {
max-width: 100%;
}
.post-content img {
border-radius: 4px;
margin: 1rem 0;
}
.post-content img[src*="#center"] {
margin: 1rem auto;
}
.post-content figure.align-center {
text-align: center;
}
/* Removed to use gallery shortcode
.post-content figure > figcaption {
color: var(--primary);
font-size: 16px;
font-weight: bold;
margin: 8px 0 16px;
}
.post-content figure > figcaption > p {
color: var(--secondary);
font-size: 14px;
font-weight: normal;
}
*/
.toc {
margin: 0 2px 40px 2px;
border: 1px solid var(--border);
background: var(--code-bg);
border-radius: var(--radius);
padding: 0.4em;
}
.dark .toc {
background: var(--entry);
}
.toc details summary {
cursor: zoom-in;
margin-inline-start: 10px;
user-select: none;
}
.toc details[open] summary {
cursor: zoom-out;
}
.toc .details {
display: inline;
font-weight: 500;
}
.toc .inner {
margin: 5px 20px 0;
padding: 0 10px;
opacity: 0.9;
}
.toc li ul {
margin-inline-start: var(--gap);
}
.toc summary:focus {
outline: 0;
}
.post-footer {
margin-top: 56px;
}
.post-footer>* {
margin-bottom: 10px;
}
.post-tags {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.post-tags li {
display: inline-block;
}
.post-tags a,
.share-buttons,
.paginav {
border-radius: var(--radius);
background: var(--code-bg);
border: 1px solid var(--border);
}
.post-tags a {
display: block;
padding: 0 14px;
color: var(--secondary);
font-size: 14px;
line-height: 34px;
background: var(--code-bg);
}
.post-tags a:hover,
.paginav a:hover {
background: var(--border);
}
.share-buttons {
padding: 10px;
display: flex;
justify-content: center;
overflow-x: auto;
gap: 10px;
}
.share-buttons li,
.share-buttons a {
display: inline-flex;
}
.share-buttons a:not(:last-of-type) {
margin-inline-end: 12px;
}
h1:hover .anchor,
h2:hover .anchor,
h3:hover .anchor,
h4:hover .anchor,
h5:hover .anchor,
h6:hover .anchor {
display: inline-flex;
color: var(--secondary);
margin-inline-start: 8px;
font-weight: 500;
user-select: none;
}
.paginav {
display: flex;
line-height: 30px;
}
.paginav a {
padding-inline-start: 14px;
padding-inline-end: 14px;
border-radius: var(--radius);
}
.paginav .title {
letter-spacing: 1px;
text-transform: uppercase;
font-size: small;
color: var(--secondary);
}
.paginav .prev,
.paginav .next {
width: 50%;
}
.paginav span:hover:not(.title) {
box-shadow: 0 1px 0;
}
.paginav .next {
margin-inline-start: auto;
text-align: right;
}
[dir="rtl"] .paginav .next {
text-align: left;
}
h1>a>svg {
display: inline;
}
img.in-text {
display: inline;
margin: auto;
}

View file

@ -0,0 +1,36 @@
.buttons,
.main .profile {
display: flex;
justify-content: center;
}
.main .profile {
align-items: center;
min-height: calc(100vh - var(--header-height) - var(--footer-height) - (var(--gap) * 2));
text-align: center;
}
.profile .profile_inner {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
}
.profile img {
border-radius: 50%;
}
.buttons {
flex-wrap: wrap;
max-width: 400px;
}
.button {
background: var(--tertiary);
border-radius: var(--radius);
margin: 8px;
padding: 6px;
transition: transform 0.1s;
}
.button-inner {
padding: 0 8px;
}
.button:active {
transform: scale(0.96);
}

39
assets/css/common/search.css Executable file
View file

@ -0,0 +1,39 @@
#searchbox input {
padding: 4px 10px;
width: 100%;
color: var(--primary);
font-weight: bold;
border: 2px solid var(--tertiary);
border-radius: var(--radius);
}
#searchbox input:focus {
border-color: var(--secondary);
}
#searchResults li {
list-style: none;
border-radius: var(--radius);
padding: 10px;
margin: 10px 0;
position: relative;
font-weight: 500;
}
#searchResults {
margin: 10px 0;
width: 100%;
}
#searchResults li:active {
transition: transform 0.1s;
transform: scale(0.98);
}
#searchResults a {
position: absolute;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
outline: none;
}
#searchResults .focus {
transform: scale(0.98);
border: 2px solid var(--tertiary);
}

16
assets/css/common/terms.css Executable file
View file

@ -0,0 +1,16 @@
.terms-tags li {
display: inline-block;
margin: 10px;
font-weight: 500;
}
.terms-tags a {
display: block;
padding: 3px 10px;
background: var(--tertiary);
border-radius: 6px;
transition: transform 0.1s;
}
.terms-tags a:active {
background: var(--tertiary);
transform: scale(0.96);
}

118
assets/css/core/reset.css Executable file
View file

@ -0,0 +1,118 @@
*,
::after,
::before {
box-sizing: border-box;
}
html {
-webkit-tap-highlight-color: transparent;
overflow-y: scroll;
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
}
a,
button,
body,
h1,
h2,
h3,
h4,
h5,
h6 {
color: var(--primary);
}
body {
font-family: 'tt2020', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 18px;
line-height: 1.6;
word-break: break-word;
background: var(--theme);
}
article,
aside,
figcaption,
figure,
footer,
header,
hgroup,
main,
nav,
section,
table {
display: block;
}
h1,
h2,
h3,
h4,
h5,
h6 {
line-height: 1.2;
}
h1,
h2,
h3,
h4,
h5,
h6,
p {
margin-top: 0;
margin-bottom: 0;
}
ul {
padding: 0;
}
a {
text-decoration: none;
}
body,
figure,
ul {
margin: 0;
}
table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
overflow-x: auto;
word-break: keep-all;
}
button,
input,
textarea {
padding: 0;
font: inherit;
background: 0 0;
border: 0;
}
input,
textarea {
outline: 0;
}
button,
input[type=button],
input[type=submit] {
cursor: pointer;
}
input:-webkit-autofill,
textarea:-webkit-autofill {
box-shadow: 0 0 0 50px var(--theme) inset;
}
img {
display: block;
max-width: 100%;
}

38
assets/css/core/theme-vars.css Executable file
View file

@ -0,0 +1,38 @@
:root {
--gap: 24px;
--content-gap: 20px;
--nav-width: 1024px;
--main-width: 720px;
--header-height: 60px;
--footer-height: 60px;
--radius: 8px;
--theme: rgb(240, 240, 240);
--entry: rgb(255, 255, 255);
--primary: rgb(30, 30, 30);
--secondary: rgb(108, 108, 108);
--tertiary: rgb(214, 214, 214);
--content: rgb(31, 31, 31);
--code-block-bg: rgb(28, 29, 33);
--code-bg: rgb(245, 245, 245);
--border: rgb(238, 238, 238);
}
.dark {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--code-bg);
}
.dark.list {
background: var(--theme);
}

55
assets/css/core/zmedia.css Executable file
View file

@ -0,0 +1,55 @@
@media screen and (max-width: 768px) {
/* theme-vars */
:root {
--gap: 14px;
}
/* profile-mode */
.profile img {
transform: scale(0.85);
}
/* post-entry */
.first-entry {
min-height: 260px;
}
/* archive */
.archive-month {
flex-direction: column;
}
.archive-year {
margin-top: 20px;
}
/* footer */
.footer {
padding: calc((var(--footer-height) - var(--gap) - 10px) / 2) var(--gap);
}
}
/* footer */
@media screen and (max-width: 900px) {
.list .top-link {
transform: translateY(-5rem);
}
}
@media screen and (max-width: 340px) {
.share-buttons {
justify-content: unset;
}
}
@media (prefers-reduced-motion) {
/* terms; profile-mode; post-single; post-entry; post-entry; search; search */
.terms-tags a:active,
.button:active,
.post-entry:active,
.top-link,
#searchResults .focus,
#searchResults li:active {
transform: none;
}
}

5
assets/css/extended/blank.css Executable file
View file

@ -0,0 +1,5 @@
/*
This is just a placeholder blank stylesheet so as to support adding custom styles budled with theme's default styles
Read https://github.com/adityatelange/hugo-PaperMod/wiki/FAQs#bundling-custom-css-with-themes-assets for more info
*/

View file

@ -0,0 +1,27 @@
/* Custom font definition */
@font-face {
font-family: 'tt2020';
src: url('/fonts/TT2020StyleE-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
font-display: swap; /* Improves loading performance */
}
/* Optional: if you have multiple weights/styles */
/*
@font-face {
font-family: 'CustomFont';
src: url('/fonts/your-font-file-bold.woff') format('woff');
font-weight: bold;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'CustomFont';
src: url('/fonts/your-font-file-italic.woff') format('woff');
font-weight: normal;
font-style: italic;
font-display: swap;
}
*/

View file

View file

@ -0,0 +1,78 @@
/* Custom styling for gallery figcaptions */
.gallery figcaption,
.fancy-figure figcaption {
background: rgba(0, 0, 0, 0.5);
color: var(--primary);
padding: 2px 5px;
margin: 0;
text-align: center;
}
/* Style for h4 inside figcaption */
.gallery figcaption h4,
.fancy-figure figcaption h4 {
margin: 0;
padding: 0;
font-size: 0.9em;
color: var(--tertiary);
}
/* Fix for dark mode */
.dark .gallery figcaption h4,
.dark .fancy-figure figcaption h4 {
color: var(--secondary);
}
/* Specific styling for standalone box figures */
.post-content .box:not(.gallery .box) figcaption,
.post-content > figure figcaption {
padding: 2px 5px;
margin: 0;
text-align: center;
background: transparent;
}
/* Specific styling for standalone figure h4 captions (not in a gallery) */
.post-content > figure figcaption h4,
.post-content .box:not(.gallery .box) figcaption h4 {
margin: 0;
padding: 0;
font-size: 0.9em;
color: var(--content);
}
.dark .post-content > figure figcaption h4,
.dark .post-content .box:not(.gallery .box) figcaption h4 {
color: var(--content);
}
/* Override margin for paragraphs inside figcaption */
/* Gallery figcaption paragraphs */
.post-content .gallery figcaption p,
.post-content .fancy-figure figcaption p {
margin: 0;
padding: 0;
font-size: 0.8em;
color: var(--tertiary);
}
/* Standalone figure figcaption paragraphs */
.post-content > figure figcaption p,
.post-content .box:not(.gallery .box) figcaption p {
margin: 0;
padding: 0;
font-size: 0.8em;
color: var(--content);
}
/* Dark mode gallery figcaption paragraphs */
.dark .post-content .gallery figcaption p,
.dark .post-content .fancy-figure figcaption p {
color: var(--secondary);
}
/* Dark mode standalone figure figcaption paragraphs */
.dark .post-content > figure figcaption p,
.dark .post-content .box:not(.gallery .box) figcaption p {
color: var(--content);
}

134
assets/css/extended/home.css Executable file
View file

@ -0,0 +1,134 @@
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center; /* Center the main-screen horizontally */
align-items: stretch; /* Ensure full height */
min-height: 100vh; /* Ensure the body takes up the full viewport height */
}
.main-screen {
display: flex;
flex-direction: row;
justify-content: space-between; /* Ensure side-screens are adjacent to main-content */
width: auto; /* Allow the width to adjust based on content */
max-width: 100%; /* Prevent overflow */
gap: 0;
text-align: left;
}
.side-screen {
height: 100vh;
overflow-y: auto; /* Allow scrolling if content overflows */
flex: 0 0 280; /* Fixed width of 400px */
}
.main-content {
display: flex;
flex-direction: column;
flex-grow: 1; /* Take up the remaining space between side-screens */
max-width: 900px; /* Optional: Limit max width */
margin: 0 25px;
}
.header {
display: flex;
justify-content: space-between; /* Space between the title and navigation */
align-items: center; /* Align items vertically in the center */
width: 100%;
padding-right: 0px; /* Dont make room for hamburger icon since the menu is displayed no matter what */
}
.title-wrapper {
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 20px;
align-items: center;
}
.site-title {
flex-grow: 0;
flex-shrink: 1;
margin: 0;
font-size: 2.5rem;
word-break: normal;
}
.site-logo {
flex-grow: 0; /* Change from 1 to 0 */
flex-shrink: 0;
display: flex;
justify-content: center;
}
.site-logo img {
height: 50px;
}
.navigation {
flex-grow: 3;
display: flex;
}
.presentation, .side-content-column > * {
background-color: var(--entry);
padding: 10px;
border-radius: var(--radius);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.center-content, .side-content-column {
display: flex;
flex-grow: 1; /* Allow it to grow */
gap: 20px; /* Optional: Add spacing between child elements */
}
.presentation, .side-content-column {
flex: 1; /* Make both elements take up equal width */
}
.presentation {
max-width: 100%; /* Ensure it doesn't exceed its container */
}
.presentation a {
text-decoration: underline;
text-decoration-thickness: 1.5px;
text-underline-offset: 3px;
}
.side-content-column {
max-width: 100%; /* Ensure it doesn't exceed its container */
flex-direction: column;
}
.excerpt {
display: flex;
align-items: center; /* Align items vertically in the center */
gap: 10px; /* Add spacing between text and image */
}
.excerpt-text {
flex: 1; /* Allow text to take up remaining space */
}
.excerpt img {
flex-shrink: 0; /* Prevent the image from shrinking */
max-width: 150px; /* Ensure the image doesn't exceed its intended size */
height: auto; /* Maintain aspect ratio */
border-radius: var(--radius);
box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.3);
}
@media (max-width: 1400px) {
.side-screen {
display: none; /* Hide side-screens on smaller screens */
}
.main-screen {
justify-content: center; /* Center main-content when side-screens are hidden */
}
}
/* Media query for when main-content is less than 700px wide */
@media (max-width: 700px) {
.center-content, .header{
flex-direction: column; /* Stack elements vertically */
}
.presentation, .side-content-column, .site-title, .navigation{
flex: none; /* Reset flex property */
width: 100%; /* Make them take full width */
}
.header {
padding: 10px 0; /* Reduce padding on mobile */
}
.title-wrapper {
width: 100%;
justify-content: space-between; /* Change from space-between to flex-start */
}
.site-title {
font-size: 2.5rem; /* Reduce title size on mobile */
max-width: 65%; /* Further limit width on mobile */
}
}

View file

@ -0,0 +1,160 @@
/*
Hugo Easy Gallery - from static/css/hugo-easy-gallery.css
Documentation and licence at https://github.com/liwenyip/hugo-easy-gallery/
*/
/*
Grid Layout Styles
*/
.gallery {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 10px;
max-width: 100%;
}
.gallery .box {
position: relative;
flex: 1 1 calc(33.333% - 10px); /* Default: 3 items per row on PC */
aspect-ratio: 1; /* Maintains square aspect ratio */
min-width: 200px; /* Minimum width before wrapping */
}
/* Responsive breakpoints */
@media (max-width: 768px) {
.gallery .box {
flex: 1 1 calc(50% - 10px); /* 2 items per row on tablets */
}
}
@media (max-width: 480px) {
.gallery .box {
flex: 1 1 100%; /* 1 item per row on mobile */
}
}
/*
Transition styles
*/
.gallery.hover-transition figure,
.gallery.hover-effect-zoom .img,
.gallery:not(.caption-effect-appear) figcaption,
.fancy-figure:not(.caption-effect-appear) figcaption {
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
/*
Figure styles
*/
figure {
position: relative; /* purely to allow absolution positioning of figcaption */
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.gallery figure {
position: absolute;
left: 5px;
right: 5px;
top: 5px;
bottom: 5px;
}
.gallery.hover-effect-grow figure:hover {
transform: scale(1.05);
}
.gallery.hover-effect-shrink figure:hover {
transform: scale(0.95);
}
.gallery.hover-effect-slidedown figure:hover {
transform: translateY(5px);
}
.gallery.hover-effect-slideup figure:hover {
transform: translateY(-5px);
}
/*
img / a styles
*/
.gallery .img {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-size: cover;
background-position: 50% 50%;
background-repeat: no-repeat;
}
.gallery figure {
border-radius: var(--radius);
box-shadow: 0px 3px 5px 0 rgba(0, 0, 0, 0.3);
}
.gallery.hover-effect-zoom figure:hover {
transform: scale(1.03);
}
.gallery img {
display: none; /* only show the img if not inside a gallery */
}
figure a {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
figure img {
box-shadow: 0px 2px 5px 0 rgba(0, 0, 0, 0.3);
}
/*
figcaption styles
*/
.gallery figcaption,
.fancy-figure figcaption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: #000;
color: #FFF;
text-align: center;
font-size: 100%; /* change this if you want bigger text */
background: rgba(0, 0, 0, 0.5);
opacity: 1;
cursor: pointer;
}
.gallery.caption-position-none figcaption,
.fancy-figure.caption-position-none figcaption {
display: none;
}
.gallery.caption-position-center figcaption,
.fancy-figure.caption-position-center figcaption {
top: 0;
padding: 40% 5px;
}
.gallery.caption-position-bottom figcaption,
.fancy-figure.caption-position-bottom figcaption {
padding: 5px;
}
.gallery.caption-effect-fade figure:not(:hover) figcaption,
.gallery.caption-effect-appear figure:not(:hover) figcaption,
.fancy-figure.caption-effect-fade figure:not(:hover) figcaption,
.fancy-figure.caption-effect-appear figure:not(:hover) figcaption {
background: rgba(0, 0, 0, 0);
opacity: 0;
}
.gallery.caption-effect-slide.caption-position-bottom figure:not(:hover) figcaption,
.fancy-figure.caption-effect-slide.caption-position-bottom figure:not(:hover) figcaption {
margin-bottom: -100%;
}
.gallery.caption-effect-slide.caption-position-center figure:not(:hover) figcaption,
.fancy-figure.caption-effect-slide.caption-position-center figure:not(:hover) figcaption {
top: 100%;
}
.post-content figure figcaption p,
.post-content .gallery figcaption p,
.post-content .fancy-figure figcaption p {
margin: 0px 0px 0px 0px; /* override style in theme */
font-size: 0.8em;
}

View file

@ -0,0 +1,24 @@
.chroma {
background-color: unset !important;
}
.chroma .hl {
display: flex;
}
.chroma .lnt {
padding: 0 0 0 12px;
}
.highlight pre.chroma code {
padding: 8px 0;
}
.highlight pre.chroma .line .cl,
.chroma .ln {
padding: 0 10px;
}
.chroma .lntd:last-of-type {
width: 100%;
}

View file

@ -0,0 +1,86 @@
/* Background */ .bg { color: #cad3f5; background-color: #24273a; }
/* PreWrapper */ .chroma { color: #cad3f5; background-color: #24273a; }
/* Other */ .chroma .x { }
/* Error */ .chroma .err { color: #ed8796 }
/* CodeLine */ .chroma .cl { }
/* LineLink */ .chroma .lnlinks { outline: none; text-decoration: none; color: inherit }
/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }
/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; }
/* LineHighlight */ .chroma .hl { background-color: #474733 }
/* LineNumbersTable */ .chroma .lnt { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #8087a2 }
/* LineNumbers */ .chroma .ln { white-space: pre; -webkit-user-select: none; user-select: none; margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #8087a2 }
/* Line */ .chroma .line { display: flex; }
/* Keyword */ .chroma .k { color: #c6a0f6 }
/* KeywordConstant */ .chroma .kc { color: #f5a97f }
/* KeywordDeclaration */ .chroma .kd { color: #ed8796 }
/* KeywordNamespace */ .chroma .kn { color: #8bd5ca }
/* KeywordPseudo */ .chroma .kp { color: #c6a0f6 }
/* KeywordReserved */ .chroma .kr { color: #c6a0f6 }
/* KeywordType */ .chroma .kt { color: #ed8796 }
/* Name */ .chroma .n { }
/* NameAttribute */ .chroma .na { color: #8aadf4 }
/* NameBuiltin */ .chroma .nb { color: #91d7e3 }
/* NameBuiltinPseudo */ .chroma .bp { color: #91d7e3 }
/* NameClass */ .chroma .nc { color: #eed49f }
/* NameConstant */ .chroma .no { color: #eed49f }
/* NameDecorator */ .chroma .nd { color: #8aadf4; font-weight: bold }
/* NameEntity */ .chroma .ni { color: #8bd5ca }
/* NameException */ .chroma .ne { color: #f5a97f }
/* NameFunction */ .chroma .nf { color: #8aadf4 }
/* NameFunctionMagic */ .chroma .fm { color: #8aadf4 }
/* NameLabel */ .chroma .nl { color: #91d7e3 }
/* NameNamespace */ .chroma .nn { color: #f5a97f }
/* NameOther */ .chroma .nx { }
/* NameProperty */ .chroma .py { color: #f5a97f }
/* NameTag */ .chroma .nt { color: #c6a0f6 }
/* NameVariable */ .chroma .nv { color: #f4dbd6 }
/* NameVariableClass */ .chroma .vc { color: #f4dbd6 }
/* NameVariableGlobal */ .chroma .vg { color: #f4dbd6 }
/* NameVariableInstance */ .chroma .vi { color: #f4dbd6 }
/* NameVariableMagic */ .chroma .vm { color: #f4dbd6 }
/* Literal */ .chroma .l { }
/* LiteralDate */ .chroma .ld { }
/* LiteralString */ .chroma .s { color: #a6da95 }
/* LiteralStringAffix */ .chroma .sa { color: #ed8796 }
/* LiteralStringBacktick */ .chroma .sb { color: #a6da95 }
/* LiteralStringChar */ .chroma .sc { color: #a6da95 }
/* LiteralStringDelimiter */ .chroma .dl { color: #8aadf4 }
/* LiteralStringDoc */ .chroma .sd { color: #6e738d }
/* LiteralStringDouble */ .chroma .s2 { color: #a6da95 }
/* LiteralStringEscape */ .chroma .se { color: #8aadf4 }
/* LiteralStringHeredoc */ .chroma .sh { color: #6e738d }
/* LiteralStringInterpol */ .chroma .si { color: #a6da95 }
/* LiteralStringOther */ .chroma .sx { color: #a6da95 }
/* LiteralStringRegex */ .chroma .sr { color: #8bd5ca }
/* LiteralStringSingle */ .chroma .s1 { color: #a6da95 }
/* LiteralStringSymbol */ .chroma .ss { color: #a6da95 }
/* LiteralNumber */ .chroma .m { color: #f5a97f }
/* LiteralNumberBin */ .chroma .mb { color: #f5a97f }
/* LiteralNumberFloat */ .chroma .mf { color: #f5a97f }
/* LiteralNumberHex */ .chroma .mh { color: #f5a97f }
/* LiteralNumberInteger */ .chroma .mi { color: #f5a97f }
/* LiteralNumberIntegerLong */ .chroma .il { color: #f5a97f }
/* LiteralNumberOct */ .chroma .mo { color: #f5a97f }
/* Operator */ .chroma .o { color: #91d7e3; font-weight: bold }
/* OperatorWord */ .chroma .ow { color: #91d7e3; font-weight: bold }
/* Punctuation */ .chroma .p { }
/* Comment */ .chroma .c { color: #6e738d; font-style: italic }
/* CommentHashbang */ .chroma .ch { color: #6e738d; font-style: italic }
/* CommentMultiline */ .chroma .cm { color: #6e738d; font-style: italic }
/* CommentSingle */ .chroma .c1 { color: #6e738d; font-style: italic }
/* CommentSpecial */ .chroma .cs { color: #6e738d; font-style: italic }
/* CommentPreproc */ .chroma .cp { color: #6e738d; font-style: italic }
/* CommentPreprocFile */ .chroma .cpf { color: #6e738d; font-weight: bold; font-style: italic }
/* Generic */ .chroma .g { }
/* GenericDeleted */ .chroma .gd { color: #ed8796; background-color: #363a4f }
/* GenericEmph */ .chroma .ge { font-style: italic }
/* GenericError */ .chroma .gr { color: #ed8796 }
/* GenericHeading */ .chroma .gh { color: #f5a97f; font-weight: bold }
/* GenericInserted */ .chroma .gi { color: #a6da95; background-color: #363a4f }
/* GenericOutput */ .chroma .go { }
/* GenericPrompt */ .chroma .gp { }
/* GenericStrong */ .chroma .gs { font-weight: bold }
/* GenericSubheading */ .chroma .gu { color: #f5a97f; font-weight: bold }
/* GenericTraceback */ .chroma .gt { color: #ed8796 }
/* GenericUnderline */ .chroma .gl { text-decoration: underline }
/* TextWhitespace */ .chroma .w { }

View file

@ -0,0 +1,63 @@
/* from reset */
::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-track {
background: var(--code-bg);
}
::-webkit-scrollbar-thumb {
background: var(--tertiary);
border: 5px solid var(--theme);
border-radius: var(--radius);
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border: 5px solid var(--code-bg);
}
::-webkit-scrollbar-thumb:hover {
background: var(--secondary);
}
::-webkit-scrollbar:not(.highlighttable, .highlight table, .gist .highlight) {
background: var(--theme);
}
/* from post-single */
.post-content .highlighttable td .highlight pre code::-webkit-scrollbar {
display: none;
}
.post-content :not(table) ::-webkit-scrollbar-thumb {
border: 2px solid var(--code-block-bg);
background: rgb(113, 113, 117);
}
.post-content :not(table) ::-webkit-scrollbar-thumb:hover {
background: rgb(163, 163, 165);
}
.gist table::-webkit-scrollbar-thumb {
border: 2px solid rgb(255, 255, 255);
background: rgb(173, 173, 173);
}
.gist table::-webkit-scrollbar-thumb:hover {
background: rgb(112, 112, 112);
}
.post-content table::-webkit-scrollbar-thumb {
border-width: 2px;
}
/* from zmedia */
@media screen and (min-width: 768px) {
/* reset */
::-webkit-scrollbar {
width: 19px;
height: 11px;
}
}

152
assets/js/fastsearch.js Executable file
View file

@ -0,0 +1,152 @@
import * as params from '@params';
let fuse; // holds our search engine
let resList = document.getElementById('searchResults');
let sInput = document.getElementById('searchInput');
let first, last, current_elem = null
let resultsAvailable = false;
// load our search index
window.onload = function () {
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let data = JSON.parse(xhr.responseText);
if (data) {
// fuse.js options; check fuse.js website for details
let options = {
distance: 100,
threshold: 0.4,
ignoreLocation: true,
keys: [
'title',
'permalink',
'summary',
'content'
]
};
if (params.fuseOpts) {
options = {
isCaseSensitive: params.fuseOpts.iscasesensitive ?? false,
includeScore: params.fuseOpts.includescore ?? false,
includeMatches: params.fuseOpts.includematches ?? false,
minMatchCharLength: params.fuseOpts.minmatchcharlength ?? 1,
shouldSort: params.fuseOpts.shouldsort ?? true,
findAllMatches: params.fuseOpts.findallmatches ?? false,
keys: params.fuseOpts.keys ?? ['title', 'permalink', 'summary', 'content'],
location: params.fuseOpts.location ?? 0,
threshold: params.fuseOpts.threshold ?? 0.4,
distance: params.fuseOpts.distance ?? 100,
ignoreLocation: params.fuseOpts.ignorelocation ?? true
}
}
fuse = new Fuse(data, options); // build the index from the json file
}
} else {
console.log(xhr.responseText);
}
}
};
xhr.open('GET', "../index.json");
xhr.send();
}
function activeToggle(ae) {
document.querySelectorAll('.focus').forEach(function (element) {
// rm focus class
element.classList.remove("focus")
});
if (ae) {
ae.focus()
document.activeElement = current_elem = ae;
ae.parentElement.classList.add("focus")
} else {
document.activeElement.parentElement.classList.add("focus")
}
}
function reset() {
resultsAvailable = false;
resList.innerHTML = sInput.value = ''; // clear inputbox and searchResults
sInput.focus(); // shift focus to input box
}
// execute search as each character is typed
sInput.onkeyup = function (e) {
// run a search query (for "term") every time a letter is typed
// in the search box
if (fuse) {
let results;
if (params.fuseOpts) {
results = fuse.search(this.value.trim(), {limit: params.fuseOpts.limit}); // the actual query being run using fuse.js along with options
} else {
results = fuse.search(this.value.trim()); // the actual query being run using fuse.js
}
if (results.length !== 0) {
// build our html if result exists
let resultSet = ''; // our results bucket
for (let item in results) {
resultSet += `<li class="post-entry"><header class="entry-header">${results[item].item.title}&nbsp;»</header>` +
`<a href="${results[item].item.permalink}" aria-label="${results[item].item.title}"></a></li>`
}
resList.innerHTML = resultSet;
resultsAvailable = true;
first = resList.firstChild;
last = resList.lastChild;
} else {
resultsAvailable = false;
resList.innerHTML = '';
}
}
}
sInput.addEventListener('search', function (e) {
// clicked on x
if (!this.value) reset()
})
// kb bindings
document.onkeydown = function (e) {
let key = e.key;
let ae = document.activeElement;
let inbox = document.getElementById("searchbox").contains(ae)
if (ae === sInput) {
let elements = document.getElementsByClassName('focus');
while (elements.length > 0) {
elements[0].classList.remove('focus');
}
} else if (current_elem) ae = current_elem;
if (key === "Escape") {
reset()
} else if (!resultsAvailable || !inbox) {
return
} else if (key === "ArrowDown") {
e.preventDefault();
if (ae == sInput) {
// if the currently focused element is the search input, focus the <a> of first <li>
activeToggle(resList.firstChild.lastChild);
} else if (ae.parentElement != last) {
// if the currently focused element's parent is last, do nothing
// otherwise select the next search result
activeToggle(ae.parentElement.nextSibling.lastChild);
}
} else if (key === "ArrowUp") {
e.preventDefault();
if (ae.parentElement == first) {
// if the currently focused element is first item, go to input box
activeToggle(sInput);
} else if (ae != sInput) {
// if the currently focused element is input box, do nothing
// otherwise select the previous search result
activeToggle(ae.parentElement.previousSibling.lastChild);
}
} else if (key === "ArrowRight") {
ae.click(); // click on active link
}
}

9
assets/js/fuse.basic.min.js vendored Executable file

File diff suppressed because one or more lines are too long

1
assets/js/main.js Executable file
View file

@ -0,0 +1 @@
console.log('This site was generated by Hugo.');

28
i18n/ar.yaml Executable file
View file

@ -0,0 +1,28 @@
- id: prev_page
translation: "السابق"
- id: next_page
translation: "التالي"
- id: read_time
translation:
one: "دقيقة واحدة"
two: "دقيقتان"
few: "بضع ثوان"
zero: "الآن"
other: "دقائق {{ .Count }}"
- id: toc
translation: "فهرس المحتوى"
- id: translations
translation: "ترجمات أخرى"
- id: home
translation: "الصفحة الرئيسية"
- id: code_copied
translation: "تم النسخ!"
- id: code_copy
translation: "نسخ الكود"

33
i18n/en.yaml Executable file
View file

@ -0,0 +1,33 @@
- id: prev_page
translation: "Prev"
- id: next_page
translation: "Next"
- id: read_time
translation:
one : "1 min"
other: "{{ .Count }} min"
- id: words
translation:
one : "word"
other: "{{ .Count }} words"
- id: toc
translation: "Table of Contents"
- id: translations
translation: "Translations"
- id: home
translation: "Home"
- id: edit_post
translation: "Edit"
- id: code_copy
translation: "copy"
- id: code_copied
translation: "copied!"

33
i18n/fr.yaml Executable file
View file

@ -0,0 +1,33 @@
- id: prev_page
translation: "Précédent"
- id: next_page
translation: "Suivant"
- id: read_time
translation:
one : "1 min"
other: "{{ .Count }} min"
- id: words
translation:
one : "mot"
other: "{{ .Count }} mots"
- id: toc
translation: "Table des matières"
- id: translations
translation: "Traductions"
- id: home
translation: "Accueil"
- id: edit_post
translation: "Modifier"
- id: code_copy
translation: "Copier"
- id: code_copied
translation: "Copié !"

10
layouts/404.html Executable file
View file

@ -0,0 +1,10 @@
{{- define "main" }}
<style>
.not-found {
position : relative;
}
</style>
<div class="not-found">404</div>
<div class="not-found" style="font-size: 1.5em;">Ouais désolé je sais pas ce que tu cherches mais c'est pas ici en tous cas</div>
{{- end }}{{/* end main */ -}}

View file

@ -0,0 +1,22 @@
{{- $u := urls.Parse .Destination -}}
{{- $src := $u.String -}}
{{- if not $u.IsAbs -}}
{{- $path := strings.TrimPrefix "./" $u.Path }}
{{- with or (.PageInner.Resources.Get $path) (resources.Get $path) -}}
{{- $src = .RelPermalink -}}
{{- with $u.RawQuery -}}
{{- $src = printf "%s?%s" $src . -}}
{{- end -}}
{{- with $u.Fragment -}}
{{- $src = printf "%s#%s" $src . -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- $attributes := merge .Attributes (dict "alt" .Text "src" $src "title" (.Title | transform.HTMLEscape) "loading" "lazy") -}}
<img
{{- range $k, $v := $attributes -}}
{{- if $v -}}
{{- printf " %s=%q" $k $v | safeHTMLAttr -}}
{{- end -}}
{{- end -}}>
{{- /**/ -}}

83
layouts/_default/archives.html Executable file
View file

@ -0,0 +1,83 @@
{{- define "main" }}
<header class="page-header">
<h1>
{{ .Title }}
{{- if (.Param "ShowRssButtonInSectionTermList") }}
{{- $rss := (.OutputFormats.Get "rss") }}
{{- if (eq .Kind `page`) }}
{{- $rss = (.Parent.OutputFormats.Get "rss") }}
{{- end }}
{{- with $rss }}
<a href="{{ .RelPermalink }}" title="RSS" aria-label="RSS">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" height="23">
<path d="M4 11a9 9 0 0 1 9 9" />
<path d="M4 4a16 16 0 0 1 16 16" />
<circle cx="5" cy="19" r="1" />
</svg>
</a>
{{- end }}
{{- end }}
</h1>
{{- if .Description }}
<div class="post-description">
{{ .Description }}
</div>
{{- end }}
</header>
{{- $pages := where site.RegularPages "Type" "in" site.Params.mainSections }}
{{- if site.Params.ShowAllPagesInArchive }}
{{- $pages = site.RegularPages }}
{{- end }}
{{- range $pages.GroupByPublishDate "2006" }}
{{- if ne .Key "0001" }}
<div class="archive-year">
{{- $year := replace .Key "0001" "" }}
<h2 class="archive-year-header" id="{{ $year }}">
<a class="archive-header-link" href="#{{ $year }}">
{{- $year -}}
</a>
<sup class="archive-count">&nbsp;{{ len .Pages }}</sup>
</h2>
{{- range .Pages.GroupByDate "January" }}
<div class="archive-month">
<h3 class="archive-month-header" id="{{ $year }}-{{ .Key }}">
<a class="archive-header-link" href="#{{ $year }}-{{ .Key }}">
{{- .Key -}}
</a>
<sup class="archive-count">&nbsp;{{ len .Pages }}</sup>
</h3>
<div class="archive-posts">
{{- range .Pages }}
{{- if eq .Kind "page" }}
<div class="archive-entry">
<h3 class="archive-entry-title entry-hint-parent">
{{- .Title | markdownify }}
{{- if .Draft }}
<span class="entry-hint" title="Draft">
<svg xmlns="http://www.w3.org/2000/svg" height="15" viewBox="0 -960 960 960" fill="currentColor">
<path
d="M160-410v-60h300v60H160Zm0-165v-60h470v60H160Zm0-165v-60h470v60H160Zm360 580v-123l221-220q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q9 9 13 20t4 22q0 11-4.5 22.5T862.09-380L643-160H520Zm300-263-37-37 37 37ZM580-220h38l121-122-18-19-19-18-122 121v38Zm141-141-19-18 37 37-18-19Z" />
</svg>
</span>
{{- end }}
</h3>
<div class="archive-meta">
{{- partial "post_meta.html" . -}}
</div>
<a class="entry-link" aria-label="post link to {{ .Title | plainify }}" href="{{ .Permalink }}"></a>
</div>
{{- end }}
{{- end }}
</div>
</div>
{{- end }}
</div>
{{- end }}
{{- end }}
{{- end }}{{/* end main */}}

29
layouts/_default/baseof.html Executable file
View file

@ -0,0 +1,29 @@
{{- if lt hugo.Version "0.125.7" }}
{{- errorf "=> hugo v0.125.7 or greater is required for hugo-PaperMod to build " }}
{{- end -}}
<!DOCTYPE html>
<html lang="{{ site.Language }}" dir="{{ .Language.LanguageDirection | default "auto" }}">
<head>
{{- partial "head.html" . }}
</head>
<body class="
{{- if (or (ne .Kind `page` ) (eq .Layout `archives`) (eq .Layout `search`)) -}}
{{- print "list" -}}
{{- end -}}
{{- if eq site.Params.defaultTheme `dark` -}}
{{- print " dark" }}
{{- end -}}
" id="top">
<div class="main-content">
{{- partialCached "header.html" . .Page -}}
<main class="main">
{{- block "main" . }}{{ end }}
</main>
{{ partialCached "footer.html" . .Layout .Kind (.Param "hideFooter") (.Param "ShowCodeCopyButtons") -}}
</div>
</body>
</html>

7
layouts/_default/index.json Executable file
View file

@ -0,0 +1,7 @@
{{- $.Scratch.Add "index" slice -}}
{{- range site.RegularPages -}}
{{- if and (not .Params.searchHidden) (ne .Layout `archives`) (ne .Layout `search`) }}
{{- $.Scratch.Add "index" (dict "title" .Title "content" .Plain "permalink" .Permalink "summary" .Summary) -}}
{{- end }}
{{- end -}}
{{- $.Scratch.Get "index" | jsonify -}}

121
layouts/_default/list.html Executable file
View file

@ -0,0 +1,121 @@
{{- define "main" }}
{{- if (and site.Params.profileMode.enabled .IsHome) }}
{{- partial "index_profile.html" . }}
{{- else }} {{/* if not profileMode */}}
{{- if not .IsHome | and .Title }}
<header class="page-header">
{{- partial "breadcrumbs.html" . }}
<h1>
{{ .Title }}
{{- if and (or (eq .Kind `term`) (eq .Kind `section`)) (.Param "ShowRssButtonInSectionTermList") }}
{{- with .OutputFormats.Get "rss" }}
<a href="{{ .RelPermalink }}" title="RSS" aria-label="RSS">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" height="23">
<path d="M4 11a9 9 0 0 1 9 9" />
<path d="M4 4a16 16 0 0 1 16 16" />
<circle cx="5" cy="19" r="1" />
</svg>
</a>
{{- end }}
{{- end }}
</h1>
{{- if .Description }}
<div class="post-description">
{{ .Description | markdownify }}
</div>
{{- end }}
</header>
{{- end }}
{{- if .Content }}
<div class="post-content">
{{- if not (.Param "disableAnchoredHeadings") }}
{{- partial "anchored_headings.html" .Content -}}
{{- else }}{{ .Content }}{{ end }}
</div>
{{- end }}
{{- $pages := union .RegularPages .Sections }}
{{- if .IsHome }}
{{- $pages = where site.RegularPages "Type" "in" site.Params.mainSections }}
{{- $pages = where $pages "Params.hiddenInHomeList" "!=" "true" }}
{{- end }}
{{- $paginator := .Paginate $pages }}
{{- if and .IsHome site.Params.homeInfoParams (eq $paginator.PageNumber 1) }}
{{- partial "home_info.html" . }}
{{- end }}
{{- $term := .Data.Term }}
{{- range $index, $page := $paginator.Pages }}
{{- $class := "post-entry" }}
{{- $user_preferred := or site.Params.disableSpecial1stPost site.Params.homeInfoParams }}
{{- if (and $.IsHome (eq $paginator.PageNumber 1) (eq $index 0) (not $user_preferred)) }}
{{- $class = "first-entry" }}
{{- else if $term }}
{{- $class = "post-entry tag-entry" }}
{{- end }}
<article class="{{ $class }}">
{{- $isHidden := (.Param "cover.hiddenInList") | default (.Param "cover.hidden") | default false }}
{{- partial "cover.html" (dict "cxt" . "IsSingle" false "isHidden" $isHidden) }}
<header class="entry-header">
<h2 class="entry-hint-parent">
{{- .Title }}
{{- if .Draft }}
<span class="entry-hint" title="Draft">
<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 -960 960 960" fill="currentColor">
<path
d="M160-410v-60h300v60H160Zm0-165v-60h470v60H160Zm0-165v-60h470v60H160Zm360 580v-123l221-220q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q9 9 13 20t4 22q0 11-4.5 22.5T862.09-380L643-160H520Zm300-263-37-37 37 37ZM580-220h38l121-122-18-19-19-18-122 121v38Zm141-141-19-18 37 37-18-19Z" />
</svg>
</span>
{{- end }}
</h2>
</header>
{{- if (ne (.Param "hideSummary") true) }}
<div class="entry-content">
<p>{{ .Summary | plainify | htmlUnescape }}{{ if .Truncated }}...{{ end }}</p>
</div>
{{- end }}
{{- if not (.Param "hideMeta") }}
<footer class="entry-footer">
{{- partial "post_meta.html" . -}}
</footer>
{{- end }}
<a class="entry-link" aria-label="post link to {{ .Title | plainify }}" href="{{ .Permalink }}"></a>
</article>
{{- end }}
{{- if gt $paginator.TotalPages 1 }}
<footer class="page-footer">
<nav class="pagination">
{{- if $paginator.HasPrev }}
<a class="prev" href="{{ $paginator.Prev.URL | absURL }}">
«&nbsp;{{ i18n "prev_page" }}&nbsp;
{{- if (.Param "ShowPageNums") }}
{{- sub $paginator.PageNumber 1 }}/{{ $paginator.TotalPages }}
{{- end }}
</a>
{{- end }}
{{- if $paginator.HasNext }}
<a class="next" href="{{ $paginator.Next.URL | absURL }}">
{{- i18n "next_page" }}&nbsp;
{{- if (.Param "ShowPageNums") }}
{{- add 1 $paginator.PageNumber }}/{{ $paginator.TotalPages }}
{{- end }}&nbsp;»
</a>
{{- end }}
</nav>
</footer>
{{- end }}
{{- end }}{{/* end profileMode */}}
{{- end }}{{- /* end main */ -}}

29
layouts/_default/search.html Executable file
View file

@ -0,0 +1,29 @@
{{- define "main" }}
<header class="page-header">
<h1>{{- (printf "%s&nbsp;" .Title ) | htmlUnescape -}}
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</h1>
{{- if .Description }}
<div class="post-description">
{{ .Description }}
</div>
{{- end }}
{{- if not (.Param "hideMeta") }}
<div class="post-meta">
{{- partial "translation_list.html" . -}}
</div>
{{- end }}
</header>
<div id="searchbox">
<input id="searchInput" autofocus placeholder="{{ .Params.placeholder | default (printf "%s " .Title) }}"
aria-label="search" type="search" autocomplete="off" maxlength="64">
<ul id="searchResults" aria-label="search results"></ul>
</div>
{{- end }}{{/* end main */}}

76
layouts/_default/single.html Executable file
View file

@ -0,0 +1,76 @@
{{- define "main" }}
<article class="post-single">
<header class="post-header">
{{ partial "breadcrumbs.html" . }}
<h1 class="post-title entry-hint-parent">
{{ .Title }}
{{- if .Draft }}
<span class="entry-hint" title="Draft">
<svg xmlns="http://www.w3.org/2000/svg" height="35" viewBox="0 -960 960 960" fill="currentColor">
<path
d="M160-410v-60h300v60H160Zm0-165v-60h470v60H160Zm0-165v-60h470v60H160Zm360 580v-123l221-220q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q9 9 13 20t4 22q0 11-4.5 22.5T862.09-380L643-160H520Zm300-263-37-37 37 37ZM580-220h38l121-122-18-19-19-18-122 121v38Zm141-141-19-18 37 37-18-19Z" />
</svg>
</span>
{{- end }}
</h1>
{{- if .Description }}
<div class="post-description">
{{ .Description }}
</div>
{{- end }}
{{- if not (.Param "hideMeta") }}
<div class="post-meta">
{{- partial "post_meta.html" . -}}
{{- partial "translation_list.html" . -}}
{{- partial "edit_post.html" . -}}
{{- partial "post_canonical.html" . -}}
</div>
{{- end }}
</header>
{{- $isHidden := (.Param "cover.hiddenInSingle") | default (.Param "cover.hidden") | default false }}
{{- partial "cover.html" (dict "cxt" . "IsSingle" true "isHidden" $isHidden) }}
{{- if (.Param "ShowToc") }}
{{- partial "toc.html" . }}
{{- end }}
{{- if .Content }}
<div class="flex-wrapper">
<!-- if the page is a collection item, add the infobox -->
{{- if eq .Section "collection" }}
{{ partial "encadre-maec.html" . }}
{{- end }}
<!-- if the page is a book, add the infobox -->
{{- if eq .Section "livres" }}
{{ partial "encadre-livre.html" . }}
{{- end }}
<div class="post-content">
{{- if not (.Param "disableAnchoredHeadings") }}
{{- partial "anchored_headings.html" .Content -}}
{{- else }}{{ .Content }}{{ end }}
</div>
{{- end }}
</div>
<footer class="post-footer">
{{- $tags := .Language.Params.Taxonomies.tag | default "tags" }}
<ul class="post-tags">
{{- range ($.GetTerms $tags) }}
<li><a href="{{ .Permalink }}">{{ .LinkTitle }}</a></li>
{{- end }}
</ul>
{{- if (.Param "ShowPostNavLinks") }}
{{- partial "post_nav_links.html" . }}
{{- end }}
{{- if (and site.Params.ShowShareButtons (ne .Params.disableShare true)) }}
{{- partial "share_icons.html" . -}}
{{- end }}
</footer>
{{- if (.Param "comments") }}
{{- partial "comments.html" . }}
{{- end }}
</article>
{{- end }}{{/* end main */}}

27
layouts/_default/terms.html Executable file
View file

@ -0,0 +1,27 @@
{{- define "main" }}
{{- if .Title }}
<header class="page-header">
<h1>{{ .Title }}</h1>
{{- if .Description }}
<div class="post-description">
{{ .Description }}
</div>
{{- end }}
</header>
{{- end }}
<ul class="terms-tags">
{{- $type := .Type }}
{{- range $key, $value := .Data.Terms.Alphabetical }}
{{- $name := .Name }}
{{- $count := .Count }}
{{- with site.GetPage (printf "/%s/%s" $type $name) }}
<li>
<a href="{{ .Permalink }}">{{ .Name }} <sup><strong><sup>{{ $count }}</sup></strong></sup> </a>
</li>
{{- end }}
{{- end }}
</ul>
{{- end }}{{/* end main */ -}}

147
layouts/collection/list.html Executable file
View file

@ -0,0 +1,147 @@
{{- define "main" }}
{{- if (and site.Params.profileMode.enabled .IsHome) }}
{{- partial "index_profile.html" . }}
{{- else }} {{/* if not profileMode */}}
{{- if not .IsHome | and .Title }}
<header class="page-header">
{{- partial "breadcrumbs.html" . }}
<h1>
{{ .Title }}
{{- if and (or (eq .Kind `term`) (eq .Kind `section`)) (.Param "ShowRssButtonInSectionTermList") }}
{{- with .OutputFormats.Get "rss" }}
<a href="{{ .RelPermalink }}" title="RSS" aria-label="RSS">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round" height="23">
<path d="M4 11a9 9 0 0 1 9 9" />
<path d="M4 4a16 16 0 0 1 16 16" />
<circle cx="5" cy="19" r="1" />
</svg>
</a>
{{- end }}
{{- end }}
</h1>
{{- if .Description }}
<div class="post-description">
{{ .Description | markdownify }}
</div>
{{- end }}
</header>
{{- end }}
<style>
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); /* Responsive grid */
gap: 10px; /* Space between grid items */
margin: 0 0;
}
.post-entry {
padding: 0;
border-radius: 8px;
background-color: var(--entry);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin: 0;
}
.entry-cover {
margin: 0;
padding: 0;
}
.entry-header {
font-size: 1.1rem;
display: inline-block;
margin: 10px 16px 10px 16px;
}
.post-entry p {
margin: 0;
color: #555;
}
</style>
{{- if .Content }}
<div class="post-content">
{{- if not (.Param "disableAnchoredHeadings") }}
{{- partial "anchored_headings.html" .Content -}}
{{- else }}{{ .Content }}{{ end }}
</div>
{{- end }}
<div class="grid-container">
{{- range .Pages }}
<a href="{{ .Permalink }}" class="post-entry">
{{- $isHidden := (.Param "cover.hiddenInList") | default (.Param "cover.hidden") | default false }}
{{- partial "cover.html" (dict "cxt" . "IsSingle" false "isHidden" $isHidden) }}
<header class="entry-header">
<h2 class="entry-hint-parent">
<span>{{ .Title }}</span>
</h2>
</header>
</a>
{{- end }}
</div>
{{- $pages := union .RegularPages .Sections }}
{{- if .IsHome }}
{{- $pages = where site.RegularPages "Type" "in" site.Params.mainSections }}
{{- $pages = where $pages "Params.hiddenInHomeList" "!=" "true" }}
{{- end }}
{{- $paginator := .Paginate $pages }}
{{- if and .IsHome site.Params.homeInfoParams (eq $paginator.PageNumber 1) }}
{{- partial "home_info.html" . }}
{{- end }}
{{- $term := .Data.Term }}
{{- range $index, $page := $paginator.Pages }}
{{- $class := "post-entry" }}
{{- $user_preferred := or site.Params.disableSpecial1stPost site.Params.homeInfoParams }}
{{- if (and $.IsHome (eq $paginator.PageNumber 1) (eq $index 0) (not $user_preferred)) }}
{{- $class = "first-entry" }}
{{- else if $term }}
{{- $class = "post-entry tag-entry" }}
{{- end }}
{{- end }}
{{- if gt $paginator.TotalPages 1 }}
<footer class="page-footer">
<nav class="pagination">
{{- if $paginator.HasPrev }}
<a class="prev" href="{{ $paginator.Prev.URL | absURL }}">
«&nbsp;{{ i18n "prev_page" }}&nbsp;
{{- if (.Param "ShowPageNums") }}
{{- sub $paginator.PageNumber 1 }}/{{ $paginator.TotalPages }}
{{- end }}
</a>
{{- end }}
{{- if $paginator.HasNext }}
<a class="next" href="{{ $paginator.Next.URL | absURL }}">
{{- i18n "next_page" }}&nbsp;
{{- if (.Param "ShowPageNums") }}
{{- add 1 $paginator.PageNumber }}/{{ $paginator.TotalPages }}
{{- end }}&nbsp;»
</a>
{{- end }}
</nav>
</footer>
{{- end }}
{{- end }}{{/* end profileMode */}}
{{- end }}{{- /* end main */ -}}

207
layouts/home.html Executable file
View file

@ -0,0 +1,207 @@
<!DOCTYPE html>
<html lang="{{ site.Language }}" dir="{{ .Language.LanguageDirection | default "auto" }}">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta charset="utf-8">
<!-- Include core CSS files -->
<link rel="stylesheet" href="{{ "css/core/reset.css" | relURL }}">
<link rel="stylesheet" href="{{ "css/core/theme-vars.css" | relURL }}">
<link rel="stylesheet" href="{{ "css/core/zmedia.css" | relURL }}">
<!-- Include home page specific styles -->
<link rel="stylesheet" href="{{ "css/home.css" | relURL }}">
<!-- Include concatenated and minified stylesheet -->
{{- $theme_vars := (resources.Get "css/core/theme-vars.css") }}
{{- $reset := (resources.Get "css/core/reset.css") }}
{{- $media := (resources.Get "css/core/zmedia.css") }}
{{- $common := (resources.Match "css/common/*.css") | resources.Concat "assets/css/common.css" }}
{{- $extended := (resources.Match "css/extended/*.css") | resources.Concat "assets/css/extended.css" }}
{{- $core := (slice $theme_vars $reset $common $media $extended) | resources.Concat "assets/css/core.css" | resources.Minify }}
<link rel="stylesheet" href="{{ $core.RelPermalink }}">
</head>
<header>
<!-- Script to automatically toggle to the right theme -->
{{- /* theme-toggle is enabled */}}
{{- if (not site.Params.disableThemeToggle) }}
{{- /* theme is light */}}
{{- if (eq site.Params.defaultTheme "light") }}
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
}
</script>
{{- /* theme is dark */}}
{{- else if (eq site.Params.defaultTheme "dark") }}
<script>
if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
}
</script>
{{- else }}
{{- /* theme is auto */}}
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
{{- end }}
{{- /* theme-toggle is disabled and theme is auto */}}
{{- else if (and (ne site.Params.defaultTheme "light") (ne site.Params.defaultTheme "dark"))}}
<script>
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
{{- end }}
</header>
<body>
<div class="main-screen">
<div class="side-screen">
{{ partial "posts-defile.html" (dict "context" . "direction" "up") }}
</div>
<div class="main-content">
<div class="header">
<div class="title-wrapper">
<h1 class="site-title">Achille<br/>Toupin</h1>
<div class="site-logo">
<img src="favicon.svg" alt="Logo de machine à écrire">
</div>
</div>
<nav class="navigation">
{{ partial "menu.html" }}
</nav>
</div>
<div class="center-content">
<div class="presentation">
{{ .Content }}
</div>
<div class="side-content-column">
<div class="dernier-article">
{{ range first 1 (where .Site.RegularPages.ByDate.Reverse "Section" "blog") }}
{{- $image := .Resources.GetMatch (printf "%s" .Params.cover.image) -}}
{{- if $image -}}
{{- $optimizedImage := $image.Fill "150x150 webp q95 Center" -}}
<a href="{{ .RelPermalink }}">
<h2>Mon dernier article :</h2>
<h3>{{ .Title }}</h3>
<div class="excerpt">
<div class="excerpt-text">
<small>{{ .Date.Format "January 2, 2006" }}</small>
<p>{{ .Plain | plainify | truncate 100 }}</p>
</div>
<img src="{{ $optimizedImage.RelPermalink }}" alt="{{ .Title }} cover image"></img>
</div>
</a>
{{ end }}
{{ end }}
</div>
<div class="dernier-article">
{{ range first 1 (where .Site.RegularPages.ByDate.Reverse "Section" "collection") }}
{{- $image := .Resources.GetMatch (printf "%s" .Params.cover.image) -}}
{{- if $image -}}
{{- $optimizedImage := $image.Fit "150x150 webp q95 Center" -}}
<a href="{{ .RelPermalink }}">
<h2>Une belle machine :</h2>
<h3>{{ .Title }}</h3>
<div class="excerpt">
<div class="excerpt-text">
<small>{{ .Date.Format "January 2, 2006" }}</small>
<p>{{ .Plain | plainify | truncate 100 }}</p>
</div>
<img src="{{ $optimizedImage.RelPermalink }}" alt="{{ .Title }} cover image"></img>
</div>
</a>
{{ end }}
{{ end }}
</div>
<div class="dernier-livre">
{{ range first 1 (where .Site.RegularPages.ByDate.Reverse "Section" "livres") }}
{{- $image := .Resources.GetMatch (printf "%s" .Params.cover.image) -}}
{{- if $image -}}
{{- $optimizedImage := $image.Fit "150x150 webp q95 Center" -}}
<a href="{{ .RelPermalink }}">
<h2>Lecture du moment :</h2>
<h3>{{ .Title }}</h3>
<div class="excerpt">
<div class="excerpt-text">
<small>{{ .Date.Format "January 2, 2006" }}</small>
<p>{{ .Plain | plainify | truncate 100 }}</p>
</div>
<img src="{{ $optimizedImage.RelPermalink }}" alt="{{ .Title }} cover image"></img>
</div>
</a>
{{ end }}
{{ end }}
</div>
</div>
</div>
{{ partial "buttons.html"}}
{{ partialCached "footer.html" . .Layout .Kind (.Param "hideFooter") (.Param "ShowCodeCopyButtons") -}}
</div>
<div class="side-screen">
{{ partial "posts-defile.html" (dict "context" . "direction" "down") }}
</div>
</div>
</body>
<footer>
<!-- Script to toggle theme. has to be at the end of the page -->
{{- if (not site.Params.disableThemeToggle) }}
<script>
document.addEventListener("DOMContentLoaded", () => {
const themeToggleButton = document.getElementById("theme-toggle");
if (themeToggleButton) {
themeToggleButton.addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
});
} else {
console.error("Theme toggle button not found");
}
});
</script>
<script>
const observer = new MutationObserver(() => {
const themeToggleButton = document.getElementById("theme-toggle");
if (themeToggleButton) {
observer.disconnect(); // Stop observing once the button is found. Explanation :
/*
the .theme-toggle button is being rendered dynamically (e.g., via a Hugo partial or JavaScript),
so it might not exist in the DOM when the script runs.
To handle this, you can use a MutationObserver to detect when the button is added to the DOM
*/
themeToggleButton.addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
});
}
});
observer.observe(document.body, { childList: true, subtree: true });
</script>
{{- end }}
</footer>
</html>

View file

@ -0,0 +1,2 @@
{{- /* formats .Content headings by adding an anchor */ -}}
{{ . | replaceRE "(<h[1-6] id=\"([^\"]+)\".+)(</h[1-6]+>)" "${1}<a hidden class=\"anchor\" aria-hidden=\"true\" href=\"#${2}\">#</a>${3}" | safeHTML }}

9
layouts/partials/author.html Executable file
View file

@ -0,0 +1,9 @@
{{- if or .Params.author site.Params.author }}
{{- $author := (.Params.author | default site.Params.author) }}
{{- $author_type := (printf "%T" $author) }}
{{- if (or (eq $author_type "[]string") (eq $author_type "[]interface {}")) }}
{{- (delimit $author ", " ) }}
{{- else }}
{{- $author }}
{{- end }}
{{- end -}}

View file

@ -0,0 +1,19 @@
{{- if (.Param "ShowBreadCrumbs") -}}
<div class="breadcrumbs">
{{- $url := replace .Parent.Permalink (printf "%s" site.Home.Permalink) "" }}
{{- $lang_url := strings.TrimPrefix (printf "%s/" .Lang) $url -}}
<a href="{{ "" | absLangURL }}">{{ i18n "home" | default "Home" }}</a>
{{- $scratch := newScratch }}
{{- range $index, $element := split $lang_url "/" }}
{{- $scratch.Add "path" (printf "%s/" $element )}}
{{- $bc_pg := site.GetPage ($scratch.Get "path") -}}
{{- if (and ($bc_pg) (gt (len . ) 0))}}
{{- print "&nbsp;»&nbsp;" | safeHTML -}}<a href="{{ $bc_pg.Permalink }}">{{ $bc_pg.Name }}</a>
{{- end }}
{{- end -}}
</div>
{{- end -}}

34
layouts/partials/buttons.html Executable file
View file

@ -0,0 +1,34 @@
<style>
.buttons {
display: flex;
flex-wrap: wrap;
justify-content: center;
max-width: 100vw; /* Make the container as wide as the viewport */
gap: 3px;
margin: 20px 0 0 0; /* Remove any default margin */
padding: 0; /* Remove any default padding */
}
.button {
display: inline-block;
border: none;
margin: 0;
padding: 0;
border-radius: 0;
background: none;
image-rendering: auto;
image-rendering: crisp-edges;
image-rendering: pixelated;
image-rendering: -webkit-optimize-contrast;
}
</style>
<div class="buttons"> <!-- https://88x31.nl/ -->
<a href="https://www.mozilla.org/fr/firefox/new/"> <img class="button" src="/buttons/firefox-now.png" alt="Bouton Firefox" title="Ils ont été vilains tho"/></a>
<a href="https://www.blender.org/download/"> <img class="button" src="/buttons/get-blender-2.8.png" alt="Bouton Blender" title="Je connais les raccourcis clavier"/></a>
<a href="https://xkcd.com/1179/"> <img class="button" src="/buttons/iso-8601.png" alt="Bouton ISO 8601" title="Par pitié, tout le monde pareil"/></a>
<a href="https://notepad-plus-plus.org/"> <img class="button" src="/buttons/made-with-notepad++.png" alt="Bouton Notepad++" title="Je veux le même pour Linux"/></a>
<a href="https://polymc.org/"> <img class="button" src="/buttons/minecraft.png" alt="Bouton Minecraft" title="Tfarcenim TMTC"/></a>
<a href="https://teegarten-miniatures.ch/"> <img class="button" src="/buttons/tea-powered.png" alt="Bouton Tea Powered" title="Nan vraiment, j'aime bien le thé"/></a>
<a href="https://ubuntu.com/download"> <img class="button" src="/buttons/ubuntu.png" alt="Bouton Ubuntu" title="Ce site vous est servi depuis Ubuntu"/></a>
<a href="https://www.linuxmint.com/"> <img class="button" src="/buttons/devOnMintGreen.png" alt="Bouton Linux Mint" title="Ce site a été développé sur Linux Mint"/></a>
</div>

0
layouts/partials/comments.html Executable file
View file

65
layouts/partials/cover.html Executable file
View file

@ -0,0 +1,65 @@
{{- with .cxt}} {{/* Apply proper context from dict */}}
{{- if (and .Params.cover.image (not $.isHidden)) }}
<figure class="entry-cover">
{{- $loading := cond $.IsSingle "eager" "lazy" }}
{{- $addLink := (and site.Params.cover.linkFullImages $.IsSingle) }}
{{- $prod := (hugo.IsProduction | or (eq site.Params.env "production")) }}
{{- $alt := (.Params.cover.alt | default .Params.cover.caption | plainify) }}
{{- $responsiveImages := (.Params.cover.responsiveImages | default site.Params.cover.responsiveImages) | default true }}
{{- $pageBundleCover := (.Resources.ByType "image").GetMatch (printf "*%s*" (.Params.cover.image)) }}
{{- $globalResourcesCover := (resources.ByType "image").GetMatch (printf "*%s*" (.Params.cover.image)) }}
{{- $cover := (or $pageBundleCover $globalResourcesCover)}}
{{- /* We are not using the .Param.cover.relative to decide the location of image */}}
{{- /* If we have the image in pageBundle or globalResources we can process the image */}}
{{- $sizes := (slice "360" "480" "720" "1080" "1500") }}
{{- $processableFormats := (slice "jpg" "jpeg" "png" "tif" "bmp" "gif") -}}
{{- if hugo.IsExtended -}}
{{- $processableFormats = $processableFormats | append "webp" -}}
{{- end -}}
{{- $imgdl := (.Params.cover.image) | absURL }}
{{- if $cover -}}
{{- $imgdl = $cover.Permalink }}
{{- end -}}
{{- if $addLink }}
<a href="{{ $imgdl }}" target="_blank" rel="noopener noreferrer">
{{- end }}
{{- if $cover -}}
{{/* i.e it is present in page bundle */}}
{{- if (and (in $processableFormats $cover.MediaType.SubType) ($responsiveImages) (eq $prod true)) }}
<img loading="{{$loading}}"
srcset='{{- range $size := $sizes -}}
{{- if (ge $cover.Width $size) }}
{{- printf "%s %s" (($cover.Resize (printf "%sx" $size)).Permalink) (printf "%sw," $size) }}
{{- end }}
{{- end }}
{{- printf "%s %dw" ($cover.Permalink) ($cover.Width) }}'
src="{{ $cover.Permalink }}"
sizes="(min-width: 768px) 720px, 100vw"
width="{{ $cover.Width }}" height="{{ $cover.Height }}"
alt="{{ $alt }}">
{{- else }}{{/* Unprocessable image or responsive images disabled */}}
<img loading="{{ $loading }}" src="{{ $imgdl }}" alt="{{ $alt }}">
{{- end }}
{{- else }}
{{- /* For absolute urls and external links, no img processing here */}}
<img loading="{{ $loading }}" src="{{ $imgdl }}" alt="{{ $alt }}">
{{- end }}
{{- if $addLink }}
</a>
{{- end -}}
{{- /* Display Caption */}}
{{- if $.IsSingle }}
{{ with .Params.cover.caption -}}
<figcaption>{{ . | markdownify }}</figcaption>
{{- end }}
{{- end }}
</figure>
{{- end }}{{/* End image */}}
{{- end -}}{{/* End context */ -}}

View file

@ -0,0 +1,28 @@
<!--
Code volé chez lucien
https://git.shenanigans.cc/globuzma/blog/commit/695e63b275ca03ec53a099d68f274c9466d0539f
-->
<span class="small-text" id="data-used">0kB chargés</span>
<script>
window.addEventListener('load', function () {
let totalTransferSize = 0;
performance.getEntriesByType('resource').map((resource) => {
const data = resource.toJSON();
totalTransferSize += data.transferSize;
});
console.log((totalTransferSize / 1024)/1024)
console.log(totalTransferSize/(1024*1024))
sizeString = totalTransferSize + "B"
if( totalTransferSize / (1024*1024) > 1) {
sizeString = Math.round(100*totalTransferSize/(1024*1024))/100 + "MB"
} else if (totalTransferSize / 1024 > 1) {
sizeString = Math.round(100*totalTransferSize / 1024)/100 + "kB"
}
document.getElementById("data-used").innerHTML = "<em>" + sizeString + "</em> chargés"
})
</script>

View file

@ -0,0 +1,8 @@
{{- if and (or .Params.editPost.URL site.Params.editPost.URL) (not (.Param "editPost.disabled")) -}}
{{- $fileUrlPath := path.Join .File.Path }}
{{- if or .Params.author site.Params.author (.Param "ShowReadingTime") (not .Date.IsZero) .IsTranslated }}&nbsp;|&nbsp;{{- end -}}
<a href="{{ .Params.editPost.URL | default site.Params.editPost.URL }}{{ if .Params.editPost.appendFilePath | default ( site.Params.editPost.appendFilePath | default false ) }}/{{ $fileUrlPath }}{{ end }}" rel="noopener noreferrer" target="_blank">
{{- .Params.editPost.Text | default (site.Params.editPost.Text | default (i18n "edit_post" | default "Edit")) -}}
</a>
{{- end }}

View file

@ -0,0 +1,106 @@
<!-- Pour montrer des infos sur le livre sur la page -->
<style>
.encadre-livre {
width: 300px;
padding: 10px;
border: 1px solid #ccc;
float: right;
margin-left: 20px;
clear: right;
box-sizing: border-box;
overflow: hidden;
}
.encadre-livre .title {
text-align: center;
margin: 0 0 20px 0;
}
.encadre-livre figure img {
margin-left: auto;
margin-right: auto;
}
</style>
{{ $specs := .Page.Params.BookData }}
{{ if $specs }}
<div class="encadre-livre">
<h3 class="title">{{$specs.title}}</h3>
<figure>
{{- if $specs.cover -}}
<!-- First try to get the image as a page resource (for page bundles) -->
{{- $coverResource := .Page.Resources.GetMatch $specs.cover -}}
{{- if not $coverResource -}}
<!-- If not found in page resources, try the global assets directory -->
{{- $coverResource = resources.Get $specs.cover -}}
{{- end -}}
{{- if $coverResource -}}
{{- $thumbCover := $coverResource.Fit "200x200 webp q85" -}}
<img src="{{ $thumbCover.RelPermalink }}" alt="1ère de couverture de {{ $specs.title }} par {{ $specs.author }}">
{{- else -}}
<!-- Cover resource not found anywhere -->
<div class="error">Image non trouvée : {{ $specs.cover }}</div>
{{- end -}}
{{- else -}}
<!-- No cover specified in frontmatter -->
<div class="error">No cover image specified</div>
{{- end -}}
</figure>
<table>
<tbody>
{{ if $specs.publishDate }}
<tr>
<th>Date de publication</th>
<td>{{ $specs.publishDate }}</td>
</tr>
{{ end }}
{{ if $specs.author }}
<tr>
<th>Auteur</th>
<td>{{ $specs.author }}</td>
</tr>
{{ end }}
{{ if $specs.ISBN }}
<tr>
<th>ISBN</th>
<td>{{ $specs.ISBN }}</td>
</tr>
{{ end }}
{{ if $specs.worldCat }}
<tr>
<th colspan="2">
<a href="{{ $specs.worldCat }}">Lien WorldCat</a>
</th>
</tr>
{{ end }}
{{ if $specs.starGrade }}
<tr>
<th>Note perso</th>
<td>
{{ range seq 1 $specs.starGrade }}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 441" width="16px" height="16px">
<path d="M 48 261 L 228 430 L 48 261 L 228 430 Q 240 441 256 441 Q 272 441 284 430 L 464 261 L 464 261 Q 511 217 512 152 L 512 146 L 512 146 Q 511 92 478 54 Q 445 15 393 5 Q 358 0 325 10 Q 293 20 268 45 L 256 57 L 256 57 L 244 45 L 244 45 Q 219 20 187 10 Q 154 0 119 5 Q 67 15 34 54 Q 1 92 0 146 L 0 152 L 0 152 Q 1 217 48 261 L 48 261 Z" />
</svg>
{{ end }}
{{ if ne $specs.starGrade 5 }}
{{ range seq 1 (sub 5 $specs.starGrade) }}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 445" width="16px" height="16px">
<path d="M 226 433 L 223 431 L 226 433 L 223 431 L 48 268 L 48 268 Q 1 223 0 158 L 0 155 L 0 155 Q 1 101 34 61 Q 66 22 119 11 Q 181 0 231 35 Q 245 44 256 57 Q 262 50 270 44 Q 275 39 281 35 Q 281 35 281 35 Q 281 35 281 35 Q 331 0 393 10 Q 446 21 478 61 Q 511 101 512 155 L 512 158 L 512 158 Q 511 223 464 268 L 289 431 L 289 431 L 286 433 L 286 433 Q 273 445 256 445 Q 239 445 226 433 L 226 433 Z M 239 110 Q 239 110 238 109 L 238 109 L 238 109 Q 238 109 238 109 L 220 89 L 220 89 L 220 89 L 220 89 Q 220 89 220 89 Q 202 69 178 61 Q 154 53 128 58 Q 93 65 71 92 Q 49 118 48 155 L 48 158 L 48 158 Q 49 202 81 233 L 256 396 L 256 396 L 431 233 L 431 233 Q 463 202 464 158 L 464 155 L 464 155 Q 463 118 441 92 Q 419 65 384 58 Q 358 53 334 61 Q 310 69 292 89 Q 292 89 292 89 Q 292 89 292 89 L 274 109 L 274 109 Q 274 109 273 110 Q 273 110 273 110 Q 266 117 256 117 Q 246 117 239 110 L 239 110 Z" />
</svg>
{{ end }}
{{ end }}
</td>
</tr>
{{ end }}
</tbody>
</table>
</div>
{{ else }}
<div class="notice warning">
<p>Pas d'informations trouvées :(</p>
</div>
{{ end }}

View file

@ -0,0 +1,108 @@
<!-- Pour montrer des infos sur la machine sur la page -->
<style>
.encadre-maec {
width: 300px;
padding: 10px;
border: 1px solid #ccc;
float: right;
margin-left: 20px;
clear: right;
box-sizing: border-box;
overflow: hidden;
}
.encadre-maec .title {
text-align: center;
margin: 0 0 20px 0;
}
.encadre-maec figure img {
margin-left: auto;
margin-right: auto;
}
</style>
{{ $specs := .Page.Params.machineSpecs }}
{{ if $specs }}
<div class="encadre-maec">
<h3 class="title">{{$specs.make}} {{$specs.model}}</h3>
<figure>
{{- if $specs.image -}}
<!-- First try to get the image as a page resource (for page bundles) -->
{{- $imageResource := .Page.Resources.GetMatch $specs.image -}}
{{- if not $imageResource -}}
<!-- If not found in page resources, try the global assets directory -->
{{- $imageResource = resources.Get $specs.image -}}
{{- end -}}
{{- if $imageResource -}}
{{- $thumbimage := $imageResource.Fit "200x200 webp q85" -}}
<img src="{{ $thumbimage.RelPermalink }}" alt="1ère de couverture de {{ $specs.title }} par {{ $specs.author }}">
{{- else -}}
<!-- image resource not found anywhere -->
<div class="error">Image non trouvée : {{ $specs.image }}</div>
{{- end -}}
{{- else -}}
<!-- No image specified in frontmatter -->
<div class="error">No image image specified</div>
{{- end -}}
</figure>
<table>
<tbody>
{{ if $specs.make }}
<tr>
<th>Marque</th>
<td>{{ $specs.make }}</td>
</tr>
{{ end }}
{{ if $specs.model }}
<tr>
<th>Modèle</th>
<td>{{ $specs.model }}</td>
</tr>
{{ end }}
{{ if $specs.type }}
<tr>
<th>Type</th>
<td>{{ $specs.type }}</td>
</tr>
{{ end }}
{{ if $specs.dateManufactured }}
<tr>
<th>Date de fabrication</th>
<td>{{ $specs.dateManufactured }}</td>
</tr>
{{ end }}
{{ if $specs.massKg }}
<tr>
<th>Masse</th>
<td>{{ $specs.massKg }} kg</td>
</tr>
{{ end }}
{{ if $specs.widthCm }}
<tr>
<th>Largeur</th>
<td>{{ $specs.widthCm }} cm</td>
</tr>
{{ end }}
{{ if $specs.serialNumber }}
<tr>
<th>N° de série</th>
<td>{{ $specs.serialNumber }}</td>
</tr>
{{ end }}
{{ if $specs.linkTpdb }}
<tr>
<th colspan="2">
<a href="{{ $specs.linkTpdb }}">Typewriter Database</a>
</th>
</tr>
{{ end }}
</tbody>
</table>
</div>
{{ else }}
<div class="notice warning">
<p>Pas d'informations trouvées :(</p>
</div>
{{ end }}

View file

@ -0,0 +1,3 @@
{{- /* Footer custom content area start */ -}}
{{- /* Insert any custom code web-analytics, resources, etc. here */ -}}
{{- /* Footer custom content area end */ -}}

View file

@ -0,0 +1,4 @@
{{- /* Head custom content area start */ -}}
{{- /* Insert any custom code (web-analytics, resources, etc.) - it will appear in the <head></head> section of every page. */ -}}
{{- /* Can be overwritten by partial with the same name in the global layouts. */ -}}
{{- /* Head custom content area end */ -}}

185
layouts/partials/footer.html Executable file
View file

@ -0,0 +1,185 @@
{{- if not (.Param "hideFooter") }}
<footer class="footer">
{{- if not site.Params.footer.hideCopyright }}
{{- if site.Copyright }}
<span>{{ site.Copyright | markdownify }}</span>
{{- else }}
<span>&copy; {{ now.Year }} <a href="{{ "" | absLangURL }}">{{ site.Title }}</a></span>
{{- end }}
{{- print " · "}}
{{- end }}
{{- with site.Params.footer.text }}
{{ . | markdownify }}
{{- print " · "}}
{{- end }}
{{- partial "donnees-chargement.html" -}}
{{- print " · "}}
<!-- Lord forgive me for I have sinned -->
<style>
.rss-icon path {
stroke: var(--primary);
}
.rss-link {
color: var(--primary);
}
</style>
<a href="/feed.xml" class="rss-link">
<svg width="16px" height="16px" stroke-width="2" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" class="rss-icon">
<path d="M12 19C12 14.8 9.2 12 5 12" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M19 19C19 10.6 13.4 5 5 5" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"></path>
<path d="M5 19.01L5.01 18.9989" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<span>Flux RSS</span>
</a>
{{- print " · "}}
{{ with (readFile "data/gitinfo.txt") }}
{{ $raw := . }}
{{ $lines := slice }}
{{ range split (replace $raw "\r\n" "\n") "\n" }}
{{ if ne . "" }}
{{ $lines = $lines | append . }}
{{ end }}
{{ end }}
{{ if ge (len $lines) 4 }}
<span>
Mis à jour le {{ index $lines 0 }} à {{ index $lines 1 }}
</span>
{{ else }}
<span>Information de mise à jour non disponible</span>
{{ end }}
{{ else }}
<span>Fichier gitinfo non trouvé</span>
{{ end }}
</footer>
{{- end }}
{{- if (not site.Params.disableScrollToTop) }}
<a href="#top" aria-label="go to top" title="Go to Top (Alt + G)" class="top-link" id="top-link" accesskey="g">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 6" fill="currentColor">
<path d="M12 6H0l6-6z" />
</svg>
</a>
{{- end }}
{{- partial "extend_footer.html" . }}
<script>
let menu = document.getElementById('menu')
if (menu) {
menu.scrollLeft = localStorage.getItem("menu-scroll-position");
menu.onscroll = function () {
localStorage.setItem("menu-scroll-position", menu.scrollLeft);
}
}
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener("click", function (e) {
e.preventDefault();
var id = this.getAttribute("href").substr(1);
if (!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView({
behavior: "smooth"
});
} else {
document.querySelector(`[id='${decodeURIComponent(id)}']`).scrollIntoView();
}
if (id === "top") {
history.replaceState(null, null, " ");
} else {
history.pushState(null, null, `#${id}`);
}
});
});
</script>
{{- if (not site.Params.disableScrollToTop) }}
<script>
var mybutton = document.getElementById("top-link");
window.onscroll = function () {
if (document.body.scrollTop > 800 || document.documentElement.scrollTop > 800) {
mybutton.style.visibility = "visible";
mybutton.style.opacity = "1";
} else {
mybutton.style.visibility = "hidden";
mybutton.style.opacity = "0";
}
};
</script>
{{- end }}
{{- if (not site.Params.disableThemeToggle) }}
<script>
document.getElementById("theme-toggle").addEventListener("click", () => {
if (document.body.className.includes("dark")) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", 'light');
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", 'dark');
}
})
</script>
{{- end }}
{{- if (and (eq .Kind "page") (ne .Layout "archives") (ne .Layout "search") (.Param "ShowCodeCopyButtons")) }}
<script>
document.querySelectorAll('pre > code').forEach((codeblock) => {
const container = codeblock.parentNode.parentNode;
const copybutton = document.createElement('button');
copybutton.classList.add('copy-code');
copybutton.innerHTML = '{{- i18n "code_copy" | default "copy" }}';
function copyingDone() {
copybutton.innerHTML = '{{- i18n "code_copied" | default "copied!" }}';
setTimeout(() => {
copybutton.innerHTML = '{{- i18n "code_copy" | default "copy" }}';
}, 2000);
}
copybutton.addEventListener('click', (cb) => {
if ('clipboard' in navigator) {
navigator.clipboard.writeText(codeblock.textContent);
copyingDone();
return;
}
const range = document.createRange();
range.selectNodeContents(codeblock);
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
try {
document.execCommand('copy');
copyingDone();
} catch (e) { };
selection.removeRange(range);
});
if (container.classList.contains("highlight")) {
container.appendChild(copybutton);
} else if (container.parentNode.firstChild == container) {
// td containing LineNos
} else if (codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.nodeName == "TABLE") {
// table containing LineNos and code
codeblock.parentNode.parentNode.parentNode.parentNode.parentNode.appendChild(copybutton);
} else {
// code blocks not having highlight as parent class
codeblock.parentNode.appendChild(copybutton);
}
});
</script>
{{- end }}

155
layouts/partials/head.html Executable file
View file

@ -0,0 +1,155 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{{- if hugo.IsProduction | or (eq site.Params.env "production") | and (ne .Params.robotsNoIndex true) }}
<meta name="robots" content="index, follow">
{{- else }}
<meta name="robots" content="noindex, nofollow">
{{- end }}
{{- /* Title */}}
<title>{{ if .IsHome }}{{ else }}{{ if .Title }}{{ .Title }} | {{ end }}{{ end }}{{ site.Title }}</title>
{{- /* Meta */}}
{{- if .IsHome }}
{{ with site.Params.keywords -}}<meta name="keywords" content="{{- range $i, $e := . }}{{ if $i }}, {{ end }}{{ $e }}{{ end }}">{{ end }}
{{- else }}
<meta name="keywords" content="{{ if .Params.keywords -}}
{{- range $i, $e := .Params.keywords }}{{ if $i }}, {{ end }}{{ $e }}{{ end }} {{- else }}
{{- range $i, $e := .Params.tags }}{{ if $i }}, {{ end }}{{ $e }}{{ end }} {{- end -}}">
{{- end }}
<meta name="description" content="{{- with .Description }}{{ . }}{{- else }}{{- if or .IsPage .IsSection}}
{{- .Summary | default (printf "%s - %s" .Title site.Title) }}{{- else }}
{{- with site.Params.description }}{{ . }}{{- end }}{{- end }}{{- end -}}">
<meta name="author" content="{{ (partial "author.html" . ) }}">
<link rel="canonical" href="{{ if .Params.canonicalURL -}} {{ trim .Params.canonicalURL " " }} {{- else -}} {{ .Permalink }} {{- end }}">
{{- if site.Params.analytics.google.SiteVerificationTag }}
<meta name="google-site-verification" content="{{ site.Params.analytics.google.SiteVerificationTag }}">
{{- end }}
{{- if site.Params.analytics.yandex.SiteVerificationTag }}
<meta name="yandex-verification" content="{{ site.Params.analytics.yandex.SiteVerificationTag }}">
{{- end }}
{{- if site.Params.analytics.bing.SiteVerificationTag }}
<meta name="msvalidate.01" content="{{ site.Params.analytics.bing.SiteVerificationTag }}">
{{- end }}
{{- if site.Params.analytics.naver.SiteVerificationTag }}
<meta name="naver-site-verification" content="{{ site.Params.analytics.naver.SiteVerificationTag }}">
{{- end }}
{{- /* Styles */}}
{{- /* includes */}}
{{- $includes := slice }}
{{- $includes = $includes | append (" " | resources.FromString "includes-blank.css")}}
{{- if not (eq site.Params.assets.disableScrollBarStyle true) }}
{{- $ScrollStyle := (resources.Get "css/includes/scroll-bar.css") }}
{{- $includes = (append $ScrollStyle $includes) }}
{{- end }}
{{- $includes_all := $includes | resources.Concat "includes.css" }}
{{- $theme_vars := (resources.Get "css/core/theme-vars.css") }}
{{- $reset := (resources.Get "css/core/reset.css") }}
{{- $media := (resources.Get "css/core/zmedia.css") }}
{{- $common := (resources.Match "css/common/*.css") | resources.Concat "common.css" }}
{{- /* markup.highlight.noClasses should be set to `false` */}}
{{- $chroma_styles := (resources.Get "css/includes/chroma-styles.css") }}
{{- $chroma_mod := (resources.Get "css/includes/chroma-mod.css") }}
{{- /* order is important */}}
{{- $core := (slice $theme_vars $reset $common $chroma_styles $chroma_mod $includes_all $media) | resources.Concat "core.css" | resources.Minify }}
{{- $extended := (resources.Match "css/extended/*.css") | resources.Concat "extended.css" | resources.Minify }}
{{- /* bundle all required css */}}
{{- /* Add extended css after theme style */ -}}
{{- $stylesheet := (slice $core $extended) | resources.Concat "stylesheet.css" }}
{{- if not site.Params.assets.disableFingerprinting }}
{{- $stylesheet := $stylesheet | fingerprint }}
<link crossorigin="anonymous" href="{{ $stylesheet.RelPermalink }}" integrity="{{ $stylesheet.Data.Integrity }}" rel="preload stylesheet" as="style">
{{- else }}
<link crossorigin="anonymous" href="{{ $stylesheet.RelPermalink }}" rel="preload stylesheet" as="style">
{{- end }}
{{- /* Search */}}
{{- if (eq .Layout `search`) -}}
<link crossorigin="anonymous" rel="preload" as="fetch" href="../index.json">
{{- $fastsearch := resources.Get "js/fastsearch.js" | js.Build (dict "params" (dict "fuseOpts" site.Params.fuseOpts)) | resources.Minify }}
{{- $fusejs := resources.Get "js/fuse.basic.min.js" }}
{{- if not site.Params.assets.disableFingerprinting }}
{{- $search := (slice $fusejs $fastsearch ) | resources.Concat "search.js" | fingerprint }}
<script defer crossorigin="anonymous" src="{{ $search.RelPermalink }}" integrity="{{ $search.Data.Integrity }}"></script>
{{- else }}
{{- $search := (slice $fusejs $fastsearch ) | resources.Concat "search.js" }}
<script defer crossorigin="anonymous" src="{{ $search.RelPermalink }}"></script>
{{- end }}
{{- end -}}
{{- /* Favicons */}}
<link rel="icon" href="{{ site.Params.assets.favicon | default "favicon.ico" | absURL }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ site.Params.assets.favicon16x16 | default "favicon-16x16.png" | absURL }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ site.Params.assets.favicon32x32 | default "favicon-32x32.png" | absURL }}">
<link rel="apple-touch-icon" href="{{ site.Params.assets.apple_touch_icon | default "apple-touch-icon.png" | absURL }}">
<link rel="mask-icon" href="{{ site.Params.assets.safari_pinned_tab | default "safari-pinned-tab.svg" | absURL }}">
<meta name="theme-color" content="{{ site.Params.assets.theme_color | default "#2e2e33" }}">
<meta name="msapplication-TileColor" content="{{ site.Params.assets.msapplication_TileColor | default "#2e2e33" }}">
{{- /* RSS */}}
{{ range .AlternativeOutputFormats -}}
<link rel="{{ .Rel }}" type="{{ .MediaType.Type | html }}" href="{{ .Permalink | safeURL }}">
{{ end -}}
{{- range .AllTranslations -}}
<link rel="alternate" hreflang="{{ .Lang }}" href="{{ .Permalink }}">
{{ end -}}
<noscript>
<style>
#theme-toggle,
.top-link {
display: none;
}
</style>
{{- if (and (ne site.Params.defaultTheme "light") (ne site.Params.defaultTheme "dark")) }}
<style>
@media (prefers-color-scheme: dark) {
:root {
--theme: rgb(29, 30, 32);
--entry: rgb(46, 46, 51);
--primary: rgb(218, 218, 219);
--secondary: rgb(155, 156, 157);
--tertiary: rgb(65, 66, 68);
--content: rgb(196, 196, 197);
--code-block-bg: rgb(46, 46, 51);
--code-bg: rgb(55, 56, 62);
--border: rgb(51, 51, 51);
}
.list {
background: var(--theme);
}
.list:not(.dark)::-webkit-scrollbar-track {
background: 0 0;
}
.list:not(.dark)::-webkit-scrollbar-thumb {
border-color: var(--theme);
}
}
</style>
{{- end }}
</noscript>
{{- partial "extend_head.html" . -}}
{{- /* Misc */}}
{{- if hugo.IsProduction | or (eq site.Params.env "production") }}
{{- template "_internal/google_analytics.html" . }}
{{- template "partials/templates/opengraph.html" . }}
{{- template "partials/templates/twitter_cards.html" . }}
{{- template "partials/templates/schema_json.html" . }}
{{- end -}}

121
layouts/partials/header.html Executable file
View file

@ -0,0 +1,121 @@
{{- /* theme-toggle is enabled */}}
{{- if (not site.Params.disableThemeToggle) }}
{{- /* theme is light */}}
{{- if (eq site.Params.defaultTheme "light") }}
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
}
</script>
{{- /* theme is dark */}}
{{- else if (eq site.Params.defaultTheme "dark") }}
<script>
if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
}
</script>
{{- else }}
{{- /* theme is auto */}}
<script>
if (localStorage.getItem("pref-theme") === "dark") {
document.body.classList.add('dark');
} else if (localStorage.getItem("pref-theme") === "light") {
document.body.classList.remove('dark')
} else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
{{- end }}
{{- /* theme-toggle is disabled and theme is auto */}}
{{- else if (and (ne site.Params.defaultTheme "light") (ne site.Params.defaultTheme "dark"))}}
<script>
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.body.classList.add('dark');
}
</script>
{{- end }}
{{- if (not site.Params.disableThemeToggle) }}
<script>
// Initialize all theme toggle buttons when the DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
const themeToggles = document.querySelectorAll('.theme-toggle-button');
themeToggles.forEach(function(button) {
button.addEventListener('click', function() {
if (document.body.classList.contains('dark')) {
document.body.classList.remove('dark');
localStorage.setItem("pref-theme", "light");
} else {
document.body.classList.add('dark');
localStorage.setItem("pref-theme", "dark");
}
});
});
});
</script>
{{- end }}
<header class="header">
<nav class="nav">
<div class="logo">
{{- $label_text := (site.Params.label.text | default site.Title) }}
{{- if site.Title }}
<a href="{{ "" | absLangURL }}" accesskey="h" title="{{ $label_text }} (Alt + H)">
{{- if site.Params.label.icon }}
{{- $img := resources.Get site.Params.label.icon }}
{{- if $img }}
{{- $processableFormats := (slice "jpg" "jpeg" "png" "tif" "bmp" "gif") -}}
{{- if hugo.IsExtended -}}
{{- $processableFormats = $processableFormats | append "webp" -}}
{{- end -}}
{{- $prod := (hugo.IsProduction | or (eq site.Params.env "production")) }}
{{- if and (in $processableFormats $img.MediaType.SubType) (eq $prod true)}}
{{- if site.Params.label.iconHeight }}
{{- $img = $img.Resize (printf "x%d" site.Params.label.iconHeight) }}
{{ else }}
{{- $img = $img.Resize "x30" }}
{{- end }}
{{- end }}
<img src="{{ $img.Permalink }}" alt="" aria-label="logo"
height="{{- site.Params.label.iconHeight | default "30" -}}">
{{- else }}
<img src="{{- site.Params.label.icon | absURL -}}" alt="" aria-label="logo"
height="{{- site.Params.label.iconHeight | default "30" -}}">
{{- end -}}
{{- else if hasPrefix site.Params.label.iconSVG "<svg" }}
{{ site.Params.label.iconSVG | safeHTML }}
{{- end -}}
{{- $label_text -}}
<img src="/favicon.svg" alt="favicon" class="site-logo">
</a>
{{- end }}
</div>
{{- $currentPage := . }}
<!-- Desktop menu -->
<div class="menu-wrapper">
{{ partial "menu.html" }}
</div>
<!-- Hamburger Menu -->
<!-- Icon -->
<label for="menu-toggle" class="hamburger-menu" aria-label="Toggle menu">
<img src="/icons/hamburger-menu.svg" alt="Menu" width="24" height="24">
</label>
<!-- Hidden checkbox for toggling menu -->
<input type="checkbox" id="menu-toggle">
<!-- Menu overlay -->
<div class="menu-overlay">
<div class="mobile-menu">
<label for="menu-toggle" class="mobile-menu-close" aria-label="Close menu">
<img src="/icons/close-menu.svg" alt="Close Menu" width="24" height="24">
</label>
{{ partial "menu.html" }}
</div>
</div>
</nav>
</header>

13
layouts/partials/home_info.html Executable file
View file

@ -0,0 +1,13 @@
{{- with site.Params.homeInfoParams }}
<article class="first-entry home-info">
<header class="entry-header">
<h1>{{ .Title | markdownify }}</h1>
</header>
<div class="entry-content">
{{ .Content | markdownify }}
</div>
<footer class="entry-footer">
{{ partial "social_icons.html" (dict "align" site.Params.homeInfoParams.AlignSocialIconsTo) }}
</footer>
</article>
{{- end -}}

View file

@ -0,0 +1,58 @@
<div class="profile">
{{- with site.Params.profileMode }}
<div class="profile_inner">
{{- if .imageUrl -}}
{{- $img := "" }}
{{- if not (urls.Parse .imageUrl).IsAbs }}
{{- $img = resources.Get .imageUrl }}
{{- end }}
{{- if $img }}
{{- $processableFormats := (slice "jpg" "jpeg" "png" "tif" "bmp" "gif") -}}
{{- if hugo.IsExtended -}}
{{- $processableFormats = $processableFormats | append "webp" -}}
{{- end -}}
{{- $prod := (hugo.IsProduction | or (eq site.Params.env "production")) }}
{{- if and (in $processableFormats $img.MediaType.SubType) (eq $prod true)}}
{{- if (not (and (not .imageHeight) (not .imageWidth))) }}
{{- $img = $img.Resize (printf "%dx%d" .imageWidth .imageHeight) }}
{{- else if .imageHeight }}
{{- $img = $img.Resize (printf "x%d" .imageHeight) }}
{{ else if .imageWidth }}
{{- $img = $img.Resize (printf "%dx" .imageWidth) }}
{{ else }}
{{- $img = $img.Resize "150x150" }}
{{- end }}
{{- end }}
<img draggable="false" src="{{ $img.Permalink }}" alt="{{ .imageTitle | default "profile image" }}" title="{{ .imageTitle }}"
height="{{ .imageHeight | default 150 }}" width="{{ .imageWidth | default 150 }}" />
{{- else }}
<img draggable="false" src="{{ .imageUrl | absURL }}" alt="{{ .imageTitle | default "profile image" }}" title="{{ .imageTitle }}"
height="{{ .imageHeight | default 150 }}" width="{{ .imageWidth | default 150 }}" />
{{- end }}
{{- end }}
<h1>{{ .title | default site.Title | markdownify }}</h1>
<span>{{ .subtitle | markdownify }}</span>
{{- partial "social_icons.html" -}}
{{- with .buttons }}
<div class="buttons">
{{- range . }}
<a class="button" href="{{ trim .url " " }}" rel="noopener" title="{{ .name }}">
<span class="button-inner">
{{ .name }}
{{- if (findRE "://" .url) }}&nbsp;
<svg fill="none" shape-rendering="geometricPrecision" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2.5" viewBox="0 0 24 24" height="14" width="14">
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"></path>
<path d="M15 3h6v6"></path>
<path d="M10 14L21 3"></path>
</svg>
{{- end }}
</span>
</a>
{{- end }}
</div>
{{- end }}
</div>
{{- end}}
</div>

91
layouts/partials/menu.html Executable file
View file

@ -0,0 +1,91 @@
<ul class="menu">
<li>
<a href="/blog">
<img class="icon" src="/icons/bulle.svg" alt="Blog">
<span>Blog</span>
</a>
</li>
<li>
<a href="/collection">
<img class="icon" src="/favicon.svg" alt="Machines">
<span>Machines</span>
</a>
</li>
<li>
<a href="/livres">
<img class="icon" src="/icons/livre.svg" alt="Lectures">
<span>Lectures</span>
</a>
</li>
<li>
<a href="/liens">
<img class="icon" src="/icons/lien.svg" alt="Liens">
<span>Liens</span>
</a>
</li>
<li>
<a href="/a-propos">
<img class="icon" src="/icons/a-propos.svg" alt="A propos">
<span>A propos</span>
</a>
</li>
<li>
<a href="/contact">
<img class="icon" src="/icons/lettre.svg" alt="Contact">
<span>Contact</span>
</a>
</li>
<li>
<a href="/feed.xml">
<img class="icon" src="/icons/rss.svg" alt="RSS">
<span>RSS</span>
</a>
</li>
<li>
<div class="logo-switches">
{{- if (not site.Params.disableThemeToggle) }}
<button class="theme-toggle-button" accesskey="t" title="(Alt + T)" aria-label="Toggle theme">
<svg class="moon-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
<svg class="sun-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="18" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</button>
{{- end }}
{{- $lang := .Lang}}
{{- with site.Home.Translations }}
<ul class="lang-switch">
{{- range . -}}
{{- if ne $lang .Lang }}
<li>
<a href="{{- .Permalink -}}" title="{{ .Language.Params.languageAltTitle | default (.Language.LanguageName | emojify) | default (.Lang | title) }}"
aria-label="{{ .Language.LanguageName | default (.Lang | title) }}">
{{- if (and site.Params.displayFullLangName (.Language.LanguageName)) }}
{{- .Language.LanguageName | emojify -}}
{{- else }}
{{- .Lang | title -}}
{{- end -}}
</a>
</li>
{{- end -}}
{{- end}}
</ul>
{{- end }}
</div>
</li>
</ul>

View file

@ -0,0 +1,9 @@
{{ if and (.Params.canonicalURL) (.Params.ShowCanonicalLink ) -}}
{{ $url := urls.Parse .Params.canonicalURL }}
{{- if or .Params.author site.Params.author (.Param "ShowReadingTime") (not .Date.IsZero) .IsTranslated (or .Params.editPost.URL site.Params.editPost.URL) }}&nbsp;|&nbsp;{{- end -}}
<span>
{{- (site.Params.CanonicalLinkText | default .Params.CanonicalLinkText) | default "Originally published at" -}}
&nbsp;<a href="{{ trim .Params.canonicalURL " " }}" title="{{ trim .Params.canonicalURL " " }}" target="_blank" rel="noopener noreferrer">{{ $url.Host }}</a>
</span>
{{- end }}

23
layouts/partials/post_meta.html Executable file
View file

@ -0,0 +1,23 @@
{{- $scratch := newScratch }}
{{- if not .Date.IsZero -}}
{{- $scratch.Add "meta" (slice (printf "<span title='%s'>%s</span>" (.Date) (.Date | time.Format (default "January 2, 2006" site.Params.DateFormat)))) }}
{{- end }}
{{- if (.Param "ShowReadingTime") -}}
{{- $scratch.Add "meta" (slice (i18n "read_time" .ReadingTime | default (printf "%d min" .ReadingTime))) }}
{{- end }}
{{- if (.Param "ShowWordCount") -}}
{{- $scratch.Add "meta" (slice (i18n "words" .WordCount | default (printf "%d words" .WordCount))) }}
{{- end }}
{{- if not (.Param "hideAuthor") -}}
{{- with (partial "author.html" .) }}
{{- $scratch.Add "meta" (slice .) }}
{{- end }}
{{- end }}
{{- with ($scratch.Get "meta") }}
{{- delimit . "&nbsp;·&nbsp;" | safeHTML -}}
{{- end -}}

View file

@ -0,0 +1,19 @@
{{- $pages := where site.RegularPages "Type" "in" site.Params.mainSections }}
{{- if and (gt (len $pages) 1) (in $pages . ) }}
<nav class="paginav">
{{- with $pages.Next . }}
<a class="prev" href="{{ .Permalink }}">
<span class="title">« {{ i18n "prev_page" }}</span>
<br>
<span>{{- .Name -}}</span>
</a>
{{- end }}
{{- with $pages.Prev . }}
<a class="next" href="{{ .Permalink }}">
<span class="title">{{ i18n "next_page" }} »</span>
<br>
<span>{{- .Name -}}</span>
</a>
{{- end }}
</nav>
{{- end }}

View file

@ -0,0 +1,141 @@
{{ $direction := .direction | default "up" }}
{{ $context := .context }}
<div class="scrolling-posts-container">
<div class="scrolling-posts-inner">
<div class="scrolling-posts {{ $direction }}-scroll">
{{- $pages := first 20 (sort (where $context.Site.RegularPages "Section" "ne" "") "Date" "desc") -}}
{{- range (sort $pages "Date" "desc") -}}
{{- $image := .Resources.GetMatch (printf "%s" .Params.cover.image) -}}
{{- if $image -}}
{{- $fittedImage := $image.Fill "400x400 smart webp q95" -}}
{{- $optimizedBlurredImage := $fittedImage.Filter (images.GaussianBlur 3) -}}
<a href="{{ .RelPermalink }}" class="scrolling-posts-item" style="background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0.2)), url('{{ $optimizedBlurredImage.RelPermalink }}');">
<span class="section-badge">{{ .Section }}</span>
<span class="scrolling-posts-item-title">{{ .Title }}</span>
<p class="scrolling-posts-date">{{ .Date.Format "2006-01-02" }}</p>
</a>
{{- end -}}
{{- end -}}
</div>
<div class="scrolling-posts {{ $direction }}-scroll">
{{- $pages := first 20 (sort (where $context.Site.RegularPages "Section" "ne" "") "Date" "desc") -}}
{{- range (sort $pages "Date" "desc") -}}
{{- $image := .Resources.GetMatch (printf "%s" .Params.cover.image) -}}
{{- if $image -}}
{{- $fittedImage := $image.Fill "400x400 smart webp q95" -}}
{{- $optimizedBlurredImage := $fittedImage.Filter (images.GaussianBlur 3) -}}
<a href="{{ .RelPermalink }}" class="scrolling-posts-item" style="background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.8), rgba(255, 255, 255, 0.2)), url('{{ $optimizedBlurredImage.RelPermalink }}');">
<span class="section-badge">{{ .Section }}</span>
<span class="scrolling-posts-item-title">{{ .Title }}</span>
<p class="scrolling-posts-date">{{ .Date.Format "2006-01-02" }}</p>
</a>
{{- end -}}
{{- end -}}
</div>
</div>
</div>
<style>
.scrolling-posts-container {
width: 100%;
border: none;
overflow: hidden;
height: 100%;
}
.scrolling-posts-inner {
display: flex;
flex-direction: column;
white-space: nowrap;
padding: 0;
margin: 0;
}
.scrolling-posts {
display: flex;
flex-direction: column;
gap: 1rem;
}
.scrolling-posts > a:nth-child(1) {
margin-top: 1rem;
}
.scrolling-posts-item {
padding: 10px;
border: solid 1px #ccc;
background: var(--entry);
border-radius: var(--radius);
border: 1px solid var(--border);
height: 100px;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.scrolling-posts-item-title {
font-size: 1em;
margin: 0;
color: #ccc;
font-weight: 400;
line-height: 1.5em;
text-decoration: none;
text-align: left;
overflow: hidden;
}
.scrolling-posts-date {
font-size: 0.8em;
color: #ccc;
margin: 0;
text-align: left;
}
.section-badge {
display: inline-block;
font-size: 0.8em;
padding: 2px 6px;
margin-right: 5px;
background-color: var(--theme);
border-radius: 3px;
color: var(--primary);
}
.up-scroll {
animation: scrollUp 50s linear infinite;
}
.down-scroll {
animation: scrollDown 50s linear infinite;
}
@keyframes scrollUp {
0% {
transform: translateY(0%);
}
100% {
transform: translateY(-100%);
}
}
@keyframes scrollDown {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(0);
}
}
</style>

View file

@ -0,0 +1,19 @@
{{ $n := 1 }} <!-- Change this value to set the number of posts to display -->
{{ range first $n (where .Site.RegularPages.ByDate.Reverse "Section" "blog") }}
{{- $image := .Resources.GetMatch (printf "%s" .Params.cover.image) -}}
{{- if $image -}}
{{- $optimizedImage := $image.Fill "100x100 webp q95 Center" -}}
<a href="{{ .RelPermalink }}" >
<h3>{{ .Title }}</h3>
<img src="{{ $optimizedImage.RelPermalink }}" alt="{{ .Title }} cover image"></img>
<small>{{ .Date.Format "January 2, 2006" }}</small>
<p>{{ .Summary | truncate 100 }}</p>
</a>
{{ end }}
{{ end }}

983
layouts/partials/svg.html Executable file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,47 @@
{{- $imgs := slice }}
{{- $imgParams := .Params.images }}
{{- $resources := .Resources.ByType "image" -}}
{{/* Find featured image resources if the images parameter is empty. */}}
{{- if not $imgParams }}
{{- $featured := $resources.GetMatch "*feature*" -}}
{{- if not $featured }}{{ $featured = $resources.GetMatch "{*cover*,*thumbnail*}" }}{{ end -}}
{{- with $featured }}
{{- $imgs = $imgs | append (dict
"Image" .
"RelPermalink" .RelPermalink
"Permalink" .Permalink) }}
{{- end }}
{{- end }}
{{/* Use the first one of site images as the fallback. */}}
{{- if and (not $imgParams) (not $imgs) }}
{{- with site.Params.images }}
{{- $imgParams = first 1 . }}
{{- end }}
{{- end }}
{{/* Parse page's images parameter. */}}
{{- range $imgParams }}
{{- $img := . }}
{{- $url := urls.Parse $img }}
{{- if eq $url.Scheme "" }}
{{/* Internal image. */}}
{{- with $resources.GetMatch $img -}}
{{/* Image resource. */}}
{{- $imgs = $imgs | append (dict
"Image" .
"RelPermalink" .RelPermalink
"Permalink" .Permalink) }}
{{- else }}
{{- $imgs = $imgs | append (dict
"RelPermalink" (relURL $img)
"Permalink" (absURL $img)
) }}
{{- end }}
{{- else }}
{{/* External image */}}
{{- $imgs = $imgs | append (dict
"RelPermalink" $img
"Permalink" $img
) }}
{{- end }}
{{- end }}
{{- return $imgs }}

View file

@ -0,0 +1,86 @@
<meta property="og:url" content="{{ .Permalink }}">
{{- with or site.Title site.Params.title | plainify }}
<meta property="og:site_name" content="{{ . }}">
{{- end }}
{{- with or .Title site.Title site.Params.title | plainify }}
<meta property="og:title" content="{{ . }}">
{{- end }}
{{- with or .Description .Summary site.Params.description | plainify | htmlUnescape | chomp }}
<meta property="og:description" content="{{ . }}">
{{- end }}
{{- with or .Params.locale site.Language.LanguageCode site.Language.Lang }}
<meta property="og:locale" content="{{ . }}">
{{- end }}
{{- if .IsPage }}
<meta property="og:type" content="article">
{{- with .Section }}
<meta property="article:section" content="{{ . }}">
{{- end }}
{{- $ISO8601 := "2006-01-02T15:04:05-07:00" }}
{{- with .PublishDate }}
<meta property="article:published_time" {{ .Format $ISO8601 | printf "content=%q" | safeHTMLAttr }}>
{{- end }}
{{- with .Lastmod }}
<meta property="article:modified_time" {{ .Format $ISO8601 | printf "content=%q" | safeHTMLAttr }}>
{{- end }}
{{- range .GetTerms "tags" | first 6 }}
<meta property="article:tag" content="{{ .Page.Title | plainify }}">
{{- end }}
{{- else }}
<meta property="og:type" content="website">
{{- end }}
{{- if .Params.cover.image -}}
{{- if (ne .Params.cover.relative true) }}
<meta property="og:image" content="{{ .Params.cover.image | absURL }}">
{{- else}}
<meta property="og:image" content="{{ (path.Join .RelPermalink .Params.cover.image ) | absURL }}">
{{- end}}
{{- else }}
{{- with partial "_funcs/get-page-images" . }}
{{- range . | first 6 }}
<meta property="og:image" content="{{ .Permalink }}">
{{- end }}
{{- end }}
{{- end }}
{{- with .Params.audio }}
{{- range . | first 6 }}
<meta property="og:audio" content="{{ . | absURL }}">
{{- end }}
{{- end }}
{{- with .Params.videos }}
{{- range . | first 6 }}
<meta property="og:video" content="{{ . | absURL }}">
{{- end }}
{{- end }}
{{- range .GetTerms "series" }}
{{- range .Pages | first 7 }}
{{- if ne $ . }}
<meta property="og:see_also" content="{{ .Permalink }}">
{{- end }}
{{- end }}
{{- end }}
{{- with site.Params.social }}
{{- if reflect.IsMap . }}
{{- with .facebook_app_id }}
<meta property="fb:app_id" content="{{ . }}">
{{- else }}
{{- with .facebook_admin }}
<meta property="fb:admins" content="{{ . }}">
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- with (.Param "social.fediverse_creator") }}
<meta name="fediverse:creator" content="{{ . }}">
{{- end }}

View file

@ -0,0 +1,128 @@
{{ if .IsHome }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "{{- ( site.Params.schema.publisherType | default "Organization") | title -}}",
"name": {{ site.Title }},
"url": {{ site.Home.Permalink }},
"description": {{ site.Params.description | plainify | truncate 180 | safeHTML }},
{{- if (eq site.Params.schema.publisherType "Person") }}
"image": {{ site.Params.assets.favicon | default "favicon.ico" | absURL }},
{{- else }}
"logo": {{ site.Params.assets.favicon | default "favicon.ico" | absURL }},
{{- end }}
"sameAs": [
{{- if site.Params.schema.sameAs }}
{{ range $i, $e := site.Params.schema.sameAs }}{{ if $i }}, {{ end }}{{ trim $e " " }}{{ end }}
{{- else}}
{{ range $i, $e := site.Params.SocialIcons }}{{ if $i }}, {{ end }}{{ trim $e.url " " | safeURL }}{{ end }}
{{- end}}
]
}
</script>
{{- else if (or .IsPage .IsSection) }}
{{/* BreadcrumbList */}}
{{- $url := replace .Parent.Permalink ( printf "%s" site.Home.Permalink) "" }}
{{- $lang_url := strings.TrimPrefix ( printf "%s/" .Lang) $url }}
{{- $bc_list := (split $lang_url "/")}}
{{- $scratch := newScratch }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{{- range $index, $element := $bc_list }}
{{- $scratch.Add "path" (printf "%s/" $element ) | safeJS }}
{{- $bc_pg := site.GetPage ($scratch.Get "path") -}}
{{- if (and ($bc_pg) (gt (len . ) 0))}}
{{- if (and $index)}}, {{end }}
{
"@type": "ListItem",
"position": {{ add 1 $index }},
"name": {{ $bc_pg.Name }},
"item": {{ $bc_pg.Permalink | safeHTML }}
}
{{- end }}
{{- end }}
{{- /* self-page addition */ -}}
{{- if (ge (len $bc_list) 2) }}, {{end }}
{
"@type": "ListItem",
"position": {{len $bc_list}},
"name": {{ .Name }},
"item": {{ .Permalink | safeHTML }}
}
]
}
</script>
{{- if .IsPage }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": {{ .Title | plainify}},
"name": "{{ .Title | plainify }}",
"description": {{ with .Description | plainify }}{{ . }}{{ else }}{{ .Summary | plainify }}{{ end -}},
"keywords": [
{{- if .Params.keywords }}
{{ range $i, $e := .Params.keywords }}{{ if $i }}, {{ end }}{{ $e }}{{ end }}
{{- else }}
{{ range $i, $e := .Params.tags }}{{ if $i }}, {{ end }}{{ $e }}{{ end }}
{{- end }}
],
"articleBody": {{ .Content | safeJS | htmlUnescape | plainify }},
"wordCount" : "{{ .WordCount }}",
"inLanguage": {{ .Language.Lang | default "en-us" }},
{{ if .Params.cover.image -}}
"image":
{{- if (ne .Params.cover.relative true) -}}
{{ .Params.cover.image | absURL }},
{{- else -}}
{{ (path.Join .RelPermalink .Params.cover.image ) | absURL }},
{{- end}}
{{- else }}
{{- $images := partial "templates/_funcs/get-page-images" . -}}
{{- with index $images 0 -}}
"image": {{ .Permalink }},
{{- end }}
{{- end -}}
"datePublished": {{ .PublishDate }},
"dateModified": {{ .Lastmod }},
{{- with (.Params.author | default site.Params.author) }}
"author":
{{- if (or (eq (printf "%T" .) "[]string") (eq (printf "%T" .) "[]interface {}")) -}}
[{{- range $i, $v := . -}}
{{- if $i }}, {{end -}}
{
"@type": "Person",
"name": {{ $v }}
}
{{- end }}],
{{- else -}}
{
"@type": "Person",
"name": {{ . }}
},
{{- end -}}
{{- end }}
"mainEntityOfPage": {
"@type": "WebPage",
"@id": {{ .Permalink | safeHTML }}
},
"publisher": {
"@type": "{{- ( site.Params.schema.publisherType | default "Organization") | title -}}",
"name": {{ site.Title }},
"logo": {
"@type": "ImageObject",
"url": {{ site.Params.assets.favicon | default "favicon.ico" | absURL }}
}
}
}
</script>
{{- end }}{{/* .IsPage end */}}
{{- end -}}

View file

@ -0,0 +1,31 @@
{{- if .Params.cover.image -}}
<meta name="twitter:card" content="summary_large_image">
{{- if (ne $.Params.cover.relative true) }}
<meta name="twitter:image" content="{{ .Params.cover.image | absURL }}">
{{- else }}
<meta name="twitter:image" content="{{ (path.Join .RelPermalink .Params.cover.image ) | absURL }}">
{{- end}}
{{- else }}
{{- $images := partial "templates/_funcs/get-page-images" . -}}
{{- with index $images 0 -}}
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="{{ .Permalink }}">
{{- else -}}
<meta name="twitter:card" content="summary">
{{- end -}}
{{- end }}
<meta name="twitter:title" content="{{ .Title }}">
<meta name="twitter:description" content="{{ with .Description }}{{ . }}{{ else }}{{if .IsPage}}{{ .Summary }}{{ else }}{{ with site.Params.description }}{{ . }}{{ end }}{{ end }}{{ end -}}">
{{- $twitterSite := "" }}
{{- with site.Params.social }}
{{- if reflect.IsMap . }}
{{- with .twitter }}
{{- $content := . }}
{{- if not (strings.HasPrefix . "@") }}
{{- $content = printf "@%v" . }}
{{- end }}
<meta name="twitter:site" content="{{ $content }}">
{{- end }}
{{- end }}
{{- end }}

97
layouts/partials/toc.html Executable file
View file

@ -0,0 +1,97 @@
{{- $headers := findRE "<h[1-6].*?>(.|\n])+?</h[1-6]>" .Content -}}
{{- $has_headers := ge (len $headers) 1 -}}
{{- if $has_headers -}}
<div class="toc">
<details {{if (.Param "TocOpen") }} open{{ end }}>
<summary accesskey="c" title="(Alt + C)">
<span class="details">{{- i18n "toc" | default "Table of Contents" }}</span>
</summary>
<div class="inner">
{{- if (.Param "UseHugoToc") }}
{{- .TableOfContents -}}
{{- else }}
{{- $largest := 6 -}}
{{- range $headers -}}
{{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}}
{{- $headerLevel := len (seq $headerLevel) -}}
{{- if lt $headerLevel $largest -}}
{{- $largest = $headerLevel -}}
{{- end -}}
{{- end -}}
{{- $firstHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers 0) 1) 0)) -}}
{{- $.Scratch.Set "bareul" slice -}}
<ul>
{{- range seq (sub $firstHeaderLevel $largest) -}}
<ul>
{{- $.Scratch.Add "bareul" (sub (add $largest .) 1) -}}
{{- end -}}
{{- range $i, $header := $headers -}}
{{- $headerLevel := index (findRE "[1-6]" . 1) 0 -}}
{{- $headerLevel := len (seq $headerLevel) -}}
{{/* get id="xyz" */}}
{{- $id := index (findRE "(id=\"(.*?)\")" $header 9) 0 }}
{{- /* strip id="" to leave xyz, no way to get regex capturing groups in hugo */ -}}
{{- $cleanedID := replace (replace $id "id=\"" "") "\"" "" }}
{{- $header := replaceRE "<h[1-6].*?>((.|\n])+?)</h[1-6]>" "$1" $header -}}
{{- if ne $i 0 -}}
{{- $prevHeaderLevel := index (findRE "[1-6]" (index $headers (sub $i 1)) 1) 0 -}}
{{- $prevHeaderLevel := len (seq $prevHeaderLevel) -}}
{{- if gt $headerLevel $prevHeaderLevel -}}
{{- range seq $prevHeaderLevel (sub $headerLevel 1) -}}
<ul>
{{/* the first should not be recorded */}}
{{- if ne $prevHeaderLevel . -}}
{{- $.Scratch.Add "bareul" . -}}
{{- end -}}
{{- end -}}
{{- else -}}
</li>
{{- if lt $headerLevel $prevHeaderLevel -}}
{{- range seq (sub $prevHeaderLevel 1) -1 $headerLevel -}}
{{- if in ($.Scratch.Get "bareul") . -}}
</ul>
{{/* manually do pop item */}}
{{- $tmp := $.Scratch.Get "bareul" -}}
{{- $.Scratch.Delete "bareul" -}}
{{- $.Scratch.Set "bareul" slice}}
{{- range seq (sub (len $tmp) 1) -}}
{{- $.Scratch.Add "bareul" (index $tmp (sub . 1)) -}}
{{- end -}}
{{- else -}}
</ul>
</li>
{{- end -}}
{{- end -}}
{{- end -}}
{{- end }}
<li>
<a href="#{{- $cleanedID -}}" aria-label="{{- $header | plainify | safeHTML -}}">{{- $header | plainify | safeHTML -}}</a>
{{- else }}
<li>
<a href="#{{- $cleanedID -}}" aria-label="{{- $header | plainify | safeHTML -}}">{{- $header | plainify | safeHTML -}}</a>
{{- end -}}
{{- end -}}
<!-- {{- $firstHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers 0) 1) 0)) -}} -->
{{- $firstHeaderLevel := $largest }}
{{- $lastHeaderLevel := len (seq (index (findRE "[1-6]" (index $headers (sub (len $headers) 1)) 1) 0)) }}
</li>
{{- range seq (sub $lastHeaderLevel $firstHeaderLevel) -}}
{{- if in ($.Scratch.Get "bareul") (add . $firstHeaderLevel) }}
</ul>
{{- else }}
</ul>
</li>
{{- end -}}
{{- end }}
</ul>
{{- end }}
</div>
</details>
</div>
{{- end }}

View file

@ -0,0 +1,19 @@
{{- if .IsTranslated -}}
{{- if (ne .Layout "search") }}
{{- if or .Params.author site.Params.author (.Param "ShowReadingTime") (not .Date.IsZero) }}&nbsp;|&nbsp;{{- end -}}
{{- end }}
{{- i18n "translations" | default "Translations" }}:
<ul class="i18n_list">
{{- range .Translations }}
<li>
<a href="{{ .Permalink }}">
{{- if (and site.Params.displayFullLangName (.Language.LanguageName)) }}
{{- .Language.LanguageName | emojify -}}
{{- else }}
{{- .Lang | title -}}
{{- end -}}
</a>
</li>
{{- end }}
</ul>
{{- end -}}

7
layouts/robots.txt Executable file
View file

@ -0,0 +1,7 @@
User-agent: *
{{- if hugo.IsProduction | or (eq site.Params.env "production") }}
Disallow:
{{- else }}
Disallow: /
{{- end }}
Sitemap: {{ "sitemap.xml" | absURL }}

100
layouts/rss.xml Executable file
View file

@ -0,0 +1,100 @@
{{- /* Deprecate site.Author.email in favor of site.Params.author.email */}}
{{- $authorEmail := "" }}
{{- with site.Params.author }}
{{- if reflect.IsMap . }}
{{- with .email }}
{{- $authorEmail = . }}
{{- end }}
{{- end }}
{{- else }}
{{- with site.Author.email }}
{{- $authorEmail = . }}
{{- warnf "The author key in site configuration is deprecated. Use params.author.email instead." }}
{{- end }}
{{- end }}
{{- /* Deprecate site.Author.name in favor of site.Params.author.name */}}
{{- $authorName := "" }}
{{- with site.Params.author }}
{{- if reflect.IsMap . }}
{{- with .name }}
{{- $authorName = . }}
{{- end }}
{{- else }}
{{- $authorName = . }}
{{- end }}
{{- else }}
{{- with site.Author.name }}
{{- $authorName = . }}
{{- warnf "The author key in site configuration is deprecated. Use params.author.name instead." }}
{{- end }}
{{- end }}
{{- /* Define allowed sections for RSS feed */}}
{{- $allowedSections := slice "blog" "collection" "livres" }}
{{- $pctx := . }}
{{- if .IsHome }}{{ $pctx = site }}{{ end }}
{{- $pages := slice }}
{{- if or $.IsHome $.IsSection }}
{{- $pages = $pctx.RegularPages }}
{{- else }}
{{- $pages = $pctx.Pages }}
{{- end }}
{{- $limit := site.Config.Services.RSS.Limit }}
{{- if ge $limit 1 }}
{{- $pages = $pages | first $limit }}
{{- end }}
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>{{ if eq .Title site.Title }}{{ site.Title }}{{ else }}{{ with .Title }}{{ . }} on {{ end }}{{ site.Title }}{{ end }}</title>
<link>{{ .Permalink }}</link>
<description>{{ site.Params.description }}</description>
{{- with site.Params.images }}
<image>
<title>{{ site.Title }}</title>
<url>{{ index . 0 | absURL }}</url>
<link>{{ index . 0 | absURL }}</link>
</image>
{{- end }}
<generator>Hugo -- {{ hugo.Version }}</generator>
<language>{{ site.Language.LanguageCode }}</language>{{ with $authorEmail }}
<managingEditor>{{.}}{{ with $authorName }} ({{ . }}){{ end }}</managingEditor>{{ end }}{{ with $authorEmail }}
<webMaster>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</webMaster>{{ end }}{{ with site.Copyright }}
<copyright>{{ . | markdownify | plainify | strings.TrimPrefix "© " }}</copyright>{{ end }}{{ if not .Date.IsZero }}
<lastBuildDate>{{ (index $pages.ByLastmod.Reverse 0).Lastmod.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
{{- with .OutputFormats.Get "RSS" }}
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
{{- end }}
{{- range $pages }}
{{- $section := .Section }}
{{- if in $allowedSections $section }}
<item>
<title>{{ .Title }}</title>
<link>{{ .Permalink }}</link>
<pubDate>{{ .PublishDate.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
{{- with $authorEmail }}<author>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</author>{{ end }}
<guid>{{ .Permalink }}</guid>
{{- /* Process content to fix image URLs */}}
{{- $summary := "" }}
{{- with .Description }}
{{- $summary = . }}
{{- else }}
{{- $summary = .Summary }}
{{- end }}
{{- $baseURLWithoutTrailing := strings.TrimSuffix "/" site.BaseURL }}
<description>{{ $summary | html }}</description>
{{- if site.Params.ShowFullTextinRSS }}
{{- $content := .Content }}
{{- $content := $content | replaceRE `src="(/[^"]*)"` (printf `src="%s$1"` $baseURLWithoutTrailing) }}
<content:encoded>{{ (printf "<![CDATA[%s]]>" $content) | safeHTML }}</content:encoded>
{{- end }}
</item>
{{- end }}
{{- end }}
</channel>
</rss>

View file

@ -0,0 +1,91 @@
{{ $csvFile := readFile "content/liens/blogroll.csv" }}
{{ $lines := split $csvFile "\n" }}
{{ $headers := split (index $lines 0) ";" }}
<style>
.blogroll {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); /* Responsive grid */
gap: 10px; /* Space between grid items */
margin: 0 0;
}
.blogroll-item a {
text-decoration: none;
box-shadow: none;
}
.blogroll-item {
padding: 0;
border-radius: 8px;
background-color: var(--entry);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin: 0;
padding: 10px;
}
.blogroll-name {
font-weight: bold;
font-size: 1.1rem;
margin-bottom: 0.5rem;
text-decoration: none;
color: var(--primary);
}
.blogroll a:hover {
color: var(--secondary);
text-decoration: underline;
text-decoration-thickness: 1.5px;
text-underline-offset: 3px;
}
.blogroll img {
width: 32px;
height: 32px;
object-fit: contain;
vertical-align: middle;
margin-right: 10px;
float: left;
}
.blogroll-desc {
flex-grow: 1; /* Allow description to take available space */
font-size: 0.9rem;
color: var(--secondary);
}
.blogroll-desc p {
margin: 0;
}
.blogroll-feed {
font-size: 0.9rem;
}
</style>
<div class="blogroll">
{{ range $i, $line := $lines }}
{{ if and (ne $i 0) (ne $line "") }}
{{ $cells := split $line ";" }}
{{ $rowData := dict }}
{{ range $j, $header := $headers }}
{{ $cellValue := index $cells $j | default "" }}
{{ $rowData = merge $rowData (dict $header $cellValue) }}
{{ end }}
<div class="blogroll-item">
<div class="blogroll-title">
{{ $siteUrl := index $rowData "url-site" }}
{{ $domain := replaceRE `^https?://([^/]+)/?.*$` "$1" $siteUrl }}
{{ $domain = replaceRE `\.[^.]+$` "" $domain }}
<img src="/blogroll-favicons/{{ $domain }}.png" alt="Favicon for {{ $domain }}" >
<a href="{{ index $rowData "url-site" }}" target="_blank">{{ index $rowData "nom" }}</a>
<span> - </span>
{{ if isset $rowData "url-feed" }}
<a class="blogroll-feed" href="{{ index $rowData "url-feed" }}" target="_blank">Feed</a>
{{ end }}
</div>
<div class="blogroll-feed">
</div>
<div class="blogroll-desc">
<p>{{ index $rowData "description" }}</p>
</div>
</div>
{{ end }}
{{ end }}
</div>

View file

@ -0,0 +1,2 @@
<!-- Include all content from static/cassette-player/index.html -->
{{ readFile "static/cassette-player/index.html" }}

View file

@ -0,0 +1,8 @@
{{ if .Get "summary" }}
{{ else }}
{{ warnf "missing value for param 'summary': %s" .Position }}
{{ end }}
<p><details {{ if (eq (.Get "openByDefault") true) }} open=true {{ end }}>
<summary markdown="span">{{ .Get "summary" | markdownify }}</summary>
{{ .Inner | markdownify }}
</details></p>

38
layouts/shortcodes/figure.html Executable file
View file

@ -0,0 +1,38 @@
<!--
Put this file in /layouts/shortcodes/figure.html
NB this overrides Hugo's built-in "figure" shortcode but is backwards compatible
Documentation and licence at https://github.com/liwenyip/hugo-easy-gallery/
-->
<!-- count how many times we've called this shortcode -->
{{- if not ($.Page.Scratch.Get "figurecount") }}{{ end }}
{{- $.Page.Scratch.Add "figurecount" 1 -}}
<!-- use either src or link-thumb for thumbnail image -->
{{- $thumb := .Get "src" | default (printf "%s." (.Get "thumb") | replace (.Get "link") ".") }}
{{- $thumbResource := $.Page.Resources.GetMatch $thumb }}
{{- $fitSize := .Get "size" | default "500" }}
{{- if $thumbResource }}
{{- if eq $thumbResource.MediaType.SubType "gif" }}
{{- /* Don't process GIFs to preserve animation */ -}}
{{- else }}
{{- $thumbResource = $thumbResource.Fit (printf "%[1]sx%[1]s webp q85" $fitSize) -}}
{{- end }}
{{- end }}
<div class="box{{ with .Get "caption-position" }} fancy-figure caption-position-{{.}}{{end}}{{ with .Get "caption-effect" }} caption-effect-{{.}}{{end}}" {{ with .Get "width" }}style="max-width:{{.}}"{{end}}>
<figure {{ with .Get "class" }}class="{{.}}"{{ end }} itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<div class="img"{{ if .Parent }} style="background-image: url('{{ if $thumbResource }}{{ $thumbResource.RelPermalink }}{{ else }}{{ $thumb | relURL }}{{ end }}');"{{ end }}{{ with .Get "size" }} data-size="{{.}}"{{ end }}>
<img itemprop="thumbnail" src="{{ if $thumbResource }}{{ $thumbResource.RelPermalink }}{{ else }}{{ $thumb | relURL }}{{ end }}" {{ with .Get "alt" | default (.Get "caption") }}alt="{{.}}"{{ end }}/><!-- <img> hidden if in .gallery -->
</div>
{{ with .Get "link" | default (.Get "src") }}<a href="{{ if $thumbResource }}{{ $thumbResource.RelPermalink }}{{ else }}{{ . | relURL }}{{ end }}" itemprop="contentUrl"></a>{{ end }}
{{- if or (or (.Get "title") (.Get "caption")) (.Get "attr")}}
<figcaption>
{{- with .Get "title" }}<h4>{{.}}</h4>{{ end }}
{{- if or (.Get "caption") (.Get "attr")}}
<p>
{{- .Get "caption" -}}
{{- with .Get "attrlink"}}<a href="{{.}}">{{ .Get "attr" }}</a>{{ else }}{{ .Get "attr"}}{{ end -}}
</p>
{{- end }}
</figcaption>
{{- end }}
</figure>
</div>

41
layouts/shortcodes/gallery.html Executable file
View file

@ -0,0 +1,41 @@
<!--
Put this file in /layouts/shortcodes/gallery.html
Documentation and licence at https://github.com/liwenyip/hugo-easy-gallery/
-->
<!-- count how many times we've called this shortcode -->
{{- if not ($.Page.Scratch.Get "figurecount") }}{{ end }}
{{- $.Page.Scratch.Add "figurecount" 1 }}
{{ $baseURL := .Site.BaseURL }}
<div class="gallery caption-position-{{ with .Get "caption-position" | default "bottom" }}{{.}}{{end}} caption-effect-{{ with .Get "caption-effect" | default "none" }}{{.}}{{end}} hover-effect-{{ with .Get "hover-effect" | default "zoom" }}{{.}}{{end}} {{ if ne (.Get "hover-transition") "none" }}hover-transition{{end}}" itemscope itemtype="http://schema.org/ImageGallery">
{{- with (.Get "dir") -}}
<!-- If a directory was specified, generate figures for all of the images in the directory -->
{{- $files := readDir (print "/static/" .) }}
{{- range $files -}}
<!-- skip files that aren't images, or that include the thumb suffix in their name -->
{{- $thumbext := $.Get "thumb" | default "-thumb" }}
{{- $isthumb := .Name | findRE ($thumbext | printf "%s\\.") }}<!-- is the current file a thumbnail image? -->
{{- $isimg := lower .Name | findRE "\\.(gif|jpg|jpeg|tiff|png|bmp|webp|avif|jxl)" }}<!-- is the current file an image? -->
{{- if and $isimg (not $isthumb) }}
{{- $caption := .Name | replaceRE "\\..*" "" | humanize }}<!-- humanized filename without extension -->
{{- $linkURL := print $baseURL ($.Get "dir") "/" .Name | absURL }}<!-- absolute URL to hi-res image -->
{{- $thumb := .Name | replaceRE "(\\.)" ($thumbext | printf "%s.") }}<!-- filename of thumbnail image -->
{{- $thumbexists := where $files "Name" $thumb }}<!-- does a thumbnail image exist? -->
{{- $thumbURL := print $baseURL ($.Get "dir") "/" $thumb | absURL }}<!-- absolute URL to thumbnail image -->
<div class="box">
<figure itemprop="associatedMedia" itemscope itemtype="http://schema.org/ImageObject">
<div class="img" style="background-image: url('{{ if $thumbexists }}{{ $thumbURL }}{{ else }}{{ $linkURL }}{{ end }}');" >
<img itemprop="thumbnail" src="{{ if $thumbexists }}{{ $thumbURL }}{{ else }}{{ $linkURL }}{{ end }}" alt="{{ $caption }}" /><!-- <img> hidden if in .gallery -->
</div>
<figcaption>
<h4>{{ $caption }}</h4>
</figcaption>
<a href="{{ $linkURL }}" itemprop="contentUrl"></a><!-- put <a> last so it is stacked on top -->
</figure>
</div>
{{- end }}
{{- end }}
{{- else -}}
<!-- If no directory was specified, include any figure shortcodes called within the gallery -->
{{ .Inner }}
{{- end }}
</div>

View file

@ -0,0 +1,284 @@
<!--
trouvé ici : https://github.com/thisdev/hugo-gallery-shortcode
modifié pour accepter les images dans le répertoire de la page
ne supporte que 5 images max (pourquoi ?)
-->
<style>
/* Gallery Grid */
.image-gallery {
overflow: auto;
margin-left: -1% !important;
}
.image-gallery li {
float: left;
display: block;
margin: 0 0 1% 1%;
}
/* Dynamic widths based on image count */
.image-gallery[data-count="2"] li {
width: 49%;
}
.image-gallery[data-count="3"] li {
width: 32%;
}
.image-gallery[data-count="4"] li {
width: 24%;
}
.image-gallery[data-count="5"] li {
width: 19%;
}
/* Override PaperMod theme link styles */
.post-content .image-gallery a {
box-shadow: none;
box-decoration-break: none;
-webkit-box-decoration-break: none;
}
.image-gallery li a {
text-align: center;
text-decoration: none;
color: #777;
display: block;
}
.image-gallery li a span {
display: block;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
padding: 3px 0;
}
.image-gallery li a img {
width: 100%;
aspect-ratio: 1 / 1;
display: block;
border-radius: 8px;
object-fit: cover;
background: #f5f5f5;
transition: transform 0.3s ease;
}
.image-gallery li a:hover img {
transform: scale(1.01);
}
/* Simple Lightbox */
.simple-lightbox {
display: none;
position: fixed;
z-index: 999;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9);
}
.simple-lightbox.active {
display: flex;
justify-content: center;
align-items: center;
}
.lightbox-content {
position: relative;
max-width: 90%;
max-height: 90vh;
}
.lightbox-content img {
max-width: 100%;
max-height: 90vh;
object-fit: contain;
}
.lightbox-caption {
position: absolute;
bottom: -60px;
left: 0;
right: 0;
color: white;
text-align: center;
padding: 10px;
}
.lightbox-close {
position: absolute;
top: 20px;
right: 20px;
color: white;
font-size: 30px;
cursor: pointer;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
}
.lightbox-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
color: white;
font-size: 30px;
cursor: pointer;
padding: 20px;
user-select: none;
}
.lightbox-prev {
left: 20px;
}
.lightbox-next {
right: 20px;
}
</style>
{{ $dir := .Get "gallery_dir" }}
<div class="simple-lightbox">
<div class="lightbox-content">
<img src="" alt="">
<div class="lightbox-caption"></div>
</div>
<div class="lightbox-close">&times;</div>
<div class="lightbox-nav lightbox-prev">&lt;</div>
<div class="lightbox-nav lightbox-next">&gt;</div>
</div>
<ul class="image-gallery">
{{ $localPath := string (.Get "gallery_dir") }}
{{ $displayTitle := ne (.Get "disp_title") "no" }}
<!-- Get images from page resources, looking in the specified directory -->
{{ $files := .Page.Resources.Match (printf "%s/*" $localPath) }}
<!-- For debugging
{{ $count := len $files }}
<div style="color: #666; font-size: 0.8em; margin-bottom: 10px;">
Found {{ $count }} images in "{{ $localPath }}" directory
</div>
-->
{{ $imageFiles := slice }}
{{ range $files }}
{{- $ext := path.Ext .Name | lower -}}
{{- if in (slice ".jpg" ".jpeg" ".png" ".gif" ".webp") $ext -}}
{{ $imageFiles = $imageFiles | append . }}
{{ end }}
{{ end }}
{{ if and (ge (len $imageFiles) 2) (le (len $imageFiles) 5) }}
{{ range $imageFiles }}
{{- $imagetitle := index (split .Name ".") 0 -}}
<li>
<a href="{{ .RelPermalink }}" title="{{ $imagetitle }}" class="gallery-image"
data-caption="{{ $imagetitle }}">
<img src="{{ .RelPermalink }}" alt="{{ $imagetitle }}" title="{{ $imagetitle }}">
{{ if $displayTitle }}
<span>{{ $imagetitle }}</span>
{{ end }}
</a>
</li>
{{ end }}
{{ else if eq (len $imageFiles) 0 }}
<div style="background: #fff3cd; color: #856404; padding: 10px; border-radius: 5px;">
<strong>Note:</strong> No images found in "{{ $localPath }}" directory. Make sure your images are in the correct location.
</div>
{{ else if eq (len $imageFiles) 1 }}
<div style="background: #fff3cd; color: #856404; padding: 10px; border-radius: 5px;">
<strong>Note:</strong> Only one image found in "{{ $localPath }}" directory. Gallery needs at least 2 images.
</div>
{{ else }}
<div style="background: #fff3cd; color: #856404; padding: 10px; border-radius: 5px;">
<strong>Note:</strong> Too many images found ({{ len $imageFiles }}). Maximum supported is 5 images.
</div>
{{ end }}
</ul>
<script>
document.addEventListener('DOMContentLoaded', function () {
const lightbox = document.querySelector('.simple-lightbox');
const lightboxImg = lightbox.querySelector('img');
const lightboxCaption = lightbox.querySelector('.lightbox-caption');
const gallery = document.querySelector('.image-gallery');
let currentIndex = 0;
let images = [];
// Set data-count attribute for CSS styling
const imageCount = gallery.querySelectorAll('.gallery-image').length;
gallery.setAttribute('data-count', imageCount.toString());
// collect all images
gallery.querySelectorAll('.gallery-image').forEach((link, index) => {
images.push({
src: link.href,
title: link.getAttribute('data-caption')
});
// click event for each image
link.addEventListener('click', (e) => {
e.preventDefault();
currentIndex = index;
showImage(currentIndex);
});
});
// show image in lightbox
function showImage(index) {
lightboxImg.src = images[index].src;
lightboxCaption.textContent = images[index].title;
lightbox.classList.add('active');
}
// close button
lightbox.querySelector('.lightbox-close').addEventListener('click', () => {
lightbox.classList.remove('active');
});
// navigation
lightbox.querySelector('.lightbox-prev').addEventListener('click', () => {
currentIndex = (currentIndex - 1 + images.length) % images.length;
showImage(currentIndex);
});
lightbox.querySelector('.lightbox-next').addEventListener('click', () => {
currentIndex = (currentIndex + 1) % images.length;
showImage(currentIndex);
});
// keyboard navigation
document.addEventListener('keydown', (e) => {
if (!lightbox.classList.contains('active')) return;
if (e.key === 'Escape') {
lightbox.classList.remove('active');
} else if (e.key === 'ArrowLeft') {
currentIndex = (currentIndex - 1 + images.length) % images.length;
showImage(currentIndex);
} else if (e.key === 'ArrowRight') {
currentIndex = (currentIndex + 1) % images.length;
showImage(currentIndex);
}
});
// click anywhere to close lightbox
lightbox.addEventListener('click', (e) => {
if (e.target === lightbox) {
lightbox.classList.remove('active');
}
});
});
</script>

View file

@ -0,0 +1,5 @@
{{- $Img := (.Get "url") }}
{{- $height := (.Get "height") }}
{{- $alt := (.Get "alt") }}
<img class="in-text" height="{{ $height | default `15` }}" src="{{$Img}}" alt="{{$alt}}">

View file

@ -0,0 +1,32 @@
<!-- https://oostens.me/posts/hugo-inline-spoiler-shortcode/ -->
<style>
.inline-spoiler {
position: relative;
display: inline-block;
cursor: help;
}
.inline-spoiler::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 1px;
color: white;
background: black;
opacity: 1;
transition: opacity 0.7s ease, transform 0.3s ease;
}
.inline-spoiler:hover::before {
opacity: 0;
transform: translateY(-50%)rotateX(80deg);
transition: opacity 1.0s ease, transform 0.5s ease;
transition-delay: 0.3s;
}
</style>
<span class="inline-spoiler">{{- .Inner | safeHTML -}}</span>

View file

@ -0,0 +1,8 @@
{{range $name, $taxonomy := .Site.Taxonomies.tags}} {{ $cnt := .Count }}
{{ with $.Site.GetPage (printf "/tags/%s" $name) }}
<div class="tagbutton">
<a href={{ .RelPermalink }} title="All pages with tag <i>{{$name}}</i>">{{$name}}</a>
<sup>{{$cnt}}</sup>
</div>
{{end}}
{{end}}

View file

@ -0,0 +1,75 @@
<!--
Put this file in /layouts/shortcodes/load-photoswipe.html
Documentation and licence at https://github.com/liwenyip/hugo-easy-gallery/
-->
<!-- prevent this shortcode from being loaded more than once per page -->
{{ if not ($.Page.Scratch.Get "photoswipeloaded") }}
{{ $.Page.Scratch.Set "photoswipeloaded" 1 }}
<!--
*** jQuery must be loaded before load-photoswipe.js ***
- If your template already loads jQuery in the header then you don't need to load it again here.
- If your template already loads jQuery in the footer, then you could load load-photoswipe.js from the footer instead
-->
<!-- these files are loaded in the theme footer
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script src="/js/load-photoswipe.js"></script>
-->
<!-- Photoswipe css/js libraries -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe.min.css" integrity="sha256-sCl5PUOGMLfFYctzDW3MtRib0ctyUvI9Qsmq2wXOeBY=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/default-skin/default-skin.min.css" integrity="sha256-BFeI1V+Vh1Rk37wswuOYn5lsTcaU96hGaI7OUVCLjPc=" crossorigin="anonymous" />
<!-- these files are loaded in the theme footer
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe.min.js" integrity="sha256-UplRCs9v4KXVJvVY+p+RSo5Q4ilAUXh7kpjyIP5odyc=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe-ui-default.min.js" integrity="sha256-PWHOlUzc96pMc8ThwRIXPn8yH4NOLu42RQ0b9SpnpFk=" crossorigin="anonymous"></script>
-->
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element, as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides.
PhotoSwipe keeps only 3 of them in DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on. -->
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
{{ end }}

View file

@ -0,0 +1,71 @@
<!--
Put this file in /layouts/shortcodes/load-photoswipe.html
Documentation and licence at https://github.com/liwenyip/hugo-easy-gallery/
-->
<!-- prevent this shortcode from being loaded more than once per page -->
{{ if not ($.Page.Scratch.Get "photoswipeloaded") }}
{{ $.Page.Scratch.Set "photoswipeloaded" 1 }}
<!--
*** jQuery must be loaded before load-photoswipe.js ***
- If your template already loads jQuery in the header then you don't need to load it again here.
- If your template already loads jQuery in the footer, then you could load load-photoswipe.js from the footer instead
-->
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script src={{ "js/load-photoswipe.js" | relURL }}></script>
<!-- Photoswipe css/js libraries -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe.min.css" integrity="sha256-sCl5PUOGMLfFYctzDW3MtRib0ctyUvI9Qsmq2wXOeBY=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/default-skin/default-skin.min.css" integrity="sha256-BFeI1V+Vh1Rk37wswuOYn5lsTcaU96hGaI7OUVCLjPc=" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe.min.js" integrity="sha256-UplRCs9v4KXVJvVY+p+RSo5Q4ilAUXh7kpjyIP5odyc=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.1/photoswipe-ui-default.min.js" integrity="sha256-PWHOlUzc96pMc8ThwRIXPn8yH4NOLu42RQ0b9SpnpFk=" crossorigin="anonymous"></script>
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element, as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides.
PhotoSwipe keeps only 3 of them in DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on. -->
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
{{ end }}

15
layouts/shortcodes/ltr.html Executable file
View file

@ -0,0 +1,15 @@
{{ $.Scratch.Set "md" false }}
{{ if .IsNamedParams }}
{{ $.Scratch.Set "md" (.Get "md") }}
{{ else }}
{{ $.Scratch.Set "md" (.Get 0) }}
{{ end }}
<div dir="ltr">
{{ if eq ($.Scratch.Get "md") false }}
{{ .Inner }}
{{ else }}
{{ .Inner | markdownify }}
{{ end }}
</div>

View file

@ -0,0 +1 @@
{{ len (where .Site.RegularPages "Section" "blog") }}

View file

@ -0,0 +1,8 @@
{{- $count := .Get 0 | default "5" -}}
<ul>
{{- range first (int $count) (sort (where .Site.RegularPages "Section" "blog") "Date" "desc") -}}
<li>
({{ .Date.Format "2006-01-02" }}) <a href="{{ .RelPermalink }}">{{ .Title }}</a>
</li>
{{- end -}}
</ul>

View file

@ -0,0 +1,2 @@
<!-- raw html -->
{{- .Inner -}}

15
layouts/shortcodes/rtl.html Executable file
View file

@ -0,0 +1,15 @@
{{ $.Scratch.Set "md" false }}
{{ if .IsNamedParams }}
{{ $.Scratch.Set "md" (.Get "md") }}
{{ else }}
{{ $.Scratch.Set "md" (.Get 0) }}
{{ end }}
<div dir="rtl">
{{ if eq ($.Scratch.Get "md") false }}
{{ .Inner }}
{{ else }}
{{ .Inner | markdownify }}
{{ end }}
</div>

74
layouts/shortcodes/video.html Executable file
View file

@ -0,0 +1,74 @@
<!-- https://github.com/martignoni/hugo-video -->
{{- /* hugo-video shortcode
/*
/* This file is part of hugo-video shortcode.
/* A Hugo component shortcode to embed videos using the HTML video element.
/*
/* @copyright @2019 onwards Nicolas Martignoni (nicolas@martignoni.net)
/* @source https://github.com/martignoni/hugo-video
/* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
/*
*/ -}}
{{- $video_src := .Get "src" -}}
{{- $video_mp4 := "" -}}
{{- $video_webm := "" -}}
{{- $video_ogg := "" -}}
{{- $video_dl := "" -}}
{{- $width := "100%" -}}
{{- $filenotfound := true -}}
{{- $unsupportedfile := true -}}
{{- /* Find all files with filename (without suffix) matching "src" parameter. */ -}}
{{- $video_files := (.Page.Resources.Match (printf "%s*" $video_src)) -}}
{{- /* Find first image file with filename (without suffix) matching "src" parameter. */ -}}
{{- $poster := ((.Page.Resources.ByType "image").GetMatch (printf "%s*" $video_src)) -}}
{{- /* Find in page bundle all valid video files with matching name. */ -}}
{{- with $video_files -}}
{{- $filenotfound = false -}}
{{- range . -}}
{{- if or (in .MediaType.Suffixes "mp4") (in .MediaType.Suffixes "m4v") -}}
{{- $unsupportedfile = false -}}
{{- $video_mp4 = . -}}
{{- end -}}
{{- if (in .MediaType.Suffixes "webm") -}}
{{- $unsupportedfile = false -}}
{{- $video_webm = . -}}
{{- end -}}
{{- if (in .MediaType.Suffixes "ogv") -}}
{{- $unsupportedfile = false -}}
{{- $video_ogg = . -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if $filenotfound -}}
{{- /* No file of given name was found, we stop here. */ -}}
{{- errorf "No file with filename %q found." $video_src -}}
{{- else if $unsupportedfile -}}
{{- errorf "No valid video file with filename %q found." $video_src -}}
{{- else -}}
<figure class="video-figure">
<video {{ if ne (.Get "controls") "false" }}controls {{ end }}preload="auto" width="{{ or (.Get "width") $width }}" {{ with .Get "height" }}height="{{.}}"{{ end }} {{ if eq (.Get "autoplay") "true" }}autoplay {{ end }}{{ if eq (.Get "loop") "true" }}loop {{ end }}{{ if eq (.Get "muted") "true" }}muted {{ end }}{{ with $poster }}poster="{{ .RelPermalink }}" {{ end }} playsinline class="html-video">
{{- with $video_webm }}
<source src="{{ .RelPermalink }}" type="video/webm">
{{- $video_dl = . -}}
{{- end }}
{{- with $video_ogg }}
<source src="{{ .RelPermalink }}" type="video/ogg">
{{- $video_dl = . -}}
{{- end }}
{{- with $video_mp4 }}
<source src="{{ .RelPermalink }}" type="video/mp4">
{{- $video_dl = . -}}
{{- end }}
<span>{{ i18n "videoUnsupported" $video_dl | safeHTML}}</span>
</video>
{{- with .Get "title" }}
<figcaption class="video-caption">{{ . }}</figcaption>
{{- end }}
</figure>
{{- end -}}

View file

@ -0,0 +1,12 @@
<!-- https://stackoverflow.com/questions/72065012/how-to-embed-a-youtube-playlist-in-hugo-website -->
{{- $pc := .Page.Site.Config.Privacy.YouTube -}}
{{- if not $pc.Disable -}}
{{- $ytHost := cond $pc.PrivacyEnhanced "www.youtube-nocookie.com" "www.youtube.com" -}}
{{- $id := .Get "id" | default (.Get 0) -}}
{{- $class := .Get "class" | default (.Get 1) -}}
{{- $title := .Get "title" | default "YouTube Video" }}
<div {{ with $class }}class="{{ . }}"{{ else }}style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"{{ end }}>
<iframe src="https://{{ $ytHost }}/embed/videoseries?list={{ $id }}{{ with .Get "autoplay" }}{{ if eq . "true" }}&autoplay=1{{ end }}{{ end }}" {{ if not $class }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}allowfullscreen title="{{ $title }}"></iframe>
</div>
{{ end -}}

2
static/admin/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
index.html
assets/

153
static/admin/config.yml Executable file
View file

@ -0,0 +1,153 @@
backend:
name: gitea
repo: gribse/blog # Path to your Gitea repository
app_id: 39e3a9e2-1bd0-41be-bc4c-7c7f7023b51b # The Client ID provided by Gitea
api_root: https://git.achilletoupin.com/api/v1 # API URL of your Gitea instance
base_url: https://git.achilletoupin.com/ # Root URL of your Gitea instance
auth_endpoint: https://git.achilletoupin.com/login/oauth/authorize
# optional, defaults to master
branch: main
local_backend: true # allows local editing via npx decap-cms-proxy-server
media_folder: "static/images/uploads" # path in repo
public_folder: "/images/uploads" # URL path
collections:
- name: "blog"
label: "Blog"
folder: "content/blog"
create: true
slug: "{{title}}/index"
sortable_fields: ["date"]
sort_value_field: "date"
sort_direction: "desc"
nested:
depth: 2
summary: "{{title}}"
filter:
field: "path"
pattern: ".*?/index.md"
fields:
- { name: "title", label: "Title", widget: "string" }
- { name: "date", label: "Date", widget: "datetime", default: "{{ .Date }}" }
- { name: "draft", label: "Draft", widget: "boolean", default: true }
- { name: "ShowToc", label: "Show TOC", widget: "boolean", default: false }
- name: "cover"
label: "Cover"
widget: "object"
fields:
- { name: "hidden", label: "Hidden", widget: "boolean", default: false }
- { name: "hiddenInList", label: "Hidden In List", widget: "boolean", default: false }
- { name: "hiddenInSingle", label: "Hidden In Single", widget: "boolean", default: true }
- { name: "image", label: "Image", widget: "string", default: "images/<image.jpg>" }
- { name: "alt", label: "Alt Text", widget: "string", default: "<alt text>" }
- { name: "caption", label: "Caption", widget: "string", default: "<text>" }
- { name: "relative", label: "Relative Path", widget: "boolean", default: true }
- { name: "ShowBreadCrumbs", label: "Show Breadcrumbs", widget: "boolean", default: true }
- { name: "ShowPostNavLinks", label: "Show Post Nav Links", widget: "boolean", default: true }
- { name: "ShowReadingTime", label: "Show Reading Time", widget: "boolean", default: true }
- { name: "body", label: "Body", widget: "markdown" }
- name: "collection"
label: "Machine"
folder: "content/collection"
create: true
slug: "{{title}}/index"
sortable_fields: ["date"]
sort_value_field: "date"
sort_direction: "desc"
nested:
depth: 2
summary: "{{title}}"
filter:
field: "path"
pattern: ".*?/index.md"
fields:
- { name: "title", label: "Title", widget: "string" }
- { name: "date", label: "Date", widget: "datetime", default: "{{ .Date }}" }
- { name: "draft", label: "Draft", widget: "boolean", default: true }
- { name: "ShowToc", label: "Show TOC", widget: "boolean", default: false }
- name: "cover"
label: "Cover"
widget: "object"
fields:
- { name: "hidden", label: "Hidden", widget: "boolean", default: false }
- { name: "hiddenInList", label: "Hidden In List", widget: "boolean", default: false }
- { name: "hiddenInSingle", label: "Hidden In Single", widget: "boolean", default: true }
- { name: "image", label: "Image", widget: "string", default: "images/<image>" }
- { name: "alt", label: "Alt Text", widget: "string", default: "<alt text>" }
- { name: "caption", label: "Caption", widget: "string", default: "<text>" }
- { name: "relative", label: "Relative Path", widget: "boolean", default: true }
- { name: "ShowBreadCrumbs", label: "Show Breadcrumbs", widget: "boolean", default: true }
- { name: "ShowPostNavLinks", label: "Show Post Nav Links", widget: "boolean", default: true }
- { name: "ShowReadingTime", label: "Show Reading Time", widget: "boolean", default: false }
- name: "tags"
label: "Tags"
widget: "list"
field: { name: "tag", label: "Tag", widget: "string", default: "<tag>" }
- name: "machineSpecs"
label: "Machine Specs"
widget: "object"
fields:
- { name: "make", label: "Make", widget: "string", required: false }
- { name: "model", label: "Model", widget: "string", required: false }
- { name: "image", label: "Image", widget: "string", default: "images/<image>", required: false }
- { name: "linkTpdb", label: "Link TPDB", widget: "string", required: false }
- { name: "type", label: "Type", widget: "string", default: "", required: false }
- { name: "dateManufactured", label: "Date Manufactured", widget: "string", required: false }
- { name: "massKg", label: "Mass (kg)", widget: "string", required: false }
- { name: "widthCm", label: "Width (cm)", widget: "string", required: false }
- { name: "serialNumber", label: "Serial Number", widget: "string", required: false }
- { name: "body", label: "Body", widget: "markdown" }
- name: "livres"
label: "Livre"
folder: "content/livres"
create: true
slug: "{{title}}/index"
sortable_fields: ["date"]
sort_value_field: "date"
sort_direction: "desc"
nested:
depth: 2
summary: "{{title}}"
filter:
field: "path"
pattern: ".*?/index.md"
fields:
- { name: "title", label: "Title", widget: "string" }
- { name: "date", label: "Date", widget: "datetime", default: "{{ .Date }}" }
- { name: "draft", label: "Draft", widget: "boolean", default: true }
- { name: "ShowToc", label: "Show TOC", widget: "boolean", default: false }
- name: "cover"
label: "Cover"
widget: "object"
fields:
- { name: "hidden", label: "Hidden", widget: "boolean", default: false }
- { name: "hiddenInList", label: "Hidden In List", widget: "boolean", default: false }
- { name: "hiddenInSingle", label: "Hidden In Single", widget: "boolean", default: true }
- { name: "image", label: "Image", widget: "string", default: "images/cover.jpg" }
- { name: "alt", label: "Alt Text", widget: "string", default: "Couverture du livre" }
- { name: "relative", label: "Relative Path", widget: "boolean", default: true }
- { name: "ShowBreadCrumbs", label: "Show Breadcrumbs", widget: "boolean", default: true }
- { name: "ShowPostNavLinks", label: "Show Post Nav Links", widget: "boolean", default: true }
- { name: "ShowReadingTime", label: "Show Reading Time", widget: "boolean", default: true }
- name: "tags"
label: "Tags"
widget: "list"
default: ["test"]
field: { name: "tag", label: "Tag", widget: "string" }
- name: "BookData"
label: "Book Data"
widget: "object"
fields:
- { name: "title", label: "Book Title", widget: "string", default: "" }
- { name: "author", label: "Author", widget: "string", default: "T" }
- { name: "ISBN", label: "ISBN", widget: "string", default: "" }
- { name: "publishDate", label: "Publish Date", widget: "string", default: "2" }
- { name: "worldCat", label: "WorldCat", widget: "string", default: "" }
- { name: "starGrade", label: "Star Grade", widget: "string", default: "" }
- { name: "cover", label: "Cover", widget: "string", default: "" }

492
static/admin/decap-cms.js Executable file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,014 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Some files were not shown because too many files have changed in this diff Show more