Compare commits

..
77 Commits
Author SHA1 Message Date
Jimmy CaiandGitHub 9f36a956ca release: 3.8.0 2022-02-06 19:36:10 +00:00
Jimmy CaiandGitHub d75dbe2b6e fix: copy code button does not work when line number is enabled (#487)
* fix: copy code button does not work when line number is enabled

* fix pre style

* Add gist shortcode to exampleSite
2022-02-06 20:32:37 +01:00
Jimmy CaiandGitHub 88beecd101 fix: hyperlinked image (#485)
* fix: hyperlinked image

closes https://github.com/CaiJimmy/hugo-theme-stack/issues/410

* feat: add support to inline images

* Remove unused code

* Remove data-alt-html
2022-02-06 19:58:10 +01:00
Jimmy CaiandGitHub 67d5156507 fix: disqus dark mode (#478)
* fix: disqus dark mode

* remove color-scheme

add custom chrome scrollbar style (removed in https://github.com/CaiJimmy/hugo-theme-stack/pull/428)
2022-01-30 10:57:16 +01:00
Jimmy CaiandGitHub 6474b9dfd8 fix(comments): fix cactus comments
closes https://github.com/CaiJimmy/hugo-theme-stack/issues/470
2022-01-23 12:59:21 +00:00
MarcelandGitHub 7dc5def217 feat(comments): add https://cactus.chat support (#298)
* feat: Add https://cactus.chat as comments provider

* Add cactus comments config fields to exampleSite

* Add cactus css and js to external.yaml and move custom cactus css to html

* Remove unneeded cactus comments css

* Load external dependencies for cactus comments in the comments provider

* Use safeJS instead of safeHTML
2022-01-23 13:10:00 +01:00
ZoroarkandGitHub 2b40a32d47 feat(article): Scrollspy for the table of contents (#425)
* Add first try at scrollspy (broken right now)

* Scrollspy actually works now

* Fix VS Code errors by setting JS version

* Recompute offsets when window size changes

* Improve list compatibility for toc active selection

Support up to 6 levels of indentation, properly support <ol>

* Remove debug string

* Add more docs in smoothAnchors

* Use a map to match ids to navigation elements
2022-01-22 10:35:08 +01:00
Jimmy CaiandGitHub 9e08854681 release: 3.7.0 2022-01-20 11:12:16 +00:00
zhixuanandGitHub 0af9d23e49 feat(article): add scroll for table (#428)
* feat: table can't scroll & delete scrollbar style for Chromium

* Undo some line breaks

* Add a table with overflow to exampleSite
2022-01-20 12:09:25 +01:00
Jimmy CaiandGitHub 3b98d3ba05 feat(sidebar): link avatar to homepage (#465)
closes https://github.com/CaiJimmy/hugo-theme-stack/issues/399
2022-01-20 11:38:16 +01:00
Andreas DeiningerandGitHub fe661c8c38 feat: turn stack theme into a hugo module (#460)
* Turn stack theme into a hugo module
2022-01-20 11:16:28 +01:00
bfd1eb8400 feat: add custom.ts (#461)
* feat: add custom.ts

* Load custom.ts only if it exists

This change avoids loading an empty .js file

Co-authored-by: Jimmy Cai <github@jimmycai.com>
2022-01-19 16:35:15 +01:00
tanmxandGitHub eebaea81e8 feat(comment): update twikoo version to 1.4.15 (#464) 2022-01-19 15:22:51 +01:00
zhixuanandGitHub ca260db07e fix(shortcode): conflict with gist shortcode (#455) 2022-01-19 01:12:29 +01:00
Jimmy CaiandGitHub 4764a92df3 refactor(search): avoid issue with one character keyword (#447)
* refactor(search): avoid issue with one character keyword

closes https://github.com/CaiJimmy/hugo-theme-stack/issues/184

* Remove keyword sorts

* fix typo: secion -> section

* fix(search): avoid matching html entity

* Use | operator to concatenate keywords

Idea from https://github.com/CaiJimmy/hugo-theme-stack/pull/436

* Add missing `matchCount`

* Limit preview length

* Don't add ellipsis to title

* add comment to `processMatches`

* Initialize DOMParser only once

* Remove marker function

* Deal with blank search

* Use const keyword for constant arrays
2022-01-18 23:19:30 +01:00
Jimmy CaiandGitHub 86cbc1b682 fix(README): demo site link
closes #449
2022-01-03 14:15:05 +01:00
Jimmy CaiandGitHub d165621568 release: 3.6.0 2021-12-29 00:32:08 +01:00
Nathan HarkenriderandGitHub dde6a10cab feat: implement cache busting for CSS (#444) 2021-12-28 23:28:33 +01:00
Jimmy CaiandGitHub a669b60cdd chore(exampleSite): make default pages use page bundle feature
To avoid confusions
2021-12-28 10:33:48 +00:00
Jimmy CaiandGitHub 455e23f22b feat: page links (#446) 2021-12-28 11:28:20 +01:00
Jimmy CaiandGitHub 4e2c8e74be fix: add missing diff syntax highlight (#445)
closes: https://github.com/CaiJimmy/hugo-theme-stack/issues/434
2021-12-28 10:48:22 +01:00
HAHWULandGitHub 359e4b34c1 Update i18n(ko) (#418)
Add dark mode, list-section, list-subsction, article-back, article-tableOfContents, article-readingTime
2021-12-04 21:16:22 +01:00
Paul-Henri ZimmerlinandGitHub 195b8d8076 fix(i18n/fr): add missing translations for reading time (#416) 2021-12-04 21:10:42 +01:00
zhixuanandGitHub 497643b363 feat: add alt message for archive & related contents images (#411) 2021-12-04 21:05:53 +01:00
Jimmy CaiandGitHub 72a5e956ee release: 3.5.0 2021-10-31 10:17:45 +01:00
25581cc446 fix(comments/cusdis): use the correct script for the self-hosted version (#403)
* Modify the Self-hosting js source path

* refactor(comments/cusdis): avoid multiple if statement

Co-authored-by: Jimmy Cai <github@jimmycai.com>
2021-10-31 10:15:57 +01:00
volodymyrmarkivandGitHub a7d316365c feat(i18n): add Ukrainian translation (#404) 2021-10-30 21:22:08 +02:00
TonyPepeBearandGitHub ea74aecadb feat(i18n): add zh-TW (#402) 2021-10-30 21:18:02 +02:00
zhixuanandGitHub c43f9d1ea8 fix(menu/social): Delete relLangURL (#406) 2021-10-29 17:20:36 +02:00
Jimmy CaiandGitHub 44fc94f008 release: 3.4.0 2021-10-23 10:00:42 +00:00
Jimmy CaiandGitHub 661e59b85d feat: social menu (#401) 2021-10-23 11:58:55 +02:00
Jimmy CaiandGitHub 7c59ac7713 refactor(menu): use .Params.icon to configure menu item icon (#400) 2021-10-23 09:18:44 +02:00
Jimmy CaiandGitHub a822411a03 chore: add Github Codespace config 2021-10-23 06:51:56 +00:00
Christos ManiosandGitHub ca9dcc870d feat(i18n): add Greek translation (#378) 2021-10-22 16:12:44 +02:00
Ar-ruk KachenandGitHub 913a4e8898 feat(i18n): Thai language (#396) 2021-10-17 12:34:19 +02:00
Daniel PessoaandGitHub 30467ae65c feat(i18n): add missing pt-BR translations (#384) 2021-10-16 11:10:25 +02:00
MikDal002andGitHub d04b3a8771 fix: appropriate back button and menu links for multi-language site (#386) 2021-10-16 10:56:55 +02:00
Jimmy CaiandGitHub b3088be62d feat: add default parameters to config.yaml (#394)
This will avoid those ugly errors caused by forgetting to copy exampleSite/config.yaml to the site folder
2021-10-16 10:14:06 +02:00
Jimmy CaiandGitHub 9859ea3f8b feat: add theme config.yaml (#393)
Add Hugo version requirement
2021-10-16 09:53:44 +02:00
WingLimandGitHub d8c9468c68 feat(comments): add Cusdis support (#372)
* feat: add cusdis support

* docs: add cusdis example config
2021-10-01 16:38:37 +02:00
zhixuanandGitHub 57bfea8338 fix(shortcodes): mixed content error with bilibili and tencent video (#365) 2021-09-24 20:32:53 +02:00
QIN2DIMandGitHub 7845f5dfe7 feat(config): add hasCJKLanguage parameter (#360) 2021-09-24 20:22:58 +02:00
CookiekiraandGitHub 66bd8a2997 feat(comments): add Gitalk support (#351) 2021-09-18 10:03:08 +02:00
Christopher John JacksonandGitHub 00c8616931 fix(article/comments): accept boolean true in .Params.comments (#352) 2021-09-17 21:29:19 +02:00
Jimmy CaiandGitHub 5693c4bf7a doc: add markup.goldmark.renderer.unsafe option in config.yaml 2021-09-03 19:05:10 +02:00
Jimmy CaiandGitHub 5bf8bdcde2 chore: change demo site link 2021-08-31 11:08:36 +02:00
Matthias ThymandGitHub 9b75823f68 refactor(i18n): Suggest improvements English translation (#329)
No need to shorten minutes
Remove period from subtitle on 404 page
2021-08-30 15:52:29 +02:00
zhixuanandGitHub 9c7e73646c feat(article): add positional parameter for video shortcode (#331) 2021-08-26 18:50:03 +02:00
Matthias ThymandGitHub 080c86ec79 feat(i18n): add German and Spanish translations for new features and refactor (#328)
* feat(i18n): add German translations for new features and refactor

add translation for feature `back`
add translation for feature `tableOfContents`
add translation for feature `readingTime`
fix translation for feature `resultTitle`
add newlines according to i18n en config

* feat(i18n): add Spanish translations for new features and refactor

add translation for feature `back`
add translation for feature `tableOfContents`
add translation for feature `readingTime`
add newlines according to i18n en config
2021-08-26 18:23:55 +02:00
Jimmy CaiandGitHub e24f5672c3 release: 3.2.0 2021-08-25 12:25:11 +02:00
MikDal002andGitHub 2013c50abe feat(i18n): add PL translation for reading time (#325) 2021-08-25 12:23:50 +02:00
Jimmy CaiandGitHub 626265bcfd refactor(article): better support for svg and external images (#326) 2021-08-25 12:20:15 +02:00
Franziskus KieferandGitHub fe94466ec4 fix(config): doc link (#323) 2021-08-24 12:16:27 +02:00
9f734a0647 feat(comments): DisqusJS integration (#307)
* add comment provider: DisqusJS

* Simplify `if` condition, and format code

* Load disqusjs.scss only when it's enabled

* Use `let` instead of `var`

Co-authored-by: sspirits <admin@lv5.moe>
Co-authored-by: Jimmy Cai <github@jimmycai.com>
2021-08-15 19:19:51 +02:00
Jimmy CaiandGitHub 90b6baccc1 release: 3.1.0 2021-08-15 12:05:12 +02:00
c4cd4bf9a1 feat(comments): giscus integration (#304)
Co-authored-by: Jimmy Cai <github@jimmycai.com>
2021-08-15 12:03:59 +02:00
zhixuanandGitHub bcbba1eed0 fix(article): change .article-time classname to .article-lastmod (#306) 2021-08-15 11:12:56 +02:00
SOT-TECHandGitHub f07d5dc515 feat(i18n): add readingTime russian translation (#297) 2021-08-10 10:28:43 +02:00
Jimmy CaiandGitHub 1055adf498 release: 3.0.0 2021-08-08 16:24:02 +00:00
Jimmy CaiandGitHub 24915a912f feat(article): copy button for highlight block (#295)
This button only shows on highlighted code blocks, because it uses the wrapper div.highlight
2021-08-08 18:15:27 +02:00
Jimmy CaiandGitHub 4a0cbac234 feat(menu): support open an entry in new tab (#294)
* feat(menu): support open an entry in new tab

closes https://github.com/CaiJimmy/hugo-theme-stack/issues/230

* Revert change in markup.tableOfContents.ordered

* Upgrade Netlify Hugo version

* doc: require Hugo Extended >= 0.87.0
2021-08-08 17:39:33 +02:00
Jimmy CaiandGitHub a052245f28 refactor!: Drop support for non-extended version of Hugo (#261)
closes https://github.com/CaiJimmy/hugo-theme-stack/issues/255
2021-08-08 17:14:36 +02:00
Jimmy CaiandGitHub 3b9e248bfd feat(article): add scrollbar to TOC (#293)
closes https://github.com/CaiJimmy/hugo-theme-stack/issues/236
2021-08-08 17:03:48 +02:00
Jimmy CaiandGitHub 5539a42b30 fix(article): unordered TOC style (#292)
closes https://github.com/CaiJimmy/hugo-theme-stack/issues/283
2021-08-08 16:47:58 +02:00
zhixuanandGitHub 61c021dae2 fix(comments): improve Twikoo style (#289) 2021-08-07 17:29:01 +02:00
zhixuanandGitHub 2fd3bde9a4 fix(comment/twikoo): submit button color (#288) 2021-08-05 11:20:03 +02:00
7b51bea912 feat(comment): add Twikoo support (#286)
* Create twikoo.html

* Upgrade to Twikoo 1.4.3 and add `lang` param

* Add twikoo section in config.yaml

Co-authored-by: Jimmy Cai <github@jimmycai.com>
2021-08-04 20:49:21 +02:00
zhixuanandGitHub 5f1a5ab83f feat(i18n): add translation for .readingTime in Chinese & Japanese (#285) 2021-08-04 20:39:01 +02:00
giacomocarrozzoandGitHub 910d93b4ce feat(i18n): Italian translation (#281) 2021-07-29 15:59:15 +02:00
zhixuanandGitHub 99c4c89f0a feat(article): add video shortcode (#280) 2021-07-27 10:42:06 +02:00
Farrel FranqoisandGitHub 8d0c65c374 feat(i18n): Add Indonesian translation for readingTime (#279) 2021-07-27 10:16:54 +02:00
zhixuanandGitHub d86b857635 chore: update KaTeX to 0.13.13 (#275) 2021-07-26 20:59:24 +02:00
44e3d20bad feat(article): use markdownify for licence in article (#273)
* Use markdownify for licence in article

So we can use links, e.g. to credits for main photo.

* refactor: move .article-copyright style to partials/layout/article

Co-authored-by: Jimmy Cai <github@jimmycai.com>
2021-07-25 19:50:52 +02:00
dcfc7b5589 feat(article): reading time (#204)
* add reading time feature

* Revert change in jsconfig.json

* feat: add article.readingTime param, and improve style

* Revert change in jsconfig.json x2

* Remove reading time in compact layout

It doesn't look right to me for now

* feat: add i18n support to reading time string

* Hide footer.article-time when there's not content

Co-authored-by: Jimmy Cai <github@jimmycai.com>
2021-07-23 18:37:30 +02:00
a25e6463bd feat(sidebar): add option to disable avatar in left sidebar (#268)
* Allow to disable logo image in left sidebar

* Enable sidebar avatar by default for backward compatibility

Co-authored-by: Jimmy Cai <github@jimmycai.com>
2021-07-23 10:56:52 +02:00
Farrel FranqoisandGitHub 8cb11d721f feat(i18n): Improve Indonesian translation (#265) 2021-07-19 12:21:49 +02:00
SOT-TECHandGitHub 99418f1056 feat(i18n): add russian translation for back and TOC (#262) 2021-07-11 11:23:52 +02:00
75 changed files with 2288 additions and 262 deletions
+31
View File
@@ -0,0 +1,31 @@
# Update the NODE_VERSION arg in docker-compose.yml to pick a Node version: 10, 12, 14
ARG NODE_VERSION=14
FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${NODE_VERSION}
# VARIANT can be either 'hugo' for the standard version or 'hugo_extended' for the extended version.
ARG VARIANT=hugo
# VERSION can be either 'latest' or a specific version number
ARG VERSION=latest
# Download Hugo
RUN apt-get update && apt-get install -y ca-certificates openssl git curl && \
rm -rf /var/lib/apt/lists/* && \
case ${VERSION} in \
latest) \
export VERSION=$(curl -s https://api.github.com/repos/gohugoio/hugo/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4)}') ;;\
esac && \
echo ${VERSION} && \
wget -O ${VERSION}.tar.gz https://github.com/gohugoio/hugo/releases/download/v${VERSION}/${VARIANT}_${VERSION}_Linux-64bit.tar.gz && \
tar xf ${VERSION}.tar.gz && \
mv hugo /usr/bin/hugo
# Hugo dev server port
EXPOSE 1313
# [Optional] Uncomment this section to install additional OS packages you may want.
#
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
# [Optional] Uncomment if you want to install more global node packages
# RUN sudo -u node npm install -g <your-package-list-here>
+45
View File
@@ -0,0 +1,45 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.202.3/containers/hugo
{
"name": "Hugo (Community)",
"build": {
"dockerfile": "Dockerfile",
"args": {
// Update VARIANT to pick hugo variant.
// Example variants: hugo, hugo_extended
// Rebuild the container if it already exists to update.
"VARIANT": "hugo_extended",
// Update VERSION to pick a specific hugo version.
// Example versions: latest, 0.73.0, 0,71.1
// Rebuild the container if it already exists to update.
"VERSION": "latest",
// Update NODE_VERSION to pick the Node.js version: 12, 14
"NODE_VERSION": "14",
}
},
// Set *default* container specific settings.json values on container create.
"settings": {
"html.format.templating": true,
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"bungcip.better-toml",
"davidanson.vscode-markdownlint"
],
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [
1313
],
// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "uname -a",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node",
"features": {
"golang": "latest"
}
}
+4
View File
@@ -0,0 +1,4 @@
public
resources
assets/jsconfig.json
.hugo_build.lock
+7 -4
View File
@@ -5,7 +5,7 @@
## Demo
[Example Site](https://theme-stack.jimmycai.com/)
[Example Site](https://demo.stack.jimmycai.com/)
[![Netlify Status](https://api.netlify.com/api/v1/badges/a2d2807a-a905-4bcb-97da-8da8d847da3d/deploy-status)](https://app.netlify.com/sites/hugo-theme-stack/deploys)
@@ -31,11 +31,14 @@ Stack is a simple card-style Hugo theme designed for bloggers, some of its featu
## Requirements
It's necessary to use **Hugo Extended ≥ 0.78.0**.
It's necessary to use **Hugo Extended ≥ 0.87.0**.
## Installation
Clone / Download this repository to `theme` folder, and edit your site config following `exampleSite/config.yaml`.
* Route 1: Clone / Download this repository to `theme` folder
* Route 2: Turn your site into a hugo module and add this theme as a module dependency
Edit your site config following `exampleSite/config.yaml`.
*Note: Remove `config.toml` if there is one in the site folder.*
@@ -77,4 +80,4 @@ Some references that I took while building this theme:
| Project | Licence|
| ------- | ------|
| [artchen/hexo-theme-element](https://github.com/artchen/hexo-theme-element) | [MIT](https://github.com/artchen/hexo-theme-element/blob/master/LICENSE) |
| [MunifTanjim/minimo](https://github.com/MunifTanjim/minimo) | [MIT](https://github.com/MunifTanjim/minimo/blob/master/LICENSE) |
| [MunifTanjim/minimo](https://github.com/MunifTanjim/minimo) | [MIT](https://github.com/MunifTanjim/minimo/blob/master/LICENSE) |
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-github" 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" fill="none"/>
<path d="M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5" />
</svg>

After

Width:  |  Height:  |  Size: 603 B

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brand-twitter" 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" fill="none"/>
<path d="M22 4.01c-1 .49 -1.98 .689 -3 .99c-1.121 -1.265 -2.783 -1.335 -4.38 -.737s-2.643 2.06 -2.62 3.737v1c-3.245 .083 -6.135 -1.395 -8 -4c0 0 -4.182 7.433 4 11c-1.872 1.247 -3.739 2.088 -6 2c3.308 1.803 6.913 2.423 10.034 1.517c3.58 -1.04 6.522 -3.723 7.651 -7.742a13.84 13.84 0 0 0 .497 -3.753c-.002 -.249 1.51 -2.772 1.818 -4.013z" />
</svg>

After

Width:  |  Height:  |  Size: 638 B

+9
View File
@@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-calendar-time" width="56" height="56" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z"/>
<path d="M11.795 21h-6.795a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v4" />
<circle cx="18" cy="18" r="4" />
<path d="M15 3v4" />
<path d="M7 3v4" />
<path d="M3 11h16" />
<path d="M18 16.496v1.504l1 1" />
</svg>

After

Width:  |  Height:  |  Size: 508 B

+2
View File
@@ -6,5 +6,7 @@
"*"
]
},
"lib": ["es2020", "dom"],
"jsx": "preserve"
}
}
+7
View File
@@ -95,7 +95,9 @@
display: flex;
align-items: center;
color: var(--card-text-color-tertiary);
gap: 15px;
margin-top: 10px;
flex-wrap: wrap;
svg {
vertical-align: middle;
@@ -108,6 +110,11 @@
time {
font-size: 1.4rem;
}
& > div {
display: inline-flex;
align-items: center;
}
}
.article-category,
-1
View File
@@ -1,7 +1,6 @@
html {
font-size: 62.5%;
overflow-y: scroll;
scroll-behavior: smooth;
}
* {
+394
View File
@@ -0,0 +1,394 @@
.disqus-container {
background-color: var(--card-background);
border-radius: var(--card-border-radius);
box-shadow: var(--shadow-l1);
padding: var(--card-padding);
}
#dsqjs * {
margin: 0;
padding: 0
}
#dsqjs a {
text-decoration: none;
color: #076dd0
}
#dsqjs .dsqjs-hide {
display: none!important
}
#dsqjs .dsqjs-disabled {
cursor: not-allowed;
opacity: .5
}
#dsqjs #dsqjs-msg {
text-align: center;
margin-top: 4px;
margin-bottom: 4px;
font-size: 14px
}
#dsqjs #dsqjs-msg .dsqjs-msg-btn {
cursor: pointer
}
#dsqjs .dsqjs-bullet {
line-height: 1.4;
margin: 0 2px
}
#dsqjs .dsqjs-bullet:after {
color: #c2c6cc;
content: "·";
font-weight: 700
}
#dsqjs .dsqjs-clearfix:after,#dsqjs .dsqjs-clearfix:before {
display: table;
content: "";
line-height: 0;
clear: both
}
#dsqjs .dsqjs-nav {
position: relative;
margin: 0 0 20px;
border-bottom: 2px solid #e7e9ee
}
#dsqjs ol,#dsqjs ul {
list-style: none;
list-style-type: none
}
#dsqjs .dsqjs-no-comment {
text-align: center;
font-size: 16px;
line-height: 1.5;
word-wrap: break-word;
overflow: hidden;
color: #2a2e2e;
margin-bottom: 6px
}
#dsqjs .dsqjs-nav-tab {
float: left;
text-transform: capitalize;
font-size: 15px;
padding: 12px 8px;
color: #656c7a;
display: block;
margin: 0 15px 0 0;
font-weight: 700;
line-height: 1;
position: relative;
transition: all .2s ease-in-out
}
#dsqjs .dsqjs-nav-tab:last-child {
margin: 0
}
#dsqjs .dsqjs-tab-active {
color: #2a2e2e
}
#dsqjs .dsqjs-tab-active>span:after {
content: " ";
display: block;
height: 2px;
background-color: #076dd0!important;
position: absolute;
bottom: -5px;
left: 0;
right: 0
}
#dsqjs .dsqjs-post-list .dsqjs-post-item {
position: relative;
margin-bottom: 16px
}
#dsqjs .dsqjs-post-list .dsqjs-post-avatar {
float: left;
margin-right: 10px;
position: relative;
background: #dbdfe4;
padding: 0;
display: block;
border-radius: 4px
}
#dsqjs .dsqjs-post-list .dsqjs-post-avatar img {
width: 44px;
height: 44px;
display: block;
border-radius: 4px
}
#dsqjs .dsqjs-post-list .dsqjs-post-header {
line-height: 1;
font-size: 14px;
margin-bottom: 3px
}
#dsqjs .dsqjs-post-list .dsqjs-post-header .dsqjs-post-author {
color: #656c7a;
font-weight: 700
}
#dsqjs .dsqjs-post-list .dsqjs-post-header .dsqjs-admin-badge {
color: #fff;
background: #687a86;
padding: 1px 3px;
margin-left: 4px;
font-size: 12px;
line-height: 1;
font-weight: 700;
border-radius: 3px;
display: inline-block;
position: relative;
top: -1px;
left: 1px
}
#dsqjs .dsqjs-post-list .dsqjs-post-header .dsqjs-meta {
display: inline-block;
font-size: 12px;
color: #656c7a
}
#dsqjs .dsqjs-post-body {
font-size: 15px;
line-height: 1.5;
word-wrap: break-word;
overflow: hidden;
color: #2a2e2e
}
#dsqjs .dsqjs-post-body code {
padding: .2em .4em;
margin: 0;
font-size: 85%;
background: #f5f5f5;
color: inherit;
border-radius: 3px
}
#dsqjs .dsqjs-post-body pre {
padding: .5em;
overflow: auto;
font-size: 85%;
line-height: 1.45;
border-radius: 3px;
background: #f5f5f5;
margin: .5em 0
}
#dsqjs .dsqjs-post-body blockquote {
padding: 0 .8em;
margin: .5em 0;
color: #6a737d;
border-left: .25em solid #dfe2e5
}
#dsqjs .dsqjs-post-body p:last-child {
margin: 0
}
#dsqjs .dsqjs-post-list.dsqjs-children>li {
margin-left: 30px
}
#dsqjs .dsqjs-post-list.dsqjs-children .dsqjs-post-avatar img {
width: 38px;
height: 38px
}
#dsqjs .dsqjs-load-more {
font-size: 14px;
font-weight: 400;
display: block;
text-align: center;
padding: 11px 14px;
margin: 0 0 24px;
background: #687a86;
color: #fff;
cursor: pointer
}
#dsqjs .dsqjs-load-more:hover {
opacity: .8
}
#dsqjs footer {
text-align: right;
line-height: 1.5;
padding-top: 10px;
padding-right: 10px;
border-top: 2px solid #e7e9ee;
margin-top: 12px;
font-weight: 700;
font-size: 16px;
color: #555
}
#dsqjs .dsqjs-disqus-logo {
background-image: url(https://c.disquscdn.com/next/embed/assets/img/sprite.654110a9206fd22f08cca0798e34a65e.png);
background-repeat: no-repeat;
display: inline-block;
background-size: 86px 40.5px;
height: 16.5px;
width: 86px;
}
#dsqjs .dsqjs-order {
display: flex;
float: right;
align-items: center;
margin-top: 10px;
margin-bottom: 12px
}
#dsqjs .dsqjs-order-radio {
display: none
}
#dsqjs .dsqjs-order-radio:checked+.dsqjs-order-label {
color: #fff;
background-color: #888
}
#dsqjs .dsqjs-order-label {
display: block;
height: 20px;
line-height: 20px;
margin-right: 10px;
font-size: 12px;
border-radius: 2px;
padding: 0 5px;
background-color: #dcdcdc;
cursor: pointer
}
#dsqjs p.dsqjs-has-more {
margin-bottom: 24px;
margin-left: 48px;
font-size: 13px;
line-height: 15px
}
#dsqjs p.dsqjs-has-more a.dsqjs-has-more-btn {
color: #656c7a;
text-decoration: underline;
cursor: pointer
}
@media (min-width: 768px) {
#dsqjs .dsqjs-post-list.dsqjs-children>li {
margin-left:48px
}
#dsqjs .dsqjs-post-list .dsqjs-post-avatar {
margin-right: 12px
}
#dsqjs .dsqjs-post-list .dsqjs-post-item {
margin-bottom: 20px
}
}
@media (min-width: 1024px) {
#dsqjs .dsqjs-post-list.dsqjs-children>li {
margin-left:60px
}
}
:root[data-scheme="light"] {
#dsqjs .dsqjs-disqus-logo {
background-position: 0 -7px;
}
}
:root[data-scheme="dark"] {
#dsqjs {
--t-s: rgba(255,255,255,0.9);
--alt: #3e4b5e;
--link-hover: #47a2e0;
--hover-bg: #3e4b5e;
--tag: #3e4b5e;
--border: #435266;
--pre: #3c495b;
--c-bg: #2f3947;
--code: #c3c7cb;
--kbd: #4e5f77;
--hl: #abb2bf;
--hlc: #808895;
--hlk: #c678dd;
--hln: #e06c75;
--hll: #56b6c2;
--hls: #98c379;
--hlt: #e6c07b;
--hlv: #d19a66;
--bg: #181c27;
--main: #252d38;
--t: rgba(255,255,255,0.86);
--t-l: rgba(255,255,255,0.66);
--logo: #fff;
--link: #38a3fd;
--title: rgba(255,255,255,0.92);
--fab: #364151;
--shadow: none;
}
#disqus_thread {
color: var(--body-text-color)
}
#dsqjs #dsqjs-msg {
color: var(--t)
}
#dsqjs a {
color:var(--link)
}
#dsqjs a:focus,#dsqjs a:hover {
color: var(--link-hover)
}
#dsqjs .dsqjs-disqus-logo {
background-position: 0 -24px;
}
#dsqjs .dsqjs-nav,#dsqjs footer {
border-color: var(--hlc)
}
#dsqjs .dsqjs-load-more,#dsqjs .dsqjs-load-more:hover,#dsqjs .dsqjs-nav-tab,#dsqjs .dsqjs-no-comment,#dsqjs .dsqjs-post-content {
color: var(--t)
}
#dsqjs .dsqjs-order-label {
background-color: var(--hlc)
}
#dsqjs .dsqjs-order-radio:checked+.dsqjs-order-label {
background-color: var(--kbd)
}
#dsqjs .dsqjs-tab-active>span:after {
background-color: #2e9fff
}
#dsqjs .dsqjs-footer,#dsqjs .dsqjs-meta {
color: var(--t-l)
}
#dsqjs .dsqjs-post-body blockquote {
border-color: var(--border)
}
}
+93 -90
View File
@@ -10,7 +10,8 @@
}
/* Other */
.chroma .x {}
.chroma .x {
}
/* Error */
.chroma .err {
@@ -40,367 +41,369 @@
.chroma .hl {
display: block;
width: 100%;
background-color: #ffffcc
background-color: #ffffcc;
}
/* LineNumbersTable */
.chroma .lnt {
margin-right: 0.4em;
padding: 0 0.4em 0 0.4em;
color: #7f7f7f
color: #7f7f7f;
}
/* LineNumbers */
.chroma .ln {
margin-right: 0.4em;
padding: 0 0.4em 0 0.4em;
color: #7f7f7f
color: #7f7f7f;
}
/* Keyword */
.chroma .k {
color: #00a8c8
color: #00a8c8;
}
/* KeywordConstant */
.chroma .kc {
color: #00a8c8
color: #00a8c8;
}
/* KeywordDeclaration */
.chroma .kd {
color: #00a8c8
color: #00a8c8;
}
/* KeywordNamespace */
.chroma .kn {
color: #f92672
color: #f92672;
}
/* KeywordPseudo */
.chroma .kp {
color: #00a8c8
color: #00a8c8;
}
/* KeywordReserved */
.chroma .kr {
color: #00a8c8
color: #00a8c8;
}
/* KeywordType */
.chroma .kt {
color: #00a8c8
color: #00a8c8;
}
/* Name */
.chroma .n {
color: #111111
color: #111111;
}
/* NameAttribute */
.chroma .na {
color: #75af00
color: #75af00;
}
/* NameBuiltin */
.chroma .nb {
color: #111111
color: #111111;
}
/* NameBuiltinPseudo */
.chroma .bp {
color: #111111
color: #111111;
}
/* NameClass */
.chroma .nc {
color: #75af00
color: #75af00;
}
/* NameConstant */
.chroma .no {
color: #00a8c8
color: #00a8c8;
}
/* NameDecorator */
.chroma .nd {
color: #75af00
color: #75af00;
}
/* NameEntity */
.chroma .ni {
color: #111111
color: #111111;
}
/* NameException */
.chroma .ne {
color: #75af00
color: #75af00;
}
/* NameFunction */
.chroma .nf {
color: #75af00
color: #75af00;
}
/* NameFunctionMagic */
.chroma .fm {
color: #111111
color: #111111;
}
/* NameLabel */
.chroma .nl {
color: #111111
color: #111111;
}
/* NameNamespace */
.chroma .nn {
color: #111111
color: #111111;
}
/* NameOther */
.chroma .nx {
color: #75af00
color: #75af00;
}
/* NameProperty */
.chroma .py {
color: #111111
color: #111111;
}
/* NameTag */
.chroma .nt {
color: #f92672
color: #f92672;
}
/* NameVariable */
.chroma .nv {
color: #111111
color: #111111;
}
/* NameVariableClass */
.chroma .vc {
color: #111111
color: #111111;
}
/* NameVariableGlobal */
.chroma .vg {
color: #111111
color: #111111;
}
/* NameVariableInstance */
.chroma .vi {
color: #111111
color: #111111;
}
/* NameVariableMagic */
.chroma .vm {
color: #111111
color: #111111;
}
/* Literal */
.chroma .l {
color: #ae81ff
color: #ae81ff;
}
/* LiteralDate */
.chroma .ld {
color: #d88200
color: #d88200;
}
/* LiteralString */
.chroma .s {
color: #d88200
color: #d88200;
}
/* LiteralStringAffix */
.chroma .sa {
color: #d88200
color: #d88200;
}
/* LiteralStringBacktick */
.chroma .sb {
color: #d88200
color: #d88200;
}
/* LiteralStringChar */
.chroma .sc {
color: #d88200
color: #d88200;
}
/* LiteralStringDelimiter */
.chroma .dl {
color: #d88200
color: #d88200;
}
/* LiteralStringDoc */
.chroma .sd {
color: #d88200
color: #d88200;
}
/* LiteralStringDouble */
.chroma .s2 {
color: #d88200
color: #d88200;
}
/* LiteralStringEscape */
.chroma .se {
color: #8045ff
color: #8045ff;
}
/* LiteralStringHeredoc */
.chroma .sh {
color: #d88200
color: #d88200;
}
/* LiteralStringInterpol */
.chroma .si {
color: #d88200
color: #d88200;
}
/* LiteralStringOther */
.chroma .sx {
color: #d88200
color: #d88200;
}
/* LiteralStringRegex */
.chroma .sr {
color: #d88200
color: #d88200;
}
/* LiteralStringSingle */
.chroma .s1 {
color: #d88200
color: #d88200;
}
/* LiteralStringSymbol */
.chroma .ss {
color: #d88200
color: #d88200;
}
/* LiteralNumber */
.chroma .m {
color: #ae81ff
color: #ae81ff;
}
/* LiteralNumberBin */
.chroma .mb {
color: #ae81ff
color: #ae81ff;
}
/* LiteralNumberFloat */
.chroma .mf {
color: #ae81ff
color: #ae81ff;
}
/* LiteralNumberHex */
.chroma .mh {
color: #ae81ff
color: #ae81ff;
}
/* LiteralNumberInteger */
.chroma .mi {
color: #ae81ff
color: #ae81ff;
}
/* LiteralNumberIntegerLong */
.chroma .il {
color: #ae81ff
color: #ae81ff;
}
/* LiteralNumberOct */
.chroma .mo {
color: #ae81ff
color: #ae81ff;
}
/* Operator */
.chroma .o {
color: #f92672
color: #f92672;
}
/* OperatorWord */
.chroma .ow {
color: #f92672
color: #f92672;
}
/* Punctuation */
.chroma .p {
color: #111111
color: #111111;
}
/* Comment */
.chroma .c {
color: #75715e
color: #75715e;
}
/* CommentHashbang */
.chroma .ch {
color: #75715e
color: #75715e;
}
/* CommentMultiline */
.chroma .cm {
color: #75715e
color: #75715e;
}
/* CommentSingle */
.chroma .c1 {
color: #75715e
color: #75715e;
}
/* CommentSpecial */
.chroma .cs {
color: #75715e
color: #75715e;
}
/* CommentPreproc */
.chroma .cp {
color: #75715e
color: #75715e;
}
/* CommentPreprocFile */
.chroma .cpf {
color: #75715e
color: #75715e;
}
/* Generic */
.chroma .g {}
.chroma .g {
}
/* GenericDeleted */
.chroma .gd {}
.chroma .gd {
color: #f92672;
}
/* GenericEmph */
.chroma .ge {
font-style: italic
font-style: italic;
}
/* GenericError */
.chroma .gr {}
.chroma .gr {
}
/* GenericHeading */
.chroma .gh {}
.chroma .gh {
}
/* GenericInserted */
.chroma .gi {}
.chroma .gi {
color: #7ca727;
}
/* GenericOutput */
.chroma .go {}
.chroma .go {
}
/* GenericPrompt */
.chroma .gp {}
.chroma .gp {
}
/* GenericStrong */
.chroma .gs {
font-weight: bold
font-weight: bold;
}
/* GenericSubheading */
.chroma .gu {}
.chroma .gu {
color: #75715e;
}
/* GenericTraceback */
.chroma .gt {}
.chroma .gt {
}
/* GenericUnderline */
.chroma .gl {}
.chroma .gl {
}
/* TextWhitespace */
.chroma .w {}
.chroma .w {
}
+112 -19
View File
@@ -70,6 +70,13 @@
flex-wrap: wrap;
text-transform: unset;
}
.article-copyright,
.article-lastmod {
a {
color: var(--body-text-color);
}
}
}
}
}
@@ -116,8 +123,6 @@
}
.article-page.has-toc {
scroll-behavior: smooth;
.left-sidebar {
display: none;
}
@@ -185,32 +190,44 @@
display: flex;
flex-direction: column;
color: var(--card-text-color-main);
overflow: hidden;
::-webkit-scrollbar-thumb {
background-color: var(--card-separator-color);
}
#TableOfContents {
overflow-x: auto;
max-height: 75vh;
ol,
ul {
margin: 0;
padding: 0;
}
ol {
counter-reset: item;
list-style-type: none;
padding: 0;
margin: 0;
}
counter-reset: item;
& > li {
padding: 0;
margin: 0;
}
li {
margin: 15px 20px;
padding: 5px;
&::before {
li a::before {
counter-increment: item;
content: counters(item, ".") ". ";
font-weight: bold;
margin-right: 5px;
}
}
& > ol {
& > ul {
padding: 0 1em;
}
li {
margin: 15px 0 15px 20px;
padding: 5px;
& > ol,
& > ul {
margin-top: 10px;
padding-left: 10px;
margin-bottom: -5px;
@@ -220,6 +237,38 @@
}
}
}
li.active-class > a {
border-left: var(--heading-border-size) solid var(--accent-color);
font-weight: bold;
}
ul li.active-class > a {
display: block;
}
@function repeat($str, $n) {
$result: "";
@for $_ from 0 to $n {
$result: $result + $str;
}
@return $result;
}
// Support up to 6 levels of indentation for lists in ToCs
@for $i from 0 to 5 {
& > ul #{repeat("> li > ul", $i)} > li.active-class > a {
$n: 25 + $i * 35;
margin-left: calc(-#{$n}px - 1em);
padding-left: calc(#{$n}px + 1em - var(--heading-border-size));
}
& > ol #{repeat("> li > ol", $i)} > li.active-class > a {
$n: 9 + $i * 35;
margin-left: calc(-#{$n}px - 1em);
padding-left: calc(#{$n}px + 1em - var(--heading-border-size));
display: block;
}
}
}
}
@@ -345,6 +394,47 @@
}
}
.highlight {
background-color: var(--pre-background-color);
padding: var(--card-padding);
position: relative;
&:hover {
.copyCodeButton {
opacity: 1;
}
}
pre {
margin: initial;
padding: 0;
margin: 0;
width: auto;
}
}
.copyCodeButton {
position: absolute;
top: calc(var(--card-padding));
right: calc(var(--card-padding));
background: var(--card-background);
border: none;
box-shadow: var(--shadow-l2);
border-radius: var(--tag-border-radius);
padding: 8px 16px;
color: var(--card-text-color-main);
cursor: pointer;
font-size: 14px;
opacity: 0;
transition: opacity 0.3s ease;
}
.table-wrapper {
padding: 0 var(--card-padding);
overflow-x: auto;
display: block;
}
table {
width: 100%;
border-collapse: collapse;
@@ -379,7 +469,8 @@
padding-bottom: 56.25%;
overflow: hidden;
& > iframe {
& > iframe,
& > video {
position: absolute;
width: 100%;
height: 100%;
@@ -392,9 +483,11 @@
/// Negative margins
blockquote,
figure,
.gallery,
.highlight,
pre,
.gallery,
.video-wrapper,
.table-wrapper,
.s_video_simple {
margin-left: calc((var(--card-padding)) * -1);
margin-right: calc((var(--card-padding)) * -1);
+15
View File
@@ -201,3 +201,18 @@
}
}
}
.social-menu {
list-style: none;
padding: 0%;
display: flex;
flex-direction: row;
gap: 10px;
svg {
width: 24px;
height: 24px;
stroke: var(--body-text-color);
stroke-width: 1.33;
}
}
+1 -1
View File
@@ -45,7 +45,7 @@ $defaultTagColors: #fff, #fff, #fff, #fff, #fff;
--accent-color-darker: #bdc3c7;
--accent-color-text: #000;
--body-text-color: rgba(255, 255, 255, 0.7);
--scrollbar-thumb: #424242;
--scrollbar-thumb: hsl(0, 0%, 40%);
--scrollbar-track: var(--body-background);
}
}
+54 -2
View File
@@ -34,7 +34,7 @@ class StackGallery {
private loadItems(container: HTMLElement) {
this.items = [];
const figures = container.querySelectorAll('figure');
const figures = container.querySelectorAll('figure.gallery-image');
for (const el of figures) {
const figcaption = el.querySelector('figcaption'),
@@ -57,7 +57,59 @@ class StackGallery {
}
public static createGallery(container: HTMLElement) {
const figuresEl = container.querySelectorAll('figure');
/// The process of wrapping image with figure tag is done using JavaScript instead of only Hugo markdown render hook
/// because it can not detect whether image is being wrapped by a link or not
/// and it lead to a invalid HTML construction (<a><figure><img></figure></a>)
const images = container.querySelectorAll('img');
for (const img of Array.from(images)) {
/// Images are wrapped with figure tag if the paragraph has only images without texts
/// This is done to allow inline images within paragraphs
const paragraph = img.closest('p');
if (paragraph.textContent.trim() == '') {
/// Once we insert figcaption, this check no longer works
/// So we add a class to paragraph to mark it
paragraph.classList.add('no-text');
}
let isNewLineImage = paragraph.classList.contains('no-text');
if (!isNewLineImage) continue;
const hasLink = img.parentElement.tagName == 'A';
let el: HTMLElement = img;
/// Wrap image with figure tag, with flex-grow and flex-basis values extracted from img's data attributes
const figure = document.createElement('figure');
figure.style.setProperty('flex-grow', img.getAttribute('data-flex-grow') || '1');
figure.style.setProperty('flex-basis', img.getAttribute('data-flex-basis') || '0');
if (hasLink) {
/// Wrap <a> if it exists
el = img.parentElement;
}
el.parentElement.insertBefore(figure, el);
figure.appendChild(el);
/// Add figcaption if it exists
if (img.hasAttribute('alt')) {
const figcaption = document.createElement('figcaption');
figcaption.innerText = img.getAttribute('alt');
figure.appendChild(figcaption);
}
/// Wrap img tag with <a> tag if image was not wrapped by <a> tag
if (!hasLink) {
figure.className = 'gallery-image';
const a = document.createElement('a');
a.href = img.src;
a.setAttribute('target', '_blank');
img.parentNode.insertBefore(a, img);
a.appendChild(img);
}
}
const figuresEl = container.querySelectorAll('figure.gallery-image');
let currentGallery = [];
+37
View File
@@ -10,6 +10,8 @@ import { getColor } from 'ts/color';
import menu from 'ts/menu';
import createElement from 'ts/createElement';
import StackColorScheme from 'ts/colorScheme';
import { setupScrollspy } from 'ts/scrollspy';
import { setupSmoothAnchors } from "ts/smoothAnchors";
let Stack = {
init: () => {
@@ -21,6 +23,8 @@ let Stack = {
const articleContent = document.querySelector('.article-content') as HTMLElement;
if (articleContent) {
new StackGallery(articleContent);
setupSmoothAnchors();
setupScrollspy();
}
/**
@@ -54,6 +58,39 @@ let Stack = {
observer.observe(articleTile)
}
/**
* Add copy button to code block
*/
const highlights = document.querySelectorAll('.article-content div.highlight');
const copyText = `Copy`,
copiedText = `Copied!`;
highlights.forEach(highlight => {
const copyButton = document.createElement('button');
copyButton.innerHTML = copyText;
copyButton.classList.add('copyCodeButton');
highlight.appendChild(copyButton);
const codeBlock = highlight.querySelector('code[data-lang]');
if (!codeBlock) return;
copyButton.addEventListener('click', () => {
navigator.clipboard.writeText(codeBlock.textContent)
.then(() => {
copyButton.textContent = copiedText;
setTimeout(() => {
copyButton.textContent = copyText;
}, 1000);
})
.catch(err => {
alert(err)
console.log('Something went wrong', err);
});
});
});
new StackColorScheme(document.getElementById('dark-mode-toggle'));
}
}
+131
View File
@@ -0,0 +1,131 @@
// Implements a scroll spy system for the ToC, displaying the current section with an indicator and scrolling to it when needed.
// Inspired from https://gomakethings.com/debouncing-your-javascript-events/
function debounced(func: Function) {
let timeout;
return () => {
if (timeout) {
window.cancelAnimationFrame(timeout);
}
timeout = window.requestAnimationFrame(() => func());
}
}
const headersQuery = ".article-content h1[id], .article-content h2[id], .article-content h3[id], .article-content h4[id], .article-content h5[id], .article-content h6[id]";
const tocQuery = "#TableOfContents";
const navigationQuery = "#TableOfContents li";
const activeClass = "active-class";
function scrollToTocElement(tocElement: HTMLElement, scrollableNavigation: HTMLElement) {
let textHeight = tocElement.querySelector("a").offsetHeight;
let scrollTop = tocElement.offsetTop - scrollableNavigation.offsetHeight / 2 + textHeight / 2 - scrollableNavigation.offsetTop;
if (scrollTop < 0) {
scrollTop = 0;
}
scrollableNavigation.scrollTo({ top: scrollTop, behavior: "smooth" });
}
type IdToElementMap = { [key: string]: HTMLElement };
function buildIdToNavigationElementMap(navigation: NodeListOf<Element>): IdToElementMap {
const sectionLinkRef: IdToElementMap = {};
navigation.forEach((navigationElement: HTMLElement) => {
const link = navigationElement.querySelector("a");
const href = link.getAttribute("href");
if (href.startsWith("#")) {
sectionLinkRef[href.slice(1)] = navigationElement;
}
});
return sectionLinkRef;
}
function computeOffsets(headers: NodeListOf<Element>) {
let sectionsOffsets = [];
headers.forEach((header: HTMLElement) => { sectionsOffsets.push({ id: header.id, offset: header.offsetTop }) });
sectionsOffsets.sort((a, b) => a.offset - b.offset);
return sectionsOffsets;
}
function setupScrollspy() {
let headers = document.querySelectorAll(headersQuery);
if (!headers) {
console.warn("No header matched query", headers);
return;
}
let scrollableNavigation = document.querySelector(tocQuery) as HTMLElement | undefined;
if (!scrollableNavigation) {
console.warn("No toc matched query", tocQuery);
return;
}
let navigation = document.querySelectorAll(navigationQuery);
if (!navigation) {
console.warn("No navigation matched query", navigationQuery);
return;
}
let sectionsOffsets = computeOffsets(headers);
// We need to avoid scrolling when the user is actively interacting with the ToC. Otherwise, if the user clicks on a link in the ToC,
// we would scroll their view, which is not optimal usability-wise.
let tocHovered: boolean = false;
scrollableNavigation.addEventListener("mouseenter", debounced(() => tocHovered = true));
scrollableNavigation.addEventListener("mouseleave", debounced(() => tocHovered = false));
let activeSectionLink: Element;
let idToNavigationElement: IdToElementMap = buildIdToNavigationElementMap(navigation);
function scrollHandler() {
let scrollPosition = document.documentElement.scrollTop || document.body.scrollTop;
let newActiveSection: HTMLElement | undefined;
// Find the section that is currently active.
// It is possible for no section to be active, so newActiveSection may be undefined.
sectionsOffsets.forEach((section) => {
if (scrollPosition >= section.offset - 20) {
newActiveSection = document.getElementById(section.id);
}
});
// Find the link for the active section. Once again, there are a few edge cases:
// - No active section = no link => undefined
// - No active section but the link does not exist in toc (e.g. because it is outside of the applicable ToC levels) => undefined
let newActiveSectionLink: HTMLElement | undefined
if (newActiveSection) {
newActiveSectionLink = idToNavigationElement[newActiveSection.id];
}
if (newActiveSection && !newActiveSectionLink) {
// The active section does not have a link in the ToC, so we can't scroll to it.
console.debug("No link found for section", newActiveSection);
} else if (newActiveSectionLink !== activeSectionLink) {
if (activeSectionLink)
activeSectionLink.classList.remove(activeClass);
if (newActiveSectionLink) {
newActiveSectionLink.classList.add(activeClass);
if (!tocHovered) {
// Scroll so that newActiveSectionLink is in the middle of scrollableNavigation, except when it's from a manual click (hence the tocHovered check)
scrollToTocElement(newActiveSectionLink, scrollableNavigation);
}
}
activeSectionLink = newActiveSectionLink;
}
}
window.addEventListener("scroll", debounced(scrollHandler));
// Resizing may cause the offset values to change: recompute them.
function resizeHandler() {
sectionsOffsets = computeOffsets(headers);
scrollHandler();
}
window.addEventListener("resize", debounced(resizeHandler));
}
export { setupScrollspy };
+118 -56
View File
@@ -8,6 +8,11 @@ interface pageData {
matchCount: number
}
interface match {
start: number,
end: number
}
/**
* Escape HTML tags as HTML entities
* Edited from:
@@ -53,79 +58,131 @@ class Search {
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
/**
* Processes search matches
* @param str original text
* @param matches array of matches
* @param ellipsis whether to add ellipsis to the end of each match
* @param charLimit max length of preview string
* @param offset how many characters before and after the match to include in preview
* @returns preview string
*/
private static processMatches(str: string, matches: match[], ellipsis: boolean = true, charLimit = 140, offset = 20): string {
matches.sort((a, b) => {
return a.start - b.start;
});
let i = 0,
lastIndex = 0,
charCount = 0;
const resultArray: string[] = [];
while (i < matches.length) {
const item = matches[i];
/// item.start >= lastIndex (equal only for the first iteration)
/// because of the while loop that comes after, iterating over variable j
if (ellipsis && item.start - offset > lastIndex) {
resultArray.push(`${replaceHTMLEnt(str.substring(lastIndex, lastIndex + offset))} [...] `);
resultArray.push(`${replaceHTMLEnt(str.substring(item.start - offset, item.start))}`);
charCount += offset * 2;
}
else {
/// If the match is too close to the end of last match, don't add ellipsis
resultArray.push(replaceHTMLEnt(str.substring(lastIndex, item.start)));
charCount += item.start - lastIndex;
}
let j = i + 1,
end = item.end;
/// Include as many matches as possible
/// [item.start, end] is the range of the match
while (j < matches.length && matches[j].start <= end) {
end = Math.max(matches[j].end, end);
++j;
}
resultArray.push(`<mark>${replaceHTMLEnt(str.substring(item.start, end))}</mark>`);
charCount += end - item.start;
i = j;
lastIndex = end;
if (ellipsis && charCount > charLimit) break;
}
/// Add the rest of the string
if (lastIndex < str.length) {
let end = str.length;
if (ellipsis) end = Math.min(end, lastIndex + offset);
resultArray.push(`${replaceHTMLEnt(str.substring(lastIndex, end))}`);
if (ellipsis && end != str.length) {
resultArray.push(` [...]`);
}
}
return resultArray.join('');
}
private async searchKeywords(keywords: string[]) {
const rawData = await this.getData();
const results: pageData[] = [];
const regex = new RegExp(keywords.filter((v, index, arr) => {
arr[index] = escapeRegExp(v);
return v.trim() !== '';
}).join('|'), 'gi');
for (const item of rawData) {
const titleMatches: match[] = [],
contentMatches: match[] = [];
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)} `;
}
}
const contentMatchAll = item.content.matchAll(regex);
for (const match of Array.from(contentMatchAll)) {
contentMatches.push({
start: match.index,
end: match.index + match[0].length
});
}
if (matched) {
result.preview += '[...]';
results.push(result);
const titleMatchAll = item.title.matchAll(regex);
for (const match of Array.from(titleMatchAll)) {
titleMatches.push({
start: match.index,
end: match.index + match[0].length
});
}
if (titleMatches.length > 0) result.title = Search.processMatches(result.title, titleMatches, false);
if (contentMatches.length > 0) {
result.preview = Search.processMatches(result.content, contentMatches);
}
else {
/// If there are no matches in the content, use the first 140 characters as preview
result.preview = replaceHTMLEnt(result.content.substring(0, 140));
}
result.matchCount = titleMatches.length + contentMatches.length;
if (result.matchCount > 0) results.push(result);
}
/** Result with more matches appears first */
/// 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();
@@ -150,6 +207,11 @@ class Search {
/// Not fetched yet
const jsonURL = this.form.dataset.json;
this.data = await fetch(jsonURL).then(res => res.json());
const parser = new DOMParser();
for (const item of this.data) {
item.content = parser.parseFromString(item.content, 'text/html').body.innerText;
}
}
return this.data;
@@ -160,7 +222,7 @@ class Search {
const eventHandler = (e) => {
e.preventDefault();
const keywords = this.input.value;
const keywords = this.input.value.trim();
Search.updateQueryString(keywords, true);
@@ -225,7 +287,7 @@ class Search {
<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>
<section class="article-preview" dangerouslySetInnerHTML={{ __html: item.preview }}></section>
</div>
{item.image &&
<div class="article-image">
+34
View File
@@ -0,0 +1,34 @@
// Implements smooth scrolling when clicking on an anchor link.
// This is required instead of using modern CSS because Chromium does not currently support scrolling
// one element with scrollTo while another element is scrolled because of a click on a link. This would
// thus not work with the ToC scrollspy and e.g. footnotes.
// Here are additional links about this issue:
// - https://stackoverflow.com/questions/49318497/google-chrome-simultaneously-smooth-scrollintoview-with-more-elements-doesn
// - https://stackoverflow.com/questions/57214373/scrollintoview-using-smooth-function-on-multiple-elements-in-chrome
// - https://bugs.chromium.org/p/chromium/issues/detail?id=833617
// - https://bugs.chromium.org/p/chromium/issues/detail?id=1043933
// - https://bugs.chromium.org/p/chromium/issues/detail?id=1121151
const anchorLinksQuery = "a[href]";
function setupSmoothAnchors() {
document.querySelectorAll(anchorLinksQuery).forEach(aElement => {
let href = aElement.getAttribute("href");
if (!href.startsWith("#")) {
return;
}
aElement.addEventListener("click", clickEvent => {
clickEvent.preventDefault();
let targetId = aElement.getAttribute("href").substring(1);
// The replace done on ':' is here for footnotes, as this character would otherwise interfere when used as a CSS selector.
let target = document.querySelector(`#${targetId.replace(":", "\\:")}`) as HTMLElement;
window.history.pushState({}, "", aElement.getAttribute("href"));
scrollTo({ top: target.offsetTop, behavior: "smooth" });
});
});
}
export { setupSmoothAnchors };
+147
View File
@@ -0,0 +1,147 @@
module:
hugoVersion:
extended: true
min: "0.87.0"
params:
mainSections:
- post
featuredImageField: image
rssFullContent: true
favicon:
footer:
since:
customText:
dateFormat:
published: Jan 02, 2006
lastUpdated: Jan 02, 2006 15:04 MST
sidebar:
emoji:
subtitle:
avatar:
enabled: true
local: true
src: img/avatar.png
article:
math: false
toc: true
readingTime: true
license:
enabled: false
default: Licensed under CC BY-NC-SA 4.0
comments:
enabled: false
provider: disqus
disqusjs:
shortname:
apiUrl:
apiKey:
admin:
adminLabel:
utterances:
repo:
issueTerm: pathname
label:
remark42:
host:
site:
locale:
vssue:
platform:
owner:
repo:
clientId:
clientSecret:
autoCreateIssue: false
# Waline client configuration see: https://waline.js.org/en/reference/client.html
waline:
serverURL:
lang:
visitor:
avatar:
emoji:
- https://cdn.jsdelivr.net/gh/walinejs/emojis/weibo
requiredMeta:
- name
- email
- url
placeholder:
locale:
admin: Admin
twikoo:
envId:
region:
path:
lang:
giscus:
repo:
repoID:
category:
categoryID:
mapping:
lightTheme:
darkTheme:
reactionsEnabled: 1
emitMetadata: 0
gitalk:
owner:
admin:
repo:
clientID:
clientSecret:
cusdis:
host:
id:
widgets:
enabled:
- search
- archives
- tag-cloud
archives:
limit: 5
tagCloud:
limit: 10
opengraph:
twitter:
# Your Twitter username
site:
# Available values: summary, summary_large_image
card: summary_large_image
defaultImage:
opengraph:
enabled: false
local: false
src:
colorScheme:
# Display toggle
toggle: true
# Available values: auto, light, dark
default: auto
imageProcessing:
cover:
enabled: true
content:
enabled: true
+14 -6
View File
@@ -23,16 +23,24 @@ PhotoSwipe:
type: style
KaTeX:
- src: https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css
integrity: sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X
- src: https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css
integrity: sha384-RZU/ijkSsFbcmivfdRBQDtwuwVqK7GMOw6IMvKyeWL2K5UAlyp6WonmB8m7Jd0Hn
type: style
- src: https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js
integrity: sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4
- src: https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.js
integrity: sha384-pK1WpvzWVBQiP0/GjnvRxV4mOb0oxFuyRxJlk6vVw146n3egcN5C925NCP7a7BY8
type: script
defer: true
- src: https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js
integrity: sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa
- src: https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/contrib/auto-render.min.js
integrity: sha384-vZTG03m+2yp6N6BNi5iM4rW4oIwk5DfcNdFfxkk9ZWpDriOkXX8voJBFrAO7MpVl
type: script
defer: true
Cactus:
- src: https://latest.cactus.chat/cactus.js
integrity:
type: script
- src: https://latest.cactus.chat/style.css
integrity:
type: style
Executable
+1
View File
@@ -0,0 +1 @@
cd exampleSite && hugo server --gc --themesDir=../..
+5 -2
View File
@@ -22,6 +22,9 @@ _testmain.go
*.exe
*.test
/public
/themes
public
themes
resources
assets/jsconfig.json
.DS_Store
+75 -3
View File
@@ -11,9 +11,13 @@ disqusShortname: hugo-theme-stack
googleAnalytics:
# Theme i18n support
# Available values: en, fr, id, ja, ko, pt-br, zh-cn, es, de, nl
# Available values: en, fr, id, ja, ko, pt-br, zh-cn, zh-tw, es, de, nl, it, th, el, uk
DefaultContentLanguage: en
# Set hasCJKLanguage to true if DefaultContentLanguage is in [zh-cn ja ko]
# This will make .Summary and .WordCount behave correctly for CJK languages.
hasCJKLanguage: false
permalinks:
post: /p/:slug/
page: /:slug/
@@ -37,12 +41,14 @@ params:
emoji: 🍥
subtitle: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
avatar:
enabled: true
local: true
src: img/avatar.png
article:
math: false
toc: true
readingTime: true
license:
enabled: true
default: Licensed under CC BY-NC-SA 4.0
@@ -51,6 +57,13 @@ params:
enabled: true
provider: disqus
disqusjs:
shortname:
apiUrl:
apiKey:
admin:
adminLabel:
utterances:
repo:
issueTerm: pathname
@@ -85,6 +98,39 @@ params:
locale:
admin: Admin
twikoo:
envId:
region:
path:
lang:
# See https://cactus.chat/docs/reference/web-client/#configuration for description of the various options
cactus:
defaultHomeserverUrl: "https://matrix.cactus.chat:8448"
serverName: "cactus.chat"
siteName: "" # You must insert a unique identifier here matching the one you registered (See https://cactus.chat/docs/getting-started/quick-start/#register-your-site)
giscus:
repo:
repoID:
category:
categoryID:
mapping:
lightTheme:
darkTheme:
reactionsEnabled: 1
emitMetadata: 0
gitalk:
owner:
admin:
repo:
clientID:
clientSecret:
cusdis:
host:
id:
widgets:
enabled:
- search
@@ -125,7 +171,7 @@ params:
enabled: true
### Custom menu
### See https://docs.stack.jimmycai.com/configuration/custom-menu
### See https://docs.stack.jimmycai.com/configuration/custom-menu.html
### To remove about, archive and search page menu item, remove `menu` field from their FrontMatter
menu:
main:
@@ -133,7 +179,23 @@ menu:
name: Home
url: /
weight: -100
pre: home
params:
### For demonstration purpose, the home link will be open in a new tab
newTab: true
icon: home
social:
- identifier: github
name: GitHub
url: https://github.com/CaiJimmy/hugo-theme-stack
params:
icon: brand-github
- identifier: twitter
name: Twitter
url: https://twitter.com
params:
icon: brand-twitter
related:
includeNewer: true
@@ -147,9 +209,19 @@ related:
weight: 200
markup:
goldmark:
renderer:
## Set to true if you have HTML content inside Markdown
unsafe: false
tableOfContents:
endLevel: 4
ordered: true
startLevel: 2
highlight:
noClasses: false
codeFences: true
guessSyntax: true
lineNoStart: 1
lineNos: true
lineNumbersInTable: true
tabWidth: 4
@@ -11,7 +11,8 @@ lastmod: '2020-10-09'
menu:
main:
weight: -90
pre: user
params:
icon: user
---
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.
@@ -6,5 +6,6 @@ slug: "archives"
menu:
main:
weight: -70
pre: archives
params:
icon: archives
---
+37
View File
@@ -0,0 +1,37 @@
---
title: Links
links:
- title: GitHub
description: GitHub is the world's largest software development platform.
website: https://github.com
image: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
- title: TypeScript
description: TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
website: https://www.typescriptlang.org
image: ts-logo-128.jpg
menu:
main:
weight: -50
params:
icon: link
comments: false
---
To use this feature, add `links` section to frontmatter.
This page's frontmatter:
```yaml
links:
- title: GitHub
description: GitHub is the world's largest software development platform.
website: https://github.com
image: https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png
- title: TypeScript
description: TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
website: https://www.typescriptlang.org
image: ts-logo-128.jpg
```
`image` field accepts both local and external images.
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -8,5 +8,6 @@ outputs:
menu:
main:
weight: -60
pre: search
params:
icon: search
---
@@ -69,6 +69,10 @@ Tables aren't part of the core Markdown spec, but Hugo supports supports them ou
| -------- | -------- | ------ |
| *italics* | **bold** | `code` |
| A | B | C | D | E | F |
|----------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|------------------------------------------------------------|----------------------------------------------------------------------|
| Lorem ipsum dolor sit amet, consectetur adipiscing elit. | Phasellus ultricies, sapien non euismod aliquam, dui ligula tincidunt odio, at accumsan nulla sapien eget ex. | Proin eleifend dictum ipsum, non euismod ipsum pulvinar et. Vivamus sollicitudin, quam in pulvinar aliquam, metus elit pretium purus | Proin sit amet velit nec enim imperdiet vehicula. | Ut bibendum vestibulum quam, eu egestas turpis gravida nec | Sed scelerisque nec turpis vel viverra. Vivamus vitae pretium sapien |
## Code Blocks
#### Code block with backticks
@@ -113,6 +117,16 @@ Tables aren't part of the core Markdown spec, but Hugo supports supports them ou
</html>
{{< /highlight >}}
#### Diff code block
```diff
[dependencies.bevy]
git = "https://github.com/bevyengine/bevy"
rev = "11f52b8c72fc3a568e8bb4a4cd1f3eb025ac2e13"
- features = ["dynamic"]
+ features = ["jpeg", "dynamic"]
```
## List Types
#### Ordered List
@@ -148,3 +162,7 @@ X<sup>n</sup> + Y<sup>n</sup> = Z<sup>n</sup>
Press <kbd><kbd>CTRL</kbd>+<kbd>ALT</kbd>+<kbd>Delete</kbd></kbd> to end the session.
Most <mark>salamanders</mark> are nocturnal, and hunt for insects, worms, and other small creatures.
## Hyperlinked image
[![Google](https://www.google.com/images/branding/googlelogo/1x/googlelogo_light_color_272x92dp.png)](https://google.com)
@@ -32,3 +32,11 @@ Hugo ships with several [Built-in Shortcodes](https://gohugo.io/content-manageme
## Vimeo Simple Shortcode
{{< vimeo_simple 48912912 >}}
## bilibilibi Shortcode
{{< bilibili av498363026 >}}
## Gist Shortcode
{{< gist spf13 7896402 >}}
+3
View File
@@ -0,0 +1,3 @@
module github.com/CaiJimmy/hugo-theme-stack
go 1.12
+19 -2
View File
@@ -17,23 +17,37 @@ list:
other: Unterabschnitte
article:
back:
other: Zurück
tableOfContents:
other: Inhaltsverzeichnis
relatedContents:
other: Verwandte Inhalte
lastUpdatedOn:
other: Zuletzt aktualisiert am
readingTime:
one: "{{ .Count }} Minute Lesezeit"
other: "{{ .Count }} Minuten Lesezeit"
notFound:
title:
other: Seite nicht gefunden
subtitle:
other: Diese Seite existiert nicht.
other: Diese Seite existiert nicht
widget:
archives:
title:
other: Archiv
more:
other: Weitere
tagCloud:
title:
other: Schlagwörter
@@ -41,13 +55,16 @@ widget:
search:
title:
other: Suche
placeholder:
other: Etwas tippen...
resultTitle:
other: "#PAGES_COUNT pages (#TIME_SECONDS seconds)"
other: "#PAGES_COUNT Seiten (#TIME_SECONDS Sekunden)"
footer:
builtWith:
other: Erstellt mit {{ .Generator }}
designedBy:
other: Theme {{ .Theme }} gestaltet von {{ .DesignedBy }}
+70
View File
@@ -0,0 +1,70 @@
toggleMenu:
other: Εναλλαγή Μενού
darkMode:
other: Σκοτεινό θέμα
list:
page:
one: "{{ .Count }} σελιδα"
other: "{{ .Count }} σελιδες"
section:
other: Ενότητα
subsection:
one: Υποενότητα
other: Υποενότητες
article:
back:
other: Πισω
tableOfContents:
other: Πινακας περιεχομενων
relatedContents:
other: Σχετικο περιεχομενο
lastUpdatedOn:
other: Τελευταια τροποποιηση στις
readingTime:
one: "{{ .Count }} λεπτό ανάγνωσης"
### Seems that there's no need to add 's' even if it's plural in English
other: "{{ .Count }} λεπτά ανάγνωσης"
notFound:
title:
other: Δε βρέθηκε
subtitle:
other: Η σελίδα δε βρέθηκε.
widget:
archives:
title:
other: Αρχειο
more:
other: Περισσότερα
tagCloud:
title:
other: Tags
search:
title:
other: Αναζήτηση
placeholder:
other: Πληκτρολογήστε κάτι...
resultTitle:
other: "#PAGES_COUNT σελιδες (#TIME_SECONDS δευτερολεπτα)"
footer:
builtWith:
other: Δημιουργήθηκε με τη χρήση {{ .Generator }}
designedBy:
other: Το θέμα {{ .Theme }} σχεδιάστηκε από το {{ .DesignedBy }}
+6 -1
View File
@@ -29,11 +29,16 @@ article:
lastUpdatedOn:
other: Last updated on
readingTime:
one: "{{ .Count }} minute read"
other: "{{ .Count }} minute read"
notFound:
title:
other: Not Found
subtitle:
other: This page does not exist.
other: This page does not exist
widget:
archives:
+17
View File
@@ -17,14 +17,26 @@ list:
other: Subsecciones
article:
back:
other: Volver
tableOfContents:
other: Tabla de contenido
relatedContents:
other: Contenidos relacionados
lastUpdatedOn:
other: Última vez actualizado
readingTime:
one: "{{ .Count }} minuto a leer"
other: "{{ .Count }} minutos a leer"
notFound:
title:
other: No Encontrado
subtitle:
other: Esta página no existe
@@ -32,8 +44,10 @@ widget:
archives:
title:
other: Archivo
more:
other: Más
tagCloud:
title:
other: Etiquetas
@@ -41,13 +55,16 @@ widget:
search:
title:
other: Búsqueda
placeholder:
other: Teclea algo...
resultTitle:
other: "#PAGES_COUNT páginas en (#TIME_SECONDS segundos)"
footer:
builtWith:
other: Creado con {{ .Generator }}
designedBy:
other: Tema {{ .Theme }} diseñado por {{ .DesignedBy }}
+4
View File
@@ -29,6 +29,10 @@ article:
lastUpdatedOn:
other: Dernière mise à jour le
readingTime:
one: "{{ .Count }} minute de lecture"
other: "{{ .Count }} minutes de lecture"
notFound:
title:
other: Page non trouvée
+33 -2
View File
@@ -1,24 +1,52 @@
toggleMenu:
other: Tampilkan Menu
darkMode:
other: Mode Gelap
list:
page:
one: "{{ .Count }} halaman"
other: "{{ .Count }} halaman"
section:
other: Bagian
subsection:
one: Subbagian
other: Subbagian
article:
back:
other: Kembali
tableOfContents:
other: Daftar Isi
relatedContents:
other: Konten terkait
lastUpdatedOn:
other: Terakhir diperbarui pada
readingTime:
one: "Waktu Membaca: {{ .Count }} menit"
other: "Waktu Membaca: {{ .Count }} menit"
notFound:
title:
other: Not Found
other: Tidak ditemukan
subtitle:
other: Halaman ini tidak ada.
other: Halaman yang Anda akses tidak ditemukan.
widget:
archives:
title:
other: Arsip
more:
other: Lebih
tagCloud:
title:
other: Tag
@@ -26,13 +54,16 @@ widget:
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 }}
+69
View File
@@ -0,0 +1,69 @@
toggleMenu:
other: Toggle Menu
darkMode:
other: Dark Mode
list:
page:
one: "{{ .Count }} pagina"
other: "{{ .Count }} pagine"
section:
other: Sezione
subsection:
one: Sottosezione
other: Sottosezioni
article:
back:
other: Indietro
tableOfContents:
other: Indice
relatedContents:
other: Contenuti correlati
lastUpdatedOn:
other: Aggiornato il
readingTime:
one: "{{ .Count }} min per leggere"
other: "{{ .Count }} min per leggere"
notFound:
title:
other: Non trovato
subtitle:
other: Questa pagina non esiste.
widget:
archives:
title:
other: Archivi
more:
other: Di più
tagCloud:
title:
other: Tags
search:
title:
other: Cerca
placeholder:
other: Scrivi qualcosa...
resultTitle:
other: "#PAGES_COUNT pagine (#TIME_SECONDS secondi)"
footer:
builtWith:
other: Realizzato con {{ .Generator }}
designedBy:
other: Tema {{ .Theme }} realizzato da {{ .DesignedBy }}
+3
View File
@@ -17,6 +17,9 @@ article:
lastUpdatedOn:
other: 最終更新
readingTime:
other: "読了時間: {{ .Count }}分"
notFound:
title:
other: 404 Not Found
+30
View File
@@ -1,15 +1,42 @@
toggleMenu:
other: 메뉴 여닫기
darkMode:
other: 다크 모드
list:
page:
one: "{{ .Count }} 페이지"
other: "{{ .Count }} 페이지"
section:
other: 섹션
subsection:
one: 서브섹션
other: 서브섹션
article:
back:
other: 뒤로가기
tableOfContents:
other: 목차
relatedContents:
other: 관련 글
lastUpdatedOn:
other: "마지막 수정: "
readingTime:
one: "{{ .Count }} 분 정도"
other: "{{ .Count }} 분 정도"
notFound:
title:
other: 찾을 수 없음
subtitle:
other: 페이지를 찾을 수 없습니다.
@@ -19,6 +46,7 @@ widget:
other: 보관함
more:
other: 더보기
tagCloud:
title:
other: 태그
@@ -26,8 +54,10 @@ widget:
search:
title:
other: 검색
placeholder:
other: 검색어를 입력하세요...
resultTitle:
other: "#PAGES_COUNT 페이지 (#TIME_SECONDS 초)"
+4
View File
@@ -28,6 +28,10 @@ article:
lastUpdatedOn:
other: Ostatnio zaktualizowany
readingTime:
one: "Przeczytasz w {{ .Count }} minutę"
other: "Przeczytasz w {{ .Count }} minut"
notFound:
title:
+12 -1
View File
@@ -17,11 +17,22 @@ list:
other: Subseções
article:
back:
other: Voltar
tableOfContents:
other: Índice
relatedContents:
other: Conteúdos Relacionados
other: Conteúdo relacionado
lastUpdatedOn:
other: Última atualização em
readingTime:
one: "{{ .Count }} minuto de leitura"
other: "{{ .Count }} minutos de leitura"
notFound:
title:
other: Não Encontrado
+6
View File
@@ -21,10 +21,16 @@ list:
other: Подразделы
article:
back:
other: Назад
relatedContents:
other: Также рекомендуем
lastUpdatedOn:
other: Обновлено
tableOfContents:
other: Содержание
readingTime:
other: "Время чтения: {{ .Count }} мин."
notFound:
title:
+70
View File
@@ -0,0 +1,70 @@
toggleMenu:
other: สลับเมนู
darkMode:
other: ธีมมืด
list:
page:
one: "{{ .Count }} หน้า"
other: "{{ .Count }} หน้า"
section:
other: หมวดหมู่
subsection:
one: หมวดหมู่ย่อย
other: หมวดหมู่ย่อยอื่นๆ
article:
back:
other: กลับไป
tableOfContents:
other: สารบัญ
relatedContents:
other: เนื้อหาคล้ายคลึงกัน
lastUpdatedOn:
other: อัปเดตล่าสุดเมื่อ
readingTime:
one: "น่าจะใช้เวลา {{ .Count }} นาทีในการอ่าน"
other: "น่าจะใช้เวลา {{ .Count }} นาทีในการอ่าน"
notFound:
title:
other: ไม่พบหัวข้อ
subtitle:
other: ไม่พบหน้านี้ในระบบ
widget:
archives:
title:
other: เนื้อหาที่เก็บถาวรแล้ว
more:
other: อื่นๆ นอกจากนี้
tagCloud:
title:
other: แท็ก
search:
title:
other: ค้นหา
placeholder:
other: พิมพ์เพื่อค้นหา ...
resultTitle:
other: "#PAGES_COUNT pages (#TIME_SECONDS seconds)"
footer:
builtWith:
other: ถูกสร้างด้วย {{ .Generator }}
designedBy:
other: ธีม {{ .Theme }} ออกแบบโดย {{ .DesignedBy }}
+71
View File
@@ -0,0 +1,71 @@
toggleMenu:
other: Показати меню
darkMode:
other: Темна тема
list:
page:
one: "{{ .Count }} сторінка"
few: "{{ .Count }} сторінки"
other: "{{ .Count }} сторінок"
section:
other: Секція
subsection:
one: Підсекція
other: Підсекції
article:
back:
other: Назад
tableOfContents:
other: Зміст
relatedContents:
other: Схожі матеріали
lastUpdatedOn:
other: Востаннє оновлено
readingTime:
one: "Час читання: {{ .Count }} хв"
other: "Час читання: {{ .Count }} хв"
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: Тема {{ .Theme }}, дизайн {{ .DesignedBy }}
+3
View File
@@ -17,6 +17,9 @@ article:
lastUpdatedOn:
other: 最后更新于
readingTime:
other: "阅读时长: {{ .Count }} 分钟"
notFound:
title:
other: 404 错误
+49
View File
@@ -0,0 +1,49 @@
toggleMenu:
other: 切換選單
darkMode:
other: 夜晚模式
article:
back:
other: 返回
tableOfContents:
other: 目錄
relatedContents:
other: 相關文章
lastUpdatedOn:
other: 最後更新
readingTime:
other: "閱讀時間: {{ .Count }} 分鐘"
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 秒)"
+39 -28
View File
@@ -1,30 +1,41 @@
{{- $image := .Page.Resources.GetMatch (printf "%s" (.Destination | safeURL)) -}}
{{- if and $image (ne (path.Ext .Destination) ".svg") -}}
{{- $alt := .PlainText | safeHTML -}}
<figure style="flex-grow: {{ div (mul $image.Width 100) $image.Height }}; flex-basis: {{ div (mul $image.Width 240) $image.Height }}px">
<a href="{{ $image.RelPermalink }}" data-size="{{ $image.Width }}x{{ $image.Height }}">
{{- $Permalink := $image.RelPermalink -}}
{{- $Width := $image.Width -}}
{{- $Height := $image.Height -}}
{{- $Srcset := "" -}}
{{- $Permalink := .Destination | relURL | safeURL -}}
{{- $alt := .PlainText | safeHTML -}}
{{- $Width := 0 -}}
{{- $Height := 0 -}}
{{- $Srcset := "" -}}
{{- if (default true .Page.Site.Params.imageProcessing.content.enabled) -}}
{{- $small := $image.Resize "480x" -}}
{{- $big := $image.Resize "1024x" -}}
{{- $Srcset = printf "%s 480w, %s 1024w" $small.RelPermalink $big.RelPermalink -}}
{{- end -}}
<img src="{{ $Permalink }}"
{{ with $Srcset }}srcset="{{ . }}"{{ end }}
width="{{ $Width }}"
height="{{ $Height }}"
loading="lazy"
{{ with $alt }}alt="{{ . }}"{{ end }}>
</a>
{{ with $alt }}
<figcaption>{{ . | markdownify }}</figcaption>
{{ end }}
</figure>
{{- else -}}
<img src="{{ .Destination | relURL | safeURL }}" alt="{{ .Text }}" {{ with .Title }} title="{{ . }}"{{ end }} />
{{- end -}}
{{/* SVG and external images won't work with gallery layout, because their width and height attributes are unknown */}}
{{- $galleryImage := false -}}
{{- if $image -}}
{{- $notSVG := ne (path.Ext .Destination) ".svg" -}}
{{- $Permalink = $image.RelPermalink -}}
{{- if $notSVG -}}
{{- $Width = $image.Width -}}
{{- $Height = $image.Height -}}
{{- $galleryImage = true -}}
{{- if (default true .Page.Site.Params.imageProcessing.content.enabled) -}}
{{- $small := $image.Resize `480x` -}}
{{- $big := $image.Resize `1024x` -}}
{{- $Srcset = printf `%s 480w, %s 1024w` $small.RelPermalink $big.RelPermalink -}}
{{- end -}}
{{- end -}}
{{- end -}}
<img src="{{ $Permalink }}"
{{ with $Width }}width="{{ . }}"{{ end }}
{{ with $Height }}height="{{ . }}"{{ end }}
{{ with $Srcset }}srcset="{{ . }}"{{ end }}
loading="lazy"
{{ with $alt }}
alt="{{ . }}"
{{ 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 }}
>
+7 -3
View File
@@ -15,9 +15,13 @@
{{ define "main" }}
{{ partial "article/article.html" . }}
{{ if .Params.links }}
{{ partial "article/components/links" . }}
{{ end }}
{{ partial "article/components/related-contents" . }}
{{ if or (not (isset .Params "comments")) (eq .Params.comments "true")}}
{{ if not (eq .Params.comments false) }}
{{ partial "comments/include" . }}
{{ end }}
@@ -29,7 +33,7 @@
{{ define "left-sidebar" }}
{{ if (.Scratch.Get "hasTOC") }}
<div id="article-toolbar">
<a href="{{ .Site.BaseURL }}" class="back-home">
<a href="{{ .Site.BaseURL | relLangURL }}" class="back-home">
{{ (resources.Get "icons/back.svg").Content | safeHTML }}
<span>{{ T "article.back" }}</span>
</a>
@@ -54,4 +58,4 @@
</section>
</aside>
{{ end }}
{{ end }}
{{ end }}
@@ -29,6 +29,7 @@
<img src="{{ $Permalink }}"
width="{{ $Width }}"
height="{{ $Height }}"
alt="{{ .Title }}"
loading="lazy">
{{ else }}
<img src="{{ $image.permalink }}" loading="lazy" alt="Featured image of post {{ .Title }}" />
+3 -2
View File
@@ -20,8 +20,9 @@
<img src="{{ $Permalink }}"
width="{{ $Width }}"
height="{{ $Height }}"
loading="lazy"
data-key="{{ .context.Slug }}"
loading="lazy"
alt="Featured image of post {{ .context.Title }}"
{{ with .context.Slug }}data-key="{{ . }}" {{ end }}
data-hash="{{ $imageRaw.Data.Integrity }}">
{{ else }}
<img src="{{ $image.permalink }}" loading="lazy" data-key="{{ .context.Slug }}" data-hash="{{ $image.permalink }}"/>
@@ -1,3 +1,5 @@
<section class="article-content">
{{ .Content }}
<!-- Refer to https://discourse.gohugo.io/t/responsive-tables-in-markdown/10639/5 -->
{{ $wrappedTable := printf "<div class=\"table-wrapper\">${1}</div>" }}
{{ .Content | replaceRE "(<table>(?:.|\n)+?</table>)" $wrappedTable | safeHTML }}
</section>
@@ -21,12 +21,25 @@
</h3>
{{ end }}
{{- if not .Date.IsZero -}}
{{ if or (not .Date.IsZero) (.Site.Params.article.readingTime) }}
<footer class="article-time">
{{ partial "helper/icon" "clock" }}
<time class="article-time--published">
{{- .Date.Format (or .Site.Params.dateFormat.published "Jan 02, 2006") -}}
</time>
{{ if not .Date.IsZero }}
<div>
{{ partial "helper/icon" "date" }}
<time class="article-time--published">
{{- .Date.Format (or .Site.Params.dateFormat.published "Jan 02, 2006") -}}
</time>
</div>
{{ end }}
{{ if .Site.Params.article.readingTime }}
<div>
{{ partial "helper/icon" "clock" }}
<time class="article-time--reading">
{{ T "article.readingTime" .ReadingTime }}
</time>
</div>
{{ end }}
</footer>
{{- end -}}
{{ end }}
</div>
@@ -4,16 +4,16 @@
{{ if and (.Site.Params.article.license.enabled) (not (eq .Params.license false)) }}
<section class="article-copyright">
{{ partial "helper/icon" "copyright" }}
<span>{{ default .Site.Params.article.license.default .Params.license }}</span>
<span>{{ default .Site.Params.article.license.default .Params.license | markdownify }}</span>
</section>
{{ end }}
{{- if ne .Lastmod .Date -}}
<section class="article-time">
<section class="article-lastmod">
{{ partial "helper/icon" "clock" }}
<span class="article-time--modified">
<span>
{{ T "article.lastUpdatedOn" }} {{ .Lastmod.Format ( or .Site.Params.dateFormat.lastUpdated "Jan 02, 2006 15:04 MST" ) }}
</span>
</section>
{{- end -}}
</footer>
</footer>
@@ -0,0 +1,26 @@
<div class="article-list--compact links">
{{ range $i, $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">
{{ with $link.description }}
{{ . }}
{{ else }}
{{ $link.website }}
{{ end }}
</footer>
</div>
{{ with $link.image }}
<div class="article-image">
<img src="{{ . }}" loading="lazy">
</div>
{{ end }}
</a>
</article>
{{ end }}
</div>
@@ -0,0 +1,29 @@
{{- with .Site.Params.comments.cactus -}}
{{- partial "helper/external" (dict "Context" $ "Namespace" "Cactus") -}}
<style>
.cactus-editor-textarea {
color: var(--body-text-color);
}
.cactus-comment-header {
color: var(--card-text-color-main);
}
.cactus-message-text > p {
color: var(--body-text-color);
}
</style>
<div id="comment-section"></div>
<script>
initComments({
node: document.getElementById("comment-section"),
defaultHomeserverUrl: "{{ .defaultHomeserverUrl | safeJS }}",
serverName: "{{ .serverName }}",
siteName: "{{ .siteName }}",
commentSectionId: "{{ $.File.UniqueID }}"
})
</script>
{{- end -}}
@@ -0,0 +1,21 @@
{{- $host := default "https://cusdis.com" .Site.Params.comments.cusdis.host -}}
<div id="cusdis_thread"
data-host="{{ $host }}"
data-app-id="{{ .Site.Params.comments.cusdis.id }}"
data-page-id="{{ .File.UniqueID }}"
data-page-url="{{ .Permalink }}"
data-page-title="{{ .Title }}"></div>
<script async defer src="{{ $host }}/js/cusdis.es.js"></script>
<script>
function setCusdisTheme(theme) {
let cusdis = document.querySelector('#cusdis_thread iframe');
if (cusdis) {
window.CUSDIS.setTheme(theme)
}
}
window.addEventListener('onColorSchemeChange', (e) => {
setCusdisTheme(e.detail)
})
</script>
@@ -0,0 +1,61 @@
{{- $pc := .Site.Config.Privacy.Disqus -}}
{{- $disqusjs := .Site.Params.Comments.disqusjs -}}
{{- if and (not $pc.Disable) (and $disqusjs.Shortname $disqusjs.ApiKey) -}}
{{- $style := resources.Get "scss/partials/comments/disqusjs.scss" | resources.ToCSS | minify -}}
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
<div class="disqus-container">
<div id="disqus_thread"></div>
<script type="application/javascript">
let disqusjs;
function loadDisqusJS() {
disqusjs = new DisqusJS({
shortname: {{ $disqusjs.Shortname }},
siteName: {{ .Site.Title }},
apikey: {{ $disqusjs.ApiKey }},
{{ with $disqusjs.ApiUrl }}api: {{ . }},{{ end }}
{{ with $disqusjs.Admin }}admin: {{ . }},{{ end }}
{{ with $disqusjs.AdminLabel }}adminLabel: {{ . }}{{ end }}
});
}
function lazyLoadDisqusJS() {
if (["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1) {
document.getElementById('disqus_thread').innerHTML = 'Disqus comments not available by default when the website is previewed locally.';
return;
}
let d = document.createElement('script');
d.src = 'https://cdn.jsdelivr.net/npm/disqusjs@1.3/dist/disqus.js';
d.async = false;
document.body.appendChild(d);
d.onload = () => {
loadDisqusJS();
window.addEventListener('onColorSchemeChange', (e) => {
if (disqusjs) {
loadDisqusJS();
}
})
}
}
let runningOnBrowser = typeof window !== "undefined";
let isBot = runningOnBrowser && !("onscroll" in window) || typeof navigator !== "undefined" && /(gle|ing|ro|msn)bot|crawl|spider|yand|duckgo/i.test(navigator.userAgent);
let supportsIntersectionObserver = runningOnBrowser && "IntersectionObserver" in window;
if (!isBot && supportsIntersectionObserver) {
let disqus_observer = new IntersectionObserver(function(entries) {
if (entries[0].isIntersecting) {
lazyLoadDisqusJS();
disqus_observer.disconnect();
}
});
disqus_observer.observe(document.getElementById('disqus_thread'));
} else {
lazyLoadDisqusJS();
}
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
</div>
{{- end -}}
@@ -0,0 +1,49 @@
{{- with .Site.Params.comments.giscus -}}
<script
src="https://giscus.app/client.js"
data-repo="{{- .repo -}}"
data-repo-id="{{- .repoID -}}"
data-category="{{- .category -}}"
data-category-id="{{- .categoryID -}}"
data-mapping="{{- default `title` .mapping -}}"
data-reactions-enabled="{{- default 1 .reactionsEnabled -}}"
data-emit-metadata="{{- default 0 .emitMetadata -}}"
data-theme="{{- default `light` .lightTheme -}}"
crossorigin="anonymous"
async
></script>
<script>
function setGiscusTheme(theme) {
let giscus = document.querySelector('iframe.giscus-frame');
if (giscus) {
giscus.contentWindow.postMessage(
{
giscus: {
setConfig: {
theme: theme
}
}
},
"https://giscus.app"
);
};
};
(function(){
addEventListener('message', (e) => {
if (event.origin !== 'https://giscus.app') return;
handler()
});
window.addEventListener('onColorSchemeChange', handler);
function handler() {
if (document.documentElement.dataset.scheme === "light") {
setGiscusTheme('{{- default "light" .lightTheme -}}');
} else {
setGiscusTheme('{{- default "dark_dimmed" .darkTheme -}}');
};
};
}());
</script>
{{- end -}}
@@ -0,0 +1,30 @@
{{- with .Site.Params.comments.gitalk -}}
<div id="gitalk-container"></div>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/gitalk@1.7.2/dist/gitalk.css"
/>
<script src="https://cdn.jsdelivr.net/npm/gitalk@1.7.2/dist/gitalk.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/blueimp-md5@2.18.0/js/md5.min.js"></script>
<script>
const gitalk = new Gitalk({
clientID: "{{- .clientID -}}",
clientSecret: "{{- .clientSecret -}}",
repo: "{{- .repo -}}",
owner: "{{- .owner -}}",
admin: ["{{- .admin -}}"],
distractionFreeMode: false, // Facebook-like distraction free mode
id: md5(location.pathname), // Max Location.pathname Legth:75 https://github.com/gitalk/gitalk/issues/102
});
(function () {
if (
["localhost", "127.0.0.1"].indexOf(window.location.hostname) != -1
) {
document.getElementById("gitalk-container").innerHTML =
"Gitalk comments not available by default when the website is previewed locally.";
return;
}
gitalk.render("gitalk-container");
})();
</script>
{{ end }}
@@ -0,0 +1,49 @@
<script src="//cdn.jsdelivr.net/npm/twikoo@1.4.15/dist/twikoo.all.min.js"></script>
<div id="tcomment"></div>
<style>
.twikoo {
background-color: var(--card-background);
border-radius: var(--card-border-radius);
box-shadow: var(--shadow-l1);
padding: var(--card-padding);
}
:root[data-scheme="dark"] {
--twikoo-body-text-color-main: rgba(255, 255, 255, 0.9);
--twikoo-body-text-color: rgba(255, 255, 255, 0.7);
}
.twikoo .el-input-group__prepend,
.twikoo .tk-action-icon,
.twikoo .tk-time,
.twikoo .tk-comments-count {
color: var(--twikoo-body-text-color);
}
.twikoo .el-input__inner,
.twikoo .el-textarea__inner,
.twikoo .tk-preview-container,
.twikoo .tk-content,
.twikoo .tk-nick,
.twikoo .tk-send {
color: var(--twikoo-body-text-color-main);
}
.twikoo .el-button{
color: var(--twikoo-body-text-color)!important;
}
</style>
{{- with .Site.Params.comments.twikoo -}}
<script>
twikoo.init({
envId: '{{- .envId -}}',
el: '#tcomment',
{{- with .region -}}
region: '{{- . -}}',
{{- end -}}
{{- with .path -}}
path: '{{- . -}}',
{{- end -}}
{{- with .lang -}}
lang: '{{- . -}}',
{{- end -}}
})
</script>
{{- end -}}
@@ -3,4 +3,10 @@
{{- $opts := dict "minify" hugo.IsProduction -}}
{{- $script := resources.Get "ts/main.ts" | js.Build $opts -}}
<script type="text/javascript" src="{{ $script.RelPermalink }}" defer></script>
<script type="text/javascript" src="{{ $script.RelPermalink }}" defer></script>
{{- with resources.Get "ts/custom.ts" -}}
{{/* Place your custom script in HUGO_SITE_FOLDER/assets/ts/custom.ts */}}
{{- $customScript := . | js.Build $opts -}}
<script type="text/javascript" src="{{ $customScript.RelPermalink }}" defer></script>
{{- end -}}
+2 -2
View File
@@ -1,4 +1,4 @@
{{- $ThemeVersion := "2.5.0" -}}
{{- $ThemeVersion := "3.8.0" -}}
<footer class="site-footer">
<section class="copyright">
&copy;
@@ -20,4 +20,4 @@
{{ T "footer.builtWith" (dict "Generator" $Generator) | safeHTML }} <br />
{{ T "footer.designedBy" (dict "Theme" $Theme "DesignedBy" $DesignedBy) | safeHTML }}
</section>
</footer>
</footer>
+1 -1
View File
@@ -1,3 +1,3 @@
{{ $sass := resources.Get "scss/style.scss" }}
{{ $style := $sass | resources.ToCSS | minify }}
{{ $style := $sass | resources.ToCSS | minify | resources.Fingerprint "sha256" }}
<link rel="stylesheet" href="{{ $style.RelPermalink }}">
+1 -1
View File
@@ -8,7 +8,7 @@
integrity="{{ . }}"
{{- end -}}
crossorigin="anonymous"
defer="{{ default false .defer }}"
{{ if .defer }}defer{{ end }}
>
</script>
{{- else if eq .type "style" -}}
+31 -4
View File
@@ -7,7 +7,9 @@
<header class="site-info">
{{ with .Site.Params.sidebar.avatar }}
{{ if (default true .enabled) }}
<figure class="site-avatar">
<a href="{{ .Site.BaseURL | relLangURL }}">
{{ if not .local }}
<img src="{{ .src }}" width="300" height="300" class="site-logo" loading="lazy" alt="Avatar">
{{ else }}
@@ -21,14 +23,35 @@
{{ errorf "Failed loading avatar from %q" . }}
{{ end }}
{{ end }}
</a>
{{ with $.Site.Params.sidebar.emoji }}
<span class="emoji">{{ . }}</span>
{{ end }}
</figure>
{{ end }}
{{ end }}
<h1 class="site-name"><a href="{{ .Site.BaseURL }}">{{ .Site.Title }}</a></h1>
<h1 class="site-name"><a href="{{ .Site.BaseURL | relLangURL }}">{{ .Site.Title }}</a></h1>
<h2 class="site-description">{{ .Site.Params.sidebar.subtitle }}</h2>
{{- with .Site.Menus.social -}}
<ol class="social-menu">
{{ range . }}
<li>
<a
href='{{ .URL }}'
{{ if eq (default true .Params.newTab) true }}target="_blank"{{ end }}
{{ with .Name }}title="{{ . }}"{{ end }}
>
{{ $icon := default "link" .Params.Icon }}
{{ with $icon }}
{{ partial "helper/icon" . }}
{{ end }}
</a>
</li>
{{ end }}
</ol>
{{- end -}}
</header>
<ol class="menu" id="main-menu">
@@ -37,9 +60,13 @@
{{ $active := or (eq $currentPage.Title .Name) (or ($currentPage.HasMenuCurrent "main" .) ($currentPage.IsMenuCurrent "main" .)) }}
<li {{ if $active }} class='current' {{ end }}>
<a href='{{ .URL }}'>
<a href='{{ .URL | relLangURL }}' {{ if eq .Params.newTab true }}target="_blank"{{ end }}>
{{ $icon := default .Pre .Params.Icon }}
{{ if .Pre }}
{{ partial "helper/icon" .Pre }}
{{ warnf "Menu item [%s] is using [pre] field to set icon, please use [params.icon] instead.\nMore information: https://docs.stack.jimmycai.com/configuration/custom-menu.html" .URL }}
{{ end }}
{{ with $icon }}
{{ partial "helper/icon" . }}
{{ end }}
<span>{{- .Name -}}</span>
</a>
+1 -1
View File
@@ -13,7 +13,7 @@
{{ end }}
<div class="video-wrapper">
<iframe src="//player.bilibili.com/player.html?{{ $basicQuery | safeURL }}&{{ $videoQuery | safeURL }}"
<iframe src="https://player.bilibili.com/player.html?{{ $basicQuery | safeURL }}&{{ $videoQuery | safeURL }}"
scrolling="no"
frameborder="no"
framespacing="0"
+1 -1
View File
@@ -1,6 +1,6 @@
{{ $vid := .Get 0 }}
<div class="video-wrapper">
<iframe src="http://v.qq.com/txp/iframe/player.html?vid={{ $vid }}&auto=0"
<iframe src="https://v.qq.com/txp/iframe/player.html?vid={{ $vid }}&auto=0"
scrolling="no"
frameborder="no"
framespacing="0"
+14
View File
@@ -0,0 +1,14 @@
{{- $src := .Get "src" | default (.Get 0) -}}
<div class="video-wrapper">
<video
controls
src="{{- $src -}}"
{{ with .Get "poster" }}poster="{{- . -}}"{{ end }}
{{ with .Get "autoplay" }}autoplay{{ end }}
>
<p>
Your browser doesn't support HTML5 video. Here is a
<a href="{{- $src -}}">link to the video</a> instead.
</p>
</video>
</div>
+1 -1
View File
@@ -2,7 +2,7 @@
publish = "exampleSite/public"
[build.environment]
HUGO_VERSION = "0.85.0"
HUGO_VERSION = "0.87.0"
HUGO_THEME = "repo"
[context.production]
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
{"Target":"scss/style.min.css","MediaType":"text/css","Data":{}}
+2 -2
View File
@@ -6,7 +6,7 @@ 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://github.com/CaiJimmy/hugo-theme-stack"
demosite = "https://theme-stack.jimmycai.com"
demosite = "https://demo.stack.jimmycai.com"
tags = ["blog", "responsive", "clean", "light", "dark", "personal"]
@@ -20,7 +20,7 @@ features = [
"search",
]
min_version = "0.78.0"
min_version = "0.87.0"
[author]
name = "Jimmy Cai"