Merge branch 'master' into production

This commit is contained in:
Cotes Chung 2022-06-09 17:59:55 +08:00
commit 4c45f3788e
No known key found for this signature in database
GPG Key ID: 0D9E54843167A808
80 changed files with 1231 additions and 758 deletions

5
.commitlintrc.json Normal file
View File

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

View File

@ -1,6 +1,6 @@
# How to Contribute
We want to thank you for sparing time to improve this project! Here are some guidelines for contributing
We'd like to thank you for sparing time to improve this project! Here are some guidelines for contributing
To ensure that the blog design is not confused, this project does not accept suggestions for design changes, such as color scheme, fonts, typography, etc. If your request is about an enhancement, it is recommended to first submit a [_Feature Request_](https://github.com/cotes2020/jekyll-theme-chirpy/issues/new?labels=enhancement&template=feature_request.md) issue to discuss whether your idea fits the project.
@ -9,34 +9,57 @@ To ensure that the blog design is not confused, this project does not accept sug
Generally, contribute to the project by:
1. Fork this project on GitHub and clone it locally.
2. Create a new branch from the default branch and give it a descriptive name (e.g., `my-new-feature`, `fix-a-bug`).
3. After completing the development, submit a new _Pull Request_.
2. Create a new branch from the default branch and give it a descriptive name (format: `feature/<add-new-feat>` / `fix/<fix-a-bug>`).
3. After completing the development, submit a new _Pull Request_. Note that the commit message must follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/), otherwise it will fail the PR check.
## Modifying JavaScript
If your contribution involves JS modification, please read the following sections.
If your contribution involves JavaScript modification, please read the following sections.
### Inline Scripts
If you need to add comments to the inline JS (the JS code between the tags `<script>` and `</script>`), please use `/**/` instead of two slashes `//`. Because the HTML will be compressed by [jekyll-compress-html](https://github.com/penibelst/jekyll-compress-html) during deployment, but it cannot handle the `//` properly. And this will disrupt the structure of the compressed HTML.
If you need to add comments to the inline JavaScript (the code between the HTML tags `<script>` and `</script>`), please use `/* */` instead of two slashes `//`. Because the HTML will be compressed by [jekyll-compress-html](https://github.com/penibelst/jekyll-compress-html) during deployment, but it cannot handle the `//` properly, which will disrupt the structure of the compressed HTML.
### External Scripts
If you need to add or modify JavaScripts in the directory `_javascript`, you need to install [Gulp.js](https://gulpjs.com/docs/en/getting-started/quick-start).
If you need to add/change/delete the JavaScript in the directory `_javascript/`, setting up [`Node.js`](https://nodejs.org/) and [`npx`](https://www.npmjs.com/package/npx) is a requirement. And then install the development dependencies:
During development, real-time debugging can be performed through the following commands:
```console
$ npm i
```
During JavaScript development, real-time debugging can be performed through the following commands:
Firstly, start a Jekyll server:
```console
$ bash tools/run.sh
```
Open another terminal tab and run:
And then open a new terminal tab and run:
```console
$ gulp dev # Type 'Ctrl + C' to stop
# Type 'Ctrl + C' to stop
$ npx gulp dev
```
After debugging, run the command `gulp` (without any argument) will automatically output the compressed files to the directory `assests/js/dist/`.
After debugging, run the command `npx gulp` (without any argument) will automatically output the compressed files to the directory `assets/js/dist/`.
## Verify the commit messages
If you want to make sure your commits pass the CI check, you can refer to the following steps.
Install `commitlint` & `husky`:
```console
$ npm i -g @commitlint/{cli,config-conventional} husky
```
And then enable `husky`:
```console
$ husky install
```
---

View File

@ -35,14 +35,15 @@ Steps to reproduce the behavior:
<!-- If applicable, add screenshots to help explain your problem. -->
### Software
### Environment
<!-- Please complete the following information -->
- Ruby version: <!-- by running: `ruby -v` -->
- Gem version: <!-- by running: `gem -v`-->
- Bundler version: <!-- by running: `bundle -v`-->
- Jekyll version: <!-- by running: `bundle list | grep " jekyll "` -->
- Theme version: <!-- by running: `gem list | grep jekyll-theme-chirpy` -->
| Command | Version |
|-----------------------------------|---------|
| `ruby -v` | |
| `gem -v` | |
| `bundle -v` | |
| `bundle exec jekyll -v` | |
| `bundle info jekyll-theme-chirpy` | |
### Desktop

View File

@ -1,4 +1,4 @@
name: 'Continuous Integration'
name: 'CI'
on:
push:
branches-ignore:
@ -18,23 +18,20 @@ on:
- '**'
jobs:
ci:
runs-on: ${{ matrix.os }}
build:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
ruby: [2.5, 2.6, 2.7, 3]
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0 # for posts's lastmod
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Test Site
run: bash tools/deploy.sh --dry-run

11
.github/workflows/commitlint.yml vendored Normal file
View File

@ -0,0 +1,11 @@
name: Lint Commit Messages
on: pull_request
jobs:
commitlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: wagoid/commitlint-github-action@v4

View File

@ -2,7 +2,7 @@ name: 'Automatic build'
on:
push:
branches:
- main
- master
paths-ignore:
- .gitignore
- README.md

3
.gitignore vendored
View File

@ -4,6 +4,9 @@
!.editorconfig
!.nojekyll
!.travis.yml
!.husky
!.commitlintrc.json
!.versionrc.json
# bundler cache
_site

4
.husky/commit-msg Executable file
View File

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

View File

@ -31,9 +31,9 @@ jobs:
stages:
- name: Upgrade
if: branch =~ /^v(\d)+(\.(\d)+){2}$/ OR tag IS present
if: branch = production
- name: Starter
if: branch =~ /^v(\d)+(\.(\d)+){2}$/ OR tag IS present
if: branch = production
- name: Docs
if: branch = docs

20
.versionrc.json Normal file
View File

@ -0,0 +1,20 @@
{
"skip": {
"commit": true,
"tag": true
},
"types": [
{
"type": "feat",
"section": "Features"
},
{
"type": "fix",
"section": "Bug Fixes"
},
{
"type": "perf",
"section": "Improvements"
}
]
}

44
CHANGELOG.md Normal file
View File

@ -0,0 +1,44 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [5.2.0](https://github.com/cotes2020/jekyll-theme-chirpy/compare/v5.1.0...v5.2.0) (2022-06-09)
### Features
* add es-ES support to locales ([#533](https://github.com/cotes2020/jekyll-theme-chirpy/issues/533)) ([efe75ad](https://github.com/cotes2020/jekyll-theme-chirpy/commit/efe75adf2784956afb7a0b67f6634b146d9cb03b))
* add fr-FR support to locales ([#582](https://github.com/cotes2020/jekyll-theme-chirpy/issues/582)) ([94e8144](https://github.com/cotes2020/jekyll-theme-chirpy/commit/94e81447afa457b1a6b7e8f487c47502803556d7))
* add Vietnamese locale ([#517](https://github.com/cotes2020/jekyll-theme-chirpy/issues/517)) ([171463d](https://github.com/cotes2020/jekyll-theme-chirpy/commit/171463d76da9b7bc25dd327b8f0a868ea79e388b))
* add pt-BR support to locales ([c2c503f](https://github.com/cotes2020/jekyll-theme-chirpy/commit/c2c503f63336884282b6bda4ec0703d6ae76771b))
* add option to turn off PWA ([#527](https://github.com/cotes2020/jekyll-theme-chirpy/issues/527)) ([106c981](https://github.com/cotes2020/jekyll-theme-chirpy/commit/106c981bac71e7434204a77e1f0c9c61d6eb1509))
* **PWA:** add Service Worker update notification ([d127183](https://github.com/cotes2020/jekyll-theme-chirpy/commit/d127183b9774f6321e409acdb66bf8a85d8814be))
* support showing description of preview image ([2bd6efa](https://github.com/cotes2020/jekyll-theme-chirpy/commit/2bd6efa95a174ac44e30a3af1e57e6f40d6e0e3a))
### Bug Fixes
* alt is not a valid attribute for 'a' tag ([58928db](https://github.com/cotes2020/jekyll-theme-chirpy/commit/58928dbc9068db4e4cda4371eeae1865920dce6a))
* assets URL is missing `baseurl` in self-hosted mode ([#591](https://github.com/cotes2020/jekyll-theme-chirpy/issues/591)) ([54124d5](https://github.com/cotes2020/jekyll-theme-chirpy/commit/54124d5134995fce52e4c2fc0a5d4d1743d6264d))
* correct the `twitter:creator` of Twitter summary card ([96a16c8](https://github.com/cotes2020/jekyll-theme-chirpy/commit/96a16c868ede51e7dfa412de63ffa1e5a49add7f))
* correctly URL encode share links ([4c1c8d8](https://github.com/cotes2020/jekyll-theme-chirpy/commit/4c1c8d8b0eacecbbaa2d522bbdd6430f350ff760)), closes [#496](https://github.com/cotes2020/jekyll-theme-chirpy/issues/496)
* follow paginate_path config for pagination ([6900d9f](https://github.com/cotes2020/jekyll-theme-chirpy/commit/6900d9f2bc9380cbda4babf611c6eeff345291af))
* force checkout of `gh-pages` branch ([#544](https://github.com/cotes2020/jekyll-theme-chirpy/issues/544)) ([5402523](https://github.com/cotes2020/jekyll-theme-chirpy/commit/5402523ae52a3740bcc15df0b226b2612644945d))
* horizontal scroll for long equations ([#545](https://github.com/cotes2020/jekyll-theme-chirpy/issues/545)) ([30787fc](https://github.com/cotes2020/jekyll-theme-chirpy/commit/30787fc4cf151e955bb7afc26dfd859f1a06fce6))
* p is not allowed in span ([4f590e2](https://github.com/cotes2020/jekyll-theme-chirpy/commit/4f590e2bba0639751771211bc0d357828ae70404))
* remove whitespace from avatar URL ([#537](https://github.com/cotes2020/jekyll-theme-chirpy/issues/537)) ([0542b51](https://github.com/cotes2020/jekyll-theme-chirpy/commit/0542b5149c8287dca60e37f46ee36f31b43455e4))
* resume the preview image SEO tag ([#529](https://github.com/cotes2020/jekyll-theme-chirpy/issues/529)) ([b8d1bcd](https://github.com/cotes2020/jekyll-theme-chirpy/commit/b8d1bcd3dea0abd1afef7ef154a4501fbb18938d))
* script code should be in head or body, not in between ([2103191](https://github.com/cotes2020/jekyll-theme-chirpy/commit/2103191b2faf714a8e4418c7c347a1f942b51af8))
* spurious header closing tags ([59e9557](https://github.com/cotes2020/jekyll-theme-chirpy/commit/59e955745f02f9b57c65af70b0979cd4a98bf53f))
* table bypass refactoring when it contains IAL ([#519](https://github.com/cotes2020/jekyll-theme-chirpy/issues/519)) ([5d85ccb](https://github.com/cotes2020/jekyll-theme-chirpy/commit/5d85ccb9943aac88dbbefebe1c2234cdcbae5c53))
* **theme mode:** `SCSS` syntax error ([#588](https://github.com/cotes2020/jekyll-theme-chirpy/issues/588)) ([76a1b6a](https://github.com/cotes2020/jekyll-theme-chirpy/commit/76a1b6a068c369138422dcd18ba08ec8cc3749a6))
* use `jsonify` to generate valid json ([#521](https://github.com/cotes2020/jekyll-theme-chirpy/issues/521)) ([dd9d5a7](https://github.com/cotes2020/jekyll-theme-chirpy/commit/dd9d5a7207b746342d07176d8969dc4f2c380bf2))
* when the `site.img_cdn` is set to the local path, the preview-image path loses the `baseurl` ([9cefe58](https://github.com/cotes2020/jekyll-theme-chirpy/commit/9cefe58993d9ea3a3a28424e7ffd8e0911567c5c))
### Improvements
* avoid post pageviews from shifting while loading ([135a16f](https://github.com/cotes2020/jekyll-theme-chirpy/commit/135a16f13ee783d9308669ff9a824847a73c951c))
* avoid the layout shift for post datetime ([6d35f5f](https://github.com/cotes2020/jekyll-theme-chirpy/commit/6d35f5f8da044cfad071628bb53776de03efaae4))
* **categories:** support singular and plural forms of locale ([#595](https://github.com/cotes2020/jekyll-theme-chirpy/issues/595)) ([35cadf9](https://github.com/cotes2020/jekyll-theme-chirpy/commit/35cadf969dd0161ee62503e242c545f006f7072b))
* improve the responsive design for ultrawide screens ([#540](https://github.com/cotes2020/jekyll-theme-chirpy/issues/540)) ([5d6e8c5](https://github.com/cotes2020/jekyll-theme-chirpy/commit/5d6e8c5ef6aa71b4d2600c5305f6e8ba540557f7))

View File

@ -115,6 +115,9 @@ assets:
# only works if `assets.self_host.enabled` is 'true'
env: # [development|production]
pwa:
enabled: true # the option for PWA feature
paginate: 10
# ------------ The following options are not recommended to be modified ------------------

17
_data/authors.yml Normal file
View File

@ -0,0 +1,17 @@
## Template https://github.com/jekyll/jekyll-seo-tag/blob/master/docs/advanced-usage.md#setting-author-url
# -------------------------------------
# {author_id}:
# name: {full name}
# twitter: {twitter_of_author}
# url: {homepage_of_author}
# -------------------------------------
cotes:
name: Cotes Chung
twitter: cotes2020
url: https://github.com/cotes2020/
sille_bille:
name: Dinesh Prasanth Moluguwan Krishnamoorthy
twitter: dinesh_MKD
url: https://github.com/SilleBille/

View File

@ -20,7 +20,7 @@ tabs:
search:
hint: search
cancel: Cancel
no_results: Oops! No result founds.
no_results: Oops! No results found.
panel:
lastmod: Recently Updated
@ -44,9 +44,10 @@ meta: Powered by :PLATFORM with :THEME theme.
not_found:
statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.
hint_template: :HEAD_BAK to try finding it again, or search for it on the :ARCHIVES_PAGE.
head_back: Head back Home
archives_page: Archives page
notification:
update_found: A new version of content is available.
update: Update
# ----- Posts related labels -----
@ -74,5 +75,9 @@ post:
# categories page
categories:
category_measure: categories
post_measure: posts
category_measure:
singular: category
plural: categories
post_measure:
singular: post
plural: posts

79
_data/locales/es-ES.yml Normal file
View File

@ -0,0 +1,79 @@
# The layout text of site
# ----- Commons label -----
layout:
post: Entrada
category: Categoría
tag: Etiqueta
# The tabs of sidebar
tabs:
# format: <filename_without_extension>: <value>
home: Inicio
categories: Categorías
tags: Etiquetas
archives: Archivo
about: Acerca de
# the text displayed in the search bar & search results
search:
hint: Buscar
cancel: Cancelar
no_results: ¡Oops! No se encuentran resultados.
panel:
lastmod: Actualizado recientemente
trending_tags: Etiquetas populares
toc: Contenido
copyright:
# Shown at the bottom of the post
license:
template: Esta entrada está licenciada bajo :LICENSE_NAME por el autor.
name: CC BY 4.0
link: https://creativecommons.org/licenses/by/4.0/
# Displayed in the footer
brief: Algunos derechos reservados.
verbose: >-
Salvo que se indique explícitamente, las entradas de este blog están licenciadas
bajo la Creative Commons Attribution 4.0 International (CC BY 4.0) License por el autor.
meta: Hecho con :PLATFORM usando el tema :THEME.
not_found:
statment: Lo sentimos, hemos perdido esa URL o apunta a algo que no existe.
notification:
update_found: Hay una nueva versión de contenido disponible.
update: Actualizar
# ----- Posts related labels -----
post:
written_by: Por
posted: Publicado
updated: Actualizado
words: palabras
pageview_measure: visitas
read_time:
unit: min
prompt: ' de lectura'
relate_posts: Lecturas adicionales
share: Compartir
button:
next: Nuevo
previous: Anterior
copy_code:
succeed: ¡Copiado!
share_link:
title: Copiar enlace
succeed: ¡Enlace copiado!
# pinned prompt of posts list on homepage
pin_prompt: Fijado
# categories page
categories:
category_measure: categorias
post_measure: entradas

79
_data/locales/fr-FR.yml Normal file
View File

@ -0,0 +1,79 @@
# The layout text of site
# ----- Commons label -----
layout:
post: Post
category: Catégorie
tag: Tag
# The tabs of sidebar
tabs:
# format: <filename_without_extension>: <value>
home: Accueil
categories: Catégories
tags: Tags
archives: Archives
about: A propos de
# the text displayed in the search bar & search results
search:
hint: recherche
cancel: Annuler
no_results: Oups ! Aucun résultat trouvé.
panel:
lastmod: Récemment mis à jour
trending_tags: Tags tendance
toc: Contenu
copyright:
# Shown at the bottom of the post
license:
template: Cet article est sous licence :LICENSE_NAME par l'auteur.
name: CC BY 4.0
link: https://creativecommons.org/licenses/by/4.0/
# Displayed in the footer
brief: Certains droits réservés.
verbose: >-
Sauf mention contraire, les articles de ce site sont publiés sous licence
sous la licence Creative Commons Attribution 4.0 International (CC BY 4.0) par l'auteur.
meta: Propulsé par :PLATFORM avec le thème :THEME
not_found:
statment: Désolé, nous avons égaré cette URL ou elle pointe vers quelque chose qui n'existe pas.
notification:
update_found: Une nouvelle version du contenu est disponible.
update: Mise à jour
# ----- Posts related labels -----
post:
written_by: Par
posted: Posté
updated: Mis à jour
words: mots
pageview_measure: vues
read_time:
unit: min
prompt: lire
relate_posts: Autres lectures
share: Partager
button:
next: Plus récent
previous: Plus ancien
copy_code:
succeed: Copié !
share_link:
title: Copier le lien
succeed: Lien copié avec succès !
# pinned prompt of posts list on homepage
pin_prompt: Épinglé
# categories page
categories:
category_measure: catégories
post_measure: posts

View File

@ -44,9 +44,10 @@ meta: Didukung oleh :PLATFORM dengan tema :THEME.
not_found:
statment: Maaf, kami gagal menemukan URL itu atau memang mengarah ke sesuatu yang tidak ada.
hint_template: :HEAD_BAK untuk mencoba mencari kembali, atau cari di :ARCHIVES_PAGE.
head_back: Kembali ke Beranda
archives_page: Halaman Arsip
notification:
update_found: Versi konten baru tersedia.
update: Perbarui
# ----- Posts related labels -----

View File

@ -44,9 +44,10 @@ meta: Powered by :PLATFORM with :THEME theme.
not_found:
statment: 해당 URL은 존재하지 않습니다.
hint_template: :HEAD_BAK을 눌러 다시 찾거나 :ARCHIVES_PAGE에서 검색해 주세요.
head_back: 홈으로 돌아가기
archives_page: 아카이브 페이지
notification:
update_found: 새 버전의 콘텐츠를 사용할 수 있습니다.
update: 업데이트
# ----- Posts related labels -----

View File

@ -44,9 +44,10 @@ meta: Powered by :PLATFORM with :THEME theme.
not_found:
statment: ဝမ်းနည်းပါသည်၊ ကျွန်ုပ်တို့သည် အဆိုပါ URL ကို မှားယွင်းစွာ နေရာချထားခြင်း သို့မဟုတ် ၎င်းသည် မရှိသောအရာကို ညွှန်ပြနေပါသည်။
hint_template: ၎င်းကို ထပ်မံရှာဖွေရန် :HEAD_BAK , သို့မဟုတ် :ARCHIVES_PAGE တွင်ရှာပါ။
head_back: အဓိကစာမျက်နှာသို့ပြန်သွားပါ။
archives_page: မှတ်တမ်း​တိုက် စာမျက်နှာ။
notification:
update_found: အကြောင်းအရာဗားရှင်းအသစ်ကို ရနိုင်ပါပြီ။
update: အပ်ဒိတ်
# ----- Posts related labels -----

79
_data/locales/pt-BR.yml Normal file
View File

@ -0,0 +1,79 @@
# The layout text of site
# ----- Commons label -----
layout:
post: Post
category: Categoria
tag: Tag
# The tabs of sidebar
tabs:
# format: <filename_without_extension>: <value>
home: Home
categories: Categorias
tags: Tags
archives: Arquivos
about: Sobre
# the text displayed in the search bar & search results
search:
hint: Buscar
cancel: Cancelar
no_results: Oops! Nenhum resultado encontrado.
panel:
lastmod: Atualizados recentemente
trending_tags: Trending Tags
toc: Conteúdo
copyright:
# Shown at the bottom of the post
license:
template: Esta postagem está licenciada sob :LICENSE_NAME pelo autor.
name: CC BY 4.0
link: https://creativecommons.org/licenses/by/4.0/
# Displayed in the footer
brief: Alguns direitos reservados.
verbose: >-
Exceto onde indicado de outra forma, as postagens do blog neste site são licenciadas sob a
Creative Commons Attribution 4.0 International (CC BY 4.0) License pelo autor.
meta: Feito com :PLATFORM usando o tema :THEME.
not_found:
statment: Desculpe, a página não foi encontrada.
notification:
update_found: Uma nova versão do conteúdo está disponível.
update: atualização
# ----- Posts related labels -----
post:
written_by: Por
posted: Postado em
updated: Atualizado
words: palavras
pageview_measure: visualizações
read_time:
unit: min
prompt: " de leitura"
relate_posts: Leia também
share: Compartilhar
button:
next: Próximo
previous: Anterior
copy_code:
succeed: Copiado!
share_link:
title: Copie o link
succeed: Link copiado com sucesso!
# pinned prompt of posts list on homepage
pin_prompt: Fixado
# categories page
categories:
category_measure: categorias
post_measure: posts

View File

@ -44,9 +44,10 @@ meta: Powered by :PLATFORM with :THEME theme.
not_found:
statment: Извините, эта ссылка указывает на ресурс который не существует.
hint_template: :HEAD_BAK чтобы снова осуществить поиск, или поищите :ARCHIVES_PAGE.
head_back: Вернитесь на домашнюю страницу
archives_page: архиве
notification:
update_found: Доступна новая версия контента.
update: Обновлять
# ----- Posts related labels -----

View File

@ -44,9 +44,10 @@ meta: Powered by :PLATFORM with :THEME theme.
not_found:
statment: Вибачте, це посилання вказує на ресурс, що не існує.
hint_template: :HEAD_BAK аби здійснити пошук, або пошукайте в :ARCHIVES_PAGE.
head_back: Поверніться на домашню сторінку
archives_page: архіві
notification:
update_found: Доступна нова версія вмісту.
update: Оновлення
# ----- Posts related labels -----

77
_data/locales/vi-VN.yml Normal file
View File

@ -0,0 +1,77 @@
# The layout text of site
# ----- Commons label -----
layout:
post: Bài viết
category: Danh mục
tag: Thẻ
# The tabs of sidebar
tabs:
# format: <filename_without_extension>: <value>
home: Trang chủ
categories: Các danh mục
tags: Các thẻ
archives: Lưu trữ
about: Giới thiệu
# the text displayed in the search bar & search results
search:
hint: tìm kiếm
cancel: Hủy
no_results: Không có kết quả tìm kiếm.
panel:
lastmod: Mới cập nhật
trending_tags: Các thẻ thịnh hành
toc: Mục lục
copyright:
# Shown at the bottom of the post
license:
template: Bài viết này được cấp phép bởi tác giả theo giấy phép :LICENSE_NAME.
name: CC BY 4.0
link: https://creativecommons.org/licenses/by/4.0/
# Displayed in the footer
brief: Một số quyền được bảo lưu.
verbose: >-
Trừ khi có ghi chú khác, các bài viết đăng trên trang này được cấp phép bởi tác giả theo giấy phép Creative Commons Attribution 4.0 International (CC BY 4.0).
meta: Trang web này được tạo bởi :PLATFORM với chủ đề :THEME.
not_found:
statment: Xin lỗi, chúng tôi đã đặt nhầm URL hoặc đường dẫn trỏ đến một trang nào đó không tồn tại.
notification:
update_found: Đã có phiên bản mới của nội dung.
update: Cập nhật
# ----- Posts related labels -----
post:
written_by: Viết bởi
posted: Đăng lúc
updated: Cập nhật lúc
words: từ
pageview_measure: lượt xem
read_time:
unit: phút
prompt: đọc
relate_posts: Bài viết liên quan
share: Chia sẻ
button:
next: Mới hơn
previous: Cũ hơn
copy_code:
succeed: Đã sao chép!
share_link:
title: Sao chép đường dẫn
succeed: Đã sao chép đường dẫn thành công!
# pinned prompt of posts list on homepage
pin_prompt: Bài ghim
# categories page
categories:
category_measure: danh mục
post_measure: bài viết

View File

@ -43,9 +43,10 @@ meta: 本站由 :PLATFORM 生成,采用 :THEME 主题。
not_found:
statment: 抱歉,我们放错了该 URL或者它指向了不存在的内容。
hint_template: :HEAD_BAK尝试再次查找它或在:ARCHIVES_PAGE上搜索它。
head_back: 返回主页
archives_page: 归档页面
notification:
update_found: 发现新版本的内容。
update: 更新
# ----- Posts related labels -----

21
_includes/datetime.html Normal file
View File

@ -0,0 +1,21 @@
<!--
Date format snippet
See: ${JS_ROOT}/utils/locale-dateime.js
-->
{% assign wrap_elem = include.wrap | default: 'em' %}
{% if site.prefer_datetime_locale == 'en' or lang == 'en' %}
{% assign df_strftime = '%b %e, %Y' %}
{% assign df_dayjs = 'll' %}
{% else %}
{% assign df_strftime = '%F' %}
{% assign df_dayjs = 'YYYY-MM-DD' %}
{% endif %}
<{{ wrap_elem }} class="{% if include.class %}{{ include.class }}{% endif %}"
data-ts="{{ include.date | date: '%s' }}"
data-df="{{ df_dayjs }}"
{% if include.tooltip %}data-toggle="tooltip" data-placement="bottom"{% endif %}>
{{ include.date | date: df_strftime }}
</{{ wrap_elem }}>

View File

@ -1,9 +1,7 @@
<!--
The Footer
-->
<!-- The Footer -->
<footer class="d-flex w-100 justify-content-center">
<div class="d-flex justify-content-between align-items-center text-muted">
<footer class="row pl-3 pr-3">
<div class="col-12 d-flex justify-content-between align-items-center text-muted pl-0 pr-0">
<div class="footer-left">
<p class="mb-0">
© {{ 'now' | date: "%Y" }}
@ -33,5 +31,6 @@
</p>
</div>
</div> <!-- div.d-flex -->
</div>
</footer>

View File

@ -23,7 +23,30 @@
{% endif %}
{% capture seo_tags %}
{% seo title=false %}
{% endcapture %}
{% if site.img_cdn and seo_tags contains 'og:image' %}
{% assign properties = 'og:image,twitter:image' | split: ',' %}
{% for prop in properties %}
{% if site.img_cdn contains '//' %}
<!-- `site.img_cdn` is a cross-origin URL -->
{% capture target %}<meta property="{{ prop }}" content="{{ site.url }}{% endcapture %}
{% capture replacement %}<meta property="{{ prop }}" content="{{ site.img_cdn }}{% endcapture %}
{% else %}
<!-- `site.img_cdn` is a local file path -->
{% capture target %}<meta property="{{ prop }}" content="{{ site.url }}{{ site.baseurl }}{% endcapture %}
{% assign replacement = target | append: site.img_cdn %}
{% endif %}
{% assign seo_tags = seo_tags | replace: target, replacement %}
{% endfor %}
{% endif %}
{{ seo_tags }}
<title>
{%- unless page.layout == "home" -%}
@ -45,7 +68,7 @@
<link rel="dns-prefetch" href="{{ cdn.url }}" {{ cdn.args }}>
{% endfor %}
<link rel="stylesheet" href="{{ site.data.assets[origin].webfonts }}">
<link rel="stylesheet" href="{{ site.data.assets[origin].webfonts | relative_url }}">
{% endif %}
@ -67,24 +90,27 @@
{% endif %}
<!-- Bootstrap -->
<link rel="stylesheet" href="{{ site.data.assets[origin].bootstrap.css }}">
<link rel="stylesheet" href="{{ site.data.assets[origin].bootstrap.css | relative_url}}">
<!-- Font Awesome -->
<link rel="stylesheet" href="{{ site.data.assets[origin].fontawesome.css }}">
<link rel="stylesheet" href="{{ site.data.assets[origin].fontawesome.css | relative_url }}">
<link rel="stylesheet" href="{{ '/assets/css/style.css' | relative_url }}">
{% if site.toc and page.toc %}
<link rel="stylesheet" href="{{ site.data.assets[origin].bootstrap-toc.css }}">
<link rel="stylesheet" href="{{ site.data.assets[origin].bootstrap-toc.css | relative_url }}">
{% endif %}
{% if page.layout == 'page' or page.layout == 'post' %}
<!-- Manific Popup -->
<link rel="stylesheet" href="{{ site.data.assets[origin].magnific-popup.css }}">
<link rel="stylesheet" href="{{ site.data.assets[origin].magnific-popup.css | relative_url }}">
{% endif %}
<!-- JavaScript -->
<script src="{{ site.data.assets[origin].jquery.js }}"></script>
<script src="{{ site.data.assets[origin].jquery.js | relative_url }}"></script>
{% unless site.theme_mode %}
{% include mode-toggle.html %}
{% endunless %}
</head>

View File

@ -7,7 +7,7 @@
{% if page.layout == 'post' %}
{% if site.google_analytics.pv.proxy_endpoint or site.google_analytics.pv.cache_path %}
<!-- pv-report needs countup.js -->
<script async src="{{ site.data.assets[origin].countup.js }}"></script>
<script async src="{{ site.data.assets[origin].countup.js | relative_url }}"></script>
<script defer src="{{ '/assets/js/dist/pvreport.min.js' | relative_url }}"></script>
{% endif %}
{% endif %}
@ -79,18 +79,22 @@
}
};
</script>
<script src="{{ site.data.assets[origin].polyfill.js }}"></script>
<script id="MathJax-script" async src="{{ site.data.assets[origin].mathjax.js }}">
<script src="{{ site.data.assets[origin].polyfill.js | relative_url }}"></script>
<script id="MathJax-script" async src="{{ site.data.assets[origin].mathjax.js | relative_url }}">
</script>
{% endif %}
<!-- commons -->
<script src="{{ site.data.assets[origin].bootstrap.js }}"></script>
<script src="{{ site.data.assets[origin].bootstrap.js | relative_url }}"></script>
{% if jekyll.environment == 'production' %}
<!-- PWA -->
{% if site.pwa.enabled %}
<script defer src="{{ '/app.js' | relative_url }}"></script>
{% else %}
<script defer src="{{ '/unregister.js' | relative_url }}"></script>
{% endif %}
<!-- GA -->
{% if site.google_analytics.id != empty and site.google_analytics.id %}

View File

@ -2,7 +2,7 @@
mermaid-js loader
-->
<script src="{{ site.data.assets[origin].mermaid.js }}"></script>
<script src="{{ site.data.assets[origin].mermaid.js | relative_url }}"></script>
<script>
$(function() {

View File

@ -9,10 +9,10 @@
<p>{{ page.previous.title }}</p>
</a>
{% else %}
<span class="btn btn-outline-primary disabled"
<div class="btn btn-outline-primary disabled"
prompt="{{ site.data.locales[lang].post.button.previous }}">
<p>-</p>
</span>
</div>
{% endif %}
{% if page.next.url %}
@ -21,10 +21,10 @@
<p>{{ page.next.title }}</p>
</a>
{% else %}
<span class="btn btn-outline-primary disabled"
<div class="btn btn-outline-primary disabled"
prompt="{{ site.data.locales[lang].post.button.next }}">
<p>-</p>
</span>
</div>
{% endif %}
</div>

View File

@ -2,7 +2,7 @@
The paginator for post list on HomgPage.
-->
<ul class="pagination align-items-center mt-4 mb-0 pl-lg-2">
<ul class="pagination align-items-center mt-4 mb-5 pl-lg-2">
<!-- left arrow -->
{% if paginator.previous_page %}
{% assign prev_url = paginator.previous_page_path | relative_url %}
@ -47,7 +47,7 @@
{% if show %}
<!-- show number -->
<li class="page-item {% if i == paginator.page %} active{% endif %}">
<a class="page-link btn-box-shadow" href="{{ site.baseurl }}/{% if i > 1%}page{{ i }}/{% endif %}">{{ i }}</a>
<a class="page-link btn-box-shadow" href="{% if i > 1 %}{{ site.paginate_path | replace: ':num', i | relative_url }}{% else %}{{ '/' | relative_url }}{% endif %}">{{ i }}</a>
</li>
{% else %}
<!-- hide number -->

View File

@ -6,10 +6,11 @@
<span class="share-label text-muted mr-1">{{ site.data.locales[lang].post.share }}</span>
<span class="share-icons">
{% capture title %}{{ page.title }} - {{ site.title }}{% endcapture %}
{% assign url = page.url | absolute_url %}
{% assign title = title | url_encode %}
{% assign url = page.url | absolute_url | url_encode %}
{% for share in site.data.share.platforms %}
{% assign link = share.link | replace: 'TITLE', title | replace: 'URL', url | escape %}
{% assign link = share.link | replace: 'TITLE', title | replace: 'URL', url %}
<a href="{{ link }}" data-toggle="tooltip" data-placement="top"
title="{{ share.type }}" target="_blank" rel="noopener" aria-label="{{ share.type }}">
<i class="fa-fw {{ share.icon }}"></i>

View File

@ -9,10 +9,11 @@
we suround the markdown table with `<div class="table-wrapper">` and `</div>`
-->
{% if _content contains '<table>' %}
{% if _content contains '<table' %}
{% assign _content = _content
| replace: '<table>', '<div class="table-wrapper"><table>'
| replace: '<table', '<div class="table-wrapper"><table'
| replace: '</table>', '</table></div>'
| replace: '<code><div class="table-wrapper">', '<code>'
| replace: '</table></div></code>', '</table></code>'
%}
{% endif %}
@ -91,7 +92,11 @@
<!-- Add CDN URL -->
{% if site.img_cdn %}
{% if site.img_cdn contains '//' %}
{% assign _src_prefix = site.img_cdn %}
{% else %}
{% assign _src_prefix = site.img_cdn | relative_url %}
{% endif %}
{% else %}
{% assign _src_prefix = site.baseurl %}
{% endif %}
@ -212,7 +217,7 @@
{% assign left = left | replace: '">', '"><span class="mr-2">' | append: '</span>' %}
{% assign _new_content = _new_content | append: mark_start
| append: left | append: anchor | append: mark_end | append: right
| append: left | append: anchor | append: right
%}
{% endfor %}

View File

@ -60,7 +60,6 @@
{% assign less = TOTAL_SIZE | minus: index_list.size %}
{% if less > 0 %}
{% for i in (0..last_index) %}
{% assign post = site.posts[i] %}
{% if post.url != page.url %}
@ -74,10 +73,8 @@
{% endunless %}
{% endif %}
{% endfor %}
{% endif %}
{% if index_list.size > 0 %}
<div id="related-posts" class="mt-5 mb-2 mb-sm-4">
<h3 class="pt-2 mt-1 mb-4 ml-1"
@ -89,7 +86,7 @@
<div class="card">
<a href="{{ post.url | relative_url }}">
<div class="card-body">
{% include timeago.html date=post.date class="small" %}
{% include datetime.html date=post.date class="small" %}
<h3 class="pt-0 mt-1 mb-3" data-toc-skip>{{ post.title }}</h3>
<div class="text-muted small">
<p>

View File

@ -16,7 +16,7 @@
{% capture not_found %}<p class="mt-5">{{ site.data.locales[lang].search.no_results }}</p>{% endcapture %}
<script src="{{ site.data.assets[origin].search.js }}"></script>
<script src="{{ site.data.assets[origin].search.js | relative_url }}"></script>
<script>
SimpleJekyllSearch({

View File

@ -5,7 +5,7 @@
<div id="sidebar" class="d-flex flex-column align-items-end">
<div class="profile-wrapper text-center">
<div id="avatar">
<a href="{{ '/' | relative_url }}" alt="avatar" class="mx-auto">
<a href="{{ '/' | relative_url }}" class="mx-auto">
{% if site.avatar != empty and site.avatar %}
{% capture avatar_url %}
{% if site.avatar contains '://' %}
@ -16,7 +16,7 @@
{{ site.avatar | relative_url }}
{% endif %}
{% endcapture %}
<img src="{{ avatar_url }}" alt="avatar" onerror="this.style.display='none'">
<img src="{{ avatar_url | strip }}" alt="avatar" onerror="this.style.display='none'">
{% endif %}
</a>
</div>

View File

@ -1,15 +0,0 @@
<!--
Date format snippet
See: ${JS_ROOT}/utils/timeago.js
-->
<em class="timeago{% if include.class %} {{ include.class }}{% endif %}"
data-ts="{{ include.date | date: '%s' }}"
{% if include.tooltip %}
data-toggle="tooltip" data-placement="bottom" data-tooltip-df="llll"
{% endif %}
{% if include.capitalize %}
data-capitalize="true"
{% endif %}>
{{ include.date | date: '%Y-%m-%d' }}
</em>

View File

@ -7,7 +7,7 @@
{% if enable_toc %}
<!-- BS-toc.js will be loaded at medium priority -->
<script src="{{ site.data.assets[origin].bootstrap-toc.js }}"></script>
<script src="{{ site.data.assets[origin].bootstrap-toc.js | relative_url }}"></script>
<div id="toc-wrapper" class="pl-0 pr-4 mb-5">
<div class="panel-heading pl-3 pt-2 mb-2">{{- site.data.locales[lang].panel.toc -}}</div>

View File

@ -2,8 +2,8 @@
The Top Bar
-->
<div id="topbar-wrapper" class="row justify-content-center">
<div id="topbar" class="col-11 d-flex h-100 align-items-center justify-content-between">
<div id="topbar-wrapper">
<div id="topbar" class="container d-flex align-items-center justify-content-between h-100 pl-3 pr-3 pl-md-4 pr-md-4">
<span id="breadcrumb">
{% assign paths = page.url | split: '/' %}

View File

@ -1,19 +0,0 @@
/**
* A tool for locale datetime
*/
const LocaleHelper = (function () {
const $preferLocale = $('meta[name="prefer-datetime-locale"]');
const locale = $preferLocale.length > 0 ?
$preferLocale.attr('content').toLowerCase() : $('html').attr('lang').substr(0, 2);
const attrTimestamp = 'data-ts';
const attrDateFormat = 'data-df';
return {
locale: () => locale,
attrTimestamp: () => attrTimestamp,
attrDateFormat: () => attrDateFormat,
getTimestamp: ($elem) => Number($elem.attr(attrTimestamp)), // unix timestamp
getDateFormat: ($elem) => $elem.attr(attrDateFormat)
};
}());

View File

@ -1,5 +1,5 @@
/*!
* Chirpy v5.1.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* Chirpy v5.2.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* © 2019 Cotes Chung
* MIT Licensed
*/

View File

@ -4,17 +4,42 @@
* Requirement: <https://github.com/iamkun/dayjs>
*/
/* A tool for locale datetime */
const LocaleHelper = (function () {
const $preferLocale = $('meta[name="prefer-datetime-locale"]');
const locale = $preferLocale.length > 0 ?
$preferLocale.attr('content').toLowerCase() : $('html').attr('lang').substr(0, 2);
const attrTimestamp = 'data-ts';
const attrDateFormat = 'data-df';
return {
locale: () => locale,
attrTimestamp: () => attrTimestamp,
attrDateFormat: () => attrDateFormat,
getTimestamp: ($elem) => Number($elem.attr(attrTimestamp)), // unix timestamp
getDateFormat: ($elem) => $elem.attr(attrDateFormat)
};
}());
$(function() {
dayjs.locale(LocaleHelper.locale());
dayjs.extend(window.dayjs_plugin_localizedFormat);
$(`[${LocaleHelper.attrTimestamp()}]`).each(function () {
const date = dayjs.unix(LocaleHelper.getTimestamp($(this)));
const df = LocaleHelper.getDateFormat($(this));
const text = date.format(df);
const text = date.format(LocaleHelper.getDateFormat($(this)));
$(this).text(text);
$(this).removeAttr(LocaleHelper.attrTimestamp());
$(this).removeAttr(LocaleHelper.attrDateFormat());
// setup tooltips
const tooltip = $(this).attr('data-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-original-title', tooltipText);
});
});

View File

@ -1,87 +0,0 @@
/**
* Calculate the Timeago
*
* Requirement: <https://github.com/iamkun/dayjs>
*/
$(function() {
const attrTimestamp = LocaleHelper.attrTimestamp();
const attrCapitalize = 'data-capitalize';
const $timeago = $(".timeago");
let timeagoTasks = $timeago.length;
let intervalId = void 0;
dayjs.locale(LocaleHelper.locale());
dayjs.extend(window.dayjs_plugin_relativeTime);
dayjs.extend(window.dayjs_plugin_localizedFormat);
function relativetime($elem) {
const now = dayjs();
const past = dayjs.unix(LocaleHelper.getTimestamp($elem));
let diffMonth = now.diff(past, 'month', true);
if (diffMonth > 10) { // year ago range: 11 months to 17months
$elem.removeAttr(attrTimestamp);
return past.format('ll'); // see: https://day.js.org/docs/en/display/format#list-of-localized-formats
}
let diffMinute = now.diff(past, 'minute', true);
if (diffMinute > 44) { // an hour ago range: 45 to 89 minutes
$elem.removeAttr(attrTimestamp);
}
return past.fromNow();
}
function updateTimeago() {
$timeago.each(function() {
if (typeof $(this).attr(attrTimestamp) === 'undefined') {
timeagoTasks -= 1;
return;
}
let relativeTime = relativetime($(this));
const capitalize = $(this).attr(attrCapitalize);
if (typeof capitalize !== 'undefined' && capitalize === 'true') {
relativeTime = relativeTime.replace(/^\w/, (c) => c.toUpperCase());
}
if ($(this).text() !== relativeTime) {
$(this).text(relativeTime);
}
});
if (timeagoTasks === 0 && typeof intervalId !== "undefined") {
clearInterval(intervalId); /* stop interval */
}
return timeagoTasks;
}
function setupTooltips() {
$timeago.each(function() {
const tooltip = $(this).attr('data-toggle');
if (typeof tooltip === 'undefined' || tooltip !== 'tooltip') {
return;
}
const df = $(this).attr('data-tooltip-df');
const ts = LocaleHelper.getTimestamp($(this));
const dateStr = dayjs.unix(ts).format(df);
$(this).attr('data-original-title', dateStr);
$(this).removeAttr('data-tooltip-df');
});
}
if (timeagoTasks === 0) {
return;
}
setupTooltips();
if (updateTimeago()) { /* run immediately */
intervalId = setInterval(updateTimeago, 60 * 1000); /* run every minute */
}
});

View File

@ -3,8 +3,17 @@ layout: page
# The Archives of posts.
---
<div id="archives" class="pl-xl-2">
{% include lang.html %}
{% if site.prefer_datetime_locale == 'en' or lang == 'en' %}
{% assign df_strftime_m = '%b' %}
{% assign df_dayjs_m = 'MMM' %}
{% else %}
{% assign df_strftime_m = '/ %m' %}
{% assign df_dayjs_m = '/ MM' %}
{% endif %}
<div id="archives" class="pl-xl-2">
{% for post in site.posts %}
{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
{% capture pre_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %}
@ -17,9 +26,11 @@ layout: page
<li>
<div>
{% assign ts = post.date | date: '%s' %}
<span class="date day" data-ts="{{ ts }}" data-df="DD">{{ post.date | date: "%d" }}</span>
<span class="date month small text-muted" data-ts="{{ ts }}" data-df="MMM">
{{ post.date | date: '%m' }}
<span class="date day" data-ts="{{ ts }}" data-df="DD">
{{ post.date | date: "%d" }}
</span>
<span class="date month small text-muted" data-ts="{{ ts }}" data-df="{{ df_dayjs_m }}">
{{ post.date | date: df_strftime_m }}
</span>
<a href="{{ post.url | relative_url }}">{{ post.title }}</a>
</div>

View File

@ -47,10 +47,24 @@ layout: page
<span class="text-muted small font-weight-light">
{% if sub_categories_size > 0 %}
{{ sub_categories_size }}
{{ site.data.locales[lang].categories.category_measure }},
{% if sub_categories_size > 1 %}
{{ site.data.locales[lang].categories.category_measure.plural
| default: site.data.locales[lang].categories.category_measure }}
{% else %}
{{ site.data.locales[lang].categories.category_measure.singular
| default: site.data.locales[lang].categories.category_measure }}
{% endif %},
{% endif %}
{{ top_posts_size }}
{{ site.data.locales[lang].categories.post_measure }}
{% if top_posts_size > 1 %}
{{ site.data.locales[lang].categories.post_measure.plural
| default: site.data.locales[lang].categories.post_measure }}
{% else %}
{{ site.data.locales[lang].categories.post_measure.singular
| default: site.data.locales[lang].categories.post_measure }}
{% endif %}
</span>
</span>
@ -83,7 +97,14 @@ layout: page
{% assign posts_size = site.categories[sub_category] | size %}
<span class="text-muted small font-weight-light">
{{ posts_size }}
{{ site.data.locales[lang].categories.post_measure }}
{% if posts_size > 1 %}
{{ site.data.locales[lang].categories.post_measure.plural
| default: site.data.locales[lang].categories.post_measure }}
{% else %}
{{ site.data.locales[lang].categories.post_measure.singular
| default: site.data.locales[lang].categories.post_measure }}
{% endif %}
</span>
</li>
{% endfor %}

View File

@ -3,6 +3,8 @@ layout: page
# The Category layout
---
{% include lang.html %}
<div id="page-category">
<h1 class="pl-lg-2">
<i class="far fa-folder-open fa-fw text-muted"></i>
@ -15,9 +17,7 @@ layout: page
<li class="d-flex justify-content-between pl-md-3 pr-md-3">
<a href="{{ post.url | relative_url }}">{{ post.title }}</a>
<span class="dash flex-grow-1"></span>
<span class="text-muted small" data-ts="{{ post.date | date: '%s' }}" data-df="ll">
{{ post.date | date: '%Y-%m-%d' }}
</span>
{% include datetime.html date=post.date wrap='span' class='text-muted small' %}
</li>
{% endfor %}
</ul>

View File

@ -19,18 +19,14 @@ layout: compress
{% include head.html %}
{% unless site.theme_mode %}
{% include mode-toggle.html %}
{% endunless %}
<body data-spy="scroll" data-target="#toc" data-topbar-visible="true">
{% include sidebar.html %}
{% include topbar.html %}
<div id="main-wrapper">
<div id="main">
<div id="main-wrapper" class="d-flex justify-content-center">
<div id="main" class="container pl-xl-4 pr-xl-4">
{{ content }}
@ -52,6 +48,23 @@ layout: compress
<i class="fas fa-angle-up"></i>
</a>
{% if site.pwa.enabled %}
<div id="notification" class="toast" role="alert" aria-live="assertive" aria-atomic="true"
data-animation="true" data-autohide="false">
<div class="toast-header">
<button type="button" class="ml-2 ml-auto close" data-dismiss="toast" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="toast-body text-center pt-0">
<p class="pl-2 pr-2 mb-3">{{ site.data.locales[lang].notification.update_found }}</p>
<button type="button" class="btn btn-primary" aria-label="Update">
{{ site.data.locales[lang].notification.update }}
</button>
</div>
</div>
{% endif %}
{% include search-loader.html %}
{% include js-selector.html %}

View File

@ -23,7 +23,6 @@ layout: page
{% assign pinned_num = 0 %}
{% endif %}
<!-- Get default posts -->
{% assign default_beg = offset | minus: pinned.size %}
@ -58,15 +57,11 @@ layout: page
</div>
<div class="post-meta text-muted d-flex">
<div class="mr-auto">
<!-- posted date -->
<i class="far fa-calendar fa-fw"></i>
{% include timeago.html date=post.date tooltip=true capitalize=true %}
<!-- time to read -->
<i class="far fa-clock fa-fw"></i>
{% include read-time.html content=post.content %}
{% include datetime.html date=post.date %}
<!-- categories -->
{% if post.categories.size > 0 %}
@ -78,6 +73,7 @@ layout: page
{% endfor %}
</span>
{% endif %}
</div>
{% if post.pin %}

View File

@ -9,8 +9,8 @@ layout: default
<div class="row">
<!-- core -->
<div id="core-wrapper" class="col-12 col-lg-11 col-xl-8">
<div class="post pl-1 pr-1 pl-sm-2 pr-sm-2 pl-md-4 pr-md-4">
<div id="core-wrapper" class="col-12 col-lg-11 col-xl-9 pr-xl-4">
<div class="post pl-1 pr-1 pl-md-2 pr-md-2">
{% capture _content %}
{% if layout.refactor or page.layout == 'page' %}
@ -54,13 +54,11 @@ layout: default
<!-- tail -->
{% if layout.tail_includes %}
<div class="row">
<div class="col-12 col-lg-11 col-xl-8">
<div id="tail-wrapper" class="pl-1 pr-1 pl-sm-2 pr-sm-2 pl-md-4 pr-md-4">
<div id="tail-wrapper" class="col-12 col-lg-11 col-xl-9 pl-3 pr-3 pr-xl-4">
{% for _include in layout.tail_includes %}
{% assign _include_path = _include | append: '.html' %}
{% include {{ _include_path }} %}
{% endfor %}
</div>
</div>
</div> <!-- .row -->
</div>
{% endif %}

View File

@ -11,11 +11,30 @@ tail_includes:
{% include lang.html %}
{% if page.image.src %}
<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 %}
</span>
<!-- lastmod date -->
{% if page.last_modified_at %}
<span>
{{ site.data.locales[lang].post.updated }}
{% include datetime.html date=page.last_modified_at tooltip=true %}
</span>
{% endif %}
{% if page.image.path %}
{% capture bg %}
{% unless page.image.no_bg %}{{ 'bg' }}{% endunless %}
{% endcapture %}
<img src="{{ page.image.src }}" class="preview-img {{ bg | strip }}"
<div class="mt-3 mb-3">
<img src="{{ page.image.path }}" class="preview-img {{ bg | strip }}"
alt="{{ page.image.alt | default: "Preview Image" }}"
{% if page.image.width %}
@ -29,24 +48,28 @@ tail_includes:
{% elsif page.image.h %}
height="{{ page.image.h }}"
{% endif %}>
{% endif %}
<h1 data-toc-skip>{{ page.title }}</h1>
{% if page.image.alt %}
<figcaption class="pt-2 pb-2">{{ page.image.alt }}</figcaption>
{% endif %}
<div class="post-meta text-muted">
</div>
{% endif %}
<div class="d-flex justify-content-between">
<!-- author -->
<div>
{% capture author_name %}{{ page.author.name | default: site.social.name }}{% endcapture %}
<span>
{% capture author_name %}{{ site.data.authors[page.author].name | default: site.social.name }}{% endcapture %}
{% assign author_link = nil %}
{% if page.author.link %}
{% assign author_link = page.author.link %}
{% if page.author %}
{% assign author_link = site.data.authors[page.author].url %}
{% elsif author_name == site.social.name %}
{% assign author_link = site.social.links[0] %}
{% endif %}
{{ site.data.locales[lang].post.written_by }}
<em>
{% if author_link %}
<a href="{{ author_link }}">{{ author_name }}</a>
@ -54,27 +77,9 @@ tail_includes:
{{ author_name }}
{% endif %}
</em>
</div>
</span>
<div class="d-flex">
<div>
<!-- published date -->
<span>
{{ site.data.locales[lang].post.posted }}
{% include timeago.html date=page.date tooltip=true %}
</span>
<!-- lastmod date -->
{% if page.last_modified_at %}
<span>
{{ site.data.locales[lang].post.updated }}
{% include timeago.html date=page.last_modified_at tooltip=true %}
</span>
{% endif %}
<!-- read time -->
{% include read-time.html content=content prompt=true %}
<!-- page views -->
{% if site.google_analytics.pv.proxy_endpoint or site.google_analytics.pv.cache_path %}
<span>
@ -84,6 +89,9 @@ tail_includes:
{{ site.data.locales[lang].post.pageview_measure }}
</span>
{% endif %}
<!-- read time -->
{% include read-time.html content=content prompt=true %}
</div>
</div> <!-- .d-flex -->

View File

@ -3,6 +3,8 @@ layout: page
# The layout for Tag page
---
{% include lang.html %}
<div id="page-tag">
<h1 class="pl-lg-2">
<i class="fa fa-tag fa-fw text-muted"></i>
@ -14,9 +16,7 @@ layout: page
<li class="d-flex justify-content-between pl-md-3 pr-md-3">
<a href="{{ post.url | relative_url }}">{{ post.title }}</a>
<span class="dash flex-grow-1"></span>
<span class="text-muted small" data-ts="{{ post.date | date: '%s' }}" data-df="ll">
{{ post.date | date: '%Y-%m-%d' }}
</span>
{% include datetime.html date=post.date wrap='span' class='text-muted small' %}
</li>
{% endfor %}
</ul>

View File

@ -14,7 +14,9 @@ layout: page
{% for t in sorted_tags %}
<div>
<a class="tag" href="{{ site.baseurl }}/tags/{{ t | slugify | url_encode }}/">{{ t }}<span class="text-muted">{{ site.tags[t].size }}</span></a>
<a class="tag" href="{{ t | slugify | url_encode | prepend: '/tags/' | append: '/' | relative_url }}">
{{ t }}<span class="text-muted">{{ site.tags[t].size }}</span>
</a>
</div>
{% endfor %}

View File

@ -1,17 +1,16 @@
---
title: Text and Typography
author:
name: Cotes Chung
link: https://github.com/cotes2020
author: cotes
date: 2019-08-08 11:33:00 +0800
categories: [Blogging, Demo]
tags: [typography]
math: true
mermaid: true
image:
src: /commons/devices-mockup.png
path: /commons/devices-mockup.png
width: 800
height: 500
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.

View File

@ -1,8 +1,6 @@
---
title: Writing a New Post
author:
name: Cotes Chung
link: https://github.com/cotes2020
author: cotes
date: 2019-08-08 14:10:00 +0800
categories: [Blogging, Tutorial]
tags: [writing]
@ -50,14 +48,27 @@ tags: [bee]
The author information of the post usually does not need to be filled in the _Front Matter_ , they will be obtained from variables `social.name` and the first entry of `social.links` of the configuration file by default. But you can also override it as follows:
Add author information in `_data/authors.yml` (If your website doesn't have this file, don't hesitate to create one.)
```yaml
<author_id>:
name: <full name>
twitter: <twitter_of_author>
url: <homepage_of_author>
```
{: file="_data/authors.yml" }
And then set up the custom author in the post's YAML block:
```yaml
---
author:
name: Full Name
link: https://example.com
author: <author_id>
---
```
> Another 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 }
## 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/):
@ -221,12 +232,12 @@ The output will be:
### Preview Image
If you want to add an image to the top of the post contents, specify the attribute `src`, `width`, `height`, and `alt` for the image:
If you want to add an image to the top of the post contents, specify the attribute `path`, `width`, `height`, and `alt` for the image:
```yaml
---
image:
src: /path/to/image/file
path: /path/to/image/file
width: 1000 # in pixels
height: 400 # in pixels
alt: image alternative text
@ -235,7 +246,7 @@ image:
Except for `alt`, all other options are necessary, especially the `width` and `height`, which are related to user experience and web page loading performance. The above section "[Size](#size)" also mentions this.
Starting from _Chirpy v5.0.0_, the attributes `height` and `width` can be abbreviated: `height``h`, `width``w`. In addition, the [`img_path`](#image-path) can also be passed to the preview image, that is, when it has been set, the attribute `src` only needs the image file name.
Starting from _Chirpy v5.0.0_, the attributes `height` and `width` can be abbreviated: `height``h`, `width``w`. In addition, 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.
## Pinned Posts

View File

@ -1,8 +1,6 @@
---
title: Getting Started
author:
name: Cotes Chung
link: https://github.com/cotes2020
author: cotes
date: 2019-08-09 20:55:00 +0800
categories: [Blogging, Tutorial]
tags: [getting started]

View File

@ -1,8 +1,6 @@
---
title: Customize the Favicon
author:
name: Cotes Chung
link: https://github.com/cotes2020
author: cotes
date: 2019-08-11 00:34:00 +0800
categories: [Blogging, Tutorial]
tags: [favicon]

View File

@ -1,8 +1,6 @@
---
title: Enable Google Page Views
author:
name: Dinesh Prasanth Moluguwan Krishnamoorthy
link: https://github.com/SilleBille
author: sille_bille
date: 2021-01-03 18:32:00 -0500
categories: [Blogging, Tutorial]
tags: [google analytics, pageviews]

View File

@ -5,7 +5,7 @@
html {
@media (prefers-color-scheme: light) {
&:not([data-mode]),
[data-mode=light] {
&[data-mode=light] {
@include light-scheme;
}
@ -126,6 +126,11 @@ blockquote {
@include prompt("danger", "\f071");
}
mjx-container {
overflow-x: auto;
overflow-y: hidden;
}
kbd {
font-family: inherit;
display: inline-block;
@ -143,18 +148,15 @@ kbd {
}
footer {
position: absolute;
bottom: 0;
padding: 0 1rem;
height: $footer-height;
@include pl-pr(1.5rem);
font-size: 0.8rem;
> div.d-flex {
height: $footer-height;
line-height: 1.2rem;
width: 95%;
max-width: 1045px;
padding-bottom: 1rem;
border-top: 1px solid var(--main-border-color);
margin-bottom: 1rem;
> div {
width: 350px;
@ -222,7 +224,6 @@ img[data-src] {
.access {
top: 2rem;
transition: top 0.2s ease-in-out;
margin-right: 1.5rem;
margin-top: 3rem;
margin-bottom: 4rem;
@ -436,7 +437,7 @@ img[data-src] {
margin-right: 2px;
}
&:hover {
&:not([class]):hover {
@extend %link-hover;
}
}
@ -871,6 +872,7 @@ $sidebar-display: "sidebar-display";
#search-result-wrapper {
display: none;
height: 100%;
width: 100%;
overflow: auto;
.post-content {
@ -928,7 +930,7 @@ $sidebar-display: "sidebar-display";
#search-wrapper {
display: flex;
width: 85%;
width: 100%;
border-radius: 1rem;
border: 1px solid var(--search-wrapper-border-color);
background: var(--search-wrapper-bg);
@ -997,7 +999,7 @@ $sidebar-display: "sidebar-display";
}
#search-results {
padding-bottom: 6rem;
padding-bottom: 3rem;
a {
&:hover {
@ -1050,7 +1052,7 @@ $sidebar-display: "sidebar-display";
}
#core-wrapper {
min-height: calc(100vh - #{$topbar-height} - #{$footer-height} - #{$bottom-min-height}) !important;
min-height: calc(100vh - #{$topbar-height} - #{$footer-height});
.categories,
#tags,
@ -1083,29 +1085,13 @@ $sidebar-display: "sidebar-display";
background-color: var(--main-wrapper-bg);
position: relative;
min-height: 100vh;
padding-bottom: $footer-height;
@include pl-pr(0);
}
#main {
.row:first-child {
> div {
&:nth-child(1),
&:nth-child(2) {
#core-wrapper,
#panel-wrapper {
margin-top: $topbar-height; /* same as the height of topbar */
}
&:first-child {
/* 3rem for topbar, 6rem for footer */
min-height: calc(100vh - #{$topbar-height} - #{$footer-height} - #{$bottom-min-height});
}
}
}
div.row:first-of-type:last-of-type { /* alone */
margin-bottom: 4rem;
}
}
#topbar-wrapper.row,
@ -1145,6 +1131,51 @@ $sidebar-display: "sidebar-display";
-webkit-transform: translate3d(0, -5px, 0);
}
#notification {
@keyframes popup {
from {
opacity: 0;
bottom: 0;
}
}
.toast-header {
background: none;
border-bottom: none;
color: inherit;
}
.toast-body {
font-family: 'Lato';
line-height: 1.25rem;
button {
font-size: 90%;
min-width: 4rem;
}
}
&.toast {
display: none;
&.show {
display: block;
min-width: 20rem;
border-radius: 0.5rem;
-webkit-backdrop-filter: blur(10px);
backdrop-filter: blur(10px);
background-color: rgba(255, 255, 255, 0.5);
color: #1b1b1eba;
position: fixed;
left: 50%;
bottom: 20%;
transform: translateX(-50%);
animation: popup 0.8s;
}
}
}
/*
Responsive Design:
@ -1155,16 +1186,11 @@ $sidebar-display: "sidebar-display";
*/
@media all and (max-width: 576px) {
$footer-height: $footer-height-mobile; /* overwrite */
footer {
height: $footer-height;
height: $footer-height-mobile;
> div.d-flex {
width: 100%;
padding: 1.5rem 0;
margin-bottom: 0.3rem;
flex-wrap: wrap;
-ms-flex-pack: distribute !important;
justify-content: space-around !important;
@ -1176,12 +1202,8 @@ $sidebar-display: "sidebar-display";
}
}
#main > div.row:first-child > div:first-child {
min-height: calc(100vh - #{$topbar-height} - #{$footer-height});
}
#core-wrapper {
min-height: calc(100vh - #{$topbar-height} - #{$footer-height} - #{$bottom-min-height}) !important;
min-height: calc(100vh - #{$topbar-height} - #{$footer-height-mobile}) !important;
h1 {
margin-top: 2.2rem;
@ -1206,10 +1228,21 @@ $sidebar-display: "sidebar-display";
@include ml-mr(1.8rem);
}
#main-wrapper {
padding-bottom: $footer-height;
}
@media all and (max-width: 768px) {
%full-width {
max-width: 100%;
}
#topbar {
@extend %full-width;
}
#main {
@extend %full-width;
@include pl-pr(0);
}
}
/* hide sidebar and panel */
@ -1260,6 +1293,11 @@ $sidebar-display: "sidebar-display";
padding-top: $topbar-height;
}
#topbar,
#main {
max-width: 100%;
}
#search-result-wrapper {
width: 100%;
}
@ -1275,8 +1313,8 @@ $sidebar-display: "sidebar-display";
left: 0;
}
#main > div.row:first-child > div:nth-child(1),
#main > div.row:first-child > div:nth-child(2) {
#core-wrapper,
#panel-wrapper {
margin-top: 0;
}
@ -1286,17 +1324,6 @@ $sidebar-display: "sidebar-display";
display: block;
}
#search-wrapper {
&.loaded ~ a {
margin-right: 1rem;
}
}
#search-input {
margin-left: 0;
width: 95%;
}
#search-result-wrapper .post-content {
letter-spacing: 0;
}
@ -1345,17 +1372,17 @@ $sidebar-display: "sidebar-display";
margin-top: 3rem;
}
#search-wrapper {
width: 22%;
min-width: 150px;
}
#search-hints {
display: none;
}
#search-wrapper {
max-width: $search-max-width;
}
#search-result-wrapper {
margin-top: 3rem;
max-width: $main-content-max-width;
}
div.post-content .table-wrapper > table {
@ -1365,17 +1392,17 @@ $sidebar-display: "sidebar-display";
/* button 'back-to-Top' position */
#back-to-top {
bottom: 5.5rem;
right: 1.2rem;
right: 5%;
}
#topbar {
@include pl-pr(2rem);
}
#topbar-title {
text-align: left;
}
footer > div.d-flex {
width: 92%;
}
}
/* Pad horizontal */
@ -1449,10 +1476,6 @@ $sidebar-display: "sidebar-display";
display: none;
}
#topbar {
padding: 0;
}
#main > div.row {
-webkit-box-pack: center !important;
-ms-flex-pack: center !important;
@ -1463,26 +1486,12 @@ $sidebar-display: "sidebar-display";
/* --- desktop mode, both sidebar and panel are visible --- */
@media all and (min-width: 1200px) {
#main > div.row > div.col-xl-8 {
-webkit-box-flex: 0;
-ms-flex: 0 0 75%;
flex: 0 0 75%;
max-width: 75%;
padding-left: 3%;
}
#topbar {
padding: 0;
max-width: 1070px;
}
#panel-wrapper {
max-width: $panel-max-width;
}
#back-to-top {
bottom: 6.5rem;
right: 4.3rem;
}
#search-wrapper {
margin-right: 4rem;
}
#search-input {
@ -1518,62 +1527,36 @@ $sidebar-display: "sidebar-display";
}
@media all and (min-width: 1400px) {
#main > div.row {
padding-left: calc((100% - #{$main-content-max-width}) / 2);
> div.col-xl-8 {
max-width: 850px;
}
}
#search-result-wrapper {
padding-right: 2rem;
> div {
max-width: 1110px;
}
}
}
@media all and (min-width: 1400px) and (max-width: 1650px) {
#topbar {
padding-right: 2rem;
#back-to-top {
right: calc((100vw - #{$sidebar-width} - 1140px) / 2 + 3rem);
}
}
@media all and (min-width: 1650px) {
#breadcrumb {
padding-left: 0;
}
#main > div.row > div.col-xl-8 {
padding-left: 0;
> div:first-child {
padding-left: 0.55rem !important;
padding-right: 1.9rem !important;
}
}
#main-wrapper {
margin-left: $sidebar-width-large;
}
#panel-wrapper {
margin-left: calc((100% - #{$main-content-max-width}) / 10);
}
#topbar-wrapper {
left: $sidebar-width-large;
}
#topbar {
max-width: #{$main-content-max-width};
#search-wrapper {
margin-right: calc(#{$main-content-max-width} * 0.25 - #{$search-max-width});
}
#search-wrapper {
margin-right: 3%;
#topbar,
#main {
max-width: $main-content-max-width;
}
#core-wrapper,
#tail-wrapper {
padding-right: 4.5rem !important;
}
#back-to-top {
right: calc((100vw - #{$sidebar-width-large} - #{$main-content-max-width}) / 2 + 2rem);
}
#sidebar {
@ -1694,58 +1677,4 @@ $sidebar-display: "sidebar-display";
} /* #sidebar */
footer > div.d-flex {
width: 92%;
max-width: 1140px;
}
#search-result-wrapper {
> div {
max-width: #{$main-content-max-width};
}
}
} /* min-width: 1650px */
@media all and (min-width: 1700px) {
#topbar-wrapper {
/* 100% - 350px - (1920px - 350px); */
padding-right: calc(100% - #{$sidebar-width-large} - (1920px - #{$sidebar-width-large}));
}
#topbar {
max-width: calc(#{$main-content-max-width} + 20px);
}
#main > div.row {
padding-left: calc((100% - #{$main-content-max-width} - 2%) / 2);
}
#panel-wrapper {
margin-left: 3%;
}
footer {
padding-left: 0;
padding-right: calc(100% - #{$sidebar-width-large} - 1180px);
}
#back-to-top {
right: calc(100% - 1920px + 15rem);
}
}
@media (min-width: 1920px) {
#main > div.row {
padding-left: 190px;
}
#search-result-wrapper {
padding-right: calc(100% - #{$sidebar-width-large} - 1180px);
}
#panel-wrapper {
margin-left: 41px;
}
}

View File

@ -8,7 +8,7 @@
html {
@media (prefers-color-scheme: light) {
&:not([data-mode]),
[data-mode=light] {
&[data-mode=light] {
@include light-syntax;
}

View File

@ -20,12 +20,12 @@ $cursor-width: 2px !default; /* the cursor width of the selected tab */
$topbar-height: 3rem !default;
$search-max-width: 210px !default;
$footer-height: 5rem !default;
$footer-height-mobile: 6rem !default; /* screen width: <= 576px */
$main-content-max-width: 1150px !default;
$panel-max-width: 300px !default;
$main-content-max-width: 1250px !default;
$bottom-min-height: 35rem !default;

View File

@ -1,7 +1,7 @@
/*!
* The styles for Jekyll theme Chirpy
*
* Chirpy v5.1.0 (https://github.com/cotes2020/jekyll-theme-chirpy)
* Chirpy v5.2.0 (https://github.com/cotes2020/jekyll-theme-chirpy)
* © 2019 Cotes Chung
* MIT Licensed
*/

View File

@ -41,8 +41,7 @@ h1 + .post-meta {
}
img.preview-img {
margin-top: 3.75rem;
margin-bottom: 0;
margin: 0;
border-radius: 6px;
&.bg[data-loaded=true] {
@ -173,6 +172,8 @@ nav[data-toggle=toc] {
em {
@extend %normal-font-style;
color: var(--relate-post-date);
}
.card {
@ -194,10 +195,6 @@ nav[data-toggle=toc] {
}
}
.timeago {
color: var(--relate-post-date);
}
p {
font-size: 0.9rem;
margin-bottom: 0.5rem;

View File

@ -12,20 +12,5 @@ redirect_from:
{% include lang.html %}
<div class="lead">
{%- capture _head_back -%}
<a href="{{ '/' | relative_url }}">{{ site.data.locales[lang].not_found.head_back }}</a>
{%- endcapture -%}
{%- capture _archives_page -%}
<a href="{{ 'archives' | relative_url }}">{{ site.data.locales[lang].not_found.archives_page }}</a>
{%- endcapture -%}
<p>{{site.data.locales[lang].not_found.statment }}</p>
<p>{{ site.data.locales[lang].not_found.hint_template
| replace: ':HEAD_BAK', _head_back
| replace: ':ARCHIVES_PAGE', _archives_page }}
</p>
</div>

View File

@ -6,13 +6,13 @@ swcache: true
[
{% for post in site.posts %}
{
"title": "{{ post.title | escape }}",
"url": "{{ post.url | relative_url }}",
"categories": "{{ post.categories | join: ', '}}",
"tags": "{{ post.tags | join: ', ' }}",
"title": {{ post.title | jsonify }},
"url": {{ post.url | relative_url | jsonify }},
"categories": {{ post.categories | join: ', ' | jsonify }},
"tags": {{ post.tags | join: ', ' | jsonify }},
"date": "{{ post.date }}",
{% include no-linenos.html content=post.content %}
"snippet": "{{ content | strip_html | strip_newlines | remove_chars | escape | replace: '\', '\\\\' }}"
"snippet": {{ content | strip_html | strip_newlines | jsonify }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]

View File

@ -1,6 +1,6 @@
/*!
* Chirpy v5.1.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* Chirpy v5.2.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* © 2019 Cotes Chung
* MIT Licensed
*/
$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))});const LocaleHelper=function(){const e=$('meta[name="prefer-datetime-locale"]'),o=0<e.length?e.attr("content").toLowerCase():$("html").attr("lang").substr(0,2),t="data-ts",a="data-df";return{locale:()=>o,attrTimestamp:()=>t,attrDateFormat:()=>a,getTimestamp:e=>Number(e.attr(t)),getDateFormat:e=>e.attr(a)}}();$(function(){$(".mode-toggle").click(e=>{const o=$(e.target);let t=o.prop("tagName")==="button".toUpperCase()?o:o.parent();t.blur(),flipMode()})});const ScrollHelper=function(){const e=$("body"),o="data-topbar-visible",t=$("#topbar-wrapper").outerHeight();let a=0,r=!1,l=!1;return{hideTopbar:()=>e.attr(o,!1),showTopbar:()=>e.attr(o,!0),addScrollUpTask:()=>{a+=1,r=r||!0},popScrollUpTask:()=>--a,hasScrollUpTask:()=>0<a,topbarLocked:()=>!0===r,unlockTopbar:()=>r=!1,getTopbarHeight:()=>t,orientationLocked:()=>!0===l,lockOrientation:()=>l=!0,unLockOrientation:()=>l=!1}}();$(function(){const e=$("#sidebar-trigger"),o=$("#search-trigger"),t=$("#search-cancel"),a=$("#main"),r=$("#topbar-title"),l=$("#search-wrapper"),n=$("#search-result-wrapper"),s=$("#search-results"),i=$("#search-input"),c=$("#search-hints"),d=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),p={on(){e.addClass("unloaded"),r.addClass("unloaded"),o.addClass("unloaded"),l.addClass("d-flex"),t.addClass("loaded")},off(){t.removeClass("loaded"),l.removeClass("d-flex"),e.removeClass("unloaded"),r.removeClass("unloaded"),o.removeClass("unloaded")}},u=function(){let e=!1;return{on(){e||(d.block(),n.removeClass("unloaded"),a.addClass("unloaded"),e=!0)},off(){e&&(s.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),a.removeClass("unloaded"),d.release(),i.val(""),e=!1)},isVisible(){return e}}}();function f(){return t.hasClass("loaded")}o.click(function(){p.on(),u.on(),i.focus()}),t.click(function(){p.off(),u.off()}),i.focus(function(){l.addClass("input-focus")}),i.focusout(function(){l.removeClass("input-focus")}),i.on("input",()=>{""===i.val()?f()?c.removeClass("unloaded"):u.off():(u.on(),f()&&c.addClass("unloaded"))})}),$(function(){var e=function(){const e="sidebar-display";let o=!1;const t=$("body");return{toggle(){!1===o?t.attr(e,""):t.removeAttr(e),o=!o}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const o=$("#search-input"),t=ScrollHelper.getTopbarHeight();let e,a=0;function r(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var e=screen.orientation.type;"landscape-primary"!==e&&"landscape-secondary"!==e||r()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&r()}),$(window).scroll(()=>{e=e||!0}),setInterval(()=>{e&&(function(){var e=$(this).scrollTop();if(!(Math.abs(a-e)<=t)){if(e>a)ScrollHelper.hideTopbar(),o.is(":focus")&&o.blur();else if(e+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}a=e}}(),e=!1)},250)}),$(function(){var o="div.post>h1:first-of-type";const t=$(o),n=$("#topbar-title");if(0!==t.length&&!t.hasClass("dynamic-title")&&!n.is(":hidden")){const s=n.text().trim();let a=t.text().trim(),r=!1,l=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),t.offset().top<$(window).scrollTop()&&n.text(a);let e=new IntersectionObserver(e=>{var o,t;r?(o=$(window).scrollTop(),t=l<o,l=o,e=e[0],t?0===e.intersectionRatio&&n.text(a):1===e.intersectionRatio&&n.text(s)):r=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]});e.observe(document.querySelector(o)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}}),$(function(){const e=$(".collapse");e.on("hide.bs.collapse",function(){var e="h_"+$(this).attr("id").substring("l_".length);e&&($(`#${e} .far.fa-folder-open`).attr("class","far fa-folder fa-fw"),$(`#${e} i.fas`).addClass("rotate"),$("#"+e).removeClass("hide-border-bottom"))}),e.on("show.bs.collapse",function(){var e="h_"+$(this).attr("id").substring("l_".length);e&&($(`#${e} .far.fa-folder`).attr("class","far fa-folder-open fa-fw"),$(`#${e} i.fas`).removeClass("rotate"),$("#"+e).addClass("hide-border-bottom"))})});
$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$(".mode-toggle").click(o=>{const e=$(o.target);let t=e.prop("tagName")==="button".toUpperCase()?e:e.parent();t.blur(),flipMode()})});const ScrollHelper=function(){const o=$("body"),e="data-topbar-visible",t=$("#topbar-wrapper").outerHeight();let l=0,a=!1,r=!1;return{hideTopbar:()=>o.attr(e,!1),showTopbar:()=>o.attr(e,!0),addScrollUpTask:()=>{l+=1,a=a||!0},popScrollUpTask:()=>--l,hasScrollUpTask:()=>0<l,topbarLocked:()=>!0===a,unlockTopbar:()=>a=!1,getTopbarHeight:()=>t,orientationLocked:()=>!0===r,lockOrientation:()=>r=!0,unLockOrientation:()=>r=!1}}();$(function(){const o=$("#sidebar-trigger"),e=$("#search-trigger"),t=$("#search-cancel"),l=$("#main"),a=$("#topbar-title"),r=$("#search-wrapper"),n=$("#search-result-wrapper"),s=$("#search-results"),i=$("#search-input"),c=$("#search-hints"),d=function(){let o=0;return{block(){o=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(o)},getOffset(){return o}}}(),p={on(){o.addClass("unloaded"),a.addClass("unloaded"),e.addClass("unloaded"),r.addClass("d-flex"),t.addClass("loaded")},off(){t.removeClass("loaded"),r.removeClass("d-flex"),o.removeClass("unloaded"),a.removeClass("unloaded"),e.removeClass("unloaded")}},f=function(){let o=!1;return{on(){o||(d.block(),n.removeClass("unloaded"),l.addClass("unloaded"),o=!0)},off(){o&&(s.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),l.removeClass("unloaded"),d.release(),i.val(""),o=!1)},isVisible(){return o}}}();function u(){return t.hasClass("loaded")}e.click(function(){p.on(),f.on(),i.focus()}),t.click(function(){p.off(),f.off()}),i.focus(function(){r.addClass("input-focus")}),i.focusout(function(){r.removeClass("input-focus")}),i.on("input",()=>{""===i.val()?u()?c.removeClass("unloaded"):f.off():(f.on(),u()&&c.addClass("unloaded"))})}),$(function(){var o=function(){const o="sidebar-display";let e=!1;const t=$("body");return{toggle(){!1===e?t.attr(o,""):t.removeAttr(o),e=!e}}}();$("#sidebar-trigger").click(o.toggle),$("#mask").click(o.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#search-input"),t=ScrollHelper.getTopbarHeight();let o,l=0;function a(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var o=screen.orientation.type;"landscape-primary"!==o&&"landscape-secondary"!==o||a()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&a()}),$(window).scroll(()=>{o=o||!0}),setInterval(()=>{o&&(!function(){var o=$(this).scrollTop();if(!(Math.abs(l-o)<=t)){if(o>l)ScrollHelper.hideTopbar(),e.is(":focus")&&e.blur();else if(o+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}l=o}}(),o=!1)},250)}),$(function(){var e="div.post>h1:first-of-type";const t=$(e),n=$("#topbar-title");if(0!==t.length&&!t.hasClass("dynamic-title")&&!n.is(":hidden")){const s=n.text().trim();let l=t.text().trim(),a=!1,r=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(l)&&(l=l.replace(/[0-9]/g,"").trim()),t.offset().top<$(window).scrollTop()&&n.text(l);let o=new IntersectionObserver(o=>{var e,t;a?(t=$(window).scrollTop(),e=r<t,r=t,t=o[0],e?0===t.intersectionRatio&&n.text(l):1===t.intersectionRatio&&n.text(s)):a=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]});o.observe(document.querySelector(e)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}}),$(function(){const o=$(".collapse");o.on("hide.bs.collapse",function(){var o="h_"+$(this).attr("id").substring("l_".length);o&&($(`#${o} .far.fa-folder-open`).attr("class","far fa-folder fa-fw"),$(`#${o} i.fas`).addClass("rotate"),$("#"+o).removeClass("hide-border-bottom"))}),o.on("show.bs.collapse",function(){var o="h_"+$(this).attr("id").substring("l_".length);o&&($(`#${o} .far.fa-folder`).attr("class","far fa-folder-open fa-fw"),$(`#${o} i.fas`).removeClass("rotate"),$("#"+o).addClass("hide-border-bottom"))})});

View File

@ -1,6 +1,6 @@
/*!
* Chirpy v5.1.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* Chirpy v5.2.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* © 2019 Cotes Chung
* MIT Licensed
*/
$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))});const LocaleHelper=function(){const e=$('meta[name="prefer-datetime-locale"]'),o=0<e.length?e.attr("content").toLowerCase():$("html").attr("lang").substr(0,2),t="data-ts",a="data-df";return{locale:()=>o,attrTimestamp:()=>t,attrDateFormat:()=>a,getTimestamp:e=>Number(e.attr(t)),getDateFormat:e=>e.attr(a)}}();$(function(){$(".mode-toggle").click(e=>{const o=$(e.target);let t=o.prop("tagName")==="button".toUpperCase()?o:o.parent();t.blur(),flipMode()})});const ScrollHelper=function(){const e=$("body"),o="data-topbar-visible",t=$("#topbar-wrapper").outerHeight();let a=0,r=!1,l=!1;return{hideTopbar:()=>e.attr(o,!1),showTopbar:()=>e.attr(o,!0),addScrollUpTask:()=>{a+=1,r=r||!0},popScrollUpTask:()=>--a,hasScrollUpTask:()=>0<a,topbarLocked:()=>!0===r,unlockTopbar:()=>r=!1,getTopbarHeight:()=>t,orientationLocked:()=>!0===l,lockOrientation:()=>l=!0,unLockOrientation:()=>l=!1}}();$(function(){const e=$("#sidebar-trigger"),o=$("#search-trigger"),t=$("#search-cancel"),a=$("#main"),r=$("#topbar-title"),l=$("#search-wrapper"),n=$("#search-result-wrapper"),s=$("#search-results"),c=$("#search-input"),i=$("#search-hints"),d=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),p={on(){e.addClass("unloaded"),r.addClass("unloaded"),o.addClass("unloaded"),l.addClass("d-flex"),t.addClass("loaded")},off(){t.removeClass("loaded"),l.removeClass("d-flex"),e.removeClass("unloaded"),r.removeClass("unloaded"),o.removeClass("unloaded")}},u=function(){let e=!1;return{on(){e||(d.block(),n.removeClass("unloaded"),a.addClass("unloaded"),e=!0)},off(){e&&(s.empty(),i.hasClass("unloaded")&&i.removeClass("unloaded"),n.addClass("unloaded"),a.removeClass("unloaded"),d.release(),c.val(""),e=!1)},isVisible(){return e}}}();function f(){return t.hasClass("loaded")}o.click(function(){p.on(),u.on(),c.focus()}),t.click(function(){p.off(),u.off()}),c.focus(function(){l.addClass("input-focus")}),c.focusout(function(){l.removeClass("input-focus")}),c.on("input",()=>{""===c.val()?f()?i.removeClass("unloaded"):u.off():(u.on(),f()&&i.addClass("unloaded"))})}),$(function(){var e=function(){const e="sidebar-display";let o=!1;const t=$("body");return{toggle(){!1===o?t.attr(e,""):t.removeAttr(e),o=!o}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const o=$("#search-input"),t=ScrollHelper.getTopbarHeight();let e,a=0;function r(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var e=screen.orientation.type;"landscape-primary"!==e&&"landscape-secondary"!==e||r()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&r()}),$(window).scroll(()=>{e=e||!0}),setInterval(()=>{e&&(function(){var e=$(this).scrollTop();if(!(Math.abs(a-e)<=t)){if(e>a)ScrollHelper.hideTopbar(),o.is(":focus")&&o.blur();else if(e+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}a=e}}(),e=!1)},250)}),$(function(){var o="div.post>h1:first-of-type";const t=$(o),n=$("#topbar-title");if(0!==t.length&&!t.hasClass("dynamic-title")&&!n.is(":hidden")){const s=n.text().trim();let a=t.text().trim(),r=!1,l=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),t.offset().top<$(window).scrollTop()&&n.text(a);let e=new IntersectionObserver(e=>{var o,t;r?(o=$(window).scrollTop(),t=l<o,l=o,e=e[0],t?0===e.intersectionRatio&&n.text(a):1===e.intersectionRatio&&n.text(s)):r=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]});e.observe(document.querySelector(o)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}});
$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$(".mode-toggle").click(o=>{const e=$(o.target);let t=e.prop("tagName")==="button".toUpperCase()?e:e.parent();t.blur(),flipMode()})});const ScrollHelper=function(){const o=$("body"),e="data-topbar-visible",t=$("#topbar-wrapper").outerHeight();let l=0,r=!1,a=!1;return{hideTopbar:()=>o.attr(e,!1),showTopbar:()=>o.attr(e,!0),addScrollUpTask:()=>{l+=1,r=r||!0},popScrollUpTask:()=>--l,hasScrollUpTask:()=>0<l,topbarLocked:()=>!0===r,unlockTopbar:()=>r=!1,getTopbarHeight:()=>t,orientationLocked:()=>!0===a,lockOrientation:()=>a=!0,unLockOrientation:()=>a=!1}}();$(function(){const o=$("#sidebar-trigger"),e=$("#search-trigger"),t=$("#search-cancel"),l=$("#main"),r=$("#topbar-title"),a=$("#search-wrapper"),n=$("#search-result-wrapper"),s=$("#search-results"),i=$("#search-input"),c=$("#search-hints"),d=function(){let o=0;return{block(){o=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(o)},getOffset(){return o}}}(),p={on(){o.addClass("unloaded"),r.addClass("unloaded"),e.addClass("unloaded"),a.addClass("d-flex"),t.addClass("loaded")},off(){t.removeClass("loaded"),a.removeClass("d-flex"),o.removeClass("unloaded"),r.removeClass("unloaded"),e.removeClass("unloaded")}},u=function(){let o=!1;return{on(){o||(d.block(),n.removeClass("unloaded"),l.addClass("unloaded"),o=!0)},off(){o&&(s.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),l.removeClass("unloaded"),d.release(),i.val(""),o=!1)},isVisible(){return o}}}();function f(){return t.hasClass("loaded")}e.click(function(){p.on(),u.on(),i.focus()}),t.click(function(){p.off(),u.off()}),i.focus(function(){a.addClass("input-focus")}),i.focusout(function(){a.removeClass("input-focus")}),i.on("input",()=>{""===i.val()?f()?c.removeClass("unloaded"):u.off():(u.on(),f()&&c.addClass("unloaded"))})}),$(function(){var o=function(){const o="sidebar-display";let e=!1;const t=$("body");return{toggle(){!1===e?t.attr(o,""):t.removeAttr(o),e=!e}}}();$("#sidebar-trigger").click(o.toggle),$("#mask").click(o.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#search-input"),t=ScrollHelper.getTopbarHeight();let o,l=0;function r(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var o=screen.orientation.type;"landscape-primary"!==o&&"landscape-secondary"!==o||r()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&r()}),$(window).scroll(()=>{o=o||!0}),setInterval(()=>{o&&(!function(){var o=$(this).scrollTop();if(!(Math.abs(l-o)<=t)){if(o>l)ScrollHelper.hideTopbar(),e.is(":focus")&&e.blur();else if(o+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}l=o}}(),o=!1)},250)}),$(function(){var e="div.post>h1:first-of-type";const t=$(e),n=$("#topbar-title");if(0!==t.length&&!t.hasClass("dynamic-title")&&!n.is(":hidden")){const s=n.text().trim();let l=t.text().trim(),r=!1,a=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(l)&&(l=l.replace(/[0-9]/g,"").trim()),t.offset().top<$(window).scrollTop()&&n.text(l);let o=new IntersectionObserver(o=>{var e,t;r?(t=$(window).scrollTop(),e=a<t,a=t,t=o[0],e?0===t.intersectionRatio&&n.text(l):1===t.intersectionRatio&&n.text(s)):r=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]});o.observe(document.querySelector(e)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}});

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
/*!
* Chirpy v5.1.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* Chirpy v5.2.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* © 2019 Cotes Chung
* MIT Licensed
*/
$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))});const LocaleHelper=function(){const e=$('meta[name="prefer-datetime-locale"]'),t=0<e.length?e.attr("content").toLowerCase():$("html").attr("lang").substr(0,2),o="data-ts",a="data-df";return{locale:()=>t,attrTimestamp:()=>o,attrDateFormat:()=>a,getTimestamp:e=>Number(e.attr(o)),getDateFormat:e=>e.attr(a)}}();$(function(){$(".mode-toggle").click(e=>{const t=$(e.target);let o=t.prop("tagName")==="button".toUpperCase()?t:t.parent();o.blur(),flipMode()})});const ScrollHelper=function(){const e=$("body"),t="data-topbar-visible",o=$("#topbar-wrapper").outerHeight();let a=0,r=!1,l=!1;return{hideTopbar:()=>e.attr(t,!1),showTopbar:()=>e.attr(t,!0),addScrollUpTask:()=>{a+=1,r=r||!0},popScrollUpTask:()=>--a,hasScrollUpTask:()=>0<a,topbarLocked:()=>!0===r,unlockTopbar:()=>r=!1,getTopbarHeight:()=>o,orientationLocked:()=>!0===l,lockOrientation:()=>l=!0,unLockOrientation:()=>l=!1}}();$(function(){const e=$("#sidebar-trigger"),t=$("#search-trigger"),o=$("#search-cancel"),a=$("#main"),r=$("#topbar-title"),l=$("#search-wrapper"),n=$("#search-result-wrapper"),s=$("#search-results"),i=$("#search-input"),c=$("#search-hints"),d=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),p={on(){e.addClass("unloaded"),r.addClass("unloaded"),t.addClass("unloaded"),l.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),l.removeClass("d-flex"),e.removeClass("unloaded"),r.removeClass("unloaded"),t.removeClass("unloaded")}},u=function(){let e=!1;return{on(){e||(d.block(),n.removeClass("unloaded"),a.addClass("unloaded"),e=!0)},off(){e&&(s.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),a.removeClass("unloaded"),d.release(),i.val(""),e=!1)},isVisible(){return e}}}();function f(){return o.hasClass("loaded")}t.click(function(){p.on(),u.on(),i.focus()}),o.click(function(){p.off(),u.off()}),i.focus(function(){l.addClass("input-focus")}),i.focusout(function(){l.removeClass("input-focus")}),i.on("input",()=>{""===i.val()?f()?c.removeClass("unloaded"):u.off():(u.on(),f()&&c.addClass("unloaded"))})}),$(function(){var e=function(){const e="sidebar-display";let t=!1;const o=$("body");return{toggle(){!1===t?o.attr(e,""):o.removeAttr(e),t=!t}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const t=$("#search-input"),o=ScrollHelper.getTopbarHeight();let e,a=0;function r(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var e=screen.orientation.type;"landscape-primary"!==e&&"landscape-secondary"!==e||r()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&r()}),$(window).scroll(()=>{e=e||!0}),setInterval(()=>{e&&(function(){var e=$(this).scrollTop();if(!(Math.abs(a-e)<=o)){if(e>a)ScrollHelper.hideTopbar(),t.is(":focus")&&t.blur();else if(e+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}a=e}}(),e=!1)},250)}),$(function(){var t="div.post>h1:first-of-type";const o=$(t),n=$("#topbar-title");if(0!==o.length&&!o.hasClass("dynamic-title")&&!n.is(":hidden")){const s=n.text().trim();let a=o.text().trim(),r=!1,l=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),o.offset().top<$(window).scrollTop()&&n.text(a);let e=new IntersectionObserver(e=>{var t,o;r?(t=$(window).scrollTop(),o=l<t,l=t,e=e[0],o?0===e.intersectionRatio&&n.text(a):1===e.intersectionRatio&&n.text(s)):r=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]});e.observe(document.querySelector(t)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}}),$(function(){dayjs.locale(LocaleHelper.locale()),dayjs.extend(window.dayjs_plugin_localizedFormat),$(`[${LocaleHelper.attrTimestamp()}]`).each(function(){const e=dayjs.unix(LocaleHelper.getTimestamp($(this)));var t=LocaleHelper.getDateFormat($(this)),t=e.format(t);$(this).text(t),$(this).removeAttr(LocaleHelper.attrTimestamp()),$(this).removeAttr(LocaleHelper.attrDateFormat())})});
$(function(){$(window).scroll(()=>{50<$(this).scrollTop()&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){$(".mode-toggle").click(e=>{const t=$(e.target);let o=t.prop("tagName")==="button".toUpperCase()?t:t.parent();o.blur(),flipMode()})});const ScrollHelper=function(){const e=$("body"),t="data-topbar-visible",o=$("#topbar-wrapper").outerHeight();let a=0,l=!1,r=!1;return{hideTopbar:()=>e.attr(t,!1),showTopbar:()=>e.attr(t,!0),addScrollUpTask:()=>{a+=1,l=l||!0},popScrollUpTask:()=>--a,hasScrollUpTask:()=>0<a,topbarLocked:()=>!0===l,unlockTopbar:()=>l=!1,getTopbarHeight:()=>o,orientationLocked:()=>!0===r,lockOrientation:()=>r=!0,unLockOrientation:()=>r=!1}}(),LocaleHelper=($(function(){const e=$("#sidebar-trigger"),t=$("#search-trigger"),o=$("#search-cancel"),a=$("#main"),l=$("#topbar-title"),r=$("#search-wrapper"),n=$("#search-result-wrapper"),s=$("#search-results"),i=$("#search-input"),c=$("#search-hints"),d=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset(){return e}}}(),p={on(){e.addClass("unloaded"),l.addClass("unloaded"),t.addClass("unloaded"),r.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),r.removeClass("d-flex"),e.removeClass("unloaded"),l.removeClass("unloaded"),t.removeClass("unloaded")}},u=function(){let e=!1;return{on(){e||(d.block(),n.removeClass("unloaded"),a.addClass("unloaded"),e=!0)},off(){e&&(s.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),n.addClass("unloaded"),a.removeClass("unloaded"),d.release(),i.val(""),e=!1)},isVisible(){return e}}}();function f(){return o.hasClass("loaded")}t.click(function(){p.on(),u.on(),i.focus()}),o.click(function(){p.off(),u.off()}),i.focus(function(){r.addClass("input-focus")}),i.focusout(function(){r.removeClass("input-focus")}),i.on("input",()=>{""===i.val()?f()?c.removeClass("unloaded"):u.off():(u.on(),f()&&c.addClass("unloaded"))})}),$(function(){var e=function(){const e="sidebar-display";let t=!1;const o=$("body");return{toggle(){!1===t?o.attr(e,""):o.removeAttr(e),t=!t}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const t=$("#search-input"),o=ScrollHelper.getTopbarHeight();let e,a=0;function l(){0!==$(window).scrollTop()&&(ScrollHelper.lockOrientation(),ScrollHelper.hideTopbar())}screen.orientation?screen.orientation.onchange=()=>{var e=screen.orientation.type;"landscape-primary"!==e&&"landscape-secondary"!==e||l()}:$(window).on("orientationchange",()=>{$(window).width()<$(window).height()&&l()}),$(window).scroll(()=>{e=e||!0}),setInterval(()=>{e&&(!function(){var e=$(this).scrollTop();if(!(Math.abs(a-e)<=o)){if(e>a)ScrollHelper.hideTopbar(),t.is(":focus")&&t.blur();else if(e+$(window).height()<$(document).height()){if(ScrollHelper.hasScrollUpTask())return;ScrollHelper.topbarLocked()?ScrollHelper.unlockTopbar():ScrollHelper.orientationLocked()?ScrollHelper.unLockOrientation():ScrollHelper.showTopbar()}a=e}}(),e=!1)},250)}),$(function(){var t="div.post>h1:first-of-type";const o=$(t),n=$("#topbar-title");if(0!==o.length&&!o.hasClass("dynamic-title")&&!n.is(":hidden")){const s=n.text().trim();let a=o.text().trim(),l=!1,r=0;($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),o.offset().top<$(window).scrollTop()&&n.text(a);let e=new IntersectionObserver(e=>{var t,o;l?(o=$(window).scrollTop(),t=r<o,r=o,o=e[0],t?0===o.intersectionRatio&&n.text(a):1===o.intersectionRatio&&n.text(s)):l=!0},{rootMargin:"-48px 0px 0px 0px",threshold:[0,1]});e.observe(document.querySelector(t)),n.click(function(){$("body,html").animate({scrollTop:0},800)})}}),function(){const e=$('meta[name="prefer-datetime-locale"]'),t=0<e.length?e.attr("content").toLowerCase():$("html").attr("lang").substr(0,2),o="data-ts",a="data-df";return{locale:()=>t,attrTimestamp:()=>o,attrDateFormat:()=>a,getTimestamp:e=>Number(e.attr(o)),getDateFormat:e=>e.attr(a)}}());$(function(){dayjs.locale(LocaleHelper.locale()),dayjs.extend(window.dayjs_plugin_localizedFormat),$(`[${LocaleHelper.attrTimestamp()}]`).each(function(){const e=dayjs.unix(LocaleHelper.getTimestamp($(this)));var t=e.format(LocaleHelper.getDateFormat($(this))),t=($(this).text(t),$(this).removeAttr(LocaleHelper.attrTimestamp()),$(this).removeAttr(LocaleHelper.attrDateFormat()),$(this).attr("data-toggle"));void 0!==t&&"tooltip"===t&&(t=e.format("llll"),$(this).attr("data-original-title",t))})});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
/*!
* Chirpy v5.1.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* Chirpy v5.2.0 (https://github.com/cotes2020/jekyll-theme-chirpy/)
* © 2019 Cotes Chung
* MIT Licensed
*/
const getInitStatus=function(){let t=!1;return()=>{var e=t;return t=t||!0,e}}(),PvOpts=function(){function t(e){return $(e).attr("content")}function e(e){e=t(e);return void 0!==e&&!1!==e}return{getProxyMeta(){return t("meta[name=pv-proxy-endpoint]")},getLocalMeta(){return t("meta[name=pv-cache-path]")},hasProxyMeta(){return e("meta[name=pv-proxy-endpoint]")},hasLocalMeta(){return e("meta[name=pv-cache-path]")}}}(),PvStorage=function(){const a={KEY_PV:"pv",KEY_PV_SRC:"pv_src",KEY_CREATION:"pv_created_date"},t={LOCAL:"same-origin",PROXY:"cors"};function r(e){return localStorage.getItem(e)}function o(e,t){localStorage.setItem(e,t)}function n(e,t){o(a.KEY_PV,e),o(a.KEY_PV_SRC,t),o(a.KEY_CREATION,(new Date).toJSON())}return{keysCount(){return Object.keys(a).length},hasCache(){return null!==localStorage.getItem(a.KEY_PV)},getCache(){return JSON.parse(localStorage.getItem(a.KEY_PV))},saveLocalCache(e){n(e,t.LOCAL)},saveProxyCache(e){n(e,t.PROXY)},isExpired(){let e=new Date(r(a.KEY_CREATION));return e.setHours(e.getHours()+1),Date.now()>=e.getTime()},isFromLocal(){return r(a.KEY_PV_SRC)===t.LOCAL},isFromProxy(){return r(a.KEY_PV_SRC)===t.PROXY},newerThan(e){return PvStorage.getCache().totalsForAllResults["ga:pageviews"]>e.totalsForAllResults["ga:pageviews"]},inspectKeys(){if(localStorage.length===PvStorage.keysCount())for(let e=0;e<localStorage.length;e++)switch(localStorage.key(e)){case a.KEY_PV:case a.KEY_PV_SRC:case a.KEY_CREATION:break;default:return void localStorage.clear()}else localStorage.clear()}}}();function countUp(t,a,r){if(t<a){let e=new CountUp(r,t,a);e.error?console.error(e.error):e.start()}}function countPV(t,a){let r=0;if(void 0!==a)for(let e=0;e<a.length;++e)if(a[parseInt(e,10)][0]===t){r+=parseInt(a[parseInt(e,10)][1],10);break}return r}function tacklePV(e,t,a,r){let o=countPV(t,e);o=0===o?1:o,r?(r=parseInt(a.text().replace(/,/g,""),10),o>r&&countUp(r,o,a.attr("id"))):a.text((new Intl.NumberFormat).format(o))}function displayPageviews(e){if(void 0!==e){let t=getInitStatus();const a=e.rows;0<$("#post-list").length?$(".post-preview").each(function(){var e=$(this).find("a").attr("href");tacklePV(a,e,$(this).find(".pageviews"),t)}):0<$(".post").length&&(e=window.location.pathname,tacklePV(a,e,$("#pv"),t))}}function fetchProxyPageviews(){PvOpts.hasProxyMeta()&&$.ajax({type:"GET",url:PvOpts.getProxyMeta(),dataType:"jsonp",jsonpCallback:"displayPageviews",success:e=>{PvStorage.saveProxyCache(JSON.stringify(e))},error:(e,t,a)=>{console.log("Failed to load pageviews from proxy server: "+a)}})}function fetchLocalPageviews(t=!1){return fetch(PvOpts.getLocalMeta()).then(e=>e.json()).then(e=>{t&&PvStorage.isFromProxy()&&PvStorage.newerThan(e)||(displayPageviews(e),PvStorage.saveLocalCache(JSON.stringify(e)))})}$(function(){$(".pageviews").length<=0||(PvStorage.inspectKeys(),PvStorage.hasCache()?(displayPageviews(PvStorage.getCache()),PvStorage.isExpired()?PvOpts.hasLocalMeta()?fetchLocalPageviews(!0).then(fetchProxyPageviews):fetchProxyPageviews():PvStorage.isFromLocal()&&fetchProxyPageviews()):PvOpts.hasLocalMeta()?fetchLocalPageviews().then(fetchProxyPageviews):fetchProxyPageviews())});
const getInitStatus=function(){let t=!1;return()=>{var e=t;return t=t||!0,e}}(),PvOpts=function(){function t(e){return $(e).attr("content")}function e(e){e=t(e);return void 0!==e&&!1!==e}return{getProxyMeta(){return t("meta[name=pv-proxy-endpoint]")},getLocalMeta(){return t("meta[name=pv-cache-path]")},hasProxyMeta(){return e("meta[name=pv-proxy-endpoint]")},hasLocalMeta(){return e("meta[name=pv-cache-path]")}}}(),PvStorage=function(){const a={KEY_PV:"pv",KEY_PV_SRC:"pv_src",KEY_CREATION:"pv_created_date"},t={LOCAL:"same-origin",PROXY:"cors"};function r(e){return localStorage.getItem(e)}function o(e,t){localStorage.setItem(e,t)}function n(e,t){o(a.KEY_PV,e),o(a.KEY_PV_SRC,t),o(a.KEY_CREATION,(new Date).toJSON())}return{keysCount(){return Object.keys(a).length},hasCache(){return null!==localStorage.getItem(a.KEY_PV)},getCache(){return JSON.parse(localStorage.getItem(a.KEY_PV))},saveLocalCache(e){n(e,t.LOCAL)},saveProxyCache(e){n(e,t.PROXY)},isExpired(){let e=new Date(r(a.KEY_CREATION));return e.setHours(e.getHours()+1),Date.now()>=e.getTime()},isFromLocal(){return r(a.KEY_PV_SRC)===t.LOCAL},isFromProxy(){return r(a.KEY_PV_SRC)===t.PROXY},newerThan(e){return PvStorage.getCache().totalsForAllResults["ga:pageviews"]>e.totalsForAllResults["ga:pageviews"]},inspectKeys(){if(localStorage.length!==PvStorage.keysCount())localStorage.clear();else for(let e=0;e<localStorage.length;e++)switch(localStorage.key(e)){case a.KEY_PV:case a.KEY_PV_SRC:case a.KEY_CREATION:break;default:return void localStorage.clear()}}}}();function countUp(t,a,r){if(t<a){let e=new CountUp(r,t,a);e.error?console.error(e.error):e.start()}}function countPV(t,a){let r=0;if(void 0!==a)for(let e=0;e<a.length;++e)if(a[parseInt(e,10)][0]===t){r+=parseInt(a[parseInt(e,10)][1],10);break}return r}function tacklePV(e,t,a,r){let o=countPV(t,e);o=0===o?1:o,r?(t=parseInt(a.text().replace(/,/g,""),10),o>t&&countUp(t,o,a.attr("id"))):a.text((new Intl.NumberFormat).format(o))}function displayPageviews(e){if(void 0!==e){let t=getInitStatus();const a=e.rows;0<$("#post-list").length?$(".post-preview").each(function(){var e=$(this).find("a").attr("href");tacklePV(a,e,$(this).find(".pageviews"),t)}):0<$(".post").length&&(e=window.location.pathname,tacklePV(a,e,$("#pv"),t))}}function fetchProxyPageviews(){PvOpts.hasProxyMeta()&&$.ajax({type:"GET",url:PvOpts.getProxyMeta(),dataType:"jsonp",jsonpCallback:"displayPageviews",success:e=>{PvStorage.saveProxyCache(JSON.stringify(e))},error:(e,t,a)=>{console.log("Failed to load pageviews from proxy server: "+a)}})}function fetchLocalPageviews(t=!1){return fetch(PvOpts.getLocalMeta()).then(e=>e.json()).then(e=>{t&&PvStorage.isFromProxy()&&PvStorage.newerThan(e)||(displayPageviews(e),PvStorage.saveLocalCache(JSON.stringify(e)))})}$(function(){$(".pageviews").length<=0||(PvStorage.inspectKeys(),PvStorage.hasCache()?(displayPageviews(PvStorage.getCache()),PvStorage.isExpired()?PvOpts.hasLocalMeta()?fetchLocalPageviews(!0).then(fetchProxyPageviews):fetchProxyPageviews():PvStorage.isFromLocal()&&fetchProxyPageviews()):PvOpts.hasLocalMeta()?fetchLocalPageviews().then(fetchProxyPageviews):fetchProxyPageviews())});

View File

@ -3,7 +3,58 @@ layout: compress
permalink: '/app.js'
---
/* Registering Service Worker */
if('serviceWorker' in navigator) {
navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}');
};
const keyWaiting = 'sw-waiting';
const $notification = $('#notification');
const $btnRefresh = $('#notification .toast-body>button');
function skipWating(registration) {
registration.waiting.postMessage('SKIP_WAITING');
localStorage.removeItem(keyWaiting);
}
if ('serviceWorker' in navigator) {
/* Registering Service Worker */
navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}')
.then(registration => {
if (registration) {
registration.addEventListener('updatefound', () => {
let serviceWorker = registration.installing;
serviceWorker.addEventListener('statechange', () => {
if (serviceWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
$notification.toast('show');
/* in case the user ignores the notification */
localStorage.setItem(keyWaiting, true);
}
}
});
});
$btnRefresh.click(() => {
skipWating(registration);
$notification.toast('hide');
});
if (localStorage.getItem(keyWaiting)) {
if (registration.waiting) {
/* there's a new Service Worker waiting to be activated */
$notification.toast('show');
} else {
/* closed all open pages after receiving notification */
localStorage.removeItem(keyWaiting);
}
}
}
});
let refreshing = false;
/* Detect controller change and refresh all the opened tabs */
navigator.serviceWorker.addEventListener('controllerchange', () => {
if (!refreshing) {
window.location.reload();
refreshing = true;
}
});
}

View File

@ -6,7 +6,7 @@ permalink: '/sw.js'
self.importScripts('{{ "/assets/js/data/swcache.js" | relative_url }}');
const cacheName = 'chirpy-{{ "now" | date: "%Y%m%d.%H%M" }}';
const cacheName = 'chirpy-{{ "now" | date: "%Y%m%d.%H%M%S" }}';
function verifyDomain(url) {
for (const domain of allowedDomains) {
@ -28,25 +28,42 @@ function isExcluded(url) {
return false;
}
self.addEventListener('install', e => {
self.skipWaiting();
e.waitUntil(
self.addEventListener('install', event => {
event.waitUntil(
caches.open(cacheName).then(cache => {
return cache.addAll(resource);
})
);
});
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(keyList => {
return Promise.all(
keyList.map(key => {
if (key !== cacheName) {
return caches.delete(key);
}
})
);
})
);
});
self.addEventListener('message', (event) => {
if (event.data === 'SKIP_WAITING') {
self.skipWaiting();
}
});
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
caches.match(event.request).then(response => {
if (response) {
return response;
}
return fetch(event.request)
.then(response => {
return fetch(event.request).then(response => {
const url = event.request.url;
if (event.request.method !== 'GET' ||
@ -60,8 +77,7 @@ self.addEventListener('fetch', event => {
*/
let responseToCache = response.clone();
caches.open(cacheName)
.then(cache => {
caches.open(cacheName).then(cache => {
/* console.log('[sw] Caching new resource: ' + event.request.url); */
cache.put(event.request, responseToCache);
});
@ -71,17 +87,3 @@ self.addEventListener('fetch', event => {
})
);
});
self.addEventListener('activate', e => {
e.waitUntil(
caches.keys().then(keyList => {
return Promise.all(
keyList.map(key => {
if(key !== cacheName) {
return caches.delete(key);
}
})
);
})
);
});

View File

@ -0,0 +1,12 @@
---
layout: compress
permalink: '/unregister.js'
---
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistrations().then((registrations) => {
for (let reg of registrations) {
reg.unregister();
}
});
}

View File

@ -34,7 +34,7 @@ const commonsJs = () => {
const homeJs = () => {
return concatJs([
`${JS_SRC}/commons/*.js`,
`${JS_SRC}/utils/timeago.js`
`${JS_SRC}/utils/locale-datetime.js`
],
'home'
);
@ -44,7 +44,7 @@ const postJs = () => {
return concatJs([
`${JS_SRC}/commons/*.js`,
`${JS_SRC}/utils/img-extra.js`,
`${JS_SRC}/utils/timeago.js`,
`${JS_SRC}/utils/locale-datetime.js`,
`${JS_SRC}/utils/checkbox.js`,
`${JS_SRC}/utils/clipboard.js`,
// 'smooth-scroll.js' must be called after ToC is ready

View File

@ -2,7 +2,7 @@
Gem::Specification.new do |spec|
spec.name = "jekyll-theme-chirpy"
spec.version = "5.1.0"
spec.version = "5.2.0"
spec.authors = ["Cotes Chung"]
spec.email = ["cotes.chung@gmail.com"]
@ -16,14 +16,14 @@ Gem::Specification.new do |spec|
spec.metadata = {
"bug_tracker_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy/issues",
"documentation_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/README.md",
"documentation_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy/#readme",
"homepage_uri" => "https://cotes2020.github.io/chirpy-demo",
"source_code_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy",
"wiki_uri" => "https://github.com/cotes2020/jekyll-theme-chirpy/wiki",
"plugin_type" => "theme"
}
spec.required_ruby_version = ">= 2.4"
spec.required_ruby_version = ">= 2.5"
spec.add_runtime_dependency "jekyll", "~> 4.1"
spec.add_runtime_dependency "jekyll-paginate", "~> 1.1"

View File

@ -1,6 +1,6 @@
{
"name": "jekyll-theme-chirpy",
"version": "5.1.0",
"version": "5.2.0",
"description": "A minimal, responsive, and powerful Jekyll theme for presenting professional writing.",
"repository": {
"type": "git",
@ -12,7 +12,7 @@
"url": "https://github.com/cotes2020/jekyll-theme-chirpy/issues"
},
"homepage": "https://github.com/cotes2020/jekyll-theme-chirpy#readme",
"dependencies": {
"devDependencies": {
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-insert": "^0.5.0",

View File

@ -1,106 +0,0 @@
#!/usr/bin/env bash
#
#
# 1. Bump latest version number to the following files:
#
# - _sass/jekyll-theme-chirpy.scss
# - _javascript/copyright
# - assets/js/dist/*.js (will be built by gulp later)
# - jekyll-theme-chirpy.gemspec
# - package.json
#
# 2. Then create a commit to automatically save the changes.
#
# Usage:
#
# Run on the default branch or hotfix branch
#
# Requires: Git, Gulp
set -eu
ASSETS=(
"_sass/jekyll-theme-chirpy.scss"
"_javascript/copyright"
)
GEM_SPEC="jekyll-theme-chirpy.gemspec"
NODE_META="package.json"
_check_src() {
if [[ ! -f $1 && ! -d $1 ]]; then
echo -e "Error: Missing file \"$1\"!\n"
exit -1
fi
}
check() {
if [[ -n $(git status . -s) ]]; then
echo "Error: Commit unstaged files first, and then run this tool againt."
exit -1
fi
for i in "${!ASSETS[@]}"; do
_check_src "${ASSETS[$i]}"
done
_check_src "$NODE_META"
_check_src "$GEM_SPEC"
}
_bump_assets() {
for i in "${!ASSETS[@]}"; do
sed -i "s/v[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/v$1/" "${ASSETS[$i]}"
done
gulp
}
_bump_gemspec() {
sed -i "s/[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/$1/" "$GEM_SPEC"
}
_bump_node() {
sed -i \
"s,[\"]version[\"]: [\"][[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+[\"],\"version\": \"$1\"," \
$NODE_META
}
bump() {
_bump_assets "$1"
_bump_gemspec "$1"
_bump_node "$1"
if [[ -n $(git status . -s) ]]; then
git add .
git commit -m "Bump version to $1"
fi
}
main() {
check
_latest_tag="$(git describe --tags $(git rev-list --tags --max-count=1))"
echo "Input a version number (hint: latest version is ${_latest_tag:1})"
read -p "> " _version
[[ $_version =~ ^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]$ ]] ||
(
echo "Error: Illegal version number: '$_version'"
exit 1
)
if git tag --list | egrep -q "^v$_version$"; then
echo "Error: version '$_version' already exists"
exit 1
fi
echo -e "Bump version to $_version\n"
bump "$_version"
}
main

View File

@ -77,7 +77,7 @@ setup_gh() {
_no_pages_branch=true
git checkout -b "$PAGES_BRANCH"
else
git checkout "$PAGES_BRANCH"
git checkout -f "$PAGES_BRANCH"
fi
}

View File

@ -1,22 +1,44 @@
#!/usr/bin/env bash
#
# According to the GitLab flow release branching model,
# cherry-pick the last commit on the main branch to the release branch,
# and then create a tag and gem package on the release branch (naming format: 'release/<X.Y>').
# Release a new version to the GitLab flow production branch.
#
# For a new major/minor version, bump version on the main branch, and then merge into the production branch.
#
# For a patch version, bump the version number on the patch branch, then merge that branch into the main branch
# and production branch.
#
#
# Usage:
# Usage: run on main branch or the patch branch
#
# It can be run on main branch, and it should be used after just finishing the last feature in the version plan,
# or just after merging the hotfix to the main branch.
#
# Requires: Git, Gulp
# Requires: Git, NPM and RubyGems
set -eu
opt_pre=false # preview mode option
working_branch="$(git branch --show-current)"
STAGING_BRANCH="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')"
PROD_BRANCH="production"
GEM_SPEC="jekyll-theme-chirpy.gemspec"
opt_pre=false
NODE_CONFIG="package.json"
FILES=(
"_sass/jekyll-theme-chirpy.scss"
"_javascript/copyright"
"$GEM_SPEC"
"$NODE_CONFIG"
)
TOOLS=(
"git"
"npm"
"standard-version"
"gem"
)
help() {
echo "A tool to release new version Chirpy gem"
@ -26,19 +48,85 @@ help() {
echo " bash ./tools/release.sh [options]"
echo
echo "Options:"
echo " -p, --preview Enable preview mode, only pakcage, and will not modify the branches"
echo " -p, --preview Enable preview mode, only package, and will not modify the branches"
echo " -h, --help Print this information."
}
check() {
_check_git() {
# ensure nothing is uncommitted
if [[ -n $(git status . -s) ]]; then
echo "Error: Commit unstaged files first, and then run this tool againt."
exit -1
echo "Abort: Commit the staged files first, and then run this tool again."
exit 1
fi
if [[ ! -f $GEM_SPEC ]]; then
echo -e "Error: Missing file \"$GEM_SPEC\"!\n"
exit -1
# ensure the working branch is the main/patch branch
if [[ $working_branch != "$STAGING_BRANCH" && $working_branch != hotfix/* ]]; then
echo "Abort: Please run on the main branch or patch branches."
exit 1
fi
}
_check_src() {
if [[ ! -f $1 && ! -d $1 ]]; then
echo -e "Error: Missing file \"$1\"!\n"
exit 1
fi
}
_check_command() {
if ! command -v "$1" &>/dev/null; then
echo "Command '$1' not found"
exit 1
fi
}
_check_node_packages() {
if [[ ! -d node_modules || "$(du node_modules | awk '{print $1}')" == "0" ]]; then
npm i
fi
}
check() {
_check_git
for i in "${!FILES[@]}"; do
_check_src "${FILES[$i]}"
done
for i in "${!TOOLS[@]}"; do
_check_command "${TOOLS[$i]}"
done
_check_node_packages
}
_bump_file() {
for i in "${!FILES[@]}"; do
sed -i "s/v[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/v$1/" "${FILES[$i]}"
done
npx gulp
}
_bump_gemspec() {
sed -i "s/[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+/$1/" "$GEM_SPEC"
}
# 1. Bump latest version number to the following files:
#
# - _sass/jekyll-theme-chirpy.scss
# - _javascript/copyright
# - assets/js/dist/*.js (will be built by gulp later)
# - jekyll-theme-chirpy.gemspec
#
# 2. Create a commit to save the changes.
bump() {
_bump_file "$1"
_bump_gemspec "$1"
if [[ $opt_pre = false && -n $(git status . -s) ]]; then
git add .
git commit -m "chore(release): $1"
fi
}
@ -52,39 +140,91 @@ resume_config() {
mv _config.yml.bak _config.yml
}
release() {
_default_branch="$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')"
_version="$(grep "spec.version" jekyll-theme-chirpy.gemspec | sed 's/.*= "//;s/".*//')" # X.Y.Z
_release_branch="release/${_version%.*}"
if [[ $opt_pre = "false" ]]; then
# Modify the GitLab release branches
if [[ -z $(git branch -v | grep "$_release_branch") ]]; then
# create a new release branch
git checkout -b "$_release_branch"
# auto-generate a new version number to the file 'package.json'
standard_version() {
if $opt_pre; then
standard-version --prerelease rc
else
# cherry-pick the latest commit from default branch to release branch
_last_commit="$(git rev-parse "$_default_branch")"
git checkout "$_release_branch"
git cherry-pick "$_last_commit" -m 1
standard-version
fi
}
# Create a new tag
echo -e "Create tag v$_version\n"
git tag "v$_version"
fi
# Prevent changelogs generated on master branch from having duplicate content
# (the another bug of `standard-version`)
standard_version_plus() {
temp_branch="prod-mirror"
temp_dir="$(mktemp -d)"
# build a gem package
echo -e "Build the gem pakcage for v$_version\n"
git checkout -b "$temp_branch" "$PROD_BRANCH"
git merge --no-ff --no-edit "$STAGING_BRANCH"
standard_version
cp package.json CHANGELOG.md "$temp_dir"
git checkout "$STAGING_BRANCH"
git reset --hard HEAD # undo the changes from $temp_branch
mv "$temp_dir"/* . # rewrite the changelog
# clean up the temp stuff
rm -rf "$temp_dir"
git branch -D "$temp_branch"
}
# build a gem package
build_gem() {
echo -e "Build the gem package for v$_version\n"
cleanup_config
rm -f ./*.gem
gem build "$GEM_SPEC"
resume_config
}
# Update the git branch graph, tag, and then build the gem package.
release() {
_version="$1" # X.Y.Z
git checkout "$PROD_BRANCH"
git merge --no-ff --no-edit "$working_branch"
# Create a new tag on production branch
echo -e "Create tag v$_version\n"
git tag "v$_version"
# merge from patch branch to the staging branch
# NOTE: This may break due to merge conflicts, so it may need to be resolved manually.
if [[ $working_branch == hotfix/* ]]; then
git checkout "$STAGING_BRANCH"
git merge --no-ff --no-edit "$working_branch"
git branch -D "$working_branch"
fi
}
main() {
check
release
if [[ "$working_branch" == "$STAGING_BRANCH" ]]; then
standard_version_plus
else
standard_version
fi
# Change heading of Patch version to level 2 (a bug from `standard-version`)
sed -i "s/^### \[/## \[/g" CHANGELOG.md
_version="$(grep '"version":' package.json | sed 's/.*: "//;s/".*//')"
echo -e "Bump version number to $_version\n"
bump "$_version"
build_gem
if [[ $opt_pre = true ]]; then
# Undo all changes on Git
git reset --hard && git clean -fd
else
release "$_version"
fi
}
while (($#)); do