mirror of
https://github.com/cotes2020/jekyll-theme-chirpy.git
synced 2025-12-18 13:44:15 +00:00
Compare commits
215 Commits
v6.3.1
...
9706811c3a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9706811c3a | ||
|
|
a4812e4a1f | ||
|
|
65f960c31a | ||
|
|
d51345e297 | ||
|
|
2f844978aa | ||
|
|
42dea8ee29 | ||
|
|
81d3d055e4 | ||
|
|
86b13c917f | ||
|
|
4ef3cd8efc | ||
|
|
c7f967529c | ||
|
|
74ed06321c | ||
|
|
d4f7f39ece | ||
|
|
c1bd9eb9ee | ||
|
|
6f461132c0 | ||
|
|
03e302cbf6 | ||
|
|
8a064a5e5a | ||
|
|
740bd84c51 | ||
|
|
93f616b25d | ||
|
|
e6b87d2811 | ||
|
|
73749067c5 | ||
|
|
fd0df8320f | ||
|
|
fbcdf8ce85 | ||
|
|
fac6116af1 | ||
|
|
5a63244721 | ||
|
|
3ab3b844d2 | ||
|
|
367262e74d | ||
|
|
cbc93193e1 | ||
|
|
a784f0a0f9 | ||
|
|
a2bf5dc58e | ||
|
|
8b7dba71e3 | ||
|
|
fc3d101258 | ||
|
|
604e01eb36 | ||
|
|
31e19c6d0f | ||
|
|
5f4dab1745 | ||
|
|
8cfd721494 | ||
|
|
64c7262245 | ||
|
|
707a209424 | ||
|
|
80bd7928a0 | ||
|
|
befc4ce9c5 | ||
|
|
bf6c996c4e | ||
|
|
99eaf6089e | ||
|
|
efd2941ce0 | ||
|
|
7f83c3d00d | ||
|
|
d74bfaeda2 | ||
|
|
23729c9c8f | ||
|
|
e347d0632f | ||
|
|
35fdea0c4f | ||
|
|
5c5910f1fc | ||
|
|
b641b36480 | ||
|
|
979f86cf64 | ||
|
|
8c30f0a9c3 | ||
|
|
e4db1a176f | ||
|
|
e3a78b6243 | ||
|
|
8673e1335f | ||
|
|
a07a57ec92 | ||
|
|
db9e58bab2 | ||
|
|
e6532ad864 | ||
|
|
fbba0a4204 | ||
|
|
c876731901 | ||
|
|
9ca7519239 | ||
|
|
0709854dc8 | ||
|
|
f1d35832f4 | ||
|
|
cf853f14e4 | ||
|
|
7ca9c59784 | ||
|
|
250880c088 | ||
|
|
88b844ce80 | ||
|
|
3b46629dc0 | ||
|
|
1e3d4a6323 | ||
|
|
1c5fa0880d | ||
|
|
64ae7a3671 | ||
|
|
0102abae06 | ||
|
|
6cb1a5ac52 | ||
|
|
20987f2afe | ||
|
|
39e4338839 | ||
|
|
33a1fa7cae | ||
|
|
00a27a1b85 | ||
|
|
5cdde7dbc5 | ||
|
|
c4b58e3502 | ||
|
|
9630fd647f | ||
|
|
90a4cc76bb | ||
|
|
e33547fe5d | ||
|
|
09b300bc62 | ||
|
|
9ffd997c3b | ||
|
|
37827d81e5 | ||
|
|
febc01db52 | ||
|
|
b2245492e6 | ||
|
|
f87fdd0ea0 | ||
|
|
fdbd7f02e3 | ||
|
|
75891e714f | ||
|
|
363a3d936b | ||
|
|
ddb48eda52 | ||
|
|
c17fba44f5 | ||
|
|
12c340e98b | ||
|
|
dcb0add47b | ||
|
|
f1c6d2a817 | ||
|
|
05ebfb705e | ||
|
|
8608147fb5 | ||
|
|
76d58fe0ff | ||
|
|
b77767f76e | ||
|
|
e0950fc973 | ||
|
|
778ebdf250 | ||
|
|
796c386037 | ||
|
|
72d93b132f | ||
|
|
e09831ba3e | ||
|
|
05e3689d17 | ||
|
|
d4a6d640bd | ||
|
|
2cfa54847a | ||
|
|
cd37f63a01 | ||
|
|
015d5670a1 | ||
|
|
63c51384df | ||
|
|
662cd331e3 | ||
|
|
d013c11c8d | ||
|
|
fe7afa379f | ||
|
|
c85e9e2394 | ||
|
|
bf16d6039a | ||
|
|
8c1be9f2f3 | ||
|
|
7808ee157c | ||
|
|
1914c786a0 | ||
|
|
44f552cbce | ||
|
|
7d48d32c7b | ||
|
|
9f8aeaadbf | ||
|
|
61bdca2db4 | ||
|
|
23be4162b3 | ||
|
|
01076cb1c2 | ||
|
|
3cc1510071 | ||
|
|
950839175a | ||
|
|
13bf51e03d | ||
|
|
ce96d7e251 | ||
|
|
7a7818b579 | ||
|
|
cef8a97384 | ||
|
|
2d649aae0e | ||
|
|
b7aa05d03a | ||
|
|
c5d5e1f75a | ||
|
|
319a082940 | ||
|
|
6044df4ff1 | ||
|
|
e5594525e7 | ||
|
|
e15eaaffe0 | ||
|
|
74cf57aaac | ||
|
|
cfe44f204b | ||
|
|
700fd5bad7 | ||
|
|
8e5fbb7a74 | ||
|
|
834931486d | ||
|
|
f865336c89 | ||
|
|
0f8e782bfd | ||
|
|
0a6c1fb251 | ||
|
|
75a3d7399b | ||
|
|
547b95cc7a | ||
|
|
2a7b56bb36 | ||
|
|
25c4166722 | ||
|
|
25b2ffa9ba | ||
|
|
8a2afae6ca | ||
|
|
6112b15b8e | ||
|
|
e24a0c73ba | ||
|
|
0f5abc82a2 | ||
|
|
795ff3f4c3 | ||
|
|
c41672b2e0 | ||
|
|
9cc62e703f | ||
|
|
19d6bafbe1 | ||
|
|
4ddd5c4370 | ||
|
|
9592146ca3 | ||
|
|
8a1568c27a | ||
|
|
388c1511d6 | ||
|
|
8849afe5cf | ||
|
|
f8390d4384 | ||
|
|
e4363871b5 | ||
|
|
b641b3f1f2 | ||
|
|
5dbda0c09f | ||
|
|
89b962557a | ||
|
|
5de0153df4 | ||
|
|
ed4d304cd2 | ||
|
|
48564bda8d | ||
|
|
b9d053b3cd | ||
|
|
cd258c92c3 | ||
|
|
6230d1d750 | ||
|
|
365abc6b3b | ||
|
|
79c65b3e44 | ||
|
|
6b34901d94 | ||
|
|
90693ff95e | ||
|
|
1a01c35e52 | ||
|
|
c335bc6ce7 | ||
|
|
f3ea7e9887 | ||
|
|
c13ec31163 | ||
|
|
bbbb66b489 | ||
|
|
74f16623c9 | ||
|
|
1127c43823 | ||
|
|
ea3a22e13c | ||
|
|
c0018b66f3 | ||
|
|
02e296ed75 | ||
|
|
4facf5b390 | ||
|
|
c5d11441bc | ||
|
|
96bdd7c1dd | ||
|
|
ba764c1380 | ||
|
|
c7cfde0930 | ||
|
|
13177979bb | ||
|
|
6a17a7d46c | ||
|
|
8c30b41e20 | ||
|
|
b2d1cb68db | ||
|
|
3589a6ee53 | ||
|
|
7efbed6a24 | ||
|
|
21d74f1183 | ||
|
|
d6d0098379 | ||
|
|
241bb4df78 | ||
|
|
82d8f2db98 | ||
|
|
9882244bd9 | ||
|
|
f243cbd858 | ||
|
|
d420b38329 | ||
|
|
ea2d238bd8 | ||
|
|
5234511a2f | ||
|
|
746a31e125 | ||
|
|
c45e031155 | ||
|
|
4a2b89d0b6 | ||
|
|
2a4fbf6a79 | ||
|
|
84ea68cab0 | ||
|
|
3ed5eb1ee0 | ||
|
|
d1a5b57e4d |
29
.devcontainer/devcontainer.json
Normal file
29
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "Jekyll",
|
||||
"image": "mcr.microsoft.com/devcontainers/jekyll:2-bullseye",
|
||||
"onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
|
||||
"postCreateCommand": "bash .devcontainer/post-create.sh",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"settings": {
|
||||
"terminal.integrated.defaultProfile.linux": "zsh"
|
||||
},
|
||||
"extensions": [
|
||||
// Liquid tags auto-complete
|
||||
"killalau.vscode-liquid-snippets",
|
||||
// Liquid syntax highlighting and formatting
|
||||
"Shopify.theme-check-vscode",
|
||||
// Shell
|
||||
"timonwong.shellcheck",
|
||||
"mkhl.shfmt",
|
||||
// Common formatter
|
||||
"EditorConfig.EditorConfig",
|
||||
"esbenp.prettier-vscode",
|
||||
"stylelint.vscode-stylelint",
|
||||
"yzhang.markdown-all-in-one",
|
||||
// Git
|
||||
"mhutchie.git-graph"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
18
.devcontainer/post-create.sh
Normal file
18
.devcontainer/post-create.sh
Normal file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [ -f package.json ]; then
|
||||
bash -i -c "nvm install --lts && nvm install-latest-npm"
|
||||
npm i
|
||||
npm run build
|
||||
fi
|
||||
|
||||
# Install dependencies for shfmt extension
|
||||
curl -sS https://webi.sh/shfmt | sh &>/dev/null
|
||||
|
||||
# Add OMZ plugins
|
||||
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ~/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting
|
||||
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.oh-my-zsh/custom/plugins/zsh-autosuggestions
|
||||
sed -i -E "s/^(plugins=\()(git)(\))/\1\2 zsh-syntax-highlighting zsh-autosuggestions\3/" ~/.zshrc
|
||||
|
||||
# Avoid git log use less
|
||||
echo -e "\nunset LESS" >>~/.zshrc
|
||||
9
.github/DISCUSSION_TEMPLATE/general.yml
vendored
9
.github/DISCUSSION_TEMPLATE/general.yml
vendored
@@ -9,15 +9,6 @@ body:
|
||||
[contributing guidelines](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md).
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: What is the topic?
|
||||
options:
|
||||
- Sharing tips and tricks
|
||||
- Just chatting
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
|
||||
7
.github/DISCUSSION_TEMPLATE/ideas.yml
vendored
Normal file
7
.github/DISCUSSION_TEMPLATE/ideas.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: Please describe in detail what you want to share.
|
||||
validations:
|
||||
required: true
|
||||
2
.github/codeql/codeql-config.yml
vendored
Normal file
2
.github/codeql/codeql-config.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
paths-ignore:
|
||||
- "assets/js"
|
||||
20
.github/dependabot.yml
vendored
20
.github/dependabot.yml
vendored
@@ -2,20 +2,18 @@ version: 2
|
||||
updates:
|
||||
- package-ecosystem: "bundler"
|
||||
directory: "/"
|
||||
versioning-strategy: increase
|
||||
groups:
|
||||
bundler:
|
||||
dependency-type: "production"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
versioning-strategy: increase
|
||||
groups:
|
||||
npm:
|
||||
dependency-type: "development"
|
||||
prod-deps:
|
||||
dependency-type: production
|
||||
dev-deps:
|
||||
dependency-type: development
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
groups:
|
||||
@@ -23,4 +21,8 @@ updates:
|
||||
update-types:
|
||||
- "major"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "devcontainers"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
|
||||
42
.github/workflows/cd.yml
vendored
42
.github/workflows/cd.yml
vendored
@@ -1,17 +1,39 @@
|
||||
name: CD
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||
branches:
|
||||
- docs
|
||||
branches: [production]
|
||||
tags-ignore: ["**"]
|
||||
|
||||
jobs:
|
||||
launch:
|
||||
release:
|
||||
if: ${{ ! startsWith(github.event.head_commit.message, 'chore(release)') }}
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
curl -X POST -H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.GH_PAT }}" \
|
||||
https://api.github.com/repos/${{ secrets.BUILDER }}/dispatches \
|
||||
-d '{"event_type":"deploy", "client_payload":{"branch": "${{ github.ref_name }}"}}'
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3.3
|
||||
bundler-cache: true
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
- run: npm install
|
||||
- run: npx semantic-release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GEM_HOST_API_KEY: ${{ secrets.GEM_HOST_API_KEY }}
|
||||
|
||||
publish:
|
||||
needs: release
|
||||
uses: ./.github/workflows/publish.yml
|
||||
secrets:
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
BUILDER: ${{ secrets.BUILDER }}
|
||||
|
||||
34
.github/workflows/ci.yml
vendored
34
.github/workflows/ci.yml
vendored
@@ -1,24 +1,34 @@
|
||||
name: "CI"
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- "production"
|
||||
- "docs"
|
||||
branches:
|
||||
- master
|
||||
- "hotfix/*"
|
||||
paths-ignore:
|
||||
- ".github/**"
|
||||
- "!.github/workflows/ci.yml"
|
||||
- ".gitignore"
|
||||
- .gitignore
|
||||
- "docs/**"
|
||||
- "README.md"
|
||||
- "LICENSE"
|
||||
- README.md
|
||||
- LICENSE
|
||||
pull_request:
|
||||
paths:
|
||||
- "**"
|
||||
paths-ignore:
|
||||
- ".github/**"
|
||||
- "!.github/workflows/ci.yml"
|
||||
- .gitignore
|
||||
- "docs/**"
|
||||
- README.md
|
||||
- LICENSE
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
ruby: ["3.1", "3.2", "3.3"]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
@@ -28,14 +38,16 @@ jobs:
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3
|
||||
ruby-version: ${{ matrix.ruby }}
|
||||
bundler-cache: true
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
- name: Build Assets
|
||||
run: npm i && npm run build
|
||||
|
||||
- name: Test Site
|
||||
run: bash tools/test
|
||||
run: bash tools/test.sh
|
||||
|
||||
14
.github/workflows/codeql.yml
vendored
14
.github/workflows/codeql.yml
vendored
@@ -2,11 +2,10 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
paths: ["**.js"]
|
||||
branches: ["master"]
|
||||
paths: ["_javascript/**/*.js"]
|
||||
pull_request:
|
||||
paths: ["**.js"]
|
||||
schedule:
|
||||
- cron: "0 0 * * 5"
|
||||
paths: ["_javascript/**/*.js"]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
@@ -29,16 +28,17 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: "${{ matrix.language }}"
|
||||
config-file: .github/codeql/codeql-config.yml
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
|
||||
12
.github/workflows/commitlint.yml
vendored
12
.github/workflows/commitlint.yml
vendored
@@ -1,11 +1,15 @@
|
||||
name: Lint Commit Messages
|
||||
on: pull_request
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- "hotfix/*"
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
commitlint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: wagoid/commitlint-github-action@v5
|
||||
- uses: wagoid/commitlint-github-action@v6
|
||||
|
||||
25
.github/workflows/pr-filter.yml
vendored
Normal file
25
.github/workflows/pr-filter.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: PR Filter
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened]
|
||||
|
||||
jobs:
|
||||
check-template:
|
||||
if: github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check PR Content
|
||||
id: intercept
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const script = require('.github/workflows/scripts/pr-filter.js');
|
||||
await script({ github, context, core });
|
||||
23
.github/workflows/publish.yml
vendored
Normal file
23
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- docs
|
||||
workflow_call:
|
||||
secrets:
|
||||
GH_PAT:
|
||||
required: true
|
||||
BUILDER:
|
||||
required: true
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
launch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
curl -X POST -H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${{ secrets.GH_PAT }}" \
|
||||
https://api.github.com/repos/${{ secrets.BUILDER }}/dispatches \
|
||||
-d '{"event_type":"deploy", "client_payload":{"branch": "${{ github.ref_name }}"}}'
|
||||
36
.github/workflows/scripts/pr-filter.js
vendored
Normal file
36
.github/workflows/scripts/pr-filter.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
function hasTypes(markdown) {
|
||||
return /## Type of change/.test(markdown) && /-\s\[x\]/i.test(markdown);
|
||||
}
|
||||
|
||||
function hasDescription(markdown) {
|
||||
return (
|
||||
/## Description/.test(markdown) &&
|
||||
!/## Description\s*\n\s*(##|\s*$)/.test(markdown)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = async ({ github, context, core }) => {
|
||||
const pr = context.payload.pull_request;
|
||||
const body = pr.body === null ? '' : pr.body;
|
||||
const markdown = body.replace(/<!--[\s\S]*?-->/g, '');
|
||||
const action = context.payload.action;
|
||||
|
||||
const isValid =
|
||||
markdown !== '' && hasTypes(markdown) && hasDescription(markdown);
|
||||
|
||||
if (!isValid) {
|
||||
await github.rest.pulls.update({
|
||||
...context.repo,
|
||||
pull_number: pr.number,
|
||||
state: 'closed'
|
||||
});
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: pr.number,
|
||||
body: `Oops, it seems you've ${action} an invalid pull request. No worries, we'll close it for you.`
|
||||
});
|
||||
|
||||
core.setFailed('PR content does not meet template requirements.');
|
||||
}
|
||||
};
|
||||
32
.github/workflows/stale.yml
vendored
32
.github/workflows/stale.yml
vendored
@@ -8,23 +8,25 @@ permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
STALE_LABEL: inactive
|
||||
EXEMPT_LABELS: "pending,planning,in progress"
|
||||
MESSAGE: >
|
||||
This conversation has been automatically marked as stale because it has not had recent activity.
|
||||
It will be closed if no further activity occurs.
|
||||
Thank you for your contributions.
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v8
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-stale: 30
|
||||
days-before-close: 1
|
||||
stale-issue-label: stale
|
||||
exempt-issue-labels: pending
|
||||
stale-issue-message: >
|
||||
This issue has been automatically marked as stale because it has not had recent activity.
|
||||
It will be closed if no further activity occurs.
|
||||
Thank you for your contributions.
|
||||
stale-pr-label: stale
|
||||
exempt-pr-labels: pending
|
||||
stale-pr-message: >
|
||||
This PR has been automatically marked as stale because it has not had recent activity.
|
||||
It will be closed if no further activity occurs.
|
||||
Thank you for your contributions.
|
||||
# 60 days before marking issues/PRs stale
|
||||
days-before-close: -1 # does not close automatically
|
||||
stale-issue-label: ${{ env.STALE_LABEL }}
|
||||
exempt-issue-labels: ${{ env.EXEMPT_LABELS }}
|
||||
stale-issue-message: ${{ env.MESSAGE }}
|
||||
stale-pr-label: ${{ env.STALE_LABEL }}
|
||||
exempt-pr-labels: ${{ env.EXEMPT_LABELS }}
|
||||
stale-pr-message: ${{ env.MESSAGE }}
|
||||
|
||||
@@ -37,12 +37,12 @@ jobs:
|
||||
|
||||
- name: Setup Pages
|
||||
id: pages
|
||||
uses: actions/configure-pages@v3
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Setup Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 3
|
||||
ruby-version: 3.3
|
||||
bundler-cache: true
|
||||
|
||||
- name: Build site
|
||||
@@ -53,11 +53,11 @@ jobs:
|
||||
- name: Test site
|
||||
run: |
|
||||
bundle exec htmlproofer _site \
|
||||
\-\-disable-external=true \
|
||||
\-\-disable-external \
|
||||
\-\-ignore-urls "/^http:\/\/127.0.0.1/,/^http:\/\/0.0.0.0/,/^http:\/\/localhost/"
|
||||
|
||||
- name: Upload site artifact
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: "_site${{ steps.pages.outputs.base_path }}"
|
||||
|
||||
@@ -70,4 +70,4 @@ jobs:
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v2
|
||||
uses: actions/deploy-pages@v4
|
||||
16
.github/workflows/style-lint.yml
vendored
16
.github/workflows/style-lint.yml
vendored
@@ -1,15 +1,13 @@
|
||||
name: "Style Lint"
|
||||
name: Style Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
- "production"
|
||||
- "docs"
|
||||
paths:
|
||||
- "_sass/**/*.scss"
|
||||
branches:
|
||||
- master
|
||||
- "hotfix/*"
|
||||
paths: ["_sass/**/*.scss"]
|
||||
pull_request:
|
||||
paths:
|
||||
- "_sass/**/*.scss"
|
||||
paths: ["_sass/**/*.scss"]
|
||||
|
||||
jobs:
|
||||
stylelint:
|
||||
@@ -21,5 +19,7 @@ jobs:
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
- run: npm i
|
||||
- run: npm test
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -5,6 +5,7 @@ Gemfile.lock
|
||||
|
||||
# Jekyll cache
|
||||
.jekyll-cache
|
||||
.jekyll-metadata
|
||||
_site
|
||||
|
||||
# RubyGems
|
||||
@@ -16,7 +17,11 @@ package-lock.json
|
||||
|
||||
# IDE configurations
|
||||
.idea
|
||||
.vscode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/tasks.json
|
||||
|
||||
# Misc
|
||||
_sass/dist
|
||||
assets/js/dist
|
||||
|
||||
5
.husky/commit-msg
Executable file → Normal file
5
.husky/commit-msg
Executable file → Normal file
@@ -1,4 +1 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no -- commitlint -x $(npm root -g)/@commitlint/config-conventional --edit
|
||||
npx --no -- commitlint --edit $1
|
||||
|
||||
8
.markdownlint.json
Normal file
8
.markdownlint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"commands-show-output": false,
|
||||
"blanks-around-fences": false,
|
||||
"line-length": false,
|
||||
"no-inline-html": {
|
||||
"allowed_elements": ["kbd", "sub"]
|
||||
}
|
||||
}
|
||||
3
.vscode/extensions.json
vendored
Normal file
3
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"recommendations": ["ms-vscode-remote.remote-containers"]
|
||||
}
|
||||
30
.vscode/settings.json
vendored
Normal file
30
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
// Prettier
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
// Shopify Liquid
|
||||
"files.associations": {
|
||||
"*.html": "liquid"
|
||||
},
|
||||
"[markdown]": {
|
||||
"editor.defaultFormatter": "yzhang.markdown-all-in-one"
|
||||
},
|
||||
// Formatter
|
||||
"[html][liquid]": {
|
||||
"editor.defaultFormatter": "Shopify.theme-check-vscode"
|
||||
},
|
||||
"[shellscript]": {
|
||||
"editor.defaultFormatter": "mkhl.shfmt"
|
||||
},
|
||||
// Disable vscode built-in stylelint
|
||||
"css.validate": false,
|
||||
"scss.validate": false,
|
||||
"less.validate": false,
|
||||
// Stylint extension settings
|
||||
"stylelint.snippet": ["css", "scss"],
|
||||
"stylelint.validate": ["css", "scss"],
|
||||
// Run tasks in macOS
|
||||
"terminal.integrated.profiles.osx": {
|
||||
"zsh": { "path": "/bin/zsh", "args": ["-l", "-i"] }
|
||||
}
|
||||
}
|
||||
64
.vscode/tasks.json
vendored
Normal file
64
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Run Jekyll Server",
|
||||
"type": "shell",
|
||||
"command": "./tools/run.sh",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Runs the Jekyll server with live reload."
|
||||
},
|
||||
{
|
||||
"label": "Build Jekyll Site",
|
||||
"type": "shell",
|
||||
"command": "./tools/test.sh",
|
||||
"group": {
|
||||
"kind": "build"
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Build the Jekyll site for production."
|
||||
},
|
||||
{
|
||||
"label": "Build JS (watch)",
|
||||
"type": "shell",
|
||||
"command": "npm run watch:js",
|
||||
"group": {
|
||||
"kind": "build"
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Build JS files in watch mode."
|
||||
},
|
||||
{
|
||||
"label": "Build CSS",
|
||||
"type": "shell",
|
||||
"command": "npm run build:css",
|
||||
"group": {
|
||||
"kind": "build"
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Build CSS files."
|
||||
},
|
||||
{
|
||||
"label": "Build JS & CSS",
|
||||
"type": "shell",
|
||||
"command": "npm run build",
|
||||
"group": {
|
||||
"kind": "build"
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"detail": "Build JS & CSS for production."
|
||||
},
|
||||
{
|
||||
"label": "Run Jekyll Server + Build JS (watch)",
|
||||
"dependsOn": ["Run Jekyll Server", "Build JS (watch)"],
|
||||
"group": {
|
||||
"kind": "build"
|
||||
},
|
||||
"detail": "Runs both the Jekyll server with live reload and build JS files in watch mode."
|
||||
}
|
||||
]
|
||||
}
|
||||
13
Gemfile
13
Gemfile
@@ -4,20 +4,11 @@ source "https://rubygems.org"
|
||||
|
||||
gemspec
|
||||
|
||||
group :test do
|
||||
gem "html-proofer", "~> 4.4"
|
||||
end
|
||||
gem "html-proofer", "~> 5.0", group: :test
|
||||
|
||||
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
|
||||
# and associated library.
|
||||
platforms :mingw, :x64_mingw, :mswin, :jruby do
|
||||
gem "tzinfo", ">= 1", "< 3"
|
||||
gem "tzinfo-data"
|
||||
end
|
||||
|
||||
# Performance-booster for watching directories on Windows
|
||||
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
|
||||
|
||||
# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
|
||||
# do not have a Java counterpart.
|
||||
gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
|
||||
gem "wdm", "~> 0.2.0", :platforms => [:mingw, :x64_mingw, :mswin]
|
||||
|
||||
56
README.md
56
README.md
@@ -1,16 +1,18 @@
|
||||
<!-- markdownlint-disable-next-line -->
|
||||
<div align="center">
|
||||
|
||||
<!-- markdownlint-disable-next-line -->
|
||||
# Chirpy Jekyll Theme
|
||||
|
||||
A minimal, responsive, and feature-rich Jekyll theme for technical writing.
|
||||
|
||||
[][gem]
|
||||
[][ci]
|
||||
[][codacy]
|
||||
[][license]
|
||||
[](https://996.icu)
|
||||
[][ci]
|
||||
[][codacy]
|
||||
[][license]
|
||||
[][gem]
|
||||
[][open-container]
|
||||
|
||||
[**Live Demo →**][demo]
|
||||
[**Live Demo** →][demo]
|
||||
|
||||
[][demo]
|
||||
|
||||
@@ -18,11 +20,7 @@
|
||||
|
||||
## Features
|
||||
|
||||
<details>
|
||||
<summary>Click to expand/close details</summary>
|
||||
|
||||
|
||||
- Dark / Light Theme Mode
|
||||
- Dark Theme
|
||||
- Localized UI language
|
||||
- Pinned Posts on Home Page
|
||||
- Hierarchical Categories
|
||||
@@ -32,17 +30,15 @@
|
||||
- Syntax Highlighting
|
||||
- Mathematical Expressions
|
||||
- Mermaid Diagrams & Flowcharts
|
||||
- Dark / Light Mode Images
|
||||
- Embed Videos
|
||||
- Disqus / Giscus / Utterances Comments
|
||||
- Dark Mode Images
|
||||
- Embed Media
|
||||
- Comment Systems
|
||||
- Built-in Search
|
||||
- Atom Feeds
|
||||
- PWA
|
||||
- Google Analytics
|
||||
- Web Analytics
|
||||
- SEO & Performance Optimization
|
||||
|
||||
</details>
|
||||
|
||||
## Documentation
|
||||
|
||||
To learn how to use, develop, and upgrade the project, please refer to the [Wiki][wiki].
|
||||
@@ -55,22 +51,18 @@ For details, see the "[Contributing Guidelines][contribute-guide]".
|
||||
|
||||
## Credits
|
||||
|
||||
This project was built primarily with the [Jekyll][jekyllrb] ecosystem,
|
||||
[Bootstrap][bootstrap], [Font Awesome][icons], and some other [wonderful tools][lib].
|
||||
The avatar and favicon design from [Clipart Max][image].
|
||||
### Contributors
|
||||
|
||||
Many thanks to the [contributors][contributors] who participated in the development
|
||||
and to the folks who reported bugs or shared ideas.
|
||||
Thanks to [all the contributors][contributors] involved in the development of the project!
|
||||
|
||||
Last but not least, thanks to [JetBrains][jetbrains] for providing the _Open Source License_.
|
||||
[][contributors]
|
||||
<sub> — Made with [contrib.rocks](https://contrib.rocks)</sub>
|
||||
|
||||
## Sponsoring
|
||||
### Third-Party Assets
|
||||
|
||||
If you like this project or have built something through it, please consider sponsoring it, and your support would be greatly appreciated.
|
||||
This project is built on the [Jekyll][jekyllrb] ecosystem and some [great libraries][lib], and is developed using [VS Code][vscode] as well as tools provided by [JetBrains][jetbrains] under a non-commercial open-source software license.
|
||||
|
||||
[][ko-fi]
|
||||
[][donation]
|
||||
[][donation]
|
||||
The avatar and favicon for the project's website are from [ClipartMAX][clipartmax].
|
||||
|
||||
## License
|
||||
|
||||
@@ -80,15 +72,13 @@ This project is published under [MIT License][license].
|
||||
[ci]: https://github.com/cotes2020/jekyll-theme-chirpy/actions/workflows/ci.yml?query=event%3Apush+branch%3Amaster
|
||||
[codacy]: https://app.codacy.com/gh/cotes2020/jekyll-theme-chirpy/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade
|
||||
[license]: https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/LICENSE
|
||||
[open-container]: https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/cotes2020/jekyll-theme-chirpy
|
||||
[jekyllrb]: https://jekyllrb.com/
|
||||
[bootstrap]: https://getbootstrap.com/
|
||||
[icons]: https://fontawesome.com/
|
||||
[image]: https://www.clipartmax.com/middle/m2i8b1m2K9Z5m2K9_ant-clipart-childrens-ant-cute/
|
||||
[clipartmax]: https://www.clipartmax.com/middle/m2i8b1m2K9Z5m2K9_ant-clipart-childrens-ant-cute/
|
||||
[demo]: https://cotes2020.github.io/chirpy-demo/
|
||||
[wiki]: https://github.com/cotes2020/jekyll-theme-chirpy/wiki
|
||||
[contribute-guide]: https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md
|
||||
[contributors]: https://github.com/cotes2020/jekyll-theme-chirpy/graphs/contributors
|
||||
[lib]: https://github.com/cotes2020/chirpy-static-assets
|
||||
[vscode]: https://code.visualstudio.com/
|
||||
[jetbrains]: https://www.jetbrains.com/?from=jekyll-theme-chirpy
|
||||
[ko-fi]: https://ko-fi.com/coteschung/
|
||||
[donation]: https://sponsor.cotes.page/
|
||||
|
||||
87
_config.yml
87
_config.yml
@@ -16,20 +16,20 @@ timezone: Asia/Shanghai
|
||||
|
||||
title: Chirpy # the main title
|
||||
|
||||
tagline: A text-focused Jekyll theme # it will display as the sub-title
|
||||
tagline: A text-focused Jekyll theme # it will display as the subtitle
|
||||
|
||||
description: >- # used by seo meta and the atom feed
|
||||
A minimal, responsive and feature-rich Jekyll theme for technical writing.
|
||||
|
||||
# Fill in the protocol & hostname for your site.
|
||||
# e.g. 'https://username.github.io', note that it does not end with a '/'.
|
||||
# E.g. 'https://username.github.io', note that it does not end with a '/'.
|
||||
url: ""
|
||||
|
||||
github:
|
||||
username: github_username # change to your github username
|
||||
username: github_username # change to your GitHub username
|
||||
|
||||
twitter:
|
||||
username: twitter_username # change to your twitter username
|
||||
username: twitter_username # change to your Twitter username
|
||||
|
||||
social:
|
||||
# Change to your full name.
|
||||
@@ -38,19 +38,44 @@ social:
|
||||
email: example@domain.com # change to your email address
|
||||
links:
|
||||
# The first element serves as the copyright owner's link
|
||||
- https://twitter.com/username # change to your twitter homepage
|
||||
- https://github.com/username # change to your github homepage
|
||||
- https://twitter.com/username # change to your Twitter homepage
|
||||
- https://github.com/username # change to your GitHub homepage
|
||||
# Uncomment below to add more social links
|
||||
# - https://www.facebook.com/username
|
||||
# - https://www.linkedin.com/in/username
|
||||
|
||||
google_site_verification: # fill in to your verification string
|
||||
# Site Verification Settings
|
||||
webmaster_verifications:
|
||||
google: # fill in your Google verification code
|
||||
bing: # fill in your Bing verification code
|
||||
alexa: # fill in your Alexa verification code
|
||||
yandex: # fill in your Yandex verification code
|
||||
baidu: # fill in your Baidu verification code
|
||||
facebook: # fill in your Facebook verification code
|
||||
|
||||
# ↑ --------------------------
|
||||
# The end of `jekyll-seo-tag` settings
|
||||
|
||||
google_analytics:
|
||||
id: # fill in your Google Analytics ID
|
||||
# Web Analytics Settings
|
||||
analytics:
|
||||
google:
|
||||
id: # fill in your Google Analytics ID
|
||||
goatcounter:
|
||||
id: # fill in your GoatCounter ID
|
||||
umami:
|
||||
id: # fill in your Umami ID
|
||||
domain: # fill in your Umami domain
|
||||
matomo:
|
||||
id: # fill in your Matomo ID
|
||||
domain: # fill in your Matomo domain
|
||||
cloudflare:
|
||||
id: # fill in your Cloudflare Web Analytics token
|
||||
fathom:
|
||||
id: # fill in your Fathom Site ID
|
||||
|
||||
# Page views settings
|
||||
pageviews:
|
||||
provider: # now only supports 'goatcounter'
|
||||
|
||||
# Prefer color scheme setting.
|
||||
#
|
||||
@@ -60,27 +85,32 @@ google_analytics:
|
||||
#
|
||||
# Available options:
|
||||
#
|
||||
# light - Use the light color scheme
|
||||
# dark - Use the dark color scheme
|
||||
# light — Use the light color scheme
|
||||
# dark — Use the dark color scheme
|
||||
#
|
||||
theme_mode: # [light|dark]
|
||||
theme_mode: # [light | dark]
|
||||
|
||||
# The CDN endpoint for images.
|
||||
# The CDN endpoint for media resources.
|
||||
# Notice that once it is assigned, the CDN url
|
||||
# will be added to all image (site avatar & posts' images) paths starting with '/'
|
||||
# will be added to all media resources (site avatar, posts' images, audio and video files) paths starting with '/'
|
||||
#
|
||||
# e.g. 'https://cdn.com'
|
||||
img_cdn: "https://chirpy-img.netlify.app"
|
||||
cdn: "https://chirpy-img.netlify.app"
|
||||
|
||||
# the avatar on sidebar, support local or CORS resources
|
||||
avatar: "/commons/avatar.jpg"
|
||||
|
||||
# The URL of the site-wide social preview image used in SEO `og:image` meta tag.
|
||||
# It can be overridden by a customized `page.image` in front matter.
|
||||
social_preview_image: # string, local or CORS resources
|
||||
|
||||
# boolean type, the global switch for TOC in posts.
|
||||
toc: true
|
||||
|
||||
comments:
|
||||
active: # The global switch for posts comments, e.g., 'disqus'. Keep it empty means disable
|
||||
# The active options are as follows:
|
||||
# Global switch for the post-comment system. Keeping it empty means disabled.
|
||||
provider: # [disqus | utterances | giscus]
|
||||
# The provider options are as follows:
|
||||
disqus:
|
||||
shortname: # fill with the Disqus shortname. › https://help.disqus.com/en/articles/1717111-what-s-a-shortname
|
||||
# utterances settings › https://utteranc.es/
|
||||
@@ -94,6 +124,7 @@ comments:
|
||||
category:
|
||||
category_id:
|
||||
mapping: # optional, default to 'pathname'
|
||||
strict: # optional, default to '0'
|
||||
input_position: # optional, default to 'bottom'
|
||||
lang: # optional, default to the value of `site.lang`
|
||||
reactions_enabled: # optional, default to the value of `1`
|
||||
@@ -104,10 +135,17 @@ assets:
|
||||
enabled: # boolean, keep empty means false
|
||||
# specify the Jekyll environment, empty means both
|
||||
# only works if `assets.self_host.enabled` is 'true'
|
||||
env: # [development|production]
|
||||
env: # [development | production]
|
||||
|
||||
pwa:
|
||||
enabled: true # the option for PWA feature
|
||||
enabled: true # The option for PWA feature (installable)
|
||||
cache:
|
||||
enabled: true # The option for PWA offline cache
|
||||
# Paths defined here will be excluded from the PWA cache.
|
||||
# Usually its value is the `baseurl` of another website that
|
||||
# shares the same domain name as the current website.
|
||||
deny_paths:
|
||||
# - "/example" # URLs match `<SITE_URL>/example/*` will not be cached by the PWA
|
||||
|
||||
paginate: 10
|
||||
|
||||
@@ -117,6 +155,7 @@ baseurl: ""
|
||||
# ------------ The following options are not recommended to be modified ------------------
|
||||
|
||||
kramdown:
|
||||
footnote_backlink: "↩︎"
|
||||
syntax_highlighter: rouge
|
||||
syntax_highlighter_opts: # Rouge Options › https://github.com/jneen/rouge#full-options
|
||||
css_class: highlight
|
||||
@@ -153,14 +192,6 @@ defaults:
|
||||
values:
|
||||
layout: page
|
||||
permalink: /:title/
|
||||
- scope:
|
||||
path: assets/img/favicons
|
||||
values:
|
||||
swcache: true
|
||||
- scope:
|
||||
path: assets/js/dist
|
||||
values:
|
||||
swcache: true
|
||||
|
||||
sass:
|
||||
style: compressed
|
||||
@@ -181,7 +212,7 @@ exclude:
|
||||
- tools
|
||||
- README.md
|
||||
- LICENSE
|
||||
- rollup.config.js
|
||||
- "*.config.js"
|
||||
- package*.json
|
||||
|
||||
jekyll-archives:
|
||||
|
||||
@@ -26,3 +26,15 @@
|
||||
# - type: stack-overflow
|
||||
# icon: 'fab fa-stack-overflow'
|
||||
# url: '' # Fill with your stackoverflow homepage
|
||||
#
|
||||
# - type: bluesky
|
||||
# icon: 'fa-brands fa-bluesky'
|
||||
# url: '' # Fill with your Bluesky profile link
|
||||
#
|
||||
# - type: reddit
|
||||
# icon: 'fa-brands fa-reddit'
|
||||
# url: '' # Fill with your Reddit profile link
|
||||
#
|
||||
# - type: threads
|
||||
# icon: 'fa-brands fa-threads'
|
||||
# url: '' # Fill with your Threads profile link
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: باستخدام :PLATFORM السمة :THEME
|
||||
|
||||
not_found:
|
||||
statment: عذرا, الرابط التالي غير صالح أو انه يشير إلى صفحة غير موجودة.
|
||||
statement: عذرا, الرابط التالي غير صالح أو انه يشير إلى صفحة غير موجودة.
|
||||
|
||||
notification:
|
||||
update_found: يتوفر اصدار جديد للمحتوى.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Създадено чрез :PLATFORM и :THEME тема
|
||||
|
||||
not_found:
|
||||
statment: Съжалявам, но на този URL адрес няма налично съдържание.
|
||||
statement: Съжалявам, но на този URL адрес няма налично съдържание.
|
||||
|
||||
notification:
|
||||
update_found: Налична е нова версия на съдържанието.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Použití :PLATFORM s motivem :THEME
|
||||
|
||||
not_found:
|
||||
statment: Omlouváme se, adresu URL jsme špatně umístili nebo odkazuje na něco, co neexistuje.
|
||||
statement: Omlouváme se, adresu URL jsme špatně umístili nebo odkazuje na něco, co neexistuje.
|
||||
|
||||
notification:
|
||||
update_found: Je k dispozici nová verze obsahu.
|
||||
|
||||
@@ -42,7 +42,7 @@ copyright:
|
||||
meta: Powered by :PLATFORM with :THEME theme
|
||||
|
||||
not_found:
|
||||
statment: Entschuldigung, dieser Link verweist auf keine vorhandene Ressource.
|
||||
statement: Entschuldigung, dieser Link verweist auf keine vorhandene Ressource.
|
||||
|
||||
notification:
|
||||
update_found: Eine neue Version ist verfügbar.
|
||||
@@ -76,7 +76,7 @@ df:
|
||||
post:
|
||||
strftime: "%d.%m.%Y"
|
||||
dayjs: "DD.MM.YYYY"
|
||||
|
||||
|
||||
# categories page
|
||||
categories:
|
||||
category_measure:
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Αξιοποιώντας την :PLATFORM theme :THEME
|
||||
|
||||
not_found:
|
||||
statment: Συγνώμη, έχουμε τοποθετήσει λάθος αυτήν την διεύθυνση URL ή υποδεικνύει κάτι που δεν υπάρχει.
|
||||
statement: Συγνώμη, έχουμε τοποθετήσει λάθος αυτήν την διεύθυνση URL ή υποδεικνύει κάτι που δεν υπάρχει.
|
||||
|
||||
notification:
|
||||
update_found: Υπάρχει διαθέσιμη μια νέα έκδοση του περιεχομένου.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Using the :THEME theme for :PLATFORM.
|
||||
|
||||
not_found:
|
||||
statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
||||
statement: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
||||
|
||||
notification:
|
||||
update_found: A new version of content is available.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Hecho con :PLATFORM usando el tema :THEME
|
||||
|
||||
not_found:
|
||||
statment: Lo sentimos, hemos perdido esa URL o apunta a algo que no existe.
|
||||
statement: Lo sentimos, hemos perdido esa URL o apunta a algo que no existe.
|
||||
|
||||
notification:
|
||||
update_found: Hay una nueva versión de contenido disponible.
|
||||
|
||||
@@ -42,7 +42,7 @@ copyright:
|
||||
meta: Käytetään :PLATFORM iä Teema :THEME
|
||||
|
||||
not_found:
|
||||
statment: Valitettavasti tällä URL-osoitteella ei ole saatavilla sisältöä.
|
||||
statement: Valitettavasti tällä URL-osoitteella ei ole saatavilla sisältöä.
|
||||
|
||||
notification:
|
||||
update_found: Uusi versio sisällöstä on saatavilla.
|
||||
|
||||
@@ -14,7 +14,7 @@ tabs:
|
||||
categories: Catégories
|
||||
tags: Tags
|
||||
archives: Archives
|
||||
about: A propos de
|
||||
about: À propos
|
||||
|
||||
# the text displayed in the search bar & search results
|
||||
search:
|
||||
@@ -32,18 +32,18 @@ copyright:
|
||||
license:
|
||||
template: Cet article est sous licence :LICENSE_NAME par l'auteur.
|
||||
name: CC BY 4.0
|
||||
link: https://creativecommons.org/licenses/by/4.0/
|
||||
link: https://creativecommons.org/licenses/by/4.0/deed.fr
|
||||
|
||||
# Displayed in the footer
|
||||
brief: Certains droits réservés.
|
||||
verbose: >-
|
||||
Sauf mention contraire, les articles de ce site sont publiés sous licence
|
||||
Sauf mention contraire, les articles de ce site sont publiés
|
||||
sous la licence Creative Commons Attribution 4.0 International (CC BY 4.0) par l'auteur.
|
||||
|
||||
meta: Propulsé par :PLATFORM avec le thème :THEME
|
||||
|
||||
not_found:
|
||||
statment: Désolé, nous avons égaré cette URL ou elle pointe vers quelque chose qui n'existe pas.
|
||||
statement: Désolé, nous avons égaré cette URL ou elle pointe vers quelque chose qui n'existe pas.
|
||||
|
||||
notification:
|
||||
update_found: Une nouvelle version du contenu est disponible.
|
||||
|
||||
@@ -14,24 +14,23 @@ tabs:
|
||||
categories: Kategóriák
|
||||
tags: Címkék
|
||||
archives: Archívum
|
||||
about: Rólam
|
||||
about: Bemutatkozás
|
||||
|
||||
# the text displayed in the search bar & search results
|
||||
search:
|
||||
hint: keresés
|
||||
cancel: Mégse
|
||||
no_results: Oops! Nincs találat a keresésre.
|
||||
no_results: Hoppá! Nincs találat a keresésre.
|
||||
|
||||
panel:
|
||||
lastmod: Legutóbb frissítve
|
||||
trending_tags: Népszerű Címkék
|
||||
toc: Tartalom
|
||||
links: Blog linkek
|
||||
|
||||
copyright:
|
||||
# Shown at the bottom of the post
|
||||
license:
|
||||
template: A bejegyzés :LICENSE_NAME licenccel rendelkezik.
|
||||
template: A bejegyzést a szerző :LICENSE_NAME licenc alatt engedélyezte.
|
||||
name: CC BY 4.0
|
||||
link: https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
@@ -42,10 +41,10 @@ copyright:
|
||||
Creative Commons Attribution 4.0 International (CC BY 4.0) licenccel rendelkeznek,
|
||||
hacsak másképp nincs jelezve.
|
||||
|
||||
meta: Készítve :PLATFORM motorral :THEME témával
|
||||
meta: Készítve :THEME témával a :PLATFORM platformra.
|
||||
|
||||
not_found:
|
||||
statment: Sajnáljuk, az URL-t rosszul helyeztük el, vagy valami nem létezőre mutat.
|
||||
statement: Sajnáljuk, az URL-t rosszul helyeztük el, vagy valami nem létezőre mutat.
|
||||
|
||||
notification:
|
||||
update_found: Elérhető a tartalom új verziója.
|
||||
@@ -73,7 +72,21 @@ post:
|
||||
title: Link másolása
|
||||
succeed: Link sikeresen másolva!
|
||||
|
||||
# Date time format.
|
||||
# See: <http://strftime.net/>, <https://day.js.org/docs/en/display/format>
|
||||
df:
|
||||
post:
|
||||
strftime: "%Y. %B. %e."
|
||||
dayjs: "YYYY. MMMM D."
|
||||
archives:
|
||||
strftime: "%B"
|
||||
dayjs: "MMM"
|
||||
|
||||
# categories page
|
||||
categories:
|
||||
category_measure: kategória
|
||||
post_measure: bejegyzés
|
||||
category_measure:
|
||||
singular: kategória
|
||||
plural: kategória
|
||||
post_measure:
|
||||
singular: bejegyzés
|
||||
plural: bejegyzés
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Didukung oleh :PLATFORM dengan tema :THEME
|
||||
|
||||
not_found:
|
||||
statment: Maaf, kami gagal menemukan URL itu atau memang mengarah ke sesuatu yang tidak ada.
|
||||
statement: Maaf, kami gagal menemukan URL itu atau memang mengarah ke sesuatu yang tidak ada.
|
||||
|
||||
notification:
|
||||
update_found: Versi konten baru tersedia.
|
||||
|
||||
@@ -42,7 +42,7 @@ copyright:
|
||||
|
||||
meta: Servizio offerto da :PLATFORM con tema :THEME
|
||||
not_found:
|
||||
statment: Ci scusiamo, non è stato possibile trovare l'URL in questione. Potrebbe puntare ad una pagina non esistente.
|
||||
statement: Ci scusiamo, non è stato possibile trovare l'URL in questione. Potrebbe puntare ad una pagina non esistente.
|
||||
|
||||
notification:
|
||||
update_found: Nuova versione del contenuto disponibile.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Powered by :PLATFORM with :THEME theme
|
||||
|
||||
not_found:
|
||||
statment: 해당 URL은 존재하지 않습니다.
|
||||
statement: 해당 URL은 존재하지 않습니다.
|
||||
|
||||
notification:
|
||||
update_found: 새 버전의 콘텐츠를 사용할 수 있습니다.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Powered by :PLATFORM with :THEME theme
|
||||
|
||||
not_found:
|
||||
statment: ဝမ်းနည်းပါသည်၊ ကျွန်ုပ်တို့သည် အဆိုပါ URL ကို မှားယွင်းစွာ နေရာချထားခြင်း သို့မဟုတ် ၎င်းသည် မရှိသောအရာကို ညွှန်ပြနေပါသည်။
|
||||
statement: ဝမ်းနည်းပါသည်၊ ကျွန်ုပ်တို့သည် အဆိုပါ URL ကို မှားယွင်းစွာ နေရာချထားခြင်း သို့မဟုတ် ၎င်းသည် မရှိသောအရာကို ညွှန်ပြနေပါသည်။
|
||||
|
||||
notification:
|
||||
update_found: အကြောင်းအရာဗားရှင်းအသစ်ကို ရနိုင်ပါပြီ။
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Feito com :PLATFORM usando o tema :THEME
|
||||
|
||||
not_found:
|
||||
statment: Desculpe, a página não foi encontrada.
|
||||
statement: Desculpe, a página não foi encontrada.
|
||||
|
||||
notification:
|
||||
update_found: Uma nova versão do conteúdo está disponível.
|
||||
|
||||
@@ -42,7 +42,7 @@ copyright:
|
||||
meta: Использует тему :THEME для :PLATFORM
|
||||
|
||||
not_found:
|
||||
statment: Извините, мы перепутали URL-адрес или он указывает на что-то несуществующее.
|
||||
statement: Извините, мы перепутали URL-адрес или он указывает на что-то несуществующее.
|
||||
|
||||
notification:
|
||||
update_found: Доступна новая версия контента.
|
||||
@@ -76,7 +76,7 @@ df:
|
||||
post:
|
||||
strftime: "%d.%m.%Y"
|
||||
dayjs: "DD.MM.YYYY"
|
||||
|
||||
|
||||
# categories page
|
||||
categories:
|
||||
category_measure:
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Uporabljena :PLATFORM tema :THEME #Using the :PLATFORM theme :THEME
|
||||
|
||||
not_found:
|
||||
statment: Oprostite, hiperpovezava je neustrezna ali vsebina ne obstajata. #Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
||||
statement: Oprostite, hiperpovezava je neustrezna ali vsebina ne obstajata. #Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
||||
|
||||
notification:
|
||||
update_found: Novejša različica vsebine je na voljo. #A new version of content is available.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Byggd med :PLATFORM och temat :THEME
|
||||
|
||||
not_found:
|
||||
statment: Ursäkta, vi har tappat bort den här webbadressen eller så pekar den på något som inte längre finns.
|
||||
statement: Ursäkta, vi har tappat bort den här webbadressen eller så pekar den på något som inte längre finns.
|
||||
|
||||
notification:
|
||||
update_found: Det finns en ny version av innehållet.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: กำลังใช้ธีมของ :PLATFORM ชื่อ :THEME
|
||||
|
||||
not_found:
|
||||
statment: ขออภัย เราวาง URL นั้นไว้ผิดที่ หรือมันชี้ไปยังสิ่งที่ไม่มีอยู่
|
||||
statement: ขออภัย เราวาง URL นั้นไว้ผิดที่ หรือมันชี้ไปยังสิ่งที่ไม่มีอยู่
|
||||
|
||||
notification:
|
||||
update_found: มีเวอร์ชันใหม่ของเนื้อหา
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: :PLATFORM ve :THEME teması
|
||||
|
||||
not_found:
|
||||
statment: Üzgünüz, bu linki yanlış yerleştirdik veya var olmayan bir şeye işaret ediyor.
|
||||
statement: Üzgünüz, bu linki yanlış yerleştirdik veya var olmayan bir şeye işaret ediyor.
|
||||
|
||||
notification:
|
||||
update_found: İçeriğin yeni bir sürümü mevcut.
|
||||
|
||||
@@ -43,7 +43,7 @@ copyright:
|
||||
meta: Powered by :PLATFORM with :THEME theme
|
||||
|
||||
not_found:
|
||||
statment: Вибачте, це посилання вказує на ресурс, що не існує.
|
||||
statement: Вибачте, це посилання вказує на ресурс, що не існує.
|
||||
|
||||
notification:
|
||||
update_found: Доступна нова версія вмісту.
|
||||
|
||||
@@ -42,7 +42,7 @@ copyright:
|
||||
meta: Trang web này được tạo bởi :PLATFORM với chủ đề :THEME
|
||||
|
||||
not_found:
|
||||
statment: Xin lỗi, chúng tôi đã đặt nhầm URL hoặc đường dẫn trỏ đến một trang nào đó không tồn tại.
|
||||
statement: Xin lỗi, chúng tôi đã đặt nhầm URL hoặc đường dẫn trỏ đến một trang nào đó không tồn tại.
|
||||
|
||||
notification:
|
||||
update_found: Đã có phiên bản mới của nội dung.
|
||||
|
||||
@@ -42,7 +42,7 @@ copyright:
|
||||
meta: 本站采用 :PLATFORM 主题 :THEME
|
||||
|
||||
not_found:
|
||||
statment: 抱歉,我们放错了该 URL,或者它指向了不存在的内容。
|
||||
statement: 抱歉,我们放错了该 URL,或者它指向了不存在的内容。
|
||||
|
||||
notification:
|
||||
update_found: 发现新版本的内容。
|
||||
|
||||
@@ -42,7 +42,7 @@ copyright:
|
||||
meta: 本網站使用 :PLATFORM 產生,採用 :THEME 主題
|
||||
|
||||
not_found:
|
||||
statment: 抱歉,您可能正在存取一個已被移動的 URL,或者它從未存在。
|
||||
statement: 抱歉,您可能正在存取一個已被移動的 URL,或者它從未存在。
|
||||
|
||||
notification:
|
||||
update_found: 發現新版本更新。
|
||||
|
||||
18
_data/media.yml
Normal file
18
_data/media.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
- extension: mp3
|
||||
mime_type: mpeg
|
||||
- extension: mov
|
||||
mime_type: quicktime
|
||||
- extension: avi
|
||||
mime_type: x-msvideo
|
||||
- extension: mkv
|
||||
mime_type: x-matroska
|
||||
- extension: ogv
|
||||
mime_type: ogg
|
||||
- extension: weba
|
||||
mime_type: webm
|
||||
- extension: 3gp
|
||||
mime_type: 3gpp
|
||||
- extension: 3g2
|
||||
mime_type: 3gpp2
|
||||
- extension: mid
|
||||
mime_type: midi
|
||||
@@ -4,13 +4,6 @@ webfonts: /assets/lib/fonts/main.css
|
||||
|
||||
# Libraries
|
||||
|
||||
jquery:
|
||||
js: /assets/lib/jquery/jquery.min.js
|
||||
|
||||
bootstrap:
|
||||
css: /assets/lib/bootstrap/bootstrap.min.css
|
||||
js: /assets/lib/bootstrap/bootstrap.bundle.min.js
|
||||
|
||||
toc:
|
||||
css: /assets/lib/tocbot/tocbot.min.css
|
||||
js: /assets/lib/tocbot/tocbot.min.js
|
||||
@@ -27,13 +20,13 @@ mermaid:
|
||||
dayjs:
|
||||
js:
|
||||
common: /assets/lib/dayjs/dayjs.min.js
|
||||
locale: /assets/lib/dayjs/locale/en.min.js
|
||||
relativeTime: /assets/lib/dayjs/plugin/relativeTime.min.js
|
||||
localizedFormat: /assets/lib/dayjs/plugin/localizedFormat.min.js
|
||||
locale: /assets/lib/dayjs/locale/en.js
|
||||
relativeTime: /assets/lib/dayjs/plugin/relativeTime.js
|
||||
localizedFormat: /assets/lib/dayjs/plugin/localizedFormat.js
|
||||
|
||||
magnific-popup:
|
||||
css: /assets/lib/magnific-popup/magnific-popup.css
|
||||
js: /assets/lib/magnific-popup/jquery.magnific-popup.min.js
|
||||
glightbox:
|
||||
css: /assets/lib/glightbox/glightbox.min.css
|
||||
js: /assets/lib/glightbox/glightbox.min.js
|
||||
|
||||
lazy-polyfill:
|
||||
css: /assets/lib/loading-attribute-polyfill/loading-attribute-polyfill.min.css
|
||||
|
||||
@@ -1,50 +1,47 @@
|
||||
# CDNs
|
||||
|
||||
cdns:
|
||||
# Google Fonts
|
||||
# Resource Hints
|
||||
resource_hints:
|
||||
- url: https://fonts.googleapis.com
|
||||
links:
|
||||
- rel: preconnect
|
||||
- rel: dns-prefetch
|
||||
- url: https://fonts.gstatic.com
|
||||
args: crossorigin
|
||||
- url: https://fonts.googleapis.com
|
||||
# jsDelivr CDN
|
||||
links:
|
||||
- rel: preconnect
|
||||
opts: [crossorigin]
|
||||
- rel: dns-prefetch
|
||||
- url: https://cdn.jsdelivr.net
|
||||
links:
|
||||
- rel: preconnect
|
||||
- rel: dns-prefetch
|
||||
|
||||
# fonts
|
||||
|
||||
webfonts: https://fonts.googleapis.com/css2?family=Lato&family=Source+Sans+Pro:wght@400;600;700;900&display=swap
|
||||
# Web Fonts
|
||||
webfonts: https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Source+Sans+Pro:wght@400;600;700;900&display=swap
|
||||
|
||||
# Libraries
|
||||
|
||||
jquery:
|
||||
js: https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js
|
||||
|
||||
bootstrap:
|
||||
css: https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css
|
||||
js: https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js
|
||||
|
||||
toc:
|
||||
css: https://cdn.jsdelivr.net/npm/tocbot@4.21.3/dist/tocbot.min.css
|
||||
js: https://cdn.jsdelivr.net/npm/tocbot@4.21.3/dist/tocbot.min.js
|
||||
css: https://cdn.jsdelivr.net/npm/tocbot@4.29.0/dist/tocbot.min.css
|
||||
js: https://cdn.jsdelivr.net/npm/tocbot@4.29.0/dist/tocbot.min.js
|
||||
|
||||
fontawesome:
|
||||
css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.2/css/all.min.css
|
||||
css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.6.0/css/all.min.css
|
||||
|
||||
search:
|
||||
js: https://cdn.jsdelivr.net/npm/simple-jekyll-search@1.10.0/dest/simple-jekyll-search.min.js
|
||||
|
||||
mermaid:
|
||||
js: https://cdn.jsdelivr.net/npm/mermaid@10.6.0/dist/mermaid.min.js
|
||||
js: https://cdn.jsdelivr.net/npm/mermaid@11.0.2/dist/mermaid.min.js
|
||||
|
||||
dayjs:
|
||||
js:
|
||||
common: https://cdn.jsdelivr.net/npm/dayjs@1.11.10/dayjs.min.js
|
||||
locale: https://cdn.jsdelivr.net/npm/dayjs@1.11.10/locale/:LOCALE.min.js
|
||||
relativeTime: https://cdn.jsdelivr.net/npm/dayjs@1.11.10/plugin/relativeTime.min.js
|
||||
localizedFormat: https://cdn.jsdelivr.net/npm/dayjs@1.11.10/plugin/localizedFormat.min.js
|
||||
common: https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js
|
||||
locale: https://cdn.jsdelivr.net/npm/dayjs@1.11.13/locale/:LOCALE.js
|
||||
relativeTime: https://cdn.jsdelivr.net/npm/dayjs@1.11.13/plugin/relativeTime.js
|
||||
localizedFormat: https://cdn.jsdelivr.net/npm/dayjs@1.11.13/plugin/localizedFormat.js
|
||||
|
||||
magnific-popup:
|
||||
css: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/magnific-popup.min.css
|
||||
js: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/jquery.magnific-popup.min.js
|
||||
glightbox:
|
||||
css: https://cdn.jsdelivr.net/npm/glightbox@3.3.0/dist/css/glightbox.min.css
|
||||
js: https://cdn.jsdelivr.net/npm/glightbox@3.3.0/dist/js/glightbox.min.js
|
||||
|
||||
lazy-polyfill:
|
||||
css: https://cdn.jsdelivr.net/npm/loading-attribute-polyfill@2.1.1/dist/loading-attribute-polyfill.min.css
|
||||
|
||||
@@ -22,7 +22,7 @@ platforms:
|
||||
#
|
||||
# - type: Weibo
|
||||
# icon: "fab fa-weibo"
|
||||
# link: "http://service.weibo.com/share/share.php?title=TITLE&url=URL"
|
||||
# link: "https://service.weibo.com/share/share.php?title=TITLE&url=URL"
|
||||
#
|
||||
# - type: Mastodon
|
||||
# icon: "fa-brands fa-mastodon"
|
||||
@@ -36,3 +36,15 @@ platforms:
|
||||
# link: "https://fosstodon.org/"
|
||||
# - label: photog.social
|
||||
# link: "https://photog.social/"
|
||||
#
|
||||
# - type: Bluesky
|
||||
# icon: "fa-brands fa-bluesky"
|
||||
# link: "https://bsky.app/intent/compose?text=TITLE%20URL"
|
||||
#
|
||||
# - type: Reddit
|
||||
# icon: "fa-brands fa-square-reddit"
|
||||
# link: "https://www.reddit.com/submit?url=URL&title=TITLE"
|
||||
#
|
||||
# - type: Threads
|
||||
# icon: "fa-brands fa-square-threads"
|
||||
# link: "https://www.threads.net/intent/post?text=TITLE%20URL"
|
||||
|
||||
6
_includes/analytics/cloudflare.html
Normal file
6
_includes/analytics/cloudflare.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- Cloudflare Web Analytics -->
|
||||
<script
|
||||
defer
|
||||
src="https://static.cloudflareinsights.com/beacon.min.js"
|
||||
data-cf-beacon='{"token": "{{ site.analytics.cloudflare.id }}"}'
|
||||
></script>
|
||||
6
_includes/analytics/fathom.html
Normal file
6
_includes/analytics/fathom.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- Fathom -->
|
||||
<script
|
||||
src="https://cdn.usefathom.com/script.js"
|
||||
data-site="{{ site.analytics.fathom.id }}"
|
||||
defer
|
||||
></script>
|
||||
6
_includes/analytics/goatcounter.html
Normal file
6
_includes/analytics/goatcounter.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- GoatCounter -->
|
||||
<script
|
||||
async
|
||||
src="https://gc.zgo.at/count.js"
|
||||
data-goatcounter="https://{{ site.analytics.goatcounter.id }}.goatcounter.com/count"
|
||||
></script>
|
||||
13
_includes/analytics/google.html
Normal file
13
_includes/analytics/google.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script defer src="https://www.googletagmanager.com/gtag/js?id={{ site.analytics.google.id }}"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
|
||||
gtag('js', new Date());
|
||||
gtag('config', '{{ site.analytics.google.id }}');
|
||||
});
|
||||
</script>
|
||||
13
_includes/analytics/matomo.html
Normal file
13
_includes/analytics/matomo.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!-- Matomo -->
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
var _paq = (window._paq = window._paq || []);
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
var u="//{{ site.analytics.matomo.domain }}/";
|
||||
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
||||
_paq.push(['setSiteId', {{ site.analytics.matomo.id }}]);
|
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
||||
});
|
||||
</script>
|
||||
6
_includes/analytics/umami.html
Normal file
6
_includes/analytics/umami.html
Normal file
@@ -0,0 +1,6 @@
|
||||
<!-- Umami -->
|
||||
<script
|
||||
defer
|
||||
src="{{ site.analytics.umami.domain }}/script.js"
|
||||
data-website-id="{{ site.analytics.umami.id }}"
|
||||
></script>
|
||||
5
_includes/comment.html
Normal file
5
_includes/comment.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<!-- The comments switcher -->
|
||||
{% if page.comments and site.comments.provider %}
|
||||
{% capture path %}comments/{{ site.comments.provider }}.html{% endcapture %}
|
||||
{% include {{ path }} %}
|
||||
{% endif %}
|
||||
@@ -1,5 +0,0 @@
|
||||
<!-- The comments switcher -->
|
||||
{% if page.comments and site.comments.active %}
|
||||
{% capture path %}comments/{{ site.comments.active }}.html{% endcapture %}
|
||||
{% include {{ path }} %}
|
||||
{% endif %}
|
||||
@@ -1,39 +1,26 @@
|
||||
<!-- The Disqus lazy loading. -->
|
||||
|
||||
<div id="disqus_thread">
|
||||
<p class="text-center text-muted small">Comments powered by <a href="https://disqus.com/">Disqus</a>.</p>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
var disqus_config = function () {
|
||||
this.page.url = '{{ page.url | absolute_url }}';
|
||||
this.page.identifier = '{{ page.url }}';
|
||||
};
|
||||
|
||||
/* Lazy loading */
|
||||
var disqus_observer = new IntersectionObserver(
|
||||
function (entries) {
|
||||
if (entries[0].isIntersecting) {
|
||||
(function () {
|
||||
var d = document,
|
||||
s = d.createElement('script');
|
||||
s.src = 'https://{{ site.comments.disqus.shortname }}.disqus.com/embed.js';
|
||||
s.setAttribute('data-timestamp', +new Date());
|
||||
(d.head || d.body).appendChild(s);
|
||||
})();
|
||||
function addDisqus() {
|
||||
let disqusThread = document.createElement('div');
|
||||
let paragraph = document.createElement('p');
|
||||
|
||||
disqus_observer.disconnect();
|
||||
}
|
||||
},
|
||||
{ threshold: [0] }
|
||||
);
|
||||
disqusThread.id = 'disqus_thread';
|
||||
paragraph.className = 'text-center text-muted small';
|
||||
paragraph.innerHTML = 'Comments powered by <a href="https://disqus.com/">Disqus</a>.';
|
||||
disqusThread.appendChild(paragraph);
|
||||
|
||||
disqus_observer.observe(document.querySelector('#disqus_thread'));
|
||||
const footer = document.querySelector('footer');
|
||||
footer.insertAdjacentElement("beforebegin", disqusThread);
|
||||
}
|
||||
|
||||
/* Auto switch theme */
|
||||
function reloadDisqus() {
|
||||
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
||||
/* Disqus hasn't been loaded */
|
||||
{%- comment -%} Auto switch theme {%- endcomment -%}
|
||||
function reloadDisqus(event) {
|
||||
if (event.source === window && event.data && event.data.id === Theme.ID) {
|
||||
{%- comment -%} Disqus hasn't been loaded {%- endcomment -%}
|
||||
if (typeof DISQUS === 'undefined') {
|
||||
return;
|
||||
}
|
||||
@@ -44,7 +31,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (document.querySelector('.mode-toggle')) {
|
||||
window.addEventListener('message', reloadDisqus);
|
||||
addDisqus();
|
||||
|
||||
if (Theme.switchable) {
|
||||
addEventListener('message', reloadDisqus);
|
||||
}
|
||||
|
||||
{%- comment -%} Lazy loading {%- endcomment -%}
|
||||
var disqusObserver = new IntersectionObserver(
|
||||
function (entries) {
|
||||
if (entries[0].isIntersecting) {
|
||||
var d = document,
|
||||
s = d.createElement('script');
|
||||
s.src = 'https://{{ site.comments.disqus.shortname }}.disqus.com/embed.js';
|
||||
s.setAttribute('data-timestamp', +new Date());
|
||||
(d.head || d.body).appendChild(s);
|
||||
|
||||
disqusObserver.disconnect();
|
||||
}
|
||||
},
|
||||
{ threshold: [0] }
|
||||
);
|
||||
|
||||
disqusObserver.observe(document.getElementById('disqus_thread'));
|
||||
</script>
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
<!-- https://giscus.app/ -->
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
(function () {
|
||||
const origin = 'https://giscus.app';
|
||||
const iframe = 'iframe.giscus-frame';
|
||||
const lightTheme = 'light';
|
||||
const darkTheme = 'dark_dimmed';
|
||||
const themeMapper = Theme.getThemeMapper('light', 'dark_dimmed');
|
||||
const initTheme = themeMapper[Theme.visualState];
|
||||
|
||||
let initTheme = lightTheme;
|
||||
const html = document.documentElement;
|
||||
|
||||
if (
|
||||
(html.hasAttribute('data-mode') &&
|
||||
html.getAttribute('data-mode') === 'dark') ||
|
||||
(!html.hasAttribute('data-mode') &&
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
initTheme = darkTheme;
|
||||
let lang = '{{ site.comments.giscus.lang | default: lang }}';
|
||||
{%- comment -%} https://github.com/giscus/giscus/tree/main/locales {%- endcomment -%}
|
||||
if (lang.length > 2 && !lang.startsWith('zh')) {
|
||||
lang = lang.slice(0, 2);
|
||||
}
|
||||
|
||||
let giscusAttributes = {
|
||||
@@ -25,40 +17,38 @@
|
||||
'data-category': '{{ site.comments.giscus.category }}',
|
||||
'data-category-id': '{{ site.comments.giscus.category_id }}',
|
||||
'data-mapping': '{{ site.comments.giscus.mapping | default: 'pathname' }}',
|
||||
'data-strict' : '{{ site.comments.giscus.strict | default: '0' }}',
|
||||
'data-reactions-enabled': '{{ site.comments.giscus.reactions_enabled | default: '1' }}',
|
||||
'data-emit-metadata': '0',
|
||||
'data-theme': initTheme,
|
||||
'data-input-position': '{{ site.comments.giscus.input_position | default: 'bottom' }}',
|
||||
'data-lang': '{{ site.comments.giscus.lang | default: lang }}',
|
||||
'data-lang': lang,
|
||||
'data-loading': 'lazy',
|
||||
crossorigin: 'anonymous',
|
||||
async: ''
|
||||
};
|
||||
|
||||
let giscusScript = document.createElement('script');
|
||||
let giscusNode = document.createElement('script');
|
||||
Object.entries(giscusAttributes).forEach(([key, value]) =>
|
||||
giscusScript.setAttribute(key, value)
|
||||
giscusNode.setAttribute(key, value)
|
||||
);
|
||||
document.getElementById('tail-wrapper').appendChild(giscusScript);
|
||||
|
||||
const $footer = document.querySelector('footer');
|
||||
$footer.insertAdjacentElement("beforebegin", giscusNode);
|
||||
|
||||
addEventListener('message', (event) => {
|
||||
if (
|
||||
event.source === window &&
|
||||
event.data &&
|
||||
event.data.direction === ModeToggle.ID
|
||||
) {
|
||||
/* global theme mode changed */
|
||||
const mode = event.data.message;
|
||||
const theme = mode === ModeToggle.DARK_MODE ? darkTheme : lightTheme;
|
||||
if (event.source === window && event.data && event.data.id === Theme.ID) {
|
||||
const newTheme = themeMapper[Theme.visualState];
|
||||
|
||||
const message = {
|
||||
setConfig: {
|
||||
theme: theme
|
||||
theme: newTheme
|
||||
}
|
||||
};
|
||||
|
||||
const giscus = document.querySelector(iframe).contentWindow;
|
||||
giscus.postMessage({ giscus: message }, origin);
|
||||
const giscus =
|
||||
document.getElementsByClassName('giscus-frame')[0].contentWindow;
|
||||
giscus.postMessage({ giscus: message }, 'https://giscus.app');
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -1,50 +1,38 @@
|
||||
<!-- https://utteranc.es/ -->
|
||||
<script
|
||||
src="https://utteranc.es/client.js"
|
||||
repo="{{ site.comments.utterances.repo }}"
|
||||
issue-term="{{ site.comments.utterances.issue_term }}"
|
||||
crossorigin="anonymous"
|
||||
async
|
||||
></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
(function () {
|
||||
const origin = 'https://utteranc.es';
|
||||
const iframe = 'iframe.utterances-frame';
|
||||
const lightTheme = 'github-light';
|
||||
const darkTheme = 'github-dark';
|
||||
let initTheme = lightTheme;
|
||||
const html = document.documentElement;
|
||||
const themeMapper = Theme.getThemeMapper('github-light', 'github-dark');
|
||||
const initTheme = themeMapper[Theme.visualState];
|
||||
|
||||
if (
|
||||
(html.hasAttribute('data-mode') && html.getAttribute('data-mode') === 'dark') ||
|
||||
(!html.hasAttribute('data-mode') && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
initTheme = darkTheme;
|
||||
}
|
||||
let script = document.createElement('script');
|
||||
script.src = 'https://utteranc.es/client.js';
|
||||
script.setAttribute('repo', '{{ site.comments.utterances.repo }}');
|
||||
script.setAttribute('issue-term', '{{ site.comments.utterances.issue_term }}');
|
||||
script.setAttribute('theme', initTheme);
|
||||
script.crossOrigin = 'anonymous';
|
||||
script.async = true;
|
||||
|
||||
const $footer = document.querySelector('footer');
|
||||
$footer.insertAdjacentElement('beforebegin', script);
|
||||
|
||||
addEventListener('message', (event) => {
|
||||
let theme;
|
||||
let newTheme;
|
||||
|
||||
/* credit to <https://github.com/utterance/utterances/issues/170#issuecomment-594036347> */
|
||||
if (event.origin === origin) {
|
||||
/* page initial */
|
||||
theme = initTheme;
|
||||
} else if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
||||
/* global theme mode changed */
|
||||
const mode = event.data.message;
|
||||
theme = mode === ModeToggle.DARK_MODE ? darkTheme : lightTheme;
|
||||
} else {
|
||||
return;
|
||||
{%- comment -%}
|
||||
Credit to <https://github.com/utterance/utterances/issues/170#issuecomment-594036347>
|
||||
{%- endcomment -%}
|
||||
if (event.source === window && event.data && event.data.id === Theme.ID) {
|
||||
newTheme = themeMapper[Theme.visualState];
|
||||
|
||||
const message = {
|
||||
type: 'set-theme',
|
||||
theme: newTheme
|
||||
};
|
||||
|
||||
const utterances = document.querySelector('.utterances-frame').contentWindow;
|
||||
utterances.postMessage(message, origin);
|
||||
}
|
||||
|
||||
const message = {
|
||||
type: 'set-theme',
|
||||
theme: theme
|
||||
};
|
||||
|
||||
const utterances = document.querySelector(iframe).contentWindow;
|
||||
utterances.postMessage(message, origin);
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
35
_includes/embed/audio.html
Normal file
35
_includes/embed/audio.html
Normal file
@@ -0,0 +1,35 @@
|
||||
{% assign src = include.src | strip %}
|
||||
{% assign title = include.title | strip %}
|
||||
{% assign types = include.types | default: '' | strip | split: '|' %}
|
||||
|
||||
{% unless src contains '://' %}
|
||||
{%- capture src -%}
|
||||
{% include media-url.html src=src subpath=page.media_subpath %}
|
||||
{%- endcapture -%}
|
||||
{% endunless %}
|
||||
|
||||
<p>
|
||||
<audio class="embed-audio" controls>
|
||||
{% assign extension = src | split: '.' | last %}
|
||||
{% assign types = extension | concat: types %}
|
||||
|
||||
{% assign ext_size = extension | size %}
|
||||
{% assign src_size = src | size %}
|
||||
{% assign slice_size = src_size | minus: ext_size %}
|
||||
|
||||
{% assign filepath = src | slice: 0, slice_size %}
|
||||
|
||||
{% for type in types %}
|
||||
{% assign src = filepath | append: type %}
|
||||
{% assign media_item = site.data.media | find: 'extension', type %}
|
||||
{% assign mime_type = media_item.mime_type | default: type %}
|
||||
<source src="{{ src }}" type="audio/{{ mime_type }}">
|
||||
{% endfor %}
|
||||
|
||||
Your browser does not support the audio tag. Here is a
|
||||
<a href="{{ src | strip }}">link to the audio file</a> instead.
|
||||
</audio>
|
||||
{% if title %}
|
||||
<em>{{ title }}</em>
|
||||
{% endif %}
|
||||
</p>
|
||||
9
_includes/embed/bilibili.html
Normal file
9
_includes/embed/bilibili.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<iframe
|
||||
class="embed-video"
|
||||
loading="lazy"
|
||||
src="https://player.bilibili.com/player.html?bvid={{ include.id }}"
|
||||
scrolling="no"
|
||||
frameborder="0"
|
||||
framespacing="0"
|
||||
allowfullscreen="true"
|
||||
></iframe>
|
||||
59
_includes/embed/video.html
Normal file
59
_includes/embed/video.html
Normal file
@@ -0,0 +1,59 @@
|
||||
{% assign video_url = include.src %}
|
||||
{% assign title = include.title %}
|
||||
{% assign poster_url = include.poster %}
|
||||
{% assign types = include.types | default: '' | strip | split: '|' %}
|
||||
|
||||
{% unless video_url contains '://' %}
|
||||
{%- capture video_url -%}
|
||||
{% include media-url.html src=video_url subpath=page.media_subpath %}
|
||||
{%- endcapture -%}
|
||||
{% endunless %}
|
||||
|
||||
{% if poster_url %}
|
||||
{% unless poster_url contains '://' %}
|
||||
{%- capture poster_url -%}
|
||||
{% include media-url.html src=poster_url subpath=page.media_subpath %}
|
||||
{%- endcapture -%}
|
||||
{% endunless %}
|
||||
{% assign poster = 'poster="' | append: poster_url | append: '"' %}
|
||||
{% endif %}
|
||||
|
||||
{% assign attributes = 'controls' %}
|
||||
|
||||
{% if include.autoplay %}
|
||||
{% assign attributes = attributes | append: ' ' | append: 'autoplay' %}
|
||||
{% endif %}
|
||||
|
||||
{% if include.loop %}
|
||||
{% assign attributes = attributes | append: ' ' | append: 'loop' %}
|
||||
{% endif %}
|
||||
|
||||
{% if include.muted %}
|
||||
{% assign attributes = attributes | append: ' ' | append: 'muted' %}
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
<video class="embed-video file" {{ poster }} {{ attributes }}>
|
||||
{% assign extension = video_url | split: '.' | last %}
|
||||
{% assign types = extension | concat: types %}
|
||||
|
||||
{% assign ext_size = extension | size %}
|
||||
{% assign src_size = video_url | size %}
|
||||
{% assign slice_size = src_size | minus: ext_size %}
|
||||
|
||||
{% assign filepath = video_url | slice: 0, slice_size %}
|
||||
|
||||
{% for type in types %}
|
||||
{% assign src = filepath | append: type %}
|
||||
{% assign media_item = site.data.media | find: 'extension', type %}
|
||||
{% assign mime_type = media_item.mime_type | default: type %}
|
||||
<source src="{{ src }}" type="video/{{ mime_type }}">
|
||||
{% endfor %}
|
||||
|
||||
Your browser does not support the video tag. Here is a
|
||||
<a href="{{ video_url | strip }}">link to the video file</a> instead.
|
||||
</video>
|
||||
{% if title %}
|
||||
<em>{{ title }}</em>
|
||||
{% endif %}
|
||||
</p>
|
||||
@@ -1,5 +1,5 @@
|
||||
<iframe
|
||||
class="embed-video youtube"
|
||||
class="embed-video"
|
||||
loading="lazy"
|
||||
src="https://www.youtube.com/embed/{{ include.id }}"
|
||||
title="YouTube video player"
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ favicon_path }}/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ favicon_path }}/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ favicon_path }}/favicon-16x16.png">
|
||||
<link rel="manifest" href="{{ favicon_path }}/site.webmanifest">
|
||||
{% if site.pwa.enabled %}
|
||||
<link rel="manifest" href="{{ favicon_path }}/site.webmanifest">
|
||||
{% endif %}
|
||||
<link rel="shortcut icon" href="{{ favicon_path }}/favicon.ico">
|
||||
<meta name="apple-mobile-web-app-title" content="{{ site.title }}">
|
||||
<meta name="application-name" content="{{ site.title }}">
|
||||
|
||||
@@ -8,9 +8,15 @@
|
||||
"
|
||||
>
|
||||
<p>
|
||||
{{ '©' }}
|
||||
{{- '©' }}
|
||||
<time>{{ 'now' | date: '%Y' }}</time>
|
||||
<a href="{{ site.social.links[0] }}">{{ site.social.name }}</a>.
|
||||
|
||||
{% if site.social.links %}
|
||||
<a href="{{ site.social.links[0] }}">{{ site.social.name }}</a>.
|
||||
{% else %}
|
||||
<em class="fst-normal">{{ site.social.name }}</em>.
|
||||
{% endif %}
|
||||
|
||||
{% if site.data.locales[include.lang].copyright.brief %}
|
||||
<span
|
||||
data-bs-toggle="tooltip"
|
||||
@@ -28,7 +34,14 @@
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture _theme -%}
|
||||
<a href="https://github.com/cotes2020/jekyll-theme-chirpy" target="_blank" rel="noopener">Chirpy</a>
|
||||
<a
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="v{{ theme.version }}"
|
||||
href="https://github.com/cotes2020/jekyll-theme-chirpy"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>Chirpy</a>
|
||||
{%- endcapture -%}
|
||||
|
||||
{{ site.data.locales[include.lang].meta | replace: ':PLATFORM', _platform | replace: ':THEME', _theme }}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
<!--
|
||||
The GA snippet
|
||||
-->
|
||||
<!-- Global site tag (gtag.js) - Google Analytics -->
|
||||
<script defer src="https://www.googletagmanager.com/gtag/js?id={{ site.google_analytics.id }}"></script>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function(event) {
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
|
||||
gtag('js', new Date());
|
||||
gtag('config', '{{ site.google_analytics.id }}');
|
||||
});
|
||||
</script>
|
||||
@@ -1,39 +1,51 @@
|
||||
<!-- The Head -->
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#f7f7f7">
|
||||
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="#1b1b1e">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, user-scalable=no initial-scale=1, shrink-to-fit=no, viewport-fit=cover"
|
||||
>
|
||||
|
||||
{% capture seo_tags %}
|
||||
{%- capture seo_tags -%}
|
||||
{% seo title=false %}
|
||||
{% endcapture %}
|
||||
{%- endcapture -%}
|
||||
|
||||
<!-- Setup Open Graph image -->
|
||||
|
||||
{% if page.image %}
|
||||
{% assign img = page.image.path | default: page.image %}
|
||||
{% assign src = page.image.path | default: page.image %}
|
||||
|
||||
{% unless img contains '://' %}
|
||||
{% assign img_path = page.img_path | append: '/' | append: img | replace: '//', '/' %}
|
||||
{% capture target %}"{{ img | absolute_url }}"{% endcapture %}
|
||||
{% unless src contains '://' %}
|
||||
{%- capture img_url -%}
|
||||
{% include media-url.html src=src subpath=page.media_subpath absolute=true %}
|
||||
{%- endcapture -%}
|
||||
|
||||
{% if site.img_cdn contains '//' %}
|
||||
<!-- it's a cross-origin URL -->
|
||||
{% capture replacement %}"{{ site.img_cdn }}{{ img_path }}"{% endcapture %}
|
||||
{% else %}
|
||||
<!-- it's a local file path -->
|
||||
{%- capture replacement -%}
|
||||
"{{ site.img_cdn | append: '/' | append: img_path | replace: '//', '/' | absolute_url }}"
|
||||
{%- endcapture -%}
|
||||
{% endif %}
|
||||
{%- capture old_url -%}{{ src | absolute_url }}{%- endcapture -%}
|
||||
{%- capture new_url -%}{{ img_url }}{%- endcapture -%}
|
||||
|
||||
{% assign seo_tags = seo_tags | replace: target, replacement %}
|
||||
{% assign seo_tags = seo_tags | replace: old_url, new_url %}
|
||||
{% endunless %}
|
||||
|
||||
{% elsif site.social_preview_image %}
|
||||
{%- capture img_url -%}
|
||||
{% include media-url.html src=site.social_preview_image absolute=true %}
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture og_image -%}
|
||||
<meta property="og:image" content="{{ img_url }}" />
|
||||
{%- endcapture -%}
|
||||
|
||||
{%- capture twitter_image -%}
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:image" content="{{ img_url }}" />
|
||||
{%- endcapture -%}
|
||||
|
||||
{% assign old_meta_clip = '<meta name="twitter:card" content="summary" />' %}
|
||||
{% assign new_meta_clip = og_image | append: twitter_image %}
|
||||
{% assign seo_tags = seo_tags | replace: old_meta_clip, new_meta_clip %}
|
||||
{% endif %}
|
||||
|
||||
{{ seo_tags }}
|
||||
@@ -47,34 +59,30 @@
|
||||
|
||||
{% include_cached favicons.html %}
|
||||
|
||||
{% if site.resources.ignore_env != jekyll.environment and site.resources.self_hosted %}
|
||||
<link href="{{ site.data.origin[type].webfonts | relative_url }}" rel="stylesheet">
|
||||
|
||||
{% else %}
|
||||
{% for cdn in site.data.origin[type].cdns %}
|
||||
<link rel="preconnect" href="{{ cdn.url }}" {{ cdn.args }}>
|
||||
<link rel="dns-prefetch" href="{{ cdn.url }}" {{ cdn.args }}>
|
||||
<!-- Resource Hints -->
|
||||
{% unless site.assets.self_host.enabled %}
|
||||
{% for hint in site.data.origin.cors.resource_hints %}
|
||||
{% for link in hint.links %}
|
||||
<link rel="{{ link.rel }}" href="{{ hint.url }}" {{ link.opts | join: ' ' }}>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type].webfonts | relative_url }}">
|
||||
{% endif %}
|
||||
|
||||
<!-- GA -->
|
||||
{% if jekyll.environment == 'production' and site.google_analytics.id != empty and site.google_analytics.id %}
|
||||
<link rel="preconnect" href="https://www.google-analytics.com" crossorigin="use-credentials">
|
||||
<link rel="dns-prefetch" href="https://www.google-analytics.com">
|
||||
|
||||
<link rel="preconnect" href="https://www.googletagmanager.com" crossorigin="anonymous">
|
||||
<link rel="dns-prefetch" href="https://www.googletagmanager.com">
|
||||
{% endif %}
|
||||
{% endunless %}
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type].bootstrap.css | relative_url}}">
|
||||
{% unless jekyll.environment == 'production' %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
|
||||
{% endunless %}
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<!-- Theme style -->
|
||||
<link rel="stylesheet" href="{{ '/assets/css/:THEME.css' | replace: ':THEME', site.theme | relative_url }}">
|
||||
|
||||
<!-- Web Font -->
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type].webfonts | relative_url }}">
|
||||
|
||||
<!-- Font Awesome Icons -->
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type].fontawesome.css | relative_url }}">
|
||||
|
||||
<link rel="stylesheet" href="{{ '/assets/css/:THEME.css' | replace: ':THEME', site.theme | relative_url }}">
|
||||
<!-- 3rd-party Dependencies -->
|
||||
|
||||
{% if site.toc and page.toc %}
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type].toc.css | relative_url }}">
|
||||
@@ -85,15 +93,36 @@
|
||||
{% endif %}
|
||||
|
||||
{% if page.layout == 'page' or page.layout == 'post' %}
|
||||
<!-- Manific Popup -->
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type].magnific-popup.css | relative_url }}">
|
||||
<!-- Image Popup -->
|
||||
<link rel="stylesheet" href="{{ site.data.origin[type].glightbox.css | relative_url }}">
|
||||
{% endif %}
|
||||
|
||||
<!-- JavaScript -->
|
||||
<!-- Scripts -->
|
||||
|
||||
{% unless site.theme_mode %}
|
||||
{% include mode-toggle.html %}
|
||||
<script src="{{ '/assets/js/dist/theme.min.js' | relative_url }}"></script>
|
||||
{% endunless %}
|
||||
|
||||
{% include js-selector.html lang=lang %}
|
||||
|
||||
{% if jekyll.environment == 'production' %}
|
||||
<!-- PWA -->
|
||||
{% if site.pwa.enabled %}
|
||||
<script
|
||||
defer
|
||||
src="{{ '/app.min.js' | relative_url }}?baseurl={{ site.baseurl | default: '' }}®ister={{ site.pwa.cache.enabled }}"
|
||||
></script>
|
||||
{% endif %}
|
||||
|
||||
<!-- Web Analytics -->
|
||||
{% for analytics in site.analytics %}
|
||||
{% capture str %}{{ analytics }}{% endcapture %}
|
||||
{% assign platform = str | split: '{' | first %}
|
||||
{% if site.analytics[platform].id and site.analytics[platform].id != empty %}
|
||||
{% include analytics/{{ platform }}.html %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% include metadata-hook.html %}
|
||||
</head>
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
|
||||
<!-- commons -->
|
||||
|
||||
{% assign urls = site.data.origin[type].jquery.js
|
||||
| append: ','
|
||||
| append: site.data.origin[type].bootstrap.js
|
||||
| append: ','
|
||||
| append: site.data.origin[type].search.js
|
||||
%}
|
||||
{% assign urls = site.data.origin[type].search.js %}
|
||||
|
||||
<!-- layout specified -->
|
||||
|
||||
@@ -18,7 +13,7 @@
|
||||
<!-- image lazy-loading & popup & clipboard -->
|
||||
{% assign urls = urls
|
||||
| append: ','
|
||||
| append: site.data.origin[type]['magnific-popup'].js
|
||||
| append: site.data.origin[type].glightbox.js
|
||||
| append: ','
|
||||
| append: site.data.origin[type].clipboard.js
|
||||
%}
|
||||
@@ -31,7 +26,7 @@
|
||||
or page.layout == 'category'
|
||||
or page.layout == 'tag'
|
||||
%}
|
||||
{% assign locale = site.lang | split: '-' | first %}
|
||||
{% assign locale = include.lang | split: '-' | first %}
|
||||
|
||||
{% assign urls = urls
|
||||
| append: ','
|
||||
@@ -66,41 +61,26 @@
|
||||
{% endcase %}
|
||||
|
||||
{% capture script %}/assets/js/dist/{{ js }}.min.js{% endcapture %}
|
||||
|
||||
<script defer src="{{ script | relative_url }}"></script>
|
||||
|
||||
{% if page.math %}
|
||||
<!-- MathJax -->
|
||||
<script>
|
||||
/* see: <https://docs.mathjax.org/en/latest/options/input/tex.html#tex-options> */
|
||||
MathJax = {
|
||||
tex: {
|
||||
/* start/end delimiter pairs for in-line math */
|
||||
inlineMath: [
|
||||
['$', '$'],
|
||||
['\\(', '\\)']
|
||||
],
|
||||
/* start/end delimiter pairs for display math */
|
||||
displayMath: [
|
||||
['$$', '$$'],
|
||||
['\\[', '\\]']
|
||||
]
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
|
||||
<script async src="{{ '/assets/js/data/mathjax.js' | relative_url }}"></script>
|
||||
<script async src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=es6"></script>
|
||||
<script id="MathJax-script" async src="{{ site.data.origin[type].mathjax.js | relative_url }}"></script>
|
||||
{% endif %}
|
||||
|
||||
{% if jekyll.environment == 'production' %}
|
||||
<!-- PWA -->
|
||||
{% if site.pwa.enabled %}
|
||||
<script defer src="{{ '/app.js' | relative_url }}"></script>
|
||||
{% else %}
|
||||
<script defer src="{{ '/unregister.js' | relative_url }}"></script>
|
||||
{% endif %}
|
||||
<!-- Pageviews -->
|
||||
{% if page.layout == 'post' %}
|
||||
{% assign provider = site.pageviews.provider %}
|
||||
|
||||
<!-- GA -->
|
||||
{% if site.google_analytics.id != empty and site.google_analytics.id %}
|
||||
{% include google-analytics.html %}
|
||||
{% if provider and provider != empty %}
|
||||
{% case provider %}
|
||||
{% when 'goatcounter' %}
|
||||
{% if site.analytics[provider].id != empty and site.analytics[provider].id %}
|
||||
{% include pageviews/{{ provider }}.html %}
|
||||
{% endif %}
|
||||
{% endcase %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% assign urls = include.urls | split: ',' %}
|
||||
|
||||
{% assign combined_urls = nil %}
|
||||
{% assign combined_urls = null %}
|
||||
|
||||
{% assign domain = 'https://cdn.jsdelivr.net/' %}
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
{% endif %}
|
||||
|
||||
{% elsif url contains '//' %}
|
||||
<script src="{{ url }}"></script>
|
||||
<script defer src="{{ url }}"></script>
|
||||
{% else %}
|
||||
<script src="{{ url | relative_url }}"></script>
|
||||
<script defer src="{{ url | relative_url }}"></script>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if combined_urls %}
|
||||
<script src="{{ combined_urls }}"></script>
|
||||
<script defer src="{{ combined_urls }}"></script>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
{% comment %}
|
||||
Detect appearance language and return it through variable "lang"
|
||||
{% endcomment %}
|
||||
{% if site.data.locales[site.lang] %}
|
||||
{% if site.data.locales[page.lang] %}
|
||||
{% assign lang = page.lang %}
|
||||
{% elsif site.data.locales[site.lang] %}
|
||||
{% assign lang = site.lang %}
|
||||
{% else %}
|
||||
{% assign lang = 'en' %}
|
||||
|
||||
37
_includes/media-url.html
Normal file
37
_includes/media-url.html
Normal file
@@ -0,0 +1,37 @@
|
||||
{%- comment -%}
|
||||
Generate media resource final URL based on `site.cdn`, `page.media_subpath`
|
||||
|
||||
Arguments:
|
||||
src - required, basic media resources path
|
||||
subpath - optional, relative path of media resources
|
||||
absolute - optional, boolean, if true, generate absolute URL
|
||||
|
||||
Return:
|
||||
media resources URL
|
||||
{%- endcomment -%}
|
||||
|
||||
{% assign url = include.src %}
|
||||
|
||||
{%- if url -%}
|
||||
{% unless url contains ':' %}
|
||||
{%- comment -%} Add media resources subpath prefix {%- endcomment -%}
|
||||
{% assign url = include.subpath | default: '' | append: '/' | append: url %}
|
||||
|
||||
{%- comment -%} Prepend CND URL {%- endcomment -%}
|
||||
{% if site.cdn %}
|
||||
{% assign url = site.cdn | append: '/' | append: url %}
|
||||
{% endif %}
|
||||
|
||||
{% assign url = url | replace: '///', '/' | replace: '//', '/' | replace: ':/', '://' %}
|
||||
|
||||
{% unless url contains '://' %}
|
||||
{% if include.absolute %}
|
||||
{% assign url = site.url | append: site.baseurl | append: url %}
|
||||
{% else %}
|
||||
{% assign url = site.baseurl | append: url %}
|
||||
{% endif %}
|
||||
{% endunless %}
|
||||
{% endunless %}
|
||||
{%- endif -%}
|
||||
|
||||
{{- url -}}
|
||||
@@ -1,58 +0,0 @@
|
||||
<!-- mermaid-js loader -->
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
function updateMermaid(event) {
|
||||
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
||||
const mode = event.data.message;
|
||||
|
||||
if (typeof mermaid === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
let expectedTheme = mode === ModeToggle.DARK_MODE ? 'dark' : 'default';
|
||||
let config = { theme: expectedTheme };
|
||||
|
||||
/* Re-render the SVG › <https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344> */
|
||||
$('.mermaid').each(function () {
|
||||
let svgCode = $(this).prev().children().html();
|
||||
$(this).removeAttr('data-processed');
|
||||
$(this).html(svgCode);
|
||||
});
|
||||
|
||||
mermaid.initialize(config);
|
||||
mermaid.init(undefined, '.mermaid');
|
||||
}
|
||||
}
|
||||
|
||||
let initTheme = 'default';
|
||||
const html = document.documentElement;
|
||||
|
||||
if (
|
||||
(html.hasAttribute('data-mode') && html.getAttribute('data-mode') === 'dark') ||
|
||||
(!html.hasAttribute('data-mode') && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||
) {
|
||||
initTheme = 'dark';
|
||||
}
|
||||
|
||||
let mermaidConf = {
|
||||
theme: initTheme /* <default|dark|forest|neutral> */
|
||||
};
|
||||
|
||||
/* Create mermaid tag */
|
||||
document.querySelectorAll('pre>code.language-mermaid').forEach((elem) => {
|
||||
const svgCode = elem.textContent;
|
||||
const backup = elem.parentElement;
|
||||
backup.classList.add('unloaded');
|
||||
/* create mermaid node */
|
||||
let mermaid = document.createElement('pre');
|
||||
mermaid.classList.add('mermaid');
|
||||
const text = document.createTextNode(svgCode);
|
||||
mermaid.appendChild(text);
|
||||
backup.after(mermaid);
|
||||
});
|
||||
|
||||
mermaid.initialize(mermaidConf);
|
||||
|
||||
window.addEventListener('message', updateMermaid);
|
||||
})();
|
||||
</script>
|
||||
@@ -1,143 +0,0 @@
|
||||
<!-- Switch the mode between dark and light. -->
|
||||
|
||||
<script type="text/javascript">
|
||||
class ModeToggle {
|
||||
static get MODE_KEY() {
|
||||
return 'mode';
|
||||
}
|
||||
static get MODE_ATTR() {
|
||||
return 'data-mode';
|
||||
}
|
||||
static get DARK_MODE() {
|
||||
return 'dark';
|
||||
}
|
||||
static get LIGHT_MODE() {
|
||||
return 'light';
|
||||
}
|
||||
static get ID() {
|
||||
return 'mode-toggle';
|
||||
}
|
||||
|
||||
constructor() {
|
||||
if (this.hasMode) {
|
||||
if (this.isDarkMode) {
|
||||
if (!this.isSysDarkPrefer) {
|
||||
this.setDark();
|
||||
}
|
||||
} else {
|
||||
if (this.isSysDarkPrefer) {
|
||||
this.setLight();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let self = this;
|
||||
|
||||
/* always follow the system prefers */
|
||||
this.sysDarkPrefers.addEventListener('change', () => {
|
||||
if (self.hasMode) {
|
||||
if (self.isDarkMode) {
|
||||
if (!self.isSysDarkPrefer) {
|
||||
self.setDark();
|
||||
}
|
||||
} else {
|
||||
if (self.isSysDarkPrefer) {
|
||||
self.setLight();
|
||||
}
|
||||
}
|
||||
|
||||
self.clearMode();
|
||||
}
|
||||
|
||||
self.notify();
|
||||
});
|
||||
} /* constructor() */
|
||||
|
||||
get sysDarkPrefers() {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)');
|
||||
}
|
||||
|
||||
get isSysDarkPrefer() {
|
||||
return this.sysDarkPrefers.matches;
|
||||
}
|
||||
|
||||
get isDarkMode() {
|
||||
return this.mode === ModeToggle.DARK_MODE;
|
||||
}
|
||||
|
||||
get isLightMode() {
|
||||
return this.mode === ModeToggle.LIGHT_MODE;
|
||||
}
|
||||
|
||||
get hasMode() {
|
||||
return this.mode != null;
|
||||
}
|
||||
|
||||
get mode() {
|
||||
return sessionStorage.getItem(ModeToggle.MODE_KEY);
|
||||
}
|
||||
|
||||
/* get the current mode on screen */
|
||||
get modeStatus() {
|
||||
if (this.isDarkMode || (!this.hasMode && this.isSysDarkPrefer)) {
|
||||
return ModeToggle.DARK_MODE;
|
||||
} else {
|
||||
return ModeToggle.LIGHT_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
setDark() {
|
||||
document.documentElement.setAttribute(ModeToggle.MODE_ATTR, ModeToggle.DARK_MODE);
|
||||
sessionStorage.setItem(ModeToggle.MODE_KEY, ModeToggle.DARK_MODE);
|
||||
}
|
||||
|
||||
setLight() {
|
||||
document.documentElement.setAttribute(ModeToggle.MODE_ATTR, ModeToggle.LIGHT_MODE);
|
||||
sessionStorage.setItem(ModeToggle.MODE_KEY, ModeToggle.LIGHT_MODE);
|
||||
}
|
||||
|
||||
clearMode() {
|
||||
document.documentElement.removeAttribute(ModeToggle.MODE_ATTR);
|
||||
sessionStorage.removeItem(ModeToggle.MODE_KEY);
|
||||
}
|
||||
|
||||
/* Notify another plugins that the theme mode has changed */
|
||||
notify() {
|
||||
window.postMessage(
|
||||
{
|
||||
direction: ModeToggle.ID,
|
||||
message: this.modeStatus
|
||||
},
|
||||
'*'
|
||||
);
|
||||
}
|
||||
|
||||
flipMode() {
|
||||
if (this.hasMode) {
|
||||
if (this.isSysDarkPrefer) {
|
||||
if (this.isLightMode) {
|
||||
this.clearMode();
|
||||
} else {
|
||||
this.setLight();
|
||||
}
|
||||
} else {
|
||||
if (this.isDarkMode) {
|
||||
this.clearMode();
|
||||
} else {
|
||||
this.setDark();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.isSysDarkPrefer) {
|
||||
this.setLight();
|
||||
} else {
|
||||
this.setDark();
|
||||
}
|
||||
}
|
||||
|
||||
this.notify();
|
||||
} /* flipMode() */
|
||||
} /* ModeToggle */
|
||||
|
||||
const modeToggle = new ModeToggle();
|
||||
</script>
|
||||
19
_includes/pageviews/goatcounter.html
Normal file
19
_includes/pageviews/goatcounter.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!-- Display GoatCounter pageviews -->
|
||||
<script>
|
||||
let pv = document.getElementById('pageviews');
|
||||
|
||||
if (pv !== null) {
|
||||
const uri = location.pathname.replace(/\/$/, '');
|
||||
const url = `https://{{ site.analytics.goatcounter.id }}.goatcounter.com/counter/${encodeURIComponent(uri)}.json`;
|
||||
|
||||
fetch(url)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
const count = data.count.replace(/\s/g, '');
|
||||
pv.innerText = new Intl.NumberFormat().format(count);
|
||||
})
|
||||
.catch((error) => {
|
||||
pv.innerText = '1';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
16
_includes/post-description.html
Normal file
16
_includes/post-description.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{%- comment -%}
|
||||
Get post description or generate it from the post content.
|
||||
{%- endcomment -%}
|
||||
|
||||
{%- assign max_length = include.max_length | default: 200 -%}
|
||||
|
||||
{%- capture description -%}
|
||||
{%- if post.description -%}
|
||||
{{- post.description -}}
|
||||
{%- else -%}
|
||||
{%- include no-linenos.html content=post.content -%}
|
||||
{{- content | markdownify | strip_html -}}
|
||||
{%- endif -%}
|
||||
{%- endcapture -%}
|
||||
|
||||
{{- description | strip | truncate: max_length | escape -}}
|
||||
@@ -48,23 +48,6 @@
|
||||
{% assign _img_content = null %}
|
||||
{% assign _img_snippets = _content | split: IMG_TAG %}
|
||||
|
||||
<!-- CDN URL -->
|
||||
{% if site.img_cdn %}
|
||||
{% if site.img_cdn contains '//' %}
|
||||
{% assign _path_prefix = site.img_cdn %}
|
||||
{% else %}
|
||||
{% assign _path_prefix = site.img_cdn | relative_url %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% assign _path_prefix = site.baseurl %}
|
||||
{% endif %}
|
||||
|
||||
<!-- Add image path -->
|
||||
{% if page.img_path %}
|
||||
{% assign _path = page.img_path | append: '/' | replace: '//', '/' %}
|
||||
{% assign _path_prefix = _path_prefix | append: _path %}
|
||||
{% endif %}
|
||||
|
||||
{% for _img_snippet in _img_snippets %}
|
||||
{% if forloop.first %}
|
||||
{% assign _img_content = _img_snippet %}
|
||||
@@ -113,6 +96,12 @@
|
||||
{% assign _final_src = null %}
|
||||
{% assign _lazyload = true %}
|
||||
|
||||
{%- capture _img_url -%}
|
||||
{% include media-url.html src=_src subpath=page.media_subpath %}
|
||||
{%- endcapture -%}
|
||||
|
||||
{% assign _path_prefix = _img_url | remove: _src %}
|
||||
|
||||
{% unless _src contains '//' %}
|
||||
{% assign _final_src = _path_prefix | append: _src %}
|
||||
{% assign _src_alt = 'src="' | append: _path_prefix %}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
{% assign match_posts = match_posts | push: site.tags[tag] | uniq %}
|
||||
{% endfor %}
|
||||
|
||||
{% assign match_posts = match_posts | reverse %}
|
||||
{% assign last_index = match_posts.size | minus: 1 %}
|
||||
{% assign score_list = '' | split: '' %}
|
||||
|
||||
@@ -81,10 +82,7 @@
|
||||
{% include datetime.html date=post.date lang=include.lang %}
|
||||
<h4 class="pt-0 my-2">{{ post.title }}</h4>
|
||||
<div class="text-muted">
|
||||
<p>
|
||||
{% include no-linenos.html content=post.content %}
|
||||
{{ content | markdownify | strip_html | truncate: 200 | escape }}
|
||||
</p>
|
||||
<p>{% include post-description.html %}</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
@@ -19,29 +19,31 @@
|
||||
{% capture not_found %}<p class="mt-5">{{ site.data.locales[include.lang].search.no_results }}</p>{% endcapture %}
|
||||
|
||||
<script>
|
||||
/* Note: dependent library will be loaded in `js-selector.html` */
|
||||
SimpleJekyllSearch({
|
||||
searchInput: document.getElementById('search-input'),
|
||||
resultsContainer: document.getElementById('search-results'),
|
||||
json: '{{ '/assets/js/data/search.json' | relative_url }}',
|
||||
searchResultTemplate: '{{ result_elem | strip_newlines }}',
|
||||
noResultsText: '{{ not_found }}',
|
||||
templateMiddleware: function(prop, value, template) {
|
||||
if (prop === 'categories') {
|
||||
if (value === '') {
|
||||
return `${value}`;
|
||||
} else {
|
||||
return `<div class="me-sm-4"><i class="far fa-folder fa-fw"></i>${value}</div>`;
|
||||
{% comment %} Note: dependent library will be loaded in `js-selector.html` {% endcomment %}
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
SimpleJekyllSearch({
|
||||
searchInput: document.getElementById('search-input'),
|
||||
resultsContainer: document.getElementById('search-results'),
|
||||
json: '{{ '/assets/js/data/search.json' | relative_url }}',
|
||||
searchResultTemplate: '{{ result_elem | strip_newlines }}',
|
||||
noResultsText: '{{ not_found }}',
|
||||
templateMiddleware: function(prop, value, template) {
|
||||
if (prop === 'categories') {
|
||||
if (value === '') {
|
||||
return `${value}`;
|
||||
} else {
|
||||
return `<div class="me-sm-4"><i class="far fa-folder fa-fw"></i>${value}</div>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prop === 'tags') {
|
||||
if (value === '') {
|
||||
return `${value}`;
|
||||
} else {
|
||||
return `<div><i class="fa fa-tag fa-fw"></i>${value}</div>`;
|
||||
if (prop === 'tags') {
|
||||
if (value === '') {
|
||||
return `${value}`;
|
||||
} else {
|
||||
return `<div><i class="fa fa-tag fa-fw"></i>${value}</div>`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- The Search results -->
|
||||
|
||||
<div id="search-result-wrapper" class="d-flex justify-content-center unloaded">
|
||||
<div id="search-result-wrapper" class="d-flex justify-content-center d-none">
|
||||
<div class="col-11 content">
|
||||
<div id="search-hints">
|
||||
{% include_cached trending-tags.html %}
|
||||
|
||||
@@ -3,23 +3,15 @@
|
||||
<aside aria-label="Sidebar" id="sidebar" class="d-flex flex-column align-items-end">
|
||||
<header class="profile-wrapper">
|
||||
<a href="{{ '/' | relative_url }}" id="avatar" class="rounded-circle">
|
||||
{% if site.avatar != empty and site.avatar %}
|
||||
{% capture avatar_url %}
|
||||
{% if site.avatar contains '://' %}
|
||||
{{ site.avatar }}
|
||||
{% elsif site.img_cdn != empty and site.img_cdn %}
|
||||
{{ site.avatar | prepend: site.img_cdn }}
|
||||
{% else %}
|
||||
{{ site.avatar | relative_url }}
|
||||
{% endif %}
|
||||
{% endcapture %}
|
||||
<img src="{{ avatar_url | strip }}" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
|
||||
{% endif %}
|
||||
{%- if site.avatar != empty and site.avatar -%}
|
||||
{%- capture avatar_url -%}
|
||||
{% include media-url.html src=site.avatar %}
|
||||
{%- endcapture -%}
|
||||
<img src="{{- avatar_url -}}" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
|
||||
{%- endif -%}
|
||||
</a>
|
||||
|
||||
<h1 class="site-title">
|
||||
<a href="{{ '/' | relative_url }}">{{ site.title }}</a>
|
||||
</h1>
|
||||
<a class="site-title d-block" href="{{ '/' | relative_url }}">{{ site.title }}</a>
|
||||
<p class="site-subtitle fst-italic mb-0">{{ site.tagline }}</p>
|
||||
</header>
|
||||
<!-- .profile-wrapper -->
|
||||
@@ -50,7 +42,7 @@
|
||||
|
||||
<div class="sidebar-bottom d-flex flex-wrap align-items-center w-100">
|
||||
{% unless site.theme_mode %}
|
||||
<button type="button" class="mode-toggle btn" aria-label="Switch Mode">
|
||||
<button type="button" class="btn btn-link nav-link" aria-label="Switch Mode" id="mode-toggle">
|
||||
<i class="fas fa-adjust"></i>
|
||||
</button>
|
||||
|
||||
|
||||
10
_includes/toc-status.html
Normal file
10
_includes/toc-status.html
Normal file
@@ -0,0 +1,10 @@
|
||||
{% comment %}
|
||||
Determine TOC state and return it through variable "enable_toc"
|
||||
{% endcomment %}
|
||||
|
||||
{% assign enable_toc = false %}
|
||||
{% if site.toc and page.toc %}
|
||||
{% if page.content contains '<h2' or page.content contains '<h3' %}
|
||||
{% assign enable_toc = true %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
@@ -1,13 +1,8 @@
|
||||
{% assign enable_toc = false %}
|
||||
{% if site.toc and page.toc %}
|
||||
{% if page.content contains '<h2' or page.content contains '<h3' %}
|
||||
{% assign enable_toc = true %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% include toc-status.html %}
|
||||
|
||||
{% if enable_toc %}
|
||||
<section id="toc-wrapper" class="ps-0 pe-4">
|
||||
<h2 class="panel-heading ps-3 pt-2 mb-2">{{- site.data.locales[include.lang].panel.toc -}}</h2>
|
||||
<h2 class="panel-heading ps-3 mb-2">{{- site.data.locales[include.lang].panel.toc -}}</h2>
|
||||
<nav id="toc"></nav>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
{% if forloop.first %}
|
||||
<span>
|
||||
<a href="{{ '/' | relative_url }}">
|
||||
{{ site.data.locales[include.lang].tabs.home | capitalize }}
|
||||
{{- site.data.locales[include.lang].tabs.home | capitalize -}}
|
||||
</a>
|
||||
</span>
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
{% elsif page.layout == 'category' or page.layout == 'tag' %}
|
||||
<span>
|
||||
<a href="{{ item | relative_url }}">
|
||||
{{ site.data.locales[include.lang].tabs[item] | default: page.title }}
|
||||
<a href="{{ item | append: '/' | relative_url }}">
|
||||
{{- site.data.locales[include.lang].tabs[item] | default: page.title -}}
|
||||
</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
@@ -59,7 +59,7 @@
|
||||
<i class="fas fa-search fa-fw"></i>
|
||||
</button>
|
||||
|
||||
<search class="align-items-center ms-3 ms-lg-0">
|
||||
<search id="search" class="align-items-center ms-3 ms-lg-0">
|
||||
<i class="fas fa-search fa-fw"></i>
|
||||
<input
|
||||
class="form-control"
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<!-- Get the last 5 posts from lastmod list. -->
|
||||
<!-- Get 5 last posted/updated posts -->
|
||||
|
||||
{% assign MAX_SIZE = 5 %}
|
||||
|
||||
{% assign all_list = '' | split: '' %}
|
||||
|
||||
{% for post in site.posts %}
|
||||
{% if post.last_modified_at and post.last_modified_at != post.date %}
|
||||
{% capture elem %}
|
||||
{{- post.last_modified_at | date: "%Y%m%d%H%M%S" -}}::{{- forloop.index0 -}}
|
||||
{% endcapture %}
|
||||
{% assign all_list = all_list | push: elem %}
|
||||
{% endif %}
|
||||
{% assign datetime = post.last_modified_at | default: post.date %}
|
||||
|
||||
{% capture elem %}
|
||||
{{- datetime | date: "%Y%m%d%H%M%S" -}}::{{- forloop.index0 -}}
|
||||
{% endcapture %}
|
||||
|
||||
{% assign all_list = all_list | push: elem %}
|
||||
{% endfor %}
|
||||
|
||||
{% assign all_list = all_list | sort | reverse %}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Chirpy v<%= pkg.version %> | © 2019 <%= pkg.author %> | <%= pkg.license %> Licensed | <%= pkg.homepage %>
|
||||
@@ -1,5 +1,5 @@
|
||||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||
import { categoryCollapse } from './modules/plugins';
|
||||
import { categoryCollapse } from './modules/components';
|
||||
|
||||
basic();
|
||||
initSidebar();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||
|
||||
basic();
|
||||
initSidebar();
|
||||
initTopbar();
|
||||
basic();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||
import { initLocaleDatetime, loadImg } from './modules/plugins';
|
||||
import { initLocaleDatetime, loadImg } from './modules/components';
|
||||
|
||||
basic();
|
||||
loadImg();
|
||||
initLocaleDatetime();
|
||||
initSidebar();
|
||||
initTopbar();
|
||||
initLocaleDatetime();
|
||||
loadImg();
|
||||
basic();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||
import { initLocaleDatetime } from './modules/plugins';
|
||||
import { initLocaleDatetime } from './modules/components';
|
||||
|
||||
basic();
|
||||
initSidebar();
|
||||
initTopbar();
|
||||
initLocaleDatetime();
|
||||
basic();
|
||||
|
||||
@@ -3,4 +3,8 @@ export { initClipboard } from './components/clipboard';
|
||||
export { loadImg } from './components/img-loading';
|
||||
export { imgPopup } from './components/img-popup';
|
||||
export { initLocaleDatetime } from './components/locale-datetime';
|
||||
export { toc } from './components/toc';
|
||||
export { initToc } from './components/toc';
|
||||
export { loadMermaid } from './components/mermaid';
|
||||
export { modeWatcher } from './components/mode-toggle';
|
||||
export { back2top } from './components/back-to-top';
|
||||
export { loadTooptip } from './components/tooltip-loader';
|
||||
@@ -3,18 +3,17 @@
|
||||
*/
|
||||
|
||||
export function back2top() {
|
||||
const $window = $(window);
|
||||
const $btn = $('#back-to-top');
|
||||
const btn = document.getElementById('back-to-top');
|
||||
|
||||
$window.on('scroll', () => {
|
||||
if ($window.scrollTop() > 50) {
|
||||
$btn.fadeIn();
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.scrollY > 50) {
|
||||
btn.classList.add('show');
|
||||
} else {
|
||||
$btn.fadeOut();
|
||||
btn.classList.remove('show');
|
||||
}
|
||||
});
|
||||
|
||||
$btn.on('click', () => {
|
||||
$window.scrollTop(0);
|
||||
btn.addEventListener('click', () => {
|
||||
window.scrollTo({ top: 0 });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
/**
|
||||
* Tab 'Categories' expand/close effect.
|
||||
*/
|
||||
|
||||
import 'bootstrap/js/src/collapse.js';
|
||||
|
||||
const childPrefix = 'l_';
|
||||
const parentPrefix = 'h_';
|
||||
const collapse = $('.collapse');
|
||||
const children = document.getElementsByClassName('collapse');
|
||||
|
||||
export function categoryCollapse() {
|
||||
/* close up top-category */
|
||||
collapse.on('hide.bs.collapse', function () {
|
||||
/* Bootstrap collapse events. */ const parentId =
|
||||
parentPrefix + $(this).attr('id').substring(childPrefix.length);
|
||||
if (parentId) {
|
||||
$(`#${parentId} .far.fa-folder-open`).attr(
|
||||
'class',
|
||||
'far fa-folder fa-fw'
|
||||
);
|
||||
$(`#${parentId} i.fas`).addClass('rotate');
|
||||
$(`#${parentId}`).removeClass('hide-border-bottom');
|
||||
}
|
||||
});
|
||||
[...children].forEach((elem) => {
|
||||
const id = parentPrefix + elem.id.substring(childPrefix.length);
|
||||
const parent = document.getElementById(id);
|
||||
|
||||
/* expand the top category */
|
||||
collapse.on('show.bs.collapse', function () {
|
||||
const parentId =
|
||||
parentPrefix + $(this).attr('id').substring(childPrefix.length);
|
||||
if (parentId) {
|
||||
$(`#${parentId} .far.fa-folder`).attr(
|
||||
'class',
|
||||
'far fa-folder-open fa-fw'
|
||||
);
|
||||
$(`#${parentId} i.fas`).removeClass('rotate');
|
||||
$(`#${parentId}`).addClass('hide-border-bottom');
|
||||
}
|
||||
// collapse sub-categories
|
||||
elem.addEventListener('hide.bs.collapse', () => {
|
||||
if (parent) {
|
||||
parent.querySelector('.far.fa-folder-open').className =
|
||||
'far fa-folder fa-fw';
|
||||
parent.querySelector('.fas.fa-angle-down').classList.add('rotate');
|
||||
parent.classList.remove('hide-border-bottom');
|
||||
}
|
||||
});
|
||||
|
||||
// expand sub-categories
|
||||
elem.addEventListener('show.bs.collapse', () => {
|
||||
if (parent) {
|
||||
parent.querySelector('.far.fa-folder').className =
|
||||
'far fa-folder-open fa-fw';
|
||||
parent.querySelector('.fas.fa-angle-down').classList.remove('rotate');
|
||||
parent.classList.add('hide-border-bottom');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,107 +2,113 @@
|
||||
* Clipboard functions
|
||||
*
|
||||
* Dependencies:
|
||||
* - popper.js (https://github.com/popperjs/popper-core)
|
||||
* - clipboard.js (https://github.com/zenorocha/clipboard.js)
|
||||
* clipboard.js (https://github.com/zenorocha/clipboard.js)
|
||||
*/
|
||||
|
||||
import Tooltip from 'bootstrap/js/src/tooltip';
|
||||
|
||||
const clipboardSelector = '.code-header>button';
|
||||
|
||||
const ICON_DEFAULT = 'far fa-clipboard';
|
||||
const ICON_SUCCESS = 'fas fa-check';
|
||||
|
||||
const ATTR_TIMEOUT = 'timeout';
|
||||
const ATTR_TITLE_SUCCEED = 'data-title-succeed';
|
||||
const ATTR_TITLE_ORIGIN = 'data-bs-original-title';
|
||||
const TIMEOUT = 2000; // in milliseconds
|
||||
|
||||
function isLocked(node) {
|
||||
if ($(node)[0].hasAttribute(ATTR_TIMEOUT)) {
|
||||
let timeout = $(node).attr(ATTR_TIMEOUT);
|
||||
if (node.hasAttribute(ATTR_TIMEOUT)) {
|
||||
let timeout = node.getAttribute(ATTR_TIMEOUT);
|
||||
if (Number(timeout) > Date.now()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function lock(node) {
|
||||
$(node).attr(ATTR_TIMEOUT, Date.now() + TIMEOUT);
|
||||
node.setAttribute(ATTR_TIMEOUT, Date.now() + TIMEOUT);
|
||||
}
|
||||
|
||||
function unlock(node) {
|
||||
$(node).removeAttr(ATTR_TIMEOUT);
|
||||
node.removeAttribute(ATTR_TIMEOUT);
|
||||
}
|
||||
|
||||
function getIcon(btn) {
|
||||
let iconNode = $(btn).children();
|
||||
return iconNode.attr('class');
|
||||
}
|
||||
|
||||
const ICON_DEFAULT = getIcon(clipboardSelector);
|
||||
|
||||
function showTooltip(btn) {
|
||||
const succeedTitle = $(btn).attr(ATTR_TITLE_SUCCEED);
|
||||
$(btn).attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show');
|
||||
const succeedTitle = btn.getAttribute(ATTR_TITLE_SUCCEED);
|
||||
btn.setAttribute(ATTR_TITLE_ORIGIN, succeedTitle);
|
||||
Tooltip.getInstance(btn).show();
|
||||
}
|
||||
|
||||
function hideTooltip(btn) {
|
||||
$(btn).tooltip('hide').removeAttr(ATTR_TITLE_ORIGIN);
|
||||
Tooltip.getInstance(btn).hide();
|
||||
btn.removeAttribute(ATTR_TITLE_ORIGIN);
|
||||
}
|
||||
|
||||
function setSuccessIcon(btn) {
|
||||
let btnNode = $(btn);
|
||||
let iconNode = btnNode.children();
|
||||
iconNode.attr('class', ICON_SUCCESS);
|
||||
const icon = btn.children[0];
|
||||
icon.setAttribute('class', ICON_SUCCESS);
|
||||
}
|
||||
|
||||
function resumeIcon(btn) {
|
||||
let btnNode = $(btn);
|
||||
let iconNode = btnNode.children();
|
||||
iconNode.attr('class', ICON_DEFAULT);
|
||||
const icon = btn.children[0];
|
||||
icon.setAttribute('class', ICON_DEFAULT);
|
||||
}
|
||||
|
||||
export function initClipboard() {
|
||||
// Initial the clipboard.js object
|
||||
if ($(clipboardSelector).length) {
|
||||
const clipboard = new ClipboardJS(clipboardSelector, {
|
||||
target(trigger) {
|
||||
let codeBlock = trigger.parentNode.nextElementSibling;
|
||||
return codeBlock.querySelector('code .rouge-code');
|
||||
}
|
||||
});
|
||||
function setCodeClipboard() {
|
||||
const clipboardList = document.querySelectorAll(clipboardSelector);
|
||||
|
||||
const clipboardList = document.querySelectorAll(clipboardSelector);
|
||||
[...clipboardList].map(
|
||||
(elem) =>
|
||||
new bootstrap.Tooltip(elem, {
|
||||
placement: 'left'
|
||||
})
|
||||
);
|
||||
|
||||
clipboard.on('success', (e) => {
|
||||
e.clearSelection();
|
||||
|
||||
const trigger = e.trigger;
|
||||
if (isLocked(trigger)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSuccessIcon(trigger);
|
||||
showTooltip(trigger);
|
||||
lock(trigger);
|
||||
|
||||
setTimeout(() => {
|
||||
hideTooltip(trigger);
|
||||
resumeIcon(trigger);
|
||||
unlock(trigger);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
if (clipboardList.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* --- Post link sharing --- */
|
||||
// Initial the clipboard.js object
|
||||
const clipboard = new ClipboardJS(clipboardSelector, {
|
||||
target: (trigger) => {
|
||||
const codeBlock = trigger.parentNode.nextElementSibling;
|
||||
return codeBlock.querySelector('code .rouge-code');
|
||||
}
|
||||
});
|
||||
|
||||
const btnCopyLink = $('#copy-link');
|
||||
[...clipboardList].map(
|
||||
(elem) =>
|
||||
new Tooltip(elem, {
|
||||
placement: 'left'
|
||||
})
|
||||
);
|
||||
|
||||
btnCopyLink.on('click', (e) => {
|
||||
let target = $(e.target);
|
||||
clipboard.on('success', (e) => {
|
||||
const trigger = e.trigger;
|
||||
|
||||
e.clearSelection();
|
||||
|
||||
if (isLocked(trigger)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSuccessIcon(trigger);
|
||||
showTooltip(trigger);
|
||||
lock(trigger);
|
||||
|
||||
setTimeout(() => {
|
||||
hideTooltip(trigger);
|
||||
resumeIcon(trigger);
|
||||
unlock(trigger);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
}
|
||||
|
||||
function setLinkClipboard() {
|
||||
const btnCopyLink = document.getElementById('copy-link');
|
||||
|
||||
if (btnCopyLink === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
btnCopyLink.addEventListener('click', (e) => {
|
||||
const target = e.target;
|
||||
|
||||
if (isLocked(target)) {
|
||||
return;
|
||||
@@ -110,21 +116,28 @@ export function initClipboard() {
|
||||
|
||||
// Copy URL to clipboard
|
||||
navigator.clipboard.writeText(window.location.href).then(() => {
|
||||
const defaultTitle = target.attr(ATTR_TITLE_ORIGIN);
|
||||
const succeedTitle = target.attr(ATTR_TITLE_SUCCEED);
|
||||
const defaultTitle = target.getAttribute(ATTR_TITLE_ORIGIN);
|
||||
const succeedTitle = target.getAttribute(ATTR_TITLE_SUCCEED);
|
||||
|
||||
// Switch tooltip title
|
||||
target.attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show');
|
||||
target.setAttribute(ATTR_TITLE_ORIGIN, succeedTitle);
|
||||
Tooltip.getInstance(target).show();
|
||||
|
||||
lock(target);
|
||||
|
||||
setTimeout(() => {
|
||||
target.attr(ATTR_TITLE_ORIGIN, defaultTitle);
|
||||
target.setAttribute(ATTR_TITLE_ORIGIN, defaultTitle);
|
||||
unlock(target);
|
||||
}, TIMEOUT);
|
||||
});
|
||||
});
|
||||
|
||||
btnCopyLink.on('mouseleave', function (e) {
|
||||
const target = $(e.target);
|
||||
target.tooltip('hide');
|
||||
btnCopyLink.addEventListener('mouseleave', (e) => {
|
||||
Tooltip.getInstance(e.target).hide();
|
||||
});
|
||||
}
|
||||
|
||||
export function initClipboard() {
|
||||
setCodeClipboard();
|
||||
setLinkClipboard();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ const cover = {
|
||||
};
|
||||
|
||||
function removeCover(clzss) {
|
||||
$(this).parent().removeClass(clzss);
|
||||
this.parentElement.classList.remove(clzss);
|
||||
}
|
||||
|
||||
function handleImage() {
|
||||
@@ -30,32 +30,38 @@ function handleImage() {
|
||||
* Switches the LQIP with the real image URL.
|
||||
*/
|
||||
function switchLQIP() {
|
||||
const $img = $(this);
|
||||
const src = $img.attr(ATTR_DATA_SRC);
|
||||
|
||||
$img.attr('src', encodeURI(src));
|
||||
$img.removeAttr(ATTR_DATA_SRC);
|
||||
const src = this.getAttribute(ATTR_DATA_SRC);
|
||||
this.setAttribute('src', encodeURI(src));
|
||||
this.removeAttribute(ATTR_DATA_SRC);
|
||||
}
|
||||
|
||||
export function loadImg() {
|
||||
const $images = $('article img');
|
||||
const images = document.querySelectorAll('article img');
|
||||
|
||||
if ($images.length) {
|
||||
$images.on('load', handleImage);
|
||||
if (images.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
images.forEach((img) => {
|
||||
img.addEventListener('load', handleImage);
|
||||
});
|
||||
|
||||
// Images loaded from the browser cache do not trigger the 'load' event
|
||||
$('article img[loading="lazy"]').each(function () {
|
||||
if (this.complete) {
|
||||
removeCover.call(this, cover.SHIMMER);
|
||||
document.querySelectorAll('article img[loading="lazy"]').forEach((img) => {
|
||||
if (img.complete) {
|
||||
removeCover.call(img, cover.SHIMMER);
|
||||
}
|
||||
});
|
||||
|
||||
// LQIPs set by the data URI or WebP will not trigger the 'load' event,
|
||||
// so manually convert the URI to the URL of a high-resolution image.
|
||||
const $lqips = $(`article img[${ATTR_DATA_LQIP}="true"]`);
|
||||
const lqips = document.querySelectorAll(
|
||||
`article img[${ATTR_DATA_LQIP}="true"]`
|
||||
);
|
||||
|
||||
if ($lqips.length) {
|
||||
$lqips.each(switchLQIP);
|
||||
if (lqips.length) {
|
||||
lqips.forEach((lqip) => {
|
||||
switchLQIP.call(lqip);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user