1
0
mirror of https://github.com/cotes2020/jekyll-theme-chirpy.git synced 2025-12-19 06:06:54 +00:00

Compare commits

..

214 Commits

Author SHA1 Message Date
semantic-release-bot
20987f2afe chore(release): 7.0.1
## [7.0.1](https://github.com/cotes2020/jekyll-theme-chirpy/compare/v7.0.0...v7.0.1) (2024-05-18)

### Bug Fixes

* **analytics:** goatcounter pv greater than 1K cannot be converted to numbers ([#1762](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1762)) ([33a1fa7](33a1fa7cae))
* audio/video path apply variable `media_subpath` ([#1745](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1745)) ([00a27a1](00a27a1b85))
2024-05-18 11:01:22 +00:00
Cotes Chung
39e4338839 Merge branch 'hotfix/7.0.1' into production 2024-05-18 18:58:08 +08:00
Cotes Chung
33a1fa7cae fix(analytics): goatcounter pv greater than 1K cannot be converted to numbers (#1762)
The goatcounter PV report splits numbers with spaces, e.g. 1024 would be '1 024'
2024-05-18 18:52:45 +08:00
Alexander Fuks
00a27a1b85 fix: audio/video path apply variable media_subpath (#1745) 2024-05-18 18:47:12 +08:00
Cotes Chung
5cdde7dbc5 ci: enable ci/style-lint for the hotfix branches 2024-05-17 20:11:08 +08:00
Cotes Chung
c4b58e3502 build: upgrade dependencies
Updates `@fortawesome/fontawesome-free` to 6.5.2
- [Release notes](https://github.com/FortAwesome/Font-Awesome/releases)
- [Changelog](https://github.com/FortAwesome/Font-Awesome/blob/6.x/CHANGELOG.md)
- [Commits](https://github.com/FortAwesome/Font-Awesome/compare/6.5.1...6.5.2)

Updates `dayjs` to 1.11.11
- [Release notes](https://github.com/iamkun/dayjs/releases)
- [Changelog](https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/iamkun/dayjs/compare/v1.11.10...v1.11.11)

Updates `mermaid` to 10.9.0
- [Release notes](https://github.com/mermaid-js/mermaid/releases)
- [Changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/mermaid-js/mermaid/compare/v10.8.0...v10.9.0)

Updates `tocbot` to 4.27.20
- [Release notes](https://github.com/tscanlin/tocbot/releases)
- [Changelog](https://github.com/tscanlin/tocbot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tscanlin/tocbot/compare/v4.25.0...v4.27.20)
2024-05-17 00:03:53 +08:00
Cotes Chung
9630fd647f ci(release): pass secrets to called workflow 2024-05-12 07:35:58 +08:00
semantic-release-bot
e33547fe5d chore(release): 7.0.0
## [7.0.0](https://github.com/cotes2020/jekyll-theme-chirpy/compare/v6.5.5...v7.0.0) (2024-05-11)

### ⚠ BREAKING CHANGES

* optimize the resource hints (#1717)
* rename media-url file and related parameters (#1651)
* rename comment setting parameter (#1563)
* **analytics:** add post pageviews for GoatCounter (#1543)

### Features

* add cloudflare web analytics ([#1723](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1723)) ([c17fba4](c17fba44f5))
* add support for embed video files ([#1558](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1558)) ([9592146](9592146ca3))
* add support for giscus strict title matching ([#1614](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1614)) ([700fd5b](700fd5bad7))
* **analytics:** add post pageviews for GoatCounter ([#1543](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1543)) ([b641b3f](b641b3f1f2))
* **analytics:** add Umami and Matomo tracking codes ([#1658](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1658)) ([61bdca2](61bdca2db4))
* change site verification settings ([#1561](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1561)) ([e436387](e4363871b5))
* **deps:** move `MathJax` configuration to a separate file ([#1670](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1670)) ([44f552c](44f552cbce))
* display theme version in footer ([#1611](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1611)) ([8349314](834931486d))
* **i18n:** allow `page.lang` to override `site.lang` ([#1586](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1586)) ([547b95c](547b95cc7a))
* make post description customizable ([#1602](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1602)) ([f865336](f865336c89))
* **media:** support audio and video tag with multi sources ([#1618](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1618)) ([23be416](23be4162b3))

### Bug Fixes

* make TOC title and entries visible at the same time ([#1711](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1711)) ([e0950fc](e0950fc973))
* mode toggle not outlined when receiving keyboard focus ([#1690](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1690)) ([cd37f63](cd37f63a01))
* prevent footnote back arrow from becoming an emoji ([#1716](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1716)) ([8608147](8608147fb5))
* **pwa:** skip range requests in service worker ([#1672](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1672)) ([76d58fe](76d58fe0ff))
* search result prompt is empty ([#1583](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1583)) ([8a2afae](8a2afae6ca))
* use `https` for Weibo sharing URL ([#1612](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1612)) ([8e5fbb7](8e5fbb7a74))

### Improvements

* improve <hr> visibility in dark mode ([#1565](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1565)) ([4ddd5c4](4ddd5c4370))
* lean bootstrap javascript ([#1734](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1734)) ([ddb48ed](ddb48eda52))
* rename comment setting parameter ([#1563](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1563)) ([f8390d4](f8390d4384))
* replace jQuery with Vanilla JS ([#1681](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1681)) ([fe7afa3](fe7afa379f))
* simplify mode toggle script ([#1692](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1692)) ([d4a6d64](d4a6d640bd))
* tree shaking Bootstrap CSS ([#1736](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1736)) ([363a3d9](363a3d936b))

### Changes

* optimize the resource hints ([#1717](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1717)) ([dcb0add](dcb0add47b))
* rename media-url file and related parameters ([#1651](https://github.com/cotes2020/jekyll-theme-chirpy/issues/1651)) ([9f8aeaa](9f8aeaadbf))
2024-05-11 07:30:33 +00:00
Cotes Chung
09b300bc62 Merge branch 'master' into production 2024-05-11 15:03:29 +08:00
Cotes Chung
9ffd997c3b ci(release): skip git status check in prep phase 2024-05-11 15:02:37 +08:00
Cotes Chung
37827d81e5 chore: correct npm script name 2024-05-11 14:24:15 +08:00
Cotes Chung
febc01db52 docs: update supported versions of Security Policy 2024-05-11 14:10:23 +08:00
Cotes Chung
b2245492e6 build(deps): upgrade jekyll-compress-html to v3.2.0 2024-05-11 14:09:15 +08:00
Cotes Chung
f87fdd0ea0 build(deps): upgrade html-proofer to v5.x 2024-05-11 14:08:39 +08:00
Cotes Chung
fdbd7f02e3 build(deps): update assets submodule 2024-05-11 13:53:15 +08:00
Cotes Chung
75891e714f build(deps-dev): bump the npm group across 1 directory with 6 updates
Updates `@babel/core` to 7.24.5
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.5/packages/babel-core)

Updates `@babel/preset-env` to 7.24.5
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.5/packages/babel-preset-env)

Updates `@commitlint/cli` to 19.3.0
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.3.0/@commitlint/cli)

Updates `rollup` to 4.17.2
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.15.0...v4.17.2)

Updates `semantic-release` to 23.1.1
- [Release notes](https://github.com/semantic-release/semantic-release/releases)
- [Commits](https://github.com/semantic-release/semantic-release/compare/v23.0.8...v23.1.1)

Updates `stylelint` to 16.5.0
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/16.3.1...16.5.0)
2024-05-11 13:51:25 +08:00
Cotes Chung
363a3d936b perf: tree shaking Bootstrap CSS (#1736) 2024-05-11 11:15:12 +08:00
Cotes Chung
ddb48eda52 perf: lean bootstrap javascript (#1734) 2024-05-11 10:29:14 +08:00
Hieu D
c17fba44f5 feat: add cloudflare web analytics (#1723) 2024-05-04 08:46:17 +08:00
Cotes Chung
12c340e98b ci: update dependabot settings 2024-05-04 01:06:56 +08:00
Cotes Chung
dcb0add47b refactor!: optimize the resource hints (#1717)
Improved the data structure for defining resource hints to the browser.
2024-05-02 05:11:45 +08:00
Cotes Chung
f1c6d2a817 build: enhance the run script 2024-05-02 03:18:35 +08:00
Cotes Chung
05ebfb705e chore: update discussion template 2024-05-02 03:16:35 +08:00
Huanyu Shi
8608147fb5 fix: prevent footnote back arrow from becoming an emoji (#1716) 2024-05-01 23:12:46 +08:00
Azamat Mambetov
76d58fe0ff fix(pwa): skip range requests in service worker (#1672) 2024-04-29 23:27:41 +08:00
Cotes Chung
b77767f76e refactor: improve js module loading order 2024-04-29 03:43:33 +08:00
Cotes Chung
e0950fc973 fix: make TOC title and entries visible at the same time (#1711)
When internet connection speeds are poor, there is a chance that the title of the TOC will appear earlier than its entries, causing a visual cutoff.
2024-04-29 03:36:16 +08:00
Cotes Chung
778ebdf250 chore: delete JS comments from HTML 2024-04-29 03:25:26 +08:00
Huanyu Shi
796c386037 refactor: add date factor to the recommended posts (#1699) 2024-04-28 03:03:13 +08:00
Cotes Chung
72d93b132f build: improve init tool 2024-04-28 02:51:16 +08:00
Cotes Chung
e09831ba3e ci: specify the node version (#1694) 2024-04-21 01:17:35 +08:00
Cotes Chung
05e3689d17 build(deps-dev): bump the npm group with 6 updates
Updates `@babel/core` to 7.24.4
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.4/packages/babel-core)

Updates `@babel/preset-env` to 7.24.4
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.4/packages/babel-preset-env)

Updates `@commitlint/cli` to 19.2.2
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.2.2/@commitlint/cli)

Updates `@commitlint/config-conventional` to 19.2.2
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.2.2/@commitlint/config-conventional)

Updates `rollup` to 4.15.0
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.13.2...v4.15.0)

Updates `stylelint-config-standard-scss` to 13.1.0
- [Release notes](https://github.com/stylelint-scss/stylelint-config-standard-scss/releases)
- [Changelog](https://github.com/stylelint-scss/stylelint-config-standard-scss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint-scss/stylelint-config-standard-scss/compare/v13.0.0...v13.1.0)
2024-04-21 01:14:21 +08:00
Cotes Chung
d4a6d640bd perf: simplify mode toggle script (#1692)
Reduce conditional logic to speed up theme mode initialization and switching.
2024-04-21 00:39:12 +08:00
Cotes Chung
2cfa54847a ci: drop Ruby 3.0 and introduce Ruby 3.3 (#1691)
See: https://www.ruby-lang.org/en/downloads/branches/
2024-04-21 00:22:01 +08:00
Cotes Chung
cd37f63a01 fix: mode toggle not outlined when receiving keyboard focus (#1690)
The Tab key focus
2024-04-21 00:15:14 +08:00
Cotes Chung
015d5670a1 refactor: reduce custom CSS 2024-04-21 00:00:50 +08:00
Cotes Chung
63c51384df chore: remove comments from compressed HTML 2024-04-20 23:59:59 +08:00
Vinicius Rocha
662cd331e3 chore: add .jekyll-metadata to .gitignore (#1686) 2024-04-19 21:36:44 +08:00
Cotes Chung
d013c11c8d docs: update readme 2024-04-17 19:25:28 +08:00
Cotes Chung
fe7afa379f perf: replace jQuery with Vanilla JS (#1681)
Also replaced `magnific-popup` with `GLightbox`
2024-04-17 06:10:01 +08:00
Cotes Chung
c85e9e2394 ci: avoid trigger redundant workflows (#1682)
CodeQL and Sytle Lint
2024-04-17 06:00:36 +08:00
Cotes Chung
bf16d6039a ci(release): replace standard-version with semantic-release (#1666)
[`standard-version`](https://github.com/conventional-changelog/standard-version/) has been deprecated since May 2022, so it is necessary to stop using it for this project.

[**`semantic-release`**](https://github.com/semantic-release/semantic-release) is available as a more capable alternative to help automate the release process:

1. Updating Node/Gem version numbers
2. Generating changelogs
3. Automating GitHub Releases
4. Building Chirpy-gem and pushing it to RubyGems.org
5. Create commits and tags on the `production` branch
6. Merge the `production` branch into the `master` branch

> ⚠️ Note: Step _6_ may be canceled in CD environments due to merge conflicts, so we need to do this step manually in such cases.

Whenever a commit is pushed to the release branch (`production`), all of the above release processes will be triggered.
2024-04-14 05:15:27 +08:00
Cotes Chung
8c1be9f2f3 ci: fix checkout depth for commitlint 2024-04-14 05:06:06 +08:00
Cotes Chung
7808ee157c chore: move starter workflow into subfolder
The `.hook` suffix does not make it easy to maintain code in the editor
2024-04-14 04:45:52 +08:00
Cotes Chung
1914c786a0 docs: add missing head to changelog 2024-04-14 04:40:01 +08:00
Cotes Chung
44f552cbce feat(deps): move MathJax configuration to a separate file (#1670)
Move `MathJax` configuration to file `assets/js/data/mathjax.js` will help add extensions.
2024-04-14 04:34:32 +08:00
Cotes Chung
7d48d32c7b ci: avoid duplicate builds for PR commits 2024-04-14 04:20:53 +08:00
Azamat Mambetov
9f8aeaadbf refactor!: rename media-url file and related parameters (#1651)
- Changed variable `img_cdn` to `cdn` in site configuration file.
- Changed the variable defining the relative path of the image in the post from `img_url` to `media_subpath`
2024-04-13 05:14:55 +08:00
Filippo
61bdca2db4 feat(analytics): add Umami and Matomo tracking codes (#1658) 2024-04-09 22:57:06 +08:00
Azamat Mambetov
23be4162b3 feat(media): support audio and video tag with multi sources (#1618) 2024-04-05 00:54:50 +08:00
Cotes Chung
01076cb1c2 build(deps-dev): bump the npm group with 2 updates
Updates `rollup` to 4.13.2
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.13.0...v4.13.2)

Updates `stylelint` to 16.3.1
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/16.2.1...16.3.1)
2024-04-03 05:14:33 +08:00
Cotes Chung
3cc1510071 build(deps): update wagoid/commitlint-github-action from 5 to 6
Bumps the gh-actions group with 1 update: [wagoid/commitlint-github-action](https://github.com/wagoid/commitlint-github-action).

Updates `wagoid/commitlint-github-action` from 5 to 6
- [Changelog](https://github.com/wagoid/commitlint-github-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wagoid/commitlint-github-action/compare/v5...v6)
2024-04-03 05:12:44 +08:00
Mascari4615
950839175a refactor: fix reference to comment parameter site.comments.provider (#1629) 2024-03-25 00:57:43 +08:00
Cotes Chung
13bf51e03d chore(editor): update markdown extension settings 2024-03-24 02:35:48 +08:00
Cotes Chung
ce96d7e251 Merge branch 'production' 2024-03-24 02:31:04 +08:00
Cotes Chung
7a7818b579 chore(release): 6.5.5 2024-03-24 02:31:02 +08:00
Cotes Chung
cef8a97384 Merge branch 'hotfix/6.5.5' into production 2024-03-24 02:31:00 +08:00
Cotes Chung
2d649aae0e fix(post): correct the image URLs (#1627) 2024-03-24 02:28:28 +08:00
Cotes Chung
b7aa05d03a docs: add v6.5.3 changelog 2024-03-24 02:26:58 +08:00
Cotes Chung
c5d5e1f75a build(deps-dev): bump the npm group with 7 updates
Updates `@babel/core` to 7.24.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.3/packages/babel-core)

Updates `@babel/plugin-transform-class-properties` to 7.24.1
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.1/packages/babel-plugin-transform-class-properties)

Updates `@babel/preset-env` to 7.24.3
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.3/packages/babel-preset-env)

Updates `@commitlint/cli` to 19.2.1
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.2.1/@commitlint/cli)

Updates `@commitlint/config-conventional` to 19.1.0
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.1.0/@commitlint/config-conventional)

Updates `rollup` to 4.13.0
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.12.0...v4.13.0)

Updates `rollup-plugin-license` to 3.3.1
- [Changelog](https://github.com/mjeanroy/rollup-plugin-license/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mjeanroy/rollup-plugin-license/compare/v3.2.0...v3.3.1)
2024-03-23 08:01:23 +08:00
Cotes Chung
319a082940 refactor(post): reduce the margin between title and description 2024-03-23 03:52:13 +08:00
Cotes Chung
6044df4ff1 Merge branch 'production' 2024-03-23 03:42:00 +08:00
Cotes Chung
e5594525e7 chore(release): 6.5.4 2024-03-23 03:41:58 +08:00
Cotes Chung
e15eaaffe0 Merge branch 'hotfix/6.5.4' into production 2024-03-23 03:41:54 +08:00
Cotes Chung
74cf57aaac fix(seo): correct social preview image path inside <meta> tag (#1623) 2024-03-23 03:32:03 +08:00
Alexander Fuks
cfe44f204b fix: correct the attribute for the Twitter social image (#1615) 2024-03-23 02:59:43 +08:00
GetOutOfMyBakery
700fd5bad7 feat: add support for giscus strict title matching (#1614) 2024-03-18 19:08:05 +08:00
Small Long
8e5fbb7a74 fix: use https for Weibo sharing URL (#1612) 2024-03-18 18:54:37 +08:00
Azamat Mambetov
834931486d feat: display theme version in footer (#1611) 2024-03-18 18:52:33 +08:00
Alexander Fuks
f865336c89 feat: make post description customizable (#1602)
---------

Co-authored-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2024-03-18 18:50:05 +08:00
Cotes Chung
0f8e782bfd Merge branch 'production' 2024-03-08 04:12:38 +08:00
Cotes Chung
0a6c1fb251 chore(release): 6.5.3 2024-03-08 04:12:36 +08:00
Sukka
75a3d7399b refactor: replace polyfill.io for cdnjs hosted link (#1598) 2024-03-08 04:05:58 +08:00
Neil Boyd
547b95cc7a feat(i18n): allow page.lang to override site.lang (#1586) 2024-03-05 03:09:39 +08:00
Cotes Chung
2a7b56bb36 build(deps-dev): bump the npm group with 5 updates
Updates `@babel/core` to 7.24.0
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.0/packages/babel-core)

Updates `@babel/preset-env` to 7.24.0
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.24.0/packages/babel-preset-env)

Updates `@commitlint/cli` from 18.6.1 to 19.0.3
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.0.3/@commitlint/cli)

Updates `@commitlint/config-conventional` from 18.6.2 to 19.0.3
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v19.0.3/@commitlint/config-conventional)

Updates `rollup` to 4.12.0
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.10.0...v4.12.0)

Close #1580
2024-03-04 18:06:06 +08:00
Cotes Chung
25c4166722 style(markdown): resolve markdownlint warnings 2024-03-02 02:14:17 +08:00
Cotes Chung
25b2ffa9ba build: configure rules for markdownlint 2024-03-02 02:07:35 +08:00
Cotes Chung
8a2afae6ca fix: search result prompt is empty (#1583) 2024-03-01 20:06:34 +08:00
Alexander Fuks
6112b15b8e refactor: change alternate url for embed video file (#1579) 2024-02-29 23:55:30 +03:00
Alexander Fuks
e24a0c73ba refactor: use explicit url for goatcounter (#1578) 2024-02-29 23:01:10 +03:00
Cotes Chung
0f5abc82a2 Merge branch 'production' 2024-03-01 03:51:26 +08:00
Cotes Chung
795ff3f4c3 chore(release): 6.5.2 2024-03-01 03:51:25 +08:00
Cotes Chung
c41672b2e0 Merge branch 'hotfix/6.5.2' into production 2024-03-01 03:51:21 +08:00
Cotes Chung
9cc62e703f build(release): build the gem on the production branch (#1577) 2024-03-01 03:11:17 +08:00
Cotes Chung
19d6bafbe1 fix: correct the base URL parameter name (#1576)
#1553 introduced
2024-03-01 02:50:10 +08:00
Alexander Fuks
4ddd5c4370 perf: improve <hr> visibility in dark mode (#1565) 2024-02-28 19:58:20 +03:00
Alexander Fuks
9592146ca3 feat: add support for embed video files (#1558) 2024-02-27 23:51:33 +03:00
Cotes Chung
8a1568c27a Merge branch 'production' 2024-02-27 02:44:32 +08:00
Cotes Chung
388c1511d6 chore(release): 6.5.1 2024-02-27 02:44:31 +08:00
Cotes Chung
8849afe5cf Merge branch 'hotfix/6.5.1' into production 2024-02-27 02:44:29 +08:00
Cotes Chung
f8390d4384 perf!: rename comment setting parameter (#1563)
Rename `site.comments.active` to `site.comments.provider`
2024-02-27 01:39:04 +08:00
Alexander Fuks
e4363871b5 feat: change site verification settings (#1561) 2024-02-26 22:17:18 +08:00
Alexander Fuks
b641b3f1f2 feat(analytics)!: add post pageviews for GoatCounter (#1543)
---------

Co-authored-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2024-02-26 02:50:41 +08:00
Dongee Seo
5dbda0c09f build(deps-dev): replace the deprecated libraries (#1559)
Replace `@babel/plugin-proposal-class-properties` with `@babel/plugin-transform-class-properties`

See: https://www.npmjs.com/package/@babel/plugin-proposal-class-properties
2024-02-25 20:30:21 +08:00
Cotes Chung
89b962557a fix: correct the generation of relative resource paths (#1553) 2024-02-23 03:07:17 +08:00
Josh Johanning
5de0153df4 build(ci): update actions versions (#1554) 2024-02-22 22:04:54 +08:00
Cotes Chung
ed4d304cd2 Merge branch 'production' 2024-02-15 00:18:40 +08:00
Cotes Chung
48564bda8d chore(release): 6.5.0 2024-02-15 00:18:39 +08:00
Cotes Chung
b9d053b3cd Merge branch 'master' into production 2024-02-15 00:18:35 +08:00
Cotes Chung
cd258c92c3 chore(deps): upgrade mermaid to 10.8.0 2024-02-15 00:18:09 +08:00
dependabot[bot]
6230d1d750 build(deps-dev): bump the npm group with 8 updates (#1540)
Updates the requirements on [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core), [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env), [@commitlint/cli](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/cli), [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/HEAD/@commitlint/config-conventional), [husky](https://github.com/typicode/husky), [rollup](https://github.com/rollup/rollup), [stylelint](https://github.com/stylelint/stylelint) and [stylelint-config-standard-scss](https://github.com/stylelint-scss/stylelint-config-standard-scss) to permit the latest version.

Updates `@babel/core` to 7.23.9
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.9/packages/babel-core)

Updates `@babel/preset-env` to 7.23.9
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.9/packages/babel-preset-env)

Updates `@commitlint/cli` to 18.6.1
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/cli/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v18.6.1/@commitlint/cli)

Updates `@commitlint/config-conventional` to 18.6.2
- [Release notes](https://github.com/conventional-changelog/commitlint/releases)
- [Changelog](https://github.com/conventional-changelog/commitlint/blob/master/@commitlint/config-conventional/CHANGELOG.md)
- [Commits](https://github.com/conventional-changelog/commitlint/commits/v18.6.2/@commitlint/config-conventional)

Updates `husky` from 8.0.3 to 9.0.11
- [Release notes](https://github.com/typicode/husky/releases)
- [Commits](https://github.com/typicode/husky/compare/v8.0.3...v9.0.11)

Updates `rollup` to 4.10.0
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.9.2...v4.10.0)

Updates `stylelint` to 16.2.1
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/16.1.0...16.2.1)

Updates `stylelint-config-standard-scss` from 12.0.0 to 13.0.0
- [Release notes](https://github.com/stylelint-scss/stylelint-config-standard-scss/releases)
- [Changelog](https://github.com/stylelint-scss/stylelint-config-standard-scss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint-scss/stylelint-config-standard-scss/compare/v12.0.0...v13.0.0)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: "@commitlint/cli"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: "@commitlint/config-conventional"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: husky
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: rollup
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: stylelint
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: stylelint-config-standard-scss
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-15 00:12:45 +08:00
Cotes Chung
365abc6b3b build(deps-dev): set update interval to weekly 2024-02-14 23:59:22 +08:00
Cotes Chung
79c65b3e44 build(security): correct scan path for CodeQL 2024-02-14 01:06:30 +08:00
Cotes Chung
6b34901d94 refactor(pwa): revert to JS and Liquid mixing
The gem package won't be able to pass `/sw.min.js` to the user end
2024-02-13 23:35:32 +08:00
Benjamin van den Hout
90693ff95e feat: add analytics support for GoatCounter (#1526) 2024-02-06 22:19:28 +08:00
Cotes Chung
1a01c35e52 chore: update stale-bot settings 2024-02-05 07:28:35 +08:00
Cotes Chung
c335bc6ce7 build(security): stop scheduled scanning 2024-02-03 18:53:35 +08:00
Cotes Chung
f3ea7e9887 build(security): improve paths filter for CodeQL 2024-02-01 01:07:46 +08:00
Piotr Held
c13ec31163 perf: enable equation numbering in MathJax (#1520)
If you place your equations inside $$\begin{equation}...\end{equation}$$
you will get MathJax equation numbering. As described here:
https://docs.mathjax.org/en/latest/input/tex/eqnumbers.html

BREAKING CHANGES: if you used \begin{equation} inside $$ you will
get equation numbering which was not previously present.
2024-01-31 03:44:19 +08:00
yeonwlee
bbbb66b489 perf: allow TOC to start at heading 3 (#1512) 2024-01-30 08:22:03 +08:00
bigsk1
74f16623c9 fix: correct the Twitter Card in social share preview (#1498)
---------

Co-authored-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2024-01-28 05:53:54 +08:00
Cotes Chung
1127c43823 feat: add pwa.cache.* option to precisely control caching (#1501) 2024-01-28 02:22:33 +08:00
TroubleDog54
ea3a22e13c docs: fix typo in the "Getting Started" post (#1502) 2024-01-23 15:23:53 +08:00
Cotes Chung
c0018b66f3 build(editor): add VS Code config
Make it easy to initialize the development environment.
2024-01-22 02:50:52 +08:00
Cotes Chung
02e296ed75 fix: missing "/" at the end of URLs for categories and tags in breadcrumb (#1495) 2024-01-19 06:19:20 +08:00
Cotes Chung
4facf5b390 perf: allow no social links to be configured (#1494) 2024-01-19 05:48:26 +08:00
Cotes Chung
c5d11441bc build(deps-dev): install husky and commitlint locally
Signed-off-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2024-01-13 22:13:15 +08:00
Cotes Chung
96bdd7c1dd Merge branch 'production' 2024-01-13 22:04:40 +08:00
Cotes Chung
ba764c1380 chore(release): 6.4.2 2024-01-13 22:02:45 +08:00
Cotes Chung
c7cfde0930 fix: resume the blockquote display type (#1480)
Undo changes in #1449
2024-01-13 22:00:08 +08:00
Cotes Chung
13177979bb Merge branch 'production' 2024-01-11 02:13:03 +08:00
Cotes Chung
6a17a7d46c chore(release): 6.4.1 2024-01-11 02:13:01 +08:00
Cotes Chung
8c30b41e20 Merge branch 'master' into production 2024-01-11 02:12:58 +08:00
Cotes Chung
b2d1cb68db fix: og:image URL is incorrect (#1468)
Introduced by #1463
2024-01-11 02:11:25 +08:00
Cotes Chung
3589a6ee53 Merge branch 'production' 2024-01-10 23:11:38 +08:00
Cotes Chung
7efbed6a24 chore(release): 6.4.0 2024-01-10 23:11:36 +08:00
Cotes Chung
21d74f1183 Merge branch 'master' into production 2024-01-10 23:11:33 +08:00
Cotes Chung
d6d0098379 build(deps): upgrade 3rd-party libraries 2024-01-10 23:09:00 +08:00
Cotes Chung
241bb4df78 feat: add site-wide social preview image settings (#1463)
- Add configuration field `social_preview_image` that sets the site-wide default social preview image.  

   For pages that do not have `page.image` set in font matter, the seo tag will use the image specified by `site.social_preview_image` as the Open Graph image.

- Refactored the generation of image URLs to reduce redundant code and enhance fault tolerance for missing or repeated slash `/` when defining image paths.
2024-01-10 09:04:27 +08:00
Cotes Chung
82d8f2db98 perf: include the latest posts in the "Recently Updated" list (#1456)
Improve the "Recently Updated" list to include the most recent (only one Git commit) posts.

This change has two benefits:

1. The post update list is consistent with the git commit timeline.
2. Avoid users not having a list of updates to show when they first publish a site.
2024-01-08 05:13:56 +08:00
Cotes Chung
9882244bd9 refactor: remove extra margins from text within blockquote
Introduced by #1449
2024-01-07 06:27:09 +08:00
Cotes Chung
f243cbd858 docs: update the credits section in README 2024-01-06 19:15:31 +08:00
dependabot[bot]
d420b38329 build(deps-dev): bump the npm group with 5 updates (#1447) 2024-01-03 09:28:03 +00:00
Cotes Chung
ea2d238bd8 fix: image float breaks quotes and prompts (#1449)
Fixes #1441
2024-01-02 18:24:37 +08:00
dependabot[bot]
5234511a2f build(deps): bump the gh-actions group with 2 updates (#1448) 2024-01-01 19:52:24 +00:00
Cotes Chung
746a31e125 build(workflow): add more stale exemption labels (#1435)
New exemption labels:

- planning
- in progress
2023-12-31 16:10:25 +08:00
Cotes Chung
c45e031155 build(deps): specify the minor version number of ruby (#1431)
Resolves #1429
2023-12-27 23:56:39 +08:00
Mill Haruto
4a2b89d0b6 feat: add bilibili embed video support (#1406)
---------
Co-authored-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2023-12-09 21:48:19 +08:00
Chuck Houpt
2a4fbf6a79 fix: url-less authors should not have empty links (#1410)
The url field from authors.yml is optional, so no link should be
build when the url is empty or not defined.

Fix #1403
2023-12-06 22:38:11 +08:00
dependabot[bot]
84ea68cab0 build(deps-dev): bump the npm group with 3 updates (#1399)
Updates the requirements on [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core), [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) and [rollup](https://github.com/rollup/rollup) to permit the latest version.

Updates `@babel/core` to 7.23.5
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.5/packages/babel-core)

Updates `@babel/preset-env` to 7.23.5
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.5/packages/babel-preset-env)

Updates `rollup` to 4.6.1
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.3.0...v4.6.1)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: rollup
  dependency-type: direct:development
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-02 03:43:38 +08:00
Cotes Chung
3ed5eb1ee0 Merge branch 'production' 2023-11-13 04:21:05 +08:00
Cotes Chung
60836af606 chore(release): 6.3.1 2023-11-13 04:21:03 +08:00
Cotes Chung
739345ac24 Merge branch 'hotfix/6.3.1' into production 2023-11-13 04:21:00 +08:00
Cotes Chung
1a977a87a0 fix(home): responsive gap at the bottom of preview image
Range of impacted screen widths:

- (width >= 768px) and (width < 1150px)
- (width >= 1200px) and (width <= 1460px)
2023-11-13 04:09:28 +08:00
Cotes Chung
d1a5b57e4d Merge branch 'production' 2023-11-10 20:10:36 +08:00
Cotes Chung
2b9d379d70 chore(release): 6.3.0 2023-11-10 20:10:34 +08:00
Cotes Chung
bdee5d6b6d Merge branch 'master' into production 2023-11-10 20:09:30 +08:00
Cotes Chung
348f6bff8b chore: add a period at the end of the meta info 2023-11-10 20:08:08 +08:00
Cotes Chung
7a3d624364 chore(deps-dev): reduce external config files 2023-11-09 01:53:47 +08:00
Cotes Chung
06f1c6f256 refactor: align the position of the share buttons 2023-11-08 01:16:00 +08:00
Cotes Chung
4a7f33f7bb build(tools): improve the release script 2023-11-07 03:38:02 +08:00
Cotes Chung
e077d2911d chore(deps): upgrade dependent libraries 2023-11-07 03:29:28 +08:00
dependabot[bot]
5f2edb0914 build(deps-dev): bump the npm group with 8 updates (#1365)
Updates the requirements on [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core), [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env), [@rollup/plugin-babel](https://github.com/rollup/plugins/tree/HEAD/packages/babel), [@rollup/plugin-terser](https://github.com/rollup/plugins/tree/HEAD/packages/terser), [rollup](https://github.com/rollup/rollup), [rollup-plugin-license](https://github.com/mjeanroy/rollup-plugin-license), [stylelint](https://github.com/stylelint/stylelint) and [stylelint-config-standard-scss](https://github.com/stylelint-scss/stylelint-config-standard-scss) to permit the latest version.

Updates `@babel/core` to 7.23.2
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/@babel/core@7.23.2/packages/babel-core)

Updates `@babel/preset-env` to 7.23.2
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.2/packages/babel-preset-env)

Updates `@rollup/plugin-babel` to 6.0.4
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/babel/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/babel-v6.0.4/packages/babel)

Updates `@rollup/plugin-terser` to 0.4.4
- [Changelog](https://github.com/rollup/plugins/blob/master/packages/terser/CHANGELOG.md)
- [Commits](https://github.com/rollup/plugins/commits/terser-v0.4.4/packages/terser)

Updates `rollup` from 3.29.4 to 4.3.0
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v3.29.4...v4.3.0)

Updates `rollup-plugin-license` to 3.2.0
- [Changelog](https://github.com/mjeanroy/rollup-plugin-license/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mjeanroy/rollup-plugin-license/compare/v3.1.0...v3.2.0)

Updates `stylelint` to 15.11.0
- [Release notes](https://github.com/stylelint/stylelint/releases)
- [Changelog](https://github.com/stylelint/stylelint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint/stylelint/compare/15.10.3...15.11.0)

Updates `stylelint-config-standard-scss` to 11.1.0
- [Release notes](https://github.com/stylelint-scss/stylelint-config-standard-scss/releases)
- [Changelog](https://github.com/stylelint-scss/stylelint-config-standard-scss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stylelint-scss/stylelint-config-standard-scss/compare/v11.0.0...v11.1.0)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: "@rollup/plugin-babel"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: "@rollup/plugin-terser"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: rollup
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: npm
- dependency-name: rollup-plugin-license
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: stylelint
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: stylelint-config-standard-scss
  dependency-type: direct:development
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-06 15:33:59 +08:00
Cotes Chung
911206be80 build(gh): reduce the frequency of dependabot PR submissions 2023-11-06 15:26:09 +08:00
Cotes Chung
18808851a9 build(deps): upgrade rubygem-deps
Ruby 2.x has passed its end of life and is now unsupported.
2023-11-06 15:26:03 +08:00
Natalie Somersall
2bf87e0de7 feat: add Mastodon sharing link (#1344)
Adds a "share to Mastodon" button as a link sharing option using @justinribeiro's share-to-mastodon package

Discussion of proposed change - #1324

---------

Co-authored-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2023-10-30 02:02:58 +08:00
dependabot[bot]
f6d96ab2b8 build(deps): upgrade actions/checkout to v4 (#1340)
Bumps the gh-actions group with 1 update: [actions/setup-node](https://github.com/actions/setup-node).

- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 03:43:40 +08:00
Cotes Chung
59c55121c7 docs: update project description 2023-10-23 05:41:55 +08:00
Cotes Chung
9f174d9088 fix: resume lazy loading for Twitch videos (#1326)
The property of lazy load is missing in #1267
2023-10-16 05:20:42 +08:00
Cotes Chung
5810bcd1d7 fix(home): crop the preview image that doesn't match 1.91:1 (#1325) 2023-10-16 01:51:02 +08:00
Cotes Chung
897b57bfb4 chore(release): 6.2.3 2023-10-10 13:00:55 +08:00
Cotes Chung
fd83462ea4 chore(release): 6.2.3 2023-10-10 13:00:54 +08:00
Cotes Chung
fa8a2a0ada Merge branch 'master' into production 2023-10-10 13:00:51 +08:00
DmitriyFrogo
7b7e69a44d chore(i18n): update Russian locale (#1308) 2023-10-09 21:54:04 +08:00
Cotes Chung
e6e2984e77 chore(deps): update library versions
See also: https://github.com/cotes2020/chirpy-static-assets/pull/11
2023-10-09 21:13:37 +08:00
Zheng Yuan
d71711d2d3 docs: add more content in Mathematics and fix some typos (#1306)
1. Add docs for block math and inline math
2. Change a grammar mistake at line 137, the single form should be used
3. Change the comma from Chinese to English for consistency of the doc.

---------

Co-authored-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2023-10-08 19:17:59 +08:00
Cotes Chung
50835b4c71 refactor: optimize meta font size 2023-10-08 04:40:16 +08:00
Cotes Chung
575dc87d83 chore: update comments for configuration options baseurl and url
Avoid newbies from misusing these two options
2023-10-06 21:02:48 +08:00
Cotes Chung
753cd0499d chore: remove console log from copy link button 2023-10-06 02:04:19 +08:00
Cotes Chung
b7e9f3ec34 docs: correct spelling in README 2023-10-05 06:04:14 +08:00
Cotes Chung
42bf39e21c perf(ux): render background color before loading preview image (#1298) 2023-10-04 16:40:16 -05:00
Cotes Chung
45c2a18884 chore(deps): update dependent libraries (#1296)
- Updates `bootstrap` to 5.3.2
- Updates `dayjs` to 1.11.10
2023-10-04 15:13:08 -05:00
dependabot[bot]
3fd3c571b5 build(deps-dev): bump the npm group with 4 updates (#1289)
Updates the requirements on [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core), [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env), [rimraf](https://github.com/isaacs/rimraf) and [rollup](https://github.com/rollup/rollup) to permit the latest version.

Updates `@babel/core` to 7.23.0
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.23.0/packages/babel-core)

Updates `@babel/preset-env` to 7.22.20
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.22.20/packages/babel-preset-env)

Updates `rimraf` to 5.0.5
- [Changelog](https://github.com/isaacs/rimraf/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/rimraf/compare/v5.0.1...v5.0.5)

Updates `rollup` to 3.29.4
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v3.29.0...v3.29.4)

---
updated-dependencies:
- dependency-name: "@babel/core"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: "@babel/preset-env"
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: rimraf
  dependency-type: direct:development
  dependency-group: npm
- dependency-name: rollup
  dependency-type: direct:development
  dependency-group: npm
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-04 14:34:38 -05:00
Cotes Chung
2574118f40 perf(ui): standardize metadata text styles (#1295) 2023-10-04 14:29:44 -05:00
Cotes Chung
0e2d593b00 chore: always use dynamic polyfill for browsers 2023-10-04 19:01:48 +08:00
Cotes Chung
2bc3172444 refactor: optimize LQIP loading
- add blur effect for external WebP format LQIP
- remove the timeout delay
2023-10-04 18:15:22 +08:00
Cotes Chung
55659315c6 docs: update project docs 2023-10-04 18:15:22 +08:00
Cotes Chung
bbd92d11cc chore: move CHANGELOG.md to docs/ 2023-10-04 18:15:22 +08:00
Cotes Chung
475d181aac refactor: optimize the basic layouts 2023-10-04 18:15:22 +08:00
Cotes Chung
f49155f034 chore(post): restore margin at the bottom of TOC 2023-09-29 05:36:01 +08:00
Cotes Chung
109725d2dc fix(home): avoid LQIP dirty data passing to the next post (#1278) 2023-09-29 05:25:10 +08:00
Cotes Chung
e3b01636ac refactor(core): optimize image loading
- JavaScript runs so fast that LQIP will never be detected
- Increase the running priority of image processing in posts

Enhancement for #1267
2023-09-29 05:07:03 +08:00
Cotes Chung
b489da89ca style(scss): update rule-empty-line-before config 2023-09-28 01:27:24 +08:00
Cotes Chung
2d56597571 perf(pwa): enhance cache privacy protection (#1275)
Hiding the time zone of the build machine enhances privacy protection.
2023-09-27 21:13:15 +08:00
Cotes Chung
97004ddc44 docs: improve readme content 2023-09-27 21:03:12 +08:00
Jens
75ea77d574 chore(i18n): update German language localisation (#1265)
* Add common German date format.
* Fix translation of read time prompt to a more correct word.

---------

Co-authored-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2023-09-27 04:46:58 +08:00
Cotes Chung
bf3a34d054 perf(core): replace lazysizes with browser-level lazy loading (#1267) 2023-09-27 04:44:32 +08:00
Cotes Chung
5015fdecf3 style(core): avoid using < or > within capture tag
This interferes with the work of the editor Liquid-HTML plugin
2023-09-25 01:49:20 +08:00
Cotes Chung
de2dff354a chore(ui): increase block radius 2023-09-24 22:18:46 +08:00
Denny Korsukéwitz
3a022bc816 docs: fix the stylesheet name in tutorial (#1260)
Fixes stylesheet name in post `2019-08-09-getting-started.md`

---------

Co-authored-by: Cotes Chung <11371340+cotes2020@users.noreply.github.com>
2023-09-23 17:44:44 +08:00
Cotes Chung
9b74070d45 docs: delete the usage guide for jekyll-docker
The project [`jekyll-docker`](https://github.com/envygeeks/jekyll-docker/) has not been updated for more than a year and is not supported by `sass-cover-3.x` (`sass-embedded`) in Jekyll `4.3` due to the old OS version.

When developing sass code, we have to consider `sass-cover-2.x` (`sassc`) compatibility, which reduces web rendering performance and increases syntax maintenance costs.

Therefore, it makes no sense to maintain this awkward situation and the use of the deprecated image `jekyll/jekyll` should be removed from the documentation.

See also:

- https://github.com/envygeeks/jekyll-docker/issues/363
- https://github.com/jekyll/jekyll-sass-converter#migrate-from-2x-to-3x
2023-09-23 05:04:31 +08:00
Cotes Chung
af4102476e docs: compress heading example 2023-09-23 05:01:29 +08:00
Cotes Chung
9d9e3bbca3 chore: update footer meta info about the project 2023-09-22 03:32:42 +08:00
Cotes Chung
6f2d3ea2bd build(gem): remove outdated config from Gemfile
`sass-embedded` supports running on `musl-libc` from version `1.58.0` onwards.

See also: <https://github.com/ntkme/sass-embedded-host-ruby/issues/94>
2023-09-22 03:31:05 +08:00
Cotes Chung
8417927264 refactor(scss): replace #{$var} with $var
This change stops forward compatibility with `jekyll-sass-converter-2.x`
2023-09-22 03:27:20 +08:00
Cotes Chung
ca39e15a78 build(gh): update checklist of issue / discussion template 2023-09-21 01:48:10 +08:00
Cotes Chung
e9c920641b perf(comments): lazy load giscus (#1254)
Enable the `giscus` lazy loading option to improve web performance.
2023-09-20 05:48:14 +08:00
Cotes Chung
0a55e1297b build: add content to bug-report template 2023-09-20 05:48:13 +08:00
Cotes Chung
0465a985dc fix(posts): resume target highlighting for superscripts and footnotes (#1253)
`<sup>` and `<footnote>` are highlighted when in `:target` state, but this feature has been missing since `v6.1.0` due to an oversight in development.
2023-09-20 04:27:32 +08:00
Cotes Chung
73e171b0fb perf(layout): optimize the main block height calculation (#1249)
If the post content height is smaller than the panel, there will be a large blank space between the bottom of the post and "Further Reading" section.
2023-09-19 04:44:35 +08:00
Cotes Chung
726085c647 fix(posts): code snippet clipboard tooltip missing title (#1246)
The layout `page` missing the `lang` specification
2023-09-19 00:43:08 +08:00
Cotes Chung
b97fa93ffd docs: simplify PR template 2023-09-18 23:57:43 +08:00
Cotes Chung
13a3c3c906 perf(layout): improve margins for tail block (#1243)
Keeps the margin of the elements in the tail area consistent regardless of the number of siblings, or if a <script> is inserted.
2023-09-18 03:26:02 +08:00
Cotes Chung
e78f67d354 build(gh): improve Issue / Discussion templates with form schema 2023-09-16 23:31:41 +08:00
Cotes Chung
b34661efd7 fix: avoid utterances initialization failure (#1234)
This issue exists since Chirpy `v6.0.0`
2023-09-15 01:24:13 +08:00
Cotes Chung
bb589e8d31 style: prettify utteranc code snippet 2023-09-15 01:13:20 +08:00
Cotes Chung
f079bb7f5b chore(release): 6.2.2 2023-09-11 02:32:38 +08:00
Cotes Chung
ac4b402f97 Merge branch 'hotfix/6.2.2' 2023-09-11 02:32:36 +08:00
Cotes Chung
87a12be897 chore(release): 6.2.2 2023-09-11 02:32:35 +08:00
Cotes Chung
0614473893 Merge branch 'hotfix/6.2.2' into production 2023-09-11 02:32:32 +08:00
Cotes Chung
273b389c51 fix(sidebar): contact icons not stacking (#1224)
Fixes #1224
2023-09-11 02:28:16 +08:00
Cotes Chung
204cb44dc3 chore(release): 6.2.1 2023-09-11 00:36:55 +08:00
Cotes Chung
f949bda15b Merge branch 'hotfix/6.2.1' 2023-09-11 00:36:54 +08:00
Cotes Chung
7ec8425e03 chore(release): 6.2.0 2023-09-10 20:37:20 +08:00
133 changed files with 2916 additions and 2049 deletions

View File

@@ -1,5 +0,0 @@
# https://github.com/browserslist/browserslist#browserslistrc
last 2 versions
> 0.2%
not dead

View File

@@ -1,8 +0,0 @@
{
"rules": {
"body-max-line-length": [
0,
"always"
]
}
}

17
.github/DISCUSSION_TEMPLATE/general.yml vendored Normal file
View 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
View 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
View 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!

View File

@@ -1,61 +0,0 @@
---
name: Bug Report
about: Create a report to help us improve
---
> **Tips**: Remember, contributions to this repository should follow the [contributing guidelines](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md).
## 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
View 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!

View File

@@ -1,26 +0,0 @@
---
name: Feature Request
about: Suggest an idea for this project
labels: enhancement
---
> **Tips**: Remember, contributions to this repository should follow the [contributing guidelines](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md).
## 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. -->

View 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.

View File

@@ -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
<!--
Please select the desired item checkbox and change it to "[x]", then delete options that are not relevant.
-->
<!-- Please select the desired item checkbox and change it from `[ ]` to `[x]` and then delete the irrelevant options. -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Improvement (refactoring and improving code)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
## Additional context
<!-- e.g. Fixes #(issue) -->
## How has this been tested
## Description
<!--
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
- [ ] I have tested this feature in the browser
## Additional context
<!-- e.g. Fixes #(issue) -->

2
.github/codeql/codeql-config.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
paths-ignore:
- "assets/js"

View File

@@ -2,10 +2,6 @@ version: 2
updates:
- package-ecosystem: "bundler"
directory: "/"
versioning-strategy: increase
groups:
bundler:
dependency-type: "production"
schedule:
interval: "weekly"
- package-ecosystem: "npm"
@@ -13,7 +9,10 @@ updates:
versioning-strategy: increase
groups:
npm:
dependency-type: "development"
update-types:
- "major"
- "minor"
- "patch"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"

View File

@@ -1,17 +1,40 @@
name: CD
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
branches:
- docs
- production
tags-ignore:
- "**"
jobs:
launch:
release:
permissions:
contents: write
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- run: |
curl -X POST -H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GH_PAT }}" \
https://api.github.com/repos/${{ secrets.BUILDER }}/dispatches \
-d '{"event_type":"deploy", "client_payload":{"branch": "${{ github.ref_name }}"}}'
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: 3.3
bundler-cache: true
- uses: actions/setup-node@v4
with:
node-version: 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
secrets:
GH_PAT: ${{ secrets.GH_PAT }}
BUILDER: ${{ secrets.BUILDER }}

View File

@@ -1,9 +1,9 @@
name: "CI"
on:
push:
branches-ignore:
- "production"
- "docs"
branches:
- "master"
- "hotfix/**"
paths-ignore:
- ".github/**"
- "!.github/workflows/ci.yml"
@@ -12,8 +12,6 @@ on:
- "README.md"
- "LICENSE"
pull_request:
paths:
- "**"
jobs:
build:
@@ -21,7 +19,7 @@ jobs:
strategy:
matrix:
ruby: [2.7, 3]
ruby: ["3.1", "3.2", "3.3"]
steps:
- name: Checkout
@@ -36,7 +34,9 @@ jobs:
bundler-cache: true
- name: Setup Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: latest
- name: Build Assets
run: npm i && npm run build

View File

@@ -2,11 +2,10 @@ name: "CodeQL"
on:
push:
paths: ["**.js"]
branches: ["master"]
paths: ["_javascript/**/*.js"]
pull_request:
paths: ["**.js"]
schedule:
- cron: "0 0 * * 5"
paths: ["_javascript/**/*.js"]
jobs:
analyze:
@@ -29,16 +28,17 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: "${{ matrix.language }}"
config-file: .github/codeql/codeql-config.yml
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"

View File

@@ -6,6 +6,4 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v5
- uses: wagoid/commitlint-github-action@v6

22
.github/workflows/publish.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: Publish
on:
push:
branches:
- docs
workflow_call:
secrets:
GH_PAT:
required: true
BUILDER:
required: true
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 }}"}}'

View File

@@ -8,23 +8,25 @@ 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@v8
- uses: actions/stale@v9
with:
days-before-stale: 30
days-before-close: 1
stale-issue-label: stale
exempt-issue-labels: pending
stale-issue-message: >
This issue has been automatically marked as stale because it has not had recent activity.
It will be closed if no further activity occurs.
Thank you for your contributions.
stale-pr-label: stale
exempt-pr-labels: pending
stale-pr-message: >
This PR has been automatically marked as stale because it has not had recent activity.
It will be closed if no further activity occurs.
Thank you for your contributions.
# 60 days before marking issues/PRs stale
days-before-close: -1 # does not close automatically
stale-issue-label: ${{ env.STALE_LABEL }}
exempt-issue-labels: ${{ env.EXEMPT_LABELS }}
stale-issue-message: ${{ env.MESSAGE }}
stale-pr-label: ${{ env.STALE_LABEL }}
exempt-pr-labels: ${{ env.EXEMPT_LABELS }}
stale-pr-message: ${{ env.MESSAGE }}

View File

@@ -37,12 +37,12 @@ jobs:
- name: Setup Pages
id: pages
uses: actions/configure-pages@v3
uses: actions/configure-pages@v4
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3
ruby-version: 3.3
bundler-cache: true
- name: Build site
@@ -53,11 +53,11 @@ jobs:
- name: Test site
run: |
bundle exec htmlproofer _site \
\-\-disable-external=true \
\-\-disable-external \
\-\-ignore-urls "/^http:\/\/127.0.0.1/,/^http:\/\/0.0.0.0/,/^http:\/\/localhost/"
- name: Upload site artifact
uses: actions/upload-pages-artifact@v1
uses: actions/upload-pages-artifact@v3
with:
path: "_site${{ steps.pages.outputs.base_path }}"
@@ -70,4 +70,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v4

View File

@@ -2,14 +2,10 @@ name: "Style Lint"
on:
push:
branches-ignore:
- "production"
- "docs"
paths:
- "_sass/**/*.scss"
branches: ["master", "hotfix/**"]
paths: ["_sass/**/*.scss"]
pull_request:
paths:
- "_sass/**/*.scss"
paths: ["_sass/**/*.scss"]
jobs:
stylelint:
@@ -20,6 +16,8 @@ jobs:
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: latest
- run: npm i
- run: npm test

4
.gitignore vendored
View File

@@ -5,6 +5,7 @@ Gemfile.lock
# Jekyll cache
.jekyll-cache
.jekyll-metadata
_site
# RubyGems
@@ -17,6 +18,9 @@ package-lock.json
# IDE configurations
.idea
.vscode
!.vscode/settings.json
!.vscode/extensions.json
# Misc
_sass/dist
assets/js/dist

View File

@@ -1,4 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no -- commitlint -x $(npm root -g)/@commitlint/config-conventional --edit
npx --no -- commitlint --edit ${1}

8
.markdownlint.json Normal file
View File

@@ -0,0 +1,8 @@
{
"commands-show-output": false,
"blanks-around-fences": false,
"line-length": false,
"no-inline-html": {
"allowed_elements": ["kbd", "sub"]
}
}

View File

@@ -1,3 +0,0 @@
{
"trailingComma": "none"
}

View File

@@ -1,23 +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": ["/^\\$/"] }],
"media-feature-range-notation": "prefix"
}
}

View File

@@ -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
View 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
View 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
View File

@@ -5,24 +5,5 @@ source "https://rubygems.org"
gemspec
group :test do
gem "html-proofer", "~> 4.4"
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"
gem "html-proofer", "~> 5.0"
end

View File

@@ -1,8 +1,10 @@
<!-- markdownlint-disable-next-line -->
<div align="center">
<!-- markdownlint-disable-next-line -->
# Chirpy Jekyll Theme
A minimal, responsive and feature-rich Jekyll theme for technical writing.
A minimal, responsive, and feature-rich Jekyll theme for technical writing.
[![Gem Version](https://img.shields.io/gem/v/jekyll-theme-chirpy?color=brightgreen)][gem]&nbsp;
[![CI](https://github.com/cotes2020/jekyll-theme-chirpy/actions/workflows/ci.yml/badge.svg?branch=master&event=push)][ci]&nbsp;
@@ -10,7 +12,7 @@
[![GitHub license](https://img.shields.io/github/license/cotes2020/jekyll-theme-chirpy.svg)][license]&nbsp;
[![996.icu](https://img.shields.io/badge/link-996.icu-%23FF4D5B.svg)](https://996.icu)
[**Live Demo →**][demo]
[**Live Demo** →][demo]
[![Devices Mockup](https://chirpy-img.netlify.app/commons/devices-mockup.png)][demo]
@@ -18,78 +20,64 @@
## Features
<details>
<summary>
<i>Click to view features</i>
</summary>
<p>
- Dark / Light Theme Mode
- Localized UI language
- Pinned Posts on Home Page
- Hierarchical Categories
- Trending Tags
- Table of Contents
- Last Modified Date
- Syntax Highlighting
- Mathematical Expressions
- Mermaid Diagrams & Flowcharts
- Dark / Light Mode Images
- Embed Videos
- Disqus / Utterances / Giscus Comments
- Built-in Search
- Atom Feeds
- PWA
- Google Analytics
- SEO & Performance Optimization
</p>
</details>
- Dark Theme
- Localized UI language
- Pinned Posts on Home Page
- Hierarchical Categories
- Trending Tags
- Table of Contents
- Last Modified Date
- Syntax Highlighting
- Mathematical Expressions
- Mermaid Diagrams & Flowcharts
- Dark Mode Images
- Embed Media
- Comment Systems
- Built-in Search
- Atom Feeds
- PWA
- Web Analytics
- SEO & Performance Optimization
## Documentation
To explore usage, development, and upgrade guide of the project, please refer to the [**Wiki**][wiki].
To learn how to use, develop, and upgrade the project, please refer to the [Wiki][wiki].
## Contributing
Contributions (Issues/PRs/Discussions) are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated. For details, see the "[Contributing Guidelines][contribute-guide]".
Contributions (_pull requests_, _issues_, and _discussions_) are what make the open-source community such an amazing place
to learn, inspire, and create. Any contributions you make are greatly appreciated.
For details, see the "[Contributing Guidelines][contribute-guide]".
## Credits
This theme is mainly built with [Jekyll][jekyllrb] ecosystem,
[Bootstrap][bootstrap], [Font Awesome][icons] and some other [wonderful tools][lib].
The avatar and favicon design come from [Clipart Max][image].
### Contributors
Many thanks to the [contributors][contributors] who participated in the development
and to the folks who reported bugs or shared ideas.
Thanks to [all the contributors][contributors] involved in the development of the project!
Last but not least, thanks to [JetBrains][jetbrains] for providing the _Open Source License_.
[![all-contributors](https://contrib.rocks/image?repo=cotes2020/jekyll-theme-chirpy&columns=16)][contributors]
<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.
[![Ko-fi](https://img.shields.io/badge/Support_Me_on_Ko--fi-ff5e5b?logo=ko-fi&logoColor=white)][ko-fi]&nbsp;
[![Wechat Pay](https://img.shields.io/badge/Tip_Me_on_WeChat-brightgreen?logo=wechat&logoColor=white)][donation]&nbsp;
[![Alipay](https://img.shields.io/badge/Tip_Me_on_Alipay-blue?logo=alipay&logoColor=white)][donation]
The avatar and favicon for the project's website are from [ClipartMAX][clipartmax].
## License
This work is published under [MIT License][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/
[bootstrap]: https://getbootstrap.com/
[icons]: https://fontawesome.com/
[image]: https://www.clipartmax.com/middle/m2i8b1m2K9Z5m2K9_ant-clipart-childrens-ant-cute/
[clipartmax]: https://www.clipartmax.com/middle/m2i8b1m2K9Z5m2K9_ant-clipart-childrens-ant-cute/
[demo]: https://cotes2020.github.io/chirpy-demo/
[wiki]: https://github.com/cotes2020/jekyll-theme-chirpy/wiki
[contribute-guide]: https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/docs/CONTRIBUTING.md
[contributors]: https://github.com/cotes2020/jekyll-theme-chirpy/graphs/contributors
[lib]: https://github.com/cotes2020/chirpy-static-assets
[vscode]: https://code.visualstudio.com/
[jetbrains]: https://www.jetbrains.com/?from=jekyll-theme-chirpy
[ko-fi]: https://ko-fi.com/coteschung/
[donation]: https://sponsor.cotes.page/

View File

@@ -3,10 +3,6 @@
# Import the theme
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
# 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'.
@@ -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
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: ""
github:
@@ -47,13 +44,36 @@ social:
# - https://www.facebook.com/username
# - https://www.linkedin.com/in/username
google_site_verification: # fill in to your verification string
# Site Verification Settings
webmaster_verifications:
google: # fill in your Google verification code
bing: # fill in your Bing verification code
alexa: # fill in your Alexa verification code
yandex: # fill in your Yandex verification code
baidu: # fill in your Baidu verification code
facebook: # fill in your Facebook verification code
# ↑ --------------------------
# The end of `jekyll-seo-tag` settings
google_analytics:
id: # fill in your Google Analytics ID
# Web Analytics Settings
analytics:
google:
id: # fill in your Google Analytics ID
goatcounter:
id: # fill in your GoatCounter ID
umami:
id: # fill in your Umami ID
domain: # fill in your Umami domain
matomo:
id: # fill in your Matomo ID
domain: # fill in your Matomo domain
cloudflare:
id: # fill in your Cloudflare Web Analytics token
# Pageviews settings
pageviews:
provider: # now only supports 'goatcounter'
# Prefer color scheme setting.
#
@@ -66,24 +86,29 @@ google_analytics:
# light - Use the light color scheme
# dark - Use the dark color scheme
#
theme_mode: # [light|dark]
theme_mode: # [light | dark]
# The CDN endpoint for images.
# The CDN endpoint for media resources.
# Notice that once it is assigned, the CDN url
# will be added to all image (site avatar & posts' images) paths starting with '/'
# will be added to all media resources (site avatar, posts' images, audio and video files) paths starting with '/'
#
# e.g. 'https://cdn.com'
img_cdn: "https://chirpy-img.netlify.app"
cdn: "https://chirpy-img.netlify.app"
# the avatar on sidebar, support local or CORS resources
avatar: "/commons/avatar.jpg"
# The URL of the site-wide social preview image used in SEO `og:image` meta tag.
# It can be overridden by a customized `page.image` in front matter.
social_preview_image: # string, local or CORS resources
# boolean type, the global switch for TOC in posts.
toc: true
comments:
active: # The global switch for posts comments, e.g., 'disqus'. Keep it empty means disable
# The active options are as follows:
# Global switch for the post comment system. Keeping it empty means disabled.
provider: # [disqus | utterances | giscus]
# The provider options are as follows:
disqus:
shortname: # fill with the Disqus shortname. https://help.disqus.com/en/articles/1717111-what-s-a-shortname
# utterances settings https://utteranc.es/
@@ -97,6 +122,7 @@ comments:
category:
category_id:
mapping: # optional, default to 'pathname'
strict: # optional, default to '0'
input_position: # optional, default to 'bottom'
lang: # optional, default to the value of `site.lang`
reactions_enabled: # optional, default to the value of `1`
@@ -107,16 +133,27 @@ assets:
enabled: # boolean, keep empty means false
# specify the Jekyll environment, empty means both
# only works if `assets.self_host.enabled` is 'true'
env: # [development|production]
env: # [development | production]
pwa:
enabled: true # the option for PWA feature
enabled: true # the option for PWA feature (installable)
cache:
enabled: true # the option for PWA offline cache
# Paths defined here will be excluded from the PWA cache.
# Usually its value is the `baseurl` of another website that
# shares the same domain name as the current website.
deny_paths:
# - "/example" # URLs match `<SITE_URL>/example/*` will not be cached by the PWA
paginate: 10
# The base URL of your site
baseurl: ""
# ------------ The following options are not recommended to be modified ------------------
kramdown:
footnote_backlink: "&#8617;&#xfe0e;"
syntax_highlighter: rouge
syntax_highlighter_opts: # Rouge Options https://github.com/jneen/rouge#full-options
css_class: highlight
@@ -153,10 +190,6 @@ defaults:
values:
layout: page
permalink: /:title/
- scope:
path: assets/img/favicons
values:
swcache: true
- scope:
path: assets/js/dist
values:
@@ -180,9 +213,8 @@ exclude:
- docs
- tools
- README.md
- CHANGELOG.md
- LICENSE
- rollup.config.js
- "*.config.js"
- package*.json
jekyll-archives:

View File

@@ -58,7 +58,7 @@ post:
pageview_measure: Aufrufe
read_time:
unit: Minuten
prompt: lesen
prompt: Lesezeit
relate_posts: Weiterlesen
share: Teilen
button:
@@ -70,6 +70,13 @@ post:
title: Link kopieren
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:
category_measure:

View File

@@ -40,7 +40,7 @@ copyright:
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.
meta: Using the :PLATFORM theme :THEME
meta: Using the :THEME theme for :PLATFORM.
not_found:
statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.

View File

@@ -3,14 +3,14 @@
# ----- Commons label -----
layout:
post: Публикация
post: Пост
category: Категория
tag: Тег
# The tabs of sidebar
tabs:
# format: <filename_without_extension>: <value>
home: Домашняя страница
home: Главная
categories: Категории
tags: Теги
archives: Архив
@@ -19,8 +19,8 @@ tabs:
# the text displayed in the search bar & search results
search:
hint: поиск
cancel: Отменить
no_results: Ох! Ничего не найдено.
cancel: Отмена
no_results: Упс! Ничего не найдено.
panel:
lastmod: Недавно обновлено
@@ -30,48 +30,58 @@ panel:
copyright:
# Shown at the bottom of the post
license:
template: Публикация защищена лицензией :LICENSE_NAME.
template: Авторский пост защищен лицензией :LICENSE_NAME.
name: CC BY 4.0
link: https://creativecommons.org/licenses/by/4.0/
# Displayed in the footer
brief: Некоторые права защищены.
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:
statment: Извините, эта ссылка указывает на ресурс который не существует.
statment: Извините, мы перепутали URL-адрес или он указывает на что-то несуществующее.
notification:
update_found: Доступна новая версия контента.
update: Обновлять
update: Обновить
# ----- Posts related labels -----
post:
written_by: Автор
posted: Время публикации
posted: Опубликовано
updated: Обновлено
words: слов
pageview_measure: просмотров
read_time:
unit: минут
unit: мин.
prompt: чтения
relate_posts: Вам также может быть интересно
relate_posts: Похожие посты
share: Поделиться
button:
next: Предыдущая публикация
previous: Следующая публикация
next: Следующий пост
previous: Предыдущий пост
copy_code:
succeed: Скопировано успешно!
succeed: Скопировано!
share_link:
title: Скопировать ссылку
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:
category_measure: категории
post_measure: публикации
category_measure:
singular: категория
plural: категории
post_measure:
singular: пост
plural: посты

18
_data/media.yml Normal file
View 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

View File

@@ -4,13 +4,6 @@ webfonts: /assets/lib/fonts/main.css
# Libraries
jquery:
js: /assets/lib/jquery/jquery.min.js
bootstrap:
css: /assets/lib/bootstrap/bootstrap.min.css
js: /assets/lib/bootstrap/bootstrap.bundle.min.js
toc:
css: /assets/lib/tocbot/tocbot.min.css
js: /assets/lib/tocbot/tocbot.min.js
@@ -31,18 +24,16 @@ dayjs:
relativeTime: /assets/lib/dayjs/plugin/relativeTime.min.js
localizedFormat: /assets/lib/dayjs/plugin/localizedFormat.min.js
magnific-popup:
css: /assets/lib/magnific-popup/magnific-popup.css
js: /assets/lib/magnific-popup/jquery.magnific-popup.min.js
glightbox:
css: /assets/lib/glightbox/glightbox.min.css
js: /assets/lib/glightbox/glightbox.min.js
lazysizes:
js: /assets/lib/lazysizes/lazysizes.min.js
lazy-polyfill:
css: /assets/lib/loading-attribute-polyfill/loading-attribute-polyfill.min.css
js: /assets/lib/loading-attribute-polyfill/loading-attribute-polyfill.umd.min.js
clipboard:
js: /assets/lib/clipboard/clipboard.min.js
polyfill:
js: /assets/lib/polyfill-v3-es6/polyfill.min.js
mathjax:
js: /assets/lib/mathjax/tex-chtml.js

View File

@@ -1,59 +1,54 @@
# CDNs
cdns:
# Google Fonts
# Resource Hints
resource_hints:
- url: https://fonts.googleapis.com
links:
- rel: preconnect
- rel: dns-prefetch
- url: https://fonts.gstatic.com
args: crossorigin
- url: https://fonts.googleapis.com
# jsDelivr CDN
links:
- rel: preconnect
opts: [crossorigin]
- rel: dns-prefetch
- url: https://cdn.jsdelivr.net
links:
- rel: preconnect
- rel: dns-prefetch
# fonts
webfonts: https://fonts.googleapis.com/css2?family=Lato&family=Source+Sans+Pro:wght@400;600;700;900&display=swap
# Web Fonts
webfonts: https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Source+Sans+Pro:wght@400;600;700;900&display=swap
# Libraries
jquery:
js: https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js
bootstrap:
css: https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css
js: https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js
toc:
css: https://cdn.jsdelivr.net/npm/tocbot@4.21.1/dist/tocbot.min.css
js: https://cdn.jsdelivr.net/npm/tocbot@4.21.1/dist/tocbot.min.js
css: https://cdn.jsdelivr.net/npm/tocbot@4.27.20/dist/tocbot.min.css
js: https://cdn.jsdelivr.net/npm/tocbot@4.27.20/dist/tocbot.min.js
fontawesome:
css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.2/css/all.min.css
css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css
search:
js: https://cdn.jsdelivr.net/npm/simple-jekyll-search@1.10.0/dest/simple-jekyll-search.min.js
mermaid:
js: https://cdn.jsdelivr.net/npm/mermaid@10.4.0/dist/mermaid.min.js
js: https://cdn.jsdelivr.net/npm/mermaid@10.9.0/dist/mermaid.min.js
dayjs:
js:
common: https://cdn.jsdelivr.net/npm/dayjs@1.11.9/dayjs.min.js
locale: https://cdn.jsdelivr.net/npm/dayjs@1.11.9/locale/:LOCALE.min.js
relativeTime: https://cdn.jsdelivr.net/npm/dayjs@1.11.9/plugin/relativeTime.min.js
localizedFormat: https://cdn.jsdelivr.net/npm/dayjs@1.11.9/plugin/localizedFormat.min.js
common: https://cdn.jsdelivr.net/npm/dayjs@1.11.11/dayjs.min.js
locale: https://cdn.jsdelivr.net/npm/dayjs@1.11.11/locale/:LOCALE.min.js
relativeTime: https://cdn.jsdelivr.net/npm/dayjs@1.11.11/plugin/relativeTime.min.js
localizedFormat: https://cdn.jsdelivr.net/npm/dayjs@1.11.11/plugin/localizedFormat.min.js
magnific-popup:
css: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/magnific-popup.min.css
js: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/jquery.magnific-popup.min.js
glightbox:
css: https://cdn.jsdelivr.net/npm/glightbox@3.3.0/dist/css/glightbox.min.css
js: https://cdn.jsdelivr.net/npm/glightbox@3.3.0/dist/js/glightbox.min.js
lazysizes:
js: https://cdn.jsdelivr.net/npm/lazysizes@5.3.2/lazysizes.min.js
lazy-polyfill:
css: https://cdn.jsdelivr.net/npm/loading-attribute-polyfill@2.1.1/dist/loading-attribute-polyfill.min.css
js: https://cdn.jsdelivr.net/npm/loading-attribute-polyfill@2.1.1/dist/loading-attribute-polyfill.umd.min.js
clipboard:
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:
js: https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-chtml.js

View File

@@ -22,4 +22,17 @@ platforms:
#
# - type: Weibo
# icon: "fab fa-weibo"
# link: "http://service.weibo.com/share/share.php?title=TITLE&url=URL"
# link: "https://service.weibo.com/share/share.php?title=TITLE&url=URL"
#
# - type: Mastodon
# icon: "fa-brands fa-mastodon"
# # 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/"

View 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 -->

View 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>

View 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>

View 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 -->

View File

@@ -0,0 +1,6 @@
<!-- Umami -->
<script
defer
src="{{ site.analytics.umami.domain }}/script.js"
data-website-id="{{ site.analytics.umami.id }}"
></script>

View File

@@ -1,5 +1,5 @@
<!-- The comments switcher -->
{% if page.comments and site.comments.active %}
{% capture path %}comments/{{ site.comments.active }}.html{% endcapture %}
<!-- The comments switcher -->
{% if page.comments and site.comments.provider %}
{% capture path %}comments/{{ site.comments.provider }}.html{% endcapture %}
{% include {{ path }} %}
{% endif %}

View File

@@ -1,6 +1,6 @@
<!-- The Disqus lazy loading. -->
<div id="disqus_thread" class="mb-5">
<div id="disqus_thread">
<p class="text-center text-muted small">Comments powered by <a href="https://disqus.com/">Disqus</a>.</p>
</div>
@@ -10,7 +10,7 @@
this.page.identifier = '{{ page.url }}';
};
/* Lazy loading */
{%- comment -%} Lazy loading {%- endcomment -%}
var disqus_observer = new IntersectionObserver(
function (entries) {
if (entries[0].isIntersecting) {
@@ -28,12 +28,12 @@
{ 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() {
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') {
return;
}
@@ -44,7 +44,7 @@
}
}
if (document.querySelector('.mode-toggle')) {
if (document.getElementById('mode-toggle')) {
window.addEventListener('message', reloadDisqus);
}
</script>

View File

@@ -2,7 +2,6 @@
<script type="text/javascript">
(function () {
const origin = 'https://giscus.app';
const iframe = 'iframe.giscus-frame';
const lightTheme = 'light';
const darkTheme = 'dark_dimmed';
@@ -25,11 +24,13 @@
'data-category': '{{ site.comments.giscus.category }}',
'data-category-id': '{{ site.comments.giscus.category_id }}',
'data-mapping': '{{ site.comments.giscus.mapping | default: 'pathname' }}',
'data-strict' : '{{ site.comments.giscus.strict | default: '0' }}',
'data-reactions-enabled': '{{ site.comments.giscus.reactions_enabled | default: '1' }}',
'data-emit-metadata': '0',
'data-theme': initTheme,
'data-input-position': '{{ site.comments.giscus.input_position | default: 'bottom' }}',
'data-lang': '{{ site.comments.giscus.lang | default: lang }}',
'data-loading': 'lazy',
crossorigin: 'anonymous',
async: ''
};
@@ -46,7 +47,7 @@
event.data &&
event.data.direction === ModeToggle.ID
) {
/* global theme mode changed */
{%- comment -%} global theme mode changed {%- endcomment -%}
const mode = event.data.message;
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);
}
});

View File

@@ -1,51 +1,49 @@
<!-- https://utteranc.es/ -->
<script src="https://utteranc.es/client.js"
repo="{{ site.comments.utterances.repo }}"
issue-term="{{ site.comments.utterances.issue_term }}"
crossorigin="anonymous"
async>
</script>
<script
src="https://utteranc.es/client.js"
repo="{{ site.comments.utterances.repo }}"
issue-term="{{ site.comments.utterances.issue_term }}"
crossorigin="anonymous"
async
></script>
<script type="text/javascript">
$(function() {
const origin = "https://utteranc.es";
const iframe = "iframe.utterances-frame";
const lightTheme = "github-light";
const darkTheme = "github-dark";
(function () {
const origin = 'https://utteranc.es';
const lightTheme = 'github-light';
const darkTheme = 'github-dark';
let initTheme = lightTheme;
const html = document.documentElement;
if ($("html[data-mode=dark]").length > 0
|| ($("html[data-mode]").length == 0
&& window.matchMedia("(prefers-color-scheme: dark)").matches)) {
if (
(html.hasAttribute('data-mode') && html.getAttribute('data-mode') === 'dark') ||
(!html.hasAttribute('data-mode') && window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
initTheme = darkTheme;
}
addEventListener("message", (event) => {
addEventListener('message', (event) => {
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) {
/* page initial */
{%- comment -%} page initial {%- endcomment -%}
theme = initTheme;
} else if (event.source === window && event.data &&
event.data.direction === ModeToggle.ID) {
/* global theme mode changed */
} else if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
{%- comment -%} global theme mode changed {%- endcomment -%}
const mode = event.data.message;
theme = (mode === ModeToggle.DARK_MODE ? darkTheme : lightTheme);
theme = mode === ModeToggle.DARK_MODE ? darkTheme : lightTheme;
} else {
return;
}
const message = {
type: "set-theme",
type: 'set-theme',
theme: theme
};
const utterances = document.querySelector(iframe).contentWindow;
const utterances = document.getElementsByClassName('utterances-frame')[0].contentWindow;
utterances.postMessage(message, origin);
});
});
})();
</script>

View File

@@ -0,0 +1,35 @@
{% assign src = include.src | strip %}
{% assign title = include.title | strip %}
{% assign types = include.types | default: '' | strip | split: '|' %}
{% unless src contains '://' %}
{%- capture src -%}
{% include media-url.html src=src subpath=page.media_subpath %}
{%- endcapture -%}
{% endunless %}
<p>
<audio class="embed-audio" controls>
{% assign extension = src | split: '.' | last %}
{% assign types = extension | concat: types %}
{% assign ext_size = extension | size %}
{% assign src_size = src | size %}
{% assign slice_size = src_size | minus: ext_size %}
{% assign filepath = src | slice: 0, slice_size %}
{% for type in types %}
{% assign src = filepath | append: type %}
{% assign media_item = site.data.media | find: 'extension', type %}
{% assign mime_type = media_item.mime_type | default: type %}
<source src="{{ src }}" type="audio/{{ mime_type }}">
{% endfor %}
Your browser does not support the audio tag. Here is a
<a href="{{ src | strip }}">link to the audio file</a> instead.
</audio>
{% if title %}
<em>{{ title }}</em>
{% endif %}
</p>

View 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>

View File

@@ -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: '/' }}"
frameborder="0" allowfullscreen="true"
scrolling="no"></iframe>
frameborder="0"
allowfullscreen="true"
scrolling="no"
></iframe>

View File

@@ -0,0 +1,59 @@
{% assign video_url = include.src %}
{% assign title = include.title %}
{% assign poster_url = include.poster %}
{% assign types = include.types | default: '' | strip | split: '|' %}
{% unless video_url contains '://' %}
{%- capture video_url -%}
{% include media-url.html src=video_url subpath=page.media_subpath %}
{%- endcapture -%}
{% endunless %}
{% if poster_url %}
{% unless poster_url contains '://' %}
{%- capture poster_url -%}
{% include media-url.html src=poster_url subpath=page.media_subpath %}
{%- endcapture -%}
{% endunless %}
{% assign poster = 'poster="' | append: poster_url | append: '"' %}
{% endif %}
{% assign attributes = 'controls' %}
{% if include.autoplay %}
{% assign attributes = attributes | append: ' ' | append: 'autoplay' %}
{% endif %}
{% if include.loop %}
{% assign attributes = attributes | append: ' ' | append: 'loop' %}
{% endif %}
{% if include.muted %}
{% assign attributes = attributes | append: ' ' | append: 'muted' %}
{% endif %}
<p>
<video class="embed-video file" {{ poster }} {{ attributes }}>
{% assign extension = video_url | split: '.' | last %}
{% assign types = extension | concat: types %}
{% assign ext_size = extension | size %}
{% assign src_size = video_url | size %}
{% assign slice_size = src_size | minus: ext_size %}
{% assign filepath = video_url | slice: 0, slice_size %}
{% for type in types %}
{% assign src = filepath | append: type %}
{% assign media_item = site.data.media | find: 'extension', type %}
{% assign mime_type = media_item.mime_type | default: type %}
<source src="{{ src }}" type="video/{{ mime_type }}">
{% endfor %}
Your browser does not support the video tag. Here is a
<a href="{{ video_url | strip }}">link to the video file</a> instead.
</video>
{% if title %}
<em>{{ title }}</em>
{% endif %}
</p>

View File

@@ -1,6 +1,9 @@
<iframe class="embed-video youtube lazyload"
<iframe
class="embed-video"
loading="lazy"
src="https://www.youtube.com/embed/{{ include.id }}"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen></iframe>
allowfullscreen
></iframe>

View File

@@ -8,7 +8,9 @@
<link rel="apple-touch-icon" sizes="180x180" href="{{ favicon_path }}/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="{{ favicon_path }}/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="{{ favicon_path }}/favicon-16x16.png">
<link rel="manifest" href="{{ favicon_path }}/site.webmanifest">
{% if site.pwa.enabled %}
<link rel="manifest" href="{{ favicon_path }}/site.webmanifest">
{% endif %}
<link rel="shortcut icon" href="{{ favicon_path }}/favicon.ico">
<meta name="apple-mobile-web-app-title" content="{{ site.title }}">
<meta name="application-name" content="{{ site.title }}">

View File

@@ -8,9 +8,15 @@
"
>
<p>
{{ '©' }}
{{- '©' }}
<time>{{ 'now' | date: '%Y' }}</time>
<a href="{{ site.social.links[0] }}">{{ site.social.name }}</a>.
{% if site.social.links %}
<a href="{{ site.social.links[0] }}">{{ site.social.name }}</a>.
{% else %}
<em class="fst-normal">{{ site.social.name }}</em>.
{% endif %}
{% if site.data.locales[include.lang].copyright.brief %}
<span
data-bs-toggle="tooltip"
@@ -28,7 +34,14 @@
{%- endcapture -%}
{%- capture _theme -%}
<a href="https://github.com/cotes2020/jekyll-theme-chirpy" target="_blank" rel="noopener">Chirpy</a>
<a
data-bs-toggle="tooltip"
data-bs-placement="top"
title="v{{ theme.version }}"
href="https://github.com/cotes2020/jekyll-theme-chirpy"
target="_blank"
rel="noopener"
>Chirpy</a>
{%- endcapture -%}
{{ site.data.locales[include.lang].meta | replace: ':PLATFORM', _platform | replace: ':THEME', _theme }}

View File

@@ -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>

View File

@@ -1,5 +1,3 @@
<!-- The Head -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="theme-color" media="(prefers-color-scheme: light)" content="#f7f7f7">
@@ -11,29 +9,43 @@
content="width=device-width, user-scalable=no initial-scale=1, shrink-to-fit=no, viewport-fit=cover"
>
{% capture seo_tags %}
{%- capture seo_tags -%}
{% seo title=false %}
{% endcapture %}
{%- endcapture -%}
<!-- Setup Open Graph image -->
{% if page.image %}
{% assign img = page.image.path | default: page.image %}
{% assign src = page.image.path | default: page.image %}
{% unless img contains '://' %}
{% assign img_path = page.img_path | append: '/' | append: img | replace: '//', '/' %}
{% capture target %}"{{ img | absolute_url }}"{% endcapture %}
{% unless src contains '://' %}
{%- capture img_url -%}
{% include media-url.html src=src subpath=page.media_subpath absolute=true %}
{%- endcapture -%}
{% if site.img_cdn contains '//' %}
<!-- it's a cross-origin URL -->
{% capture replacement %}"{{ site.img_cdn }}{{ img_path }}"{% endcapture %}
{% else %}
<!-- it's a local file path -->
{%- capture replacement -%}
"{{ site.img_cdn | append: '/' | append: img_path | replace: '//', '/' | absolute_url }}"
{%- endcapture -%}
{% endif %}
{%- capture old_url -%}{{ src | absolute_url }}{%- endcapture -%}
{%- capture new_url -%}{{ img_url }}{%- endcapture -%}
{% assign seo_tags = seo_tags | replace: target, replacement %}
{% assign seo_tags = seo_tags | replace: old_url, new_url %}
{% endunless %}
{% elsif site.social_preview_image %}
{%- capture img_url -%}
{% include media-url.html src=site.social_preview_image absolute=true %}
{%- endcapture -%}
{%- capture og_image -%}
<meta property="og:image" content="{{ img_url }}" />
{%- endcapture -%}
{%- capture twitter_image -%}
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:image" content="{{ img_url }}" />
{%- endcapture -%}
{% assign old_meta_clip = '<meta name="twitter:card" content="summary" />' %}
{% assign new_meta_clip = og_image | append: twitter_image %}
{% assign seo_tags = seo_tags | replace: old_meta_clip, new_meta_clip %}
{% endif %}
{{ seo_tags }}
@@ -47,42 +59,42 @@
{% include_cached favicons.html %}
{% if site.resources.ignore_env != jekyll.environment and site.resources.self_hosted %}
<link href="{{ site.data.origin[type].webfonts | relative_url }}" rel="stylesheet">
{% else %}
{% for cdn in site.data.origin[type].cdns %}
<link rel="preconnect" href="{{ cdn.url }}" {{ cdn.args }}>
<link rel="dns-prefetch" href="{{ cdn.url }}" {{ cdn.args }}>
<!-- Resource Hints -->
{% unless site.assets.self_host.enabled %}
{% for hint in site.data.origin.cors.resource_hints %}
{% for link in hint.links %}
<link rel="{{ link.rel }}" href="{{ hint.url }}" {{ link.opts | join: ' ' }}>
{% endfor %}
{% endfor %}
<link rel="stylesheet" href="{{ site.data.origin[type].webfonts | relative_url }}">
{% endif %}
<!-- GA -->
{% if jekyll.environment == 'production' and site.google_analytics.id != empty and site.google_analytics.id %}
<link rel="preconnect" href="https://www.google-analytics.com" crossorigin="use-credentials">
<link rel="dns-prefetch" href="https://www.google-analytics.com">
<link rel="preconnect" href="https://www.googletagmanager.com" crossorigin="anonymous">
<link rel="dns-prefetch" href="https://www.googletagmanager.com">
{% endif %}
{% endunless %}
<!-- Bootstrap -->
<link rel="stylesheet" href="{{ site.data.origin[type].bootstrap.css | relative_url}}">
{% unless jekyll.environment == 'production' %}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
{% endunless %}
<!-- Font Awesome -->
<!-- Theme style -->
<link rel="stylesheet" href="{{ '/assets/css/:THEME.css' | replace: ':THEME', site.theme | relative_url }}">
<!-- Web Font -->
<link rel="stylesheet" href="{{ site.data.origin[type].webfonts | relative_url }}">
<!-- Font Awesome Icons -->
<link rel="stylesheet" href="{{ site.data.origin[type].fontawesome.css | relative_url }}">
<link rel="stylesheet" href="{{ '/assets/css/:THEME.css' | replace: ':THEME', site.theme | relative_url }}">
<!-- 3rd-party Dependencies -->
{% if site.toc and page.toc %}
<link rel="stylesheet" href="{{ site.data.origin[type].toc.css | relative_url }}">
{% 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' %}
<!-- Manific Popup -->
<link rel="stylesheet" href="{{ site.data.origin[type].magnific-popup.css | relative_url }}">
<!-- Image Popup -->
<link rel="stylesheet" href="{{ site.data.origin[type].glightbox.css | relative_url }}">
{% endif %}
<!-- JavaScript -->

View File

@@ -2,23 +2,20 @@
<!-- commons -->
{% assign urls = site.data.origin[type].jquery.js
| append: ','
| append: site.data.origin[type].bootstrap.js
| append: ','
| append: site.data.origin[type].search.js
%}
{% assign urls = site.data.origin[type].search.js %}
<!-- layout specified -->
{% assign js_dist = '/assets/js/dist/' %}
{% 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' %}
<!-- image lazy-loading & popup & clipboard -->
{% assign urls = urls
| append: ','
| append: site.data.origin[type]['magnific-popup'].js
| append: site.data.origin[type].glightbox.js
| append: ','
| append: site.data.origin[type].clipboard.js
%}
@@ -31,7 +28,7 @@
or page.layout == 'category'
or page.layout == 'tag'
%}
{% assign locale = site.lang | split: '-' | first %}
{% assign locale = include.lang | split: '-' | first %}
{% assign urls = urls
| append: ','
@@ -65,42 +62,46 @@
{% assign js = 'commons' %}
{% endcase %}
{% capture script %}/assets/js/dist/{{ js }}.min.js{% endcapture %}
<script defer src="{{ script | relative_url }}"></script>
{% capture script %}{{ js_dist }}{{ js }}.min.js{% endcapture %}
<script src="{{ script | relative_url }}"></script>
{% if page.math %}
<!-- MathJax -->
<script>
/* see: <https://docs.mathjax.org/en/latest/options/input/tex.html#tex-options> */
MathJax = {
tex: {
/* start/end delimiter pairs for in-line math */
inlineMath: [
['$', '$'],
['\\(', '\\)']
],
/* start/end delimiter pairs for display math */
displayMath: [
['$$', '$$'],
['\\[', '\\]']
]
}
};
</script>
<script src="{{ site.data.origin[type].polyfill.js | relative_url }}"></script>
<script src="{{ '/assets/js/data/mathjax.js' | relative_url }}"></script>
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async src="{{ site.data.origin[type].mathjax.js | relative_url }}"></script>
{% endif %}
<!-- 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' %}
<!-- PWA -->
{% if site.pwa.enabled %}
<script defer src="{{ '/app.js' | relative_url }}"></script>
{% else %}
<script defer src="{{ '/unregister.js' | relative_url }}"></script>
<script defer src="{{ 'app.min.js' | prepend: js_dist | relative_url }}"></script>
{% endif %}
<!-- GA -->
{% if site.google_analytics.id != empty and site.google_analytics.id %}
{% include google-analytics.html %}
{% endif %}
<!-- Web Analytics -->
{% for analytics in site.analytics %}
{% 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 %}
{% endfor %}
{% endif %}

View File

@@ -1,7 +1,9 @@
{% comment %}
Detect appearance language and return it through variable "lang"
{% endcomment %}
{% if site.data.locales[site.lang] %}
{% if site.data.locales[page.lang] %}
{% assign lang = page.lang %}
{% elsif site.data.locales[site.lang] %}
{% assign lang = site.lang %}
{% else %}
{% assign lang = 'en' %}

37
_includes/media-url.html Normal file
View 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 -}}

View File

@@ -1,29 +1,33 @@
<!-- mermaid-js loader -->
<script type="text/javascript">
(function () {
function updateMermaid(event) {
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
const mode = event.data.message;
function updateMermaid(event) {
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
const mode = event.data.message;
if (typeof mermaid === 'undefined') {
return;
}
let expectedTheme = mode === ModeToggle.DARK_MODE ? 'dark' : 'default';
let config = { theme: expectedTheme };
/* Re-render the SVG <https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344> */
$('.mermaid').each(function () {
let svgCode = $(this).prev().children().html();
$(this).removeAttr('data-processed');
$(this).html(svgCode);
});
mermaid.initialize(config);
mermaid.init(undefined, '.mermaid');
if (typeof mermaid === 'undefined') {
return;
}
}
let expectedTheme = mode === ModeToggle.DARK_MODE ? 'dark' : 'default';
let config = { theme: expectedTheme };
{%- comment -%}
Re-render the SVG <https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344>
{%- endcomment -%}
const mermaidList = document.getElementsByClassName('mermaid');
[...mermaidList].forEach((elem) => {
const svgCode = elem.previousSibling.children.item(0).innerHTML;
elem.innerHTML = svgCode;
elem.removeAttribute('data-processed');
});
mermaid.initialize(config);
mermaid.init(undefined, '.mermaid');
}
}
(function () {
let initTheme = 'default';
const html = document.documentElement;
@@ -35,15 +39,16 @@
}
let mermaidConf = {
theme: initTheme /* <default|dark|forest|neutral> */
theme: initTheme {%- comment -%} <default | dark | forest | neutral> {%- endcomment -%}
};
/* Create mermaid tag */
document.querySelectorAll('pre>code.language-mermaid').forEach((elem) => {
{%- comment -%} Create mermaid tag {%- endcomment -%}
const basicList = document.getElementsByClassName('language-mermaid');
[...basicList].forEach((elem) => {
const svgCode = elem.textContent;
const backup = elem.parentElement;
backup.classList.add('unloaded');
/* create mermaid node */
backup.classList.add('d-none');
{%- comment -%} create mermaid node {%- endcomment -%}
let mermaid = document.createElement('pre');
mermaid.classList.add('mermaid');
const text = document.createTextNode(svgCode);
@@ -52,7 +57,6 @@
});
mermaid.initialize(mermaidConf);
window.addEventListener('message', updateMermaid);
})();
</script>

View File

@@ -19,45 +19,32 @@
}
constructor() {
if (this.hasMode) {
if (this.isDarkMode) {
if (!this.isSysDarkPrefer) {
this.setDark();
}
} else {
if (this.isSysDarkPrefer) {
this.setLight();
}
}
}
let self = this;
/* always follow the system prefers */
{%- comment -%} always follow the system prefers {%- endcomment -%}
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() */
if (!this.hasMode) {
return;
}
if (this.isDarkMode) {
this.setDark();
} else {
this.setLight();
}
}
get sysDarkPrefers() {
return window.matchMedia('(prefers-color-scheme: dark)');
}
get isSysDarkPrefer() {
get isPreferDark() {
return this.sysDarkPrefers.matches;
}
@@ -65,10 +52,6 @@
return this.mode === ModeToggle.DARK_MODE;
}
get isLightMode() {
return this.mode === ModeToggle.LIGHT_MODE;
}
get hasMode() {
return this.mode != null;
}
@@ -77,12 +60,12 @@
return sessionStorage.getItem(ModeToggle.MODE_KEY);
}
/* get the current mode on screen */
{%- comment -%} get the current mode on screen {%- endcomment -%}
get modeStatus() {
if (this.isDarkMode || (!this.hasMode && this.isSysDarkPrefer)) {
return ModeToggle.DARK_MODE;
if (this.hasMode) {
return this.mode;
} else {
return ModeToggle.LIGHT_MODE;
return this.isPreferDark ? ModeToggle.DARK_MODE : ModeToggle.LIGHT_MODE;
}
}
@@ -101,7 +84,9 @@
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() {
window.postMessage(
{
@@ -114,21 +99,9 @@
flipMode() {
if (this.hasMode) {
if (this.isSysDarkPrefer) {
if (this.isLightMode) {
this.clearMode();
} else {
this.setLight();
}
} else {
if (this.isDarkMode) {
this.clearMode();
} else {
this.setDark();
}
}
this.clearMode();
} else {
if (this.isSysDarkPrefer) {
if (this.isPreferDark) {
this.setLight();
} else {
this.setDark();
@@ -136,8 +109,8 @@
}
this.notify();
} /* flipMode() */
} /* ModeToggle */
}
}
const modeToggle = new ModeToggle();
</script>

View File

@@ -0,0 +1,19 @@
<!-- Display GoatCounter pageviews -->
<script>
let pv = document.getElementById('pageviews');
if (pv !== null) {
const uri = location.pathname.replace(/\/$/, '');
const url = `https://{{ site.analytics.goatcounter.id }}.goatcounter.com/counter/${encodeURIComponent(uri)}.json`;
fetch(url)
.then((response) => response.json())
.then((data) => {
const count = data.count.replace(/\s/g, '');
pv.innerText = new Intl.NumberFormat().format(count);
})
.catch((error) => {
pv.innerText = '1';
});
}
</script>

View 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 -}}

View File

@@ -1,23 +1,38 @@
<!-- Post sharing snippet -->
<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">
{% capture title %}{{ page.title }} - {{ site.title }}{% endcapture %}
{% assign title = title | uri_escape %}
{% assign url = page.url | absolute_url | url_encode %}
{% for share in site.data.share.platforms %}
{% for share in site.data.share.platforms -%}
{%- capture tooltip -%}
data-bs-toggle="tooltip" data-bs-placement="top" title="{{ share.type }}" aria-label="{{ share.type }}"
{%- endcapture -%}
{% if share.type == 'Mastodon' %}
<script defer type="module" src="https://cdn.jsdelivr.net/npm/@justinribeiro/share-to-mastodon/+esm"></script>
<button class="btn text-start" {{ tooltip }}>
<share-to-mastodon
class="share-mastodon"
message="{{ title }}"
url="{{ url }}"
{%- if share.instances -%}
customInstanceList="{{ share.instances | jsonify | xml_escape }}"
{%- endif %}
>
<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 }}"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="{{ share.type }}"
target="_blank"
rel="noopener"
aria-label="{{ share.type }}"
>
<a href="{{ link }}" target="_blank" rel="noopener" {{ tooltip }}>
<i class="fa-fw {{ share.icon }}"></i>
</a>
{% endfor %}
@@ -31,7 +46,7 @@
title="{{ site.data.locales[include.lang].post.button.share_link.title }}"
data-title-succeed="{{ site.data.locales[include.lang].post.button.share_link.succeed }}"
>
<i class="fa-fw fas fa-link pe-none"></i>
<i class="fa-fw fas fa-link pe-none fs-6"></i>
</button>
</span>
</div>

View File

@@ -30,41 +30,24 @@
{% endif %}
<!-- Change the icon of checkbox -->
{% if _content contains '<input type="checkbox"' %}
{% assign _content = _content
| replace:
'<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />',
'<i class="fas fa-check-circle fa-fw checked"></i>'
| replace:
'<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />',
'<i class="far fa-circle fa-fw"></i>'
| replace: '<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" checked="checked" />',
'<i class="fas fa-check-circle fa-fw checked"></i>'
| replace: '<input type="checkbox" class="task-list-item-checkbox" disabled="disabled" />',
'<i class="far fa-circle fa-fw"></i>'
%}
{% endif %}
<!-- images -->
<!-- Handle images -->
{% assign IMG_TAG = '<img ' %}
{% if _content contains IMG_TAG %}
{% assign _img_content = nil %}
{% assign _img_content = null %}
{% assign _img_snippets = _content | split: IMG_TAG %}
<!-- CDN URL -->
{% if site.img_cdn %}
{% if site.img_cdn contains '//' %}
{% assign _path_prefix = site.img_cdn %}
{% else %}
{% assign _path_prefix = site.img_cdn | relative_url %}
{% endif %}
{% else %}
{% assign _path_prefix = site.baseurl %}
{% endif %}
<!-- Add image path -->
{% if page.img_path %}
{% assign _path = page.img_path | append: '/' | replace: '//', '/' %}
{% assign _path_prefix = _path_prefix | append: _path %}
{% endif %}
{% for _img_snippet in _img_snippets %}
{% if forloop.first %}
{% assign _img_content = _img_snippet %}
@@ -81,10 +64,9 @@
{% assign _left = _left | remove: ' /' | replace: ' w=', ' width=' | replace: ' h=', ' height=' %}
{% assign _attrs = _left | split: '" ' %}
{% assign _width = nil %}
{% assign _height = nil %}
{% assign _lqip = nil %}
{% assign _class = nil %}
{% assign _src = null %}
{% assign _lqip = null %}
{% assign _class = null %}
{% for _attr in _attrs %}
{% unless _attr contains '=' %}
@@ -96,10 +78,6 @@
{% capture _value %}{{ _pair | last | remove: '"' }}{% endcapture %}
{% case _key %}
{% when 'width' %}
{% assign _width = _value %}
{% when 'height' %}
{% assign _height = _value %}
{% when 'src' %}
{% assign _src = _value %}
{% when 'lqip' %}
@@ -115,54 +93,46 @@
{% assign _left = _left | remove: _old_class %}
{% 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 '//' %}
{% assign _final_src = _path_prefix | append: _src %}
{% capture _src_from %}"{{ _src }}"{% endcapture %}
{% capture _src_to %}"{{ _final_src }}"{% endcapture %}
{% assign _left = _left | replace: _src_from, _src_to %}
{% assign _src_alt = 'src="' | append: _path_prefix %}
{% assign _left = _left | replace: 'src="', _src_alt %}
{% endunless %}
{% if _lqip %}
{% unless _lqip contains ':' %}
{% assign _final_lqip = _path_prefix | append: _lqip %}
{% capture _lqip_from %}"{{ _lqip }}"{% endcapture %}
{% capture _lqip_to %}"{{ _final_lqip }}"{% endcapture %}
{% assign _left = _left | replace: _lqip_from, _lqip_to %}
{% assign _lazyload = false %}
{% assign _class = _class | append: ' blur' %}
{% unless _lqip contains 'data:' %}
{% assign _lqip_alt = 'lqip="' | append: _path_prefix %}
{% assign _left = _left | replace: 'lqip="', _lqip_alt %}
{% endunless %}
{% endif %}
<!-- lazy-load images <https://github.com/aFarkas/lazysizes#readme> -->
{% assign _left = _left | replace: 'src=', 'data-src=' %}
{% if _left contains 'class=' %}
{% assign _left = _left | replace: 'class="', 'class="lazyload '%}
<!-- add image placeholder -->
{% assign _left = _left | replace: 'src=', 'data-src=' | replace: ' lqip=', ' data-lqip="true" src=' %}
{% else %}
{% assign _left = _left | append: ' class="lazyload"' %}
{% assign _class = _class | append: ' shimmer' %}
{% endif %}
<!-- add image placeholder -->
{% if _lqip %}
{% assign _left = _left | replace: ' lqip=', ' data-lqip="true" src=' %}
{% 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' %}
{% endif %}
<!-- lazy-load images -->
{% if _lazyload %}
{% assign _left = _left | append: ' loading="lazy"' %}
{% endif %}
<!-- Bypass the HTML-proofer test -->
{% assign _left = _left | append: ' data-proofer-ignore' %}
{% if page.layout == 'home' %}
<!-- create the image wrapper -->
{%- capture _wrapper_start -%}
<div class="preview-img {{ _class | strip }}">
{%- endcapture -%}
{% assign _wrapper_start = '<div class="preview-img ' | append: _class | append: '">' %}
{% assign _img_content = _img_content | append: _wrapper_start %}
{% assign _right = _right | prepend: '></div' %}
@@ -176,26 +146,30 @@
{% capture _class %}
class="img-link{% unless _lqip %} shimmer{% endunless %}"
{% endcapture %}
{% assign _img_content = _img_content | slice: 0, _size | append: _class | append: '>' %}
{% assign _img_content = _img_content | slice: 0, _size | append: _class | append: '>' %}
{% else %}
<!-- create the image wrapper -->
{%- capture _wrapper_start -%}
<a href="{{ _final_src | default: _src }}" class="popup img-link {{ _class }}">
{%- endcapture -%}
{% assign _wrapper_start = _final_src
| default: _src
| prepend: '<a href="'
| append: '" class="popup img-link '
| append: _class
| append: '">'
%}
{% assign _img_content = _img_content | append: _wrapper_start %}
{% assign _right = _right | prepend: '></a' %}
{% assign _right = '></a' | append: _right %}
{% endif %}
{% endif %}
<!-- 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 %}
{% if _img_content %}
{% assign _content = _img_content %}
{% endif %}
{% endif %}
<!-- Add header for code snippets -->
@@ -205,13 +179,11 @@
{% assign _new_content = '' %}
{% for _snippet in _code_spippets %}
{% if forloop.last %}
{% assign _new_content = _new_content | append: _snippet %}
{% else %}
{% assign _left = _snippet | split: '><' | last%}
{% assign _left = _snippet | split: '><' | last %}
{% if _left contains 'file="' %}
{% assign _label_text = _left | split: 'file="' | last | split: '"' | first %}
@@ -226,21 +198,19 @@
<span data-label-text="{{ _label_text | strip }}"><i class="{{ _label_icon }}"></i></span>
{% endcapture %}
{% assign _new_content = _new_content | append: _snippet
| append: '<div class="code-header">'
| append: _label
| append: '<button aria-label="copy" data-title-succeed="'
| append: site.data.locales[include.lang].post.button.copy_code.succeed
| append: '"><i class="far fa-clipboard"></i></button></div>'
| append: '<div class="highlight"><code>'
{% assign _new_content = _new_content
| append: _snippet
| append: '<div class="code-header">'
| append: _label
| append: '<button aria-label="copy" data-title-succeed="'
| append: site.data.locales[include.lang].post.button.copy_code.succeed
| append: '"><i class="far fa-clipboard"></i></button></div>'
| append: '<div class="highlight"><code>'
%}
{% endif %}
{% endfor %}
{% assign _content = _new_content %}
{% endif %}
<!-- Create heading anchors -->
@@ -249,11 +219,11 @@
{% assign _heading_content = _content %}
{% for level in heading_levels %}
{% capture mark_start %}<h{{ level }} id="{% endcapture %}
{% capture mark_end %}</h{{ level }}>{% endcapture %}
{% assign mark_start = '<h' | append: level | append: ' id="' %}
{% assign mark_end = '</h' | append: level | append: '>' %}
{% if _heading_content contains mark_start %}
{% assign _new_content = nil %}
{% assign _new_content = null %}
{% assign heading_snippets = _heading_content | split: mark_start %}
{% for snippet in heading_snippets %}
@@ -263,20 +233,19 @@
{% endif %}
{% 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 right = snippet | slice: left.size, snippet.size %}
{% assign left = left | replace_first: '">', '"><span class="me-2">' | append: '</span>' %}
{% assign _new_content = _new_content | append: mark_start
| append: left | append: anchor | append: right
%}
{% assign _new_content = _new_content | append: mark_start | append: left | append: anchor | append: right %}
{% endfor %}
{% assign _heading_content = _new_content %}
{% endif %}
{% endfor %}

View File

@@ -21,6 +21,7 @@
{% assign match_posts = match_posts | push: site.tags[tag] | uniq %}
{% endfor %}
{% assign match_posts = match_posts | reverse %}
{% assign last_index = match_posts.size | minus: 1 %}
{% assign score_list = '' | split: '' %}
@@ -78,13 +79,10 @@
<article class="col">
<a href="{{ post.url | relative_url }}" class="post-preview card h-100">
<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">{{ post.title }}</h4>
<div class="text-muted small">
<p>
{% include no-linenos.html content=post.content %}
{{ content | markdownify | strip_html | truncate: 200 | escape }}
</p>
<div class="text-muted">
<p>{% include post-description.html %}</p>
</div>
</div>
</a>

View File

@@ -19,7 +19,7 @@
{% capture not_found %}<p class="mt-5">{{ site.data.locales[include.lang].search.no_results }}</p>{% endcapture %}
<script>
/* Note: dependent library will be loaded in `js-selector.html` */
{%- comment -%} Note: dependent library will be loaded in `js-selector.html` {%- endcomment -%}
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('search-results'),

View File

@@ -1,6 +1,6 @@
<!-- The Search results -->
<div id="search-result-wrapper" class="d-flex justify-content-center unloaded">
<div id="search-result-wrapper" class="d-flex justify-content-center d-none">
<div class="col-11 content">
<div id="search-hints">
{% include_cached trending-tags.html %}

View File

@@ -3,18 +3,12 @@
<aside aria-label="Sidebar" id="sidebar" class="d-flex flex-column align-items-end">
<header class="profile-wrapper">
<a href="{{ '/' | relative_url }}" id="avatar" class="rounded-circle">
{% if site.avatar != empty and site.avatar %}
{% capture avatar_url %}
{% if site.avatar contains '://' %}
{{ site.avatar }}
{% elsif site.img_cdn != empty and site.img_cdn %}
{{ site.avatar | prepend: site.img_cdn }}
{% else %}
{{ site.avatar | relative_url }}
{% endif %}
{% endcapture %}
<img src="{{ avatar_url | strip }}" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
{% endif %}
{%- if site.avatar != empty and site.avatar -%}
{%- capture avatar_url -%}
{% include media-url.html src=site.avatar %}
{%- endcapture -%}
<img src="{{- avatar_url -}}" width="112" height="112" alt="avatar" onerror="this.style.display='none'">
{%- endif -%}
</a>
<h1 class="site-title">
@@ -50,7 +44,7 @@
<div class="sidebar-bottom d-flex flex-wrap align-items-center w-100">
{% unless site.theme_mode %}
<button type="button" class="mode-toggle btn" aria-label="Switch Mode">
<button type="button" class="btn btn-link nav-link" aria-label="Switch Mode" id="mode-toggle">
<i class="fas fa-adjust"></i>
</button>
@@ -59,48 +53,46 @@
{% endif %}
{% endunless %}
<address class="d-flex mb-0">
{% for entry in site.data.contact %}
{% case entry.type %}
{% when 'github', 'twitter' %}
{%- capture url -%}
{% for entry in site.data.contact %}
{% case entry.type %}
{% when 'github', 'twitter' %}
{%- capture url -%}
https://{{ entry.type }}.com/{{ site[entry.type].username }}
{%- endcapture -%}
{% when 'email' %}
{% assign email = site.social.email | split: '@' %}
{%- capture url -%}
{% when 'email' %}
{% assign email = site.social.email | split: '@' %}
{%- capture url -%}
javascript:location.href = 'mailto:' + ['{{ email[0] }}','{{ email[1] }}'].join('@')
{%- endcapture -%}
{% when 'rss' %}
{% assign url = '/feed.xml' | relative_url %}
{% else %}
{% assign url = entry.url %}
{% endcase %}
{% when 'rss' %}
{% assign url = '/feed.xml' | relative_url %}
{% else %}
{% assign url = entry.url %}
{% endcase %}
{% if url %}
<a
href="{{ url }}"
aria-label="{{ entry.type }}"
{% assign link_types = '' %}
{% if url %}
<a
href="{{ url }}"
aria-label="{{ entry.type }}"
{% assign link_types = '' %}
{% unless entry.noblank %}
target="_blank"
{% assign link_types = 'noopener noreferrer' %}
{% endunless %}
{% unless entry.noblank %}
target="_blank"
{% assign link_types = 'noopener noreferrer' %}
{% endunless %}
{% if entry.type == 'mastodon' %}
{% assign link_types = link_types | append: ' me' | strip %}
{% endif %}
{% if entry.type == 'mastodon' %}
{% assign link_types = link_types | append: ' me' | strip %}
{% endif %}
{% unless link_types == empty %}
rel="{{ link_types }}"
{% endunless %}
>
<i class="{{ entry.icon }}"></i>
</a>
{% endif %}
{% endfor %}
</address>
{% unless link_types == empty %}
rel="{{ link_types }}"
{% endunless %}
>
<i class="{{ entry.icon }}"></i>
</a>
{% endif %}
{% endfor %}
</div>
<!-- .sidebar-bottom -->
</aside>

View File

@@ -6,8 +6,8 @@
{% endif %}
{% if enable_toc %}
<section id="toc-wrapper" class="ps-0 pe-4 mb-5">
<h2 class="panel-heading ps-3 pt-2 mb-2">{{- site.data.locales[include.lang].panel.toc -}}</h2>
<section id="toc-wrapper" class="d-none ps-0 pe-4">
<h2 class="panel-heading ps-3 mb-2">{{- site.data.locales[include.lang].panel.toc -}}</h2>
<nav id="toc"></nav>
</section>
{% endif %}

View File

@@ -17,7 +17,7 @@
{% if forloop.first %}
<span>
<a href="{{ '/' | relative_url }}">
{{ site.data.locales[include.lang].tabs.home | capitalize }}
{{- site.data.locales[include.lang].tabs.home | capitalize -}}
</a>
</span>
@@ -30,8 +30,8 @@
{% elsif page.layout == 'category' or page.layout == 'tag' %}
<span>
<a href="{{ item | relative_url }}">
{{ site.data.locales[include.lang].tabs[item] | default: page.title }}
<a href="{{ item | append: '/' | relative_url }}">
{{- site.data.locales[include.lang].tabs[item] | default: page.title -}}
</a>
</span>
{% endif %}
@@ -59,7 +59,7 @@
<i class="fas fa-search fa-fw"></i>
</button>
<search class="align-items-center ms-3 ms-lg-0">
<search id="search" class="align-items-center ms-3 ms-lg-0">
<i class="fas fa-search fa-fw"></i>
<input
class="form-control"

View File

@@ -1,16 +1,17 @@
<!-- Get the last 5 posts from lastmod list. -->
<!-- Get 5 last posted/updated posts -->
{% assign MAX_SIZE = 5 %}
{% assign all_list = '' | split: '' %}
{% for post in site.posts %}
{% if post.last_modified_at and post.last_modified_at != post.date %}
{% capture elem %}
{{- post.last_modified_at | date: "%Y%m%d%H%M%S" -}}::{{- forloop.index0 -}}
{% endcapture %}
{% assign all_list = all_list | push: elem %}
{% endif %}
{% assign datetime = post.last_modified_at | default: post.date %}
{% capture elem %}
{{- datetime | date: "%Y%m%d%H%M%S" -}}::{{- forloop.index0 -}}
{% endcapture %}
{% assign all_list = all_list | push: elem %}
{% endfor %}
{% assign all_list = all_list | sort | reverse %}

View File

@@ -1,5 +1,5 @@
import { basic, initSidebar, initTopbar } from './modules/layouts';
basic();
initSidebar();
initTopbar();
basic();

View File

@@ -1,8 +1,8 @@
import { basic, initSidebar, initTopbar } from './modules/layouts';
import { initLocaleDatetime, imgLazy } from './modules/plugins';
import { initLocaleDatetime, loadImg } from './modules/plugins';
basic();
loadImg();
initLocaleDatetime();
initSidebar();
initTopbar();
initLocaleDatetime();
imgLazy();
basic();

View File

@@ -1,7 +1,7 @@
import { basic, initSidebar, initTopbar } from './modules/layouts';
import { initLocaleDatetime } from './modules/plugins';
basic();
initSidebar();
initTopbar();
initLocaleDatetime();
basic();

View File

@@ -3,18 +3,17 @@
*/
export function back2top() {
const $window = $(window);
const $btn = $('#back-to-top');
const btn = document.getElementById('back-to-top');
$window.on('scroll', () => {
if ($window.scrollTop() > 50) {
$btn.fadeIn();
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
btn.classList.add('show');
} else {
$btn.fadeOut();
btn.classList.remove('show');
}
});
$btn.on('click', () => {
$window.scrollTop(0);
btn.addEventListener('click', () => {
window.scrollTo({ top: 0 });
});
}

View File

@@ -1,36 +1,36 @@
/**
* Tab 'Categories' expand/close effect.
*/
import 'bootstrap/js/src/collapse.js';
const childPrefix = 'l_';
const parentPrefix = 'h_';
const collapse = $('.collapse');
const children = document.getElementsByClassName('collapse');
export function categoryCollapse() {
/* close up top-category */
collapse.on('hide.bs.collapse', function () {
/* Bootstrap collapse events. */ const parentId =
parentPrefix + $(this).attr('id').substring(childPrefix.length);
if (parentId) {
$(`#${parentId} .far.fa-folder-open`).attr(
'class',
'far fa-folder fa-fw'
);
$(`#${parentId} i.fas`).addClass('rotate');
$(`#${parentId}`).removeClass('hide-border-bottom');
}
});
[...children].forEach((elem) => {
const id = parentPrefix + elem.id.substring(childPrefix.length);
const parent = document.getElementById(id);
/* expand the top category */
collapse.on('show.bs.collapse', function () {
const parentId =
parentPrefix + $(this).attr('id').substring(childPrefix.length);
if (parentId) {
$(`#${parentId} .far.fa-folder`).attr(
'class',
'far fa-folder-open fa-fw'
);
$(`#${parentId} i.fas`).removeClass('rotate');
$(`#${parentId}`).addClass('hide-border-bottom');
}
// collapse sub-categories
elem.addEventListener('hide.bs.collapse', () => {
if (parent) {
parent.querySelector('.far.fa-folder-open').className =
'far fa-folder fa-fw';
parent.querySelector('.fas.fa-angle-down').classList.add('rotate');
parent.classList.remove('hide-border-bottom');
}
});
// expand sub-categories
elem.addEventListener('show.bs.collapse', () => {
if (parent) {
parent.querySelector('.far.fa-folder').className =
'far fa-folder-open fa-fw';
parent.querySelector('.fas.fa-angle-down').classList.remove('rotate');
parent.classList.add('hide-border-bottom');
}
});
});
}

View File

@@ -2,107 +2,113 @@
* Clipboard functions
*
* Dependencies:
* - popper.js (https://github.com/popperjs/popper-core)
* - clipboard.js (https://github.com/zenorocha/clipboard.js)
* clipboard.js (https://github.com/zenorocha/clipboard.js)
*/
import Tooltip from 'bootstrap/js/src/tooltip';
const clipboardSelector = '.code-header>button';
const ICON_DEFAULT = 'far fa-clipboard';
const ICON_SUCCESS = 'fas fa-check';
const ATTR_TIMEOUT = 'timeout';
const ATTR_TITLE_SUCCEED = 'data-title-succeed';
const ATTR_TITLE_ORIGIN = 'data-bs-original-title';
const TIMEOUT = 2000; // in milliseconds
function isLocked(node) {
if ($(node)[0].hasAttribute(ATTR_TIMEOUT)) {
let timeout = $(node).attr(ATTR_TIMEOUT);
if (node.hasAttribute(ATTR_TIMEOUT)) {
let timeout = node.getAttribute(ATTR_TIMEOUT);
if (Number(timeout) > Date.now()) {
return true;
}
}
return false;
}
function lock(node) {
$(node).attr(ATTR_TIMEOUT, Date.now() + TIMEOUT);
node.setAttribute(ATTR_TIMEOUT, Date.now() + TIMEOUT);
}
function unlock(node) {
$(node).removeAttr(ATTR_TIMEOUT);
node.removeAttribute(ATTR_TIMEOUT);
}
function getIcon(btn) {
let iconNode = $(btn).children();
return iconNode.attr('class');
}
const ICON_DEFAULT = getIcon(clipboardSelector);
function showTooltip(btn) {
const succeedTitle = $(btn).attr(ATTR_TITLE_SUCCEED);
$(btn).attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show');
const succeedTitle = btn.getAttribute(ATTR_TITLE_SUCCEED);
btn.setAttribute(ATTR_TITLE_ORIGIN, succeedTitle);
Tooltip.getInstance(btn).show();
}
function hideTooltip(btn) {
$(btn).tooltip('hide').removeAttr(ATTR_TITLE_ORIGIN);
Tooltip.getInstance(btn).hide();
btn.removeAttribute(ATTR_TITLE_ORIGIN);
}
function setSuccessIcon(btn) {
let btnNode = $(btn);
let iconNode = btnNode.children();
iconNode.attr('class', ICON_SUCCESS);
const icon = btn.children[0];
icon.setAttribute('class', ICON_SUCCESS);
}
function resumeIcon(btn) {
let btnNode = $(btn);
let iconNode = btnNode.children();
iconNode.attr('class', ICON_DEFAULT);
const icon = btn.children[0];
icon.setAttribute('class', ICON_DEFAULT);
}
export function initClipboard() {
// Initial the clipboard.js object
if ($(clipboardSelector).length) {
const clipboard = new ClipboardJS(clipboardSelector, {
target(trigger) {
let codeBlock = trigger.parentNode.nextElementSibling;
return codeBlock.querySelector('code .rouge-code');
}
});
function setCodeClipboard() {
const clipboardList = document.querySelectorAll(clipboardSelector);
const clipboardList = document.querySelectorAll(clipboardSelector);
[...clipboardList].map(
(elem) =>
new bootstrap.Tooltip(elem, {
placement: 'left'
})
);
clipboard.on('success', (e) => {
e.clearSelection();
const trigger = e.trigger;
if (isLocked(trigger)) {
return;
}
setSuccessIcon(trigger);
showTooltip(trigger);
lock(trigger);
setTimeout(() => {
hideTooltip(trigger);
resumeIcon(trigger);
unlock(trigger);
}, TIMEOUT);
});
if (clipboardList.length === 0) {
return;
}
/* --- Post link sharing --- */
// Initial the clipboard.js object
const clipboard = new ClipboardJS(clipboardSelector, {
target: (trigger) => {
const codeBlock = trigger.parentNode.nextElementSibling;
return codeBlock.querySelector('code .rouge-code');
}
});
const btnCopyLink = $('#copy-link');
[...clipboardList].map(
(elem) =>
new Tooltip(elem, {
placement: 'left'
})
);
btnCopyLink.on('click', (e) => {
let target = $(e.target);
clipboard.on('success', (e) => {
const trigger = e.trigger;
e.clearSelection();
if (isLocked(trigger)) {
return;
}
setSuccessIcon(trigger);
showTooltip(trigger);
lock(trigger);
setTimeout(() => {
hideTooltip(trigger);
resumeIcon(trigger);
unlock(trigger);
}, TIMEOUT);
});
}
function setLinkClipboard() {
const btnCopyLink = document.getElementById('copy-link');
if (btnCopyLink === null) {
return;
}
btnCopyLink.addEventListener('click', (e) => {
const target = e.target;
if (isLocked(target)) {
return;
@@ -110,22 +116,28 @@ export function initClipboard() {
// Copy URL to clipboard
navigator.clipboard.writeText(window.location.href).then(() => {
const defaultTitle = target.attr(ATTR_TITLE_ORIGIN);
const succeedTitle = target.attr(ATTR_TITLE_SUCCEED);
const defaultTitle = target.getAttribute(ATTR_TITLE_ORIGIN);
const succeedTitle = target.getAttribute(ATTR_TITLE_SUCCEED);
// Switch tooltip title
target.attr(ATTR_TITLE_ORIGIN, succeedTitle).tooltip('show');
target.setAttribute(ATTR_TITLE_ORIGIN, succeedTitle);
Tooltip.getInstance(target).show();
lock(target);
setTimeout(() => {
target.attr(ATTR_TITLE_ORIGIN, defaultTitle);
target.setAttribute(ATTR_TITLE_ORIGIN, defaultTitle);
unlock(target);
}, TIMEOUT);
});
});
btnCopyLink.on('mouseleave', function (e) {
const target = $(e.target);
target.tooltip('hide');
console.log('mouse leave...');
btnCopyLink.addEventListener('mouseleave', (e) => {
Tooltip.getInstance(e.target).hide();
});
}
export function initClipboard() {
setCodeClipboard();
setLinkClipboard();
}

View File

@@ -1,27 +0,0 @@
/**
* Set up image lazy-load
*/
function stopShimmer($node) {
$node.parent().removeClass('shimmer');
}
export function imgLazy() {
const $images = $('main img[data-src]');
if ($images.length <= 0) {
return;
}
/* Stop shimmer when image loaded */
document.addEventListener('lazyloaded', function (e) {
stopShimmer($(e.target));
});
/* Stop shimmer from cached images */
$images.each(function () {
if ($(this).hasClass('ls-is-cached')) {
stopShimmer($(this));
}
});
}

View 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);
});
}
}

View File

@@ -1,22 +1,15 @@
/**
* 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() {
if ($('.popup') <= 0) {
if (document.getElementsByClassName(IMG_CLASS).length === 0) {
return;
}
$('.popup').magnificPopup({
type: 'image',
closeOnContentClick: true,
showCloseBtn: false,
zoom: {
enabled: true,
duration: 300,
easing: 'ease-in-out'
}
});
GLightbox({ selector: `.${IMG_CLASS}` });
}

View File

@@ -15,15 +15,15 @@ class LocaleHelper {
}
static get locale() {
return $('html').attr('lang').substring(0, 2);
return document.documentElement.getAttribute('lang').substring(0, 2);
}
static getTimestamp(elem) {
return Number(elem.attr(LocaleHelper.attrTimestamp)); // unix timestamp
return Number(elem.getAttribute(this.attrTimestamp)); // unix timestamp
}
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.extend(window.dayjs_plugin_localizedFormat);
$(`[${LocaleHelper.attrTimestamp}]`).each(function () {
const date = dayjs.unix(LocaleHelper.getTimestamp($(this)));
const text = date.format(LocaleHelper.getDateFormat($(this)));
$(this).text(text);
$(this).removeAttr(LocaleHelper.attrTimestamp);
$(this).removeAttr(LocaleHelper.attrDateFormat);
document
.querySelectorAll(`[${LocaleHelper.attrTimestamp}]`)
.forEach((elem) => {
const date = dayjs.unix(LocaleHelper.getTimestamp(elem));
const text = date.format(LocaleHelper.getDateFormat(elem));
elem.textContent = text;
elem.removeAttribute(LocaleHelper.attrTimestamp);
elem.removeAttribute(LocaleHelper.attrDateFormat);
// setup tooltips
const tooltip = $(this).attr('data-bs-toggle');
if (typeof tooltip === 'undefined' || tooltip !== 'tooltip') {
return;
}
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));
});
// setup tooltips
if (
elem.hasAttribute('data-bs-toggle') &&
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);
}
});
}

View File

@@ -1,21 +1,14 @@
/**
* Add listener for theme mode toggle
*/
const $toggleElem = $('.mode-toggle');
const toggle = document.getElementById('mode-toggle');
export function modeWatcher() {
if ($toggleElem.length === 0) {
if (!toggle) {
return;
}
$toggleElem.off().on('click', (e) => {
const $target = $(e.target);
let $btn =
$target.prop('tagName') === 'button'.toUpperCase()
? $target
: $target.parent();
modeToggle.flipMode(); // modeToggle: `_includes/mode-toggle.html`
$btn.trigger('blur'); // remove the clicking outline
toggle.addEventListener('click', () => {
modeToggle.flipMode();
});
}

View File

@@ -1,121 +1,109 @@
/**
* 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-wrapper>.container>.row');
const $topbarTitle = $('#topbar-title');
const $search = $('search');
const $resultWrapper = $('#search-result-wrapper');
const $results = $('#search-results');
const $input = $('#search-input');
const $hints = $('#search-hints');
const $viewport = $('html,body');
// class names
const C_LOADED = 'loaded';
const C_UNLOADED = 'unloaded';
const C_FOCUS = 'input-focus';
const C_FLEX = 'd-flex';
const btnSbTrigger = document.getElementById('sidebar-trigger');
const btnSearchTrigger = document.getElementById('search-trigger');
const btnCancel = document.getElementById('search-cancel');
const content = document.querySelectorAll('#main-wrapper>.container>.row');
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 {
static offset = 0;
static resultVisible = false;
// CSS class names
const LOADED = 'd-block';
const UNLOADED = 'd-none';
const FOCUS = 'input-focus';
const FLEX = 'd-flex';
static on() {
ScrollBlocker.offset = window.scrollY;
$viewport.scrollTop(0);
}
static off() {
$viewport.scrollTop(ScrollBlocker.offset);
}
}
/*--- Actions in mobile screens (Sidebar hidden) ---*/
/* Actions in mobile screens (Sidebar hidden) */
class MobileSearchBar {
static on() {
$btnSbTrigger.addClass(C_UNLOADED);
$topbarTitle.addClass(C_UNLOADED);
$btnSearchTrigger.addClass(C_UNLOADED);
$search.addClass(C_FLEX);
$btnCancel.addClass(C_LOADED);
btnSbTrigger.classList.add(UNLOADED);
topbarTitle.classList.add(UNLOADED);
btnSearchTrigger.classList.add(UNLOADED);
search.classList.add(FLEX);
btnCancel.classList.add(LOADED);
}
static off() {
$btnCancel.removeClass(C_LOADED);
$search.removeClass(C_FLEX);
$btnSbTrigger.removeClass(C_UNLOADED);
$topbarTitle.removeClass(C_UNLOADED);
$btnSearchTrigger.removeClass(C_UNLOADED);
btnCancel.classList.remove(LOADED);
search.classList.remove(FLEX);
btnSbTrigger.classList.remove(UNLOADED);
topbarTitle.classList.remove(UNLOADED);
btnSearchTrigger.classList.remove(UNLOADED);
}
}
class ResultSwitch {
static resultVisible = false;
static on() {
if (!ScrollBlocker.resultVisible) {
// the block method must be called before $(#main-wrapper>.container) unloaded.
ScrollBlocker.on();
$resultWrapper.removeClass(C_UNLOADED);
$content.addClass(C_UNLOADED);
ScrollBlocker.resultVisible = true;
if (!this.resultVisible) {
resultWrapper.classList.remove(UNLOADED);
content.forEach((el) => {
el.classList.add(UNLOADED);
});
this.resultVisible = true;
}
}
static off() {
if (ScrollBlocker.resultVisible) {
$results.empty();
if ($hints.hasClass(C_UNLOADED)) {
$hints.removeClass(C_UNLOADED);
if (this.resultVisible) {
results.innerHTML = '';
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-wrapper>.container) display
ScrollBlocker.off();
$input.val('');
ScrollBlocker.resultVisible = false;
resultWrapper.classList.add(UNLOADED);
content.forEach((el) => {
el.classList.remove(UNLOADED);
});
input.textContent = '';
this.resultVisible = false;
}
}
}
function isMobileView() {
return $btnCancel.hasClass(C_LOADED);
return btnCancel.classList.contains(LOADED);
}
export function displaySearch() {
$btnSearchTrigger.on('click', function () {
btnSearchTrigger.addEventListener('click', () => {
MobileSearchBar.on();
ResultSwitch.on();
$input.trigger('focus');
input.focus();
});
$btnCancel.on('click', function () {
btnCancel.addEventListener('click', () => {
MobileSearchBar.off();
ResultSwitch.off();
});
$input.on('focus', function () {
$search.addClass(C_FOCUS);
input.addEventListener('focus', () => {
search.classList.add(FOCUS);
});
$input.on('focusout', function () {
$search.removeClass(C_FOCUS);
input.addEventListener('focusout', () => {
search.classList.remove(FOCUS);
});
$input.on('input', () => {
if ($input.val() === '') {
input.addEventListener('input', () => {
if (input.value === '') {
if (isMobileView()) {
$hints.removeClass(C_UNLOADED);
hints.classList.remove(UNLOADED);
} else {
ResultSwitch.off();
}
} else {
ResultSwitch.on();
if (isMobileView()) {
$hints.addClass(C_UNLOADED);
hints.classList.add(UNLOADED);
}
}
});

View File

@@ -2,7 +2,6 @@
* Expand or close the sidebar in mobile screens.
*/
const $body = $('body');
const ATTR_DISPLAY = 'sidebar-display';
class SidebarUtil {
@@ -10,9 +9,9 @@ class SidebarUtil {
static toggle() {
if (SidebarUtil.isExpanded === false) {
$body.attr(ATTR_DISPLAY, '');
document.body.setAttribute(ATTR_DISPLAY, '');
} else {
$body.removeAttr(ATTR_DISPLAY);
document.body.removeAttribute(ATTR_DISPLAY);
}
SidebarUtil.isExpanded = !SidebarUtil.isExpanded;
@@ -20,6 +19,9 @@ class SidebarUtil {
}
export function sidebarExpand() {
$('#sidebar-trigger').on('click', SidebarUtil.toggle);
$('#mask').on('click', SidebarUtil.toggle);
document
.getElementById('sidebar-trigger')
.addEventListener('click', SidebarUtil.toggle);
document.getElementById('mask').addEventListener('click', SidebarUtil.toggle);
}

View File

@@ -1,5 +1,5 @@
export function toc() {
if (document.querySelector('main h2')) {
if (document.querySelector('main h2, main h3')) {
// see: https://github.com/tscanlin/tocbot#usage
tocbot.init({
tocSelector: '#toc',
@@ -9,5 +9,7 @@ export function toc() {
orderedList: false,
scrollSmooth: false
});
document.getElementById('toc-wrapper').classList.remove('d-none');
}
}

View File

@@ -1,12 +1,11 @@
/**
* Initial Bootstrap Tooltip.
*/
import Tooltip from 'bootstrap/js/src/tooltip';
export function loadTooptip() {
const tooltipTriggerList = document.querySelectorAll(
'[data-bs-toggle="tooltip"]'
);
[...tooltipTriggerList].map(
(tooltipTriggerEl) => new bootstrap.Tooltip(tooltipTriggerEl)
(tooltipTriggerEl) => new Tooltip(tooltipTriggerEl)
);
}

View File

@@ -1,6 +1,6 @@
export { categoryCollapse } from './components/category-collapse';
export { initClipboard } from './components/clipboard';
export { imgLazy } from './components/img-lazyload';
export { loadImg } from './components/img-loading';
export { imgPopup } from './components/img-popup';
export { initLocaleDatetime } from './components/locale-datetime';
export { toc } from './components/toc';

View File

@@ -1,9 +1,9 @@
import { basic, initSidebar, initTopbar } from './modules/layouts';
import { imgLazy, imgPopup, initClipboard } from './modules/plugins';
import { loadImg, imgPopup, initClipboard } from './modules/plugins';
basic();
loadImg();
imgPopup();
initSidebar();
initTopbar();
imgLazy();
imgPopup();
initClipboard();
basic();

View File

@@ -1,17 +1,17 @@
import { basic, initSidebar, initTopbar } from './modules/layouts';
import {
imgLazy,
loadImg,
imgPopup,
initLocaleDatetime,
initClipboard,
toc
} from './modules/plugins';
basic();
initSidebar();
initTopbar();
imgLazy();
loadImg();
toc();
imgPopup();
initSidebar();
initLocaleDatetime();
initClipboard();
toc();
initTopbar();
basic();

View File

@@ -0,0 +1,3 @@
---
permalink: /:basename
---

51
_javascript/pwa/app.js Normal file
View File

@@ -0,0 +1,51 @@
import { pwa, baseurl } from '../../_config.yml';
import Toast from 'bootstrap/js/src/toast';
if ('serviceWorker' in navigator) {
if (pwa.enabled) {
const swUrl = `${baseurl}/sw.min.js`;
const notification = document.getElementById('notification');
const btnRefresh = notification.querySelector('.toast-body>button');
const popupWindow = Toast.getOrCreateInstance(notification);
navigator.serviceWorker.register(swUrl).then((registration) => {
// In case the user ignores the notification
if (registration.waiting) {
popupWindow.show();
}
registration.addEventListener('updatefound', () => {
registration.installing.addEventListener('statechange', () => {
if (registration.waiting) {
if (navigator.serviceWorker.controller) {
popupWindow.show();
}
}
});
});
btnRefresh.addEventListener('click', () => {
if (registration.waiting) {
registration.waiting.postMessage('SKIP_WAITING');
}
popupWindow.hide();
});
});
let refreshing = false;
// Detect controller change and refresh all the opened tabs
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (!refreshing) {
window.location.reload();
refreshing = true;
}
});
} else {
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) {
registration.unregister();
}
});
}
}

82
_javascript/pwa/sw.js Normal file
View File

@@ -0,0 +1,82 @@
import { baseurl } from '../../_config.yml';
importScripts(`${baseurl}/assets/js/data/swconf.js`);
const purge = swconf.purge;
function verifyUrl(url) {
const requestPath = new URL(url).pathname;
for (const path of swconf.denyPaths) {
if (requestPath.startsWith(path)) {
return false;
}
}
return true;
}
self.addEventListener('install', (event) => {
if (purge) {
return;
}
event.waitUntil(
caches.open(swconf.cacheName).then((cache) => {
return cache.addAll(swconf.resources);
})
);
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keyList) => {
return Promise.all(
keyList.map((key) => {
if (purge) {
return caches.delete(key);
} else {
if (key !== swconf.cacheName) {
return caches.delete(key);
}
}
})
);
})
);
});
self.addEventListener('message', (event) => {
if (event.data === 'SKIP_WAITING') {
self.skipWaiting();
}
});
self.addEventListener('fetch', (event) => {
if (event.request.headers.has('range')) {
return;
}
event.respondWith(
caches.match(event.request).then((response) => {
if (response) {
return response;
}
return fetch(event.request).then((response) => {
const url = event.request.url;
if (purge || event.request.method !== 'GET' || !verifyUrl(url)) {
return response;
}
// See: <https://developers.google.com/web/fundamentals/primers/service-workers#cache_and_return_requests>
let responseToCache = response.clone();
caches.open(swconf.cacheName).then((cache) => {
cache.put(event.request, responseToCache);
});
return response;
});
})
);
});

View File

@@ -1,10 +1,10 @@
---
# Jekyll layout that compresses HTML
# v3.1.0
# v3.2.0
# http://jch.penibelst.de/
# © 20142015 Anatol Broder
# MIT License
---
{% capture _LINE_FEED %}
{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}</{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "<!-- -->" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "<pre" %}{% assign _content = "" %}{% for _pre_before in _pre_befores %}{% assign _pres = _pre_before | split: "</pre>" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "</pre>" %}<pre{{ _pres.first }}</pre>{% endif %}{% unless _pre_before contains "</pre>" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " <e;<e; </e>;</e>;</e> ;</e>" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %} <table id="compress_html_profile_{{ site.time | date: "%Y%m%d" }}" class="compress_html_profile"> <thead> <tr> <td>Step <td>Bytes <tbody> <tr> <td>raw <td>{{ content | size }}{% if _profile_endings %} <tr> <td>endings <td>{{ _profile_endings }}{% endif %}{% if _profile_startings %} <tr> <td>startings <td>{{ _profile_startings }}{% endif %}{% if _profile_comments %} <tr> <td>comments <td>{{ _profile_comments }}{% endif %}{% if _profile_collapse %} <tr> <td>collapse <td>{{ _profile_collapse }}{% endif %}{% if _profile_clippings %} <tr> <td>clippings <td>{{ _profile_clippings }}{% endif %} </table>{% endif %}{% endif %}
{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" or page.compress_html == false %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}</{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "<!-- -->" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "<pre" %}{% assign _content = "" %}{% for _pre_before in _pre_befores %}{% assign _pres = _pre_before | split: "</pre>" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "</pre>" %}<pre{{ _pres.first }}</pre>{% endif %}{% unless _pre_before contains "</pre>" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " <e;<e; </e>;</e>;</e> ;</e>" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %} <table id="compress_html_profile_{{ site.time | date: "%Y%m%d" }}" class="compress_html_profile"> <thead> <tr> <td>Step <td>Bytes <tbody> <tr> <td>raw <td>{{ content | size }}{% if _profile_endings %} <tr> <td>endings <td>{{ _profile_endings }}{% endif %}{% if _profile_startings %} <tr> <td>startings <td>{{ _profile_startings }}{% endif %}{% if _profile_comments %} <tr> <td>comments <td>{{ _profile_comments }}{% endif %}{% if _profile_collapse %} <tr> <td>collapse <td>{{ _profile_collapse }}{% endif %}{% if _profile_clippings %} <tr> <td>clippings <td>{{ _profile_clippings }}{% endif %} </table>{% endif %}{% endif %}

View File

@@ -1,6 +1,5 @@
---
layout: compress
# Default layout
---
<!doctype html>
@@ -9,37 +8,32 @@ layout: compress
{% include lang.html %}
{% capture prefer_mode %}
{% if site.theme_mode %}
data-mode="{{ site.theme_mode }}"
{% endif %}
{% endcapture %}
{% if layout.tail_includes %}
{% assign has_tail = true %}
{% if site.theme_mode %}
{% capture prefer_mode %}data-mode="{{ site.theme_mode }}"{% endcapture %}
{% endif %}
<!-- `site.alt_lang` can specify a language different from the UI -->
<html lang="{{ site.alt_lang | default: site.lang }}" {{ prefer_mode }}>
<html lang="{{ page.lang | default: site.alt_lang | default: site.lang }}" {{ prefer_mode }}>
{% include head.html %}
<body>
{% include sidebar.html lang=lang %}
<div id="main-wrapper" class="d-flex justify-content-center">
<div class="container px-xxl-5">
<div class="container d-flex flex-column px-xxl-5">
{% include topbar.html lang=lang %}
<div class="row">
<main
aria-label="Main Content"
class="col-12 col-lg-11 col-xl-9 px-md-4{% unless has_tail %} pb-5{% endunless %}"
>
{{ content }}
<div class="row flex-grow-1">
<main aria-label="Main Content" class="col-12 col-lg-11 col-xl-9 px-md-4">
{% if layout.refactor or layout.layout == 'default' %}
{% include refactor-content.html content=content lang=lang %}
{% else %}
{{ content }}
{% endif %}
</main>
<!-- panel -->
<aside aria-label="Panel" id="panel-wrapper" class="col-xl-3 ps-2 text-muted">
<aside aria-label="Panel" id="panel-wrapper" class="col-xl-3 ps-2 mb-5 text-muted">
<div class="access">
{% include_cached update-list.html lang=lang %}
{% include_cached trending-tags.html lang=lang %}
@@ -55,12 +49,10 @@ layout: compress
<div class="row">
<!-- tail -->
<div id="tail-wrapper" class="col-12 col-lg-11 col-xl-9 px-md-4">
{% if has_tail %}
{% for _include in layout.tail_includes %}
{% assign _include_path = _include | append: '.html' %}
{% include {{ _include_path }} lang=lang %}
{% endfor %}
{% endif %}
{% for _include in layout.tail_includes %}
{% assign _include_path = _include | append: '.html' %}
{% include {{ _include_path }} lang=lang %}
{% endfor %}
{% include_cached footer.html lang=lang %}
</div>
@@ -83,13 +75,8 @@ layout: compress
{% endif %}
<!-- JavaScripts -->
{% include js-selector.html lang=lang %}
{% include js-selector.html %}
{% if page.mermaid %}
{% include mermaid.html %}
{% endif %}
{% include_cached search-loader.html %}
{% include_cached search-loader.html lang=lang %}
</body>
</html>

View File

@@ -1,5 +1,6 @@
---
layout: default
refactor: true
---
{% include lang.html %}
@@ -39,70 +40,73 @@ layout: default
{% endfor %}
{% endif %}
{% capture content %}
<div id="post-list" class="flex-grow-1 px-xl-1">
{% for post in posts %}
<article class="card-wrapper">
<a href="{{ post.url | relative_url }}" class="card post-preview flex-md-row-reverse">
{% if post.image %}
{% if post.image.lqip %}
{% capture lqip %}lqip="{{ post.image.lqip }}"{% endcapture %}
{% endif %}
<article class="card-wrapper card">
<a href="{{ post.url | relative_url }}" class="post-preview row g-0 flex-md-row-reverse">
{% assign card_body_col = '12' %}
{% if post.image %}
{% assign src = post.image.path | default: post.image %}
{% unless src contains '//' %}
{% assign src = post.img_path | append: '/' | append: src | replace: '//', '/' %}
{% assign src = post.media_subpath | append: '/' | append: src | replace: '//', '/' %}
{% endunless %}
{% assign alt = post.image.alt | xml_escape | default: 'Preview Image' %}
<img src="{{ src }}" w="17" h="10" alt="{{ alt }}" {{ lqip }}>
{% assign lqip = null %}
{% if post.image.lqip %}
{% capture lqip %}lqip="{{ post.image.lqip }}"{% endcapture %}
{% endif %}
<div class="col-md-5">
<img src="{{ src }}" alt="{{ alt }}" {{ lqip }}>
</div>
{% assign card_body_col = '7' %}
{% endif %}
<div class="card-body d-flex flex-column">
<h1 class="card-title my-2 mt-md-0">{{ post.title }}</h1>
<div class="col-md-{{ card_body_col }}">
<div class="card-body d-flex flex-column">
<h1 class="card-title my-2 mt-md-0">{{ post.title }}</h1>
<div class="card-text content mt-0 mb-2">
<p>
{% include no-linenos.html content=post.content %}
{{ content | markdownify | strip_html | truncate: 200 | escape }}
</p>
</div>
<div class="post-meta flex-grow-1 d-flex align-items-end">
<div class="me-auto">
<!-- posted date -->
<i class="far fa-calendar fa-fw me-1"></i>
{% include datetime.html date=post.date lang=lang %}
<!-- categories -->
{% if post.categories.size > 0 %}
<i class="far fa-folder-open fa-fw me-1"></i>
<span class="categories">
{% for category in post.categories %}
{{ category }}
{%- unless forloop.last -%},{%- endunless -%}
{% endfor %}
</span>
{% endif %}
<div class="card-text content mt-0 mb-3">
<p>{% include post-description.html %}</p>
</div>
{% if post.pin %}
<div class="pin ms-1">
<i class="fas fa-thumbtack fa-fw"></i>
<span>{{ site.data.locales[lang].post.pin_prompt }}</span>
<div class="post-meta flex-grow-1 d-flex align-items-end">
<div class="me-auto">
<!-- posted date -->
<i class="far fa-calendar fa-fw me-1"></i>
{% include datetime.html date=post.date lang=lang %}
<!-- categories -->
{% if post.categories.size > 0 %}
<i class="far fa-folder-open fa-fw me-1"></i>
<span class="categories">
{% for category in post.categories %}
{{ category }}
{%- unless forloop.last -%},{%- endunless -%}
{% endfor %}
</span>
{% endif %}
</div>
{% endif %}
{% if post.pin %}
<div class="pin ms-1">
<i class="fas fa-thumbtack fa-fw"></i>
<span>{{ site.data.locales[lang].post.pin_prompt }}</span>
</div>
{% endif %}
</div>
<!-- .post-meta -->
</div>
<!-- .post-meta -->
<!-- .card-body -->
</div>
<!-- .card-body -->
</a>
</article>
{% endfor %}
{% endcapture %}
<div id="post-list" class="flex-grow-1 pe-xl-2">
{% include refactor-content.html content=content lang=lang %}
</div>
<!-- #post-list -->

View File

@@ -2,13 +2,7 @@
layout: default
---
{% capture _content %}
{% if layout.refactor or page.layout == 'page' %}
{% include refactor-content.html content=content lang=lang %}
{% else %}
{{ content }}
{% endif %}
{% endcapture %}
{% include lang.html %}
<article class="px-1">
{% if page.layout == 'page' or page.collection == 'tabs' %}
@@ -18,9 +12,9 @@ layout: default
{{ title }}
</h1>
<div class="content">
{{ _content }}
{{ content }}
</div>
{% else %}
{{ _content }}
{{ content }}
{% endif %}
</article>

View File

@@ -1,5 +1,5 @@
---
layout: page
layout: default
refactor: true
panel_includes:
- toc
@@ -11,125 +11,142 @@ tail_includes:
{% include lang.html %}
<header>
<h1 data-toc-skip>{{ page.title }}</h1>
<div class="post-meta text-muted">
<!-- published date -->
<span>
{{ site.data.locales[lang].post.posted }}
{% include datetime.html date=page.date tooltip=true lang=lang %}
</span>
<!-- lastmod date -->
{% if page.last_modified_at and page.last_modified_at != page.date %}
<span>
{{ site.data.locales[lang].post.updated }}
{% include datetime.html date=page.last_modified_at tooltip=true lang=lang %}
</span>
<article class="px-1">
<header>
<h1 data-toc-skip>{{ page.title }}</h1>
{% if page.description %}
<p class="post-desc fw-light mb-4">{{ page.description }}</p>
{% endif %}
{% if page.image %}
{% capture src %}src="{{ page.image.path | default: page.image }}"{% endcapture %}
{% capture class %}class="preview-img{% if page.image.no_bg %}{{ ' no-bg' }}{% endif %}"{% endcapture %}
{% capture alt %}alt="{{ page.image.alt | xml_escape | default: "Preview Image" }}"{% endcapture %}
<div class="post-meta text-muted">
<!-- published date -->
<span>
{{ site.data.locales[lang].post.posted }}
{% include datetime.html date=page.date tooltip=true lang=lang %}
</span>
{% capture lqip %}
{% if page.image.lqip %}
lqip="{{ page.image.lqip }}"
<!-- lastmod date -->
{% if page.last_modified_at and page.last_modified_at != page.date %}
<span>
{{ site.data.locales[lang].post.updated }}
{% include datetime.html date=page.last_modified_at tooltip=true lang=lang %}
</span>
{% endif %}
{% endcapture %}
<div class="mt-3 mb-3">
<img {{ src }} {{ class }} {{ alt }} w="1200" h="630" {{ lqip | strip }}>
{%- if page.image.alt -%}
<figcaption class="text-center pt-2 pb-2">{{ page.image.alt }}</figcaption>
{%- endif -%}
{% if page.image %}
{% capture src %}src="{{ page.image.path | default: page.image }}"{% endcapture %}
{% capture class %}class="preview-img{% if page.image.no_bg %}{{ ' no-bg' }}{% endif %}"{% endcapture %}
{% capture alt %}alt="{{ page.image.alt | xml_escape | default: "Preview Image" }}"{% endcapture %}
{% if page.image.lqip %}
{%- capture lqip -%}lqip="{{ page.image.lqip }}"{%- endcapture -%}
{% endif %}
<div class="mt-3 mb-3">
<img {{ src }} {{ class }} {{ alt }} w="1200" h="630" {{ lqip }}>
{%- if page.image.alt -%}
<figcaption class="text-center pt-2 pb-2">{{ page.image.alt }}</figcaption>
{%- endif -%}
</div>
{% endif %}
<div class="d-flex justify-content-between">
<!-- author(s) -->
<span>
{% if page.author %}
{% assign authors = page.author %}
{% elsif page.authors %}
{% assign authors = page.authors %}
{% endif %}
{{ site.data.locales[lang].post.written_by }}
<em>
{% if authors %}
{% for author in authors %}
{% if site.data.authors[author].url -%}
<a href="{{ site.data.authors[author].url }}">{{ site.data.authors[author].name }}</a>
{%- else -%}
{{ site.data.authors[author].name }}
{%- endif %}
{% unless forloop.last %}{{ '</em>, <em>' }}{% endunless %}
{% endfor %}
{% else %}
<a href="{{ site.social.links[0] }}">{{ site.social.name }}</a>
{% endif %}
</em>
</span>
<div>
<!-- pageviews -->
{% if site.pageviews.provider and site.analytics[site.pageviews.provider].id %}
<span>
<em id="pageviews">
<i class="fas fa-spinner fa-spin small"></i>
</em>
{{ site.data.locales[lang].post.pageview_measure }}
</span>
{% endif %}
<!-- read time -->
{% include read-time.html content=content prompt=true lang=lang %}
</div>
</div>
</div>
</header>
<div class="content">
{{ content }}
</div>
<div class="post-tail-wrapper text-muted">
<!-- categories -->
{% if page.categories.size > 0 %}
<div class="post-meta mb-3">
<i class="far fa-folder-open fa-fw me-1"></i>
{% for category in page.categories %}
<a href="{{ site.baseurl }}/categories/{{ category | slugify | url_encode }}/">{{ category }}</a>
{%- unless forloop.last -%},{%- endunless -%}
{% endfor %}
</div>
{% endif %}
<div class="d-flex justify-content-between">
<!-- author(s) -->
<span>
{% if page.author %}
{% assign authors = page.author %}
{% elsif page.authors %}
{% assign authors = page.authors %}
{% endif %}
<!-- tags -->
{% if page.tags.size > 0 %}
<div class="post-tags">
<i class="fa fa-tags fa-fw me-1"></i>
{% for tag in page.tags %}
<a
href="{{ site.baseurl }}/tags/{{ tag | slugify | url_encode }}/"
class="post-tag no-text-decoration"
>
{{- tag -}}
</a>
{% endfor %}
</div>
{% endif %}
{{ site.data.locales[lang].post.written_by }}
<em>
{% if authors %}
{% for author in authors %}
<a href="{{ site.data.authors[author].url }}">{{ site.data.authors[author].name }}</a>
{% unless forloop.last %}{{ '</em>, <em>' }}{% endunless %}
{% endfor %}
{% else %}
<a href="{{ site.social.links[0] }}">{{ site.social.name }}</a>
{% endif %}
</em>
</span>
<!-- read time -->
{% include read-time.html content=content prompt=true lang=lang %}
</div>
<!-- .d-flex -->
</div>
<!-- .post-meta -->
</header>
<div class="content">
{{ content }}
</div>
<div class="post-tail-wrapper text-muted">
<!-- categories -->
{% if page.categories.size > 0 %}
<div class="post-meta mb-3">
<i class="far fa-folder-open fa-fw me-1"></i>
{% for category in page.categories %}
<a href="{{ site.baseurl }}/categories/{{ category | slugify | url_encode }}/">{{ category }}</a>
{%- unless forloop.last -%},{%- endunless -%}
{% endfor %}
</div>
{% endif %}
<!-- tags -->
{% if page.tags.size > 0 %}
<div class="post-tags">
<i class="fa fa-tags fa-fw me-1"></i>
{% for tag in page.tags %}
<a
href="{{ site.baseurl }}/tags/{{ tag | slugify | url_encode }}/"
class="post-tag no-text-decoration"
>
{{- tag -}}
</a>
{% endfor %}
</div>
{% endif %}
<div
class="
post-tail-bottom
d-flex justify-content-between align-items-center mt-5 pb-2
"
>
<div class="license-wrapper">
{% if site.data.locales[lang].copyright.license.template %}
{% capture _replacement %}
<div
class="
post-tail-bottom
d-flex justify-content-between align-items-center mt-5 pb-2
"
>
<div class="license-wrapper">
{% if site.data.locales[lang].copyright.license.template %}
{% capture _replacement %}
<a href="{{ site.data.locales[lang].copyright.license.link }}">
{{ site.data.locales[lang].copyright.license.name }}
</a>
{% endcapture %}
{{ site.data.locales[lang].copyright.license.template | replace: ':LICENSE_NAME', _replacement }}
{% endif %}
</div>
{{ site.data.locales[lang].copyright.license.template | replace: ':LICENSE_NAME', _replacement }}
{% endif %}
</div>
{% include post-sharing.html lang=lang %}
{% include post-sharing.html lang=lang %}
</div>
<!-- .post-tail-bottom -->
</div>
<!-- .post-tail-bottom -->
</div>
<!-- div.post-tail-wrapper -->
<!-- div.post-tail-wrapper -->
</article>

View File

@@ -1,5 +1,6 @@
---
title: Text and Typography
description: Examples of text, typography, math equations, diagrams, flowcharts, pictures, videos, and more.
author: cotes
date: 2019-08-08 11:33:00 +0800
categories: [Blogging, Demo]
@@ -13,17 +14,22 @@ image:
alt: Responsive rendering of Chirpy theme on multiple devices.
---
This post is to show Markdown syntax rendering on [**Chirpy**](https://github.com/cotes2020/jekyll-theme-chirpy/fork), you can also use it as an example of writing. Now, let's start looking at text and typography.
## Headings
<h1 class="mt-5">H1 - heading</h1>
<!-- markdownlint-capture -->
<!-- markdownlint-disable -->
# H1 - heading
{: .mt-4 .mb-0 }
<h2 data-toc-skip>H2 - heading</h2>
## H2 - heading
{: data-toc-skip='' .mt-4 .mb-0 }
<h3 data-toc-skip>H3 - heading</h3>
### H3 - heading
{: data-toc-skip='' .mt-4 .mb-0 }
<h4 data-toc-skip>H4 - heading</h4>
#### H4 - heading
{: data-toc-skip='' .mt-4 }
<!-- markdownlint-restore -->
## Paragraph
@@ -40,15 +46,15 @@ Quisque egestas convallis ipsum, ut sollicitudin risus tincidunt a. Maecenas int
### Unordered list
- Chapter
+ Section
* Paragraph
- Section
- Paragraph
### ToDo list
- [ ] Job
+ [x] Step 1
+ [x] Step 2
+ [ ] Step 3
- [x] Step 1
- [x] Step 2
- [ ] Step 3
### Description list
@@ -64,6 +70,8 @@ Moon
## Prompts
<!-- markdownlint-capture -->
<!-- markdownlint-disable -->
> An example showing the `tip` type prompt.
{: .prompt-tip }
@@ -75,14 +83,15 @@ Moon
> An example showing the `danger` type prompt.
{: .prompt-danger }
<!-- markdownlint-restore -->
## Tables
| Company | Contact | Country |
|:-----------------------------|:-----------------|--------:|
| :--------------------------- | :--------------- | ------: |
| Alfreds Futterkiste | Maria Anders | Germany |
| Island Trading | Helen Bennett | UK |
| Magazzini Alimentari Riuniti | Giovanni Rovelli | Italy |
| Island Trading | Helen Bennett | UK |
| Magazzini Alimentari Riuniti | Giovanni Rovelli | Italy |
## Links
@@ -104,7 +113,7 @@ Here is the `/path/to/the/file.extend`{: .filepath}.
### Common
```
```text
This is a common code snippet, without syntax highlight and line number.
```
@@ -130,7 +139,14 @@ fi;
The mathematics powered by [**MathJax**](https://www.mathjax.org/):
$$ \sum_{n=1}^\infty 1/n^2 = \frac{\pi^2}{6} $$
$$
\begin{equation}
\sum_{n=1}^\infty 1/n^2 = \frac{\pi^2}{6}
\label{eq:series}
\end{equation}
$$
We can reference the equation as \eqref{eq:series}.
When $a \ne 0$, there are two solutions to $ax^2 + bx + c = 0$ and they are

View File

@@ -58,7 +58,6 @@ Adding author information in `_data/authors.yml` (If your website doesn't have t
```
{: file="_data/authors.yml" }
And then use `author` to specify a single entry or `authors` to specify multiple entries:
```yaml
@@ -69,12 +68,23 @@ authors: [<author1_id>, <author2_id>] # for multiple entries
---
```
Having said that, the key `author` can also identify multiple entries.
> The benefit of reading the author information from the file `_data/authors.yml`{: .filepath } is that the page will have the meta tag `twitter:creator`, which enriches the [Twitter Cards](https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started#card-and-content-attribution) and is good for SEO.
{: .prompt-info }
### Post Description
By default, the first words of the post are used to display on the home page for a list of posts, in the _Further Reading_ section, and in the XML of the RSS feed. If you don't want to display the auto-generated description for the post, you can customize it using the `description` field in the _Front Matter_ as follows:
```yaml
---
description: Short summary of the post.
---
```
Additionally, the `description` text will also be displayed under the post title on the post's page.
## Table of Contents
By default, the **T**able **o**f **C**ontents (TOC) is displayed on the right panel of the post. If you want to turn it off globally, go to `_config.yml`{: .filepath} and set the value of variable `toc` to `false`. If you want to turn off TOC for a specific post, add the following to the post's [Front Matter](https://jekyllrb.com/docs/front-matter/):
@@ -97,33 +107,37 @@ comments: false
---
```
## Mathematics
## Media
For website performance reasons, the mathematical feature won't be loaded by default. But it can be enabled by:
We refer to images, audio and video as media resources in _Chirpy_.
```yaml
---
math: true
---
```
### URL Prefix
## Mermaid
From time to time we have to define duplicate URL prefixes for multiple resources in a post, which is a boring task that you can avoid by setting two parameters.
[**Mermaid**](https://github.com/mermaid-js/mermaid) is a great diagrams generation tool. To enable it on your post, add the following to the YAML block:
- If you are using a CDN to host media files, you can specify the `cdn` in `_config.yml`{: .filepath }. The URLs of media resources for site avatar and posts are then prefixed with the CDN domain name.
```yaml
---
mermaid: true
---
```
```yaml
cdn: https://cdn.com
```
{: file='_config.yml' .nolineno }
Then you can use it like other markdown languages: surround the graph code with ```` ```mermaid ```` and ```` ``` ````.
- To specify the resource path prefix for the current post/page range, set `media_subpath` in the _front matter_ of the post:
## Images
```yaml
---
media_subpath: /path/to/media/
---
```
{: .nolineno }
### Caption
The option `site.cdn` and `page.media_subpath` can be used individually or in combination to flexibly compose the final resource URL: `[site.cdn/][page.media_subpath/]file.ext`
Add italics to the next line of an imagethen it will become the caption and appear at the bottom of the image:
### Images
#### Caption
Add italics to the next line of an image, then it will become the caption and appear at the bottom of the image:
```markdown
![img-description](/path/to/image)
@@ -131,7 +145,7 @@ _Image Caption_
```
{: .nolineno}
### Size
#### Size
In order to prevent the page content layout from shifting when the image is loaded, we should set the width and height for each image.
@@ -150,7 +164,7 @@ Starting from _Chirpy v5.0.0_, `height` and `width` support abbreviations (`heig
```
{: .nolineno}
### Position
#### Position
By default, the image is centered, but you can specify the position by using one of the classes `normal`, `left`, and `right`.
@@ -180,7 +194,7 @@ By default, the image is centered, but you can specify the position by using one
```
{: .nolineno}
### Dark/Light mode
#### Dark/Light mode
You can make images follow theme preferences in dark/light mode. This requires you to prepare two images, one for dark mode and one for light mode, and then assign them a specific class (`dark` or `light`):
@@ -189,7 +203,7 @@ You can make images follow theme preferences in dark/light mode. This requires y
![Dark mode only](/path/to/dark-mode.png){: .dark }
```
### Shadow
#### Shadow
The screenshots of the program window can be considered to show the shadow effect:
@@ -198,56 +212,7 @@ The screenshots of the program window can be considered to show the shadow effec
```
{: .nolineno}
### CDN URL
If you host the images on the CDN, you can save the time of repeatedly writing the CDN URL by assigning the variable `img_cdn` of `_config.yml`{: .filepath} file:
```yaml
img_cdn: https://cdn.com
```
{: file='_config.yml' .nolineno}
Once `img_cdn` is assigned, the CDN URL will be added to the path of all images (images of site avatar and posts) starting with `/`.
For instance, when using images:
```markdown
![The flower](/path/to/flower.png)
```
{: .nolineno}
The parsing result will automatically add the CDN prefix `https://cdn.com` before the image path:
```html
<img src="https://cdn.com/path/to/flower.png" alt="The flower">
```
{: .nolineno }
### Image Path
When a post contains many images, it will be a time-consuming task to repeatedly define the path of the images. To solve this, we can define this path in the YAML block of the post:
```yml
---
img_path: /img/path/
---
```
And then, the image source of Markdown can write the file name directly:
```md
![The flower](flower.png)
```
{: .nolineno }
The output will be:
```html
<img src="/img/path/flower.png" alt="The flower">
```
{: .nolineno }
### Preview Image
#### Preview Image
If you want to add an image at the top of the post, please provide an image with a resolution of `1200 x 630`. Please note that if the image aspect ratio does not meet `1.91 : 1`, the image will be scaled and cropped.
@@ -261,7 +226,7 @@ image:
---
```
Note that the [`img_path`](#image-path) can also be passed to the preview image, that is, when it has been set, the attribute `path` only needs the image file name.
Note that the [`media_subpath`](#url-prefix) can also be passed to the preview image, that is, when it has been set, the attribute `path` only needs the image file name.
For simple use, you can also just use `image` to define the path.
@@ -271,7 +236,7 @@ image: /path/to/image
---
```
### LQIP
#### LQIP
For preview images:
@@ -282,8 +247,7 @@ image:
---
```
> You can observe LQIP in the preview image of post [_Text and Typography_](/posts/text-and-typography/).
> You can observe LQIP in the preview image of post \"[Text and Typography](../text-and-typography/)\".
For normal images:
@@ -292,6 +256,86 @@ For normal images:
```
{: .nolineno }
### Video
#### Social Media Platform
You can embed videos from social media platforms with the following syntax:
```liquid
{% include embed/{Platform}.html id='{ID}' %}
```
Where `Platform` is the lowercase of the platform name, and `ID` is the video ID.
The following table shows how to get the two parameters we need in a given video URL, and you can also know the currently supported video platforms.
| Video URL | Platform | ID |
| -------------------------------------------------------------------------------------------------- | ---------- | :------------- |
| [https://www.**youtube**.com/watch?v=**H-B46URT4mg**](https://www.youtube.com/watch?v=H-B46URT4mg) | `youtube` | `H-B46URT4mg` |
| [https://www.**twitch**.tv/videos/**1634779211**](https://www.twitch.tv/videos/1634779211) | `twitch` | `1634779211` |
| [https://www.**bilibili**.com/video/**BV1Q44y1B7Wf**](https://www.bilibili.com/video/BV1Q44y1B7Wf) | `bilibili` | `BV1Q44y1B7Wf` |
#### Video Files
If you want to embed a video file directly, use the following syntax:
```liquid
{% include embed/video.html src='{URL}' %}
```
Where `URL` is an URL to a video file e.g. `/path/to/sample/video.mp4`.
You can also specify additional attributes for the embedded video file. Here is a full list of attributes allowed.
- `poster='/path/to/poster.png'` — poster image for a video that is shown while video is downloading
- `title='Text'` — title for a video that appears below the video and looks same as for images
- `autoplay=true` — video automatically begins to play back as soon as it can
- `loop=true` — automatically seek back to the start upon reaching the end of the video
- `muted=true` — audio will be initially silenced
- `types` — specify the extensions of additional video formats separated by `|`. Ensure these files exist in the same directory as your primary video file.
Consider an example utilizing all of the above:
```liquid
{%
include embed/video.html
src='/path/to/video.mp4'
types='ogg|mov'
poster='poster.png'
title='Demo video'
autoplay=true
loop=true
muted=true
%}
```
### Audios
If you want to embed an audio file directly, use the following syntax:
```liquid
{% include embed/audio.html src='{URL}' %}
```
Where `URL` is an URL to an audio file e.g. `/path/to/audio.mp3`.
You can also specify additional attributes for the embedded audio file. Here is a full list of attributes allowed.
- `title='Text'` — title for an audio that appears below the audio and looks same as for images
- `types` — specify the extensions of additional audio formats separated by `|`. Ensure these files exist in the same directory as your primary audio file.
Consider an example utilizing all of the above:
```liquid
{%
include embed/audio.html
src='/path/to/audio.mp3'
types='ogg|wav|aac'
title='Demo audio'
%}
```
## Pinned Posts
You can pin one or more posts to the top of the home page, and the fixed posts are sorted in reverse order according to their release date. Enable by:
@@ -389,23 +433,74 @@ If you want to display the **Liquid** snippet, surround the liquid code with `{%
Or adding `render_with_liquid: false` (Requires Jekyll 4.0 or higher) to the post's YAML block.
## Videos
You can embed a video with the following syntax:
```liquid
{% include embed/{Platform}.html id='{ID}' %}
```
Where `Platform` is the lowercase of the platform name, and `ID` is the video ID.
The following table shows how to get the two parameters we need in a given video URL, and you can also know the currently supported video platforms.
## Mathematics
| Video URL | Platform | ID |
|----------------------------------------------------------------------------------------------------|-----------|:--------------|
| [https://www.**youtube**.com/watch?v=**H-B46URT4mg**](https://www.youtube.com/watch?v=H-B46URT4mg) | `youtube` | `H-B46URT4mg` |
| [https://www.**twitch**.tv/videos/**1634779211**](https://www.twitch.tv/videos/1634779211) | `twitch` | `1634779211` |
We use [**MathJax**][mathjax] to generate mathematics. For website performance reasons, the mathematical feature won't be loaded by default. But it can be enabled by:
[mathjax]: https://www.mathjax.org/
```yaml
---
math: true
---
```
After enabling the mathematical feature, you can add math equations with the following syntax:
- **Block math** should be added with `$$ math $$` with **mandatory** blank lines before and after `$$`
- **Inserting equation numbering** should be added with `$$\begin{equation} math \end{equation}$$`
- **Referencing equation numbering** should be done with `\label{eq:label_name}` in the equation block and `\eqref{eq:label_name}` inline with text (see example below)
- **Inline math** (in lines) should be added with `$$ math $$` without any blank line before or after `$$`
- **Inline math** (in lists) should be added with `\$$ math $$`
```markdown
<!-- Block math, keep all blank lines -->
$$
LaTeX_math_expression
$$
<!-- Equation numbering, keep all blank lines -->
$$
\begin{equation}
LaTeX_math_expression
\label{eq:label_name}
\end{equation}
$$
Can be referenced as \eqref{eq:label_name}.
<!-- Inline math in lines, NO blank lines -->
"Lorem ipsum dolor sit amet, $$ LaTeX_math_expression $$ consectetur adipiscing elit."
<!-- Inline math in lists, escape the first `$` -->
1. \$$ LaTeX_math_expression $$
2. \$$ LaTeX_math_expression $$
3. \$$ LaTeX_math_expression $$
```
> Starting with `v7.0.0`, configuration options for **MathJax** have been moved to file `assets/js/data/mathjax.js`{: .filepath }, and you can change the options as needed, such as adding [extensions][mathjax-exts].
> If you are building the site via `chirpy-starter`, copy that file from the gem installation directory (check with command `bundle info --path jekyll-theme-chirpy`) to the same directory in your repository.
{: .prompt-tip }
[mathjax-exts]: https://docs.mathjax.org/en/latest/input/tex/extensions/index.html
## Mermaid
[**Mermaid**](https://github.com/mermaid-js/mermaid) is a great diagram generation tool. To enable it on your post, add the following to the YAML block:
```yaml
---
mermaid: true
---
```
Then you can use it like other markdown languages: surround the graph code with ```` ```mermaid ```` and ```` ``` ````.
## Learn More

Some files were not shown because too many files have changed in this diff Show More