mirror of
https://github.com/CaiJimmy/hugo-theme-stack.git
synced 2025-04-28 19:43:31 +08:00
Merge branch 'master' into toggle-dark-mode
This commit is contained in:
parent
7e1c7b94bf
commit
8d018a703f
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
custom: ['https://www.buymeacoffee.com/jimmycai']
|
31
.github/release-drafter.yml
vendored
Normal file
31
.github/release-drafter.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
name-template: 'v$RESOLVED_VERSION 🌈'
|
||||
tag-template: 'v$RESOLVED_VERSION'
|
||||
categories:
|
||||
- title: '🚀 Features'
|
||||
labels:
|
||||
- 'feature'
|
||||
- 'enhancement'
|
||||
- title: '🐛 Bug Fixes'
|
||||
labels:
|
||||
- 'fix'
|
||||
- 'bugfix'
|
||||
- 'bug'
|
||||
- title: '🧰 Maintenance'
|
||||
label: 'chore'
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks.
|
||||
version-resolver:
|
||||
major:
|
||||
labels:
|
||||
- 'major'
|
||||
minor:
|
||||
labels:
|
||||
- 'minor'
|
||||
patch:
|
||||
labels:
|
||||
- 'patch'
|
||||
default: patch
|
||||
template: |
|
||||
## Changes
|
||||
|
||||
$CHANGES
|
16
.github/workflows/release-drafter.yml
vendored
Normal file
16
.github/workflows/release-drafter.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
name: Release Drafter
|
||||
|
||||
on:
|
||||
push:
|
||||
# branches to consider in the event; optional, defaults to all
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Drafts your next Release notes as Pull Requests are merged into "master"
|
||||
- uses: release-drafter/release-drafter@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
19
README.md
19
README.md
@ -11,7 +11,7 @@
|
||||
|
||||
## Documentation & more information
|
||||
|
||||
[Documentation](https://www.notion.so/jimmycai/Hugo-Theme-Stack-511aec5b9ed845ce9b6e3ae0bf7fb6d4) | [中文文档](https://www.notion.so/jimmycai/Hugo-Theme-Stack-511aec5b9ed845ce9b6e3ae0bf7fb6d4)
|
||||
[Documentation](https://docs.stack.jimmycai.com/) | [中文文档](https://docs.stack.jimmycai.com/v/zh-cn/)
|
||||
|
||||
## Introduction
|
||||
|
||||
@ -35,7 +35,12 @@ The only JavaScript library being used is [node-vibrant](https://github.com/Vibr
|
||||
|
||||
This theme uses SCSS and TypeScript. For that reason, it's necessary to use **Hugo ≥ 0.74.0**.
|
||||
|
||||
**Note**: You'll need Hugo Extended version to edit SCSS files
|
||||
Use Hugo Extended version if you want to:
|
||||
|
||||
* Use the latest feature/fix from `master` branch
|
||||
* Edit SCSS files
|
||||
|
||||
**Compiled CSS are updated once per release.**
|
||||
|
||||
## Installation
|
||||
|
||||
@ -51,6 +56,14 @@ Please do not remove the "*Theme Stack designed by Jimmy*" text and link.
|
||||
|
||||
If you want to port this theme to another blogging platform, please let me know🙏.
|
||||
|
||||
## Sponsoring
|
||||
|
||||
If you like this theme, consider supporting its development:
|
||||
|
||||
<a href="https://www.buymeacoffee.com/jimmycai" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="Buy Me A Coffee" height="60px" width="217px"></a>
|
||||
|
||||
Your support is greatly appreciated :)
|
||||
|
||||
## Thanks to
|
||||
|
||||
- [Vibrant-Colors/node-vibrant](https://github.com/Vibrant-Colors/node-vibrant)
|
||||
@ -62,4 +75,4 @@ If you want to port this theme to another blogging platform, please let me know
|
||||
- [artchen/hexo-theme-element](https://github.com/artchen/hexo-theme-element)
|
||||
- [MunifTanjim/minimo](https://github.com/MunifTanjim/minimo)
|
||||
- [lepture/yue.css](https://github.com/lepture/yue.css)
|
||||
- Markdown gallery syntax from [Typlog](https://typlog.com/)
|
||||
- Markdown gallery syntax from [Typlog](https://typlog.com/)
|
||||
|
7
assets/icons/search.svg
Normal file
7
assets/icons/search.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-search" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z"/>
|
||||
<circle cx="10" cy="10" r="7" />
|
||||
<line x1="21" y1="21" x2="15" y2="15" />
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 355 B |
1
assets/scss/custom.scss
Normal file
1
assets/scss/custom.scss
Normal file
@ -0,0 +1 @@
|
||||
/* Place your custom SCSS in HUGO_SITE_FOLDER/assets/scss/custom.scss */
|
119
assets/scss/grid.scss
Normal file
119
assets/scss/grid.scss
Normal file
@ -0,0 +1,119 @@
|
||||
.container {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
&.extended {
|
||||
@media (min-width: $on-phone) {
|
||||
max-width: 800px;
|
||||
|
||||
.left-sidebar {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $on-tablet) {
|
||||
max-width: 972px;
|
||||
|
||||
.right-sidebar {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop) {
|
||||
max-width: 1200px;
|
||||
|
||||
.left-sidebar {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
.right-sidebar {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop-large) {
|
||||
max-width: 1536px;
|
||||
|
||||
.left-sidebar {
|
||||
width: 15%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.compact {
|
||||
@media (min-width: $on-phone) {
|
||||
max-width: 800px;
|
||||
|
||||
.left-sidebar {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $on-tablet) {
|
||||
max-width: 972px;
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop) {
|
||||
max-width: 1050px;
|
||||
|
||||
.left-sidebar {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop-large) {
|
||||
max-width: 1300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
&.column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&.on-phone--column {
|
||||
@media (max-width: $on-phone) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
&.align-items--flex-start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.do-not-shrink {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.do-not-overflow {
|
||||
min-width: 0;
|
||||
flex-shrink: 1;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
main.main {
|
||||
min-width: 0;
|
||||
padding: 0 15px;
|
||||
max-width: 100%;
|
||||
flex-grow: 1;
|
||||
padding-top: var(--main-top-padding);
|
||||
}
|
||||
|
||||
.main-grid {
|
||||
@media (max-width: $on-phone) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
@ -11,8 +11,8 @@
|
||||
border-radius: var(--card-border-radius);
|
||||
overflow: hidden;
|
||||
|
||||
transition: box-shadow .3s ease;
|
||||
|
||||
transition: box-shadow 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-l2);
|
||||
}
|
||||
@ -53,7 +53,7 @@
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
padding: var(--content-padding);
|
||||
padding: var(--card-padding);
|
||||
}
|
||||
|
||||
.article-category {
|
||||
@ -75,10 +75,14 @@
|
||||
}
|
||||
|
||||
.article-title {
|
||||
font-size: 2.4rem;
|
||||
font-weight: 600;
|
||||
margin: 10px 0;
|
||||
color: var(--card-text-color-main);
|
||||
font-size: 2.2rem;
|
||||
|
||||
@media (min-width: $on-desktop-large) {
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--card-text-color-main);
|
||||
@ -88,14 +92,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop-large) {
|
||||
font-size: 2.4rem;
|
||||
}
|
||||
|
||||
@media (max-width: $on-desktop) {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
& + .article-subtitle {
|
||||
margin-top: 0;
|
||||
}
|
||||
@ -103,18 +99,14 @@
|
||||
|
||||
.article-subtitle {
|
||||
font-weight: normal;
|
||||
font-size: 1.8rem;
|
||||
color: var(--card-text-color-secondary);
|
||||
margin: 5px 0;
|
||||
line-height: 1.5;
|
||||
|
||||
font-size: 1.75rem;
|
||||
@media (min-width: $on-desktop-large) {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
@media (max-width: $on-desktop) {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
.article-time {
|
||||
@ -125,9 +117,10 @@
|
||||
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
margin-right: 8px;
|
||||
margin-right: 15px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
stroke-width: 1.33;
|
||||
}
|
||||
|
||||
time {
|
||||
@ -159,24 +152,32 @@
|
||||
border-radius: var(--card-border-radius);
|
||||
box-shadow: var(--shadow-l1);
|
||||
background-color: var(--card-background);
|
||||
--image-size: 60px;
|
||||
|
||||
@media (max-width: $on-tablet) {
|
||||
--image-size: 50px;
|
||||
}
|
||||
|
||||
& + .pagination {
|
||||
margin-top: var(--section-separation);
|
||||
}
|
||||
|
||||
article {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--small-card-padding);
|
||||
& > a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--small-card-padding);
|
||||
}
|
||||
|
||||
&:not(:last-of-type) {
|
||||
border-bottom: 2px solid var(--card-separator-color);
|
||||
border-bottom: 1.5px solid var(--card-separator-color);
|
||||
}
|
||||
|
||||
.article-details {
|
||||
flex-grow: 1;
|
||||
padding: 0;
|
||||
padding-right: 15px;
|
||||
min-height: var(--image-size);
|
||||
}
|
||||
|
||||
.article-title {
|
||||
@ -190,10 +191,21 @@
|
||||
|
||||
.article-image {
|
||||
img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
width: var(--image-size);
|
||||
height: var(--image-size);
|
||||
}
|
||||
}
|
||||
|
||||
.article-time {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.article-preview{
|
||||
font-size: 1.4rem;
|
||||
color: var(--card-text-color-tertiary);
|
||||
margin-top: 10px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,5 +2,5 @@
|
||||
background-color: var(--card-background);
|
||||
box-shadow: var(--shadow-l1);
|
||||
border-radius: var(--card-border-radius);
|
||||
padding: var(--content-padding);
|
||||
padding: var(--card-padding);
|
||||
}
|
||||
|
@ -1,15 +1,5 @@
|
||||
.archives-group {
|
||||
margin-bottom: var(--section-separation);
|
||||
.archives-date {
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.6rem;
|
||||
font-weight: bold;
|
||||
|
||||
a {
|
||||
color: var(--body-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.template-archives {
|
||||
|
@ -43,7 +43,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
article {
|
||||
.main-article {
|
||||
background: var(--card-background);
|
||||
border-radius: var(--card-border-radius);
|
||||
box-shadow: var(--shadow-l1);
|
||||
@ -64,13 +64,13 @@
|
||||
}
|
||||
|
||||
.article-details {
|
||||
padding: var(--content-padding);
|
||||
padding: var(--card-padding);
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.article-content {
|
||||
margin: var(--content-padding) 0;
|
||||
margin: var(--card-padding) 0;
|
||||
color: var(--card-text-color-main);
|
||||
|
||||
img {
|
||||
@ -80,11 +80,11 @@
|
||||
}
|
||||
|
||||
.article-footer {
|
||||
padding: var(--content-padding);
|
||||
padding-top: 0;
|
||||
margin: var(--card-padding);
|
||||
margin-top: 0;
|
||||
|
||||
section:not(:first-child) {
|
||||
margin-top: var(--content-padding);
|
||||
margin-top: var(--card-padding);
|
||||
}
|
||||
|
||||
section {
|
||||
@ -104,6 +104,7 @@
|
||||
|
||||
.article-tags {
|
||||
flex-wrap: wrap;
|
||||
text-transform: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,7 +193,7 @@
|
||||
|
||||
& > p {
|
||||
margin: 1.5em 0;
|
||||
padding: 0 var(--content-padding);
|
||||
padding: 0 var(--card-padding);
|
||||
}
|
||||
|
||||
h1,
|
||||
@ -201,7 +202,7 @@
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
padding: 0 calc(var(--content-padding) - var(--heading-border-size));
|
||||
padding: 0 calc(var(--card-padding) - var(--heading-border-size));
|
||||
border-left: var(--heading-border-size) solid var(--accent-color);
|
||||
}
|
||||
|
||||
@ -219,13 +220,13 @@
|
||||
position: relative;
|
||||
margin: 10px 0;
|
||||
border-left: var(--blockquote-border-size) solid var(--card-separator-color);
|
||||
padding: 15px calc(var(--content-padding) - var(--blockquote-border-size));
|
||||
padding: 15px calc(var(--card-padding) - var(--blockquote-border-size));
|
||||
background-color: var(--blockquote-background-color);
|
||||
}
|
||||
|
||||
& > ul,
|
||||
& > ol {
|
||||
margin: 1em var(--content-padding);
|
||||
margin: 1em var(--card-padding);
|
||||
}
|
||||
|
||||
hr {
|
||||
@ -270,7 +271,7 @@
|
||||
font-family: var(--code-font-family);
|
||||
line-height: 1.428571429;
|
||||
word-break: break-all;
|
||||
padding: var(--content-padding);
|
||||
padding: var(--card-padding);
|
||||
|
||||
code {
|
||||
color: unset;
|
||||
@ -281,9 +282,9 @@
|
||||
}
|
||||
|
||||
table {
|
||||
margin: 0 var(--content-padding);
|
||||
margin: 0 var(--card-padding);
|
||||
width: 100%;
|
||||
max-width: calc(100% - var(--content-padding) * 2);
|
||||
max-width: calc(100% - var(--card-padding) * 2);
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
margin-bottom: 1.5em;
|
||||
|
82
assets/scss/partials/layout/search.scss
Normal file
82
assets/scss/partials/layout/search.scss
Normal file
@ -0,0 +1,82 @@
|
||||
.search-form {
|
||||
margin-bottom: var(--section-separation);
|
||||
position: relative;
|
||||
--button-size: 80px;
|
||||
|
||||
&.widget {
|
||||
--button-size: 60px;
|
||||
|
||||
label {
|
||||
font-size: 1.3rem;
|
||||
top: 10px;
|
||||
}
|
||||
|
||||
input {
|
||||
font-size: 1.5rem;
|
||||
padding: 30px 20px 15px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 20px;
|
||||
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);
|
||||
color: var(--card-text-color-main);
|
||||
width: 100%;
|
||||
border: 0;
|
||||
-webkit-appearance: none;
|
||||
|
||||
transition: box-shadow 0.3s ease;
|
||||
|
||||
font-size: 1.8rem;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
box-shadow: var(--shadow-l2);
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: var(--button-size);
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
|
||||
padding: 0 10px;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
|
||||
svg {
|
||||
stroke-width: 2;
|
||||
color: var(--accent-color);
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
color: var(--card-text-color-secondary);
|
||||
stroke-width: 1.33;
|
||||
transition: all 0.3s ease;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,3 @@
|
||||
.taxonomy-type {
|
||||
text-transform: uppercase;
|
||||
color: var(--body-text-color);
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.taxonomy-card {
|
||||
border-radius: var(--card-border-radius);
|
||||
background-color: var(--card-background);
|
||||
|
@ -126,9 +126,11 @@
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 25px;
|
||||
margin-top: var(--sidebar-element-separation);
|
||||
margin-bottom: 0;
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
font-size: 1.5rem;
|
||||
|
||||
@media (min-width: $on-desktop-large) {
|
||||
margin-top: 30px;
|
||||
@ -180,6 +182,11 @@
|
||||
height: 25px;
|
||||
stroke-width: 1.33;
|
||||
margin-right: 40px;
|
||||
|
||||
@media (max-width: $on-desktop-large) {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
@ -187,9 +194,8 @@
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
color: var(--body-text-color);
|
||||
font-size: 1.5rem;
|
||||
|
||||
@media (max-width: $on-desktop) {
|
||||
@media (max-width: $on-desktop-large) {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,14 @@
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
|
||||
--sidebar-avatar-size: 150px;
|
||||
--sidebar-element-separation: 25px;
|
||||
|
||||
@media (max-width: $on-desktop-large) {
|
||||
--sidebar-avatar-size: 120px;
|
||||
--sidebar-element-separation: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: $on-phone) {
|
||||
width: 100%;
|
||||
padding: 30px 0;
|
||||
@ -23,19 +31,10 @@
|
||||
}
|
||||
|
||||
@media (min-width: $on-phone + 1) {
|
||||
width: 25%;
|
||||
margin-right: 1%;
|
||||
padding: var(--main-top-padding) 15px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop) {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop-large) {
|
||||
width: 15%;
|
||||
}
|
||||
}
|
||||
|
||||
.right-sidebar {
|
||||
@ -50,19 +49,15 @@
|
||||
}
|
||||
|
||||
@media (min-width: $on-tablet) {
|
||||
width: 25%;
|
||||
margin-left: 1%;
|
||||
padding-top: 50px;
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop + 1) {
|
||||
width: 25%;
|
||||
padding-top: var(--main-top-padding);
|
||||
}
|
||||
}
|
||||
|
||||
.site-info {
|
||||
z-index: 1;
|
||||
transition: box-shadow 0.5s ease;
|
||||
|
||||
@media (max-width: $on-phone) {
|
||||
padding: 15px 30px;
|
||||
}
|
||||
@ -70,14 +65,10 @@
|
||||
.site-avatar {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
margin-bottom: 25px;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
width: var(--sidebar-avatar-size);
|
||||
height: var(--sidebar-avatar-size);
|
||||
|
||||
@media (max-width: $on-desktop-large) {
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
}
|
||||
margin-bottom: var(--sidebar-element-separation);
|
||||
|
||||
.site-logo {
|
||||
width: 100%;
|
||||
@ -131,16 +122,15 @@
|
||||
|
||||
.sidebar {
|
||||
.widget {
|
||||
&:not(:last-of-type) {
|
||||
margin-bottom: var(--section-separation);
|
||||
&:after {
|
||||
content: "";
|
||||
width: 100px;
|
||||
height: 2px;
|
||||
background-color: var(--body-text-color);
|
||||
display: block;
|
||||
margin-top: var(--section-separation);
|
||||
}
|
||||
margin-bottom: var(--section-separation);
|
||||
|
||||
&:not(:last-of-type):after {
|
||||
content: "";
|
||||
width: 100px;
|
||||
height: 2px;
|
||||
background-color: var(--body-text-color);
|
||||
display: block;
|
||||
margin-top: var(--section-separation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,4 @@
|
||||
.widget {
|
||||
.widget-title {
|
||||
text-transform: uppercase;
|
||||
color: var(--body-text-color);
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.widget-icon {
|
||||
svg {
|
||||
width: 32px;
|
||||
@ -45,28 +36,26 @@
|
||||
|
||||
/* Archives widget */
|
||||
.widget.archives {
|
||||
.widget-archive--list {
|
||||
border-radius: var(--card-border-radius);
|
||||
box-shadow: var(--shadow-l1);
|
||||
background-color: var(--card-background);
|
||||
}
|
||||
|
||||
.archives-year {
|
||||
margin-bottom: 10px;
|
||||
&:not(:last-of-type) {
|
||||
border-bottom: 1.5px solid var(--card-separator-color);
|
||||
}
|
||||
|
||||
a {
|
||||
background-color: var(--card-background);
|
||||
padding: 15px 25px;
|
||||
border-radius: var(--card-border-radius);
|
||||
box-shadow: var(--shadow-l1);
|
||||
font-size: 1.4rem;
|
||||
padding: 18px 25px;
|
||||
display: flex;
|
||||
transition: box-shadow 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: var(--shadow-l2);
|
||||
}
|
||||
|
||||
@media (max-width: $on-desktop-large) {
|
||||
padding: 12px 20px;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
span.year {
|
||||
flex: 1;
|
||||
color: var(--card-text-color-main);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.count {
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
@import "breakpoints.scss";
|
||||
@import "variables.scss";
|
||||
@import "grid.scss";
|
||||
|
||||
@import "external/normalize.scss";
|
||||
|
||||
@ -22,6 +23,9 @@
|
||||
@import "partials/layout/article.scss";
|
||||
@import "partials/layout/taxonomy.scss";
|
||||
@import "partials/layout/404.scss";
|
||||
@import "partials/layout/search.scss";
|
||||
|
||||
@import "custom.scss";
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
@ -41,96 +45,16 @@ a {
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
.section-title {
|
||||
text-transform: uppercase;
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
font-size: 1.6rem;
|
||||
font-weight: bold;
|
||||
color: var(--body-text-color);
|
||||
|
||||
&.extended {
|
||||
@media (min-width: $on-phone) {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
@media (min-width: $on-tablet) {
|
||||
max-width: 972px;
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop) {
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop-large) {
|
||||
max-width: 1536px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main.main {
|
||||
min-width: 0;
|
||||
padding: 0 15px;
|
||||
max-width: 100%;
|
||||
flex-grow: 1;
|
||||
padding-top: var(--main-top-padding);
|
||||
}
|
||||
|
||||
.main-grid {
|
||||
@media (max-width: $on-phone) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
&.column {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&.on-phone--column {
|
||||
@media (max-width: $on-phone) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
&.align-items--flex-start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.do-not-shrink {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.do-not-overflow {
|
||||
min-width: 0;
|
||||
flex-shrink: 1;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.alert {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
bottom: 20px;
|
||||
z-index: 5;
|
||||
background: var(--card-background);
|
||||
max-width: 400px;
|
||||
padding: 15px 20px;
|
||||
border-radius: var(--card-border-radius);
|
||||
line-height: 1.75;
|
||||
color: var(--card-text-color-secondary);
|
||||
box-shadow: var(--shadow-l2);
|
||||
|
||||
@media (max-width: $on-phone) {
|
||||
max-width: 100vw;
|
||||
width: calc(100% - 30px);
|
||||
left: 15px;
|
||||
a {
|
||||
color: var(--body-text-color);
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,14 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff;
|
||||
*/
|
||||
:root {
|
||||
@media (min-width: $on-phone + 1) {
|
||||
--main-top-padding: 35px;
|
||||
}
|
||||
|
||||
@media (min-width: $on-desktop-large) {
|
||||
--main-top-padding: 50px;
|
||||
}
|
||||
|
||||
|
||||
--body-background: #f5f5fa;
|
||||
|
||||
--accent-color: #34495e;
|
||||
@ -54,15 +59,18 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff;
|
||||
|
||||
--card-border-radius: 10px;
|
||||
|
||||
--content-padding: 30px;
|
||||
--card-padding: 30px;
|
||||
@media (max-width: $on-desktop-large) {
|
||||
--content-padding: 25px;
|
||||
--card-padding: 25px;
|
||||
}
|
||||
@media (max-width: $on-tablet) {
|
||||
--content-padding: 20px;
|
||||
--card-padding: 20px;
|
||||
}
|
||||
|
||||
--small-card-padding: 25px;
|
||||
@media (max-width: $on-tablet) {
|
||||
--small-card-padding: 25px 20px;
|
||||
}
|
||||
|
||||
.theme-dark {
|
||||
--card-background: #424242;
|
||||
|
34
assets/ts/createElement.ts
Normal file
34
assets/ts/createElement.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* createElement
|
||||
* Edited from:
|
||||
* @link https://stackoverflow.com/a/42405694
|
||||
*/
|
||||
function createElement(tag, attrs, children) {
|
||||
var element = document.createElement(tag);
|
||||
|
||||
for (let name in attrs) {
|
||||
if (name && attrs.hasOwnProperty(name)) {
|
||||
let value = attrs[name];
|
||||
|
||||
if (name == "dangerouslySetInnerHTML") {
|
||||
element.innerHTML = value.__html;
|
||||
}
|
||||
else if (value === true) {
|
||||
element.setAttribute(name, name);
|
||||
} else if (value !== false && value != null) {
|
||||
element.setAttribute(name, value.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 2; i < arguments.length; i++) {
|
||||
let child = arguments[i];
|
||||
if (child) {
|
||||
element.appendChild(
|
||||
child.nodeType == null ?
|
||||
document.createTextNode(child.toString()) : child);
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
export default createElement;
|
@ -236,10 +236,10 @@ function wrap(gallery: HTMLElement[]) {
|
||||
*/
|
||||
function loadPhotoSwipe() {
|
||||
const tasks = [
|
||||
loadScript("https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js"),
|
||||
loadScript("https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js"),
|
||||
loadStyle("https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.css"),
|
||||
loadStyle("https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.min.css")
|
||||
loadScript("https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"),
|
||||
loadScript("https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"),
|
||||
loadStyle("https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css"),
|
||||
loadStyle("https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css")
|
||||
];
|
||||
|
||||
return Promise.all(tasks);
|
||||
|
@ -10,6 +10,7 @@ import { createGallery } from "./gallery"
|
||||
import { getColor } from './color';
|
||||
import menu from './menu';
|
||||
import darkmode from "./darkmode";
|
||||
import createElement from './createElement';
|
||||
|
||||
let Stack = {
|
||||
init: () => {
|
||||
@ -68,29 +69,6 @@ let Stack = {
|
||||
|
||||
observer.observe(articleTile)
|
||||
}
|
||||
},
|
||||
alert: (content, time = 5000, animationSpeed = 500) => {
|
||||
const alert = document.createElement('div');
|
||||
alert.innerHTML = content;
|
||||
alert.className = 'alert';
|
||||
alert.style.visibility = 'hidden';
|
||||
document.body.appendChild(alert);
|
||||
|
||||
alert.style.transform = `translateY(${alert.clientHeight + 50}px)`;
|
||||
alert.style.transition = `transform ${animationSpeed / 1000}s ease`;
|
||||
|
||||
setTimeout(() => {
|
||||
alert.style.removeProperty('visibility');
|
||||
alert.style.transform = `translateY(0)`;
|
||||
}, animationSpeed);
|
||||
|
||||
setTimeout(() => {
|
||||
alert.style.transform = `translateY(${alert.clientHeight + 50}px)`;
|
||||
}, animationSpeed + time);
|
||||
|
||||
setTimeout(() => {
|
||||
alert.remove();
|
||||
}, 2 * animationSpeed + time);
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,4 +78,12 @@ window.addEventListener('load', () => {
|
||||
}, 0);
|
||||
})
|
||||
|
||||
window.Stack = Stack;
|
||||
declare global {
|
||||
interface Window {
|
||||
createElement: any;
|
||||
Stack: any
|
||||
}
|
||||
}
|
||||
|
||||
window.Stack = Stack;
|
||||
window.createElement = createElement;
|
263
assets/ts/search.tsx
Normal file
263
assets/ts/search.tsx
Normal file
@ -0,0 +1,263 @@
|
||||
interface pageData {
|
||||
title: string,
|
||||
date: string,
|
||||
permalink: string,
|
||||
content: string,
|
||||
image?: string,
|
||||
preview: string,
|
||||
matchCount: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape HTML tags as HTML entities
|
||||
* Edited from:
|
||||
* @link https://stackoverflow.com/a/5499821
|
||||
*/
|
||||
const tagsToReplace = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'…': '…'
|
||||
};
|
||||
|
||||
function replaceTag(tag) {
|
||||
return tagsToReplace[tag] || tag;
|
||||
}
|
||||
|
||||
function replaceHTMLEnt(str) {
|
||||
return str.replace(/[&<>"]/g, replaceTag);
|
||||
}
|
||||
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
class Search {
|
||||
private data: pageData[];
|
||||
private form: HTMLFormElement;
|
||||
private input: HTMLInputElement;
|
||||
private list: HTMLDivElement;
|
||||
private resultTitle: HTMLHeadElement;
|
||||
private resultTitleTemplate: string;
|
||||
|
||||
constructor({ form, input, list, resultTitle, resultTitleTemplate }) {
|
||||
this.form = form;
|
||||
this.input = input;
|
||||
this.list = list;
|
||||
this.resultTitle = resultTitle;
|
||||
this.resultTitleTemplate = resultTitleTemplate;
|
||||
|
||||
this.handleQueryString();
|
||||
this.bindQueryStringChange();
|
||||
this.bindSearchForm();
|
||||
}
|
||||
|
||||
private async searchKeywords(keywords: string[]) {
|
||||
const rawData = await this.getData();
|
||||
let results: pageData[] = [];
|
||||
|
||||
/// Sort keywords by their length
|
||||
keywords.sort((a, b) => {
|
||||
return b.length - a.length
|
||||
});
|
||||
|
||||
for (const item of rawData) {
|
||||
let result = {
|
||||
...item,
|
||||
preview: '',
|
||||
matchCount: 0
|
||||
}
|
||||
|
||||
let matched = false;
|
||||
|
||||
for (const keyword of keywords) {
|
||||
if (keyword === '') continue;
|
||||
|
||||
const regex = new RegExp(escapeRegExp(replaceHTMLEnt(keyword)), 'gi');
|
||||
|
||||
const contentMatch = regex.exec(result.content);
|
||||
regex.lastIndex = 0; /// Reset regex
|
||||
|
||||
const titleMatch = regex.exec(result.title);
|
||||
regex.lastIndex = 0; /// Reset regex
|
||||
|
||||
if (titleMatch) {
|
||||
result.title = result.title.replace(regex, Search.marker);
|
||||
}
|
||||
|
||||
if (titleMatch || contentMatch) {
|
||||
matched = true;
|
||||
++result.matchCount;
|
||||
|
||||
let start = 0,
|
||||
end = 100;
|
||||
|
||||
if (contentMatch) {
|
||||
start = contentMatch.index - 20;
|
||||
end = contentMatch.index + 80
|
||||
|
||||
if (start < 0) start = 0;
|
||||
}
|
||||
|
||||
if (result.preview.indexOf(keyword) !== -1) {
|
||||
result.preview = result.preview.replace(regex, Search.marker);
|
||||
}
|
||||
else {
|
||||
if (start !== 0) result.preview += `[...] `;
|
||||
result.preview += `${result.content.slice(start, end).replace(regex, Search.marker)} `;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
result.preview += '[...]';
|
||||
results.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
/** Result with more matches appears first */
|
||||
return results.sort((a, b) => {
|
||||
return b.matchCount - a.matchCount;
|
||||
});
|
||||
}
|
||||
|
||||
public static marker(match) {
|
||||
return '<mark>' + match + '</mark>';
|
||||
}
|
||||
|
||||
private async doSearch(keywords: string[]) {
|
||||
const startTime = performance.now();
|
||||
|
||||
const results = await this.searchKeywords(keywords);
|
||||
this.clear();
|
||||
|
||||
for (const item of results) {
|
||||
this.list.append(Search.render(item));
|
||||
}
|
||||
|
||||
const endTime = performance.now();
|
||||
|
||||
this.resultTitle.innerText = this.generateResultTitle(results.length, ((endTime - startTime) / 1000).toPrecision(1));
|
||||
}
|
||||
|
||||
private generateResultTitle(resultLen, time) {
|
||||
return this.resultTitleTemplate.replace("#PAGES_COUNT", resultLen).replace("#TIME_SECONDS", time);
|
||||
}
|
||||
|
||||
public async getData() {
|
||||
if (!this.data) {
|
||||
/// Not fetched yet
|
||||
const jsonURL = this.form.dataset.json;
|
||||
this.data = await fetch(jsonURL).then(res => res.json());
|
||||
}
|
||||
|
||||
return this.data;
|
||||
}
|
||||
|
||||
private bindSearchForm() {
|
||||
let lastSearch = '';
|
||||
|
||||
const eventHandler = (e) => {
|
||||
e.preventDefault();
|
||||
const keywords = this.input.value;
|
||||
|
||||
Search.updateQueryString(keywords, true);
|
||||
|
||||
if (keywords === '') {
|
||||
return this.clear();
|
||||
}
|
||||
|
||||
if (lastSearch === keywords) return;
|
||||
lastSearch = keywords;
|
||||
|
||||
this.doSearch(keywords.split(' '));
|
||||
}
|
||||
|
||||
this.input.addEventListener('input', eventHandler);
|
||||
this.input.addEventListener('compositionend', eventHandler);
|
||||
}
|
||||
|
||||
private clear() {
|
||||
this.list.innerHTML = '';
|
||||
this.resultTitle.innerText = '';
|
||||
}
|
||||
|
||||
private bindQueryStringChange() {
|
||||
window.addEventListener('popstate', (e) => {
|
||||
this.handleQueryString()
|
||||
})
|
||||
}
|
||||
|
||||
private handleQueryString() {
|
||||
const pageURL = new URL(window.location.toString());
|
||||
const keywords = pageURL.searchParams.get('keyword');
|
||||
this.input.value = keywords;
|
||||
|
||||
if (keywords) {
|
||||
this.doSearch(keywords.split(' '));
|
||||
}
|
||||
else {
|
||||
this.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private static updateQueryString(keywords: string, replaceState = false) {
|
||||
const pageURL = new URL(window.location.toString());
|
||||
|
||||
if (keywords === '') {
|
||||
pageURL.searchParams.delete('keyword')
|
||||
}
|
||||
else {
|
||||
pageURL.searchParams.set('keyword', keywords);
|
||||
}
|
||||
|
||||
if (replaceState) {
|
||||
window.history.replaceState('', '', pageURL.toString());
|
||||
}
|
||||
else {
|
||||
window.history.pushState('', '', pageURL.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static render(item: pageData) {
|
||||
return <article>
|
||||
<a href={item.permalink}>
|
||||
<div class="article-details">
|
||||
<h2 class="article-title" dangerouslySetInnerHTML={{ __html: item.title }}></h2>
|
||||
<secion class="article-preview" dangerouslySetInnerHTML={{ __html: item.preview }}></secion>
|
||||
</div>
|
||||
{item.image &&
|
||||
<div class="article-image">
|
||||
<img src={item.image} loading="lazy" />
|
||||
</div>
|
||||
}
|
||||
</a>
|
||||
</article>;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
searchResultTitleTemplate: string;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
setTimeout(function () {
|
||||
const searchForm = document.querySelector('.search-form') as HTMLFormElement,
|
||||
searchInput = searchForm.querySelector('input') as HTMLInputElement,
|
||||
searchResultList = document.querySelector('.search-result--list') as HTMLDivElement,
|
||||
searchResultTitle = document.querySelector('.search-result--title') as HTMLHeadingElement;
|
||||
|
||||
new Search({
|
||||
form: searchForm,
|
||||
input: searchInput,
|
||||
list: searchResultList,
|
||||
resultTitle: searchResultTitle,
|
||||
resultTitleTemplate: window.searchResultTitleTemplate
|
||||
});
|
||||
}, 0);
|
||||
})
|
||||
|
||||
export default Search;
|
@ -1,92 +0,0 @@
|
||||
baseurl = "https://example.com"
|
||||
languageCode = "en-us"
|
||||
theme = "hugo-theme-stack"
|
||||
paginate = 5
|
||||
title = "Example Site"
|
||||
disqusShortname = "hugo-theme-stack" # Change it to your Disqus shortname before using
|
||||
DefaultContentLanguage = "en" # Theme i18n support
|
||||
|
||||
[permalinks]
|
||||
post = "/p/:slug/"
|
||||
page = "/:slug/"
|
||||
|
||||
[params]
|
||||
mainSections = ["post"]
|
||||
featuredImageField = "image"
|
||||
[params.dateFormat]
|
||||
published = "Jan 02, 2006"
|
||||
lastUpdated = "Jan 02, 2006 15:04 MST"
|
||||
[params.sidebar]
|
||||
emoji = "🍥"
|
||||
avatar = "img/avatar.png"
|
||||
subtitle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
||||
[params.article]
|
||||
[params.article.license]
|
||||
enabled = true
|
||||
default = "Licenced under CC BY-NC-SA 4.0"
|
||||
[params.comments]
|
||||
enabled = true
|
||||
# Only Disqus is available so far
|
||||
provider = "disqus"
|
||||
[params.widgets]
|
||||
enabled = ['archives', 'tag-cloud']
|
||||
[params.widgets.archives]
|
||||
limit = 5
|
||||
### Archives page relative URL
|
||||
path = "archives"
|
||||
[params.widgets.tagCloud]
|
||||
limit = 10
|
||||
[params.opengraph]
|
||||
[params.opengraph.twitter]
|
||||
site = ""
|
||||
card = "summary_large_image"
|
||||
[params.defaultImage]
|
||||
[params.defaultImage.article]
|
||||
enabled = false
|
||||
local = false
|
||||
src = ""
|
||||
[params.defaultImage.articleList]
|
||||
enabled = false
|
||||
local = true
|
||||
src = ""
|
||||
[params.defaultImage.opengraph]
|
||||
enabled = false
|
||||
local = false
|
||||
src = ""
|
||||
|
||||
[menu]
|
||||
[[menu.main]]
|
||||
identifier = "home"
|
||||
name = "Home"
|
||||
url = "/"
|
||||
weight = -100
|
||||
pre = "home"
|
||||
[[menu.main]]
|
||||
identifier = "about-cn"
|
||||
name = "About"
|
||||
url = "about"
|
||||
weight = -90
|
||||
pre = "user"
|
||||
[[menu.main]]
|
||||
identifier = "archives"
|
||||
name = "Archives"
|
||||
url = "archives"
|
||||
weight = -70
|
||||
pre = "archives"
|
||||
|
||||
[related]
|
||||
includeNewer = true
|
||||
threshold = 60
|
||||
toLower = false
|
||||
|
||||
[[related.indices]]
|
||||
name = "tags"
|
||||
weight = 100
|
||||
|
||||
[[related.indices]]
|
||||
name = "categories"
|
||||
weight = 200
|
||||
|
||||
[markup]
|
||||
[markup.highlight]
|
||||
noClasses = false
|
113
exampleSite/config.yaml
Normal file
113
exampleSite/config.yaml
Normal file
@ -0,0 +1,113 @@
|
||||
baseurl: https://example.com
|
||||
languageCode: en-us
|
||||
theme: hugo-theme-stack
|
||||
paginate: 5
|
||||
title: Example Site
|
||||
|
||||
# Change it to your Disqus shortname before using
|
||||
disqusShortname: hugo-theme-stack
|
||||
|
||||
# Theme i18n support
|
||||
# Available values: en, fr, id, ja, ko, pt-br, zh-cn
|
||||
DefaultContentLanguage: en
|
||||
|
||||
permalinks:
|
||||
post: /p/:slug/
|
||||
page: /:slug/
|
||||
|
||||
params:
|
||||
mainSections:
|
||||
- post
|
||||
featuredImageField: image
|
||||
rssFullContent: true
|
||||
|
||||
dateFormat:
|
||||
published: Jan 02, 2006
|
||||
lastUpdated: Jan 02, 2006 15:04 MST
|
||||
|
||||
sidebar:
|
||||
emoji: 🍥
|
||||
subtitle: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
avatar:
|
||||
local: true
|
||||
src: img/avatar.png
|
||||
|
||||
article:
|
||||
math: false
|
||||
license:
|
||||
enabled: true
|
||||
default: Licensed under CC BY-NC-SA 4.0
|
||||
|
||||
comments:
|
||||
enabled: true
|
||||
provider: disqus
|
||||
utterances:
|
||||
repo:
|
||||
issueTerm: pathname
|
||||
label:
|
||||
theme: preferred-color-scheme
|
||||
|
||||
widgets:
|
||||
enabled:
|
||||
- search
|
||||
- archives
|
||||
- tag-cloud
|
||||
|
||||
archives:
|
||||
limit: 5
|
||||
path: archives
|
||||
|
||||
tagCloud:
|
||||
limit: 10
|
||||
|
||||
opengraph:
|
||||
twitter:
|
||||
site:
|
||||
card: summary_large_image
|
||||
|
||||
defaultImage:
|
||||
opengraph:
|
||||
enabled: false
|
||||
local: false
|
||||
src:
|
||||
|
||||
menu:
|
||||
main:
|
||||
- identifier: home
|
||||
name: Home
|
||||
url: /
|
||||
weight: -100
|
||||
pre: home
|
||||
|
||||
- identifier: about
|
||||
name: About
|
||||
url: about
|
||||
weight: -90
|
||||
pre: user
|
||||
|
||||
- identifier: archives
|
||||
name: Archives
|
||||
url: archives
|
||||
weight: -70
|
||||
pre: archives
|
||||
|
||||
- identifier: search
|
||||
name: Search
|
||||
url: search
|
||||
weight: -60
|
||||
pre: search
|
||||
|
||||
related:
|
||||
includeNewer: true
|
||||
threshold: 60
|
||||
toLower: false
|
||||
indices:
|
||||
- name: tags
|
||||
weight: 100
|
||||
|
||||
- name: categories
|
||||
weight: 200
|
||||
|
||||
markup:
|
||||
highlight:
|
||||
noClasses: false
|
@ -5,6 +5,7 @@ date = "2019-02-28"
|
||||
aliases = ["about-us", "about-hugo", "contact"]
|
||||
author = "Hugo Authors"
|
||||
license = "CC BY-NC-ND"
|
||||
lastmod = "2020-10-09"
|
||||
+++
|
||||
|
||||
Written in Go, Hugo is an open source static site generator available under the [Apache Licence 2.0.](https://github.com/gohugoio/hugo/blob/master/LICENSE) Hugo supports TOML, YAML and JSON data file types, Markdown and HTML content files and uses shortcodes to add rich content. Other notable features are taxonomies, multilingual mode, image processing, custom output formats, HTML/CSS/JS minification and support for Sass SCSS workflows.
|
||||
|
8
exampleSite/content/page/search.md
Normal file
8
exampleSite/content/page/search.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
title: "Search"
|
||||
slug: "search"
|
||||
layout: "search"
|
||||
outputs:
|
||||
- html
|
||||
- json
|
||||
---
|
@ -1,11 +1,12 @@
|
||||
---
|
||||
title: 中文文章内容测试
|
||||
title: Chinese Test
|
||||
description: 这是一个副标题
|
||||
date: 2020-09-09
|
||||
slug: test-chinese
|
||||
image: helena-hertz-wWZzXlDpMog-unsplash.jpg
|
||||
categories:
|
||||
- Test
|
||||
- 测试
|
||||
---
|
||||
|
||||
## 正文测试
|
||||
|
@ -4,11 +4,13 @@ title = "Placeholder Text"
|
||||
date = "2019-03-09"
|
||||
description = "Lorem Ipsum Dolor Si Amet"
|
||||
categories = [
|
||||
"Test"
|
||||
"Test",
|
||||
"Test with whitespaces"
|
||||
]
|
||||
tags = [
|
||||
"markdown",
|
||||
"text",
|
||||
"tag with whitespaces"
|
||||
]
|
||||
image = "matt-le-SJSpo9hQf7s-unsplash.jpg"
|
||||
+++
|
||||
|
@ -13,14 +13,6 @@ Hugo ships with several [Built-in Shortcodes](https://gohugo.io/content-manageme
|
||||
<!--more-->
|
||||
---
|
||||
|
||||
## Instagram Simple Shortcode
|
||||
|
||||
{{< instagram_simple BGvuInzyFAe hidecaption >}}
|
||||
|
||||
<br>
|
||||
|
||||
---
|
||||
|
||||
## YouTube Privacy Enhanced Shortcode
|
||||
|
||||
{{< youtube ZJthWmvUzzc >}}
|
||||
|
26
i18n/en.toml
26
i18n/en.toml
@ -1,26 +0,0 @@
|
||||
[toggleMenu]
|
||||
other = "Toggle Menu"
|
||||
|
||||
[relatedContents]
|
||||
other = "Related contents"
|
||||
|
||||
[lastUpdatedOn]
|
||||
other ="Last updated on {{ .Count }}"
|
||||
|
||||
[widgetArchivesTitle]
|
||||
other = "Archives"
|
||||
|
||||
[widgetArchivesMore]
|
||||
other = "More"
|
||||
|
||||
[widgetTagCloudTitle]
|
||||
other = "Tags"
|
||||
|
||||
[notFoundTitle]
|
||||
other = "Not Found"
|
||||
|
||||
[notFoundSubtitle]
|
||||
other = "This page does not exist."
|
||||
|
||||
[darkModeToggle]
|
||||
other = "Dark Mode"
|
46
i18n/en.yaml
Normal file
46
i18n/en.yaml
Normal file
@ -0,0 +1,46 @@
|
||||
toggleMenu:
|
||||
other: Toggle Menu
|
||||
|
||||
darkMode:
|
||||
toggle:
|
||||
other: Dark Mode
|
||||
|
||||
archives:
|
||||
categories:
|
||||
other: Categories
|
||||
|
||||
article:
|
||||
relatedContents:
|
||||
other: Related contents
|
||||
lastUpdatedOn:
|
||||
other: Last updated on
|
||||
|
||||
notFound:
|
||||
title:
|
||||
other: Not Found
|
||||
subtitle:
|
||||
other: This page does not exist.
|
||||
|
||||
widget:
|
||||
archives:
|
||||
title:
|
||||
other: Archives
|
||||
more:
|
||||
other: More
|
||||
tagCloud:
|
||||
title:
|
||||
other: Tags
|
||||
|
||||
search:
|
||||
title:
|
||||
other: Search
|
||||
placeholder:
|
||||
other: Type something...
|
||||
resultTitle:
|
||||
other: "#PAGES_COUNT pages (#TIME_SECONDS seconds)"
|
||||
|
||||
footer:
|
||||
builtWith:
|
||||
other: Built with {{ .Generator }}
|
||||
designedBy:
|
||||
other: Theme {{ .Theme }} designed by {{ .DesignedBy }}
|
38
i18n/fr.yaml
Normal file
38
i18n/fr.yaml
Normal file
@ -0,0 +1,38 @@
|
||||
toggleMenu:
|
||||
other: Afficher le menu
|
||||
|
||||
article:
|
||||
relatedContents:
|
||||
other: Contenus liés
|
||||
lastUpdatedOn:
|
||||
other: Dernière mise à jour le
|
||||
|
||||
notFound:
|
||||
title:
|
||||
other: Page non trouvée
|
||||
subtitle:
|
||||
other: Cette page n'existe pas.
|
||||
|
||||
widget:
|
||||
archives:
|
||||
title:
|
||||
other: Archives
|
||||
more:
|
||||
other: Autres
|
||||
tagCloud:
|
||||
title:
|
||||
other: Mots clés
|
||||
|
||||
search:
|
||||
title:
|
||||
other: Rechercher
|
||||
placeholder:
|
||||
other: Cherchez un article, une publication, etc.
|
||||
resultTitle:
|
||||
other: "#PAGES_COUNT pages (#TIME_SECONDS secondes)"
|
||||
|
||||
footer:
|
||||
builtWith:
|
||||
other: Généré avec {{ .Generator }}
|
||||
designedBy:
|
||||
other: Thème {{ .Theme }} conçu par {{ .DesignedBy }}
|
38
i18n/id.yaml
Normal file
38
i18n/id.yaml
Normal file
@ -0,0 +1,38 @@
|
||||
toggleMenu:
|
||||
other: Tampilkan Menu
|
||||
|
||||
article:
|
||||
relatedContents:
|
||||
other: Konten terkait
|
||||
lastUpdatedOn:
|
||||
other: Terakhir diperbarui pada
|
||||
|
||||
notFound:
|
||||
title:
|
||||
other: Not Found
|
||||
subtitle:
|
||||
other: Halaman ini tidak ada.
|
||||
|
||||
widget:
|
||||
archives:
|
||||
title:
|
||||
other: Arsip
|
||||
more:
|
||||
other: Lebih
|
||||
tagCloud:
|
||||
title:
|
||||
other: Tag
|
||||
|
||||
search:
|
||||
title:
|
||||
other: Cari
|
||||
placeholder:
|
||||
other: Ketik sesuatu...
|
||||
resultTitle:
|
||||
other: "#PAGES_COUNT halaman (#TIME_SECONDS detik)"
|
||||
|
||||
footer:
|
||||
builtWith:
|
||||
other: Dibangun dengan {{ .Generator }}
|
||||
designedBy:
|
||||
other: Tema {{ .Theme }} dirancang oleh {{ .DesignedBy }}
|
24
i18n/ja.yaml
Normal file
24
i18n/ja.yaml
Normal file
@ -0,0 +1,24 @@
|
||||
toggleMenu:
|
||||
other: メニューを開く・閉じる
|
||||
|
||||
article:
|
||||
relatedContents:
|
||||
other: 関連するコンテンツ
|
||||
lastUpdatedOn:
|
||||
other: 最終更新
|
||||
|
||||
notFound:
|
||||
title:
|
||||
other: 404 Not Found
|
||||
subtitle:
|
||||
other: 指定されたページは存在しません。
|
||||
|
||||
widget:
|
||||
archives:
|
||||
title:
|
||||
other: アーカイブ
|
||||
more:
|
||||
other: さらに見る
|
||||
tagCloud:
|
||||
title:
|
||||
other: タグ
|
38
i18n/ko.yaml
Normal file
38
i18n/ko.yaml
Normal file
@ -0,0 +1,38 @@
|
||||
toggleMenu:
|
||||
other: 메뉴 여닫기
|
||||
|
||||
article:
|
||||
relatedContents:
|
||||
other: 관련 글
|
||||
lastUpdatedOn:
|
||||
other: "마지막 수정: "
|
||||
|
||||
notFound:
|
||||
title:
|
||||
other: 찾을 수 없음
|
||||
subtitle:
|
||||
other: 페이지를 찾을 수 없습니다.
|
||||
|
||||
widget:
|
||||
archives:
|
||||
title:
|
||||
other: 보관함
|
||||
more:
|
||||
other: 더보기
|
||||
tagCloud:
|
||||
title:
|
||||
other: 태그
|
||||
|
||||
search:
|
||||
title:
|
||||
other: 검색
|
||||
placeholder:
|
||||
other: 검색어를 입력하세요...
|
||||
resultTitle:
|
||||
other: "#PAGES_COUNT 페이지 (#TIME_SECONDS 초)"
|
||||
|
||||
footer:
|
||||
builtWith:
|
||||
other: "{{ .Generator }}로 만듦"
|
||||
designedBy:
|
||||
other: "{{ .DesignedBy }}의 {{ .Theme }} 테마 사용 중"
|
42
i18n/pt-BR.yaml
Normal file
42
i18n/pt-BR.yaml
Normal file
@ -0,0 +1,42 @@
|
||||
toggleMenu:
|
||||
other: Alternar Menu
|
||||
|
||||
archives:
|
||||
categories:
|
||||
other: Categorias
|
||||
|
||||
article:
|
||||
relatedContents:
|
||||
other: Conteúdos Relacionados
|
||||
lastUpdatedOn:
|
||||
other: Última atualização em
|
||||
|
||||
notFound:
|
||||
title:
|
||||
other: Não Encontrado
|
||||
subtitle:
|
||||
other: Esta página não existe.
|
||||
|
||||
widget:
|
||||
archives:
|
||||
title:
|
||||
other: Arquivos
|
||||
more:
|
||||
other: Mais
|
||||
tagCloud:
|
||||
title:
|
||||
other: Tags
|
||||
|
||||
search:
|
||||
title:
|
||||
other: Busca
|
||||
placeholder:
|
||||
other: Digite algo...
|
||||
resultTitle:
|
||||
other: "#PAGES_COUNT páginas (#TIME_SECONDS segundos)"
|
||||
|
||||
footer:
|
||||
builtWith:
|
||||
other: Criado com {{ .Generator }}
|
||||
designedBy:
|
||||
other: Tema {{ .Theme }} desenvolvido por {{ .DesignedBy }}
|
@ -1,26 +0,0 @@
|
||||
[toggleMenu]
|
||||
other = "切换菜单"
|
||||
|
||||
[relatedContents]
|
||||
other = "相关文章"
|
||||
|
||||
[lastUpdatedOn]
|
||||
other ="最后更新于 {{ .Count }}"
|
||||
|
||||
[widgetArchivesTitle]
|
||||
other = "归档"
|
||||
|
||||
[widgetArchivesMore]
|
||||
other = "更多"
|
||||
|
||||
[widgetTagCloudTitle]
|
||||
other = "标签云"
|
||||
|
||||
[notFoundTitle]
|
||||
other = "404 错误"
|
||||
|
||||
[notFoundSubtitle]
|
||||
other = "页面不存在"
|
||||
|
||||
[darkModeToggle]
|
||||
other = "暗色模式"
|
40
i18n/zh-CN.yaml
Normal file
40
i18n/zh-CN.yaml
Normal file
@ -0,0 +1,40 @@
|
||||
toggleMenu:
|
||||
other: 切换菜单
|
||||
|
||||
darkMode:
|
||||
toggle:
|
||||
other: 暗色模式
|
||||
|
||||
archives:
|
||||
categories:
|
||||
other: 分类
|
||||
|
||||
article:
|
||||
relatedContents:
|
||||
other: 相关文章
|
||||
lastUpdatedOn:
|
||||
other: 最后更新于
|
||||
|
||||
notFound:
|
||||
title:
|
||||
other: 404 错误
|
||||
subtitle:
|
||||
other: 页面不存在
|
||||
|
||||
widget:
|
||||
archives:
|
||||
title:
|
||||
other: 归档
|
||||
more:
|
||||
other: 更多
|
||||
tagCloud:
|
||||
title:
|
||||
other: 标签云
|
||||
|
||||
search:
|
||||
title:
|
||||
other: 搜索
|
||||
placeholder:
|
||||
other: 输入关键词...
|
||||
resultTitle:
|
||||
other: "#PAGES_COUNT 个结果 (用时 #TIME_SECONDS 秒)"
|
@ -1,7 +1,7 @@
|
||||
{{ define "main" }}
|
||||
<div class="not-found-card">
|
||||
<h1 class="article-title">{{ T "notFoundTitle" }}</h1>
|
||||
<h2 class="article-subtitle">{{ T "notFoundSubtitle" }}</h2>
|
||||
<h1 class="article-title">{{ T "notFound.title" }}</h1>
|
||||
<h2 class="article-subtitle">{{ T "notFound.subtitle" }}</h2>
|
||||
</div>
|
||||
{{ partialCached "footer/footer" . }}
|
||||
{{ end }}
|
@ -2,14 +2,12 @@
|
||||
{{ define "main" }}
|
||||
{{ $categories := ($.Site.GetPage "taxonomyTerm" "categories").Pages }}
|
||||
{{ if $categories }}
|
||||
<div class="widget">
|
||||
<h1 class="widget-title">Categories</h1>
|
||||
<div class="category-list">
|
||||
<div class="article-list--tile">
|
||||
{{ range $categories }}
|
||||
{{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "taxonomy") }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<h2 class="section-title">{{ T "archives.categories" }}</h2>
|
||||
<div class="category-list">
|
||||
<div class="article-list--tile">
|
||||
{{ range $categories }}
|
||||
{{ partial "article-list/tile" (dict "context" . "size" "250x150" "Type" "taxonomy") }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
@ -21,7 +19,7 @@
|
||||
{{ range $filtered.GroupByDate "2006" }}
|
||||
{{ $id := lower (replace .Key " " "-") }}
|
||||
<div class="archives-group" id="{{ $id }}">
|
||||
<h3 class="archives-date"><a href="{{ $.Permalink }}#{{ $id }}">{{ .Key }}</a></h3>
|
||||
<h2 class="archives-date section-title"><a href="{{ $.RelPermalink }}#{{ $id }}">{{ .Key }}</a></h2>
|
||||
<div class="article-list--compact">
|
||||
{{ range .Pages }}
|
||||
{{ partial "article-list/compact" . }}
|
||||
@ -31,4 +29,4 @@
|
||||
{{ end }}
|
||||
|
||||
{{ partialCached "footer/footer" . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
@ -1,6 +1,9 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ .Site.LanguageCode }}">
|
||||
{{- partial "head/head.html" . -}}
|
||||
<head>
|
||||
{{- partial "head/head.html" . -}}
|
||||
{{- block "head" . -}}{{ end }}
|
||||
</head>
|
||||
<body class="{{ block `body-class` . }}{{ end }}">
|
||||
<script>
|
||||
(function() {
|
||||
@ -15,7 +18,7 @@
|
||||
})();
|
||||
</script>
|
||||
|
||||
<div class="container extended flex on-phone--column align-items--flex-start {{ block `container-class` . }}{{end}}">
|
||||
<div class="container flex on-phone--column align-items--flex-start {{ if .Site.Params.widgets.enabled }}extended{{ else }}compact{{ end }} {{ block `container-class` . }}{{end}}">
|
||||
{{ partial "sidebar/left.html" . }}
|
||||
<main class="main full-width">
|
||||
{{- block "main" . }}{{- end }}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{{ define "main" }}
|
||||
<h3 class="taxonomy-type">{{ .Type | singularize | humanize }}</h3>
|
||||
<h3 class="taxonomy-type section-title">{{ .Type | singularize | humanize }}</h3>
|
||||
<div class="taxonomy-card">
|
||||
<div class="taxonomy-details">
|
||||
<h3 class="taxonomy-count">{{ len .Pages }} post{{ if gt (len .Pages) 1 }}s{{ end }}</h3>
|
||||
|
@ -15,5 +15,5 @@
|
||||
{{ end }}
|
||||
|
||||
{{ define "right-sidebar" }}
|
||||
{{ partialCached "sidebar/right.html" . }}
|
||||
{{ partial "sidebar/right.html" . }}
|
||||
{{ end }}
|
31
layouts/page/search.html
Normal file
31
layouts/page/search.html
Normal file
@ -0,0 +1,31 @@
|
||||
{{ define "body-class" }}template-search{{ end }}
|
||||
{{ define "head" }}
|
||||
{{- with .OutputFormats.Get "json" -}}
|
||||
<link rel="preload" href="{{ .Permalink }}" as="fetch" crossorigin="anonymous">
|
||||
{{- end -}}
|
||||
{{ end }}
|
||||
{{ define "main" }}
|
||||
<form action="{{ .Permalink }}" class="search-form"{{ with .OutputFormats.Get "json" -}} data-json="{{ .Permalink }}"{{- end }}>
|
||||
<p>
|
||||
<label>{{ T "search.title" }}</label>
|
||||
<input name="keyword" placeholder="{{ T `search.placeholder` }}" />
|
||||
</p>
|
||||
|
||||
<button title="Search">
|
||||
{{ partial "helper/icon" "search" }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<h3 class="search-result--title section-title"></h3>
|
||||
<div class="search-result--list article-list--compact"></div>
|
||||
|
||||
<script>
|
||||
window.searchResultTitleTemplate = "{{ T `search.resultTitle` }}"
|
||||
</script>
|
||||
|
||||
{{- $opts := dict "minify" hugo.IsProduction "JSXFactory" "createElement" -}}
|
||||
{{- $searchScript := resources.Get "ts/search.tsx" | js.Build $opts -}}
|
||||
<script type="text/javascript" src="{{ $searchScript.RelPermalink }}" defer></script>
|
||||
|
||||
{{ partialCached "footer/footer" . }}
|
||||
{{ end }}
|
20
layouts/page/search.json
Normal file
20
layouts/page/search.json
Normal file
@ -0,0 +1,20 @@
|
||||
{{- $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections -}}
|
||||
{{- $notHidden := where .Site.RegularPages "Params.hidden" "!=" true -}}
|
||||
{{- $filtered := ($pages | intersect $notHidden) -}}
|
||||
|
||||
{{- $result := slice -}}
|
||||
|
||||
{{- range $filtered -}}
|
||||
{{- $data := dict "title" .Title "date" .Date "permalink" .Permalink "content" (.Plain) -}}
|
||||
|
||||
{{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}}
|
||||
{{- if and $image.exists $image.resource -}}
|
||||
{{- $thumbnail := $image.resource.Fill "120x120" -}}
|
||||
{{- $image := dict "image" (absURL $thumbnail.Permalink) -}}
|
||||
{{- $data = merge $data $image -}}
|
||||
{{ end }}
|
||||
|
||||
{{- $result = $result | append $data -}}
|
||||
{{- end -}}
|
||||
|
||||
{{ jsonify $result }}
|
@ -1,27 +1,27 @@
|
||||
<article>
|
||||
<div class="article-details">
|
||||
<h2 class="article-title">
|
||||
<a href="{{ .Permalink }}">
|
||||
<a href="{{ .RelPermalink }}">
|
||||
<div class="article-details">
|
||||
<h2 class="article-title">
|
||||
{{- .Title -}}
|
||||
</a>
|
||||
</h2>
|
||||
<footer class="article-time">
|
||||
<time datetime='{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}'>
|
||||
{{- .Date.Format (or .Site.Params.dateFormat.published "Jan 02, 2006") -}}
|
||||
</time>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}}
|
||||
{{ if $image.exists }}
|
||||
<div class="article-image">
|
||||
{{ if $image.resource }}
|
||||
{{- $thumbnail := $image.resource.Fill "120x120" -}}
|
||||
<img src="{{ $thumbnail.RelPermalink }}" width="{{ $thumbnail.Width }}"
|
||||
height="{{ $thumbnail.Height }}" loading="lazy">
|
||||
{{ else }}
|
||||
<img src="{{ $image.permalink }}" loading="lazy" alt="Featured image of post {{ .Title }}" />
|
||||
{{ end }}
|
||||
</h2>
|
||||
<footer class="article-time">
|
||||
<time datetime='{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}'>
|
||||
{{- .Date.Format (or .Site.Params.dateFormat.published "Jan 02, 2006") -}}
|
||||
</time>
|
||||
</footer>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{- $image := partialCached "helper/image" (dict "Context" . "Type" "articleList") .RelPermalink "articleList" -}}
|
||||
{{ if $image.exists }}
|
||||
<div class="article-image">
|
||||
{{ if $image.resource }}
|
||||
{{- $thumbnail := $image.resource.Fill "120x120" -}}
|
||||
<img src="{{ $thumbnail.RelPermalink }}" width="{{ $thumbnail.Width }}"
|
||||
height="{{ $thumbnail.Height }}" loading="lazy">
|
||||
{{ else }}
|
||||
<img src="{{ $image.permalink }}" loading="lazy" alt="Featured image of post {{ .Title }}" />
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</a>
|
||||
</article>
|
@ -2,7 +2,7 @@
|
||||
<article class="{{ if $image.exists }}has-image{{ end }}">
|
||||
{{ if $image.exists }}
|
||||
<div class="article-image">
|
||||
<a href="{{ .Permalink }}">
|
||||
<a href="{{ .RelPermalink }}">
|
||||
{{ if $image.resource }}
|
||||
{{- $thumbnail := $image.resource.Fill "800x250" -}}
|
||||
{{- $thumbnailRetina := $image.resource.Fill "1600x500" -}}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{{ $image := partialCached "helper/image" (dict "Context" .context "Type" .Type) .context.RelPermalink .Type }}
|
||||
<article class="{{ if $image.exists }}has-image{{ end }}">
|
||||
<a href="{{ .context.Permalink }}">
|
||||
<a href="{{ .context.RelPermalink }}">
|
||||
|
||||
{{ if $image.exists }}
|
||||
<div class="article-image">
|
||||
|
@ -4,4 +4,8 @@
|
||||
{{ partial "article/components/content" . }}
|
||||
|
||||
{{ partial "article/components/footer" . }}
|
||||
|
||||
{{ if or .Params.math .Site.Params.article.math }}
|
||||
{{ partialCached "article/components/math.html" . }}
|
||||
{{ end }}
|
||||
</article>
|
@ -1,25 +1,28 @@
|
||||
{{ $image := partialCached "helper/image" (dict "Context" . "Type" "article") .RelPermalink "article" }}
|
||||
{{- $context := . -}}
|
||||
{{- $categories := .Params.categories -}}
|
||||
<div class="article-details">
|
||||
{{ if $categories }}
|
||||
{{ if .Params.categories }}
|
||||
<header class="article-category">
|
||||
{{ range $category := $categories }}
|
||||
{{ $term := $.Site.GetPage (printf "/categories/%s" $category) }}
|
||||
{{ range (.GetTerms "categories") }}
|
||||
{{ if and $image.exists $image.resource }}
|
||||
{{- $imageRaw := $image.resource | resources.Fingerprint "md5" -}}
|
||||
{{- $20x := $imageRaw.Fill "20x20 smart" -}}
|
||||
<a href="{{ $term.Permalink }}" class="color-tag"
|
||||
data-image="{{ $20x.RelPermalink }}" data-key="{{ $context.Slug }}" data-hash="{{ $imageRaw.Data.Integrity }}">{{ $term.Title | humanize }}</a>
|
||||
<a href="{{ .RelPermalink }}"
|
||||
class="color-tag"
|
||||
data-image="{{ $20x.RelPermalink }}"
|
||||
data-key="{{ $context.Slug }}"
|
||||
data-hash="{{ $imageRaw.Data.Integrity }}">
|
||||
{{ .LinkTitle }}
|
||||
</a>
|
||||
{{ else }}
|
||||
<a href="{{ $term.Permalink }}">{{ $term.Title | humanize }}</a>
|
||||
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</header>
|
||||
{{ end }}
|
||||
|
||||
<h2 class="article-title">
|
||||
<a href="{{ .Permalink }}">
|
||||
<a href="{{ .RelPermalink }}">
|
||||
{{- .Title -}}
|
||||
</a>
|
||||
</h2>
|
||||
@ -32,7 +35,7 @@
|
||||
|
||||
{{- if not .Date.IsZero -}}
|
||||
<footer class="article-time">
|
||||
{{ (resources.Get "icons/clock.svg").Content | safeHTML }}
|
||||
{{ partial "helper/icon" "clock" }}
|
||||
<time class="article-time--published">
|
||||
{{- .Date.Format (or .Site.Params.dateFormat.published "Jan 02, 2006") -}}
|
||||
</time>
|
||||
|
@ -3,16 +3,16 @@
|
||||
|
||||
{{ if and (.Site.Params.article.license.enabled) (not (eq .Params.license false)) }}
|
||||
<section class="article-copyright">
|
||||
{{ (resources.Get "icons/copyright.svg").Content | safeHTML }}
|
||||
{{ partial "helper/icon" "copyright" }}
|
||||
<span>{{ default .Site.Params.article.license.default .Params.license }}</span>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
||||
{{- if ne .Lastmod .Date -}}
|
||||
<section class="article-time">
|
||||
{{ (resources.Get "icons/clock.svg").Content | safeHTML }}
|
||||
{{ partial "helper/icon" "clock" }}
|
||||
<span class="article-time--modified">
|
||||
{{ T "lastUpdatedOn" (.Lastmod.Format ( or .Site.Params.dateFormat.lastUpdated "Jan 02, 2006 15:04 MST" )) }}
|
||||
{{ T "article.lastUpdatedOn" }} {{ .Lastmod.Format ( or .Site.Params.dateFormat.lastUpdated "Jan 02, 2006 15:04 MST" ) }}
|
||||
</span>
|
||||
</section>
|
||||
{{- end -}}
|
||||
|
8
layouts/partials/article/components/math.html
Normal file
8
layouts/partials/article/components/math.html
Normal file
@ -0,0 +1,8 @@
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css"
|
||||
integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js"
|
||||
integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4"
|
||||
crossorigin="anonymous"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js"
|
||||
integrity="sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa" crossorigin="anonymous"
|
||||
onload="renderMathInElement(document.querySelector(`.article-content`));"></script>
|
@ -1,7 +1,7 @@
|
||||
<aside class="widget related-contents--wrapper">
|
||||
{{ $related := .Site.RegularPages.Related . | first 5 }}
|
||||
<aside class="related-contents--wrapper">
|
||||
{{ $related := (where (.Site.RegularPages.Related .) "Params.hidden" "!=" true) | first 5 }}
|
||||
{{ with $related }}
|
||||
<h1 class="widget-title">{{ T "relatedContents" }}</h1>
|
||||
<h2 class="section-title">{{ T "article.relatedContents" }}</h2>
|
||||
<div class="related-contents">
|
||||
<div class="flex article-list--tile">
|
||||
{{ range . }}
|
||||
@ -10,4 +10,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</aside>
|
||||
</aside>
|
||||
|
@ -1,10 +1,7 @@
|
||||
{{- $tags := .Params.Tags -}}
|
||||
{{ if $tags }}
|
||||
{{ if .Params.Tags }}
|
||||
<section class="article-tags">
|
||||
{{ range $tag := $tags }}
|
||||
{{ with $.Site.GetPage (printf "/tags/%s" $tag) }}
|
||||
<a href="{{ .Permalink }}">{{ .Title | humanize }}</a>
|
||||
{{ end }}
|
||||
{{ range (.GetTerms "tags") }}
|
||||
<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{ end }}
|
@ -7,6 +7,6 @@
|
||||
background-color: var(--card-background);
|
||||
border-radius: var(--card-border-radius);
|
||||
box-shadow: var(--shadow-l1);
|
||||
padding: var(--content-padding);
|
||||
padding: var(--card-padding);
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
16
layouts/partials/comments/provider/utterances.html
Normal file
16
layouts/partials/comments/provider/utterances.html
Normal file
@ -0,0 +1,16 @@
|
||||
<script src="https://utteranc.es/client.js"
|
||||
repo="{{ .Site.Params.comments.utterances.repo }}"
|
||||
issue-term="{{ .Site.Params.comments.utterances.issueTerm }}"
|
||||
theme="{{ .Site.Params.comments.utterances.theme }}"
|
||||
{{ with .Site.Params.comments.utterances.label }}
|
||||
label="{{ . }}"
|
||||
{{ end }}
|
||||
crossorigin="anonymous"
|
||||
async>
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.utterances {
|
||||
max-width: unset;
|
||||
}
|
||||
</style>
|
@ -1,4 +1,4 @@
|
||||
{{- $light := resources.Get "css/highlight/light.css" | minify -}}
|
||||
{{- $dark := resources.Get "css/highlight/dark.css" | minify -}}
|
||||
<link rel="stylesheet" href="{{ $light.Permalink }}" media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet" href="{{ $dark.Permalink }}" media="(prefers-color-scheme: dark)">
|
||||
<link rel="stylesheet" href="{{ $light.RelPermalink }}" media="(prefers-color-scheme: light)">
|
||||
<link rel="stylesheet" href="{{ $dark.RelPermalink }}" media="(prefers-color-scheme: dark)">
|
@ -1,8 +1,12 @@
|
||||
{{- $ThemeVersion := "1.1.0" -}}
|
||||
<footer class="site-footer">
|
||||
<section class="copyright">© {{ now.Format "2006" }} {{ .Site.Title }}</section>
|
||||
<section class="powerby">
|
||||
Built with <a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a> <br />
|
||||
Theme <b><a href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener">Stack</a></b> designed by
|
||||
<a href="https://jimmycai.com" target="_blank" rel="noopener">Jimmy</a>
|
||||
{{- $Generator := `<a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a>` -}}
|
||||
{{- $Theme := printf `<b><a href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener" data-version="%s">Stack</a></b>` $ThemeVersion -}}
|
||||
{{- $DesignedBy := `<a href="https://jimmycai.com" target="_blank" rel="noopener">Jimmy</a>` -}}
|
||||
|
||||
{{ T "footer.builtWith" (dict "Generator" $Generator) | safeHTML }} <br />
|
||||
{{ T "footer.designedBy" (dict "Theme" $Theme "DesignedBy" $DesignedBy) | safeHTML }}
|
||||
</section>
|
||||
</footer>
|
@ -1,22 +1,20 @@
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
|
||||
{{- $description := partialCached "data/description" . .RelPermalink -}}
|
||||
<meta name='description' content='{{ $description }}'>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1'>
|
||||
|
||||
{{- $title := partialCached "data/title" . .RelPermalink -}}
|
||||
<title>{{ $title }}</title>
|
||||
|
||||
<link rel='canonical' href='{{ .Permalink }}'>
|
||||
|
||||
{{- partial "head/style.html" . -}}
|
||||
{{- partial "head/script.html" . -}}
|
||||
{{- partial "head/opengraph/include.html" . -}}
|
||||
{{- $description := partialCached "data/description" . .RelPermalink -}}
|
||||
<meta name='description' content='{{ $description }}'>
|
||||
|
||||
{{- range .AlternativeOutputFormats -}}
|
||||
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
|
||||
{{- end -}}
|
||||
|
||||
{{- partial "head/custom.html" . -}}
|
||||
</head>
|
||||
{{- $title := partialCached "data/title" . .RelPermalink -}}
|
||||
<title>{{ $title }}</title>
|
||||
|
||||
<link rel='canonical' href='{{ .Permalink }}'>
|
||||
|
||||
{{- partial "head/style.html" . -}}
|
||||
{{- partial "head/script.html" . -}}
|
||||
{{- partial "head/opengraph/include.html" . -}}
|
||||
|
||||
{{- range .AlternativeOutputFormats -}}
|
||||
<link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}">
|
||||
{{- end -}}
|
||||
|
||||
{{- partial "head/custom.html" . -}}
|
@ -1,3 +1,3 @@
|
||||
{{ $sass := resources.Get "scss/style.scss" }}
|
||||
{{ $style := $sass | resources.ToCSS | minify }}
|
||||
<link rel="stylesheet" href="{{ $style.Permalink }}">
|
||||
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
|
6
layouts/partials/helper/icon.html
Normal file
6
layouts/partials/helper/icon.html
Normal file
@ -0,0 +1,6 @@
|
||||
{{- $iconFile := resources.GetMatch (printf "icons/%s.svg" .) -}}
|
||||
{{- if $iconFile -}}
|
||||
{{- $iconFile.Content | safeHTML -}}
|
||||
{{- else -}}
|
||||
{{- errorf "Error: icon '%s.svg' is not found under 'assets/icons' folder" . -}}
|
||||
{{- end -}}
|
@ -8,17 +8,23 @@
|
||||
<header class="site-info">
|
||||
{{ with .Site.Params.sidebar.avatar }}
|
||||
<figure class="site-avatar">
|
||||
{{ $avatar := resources.Get (.) }}
|
||||
|
||||
{{ if $avatar }}
|
||||
{{ $avatarResized := $avatar.Resize "300x300" }}
|
||||
<img src="{{ $avatarResized.RelPermalink }}" width="{{ $avatarResized.Width }}"
|
||||
height="{{ $avatarResized.Height }}" class="site-logo" loading="lazy" alt="Avatar">
|
||||
{{ if not .local }}
|
||||
<img src="{{ .src }}" width="300" height="300" class="site-logo" loading="lazy" alt="Avatar">
|
||||
{{ else }}
|
||||
{{ errorf "Failed loading avatar from %q" . }}
|
||||
{{ $avatar := resources.Get (.src) }}
|
||||
|
||||
{{ if $avatar }}
|
||||
{{ $avatarResized := $avatar.Resize "300x" }}
|
||||
<img src="{{ $avatarResized.RelPermalink }}" width="{{ $avatarResized.Width }}"
|
||||
height="{{ $avatarResized.Height }}" class="site-logo" loading="lazy" alt="Avatar">
|
||||
{{ else }}
|
||||
{{ errorf "Failed loading avatar from %q" . }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
<span class="emoji">{{ $.Site.Params.sidebar.emoji }}</span>
|
||||
{{ with $.Site.Params.sidebar.emoji }}
|
||||
<span class="emoji">{{ . }}</span>
|
||||
{{ end }}
|
||||
</figure>
|
||||
{{ end }}
|
||||
<h1 class="site-name"><a href="{{ .Site.BaseURL }}">{{ .Site.Title }}</a></h1>
|
||||
@ -31,9 +37,9 @@
|
||||
{{ $active := or (eq $currentPage.Title .Name) (or ($currentPage.HasMenuCurrent "main" .) ($currentPage.IsMenuCurrent "main" .)) }}
|
||||
|
||||
<li {{ if $active }} class='current' {{ end }}>
|
||||
<a href='{{ .URL | absLangURL }}'>
|
||||
<a href='{{ .URL | relURL }}'>
|
||||
{{ if .Pre }}
|
||||
{{ (resources.Get (delimit (slice "icons/" .Pre ".svg") "")).Content | safeHTML }}
|
||||
{{ partial "helper/icon" .Pre }}
|
||||
{{ end }}
|
||||
<span>{{- .Name -}}</span>
|
||||
</a>
|
||||
@ -43,7 +49,7 @@
|
||||
<li id="dark-mode-toggle">
|
||||
{{ (resources.Get "icons/toggle-left.svg").Content | safeHTML }}
|
||||
{{ (resources.Get "icons/toggle-right.svg").Content | safeHTML }}
|
||||
<span>{{ T "darkModeToggle" }}</span>
|
||||
<span>{{ T "darkMode.toggle" }}</span>
|
||||
</li>
|
||||
</ol>
|
||||
</aside>
|
||||
</aside>
|
||||
|
@ -1,29 +1,27 @@
|
||||
<section class="widget archives">
|
||||
<div class="widget-icon">
|
||||
{{ (resources.Get "icons/infinity.svg").Content | safeHTML }}
|
||||
{{ partial "helper/icon" "infinity" }}
|
||||
</div>
|
||||
<h1 class="widget-title">{{ T "widgetArchivesTitle" }}</h1>
|
||||
<h2 class="widget-title section-title">{{ T "widget.archives.title" }}</h2>
|
||||
|
||||
{{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
|
||||
{{ $notHidden := where .Site.RegularPages "Params.hidden" "!=" true }}
|
||||
{{ $filtered := ($pages | intersect $notHidden) }}
|
||||
{{ $archives := $filtered.GroupByDate "2006" }}
|
||||
|
||||
{{ range first .Site.Params.widgets.archives.limit ($archives) }}
|
||||
{{ $id := lower (replace .Key " " "-") }}
|
||||
<div class="archives-year">
|
||||
<a href="{{ $.Site.Params.widgets.archives.path | relLangURL }}#{{ $id }}">
|
||||
<span class="year">{{ .Key }}</span>
|
||||
<span class="count">{{ len .Pages }}</span>
|
||||
</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if gt (len $archives) .Site.Params.widgets.archives.limit }}
|
||||
<div class="archives-year">
|
||||
<a href="{{ $.Site.Params.widgets.archives.path | relLangURL }}">
|
||||
<span class="year">{{ T "widgetArchivesMore" }}</span>
|
||||
</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<div class="widget-archive--list">
|
||||
{{ range $index, $item := first (add .Site.Params.widgets.archives.limit 1) ($archives) }}
|
||||
{{- $id := lower (replace $item.Key " " "-") -}}
|
||||
<div class="archives-year">
|
||||
<a href="{{ $.Site.Params.widgets.archives.path | relLangURL }}#{{ $id }}">
|
||||
{{ if eq $index $.Site.Params.widgets.archives.limit }}
|
||||
<span class="year">{{ T "widget.archives.more" }}</span>
|
||||
{{ else }}
|
||||
<span class="year">{{ .Key }}</span>
|
||||
<span class="count">{{ len $item.Pages }}</span>
|
||||
{{ end }}
|
||||
</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
10
layouts/partials/widget/search.html
Normal file
10
layouts/partials/widget/search.html
Normal file
@ -0,0 +1,10 @@
|
||||
<form action="/search" class="search-form widget" {{ with .OutputFormats.Get "json" -}}data-json="{{ .Permalink }}" {{- end }}>
|
||||
<p>
|
||||
<label>{{ T "search.title" }}</label>
|
||||
<input name="keyword" required placeholder="{{ T `search.placeholder` }}" />
|
||||
|
||||
<button title="Search">
|
||||
{{ partial "helper/icon" "search" }}
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
@ -1,16 +1,13 @@
|
||||
{{ $tags := .Site.Taxonomies.tags.ByCount }}
|
||||
|
||||
<section class="widget tagCloud">
|
||||
<div class="widget-icon">
|
||||
{{ (resources.Get "icons/tag.svg").Content | safeHTML }}
|
||||
{{ partial "helper/icon" "tag" }}
|
||||
</div>
|
||||
<h1 class="widget-title">{{ T "widgetTagCloudTitle" }}</h1>
|
||||
<h2 class="widget-title section-title">{{ T "widget.tagCloud.title" }}</h2>
|
||||
|
||||
<div class="tagCloud-tags">
|
||||
{{ range first .Site.Params.widgets.tagCloud.limit $tags }}
|
||||
{{ $term := $.Site.GetPage (printf "/tags/%s" .Term) }}
|
||||
<a href="{{ $term.Permalink }}" class="font_size_{{ .Count }}">
|
||||
{{ $term.Title | humanize }}
|
||||
{{ range first .Site.Params.widgets.tagCloud.limit .Site.Taxonomies.tags.ByCount }}
|
||||
<a href="{{ .Page.RelPermalink }}" class="font_size_{{ .Count }}">
|
||||
{{ .Page.Title }}
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
42
layouts/rss.xml
Normal file
42
layouts/rss.xml
Normal file
@ -0,0 +1,42 @@
|
||||
{{- $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections -}}
|
||||
{{- $notHidden := where .Site.RegularPages "Params.hidden" "!=" true -}}
|
||||
{{- $filtered := ($pages | intersect $notHidden) -}}
|
||||
{{- $limit := .Site.Config.Services.RSS.Limit -}}
|
||||
{{- if ge $limit 1 -}}
|
||||
{{- $filtered = $filtered | 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">
|
||||
<channel>
|
||||
<title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}</description>
|
||||
<generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
|
||||
<language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
|
||||
<managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
|
||||
<webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
|
||||
<copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
|
||||
<lastBuildDate>{{ .Date.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 $filtered }}
|
||||
{{- $content := safeHTML (.Summary | html) -}}
|
||||
{{- if .Site.Params.rssFullContent -}}
|
||||
{{- $content = safeHTML (.Content | html) -}}
|
||||
{{- end -}}
|
||||
<item>
|
||||
<title>{{ .Title }}</title>
|
||||
<link>{{ .Permalink }}</link>
|
||||
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
|
||||
{{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
|
||||
<guid>{{ .Permalink }}</guid>
|
||||
<description>
|
||||
{{- $image := partial "helper/image" (dict "Context" . "Type" "rss") -}}
|
||||
{{- if $image.exists -}}
|
||||
{{ "<" | html }}img src="{{ $image.permalink | absURL }}" alt="Featured image of post {{ .Title }}" {{ "/>" | html}}
|
||||
{{- end -}}{{ $content }}</description>
|
||||
</item>
|
||||
{{ end }}
|
||||
</channel>
|
||||
</rss>
|
@ -2,7 +2,7 @@
|
||||
publish = "exampleSite/public"
|
||||
|
||||
[build.environment]
|
||||
HUGO_VERSION = "0.74.3"
|
||||
HUGO_VERSION = "0.79.0"
|
||||
HUGO_THEME = "repo"
|
||||
|
||||
[context.production]
|
||||
|
File diff suppressed because one or more lines are too long
@ -5,7 +5,7 @@ name = "Stack"
|
||||
license = "GPL-3.0-only"
|
||||
licenselink = "https://github.com/CaiJimmy/hugo-theme-stack/blob/master/LICENSE"
|
||||
description = "Card-style Hugo theme designed for bloggers"
|
||||
homepage = "https://blog.jimmycai.com/p/hugo-theme-stack"
|
||||
homepage = "https://theme-stack.jimmycai.com"
|
||||
tags = [
|
||||
"blog",
|
||||
"responsive",
|
||||
@ -24,4 +24,4 @@ min_version = "0.74.0"
|
||||
|
||||
[author]
|
||||
name = "Jimmy Cai"
|
||||
homepage = "https://jimmycai.com"
|
||||
homepage = "https://jimmycai.com"
|
||||
|
Loading…
Reference in New Issue
Block a user