Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e3687431f | ||
|
|
cfcdb20d17 | ||
|
|
0c941ebb04 | ||
|
|
f13c478718 | ||
|
|
bde2914dec | ||
|
|
f5adf4a273 | ||
|
|
07fa7615eb | ||
|
|
628bb9a501 | ||
|
|
11aa9e349a | ||
|
|
25bf63778c | ||
|
|
a95d0e7c85 | ||
|
|
12f05571cf | ||
|
|
230a28fa8d | ||
|
|
a9a14ce815 | ||
|
|
0ad02c5c0f | ||
|
|
88468ad84e | ||
|
|
3dae60ac7a | ||
|
|
22edce91ab | ||
|
|
78800c7379 | ||
|
|
a0bd0073bb | ||
|
|
3ca74956a6 |
+1
-1
@@ -10,7 +10,7 @@
|
||||
main() {
|
||||
DART_SASS_VERSION=1.97.1
|
||||
GO_VERSION=1.25.5
|
||||
HUGO_VERSION=0.154.5
|
||||
HUGO_VERSION=0.157.0
|
||||
NODE_VERSION=24.12.0
|
||||
|
||||
export TZ=Europe/Oslo
|
||||
|
||||
@@ -19,7 +19,7 @@ a {
|
||||
.section-title {
|
||||
text-transform: uppercase;
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: var(--spacing-sm);
|
||||
display: block;
|
||||
font-size: 1.6rem;
|
||||
font-weight: bold;
|
||||
|
||||
@@ -60,14 +60,10 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
&.column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&.on-phone--column {
|
||||
flex-direction: column;
|
||||
@include respond(md) {
|
||||
flex-direction: unset;
|
||||
flex-direction: row;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,11 +89,11 @@ main.main {
|
||||
.main-container {
|
||||
min-height: 100vh;
|
||||
align-items: flex-start;
|
||||
padding: 0 15px;
|
||||
padding: 0 var(--container-padding);
|
||||
gap: var(--section-separation);
|
||||
padding-top: var(--main-top-padding);
|
||||
|
||||
@include respond(md) {
|
||||
padding: 0 20px;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
@mixin card-style {
|
||||
background-color: var(--card-background);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--card-border-radius);
|
||||
}
|
||||
@@ -7,9 +7,7 @@
|
||||
article {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--card-background);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--card-border-radius);
|
||||
@include card-style;
|
||||
overflow: hidden;
|
||||
|
||||
transition: box-shadow 0.3s ease;
|
||||
@@ -21,16 +19,8 @@
|
||||
.article-image {
|
||||
img {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
height: var(--article-image-height);
|
||||
object-fit: cover;
|
||||
|
||||
@include respond(md) {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
@include respond(xl) {
|
||||
height: 250px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +31,7 @@
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: var(--card-padding);
|
||||
gap: 15px;
|
||||
gap: var(--spacing-md);
|
||||
}
|
||||
|
||||
.article-title {
|
||||
@@ -59,7 +49,7 @@
|
||||
color: var(--card-text-color-main);
|
||||
|
||||
&:hover {
|
||||
color: var(--card-text-color-main);
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,12 +71,11 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.article-time,
|
||||
.article-translations,
|
||||
.article-header-tags {
|
||||
.article-meta {
|
||||
display: flex;
|
||||
color: var(--card-text-color-tertiary);
|
||||
gap: 15px;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-lg);
|
||||
font-size: 1.4rem;
|
||||
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
@@ -96,34 +85,26 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
&,
|
||||
time,
|
||||
a {
|
||||
a,
|
||||
span {
|
||||
font-size: 1.4rem;
|
||||
color: var(--card-text-color-tertiary);
|
||||
}
|
||||
|
||||
& > div {
|
||||
& > .inline-meta {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.article-time {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.article-translations,
|
||||
.article-header-tags {
|
||||
& > div {
|
||||
flex-wrap: wrap;
|
||||
gap: var(--spacing-md);
|
||||
}
|
||||
}
|
||||
|
||||
.article-category,
|
||||
.article-tags {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
flex-wrap: wrap;
|
||||
|
||||
a {
|
||||
@@ -144,21 +125,15 @@
|
||||
|
||||
/* Compact style article list */
|
||||
.article-list--compact {
|
||||
border-radius: var(--card-border-radius);
|
||||
box-shadow: var(--shadow-l1);
|
||||
background-color: var(--card-background);
|
||||
--image-size: 50px;
|
||||
|
||||
@include respond(md) {
|
||||
--image-size: 60px;
|
||||
}
|
||||
@include card-style;
|
||||
--image-size: var(--article-compact-image-size);
|
||||
|
||||
article {
|
||||
& > a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--small-card-padding);
|
||||
gap: 15px;
|
||||
gap: var(--spacing-md);
|
||||
}
|
||||
|
||||
&:not(:last-of-type) {
|
||||
@@ -169,7 +144,7 @@
|
||||
flex-grow: 1;
|
||||
padding: 0;
|
||||
min-height: var(--image-size);
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
}
|
||||
|
||||
.article-title {
|
||||
@@ -189,10 +164,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.article-time {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.article-preview {
|
||||
font-size: 1.4rem;
|
||||
color: var(--card-text-color-tertiary);
|
||||
@@ -204,14 +175,12 @@
|
||||
/* Tile style article list */
|
||||
.article-list--tile {
|
||||
article {
|
||||
border-radius: var(--card-border-radius);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 350px;
|
||||
width: 250px;
|
||||
box-shadow: var(--shadow-l1);
|
||||
width: var(--article-tile-width);
|
||||
height: var(--article-tile-height);
|
||||
@include card-style;
|
||||
overflow: hidden;
|
||||
transition: box-shadow 0.3s ease;
|
||||
background-color: var(--card-background);
|
||||
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-l2);
|
||||
@@ -219,11 +188,11 @@
|
||||
|
||||
&.has-image {
|
||||
.article-details {
|
||||
background-color: rgba(#000, 0.25);
|
||||
background-color: var(--article-tile-overlay-bg);
|
||||
}
|
||||
|
||||
.article-title {
|
||||
color: #fff;
|
||||
color: var(--article-tile-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,19 +297,19 @@
|
||||
|
||||
button {
|
||||
padding: 0.5rem 1rem;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border: 2px solid #333;
|
||||
background: var(--mermaid-toolbar-btn-bg);
|
||||
border: 2px solid var(--mermaid-toolbar-btn-text);
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
color: var(--mermaid-toolbar-btn-text);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
background: var(--mermaid-toolbar-btn-text);
|
||||
color: var(--card-background);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
@@ -354,7 +323,7 @@
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
background: var(--mermaid-modal-bg);
|
||||
z-index: 9999;
|
||||
|
||||
&.active {
|
||||
@@ -379,14 +348,15 @@
|
||||
.mermaid-modal-controls button,
|
||||
.mermaid-modal-close {
|
||||
padding: 0.5rem 1rem;
|
||||
background: #fff;
|
||||
background: var(--mermaid-modal-btn-bg);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
color: var(--card-text-color-main);
|
||||
|
||||
&:hover {
|
||||
background: #ddd;
|
||||
background: var(--mermaid-modal-btn-hover);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,11 +374,7 @@
|
||||
bottom: 1rem;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
|
||||
[data-scheme="dark"] & {
|
||||
background: #1e1e1e;
|
||||
}
|
||||
background: var(--mermaid-modal-content-bg);
|
||||
}
|
||||
|
||||
.mermaid-panzoom-container {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
html {
|
||||
font-size: 62.5%;
|
||||
overflow-y: scroll;
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
* {
|
||||
@@ -18,24 +19,3 @@ body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* scrollbar styles for Firefox */
|
||||
* {
|
||||
scrollbar-width: auto;
|
||||
scrollbar-color: var(--scrollbar-thumb) transparent;
|
||||
}
|
||||
/**/
|
||||
|
||||
/* scrollbar styles for Chromium */
|
||||
::-webkit-scrollbar {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--scrollbar-thumb);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
/**/
|
||||
|
||||
@@ -16,17 +16,17 @@
|
||||
margin: 0 auto;
|
||||
background: var(--card-background);
|
||||
border-radius: var(--card-border-radius);
|
||||
box-shadow: var(--shadow-l3);
|
||||
box-shadow: var(--shadow-l2);
|
||||
padding: var(--card-padding);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
gap: var(--spacing-md);
|
||||
|
||||
@include respond(md) {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
gap: var(--spacing-lg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
display: block;
|
||||
color: var(--card-text-color-main);
|
||||
font-size: 1.6rem;
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: var(--spacing-xs);
|
||||
}
|
||||
|
||||
p {
|
||||
@@ -51,7 +51,7 @@
|
||||
|
||||
.cookie-banner__actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,6 @@
|
||||
}
|
||||
|
||||
@include respond(md) {
|
||||
width: auto;
|
||||
margin-left: auto;
|
||||
align-self: center;
|
||||
}
|
||||
@@ -117,19 +116,19 @@
|
||||
h3 {
|
||||
color: var(--card-text-color-main);
|
||||
font-size: 1.6rem;
|
||||
margin: 0 0 15px 0;
|
||||
margin: 0 0 var(--spacing-md) 0;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
margin-top: 20px;
|
||||
gap: var(--spacing-sm);
|
||||
margin-top: var(--spacing-lg);
|
||||
}
|
||||
}
|
||||
|
||||
.cookie-category {
|
||||
padding: 15px 0;
|
||||
padding: var(--spacing-md) 0;
|
||||
border-bottom: 1px solid var(--card-separator-color);
|
||||
|
||||
&:last-of-type {
|
||||
@@ -139,7 +138,7 @@
|
||||
label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
cursor: pointer;
|
||||
|
||||
input[type="checkbox"] {
|
||||
@@ -186,14 +185,13 @@
|
||||
|
||||
// Comments placeholder when consent not given
|
||||
.consent-placeholder {
|
||||
background: var(--card-background);
|
||||
border-radius: var(--card-border-radius);
|
||||
@include card-style;
|
||||
padding: var(--card-padding);
|
||||
text-align: center;
|
||||
color: var(--card-text-color-secondary);
|
||||
font-size: 1.4rem;
|
||||
|
||||
p {
|
||||
margin: 0 0 15px 0;
|
||||
margin: 0 0 var(--spacing-md) 0;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
footer.site-footer {
|
||||
padding: 20px 0 var(--section-separation) 0;
|
||||
padding: var(--spacing-lg) 0 var(--section-separation) 0;
|
||||
font-size: 1.4rem;
|
||||
line-height: 1.75;
|
||||
|
||||
@@ -9,13 +9,13 @@ footer.site-footer {
|
||||
height: 3px;
|
||||
width: 50px;
|
||||
background: var(--body-text-color);
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.copyright {
|
||||
color: var(--accent-color);
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.powerby {
|
||||
|
||||
@@ -45,41 +45,7 @@
|
||||
|
||||
.article-footer {
|
||||
margin: var(--card-padding);
|
||||
margin-top: 0;
|
||||
|
||||
section:not(:first-child) {
|
||||
margin-top: var(--card-padding);
|
||||
}
|
||||
|
||||
section {
|
||||
color: var(--card-text-color-tertiary);
|
||||
text-transform: uppercase;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 1.4rem;
|
||||
gap: 15px;
|
||||
|
||||
svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
stroke-width: 1.33;
|
||||
}
|
||||
}
|
||||
|
||||
.article-tags {
|
||||
text-transform: unset;
|
||||
}
|
||||
|
||||
.article-copyright,
|
||||
.article-lastmod {
|
||||
a {
|
||||
color: var(--body-text-color);
|
||||
}
|
||||
|
||||
a.link {
|
||||
box-shadow: unset;
|
||||
}
|
||||
}
|
||||
gap: var(--spacing-2xl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,14 +77,14 @@
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 15px 0 15px 20px;
|
||||
padding: 5px;
|
||||
margin: var(--spacing-md) 0 var(--spacing-md) var(--spacing-lg);
|
||||
padding: var(--spacing-xs);
|
||||
|
||||
&>ol,
|
||||
&>ul {
|
||||
margin-top: 10px;
|
||||
padding-left: 10px;
|
||||
margin-bottom: -5px;
|
||||
margin-top: var(--spacing-sm);
|
||||
padding-left: var(--spacing-sm);
|
||||
margin-bottom: calc(var(--spacing-xs) * -1);
|
||||
|
||||
&>li:last-child {
|
||||
margin-bottom: 0;
|
||||
@@ -167,10 +133,6 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: var(--card-text-color-main);
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: var(--card-separator-color);
|
||||
}
|
||||
}
|
||||
|
||||
.widget--toc {
|
||||
@@ -182,7 +144,7 @@
|
||||
|
||||
.article-toc {
|
||||
padding: 0 var(--card-padding);
|
||||
margin-top: 20px;
|
||||
margin-top: var(--spacing-lg);
|
||||
|
||||
@include respond(lg) {
|
||||
display: none;
|
||||
@@ -203,7 +165,7 @@
|
||||
|
||||
summary {
|
||||
list-style: none;
|
||||
padding: 15px 20px;
|
||||
padding: var(--spacing-md) var(--spacing-lg);
|
||||
cursor: pointer;
|
||||
|
||||
&::-webkit-details-marker {
|
||||
@@ -213,7 +175,7 @@
|
||||
.article-toc-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
text-transform: uppercase;
|
||||
font-size: 1.4rem;
|
||||
font-weight: bold;
|
||||
@@ -230,35 +192,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.related-content {
|
||||
overflow-x: auto;
|
||||
padding-bottom: 15px;
|
||||
|
||||
&>.flex {
|
||||
float: left;
|
||||
}
|
||||
|
||||
article {
|
||||
margin-right: 15px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
width: 250px;
|
||||
height: 150px;
|
||||
|
||||
.article-title {
|
||||
font-size: 1.8rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&.has-image {
|
||||
.article-details {
|
||||
padding: 20px;
|
||||
background: linear-gradient(0deg, rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0.75) 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.article-content {
|
||||
font-family: var(--article-font-family);
|
||||
font-size: var(--article-font-size);
|
||||
@@ -315,7 +248,7 @@
|
||||
position: relative;
|
||||
margin: 1.5em 0;
|
||||
border-inline-start: var(--blockquote-border-size) solid var(--card-separator-color);
|
||||
padding: 15px calc(var(--card-padding) - var(--blockquote-border-size));
|
||||
padding: var(--spacing-md) calc(var(--card-padding) - var(--blockquote-border-size));
|
||||
background-color: var(--blockquote-background-color);
|
||||
|
||||
.cite {
|
||||
@@ -385,7 +318,7 @@
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
margin: 1.5em 0;
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
|
||||
figure {
|
||||
margin: 0;
|
||||
@@ -420,6 +353,10 @@
|
||||
padding: var(--card-padding);
|
||||
position: relative;
|
||||
|
||||
pre {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.copyCodeButton {
|
||||
opacity: 1;
|
||||
@@ -432,7 +369,6 @@
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: initial;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: auto;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
.section-card {
|
||||
border-radius: var(--card-border-radius);
|
||||
background-color: var(--card-background);
|
||||
@include card-style;
|
||||
padding: var(--small-card-padding);
|
||||
box-shadow: var(--shadow-l1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
gap: var(--spacing-lg);
|
||||
|
||||
--separation: 15px;
|
||||
|
||||
@@ -47,18 +45,24 @@
|
||||
}
|
||||
|
||||
.subsection-list {
|
||||
--shadow-overlap-x: calc(var(--shadow-l2-blur) + 4px);
|
||||
--shadow-overlap-y: calc(var(--shadow-l2-blur) + var(--shadow-l2-y) + 4px);
|
||||
|
||||
overflow-x: auto;
|
||||
margin-left: -24px;
|
||||
|
||||
/// These values are computed from the shadow of the article-list--tile (which uses shadow-l1 and shadow-l2)
|
||||
/// so that the shadow is not cut off
|
||||
margin-left: calc(var(--shadow-overlap-x) * -1);
|
||||
margin-right: calc(var(--shadow-overlap-x) * -1);
|
||||
margin-bottom: calc(var(--shadow-overlap-y) * -1);
|
||||
|
||||
.article-list--tile {
|
||||
display: flex;
|
||||
padding: 8px 0 34px 24px;
|
||||
padding: var(--spacing-xs) var(--shadow-overlap-x) var(--shadow-overlap-y) var(--shadow-overlap-x);
|
||||
width: max-content;
|
||||
gap: var(--spacing-lg);
|
||||
|
||||
article {
|
||||
width: 250px;
|
||||
height: 150px;
|
||||
margin-right: 20px;
|
||||
flex-shrink: 0;
|
||||
|
||||
.article-title {
|
||||
@@ -67,7 +71,7 @@
|
||||
}
|
||||
|
||||
.article-details {
|
||||
padding: 20px;
|
||||
padding: var(--spacing-lg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
|
||||
label {
|
||||
font-size: 1.3rem;
|
||||
top: 10px;
|
||||
top: var(--spacing-sm);
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: 1.5rem;
|
||||
padding: 30px 20px 15px 20px;
|
||||
padding: var(--spacing-2xl) var(--spacing-lg) var(--spacing-md) var(--spacing-lg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,21 +23,20 @@
|
||||
|
||||
label {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
inset-inline-start: 20px;
|
||||
top: var(--spacing-md);
|
||||
inset-inline-start: var(--spacing-lg);
|
||||
font-size: 1.4rem;
|
||||
color: var(--card-text-color-tertiary);
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 40px 20px 20px;
|
||||
border-radius: var(--card-border-radius);
|
||||
background-color: var(--card-background);
|
||||
box-shadow: var(--shadow-l1);
|
||||
@include card-style;
|
||||
color: var(--card-text-color-main);
|
||||
width: 100%;
|
||||
border: 0;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
|
||||
transition: box-shadow 0.3s ease;
|
||||
|
||||
@@ -80,3 +79,9 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.search-result {
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
.hamburger {
|
||||
padding-top: 10px;
|
||||
padding-top: var(--spacing-sm);
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
transition-property: opacity, filter;
|
||||
@@ -26,16 +26,6 @@
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.hamburger.is-active:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.hamburger.is-active .hamburger-inner,
|
||||
.hamburger.is-active .hamburger-inner::before,
|
||||
.hamburger.is-active .hamburger-inner::after {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.hamburger-box {
|
||||
width: 30px;
|
||||
height: 24px;
|
||||
@@ -149,7 +139,7 @@
|
||||
display: none;
|
||||
margin: 0 calc(var(--container-padding) * -1);
|
||||
|
||||
padding: 30px 30px;
|
||||
padding: var(--spacing-2xl);
|
||||
|
||||
@include respond(xl) {
|
||||
padding: 15px 0;
|
||||
@@ -158,10 +148,10 @@
|
||||
&,
|
||||
.menu-bottom-section ol {
|
||||
flex-direction: column;
|
||||
gap: 30px;
|
||||
gap: var(--spacing-2xl);
|
||||
|
||||
@include respond(xl) {
|
||||
gap: 25px;
|
||||
gap: var(--spacing-xl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +220,7 @@
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
|
||||
svg {
|
||||
width: 24px;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
.pagination {
|
||||
display: flex;
|
||||
background-color: var(--card-background);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--card-border-radius);
|
||||
@include card-style;
|
||||
overflow: hidden;
|
||||
|
||||
.page-link {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
position: relative;
|
||||
|
||||
--sidebar-avatar-size: 100px;
|
||||
--sidebar-element-separation: 20px;
|
||||
--sidebar-element-separation: var(--spacing-lg);
|
||||
--emoji-size: 40px;
|
||||
--emoji-font-size: 20px;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
@include respond(2xl) {
|
||||
--sidebar-avatar-size: 120px;
|
||||
--sidebar-element-separation: 25px;
|
||||
--sidebar-element-separation: var(--spacing-xl);
|
||||
--emoji-size: 40px;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
}
|
||||
|
||||
.site-meta {
|
||||
gap: 5px;
|
||||
gap: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.site-name {
|
||||
@@ -144,7 +144,7 @@
|
||||
.site-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
.widget-icon {
|
||||
svg {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: var(--widget-icon-size);
|
||||
height: var(--widget-icon-size);
|
||||
stroke-width: 1.6;
|
||||
color: var(--body-text-color);
|
||||
}
|
||||
@@ -17,11 +17,10 @@
|
||||
.tagCloud-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
gap: var(--spacing-sm);
|
||||
|
||||
a {
|
||||
background: var(--card-background);
|
||||
box-shadow: var(--shadow-l1);
|
||||
@include card-style;
|
||||
border-radius: var(--tag-border-radius);
|
||||
padding: 8px 20px;
|
||||
color: var(--card-text-color-main);
|
||||
@@ -38,9 +37,7 @@
|
||||
/* Archives widget */
|
||||
.widget.archives {
|
||||
.widget-archive--list {
|
||||
border-radius: var(--card-border-radius);
|
||||
box-shadow: var(--shadow-l1);
|
||||
background-color: var(--card-background);
|
||||
@include card-style;
|
||||
}
|
||||
|
||||
.archives-year {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
@import "breakpoints.scss";
|
||||
@import "variables.scss";
|
||||
@import "mixins.scss";
|
||||
@import "grid.scss";
|
||||
|
||||
@import "external/normalize.scss";
|
||||
|
||||
+68
-13
@@ -19,17 +19,12 @@
|
||||
|
||||
--section-separation: 40px;
|
||||
|
||||
--scrollbar-thumb: hsl(0, 0%, 85%);
|
||||
--scrollbar-track: var(--body-background);
|
||||
|
||||
&[data-scheme="dark"] {
|
||||
--body-background: #303030;
|
||||
--accent-color: #ecf0f1;
|
||||
--accent-color-darker: #bdc3c7;
|
||||
--accent-color-text: #000;
|
||||
--body-text-color: rgba(255, 255, 255, 0.7);
|
||||
--scrollbar-thumb: hsl(0, 0%, 40%);
|
||||
--scrollbar-track: var(--body-background);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,9 +115,6 @@
|
||||
--link-background-opacity: 0.5;
|
||||
--link-background-opacity-hover: 0.7;
|
||||
|
||||
--pre-background-color: #272822;
|
||||
--pre-text-color: #f8f8f2;
|
||||
|
||||
--code-background-color: rgba(0, 0, 0, 0.12);
|
||||
--code-text-color: #808080;
|
||||
|
||||
@@ -147,11 +139,13 @@
|
||||
* Thanks to https://www.figma.com/community/plugin/744987207861965946/Shadow-picker
|
||||
*/
|
||||
:root {
|
||||
--shadow-l1: 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 0px 2px rgba(0, 0, 0, 0.06), 0px 0px 1px rgba(0, 0, 0, 0.04);
|
||||
--shadow-l2: 0px 10px 20px rgba(0, 0, 0, 0.04), 0px 2px 6px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.04);
|
||||
--shadow-l3: 0px 10px 20px rgba(0, 0, 0, 0.04), 0px 2px 6px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.04);
|
||||
--shadow-l4: 0px 24px 32px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), 0px 4px 8px rgba(0, 0, 0, 0.04),
|
||||
0px 0px 1px rgba(0, 0, 0, 0.04);
|
||||
--shadow-l1-y: 4px;
|
||||
--shadow-l1-blur: 8px;
|
||||
--shadow-l2-y: 10px;
|
||||
--shadow-l2-blur: 20px;
|
||||
|
||||
--shadow-l1: 0px var(--shadow-l1-y) var(--shadow-l1-blur) rgba(0, 0, 0, 0.04), 0px 0px 2px rgba(0, 0, 0, 0.06), 0px 0px 1px rgba(0, 0, 0, 0.04);
|
||||
--shadow-l2: 0px var(--shadow-l2-y) var(--shadow-l2-blur) rgba(0, 0, 0, 0.04), 0px 2px 6px rgba(0, 0, 0, 0.04), 0px 0px 1px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
[data-scheme="light"] {
|
||||
@@ -169,5 +163,66 @@
|
||||
:root {
|
||||
--menu-icon-separation: 40px;
|
||||
--container-padding: 15px;
|
||||
|
||||
@include respond(md) {
|
||||
--container-padding: 20px;
|
||||
}
|
||||
|
||||
--widget-separation: var(--section-separation);
|
||||
|
||||
/* Spacing tokens */
|
||||
--spacing-xs: 5px;
|
||||
--spacing-sm: 10px;
|
||||
--spacing-md: 15px;
|
||||
--spacing-lg: 20px;
|
||||
--spacing-xl: 25px;
|
||||
--spacing-2xl: 30px;
|
||||
--spacing-3xl: 40px;
|
||||
|
||||
/* Article image height variables */
|
||||
--article-image-height: 150px;
|
||||
|
||||
@include respond(md) {
|
||||
--article-image-height: 200px;
|
||||
}
|
||||
|
||||
@include respond(xl) {
|
||||
--article-image-height: 250px;
|
||||
}
|
||||
|
||||
/* Mermaid component variables */
|
||||
--mermaid-toolbar-btn-bg: rgba(255, 255, 255, 0.95);
|
||||
--mermaid-toolbar-btn-text: #333;
|
||||
--mermaid-modal-bg: rgba(0, 0, 0, 0.95);
|
||||
--mermaid-modal-content-bg: #fff;
|
||||
--mermaid-modal-btn-bg: #fff;
|
||||
--mermaid-modal-btn-hover: #ddd;
|
||||
|
||||
&[data-scheme="dark"] {
|
||||
--mermaid-toolbar-btn-bg: rgba(0, 0, 0, 0.85);
|
||||
--mermaid-toolbar-btn-text: #eee;
|
||||
--mermaid-modal-content-bg: #1e1e1e;
|
||||
--mermaid-modal-btn-bg: #333;
|
||||
--mermaid-modal-btn-hover: #444;
|
||||
}
|
||||
|
||||
/* Article compact image size */
|
||||
--article-compact-image-size: 50px;
|
||||
|
||||
@include respond(md) {
|
||||
--article-compact-image-size: 60px;
|
||||
}
|
||||
|
||||
/* Widget icon size */
|
||||
--widget-icon-size: 32px;
|
||||
|
||||
/* Article list tile variables */
|
||||
--article-tile-width: 250px;
|
||||
--article-tile-height: 150px;
|
||||
--article-tile-overlay-bg: rgba(0, 0, 0, 0.25);
|
||||
--article-tile-text-color: #fff;
|
||||
|
||||
&[data-scheme="dark"] {
|
||||
--article-tile-overlay-bg: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
}
|
||||
+28
-13
@@ -26,15 +26,15 @@ const tagsToReplace = {
|
||||
'…': '…'
|
||||
};
|
||||
|
||||
function replaceTag(tag) {
|
||||
return tagsToReplace[tag] || tag;
|
||||
function replaceTag(tag: string) {
|
||||
return (tagsToReplace as Record<string, string>)[tag] || tag;
|
||||
}
|
||||
|
||||
function replaceHTMLEnt(str) {
|
||||
function replaceHTMLEnt(str: string) {
|
||||
return str.replace(/[&<>"]/g, replaceTag);
|
||||
}
|
||||
|
||||
function escapeRegExp(string) {
|
||||
function escapeRegExp(string: string) {
|
||||
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
@@ -45,13 +45,21 @@ class Search {
|
||||
private list: HTMLDivElement;
|
||||
private resultTitle: HTMLHeadElement;
|
||||
private resultTitleTemplate: string;
|
||||
private container: HTMLDivElement;
|
||||
|
||||
constructor({ form, input, list, resultTitle, resultTitleTemplate }) {
|
||||
constructor({ form, input, list, resultTitle, resultTitleTemplate }: {
|
||||
form: HTMLFormElement,
|
||||
input: HTMLInputElement,
|
||||
list: HTMLDivElement,
|
||||
resultTitle: HTMLHeadingElement,
|
||||
resultTitleTemplate: string
|
||||
}) {
|
||||
this.form = form;
|
||||
this.input = input;
|
||||
this.list = list;
|
||||
this.resultTitle = resultTitle;
|
||||
this.resultTitleTemplate = resultTitleTemplate;
|
||||
this.container = list.parentElement as HTMLDivElement;
|
||||
|
||||
/// Check if there's already value in the search input
|
||||
if (this.input.value.trim() !== '') {
|
||||
@@ -203,16 +211,18 @@ class Search {
|
||||
const endTime = performance.now();
|
||||
|
||||
this.resultTitle.innerText = this.generateResultTitle(results.length, ((endTime - startTime) / 1000).toPrecision(1));
|
||||
|
||||
this.container?.classList.remove('hidden');
|
||||
}
|
||||
|
||||
private generateResultTitle(resultLen, time) {
|
||||
return this.resultTitleTemplate.replace("#PAGES_COUNT", resultLen).replace("#TIME_SECONDS", time);
|
||||
private generateResultTitle(resultLen: number, time: string) {
|
||||
return this.resultTitleTemplate.replace("#PAGES_COUNT", resultLen.toString()).replace("#TIME_SECONDS", time);
|
||||
}
|
||||
|
||||
public async getData() {
|
||||
if (!this.data) {
|
||||
/// Not fetched yet
|
||||
const jsonURL = this.form.dataset.json;
|
||||
const jsonURL = this.form.dataset.json as string;
|
||||
this.data = await fetch(jsonURL).then(res => res.json());
|
||||
const parser = new DOMParser();
|
||||
|
||||
@@ -227,7 +237,7 @@ class Search {
|
||||
private bindSearchForm() {
|
||||
let lastSearch = '';
|
||||
|
||||
const eventHandler = (e) => {
|
||||
const eventHandler = (e: Event) => {
|
||||
e.preventDefault();
|
||||
const keywords = this.input.value.trim();
|
||||
|
||||
@@ -251,6 +261,7 @@ class Search {
|
||||
private clear() {
|
||||
this.list.innerHTML = '';
|
||||
this.resultTitle.innerText = '';
|
||||
this.container.classList.add('hidden');
|
||||
}
|
||||
|
||||
private bindQueryStringChange() {
|
||||
@@ -261,7 +272,7 @@ class Search {
|
||||
|
||||
private handleQueryString() {
|
||||
const pageURL = new URL(window.location.toString());
|
||||
const keywords = pageURL.searchParams.get('keyword');
|
||||
const keywords = pageURL.searchParams.get('keyword') || '';
|
||||
this.input.value = keywords;
|
||||
|
||||
if (keywords) {
|
||||
@@ -291,7 +302,8 @@ class Search {
|
||||
}
|
||||
|
||||
public static render(item: pageData) {
|
||||
return <article>
|
||||
return (
|
||||
<article>
|
||||
<a href={item.permalink}>
|
||||
<div class="article-details">
|
||||
<h2 class="article-title" dangerouslySetInnerHTML={{ __html: item.title }}></h2>
|
||||
@@ -303,7 +315,8 @@ class Search {
|
||||
</div>
|
||||
}
|
||||
</a>
|
||||
</article>;
|
||||
</article>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,10 +329,12 @@ declare global {
|
||||
window.addEventListener('load', () => {
|
||||
setTimeout(function () {
|
||||
const searchForm = document.querySelector('.search-form') as HTMLFormElement,
|
||||
searchInput = searchForm.querySelector('input') as HTMLInputElement,
|
||||
searchInput = searchForm?.querySelector('input') as HTMLInputElement,
|
||||
searchResultList = document.querySelector('.search-result--list') as HTMLDivElement,
|
||||
searchResultTitle = document.querySelector('.search-result--title') as HTMLHeadingElement;
|
||||
|
||||
if (!searchForm || !searchInput || !searchResultList || !searchResultTitle) return;
|
||||
|
||||
new Search({
|
||||
form: searchForm,
|
||||
input: searchInput,
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[hugoVersion]
|
||||
extended = true
|
||||
min = "0.154.0"
|
||||
min = "0.157.0"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
mainSections = ["post"]
|
||||
featuredImageField = "image"
|
||||
rssFullContent = true
|
||||
# Accepted values: "default", "lastmod"
|
||||
# default = see https://gohugo.io/quick-reference/glossary/#default-sort-order
|
||||
@@ -75,10 +74,17 @@ SortBy = "default"
|
||||
toggle = true
|
||||
default = "auto"
|
||||
|
||||
[imageProcessing.cover]
|
||||
[imageProcessing]
|
||||
autoOrient = false
|
||||
|
||||
[imageProcessing.external]
|
||||
timeout = "5s"
|
||||
|
||||
[imageProcessing.content]
|
||||
widths = [800, 1600, 2400]
|
||||
enabled = true
|
||||
|
||||
[imageProcessing.content]
|
||||
[imageProcessing.thumbnail]
|
||||
enabled = true
|
||||
|
||||
# GDPR Cookie Consent Configuration
|
||||
|
||||
@@ -13,7 +13,7 @@ favicon = "img/avatar.png"
|
||||
[article]
|
||||
[article.license]
|
||||
enabled = true
|
||||
default = "Licensed under CC BY-NC-SA 4.0"
|
||||
default = "Licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)"
|
||||
|
||||
[widgets]
|
||||
homepage = [
|
||||
|
||||
@@ -1,24 +1,30 @@
|
||||
{{- $image := partial "helper/image" (dict "Resources" .Page.Resources "Image" .Destination) -}}
|
||||
{{- $image := partial "helper/image" (dict "Resources" .Page.Resources "Image" .Destination "Context" .Page) -}}
|
||||
{{- $alt := .PlainText | safeHTML -}}
|
||||
{{- $title := .Title | markdownify -}}
|
||||
|
||||
{{/* SVG and external images won't work with gallery layout, because their width and height attributes are unknown */}}
|
||||
{{/* There are some types of images that don't have width and height attributes, such as SVG */}}
|
||||
{{- $galleryImage := and $image.Height $image.Width -}}
|
||||
|
||||
<img src="{{ $image.Permalink }}"
|
||||
{{ with $image.Width }}width="{{ . }}"{{ end }}
|
||||
{{ with $image.Height }}height="{{ . }}"{{ end }}
|
||||
loading="lazy"
|
||||
{{ with $alt }}
|
||||
alt="{{ . }}"
|
||||
{{ end }}
|
||||
{{ with $title }}
|
||||
title="{{ . }}"
|
||||
data-title-escaped="{{ . | htmlEscape }}"
|
||||
{{ end }}
|
||||
{{ if $galleryImage }}
|
||||
class="gallery-image"
|
||||
data-flex-grow="{{ div (mul $image.Width 100) $image.Height }}"
|
||||
data-flex-basis="{{ div (mul $image.Width 240) $image.Height }}px"
|
||||
{{ end }}
|
||||
>
|
||||
{{- $attributes := dict -}}
|
||||
{{- if $galleryImage -}}
|
||||
{{- $attributes = (dict
|
||||
"data-flex-grow" (div (mul $image.Width 100) $image.Height)
|
||||
"data-flex-basis" (printf "%dpx" (div (mul $image.Width 240) $image.Height))
|
||||
) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{ partial "helper/responsive-image" (dict
|
||||
"Resource" $image.Resource
|
||||
"Widths" (cond .Page.Site.Params.ImageProcessing.Content.Enabled .Page.Site.Params.ImageProcessing.Content.Widths nil)
|
||||
"Attributes" (merge $attributes (dict
|
||||
"src" $image.Permalink
|
||||
"width" $image.Width
|
||||
"height" $image.Height
|
||||
"alt" $alt
|
||||
"title" $title
|
||||
"data-title-escaped" ($title | htmlEscape)
|
||||
"class" (cond $galleryImage "gallery-image" "")
|
||||
"loading" "lazy"
|
||||
"sizes" "(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px"
|
||||
))
|
||||
) }}
|
||||
@@ -4,18 +4,45 @@
|
||||
<h2 class="article-title">
|
||||
{{- .Title -}}
|
||||
</h2>
|
||||
<footer class="article-time">
|
||||
<time datetime='{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}'>
|
||||
{{- .Date | time.Format (or .Site.Params.dateFormat.published "Jan 02, 2006") -}}
|
||||
|
||||
{{- $description := .Params.description -}}
|
||||
{{- $IsTerm := in .Kind "term" -}}
|
||||
{{- if $IsTerm -}}
|
||||
{{- $description = $description | default (T "list.page" (len .Pages)) -}}
|
||||
{{- end -}}
|
||||
{{- if or $description (not .Date.IsZero) -}}
|
||||
{{/*
|
||||
If it's a term, the date is extracted from the first page of the collection, which is not very useful.
|
||||
In that case, we prefer to display the description (if set), or the number of pages within the collection.
|
||||
*/}}
|
||||
<footer class="article-meta">
|
||||
{{- if or $IsTerm .Date.IsZero -}}
|
||||
<span class="article-description">{{- $description -}}</span>
|
||||
{{- else if not .Date.IsZero -}}
|
||||
<time datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">
|
||||
{{- .Date | time.Format .Site.Params.dateFormat.published -}}
|
||||
</time>
|
||||
{{- end }}
|
||||
</footer>
|
||||
{{- end -}}
|
||||
</div>
|
||||
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources) -}}
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources "Context" .) -}}
|
||||
{{ if $image }}
|
||||
<div class="article-image">
|
||||
<img src="{{ $image.Permalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}" alt="{{ .Title }}"
|
||||
loading="lazy">
|
||||
{{ partial "helper/thumbnail-image" (dict
|
||||
"Resource" $image.Resource
|
||||
"Width" 60
|
||||
"Height" 60
|
||||
"Resize" .Site.Params.ImageProcessing.Thumbnail.Enabled
|
||||
"Attributes" (dict
|
||||
"src" $image.Permalink
|
||||
"alt" .Title
|
||||
"loading" "lazy"
|
||||
"width" $image.Width
|
||||
"height" $image.Height
|
||||
)
|
||||
) }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</a>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{{ $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources) }}
|
||||
{{ $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources "Context" .) }}
|
||||
<article class="{{ if $image }}has-image{{ end }}">
|
||||
{{ partial "article/components/header" (dict "Page" . "IsList" true) }}
|
||||
</article>
|
||||
@@ -1,15 +1,26 @@
|
||||
{{ $image := partial "helper/image" (dict "Image" .context.Params.image "Resources" .context.Resources) }}
|
||||
{{ $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources "Context" .) }}
|
||||
<article class="{{ if $image }}has-image{{ end }}">
|
||||
<a href="{{ .context.RelPermalink }}">
|
||||
<a href="{{ .RelPermalink }}">
|
||||
{{ if $image }}
|
||||
<div class="article-image">
|
||||
<img src="{{ $image.Permalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}" loading="lazy"
|
||||
alt="Featured image of post {{ .context.Title }}">
|
||||
{{ partial "helper/thumbnail-image" (dict
|
||||
"Resource" $image.Resource
|
||||
"Width" 250
|
||||
"Height" 150
|
||||
"Resize" .Site.Params.ImageProcessing.Thumbnail.Enabled
|
||||
"Attributes" (dict
|
||||
"src" $image.Permalink
|
||||
"alt" (printf "Featured image of post %s" .Title)
|
||||
"loading" "lazy"
|
||||
"width" $image.Width
|
||||
"height" $image.Height
|
||||
)
|
||||
) }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<div class="article-details"
|
||||
{{- if and $image $image.Resource -}}
|
||||
{{- if and $image (reflect.IsImageResourceProcessable $image.Resource) -}}
|
||||
{{- $colors := $image.Resource.Colors -}}
|
||||
{{- if $colors -}}
|
||||
{{- $vibrant := index $colors 0 -}}
|
||||
@@ -19,7 +30,7 @@
|
||||
{{- end -}}
|
||||
>
|
||||
<h2 class="article-title">
|
||||
{{- .context.Title -}}
|
||||
{{- .Title -}}
|
||||
</h2>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -28,50 +28,49 @@
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{ $showReadingTime := $Page.Params.readingTime | default (.Site.Params.article.readingTime) }}
|
||||
{{ $showReadingTime := $Page.Params.readingTime | default ($Page.Site.Params.article.readingTime) }}
|
||||
{{ $showDate := not $Page.Date.IsZero }}
|
||||
{{ $showFooter := or $showDate $showReadingTime }}
|
||||
{{ if $showFooter }}
|
||||
<footer class="article-time">
|
||||
{{ $showTime := or $showDate $showReadingTime }}
|
||||
{{ $showTranslations := $Page.IsTranslated }}
|
||||
{{ $showTags := and $Page.Site.Params.Article.List.ShowTags ($Page.GetTerms "tags") $IsList }}
|
||||
|
||||
{{ if or $showTime $showTranslations $showTags }}
|
||||
<footer class="article-meta">
|
||||
{{ if $showTime }}
|
||||
<div class="inline-meta">
|
||||
{{ if $showDate }}
|
||||
<div>
|
||||
{{ partial "helper/icon" "date" }}
|
||||
<time class="article-time--published" datetime='{{ $Page.Date.Format "2006-01-02T15:04:05Z07:00" }}'>
|
||||
{{- $Page.Date | time.Format $Page.Site.Params.dateFormat.published -}}
|
||||
</time>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if $showReadingTime }}
|
||||
<div>
|
||||
{{ partial "helper/icon" "clock" }}
|
||||
<time class="article-time--reading">
|
||||
{{ T "article.readingTime" $Page.ReadingTime }}
|
||||
</time>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</footer>
|
||||
{{ end }}
|
||||
|
||||
{{ if $Page.IsTranslated }}
|
||||
<footer class="article-translations">
|
||||
{{ if $showTranslations }}
|
||||
<div class="inline-meta">
|
||||
{{ partial "helper/icon" "language" }}
|
||||
<div>
|
||||
{{ range $Page.Translations }}
|
||||
<a href="{{ .RelPermalink }}" class="link">{{ .Language.LanguageName }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</footer>
|
||||
{{ end }}
|
||||
|
||||
{{ if and $Page.Site.Params.Article.List.ShowTags ($Page.GetTerms "tags") $IsList }}
|
||||
<footer class="article-header-tags">
|
||||
{{ if $showTags }}
|
||||
<div class="article-tags inline-meta">
|
||||
{{ partial "helper/icon" "tag" }}
|
||||
<div>
|
||||
{{ range ($Page.GetTerms "tags") }}
|
||||
<a href="{{ .RelPermalink }}" class="link">{{ .LinkTitle }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</footer>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<footer class="article-footer">
|
||||
<footer class="article-meta article-footer">
|
||||
{{ partial "article/components/tags" . }}
|
||||
|
||||
{{ if and (.Site.Params.article.license.enabled) (not (eq .Params.license false)) }}
|
||||
<section class="article-copyright">
|
||||
<section class="article-copyright inline-meta">
|
||||
{{ partial "helper/icon" "copyright" }}
|
||||
<span>{{ default .Site.Params.article.license.default .Params.license | markdownify }}</span>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{- if ne .Lastmod .Date -}}
|
||||
<section class="article-lastmod">
|
||||
<section class="article-lastmod inline-meta">
|
||||
{{ partial "helper/icon" "clock" }}
|
||||
<span>
|
||||
{{ T "article.lastUpdatedOn" }} {{ .Lastmod | time.Format .Site.Params.dateFormat.lastUpdated }}
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
{{- $IsList := .IsList -}}
|
||||
{{- $Page := .Page -}}
|
||||
<header class="article-header">
|
||||
{{- $image := partial "helper/image" (dict "Image" $Page.Params.image "Resources" $Page.Resources) -}}
|
||||
{{- $image := partial "helper/image" (dict "Image" $Page.Params.image "Resources" $Page.Resources "Context" $Page) -}}
|
||||
{{ if $image }}
|
||||
<div class="article-image">
|
||||
<a href="{{ $Page.RelPermalink }}">
|
||||
<img src="{{ $image.Permalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}" loading="lazy"
|
||||
alt="Featured image of post {{ $Page.Title }}" />
|
||||
{{ partial "helper/responsive-image" (dict
|
||||
"Resource" $image.Resource
|
||||
"Widths" (cond $Page.Site.Params.ImageProcessing.Content.Enabled $Page.Site.Params.ImageProcessing.Content.Widths nil)
|
||||
"Attributes" (dict
|
||||
"src" $image.Permalink
|
||||
"width" $image.Width
|
||||
"height" $image.Height
|
||||
"alt" (printf "Featured image of post %s" $Page.Title)
|
||||
"loading" "lazy"
|
||||
"sizes" "(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px"
|
||||
)
|
||||
) }}
|
||||
</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<div class="article-list--compact links">
|
||||
{{ range $i, $link := .Params.links }}
|
||||
{{ range $link := .Params.links }}
|
||||
<article>
|
||||
<a href="{{ $link.website }}" target="_blank" rel="noopener">
|
||||
<div class="article-details">
|
||||
<h2 class="article-title">
|
||||
{{- $link.title -}}
|
||||
</h2>
|
||||
<footer class="article-time">
|
||||
<footer class="article-meta">
|
||||
{{ with $link.description }}
|
||||
{{ . }}
|
||||
{{ else }}
|
||||
@@ -15,13 +15,22 @@
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{{ with $link.image }}
|
||||
{{ $permalink := . }}
|
||||
{{ with ($.Resources.GetMatch (printf "%s" (. | safeURL))) }}
|
||||
{{ $permalink = .RelPermalink }}
|
||||
{{ end }}
|
||||
{{- $image := partial "helper/image" (dict "Image" $link.image "Resources" $.Resources "Context" .) -}}
|
||||
{{- with $image -}}
|
||||
<div class="article-image">
|
||||
<img src="{{ $permalink }}" loading="lazy"{{ with $link.alt }} alt="{{ . }}"{{ end }}>
|
||||
{{ partial "helper/thumbnail-image" (dict
|
||||
"Resource" .Resource
|
||||
"Width" 60
|
||||
"Height" 60
|
||||
"Resize" $.Site.Params.ImageProcessing.Thumbnail.Enabled
|
||||
"Attributes" (dict
|
||||
"src" $image.Permalink
|
||||
"alt" $link.title
|
||||
"loading" "lazy"
|
||||
"width" .Width
|
||||
"height" .Height
|
||||
)
|
||||
) }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</a>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{{ $related := (.Site.RegularPages.Related .) | first 5 }}
|
||||
{{ with $related }}
|
||||
<aside class="related-content--wrapper">
|
||||
<aside>
|
||||
<h2 class="section-title">{{ T "article.relatedContent" }}</h2>
|
||||
<div class="related-content">
|
||||
<div class="flex article-list--tile">
|
||||
<div class="subsection-list">
|
||||
<div class="article-list--tile">
|
||||
{{ range . }}
|
||||
{{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "articleList") }}
|
||||
{{ partial "article-list/tile" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
|
||||
{{- end -}}
|
||||
|
||||
{{- $favicon := partial "helper/image" (dict "Image" .Site.Params.favicon "Resources" resources) -}}
|
||||
{{- $favicon := partial "helper/image" (dict "Image" .Site.Params.favicon "Resources" resources "Context" .) -}}
|
||||
{{ with $favicon }}
|
||||
<link rel="shortcut icon" href="{{ .Permalink }}" />
|
||||
{{ end }}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{ $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources) }}
|
||||
{{ $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources "Context" .) }}
|
||||
{{- if $image -}}
|
||||
<meta property='og:image' content='{{ absURL $image.permalink }}' />
|
||||
{{- end -}}
|
||||
@@ -9,7 +9,7 @@
|
||||
<meta name="twitter:title" {{ printf "content=%q" $title | safeHTMLAttr }}>
|
||||
<meta name="twitter:description" {{ printf "content=%q" $description | safeHTMLAttr }}>
|
||||
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources) -}}
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources "Context" .) -}}
|
||||
{{- if $image -}}
|
||||
<meta name="twitter:card" content="{{ .Site.Params.opengraph.twitter.card }}">
|
||||
<meta name="twitter:image" content='{{ absURL $image.permalink }}' />
|
||||
|
||||
@@ -1,52 +1,69 @@
|
||||
/// Params:
|
||||
/// Resources: Where to search for images
|
||||
/// Image: Image URL
|
||||
/// Context: page context (used to access the configuration)
|
||||
|
||||
/// Returns:
|
||||
/// Local: true if the image is local, false if it is remote
|
||||
/// Resource: Hugo image resource object, not nil if the image is local
|
||||
/// Resource: Hugo image resource object
|
||||
/// Permalink: Image URL
|
||||
/// Height: Image height
|
||||
/// Width: Image width
|
||||
|
||||
{{ $result := "" }}
|
||||
{{ $result := dict }}
|
||||
|
||||
{{ if .Image }}
|
||||
{{ $url := urls.Parse .Image }}
|
||||
{{ $resource := "" }}
|
||||
{{ $permalink := .Image }}
|
||||
{{ $resource := dict
|
||||
"Resource" nil
|
||||
"Permalink" $permalink
|
||||
"Height" nil
|
||||
"Width" nil
|
||||
}}
|
||||
{{ $local := true }}
|
||||
|
||||
{{ if not (in (slice "https" "http") $url.Scheme) }}
|
||||
{{/* Local image */}}
|
||||
{{ $resource = .Resources.Get (printf "%s" (.Image | safeURL)) }}
|
||||
{{ else }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{/* Remote image */}}
|
||||
{{ with try (resources.GetRemote $url (dict "timeout" .Context.Site.Params.imageProcessing.external.timeout)) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "%s" . }}
|
||||
{{ warnf "Failed to fetch remote resource %q: %s" $url . }}
|
||||
{{ else with .Value }}
|
||||
{{ $resource = . }}
|
||||
{{ $local = false }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ warnf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $resource }}
|
||||
{{- $isSVG := eq $resource.MediaType.SubType "svg" -}}
|
||||
{{- if $isSVG -}}
|
||||
{{ if and .Context.Site.Params.imageProcessing.autoOrient (reflect.IsImageResourceProcessable $resource) }}
|
||||
{{ $filter := images.AutoOrient }}
|
||||
{{ $resource = $resource | images.Filter $filter }}
|
||||
{{ end }}
|
||||
|
||||
{{ if $local }}
|
||||
{{ $permalink = $resource.RelPermalink }}
|
||||
{{ end }}
|
||||
|
||||
{{ if reflect.IsImageResourceWithMeta $resource }}
|
||||
{{ $result = dict
|
||||
"Local" true
|
||||
"Resource" $resource
|
||||
"Permalink" $resource.RelPermalink
|
||||
"Height" nil
|
||||
"Width" nil
|
||||
}}
|
||||
{{- else -}}
|
||||
{{- $result = dict
|
||||
"Local" true
|
||||
"Resource" $resource
|
||||
"Permalink" $resource.RelPermalink
|
||||
"Permalink" $permalink
|
||||
"Height" $resource.Height
|
||||
"Width" $resource.Width
|
||||
}}
|
||||
{{- end -}}
|
||||
{{ else }}
|
||||
{{ $result = dict
|
||||
"Resource" $resource
|
||||
"Permalink" $permalink
|
||||
"Height" nil
|
||||
"Width" nil
|
||||
}}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{{- /*
|
||||
Params:
|
||||
Resource: Hugo image resource object (Optional, for processing)
|
||||
Widths: Slice of widths to generate for srcset
|
||||
Attributes: Map of HTML attributes for the <img> tag
|
||||
*/ -}}
|
||||
|
||||
{{- $resource := .Resource -}}
|
||||
{{- $widths := .Widths -}}
|
||||
{{- $attributes := .Attributes | default dict -}}
|
||||
|
||||
{{/* Generate srcset if Resource and Widths are provided */}}
|
||||
{{- if and $widths $resource (reflect.IsImageResourceProcessable $resource) -}}
|
||||
{{- $srcset := slice -}}
|
||||
{{- range $widths -}}
|
||||
{{- if lt . $resource.Width -}}
|
||||
{{- $resized := $resource.Resize (printf "%dx" .) -}}
|
||||
{{- $srcset = $srcset | append (printf "%s %dw" $resized.RelPermalink .) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if gt (len $srcset) 0 -}}
|
||||
{{- $permalink := default $resource.RelPermalink (index $attributes "src") -}}
|
||||
{{- $srcset = $srcset | append (printf "%s %dw" $permalink $resource.Width) -}}
|
||||
{{- $attributes = merge $attributes (dict "srcset" (delimit $srcset ", ")) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
<img {{- range $k, $v := $attributes -}}
|
||||
{{- if $v -}}
|
||||
{{- printf " %s=%q" (lower $k) (printf "%v" $v) | safeHTMLAttr -}}
|
||||
{{- end -}}
|
||||
{{- end -}}>
|
||||
@@ -0,0 +1,41 @@
|
||||
{{- /*
|
||||
Params:
|
||||
Resource: Hugo image resource object (Optional, for processing)
|
||||
Width: Image width (Required)
|
||||
Height: Image height (Required)
|
||||
Resize: Whether to perform resize (Optional, default: false)
|
||||
Attributes: Map of HTML attributes for the <img> tag
|
||||
*/ -}}
|
||||
|
||||
{{- $resource := .Resource -}}
|
||||
{{- $width := .Width -}}
|
||||
{{- $height := .Height -}}
|
||||
{{- $resize := .Resize -}}
|
||||
{{- $attributes := .Attributes | default dict -}}
|
||||
|
||||
{{- if and $resize $resource (reflect.IsImageResourceProcessable $resource) $width $height -}}
|
||||
{{/* Create thumbnail with 1x/2x descriptors */}}
|
||||
{{- $srcset := slice -}}
|
||||
{{- range (slice 1 2) -}}
|
||||
{{- $w := mul $width . -}}
|
||||
{{- $h := mul $height . -}}
|
||||
{{- if and (le $w $resource.Width) (le $h $resource.Height) -}}
|
||||
{{- $resized := $resource.Fill (printf "%dx%d" $w $h) -}}
|
||||
{{- $srcset = $srcset | append (printf "%s %dx" $resized.RelPermalink .) -}}
|
||||
|
||||
{{- if eq . 1 -}}
|
||||
{{- $attributes = merge $attributes (dict "src" $resized.RelPermalink) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if gt (len $srcset) 0 -}}
|
||||
{{- $attributes = merge $attributes (dict "width" $width "height" $height "srcset" (delimit $srcset ", ")) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
<img {{- range $k, $v := $attributes -}}
|
||||
{{- if $v -}}
|
||||
{{- printf " %s=%q" (lower $k) (printf "%v" $v) | safeHTMLAttr -}}
|
||||
{{- end -}}
|
||||
{{- end -}}>
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
<header>
|
||||
{{ with .Site.Params.sidebar.avatar }}
|
||||
{{- $avatar := partial "helper/image" (dict "Image" . "Resources" resources) -}}
|
||||
{{- $avatar := partial "helper/image" (dict "Image" . "Resources" resources "Context" $) -}}
|
||||
<figure class="site-avatar">
|
||||
<a href="{{ $.Site.Home.RelPermalink }}">
|
||||
<img src="{{ $avatar.Permalink }}"
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
<div class="widget-icon">
|
||||
{{ partial "helper/icon" "infinity" }}
|
||||
</div>
|
||||
<h2 class="widget-title section-title">{{ T "widget.archives.title" }}</h2>
|
||||
<h2 class="widget-title section-title">
|
||||
<a href="{{ $archivesPage.RelPermalink }}">
|
||||
{{ T "widget.archives.title" }}
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
{{ $pages := partial "helper/pages.html" $context.Site.Home }}
|
||||
{{ $archives := $pages.GroupByDate "2006" }}
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
{{- $widgetTitle := .Params.title -}}
|
||||
{{- $limit := default 10 .Params.limit -}}
|
||||
{{- $icon := default .Params.taxonomy .Params.icon -}}
|
||||
{{- $showLink := default false .Params.showLink -}}
|
||||
{{- $showLink := default true .Params.showLink -}}
|
||||
|
||||
<section class="widget tagCloud">
|
||||
<div class="widget-icon">
|
||||
{{ partial "helper/icon" $icon }}
|
||||
</div>
|
||||
<h2 class="widget-title section-title">
|
||||
{{ if $showLink }}
|
||||
{{ if and $showLink $taxonomyPage }}
|
||||
<a href="{{ $taxonomyPage.RelPermalink }}">
|
||||
{{ $widgetTitle }}
|
||||
</a>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<div class="subsection-list">
|
||||
<div class="article-list--tile">
|
||||
{{ range $terms }}
|
||||
{{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "taxonomy") }}
|
||||
{{ partial "article-list/tile" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+15
-6
@@ -17,13 +17,22 @@
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources) -}}
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources "Context" .) -}}
|
||||
{{ if $image }}
|
||||
<div class="section-image">
|
||||
<img src="{{ $image.Permalink }}"
|
||||
width="{{ $image.Width }}"
|
||||
height="{{ $image.Height }}"
|
||||
loading="lazy">
|
||||
{{ partial "helper/thumbnail-image" (dict
|
||||
"Resource" $image.Resource
|
||||
"Width" 60
|
||||
"Height" 60
|
||||
"Resize" .Site.Params.ImageProcessing.Thumbnail.Enabled
|
||||
"Attributes" (dict
|
||||
"src" $image.Permalink
|
||||
"alt" .Title
|
||||
"loading" "lazy"
|
||||
"width" $image.Width
|
||||
"height" $image.Height
|
||||
)
|
||||
) }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
@@ -42,7 +51,7 @@
|
||||
<div class="subsection-list">
|
||||
<div class="article-list--tile">
|
||||
{{ range . }}
|
||||
{{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "section") }}
|
||||
{{ partial "article-list/tile" . }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="search-result">
|
||||
<div class="search-result hidden">
|
||||
<h3 class="search-result--title section-title"></h3>
|
||||
<div class="search-result--list article-list--compact"></div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
{{- range $pages -}}
|
||||
{{- $data := dict "title" .Title "date" .Date "permalink" .RelPermalink "content" (.Plain) -}}
|
||||
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources) -}}
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources "Context" .) -}}
|
||||
{{- if $image -}}
|
||||
{{- $data = merge $data (dict "image" $image.Permalink) -}}
|
||||
{{- end -}}
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
{{- if .Site.Params.RSSFullContent -}}
|
||||
{{- $content = .Content -}}
|
||||
{{- end -}}
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources) -}}
|
||||
{{- $image := partial "helper/image" (dict "Image" .Params.image "Resources" .Resources "Context" .) -}}
|
||||
{{- if $image -}}
|
||||
{{- $imgTag := printf "<img src=\"%s\" alt=\"Featured image of post %s\" />" ($image.permalink | absURL) .Title -}}
|
||||
{{- $content = printf "%s%s" $imgTag $content -}}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ features = [
|
||||
"search",
|
||||
]
|
||||
|
||||
min_version = "0.154.0"
|
||||
min_version = "0.157.0"
|
||||
|
||||
[author]
|
||||
name = "Jimmy Cai"
|
||||
|
||||
Reference in New Issue
Block a user