mirror of
https://github.com/cotes2020/jekyll-theme-chirpy.git
synced 2025-12-19 14:14:17 +00:00
Compare commits
269 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
60836af606 | ||
|
|
739345ac24 | ||
|
|
1a977a87a0 | ||
|
|
d1a5b57e4d | ||
|
|
2b9d379d70 | ||
|
|
bdee5d6b6d | ||
|
|
348f6bff8b | ||
|
|
7a3d624364 | ||
|
|
06f1c6f256 | ||
|
|
4a7f33f7bb | ||
|
|
e077d2911d | ||
|
|
5f2edb0914 | ||
|
|
911206be80 | ||
|
|
18808851a9 | ||
|
|
2bf87e0de7 | ||
|
|
f6d96ab2b8 | ||
|
|
59c55121c7 | ||
|
|
9f174d9088 | ||
|
|
5810bcd1d7 | ||
|
|
897b57bfb4 | ||
|
|
fd83462ea4 | ||
|
|
fa8a2a0ada | ||
|
|
7b7e69a44d | ||
|
|
e6e2984e77 | ||
|
|
d71711d2d3 | ||
|
|
50835b4c71 | ||
|
|
575dc87d83 | ||
|
|
753cd0499d | ||
|
|
b7e9f3ec34 | ||
|
|
42bf39e21c | ||
|
|
45c2a18884 | ||
|
|
3fd3c571b5 | ||
|
|
2574118f40 | ||
|
|
0e2d593b00 | ||
|
|
2bc3172444 | ||
|
|
55659315c6 | ||
|
|
bbd92d11cc | ||
|
|
475d181aac | ||
|
|
f49155f034 | ||
|
|
109725d2dc | ||
|
|
e3b01636ac | ||
|
|
b489da89ca | ||
|
|
2d56597571 | ||
|
|
97004ddc44 | ||
|
|
75ea77d574 | ||
|
|
bf3a34d054 | ||
|
|
5015fdecf3 | ||
|
|
de2dff354a | ||
|
|
3a022bc816 | ||
|
|
9b74070d45 | ||
|
|
af4102476e | ||
|
|
9d9e3bbca3 | ||
|
|
6f2d3ea2bd | ||
|
|
8417927264 | ||
|
|
ca39e15a78 | ||
|
|
e9c920641b | ||
|
|
0a55e1297b | ||
|
|
0465a985dc | ||
|
|
73e171b0fb | ||
|
|
726085c647 | ||
|
|
b97fa93ffd | ||
|
|
13a3c3c906 | ||
|
|
e78f67d354 | ||
|
|
b34661efd7 | ||
|
|
bb589e8d31 | ||
|
|
f079bb7f5b | ||
|
|
ac4b402f97 | ||
|
|
87a12be897 | ||
|
|
0614473893 | ||
|
|
273b389c51 | ||
|
|
204cb44dc3 | ||
|
|
f949bda15b | ||
|
|
b3005f4e1a | ||
|
|
14d3960ca0 | ||
|
|
4da7406dfe | ||
|
|
1a041e0443 | ||
|
|
7ec8425e03 | ||
|
|
52084f85d4 | ||
|
|
5c6df66324 | ||
|
|
3f9f5c79e8 | ||
|
|
aff7566774 | ||
|
|
4237d078fa | ||
|
|
806fa3aa1a | ||
|
|
ec69bea841 | ||
|
|
75a2504fd9 | ||
|
|
8542b57e8b | ||
|
|
ed9bda022d | ||
|
|
25a27056e0 | ||
|
|
a069960439 | ||
|
|
c574166b51 | ||
|
|
ff87349fe7 | ||
|
|
505e314a31 | ||
|
|
41b8f9f519 | ||
|
|
62bcd601fc | ||
|
|
414b8f97ce | ||
|
|
229c2a2e2b | ||
|
|
c4af75389a | ||
|
|
4f86b04a84 | ||
|
|
2a5c184373 | ||
|
|
7b43a83c40 | ||
|
|
f659109de2 | ||
|
|
b39c6b526c | ||
|
|
7819fd0843 | ||
|
|
ba397a21aa | ||
|
|
0d4103d47b | ||
|
|
54e1dbe325 | ||
|
|
37c976499e | ||
|
|
0fd4c0bd0f | ||
|
|
0da2f80dd4 | ||
|
|
e8ef69ad17 | ||
|
|
2eb4267cdd | ||
|
|
e4e76f0a11 | ||
|
|
e07e6d46d7 | ||
|
|
2bbfda79ad | ||
|
|
b0f4ae5eec | ||
|
|
8b0fbf5a83 | ||
|
|
2639f8ed45 | ||
|
|
926d1ca068 | ||
|
|
df8ff546ec | ||
|
|
c075e11a4e | ||
|
|
b6d1992f85 | ||
|
|
74ab6f8adc | ||
|
|
4fe145e980 | ||
|
|
a60e90791d | ||
|
|
fa3257873e | ||
|
|
1682ce9d7c | ||
|
|
29a8bc26bc | ||
|
|
83625644ea | ||
|
|
728094d1ba | ||
|
|
ce2f6f5abe | ||
|
|
c4da99c7ea | ||
|
|
73af59194a | ||
|
|
f6bf6d0864 | ||
|
|
bef2ac085e | ||
|
|
83eecdabcb |
@@ -1,5 +0,0 @@
|
|||||||
# https://github.com/browserslist/browserslist#browserslistrc
|
|
||||||
|
|
||||||
last 2 versions
|
|
||||||
> 0.2%
|
|
||||||
not dead
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"rules": {
|
|
||||||
"body-max-line-length": [
|
|
||||||
0,
|
|
||||||
"always"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
55
.github/CONTRIBUTING.md
vendored
55
.github/CONTRIBUTING.md
vendored
@@ -1,55 +0,0 @@
|
|||||||
# How to Contribute
|
|
||||||
|
|
||||||
:tada: We really appreciate you taking the time to improve this project! :tada:
|
|
||||||
|
|
||||||
To ensure that the blog design is not confusing, this project does not accept
|
|
||||||
suggestions for design changes, such as color scheme, fonts, typography, etc.
|
|
||||||
If your request is about an enhancement, it is recommended to first submit a
|
|
||||||
[Feature Request][pr-issue] issue to discuss whether your idea fits the project.
|
|
||||||
|
|
||||||
Basically, you can follow these steps to complete the contribution.
|
|
||||||
|
|
||||||
1. Fork this project on GitHub and clone it locally.
|
|
||||||
2. Create a new branch from the default branch and give it a descriptive name
|
|
||||||
(format: `feature/<add-new-feat>` or `fix/<fix-a-bug>`).
|
|
||||||
3. After completing development, create a [Conventional Commit][cc] with git.
|
|
||||||
(See also: ["Verify the commits"](#verify-the-commits))
|
|
||||||
4. Create a [Pull Request][gh-pr].
|
|
||||||
|
|
||||||
## Make sure you can pass the CI tests
|
|
||||||
|
|
||||||
This project has [CI][ci] turned on. In order for your [PR][gh-pr] to pass the test,
|
|
||||||
please read the following.
|
|
||||||
|
|
||||||
### Check the core functionality
|
|
||||||
|
|
||||||
```console
|
|
||||||
bash ./tools/test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Check the SASS syntax style
|
|
||||||
|
|
||||||
```console
|
|
||||||
npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
### Verify the commits
|
|
||||||
|
|
||||||
Before you create a git commit, please complete the following setup.
|
|
||||||
|
|
||||||
Install `commitlint` & `husky`:
|
|
||||||
|
|
||||||
```console
|
|
||||||
npm i -g @commitlint/{cli,config-conventional} husky
|
|
||||||
```
|
|
||||||
|
|
||||||
And then enable `husky`:
|
|
||||||
|
|
||||||
```console
|
|
||||||
husky install
|
|
||||||
```
|
|
||||||
|
|
||||||
[pr-issue]: https://github.com/cotes2020/jekyll-theme-chirpy/issues/new?labels=enhancement&template=feature_request.md
|
|
||||||
[gh-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests
|
|
||||||
[cc]: https://www.conventionalcommits.org/
|
|
||||||
[ci]: https://en.wikipedia.org/wiki/Continuous_integration
|
|
||||||
17
.github/DISCUSSION_TEMPLATE/general.yml
vendored
Normal file
17
.github/DISCUSSION_TEMPLATE/general.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Following the guidelines can make you more likely to get responses.
|
||||||
|
options:
|
||||||
|
- label: >-
|
||||||
|
I have read and accepted the
|
||||||
|
[contributing guidelines](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md).
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Please describe in detail what you want to share.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
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
|
||||||
40
.github/DISCUSSION_TEMPLATE/q-a.yml
vendored
Normal file
40
.github/DISCUSSION_TEMPLATE/q-a.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Following the guidelines can make you more likely to get responses.
|
||||||
|
options:
|
||||||
|
- label: >-
|
||||||
|
I have read and accepted the
|
||||||
|
[contributing guidelines](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md).
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: download
|
||||||
|
attributes:
|
||||||
|
label: How did you create the site?
|
||||||
|
options:
|
||||||
|
- Generated from `chirpy-starter`
|
||||||
|
- Built from `jekyll-theme-chirpy`
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Description
|
||||||
|
description: Please describe your need in detail.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Operations you have already tried
|
||||||
|
description: Describe the effort you went through.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Anything else?
|
||||||
|
description: |
|
||||||
|
Links? References? Or logs? Anything that will give us more context about the issue you are encountering!
|
||||||
68
.github/ISSUE_TEMPLATE/bug_report.md
vendored
68
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,68 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug Report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
---
|
|
||||||
|
|
||||||
**NOTE:** Before you start, the following should be completed.
|
|
||||||
|
|
||||||
- Read [Wiki][wiki] to understand the usage and the correct effect of functional design.
|
|
||||||
- Make sure no [similar issue(including closed ones)][issues] exists.
|
|
||||||
- Make sure the bug is found in the latest code of the `master` branch.
|
|
||||||
|
|
||||||
[wiki]: https://github.com/cotes2020/jekyll-theme-chirpy/wiki
|
|
||||||
[issues]: https://github.com/cotes2020/jekyll-theme-chirpy/issues?q=is%3Aissue
|
|
||||||
|
|
||||||
## Describe the bug
|
|
||||||
|
|
||||||
<!-- A clear and concise description of what the bug is. -->
|
|
||||||
|
|
||||||
## To Reproduce
|
|
||||||
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
<!--
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Expected behavior
|
|
||||||
|
|
||||||
<!-- A clear and concise description of what you expected to happen. -->
|
|
||||||
|
|
||||||
## Logs/Screenshots
|
|
||||||
|
|
||||||
<!-- If applicable, add logs/screenshots to help explain your problem. -->
|
|
||||||
|
|
||||||
## Environment
|
|
||||||
|
|
||||||
| Command | Version |
|
|
||||||
|-----------------------------------|---------|
|
|
||||||
| `ruby -v` | |
|
|
||||||
| `gem -v` | |
|
|
||||||
| `bundle -v` | |
|
|
||||||
| `bundle exec jekyll -v` | |
|
|
||||||
| `bundle info jekyll-theme-chirpy` | |
|
|
||||||
|
|
||||||
<!-- If necessary, uncomment and fill in the following list:
|
|
||||||
|
|
||||||
### Desktop
|
|
||||||
|
|
||||||
- OS: [e.g. macOS 10.15.6]
|
|
||||||
- Browser: [e.g. Chrome 85.0.4183.83 (64-bit)]
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- If necessary, uncomment and fill in the following list:
|
|
||||||
|
|
||||||
### Smartphone
|
|
||||||
|
|
||||||
- Device: [e.g. iPhone 6]
|
|
||||||
- OS: [e.g. iOS 13.6.1]
|
|
||||||
- Browser: [e.g. Chrome 22]
|
|
||||||
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Additional context
|
|
||||||
|
|
||||||
<!-- Add any other context about the problem here. -->
|
|
||||||
64
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
64
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: Create a report to help us improve
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Following the guidelines can make you more likely to get responses.
|
||||||
|
options:
|
||||||
|
- label: >-
|
||||||
|
I have read and accepted the
|
||||||
|
[contributing guidelines](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md).
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: download
|
||||||
|
attributes:
|
||||||
|
label: How did you create the site?
|
||||||
|
options:
|
||||||
|
- Generated from `chirpy-starter`
|
||||||
|
- Built from `jekyll-theme-chirpy`
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: A clear and concise description of what the bug is.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Steps To Reproduce
|
||||||
|
description: Steps to reproduce the behavior.
|
||||||
|
placeholder: |
|
||||||
|
1. In this environment...
|
||||||
|
2. With this config...
|
||||||
|
3. Run '...'
|
||||||
|
4. See error...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected Behavior
|
||||||
|
description: A concise description of what you expected to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Environment
|
||||||
|
value: |
|
||||||
|
- Ruby: <!-- run `ruby -v` -->
|
||||||
|
- Jekyll: <!-- run `bundle exec jekyll -v` -->
|
||||||
|
- Chirpy: <!-- run `bundle info jekyll-theme-chirpy` -->
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Anything else?
|
||||||
|
description: |
|
||||||
|
Links? References? Or logs? Anything that will give us more context about the issue you are encountering!
|
||||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Ask the community for help
|
||||||
|
url: https://github.com/cotes2020/jekyll-theme-chirpy/discussions
|
||||||
|
about: Please ask and answer questions here.
|
||||||
33
.github/ISSUE_TEMPLATE/feature_request.md
vendored
33
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,33 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature Request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
labels: enhancement
|
|
||||||
---
|
|
||||||
|
|
||||||
**NOTE:** Before you start, the following should be completed.
|
|
||||||
|
|
||||||
- Read [Wiki][wiki] to understand the usage and the correct effect of functional design.
|
|
||||||
- Make sure no [similar issue(including closed ones)][issues] exists.
|
|
||||||
- Make sure the request is based on the latest code in the `master` branch.
|
|
||||||
|
|
||||||
[wiki]: https://github.com/cotes2020/jekyll-theme-chirpy/wiki
|
|
||||||
[issues]: https://github.com/cotes2020/jekyll-theme-chirpy/issues?q=is%3Aissue
|
|
||||||
|
|
||||||
## Is your feature request related to a problem? Please describe
|
|
||||||
|
|
||||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
|
|
||||||
|
|
||||||
|
|
||||||
## Describe the solution you'd like
|
|
||||||
|
|
||||||
<!-- A clear and concise description of what you want to happen. -->
|
|
||||||
|
|
||||||
|
|
||||||
## Describe alternatives you've considered
|
|
||||||
|
|
||||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
|
||||||
|
|
||||||
|
|
||||||
## Additional context
|
|
||||||
|
|
||||||
<!-- Add any other context or screenshots about the feature request here. -->
|
|
||||||
38
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
38
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
name: Feature Request
|
||||||
|
description: Suggest an idea for this project
|
||||||
|
labels:
|
||||||
|
- enhancement
|
||||||
|
body:
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Checklist
|
||||||
|
description: Following the guidelines can make you more likely to get responses.
|
||||||
|
options:
|
||||||
|
- label: >-
|
||||||
|
I have read and accepted the
|
||||||
|
[contributing guidelines](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md).
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Is your feature request related to a problem? Please describe
|
||||||
|
description: A clear and concise description of what the problem is.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Describe the solution you'd like
|
||||||
|
description: A clear and concise description of what you want to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Describe alternatives you've considered
|
||||||
|
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context or screenshots about the feature request here.
|
||||||
28
.github/ISSUE_TEMPLATE/help_wanted.md
vendored
28
.github/ISSUE_TEMPLATE/help_wanted.md
vendored
@@ -1,28 +0,0 @@
|
|||||||
---
|
|
||||||
name: Help Wanted
|
|
||||||
about: Need help that is not covered in the tutorial
|
|
||||||
labels: 'help wanted'
|
|
||||||
---
|
|
||||||
|
|
||||||
**NOTE:** Before you start, the following should be completed.
|
|
||||||
|
|
||||||
- Read [Wiki][wiki] to understand the usage and the correct effect of functional design.
|
|
||||||
- Make sure no [similar issue(including closed ones)][issues] exists.
|
|
||||||
- Try to find the answer on [Jekyll Forum][forum] and [StackOverflow][stack_overflow].
|
|
||||||
|
|
||||||
[wiki]: https://github.com/cotes2020/jekyll-theme-chirpy/wiki
|
|
||||||
[issues]: https://github.com/cotes2020/jekyll-theme-chirpy/issues?q=is%3Aissue
|
|
||||||
[forum]: https://talk.jekyllrb.com/
|
|
||||||
[stack_overflow]: https://stackoverflow.com/questions/tagged/jekyll
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
<!-- Please describe your need in detail. -->
|
|
||||||
|
|
||||||
## Operations you have already tried
|
|
||||||
|
|
||||||
<!-- Describe the effort you went through. -->
|
|
||||||
|
|
||||||
## Logs/Screenshots
|
|
||||||
|
|
||||||
<!-- If applicable, add logs/screenshots to help explain your problem. -->
|
|
||||||
20
.github/ISSUE_TEMPLATE/question.md
vendored
20
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
name: Question
|
|
||||||
about: Issues that differ from other templates
|
|
||||||
labels: question
|
|
||||||
---
|
|
||||||
|
|
||||||
**NOTE:** Before you start, the following should be completed.
|
|
||||||
|
|
||||||
- Read [Wiki][wiki] to understand the usage and the correct effect of functional design.
|
|
||||||
- Make sure no [similar issue(including closed ones)][issues] exists.
|
|
||||||
- Try to find the answer on [Jekyll Forum][forum] and [StackOverflow][stack_overflow].
|
|
||||||
|
|
||||||
[wiki]: https://github.com/cotes2020/jekyll-theme-chirpy/wiki
|
|
||||||
[issues]: https://github.com/cotes2020/jekyll-theme-chirpy/issues?q=is%3Aissue
|
|
||||||
[forum]: https://talk.jekyllrb.com/
|
|
||||||
[stack_overflow]: https://stackoverflow.com/questions/tagged/jekyll
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
<!-- Please describe your question in detail. -->
|
|
||||||
26
.github/PULL_REQUEST_TEMPLATE.md
vendored
26
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,29 +1,17 @@
|
|||||||
## Description
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
|
|
||||||
-->
|
|
||||||
|
|
||||||
## Type of change
|
## Type of change
|
||||||
|
<!-- Please select the desired item checkbox and change it from `[ ]` to `[x]` and then delete the irrelevant options. -->
|
||||||
<!--
|
|
||||||
Please select the desired item checkbox and change it to "[x]", then delete options that are not relevant.
|
|
||||||
-->
|
|
||||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||||
- [ ] New feature (non-breaking change which adds functionality)
|
- [ ] New feature (non-breaking change which adds functionality)
|
||||||
- [ ] Improvement (refactoring and improving code)
|
- [ ] Improvement (refactoring and improving code)
|
||||||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
|
||||||
- [ ] Documentation update
|
- [ ] Documentation update
|
||||||
|
|
||||||
## Additional context
|
## Description
|
||||||
|
|
||||||
<!-- e.g. Fixes #(issue) -->
|
|
||||||
|
|
||||||
## How has this been tested
|
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
|
Please include a summary of the change and which issue is fixed.
|
||||||
|
Please also include relevant motivation and context.
|
||||||
|
List any dependencies that are required for this change.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
- [ ] I have run `bash ./tools/test` (at the root of the project) locally and passed
|
## Additional context
|
||||||
- [ ] I have tested this feature in the browser
|
<!-- e.g. Fixes #(issue) -->
|
||||||
|
|||||||
12
.github/SECURITY.md
vendored
12
.github/SECURITY.md
vendored
@@ -1,12 +0,0 @@
|
|||||||
# Security Policy
|
|
||||||
|
|
||||||
## Supported Versions
|
|
||||||
|
|
||||||
| Version | Supported |
|
|
||||||
|---------| ------------------ |
|
|
||||||
| 5.x | :white_check_mark: |
|
|
||||||
| < 5.0.0 | :x: |
|
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
|
||||||
|
|
||||||
If you find a vulnerability, please report it to `cotes.chung@gmail.com`. We will try our best to respond within a week. Thank you for your time!
|
|
||||||
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"
|
||||||
25
.github/dependabot.yml
vendored
Normal file
25
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "bundler"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/"
|
||||||
|
versioning-strategy: increase
|
||||||
|
groups:
|
||||||
|
npm:
|
||||||
|
update-types:
|
||||||
|
- "major"
|
||||||
|
- "minor"
|
||||||
|
- "patch"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
groups:
|
||||||
|
gh-actions:
|
||||||
|
update-types:
|
||||||
|
- "major"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
17
.github/stale.yml
vendored
17
.github/stale.yml
vendored
@@ -1,17 +0,0 @@
|
|||||||
# Clean up the stale issues
|
|
||||||
|
|
||||||
daysUntilStale: 30
|
|
||||||
daysUntilClose: 1
|
|
||||||
|
|
||||||
exemptLabels:
|
|
||||||
- in progress
|
|
||||||
- pending
|
|
||||||
|
|
||||||
staleLabel: stale
|
|
||||||
|
|
||||||
markComment: >
|
|
||||||
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.
|
|
||||||
|
|
||||||
closeComment: false
|
|
||||||
37
.github/workflows/cd.yml
vendored
37
.github/workflows/cd.yml
vendored
@@ -1,14 +1,37 @@
|
|||||||
name: CD
|
name: CD
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [production, docs]
|
branches:
|
||||||
|
- production
|
||||||
|
tags-ignore:
|
||||||
|
- "**"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
launch:
|
release:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- run: |
|
- uses: actions/checkout@v4
|
||||||
curl -X POST -H "Accept: application/vnd.github+json" \
|
|
||||||
-H "Authorization: Bearer ${{ secrets.GH_PAT }}" \
|
- uses: ruby/setup-ruby@v1
|
||||||
https://api.github.com/repos/${{ secrets.BUILDER }}/dispatches \
|
with:
|
||||||
-d '{"event_type":"deploy", "client_payload":{"branch": "${{ github.ref_name }}"}}'
|
ruby-version: 3.3
|
||||||
|
bundler-cache: true
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: latest
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|||||||
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
@@ -1,18 +1,16 @@
|
|||||||
name: "CI"
|
name: "CI"
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches-ignore:
|
branches:
|
||||||
- "production"
|
- "master"
|
||||||
- "docs"
|
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- ".github/**"
|
- ".github/**"
|
||||||
- "!.github/workflows/ci.yml"
|
- "!.github/workflows/ci.yml"
|
||||||
- ".gitignore"
|
- ".gitignore"
|
||||||
|
- "docs/**"
|
||||||
- "README.md"
|
- "README.md"
|
||||||
- "LICENSE"
|
- "LICENSE"
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
|
||||||
- "**"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -20,11 +18,11 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
ruby: [2.7, 3]
|
ruby: ["3.1", "3.2", "3.3"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # for posts's lastmod
|
fetch-depth: 0 # for posts's lastmod
|
||||||
|
|
||||||
@@ -35,7 +33,9 @@ jobs:
|
|||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: latest
|
||||||
|
|
||||||
- name: Build Assets
|
- name: Build Assets
|
||||||
run: npm i && npm run build
|
run: npm i && npm run build
|
||||||
|
|||||||
16
.github/workflows/codeql.yml
vendored
16
.github/workflows/codeql.yml
vendored
@@ -2,11 +2,10 @@ name: "CodeQL"
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths: ["**.js"]
|
branches: ["master"]
|
||||||
|
paths: ["_javascript/**/*.js"]
|
||||||
pull_request:
|
pull_request:
|
||||||
paths: ["**.js"]
|
paths: ["_javascript/**/*.js"]
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * 5"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
@@ -25,20 +24,21 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v3
|
||||||
with:
|
with:
|
||||||
languages: "${{ matrix.language }}"
|
languages: "${{ matrix.language }}"
|
||||||
|
config-file: .github/codeql/codeql-config.yml
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
# 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)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v2
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v3
|
||||||
with:
|
with:
|
||||||
category: "/language:${{ matrix.language }}"
|
category: "/language:${{ matrix.language }}"
|
||||||
|
|||||||
6
.github/workflows/commitlint.yml
vendored
6
.github/workflows/commitlint.yml
vendored
@@ -5,7 +5,5 @@ jobs:
|
|||||||
commitlint:
|
commitlint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
- uses: wagoid/commitlint-github-action@v6
|
||||||
fetch-depth: 0
|
|
||||||
- uses: wagoid/commitlint-github-action@v5
|
|
||||||
|
|||||||
17
.github/workflows/publish.yml
vendored
Normal file
17
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
name: Publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- docs
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
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 }}"}}'
|
||||||
32
.github/workflows/stale.yml
vendored
Normal file
32
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: "Close stale issues and PRs"
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *" # every day at 00:00 UTC
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
STALE_LABEL: stale
|
||||||
|
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@v9
|
||||||
|
with:
|
||||||
|
# 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 }}
|
||||||
@@ -28,7 +28,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
# submodules: true
|
# submodules: true
|
||||||
@@ -37,12 +37,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup Pages
|
- name: Setup Pages
|
||||||
id: pages
|
id: pages
|
||||||
uses: actions/configure-pages@v3
|
uses: actions/configure-pages@v4
|
||||||
|
|
||||||
- name: Setup Ruby
|
- name: Setup Ruby
|
||||||
uses: ruby/setup-ruby@v1
|
uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
ruby-version: 3 # reads from a '.ruby-version' or '.tools-version' file if 'ruby-version' is omitted
|
ruby-version: 3.3
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
|
|
||||||
- name: Build site
|
- name: Build site
|
||||||
@@ -52,10 +52,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Test site
|
- name: Test site
|
||||||
run: |
|
run: |
|
||||||
bundle exec htmlproofer _site --disable-external --check-html --allow_hash_href
|
bundle exec htmlproofer _site \
|
||||||
|
\-\-disable-external \
|
||||||
|
\-\-ignore-urls "/^http:\/\/127.0.0.1/,/^http:\/\/0.0.0.0/,/^http:\/\/localhost/"
|
||||||
|
|
||||||
- name: Upload site artifact
|
- name: Upload site artifact
|
||||||
uses: actions/upload-pages-artifact@v1
|
uses: actions/upload-pages-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: "_site${{ steps.pages.outputs.base_path }}"
|
path: "_site${{ steps.pages.outputs.base_path }}"
|
||||||
|
|
||||||
@@ -68,4 +70,4 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
id: deployment
|
id: deployment
|
||||||
uses: actions/deploy-pages@v1
|
uses: actions/deploy-pages@v4
|
||||||
16
.github/workflows/style-lint.yml
vendored
16
.github/workflows/style-lint.yml
vendored
@@ -2,14 +2,10 @@ name: "Style Lint"
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches-ignore:
|
branches: ["master"]
|
||||||
- "production"
|
paths: ["_sass/**/*.scss"]
|
||||||
- "docs"
|
|
||||||
paths:
|
|
||||||
- "_sass/**/*.scss"
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths: ["_sass/**/*.scss"]
|
||||||
- "_sass/**/*.scss"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stylelint:
|
stylelint:
|
||||||
@@ -17,9 +13,11 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: latest
|
||||||
- run: npm i
|
- run: npm i
|
||||||
- run: npm test
|
- run: npm test
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -5,6 +5,7 @@ Gemfile.lock
|
|||||||
|
|
||||||
# Jekyll cache
|
# Jekyll cache
|
||||||
.jekyll-cache
|
.jekyll-cache
|
||||||
|
.jekyll-metadata
|
||||||
_site
|
_site
|
||||||
|
|
||||||
# RubyGems
|
# RubyGems
|
||||||
@@ -17,6 +18,9 @@ package-lock.json
|
|||||||
# IDE configurations
|
# IDE configurations
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
|
_sass/dist
|
||||||
assets/js/dist
|
assets/js/dist
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
. "$(dirname "$0")/_/husky.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"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"trailingComma": "none"
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "stylelint-config-standard-scss",
|
|
||||||
"rules": {
|
|
||||||
"no-descending-specificity": null,
|
|
||||||
"shorthand-property-no-redundant-values": null,
|
|
||||||
"at-rule-no-vendor-prefix": null,
|
|
||||||
"property-no-vendor-prefix": null,
|
|
||||||
"selector-no-vendor-prefix": null,
|
|
||||||
"value-no-vendor-prefix": null,
|
|
||||||
"color-function-notation": "legacy",
|
|
||||||
"alpha-value-notation": "number",
|
|
||||||
"selector-not-notation": "simple",
|
|
||||||
"color-hex-length": "long",
|
|
||||||
"declaration-block-single-line-max-declarations": 3,
|
|
||||||
"scss/operator-no-newline-after": null,
|
|
||||||
"rule-empty-line-before": [
|
|
||||||
"always",
|
|
||||||
{ "ignore": ["after-comment", "first-nested", "inside-block"] }
|
|
||||||
],
|
|
||||||
"value-keyword-case": ["lower", { "ignoreProperties": ["/^\\$/"] }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"skip": {
|
|
||||||
"commit": true,
|
|
||||||
"tag": true
|
|
||||||
},
|
|
||||||
"types": [
|
|
||||||
{
|
|
||||||
"type": "feat",
|
|
||||||
"section": "Features"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "fix",
|
|
||||||
"section": "Bug Fixes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "perf",
|
|
||||||
"section": "Improvements"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
13
.vscode/extensions.json
vendored
Normal file
13
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
// Liquid tags auto-complete
|
||||||
|
"killalau.vscode-liquid-snippets",
|
||||||
|
// Liquid syntax highlighting and formatting
|
||||||
|
"Shopify.theme-check-vscode",
|
||||||
|
// Common formatter
|
||||||
|
"esbenp.prettier-vscode",
|
||||||
|
"foxundermoon.shell-format",
|
||||||
|
"stylelint.vscode-stylelint",
|
||||||
|
"yzhang.markdown-all-in-one"
|
||||||
|
]
|
||||||
|
}
|
||||||
27
.vscode/settings.json
vendored
Normal file
27
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
// Prettier
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"prettier.trailingComma": "none",
|
||||||
|
// 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": "foxundermoon.shell-format"
|
||||||
|
},
|
||||||
|
// Disable vscode built-in stylelint
|
||||||
|
"css.validate": false,
|
||||||
|
"scss.validate": false,
|
||||||
|
"less.validate": false,
|
||||||
|
// Stylint extension settings
|
||||||
|
"stylelint.snippet": ["css", "less", "postcss", "scss"],
|
||||||
|
"stylelint.validate": ["css", "less", "postcss", "scss"]
|
||||||
|
}
|
||||||
21
Gemfile
21
Gemfile
@@ -5,24 +5,5 @@ source "https://rubygems.org"
|
|||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem "html-proofer", "~> 3.18"
|
gem "html-proofer", "~> 5.0"
|
||||||
end
|
|
||||||
|
|
||||||
# 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]
|
|
||||||
|
|
||||||
# Lock jekyll-sass-converter to 2.x on Linux-musl
|
|
||||||
if RUBY_PLATFORM =~ /linux-musl/
|
|
||||||
gem "jekyll-sass-converter", "~> 2.0"
|
|
||||||
end
|
end
|
||||||
|
|||||||
102
README.md
102
README.md
@@ -1,16 +1,18 @@
|
|||||||
|
<!-- markdownlint-disable-next-line -->
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
|
<!-- markdownlint-disable-next-line -->
|
||||||
# Chirpy Jekyll Theme
|
# Chirpy Jekyll Theme
|
||||||
|
|
||||||
A minimal, responsive and feature-rich Jekyll theme for technical writing.
|
A minimal, responsive, and feature-rich Jekyll theme for technical writing.
|
||||||
|
|
||||||
[](https://rubygems.org/gems/jekyll-theme-chirpy)
|
[][gem]
|
||||||
[](https://github.com/cotes2020/jekyll-theme-chirpy/actions/workflows/ci.yml)
|
[][ci]
|
||||||
[](https://www.codacy.com/gh/cotes2020/jekyll-theme-chirpy/dashboard?utm_source=github.com&utm_medium=referral&utm_content=cotes2020/jekyll-theme-chirpy&utm_campaign=Badge_Grade)
|
[][codacy]
|
||||||
[](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/LICENSE)
|
[][license]
|
||||||
[](https://996.icu)
|
[](https://996.icu)
|
||||||
|
|
||||||
[**Live Demo →**][demo]
|
[**Live Demo** →][demo]
|
||||||
|
|
||||||
[][demo]
|
[][demo]
|
||||||
|
|
||||||
@@ -18,78 +20,64 @@
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
<details>
|
- Dark Theme
|
||||||
<summary>
|
- Localized UI language
|
||||||
<i>Click to view features</i>
|
- Pinned Posts on Home Page
|
||||||
</summary>
|
- Hierarchical Categories
|
||||||
<p>
|
- Trending Tags
|
||||||
|
- Table of Contents
|
||||||
- Dark / Light Theme Mode
|
- Last Modified Date
|
||||||
- Localized UI language
|
- Syntax Highlighting
|
||||||
- Pinned Posts
|
- Mathematical Expressions
|
||||||
- Hierarchical Categories
|
- Mermaid Diagrams & Flowcharts
|
||||||
- Trending Tags
|
- Dark Mode Images
|
||||||
- Table of Contents
|
- Embed Media
|
||||||
- Last Modified Date of Posts
|
- Comment Systems
|
||||||
- Syntax Highlighting
|
- Built-in Search
|
||||||
- Mathematical Expressions
|
- Atom Feeds
|
||||||
- Mermaid Diagram & Flowchart
|
- PWA
|
||||||
- Dark / Light Mode Images
|
- Web Analytics
|
||||||
- Embed Videos
|
- SEO & Performance Optimization
|
||||||
- Disqus / Utterances / Giscus Comments
|
|
||||||
- Search
|
|
||||||
- Atom Feeds
|
|
||||||
- Google Analytics
|
|
||||||
- Page Views Reporting
|
|
||||||
- SEO & Performance Optimization
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
To explore usage, development, and upgrade guide of the project, please refer to
|
To learn how to use, develop, and upgrade the project, please refer to the [Wiki][wiki].
|
||||||
the [Wiki][wiki].
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Welcome to report bugs, help improve the code or submit new features.
|
Contributions (_pull requests_, _issues_, and _discussions_) are what make the open-source community such an amazing place
|
||||||
For more information, please see the ["Contributing Guidelines"][contribute-guide].
|
to learn, inspire, and create. Any contributions you make are greatly appreciated.
|
||||||
|
For details, see the "[Contributing Guidelines][contribute-guide]".
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
This theme is mainly built with [Jekyll][jekyllrb] ecosystem,
|
### Contributors
|
||||||
[Bootstrap][bootstrap], [Font Awesome][icons] and some other [wonderful tools][lib].
|
|
||||||
The avatar and favicon design come from [Clipart Max][image].
|
|
||||||
|
|
||||||
Thanks to all the [contributors][contributors]. Also, folks who submitted issues
|
Thanks to [all the contributors][contributors] involved in the development of the project!
|
||||||
or unmerged PRs should not be forgotten. Because they reported bugs, shared ideas,
|
|
||||||
or inspired me to write more readable documentation.
|
|
||||||
|
|
||||||
Last but not least, thanks to [JetBrains][jetbrains] for providing the
|
[][contributors]
|
||||||
_Open Source Development_ license.
|
<sub> — Made with [contrib.rocks](https://contrib.rocks)</sub>
|
||||||
|
|
||||||
## Sponsoring
|
### Third-Party Assets
|
||||||
|
|
||||||
If you'd like to sponsor this project, the following options are available.
|
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.
|
||||||
|
|
||||||
[](https://ko-fi.com/coteschung)
|
The avatar and favicon for the project's website are from [ClipartMAX][clipartmax].
|
||||||
[][donation]
|
|
||||||
[][donation]
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This work is published under [MIT][mit] License.
|
This project is published under [MIT License][license].
|
||||||
|
|
||||||
|
[gem]: https://rubygems.org/gems/jekyll-theme-chirpy
|
||||||
|
[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
|
||||||
[jekyllrb]: https://jekyllrb.com/
|
[jekyllrb]: https://jekyllrb.com/
|
||||||
[bootstrap]: https://getbootstrap.com/
|
[clipartmax]: https://www.clipartmax.com/middle/m2i8b1m2K9Z5m2K9_ant-clipart-childrens-ant-cute/
|
||||||
[icons]: https://fontawesome.com/
|
|
||||||
[image]: https://www.clipartmax.com/middle/m2i8b1m2K9Z5m2K9_ant-clipart-childrens-ant-cute/
|
|
||||||
[demo]: https://cotes2020.github.io/chirpy-demo/
|
[demo]: https://cotes2020.github.io/chirpy-demo/
|
||||||
[wiki]: https://github.com/cotes2020/jekyll-theme-chirpy/wiki
|
[wiki]: https://github.com/cotes2020/jekyll-theme-chirpy/wiki
|
||||||
[contribute-guide]: https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/.github/CONTRIBUTING.md
|
[contribute-guide]: https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md
|
||||||
[contributors]: https://github.com/cotes2020/jekyll-theme-chirpy/graphs/contributors
|
[contributors]: https://github.com/cotes2020/jekyll-theme-chirpy/graphs/contributors
|
||||||
[lib]: https://github.com/cotes2020/chirpy-static-assets
|
[lib]: https://github.com/cotes2020/chirpy-static-assets
|
||||||
|
[vscode]: https://code.visualstudio.com/
|
||||||
[jetbrains]: https://www.jetbrains.com/?from=jekyll-theme-chirpy
|
[jetbrains]: https://www.jetbrains.com/?from=jekyll-theme-chirpy
|
||||||
[donation]: https://sponsor.cotes.page/
|
|
||||||
[mit]: https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/LICENSE
|
|
||||||
|
|||||||
82
_config.yml
82
_config.yml
@@ -3,16 +3,12 @@
|
|||||||
# Import the theme
|
# Import the theme
|
||||||
theme: jekyll-theme-chirpy
|
theme: jekyll-theme-chirpy
|
||||||
|
|
||||||
# Change the following value to '/PROJECT_NAME' ONLY IF your site type is GitHub Pages Project sites
|
|
||||||
# and doesn't have a custom domain.
|
|
||||||
baseurl: ""
|
|
||||||
|
|
||||||
# The language of the webpage › http://www.lingoes.net/en/translator/langcode.htm
|
# The language of the webpage › http://www.lingoes.net/en/translator/langcode.htm
|
||||||
# If it has the same name as one of the files in folder `_data/locales`, the layout language will also be changed,
|
# If it has the same name as one of the files in folder `_data/locales`, the layout language will also be changed,
|
||||||
# otherwise, the layout language will use the default value of 'en'.
|
# otherwise, the layout language will use the default value of 'en'.
|
||||||
lang: en
|
lang: en
|
||||||
|
|
||||||
# Change to your timezone › http://www.timezoneconverter.com/cgi-bin/findzone/findzone
|
# Change to your timezone › https://kevinnovak.github.io/Time-Zone-Picker
|
||||||
timezone: Asia/Shanghai
|
timezone: Asia/Shanghai
|
||||||
|
|
||||||
# jekyll-seo-tag settings › https://github.com/jekyll/jekyll-seo-tag/blob/master/docs/usage.md
|
# jekyll-seo-tag settings › https://github.com/jekyll/jekyll-seo-tag/blob/master/docs/usage.md
|
||||||
@@ -25,7 +21,8 @@ tagline: A text-focused Jekyll theme # it will display as the sub-title
|
|||||||
description: >- # used by seo meta and the atom feed
|
description: >- # used by seo meta and the atom feed
|
||||||
A minimal, responsive and feature-rich Jekyll theme for technical writing.
|
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'
|
# Fill in the protocol & hostname for your site.
|
||||||
|
# e.g. 'https://username.github.io', note that it does not end with a '/'.
|
||||||
url: ""
|
url: ""
|
||||||
|
|
||||||
github:
|
github:
|
||||||
@@ -47,17 +44,36 @@ social:
|
|||||||
# - https://www.facebook.com/username
|
# - https://www.facebook.com/username
|
||||||
# - https://www.linkedin.com/in/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
|
# The end of `jekyll-seo-tag` settings
|
||||||
|
|
||||||
google_analytics:
|
# Web Analytics Settings
|
||||||
|
analytics:
|
||||||
|
google:
|
||||||
id: # fill in your Google Analytics ID
|
id: # fill in your Google Analytics ID
|
||||||
# Google Analytics pageviews report settings
|
goatcounter:
|
||||||
pv:
|
id: # fill in your GoatCounter ID
|
||||||
proxy_endpoint: # fill in the Google Analytics superProxy endpoint of Google App Engine
|
umami:
|
||||||
cache_path: # the local PV cache data, friendly to visitors from GFW region
|
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
|
||||||
|
|
||||||
|
# Pageviews settings
|
||||||
|
pageviews:
|
||||||
|
provider: # now only supports 'goatcounter'
|
||||||
|
|
||||||
# Prefer color scheme setting.
|
# Prefer color scheme setting.
|
||||||
#
|
#
|
||||||
@@ -70,24 +86,29 @@ google_analytics:
|
|||||||
# light - Use the light color scheme
|
# light - Use the light color scheme
|
||||||
# dark - Use the dark 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
|
# 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'
|
# 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
|
# the avatar on sidebar, support local or CORS resources
|
||||||
avatar: "/commons/avatar.jpg"
|
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.
|
# boolean type, the global switch for TOC in posts.
|
||||||
toc: true
|
toc: true
|
||||||
|
|
||||||
comments:
|
comments:
|
||||||
active: # The global switch for posts comments, e.g., 'disqus'. Keep it empty means disable
|
# Global switch for the post comment system. Keeping it empty means disabled.
|
||||||
# The active options are as follows:
|
provider: # [disqus | utterances | giscus]
|
||||||
|
# The provider options are as follows:
|
||||||
disqus:
|
disqus:
|
||||||
shortname: # fill with the Disqus shortname. › https://help.disqus.com/en/articles/1717111-what-s-a-shortname
|
shortname: # fill with the Disqus shortname. › https://help.disqus.com/en/articles/1717111-what-s-a-shortname
|
||||||
# utterances settings › https://utteranc.es/
|
# utterances settings › https://utteranc.es/
|
||||||
@@ -101,6 +122,7 @@ comments:
|
|||||||
category:
|
category:
|
||||||
category_id:
|
category_id:
|
||||||
mapping: # optional, default to 'pathname'
|
mapping: # optional, default to 'pathname'
|
||||||
|
strict: # optional, default to '0'
|
||||||
input_position: # optional, default to 'bottom'
|
input_position: # optional, default to 'bottom'
|
||||||
lang: # optional, default to the value of `site.lang`
|
lang: # optional, default to the value of `site.lang`
|
||||||
reactions_enabled: # optional, default to the value of `1`
|
reactions_enabled: # optional, default to the value of `1`
|
||||||
@@ -111,16 +133,27 @@ assets:
|
|||||||
enabled: # boolean, keep empty means false
|
enabled: # boolean, keep empty means false
|
||||||
# specify the Jekyll environment, empty means both
|
# specify the Jekyll environment, empty means both
|
||||||
# only works if `assets.self_host.enabled` is 'true'
|
# only works if `assets.self_host.enabled` is 'true'
|
||||||
env: # [development|production]
|
env: # [development | production]
|
||||||
|
|
||||||
pwa:
|
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
|
paginate: 10
|
||||||
|
|
||||||
|
# The base URL of your site
|
||||||
|
baseurl: ""
|
||||||
|
|
||||||
# ------------ The following options are not recommended to be modified ------------------
|
# ------------ The following options are not recommended to be modified ------------------
|
||||||
|
|
||||||
kramdown:
|
kramdown:
|
||||||
|
footnote_backlink: "↩︎"
|
||||||
syntax_highlighter: rouge
|
syntax_highlighter: rouge
|
||||||
syntax_highlighter_opts: # Rouge Options › https://github.com/jneen/rouge#full-options
|
syntax_highlighter_opts: # Rouge Options › https://github.com/jneen/rouge#full-options
|
||||||
css_class: highlight
|
css_class: highlight
|
||||||
@@ -157,10 +190,6 @@ defaults:
|
|||||||
values:
|
values:
|
||||||
layout: page
|
layout: page
|
||||||
permalink: /:title/
|
permalink: /:title/
|
||||||
- scope:
|
|
||||||
path: assets/img/favicons
|
|
||||||
values:
|
|
||||||
swcache: true
|
|
||||||
- scope:
|
- scope:
|
||||||
path: assets/js/dist
|
path: assets/js/dist
|
||||||
values:
|
values:
|
||||||
@@ -181,12 +210,11 @@ compress_html:
|
|||||||
exclude:
|
exclude:
|
||||||
- "*.gem"
|
- "*.gem"
|
||||||
- "*.gemspec"
|
- "*.gemspec"
|
||||||
|
- docs
|
||||||
- tools
|
- tools
|
||||||
- README.md
|
- README.md
|
||||||
- CHANGELOG.md
|
|
||||||
- LICENSE
|
- LICENSE
|
||||||
- rollup.config.js
|
- "*.config.js"
|
||||||
- node_modules
|
|
||||||
- package*.json
|
- package*.json
|
||||||
|
|
||||||
jekyll-archives:
|
jekyll-archives:
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
icon: "fab fa-github"
|
icon: "fab fa-github"
|
||||||
|
|
||||||
- type: twitter
|
- type: twitter
|
||||||
icon: "fab fa-twitter"
|
icon: "fa-brands fa-x-twitter"
|
||||||
|
|
||||||
- type: email
|
- type: email
|
||||||
icon: "fas fa-envelope"
|
icon: "fas fa-envelope"
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ post:
|
|||||||
pageview_measure: Aufrufe
|
pageview_measure: Aufrufe
|
||||||
read_time:
|
read_time:
|
||||||
unit: Minuten
|
unit: Minuten
|
||||||
prompt: lesen
|
prompt: Lesezeit
|
||||||
relate_posts: Weiterlesen
|
relate_posts: Weiterlesen
|
||||||
share: Teilen
|
share: Teilen
|
||||||
button:
|
button:
|
||||||
@@ -70,6 +70,13 @@ post:
|
|||||||
title: Link kopieren
|
title: Link kopieren
|
||||||
succeed: Link erfolgreich kopiert!
|
succeed: Link erfolgreich kopiert!
|
||||||
|
|
||||||
|
# Date time format.
|
||||||
|
# See: <http://strftime.net/>, <https://day.js.org/docs/en/display/format>
|
||||||
|
df:
|
||||||
|
post:
|
||||||
|
strftime: "%d.%m.%Y"
|
||||||
|
dayjs: "DD.MM.YYYY"
|
||||||
|
|
||||||
# categories page
|
# categories page
|
||||||
categories:
|
categories:
|
||||||
category_measure:
|
category_measure:
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ copyright:
|
|||||||
Except where otherwise noted, the blog posts on this site are licensed
|
Except where otherwise noted, the blog posts on this site are licensed
|
||||||
under the Creative Commons Attribution 4.0 International (CC BY 4.0) License by the author.
|
under the Creative Commons Attribution 4.0 International (CC BY 4.0) License by the author.
|
||||||
|
|
||||||
meta: Using the :PLATFORM theme :THEME
|
meta: Using the :THEME theme for :PLATFORM.
|
||||||
|
|
||||||
not_found:
|
not_found:
|
||||||
statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
# ----- Commons label -----
|
# ----- Commons label -----
|
||||||
|
|
||||||
layout:
|
layout:
|
||||||
post: Публикация
|
post: Пост
|
||||||
category: Категория
|
category: Категория
|
||||||
tag: Тег
|
tag: Тег
|
||||||
|
|
||||||
# The tabs of sidebar
|
# The tabs of sidebar
|
||||||
tabs:
|
tabs:
|
||||||
# format: <filename_without_extension>: <value>
|
# format: <filename_without_extension>: <value>
|
||||||
home: Домашняя страница
|
home: Главная
|
||||||
categories: Категории
|
categories: Категории
|
||||||
tags: Теги
|
tags: Теги
|
||||||
archives: Архив
|
archives: Архив
|
||||||
@@ -19,8 +19,8 @@ tabs:
|
|||||||
# the text displayed in the search bar & search results
|
# the text displayed in the search bar & search results
|
||||||
search:
|
search:
|
||||||
hint: поиск
|
hint: поиск
|
||||||
cancel: Отменить
|
cancel: Отмена
|
||||||
no_results: Ох! Ничего не найдено.
|
no_results: Упс! Ничего не найдено.
|
||||||
|
|
||||||
panel:
|
panel:
|
||||||
lastmod: Недавно обновлено
|
lastmod: Недавно обновлено
|
||||||
@@ -30,48 +30,58 @@ panel:
|
|||||||
copyright:
|
copyright:
|
||||||
# Shown at the bottom of the post
|
# Shown at the bottom of the post
|
||||||
license:
|
license:
|
||||||
template: Публикация защищена лицензией :LICENSE_NAME.
|
template: Авторский пост защищен лицензией :LICENSE_NAME.
|
||||||
name: CC BY 4.0
|
name: CC BY 4.0
|
||||||
link: https://creativecommons.org/licenses/by/4.0/
|
link: https://creativecommons.org/licenses/by/4.0/
|
||||||
|
|
||||||
# Displayed in the footer
|
# Displayed in the footer
|
||||||
brief: Некоторые права защищены.
|
brief: Некоторые права защищены.
|
||||||
verbose: >-
|
verbose: >-
|
||||||
Публикации на сайте защищены лицензией Creative Commons Attribution 4.0 International (CC BY 4.0),
|
Если не указано иное, авторские посты на этом сайте защищены лицензией Creative Commons Attribution 4.0 International (CC BY 4.0).
|
||||||
если в тексте публикации не указано иное.
|
|
||||||
|
|
||||||
meta: Powered by :PLATFORM with :THEME theme
|
meta: Использует тему :THEME для :PLATFORM
|
||||||
|
|
||||||
not_found:
|
not_found:
|
||||||
statment: Извините, эта ссылка указывает на ресурс который не существует.
|
statment: Извините, мы перепутали URL-адрес или он указывает на что-то несуществующее.
|
||||||
|
|
||||||
notification:
|
notification:
|
||||||
update_found: Доступна новая версия контента.
|
update_found: Доступна новая версия контента.
|
||||||
update: Обновлять
|
update: Обновить
|
||||||
|
|
||||||
# ----- Posts related labels -----
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
post:
|
post:
|
||||||
written_by: Автор
|
written_by: Автор
|
||||||
posted: Время публикации
|
posted: Опубликовано
|
||||||
updated: Обновлено
|
updated: Обновлено
|
||||||
words: слов
|
words: слов
|
||||||
pageview_measure: просмотров
|
pageview_measure: просмотров
|
||||||
read_time:
|
read_time:
|
||||||
unit: минут
|
unit: мин.
|
||||||
prompt: чтения
|
prompt: чтения
|
||||||
relate_posts: Вам также может быть интересно
|
relate_posts: Похожие посты
|
||||||
share: Поделиться
|
share: Поделиться
|
||||||
button:
|
button:
|
||||||
next: Предыдущая публикация
|
next: Следующий пост
|
||||||
previous: Следующая публикация
|
previous: Предыдущий пост
|
||||||
copy_code:
|
copy_code:
|
||||||
succeed: Скопировано успешно!
|
succeed: Скопировано!
|
||||||
share_link:
|
share_link:
|
||||||
title: Скопировать ссылку
|
title: Скопировать ссылку
|
||||||
succeed: Ссылка успешно скопирована!
|
succeed: Ссылка успешно скопирована!
|
||||||
|
|
||||||
|
# Date time format.
|
||||||
|
# See: <http://strftime.net/>, <https://day.js.org/docs/en/display/format>
|
||||||
|
df:
|
||||||
|
post:
|
||||||
|
strftime: "%d.%m.%Y"
|
||||||
|
dayjs: "DD.MM.YYYY"
|
||||||
|
|
||||||
# categories page
|
# categories page
|
||||||
categories:
|
categories:
|
||||||
category_measure: категории
|
category_measure:
|
||||||
post_measure: публикации
|
singular: категория
|
||||||
|
plural: категории
|
||||||
|
post_measure:
|
||||||
|
singular: пост
|
||||||
|
plural: посты
|
||||||
|
|||||||
91
_data/locales/th.yml
Normal file
91
_data/locales/th.yml
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# The layout text of site
|
||||||
|
|
||||||
|
# ----- Commons label -----
|
||||||
|
|
||||||
|
layout:
|
||||||
|
post: โพสต์
|
||||||
|
category: หมวดหมู่
|
||||||
|
tag: แท็ก
|
||||||
|
|
||||||
|
# The tabs of sidebar
|
||||||
|
tabs:
|
||||||
|
# format: <filename_without_extension>: <value>
|
||||||
|
home: หน้าแรก
|
||||||
|
categories: หมวดหมู่
|
||||||
|
tags: แท็ก
|
||||||
|
archives: คลังเก็บ
|
||||||
|
about: เกี่ยวกับ
|
||||||
|
|
||||||
|
# the text displayed in the search bar & search results
|
||||||
|
search:
|
||||||
|
hint: ค้นหา
|
||||||
|
cancel: ยกเลิก
|
||||||
|
no_results: โอ๊ะ! ไม่พบผลลัพธ์
|
||||||
|
|
||||||
|
panel:
|
||||||
|
lastmod: อัปเดตล่าสุด
|
||||||
|
trending_tags: แท็กยอดนิยม
|
||||||
|
toc: เนื้อหา
|
||||||
|
|
||||||
|
copyright:
|
||||||
|
# Shown at the bottom of the post
|
||||||
|
license:
|
||||||
|
template: โพสต์นี้อยู่ภายใต้การอนุญาต :LICENSE_NAME โดยผู้เขียน
|
||||||
|
name: CC BY 4.0
|
||||||
|
link: https://creativecommons.org/licenses/by/4.0/
|
||||||
|
|
||||||
|
# Displayed in the footer
|
||||||
|
brief: สงวนลิขสิทธิ์เป็นบางส่วน
|
||||||
|
verbose: >-
|
||||||
|
เว้นแต่ว่าจะระบุเป็นอย่างอื่น โพสต์บนเว็บไซต์นี้อยู่ภายใต้
|
||||||
|
สัญญาอนุญาตครีเอทีฟคอมมอนส์แบบ 4.0 นานาชาติ (CC BY 4.0) โดยผู้เขียน
|
||||||
|
|
||||||
|
meta: กำลังใช้ธีมของ :PLATFORM ชื่อ :THEME
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
statment: ขออภัย เราวาง URL นั้นไว้ผิดที่ หรือมันชี้ไปยังสิ่งที่ไม่มีอยู่
|
||||||
|
|
||||||
|
notification:
|
||||||
|
update_found: มีเวอร์ชันใหม่ของเนื้อหา
|
||||||
|
update: อัปเดต
|
||||||
|
|
||||||
|
# ----- Posts related labels -----
|
||||||
|
|
||||||
|
post:
|
||||||
|
written_by: โดย
|
||||||
|
posted: โพสต์เมื่อ
|
||||||
|
updated: อัปเดตเมื่อ
|
||||||
|
words: คำ
|
||||||
|
pageview_measure: ครั้ง
|
||||||
|
read_time:
|
||||||
|
unit: นาที
|
||||||
|
prompt: อ่าน
|
||||||
|
relate_posts: อ่านต่อ
|
||||||
|
share: แชร์
|
||||||
|
button:
|
||||||
|
next: ใหม่กว่า
|
||||||
|
previous: เก่ากว่า
|
||||||
|
copy_code:
|
||||||
|
succeed: คัดลอกแล้ว!
|
||||||
|
share_link:
|
||||||
|
title: คัดลอกลิงก์
|
||||||
|
succeed: คัดลอกลิงก์เรียบร้อยแล้ว!
|
||||||
|
|
||||||
|
# Date time format.
|
||||||
|
# See: <http://strftime.net/>, <https://day.js.org/docs/en/display/format>
|
||||||
|
df:
|
||||||
|
post:
|
||||||
|
strftime: "%b %e, %Y"
|
||||||
|
dayjs: "ll"
|
||||||
|
archives:
|
||||||
|
strftime: "%b"
|
||||||
|
dayjs: "MMM"
|
||||||
|
|
||||||
|
# categories page
|
||||||
|
categories:
|
||||||
|
category_measure:
|
||||||
|
singular: หมวดหมู่
|
||||||
|
plural: หมวดหมู่
|
||||||
|
post_measure:
|
||||||
|
singular: โพสต์
|
||||||
|
plural: โพสต์
|
||||||
@@ -23,7 +23,7 @@ search:
|
|||||||
no_results: Hop! Öyle bir şey bulamadım.
|
no_results: Hop! Öyle bir şey bulamadım.
|
||||||
|
|
||||||
panel:
|
panel:
|
||||||
lastmod: Yeni Güncellendi
|
lastmod: Son Güncellenenler
|
||||||
trending_tags: Yükselen Etiketler
|
trending_tags: Yükselen Etiketler
|
||||||
toc: İçindekiler
|
toc: İçindekiler
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ copyright:
|
|||||||
brief: Bazı hakları saklıdır.
|
brief: Bazı hakları saklıdır.
|
||||||
verbose: >-
|
verbose: >-
|
||||||
Aksi belirtilmediği sürece, bu sitedeki gönderiler Creative Commons Atıf 4.0 Uluslararası (CC BY 4.0) Lisansı altındadır.
|
Aksi belirtilmediği sürece, bu sitedeki gönderiler Creative Commons Atıf 4.0 Uluslararası (CC BY 4.0) Lisansı altındadır.
|
||||||
Kısaca sayfa linkini de vererek paylaşabilir veya düzenleyip paylaşabilirsin.
|
Kısaca sayfa linkini vererek değiştirebilir / paylaşabilirsiniz.
|
||||||
|
|
||||||
meta: :PLATFORM ve :THEME teması
|
meta: :PLATFORM ve :THEME teması
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ notification:
|
|||||||
|
|
||||||
post:
|
post:
|
||||||
written_by: Yazan
|
written_by: Yazan
|
||||||
posted: Gönderilme Tarihi
|
posted: Gönderim
|
||||||
updated: Güncellenme Tarihi
|
updated: Güncelleme
|
||||||
words: sözcük
|
words: sözcük
|
||||||
pageview_measure: görüntülenme
|
pageview_measure: görüntülenme
|
||||||
read_time:
|
read_time:
|
||||||
|
|||||||
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
|
# 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:
|
toc:
|
||||||
css: /assets/lib/tocbot/tocbot.min.css
|
css: /assets/lib/tocbot/tocbot.min.css
|
||||||
js: /assets/lib/tocbot/tocbot.min.js
|
js: /assets/lib/tocbot/tocbot.min.js
|
||||||
@@ -31,21 +24,16 @@ dayjs:
|
|||||||
relativeTime: /assets/lib/dayjs/plugin/relativeTime.min.js
|
relativeTime: /assets/lib/dayjs/plugin/relativeTime.min.js
|
||||||
localizedFormat: /assets/lib/dayjs/plugin/localizedFormat.min.js
|
localizedFormat: /assets/lib/dayjs/plugin/localizedFormat.min.js
|
||||||
|
|
||||||
countup:
|
glightbox:
|
||||||
js: /assets/lib/countup.js/countUp.min.js
|
css: /assets/lib/glightbox/glightbox.min.css
|
||||||
|
js: /assets/lib/glightbox/glightbox.min.js
|
||||||
|
|
||||||
magnific-popup:
|
lazy-polyfill:
|
||||||
css: /assets/lib/magnific-popup/magnific-popup.css
|
css: /assets/lib/loading-attribute-polyfill/loading-attribute-polyfill.min.css
|
||||||
js: /assets/lib/magnific-popup/jquery.magnific-popup.min.js
|
js: /assets/lib/loading-attribute-polyfill/loading-attribute-polyfill.umd.min.js
|
||||||
|
|
||||||
lazysizes:
|
|
||||||
js: /assets/lib/lazysizes/lazysizes.min.js
|
|
||||||
|
|
||||||
clipboard:
|
clipboard:
|
||||||
js: /assets/lib/clipboard/clipboard.min.js
|
js: /assets/lib/clipboard/clipboard.min.js
|
||||||
|
|
||||||
polyfill:
|
|
||||||
js: /assets/lib/polyfill-v3-es6/polyfill.min.js
|
|
||||||
|
|
||||||
mathjax:
|
mathjax:
|
||||||
js: /assets/lib/mathjax/tex-chtml.js
|
js: /assets/lib/mathjax/tex-chtml.js
|
||||||
|
|||||||
@@ -1,62 +1,54 @@
|
|||||||
# CDNs
|
# Resource Hints
|
||||||
|
resource_hints:
|
||||||
cdns:
|
|
||||||
# Google Fonts
|
|
||||||
- url: https://fonts.googleapis.com
|
- url: https://fonts.googleapis.com
|
||||||
|
links:
|
||||||
|
- rel: preconnect
|
||||||
|
- rel: dns-prefetch
|
||||||
- url: https://fonts.gstatic.com
|
- url: https://fonts.gstatic.com
|
||||||
args: crossorigin
|
links:
|
||||||
- url: https://fonts.googleapis.com
|
- rel: preconnect
|
||||||
# jsDelivr CDN
|
opts: [crossorigin]
|
||||||
|
- rel: dns-prefetch
|
||||||
- url: https://cdn.jsdelivr.net
|
- url: https://cdn.jsdelivr.net
|
||||||
|
links:
|
||||||
|
- rel: preconnect
|
||||||
|
- rel: dns-prefetch
|
||||||
|
|
||||||
# fonts
|
# Web Fonts
|
||||||
|
webfonts: https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Source+Sans+Pro:wght@400;600;700;900&display=swap
|
||||||
webfonts: https://fonts.googleapis.com/css2?family=Lato&family=Source+Sans+Pro:wght@400;600;900&display=swap
|
|
||||||
|
|
||||||
# Libraries
|
# Libraries
|
||||||
|
|
||||||
jquery:
|
|
||||||
js: https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js
|
|
||||||
|
|
||||||
bootstrap:
|
|
||||||
css: https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css
|
|
||||||
js: https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js
|
|
||||||
|
|
||||||
toc:
|
toc:
|
||||||
css: https://cdn.jsdelivr.net/npm/tocbot@4.21.0/dist/tocbot.min.css
|
css: https://cdn.jsdelivr.net/npm/tocbot@4.25.0/dist/tocbot.min.css
|
||||||
js: https://cdn.jsdelivr.net/npm/tocbot@4.21.0/dist/tocbot.min.js
|
js: https://cdn.jsdelivr.net/npm/tocbot@4.25.0/dist/tocbot.min.js
|
||||||
|
|
||||||
fontawesome:
|
fontawesome:
|
||||||
css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/css/all.min.css
|
css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css
|
||||||
|
|
||||||
search:
|
search:
|
||||||
js: https://cdn.jsdelivr.net/npm/simple-jekyll-search@1.10.0/dest/simple-jekyll-search.min.js
|
js: https://cdn.jsdelivr.net/npm/simple-jekyll-search@1.10.0/dest/simple-jekyll-search.min.js
|
||||||
|
|
||||||
mermaid:
|
mermaid:
|
||||||
js: https://cdn.jsdelivr.net/npm/mermaid@9.4.3/dist/mermaid.min.js
|
js: https://cdn.jsdelivr.net/npm/mermaid@10.8.0/dist/mermaid.min.js
|
||||||
|
|
||||||
dayjs:
|
dayjs:
|
||||||
js:
|
js:
|
||||||
common: https://cdn.jsdelivr.net/npm/dayjs@1.11.7/dayjs.min.js
|
common: https://cdn.jsdelivr.net/npm/dayjs@1.11.10/dayjs.min.js
|
||||||
locale: https://cdn.jsdelivr.net/npm/dayjs@1.11.7/locale/:LOCALE.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.7/plugin/relativeTime.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.7/plugin/localizedFormat.min.js
|
localizedFormat: https://cdn.jsdelivr.net/npm/dayjs@1.11.10/plugin/localizedFormat.min.js
|
||||||
|
|
||||||
countup:
|
glightbox:
|
||||||
js: https://cdn.jsdelivr.net/npm/countup.js@1.9.3/dist/countUp.min.js
|
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
|
||||||
|
|
||||||
magnific-popup:
|
lazy-polyfill:
|
||||||
css: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/magnific-popup.min.css
|
css: https://cdn.jsdelivr.net/npm/loading-attribute-polyfill@2.1.1/dist/loading-attribute-polyfill.min.css
|
||||||
js: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/jquery.magnific-popup.min.js
|
js: https://cdn.jsdelivr.net/npm/loading-attribute-polyfill@2.1.1/dist/loading-attribute-polyfill.umd.min.js
|
||||||
|
|
||||||
lazysizes:
|
|
||||||
js: https://cdn.jsdelivr.net/npm/lazysizes@5.3.2/lazysizes.min.js
|
|
||||||
|
|
||||||
clipboard:
|
clipboard:
|
||||||
js: https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js
|
js: https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js
|
||||||
|
|
||||||
polyfill:
|
|
||||||
js: https://polyfill.io/v3/polyfill.min.js?features=es6
|
|
||||||
|
|
||||||
mathjax:
|
mathjax:
|
||||||
js: https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-chtml.js
|
js: https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-chtml.js
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
platforms:
|
platforms:
|
||||||
- type: Twitter
|
- type: Twitter
|
||||||
icon: "fab fa-twitter"
|
icon: "fa-brands fa-square-x-twitter"
|
||||||
link: "https://twitter.com/intent/tweet?text=TITLE&url=URL"
|
link: "https://twitter.com/intent/tweet?text=TITLE&url=URL"
|
||||||
|
|
||||||
- type: Facebook
|
- type: Facebook
|
||||||
@@ -22,4 +22,17 @@ platforms:
|
|||||||
#
|
#
|
||||||
# - type: Weibo
|
# - type: Weibo
|
||||||
# icon: "fab fa-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"
|
||||||
|
# # See: https://github.com/justinribeiro/share-to-mastodon#properties
|
||||||
|
# instances:
|
||||||
|
# - label: mastodon.social
|
||||||
|
# link: "https://mastodon.social/"
|
||||||
|
# - label: mastodon.online
|
||||||
|
# link: "https://mastodon.online/"
|
||||||
|
# - label: fosstodon.org
|
||||||
|
# link: "https://fosstodon.org/"
|
||||||
|
# - label: photog.social
|
||||||
|
# link: "https://photog.social/"
|
||||||
|
|||||||
7
_includes/analytics/cloudflare.html
Normal file
7
_includes/analytics/cloudflare.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<!-- Cloudflare Web Analytics -->
|
||||||
|
<script
|
||||||
|
defer
|
||||||
|
src="https://static.cloudflareinsights.com/beacon.min.js"
|
||||||
|
data-cf-beacon='{"token": "{{ site.analytics.cloudflare.id }}"}'
|
||||||
|
></script>
|
||||||
|
<!-- End Cloudflare Web Analytics -->
|
||||||
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', function (event) {
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag() {
|
||||||
|
dataLayer.push(arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', '{{ site.analytics.google.id }}');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
14
_includes/analytics/matomo.html
Normal file
14
_includes/analytics/matomo.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<!-- Matomo -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var _paq = window._paq = window._paq || [];
|
||||||
|
_paq.push(['trackPageView']);
|
||||||
|
_paq.push(['enableLinkTracking']);
|
||||||
|
(function() {
|
||||||
|
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>
|
||||||
|
<!-- End Matomo Code -->
|
||||||
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>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- The comments switcher -->
|
<!-- The comments switcher -->
|
||||||
{% if page.comments and site.comments.active %}
|
{% if page.comments and site.comments.provider %}
|
||||||
{% capture path %}comments/{{ site.comments.active }}.html{% endcapture %}
|
{% capture path %}comments/{{ site.comments.provider }}.html{% endcapture %}
|
||||||
{% include {{ path }} %}
|
{% include {{ path }} %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<!-- The Disqus lazy loading. -->
|
<!-- The Disqus lazy loading. -->
|
||||||
<div id="disqus_thread" class="pt-2 pb-2">
|
|
||||||
|
<div id="disqus_thread">
|
||||||
<p class="text-center text-muted small">Comments powered by <a href="https://disqus.com/">Disqus</a>.</p>
|
<p class="text-center text-muted small">Comments powered by <a href="https://disqus.com/">Disqus</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@
|
|||||||
this.page.identifier = '{{ page.url }}';
|
this.page.identifier = '{{ page.url }}';
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Lazy loading */
|
{%- comment -%} Lazy loading {%- endcomment -%}
|
||||||
var disqus_observer = new IntersectionObserver(
|
var disqus_observer = new IntersectionObserver(
|
||||||
function (entries) {
|
function (entries) {
|
||||||
if (entries[0].isIntersecting) {
|
if (entries[0].isIntersecting) {
|
||||||
@@ -27,12 +28,12 @@
|
|||||||
{ threshold: [0] }
|
{ threshold: [0] }
|
||||||
);
|
);
|
||||||
|
|
||||||
disqus_observer.observe(document.querySelector('#disqus_thread'));
|
disqus_observer.observe(document.getElementById('disqus_thread'));
|
||||||
|
|
||||||
/* Auto switch theme */
|
{%- comment -%} Auto switch theme {%- endcomment -%}
|
||||||
function reloadDisqus() {
|
function reloadDisqus() {
|
||||||
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
||||||
/* Disqus hasn't been loaded */
|
{%- comment -%} Disqus hasn't been loaded {%- endcomment -%}
|
||||||
if (typeof DISQUS === 'undefined') {
|
if (typeof DISQUS === 'undefined') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -43,7 +44,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.querySelector('.mode-toggle')) {
|
if (document.getElementById('mode-toggle')) {
|
||||||
window.addEventListener('message', reloadDisqus);
|
window.addEventListener('message', reloadDisqus);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
(function () {
|
(function () {
|
||||||
const origin = 'https://giscus.app';
|
const origin = 'https://giscus.app';
|
||||||
const iframe = 'iframe.giscus-frame';
|
|
||||||
const lightTheme = 'light';
|
const lightTheme = 'light';
|
||||||
const darkTheme = 'dark_dimmed';
|
const darkTheme = 'dark_dimmed';
|
||||||
|
|
||||||
@@ -25,11 +24,13 @@
|
|||||||
'data-category': '{{ site.comments.giscus.category }}',
|
'data-category': '{{ site.comments.giscus.category }}',
|
||||||
'data-category-id': '{{ site.comments.giscus.category_id }}',
|
'data-category-id': '{{ site.comments.giscus.category_id }}',
|
||||||
'data-mapping': '{{ site.comments.giscus.mapping | default: 'pathname' }}',
|
'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-reactions-enabled': '{{ site.comments.giscus.reactions_enabled | default: '1' }}',
|
||||||
'data-emit-metadata': '0',
|
'data-emit-metadata': '0',
|
||||||
'data-theme': initTheme,
|
'data-theme': initTheme,
|
||||||
'data-input-position': '{{ site.comments.giscus.input_position | default: 'bottom' }}',
|
'data-input-position': '{{ site.comments.giscus.input_position | default: 'bottom' }}',
|
||||||
'data-lang': '{{ site.comments.giscus.lang | default: lang }}',
|
'data-lang': '{{ site.comments.giscus.lang | default: lang }}',
|
||||||
|
'data-loading': 'lazy',
|
||||||
crossorigin: 'anonymous',
|
crossorigin: 'anonymous',
|
||||||
async: ''
|
async: ''
|
||||||
};
|
};
|
||||||
@@ -46,7 +47,7 @@
|
|||||||
event.data &&
|
event.data &&
|
||||||
event.data.direction === ModeToggle.ID
|
event.data.direction === ModeToggle.ID
|
||||||
) {
|
) {
|
||||||
/* global theme mode changed */
|
{%- comment -%} global theme mode changed {%- endcomment -%}
|
||||||
const mode = event.data.message;
|
const mode = event.data.message;
|
||||||
const theme = mode === ModeToggle.DARK_MODE ? darkTheme : lightTheme;
|
const theme = mode === ModeToggle.DARK_MODE ? darkTheme : lightTheme;
|
||||||
|
|
||||||
@@ -56,7 +57,7 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const giscus = document.querySelector(iframe).contentWindow;
|
const giscus = document.getElementsByClassName('giscus-frame')[0].contentWindow;
|
||||||
giscus.postMessage({ giscus: message }, origin);
|
giscus.postMessage({ giscus: message }, origin);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,51 +1,49 @@
|
|||||||
<!-- https://utteranc.es/ -->
|
<!-- https://utteranc.es/ -->
|
||||||
<script src="https://utteranc.es/client.js"
|
<script
|
||||||
|
src="https://utteranc.es/client.js"
|
||||||
repo="{{ site.comments.utterances.repo }}"
|
repo="{{ site.comments.utterances.repo }}"
|
||||||
issue-term="{{ site.comments.utterances.issue_term }}"
|
issue-term="{{ site.comments.utterances.issue_term }}"
|
||||||
crossorigin="anonymous"
|
crossorigin="anonymous"
|
||||||
async>
|
async
|
||||||
</script>
|
></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function() {
|
(function () {
|
||||||
const origin = "https://utteranc.es";
|
const origin = 'https://utteranc.es';
|
||||||
const iframe = "iframe.utterances-frame";
|
const lightTheme = 'github-light';
|
||||||
const lightTheme = "github-light";
|
const darkTheme = 'github-dark';
|
||||||
const darkTheme = "github-dark";
|
|
||||||
let initTheme = lightTheme;
|
let initTheme = lightTheme;
|
||||||
|
const html = document.documentElement;
|
||||||
|
|
||||||
if ($("html[data-mode=dark]").length > 0
|
if (
|
||||||
|| ($("html[data-mode]").length == 0
|
(html.hasAttribute('data-mode') && html.getAttribute('data-mode') === 'dark') ||
|
||||||
&& window.matchMedia("(prefers-color-scheme: dark)").matches)) {
|
(!html.hasAttribute('data-mode') && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
||||||
|
) {
|
||||||
initTheme = darkTheme;
|
initTheme = darkTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
addEventListener("message", (event) => {
|
addEventListener('message', (event) => {
|
||||||
let theme;
|
let theme;
|
||||||
|
|
||||||
/* credit to <https://github.com/utterance/utterances/issues/170#issuecomment-594036347> */
|
{%- comment -%} credit to <https://github.com/utterance/utterances/issues/170#issuecomment-594036347> {%- endcomment -%}
|
||||||
if (event.origin === origin) {
|
if (event.origin === origin) {
|
||||||
/* page initial */
|
{%- comment -%} page initial {%- endcomment -%}
|
||||||
theme = initTheme;
|
theme = initTheme;
|
||||||
|
} else if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
||||||
} else if (event.source === window && event.data &&
|
{%- comment -%} global theme mode changed {%- endcomment -%}
|
||||||
event.data.direction === ModeToggle.ID) {
|
|
||||||
/* global theme mode changed */
|
|
||||||
const mode = event.data.message;
|
const mode = event.data.message;
|
||||||
theme = (mode === ModeToggle.DARK_MODE ? darkTheme : lightTheme);
|
theme = mode === ModeToggle.DARK_MODE ? darkTheme : lightTheme;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = {
|
const message = {
|
||||||
type: "set-theme",
|
type: 'set-theme',
|
||||||
theme: theme
|
theme: theme
|
||||||
};
|
};
|
||||||
|
|
||||||
const utterances = document.querySelector(iframe).contentWindow;
|
const utterances = document.getElementsByClassName('utterances-frame')[0].contentWindow;
|
||||||
utterances.postMessage(message, origin);
|
utterances.postMessage(message, origin);
|
||||||
});
|
});
|
||||||
|
})();
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
See: ${JS_ROOT}/utils/locale-dateime.js
|
See: ${JS_ROOT}/utils/locale-dateime.js
|
||||||
-->
|
-->
|
||||||
|
|
||||||
{% assign wrap_elem = include.wrap | default: 'em' %}
|
|
||||||
{% assign df_strftime = site.data.locales[include.lang].df.post.strftime | default: '%d/%m/%Y' %}
|
{% assign df_strftime = site.data.locales[include.lang].df.post.strftime | default: '%d/%m/%Y' %}
|
||||||
{% assign df_dayjs = site.data.locales[include.lang].df.post.dayjs | default: 'DD/MM/YYYY' %}
|
{% assign df_dayjs = site.data.locales[include.lang].df.post.dayjs | default: 'DD/MM/YYYY' %}
|
||||||
|
|
||||||
<{{ wrap_elem }}
|
<time
|
||||||
class="{% if include.class %}{{ include.class }}{% endif %}"
|
{% if include.class %}
|
||||||
|
class="{{ include.class }}"
|
||||||
|
{% endif %}
|
||||||
data-ts="{{ include.date | date: '%s' }}"
|
data-ts="{{ include.date | date: '%s' }}"
|
||||||
data-df="{{ df_dayjs }}"
|
data-df="{{ df_dayjs }}"
|
||||||
{% if include.tooltip %}
|
{% if include.tooltip %}
|
||||||
@@ -16,4 +17,4 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
>
|
>
|
||||||
{{ include.date | date: df_strftime }}
|
{{ include.date | date: df_strftime }}
|
||||||
</{{ wrap_elem }}>
|
</time>
|
||||||
|
|||||||
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 %}
|
||||||
|
{%- 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>
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
<iframe class="embed-video twitch lazyload"
|
<iframe
|
||||||
|
class="embed-video twitch"
|
||||||
|
loading="lazy"
|
||||||
src="https://player.twitch.tv/?video={{ include.id }}&parent={{ site.url | split: '://' | last | remove: '/' }}"
|
src="https://player.twitch.tv/?video={{ include.id }}&parent={{ site.url | split: '://' | last | remove: '/' }}"
|
||||||
frameborder="0" allowfullscreen="true"
|
frameborder="0"
|
||||||
scrolling="no"></iframe>
|
allowfullscreen="true"
|
||||||
|
scrolling="no"
|
||||||
|
></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 %}
|
||||||
|
{%- 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,6 +1,9 @@
|
|||||||
<iframe class="embed-video youtube lazyload"
|
<iframe
|
||||||
|
class="embed-video"
|
||||||
|
loading="lazy"
|
||||||
src="https://www.youtube.com/embed/{{ include.id }}"
|
src="https://www.youtube.com/embed/{{ include.id }}"
|
||||||
title="YouTube video player"
|
title="YouTube video player"
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
||||||
allowfullscreen></iframe>
|
allowfullscreen
|
||||||
|
></iframe>
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ favicon_path }}/apple-touch-icon.png">
|
<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="32x32" href="{{ favicon_path }}/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ favicon_path }}/favicon-16x16.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">
|
<link rel="shortcut icon" href="{{ favicon_path }}/favicon.ico">
|
||||||
<meta name="apple-mobile-web-app-title" content="{{ site.title }}">
|
<meta name="apple-mobile-web-app-title" content="{{ site.title }}">
|
||||||
<meta name="application-name" content="{{ site.title }}">
|
<meta name="application-name" content="{{ site.title }}">
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
<!-- The Footer -->
|
<!-- The Footer -->
|
||||||
|
|
||||||
<footer>
|
<footer
|
||||||
<div class="container px-lg-4">
|
aria-label="Site Info"
|
||||||
<div class="d-flex justify-content-center align-items-center text-muted mx-md-3">
|
class="
|
||||||
<p>
|
d-flex flex-column justify-content-center text-muted
|
||||||
{%- capture _platform -%}
|
flex-lg-row justify-content-lg-between align-items-lg-center pb-lg-3
|
||||||
<a href="https://jekyllrb.com" target="_blank" rel="noopener">Jekyll</a>
|
"
|
||||||
{%- endcapture -%}
|
>
|
||||||
|
|
||||||
{%- capture _theme -%}
|
|
||||||
<a 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 }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
{{- '©' }}
|
{{- '©' }}
|
||||||
{{ 'now' | date: '%Y' }}
|
<time>{{ 'now' | date: '%Y' }}</time>
|
||||||
|
|
||||||
|
{% if site.social.links %}
|
||||||
<a href="{{ site.social.links[0] }}">{{ site.social.name }}</a>.
|
<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 %}
|
{% if site.data.locales[include.lang].copyright.brief %}
|
||||||
<span
|
<span
|
||||||
data-bs-toggle="tooltip"
|
data-bs-toggle="tooltip"
|
||||||
@@ -29,6 +27,23 @@
|
|||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
</div>
|
<p>
|
||||||
|
{%- capture _platform -%}
|
||||||
|
<a href="https://jekyllrb.com" target="_blank" rel="noopener">Jekyll</a>
|
||||||
|
{%- endcapture -%}
|
||||||
|
|
||||||
|
{%- capture _theme -%}
|
||||||
|
<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 }}
|
||||||
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -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,5 +1,3 @@
|
|||||||
<!-- The Head -->
|
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<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: light)" content="#f7f7f7">
|
||||||
@@ -11,39 +9,43 @@
|
|||||||
content="width=device-width, user-scalable=no initial-scale=1, shrink-to-fit=no, viewport-fit=cover"
|
content="width=device-width, user-scalable=no initial-scale=1, shrink-to-fit=no, viewport-fit=cover"
|
||||||
>
|
>
|
||||||
|
|
||||||
{% if page.layout == 'home' or page.layout == 'post' %}
|
{%- capture seo_tags -%}
|
||||||
{% if site.google_analytics.pv.proxy_endpoint %}
|
|
||||||
<meta name="pv-proxy-endpoint" content="{{ site.google_analytics.pv.proxy_endpoint }}">
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if site.google_analytics.pv.cache_path %}
|
|
||||||
<meta name="pv-cache-path" content="{{ site.google_analytics.pv.cache_path | relative_url }}">
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% capture seo_tags %}
|
|
||||||
{% seo title=false %}
|
{% seo title=false %}
|
||||||
{% endcapture %}
|
{%- endcapture -%}
|
||||||
|
|
||||||
|
<!-- Setup Open Graph image -->
|
||||||
|
|
||||||
{% if page.image %}
|
{% if page.image %}
|
||||||
{% assign img = page.image.path | default: page.image %}
|
{% assign src = page.image.path | default: page.image %}
|
||||||
|
|
||||||
{% unless img contains '://' %}
|
{% unless src contains '://' %}
|
||||||
{% assign img_path = page.img_path | append: '/' | append: img | replace: '//', '/' %}
|
{%- capture img_url -%}
|
||||||
{% capture target %}"{{ img | absolute_url }}"{% endcapture %}
|
{% include media-url.html src=src subpath=page.media_subpath absolute=true %}
|
||||||
|
|
||||||
{% 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 -%}
|
{%- endcapture -%}
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% assign seo_tags = seo_tags | replace: target, replacement %}
|
{%- capture old_url -%}{{ src | absolute_url }}{%- endcapture -%}
|
||||||
|
{%- capture new_url -%}{{ img_url }}{%- endcapture -%}
|
||||||
|
|
||||||
|
{% assign seo_tags = seo_tags | replace: old_url, new_url %}
|
||||||
{% endunless %}
|
{% 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 %}
|
{% endif %}
|
||||||
|
|
||||||
{{ seo_tags }}
|
{{ seo_tags }}
|
||||||
@@ -55,55 +57,44 @@
|
|||||||
{{ site.title }}
|
{{ site.title }}
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
{% include favicons.html %}
|
{% include_cached favicons.html %}
|
||||||
|
|
||||||
{% if site.resources.ignore_env != jekyll.environment and site.resources.self_hosted %}
|
<!-- Resource Hints -->
|
||||||
<link href="{{ site.data.origin[type].webfonts | relative_url }}" rel="stylesheet">
|
{% unless site.assets.self_host.enabled %}
|
||||||
|
{% for hint in site.data.origin.cors.resource_hints %}
|
||||||
{% else %}
|
{% for link in hint.links %}
|
||||||
{% for cdn in site.data.origin[type].cdns %}
|
<link rel="{{ link.rel }}" href="{{ hint.url }}" {{ link.opts | join: ' ' }}>
|
||||||
<link rel="preconnect" href="{{ cdn.url }}" {{ cdn.args }}>
|
|
||||||
<link rel="dns-prefetch" href="{{ cdn.url }}" {{ cdn.args }}>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
<link rel="stylesheet" href="{{ site.data.origin[type].webfonts | relative_url }}">
|
{% endunless %}
|
||||||
{% 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">
|
|
||||||
|
|
||||||
{% if site.google_analytics.pv.proxy_endpoint %}
|
|
||||||
{% assign proxy_url = site.google_analytics.pv.proxy_endpoint
|
|
||||||
| replace: 'https://', ''
|
|
||||||
| split: '/'
|
|
||||||
| first
|
|
||||||
| prepend: 'https://'
|
|
||||||
%}
|
|
||||||
<link rel="preconnect" href="{{ proxy_url }}" crossorigin="use-credentials">
|
|
||||||
<link rel="dns-prefetch" href="{{ proxy_url }}">
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- Bootstrap -->
|
<!-- 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="{{ site.data.origin[type].fontawesome.css | relative_url }}">
|
||||||
|
|
||||||
<link rel="stylesheet" href="{{ '/assets/css/style.css' | relative_url }}">
|
<!-- 3rd-party Dependencies -->
|
||||||
|
|
||||||
{% if site.toc and page.toc %}
|
{% if site.toc and page.toc %}
|
||||||
<link rel="stylesheet" href="{{ site.data.origin[type].toc.css | relative_url }}">
|
<link rel="stylesheet" href="{{ site.data.origin[type].toc.css | relative_url }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if page.layout == 'post' or page.layout == 'page' or page.layout == 'home' %}
|
||||||
|
<link rel="stylesheet" href="{{ site.data.origin[type]['lazy-polyfill'].css | relative_url }}">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if page.layout == 'page' or page.layout == 'post' %}
|
{% if page.layout == 'page' or page.layout == 'post' %}
|
||||||
<!-- Manific Popup -->
|
<!-- Image Popup -->
|
||||||
<link rel="stylesheet" href="{{ site.data.origin[type].magnific-popup.css | relative_url }}">
|
<link rel="stylesheet" href="{{ site.data.origin[type].glightbox.css | relative_url }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- JavaScript -->
|
<!-- JavaScript -->
|
||||||
|
|||||||
@@ -2,30 +2,20 @@
|
|||||||
|
|
||||||
<!-- commons -->
|
<!-- commons -->
|
||||||
|
|
||||||
{% assign urls = site.data.origin[type].jquery.js
|
{% assign urls = site.data.origin[type].search.js %}
|
||||||
| append: ','
|
|
||||||
| append: site.data.origin[type].bootstrap.js
|
|
||||||
| append: ','
|
|
||||||
| append: site.data.origin[type].search.js
|
|
||||||
%}
|
|
||||||
|
|
||||||
<!-- layout specified -->
|
<!-- layout specified -->
|
||||||
|
|
||||||
{% if page.layout == 'post' %}
|
{% assign js_dist = '/assets/js/dist/' %}
|
||||||
{% if site.google_analytics.pv.proxy_endpoint or site.google_analytics.pv.cache_path %}
|
|
||||||
<!-- pv-report needs countup.js -->
|
|
||||||
{% assign urls = urls | append: ',' | append: site.data.origin[type].countup.js %}
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if page.layout == 'post' or page.layout == 'page' or page.layout == 'home' %}
|
{% if page.layout == 'post' or page.layout == 'page' or page.layout == 'home' %}
|
||||||
{% assign urls = urls | append: ',' | append: site.data.origin[type].lazysizes.js %}
|
{% assign urls = urls | append: ',' | append: site.data.origin[type]['lazy-polyfill'].js %}
|
||||||
|
|
||||||
{% unless page.layout == 'home' %}
|
{% unless page.layout == 'home' %}
|
||||||
<!-- image lazy-loading & popup & clipboard -->
|
<!-- image lazy-loading & popup & clipboard -->
|
||||||
{% assign urls = urls
|
{% assign urls = urls
|
||||||
| append: ','
|
| append: ','
|
||||||
| append: site.data.origin[type]['magnific-popup'].js
|
| append: site.data.origin[type].glightbox.js
|
||||||
| append: ','
|
| append: ','
|
||||||
| append: site.data.origin[type].clipboard.js
|
| append: site.data.origin[type].clipboard.js
|
||||||
%}
|
%}
|
||||||
@@ -38,7 +28,7 @@
|
|||||||
or page.layout == 'category'
|
or page.layout == 'category'
|
||||||
or page.layout == 'tag'
|
or page.layout == 'tag'
|
||||||
%}
|
%}
|
||||||
{% assign locale = site.lang | split: '-' | first %}
|
{% assign locale = include.lang | split: '-' | first %}
|
||||||
|
|
||||||
{% assign urls = urls
|
{% assign urls = urls
|
||||||
| append: ','
|
| append: ','
|
||||||
@@ -72,42 +62,46 @@
|
|||||||
{% assign js = 'commons' %}
|
{% assign js = 'commons' %}
|
||||||
{% endcase %}
|
{% endcase %}
|
||||||
|
|
||||||
{% capture script %}/assets/js/dist/{{ js }}.min.js{% endcapture %}
|
{% capture script %}{{ js_dist }}{{ js }}.min.js{% endcapture %}
|
||||||
<script defer src="{{ script | relative_url }}"></script>
|
<script src="{{ script | relative_url }}"></script>
|
||||||
|
|
||||||
{% if page.math %}
|
{% if page.math %}
|
||||||
<!-- MathJax -->
|
<!-- MathJax -->
|
||||||
<script>
|
<script src="{{ '/assets/js/data/mathjax.js' | relative_url }}"></script>
|
||||||
/* see: <https://docs.mathjax.org/en/latest/options/input/tex.html#tex-options> */
|
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=es6"></script>
|
||||||
MathJax = {
|
|
||||||
tex: {
|
|
||||||
/* start/end delimiter pairs for in-line math */
|
|
||||||
inlineMath: [
|
|
||||||
['$', '$'],
|
|
||||||
['\\(', '\\)']
|
|
||||||
],
|
|
||||||
/* start/end delimiter pairs for display math */
|
|
||||||
displayMath: [
|
|
||||||
['$$', '$$'],
|
|
||||||
['\\[', '\\]']
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script src="{{ site.data.origin[type].polyfill.js | relative_url }}"></script>
|
|
||||||
<script id="MathJax-script" async src="{{ site.data.origin[type].mathjax.js | relative_url }}"></script>
|
<script id="MathJax-script" async src="{{ site.data.origin[type].mathjax.js | relative_url }}"></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Pageviews -->
|
||||||
|
{% if page.layout == 'post' %}
|
||||||
|
{% assign provider = site.pageviews.provider %}
|
||||||
|
|
||||||
|
{% 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 %}
|
||||||
|
|
||||||
|
{% if page.mermaid %}
|
||||||
|
{% include mermaid.html %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if jekyll.environment == 'production' %}
|
{% if jekyll.environment == 'production' %}
|
||||||
<!-- PWA -->
|
<!-- PWA -->
|
||||||
{% if site.pwa.enabled %}
|
{% if site.pwa.enabled %}
|
||||||
<script defer src="{{ '/app.js' | relative_url }}"></script>
|
<script defer src="{{ 'app.min.js' | prepend: js_dist | relative_url }}"></script>
|
||||||
{% else %}
|
|
||||||
<script defer src="{{ '/unregister.js' | relative_url }}"></script>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- GA -->
|
<!-- Web Analytics -->
|
||||||
{% if site.google_analytics.id != empty and site.google_analytics.id %}
|
{% for analytics in site.analytics %}
|
||||||
{% include google-analytics.html %}
|
{% capture str %}{{ analytics }}{% endcapture %}
|
||||||
|
{% assign type = str | split: '{' | first %}
|
||||||
|
{% if site.analytics[type].id and site.analytics[type].id != empty %}
|
||||||
|
{% include analytics/{{ type }}.html %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
{% comment %}
|
{% comment %}
|
||||||
Detect appearance language and return it through variable "lang"
|
Detect appearance language and return it through variable "lang"
|
||||||
{% endcomment %}
|
{% 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 %}
|
{% assign lang = site.lang %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% assign lang = 'en' %}
|
{% 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,6 +1,5 @@
|
|||||||
<!-- mermaid-js loader -->
|
<!-- mermaid-js loader -->
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
(function () {
|
|
||||||
function updateMermaid(event) {
|
function updateMermaid(event) {
|
||||||
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
||||||
const mode = event.data.message;
|
const mode = event.data.message;
|
||||||
@@ -12,11 +11,15 @@
|
|||||||
let expectedTheme = mode === ModeToggle.DARK_MODE ? 'dark' : 'default';
|
let expectedTheme = mode === ModeToggle.DARK_MODE ? 'dark' : 'default';
|
||||||
let config = { theme: expectedTheme };
|
let config = { theme: expectedTheme };
|
||||||
|
|
||||||
/* Re-render the SVG › <https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344> */
|
{%- comment -%}
|
||||||
$('.mermaid').each(function () {
|
Re-render the SVG › <https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344>
|
||||||
let svgCode = $(this).prev().children().html();
|
{%- endcomment -%}
|
||||||
$(this).removeAttr('data-processed');
|
const mermaidList = document.getElementsByClassName('mermaid');
|
||||||
$(this).html(svgCode);
|
|
||||||
|
[...mermaidList].forEach((elem) => {
|
||||||
|
const svgCode = elem.previousSibling.children.item(0).innerHTML;
|
||||||
|
elem.innerHTML = svgCode;
|
||||||
|
elem.removeAttribute('data-processed');
|
||||||
});
|
});
|
||||||
|
|
||||||
mermaid.initialize(config);
|
mermaid.initialize(config);
|
||||||
@@ -24,6 +27,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(function () {
|
||||||
let initTheme = 'default';
|
let initTheme = 'default';
|
||||||
const html = document.documentElement;
|
const html = document.documentElement;
|
||||||
|
|
||||||
@@ -35,15 +39,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mermaidConf = {
|
let mermaidConf = {
|
||||||
theme: initTheme /* <default|dark|forest|neutral> */
|
theme: initTheme {%- comment -%} <default | dark | forest | neutral> {%- endcomment -%}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Create mermaid tag */
|
{%- comment -%} Create mermaid tag {%- endcomment -%}
|
||||||
document.querySelectorAll('pre>code.language-mermaid').forEach((elem) => {
|
const basicList = document.getElementsByClassName('language-mermaid');
|
||||||
|
[...basicList].forEach((elem) => {
|
||||||
const svgCode = elem.textContent;
|
const svgCode = elem.textContent;
|
||||||
const backup = elem.parentElement;
|
const backup = elem.parentElement;
|
||||||
backup.classList.add('unloaded');
|
backup.classList.add('d-none');
|
||||||
/* create mermaid node */
|
{%- comment -%} create mermaid node {%- endcomment -%}
|
||||||
let mermaid = document.createElement('pre');
|
let mermaid = document.createElement('pre');
|
||||||
mermaid.classList.add('mermaid');
|
mermaid.classList.add('mermaid');
|
||||||
const text = document.createTextNode(svgCode);
|
const text = document.createTextNode(svgCode);
|
||||||
@@ -52,7 +57,6 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
mermaid.initialize(mermaidConf);
|
mermaid.initialize(mermaidConf);
|
||||||
|
|
||||||
window.addEventListener('message', updateMermaid);
|
window.addEventListener('message', updateMermaid);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -19,45 +19,32 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
if (this.hasMode) {
|
let self = this;
|
||||||
if (this.isDarkMode) {
|
|
||||||
if (!this.isSysDarkPrefer) {
|
{%- comment -%} always follow the system prefers {%- endcomment -%}
|
||||||
this.setDark();
|
this.sysDarkPrefers.addEventListener('change', () => {
|
||||||
|
if (self.hasMode) {
|
||||||
|
self.clearMode();
|
||||||
}
|
}
|
||||||
|
self.notify();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!this.hasMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isDarkMode) {
|
||||||
|
this.setDark();
|
||||||
} else {
|
} else {
|
||||||
if (this.isSysDarkPrefer) {
|
|
||||||
this.setLight();
|
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() {
|
get sysDarkPrefers() {
|
||||||
return window.matchMedia('(prefers-color-scheme: dark)');
|
return window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
}
|
}
|
||||||
|
|
||||||
get isSysDarkPrefer() {
|
get isPreferDark() {
|
||||||
return this.sysDarkPrefers.matches;
|
return this.sysDarkPrefers.matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,10 +52,6 @@
|
|||||||
return this.mode === ModeToggle.DARK_MODE;
|
return this.mode === ModeToggle.DARK_MODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isLightMode() {
|
|
||||||
return this.mode === ModeToggle.LIGHT_MODE;
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasMode() {
|
get hasMode() {
|
||||||
return this.mode != null;
|
return this.mode != null;
|
||||||
}
|
}
|
||||||
@@ -77,12 +60,12 @@
|
|||||||
return sessionStorage.getItem(ModeToggle.MODE_KEY);
|
return sessionStorage.getItem(ModeToggle.MODE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the current mode on screen */
|
{%- comment -%} get the current mode on screen {%- endcomment -%}
|
||||||
get modeStatus() {
|
get modeStatus() {
|
||||||
if (this.isDarkMode || (!this.hasMode && this.isSysDarkPrefer)) {
|
if (this.hasMode) {
|
||||||
return ModeToggle.DARK_MODE;
|
return this.mode;
|
||||||
} else {
|
} else {
|
||||||
return ModeToggle.LIGHT_MODE;
|
return this.isPreferDark ? ModeToggle.DARK_MODE : ModeToggle.LIGHT_MODE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +84,9 @@
|
|||||||
sessionStorage.removeItem(ModeToggle.MODE_KEY);
|
sessionStorage.removeItem(ModeToggle.MODE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify another plugins that the theme mode has changed */
|
{%- comment -%}
|
||||||
|
Notify another plugins that the theme mode has changed
|
||||||
|
{%- endcomment -%}
|
||||||
notify() {
|
notify() {
|
||||||
window.postMessage(
|
window.postMessage(
|
||||||
{
|
{
|
||||||
@@ -114,21 +99,9 @@
|
|||||||
|
|
||||||
flipMode() {
|
flipMode() {
|
||||||
if (this.hasMode) {
|
if (this.hasMode) {
|
||||||
if (this.isSysDarkPrefer) {
|
|
||||||
if (this.isLightMode) {
|
|
||||||
this.clearMode();
|
this.clearMode();
|
||||||
} else {
|
} else {
|
||||||
this.setLight();
|
if (this.isPreferDark) {
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.isDarkMode) {
|
|
||||||
this.clearMode();
|
|
||||||
} else {
|
|
||||||
this.setDark();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (this.isSysDarkPrefer) {
|
|
||||||
this.setLight();
|
this.setLight();
|
||||||
} else {
|
} else {
|
||||||
this.setDark();
|
this.setDark();
|
||||||
@@ -136,8 +109,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.notify();
|
this.notify();
|
||||||
} /* flipMode() */
|
}
|
||||||
} /* ModeToggle */
|
}
|
||||||
|
|
||||||
const modeToggle = new ModeToggle();
|
const modeToggle = new ModeToggle();
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
24
_includes/notification.html
Normal file
24
_includes/notification.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<aside
|
||||||
|
id="notification"
|
||||||
|
class="toast"
|
||||||
|
role="alert"
|
||||||
|
aria-live="assertive"
|
||||||
|
aria-atomic="true"
|
||||||
|
data-bs-animation="true"
|
||||||
|
data-bs-autohide="false"
|
||||||
|
>
|
||||||
|
<div class="toast-header">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn-close ms-auto"
|
||||||
|
data-bs-dismiss="toast"
|
||||||
|
aria-label="Close"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div class="toast-body text-center pt-0">
|
||||||
|
<p class="px-2 mb-3">{{ site.data.locales[include.lang].notification.update_found }}</p>
|
||||||
|
<button type="button" class="btn btn-primary" aria-label="Update">
|
||||||
|
{{ site.data.locales[include.lang].notification.update }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
18
_includes/pageviews/goatcounter.html
Normal file
18
_includes/pageviews/goatcounter.html
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<!-- 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) => {
|
||||||
|
pv.innerText = new Intl.NumberFormat().format(data.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 -}}
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
<!-- Navigation buttons at the bottom of the post. -->
|
<!-- Navigation buttons at the bottom of the post. -->
|
||||||
|
|
||||||
<div class="post-navigation d-flex justify-content-between">
|
<nav class="post-navigation d-flex justify-content-between" aria-label="Post Navigation">
|
||||||
|
{% assign previous = site.data.locales[include.lang].post.button.previous %}
|
||||||
|
{% assign next = site.data.locales[include.lang].post.button.next %}
|
||||||
|
|
||||||
{% if page.previous.url %}
|
{% if page.previous.url %}
|
||||||
<a
|
<a
|
||||||
href="{{ site.baseurl }}{{ page.previous.url }}"
|
href="{{ site.baseurl }}{{ page.previous.url }}"
|
||||||
class="btn btn-outline-primary"
|
class="btn btn-outline-primary"
|
||||||
prompt="{{ site.data.locales[include.lang].post.button.previous }}"
|
aria-label="{{ previous }}"
|
||||||
>
|
>
|
||||||
<p>{{ page.previous.title }}</p>
|
<p>{{ page.previous.title }}</p>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div
|
<div class="btn btn-outline-primary disabled" aria-label="{{ previous }}">
|
||||||
class="btn btn-outline-primary disabled"
|
|
||||||
prompt="{{ site.data.locales[include.lang].post.button.previous }}"
|
|
||||||
>
|
|
||||||
<p>-</p>
|
<p>-</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -22,16 +22,13 @@
|
|||||||
<a
|
<a
|
||||||
href="{{ site.baseurl }}{{page.next.url}}"
|
href="{{ site.baseurl }}{{page.next.url}}"
|
||||||
class="btn btn-outline-primary"
|
class="btn btn-outline-primary"
|
||||||
prompt="{{ site.data.locales[include.lang].post.button.next }}"
|
aria-label="{{ next }}"
|
||||||
>
|
>
|
||||||
<p>{{ page.next.title }}</p>
|
<p>{{ page.next.title }}</p>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div
|
<div class="btn btn-outline-primary disabled" aria-label="{{ next }}">
|
||||||
class="btn btn-outline-primary disabled"
|
|
||||||
prompt="{{ site.data.locales[include.lang].post.button.next }}"
|
|
||||||
>
|
|
||||||
<p>-</p>
|
<p>-</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</nav>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<!-- The paginator for post list on HomgPage. -->
|
<!-- The paginator for post list on HomgPage. -->
|
||||||
|
|
||||||
<ul class="pagination align-items-center mt-4 mb-1 ps-lg-2">
|
<nav aria-label="Page Navigation">
|
||||||
|
<ul class="pagination align-items-center mt-4 mb-0">
|
||||||
<!-- left arrow -->
|
<!-- left arrow -->
|
||||||
{% if paginator.previous_page %}
|
{% if paginator.previous_page %}
|
||||||
{% assign prev_url = paginator.previous_page_path | relative_url %}
|
{% assign prev_url = paginator.previous_page_path | relative_url %}
|
||||||
@@ -9,7 +10,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<li class="page-item {% unless paginator.previous_page %}disabled{% endunless %}">
|
<li class="page-item {% unless paginator.previous_page %}disabled{% endunless %}">
|
||||||
<a class="page-link btn-box-shadow" href="{{ prev_url }}" aria-label="previous-page">
|
<a class="page-link" href="{{ prev_url }}" aria-label="previous-page">
|
||||||
<i class="fas fa-angle-left"></i>
|
<i class="fas fa-angle-left"></i>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
<!-- show number -->
|
<!-- show number -->
|
||||||
<li class="page-item {% if i == paginator.page %} active{% endif %}">
|
<li class="page-item {% if i == paginator.page %} active{% endif %}">
|
||||||
<a
|
<a
|
||||||
class="page-link btn-box-shadow"
|
class="page-link"
|
||||||
href="{% if i > 1 %}{{ site.paginate_path | replace: ':num', i | relative_url }}{% else %}{{ '/' | relative_url }}{% endif %}"
|
href="{% if i > 1 %}{{ site.paginate_path | replace: ':num', i | relative_url }}{% else %}{{ '/' | relative_url }}{% endif %}"
|
||||||
>
|
>
|
||||||
{{- i -}}
|
{{- i -}}
|
||||||
@@ -55,12 +56,12 @@
|
|||||||
<!-- hide number -->
|
<!-- hide number -->
|
||||||
{% if i < pre and left_ellipsis == false %}
|
{% if i < pre and left_ellipsis == false %}
|
||||||
<li class="page-item disabled">
|
<li class="page-item disabled">
|
||||||
<span class="page-link btn-box-shadow">...</span>
|
<span class="page-link">...</span>
|
||||||
</li>
|
</li>
|
||||||
{% assign left_ellipsis = true %}
|
{% assign left_ellipsis = true %}
|
||||||
{% elsif i > next and right_ellipsis == false %}
|
{% elsif i > next and right_ellipsis == false %}
|
||||||
<li class="page-item disabled">
|
<li class="page-item disabled">
|
||||||
<span class="page-link btn-box-shadow">...</span>
|
<span class="page-link">...</span>
|
||||||
</li>
|
</li>
|
||||||
{% assign right_ellipsis = true %}
|
{% assign right_ellipsis = true %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -81,9 +82,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<li class="page-item {% unless paginator.next_page_path %}disabled{% endunless %}">
|
<li class="page-item {% unless paginator.next_page_path %}disabled{% endunless %}">
|
||||||
<a class="page-link btn-box-shadow" href="{{ next_url }}" aria-label="next-page">
|
<a class="page-link" href="{{ next_url }}" aria-label="next-page">
|
||||||
<i class="fas fa-angle-right"></i>
|
<i class="fas fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</nav>
|
||||||
<!-- .pagination -->
|
<!-- .pagination -->
|
||||||
|
|||||||
@@ -1,35 +1,52 @@
|
|||||||
<!-- Post sharing snippet -->
|
<!-- Post sharing snippet -->
|
||||||
|
|
||||||
<div class="share-wrapper">
|
<div class="share-wrapper d-flex align-items-center">
|
||||||
<span class="share-label text-muted me-1">{{ site.data.locales[include.lang].post.share }}</span>
|
<span class="share-label text-muted">{{ site.data.locales[include.lang].post.share }}</span>
|
||||||
<span class="share-icons">
|
<span class="share-icons">
|
||||||
{% capture title %}{{ page.title }} - {{ site.title }}{% endcapture %}
|
{% capture title %}{{ page.title }} - {{ site.title }}{% endcapture %}
|
||||||
{% assign title = title | uri_escape %}
|
{% assign title = title | uri_escape %}
|
||||||
{% assign url = page.url | absolute_url | url_encode %}
|
{% assign url = page.url | absolute_url | url_encode %}
|
||||||
|
|
||||||
{% for share in site.data.share.platforms %}
|
{% for share in site.data.share.platforms -%}
|
||||||
{% assign link = share.link | replace: 'TITLE', title | replace: 'URL', url %}
|
{%- capture tooltip -%}
|
||||||
<a
|
data-bs-toggle="tooltip" data-bs-placement="top" title="{{ share.type }}" aria-label="{{ share.type }}"
|
||||||
href="{{ link }}"
|
{%- endcapture -%}
|
||||||
data-bs-toggle="tooltip"
|
|
||||||
data-bs-placement="top"
|
{% if share.type == 'Mastodon' %}
|
||||||
title="{{ share.type }}"
|
<script defer type="module" src="https://cdn.jsdelivr.net/npm/@justinribeiro/share-to-mastodon/+esm"></script>
|
||||||
target="_blank"
|
<button class="btn text-start" {{ tooltip }}>
|
||||||
rel="noopener"
|
<share-to-mastodon
|
||||||
aria-label="{{ share.type }}"
|
class="share-mastodon"
|
||||||
|
message="{{ title }}"
|
||||||
|
url="{{ url }}"
|
||||||
|
{%- if share.instances -%}
|
||||||
|
customInstanceList="{{ share.instances | jsonify | xml_escape }}"
|
||||||
|
{%- endif %}
|
||||||
>
|
>
|
||||||
<i class="fa-fw {{ share.icon }}"></i>
|
<i class="fa-fw {{ share.icon }}"></i>
|
||||||
|
</share-to-mastodon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{% continue %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% assign link = share.link | replace: 'TITLE', title | replace: 'URL', url %}
|
||||||
|
|
||||||
|
<a href="{{ link }}" target="_blank" rel="noopener" {{ tooltip }}>
|
||||||
|
<i class="fa-fw {{ share.icon }}"></i>
|
||||||
</a>
|
</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<i
|
<button
|
||||||
id="copy-link"
|
id="copy-link"
|
||||||
class="fa-fw fas fa-link small"
|
aria-label="Copy link"
|
||||||
|
class="btn small"
|
||||||
data-bs-toggle="tooltip"
|
data-bs-toggle="tooltip"
|
||||||
data-bs-placement="top"
|
data-bs-placement="top"
|
||||||
title="{{ site.data.locales[include.lang].post.button.share_link.title }}"
|
title="{{ site.data.locales[include.lang].post.button.share_link.title }}"
|
||||||
data-title-succeed="{{ site.data.locales[include.lang].post.button.share_link.succeed }}"
|
data-title-succeed="{{ site.data.locales[include.lang].post.button.share_link.succeed }}"
|
||||||
>
|
>
|
||||||
</i>
|
<i class="fa-fw fas fa-link pe-none fs-6"></i>
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -30,41 +30,24 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Change the icon of checkbox -->
|
<!-- Change the icon of checkbox -->
|
||||||
|
|
||||||
{% if _content contains '<input type="checkbox"' %}
|
{% if _content contains '<input type="checkbox"' %}
|
||||||
{% assign _content = _content
|
{% assign _content = _content
|
||||||
| replace:
|
| replace: '<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />',
|
||||||
'<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />',
|
|
||||||
'<i class="fas fa-check-circle fa-fw checked"></i>'
|
'<i class="fas fa-check-circle fa-fw checked"></i>'
|
||||||
| replace:
|
| replace: '<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />',
|
||||||
'<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />',
|
|
||||||
'<i class="far fa-circle fa-fw"></i>'
|
'<i class="far fa-circle fa-fw"></i>'
|
||||||
%}
|
%}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- images -->
|
<!-- Handle images -->
|
||||||
|
|
||||||
{% assign IMG_TAG = '<img ' %}
|
{% assign IMG_TAG = '<img ' %}
|
||||||
|
|
||||||
{% if _content contains IMG_TAG %}
|
{% if _content contains IMG_TAG %}
|
||||||
{% assign _img_content = nil %}
|
{% assign _img_content = null %}
|
||||||
{% assign _img_snippets = _content | split: IMG_TAG %}
|
{% 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 %}
|
{% for _img_snippet in _img_snippets %}
|
||||||
{% if forloop.first %}
|
{% if forloop.first %}
|
||||||
{% assign _img_content = _img_snippet %}
|
{% assign _img_content = _img_snippet %}
|
||||||
@@ -81,10 +64,9 @@
|
|||||||
{% assign _left = _left | remove: ' /' | replace: ' w=', ' width=' | replace: ' h=', ' height=' %}
|
{% assign _left = _left | remove: ' /' | replace: ' w=', ' width=' | replace: ' h=', ' height=' %}
|
||||||
{% assign _attrs = _left | split: '" ' %}
|
{% assign _attrs = _left | split: '" ' %}
|
||||||
|
|
||||||
{% assign _width = nil %}
|
{% assign _src = null %}
|
||||||
{% assign _height = nil %}
|
{% assign _lqip = null %}
|
||||||
{% assign _lqip = nil %}
|
{% assign _class = null %}
|
||||||
{% assign _class = nil %}
|
|
||||||
|
|
||||||
{% for _attr in _attrs %}
|
{% for _attr in _attrs %}
|
||||||
{% unless _attr contains '=' %}
|
{% unless _attr contains '=' %}
|
||||||
@@ -96,10 +78,6 @@
|
|||||||
{% capture _value %}{{ _pair | last | remove: '"' }}{% endcapture %}
|
{% capture _value %}{{ _pair | last | remove: '"' }}{% endcapture %}
|
||||||
|
|
||||||
{% case _key %}
|
{% case _key %}
|
||||||
{% when 'width' %}
|
|
||||||
{% assign _width = _value %}
|
|
||||||
{% when 'height' %}
|
|
||||||
{% assign _height = _value %}
|
|
||||||
{% when 'src' %}
|
{% when 'src' %}
|
||||||
{% assign _src = _value %}
|
{% assign _src = _value %}
|
||||||
{% when 'lqip' %}
|
{% when 'lqip' %}
|
||||||
@@ -115,54 +93,46 @@
|
|||||||
{% assign _left = _left | remove: _old_class %}
|
{% assign _left = _left | remove: _old_class %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% assign _final_src = nil %}
|
{% 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 '//' %}
|
{% unless _src contains '//' %}
|
||||||
{% assign _final_src = _path_prefix | append: _src %}
|
{% assign _final_src = _path_prefix | append: _src %}
|
||||||
{% capture _src_from %}"{{ _src }}"{% endcapture %}
|
{% assign _src_alt = 'src="' | append: _path_prefix %}
|
||||||
{% capture _src_to %}"{{ _final_src }}"{% endcapture %}
|
{% assign _left = _left | replace: 'src="', _src_alt %}
|
||||||
{% assign _left = _left | replace: _src_from, _src_to %}
|
|
||||||
{% endunless %}
|
{% endunless %}
|
||||||
|
|
||||||
{% if _lqip %}
|
{% if _lqip %}
|
||||||
{% unless _lqip contains ':' %}
|
{% assign _lazyload = false %}
|
||||||
{% assign _final_lqip = _path_prefix | append: _lqip %}
|
{% assign _class = _class | append: ' blur' %}
|
||||||
{% capture _lqip_from %}"{{ _lqip }}"{% endcapture %}
|
|
||||||
{% capture _lqip_to %}"{{ _final_lqip }}"{% endcapture %}
|
|
||||||
{% assign _left = _left | replace: _lqip_from, _lqip_to %}
|
|
||||||
{% endunless %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
|
{% unless _lqip contains 'data:' %}
|
||||||
{% assign _left = _left | replace: 'src=', 'data-src=' %}
|
{% assign _lqip_alt = 'lqip="' | append: _path_prefix %}
|
||||||
{% if _left contains 'class=' %}
|
{% assign _left = _left | replace: 'lqip="', _lqip_alt %}
|
||||||
{% assign _left = _left | replace: 'class="', 'class="lazyload '%}
|
{% endunless %}
|
||||||
{% else %}
|
|
||||||
{% assign _left = _left | append: ' class="lazyload"' %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- add image placeholder -->
|
<!-- add image placeholder -->
|
||||||
{% if _lqip %}
|
{% assign _left = _left | replace: 'src=', 'data-src=' | replace: ' lqip=', ' data-lqip="true" src=' %}
|
||||||
{% assign _left = _left | replace: ' lqip=', ' data-lqip="true" src=' %}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{% if _width and _height %}
|
|
||||||
<!-- add SVG placehoder -->
|
|
||||||
{%- capture _svg -%}
|
|
||||||
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 {{ _width }} {{ _height }}'%3E%3C/svg%3E"
|
|
||||||
{%- endcapture -%}
|
|
||||||
{% assign _left = _svg | append: ' ' | append: _left %}
|
|
||||||
{% assign _class = _class | append: ' shimmer' %}
|
{% assign _class = _class | append: ' shimmer' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<!-- Bypass the HTML-proofer test -->
|
<!-- lazy-load images -->
|
||||||
{% assign _left = _left | append: ' data-proofer-ignore' %}
|
{% if _lazyload %}
|
||||||
|
{% assign _left = _left | append: ' loading="lazy"' %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if page.layout == 'home' %}
|
{% if page.layout == 'home' %}
|
||||||
<!-- create the image wrapper -->
|
<!-- create the image wrapper -->
|
||||||
{%- capture _wrapper_start -%}
|
{% assign _wrapper_start = '<div class="preview-img ' | append: _class | append: '">' %}
|
||||||
<div class="preview-img {{ _class | strip }}">
|
|
||||||
{%- endcapture -%}
|
|
||||||
{% assign _img_content = _img_content | append: _wrapper_start %}
|
{% assign _img_content = _img_content | append: _wrapper_start %}
|
||||||
{% assign _right = _right | prepend: '></div' %}
|
{% assign _right = _right | prepend: '></div' %}
|
||||||
|
|
||||||
@@ -177,25 +147,29 @@
|
|||||||
class="img-link{% unless _lqip %} shimmer{% endunless %}"
|
class="img-link{% unless _lqip %} shimmer{% endunless %}"
|
||||||
{% endcapture %}
|
{% endcapture %}
|
||||||
{% assign _img_content = _img_content | slice: 0, _size | append: _class | append: '>' %}
|
{% assign _img_content = _img_content | slice: 0, _size | append: _class | append: '>' %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<!-- create the image wrapper -->
|
<!-- create the image wrapper -->
|
||||||
{%- capture _wrapper_start -%}
|
{% assign _wrapper_start = _final_src
|
||||||
<a href="{{ _final_src | default: _src }}" class="popup img-link {{ _class }}">
|
| default: _src
|
||||||
{%- endcapture -%}
|
| prepend: '<a href="'
|
||||||
|
| append: '" class="popup img-link '
|
||||||
|
| append: _class
|
||||||
|
| append: '">'
|
||||||
|
%}
|
||||||
|
|
||||||
{% assign _img_content = _img_content | append: _wrapper_start %}
|
{% assign _img_content = _img_content | append: _wrapper_start %}
|
||||||
{% assign _right = _right | prepend: '></a' %}
|
{% assign _right = '></a' | append: _right %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- combine -->
|
<!-- combine -->
|
||||||
{% assign _img_content = _img_content | append: debug | append: IMG_TAG | append: _left | append: _right %}
|
{% assign _img_content = _img_content | append: IMG_TAG | append: _left | append: _right %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if _img_content %}
|
{% if _img_content %}
|
||||||
{% assign _content = _img_content %}
|
{% assign _content = _img_content %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Add header for code snippets -->
|
<!-- Add header for code snippets -->
|
||||||
@@ -205,13 +179,11 @@
|
|||||||
{% assign _new_content = '' %}
|
{% assign _new_content = '' %}
|
||||||
|
|
||||||
{% for _snippet in _code_spippets %}
|
{% for _snippet in _code_spippets %}
|
||||||
|
|
||||||
{% if forloop.last %}
|
{% if forloop.last %}
|
||||||
{% assign _new_content = _new_content | append: _snippet %}
|
{% assign _new_content = _new_content | append: _snippet %}
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
{% assign _left = _snippet | split: '><' | last %}
|
||||||
{% assign _left = _snippet | split: '><' | last%}
|
|
||||||
|
|
||||||
{% if _left contains 'file="' %}
|
{% if _left contains 'file="' %}
|
||||||
{% assign _label_text = _left | split: 'file="' | last | split: '"' | first %}
|
{% assign _label_text = _left | split: 'file="' | last | split: '"' | first %}
|
||||||
@@ -226,7 +198,8 @@
|
|||||||
<span data-label-text="{{ _label_text | strip }}"><i class="{{ _label_icon }}"></i></span>
|
<span data-label-text="{{ _label_text | strip }}"><i class="{{ _label_icon }}"></i></span>
|
||||||
{% endcapture %}
|
{% endcapture %}
|
||||||
|
|
||||||
{% assign _new_content = _new_content | append: _snippet
|
{% assign _new_content = _new_content
|
||||||
|
| append: _snippet
|
||||||
| append: '<div class="code-header">'
|
| append: '<div class="code-header">'
|
||||||
| append: _label
|
| append: _label
|
||||||
| append: '<button aria-label="copy" data-title-succeed="'
|
| append: '<button aria-label="copy" data-title-succeed="'
|
||||||
@@ -234,13 +207,10 @@
|
|||||||
| append: '"><i class="far fa-clipboard"></i></button></div>'
|
| append: '"><i class="far fa-clipboard"></i></button></div>'
|
||||||
| append: '<div class="highlight"><code>'
|
| append: '<div class="highlight"><code>'
|
||||||
%}
|
%}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% assign _content = _new_content %}
|
{% assign _content = _new_content %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Create heading anchors -->
|
<!-- Create heading anchors -->
|
||||||
@@ -249,11 +219,11 @@
|
|||||||
{% assign _heading_content = _content %}
|
{% assign _heading_content = _content %}
|
||||||
|
|
||||||
{% for level in heading_levels %}
|
{% for level in heading_levels %}
|
||||||
{% capture mark_start %}<h{{ level }} id="{% endcapture %}
|
{% assign mark_start = '<h' | append: level | append: ' id="' %}
|
||||||
{% capture mark_end %}</h{{ level }}>{% endcapture %}
|
{% assign mark_end = '</h' | append: level | append: '>' %}
|
||||||
|
|
||||||
{% if _heading_content contains mark_start %}
|
{% if _heading_content contains mark_start %}
|
||||||
{% assign _new_content = nil %}
|
{% assign _new_content = null %}
|
||||||
{% assign heading_snippets = _heading_content | split: mark_start %}
|
{% assign heading_snippets = _heading_content | split: mark_start %}
|
||||||
|
|
||||||
{% for snippet in heading_snippets %}
|
{% for snippet in heading_snippets %}
|
||||||
@@ -263,20 +233,19 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% assign id = snippet | split: '"' | first %}
|
{% assign id = snippet | split: '"' | first %}
|
||||||
{% capture anchor %}<a href="#{{ id }}" class="anchor text-muted"><i class="fas fa-hashtag"></i></a>{% endcapture %}
|
{% assign anchor = '<a href="#'
|
||||||
|
| append: id
|
||||||
|
| append: '" class="anchor text-muted"><i class="fas fa-hashtag"></i></a>'
|
||||||
|
%}
|
||||||
|
|
||||||
{% assign left = snippet | split: mark_end | first %}
|
{% assign left = snippet | split: mark_end | first %}
|
||||||
{% assign right = snippet | slice: left.size, snippet.size %}
|
{% assign right = snippet | slice: left.size, snippet.size %}
|
||||||
{% assign left = left | replace_first: '">', '"><span class="me-2">' | append: '</span>' %}
|
{% assign left = left | replace_first: '">', '"><span class="me-2">' | append: '</span>' %}
|
||||||
|
|
||||||
{% assign _new_content = _new_content | append: mark_start
|
{% assign _new_content = _new_content | append: mark_start | append: left | append: anchor | append: right %}
|
||||||
| append: left | append: anchor | append: right
|
|
||||||
%}
|
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% assign _heading_content = _new_content %}
|
{% assign _heading_content = _new_content %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
<!--
|
<!-- Recommend the other 3 posts according to the tags and categories of the current post. -->
|
||||||
Recommend the other 3 posts according to the tags and categories of the current post,
|
|
||||||
if the number is not enough, use the other latest posts to supplement.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- The total size of related posts -->
|
<!-- The total size of related posts -->
|
||||||
{% assign TOTAL_SIZE = 3 %}
|
{% assign TOTAL_SIZE = 3 %}
|
||||||
@@ -14,11 +11,22 @@
|
|||||||
|
|
||||||
{% assign SEPARATOR = ':' %}
|
{% assign SEPARATOR = ':' %}
|
||||||
|
|
||||||
|
{% assign match_posts = '' | split: '' %}
|
||||||
|
|
||||||
|
{% for category in page.categories %}
|
||||||
|
{% assign match_posts = match_posts | push: site.categories[category] | uniq %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for tag in page.tags %}
|
||||||
|
{% 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: '' %}
|
{% assign score_list = '' | split: '' %}
|
||||||
{% assign last_index = site.posts.size | minus: 1 %}
|
|
||||||
|
|
||||||
{% for i in (0..last_index) %}
|
{% for i in (0..last_index) %}
|
||||||
{% assign post = site.posts[i] %}
|
{% assign post = match_posts[i] %}
|
||||||
|
|
||||||
{% if post.url == page.url %}
|
{% if post.url == page.url %}
|
||||||
{% continue %}
|
{% continue %}
|
||||||
@@ -54,51 +62,33 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- Fill with the other newlest posts -->
|
{% assign relate_posts = '' | split: '' %}
|
||||||
{% assign less = TOTAL_SIZE | minus: index_list.size %}
|
|
||||||
|
|
||||||
{% if less > 0 %}
|
{% for index in index_list %}
|
||||||
{% for i in (0..last_index) %}
|
{% assign i = index | to_integer %}
|
||||||
{% assign post = site.posts[i] %}
|
{% assign relate_posts = relate_posts | push: match_posts[i] %}
|
||||||
{% if post.url != page.url %}
|
{% endfor %}
|
||||||
{% capture cur_index %}{{ i }}{% endcapture %}
|
|
||||||
{% unless index_list contains cur_index %}
|
|
||||||
{% assign index_list = index_list | push: cur_index %}
|
|
||||||
{% assign less = less | minus: 1 %}
|
|
||||||
{% if less <= 0 %}
|
|
||||||
{% break %}
|
|
||||||
{% endif %}
|
|
||||||
{% endunless %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if index_list.size > 0 %}
|
{% if relate_posts.size > 0 %}
|
||||||
<div id="related-posts" class="mb-2 mb-sm-4">
|
<aside id="related-posts" aria-labelledby="related-label">
|
||||||
<h3 class="pt-2 mb-4 ms-1" data-toc-skip>
|
<h3 class="mb-4" id="related-label">
|
||||||
{{ site.data.locales[include.lang].post.relate_posts }}
|
{{- site.data.locales[include.lang].post.relate_posts -}}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="row row-cols-1 row-cols-md-2 row-cols-xl-3 g-4 mb-4">
|
<nav class="row row-cols-1 row-cols-md-2 row-cols-xl-3 g-4 mb-4">
|
||||||
{% for entry in index_list %}
|
{% for post in relate_posts %}
|
||||||
{% assign index = entry | plus: 0 %}
|
<article class="col">
|
||||||
{% assign post = site.posts[index] %}
|
<a href="{{ post.url | relative_url }}" class="post-preview card h-100">
|
||||||
<div class="col">
|
|
||||||
<a href="{{ post.url | relative_url }}" class="card post-preview h-100">
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
{% include datetime.html date=post.date class="small" lang=include.lang %}
|
{% include datetime.html date=post.date lang=include.lang %}
|
||||||
<h4 class="pt-0 my-2" data-toc-skip>{{ post.title }}</h4>
|
<h4 class="pt-0 my-2">{{ post.title }}</h4>
|
||||||
<div class="text-muted small">
|
<div class="text-muted">
|
||||||
<p>
|
<p>{% include post-description.html %}</p>
|
||||||
{% include no-linenos.html content=post.content %}
|
|
||||||
{{ content | markdownify | strip_html | truncate: 200 | escape }}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</article>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</nav>
|
||||||
<!-- .card-deck -->
|
</aside>
|
||||||
</div>
|
|
||||||
<!-- #related-posts -->
|
<!-- #related-posts -->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -4,20 +4,22 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
{% capture result_elem %}
|
{% capture result_elem %}
|
||||||
<div class="px-1 px-sm-2 px-lg-4 px-xl-0">
|
<article class="px-1 px-sm-2 px-lg-4 px-xl-0">
|
||||||
<a href="{url}">{title}</a>
|
<header>
|
||||||
|
<h2><a href="{url}">{title}</a></h2>
|
||||||
<div class="post-meta d-flex flex-column flex-sm-row text-muted mt-1 mb-1">
|
<div class="post-meta d-flex flex-column flex-sm-row text-muted mt-1 mb-1">
|
||||||
{categories}
|
{categories}
|
||||||
{tags}
|
{tags}
|
||||||
</div>
|
</div>
|
||||||
|
</header>
|
||||||
<p>{snippet}</p>
|
<p>{snippet}</p>
|
||||||
</div>
|
</article>
|
||||||
{% endcapture %}
|
{% endcapture %}
|
||||||
|
|
||||||
{% capture not_found %}<p class="mt-5">{{ site.data.locales[include.lang].search.no_results }}</p>{% endcapture %}
|
{% capture not_found %}<p class="mt-5">{{ site.data.locales[include.lang].search.no_results }}</p>{% endcapture %}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* Note: dependent library will be loaded in `js-selector.html` */
|
{%- comment -%} Note: dependent library will be loaded in `js-selector.html` {%- endcomment -%}
|
||||||
SimpleJekyllSearch({
|
SimpleJekyllSearch({
|
||||||
searchInput: document.getElementById('search-input'),
|
searchInput: document.getElementById('search-input'),
|
||||||
resultsContainer: document.getElementById('search-results'),
|
resultsContainer: document.getElementById('search-results'),
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!-- The Search results -->
|
<!-- 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 post-content">
|
<div class="col-11 content">
|
||||||
<div id="search-hints">
|
<div id="search-hints">
|
||||||
{% include trending-tags.html %}
|
{% include_cached trending-tags.html %}
|
||||||
</div>
|
</div>
|
||||||
<div id="search-results" class="d-flex flex-wrap justify-content-center text-muted mt-3"></div>
|
<div id="search-results" class="d-flex flex-wrap justify-content-center text-muted mt-3"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,30 +1,25 @@
|
|||||||
<!-- The Side Bar -->
|
<!-- The Side Bar -->
|
||||||
|
|
||||||
<div id="sidebar" class="d-flex flex-column align-items-end">
|
<aside aria-label="Sidebar" id="sidebar" class="d-flex flex-column align-items-end">
|
||||||
<div class="profile-wrapper">
|
<header class="profile-wrapper">
|
||||||
<a href="{{ '/' | relative_url }}" id="avatar" class="rounded-circle">
|
<a href="{{ '/' | relative_url }}" id="avatar" class="rounded-circle">
|
||||||
{% if site.avatar != empty and site.avatar %}
|
{%- if site.avatar != empty and site.avatar -%}
|
||||||
{% capture avatar_url %}
|
{%- capture avatar_url -%}
|
||||||
{% if site.avatar contains '://' %}
|
{% include media-url.html src=site.avatar %}
|
||||||
{{ site.avatar }}
|
{%- endcapture -%}
|
||||||
{% elsif site.img_cdn != empty and site.img_cdn %}
|
<img src="{{- avatar_url -}}" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
|
||||||
{{ site.avatar | prepend: site.img_cdn }}
|
{%- endif -%}
|
||||||
{% else %}
|
|
||||||
{{ site.avatar | relative_url }}
|
|
||||||
{% endif %}
|
|
||||||
{% endcapture %}
|
|
||||||
<img src="{{ avatar_url | strip }}" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
|
|
||||||
{% endif %}
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="site-title">
|
<h1 class="site-title">
|
||||||
<a href="{{ '/' | relative_url }}">{{ site.title }}</a>
|
<a href="{{ '/' | relative_url }}">{{ site.title }}</a>
|
||||||
</div>
|
</h1>
|
||||||
<div class="site-subtitle fst-italic">{{ site.tagline }}</div>
|
<p class="site-subtitle fst-italic mb-0">{{ site.tagline }}</p>
|
||||||
</div>
|
</header>
|
||||||
<!-- .profile-wrapper -->
|
<!-- .profile-wrapper -->
|
||||||
|
|
||||||
<ul class="nav flex-column flex-grow-1 w-100 ps-0">
|
<nav class="flex-column flex-grow-1 w-100 ps-0">
|
||||||
|
<ul class="nav">
|
||||||
<!-- home -->
|
<!-- home -->
|
||||||
<li class="nav-item{% if page.layout == 'home' %}{{ " active" }}{% endif %}">
|
<li class="nav-item{% if page.layout == 'home' %}{{ " active" }}{% endif %}">
|
||||||
<a href="{{ '/' | relative_url }}" class="nav-link">
|
<a href="{{ '/' | relative_url }}" class="nav-link">
|
||||||
@@ -45,11 +40,11 @@
|
|||||||
<!-- .nav-item -->
|
<!-- .nav-item -->
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
<!-- ul.nav.flex-column -->
|
</nav>
|
||||||
|
|
||||||
<div class="sidebar-bottom d-flex flex-wrap align-items-center w-100">
|
<div class="sidebar-bottom d-flex flex-wrap align-items-center w-100">
|
||||||
{% unless site.theme_mode %}
|
{% unless site.theme_mode %}
|
||||||
<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>
|
<i class="fas fa-adjust"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -100,5 +95,5 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<!-- .sidebar-bottom -->
|
<!-- .sidebar-bottom -->
|
||||||
</div>
|
</aside>
|
||||||
<!-- #sidebar -->
|
<!-- #sidebar -->
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if enable_toc %}
|
{% if enable_toc %}
|
||||||
<div id="toc-wrapper" class="ps-0 pe-4 mb-5">
|
<section id="toc-wrapper" class="d-none ps-0 pe-4">
|
||||||
<div class="panel-heading ps-3 pt-2 mb-2">{{- site.data.locales[include.lang].panel.toc -}}</div>
|
<h2 class="panel-heading ps-3 mb-2">{{- site.data.locales[include.lang].panel.toc -}}</h2>
|
||||||
<nav id="toc"></nav>
|
<nav id="toc"></nav>
|
||||||
</div>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<!-- The Top Bar -->
|
<!-- The Top Bar -->
|
||||||
|
|
||||||
<div id="topbar-wrapper">
|
<header id="topbar-wrapper" aria-label="Top Bar">
|
||||||
<div
|
<div
|
||||||
id="topbar"
|
id="topbar"
|
||||||
class="container d-flex align-items-center justify-content-between h-100"
|
class="d-flex align-items-center justify-content-between px-lg-3 h-100"
|
||||||
>
|
>
|
||||||
<span id="breadcrumb">
|
<nav id="breadcrumb" aria-label="Breadcrumb">
|
||||||
{% assign paths = page.url | split: '/' %}
|
{% assign paths = page.url | split: '/' %}
|
||||||
|
|
||||||
{% if paths.size == 0 or page.layout == 'home' %}
|
{% if paths.size == 0 or page.layout == 'home' %}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
{% if forloop.first %}
|
{% if forloop.first %}
|
||||||
<span>
|
<span>
|
||||||
<a href="{{ '/' | relative_url }}">
|
<a href="{{ '/' | relative_url }}">
|
||||||
{{ site.data.locales[include.lang].tabs.home | capitalize }}
|
{{- site.data.locales[include.lang].tabs.home | capitalize -}}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@@ -30,17 +30,19 @@
|
|||||||
|
|
||||||
{% elsif page.layout == 'category' or page.layout == 'tag' %}
|
{% elsif page.layout == 'category' or page.layout == 'tag' %}
|
||||||
<span>
|
<span>
|
||||||
<a href="{{ item | relative_url }}">
|
<a href="{{ item | append: '/' | relative_url }}">
|
||||||
{{ site.data.locales[include.lang].tabs[item] | default: page.title }}
|
{{- site.data.locales[include.lang].tabs[item] | default: page.title -}}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</span>
|
</nav>
|
||||||
<!-- endof #breadcrumb -->
|
<!-- endof #breadcrumb -->
|
||||||
|
|
||||||
<i id="sidebar-trigger" class="fas fa-bars fa-fw"></i>
|
<button type="button" id="sidebar-trigger" class="btn btn-link">
|
||||||
|
<i class="fas fa-bars fa-fw"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
<div id="topbar-title">
|
<div id="topbar-title">
|
||||||
{% if page.layout == 'home' %}
|
{% if page.layout == 'home' %}
|
||||||
@@ -53,8 +55,11 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<i id="search-trigger" class="fas fa-search fa-fw"></i>
|
<button type="button" id="search-trigger" class="btn btn-link">
|
||||||
<span id="search-wrapper" class="align-items-center">
|
<i class="fas fa-search fa-fw"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<search id="search" class="align-items-center ms-3 ms-lg-0">
|
||||||
<i class="fas fa-search fa-fw"></i>
|
<i class="fas fa-search fa-fw"></i>
|
||||||
<input
|
<input
|
||||||
class="form-control"
|
class="form-control"
|
||||||
@@ -64,7 +69,9 @@
|
|||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder="{{ site.data.locales[include.lang].search.hint | capitalize }}..."
|
placeholder="{{ site.data.locales[include.lang].search.hint | capitalize }}..."
|
||||||
>
|
>
|
||||||
</span>
|
</search>
|
||||||
<span id="search-cancel">{{ site.data.locales[include.lang].search.cancel }}</span>
|
<button type="button" class="btn btn-link text-decoration-none" id="search-cancel">
|
||||||
|
{{- site.data.locales[include.lang].search.cancel -}}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</header>
|
||||||
|
|||||||
@@ -34,13 +34,13 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if trending_tags.size > 0 %}
|
{% if trending_tags.size > 0 %}
|
||||||
<div id="access-tags">
|
<section>
|
||||||
<div class="panel-heading">{{- site.data.locales[include.lang].panel.trending_tags -}}</div>
|
<h2 class="panel-heading">{{- site.data.locales[include.lang].panel.trending_tags -}}</h2>
|
||||||
<div class="d-flex flex-wrap mt-3 mb-1 me-3">
|
<div class="d-flex flex-wrap mt-3 mb-1 me-3">
|
||||||
{% for tag_name in trending_tags %}
|
{% for tag_name in trending_tags %}
|
||||||
{% assign url = tag_name | slugify | url_encode | prepend: '/tags/' | append: '/' %}
|
{% assign url = tag_name | slugify | url_encode | prepend: '/tags/' | append: '/' %}
|
||||||
<a class="post-tag btn btn-outline-primary" href="{{ url | relative_url }}">{{ tag_name }}</a>
|
<a class="post-tag btn btn-outline-primary" href="{{ url | relative_url }}">{{ tag_name }}</a>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<!-- Get the last 5 posts from lastmod list. -->
|
<!-- Get 5 last posted/updated posts -->
|
||||||
|
|
||||||
{% assign MAX_SIZE = 5 %}
|
{% assign MAX_SIZE = 5 %}
|
||||||
|
|
||||||
{% assign all_list = '' | split: '' %}
|
{% assign all_list = '' | split: '' %}
|
||||||
|
|
||||||
{% for post in site.posts %}
|
{% for post in site.posts %}
|
||||||
{% if post.last_modified_at and post.last_modified_at != post.date %}
|
{% assign datetime = post.last_modified_at | default: post.date %}
|
||||||
|
|
||||||
{% capture elem %}
|
{% capture elem %}
|
||||||
{{- post.last_modified_at | date: "%Y%m%d%H%M%S" -}}::{{- forloop.index0 -}}
|
{{- datetime | date: "%Y%m%d%H%M%S" -}}::{{- forloop.index0 -}}
|
||||||
{% endcapture %}
|
{% endcapture %}
|
||||||
|
|
||||||
{% assign all_list = all_list | push: elem %}
|
{% assign all_list = all_list | push: elem %}
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% assign all_list = all_list | sort | reverse %}
|
{% assign all_list = all_list | sort | reverse %}
|
||||||
@@ -22,9 +23,9 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% if update_list.size > 0 %}
|
{% if update_list.size > 0 %}
|
||||||
<div id="access-lastmod" class="post">
|
<section id="access-lastmod">
|
||||||
<div class="panel-heading">{{- site.data.locales[include.lang].panel.lastmod -}}</div>
|
<h2 class="panel-heading">{{- site.data.locales[include.lang].panel.lastmod -}}</h2>
|
||||||
<ul class="post-content list-unstyled ps-0 pb-1 ms-1 mt-2">
|
<ul class="content list-unstyled ps-0 pb-1 ms-1 mt-2">
|
||||||
{% for item in update_list %}
|
{% for item in update_list %}
|
||||||
{% assign index = item | split: '::' | last | plus: 0 %}
|
{% assign index = item | split: '::' | last | plus: 0 %}
|
||||||
{% assign post = site.posts[index] %}
|
{% assign post = site.posts[index] %}
|
||||||
@@ -34,6 +35,6 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</section>
|
||||||
<!-- #access-lastmod -->
|
<!-- #access-lastmod -->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
Chirpy v<%= pkg.version %> (<%= pkg.homepage %>)
|
Chirpy v<%= pkg.version %> | © 2019 <%= pkg.author %> | <%= pkg.license %> Licensed | <%= pkg.homepage %>
|
||||||
© 2019 <%= pkg.author %>
|
|
||||||
<%= pkg.license %> Licensed
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||||
|
|
||||||
basic();
|
|
||||||
initSidebar();
|
initSidebar();
|
||||||
initTopbar();
|
initTopbar();
|
||||||
|
basic();
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||||
import { initLocaleDatetime, imgLazy } from './modules/plugins';
|
import { initLocaleDatetime, loadImg } from './modules/plugins';
|
||||||
|
|
||||||
basic();
|
loadImg();
|
||||||
|
initLocaleDatetime();
|
||||||
initSidebar();
|
initSidebar();
|
||||||
initTopbar();
|
initTopbar();
|
||||||
initLocaleDatetime();
|
basic();
|
||||||
imgLazy();
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
import { basic, initSidebar, initTopbar } from './modules/layouts';
|
||||||
import { initLocaleDatetime } from './modules/plugins';
|
import { initLocaleDatetime } from './modules/plugins';
|
||||||
|
|
||||||
basic();
|
|
||||||
initSidebar();
|
initSidebar();
|
||||||
initTopbar();
|
initTopbar();
|
||||||
initLocaleDatetime();
|
initLocaleDatetime();
|
||||||
|
basic();
|
||||||
|
|||||||
@@ -3,15 +3,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export function back2top() {
|
export function back2top() {
|
||||||
$(window).on('scroll', () => {
|
const btn = document.getElementById('back-to-top');
|
||||||
if ($(window).scrollTop() > 50) {
|
|
||||||
$('#back-to-top').fadeIn();
|
window.addEventListener('scroll', () => {
|
||||||
|
if (window.scrollY > 50) {
|
||||||
|
btn.classList.add('show');
|
||||||
} else {
|
} else {
|
||||||
$('#back-to-top').fadeOut();
|
btn.classList.remove('show');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#back-to-top').on('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo({ top: 0 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
/**
|
/**
|
||||||
* Tab 'Categories' expand/close effect.
|
* Tab 'Categories' expand/close effect.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import 'bootstrap/js/src/collapse.js';
|
||||||
|
|
||||||
const childPrefix = 'l_';
|
const childPrefix = 'l_';
|
||||||
const parentPrefix = 'h_';
|
const parentPrefix = 'h_';
|
||||||
const collapse = $('.collapse');
|
const children = document.getElementsByClassName('collapse');
|
||||||
|
|
||||||
export function categoryCollapse() {
|
export function categoryCollapse() {
|
||||||
/* close up top-category */
|
[...children].forEach((elem) => {
|
||||||
collapse.on('hide.bs.collapse', function () {
|
const id = parentPrefix + elem.id.substring(childPrefix.length);
|
||||||
/* Bootstrap collapse events. */ const parentId =
|
const parent = document.getElementById(id);
|
||||||
parentPrefix + $(this).attr('id').substring(childPrefix.length);
|
|
||||||
if (parentId) {
|
// collapse sub-categories
|
||||||
$(`#${parentId} .far.fa-folder-open`).attr(
|
elem.addEventListener('hide.bs.collapse', () => {
|
||||||
'class',
|
if (parent) {
|
||||||
'far fa-folder fa-fw'
|
parent.querySelector('.far.fa-folder-open').className =
|
||||||
);
|
'far fa-folder fa-fw';
|
||||||
$(`#${parentId} i.fas`).addClass('rotate');
|
parent.querySelector('.fas.fa-angle-down').classList.add('rotate');
|
||||||
$(`#${parentId}`).removeClass('hide-border-bottom');
|
parent.classList.remove('hide-border-bottom');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* expand the top category */
|
// expand sub-categories
|
||||||
collapse.on('show.bs.collapse', function () {
|
elem.addEventListener('show.bs.collapse', () => {
|
||||||
const parentId =
|
if (parent) {
|
||||||
parentPrefix + $(this).attr('id').substring(childPrefix.length);
|
parent.querySelector('.far.fa-folder').className =
|
||||||
if (parentId) {
|
'far fa-folder-open fa-fw';
|
||||||
$(`#${parentId} .far.fa-folder`).attr(
|
parent.querySelector('.fas.fa-angle-down').classList.remove('rotate');
|
||||||
'class',
|
parent.classList.add('hide-border-bottom');
|
||||||
'far fa-folder-open fa-fw'
|
|
||||||
);
|
|
||||||
$(`#${parentId} i.fas`).removeClass('rotate');
|
|
||||||
$(`#${parentId}`).addClass('hide-border-bottom');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,85 +2,88 @@
|
|||||||
* Clipboard functions
|
* Clipboard functions
|
||||||
*
|
*
|
||||||
* Dependencies:
|
* 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 clipboardSelector = '.code-header>button';
|
||||||
|
|
||||||
|
const ICON_DEFAULT = 'far fa-clipboard';
|
||||||
const ICON_SUCCESS = 'fas fa-check';
|
const ICON_SUCCESS = 'fas fa-check';
|
||||||
|
|
||||||
const ATTR_TIMEOUT = 'timeout';
|
const ATTR_TIMEOUT = 'timeout';
|
||||||
const ATTR_TITLE_SUCCEED = 'data-title-succeed';
|
const ATTR_TITLE_SUCCEED = 'data-title-succeed';
|
||||||
const ATTR_TITLE_ORIGIN = 'data-bs-original-title';
|
const ATTR_TITLE_ORIGIN = 'data-bs-original-title';
|
||||||
const TIMEOUT = 2000; // in milliseconds
|
const TIMEOUT = 2000; // in milliseconds
|
||||||
|
|
||||||
function isLocked(node) {
|
function isLocked(node) {
|
||||||
if ($(node)[0].hasAttribute(ATTR_TIMEOUT)) {
|
if (node.hasAttribute(ATTR_TIMEOUT)) {
|
||||||
let timeout = $(node).attr(ATTR_TIMEOUT);
|
let timeout = node.getAttribute(ATTR_TIMEOUT);
|
||||||
if (Number(timeout) > Date.now()) {
|
if (Number(timeout) > Date.now()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function lock(node) {
|
function lock(node) {
|
||||||
$(node).attr(ATTR_TIMEOUT, Date.now() + TIMEOUT);
|
node.setAttribute(ATTR_TIMEOUT, Date.now() + TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
function unlock(node) {
|
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) {
|
function showTooltip(btn) {
|
||||||
const succeedTitle = $(btn).attr(ATTR_TITLE_SUCCEED);
|
const succeedTitle = btn.getAttribute(ATTR_TITLE_SUCCEED);
|
||||||
$(btn).attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show');
|
btn.setAttribute(ATTR_TITLE_ORIGIN, succeedTitle);
|
||||||
|
Tooltip.getInstance(btn).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideTooltip(btn) {
|
function hideTooltip(btn) {
|
||||||
$(btn).tooltip('hide').removeAttr(ATTR_TITLE_ORIGIN);
|
Tooltip.getInstance(btn).hide();
|
||||||
|
btn.removeAttribute(ATTR_TITLE_ORIGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSuccessIcon(btn) {
|
function setSuccessIcon(btn) {
|
||||||
let btnNode = $(btn);
|
const icon = btn.children[0];
|
||||||
let iconNode = btnNode.children();
|
icon.setAttribute('class', ICON_SUCCESS);
|
||||||
iconNode.attr('class', ICON_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resumeIcon(btn) {
|
function resumeIcon(btn) {
|
||||||
let btnNode = $(btn);
|
const icon = btn.children[0];
|
||||||
let iconNode = btnNode.children();
|
icon.setAttribute('class', ICON_DEFAULT);
|
||||||
iconNode.attr('class', ICON_DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initClipboard() {
|
function setCodeClipboard() {
|
||||||
|
const clipboardList = document.querySelectorAll(clipboardSelector);
|
||||||
|
|
||||||
|
if (clipboardList.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Initial the clipboard.js object
|
// Initial the clipboard.js object
|
||||||
if ($(clipboardSelector).length) {
|
|
||||||
const clipboard = new ClipboardJS(clipboardSelector, {
|
const clipboard = new ClipboardJS(clipboardSelector, {
|
||||||
target(trigger) {
|
target: (trigger) => {
|
||||||
let codeBlock = trigger.parentNode.nextElementSibling;
|
const codeBlock = trigger.parentNode.nextElementSibling;
|
||||||
return codeBlock.querySelector('code .rouge-code');
|
return codeBlock.querySelector('code .rouge-code');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const clipboardList = document.querySelectorAll(clipboardSelector);
|
|
||||||
[...clipboardList].map(
|
[...clipboardList].map(
|
||||||
(elem) =>
|
(elem) =>
|
||||||
new bootstrap.Tooltip(elem, {
|
new Tooltip(elem, {
|
||||||
placement: 'left'
|
placement: 'left'
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
clipboard.on('success', (e) => {
|
clipboard.on('success', (e) => {
|
||||||
|
const trigger = e.trigger;
|
||||||
|
|
||||||
e.clearSelection();
|
e.clearSelection();
|
||||||
|
|
||||||
const trigger = e.trigger;
|
|
||||||
if (isLocked(trigger)) {
|
if (isLocked(trigger)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -95,12 +98,17 @@ export function initClipboard() {
|
|||||||
unlock(trigger);
|
unlock(trigger);
|
||||||
}, TIMEOUT);
|
}, TIMEOUT);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLinkClipboard() {
|
||||||
|
const btnCopyLink = document.getElementById('copy-link');
|
||||||
|
|
||||||
|
if (btnCopyLink === null) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Post link sharing --- */
|
btnCopyLink.addEventListener('click', (e) => {
|
||||||
|
const target = e.target;
|
||||||
$('#copy-link').on('click', (e) => {
|
|
||||||
let target = $(e.target);
|
|
||||||
|
|
||||||
if (isLocked(target)) {
|
if (isLocked(target)) {
|
||||||
return;
|
return;
|
||||||
@@ -108,16 +116,28 @@ export function initClipboard() {
|
|||||||
|
|
||||||
// Copy URL to clipboard
|
// Copy URL to clipboard
|
||||||
navigator.clipboard.writeText(window.location.href).then(() => {
|
navigator.clipboard.writeText(window.location.href).then(() => {
|
||||||
const defaultTitle = target.attr(ATTR_TITLE_ORIGIN);
|
const defaultTitle = target.getAttribute(ATTR_TITLE_ORIGIN);
|
||||||
const succeedTitle = target.attr(ATTR_TITLE_SUCCEED);
|
const succeedTitle = target.getAttribute(ATTR_TITLE_SUCCEED);
|
||||||
|
|
||||||
// Switch tooltip title
|
// Switch tooltip title
|
||||||
target.attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show');
|
target.setAttribute(ATTR_TITLE_ORIGIN, succeedTitle);
|
||||||
|
Tooltip.getInstance(target).show();
|
||||||
|
|
||||||
lock(target);
|
lock(target);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
target.attr(ATTR_TITLE_ORIGIN, defaultTitle);
|
target.setAttribute(ATTR_TITLE_ORIGIN, defaultTitle);
|
||||||
unlock(target);
|
unlock(target);
|
||||||
}, TIMEOUT);
|
}, TIMEOUT);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
btnCopyLink.addEventListener('mouseleave', (e) => {
|
||||||
|
Tooltip.getInstance(e.target).hide();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initClipboard() {
|
||||||
|
setCodeClipboard();
|
||||||
|
setLinkClipboard();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
/**
|
|
||||||
* Set up image lazy-load
|
|
||||||
*/
|
|
||||||
|
|
||||||
export function imgLazy() {
|
|
||||||
if ($('#core-wrapper img[data-src]') <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Stop shimmer when image loaded */
|
|
||||||
document.addEventListener('lazyloaded', function (e) {
|
|
||||||
const $img = $(e.target);
|
|
||||||
$img.parent().removeClass('shimmer');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
67
_javascript/modules/components/img-loading.js
Normal file
67
_javascript/modules/components/img-loading.js
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Setting up image lazy loading and LQIP switching
|
||||||
|
*/
|
||||||
|
|
||||||
|
const ATTR_DATA_SRC = 'data-src';
|
||||||
|
const ATTR_DATA_LQIP = 'data-lqip';
|
||||||
|
|
||||||
|
const cover = {
|
||||||
|
SHIMMER: 'shimmer',
|
||||||
|
BLUR: 'blur'
|
||||||
|
};
|
||||||
|
|
||||||
|
function removeCover(clzss) {
|
||||||
|
this.parentElement.classList.remove(clzss);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleImage() {
|
||||||
|
if (!this.complete) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.hasAttribute(ATTR_DATA_LQIP)) {
|
||||||
|
removeCover.call(this, cover.BLUR);
|
||||||
|
} else {
|
||||||
|
removeCover.call(this, cover.SHIMMER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches the LQIP with the real image URL.
|
||||||
|
*/
|
||||||
|
function switchLQIP() {
|
||||||
|
const src = this.getAttribute(ATTR_DATA_SRC);
|
||||||
|
this.setAttribute('src', encodeURI(src));
|
||||||
|
this.removeAttribute(ATTR_DATA_SRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadImg() {
|
||||||
|
const images = document.querySelectorAll('article img');
|
||||||
|
|
||||||
|
if (images.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
images.forEach((img) => {
|
||||||
|
img.addEventListener('load', handleImage);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Images loaded from the browser cache do not trigger the 'load' event
|
||||||
|
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 = document.querySelectorAll(
|
||||||
|
`article img[${ATTR_DATA_LQIP}="true"]`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (lqips.length) {
|
||||||
|
lqips.forEach((lqip) => {
|
||||||
|
switchLQIP.call(lqip);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,22 +1,15 @@
|
|||||||
/**
|
/**
|
||||||
* Set up image popup
|
* Set up image popup
|
||||||
*
|
*
|
||||||
* See: https://github.com/dimsemenov/Magnific-Popup
|
* Dependencies: https://github.com/biati-digital/glightbox
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const IMG_CLASS = 'popup';
|
||||||
|
|
||||||
export function imgPopup() {
|
export function imgPopup() {
|
||||||
if ($('.popup') <= 0) {
|
if (document.getElementsByClassName(IMG_CLASS).length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.popup').magnificPopup({
|
GLightbox({ selector: `.${IMG_CLASS}` });
|
||||||
type: 'image',
|
|
||||||
closeOnContentClick: true,
|
|
||||||
showCloseBtn: false,
|
|
||||||
zoom: {
|
|
||||||
enabled: true,
|
|
||||||
duration: 300,
|
|
||||||
easing: 'ease-in-out'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ class LocaleHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static get locale() {
|
static get locale() {
|
||||||
return $('html').attr('lang').substring(0, 2);
|
return document.documentElement.getAttribute('lang').substring(0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTimestamp(elem) {
|
static getTimestamp(elem) {
|
||||||
return Number(elem.attr(LocaleHelper.attrTimestamp)); // unix timestamp
|
return Number(elem.getAttribute(this.attrTimestamp)); // unix timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDateFormat(elem) {
|
static getDateFormat(elem) {
|
||||||
return elem.attr(LocaleHelper.attrDateFormat);
|
return elem.getAttribute(this.attrDateFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,21 +31,23 @@ export function initLocaleDatetime() {
|
|||||||
dayjs.locale(LocaleHelper.locale);
|
dayjs.locale(LocaleHelper.locale);
|
||||||
dayjs.extend(window.dayjs_plugin_localizedFormat);
|
dayjs.extend(window.dayjs_plugin_localizedFormat);
|
||||||
|
|
||||||
$(`[${LocaleHelper.attrTimestamp}]`).each(function () {
|
document
|
||||||
const date = dayjs.unix(LocaleHelper.getTimestamp($(this)));
|
.querySelectorAll(`[${LocaleHelper.attrTimestamp}]`)
|
||||||
const text = date.format(LocaleHelper.getDateFormat($(this)));
|
.forEach((elem) => {
|
||||||
$(this).text(text);
|
const date = dayjs.unix(LocaleHelper.getTimestamp(elem));
|
||||||
$(this).removeAttr(LocaleHelper.attrTimestamp);
|
const text = date.format(LocaleHelper.getDateFormat(elem));
|
||||||
$(this).removeAttr(LocaleHelper.attrDateFormat);
|
elem.textContent = text;
|
||||||
|
elem.removeAttribute(LocaleHelper.attrTimestamp);
|
||||||
|
elem.removeAttribute(LocaleHelper.attrDateFormat);
|
||||||
|
|
||||||
// setup tooltips
|
// setup tooltips
|
||||||
const tooltip = $(this).attr('data-bs-toggle');
|
if (
|
||||||
if (typeof tooltip === 'undefined' || tooltip !== 'tooltip') {
|
elem.hasAttribute('data-bs-toggle') &&
|
||||||
return;
|
elem.getAttribute('data-bs-toggle') === 'tooltip'
|
||||||
|
) {
|
||||||
|
// see: https://day.js.org/docs/en/display/format#list-of-localized-formats
|
||||||
|
const tooltipText = date.format('llll');
|
||||||
|
elem.setAttribute('data-bs-title', tooltipText);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tooltipText = date.format('llll'); // see: https://day.js.org/docs/en/display/format#list-of-localized-formats
|
|
||||||
$(this).attr('data-bs-title', tooltipText);
|
|
||||||
new bootstrap.Tooltip($(this));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,14 @@
|
|||||||
/**
|
/**
|
||||||
* Add listener for theme mode toggle
|
* Add listener for theme mode toggle
|
||||||
*/
|
*/
|
||||||
const $toggleElem = $('.mode-toggle');
|
const toggle = document.getElementById('mode-toggle');
|
||||||
|
|
||||||
export function modeWatcher() {
|
export function modeWatcher() {
|
||||||
if ($toggleElem.length === 0) {
|
if (!toggle) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$toggleElem.off().on('click', (e) => {
|
toggle.addEventListener('click', () => {
|
||||||
const $target = $(e.target);
|
modeToggle.flipMode();
|
||||||
let $btn =
|
|
||||||
$target.prop('tagName') === 'button'.toUpperCase()
|
|
||||||
? $target
|
|
||||||
: $target.parent();
|
|
||||||
|
|
||||||
modeToggle.flipMode(); // modeToggle: `_includes/mode-toggle.html`
|
|
||||||
$btn.trigger('blur'); // remove the clicking outline
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,248 +0,0 @@
|
|||||||
/**
|
|
||||||
* Count page views form GA or local cache file.
|
|
||||||
*
|
|
||||||
* Dependencies:
|
|
||||||
* - jQuery
|
|
||||||
* - countUp.js <https://github.com/inorganik/countUp.js>
|
|
||||||
*/
|
|
||||||
|
|
||||||
const getInitStatus = (function () {
|
|
||||||
let hasInit = false;
|
|
||||||
return () => {
|
|
||||||
let ret = hasInit;
|
|
||||||
if (!hasInit) {
|
|
||||||
hasInit = true;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
const PvOpts = (function () {
|
|
||||||
function getContent(selector) {
|
|
||||||
return $(selector).attr('content');
|
|
||||||
}
|
|
||||||
|
|
||||||
function hasContent(selector) {
|
|
||||||
let content = getContent(selector);
|
|
||||||
return typeof content !== 'undefined' && content !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
getProxyMeta() {
|
|
||||||
return getContent('meta[name=pv-proxy-endpoint]');
|
|
||||||
},
|
|
||||||
getLocalMeta() {
|
|
||||||
return getContent('meta[name=pv-cache-path]');
|
|
||||||
},
|
|
||||||
hasProxyMeta() {
|
|
||||||
return hasContent('meta[name=pv-proxy-endpoint]');
|
|
||||||
},
|
|
||||||
hasLocalMeta() {
|
|
||||||
return hasContent('meta[name=pv-cache-path]');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
const PvStorage = (function () {
|
|
||||||
const Keys = {
|
|
||||||
KEY_PV: 'pv',
|
|
||||||
KEY_PV_SRC: 'pv_src',
|
|
||||||
KEY_CREATION: 'pv_created_date'
|
|
||||||
};
|
|
||||||
|
|
||||||
const Source = {
|
|
||||||
LOCAL: 'same-origin',
|
|
||||||
PROXY: 'cors'
|
|
||||||
};
|
|
||||||
|
|
||||||
function get(key) {
|
|
||||||
return localStorage.getItem(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function set(key, val) {
|
|
||||||
localStorage.setItem(key, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveCache(pv, src) {
|
|
||||||
set(Keys.KEY_PV, pv);
|
|
||||||
set(Keys.KEY_PV_SRC, src);
|
|
||||||
set(Keys.KEY_CREATION, new Date().toJSON());
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
keysCount() {
|
|
||||||
return Object.keys(Keys).length;
|
|
||||||
},
|
|
||||||
hasCache() {
|
|
||||||
return localStorage.getItem(Keys.KEY_PV) !== null;
|
|
||||||
},
|
|
||||||
getCache() {
|
|
||||||
return JSON.parse(localStorage.getItem(Keys.KEY_PV));
|
|
||||||
},
|
|
||||||
saveLocalCache(pv) {
|
|
||||||
saveCache(pv, Source.LOCAL);
|
|
||||||
},
|
|
||||||
saveProxyCache(pv) {
|
|
||||||
saveCache(pv, Source.PROXY);
|
|
||||||
},
|
|
||||||
isExpired() {
|
|
||||||
let date = new Date(get(Keys.KEY_CREATION));
|
|
||||||
date.setHours(date.getHours() + 1); // per hour
|
|
||||||
return Date.now() >= date.getTime();
|
|
||||||
},
|
|
||||||
isFromLocal() {
|
|
||||||
return get(Keys.KEY_PV_SRC) === Source.LOCAL;
|
|
||||||
},
|
|
||||||
isFromProxy() {
|
|
||||||
return get(Keys.KEY_PV_SRC) === Source.PROXY;
|
|
||||||
},
|
|
||||||
newerThan(pv) {
|
|
||||||
return (
|
|
||||||
PvStorage.getCache().totalsForAllResults['ga:pageviews'] >
|
|
||||||
pv.totalsForAllResults['ga:pageviews']
|
|
||||||
);
|
|
||||||
},
|
|
||||||
inspectKeys() {
|
|
||||||
if (localStorage.length !== PvStorage.keysCount()) {
|
|
||||||
localStorage.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < localStorage.length; i++) {
|
|
||||||
const key = localStorage.key(i);
|
|
||||||
switch (key) {
|
|
||||||
case Keys.KEY_PV:
|
|
||||||
case Keys.KEY_PV_SRC:
|
|
||||||
case Keys.KEY_CREATION:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
localStorage.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})(); /* PvStorage */
|
|
||||||
|
|
||||||
function countUp(min, max, destId) {
|
|
||||||
if (min < max) {
|
|
||||||
let numAnim = new CountUp(destId, min, max);
|
|
||||||
if (!numAnim.error) {
|
|
||||||
numAnim.start();
|
|
||||||
} else {
|
|
||||||
console.error(numAnim.error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function countPV(path, rows) {
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
if (typeof rows !== 'undefined') {
|
|
||||||
for (let i = 0; i < rows.length; ++i) {
|
|
||||||
const gaPath = rows[parseInt(i, 10)][0];
|
|
||||||
if (gaPath === path) {
|
|
||||||
/* path format see: site.permalink */
|
|
||||||
count += parseInt(rows[parseInt(i, 10)][1], 10);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
function tacklePV(rows, path, elem, hasInit) {
|
|
||||||
let count = countPV(path, rows);
|
|
||||||
count = count === 0 ? 1 : count;
|
|
||||||
|
|
||||||
if (!hasInit) {
|
|
||||||
elem.text(new Intl.NumberFormat().format(count));
|
|
||||||
} else {
|
|
||||||
const initCount = parseInt(elem.text().replace(/,/g, ''), 10);
|
|
||||||
if (count > initCount) {
|
|
||||||
countUp(initCount, count, elem.attr('id'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayPageviews(data) {
|
|
||||||
if (typeof data === 'undefined') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let hasInit = getInitStatus();
|
|
||||||
const rows = data.rows; /* could be undefined */
|
|
||||||
|
|
||||||
if ($('.post').length > 0) {
|
|
||||||
/* the post */
|
|
||||||
const path = window.location.pathname;
|
|
||||||
tacklePV(rows, path, $('#pv'), hasInit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchProxyPageviews() {
|
|
||||||
if (PvOpts.hasProxyMeta()) {
|
|
||||||
$.ajax({
|
|
||||||
type: 'GET',
|
|
||||||
url: PvOpts.getProxyMeta(),
|
|
||||||
dataType: 'jsonp',
|
|
||||||
success: (data) => {
|
|
||||||
displayPageviews(data);
|
|
||||||
PvStorage.saveProxyCache(JSON.stringify(data));
|
|
||||||
},
|
|
||||||
error: (jqXHR, textStatus, errorThrown) => {
|
|
||||||
console.log(
|
|
||||||
'Failed to load pageviews from proxy server: ' + errorThrown
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchLocalPageviews(hasCache = false) {
|
|
||||||
return fetch(PvOpts.getLocalMeta())
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => {
|
|
||||||
if (hasCache) {
|
|
||||||
// The cache from the proxy will sometimes be more recent than the local one
|
|
||||||
if (PvStorage.isFromProxy() && PvStorage.newerThan(data)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
displayPageviews(data);
|
|
||||||
PvStorage.saveLocalCache(JSON.stringify(data));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function initPageviews() {
|
|
||||||
if ($('.pageviews').length <= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PvStorage.inspectKeys();
|
|
||||||
|
|
||||||
if (PvStorage.hasCache()) {
|
|
||||||
displayPageviews(PvStorage.getCache());
|
|
||||||
|
|
||||||
if (PvStorage.isExpired()) {
|
|
||||||
if (PvOpts.hasLocalMeta()) {
|
|
||||||
fetchLocalPageviews(true).then(fetchProxyPageviews);
|
|
||||||
} else {
|
|
||||||
fetchProxyPageviews();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (PvStorage.isFromLocal()) {
|
|
||||||
fetchProxyPageviews();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// no cached
|
|
||||||
|
|
||||||
if (PvOpts.hasLocalMeta()) {
|
|
||||||
fetchLocalPageviews().then(fetchProxyPageviews);
|
|
||||||
} else {
|
|
||||||
fetchProxyPageviews();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +1,109 @@
|
|||||||
/**
|
/**
|
||||||
* This script make #search-result-wrapper switch to unloaded or shown automatically.
|
* This script make #search-result-wrapper switch to unloaded or shown automatically.
|
||||||
*/
|
*/
|
||||||
const $btnSbTrigger = $('#sidebar-trigger');
|
|
||||||
const $btnSearchTrigger = $('#search-trigger');
|
|
||||||
const $btnCancel = $('#search-cancel');
|
|
||||||
const $content = $('#main>.row');
|
|
||||||
const $topbarTitle = $('#topbar-title');
|
|
||||||
const $searchWrapper = $('#search-wrapper');
|
|
||||||
const $resultWrapper = $('#search-result-wrapper');
|
|
||||||
const $results = $('#search-results');
|
|
||||||
const $input = $('#search-input');
|
|
||||||
const $hints = $('#search-hints');
|
|
||||||
const $viewport = $('html,body');
|
|
||||||
|
|
||||||
// class names
|
const btnSbTrigger = document.getElementById('sidebar-trigger');
|
||||||
const C_LOADED = 'loaded';
|
const btnSearchTrigger = document.getElementById('search-trigger');
|
||||||
const C_UNLOADED = 'unloaded';
|
const btnCancel = document.getElementById('search-cancel');
|
||||||
const C_FOCUS = 'input-focus';
|
const content = document.querySelectorAll('#main-wrapper>.container>.row');
|
||||||
const C_FLEX = 'd-flex';
|
const topbarTitle = document.getElementById('topbar-title');
|
||||||
|
const search = document.getElementById('search');
|
||||||
|
const resultWrapper = document.getElementById('search-result-wrapper');
|
||||||
|
const results = document.getElementById('search-results');
|
||||||
|
const input = document.getElementById('search-input');
|
||||||
|
const hints = document.getElementById('search-hints');
|
||||||
|
|
||||||
class ScrollBlocker {
|
// CSS class names
|
||||||
static offset = 0;
|
const LOADED = 'd-block';
|
||||||
static resultVisible = false;
|
const UNLOADED = 'd-none';
|
||||||
|
const FOCUS = 'input-focus';
|
||||||
|
const FLEX = 'd-flex';
|
||||||
|
|
||||||
static on() {
|
/* Actions in mobile screens (Sidebar hidden) */
|
||||||
ScrollBlocker.offset = window.scrollY;
|
|
||||||
$viewport.scrollTop(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static off() {
|
|
||||||
$viewport.scrollTop(ScrollBlocker.offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--- Actions in mobile screens (Sidebar hidden) ---*/
|
|
||||||
class MobileSearchBar {
|
class MobileSearchBar {
|
||||||
static on() {
|
static on() {
|
||||||
$btnSbTrigger.addClass(C_UNLOADED);
|
btnSbTrigger.classList.add(UNLOADED);
|
||||||
$topbarTitle.addClass(C_UNLOADED);
|
topbarTitle.classList.add(UNLOADED);
|
||||||
$btnSearchTrigger.addClass(C_UNLOADED);
|
btnSearchTrigger.classList.add(UNLOADED);
|
||||||
$searchWrapper.addClass(C_FLEX);
|
search.classList.add(FLEX);
|
||||||
$btnCancel.addClass(C_LOADED);
|
btnCancel.classList.add(LOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static off() {
|
static off() {
|
||||||
$btnCancel.removeClass(C_LOADED);
|
btnCancel.classList.remove(LOADED);
|
||||||
$searchWrapper.removeClass(C_FLEX);
|
search.classList.remove(FLEX);
|
||||||
$btnSbTrigger.removeClass(C_UNLOADED);
|
btnSbTrigger.classList.remove(UNLOADED);
|
||||||
$topbarTitle.removeClass(C_UNLOADED);
|
topbarTitle.classList.remove(UNLOADED);
|
||||||
$btnSearchTrigger.removeClass(C_UNLOADED);
|
btnSearchTrigger.classList.remove(UNLOADED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResultSwitch {
|
class ResultSwitch {
|
||||||
|
static resultVisible = false;
|
||||||
|
|
||||||
static on() {
|
static on() {
|
||||||
if (!ScrollBlocker.resultVisible) {
|
if (!this.resultVisible) {
|
||||||
// the block method must be called before $(#main) unloaded.
|
resultWrapper.classList.remove(UNLOADED);
|
||||||
ScrollBlocker.on();
|
content.forEach((el) => {
|
||||||
$resultWrapper.removeClass(C_UNLOADED);
|
el.classList.add(UNLOADED);
|
||||||
$content.addClass(C_UNLOADED);
|
});
|
||||||
ScrollBlocker.resultVisible = true;
|
this.resultVisible = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static off() {
|
static off() {
|
||||||
if (ScrollBlocker.resultVisible) {
|
if (this.resultVisible) {
|
||||||
$results.empty();
|
results.innerHTML = '';
|
||||||
if ($hints.hasClass(C_UNLOADED)) {
|
|
||||||
$hints.removeClass(C_UNLOADED);
|
if (hints.classList.contains(UNLOADED)) {
|
||||||
|
hints.classList.remove(UNLOADED);
|
||||||
}
|
}
|
||||||
$resultWrapper.addClass(C_UNLOADED);
|
|
||||||
$content.removeClass(C_UNLOADED);
|
|
||||||
|
|
||||||
// now the release method must be called after $(#main) display
|
resultWrapper.classList.add(UNLOADED);
|
||||||
ScrollBlocker.off();
|
content.forEach((el) => {
|
||||||
|
el.classList.remove(UNLOADED);
|
||||||
$input.val('');
|
});
|
||||||
ScrollBlocker.resultVisible = false;
|
input.textContent = '';
|
||||||
|
this.resultVisible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isMobileView() {
|
function isMobileView() {
|
||||||
return $btnCancel.hasClass(C_LOADED);
|
return btnCancel.classList.contains(LOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function displaySearch() {
|
export function displaySearch() {
|
||||||
$btnSearchTrigger.on('click', function () {
|
btnSearchTrigger.addEventListener('click', () => {
|
||||||
MobileSearchBar.on();
|
MobileSearchBar.on();
|
||||||
ResultSwitch.on();
|
ResultSwitch.on();
|
||||||
$input.trigger('focus');
|
input.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
$btnCancel.on('click', function () {
|
btnCancel.addEventListener('click', () => {
|
||||||
MobileSearchBar.off();
|
MobileSearchBar.off();
|
||||||
ResultSwitch.off();
|
ResultSwitch.off();
|
||||||
});
|
});
|
||||||
|
|
||||||
$input.on('focus', function () {
|
input.addEventListener('focus', () => {
|
||||||
$searchWrapper.addClass(C_FOCUS);
|
search.classList.add(FOCUS);
|
||||||
});
|
});
|
||||||
|
|
||||||
$input.on('focusout', function () {
|
input.addEventListener('focusout', () => {
|
||||||
$searchWrapper.removeClass(C_FOCUS);
|
search.classList.remove(FOCUS);
|
||||||
});
|
});
|
||||||
|
|
||||||
$input.on('input', () => {
|
input.addEventListener('input', () => {
|
||||||
if ($input.val() === '') {
|
if (input.value === '') {
|
||||||
if (isMobileView()) {
|
if (isMobileView()) {
|
||||||
$hints.removeClass(C_UNLOADED);
|
hints.classList.remove(UNLOADED);
|
||||||
} else {
|
} else {
|
||||||
ResultSwitch.off();
|
ResultSwitch.off();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ResultSwitch.on();
|
ResultSwitch.on();
|
||||||
if (isMobileView()) {
|
if (isMobileView()) {
|
||||||
$hints.addClass(C_UNLOADED);
|
hints.classList.add(UNLOADED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user