diff --git a/.github/workflows/pages-deploy.yml b/.github/workflows/pages-deploy.yml new file mode 100644 index 000000000000..e84439f61e17 --- /dev/null +++ b/.github/workflows/pages-deploy.yml @@ -0,0 +1,81 @@ +name: 'Automatic build' +on: + push: + branches: + - master + paths-ignore: + - .gitignore + - README.md + - LICENSE + +jobs: + continuous-delivery: + + runs-on: ubuntu-latest + + env: + GEMS_PATH: /tmp/bundle + + steps: + - uses: actions/setup-ruby@v1 + with: + ruby-version: 2.6.x + + - name: Install tools + run: | + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CC86BB64 + sudo add-apt-repository ppa:rmescandon/yq + sudo apt update + sudo apt install yq -y + + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Bundle Caching + id: bundle-cache + uses: actions/cache@v1 + with: + path: ${{ env.GEMS_PATH }} + key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Bundle config + run: | + bundle config path ${{ env.GEMS_PATH }} + + - name: Bundle Install + if: steps.bundle-cache.outputs.cache-hit != 'true' + run: | + bundle install + + - name: Bundle Install locally + if: steps.bundle-cache.outputs.cache-hit == 'true' + run: | + bundle install --local + + - name: Check baseurl + run: | + baseurl="$(grep '^baseurl:' _config.yml | yq r - baseurl)" + if [[ -n $baseurl ]]; then + echo "SPEC_TEST=_site_no_baseurl" >> $GITHUB_ENV + fi + + - name: Build Site + run: | + bash tools/build.sh + + if [[ -n $SPEC_TEST ]]; then + # Bypass the defects of htmlproofer + bash tools/build.sh -b "" -d "$SPEC_TEST" + fi + + - name: Test Site + run: | + bash tools/test.sh "$SPEC_TEST" + + - name: Deploy + run: | + bash tools/deploy.sh diff --git a/.gitignore b/.gitignore index 3b16889fd633..6c33261ad432 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ +# hidden files .* + +# python compiled files *.pyc # jekyll debug @@ -9,3 +12,6 @@ Gemfile.lock # yui-compressor *.jar + +# bundle cache +vendor diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index d8046c111ff9..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -language: ruby -rvm: 2.5.3 - -before_install: - - pyenv global 3.7.1 - -install: - - pip install --upgrade pip - - pip install ruamel.yaml - -script: - - >- - git clone https://${GH_TOKEN}@github.com/cotes2020/blog-builder.git - ../blog-builder --depth=1 -q - - cp -r ../blog-builder/framework/* . - - bash _cibuild.sh - -branches: - only: master - -git: - depth: false # for posts lastmod - -cache: - directories: - - vendor/bundle - -notifications: - email: - recipients: - - secure: "GdZFhI2fu6MHwHeGkI9AI8NJexfT+cncJKoOTBxrMPywxvfm6HZ1vZTOwLD9mwG4XZUSznruD4NwRiXMBKs/94n8Z2f0QagCp2is/TuQWBVDUn1bowTbx1S7da6I3qTBGyIHvQWySwFgJuK9/uUeHdQF9ojMejESKZWfc6NjlgYie3Us3ax+Lygq6o4x+8+YPqlC/XwEKUUMUpXZT8Yubxg+s1mLwY9zmp2kJwB1snf6u498FPCWtCuQdGc91HEL4McfUfevnkNKttJQFwdE+mFkLoLn1FcXN0WQ8hPVTQvD/5TaCvACuB1oQ4dm4cnnoIRC5iuQntkP2Am7jPLnHLwxHDqB8vLDNxi1phbfGTk89ffY4n5FirF7DiYIn7hDDbDBlE4++9Pv/i7xgLp9+NzAzz25tdcfKZfXujrwE6b/2NbtXer/eWXyi7d6V/qWO6x8m7/IerX2/VrbXyQIgTvIDe2sSAraM77MMIiQ2KS6yhPIfjyCsC1sokFNRqUWut2UkqMFKOmAnSi/jTQY6/t1aOXGHtVRwgjFoyvBTk9F9NElxt3mseK26Mad3yAv5xLqhqHPFZJbVHJ8dP6RQvWwuvMK1uSqobTl+t0qBvvdSbt1/Oc/ubN1T2clObx1faF2luoMFhRtN+H5s7wfEMrO+sJAuSZnAHuDRpDIwCs=" - on_success: never - -env: - global: - - secure: "QNAqDoDQ+mF/3DFxKbc7fnYa5+FysJTX9Vs4XneH6iH63MS2lNtHfC7uT/M0/sRJaygK9eAdb+RaIeADE7CAMzqP3qdWx7l2N6qWab/kyK9KujUBsvoTGX6lDQTwC2Z+zlr5uUScHfLOhqHh6dbm6glziy2NB4dn9pVBXQrmBn09Rf9LImRT2u2h8gzmdl19hZ9TsW1/ROOb/1Soc3JElGRPrIxKI7ufHLQZt0UzZkYXGejQJwtstEEkRSmhfkJjlASeaeuyOFBvkWXjL1nKPsElwEKsAR+4II98JKA83YVqa9TJT2YSnXeLEFIhYDVSG6RLAMEU4rrITzRYC/hWKBKje4G0PDEM/cpnytk9Xhq+7oUFRmXCq3ZQgTQgzWhzl1kExC8b96hiWmQ+lVCw+Q2BG6+NloEEuOHOM839CTXfiitjRJ8KYUdLgW6IaruaingySBsbh1Vl+Dhu73QZ5H40KLdIH6woLXWAgtxkjpaL6DTeWDO6xMiwDreBa/2CJRT5R1tiG45CurZ+AkQ+yAAfSOEwGtE29oZl0sWeWMwVTaAClc0IJaG1+h8jxIVuQqHvK3fzd5RdlDtShrfCCVvQD0n29wXrdeNEg90F92kvdtmw8XgKc2P/Cl5uNzvVeTbFF3ZIHYpCVV4LW4Hn8clgYu+WUa/w4pVrBSdQOUw=" \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 000000000000..a708b68e1108 --- /dev/null +++ b/404.html @@ -0,0 +1,25 @@ +--- +# The 404 page +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +layout: page +title: "404: Page not found" +permalink: /404.html + +redirect_from: # part of site.sitemap_exclude + - /norobots/ + - /assets/ + - /tabs/ + - /categories/ + - /tags/ + - /posts/ + +dynamic_title: true +--- + +
+

Sorry, we've misplaced that URL or it's pointing to something that doesn't exist.

+

Head back Home to try finding it again, or search for it on the Archives page.

+
\ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 000000000000..c068cc01440a --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +x2python.com diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000000..7a2f0504e89c --- /dev/null +++ b/Gemfile @@ -0,0 +1,14 @@ +source "https://rubygems.org" + +gem "jekyll", ">=3.8.6" + +# Official Plugins +group :jekyll_plugins do + gem "jekyll-paginate" + gem "jekyll-redirect-from" + gem "jekyll-seo-tag", "~> 2.6.1" +end + +group :test do + gem "html-proofer" +end diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000000..299d89fd89c8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 Cotes Chung + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 2b626256cdb5..e10174c38f67 100644 --- a/README.md +++ b/README.md @@ -1,55 +1,202 @@ -# Jekyll Theme Chirpy +# Chirpy -[![Build Status](https://travis-ci.com/cotes2020/jekyll-theme-chirpy.svg?branch=master)](https://travis-ci.com/cotes2020/jekyll-theme-chirpy) +🌏 English • [简体中文](docs/README_zh-CN.md) + +[![Build Status](https://github.com/cotes2020/jekyll-theme-chirpy/workflows/build/badge.svg?branch=master&event=push)](https://github.com/cotes2020/jekyll-theme-chirpy/actions?query=branch%3Amaster+event%3Apush) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/8220b926db514f13afc3f02b7f884f4b)](https://app.codacy.com/manual/cotes2020/jekyll-theme-chirpy?utm_source=github.com&utm_medium=referral&utm_content=cotes2020/jekyll-theme-chirpy&utm_campaign=Badge_Grade_Dashboard) [![GitHub license](https://img.shields.io/github/license/cotes2020/jekyll-theme-chirpy.svg)](https://github.com/cotes2020/jekyll-theme-chirpy/blob/master/LICENSE) -[![996.icu](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu) +[![996.icu](https://img.shields.io/badge/link-996.icu-%23FF4D5B.svg)](https://996.icu) + +A minimal, sidebar, responsive web design Jekyll theme, focusing on text presentation, aim to help you easily record and share your knowledge. [Live Demo »](https://chirpy.cotes.info) -![devices-mockup](assets/img/sample/devices-mockup.png) +[![Devices Mockup](https://raw.githubusercontent.com/cotes2020/jekyll-theme-chirpy/master/assets/img/sample/devices-mockup.png)](https://chirpy.cotes.info) -A Jekyll theme with responsive web design that focuses on text presentation. [Live Demo »](https://chirpy.cotes.info) +## Table of Contents + +- [Features](#features) +- [Installation](#installation) +- [Usage](#usage) +- [Contributing](#contributing) +- [Credits](#credits) +- [Support](#support) +- [License](#license) ## Features -* Last modified date -* Table of Contents -* Disqus Comments -* Syntax highlighting -* Two Level Categories -* Search -* HTML compress -* Atom feeds -* Google Analytics -* Pageviews (Advanced) +- Pinned Posts +- Configurable theme mode +- Double-level Categories +- Last modified date for posts +- Table of Contents +- Automatically recommend related posts +- Syntax highlighting +- Mathematical expressions +- Search +- Atom Feeds +- Disqus Comments +- Google Analytics +- GA Pageviews reporting (Advanced) +- SEO and Performance Optimization + +## Installation + +[Fork **Chirpy**](https://github.com/cotes2020/jekyll-theme-chirpy/fork) on GitHub, rename the repository to `USERNAME.github.io` (where `USERNAME` is your GitHub username), and then open terminal and clone the fork to local by: + +```terminal +$ git clone https://github.com/USERNAME/USERNAME.github.io.git -b master --single-branch +``` + +### Setting up the local envrionment + +If you would like to run or build the project on your local machine, please follow the [Jekyll Docs](https://jekyllrb.com/docs/installation/) to complete the installation of `Ruby`, `RubyGems` and `Bundler`. -## Quick start +Before running or building for the first time, please complete the installation of the Jekyll plugins. Go to the root directory of project and run: -First of all, complete the installation of the following environment dependencies: +```terminal +$ bundle install +``` -- [Ruby](https://www.ruby-lang.org/en/downloads/) -- [RubyGem](https://rubygems.org/pages/download) -- [Bundler](https://bundler.io/) -- [Jekyll](https://jekyllrb.com/) -- [Python](https://www.python.org/downloads/) -- [ruamel.yaml](https://pypi.org/project/ruamel.yaml/) +`bundle` will automatically install all the dependencies specified by `Gemfile`. -Clone the repository locally, but to prevent losing the latest features, consider using **Fork** instead of cloning. +In order to generate some extra files (_categories_, _tags_ and _last modified list_), we need to use some tool scripts. And they require dependency package [yq](https://github.com/mikefarah/yq#install) to be installed. What's more, if your machine is running Debian or macOS, you also need to install [GNU coreutils](https://www.gnu.org/software/coreutils/). -Install the Jekyll plugins: +- on Debian: + ```console + $ sudo apt-get install coreutils + ``` + +- on macOS: + + ```console + $ brew install coreutils + ``` + +### Setting up Docker environment (optional) + +If you're a loyal fan of [**Docker**](https://www.docker.com/) or just too lazy to install the packages mentioned in [_Setting up the local envrionment_](#setting-up-the-local-envrionment), please make sure you have **Docker Engine** installed and running, and then get Docker image `jekyll/jekyll` from Docker Hub by the following command: + +```console +$ docker pull jekyll/jekyll:latest ``` -$ bundle install + +## Usage + +Running [**Chirpy**](https://github.com/cotes2020/jekyll-theme-chirpy/) requires some extra files, which cannot be generated by Jekyll native commands, so please strictly follow the methods mentioned below to run or deploy your website. + +### Initialization + +Go to the root directory of the project and start initialization: + +```console +$ bash tools/init.sh ``` -Boot your site locally: +> **Note**: If you not intend to deploy it on GitHub Pages, append parameter option `--no-gh` at the end of the above command. + +What it does is: + +1. Remove some files or directories from your repository: + + - `.travis.yml` + - files under `_posts` + - folder `docs` + +2. If you use the `--no-gh` option, the directory `.github` will be deleted. Otherwise, setup the GitHub Action workflow by removing extension `.hook` of `.github/workflows/pages-deploy.yml.hook`, and then remove the other files and directories in folder `.github`. +3. Automatically create a commit to save the changes. + +### Configuration + +Generally, go to `_config.yml` and configure the variables as needed. Some of them are typical options: + +- `url` +- `avatar` +- `timezone` +- `theme_mode` + +### Run Locally + +You may want to preview the site contents before publishing, so just run it by: + +```terminal +$ bash tools/run.sh ``` -$ bash run.sh + +Then open a browser and visit to . + +Few days later, you may find that the file changes does not refresh in real time by using `run.sh`. Don't worry, the advanced option `-r` (or `--realtime`) will solve this problem, but it requires [**fswatch**](http://emcrisostomo.github.io/fswatch/) to be installed on your machine. + +### Run on Docker + +Run the site on Docker with the following command: + +```terminal +$ docker run --rm -it \ + --volume="$PWD:/srv/jekyll" \ + -p 4000:4000 jekyll/jekyll \ + bash tools/run.sh --docker ``` -Now, open your favorite brower and visit +Please note that on Docker containers, you'll lose the real-time refresh feature. + +### Deployment + +Before the deployment begins, checkout the file `_config.yml` and make sure the `url` is configured correctly. Furthermore, if you prefer the [_project site_](https://help.github.com/en/github/working-with-github-pages/about-github-pages#types-of-github-pages-sites) and don't use a custom domain, or you want to visit your website with a base url on a web server other than **GitHub Pages**, remember to change the `baseurl` to your project name that starting with a slash. For example, `/project`. + +Assuming you have already gone through the [initialization](#initialization), you can now choose ONE of the following methods to deploy your website. + +#### Deploy on GitHub Pages + +For security reasons, GitHub Pages build runs on `safe` mode, which restricts us from using tool scripts to generate additional page files. Therefore, we can use **GitHub Actions** to build the site, store the built site files on a new branch, and use that branch as the source of the Pages service. + +1. Push any commit to `origin/master` to trigger the GitHub Actions workflow. Once the build is complete and successful, a new remote branch named `gh-pages` will appear to store the built site files. + +2. Browse to your repository on GitHub and choose the branch `gh-pages` as the [publishing source](https://docs.github.com/en/github/working-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site) throught _Settings_ → _Options_ → _GitHub Pages_: + ![gh-pages-sources](https://raw.githubusercontent.com/cotes2020/jekyll-theme-chirpy/master/assets/img/sample/gh-pages-sources.png) + +3. Visit your website at the address indicated by GitHub. + +#### Deploy on Other Platforms + +On platforms other than GitHub, we cannot enjoy the convenience of **GitHub Actions**. Therefore, we should build the site locally (or on some other 3rd-party CI platform) and then put the site files on the server. + +Go to the root of the source project, build your site by: + +```console +$ bash tools/build.sh +``` + +> **Note**: The output path can be specified with the option `-d`. + +Or, build the site with Docker by: + +```terminal +$ docker run --rm -it \ + --volume="$PWD:/srv/jekyll" \ + jekyll/jekyll \ + bash tools/build.sh --docker +``` + +Unless you specified the output path, the generated site files will be placed in folder `_site` of the project's root directory. Now you should upload those files to your web server. + +### Documentation + +For more details and the better reading experience, please check out the [tutorials on demo site](https://chirpy.cotes.info/categories/tutorial/). In the meanwhile, a copy of the tutorial is also available on the [Wiki](https://github.com/cotes2020/jekyll-theme-chirpy/wiki). + +## Contributing + +The old saying, "Two heads are better than one." Consequently, welcome to report bugs, improve code quality or submit a new feature. For more information, see [contributing guidelines](.github/CONTRIBUTING.md). + +## Credits + +This theme is mainly built with [Jekyll](https://jekyllrb.com/) ecosystem, [Bootstrap](https://getbootstrap.com/), [Font Awesome](https://fontawesome.com/) and some other wonderful tools (their copyright information can be found in the relevant files). + +:tada: Thanks to all the volunteers who contributed to this project, their GitHub IDs are on [this list](https://github.com/cotes2020/jekyll-theme-chirpy/graphs/contributors). Also, I won't forget those guys who submitted the issues or unmerged PR because they reported bugs, shared ideas or inspired me to write more readable documentation. -Please refer to the [documentation](https://chirpy.cotes.info/posts/getting-started/) for more details. Hope you like it. +## Support +If you enjoy this theme or find it helpful, please consider becoming my sponsor, I'd really appreciate it! Click the button :heart: Sponsor at the top of the [Home Page](https://github.com/cotes2020/jekyll-theme-chirpy) and choose a link that suits you to donate; this will encourage and help me better maintain the project. ## License diff --git a/_config.yml b/_config.yml new file mode 100644 index 000000000000..5b743d5b3ed9 --- /dev/null +++ b/_config.yml @@ -0,0 +1,195 @@ +# The Site Settings +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT licensed + + +# jekyll-seo-tag settings › https://github.com/jekyll/jekyll-seo-tag/blob/master/docs/usage.md +#-------------------------- + +title: Data Focused Python # the main title + +tagline: A practical approach. # it will display as the sub-title + +description: >- # used by seo meta and the atom feed + Data focused python site to diplay a practical approach to learning python + +# Replace with the website url, e.g. 'https://username.github.io' +url: 'https://x2python.com' + +author: Erick Rodriguez # change to your full name + +avatar: /assets/img/favicons/ms-icon-310x310.png # support internet resources + +github: + username: erickger # change to your github username + +social: + name: Erick Rodriguez # it will shows as the copyright owner in Footer + email: egrodriguezal@gmail.com # change to your email address + links: + # The first element serves as the copyright owner's link + - https://twitter.com/erickger # change to your twitter homepage + - https://github.com/erickger # change to your github homepage + # Uncomment below to add more social links + # - https://www.facebook.com/username + - https://www.linkedin.com/in/erickger-rodriguez + +google_site_verification: google_meta_tag_verification # change to your verification string + +#-------------------------- + + +# Only if your site type is GitHub Project sites and doesn't have a custom domain, +# change below value to '/projectname'. +baseurl: '' + +# Change to your timezone › http://www.timezoneconverter.com/cgi-bin/findzone/findzone +timezone: Australia/Adelaide + +google_analytics: + id: '' # Fill with your Google Analytics ID + pv: + # The Google Analytics pageviews switch. + # DO NOT enable it unless you know how to deploy the Google Analytics superProxy. + enabled: false + # the next options only valid when `google_analytics.pv` is enabled. + proxy_url: '' + proxy_endpoint: '' + cache: false # pv data local cache, good for the users from GFW area. + +disqus: + comments: true # boolean type, the global switch for posts comments. + shortname: 'x2python' # Fill with your Disqus shortname. › https://help.disqus.com/en/articles/1717111-what-s-a-shortname + + +# Prefer color scheme setting, available values: +# +# dual - Follow the system prefer color by default, and a toggle will display +# in the left bottom of Sidebar, which used for switch the theme between dark and light. +# +# light - Use the light color scheme +# +# dark - Use the dark color scheme +# +theme_mode: dual + +# boolean type, global switch for ToC in posts. +toc: true + +paginate: 10 + +markdown: kramdown + +highlighter: rouge + +kramdown: + input: GFM + syntax_highlighter: rouge + syntax_highlighter_opts: # Rouge Options › https://github.com/jneen/rouge#full-options + css_class: 'highlight' + # default_lang: console + span: + line_numbers: false + block: + line_numbers: true + start_line: 1 + +# DO NOT change this unless you're a Pro user on Jekyll and Web development, +# or you think you're smart enough to change other relevant URLs within this template. +permalink: /posts/:title/ + +defaults: + - + scope: + path: "" # An empty string here means all files in the project + type: posts + values: + layout: post + comments: true # Enable comments in posts. + toc: true # Display TOC column in posts. + location: Post + breadcrumb: + - + label: Posts + url: / + - + scope: + path: _drafts + values: + comments: false + - + scope: + path: tags + values: + tab_active: Tags + location: Tag + breadcrumb: + - + label: Home + url: / + - + label: Tags + url: /tabs/tags/ + - + scope: + path: categories + values: + tab_active: Categories + location: Category + breadcrumb: + - + label: Home + url: / + - + label: Categories + url: /tabs/categories/ + - + scope: + path: tabs + values: + layout: page + dynamic_title: true # Hide title in mobile screens. + breadcrumb: + - + label: Home + url: / + + +sass: + sass_dir: /assets/css + style: compressed + +compress_html: + clippings: all + comments: all + endings: all + profile: false + blanklines: false + ignore: + envs: [] + +exclude: + - vendor # Avoid Jekyll mistakenly read the vendor directory on Travis-CI's VM . + - Gemfile.lock + - Gemfile + - tools + - docs + - README.md + - LICENSE + +sitemap_exclude: # Sitemap will exclude the following items. + fuzzy: + - /assets/ + accurate: + - /norobots/ + - /tabs/ + - /categories/ + - /tags/ + - /posts/ + - 404.html + - feed.xml + - sitemap.xml + - robots.txt + - redirects.json diff --git a/_data/contact.yml b/_data/contact.yml new file mode 100644 index 000000000000..88f9a6bbd88a --- /dev/null +++ b/_data/contact.yml @@ -0,0 +1,34 @@ +# The contact options. +# v2.3 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed + +- + type: github + icon: 'fab fa-github-alt' +- + type: twitter + icon: 'fab fa-twitter' +- + type: email + icon: 'fas fa-envelope' + noblank: true # open link in current tab +- + type: rss + icon: 'fas fa-rss' + noblank: true + +# Uncomment and complete the url below to enable more contact options +# - +# type: mastodon +# icon: 'fab fa-mastodon' # icons powered by +# url: '' # Fill with your mastodon account page +# - +# type: linkedin +# icon: 'fab fa-linkedin' # icons powered by +# url: '' # Fill with your Linkedin homepage +# - +# type: stack-overflow +# icon: 'fab fa-stack-overflow' +# url: '' # Fill with your stackoverflow homepage diff --git a/_data/date_format.yml b/_data/date_format.yml new file mode 100644 index 000000000000..0a984ffae6fa --- /dev/null +++ b/_data/date_format.yml @@ -0,0 +1,11 @@ +# The date format +# v2.1 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed + + +tooltip: "%a, %b %e, %Y, %l:%M %p %z" +post: + long: "%b %e, %Y" + short: "%b %e" diff --git a/_data/label.yml b/_data/label.yml new file mode 100644 index 000000000000..53761bc7bd63 --- /dev/null +++ b/_data/label.yml @@ -0,0 +1,19 @@ +# The label text of site. +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT Licensed + + +panel: + lastmod: "Recent Update" + trending_tags: "Trending Tags" + toc: "Contents" + +post: + relate_posts: "Further Reading" + button: + next: Newer + previous: Older + +search_hint: "Search" # text show on search bar \ No newline at end of file diff --git a/_data/meta.yml b/_data/meta.yml new file mode 100644 index 000000000000..7842dce8fc8c --- /dev/null +++ b/_data/meta.yml @@ -0,0 +1,3 @@ +name: Chirpy +version: v2.5.1 +homepage: https://github.com/cotes2020/jekyll-theme-chirpy/ diff --git a/_data/rights.yml b/_data/rights.yml new file mode 100644 index 000000000000..bedc283d9db4 --- /dev/null +++ b/_data/rights.yml @@ -0,0 +1,17 @@ +# License data. +# +# v2.1 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed + + +license: + name: CC BY 4.0 + link: "https://creativecommons.org/licenses/by/4.0/" + +brief: Some rights reserved. + +verbose: >- + Except where otherwise noted, the blog posts on this site are licensed + under the Creative Commons Attribution 4.0 International (CC BY 4.0) License by the author. \ No newline at end of file diff --git a/_data/share.yml b/_data/share.yml new file mode 100644 index 000000000000..7bb7d8d3e649 --- /dev/null +++ b/_data/share.yml @@ -0,0 +1,34 @@ +# Sharing options at the bottom of the post. +# Icons from +# +# v2.1 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed + +label: "Share" + +platforms: + - + type: Twitter + icon: "fab fa-twitter" + link: "https://twitter.com/intent/tweet?text=TITLE&url=URL" + - + type: Facebook + icon: "fab fa-facebook-square" + link: "https://www.facebook.com/sharer/sharer.php?title=TITLE&u=URL" + - + type: Telegram + icon: "fab fa-telegram" + link: "https://telegram.me/share?text=TITLE&url=URL" + + # Uncomment below if you need to. + # - + # type: Linkedin + # icon: "fab fa-linkedin" + # link: "https://www.linkedin.com/sharing/share-offsite/?url=URL" + # + # - + # type: Weibo + # icon: "fab fa-weibo" + # link: "http://service.weibo.com/share/share.php?title=TITLE&url=URL" diff --git a/_data/tabs.yml b/_data/tabs.yml new file mode 100644 index 000000000000..0f6584109002 --- /dev/null +++ b/_data/tabs.yml @@ -0,0 +1,30 @@ +# The tab data. +# v2.1 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed + + +- + name: Home + icon: "fas fa-home" +- + name: Categories + icon: "fas fa-stream" + path: tabs + url: categories +- + name: "Tags" + icon: "fas fa-tags" + path: tabs + url: tags +- + name: "Archives" + path: tabs + url: archives + icon: "fas fa-archive" +- + name: "About" + icon: "fas fa-info" + path: tabs + url: about \ No newline at end of file diff --git a/_includes/css-selector.html b/_includes/css-selector.html new file mode 100644 index 000000000000..53e53db9991c --- /dev/null +++ b/_includes/css-selector.html @@ -0,0 +1,54 @@ + + +{% if page.layout == 'home' %} + + + +{% elsif page.layout == 'page' %} + + {% if page.type == 'categories' %} + + + + + {% elsif page.type == 'tags' %} + + + + + {% elsif page.type == 'archives' %} + + + + + {% else %} + + + + + {% endif %} + +{% elsif page.layout == 'category' or page.layout == 'tag' %} + + + + +{% elsif page.layout == 'post' %} + + + + + {% if site.toc and page.toc %} + + + + + {% endif %} + +{% endif %} diff --git a/_includes/disqus.html b/_includes/disqus.html new file mode 100644 index 000000000000..4b4b1495c25e --- /dev/null +++ b/_includes/disqus.html @@ -0,0 +1,28 @@ + + +
+

+ Comments powered by Disqus. +

+
+ + + \ No newline at end of file diff --git a/_includes/favicons.html b/_includes/favicons.html new file mode 100644 index 000000000000..a72cd5317caf --- /dev/null +++ b/_includes/favicons.html @@ -0,0 +1,36 @@ + + +{% capture icon_url %}{{ site.baseurl }}/assets/img/favicons{% endcapture %} + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_includes/footer.html b/_includes/footer.html new file mode 100644 index 000000000000..b327c3e603dc --- /dev/null +++ b/_includes/footer.html @@ -0,0 +1,33 @@ + + + diff --git a/_includes/google-analytics.html b/_includes/google-analytics.html new file mode 100644 index 000000000000..74bbc87080db --- /dev/null +++ b/_includes/google-analytics.html @@ -0,0 +1,16 @@ + + + + diff --git a/_includes/head.html b/_includes/head.html new file mode 100644 index 000000000000..439f0aafca9d --- /dev/null +++ b/_includes/head.html @@ -0,0 +1,69 @@ + + + + + + + + {% seo title=false %} + + + {%- unless page.layout == "home" -%} + {{ page.title | append: " | "}} + {%- endunless -%} + {{ site.title }} + + + {% include favicons.html %} + + + + + + + {% if jekyll.environment == 'production' %} + + + + + + + {% if site.google_analytics.pv.proxy_url and site.google_analytics.pv.enabled %} + + + {% endif %} + {% endif %} + + + + + + + + + + + + {% include css-selector.html %} + + + + + + + + {% include js-selector.html %} + + diff --git a/_includes/js-selector.html b/_includes/js-selector.html new file mode 100644 index 000000000000..62a36e69de62 --- /dev/null +++ b/_includes/js-selector.html @@ -0,0 +1,41 @@ + + +{% if page.layout == 'home' %} + + + +{% elsif page.layout == 'post' %} + + + + {% if page.math %} + + + + {% endif %} + +{% elsif page.layout == 'page' %} + + {% if page.type == 'categories' %} + + {% else %} + + {% endif %} + +{% else %} + + + +{% endif %} + + +{% if jekyll.environment == 'production' %} + + +{% endif %} diff --git a/_includes/lozad.html b/_includes/lozad.html new file mode 100644 index 000000000000..accfbfca2399 --- /dev/null +++ b/_includes/lozad.html @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/_includes/mode-toggle.html b/_includes/mode-toggle.html new file mode 100644 index 000000000000..44759d6d07f3 --- /dev/null +++ b/_includes/mode-toggle.html @@ -0,0 +1,118 @@ + + + + + + diff --git a/_includes/no-linenos.html b/_includes/no-linenos.html new file mode 100644 index 000000000000..0b3a1ece588d --- /dev/null +++ b/_includes/no-linenos.html @@ -0,0 +1,14 @@ +{% comment %} + Remove the line number of the code snippet. + v2.2 + https://github.com/cotes2020/jekyll-theme-chirpy + © 2020 Cotes Chung + Published under the MIT License +{% endcomment %} + +{% assign content = include.content %} + +{% if content contains '
' %}
+  {% assign content = content | replace: '
', '' %}
+{% endif %}
diff --git a/_includes/panel.html b/_includes/panel.html
new file mode 100644
index 000000000000..35997c2a48f6
--- /dev/null
+++ b/_includes/panel.html
@@ -0,0 +1,67 @@
+
+
+
+ +
+ + {% if site.data.updates %} + + {% include update-list.html %} + + {% if update_list.size > 0 %} + +
+ {{- site.data.label.panel.lastmod -}} +
    + + {% for item in update_list %} + {% assign post_url = item | split: "::" | last | url_encode | prepend: "/posts/" | append: "/" %} + {% assign post = site.posts | where: "url", post_url | first %} + + {% if post %} + {% assign url = post.url | relative_url %} +
  • {{ post.title }}
  • + {% endif %} + + {% endfor %} + +
+
+ + {% endif %} + + {% endif %} + + {% include trending-tags.html %} + + {% if trending_tags.size > 0 %} +
+ {{- site.data.label.panel.trending_tags -}} +
+ + {% for tag in trending_tags %} + {% capture url %}/tags/{{ tag | downcase | url_encode }}/{% endcapture %} + + {% endfor %} + +
+
+ {% endif %} +
+ + {% if page.layout == 'post' and site.toc and page.toc %} +
+ + {{- site.data.label.panel.toc -}} + + +
+ {% endif %} + +
diff --git a/_includes/post-nav.html b/_includes/post-nav.html new file mode 100644 index 000000000000..81a6231ffb61 --- /dev/null +++ b/_includes/post-nav.html @@ -0,0 +1,31 @@ + + +
+ {% if page.previous.url %} + +

{{ page.previous.title }}

+
+ {% else %} + +

-

+
+ {% endif %} + + {% if page.next.url %} + +

{{ page.next.title }}

+
+ {% else %} + +

-

+
+ {% endif %} + +
\ No newline at end of file diff --git a/_includes/post-paginator.html b/_includes/post-paginator.html new file mode 100644 index 000000000000..cfc53ec32a07 --- /dev/null +++ b/_includes/post-paginator.html @@ -0,0 +1,85 @@ + + +
    + + {% if paginator.previous_page %} + {% assign prev_url = paginator.previous_page_path | relative_url %} + {% else %} + {% assign prev_url = "#" %} + {% endif %} +
  • + + + +
  • + + + {% assign left_ellipsis = false %} + {% assign right_ellipsis = false %} + + {% for i in (1..paginator.total_pages) %} + + {% assign pre = paginator.page | minus: 1 %} + {% assign next = paginator.page | plus: 1 %} + {% assign pre_less = pre | minus: 1 %} + {% assign next_more = next | plus: 1 %} + {% assign show = false %} + + {% if paginator.page == 1 %} + {% if i <= 3 or i == paginator.total_pages %} + {% assign show = true %} + {% endif %} + {% elsif paginator.page == paginator.total_pages %} + {% if i == 1 or i >= pre_less %} + {% assign show = true %} + {% endif %} + {% else %} + {% if i == 1 or i == paginator.total_pages%} + {% assign show = true %} + {% elsif i >= pre and i <= next %} + {% assign show = true %} + {% endif %} + {% endif %} + + {% if show %} + +
  • + {{ i }} +
  • + {% else %} + + {% if i < pre and left_ellipsis == false %} +
  • + ... +
  • + {% assign left_ellipsis = true %} + {% elsif i > next and right_ellipsis == false %} +
  • + ... +
  • + {% assign right_ellipsis = true %} + {% endif %} + {% endif %} + + {% endfor %} + + + {% if paginator.next_page_path %} + {% assign next_url = paginator.next_page_path | relative_url %} + {% else %} + {% assign next_url = "#" %} + {% endif %} +
  • + + + +
  • + +
diff --git a/_includes/post-sharing.html b/_includes/post-sharing.html new file mode 100644 index 000000000000..04e41eeeb4c4 --- /dev/null +++ b/_includes/post-sharing.html @@ -0,0 +1,28 @@ + + + diff --git a/_includes/refactor-content.html b/_includes/refactor-content.html new file mode 100644 index 000000000000..876d66e3378f --- /dev/null +++ b/_includes/refactor-content.html @@ -0,0 +1,27 @@ + + +{% assign _content = include.content %} + + +{% if _content contains '' %} + {% assign _content = _content | replace: '
', '
' %} + {% assign _content = _content | replace: '
', '' %} + {% assign _content = _content | replace: '', '' %} +{% endif %} + + + +{% if _content contains '
' %}
+  {% assign _content = _content | replace: '
', '' %} +{% endif %} + +{{ _content }} diff --git a/_includes/related-posts.html b/_includes/related-posts.html new file mode 100644 index 000000000000..03c1828758a2 --- /dev/null +++ b/_includes/related-posts.html @@ -0,0 +1,110 @@ + + + +{% assign TOTAL_SIZE = 3 %} + + +{% assign TAG_SCORE = 1 %} + + +{% assign CATEGORY_SCORE = 0.5 %} + +{% assign SEPARATOR = ":" %} + +{% assign score_list = "" | split: "" %} +{% assign last_index = site.posts.size | minus: 1 %} + +{% for i in (0..last_index) %} + {% assign post = site.posts[i] %} + + {% if post.url == page.url %} + {% continue %} + {% endif %} + + {% assign score = 0 %} + + {% for tag in post.tags %} + {% if page.tags contains tag %} + {% assign score = score | plus: TAG_SCORE %} + {% endif %} + {% endfor %} + + {% for category in post.categories %} + {% if page.categories contains category %} + {% assign score = score | plus: CATEGORY_SCORE %} + {% endif %} + {% endfor %} + + {% if score > 0 %} + {% capture score_item %}{{ score }}{{ SEPARATOR }}{{ i }}{% endcapture %} + {% assign score_list = score_list | push: score_item %} + {% endif %} + +{% endfor %} + + +{% assign index_list = "" | split: "" %} + +{% if score_list.size > 0 %} + {% assign score_list = score_list | sort | reverse %} + {% for entry in score_list limit: TOTAL_SIZE %} + {% assign index = entry | split: SEPARATOR | last %} + {% assign index_list = index_list | push: index %} + {% endfor %} +{% endif %} + + +{% 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 %} + {% capture cur_index %}{{ i }}{% endcapture %} + {% unless index_list contains cur_index %} + {% assign index_list = index_list | push: cur_index %} + {% assign less = less | minus: 1 %} + {% if less <= 0 %} + {% break %} + {% endif %} + {% endunless %} + {% endif %} + {% endfor %} + +{% endif %} + + +{% if index_list.size > 0 %} + +{% endif %} diff --git a/_includes/search-loader.html b/_includes/search-loader.html new file mode 100644 index 000000000000..af7ebb100c79 --- /dev/null +++ b/_includes/search-loader.html @@ -0,0 +1,32 @@ + + +{% capture result_elem %} +
+ {title} + +

{snippet}

+
+{% endcapture %} + +{% capture not_found %}

Oops! No result founds.

{% endcapture %} + + + + \ No newline at end of file diff --git a/_includes/search-results.html b/_includes/search-results.html new file mode 100644 index 000000000000..078f425fba40 --- /dev/null +++ b/_includes/search-results.html @@ -0,0 +1,23 @@ + +
+
+
+

{{ site.data.label.panel.trending_tags }}

+ + {% include trending-tags.html %} + + {% for tag in trending_tags %} + {% capture url %}/tags/{{ tag | downcase | url_encode }}/{% endcapture %} + + {% endfor %} + +
+
+
+
\ No newline at end of file diff --git a/_includes/sidebar.html b/_includes/sidebar.html new file mode 100644 index 000000000000..1e9e4a1662ac --- /dev/null +++ b/_includes/sidebar.html @@ -0,0 +1,90 @@ + + + + + diff --git a/_includes/timeago.html b/_includes/timeago.html new file mode 100644 index 000000000000..b6b7bcda44c3 --- /dev/null +++ b/_includes/timeago.html @@ -0,0 +1,27 @@ + + + + {% assign this_year = site.time | date: "%Y" %} + {% assign post_year = include.date | date: "%Y" %} + + {% if post_year == this_year %} + {{ include.date | date: site.data.date_format.post.short }} + {% else %} + {{ include.date | date: site.data.date_format.post.long }} + {% endif %} + + {{ include.date | date_to_xmlschema }} + + \ No newline at end of file diff --git a/_includes/topbar.html b/_includes/topbar.html new file mode 100644 index 000000000000..1d4f144bcde2 --- /dev/null +++ b/_includes/topbar.html @@ -0,0 +1,51 @@ + +
+
+ + {% for item in page.breadcrumb %} + {% if item.url %} + + + {{ item.label }} + + + {% else %} + {{ item.label }} + {% endif %} + {% endfor %} + + {% unless page.layout == "home" %} + {{ page.title }} + {% endunless %} + + + + + +
+ {% if page.location %} + {{- page.location -}} + {% elsif page.layout == "home" %} + {{- site.title -}} + {% else %} + {{- page.title -}} + {% endif %} +
+ + + + + + + + Cancel +
+ +
diff --git a/_includes/trending-tags.html b/_includes/trending-tags.html new file mode 100644 index 000000000000..41351e4fb86c --- /dev/null +++ b/_includes/trending-tags.html @@ -0,0 +1,40 @@ +{% comment %} + The trending tags list + v2.0 + https://github.com/cotes2020/jekyll-theme-chirpy + © 2019 Cotes Chung + MIT Licensed +{% endcomment %} + +{% assign MAX = 10 %} + +{% assign size_list = "" | split: "" %} +{% assign tag_list = "" | split: "" %} + +{% for tag in site.tags %} + {% assign size = tag | last | size %} + {% assign size_list = size_list | push: size %} + + {% assign tag_str = tag | first | replace: " ", "-" | append: "::" | append: size %} + {% assign tag_list = tag_list | push: tag_str %} +{% endfor %} + +{% assign size_list = size_list | sort | reverse %} + +{% assign tag_list = tag_list | sort_natural %} + +{% assign trending_tags = "" | split: "" %} + +{% for size in size_list limit: MAX %} + {% for tag_str in tag_list %} + {% assign tag = tag_str | split: "::" %} + {% assign tag_name = tag | first %} + {% assign tag_size = tag | last | plus: 0 %} + {% if tag_size == size %} + {% unless trending_tags contains tag_name %} + {% assign trending_tags = trending_tags | push: tag_name %} + {% break %} + {% endunless %} + {% endif %} + {% endfor %} +{% endfor %} diff --git a/_includes/update-list.html b/_includes/update-list.html new file mode 100644 index 000000000000..231d9a07b1ce --- /dev/null +++ b/_includes/update-list.html @@ -0,0 +1,26 @@ +{% comment %} + Get the last 5 posts from lastmod list. + v2.2 + https://github.com/cotes2020/jekyll-theme-chirpy + © 2020 Cotes Chung + MIT License +{% endcomment %} + +{% assign MAX_SIZE = 5 %} + +{% assign all_list = "" | split: "" %} + +{% for entry in site.data.updates %} + {% capture elem %} + {{- entry.lastmod -}}::{{- entry.filename -}} + {% endcapture %} + {% assign all_list = all_list | push: elem %} +{% endfor %} + +{% assign all_list = all_list | sort | reverse %} + +{% assign update_list = "" | split: "" %} + +{% for entry in all_list limit:MAX_SIZE %} + {% assign update_list = update_list | push: entry %} +{% endfor %} diff --git a/_layouts/category.html b/_layouts/category.html new file mode 100644 index 000000000000..70fec40fd0d6 --- /dev/null +++ b/_layouts/category.html @@ -0,0 +1,25 @@ +--- +layout: page +# The Category layout +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# MIT Licensed +--- + +
+

+ + {{ page.title }} + {{ site.categories[page.category] | size }} +

+ +
    + {% for post in site.categories[page.category] %} +
  • + {{ post.title }} + + {{ post.date | date: site.data.date_format.post.long }} +
  • + {% endfor %} +
+
\ No newline at end of file diff --git a/_layouts/compress.html b/_layouts/compress.html new file mode 100644 index 000000000000..bb34487d2a75 --- /dev/null +++ b/_layouts/compress.html @@ -0,0 +1,10 @@ +--- +# Jekyll layout that compresses HTML +# v3.1.0 +# http://jch.penibelst.de/ +# © 2014–2015 Anatol Broder +# MIT License +--- + +{% capture _LINE_FEED %} +{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "
" %}{% endif %}{% unless _pre_before contains "
" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " ;; ;" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %}
Step Bytes
raw {{ content | size }}{% if _profile_endings %}
endings {{ _profile_endings }}{% endif %}{% if _profile_startings %}
startings {{ _profile_startings }}{% endif %}{% if _profile_comments %}
comments {{ _profile_comments }}{% endif %}{% if _profile_collapse %}
collapse {{ _profile_collapse }}{% endif %}{% if _profile_clippings %}
clippings {{ _profile_clippings }}{% endif %}
{% endif %}{% endif %} diff --git a/_layouts/default.html b/_layouts/default.html new file mode 100644 index 000000000000..4b4b34caf20f --- /dev/null +++ b/_layouts/default.html @@ -0,0 +1,63 @@ +--- +layout: compress +# Default layout +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT Licensed +--- + + + +{% if site.lang %} + {% assign lang = site.lang | split: "_" | first %} +{% else %} + {% assign lang = 'en' %} +{% endif %} + +{% capture prefer_mode %} + {% if site.theme_mode != "dual" %} + mode="{{ site.theme_mode }}" + {% endif %} +{% endcapture %} + + + + {% include head.html %} + + + + + + {% include topbar.html %} + +
+
+ + {% include refactor-content.html content=content %} + + {% include footer.html %} + +
+ + {% include search-results.html %} + +
+ +
+ + + + + + {% include search-loader.html %} + + {% if site.google_analytics.id and jekyll.environment == 'production' %} + {% include google-analytics.html %} + {% endif %} + + + + diff --git a/_layouts/home.html b/_layouts/home.html new file mode 100644 index 000000000000..76c66d5f80d8 --- /dev/null +++ b/_layouts/home.html @@ -0,0 +1,87 @@ +--- +layout: page +# The Home page layout +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT Licensed +--- + + +{% assign pinned = site.posts | where_exp: "item", "item.pin == true" %} +{% assign default = site.posts | where_exp: "item", "item.pin != true" %} +{% assign posts = "" | split: "" %} + + + +{% assign offset = paginator.page | minus: 1 | times: paginator.per_page %} +{% assign pinned_num = pinned.size | minus: offset %} + +{% if pinned_num > 0 %} + {% for i in (offset..pinned.size) limit: pinned_num %} + {% assign posts = posts | push: pinned[i] %} + {% endfor %} +{% else %} + {% assign pinned_num = 0 %} +{% endif %} + + + + +{% assign default_beg = offset | minus: pinned.size %} + +{% if default_beg < 0 %} + {% assign default_beg = 0 %} +{% endif %} + +{% assign default_num = paginator.posts | size | minus: pinned_num %} +{% assign default_end = default_beg | plus: default_num | minus: 1 %} + +{% if default_num > 0 %} + {% for i in (default_beg..default_end) %} + {% assign posts = posts | push: default[i] %} + {% endfor %} +{% endif %} + + +
+ +{% for post in posts %} + +
+
+

{{ post.title }}

+ {% if post.pin == true %} + + {% endif %} +
+
+

+ {% include no-linenos.html content=post.content %} + {{ content | markdownify | strip_html | truncate: 200 }} +

+
+ + +
+ +{% endfor %} + +
+ +{% if paginator.total_pages > 0 %} + {% include post-paginator.html %} +{% endif %} diff --git a/_layouts/page.html b/_layouts/page.html new file mode 100644 index 000000000000..1473f1f62cb3 --- /dev/null +++ b/_layouts/page.html @@ -0,0 +1,38 @@ +--- +layout: default +# The page layout +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +--- + +
+
+
+ {% if page.dynamic_title %} +

{{ page.title }}

+
+ {{ content }} +
+ {% else %} + {{ content }} + {% endif %} +
+
+ + {% include panel.html %} + +
+ +{% if site.disqus.comments and page.comments %} +
+
+
+ + {% include disqus.html %} + +
+
+
+{% endif %} diff --git a/_layouts/post.html b/_layouts/post.html new file mode 100644 index 000000000000..94ea43af7076 --- /dev/null +++ b/_layouts/post.html @@ -0,0 +1,151 @@ +--- +layout: default +# The posts' layout +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT Licensed +--- + +
+ +
+ +
+ +

{{ page.title }}

+ + + +
+ + {%- capture img_placehodler -%} + data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7 + {% endcapture%} + + {% if page.image %} + + {% endif %} + + + {% if content contains '{{ category }} + {%- unless forloop.last -%}, {%- endunless -%} + {% endfor %} +
+ {% endif %} + + + {% if page.tags.size > 0 %} + + {% endif %} + +
+ {% if site.data.rights.license %} +
+ This post is licensed under + {{ site.data.rights.license.name }} + by the author. +
+ {% endif %} + + {% include post-sharing.html %} + +
+ +
+ +
+ + +
+ + {% include panel.html %} + + + +
+
+
+ + {% include related-posts.html %} + + {% include post-nav.html %} + + {% if site.disqus.comments and page.comments %} + {% include disqus.html %} + {% endif %} + +
+ +
+ +
+ +{% include lozad.html %} diff --git a/_layouts/tag.html b/_layouts/tag.html new file mode 100644 index 000000000000..646162d34313 --- /dev/null +++ b/_layouts/tag.html @@ -0,0 +1,25 @@ +--- +layout: page +# The layout for Tag page +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT Licensed +--- + +
+

+ + {{ page.title }} + {{ site.tags[page.tag] | size }} +

+
    + {% for post in site.tags[page.tag] %} +
  • + {{ post.title }} + + {{ post.date | date: site.data.date_format.post.long }} +
  • + {% endfor %} +
+
\ No newline at end of file diff --git a/_posts/2020-11-04-python-introduction.md b/_posts/2020-11-04-python-introduction.md new file mode 100644 index 000000000000..ca54d88df6d2 --- /dev/null +++ b/_posts/2020-11-04-python-introduction.md @@ -0,0 +1,37 @@ +--- +title: Introduction to Python +date: 2020-11-04 6:00:00 +1030 +categories: [INTRODUCTION, FOUDATIONS] +tags: [python] +image: /assets/img/posts/Guido_van_Rossum.jpg +--- + +## What is Python? + +Python is an object-oriented programming language that was created in the late 1980's in the Netherlands by Guido van Rossum. Yes! Python is not as young as you might have thought. Guido named this programming language "Python" inspired by the BBC comedy series "Monty Python". In 2003 Python started becoming popular, especially due to its readability, simplicity, and accessibility. Nowadays, Python has become extensively used not only for analysis but for development. Python ranks second according to GitHub1, being JavaScript the first language within this ranking. Thus, we could say that Python is the most popular programming language with analytics capabilities. + +![GitHub Ranking](/assets/img/posts/programming_languages_ranking_github.jpg) +*Source:https://madnight.github.io/githut/#/pull_requests/2020/3* + +Let's go to what's important to us. + +## Why to use Python? + +- Python is **simple**. Python can be easily learned in comparison to other programming languages. Python is very intuitive and very easy to read. +- A lot of **packages**. Simplicity also means you don't need to write code for complex models. Python has a myriad of packages for data manipulation, analysis, and machine learning (e.g. Pandas, NumPy, StatsModels, etc.). +- Plenty of **support**. Since Python is very popular, it has a lot of support. You can find all types of resources on the python website [(python documentation website)](https://docs.python.org/3/). Additionally, there are many pages like StackOverflow, where you can find answers to your questions straight away. If you have a problem and you are stuck then most likely somebody else has already solved it. +- You have access to rich **visualization** libraries. Python has many libraries that can be used to visualize data. That means you can go from straightforward charts to very complex multidimensional visualizations. +- Python is **free**. Yes! Python is an open-source platform and you can use it for free. This in comparison to other software makes Python very popular. +- Python is not only for analytics but also for **software development**. Python is so powerful that can be used additionally as a software development tool. With Python, you can go from creating dektop software to web applications. For instance, you could create websites with Flask, which is a web framework in Python. + +Python is a powerful tool for **analytics**, which allows for better and faster ETL2 tasks. Moreover, with the vast number of libraries available, statistics and machine learning outcomes are easy to achieve with the right knowledge. + +In the next posts, I will be talking about the differences between Python and other programing languages that are used for analytics purposes. + +I wish you all can benefit from these posts, and I am looking forward to receiving your feedback. Happy coding! + +--- + +1GitHub is a very popular version control system in the cloud for software development. Nowadays, GitHub can do more than just version control. For instance this website is hosted on GitHub. For more information go to [https://github.com/](https://github.com/) + +2ETL is the acronym for Extraction, Transformation and Loading. This is avery important process in the analytics life cycle. For more information go to [https://en.wikipedia.org/wiki/Extract,_transform,_load](https://en.wikipedia.org/wiki/Extract,_transform,_load) \ No newline at end of file diff --git a/_scripts/sh/create_pages.sh b/_scripts/sh/create_pages.sh new file mode 100755 index 000000000000..c2cf292a1700 --- /dev/null +++ b/_scripts/sh/create_pages.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash +# +# Create HTML pages for Categories and Tags in posts. +# +# Usage: +# Call from the '_posts' sibling directory. +# +# v2.2 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# Published under MIT License + +set -eu + +TYPE_CATEGORY=0 +TYPE_TAG=1 + +category_count=0 +tag_count=0 + +_read_yaml() { + local _endline="$(grep -n "\-\-\-" "$1" | cut -d: -f 1 | sed -n '2p')" + head -"$_endline" "$1" +} + +read_categories() { + local _yaml="$(_read_yaml "$1")" + local _categories="$(echo "$_yaml" | yq r - "categories.*")" + local _category="$(echo "$_yaml" | yq r - "category")" + + if [[ -n $_categories ]]; then + echo "$_categories" + elif [[ -n $_category ]]; then + echo "$_category" + fi +} + +read_tags() { + local _yaml="$(_read_yaml "$1")" + local _tags="$(echo "$_yaml" | yq r - "tags.*")" + local _tag="$(echo "$_yaml" | yq r - "tag")" + + if [[ -n $_tags ]]; then + echo "$_tags" + elif [[ -n $_tag ]]; then + echo "$_tag" + fi +} + +init() { + + if [[ -d categories ]]; then + rm -rf categories + fi + + if [[ -d tags ]]; then + rm -rf tags + fi + + if [[ ! -d _posts ]]; then + exit 0 + fi + + mkdir categories tags +} + +create_category() { + if [[ -n $1 ]]; then + local _name=$1 + local _filepath="categories/$(echo "$_name" | sed 's/ /-/g' | awk '{print tolower($0)}').html" + + if [[ ! -f $_filepath ]]; then + echo "---" > "$_filepath" + echo "layout: category" >> "$_filepath" + echo "title: $_name" >> "$_filepath" + echo "category: $_name" >> "$_filepath" + echo "---" >> "$_filepath" + + ((category_count = category_count + 1)) + fi + fi +} + +create_tag() { + if [[ -n $1 ]]; then + local _name=$1 + local _filepath="tags/$(echo "$_name" | sed "s/ /-/g;s/'//g" | awk '{print tolower($0)}').html" + + if [[ ! -f $_filepath ]]; then + + echo "---" > "$_filepath" + echo "layout: tag" >> "$_filepath" + echo "title: $_name" >> "$_filepath" + echo "tag: $_name" >> "$_filepath" + echo "---" >> "$_filepath" + + ((tag_count = tag_count + 1)) + fi + fi +} + +######################################### +# Create HTML pages for Categories/Tags. +# Arguments: +# $1 - an array string +# $2 - type specified option +######################################### +create_pages() { + if [[ -n $1 ]]; then + # split string to array + IFS_BAK=$IFS + IFS=$'\n' + local _string=$1 + + case $2 in + + $TYPE_CATEGORY) + for i in $_string; do + create_category "$i" + done + ;; + + $TYPE_TAG) + for i in $_string; do + create_tag "$i" + done + ;; + + *) ;; + + esac + + IFS=$IFS_BAK + fi + +} + +main() { + + init + + for _file in $(find "_posts" -type f \( -iname \*.md -o -iname \*.markdown \)); do + local _categories=$(read_categories "$_file") + local _tags=$(read_tags "$_file") + + create_pages "$_categories" $TYPE_CATEGORY + create_pages "$_tags" $TYPE_TAG + done + + if [[ $category_count -gt 0 ]]; then + echo "[INFO] Succeed! $category_count category-pages created." + fi + + if [[ $tag_count -gt 0 ]]; then + echo "[INFO] Succeed! $tag_count tag-pages created." + fi +} + +main diff --git a/_scripts/sh/dump_lastmod.sh b/_scripts/sh/dump_lastmod.sh new file mode 100755 index 000000000000..400494c7b36f --- /dev/null +++ b/_scripts/sh/dump_lastmod.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# +# Find out the posts that have been modified and record +# its lastmod information to file '_data/updates.yml' +# +# Usage: +# Call from the '_posts' sibling directory. +# +# v2.2 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# Published under MIT License + +set -eu + +POST_DIR=_posts +OUTPUT_DIR=_data +OUTPUT_FILE=updates.yml + +_init() { + + if [[ ! -d "$OUTPUT_DIR" ]]; then + mkdir "$OUTPUT_DIR" + fi + + if [[ -f "$OUTPUT_DIR/$OUTPUT_FILE" ]]; then + rm -f "$OUTPUT_DIR/$OUTPUT_FILE" + fi + + if [[ ! -d $POST_DIR ]]; then + exit 0 + fi +} + +_has_changed() { + local _log_count="$(git log --pretty=%ad "$1" | wc -l | sed 's/ *//')" + _log_count=$((_log_count + 0)) + + if [[ $_log_count > 1 ]]; then + return 0 # true + fi + + return 1 # false +} + +################################### +# Storage the posts' lastmod. +# +# Args: +# - $1 the post's filename +# - $2 the post's filepath +# Output: +# the file '_data/updates.yml' +################################### +_dump() { + local _lasmod="$(git log -1 --pretty=%ad --date=iso "$2")" + + if [[ ! -f "$OUTPUT_DIR/$OUTPUT_FILE" ]]; then + touch "$OUTPUT_DIR/$OUTPUT_FILE" + fi + + echo "-" >> "$OUTPUT_DIR/$OUTPUT_FILE" + echo " filename: '$1'" >> "$OUTPUT_DIR/$OUTPUT_FILE" + echo " lastmod: '$_lasmod'" >> "$OUTPUT_DIR/$OUTPUT_FILE" +} + +main() { + + _init + + local _count=0 + + for _file in $(find ${POST_DIR} -type f \( -iname \*.md -o -iname \*.markdown \)); do + _filename="$(basename "$_file" | sed 's/-\-\+/-/;s/[[:digit:]]\([[:digit:]]*-\)//g;s/\..*//')" # remove date and extension + + if _has_changed "$_file"; then + _dump "$_filename" "$_file" + ((_count = _count + 1)) + fi + + done + + if [[ $_count > 0 ]]; then + echo "[INFO] Success to update lastmod for $_count post(s)." + fi +} + +main diff --git a/_scripts/sh/sync_monitor.sh b/_scripts/sh/sync_monitor.sh new file mode 100644 index 000000000000..9f58200b7c21 --- /dev/null +++ b/_scripts/sh/sync_monitor.sh @@ -0,0 +1,37 @@ +#!/bin/bash + +# Files sync monitor +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT Licensed + +# $1 -> the origin file with absolute path. +# $2 -> the origin sync directory +# $3 -> the destination sync directory + +# Omit the system temp file +if [[ ! -f $1 ]]; then + exit 0 +fi + +src_dir="$(dirname "$(realpath "$1")")" + +dir_prefix="$(realpath "$2")/" + +related_dir="${src_dir:${#dir_prefix}}" + +dest="$(realpath "$3")/${related_dir}" + +if [[ ! -d $dest ]]; then + mkdir -p "$dest" +fi + +if [[ -f $1 ]]; then + cp "$1" "$dest" +fi + +if [[ $related_dir == "_posts" ]]; then + bash "$3"/_scripts/sh/create_pages.sh + bash "$3"/_scripts/sh/dump_lastmod.sh +fi diff --git a/app.js b/app.js new file mode 100644 index 000000000000..9b80e00096d1 --- /dev/null +++ b/app.js @@ -0,0 +1,12 @@ +--- +layout: compress +# Chirpy v2.2 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed +--- + +/* Registering Service Worker */ +if('serviceWorker' in navigator) { + navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}'); +}; \ No newline at end of file diff --git a/assets/css/_addon/fonts.scss b/assets/css/_addon/fonts.scss new file mode 100644 index 000000000000..0b87d8144dd2 --- /dev/null +++ b/assets/css/_addon/fonts.scss @@ -0,0 +1,7 @@ +/* + * The field 'font-display' is added for Google-fonts. + * + * See: + */ + +@import url('https://fonts.googleapis.com/css2?family=Lato&family=Roboto+Condensed:wght@400;700&family=Source+Sans+Pro:wght@400;600;700;900&display=swap'); diff --git a/assets/css/_addon/main.scss b/assets/css/_addon/main.scss new file mode 100644 index 000000000000..1dc79eaf5e44 --- /dev/null +++ b/assets/css/_addon/main.scss @@ -0,0 +1,1558 @@ +/* +* The main styles. +* v2.0 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2018-2019 Cotes Chung +* MIT Licensed +*/ + +@import "_addon/fonts"; +@import "_addon/module"; +@import "_addon/variables"; +@import "_colors/light-typography"; +@import "_colors/dark-typography"; + +@mixin set-visible($light-display, $dark-display) { + [light-mode-invisible] { + display: $light-display; + } + + [dark-mode-invisible] { + display: $dark-display; + } +} + +@mixin mode-toggle($dark-mode: false) { + @if $dark-mode { + @include set-visible(inline-block, none); + @include dark-scheme; + } @else { + @include set-visible(none, inline-block); + @include light-scheme; + } +} + +html:not([mode]), html[mode=light] { + @include mode-toggle(); +} + +html[mode=dark] { + @include mode-toggle(true); +} + +@media (prefers-color-scheme: dark) { + html:not([mode]), html[mode=dark] { + @include mode-toggle(true); + } + + html[mode=light] { + @include mode-toggle(); + } +} + +html, body { + font-size: 16px; +} + +body { + line-height: 1.75rem; + background: var(--body-bg); + color: var(--text-color); + -webkit-font-smoothing: antialiased; + font-family: 'Source Sans Pro', 'Microsoft Yahei', sans-serif; +} + +/*--- sidebar layout ---*/ + +$tab-count: {{ site.data.tabs | size }}; + +$sidebar-display: "sidebar-display"; + +#sidebar { + @include pl-pr(0); + position: fixed; + top: 0; + left: 0; + height: 100%; + overflow-y: auto; + width: $sidebar-width-medium; + z-index: 99; + background: var(--sidebar-bg); + a { + @include sidebar-links; + } + + .site-title { + text-align: center; + a { + font-weight: 900; + font-size: 1.5rem; + letter-spacing: 0.5px; + &:hover { + color: #fff; + text-decoration: none; + } + } + } + + .site-subtitle { + font-size: 95%; + text-align: center; + color: #828282; + line-height: 1.2rem; + word-spacing: 1px; + margin: 0.5rem 1.5rem 2rem 1.5rem; + } + + .sidebar-bottom { + .icon-border + a { // the icon behide mode-toggle + margin-left: 0.1rem; + } + } + .nav-link { + border-radius: 0; + font-size: 0.95rem; + font-weight: 600; + letter-spacing: 1px; + } + .nav-item { + height: $tab-height; + &:hover { + .nav-link { + color: #f8f9facf; + } + } + &.active { + .nav-link { + color: #fcfcfc; + } + } + } + ul { + height: $tab-height * $tab-count; + display: -webkit-box; + display: -ms-flexbox; + + > li:last-child { + > a { + margin-right: -3px; + max-width: calc(100% - 3px); + } + &::after { // the cursor + visibility: hidden; + content: ""; + position: relative; + right: 1px; + width: 3px; + height: $tab-cursor-height; + background-color: var(--nav-cursor-color); + pointer-events: none; + } + } + + @mixin fix-cursor($top) { + top: $top; + visibility: visible; + } + + @for $i from 1 through $tab-count { + $offset: $tab-count - $i; + $top: -$offset * $tab-height + $tab-cursor-height / 2; + + @if $i < $tab-count { + > li.active:nth-child(#{$i}), + > li.nav-item:nth-child(#{$i}):hover { + ~li:last-child::after { + @include fix-cursor($top); + } + } + } @else { + > li.active:nth-child(#{$i}):last-child::after, + > li.nav-item:nth-child(#{$i}):last-child:hover::after { + @include fix-cursor($top); + } + } + + } // @for + + } // ul + + .sidebar-bottom { + font-size: 1.2rem; + margin: 2rem 2.5rem 1.6rem; + a { + margin-bottom: 0.5rem; // icons may have multi lines + } + + a:hover, #mode-toggle-wrapper > i:hover { + color: #fff; + } + + #mode-toggle-wrapper { + i { + @include sidebar-links; + margin-right: 0; + font-size: 1.05rem; + text-align: center; + position: relative; + bottom: 1px; + } + } + + .icon-border { + background: #525354; + width: 3px; + height: 3px; + border-radius: 50%; + margin-top: 0.75rem; + } + } +} // #sidebar + +@media (hover: hover) { + #sidebar ul > li:last-child::after { + -webkit-transition: top .5s ease; + -moz-transition: top .5s ease; + -o-transition: top .5s ease; + transition: top .5s ease; + } +} + +#nav-wrapper { + width: 100%; + flex-grow: 1; +} + +#profile-wrapper { + margin-top: 2rem; +} + +#avatar { + > a { + display: block; + width: 6rem; + height: 6rem; + border-radius: 50%; + border: 2px solid #b6b6b6; + overflow: hidden; + transform: translateZ(0); // fixed the zoom in Safari + -webkit-transition: border-color 0.35s ease-in-out; + -moz-transition: border-color 0.35s ease-in-out; + transition: border-color 0.35s ease-in-out; + } + + &:hover > a { + border-color: #fff; + } + + img { + width: 100%; + height: 100%; + -webkit-transition: transform .5s; + -moz-transition: transform .5s; + transition: transform .5s; + + &:hover { + -ms-transform: scale(1.2); + -moz-transform: scale(1.2); + -webkit-transform: scale(1.2); + transform: scale(1.2); + } + } +} // #avatar + +#search-result-wrapper { + display: none; + position: fixed; + top: 0; + padding-top: 3rem; + height: 100%; + overflow: auto; + .post-content { + margin-top: 2rem; + } +} + +/*--- top-bar ---*/ + +#topbar-wrapper { + height: $topbar-height; + position: fixed; + top: 0; + left: 260px; /* same as sidebar width */ + right: 0; + transition: top 0.2s ease-in-out; + z-index: 50; + border-bottom: 1px solid rgba(0, 0, 0, 0.07); + box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.05); + background-color: var(--topbar-wrapper-bg); +} + +#topbar i { // icons + color: #999; +} + +#breadcrumb { + font-size: 1rem; + color: gray; + padding-left: 0.5rem; + a:hover { + @extend %link-hover; + } + span { + &:not(:last-child) { + &::after { + content: "›"; + padding: 0 .3rem; + } + } + } +} + +#sidebar-trigger, +#search-trigger { + display: none; +} + +#search-wrapper { + display: flex; + width: 95%; + border-radius: 1rem; + border: 1px solid var(--search-wrapper-bg); + background: var(--search-wrapper-bg); + padding: 0 .5rem; + i { + z-index: 2; + font-size: 0.9rem; + color: var(--search-icon-color); + } + .fa-times-circle { /* button 'clean up' */ + visibility: hidden; + } +} + +#search-cancel { /* 'Cancel' link */ + color: var(--link-color); + margin-left: 1rem; + display: none; +} + +#search-input { + background: center; + border: 0; + border-radius: 0; + padding: 0.18rem .3rem; + color: var(--text-color); +} + +#search-input { + &:focus { + box-shadow: none; + background: center; + &.form-control { + &::-webkit-input-placeholder { @include input-placeholder } + &::-moz-placeholder { @include input-placeholder } + &:-ms-input-placeholder { @include input-placeholder } + &::placeholder { @include input-placeholder } + } + } +} + +#search-hints { + display: none; + .post-tag { + display: inline-block; + line-height: 1rem; + font-size: 1rem; + background: var(--search-tag-bg); + border: none; + padding: 0.5rem; + margin: 0 1rem 1rem 0; + &::before { + content: "#"; + color: var(--text-muted-color); + padding-right: 0.2rem; + } + } +} + +#search-results { + padding-bottom: 6rem; + a { + @extend %link-color; + @extend %no-bottom-border; + @extend %heading; + font-size: 1.4rem; + line-height: 2.5rem; + &:hover { + @extend %link-hover; + } + } + > div { + max-width: 100%; + &:not(:last-child) { + margin-bottom: 1rem; + } + i { // icons + color: #818182; + margin-right: 0.15rem; + font-size: 80%; + } + > p { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + } + } +} + +#topbar-title { + display: none; + font-size: 1.1rem; + font-weight: 600; + font-family: sans-serif; + color: var(--topbar-text-color); + text-align: center; + width: 70%; + overflow: hidden; + text-overflow: ellipsis; + word-break: keep-all; + white-space: nowrap; +} + +#mask { + display: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 100%; + width: 100%; + z-index: 1; + @at-root [#{$sidebar-display}] & { + display: block!important; + } +} + +/*--- main wrapper ---*/ + +#main-wrapper { + background-color: var(--main-wrapper-bg); + position: relative; + min-height: 100vh; + padding-bottom: $footer-height; + @include pl-pr(0); +} + +#main > div.row:first-child > div { + &:nth-child(1), &:nth-child(2) { + 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} - #{$post-extend-min-height}); + } +} + +#post-wrapper { + min-height: calc(100vh - #{$topbar-height} + - #{$footer-height} - #{$post-extend-min-height})!important; +} + +#topbar-wrapper.row, +#main>.row, +#search-result-wrapper>.row { + @include ml-mr(0); +} + +footer { + position: absolute; + bottom: 0; + padding: 0 1rem; + height: $footer-height; + font-size: 0.8rem; + color: #7a7b7d; + background-color: var(--footer-bg-color); + > div.d-flex { + line-height: 1.2rem; + width: 95%; + max-width: 1045px; + border-top: 1px solid var(--main-border-color); + margin-bottom: 1rem; + > div { + width: 350px; + } + } + a { + color: var(--footer-link); + &:link { + @include no-text-decoration; + } + &:hover { + @extend %link-hover; + @include no-text-decoration; + } + } + .footer-right { + text-align: right; + } +} + +/*--- Panels ---*/ + +.access { + top: 2rem; + transition: top 0.2s ease-in-out; + margin-right: 1.5rem; + margin-top: 3rem; + margin-bottom: 4rem; + &:only-child { + position: -webkit-sticky; /* Safari */ + position: sticky; + } + &.topbar-down { + top: 6rem; + } + > div { + padding-left: 1rem; + border-left: 1px solid var(--main-border-color); + &:not(:last-child) { + margin-bottom: 4rem; + } + } + span { + @include panel-label; + } + .post-content { + font-size: 0.9rem; + } +} + + +#access-tags { + > div.post-content > div { + max-width: 80%; + } + .post-tag { + display: inline-block; + line-height: 1rem; + font-size: 0.85rem; + background: none; + border: 1px solid var(--btn-border-color); + border-radius: 0.8rem; + padding: 0.3rem .5rem; + margin: 0 .35rem .5rem 0; + &:hover { + background-color: #2a408e; + border-color: #2a408e; + color: #fff; + transition: none; + } + } +} + +#access-lastmod { + ul { + > li { + height: 1.8rem; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + list-style: none; + } + a { + color: #6c757d; + } + } + + a { + @extend %no-bottom-border; + &:hover { + @extend %link-hover; + } + } +} + +/*--- button back-to-top ---*/ + +#back-to-top { + display: none; + z-index: 1; + cursor: pointer; + position: fixed; + background: var(--button-bg); + color: var(--btn-backtotop-color); + height: 2.6em; + width: 2.7em; + border-radius: 50%; + border: 1px solid var(--btn-backtotop-border-color); + transition: 0.2s ease-out; + -webkit-transition: 0.2s ease-out; +} + +#back-to-top:hover { + transform: translate3d(0, -5px, 0); + -webkit-transform: translate3d(0, -5px, 0); +} + +/*--- Typography ---*/ + +h1 { + @extend %heading; + font-size: 1.8rem; +} + +h2 { + @extend %heading; + @extend %section; + @extend %anchor; + font-size: 1.4rem; +} + +h3 { + @extend %heading; + @extend %section; + @extend %anchor; + font-size: 1.25rem; +} + +h4 { + @extend %heading; + @extend %section; + @extend %anchor; + font-size: 1.15rem; +} + +h5 { + @extend %heading; + @extend %section; + @extend %anchor; + font-size: 1.1rem; +} + +blockquote { + border-left: 5px solid var(--blockquote-border-color); + padding-left: 1rem; + color: var(--blockquote-text-color); + .post-content & { + a { + color: var(--link-color); + } + } +} + +kbd { + margin: 0 .3rem; +} + +sup { + z-index: 1; + &:target { + @extend %anchor; + z-index: 0; + } +} + +.footnotes ol { + margin-top: 0.5rem; + > li { + padding-top: 0.2rem; + margin-top: -0.2rem; + > p { + padding-left: 0.2em; + } + &:not(:last-child) { + margin-bottom: -.8rem; + } + &:target > p { + background-color: var(--footnote-target-bg); + width: fit-content; + -webkit-transition: background-color 1.5s ease-in-out; + /* Safari prior 6.1 */ + transition: background-color 1.5s ease-in-out; + } + } +} + +.footnote { + @at-root a#{&} { + margin: 0 .2em; + border-bottom-style: none !important; + -webkit-transition: background-color 1.5s ease-in-out; /* Safari prior 6.1 */ + transition: background-color 1.5s ease-in-out; + } + @at-root sup:target > a#{&} { + background-color: var(--footnote-target-bg); + padding: 0 2px; + } +} + +.reversefootnote { + @at-root a#{&} { + font-size: 0.6rem; + position: absolute; + line-height: 1; + padding-top: 0.5em; + margin-left: 0.5em; + border-bottom-style: none !important; + } +} + +a { + @at-root p>#{&} { + @extend %link-color; + } + @at-root span>#{&} { + @extend %link-color; + } + .post-preview & { + @extend %link-color; + &:hover { + @extend %link-hover; + } + } + .categories &, + #page-category &, + #tags &, + #archives & { + &:not(:hover) { + @extend %no-bottom-border; + } + } + +} // a + +img { + max-width: 100%; +} + +.post { + h1 { + margin-top: 3rem; + margin-bottom: 1rem; + } + em { /* MarkDown italic */ + padding-right: 0.2rem; + } + a:hover { + code { + @extend %link-hover; + } + } +} + + +/*--- Begin of Markdown table style ---*/ +div.post-content .table-wrapper { + overflow-x: auto; + + > table { + min-width: 60%; + overflow-x: auto; + border-spacing: 0; + margin-bottom: 1.5rem; + + thead { + border-bottom: solid 2px rgba(210, 215, 217, 0.75); + th { + @extend %table-cell; + } + } + + tbody { + tr { + &:nth-child(2n) { + background-color: var(--tb-even-bg); + } + &:nth-child(2n + 1) { + background-color: var(--tb-odd-bg); + } + & { + border-bottom: 1px solid var(--tb-border-color); + } + td { + @extend %table-cell; + } + } + } + } +} + + +/*--- post ---*/ + +.pageviews .fa-spinner { + font-size: 80%; +} + +.post-meta { + font-size: 0.85rem; + word-spacing: 1px; + a { + @extend %link-color; + @extend %link-underline; + &:not(:last-child) { + margin-right: 2px; + } + &:hover { + @extend %link-hover; + } + } +} + +.post-content { + line-height: 1.8; + margin-top: 2rem; + overflow-wrap: break-word; + word-wrap: break-word; + + @mixin img($caption: false) { + > img:not([style]) { + margin: 0.5rem 0; + + &:not(.normal):not(.left):not(.right) { + @include align-center; + + @if $caption { + @include img-caption; + } + } + + &.left { + float: left; + margin: 0.75rem 1rem 1rem 0; + } + + &.right { + float: right; + margin: 0.75rem 0 1rem 1rem; + } + + } + } + + @mixin img-caption { + + em { + display: block; + text-align: center; + font-style: normal; + font-size: 80%; + padding: 0; + color: #6d6c6c; + } + } + + a { + &:not(.img-hyperlink) { + @extend %link-color; + @extend %link-underline; + &:hover { + @extend %link-hover; + } + } + &.img-hyperlink { + @include img; + @include img-caption; + } + } + + p { + font-size: 1.08rem; + @include img(true); + }// p +} + +.tag:hover { + @extend %tag-hover; +} + +.post-tag { + display: inline-block; + min-width: 2rem; + text-align: center; + background: var(--tag-bg); + border-radius: 0.3rem; + padding: 0 .4rem; + color: inherit; + line-height: 1.3rem; + &:not(:last-child) { + margin-right: 0.2rem; + } + + &:hover { + @extend %tag-hover; + border-bottom: none; + text-decoration: none; + color: #d2603a; + } +} + +/* --- buttons --- */ +.btn-lang { + border: 1px solid !important; + padding: 1px 3px; + border-radius: 3px; + color: var(--link-color); + &:focus { + box-shadow: none; + } +} + +/* --- Effects classes --- */ + +.loaded { + display: block !important; + @at-root .d-flex#{&} { + display: flex !important; + } +} + +.unloaded { + display: none !important; +} + +.visable { + visibility: visible !important; +} + +.hidden { + visibility: hidden !important; +} + +.flex-grow-1 { + -ms-flex-positive: 1!important; + flex-grow: 1!important; +} + +.btn-box-shadow { + box-shadow: 0 0 8px 0 var(--btn-box-shadow)!important; +} + +.topbar-up { + top: -3rem !important; /* same as topbar height. */ +} + +.no-text-decoration { + @include no-text-decoration; +} + +.tooltip-inner { /* Overrided BS4 Tooltip */ + font-size: 0.7rem; + max-width: 220px; + text-align: left; +} + +.disabled { + color: rgb(206, 196, 196); + pointer-events: auto; + cursor: not-allowed; +} + +.hide-border-bottom { + border-bottom: none!important; +} + +.input-focus { + box-shadow: none; + border-color: var(--input-focus-border-color) !important; + background: center !important; + transition: background-color .15s ease-in-out,border-color .15s ease-in-out; +} + +/*--- Responsive Design ---*/ + +@media all and (max-width: 576px) { + + $footer-height: 6rem; // overwrite + + #main > div.row:first-child > div:first-child { + min-height: calc(100vh - #{$topbar-height} - #{$footer-height}); + } + + #post-wrapper { + min-height: calc(100vh - #{$topbar-height} + - #{$footer-height} - #{$post-extend-min-height}) !important; + h1 { + margin-top: 2.2rem; + font-size: 1.55rem; + } + } + + #avatar > a { + width: 5rem; + height: 5rem; + } + + .site-subtitle { + @include ml-mr(1.8rem); + } + + /* table text in small screens */ + div > table, p ~ table { + width: 100%; + table-layout: fixed; + word-wrap: break-word; + } + + #main-wrapper { + padding-bottom: $footer-height; + } + + footer { + height: $footer-height; + > div.d-flex { + width: 100%; + padding: 1.5rem 0; + margin-bottom: 0.3rem; + flex-wrap: wrap; + justify-content: left!important; + -ms-flex-pack: distribute!important; + justify-content: space-around!important; + } + .footer-left, .footer-right { + text-align: center; + } + } + +} + + +/* Hide Sidebar and TOC */ +@media all and (max-width: 830px) { + %slide { + -webkit-transition: transform 0.4s ease; + transition: transform 0.4s ease; + } + + + html, body { + overflow-x: hidden; + } + + [#{$sidebar-display}] { + + #sidebar { + transform: translateX(0); + } + + #topbar-wrapper, + #main-wrapper { + transform: translateX(#{$sidebar-width-medium}); + } + + } + + #sidebar { + @extend %slide; + + transform: translateX(-#{$sidebar-width-medium}); // hide + -webkit-transform: translateX(-#{$sidebar-width-medium}); + + .cursor { + -webkit-transition: none; + -moz-transition: none; + transition: none; + } + } + + #topbar-wrapper { + @extend %slide; + } + + #main-wrapper { + @extend %slide; + padding-top: $topbar-height; + } + + #search-result-wrapper { + width: 100%; + } + + #page h1.dynamic-title { + display: none; + ~.post-content { + margin-top: 3rem; + } + } + + #breadcrumb, + #search-wrapper { + display: none; + } + + #topbar-wrapper { + left: 0; + } + + .topbar-up { + top: 0 !important; + } + + #main > div.row:first-child > div:nth-child(1), + #main > div.row:first-child > div:nth-child(2) { + margin-top: 0; + } + + #topbar-title, + #sidebar-trigger, + #search-trigger { + display: block; + } + + #search-wrapper { + &.loaded ~ a { + margin-right: 1rem; + } + .fa-times-circle { + right: 5.2rem; + } + } + + #search-input { + margin-left: 0; + width: 95%; + } + + #search-result-wrapper .post-content { + letter-spacing: 0; + } + + #search-hints { + display: block; + padding: 0 1rem; + } + + #tags { + -webkit-box-pack: center!important; + -ms-flex-pack: center!important; + justify-content: center!important; + } + + sup:target { + padding-top: 3.4rem; + } + + .footnotes ol > li { + padding-top: 3.5rem; + margin-top: -4.3rem; + &:first-child { + margin-top: -3.5rem; + } + } +} + + +@media all and (min-width: 577px) and (max-width: 1199px) { + footer>.d-flex > div { + width: 312px; + } +} + + +/* Sidebar visible */ +@media all and (min-width: 831px) { + + /* Solved jumping scrollbar */ + html { + overflow-y: scroll; + } + + #main-wrapper { + margin-left: $sidebar-width-medium; + } + + #profile-wrapper { + margin-top: 3rem; + } + + #search-wrapper { + width: 22%; + min-width: 150px; + } + + /* button 'back-to-Top' position */ + #back-to-top { + bottom: 5.5rem; + right: 1.2rem; + } + + .topbar-up { + box-shadow: none !important; + } + + #topbar-title { + text-align: left; + } + + footer > div.d-flex { + width: 92%; + } + +} + +/* iPad 9.7" horizontal */ +@media all and (min-width: 992px) and (max-width: 1024px) { + #main-wrapper .col-lg-11 { + -webkit-box-flex: 0; + -ms-flex: 0 0 96%; + flex: 0 0 96%; + max-width: 96%; + } +} + +/* Compact icons in sidebar & TOC hidden */ +@media all and (min-width: 832px) and (max-width: 1199px) { + + #sidebar { + width: $sidebar-width-small; + .sidebar-bottom { + @include ml-mr(1.5rem); + .icon-border { + @include ml-mr(.25rem); + } + } + } + + #topbar-wrapper { + left: 210px; + } + + #search-result-wrapper { + width: calc(100% - 210px); + } + + #search-results > div { + max-width: 700px; + } + + .site-title { + font-size: 1.3rem; + margin-left: 0!important; + } + + .site-subtitle { + font-size: 90%; + @include ml-mr(1rem); + } + + #main-wrapper { + margin-left: 210px; + } + + #breadcrumb { + width: 65%; + overflow: hidden; + text-overflow: ellipsis; + word-break: keep-all; + white-space: nowrap; + } + +} + +/* Pannel hidden */ +@media all and (max-width: 1199px) { + #panel-wrapper { + display: none; + } + + #topbar { + padding: 0; + } + + #main > div.row { + -webkit-box-pack: center!important; + -ms-flex-pack: center!important; + justify-content: center!important; + } +} + + +/*--- 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-input { + -webkit-transition: all .3s ease-in-out; + transition: all .3s ease-in-out; + } + + #search-result-wrapper { + width: calc(100% - 260px); + } + + #search-results > div { + max-width: 46%; + &:nth-child(odd) { + margin-right: 1.5rem; + } + &:nth-child(even) { + margin-left: 1.5rem; + } + &:last-child:nth-child(odd) { + position: relative; + right: 24.3%; + } + } + + .post-content p { + font-size: 1.03rem; + } + + footer > div.d-felx { + width: 85%; + } + +} + +@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; + } + } + + #search-wrapper .fa-times-circle { + right: 2.6rem; + } + +} + +@media all and (min-width: 1400px) and (max-width: 1650px) { + #topbar { + padding-right: 2rem; + } +} + +@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: 3%; + } + + #profile-wrapper { + margin: 4rem 2rem 3rem 4rem; + -ms-flex-direction: column!important; + + #avatar { + -webkit-box-pack: normal !important; + -ms-flex-pack: normal !important; + justify-content: normal !important; + > a { + width: 6.2rem; + height: 6.2rem; + } + } + + .profile-text { + margin-left: 0.5rem; + /* .d-flex */ + display: -webkit-box!important; + display: -ms-flexbox!important; + display: flex!important; + /* .flex-wrap */ + -ms-flex-wrap: wrap!important; + flex-wrap: wrap!important; + /* .align-content-center */ + -ms-flex-line-pack: center!important; + align-content: center!important; + > div { + text-align: left !important; + width: 100%; + } + } + } + + #sidebar { + width: $sidebar-width-large; + + .site-title a { + font-size: 1.7rem; + letter-spacing: 1px; + margin: 0; + } + + .site-subtitle { + word-spacing: 0; + margin: 0.3rem 0 0 0; + } + + ul { + margin-left: 3%; + > li > a { + padding-left: 2.5rem; + -webkit-box-pack: start!important; + -ms-flex-pack: start!important; + justify-content: flex-start!important; + } + } + + .nav-link { + > span { + letter-spacing: 3px; + } + > i { + @include icon-round(1.65rem); + line-height: 1rem; + font-size: 0.6rem; + padding: 0.5em 0 0 .1em; + display: inline-block!important; + } + } + + .sidebar-bottom { + margin-left: 3.5rem; + margin-right: 3rem; + font-size: 1.3rem; + a { + border: 1px solid; + border-radius: 50%; + font-size: 1rem; + width: 2rem; + height: 2rem; + text-align: center; + i { + text-align: center; + width: 1.25em; + padding-top: 0.44rem; + } + } + + #mode-toggle-wrapper { + font-size: 0.9rem; + i { + @include icon-round(2rem); + padding-top: 0.44rem; + bottom: 0; + } + } + + .icon-border { + @include ml-mr(.2rem); + margin-top: 0.85rem; + +a { + margin-left: 0; + } + } + } // .sidebar-bottom + } // #sidebar + footer > div.d-flex { + width: 87%; + max-width: 1140px; + } + + #search-result-wrapper { + width: calc(100% - #{$sidebar-width-large}); + > div { + max-width: #{$main-content-max-width}; + } + } + +} // min-width: 1650px + + +@media all and (min-width: 1700px) { + #topbar-wrapper { + padding-right: calc(100% - #{$sidebar-width-large} + - (1920px - #{$sidebar-width-large}) ) /* 100% - 350px - (1920px - 350px); */ + } + + #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} - 1530px); + } + + #panel-wrapper { + margin-left: 41px; + } +} diff --git a/assets/css/_addon/module.scss b/assets/css/_addon/module.scss new file mode 100644 index 000000000000..94505f447ffc --- /dev/null +++ b/assets/css/_addon/module.scss @@ -0,0 +1,119 @@ +/* +* Mainly scss modules, only imported to `assets/css/main.scss` +* +* v2.1 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2020 Cotes Chung +* MIT Licensed +*/ + +/* ---------- scss placeholder --------- */ + +%tag-hover { + background: var(--tag-hover); + transition: background 0.35s ease-in-out; +} + +%table-cell { + padding: 0.4rem 1rem; + font-size: 95%; +} + +%link-hover { + color: #d2603a !important; + border-bottom: 1px solid #d2603a; + text-decoration: none; +} + +%link-color { + color: var(--link-color); +} + +%link-underline { + border-bottom: 1px solid var(--link-underline-color); +} + +%no-bottom-border { + border-bottom: none; +} + +%heading { + font-weight: 400; + font-family: 'Lato', 'Microsoft Yahei', sans-serif; +} + +%section { + #post-wrapper & { + line-height: 1.2; + margin-bottom: 1rem; + } +} + +%anchor { + padding-top: 3.5rem; + margin-top: -2.5rem; +} + +/* ---------- scss mixin --------- */ + +@mixin no-text-decoration { + text-decoration: none; +} + +@mixin sidebar-links($color: rgba(255, 255, 255, 0.5)) { + color: $color; + transition: color 0.35s ease-in-out; + user-select: none; + margin: 0 0.25rem; +} + +@mixin icon-round($diameter) { + border: 1px solid; + border-radius: 50%; + width: $diameter; + height: $diameter; +} + +@mixin ml-mr($value) { + margin-left: $value; + margin-right: $value; +} + +@mixin pl-pr($val) { + padding-left: $val; + padding-right: $val; +} + +@mixin input-placeholder { + opacity: 0.6; +} + +@mixin semi-bold { + font-weight: 600; +} + +@mixin label($font-size: 1rem, $font-weight: 600, $color: var(--label-color)) { + color: $color; + font-size: $font-size; + font-weight: $font-weight; + font-family: 'Roboto Condensed', 'Microsoft Yahei', sans-serif; +} + +@mixin panel-label { + @include label(inherit); + display: block; + line-height: 1.2; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + margin-top: 0; + margin-bottom: 0; + letter-spacing: -0.02em; +} + +@mixin align-center { + position: relative; + left: 50%; + -webkit-transform: translateX(-50%); + -ms-transform: translateX(-50%); + transform: translateX(-50%); +} diff --git a/assets/css/_addon/syntax.scss b/assets/css/_addon/syntax.scss new file mode 100644 index 000000000000..cd3bab72102f --- /dev/null +++ b/assets/css/_addon/syntax.scss @@ -0,0 +1,151 @@ +/* +* The syntax highlight. +* v2.0 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2018-2019 Cotes Chung +* MIT Licensed +*/ + +@import "_colors/light-syntax"; +@import "_colors/dark-syntax"; + +html:not([mode]), +html[mode=light] { + @include light-syntax; +} + +html[mode=dark] { + @include dark-syntax; +} + +@media (prefers-color-scheme: dark) { + html:not([mode]), + html[mode=dark] { + @include dark-syntax; + } + + html[mode=light] { + @include light-syntax; + } +} + +/* -- Codes Snippet -- */ + +%code-snippet-bg { + background: var(--highlight-bg-color); +} + +%code-snippet-radius { + border-radius: 5px; +} + +%code-snippet-padding { + padding: 0.8rem 1rem; +} + +$code-font-size: 0.85rem; + +div > pre { + @extend %code-snippet-bg; + @extend %code-snippet-radius; + @extend %code-snippet-padding; +} + +.highlighter-rouge { + @extend %code-snippet-bg; + @extend %code-snippet-radius; + + color: var(--highlighter-rouge-color); + margin-bottom: 1.2em; /* Override BS Inline-code style */ +} + +.highlight { + @extend %code-snippet-radius; + @extend %code-snippet-bg; + + @at-root figure#{&} { + @extend %code-snippet-bg; + } + + overflow: auto; + .lineno { + margin: 0.8rem 0; + padding: 0 0.5rem; + min-width: 2.2rem; + text-align: right; + color: var(--highlight-lineno-color); + border-right: 1px solid var(--highlight-lineno-border-color); + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; + } + pre { + margin-bottom: 0; + font-size: $code-font-size; + line-height: 1.4rem; + word-wrap: normal; /* Fixed Safari overflow-x */ + } + table { + padding: 0; + border: 0; + td pre { + overflow: visible; /* Fixed iOS safari overflow-x */ + word-break: normal; /* Fixed iOS safari linenos code break */ + } + } + td { + padding: 0; + border: 0; + } +} //.highlight + +code { + -webkit-hyphens: none; + -ms-hyphens: none; + -moz-hyphens: none; + hyphens: none; + + &.highlighter-rouge { + font-size: $code-font-size; + padding: 3px 5px; + margin: 0 0.15rem; + border-radius: 4px; + background-color: var(--inline-code-bg); + } + + @at-root a > &.highlighter-rouge { + padding-bottom: 0; // show link's underlinke + color: inherit; + } + + @at-root a:hover > &.highlighter-rouge { + border-bottom: none; + } + + blockquote &.highlighter-rouge { + color: inherit; + } +} + +td.rouge-code { + padding-left: 1rem; + padding-right: 1rem; +} + +/* Hide line numbers for default, console, and terminal code snippets */ +div { + &[class^='highlighter-rouge'], + &.language-plaintext.highlighter-rouge, + &.language-console.highlighter-rouge, + &.language-terminal.highlighter-rouge { + pre.lineno { + display: none; + } + td.rouge-code { + @extend %code-snippet-padding; + } + } +} diff --git a/assets/css/_addon/variables.scss b/assets/css/_addon/variables.scss new file mode 100644 index 000000000000..7c655f44a594 --- /dev/null +++ b/assets/css/_addon/variables.scss @@ -0,0 +1,27 @@ +/* +* Mainly scss variables +* +* v2.1 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2020 Cotes Chung +* MIT Licensed +*/ + +/* --- ↓ width and height ---- */ + +$tab-height: 3.3rem; +$tab-cursor-height: 1.6rem; + +$sidebar-width-small: 210px; +$sidebar-width-medium: 260px; +$sidebar-width-large: 350px; + +$topbar-height: 3rem; + +$footer-height: 5rem; + +$main-content-max-width: 1150px; + +$panel-max-width: 300px; + +$post-extend-min-height: 35rem; diff --git a/assets/css/_colors/dark-syntax.scss b/assets/css/_colors/dark-syntax.scss new file mode 100644 index 000000000000..41f3f28d8380 --- /dev/null +++ b/assets/css/_colors/dark-syntax.scss @@ -0,0 +1,88 @@ +/*! +* The syntax dark mode styles. +* v2.0 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2018-2019 Cotes Chung +* MIT Licensed +*/ + +@mixin dark-syntax { + /* ----- My styles ------ */ + --highlight-bg-color: #272822; + --highlighter-rouge-color: #de6b18; + --highlight-lineno-color: #6c6c6d; + --highlight-lineno-border-color: #3c4042; + --inline-code-bg: var(--highlight-bg-color); + + .highlight { + .gp { color: #818c96; } + } + + pre { color: #818c96; } /* override Bootstrap */ + kbd { background-color: black; } + + /* syntax highlight colors from https://raw.githubusercontent.com/jwarby/pygments-css/master/monokai.css */ + .highlight pre { background-color: #272822; } + .highlight .hll { background-color: #272822; } + .highlight .c { color: #75715e; } /* Comment */ + .highlight .err { color: #960050; background-color: #1e0010; } /* Error */ + .highlight .k { color: #66d9ef; } /* Keyword */ + .highlight .l { color: #ae81ff; } /* Literal */ + .highlight .n { color: #f8f8f2; } /* Name */ + .highlight .o { color: #f92672; } /* Operator */ + .highlight .p { color: #f8f8f2; } /* Punctuation */ + .highlight .cm { color: #75715e; } /* Comment.Multiline */ + .highlight .cp { color: #75715e; } /* Comment.Preproc */ + .highlight .c1 { color: #75715e; } /* Comment.Single */ + .highlight .cs { color: #75715e; } /* Comment.Special */ + .highlight .ge { font-style: italic; } /* Generic.Emph */ + .highlight .gs { font-weight: bold; } /* Generic.Strong */ + .highlight .kc { color: #66d9ef; } /* Keyword.Constant */ + .highlight .kd { color: #66d9ef; } /* Keyword.Declaration */ + .highlight .kn { color: #f92672; } /* Keyword.Namespace */ + .highlight .kp { color: #66d9ef; } /* Keyword.Pseudo */ + .highlight .kr { color: #66d9ef; } /* Keyword.Reserved */ + .highlight .kt { color: #66d9ef; } /* Keyword.Type */ + .highlight .ld { color: #e6db74; } /* Literal.Date */ + .highlight .m { color: #ae81ff; } /* Literal.Number */ + .highlight .s { color: #e6db74; } /* Literal.String */ + .highlight .na { color: #a6e22e; } /* Name.Attribute */ + .highlight .nb { color: #f8f8f2; } /* Name.Builtin */ + .highlight .nc { color: #a6e22e; } /* Name.Class */ + .highlight .no { color: #66d9ef; } /* Name.Constant */ + .highlight .nd { color: #a6e22e; } /* Name.Decorator */ + .highlight .ni { color: #f8f8f2; } /* Name.Entity */ + .highlight .ne { color: #a6e22e; } /* Name.Exception */ + .highlight .nf { color: #a6e22e; } /* Name.Function */ + .highlight .nl { color: #f8f8f2; } /* Name.Label */ + .highlight .nn { color: #f8f8f2; } /* Name.Namespace */ + .highlight .nx { color: #a6e22e; } /* Name.Other */ + .highlight .py { color: #f8f8f2; } /* Name.Property */ + .highlight .nt { color: #f92672; } /* Name.Tag */ + .highlight .nv { color: #f8f8f2; } /* Name.Variable */ + .highlight .ow { color: #f92672; } /* Operator.Word */ + .highlight .w { color: #f8f8f2; } /* Text.Whitespace */ + .highlight .mf { color: #ae81ff; } /* Literal.Number.Float */ + .highlight .mh { color: #ae81ff; } /* Literal.Number.Hex */ + .highlight .mi { color: #ae81ff; } /* Literal.Number.Integer */ + .highlight .mo { color: #ae81ff; } /* Literal.Number.Oct */ + .highlight .sb { color: #e6db74; } /* Literal.String.Backtick */ + .highlight .sc { color: #e6db74; } /* Literal.String.Char */ + .highlight .sd { color: #e6db74; } /* Literal.String.Doc */ + .highlight .s2 { color: #e6db74; } /* Literal.String.Double */ + .highlight .se { color: #ae81ff; } /* Literal.String.Escape */ + .highlight .sh { color: #e6db74; } /* Literal.String.Heredoc */ + .highlight .si { color: #e6db74; } /* Literal.String.Interpol */ + .highlight .sx { color: #e6db74; } /* Literal.String.Other */ + .highlight .sr { color: #e6db74; } /* Literal.String.Regex */ + .highlight .s1 { color: #e6db74; } /* Literal.String.Single */ + .highlight .ss { color: #e6db74; } /* Literal.String.Symbol */ + .highlight .bp { color: #f8f8f2; } /* Name.Builtin.Pseudo */ + .highlight .vc { color: #f8f8f2; } /* Name.Variable.Class */ + .highlight .vg { color: #f8f8f2; } /* Name.Variable.Global */ + .highlight .vi { color: #f8f8f2; } /* Name.Variable.Instance */ + .highlight .il { color: #ae81ff; } /* Literal.Number.Integer.Long */ + .highlight .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ + .highlight .gd { color: #f92672; background-color: #561c08; } /* Generic.Deleted & Diff Deleted */ + .highlight .gi { color: #a6e22e; background-color: #0b5858; } /* Generic.Inserted & Diff Inserted */ +} diff --git a/assets/css/_colors/dark-typography.scss b/assets/css/_colors/dark-typography.scss new file mode 100644 index 000000000000..5bd7892ee302 --- /dev/null +++ b/assets/css/_colors/dark-typography.scss @@ -0,0 +1,135 @@ +/*! +* The main dark mode styles +* v2.0 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2018-2019 Cotes Chung +* MIT Licensed +*/ + +@mixin dark-scheme { + /* framework */ + --main-wrapper-bg: rgb(27, 27, 30); + --body-bg: var(--main-wrapper-bg); + --topbar-wrapper-bg: rgb(39, 40, 43); + --search-wrapper-bg: rgb(34, 34, 39); + --search-icon-color: rgb(100, 102, 105); + --input-focus-border-color: rgb(112, 114, 115); + --mask-bg: rgb(68, 69, 70); + --footer-bg-color: var(--main-wrapper-bg); + + /* common color */ + --text-color: rgb(175, 176, 177); + --text-muted-color: rgb(107, 116, 124); + --link-color: rgb(138, 180, 248); + --link-underline-color: rgb(82, 108, 150); + --main-border-color: rgb(44, 45, 45); + --button-bg: rgb(39, 40, 43); + --blockquote-border-color: rgb(66, 66, 66); + --blockquote-text-color: rgb(117, 117, 117); + --btn-border-color: rgb(63, 65, 68); + --btn-backtotop-color: var(--text-color); + --btn-backtotop-border-color: var(--btn-border-color); + --btn-box-shadow: var(--main-wrapper-bg); + --card-header-bg: rgb(51, 50, 50); + --label-color: rgb(108, 117, 125); + + /* Sidebar */ + --nav-cursor-color: rgb(183, 182, 182); + --sidebar-bg: radial-gradient(circle, #242424 0%, #1d1f27 100%); + + /* Top Bar */ + --topbar-text-color: var(--text-color); + + /* Home page */ + --post-list-text-color: rgb(175, 176, 177); + --btn-patinator-text-color: var(--text-color); + --btn-paginator-hover-color: rgb(64, 65, 66); + --btn-active-bg: rgba(28, 52, 94, 1); + --btn-active-border-color: rgb(66, 94, 138); + --btn-text-color: var(--text-color); + --btn-paginator-border-color: var(--btn-border-color); + --btn-paginator-shadow: var(--main-wrapper-bg); + + /* Posts */ + --toc-highlight: rgb(116, 178, 243); + --tag-bg: rgb(41, 40, 40); + --tag-hover: rgb(43, 56, 62); + --tb-odd-bg: rgba(42, 47, 53, 0.52); /* odd rows of the posts' table */ + --tb-even-bg: rgb(31, 31, 34); /* even rows of the posts' table */ + --tb-border-color: var(--tb-odd-bg); + --footnote-target-bg: rgb(63, 81, 181); + --btn-share-color: #6c757d; + --btn-share-hover-color: #bfc1ca; + --relate-post-date: var(--text-muted-color); + --card-bg: rgb(39, 40, 43); + --card-border-color: rgb(53, 53, 60); + --card-box-shadow: var(--main-wrapper-bg); + + /* tags */ + --tag-border: rgb(59, 79, 88); + --tag-shadow: rgb(32, 33, 33); + --search-tag-bg: var(--tag-bg); + --dash-color: rgb(63, 65, 68); + + /* categories */ + --categories-border: rgb(64, 66, 69); + --categories-hover-bg: rgb(73, 75, 76); + + /* archives */ + --timeline-node-bg: rgb(150, 152, 156); + --timeline-color: rgb(63, 65, 68); + --timeline-year-dot-color: var(--timeline-color); + + /* Footer */ + --footer-link: rgb(171, 171, 171); + + .post-content img { + filter: brightness(90%); + } + + hr { + border-color: var(--main-border-color); + } + + /* posts' toc, override BS */ + nav[data-toggle=toc] .nav-link.active, + nav[data-toggle=toc] .nav-link.active:focus, + nav[data-toggle=toc] .nav-link.active:hover, + nav[data-toggle=toc] .nav > li > a:focus, + nav[data-toggle=toc] .nav > li > a:hover { + color: var(--toc-highlight) !important; + border-left-color: var(--toc-highlight) !important; + } + + /* categories */ + .categories.card, + .list-group-item { + background-color: var(--card-bg); + } + + .categories { + .card-header { + background-color: var(--card-header-bg); + } + .list-group-item { + border-left: none; + border-right: none; + padding-left: 2rem; + border-color: var(--categories-border); + &:last-child { + border-bottom-color: var(--card-bg); + } + } + } + + #archives li:nth-child(odd) { + background-image: linear-gradient( + to left, + rgb(26, 26, 30), + rgb(39, 39, 45), + rgb(39, 39, 45), + rgb(39, 39, 45), + rgb(26, 26, 30)); + } + +} // dark-scheme diff --git a/assets/css/_colors/light-syntax.scss b/assets/css/_colors/light-syntax.scss new file mode 100644 index 000000000000..7fb0d2743882 --- /dev/null +++ b/assets/css/_colors/light-syntax.scss @@ -0,0 +1,79 @@ +/*! +* The syntax light mode code snippet colors. +* v2.1 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2020 Cotes Chung +* MIT Licensed +*/ + +@mixin light-syntax { + /* see: */ + .highlight .hll { background-color: #ffffcc; } + .highlight .c { color: #999988; font-style: italic; } /* Comment */ + .highlight .err { color: #a61717; background-color: #e3d2d2; } /* Error */ + .highlight .k { color: #000000; font-weight: bold; } /* Keyword */ + .highlight .o { color: #000000; font-weight: bold; } /* Operator */ + .highlight .cm { color: #999988; font-style: italic; } /* Comment.Multiline */ + .highlight .cp { color: #999999; font-weight: bold; font-style: italic; } /* Comment.Preproc */ + .highlight .c1 { color: #999988; font-style: italic; } /* Comment.Single */ + .highlight .cs { color: #999999; font-weight: bold; font-style: italic; } /* Comment.Special */ + .highlight .gd { color: #d01040; background-color: #ffdddd; } /* Generic.Deleted */ + .highlight .ge { color: #000000; font-style: italic; } /* Generic.Emph */ + .highlight .gr { color: #aa0000; } /* Generic.Error */ + .highlight .gh { color: #999999; } /* Generic.Heading */ + .highlight .gi { color: #008080; background-color: #ddffdd; } /* Generic.Inserted */ + .highlight .go { color: #888888; } /* Generic.Output */ + .highlight .gp { color: #555555; } /* Generic.Prompt */ + .highlight .gs { font-weight: bold; } /* Generic.Strong */ + .highlight .gu { color: #aaaaaa; } /* Generic.Subheading */ + .highlight .gt { color: #aa0000; } /* Generic.Traceback */ + .highlight .kc { color: #000000; font-weight: bold; } /* Keyword.Constant */ + .highlight .kd { color: #000000; font-weight: bold; } /* Keyword.Declaration */ + .highlight .kn { color: #000000; font-weight: bold; } /* Keyword.Namespace */ + .highlight .kp { color: #000000; font-weight: bold; } /* Keyword.Pseudo */ + .highlight .kr { color: #000000; font-weight: bold; } /* Keyword.Reserved */ + .highlight .kt { color: #445588; font-weight: bold; } /* Keyword.Type */ + .highlight .m { color: #009999; } /* Literal.Number */ + .highlight .s { color: #d01040; } /* Literal.String */ + .highlight .na { color: #008080; } /* Name.Attribute */ + .highlight .nb { color: #0086b3; } /* Name.Builtin */ + .highlight .nc { color: #445588; font-weight: bold; } /* Name.Class */ + .highlight .no { color: #008080; } /* Name.Constant */ + .highlight .nd { color: #3c5d5d; font-weight: bold; } /* Name.Decorator */ + .highlight .ni { color: #800080; } /* Name.Entity */ + .highlight .ne { color: #990000; font-weight: bold; } /* Name.Exception */ + .highlight .nf { color: #990000; font-weight: bold; } /* Name.Function */ + .highlight .nl { color: #990000; font-weight: bold; } /* Name.Label */ + .highlight .nn { color: #555555; } /* Name.Namespace */ + .highlight .nt { color: #000080; } /* Name.Tag */ + .highlight .nv { color: #008080; } /* Name.Variable */ + .highlight .ow { color: #000000; font-weight: bold; } /* Operator.Word */ + .highlight .w { color: #bbbbbb; } /* Text.Whitespace */ + .highlight .mf { color: #009999; } /* Literal.Number.Float */ + .highlight .mh { color: #009999; } /* Literal.Number.Hex */ + .highlight .mi { color: #009999; } /* Literal.Number.Integer */ + .highlight .mo { color: #009999; } /* Literal.Number.Oct */ + .highlight .sb { color: #d01040; } /* Literal.String.Backtick */ + .highlight .sc { color: #d01040; } /* Literal.String.Char */ + .highlight .sd { color: #d01040; } /* Literal.String.Doc */ + .highlight .s2 { color: #d01040; } /* Literal.String.Double */ + .highlight .se { color: #d01040; } /* Literal.String.Escape */ + .highlight .sh { color: #d01040; } /* Literal.String.Heredoc */ + .highlight .si { color: #d01040; } /* Literal.String.Interpol */ + .highlight .sx { color: #d01040; } /* Literal.String.Other */ + .highlight .sr { color: #009926; } /* Literal.String.Regex */ + .highlight .s1 { color: #d01040; } /* Literal.String.Single */ + .highlight .ss { color: #990073; } /* Literal.String.Symbol */ + .highlight .bp { color: #999999; } /* Name.Builtin.Pseudo */ + .highlight .vc { color: #008080; } /* Name.Variable.Class */ + .highlight .vg { color: #008080; } /* Name.Variable.Global */ + .highlight .vi { color: #008080; } /* Name.Variable.Instance */ + .highlight .il { color: #009999; } /* Literal.Number.Integer.Long */ + + /* --- custom light colors --- */ + --highlight-bg-color: #f7f7f7; + --highlighter-rouge-color: #353a3d; + --highlight-lineno-color: #c2c6cc; + --highlight-lineno-border-color: #e9ecef; + --inline-code-bg: #f3f3f3; +} // light-syntax diff --git a/assets/css/_colors/light-typography.scss b/assets/css/_colors/light-typography.scss new file mode 100644 index 000000000000..d4388f4d0528 --- /dev/null +++ b/assets/css/_colors/light-typography.scss @@ -0,0 +1,76 @@ +/*! +* The syntax light mode typography colors +* v2.1 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2020 Cotes Chung +* MIT Licensed +*/ + +@mixin light-scheme { + /* Common */ + --body-bg: #fafafa; + --mask-bg: #c1c3c5; + --main-wrapper-bg: white; + --main-border-color: #f3f3f3; + --btn-border-color: #e9ecef; + --text-color: #333333; + --blockquote-border-color: #eee; + --blockquote-text-color: #9a9a9a; + --link-color: #2a408e; + --link-underline-color: #dee2e6; + --text-muted-color: gray; + --tb-odd-bg: #fbfcfd; + --tb-border-color: #eaeaea; + --button-bg: #fff; + --btn-backtotop-color: #686868; + --btn-backtotop-border-color: #f1f1f1; //--main-border-color, + --btn-box-shadow: #eaeaea; + + /* Sidebar */ + --sidebar-bg: radial-gradient( + circle, + rgba(42, 30, 107, 1) 0%, + rgba(35, 37, 46, 1) 100%); + --nav-cursor-color: #fcfcfc; + + /* Topbar */ + --topbar-wrapper-bg: white; + --topbar-text-color: rgb(78, 78, 78); + --search-wrapper-bg: #f5f5f5; + --search-tag-bg: #f8f9fa; + --search-icon-color: #c2c6cc; + --input-focus-border-color: var(--btn-border-color); + + /* Home page */ + --post-list-text-color: dimgray; + --btn-patinator-text-color: #555555; + --btn-paginator-hover-color: #e9ecef; + --btn-active-bg: #2a408e; + --btn-active-border-color: #007bff; + --btn-text-color: #f8f8f8; + --btn-paginator-border-color: #f1f1f1; + --btn-paginator-shadow: #4b92d2; + + /* Posts */ + --btn-share-hover-color: var(--link-color); + --card-border-color: #f1f1f1; + --card-box-shadow: rgba(234, 234, 234, 0.7686274509803922); + --label-color: #808080; + --relate-post-date: rgba(30, 55, 70, 0.4); + --tag-bg: rgba(0, 0, 0, 0.075); + --tag-border: #dee2e6; + --tag-shadow: var(--btn-border-color); + --tag-hover: rgb(222, 226, 230); + --categories-hover-bg: var(--btn-border-color); + --dash-color: silver; + + /* Archive */ + --timeline-color: rgba(0, 0, 0, 0.075); + --timeline-node-bg: #c2c6cc; + --timeline-year-dot-color: #ffffff; + + /* Footer */ + --footer-bg-color: #ffffff; + --footnote-target-bg: lightcyan; + --footer-link: #424242; +} // light-scheme diff --git a/assets/css/archives.scss b/assets/css/archives.scss new file mode 100644 index 000000000000..db6224ae2c2e --- /dev/null +++ b/assets/css/archives.scss @@ -0,0 +1,150 @@ +--- +# Style for Archives +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT License +--- + + +{% include_relative _addon/main.scss %} + +%date-timeline { + content: ""; + width: 4px; + left: 75px; + display: inline-block; + float: left; + position: relative; + background-color: var(--timeline-color); +} + +%date-font { + font-family: 'Roboto Condensed', sans-serif; +} + +#archives { + letter-spacing: 0.03rem; + li { + font-size: 1.1rem; + line-height: 3rem; + &:nth-child(odd) { + background-color: var(--main-wrapper-bg, #fff); + background-image: linear-gradient( + to left, #fff, #fbfbfb, #fbfbfb, #fbfbfb, #fff); + } + > div { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + span.lead { + font-size: 1.5rem; + @extend %date-font; + position: relative; + left: 8px; + + &:not(:first-child) { + position: relative; + left: 4px; + &::after { + left: 67px; + } + } + + &::after { + /* Year dot */ + content: ""; + display: block; + position: relative; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + width: 12px; + height: 12px; + top: -26px; + left: 63px; + border: 3px solid; + background-color: var(--timeline-year-dot-color); + border-color: var(--timeline-node-bg); + box-shadow: 0 0 2px 0 #c2c6cc; + z-index: 1; + } + } // #archives span.lead + + .date { + white-space: nowrap; + display: inline-block; + &.month { + width: 1.4rem; + text-align: center; + @extend %date-font; + ~a::before { + /* A dot for Month and Day */ + content: ""; + display: inline-block; + position: relative; + -webkit-border-radius: 50%; + -moz-border-radius: 50%; + border-radius: 50%; + width: 8px; + height: 8px; + float: left; + top: 1.35rem; + left: 69px; + background-color: var(--timeline-node-bg); + box-shadow: 0 0 3px 0 #c2c6cc; + z-index: 1; + } + } + &.day { + font-size: 85%; + font-family: 'Lato', sans-serif; + text-align: center; + margin-right: -2px; + width: 1.2rem; + position: relative; + left: -.15rem; + } + } // #archives .date + + ul { + > li { + > div > a { + /* post title in Archvies */ + margin-left: 2.5rem; + position: relative; + top: 0.1rem; + } + &::after { + @extend %date-timeline; + height: 2.8rem; + top: -1.3rem; + } + &:first-child::before { + @extend %date-timeline; + height: 3.06rem; + top: -1.61rem; + } + } + &:not(:last-child) > li:last-child::after { + height: 3.4rem; + } + &:last-child > li:last-child::after { + display: none; + } + } // #archives ul + +} // #archives + + +@media all and (max-width: 576px) { + #archives { + margin-top: -1rem; + ul { + letter-spacing: 0; + } + } +} diff --git a/assets/css/categories.scss b/assets/css/categories.scss new file mode 100644 index 000000000000..a72ebe9196cb --- /dev/null +++ b/assets/css/categories.scss @@ -0,0 +1,71 @@ +--- +# Style for Tab Categories +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT License +--- + + +{% include_relative _addon/main.scss %} + +%category-icon-color { + color: gray; +} + +.categories { + margin-bottom: 2rem; + .card-header { + padding-right: 12px; + } + .list-group-item { + border-left: none; + border-right: none; + padding-left: 2rem; + > i { + @extend %category-icon-color; + } + &:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; + } + + } + + .card-header > span > i:first-child { + @extend %category-icon-color; + } + + i { + &.far, &.fas { + font-size: 86%; // fontawesome icons + } + } + +} // .categories + +.category-trigger { + width: 1.7rem; + height: 1.7rem; + border-radius: 50%; + text-align: center; + color: #6c757d!important; + > i.fas { + position: relative; + height: 0.7rem; + width: 1rem; + transition: 300ms ease all; + } +} + +@media (hover: hover) { // only works on desktop + .category-trigger:hover { + background-color: var(--categories-hover-bg); + } +} + +.rotate { + -ms-transform: rotate(-90deg); /* IE 9 */ + -webkit-transform: rotate(-90deg); /* Safari 3-8 */ + transform: rotate(-90deg); +} diff --git a/assets/css/category-tag.scss b/assets/css/category-tag.scss new file mode 100644 index 000000000000..87c20413a368 --- /dev/null +++ b/assets/css/category-tag.scss @@ -0,0 +1,73 @@ +--- +# Style for page Category and Tag +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT License +--- + + +{% include_relative _addon/main.scss %} + +#page-category, #page-tag { + ul > li { + line-height: 1.5rem; + padding: 0.6rem 0; + &::before { // dot + background: #999; + width: 5px; + height: 5px; + border-radius: 50%; + display: block; + content: ""; + position: relative; + top: 0.6rem; + margin-right: 0.5rem; + } + > a { /* post's title */ + font-size: 1.1rem; + @extend %no-bottom-border; + } + > span:last-child { + white-space: nowrap; + } + /* post's date */ + } +} + +#page-tag h1 > i { // tag icon + font-size: 1.2rem; +} + +#page-category h1 > i { + font-size: 1.25rem; +} + +a:hover { + #page-category &, + #page-tag &, + #access-lastmod & { + @extend %link-hover; + margin-bottom: -1px; // Avoid jumping + } +} + +.dash { + margin: 0 .5rem .6rem .5rem; + border-bottom: 2px dotted var(--dash-color); +} + +@media all and (max-width: 576px) { + #page-category, #page-tag { + ul > li { + &::before { + margin: 0 .5rem; + } + > a { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + } +} diff --git a/assets/css/home.scss b/assets/css/home.scss new file mode 100644 index 000000000000..0cbf7e5917a1 --- /dev/null +++ b/assets/css/home.scss @@ -0,0 +1,145 @@ +--- +# Style for Homepage +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT License +--- + +{% include_relative _addon/main.scss %} + +#post-list { + margin-top: 1rem; + padding-right: 0.5rem; + + .post-preview { + padding-top: 1.5rem; + padding-bottom: 1rem; + border-bottom: 1px solid var(--main-border-color); + + h1 { + font-size: 1.4rem; + margin: 0; + ~i { // pinned icon + font-size: 0.86rem; + } + } + + .post-meta { + i { + font-size: 0.73rem; + &:not(:first-child) { // post-meta icons on the homepage + margin-left: 1.5rem; + } + } + } + + .post-content { + margin-top: 0.6rem; + margin-bottom: 0.6rem; + color: var(--post-list-text-color); + >p { + /* Make preview shorter on the homepage */ + margin: 0; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + } + } + + } // .post-preview + +} // #post-list + +.pagination { + font-size: 1rem; + a:hover { + text-decoration: none; + } + + .page-item { + .page-link { + color: var(--btn-patinator-text-color); + width: 2.5rem; + height: 2.5rem; + padding: 0; + text-align: center; + display: -webkit-box; + display: flex; + -webkit-box-pack: center; + justify-content: center; + -webkit-box-align: center; + align-items: center; + border-radius: 50%; + border: 1px solid var(--btn-paginator-border-color); + font-family: 'Lato', sans-serif; + background-color: var(--button-bg); + &:hover { + background-color: var(--btn-paginator-hover-color) + } + } + &.active { + .page-link { + background-color: var(--btn-active-bg); + border-color: var(--btn-active-border-color); + box-shadow: 0 0 8px 0 var(--btn-paginator-shadow) !important; + color: var(--btn-text-color); + } + } + &.disabled { + cursor: not-allowed; + .page-link { + color: rgba(108, 117, 125, 0.57); + border-color: var(--btn-paginator-border-color); + background-color: var(--button-bg); + } + } + &:first-child .page-link, + &:last-child .page-link { + border-radius: 50%; + } + &:not(:last-child) { + margin-right: 0.7rem; + } + } // .page-item + +} // .pagination + +@media all and (max-width: 576px) { + #post-list .post-meta>span i:not(:first-child) { + margin-left: 1rem; + } +} + +/* Hide SideBar and TOC */ +@media all and (max-width: 830px) { + .pagination { + justify-content: center; + } +} + +/* Sidebar is visible */ +@media all and (min-width: 831px) { + + #post-list { + margin-top: 1.5rem; + } + + .pagination { + font-size: 0.85rem; + .page-item .page-link { + width: 2.2rem; + height: 2.2rem; + } + } + +} + +/* Pannel hidden */ +@media all and (max-width: 1200px) { + #post-list { + padding-right: 0; + } +} diff --git a/assets/css/lib/bootstrap-toc.min.css b/assets/css/lib/bootstrap-toc.min.css new file mode 100644 index 000000000000..3c6210780b47 --- /dev/null +++ b/assets/css/lib/bootstrap-toc.min.css @@ -0,0 +1,4 @@ +/*! + * Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */nav[data-toggle=toc] .nav>li>a{display:block;padding:4px 20px;font-size:13px;font-weight:500;color:#767676}nav[data-toggle=toc] .nav>li>a:focus,nav[data-toggle=toc] .nav>li>a:hover{padding-left:19px;color:#563d7c;text-decoration:none;background-color:transparent;border-left:1px solid #563d7c}nav[data-toggle=toc] .nav-link.active,nav[data-toggle=toc] .nav-link.active:focus,nav[data-toggle=toc] .nav-link.active:hover{padding-left:18px;font-weight:700;color:#563d7c;background-color:transparent;border-left:2px solid #563d7c}nav[data-toggle=toc] .nav-link+ul{display:none;padding-bottom:10px}nav[data-toggle=toc] .nav .nav>li>a{padding-top:1px;padding-bottom:1px;padding-left:30px;font-size:12px;font-weight:400}nav[data-toggle=toc] .nav .nav>li>a:focus,nav[data-toggle=toc] .nav .nav>li>a:hover{padding-left:29px}nav[data-toggle=toc] .nav .nav>li>.active,nav[data-toggle=toc] .nav .nav>li>.active:focus,nav[data-toggle=toc] .nav .nav>li>.active:hover{padding-left:28px;font-weight:500}nav[data-toggle=toc] .nav-link.active+ul{display:block} \ No newline at end of file diff --git a/assets/css/page.scss b/assets/css/page.scss new file mode 100644 index 000000000000..10ef9fa3e60a --- /dev/null +++ b/assets/css/page.scss @@ -0,0 +1,10 @@ +--- +# The default style for layout Page +# v2.2 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT License +--- + +{% include_relative _addon/main.scss %} +{% include_relative _addon/syntax.scss %} diff --git a/assets/css/post.scss b/assets/css/post.scss new file mode 100644 index 000000000000..77a6eec06342 --- /dev/null +++ b/assets/css/post.scss @@ -0,0 +1,350 @@ +--- +# Post-specific style +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT License +--- + + +{% include_relative _addon/main.scss %} +{% include_relative _addon/syntax.scss %} + +$prompt-older: "{{ site.data.label.post.button.previous }}"; +$prompt-newer: "{{ site.data.label.post.button.next }}"; + +@mixin btn-sharing-color($light-color, $important: false) { + @if $important { + color: var(--btn-share-color, $light-color)!important; + } @else { + color: var(--btn-share-color, $light-color); + } +} + +@mixin btn-post-nav { + width: 50%; + position: relative; + border-color: var(--btn-border-color); +} + +.post-content { + > ol, > ul, > dl { + padding-left: 2rem; + li+li { + margin-top: 0.3rem; + } + } + li { + > ol, > ul, > dl { // sub list + padding-left: 2rem; + } + > p { + margin: 1rem 0 0.8rem; + } + } + .post-preview-img { + margin-top: 0; + margin-bottom: 2.5rem; + @include align-center; + } +} + +.post-tail-wrapper { + margin-top: 6rem; + border-bottom: 1px double var(--main-border-color); + font-size: 0.85rem; +} + +.post-tags { + line-height: 2rem; +} + +.post-navigation { + padding-top: 3rem; + padding-bottom: 4rem; + + .btn { + @include btn-post-nav; + color: var(--link-color); + &:hover { + background: #2a408e; + color: #fff; + border-color: #2a408e; + } + &.disabled { + @include btn-post-nav; + pointer-events: auto; + cursor: not-allowed; + background: none; + color: gray; + &:hover { + border-color: none; + } + } + &.btn-outline-primary.disabled:focus { + box-shadow: none; + } + } + + p { + font-size: 1.1rem; + line-height: 1.5rem; + margin-top: 0.3rem; + white-space: normal; + } + + a, span { + &::before { + color: var(--text-muted-color); + font-size: 0.65rem; + text-transform: uppercase; + } + &:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + left: 0.5px; + &::before { + content: $prompt-older + } + } + &:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + right: 0.5px; + &::before { + content: $prompt-newer + } + } + } +} // .post-navigation + +@keyframes fade-up { + from { + opacity: 0; + position: relative; + top: 2rem; + } + to { + opacity: 1; + position: relative; + top: 0; + } +} + +#toc-wrapper { + border-left: 1px solid rgba(158, 158, 158, 0.17); + position: -webkit-sticky; + position: sticky; + top: 4rem; + transition: top 0.2s ease-in-out; + animation: fade-up .8s; + &.topbar-down { + top: 6rem; + } + > span { + @include panel-label; + } +} + +#toc li>a { + line-height: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + + +/*--- Related Posts ---*/ + +#related-posts { + >h3 { + @include label(1.1rem, 600); + } + .card { + border: 1px solid var(--card-border-color); + background-color: var(--card-bg); + box-shadow: 0 0 5px 0 var(--card-box-shadow); + -webkit-transition: all .3s ease-in-out; + -moz-transition: all .3s ease-in-out; + transition: all .3s ease-in-out; + h3 { + color: var(--text-color); + } + &:hover { + -webkit-transform: translate3d(0, -3px, 0); + transform: translate3d(0, -3px, 0); + box-shadow: 0 20px 35px -4px rgba(0, 0, 0, 0.15); + } + } + + .timeago { + color: var(--relate-post-date); + } + + p { + font-size: 0.9rem; + margin-bottom: 0.5rem; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + } + + a:hover { + text-decoration: none; + } + + ul { + list-style-type: none; + padding-inline-start: 1.5rem; + >li::before { + background: #c2c9d4; + width: 5px; + height: 5px; + border-radius: 1px; + display: block; + content: ""; + position: relative; + top: 1rem; + right: 1rem; + } + } +} + +#post-extend-wrapper { + min-height: 2rem; + #disqus_thread { + margin-bottom: 2rem; + } +} + +.post-tail-bottom a { + color: inherit; +} + +%btn-share-hovor { + color: var(--btn-share-hover-color)!important; +} + +.share-wrapper { + vertical-align: middle; + user-select: none; + .share-icons { + font-size: 1.2rem; + a { + &:not(:last-child) { + margin-right: 0.25rem; + } + &:hover { + text-decoration: none; + >i { + @extend %btn-share-hovor; + } + } + } + >i { + padding-top: 0.35rem; + &:hover { + @extend %btn-share-hovor; + } + } + .fab { + &.fa-twitter { + @include btn-sharing-color(rgba(29, 161, 242, 1.00)); + } + &.fa-facebook-square { + @include btn-sharing-color(rgb(66, 95, 156)); + } + &.fa-telegram { + @include btn-sharing-color(rgb(39, 159, 217)); + } + &.fa-weibo { + @include btn-sharing-color(rgb(229, 20, 43)); + } + } + + } // .share-icons + + .fas.fa-link { + @include btn-sharing-color(rgb(171, 171, 171)); + } + +} // .share-wrapper + + +.share-label { + @include label(inherit, 400, inherit); + &::after { + content: ":"; + } +} + +.license-wrapper { + line-height: 1.2rem; + >a { + font-weight: 600; + &:hover { + @extend %link-hover; + } + } + i { + font-weight: 400; + } + span:last-child { + font-size: 0.85rem; + } +} // .license-wrapper + + +@media all and (max-width: 576px) { + .post-tail-bottom { + -ms-flex-wrap: wrap-reverse!important; + flex-wrap: wrap-reverse!important; + >div:first-child { + width: 100%; + margin-top: 1rem; + } + } +} + +@media all and (max-width: 768px) { + .post img { + max-width: calc(100% + 1rem); + } +} + +@media all and (min-width: 768px) { + .post { + .post-meta { + >div:not(:first-child)::before { + content: "\2022"; + color: rgba(158, 158, 158, 0.8); + font-weight: bold; + padding-left: 0.5rem; + padding-right: 0.3rem; + } + &.flex-column { + -webkit-box-orient: horizontal!important; + -webkit-box-direction: normal!important; + -ms-flex-direction: row!important; + flex-direction: row!important; + } + } + } // .post +} + +@media all and (min-width: 768px) and (max-width: 830px) { + .post img { + max-width: calc(100% + 2rem); + } +} + +/* Hide SideBar and TOC */ +@media all and (max-width: 830px) { + .post-navigation { + padding-left: 0; + padding-right: 0; + margin-left: -.5rem; + margin-right: -.5rem; + } +} diff --git a/assets/css/tags.scss b/assets/css/tags.scss new file mode 100644 index 000000000000..e8e4f8c72bb0 --- /dev/null +++ b/assets/css/tags.scss @@ -0,0 +1,25 @@ +--- +# Styles for Tab Tags +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT License +--- + + +{% include_relative _addon/main.scss %} + +.tag { + border-radius: 0.7em; + padding: 6px 8px 7px; + margin-right: 0.8rem; + line-height: 3rem; + letter-spacing: 0; + border: 1px solid var(--tag-border) !important; + box-shadow: 0 0 3px 0 var(--tag-shadow); + span { + margin-left: 0.6em; + font-size: 0.7em; + font-family: 'Oswald', sans-serif; + } +} diff --git a/assets/img/favicons/android-icon-144x144.png b/assets/img/favicons/android-icon-144x144.png new file mode 100644 index 000000000000..b8a1fdfd01dd Binary files /dev/null and b/assets/img/favicons/android-icon-144x144.png differ diff --git a/assets/img/favicons/android-icon-192x192.png b/assets/img/favicons/android-icon-192x192.png new file mode 100644 index 000000000000..c4ccd882d21e Binary files /dev/null and b/assets/img/favicons/android-icon-192x192.png differ diff --git a/assets/img/favicons/android-icon-36x36.png b/assets/img/favicons/android-icon-36x36.png new file mode 100644 index 000000000000..b87f75b82a75 Binary files /dev/null and b/assets/img/favicons/android-icon-36x36.png differ diff --git a/assets/img/favicons/android-icon-48x48.png b/assets/img/favicons/android-icon-48x48.png new file mode 100644 index 000000000000..ce34afe4c1ed Binary files /dev/null and b/assets/img/favicons/android-icon-48x48.png differ diff --git a/assets/img/favicons/android-icon-72x72.png b/assets/img/favicons/android-icon-72x72.png new file mode 100644 index 000000000000..7e6afdea0ecd Binary files /dev/null and b/assets/img/favicons/android-icon-72x72.png differ diff --git a/assets/img/favicons/android-icon-96x96.png b/assets/img/favicons/android-icon-96x96.png new file mode 100644 index 000000000000..b16e4eadc646 Binary files /dev/null and b/assets/img/favicons/android-icon-96x96.png differ diff --git a/assets/img/favicons/apple-icon-114x114.png b/assets/img/favicons/apple-icon-114x114.png new file mode 100644 index 000000000000..e7a3c727a69f Binary files /dev/null and b/assets/img/favicons/apple-icon-114x114.png differ diff --git a/assets/img/favicons/apple-icon-120x120.png b/assets/img/favicons/apple-icon-120x120.png new file mode 100644 index 000000000000..74fbd06426bd Binary files /dev/null and b/assets/img/favicons/apple-icon-120x120.png differ diff --git a/assets/img/favicons/apple-icon-144x144.png b/assets/img/favicons/apple-icon-144x144.png new file mode 100644 index 000000000000..b8a1fdfd01dd Binary files /dev/null and b/assets/img/favicons/apple-icon-144x144.png differ diff --git a/assets/img/favicons/apple-icon-152x152.png b/assets/img/favicons/apple-icon-152x152.png new file mode 100644 index 000000000000..d4363efa993b Binary files /dev/null and b/assets/img/favicons/apple-icon-152x152.png differ diff --git a/assets/img/favicons/apple-icon-180x180.png b/assets/img/favicons/apple-icon-180x180.png new file mode 100644 index 000000000000..691b68d46fea Binary files /dev/null and b/assets/img/favicons/apple-icon-180x180.png differ diff --git a/assets/img/favicons/apple-icon-57x57.png b/assets/img/favicons/apple-icon-57x57.png new file mode 100644 index 000000000000..43a53d9a9abb Binary files /dev/null and b/assets/img/favicons/apple-icon-57x57.png differ diff --git a/assets/img/favicons/apple-icon-60x60.png b/assets/img/favicons/apple-icon-60x60.png new file mode 100644 index 000000000000..10062d15787d Binary files /dev/null and b/assets/img/favicons/apple-icon-60x60.png differ diff --git a/assets/img/favicons/apple-icon-72x72.png b/assets/img/favicons/apple-icon-72x72.png new file mode 100644 index 000000000000..7e6afdea0ecd Binary files /dev/null and b/assets/img/favicons/apple-icon-72x72.png differ diff --git a/assets/img/favicons/apple-icon-76x76.png b/assets/img/favicons/apple-icon-76x76.png new file mode 100644 index 000000000000..bfbee31f71d3 Binary files /dev/null and b/assets/img/favicons/apple-icon-76x76.png differ diff --git a/assets/img/favicons/apple-icon-precomposed.png b/assets/img/favicons/apple-icon-precomposed.png new file mode 100644 index 000000000000..fe6fc1d9dabb Binary files /dev/null and b/assets/img/favicons/apple-icon-precomposed.png differ diff --git a/assets/img/favicons/apple-icon.png b/assets/img/favicons/apple-icon.png new file mode 100644 index 000000000000..fe6fc1d9dabb Binary files /dev/null and b/assets/img/favicons/apple-icon.png differ diff --git a/assets/img/favicons/browserconfig.xml b/assets/img/favicons/browserconfig.xml new file mode 100644 index 000000000000..c55414822300 --- /dev/null +++ b/assets/img/favicons/browserconfig.xml @@ -0,0 +1,2 @@ + +#ffffff \ No newline at end of file diff --git a/assets/img/favicons/favicon-16x16.png b/assets/img/favicons/favicon-16x16.png new file mode 100644 index 000000000000..7e64846c2273 Binary files /dev/null and b/assets/img/favicons/favicon-16x16.png differ diff --git a/assets/img/favicons/favicon-32x32.png b/assets/img/favicons/favicon-32x32.png new file mode 100644 index 000000000000..6c08918cd7e5 Binary files /dev/null and b/assets/img/favicons/favicon-32x32.png differ diff --git a/assets/img/favicons/favicon-96x96.png b/assets/img/favicons/favicon-96x96.png new file mode 100644 index 000000000000..b16e4eadc646 Binary files /dev/null and b/assets/img/favicons/favicon-96x96.png differ diff --git a/assets/img/favicons/favicon.ico b/assets/img/favicons/favicon.ico new file mode 100644 index 000000000000..66666d79d8d3 Binary files /dev/null and b/assets/img/favicons/favicon.ico differ diff --git a/assets/img/favicons/manifest.json b/assets/img/favicons/manifest.json new file mode 100644 index 000000000000..013d4a6a5333 --- /dev/null +++ b/assets/img/favicons/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} \ No newline at end of file diff --git a/assets/img/favicons/ms-icon-144x144.png b/assets/img/favicons/ms-icon-144x144.png new file mode 100644 index 000000000000..b8a1fdfd01dd Binary files /dev/null and b/assets/img/favicons/ms-icon-144x144.png differ diff --git a/assets/img/favicons/ms-icon-150x150.png b/assets/img/favicons/ms-icon-150x150.png new file mode 100644 index 000000000000..6001e42722a2 Binary files /dev/null and b/assets/img/favicons/ms-icon-150x150.png differ diff --git a/assets/img/favicons/ms-icon-310x310.png b/assets/img/favicons/ms-icon-310x310.png new file mode 100644 index 000000000000..0df87e62b2a9 Binary files /dev/null and b/assets/img/favicons/ms-icon-310x310.png differ diff --git a/assets/img/favicons/ms-icon-70x70.png b/assets/img/favicons/ms-icon-70x70.png new file mode 100644 index 000000000000..9747f42210f8 Binary files /dev/null and b/assets/img/favicons/ms-icon-70x70.png differ diff --git a/assets/img/posts/Guido_van_Rossum.jpg b/assets/img/posts/Guido_van_Rossum.jpg new file mode 100644 index 000000000000..e18bd00e35a6 Binary files /dev/null and b/assets/img/posts/Guido_van_Rossum.jpg differ diff --git a/assets/img/posts/programming_languages_ranking_github.jpg b/assets/img/posts/programming_languages_ranking_github.jpg new file mode 100644 index 000000000000..dc25f7b3f9b6 Binary files /dev/null and b/assets/img/posts/programming_languages_ranking_github.jpg differ diff --git a/assets/img/sample/avatar.jpg b/assets/img/sample/avatar.jpg new file mode 100644 index 000000000000..e8481d35f9ba Binary files /dev/null and b/assets/img/sample/avatar.jpg differ diff --git a/assets/img/sample/devices-mockup.png b/assets/img/sample/devices-mockup.png new file mode 100644 index 000000000000..dd58e500bb71 Binary files /dev/null and b/assets/img/sample/devices-mockup.png differ diff --git a/assets/img/sample/download-icons.png b/assets/img/sample/download-icons.png new file mode 100644 index 000000000000..ae0933aeb3d9 Binary files /dev/null and b/assets/img/sample/download-icons.png differ diff --git a/assets/img/sample/gh-pages-sources.png b/assets/img/sample/gh-pages-sources.png new file mode 100644 index 000000000000..52f77c7b6244 Binary files /dev/null and b/assets/img/sample/gh-pages-sources.png differ diff --git a/assets/img/sample/mockup.png b/assets/img/sample/mockup.png new file mode 100644 index 000000000000..573c33bc81e0 Binary files /dev/null and b/assets/img/sample/mockup.png differ diff --git a/assets/img/sample/upload-image.png b/assets/img/sample/upload-image.png new file mode 100644 index 000000000000..46eab79e7101 Binary files /dev/null and b/assets/img/sample/upload-image.png differ diff --git a/assets/js/_commons.js b/assets/js/_commons.js new file mode 100644 index 000000000000..d472dde05191 --- /dev/null +++ b/assets/js/_commons.js @@ -0,0 +1,21 @@ +/*! + Aggregation of common JS. + Chirpy@2.3 + https://github.com/cotes2020/jekyll-theme-chirpy + © 2020 Cotes Chung + MIT License +*/ + +{% include_relative _commons/back-to-top.js %} + +{% include_relative _commons/search-display.js %} + +{% include_relative _commons/sidebar.js %} + +{% include_relative _commons/topbar-switch.js %} + +{% include_relative _commons/topbar-title.js %} + +{% include_relative _commons/copy-link.js %} + +{% include_relative _utils/tooltip-loader.js %} diff --git a/assets/js/_commons/back-to-top.js b/assets/js/_commons/back-to-top.js new file mode 100644 index 000000000000..07532ae0df79 --- /dev/null +++ b/assets/js/_commons/back-to-top.js @@ -0,0 +1,18 @@ +/* +Reference: https://bootsnipp.com/snippets/featured/link-to-top-page +*/ +$(window).scroll(function() { + if ($(this).scrollTop() > 50 + && $("#sidebar-trigger").css("display") === "none") { + $("#back-to-top").fadeIn(); + } else { + $("#back-to-top").fadeOut(); + } +}); + +$(function() { + $("#back-to-top").click(function() { + $("body,html").animate({scrollTop: 0}, 800); + return false; + }); +}); \ No newline at end of file diff --git a/assets/js/_commons/copy-link.js b/assets/js/_commons/copy-link.js new file mode 100644 index 000000000000..5a9c1005ad71 --- /dev/null +++ b/assets/js/_commons/copy-link.js @@ -0,0 +1,22 @@ +/* + * Copy current page url to clipboard. + * v2.1 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2020 Cotes Chung + * MIT License + */ + +function copyLink(url) { + if (!url || 0 === url.length) { + url = window.location.href; + } + + var $temp = $(""); + $("body").append($temp); + $temp.val(url).select(); + document.execCommand("copy"); + $temp.remove(); + + alert("Link copied successfully!"); + +} diff --git a/assets/js/_commons/search-display.js b/assets/js/_commons/search-display.js new file mode 100644 index 000000000000..933d94077f5b --- /dev/null +++ b/assets/js/_commons/search-display.js @@ -0,0 +1,155 @@ +/* +* This script make #search-result-wrapper switch to unloaded or shown automatically. +* v2.0 +* https://github.com/cotes2020/jekyll-theme-chirpy +* © 2018-2019 Cotes Chung +* MIT License +*/ + +$(function() { + + var btnSbTrigger = $("#sidebar-trigger"); + var btnSearchTrigger = $("#search-trigger"); + var btnCancel = $("#search-cancel"); + var btnClear = $("#search-cleaner"); + + var main = $("#main"); + var topbarTitle = $("#topbar-title"); + var searchWrapper = $("#search-wrapper"); + var resultWrapper = $("#search-result-wrapper"); + var results = $("#search-results"); + var input = $("#search-input"); + var hints = $("#search-hints"); + + + /*--- Actions in small screens (Sidebar unloaded) ---*/ + + var scrollBlocker = (function() { + var offset = 0; + return { + block() { + offset = $(window).scrollTop(); + }, + release() { + $("html,body").scrollTop(offset); + }, + getOffset() { + return offset; + } + }; + }()); + + var mobileSearchBar = (function() { + return { + on() { + btnSbTrigger.addClass("unloaded"); + topbarTitle.addClass("unloaded"); + btnSearchTrigger.addClass("unloaded"); + searchWrapper.addClass("d-flex"); + btnCancel.addClass("loaded"); + }, + off() { + btnCancel.removeClass("loaded"); + searchWrapper.removeClass("d-flex"); + btnSbTrigger.removeClass("unloaded"); + topbarTitle.removeClass("unloaded"); + btnSearchTrigger.removeClass("unloaded"); + } + }; + }()); + + var resultSwitch = (function() { + var visable = false; + + return { + on() { + if (!visable) { + resultWrapper.removeClass("unloaded"); + main.addClass("hidden"); + + visable = true; + scrollBlocker.block(); + } + }, + off() { + if (visable) { + results.empty(); + if (hints.hasClass("unloaded")) { + hints.removeClass("unloaded"); + } + resultWrapper.addClass("unloaded"); + btnClear.removeClass("visable"); + main.removeClass("hidden"); + + input.val(""); + visable = false; + + scrollBlocker.release(); + } + }, + isVisable() { + return visable; + } + }; + + }()); + + + function isMobileView() { + return btnCancel.hasClass("loaded"); + } + + btnSearchTrigger.click(function() { + mobileSearchBar.on(); + resultSwitch.on(); + input.focus(); + }); + + btnCancel.click(function() { + mobileSearchBar.off(); + resultSwitch.off(); + }); + + input.focus(function() { + searchWrapper.addClass("input-focus"); + }); + + input.focusout(function() { + searchWrapper.removeClass("input-focus"); + }); + + input.on("keyup", function(e) { + if (e.keyCode === 8 && input.val() === "") { + if (!isMobileView()) { + resultSwitch.off(); + } else { + hints.removeClass("unloaded"); + } + } else { + if (input.val() !== "") { + resultSwitch.on(); + + if (!btnClear.hasClass("visible")) { + btnClear.addClass("visable"); + } + + if (isMobileView()) { + hints.addClass("unloaded"); + } + } + } + }); + + btnClear.on("click", function() { + input.val(""); + if (isMobileView()) { + hints.removeClass("unloaded"); + results.empty(); + } else { + resultSwitch.off(); + } + input.focus(); + btnClear.removeClass("visable"); + }); + +}); diff --git a/assets/js/_commons/sidebar.js b/assets/js/_commons/sidebar.js new file mode 100644 index 000000000000..44bf3f400c72 --- /dev/null +++ b/assets/js/_commons/sidebar.js @@ -0,0 +1,34 @@ +/** + * Expand or close the sidebar in mobile screens. + * v2.0 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2018-2019 Cotes Chung + * MIT License + */ + +$(function() { + + var sidebarUtil = (function() { + const ATTR_DISPLAY = "sidebar-display"; + var isExpanded = false; + var body = $("body"); + + return { + toggle() { + if (isExpanded === false) { + body.attr(ATTR_DISPLAY, ""); + } else { + body.removeAttr(ATTR_DISPLAY); + } + + isExpanded = !isExpanded; + } + }; + + }()); + + $("#sidebar-trigger").click(sidebarUtil.toggle); + + $("#mask").click(sidebarUtil.toggle); + +}); diff --git a/assets/js/_commons/topbar-switch.js b/assets/js/_commons/topbar-switch.js new file mode 100644 index 000000000000..0f915bb57ede --- /dev/null +++ b/assets/js/_commons/topbar-switch.js @@ -0,0 +1,69 @@ +/* + * Hide Header on scroll down + * v2.0 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2018-2019 Cotes Chung + * MIT License + */ + +$(function() { + + var didScroll; + var lastScrollTop = 0; + var delta = 5; + var topbarHeight = $("#topbar-wrapper").outerHeight(); + + function hasScrolled() { + var st = $(this).scrollTop(); + + /* Make sure they scroll more than delta */ + if (Math.abs(lastScrollTop - st) <= delta) { + return; + } + + if (st > lastScrollTop && st > topbarHeight) { + /* Scroll Down */ + $("#topbar-wrapper").removeClass("topbar-down").addClass("topbar-up"); + + if ($("#toc-wrapper").length > 0) { + $("#toc-wrapper").removeClass("topbar-down"); + } + + if ($(".access").length > 0) { + $(".access").removeClass("topbar-down"); + } + + if ($("#search-input").is(":focus")) { + $("#search-input").blur(); /* remove focus */ + } + + } else { + /* Scroll Up */ + if (st + $(window).height() < $(document).height()) { + $("#topbar-wrapper").removeClass("topbar-up").addClass("topbar-down"); + if ($("#toc-wrapper").length > 0) { + $("#toc-wrapper").addClass("topbar-down"); + } + if ($(".access").length > 0) { + $(".access").addClass("topbar-down"); + } + } + } + + lastScrollTop = st; + } + + $(window).scroll(function(event) { + if ($("#topbar-title").is(":hidden")) { /* Not in small screens */ + didScroll = true; + } + }); + + setInterval(function() { + if (didScroll) { + hasScrolled(); + didScroll = false; + } + }, 250); + +}); \ No newline at end of file diff --git a/assets/js/_commons/topbar-title.js b/assets/js/_commons/topbar-title.js new file mode 100644 index 000000000000..dc39ae40f105 --- /dev/null +++ b/assets/js/_commons/topbar-title.js @@ -0,0 +1,47 @@ +/* + * Topbar title auto change while scrolling in mobile screens. + * v2.0 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2018-2019 Cotes Chung + * MIT License +*/ + +$(function() { + + var DEFAULT = $("#topbar-title").text().trim(); + var title = ($("div.post>h1").length > 0) ? + $("div.post>h1").text().trim() : $("h1").text().trim(); + + if ($("#page-category").length || $("#page-tag").length) { + /* The title in Category or Tag page will be " <count_of_posts>" */ + if (/\s/.test(title)) { + title = title.replace(/[0-9]/g, "").trim(); + } + } + + /* Replace topbar title while scroll screens. */ + $(window).scroll(function () { + if ($("#post-list").length /* in Home page */ + || $("div.post>h1").is(":hidden") /* is tab pages */ + || $("#topbar-title").is(":hidden") /* not mobile screens */ + || $("#sidebar.sidebar-expand").length) { /* when the sidebar trigger is clicked */ + return false; + } + + if ($(this).scrollTop() >= 95) { + if ($("#topbar-title").text() !== title) { + $("#topbar-title").text(title); + } + } else { + if ($("#topbar-title").text() !== DEFAULT) { + $("#topbar-title").text(DEFAULT); + } + } + }); + + /* Click title remove hover effect. */ + $("#topbar-title").click(function() { + $("body,html").animate({scrollTop: 0}, 800); + }); + +}); \ No newline at end of file diff --git a/assets/js/_home-post.js b/assets/js/_home-post.js new file mode 100644 index 000000000000..c80277769f17 --- /dev/null +++ b/assets/js/_home-post.js @@ -0,0 +1,22 @@ +/*! + JS group for layout Home or Post + Chirpy v2.3 + https://github.com/cotes2020/jekyll-theme-chirpy + © 2020 Cotes Chung + MIT License +*/ + +{% include_relative _commons.js %} + +{% include_relative _utils/timeago.js %} + + +{% if site.google_analytics.pv.enabled %} + + {% include_relative _pv-config.js %} + + {% include_relative _utils/pageviews.js %} + + {% include_relative lib/_countUp.min.js %} + +{% endif %} diff --git a/assets/js/_pv-config.js b/assets/js/_pv-config.js new file mode 100644 index 000000000000..29acbbe46289 --- /dev/null +++ b/assets/js/_pv-config.js @@ -0,0 +1,14 @@ +/*! + PV configuration and Javascript conversion. +*/ + +const proxyEndpoint = "{{ site.google_analytics.pv.proxy_endpoint }}"; + + +{% if site.google_analytics.pv.cache and site.google_analytics.pv.enabled %} + {% assign enabled = true %} +{% else %} + {% assign enabled = false %} +{% endif %} + +const pvCacheEnabled = {{ enabled }}; diff --git a/assets/js/_utils/category-collapse.js b/assets/js/_utils/category-collapse.js new file mode 100644 index 000000000000..71080b629e4e --- /dev/null +++ b/assets/js/_utils/category-collapse.js @@ -0,0 +1,33 @@ +/* + * Tab 'Categories' expand/close effect. + * v2.0 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2018-2019 Cotes Chung + * MIT License + */ + +$(function() { + var childPrefix = "l_"; + var parentPrefix = "h_"; + + /* close up top-category */ + $(".collapse").on("hide.bs.collapse", function() { /* Bootstrap collapse events. */ + var parentId = parentPrefix + $(this).attr("id").substring(childPrefix.length); + if (parentId) { + $("#" + parentId + " .far.fa-folder-open").attr("class", "far fa-folder fa-fw"); + $("#" + parentId + " i.fas").addClass("rotate"); + $("#" + parentId).removeClass("hide-border-bottom"); + } + }); + + /* expand the top category */ + $(".collapse").on("show.bs.collapse", function() { + var parentId = parentPrefix + $(this).attr("id").substring(childPrefix.length); + if (parentId) { + $("#" + parentId + " .far.fa-folder").attr("class", "far fa-folder-open fa-fw"); + $("#" + parentId + " i.fas").removeClass("rotate"); + $("#" + parentId).addClass("hide-border-bottom"); + } + }); + +}); \ No newline at end of file diff --git a/assets/js/_utils/img-hyperlink.js b/assets/js/_utils/img-hyperlink.js new file mode 100644 index 000000000000..c910af0fa0d5 --- /dev/null +++ b/assets/js/_utils/img-hyperlink.js @@ -0,0 +1,16 @@ +/* + * Find out the <a> tag contains an image and mark it. + * + * v2.5.1 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2020 Cotes Chung + * MIT Licensed + */ + +$(function() { + + var MARK="img-hyperlink"; + + $("a:has(img)").addClass(MARK); + +}); diff --git a/assets/js/_utils/pageviews.js b/assets/js/_utils/pageviews.js new file mode 100644 index 000000000000..17de533567b4 --- /dev/null +++ b/assets/js/_utils/pageviews.js @@ -0,0 +1,225 @@ +/** + * Count pageviews form GA or local cache file. + * + * Dependences: + * - jQuery + * - countUp.js <https://github.com/inorganik/countUp.js> + * + * v2.0 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2018-2019 Cotes Chung + * MIT License + */ + +var getInitStatus = (function () { + var hasInit = false; + return () => { + let ret = hasInit; + if (!hasInit) { + hasInit = true; + } + return ret; + }; +}()); + + +var PvCache = (function () { + const KEY_PV = "pv"; + const KEY_CREATION = "pv_created_date"; + const KEY_PV_SRC = "pv_source"; + + var Source = { + ORIGIN: "origin", + PROXY: "proxy" + }; + + function get(key) { + return localStorage.getItem(key); + } + + function set(key, val) { + localStorage.setItem(key, val); + } + + return { + getData() { + return JSON.parse(localStorage.getItem(KEY_PV) ); + }, + saveOriginCache(pv) { + set(KEY_PV, pv); + set(KEY_PV_SRC, Source.ORIGIN ); + set(KEY_CREATION, new Date().toJSON() ); + }, + saveProxyCache(pv) { + set(KEY_PV, pv); + set(KEY_PV_SRC, Source.PROXY ); + set(KEY_CREATION, new Date().toJSON() ); + }, + isFromOrigin() { + return get(KEY_PV_SRC) === Source.ORIGIN; + }, + isFromProxy() { + return get(KEY_PV_SRC) === Source.PROXY; + }, + isExpired() { + if (PvCache.isFromOrigin() ) { + let date = new Date(get(KEY_CREATION)); + date.setDate(date.getDate() + 1); /* update origin records every day */ + return Date.now() >= date.getTime(); + + } else if (PvCache.isFromProxy() ) { + let date = new Date(get(KEY_CREATION) ); + date.setHours(date.getHours() + 1); /* update proxy records per hour */ + return Date.now() >= date.getTime(); + } + return false; + }, + getAllPagevies() { + return PvCache.getData().totalsForAllResults["ga:pageviews"]; + }, + newerThan(pv) { + return PvCache.getAllPagevies() > pv.totalsForAllResults["ga:pageviews"]; + }, + inspectKeys() { + if (localStorage.getItem(KEY_PV) === null + || localStorage.getItem(KEY_PV_SRC) === null + || localStorage.getItem(KEY_CREATION) === null) { + localStorage.clear(); + } + } + }; + +}()); /* PvCache */ + +function countUp(min, max, destId) { + if (min < max) { + var numAnim = new CountUp(destId, min, max); + if (!numAnim.error) { + numAnim.start(); + } else { + console.error(numAnim.error); + } + } +} + + +function countPV(path, rows) { + var count = 0; + + if (typeof rows !== "undefined" ) { + for (var i = 0; i < rows.length; ++i) { + var gaPath = rows[parseInt(i, 10)][0]; + if (gaPath === path) { /* path format see: site.permalink */ + count += parseInt(rows[parseInt(i, 10)][1], 10); + break; + } + } + } + + return count; +} + + +function tacklePV(rows, path, elem, hasInit) { + var count = countPV(path, rows); + count = (count === 0 ? 1 : count); + + if (!hasInit) { + elem.text(new Intl.NumberFormat().format(count)); + } else { + var initCount = parseInt(elem.text().replace(/,/g, ""), 10); + if (count > initCount) { + countUp(initCount, count, elem.attr("id")); + } + } +} + + +function displayPageviews(data) { + if (typeof data === "undefined") { + return; + } + + var hasInit = getInitStatus(); + var rows = data.rows; /* could be undefined */ + + if ($("#post-list").length > 0) { /* the Home page */ + $(".post-preview").each(function() { + var path = $(this).children("div").children("h1").children("a").attr("href"); + tacklePV(rows, path, $(this).find(".pageviews"), hasInit); + }); + + } else if ($(".post").length > 0) { /* the post */ + var path = window.location.pathname; + tacklePV(rows, path, $("#pv"), hasInit); + } +} + + +function fetchProxyPageviews() { + $.ajax({ + type: "GET", + url: proxyEndpoint, /* see: /assets/js/_pv-config.js */ + dataType: "jsonp", + jsonpCallback: "displayPageviews", + success: (data, textStatus, jqXHR) => { + PvCache.saveProxyCache(JSON.stringify(data)); + }, + error: (jqXHR, textStatus, errorThrown) => { + console.log("Failed to load pageviews from proxy server: " + errorThrown); + } + }); +} + + +function fetchPageviews(fetchOrigin = true, filterOrigin = false) { + /* pvCacheEnabled › see: /assets/js/_pv-config.js */ + if (pvCacheEnabled && fetchOrigin) { + fetch("/assets/js/data/pageviews.json") + .then((response) => response.json()) + .then((data) => { + if (filterOrigin) { + if (PvCache.newerThan(data)) { + return; + } + } + displayPageviews(data); + PvCache.saveOriginCache(JSON.stringify(data)); + }) + .then(() => fetchProxyPageviews()); + + } else { + fetchProxyPageviews(); + } + +} + + +$(function() { + + if ($(".pageviews").length > 0) { + + PvCache.inspectKeys(); + let cache = PvCache.getData(); + + if (cache) { + displayPageviews(cache); + + if (PvCache.isExpired()) { + fetchPageviews(true, PvCache.isFromProxy()); + + } else { + + if (PvCache.isFromOrigin()) { + fetchPageviews(false); + } + + } + + } else { + fetchPageviews(); + } + + } + +}); diff --git a/assets/js/_utils/timeago.js b/assets/js/_utils/timeago.js new file mode 100644 index 000000000000..f98c706c557c --- /dev/null +++ b/assets/js/_utils/timeago.js @@ -0,0 +1,83 @@ +/* + * Caculate the Timeago + * v2.0 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2019 Cotes Chung + * MIT Licensed + */ + +$(function() { + + var toRefresh = $(".timeago").length; + + var intervalId = void 0; + + function timeago(iso, isLastmod) { + let now = new Date(); + let past = new Date(iso); + + if (past.getFullYear() !== now.getFullYear()) { + toRefresh -= 1; + return past.toLocaleString("en-US", { + year: "numeric", + month: "short", + day: "numeric" + }); + } + + if (past.getMonth() !== now.getMonth()) { + toRefresh -= 1; + return past.toLocaleString("en-US", { + month: "short", + day: "numeric" + }); + } + + let seconds = Math.floor((now - past) / 1000); + + let day = Math.floor(seconds / 86400); + if (day >= 1) { + toRefresh -= 1; + return day + " day" + (day > 1 ? "s" : "") + " ago"; + } + + let hour = Math.floor(seconds / 3600); + if (hour >= 1) { + return hour + " hour" + (hour > 1 ? "s" : "") + " ago"; + } + + let minute = Math.floor(seconds / 60); + if (minute >= 1) { + return minute + " minute" + (minute > 1 ? "s" : "") + " ago"; + } + + return (isLastmod ? "just" : "Just") + " now"; + } + + function updateTimeago() { + $(".timeago").each(function() { + if ($(this).children("i").length > 0) { + var basic = $(this).text(); + var isLastmod = $(this).hasClass("lastmod"); + var node = $(this).children("i"); + var date = node.text(); /* ISO Date: "YYYY-MM-DDTHH:MM:SSZ" */ + $(this).text(timeago(date, isLastmod)); + $(this).append(node); + } + }); + + if (toRefresh === 0 && typeof intervalId !== "undefined") { + clearInterval(intervalId); /* stop interval */ + } + return toRefresh; + } + + if (toRefresh === 0) { + return; + } + + if (updateTimeago() > 0) { /* run immediately */ + intervalId = setInterval(updateTimeago, 60000); /* run every minute */ + } + +}); diff --git a/assets/js/_utils/toc-filter.js b/assets/js/_utils/toc-filter.js new file mode 100644 index 000000000000..1c4f8f984714 --- /dev/null +++ b/assets/js/_utils/toc-filter.js @@ -0,0 +1,14 @@ +/* + * Hide the empty ToC in posts. + * v2.0 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2019 Cotes Chung + * MIT Licensed + */ + +$(function() { + if ($("#post-wrapper .post-content h1").length === 0 + && $("#post-wrapper .post-content h2").length === 0) { + $("#toc-wrapper").addClass("unloaded"); + } +}); \ No newline at end of file diff --git a/assets/js/_utils/tooltip-loader.js b/assets/js/_utils/tooltip-loader.js new file mode 100644 index 000000000000..de6ed9bd9599 --- /dev/null +++ b/assets/js/_utils/tooltip-loader.js @@ -0,0 +1,10 @@ +/** + * Initial Bootstrap Tooltip. + * v2.0 + * https://github.com/cotes2020/jekyll-theme-chirpy + * © 2019 Cotes Chung + * MIT License +*/ +$(function () { + $("[data-toggle=\"tooltip\"]").tooltip(); +}); diff --git a/assets/js/categories.min.js b/assets/js/categories.min.js new file mode 100644 index 000000000000..c8230eb0d91a --- /dev/null +++ b/assets/js/categories.min.js @@ -0,0 +1,13 @@ +--- +layout: compress + +# JS for layout tab Categories. +# Chirpy v2.3 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT License +--- + +{% include_relative _commons.js %} + +{% include_relative _utils/category-collapse.js %} diff --git a/assets/js/data/cache-list.js b/assets/js/data/cache-list.js new file mode 100644 index 000000000000..df6f7d21b316 --- /dev/null +++ b/assets/js/data/cache-list.js @@ -0,0 +1,111 @@ +--- +layout: compress + +# The list to be cached by PWA +# Chirpy v2.2 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed +--- + +const include = [ + + /*--- CSS ---*/ + + '{{ "/assets/css/home.css" | relative_url }}', + '{{ "/assets/css/categories.css" | relative_url }}', + '{{ "/assets/css/tags.css" | relative_url }}', + '{{ "/assets/css/archives.css" | relative_url }}', + '{{ "/assets/css/page.css" | relative_url }}', + '{{ "/assets/css/post.css" | relative_url }}', + '{{ "/assets/css/category-tag.css" | relative_url }}', + '{{ "/assets/css/lib/bootstrap-toc.min.css" | relative_url }}', + + /*--- Javascripts ---*/ + + '{{ "/assets/js/home.min.js" | relative_url }}', + '{{ "/assets/js/page.min.js" | relative_url }}', + '{{ "/assets/js/post.min.js" | relative_url }}', + + /*--- HTML ---*/ + + /* Tabs */ + {% for tab in site.data.tabs %} + {% capture item %} + {%- unless tab.name == 'Home' -%} + /tabs/{{ tab.name | downcase }} + {%- endunless -%} + {{- "/" -}} + {% endcapture %} + '{{ item | relative_url }}', + {% endfor %} + + /* The posts of first Home page and recent update list */ + {% assign post_list = "" | split: "" %} + + {% for post in site.posts limit: site.paginate %} + {% capture post_url %}{{ post.url | relative_url }}{% endcapture %} + {% assign post_list = post_list | push: post_url %} + {% endfor %} + + {% include update-list.html %} + + {% for item in update_list %} + {% assign url = item | split: "::" | last | url_encode | prepend: "/posts/" | append: "/" | relative_url %} + {% assign post_list = post_list | push: url %} + {% endfor %} + + {% assign post_list = post_list | uniq %} + + {% for url in post_list %} + '{{ url }}', + {% endfor %} + + /* Trending tags */ + {% include trending-tags.html %} + {% for tag in trending_tags %} + {% capture tag_url %}/tags/{{ tag | downcase | url_encode }}/{% endcapture %} + '{{ tag_url | relative_url }}', + {% endfor %} + + /*--- Icons ---*/ + + {%- capture icon_url -%} + {{ "/assets/img/favicons" | relative_url }} + {%- endcapture -%} + '{{ icon_url }}/favicon.ico', + '{{ icon_url }}/apple-icon.png', + '{{ icon_url }}/apple-icon-precomposed.png', + '{{ icon_url }}/apple-icon-57x57.png', + '{{ icon_url }}/apple-icon-60x60.png', + '{{ icon_url }}/apple-icon-72x72.png', + '{{ icon_url }}/apple-icon-76x76.png', + '{{ icon_url }}/apple-icon-114x114.png', + '{{ icon_url }}/apple-icon-120x120.png', + '{{ icon_url }}/apple-icon-144x144.png', + '{{ icon_url }}/apple-icon-152x152.png', + '{{ icon_url }}/apple-icon-180x180.png', + '{{ icon_url }}/android-icon-192x192.png', + '{{ icon_url }}/favicon-32x32.png', + '{{ icon_url }}/favicon-96x96.png', + '{{ icon_url }}/favicon-16x16.png', + '{{ icon_url }}/ms-icon-144x144.png', + '{{ icon_url }}/manifest.json', + '{{ icon_url }}/browserconfig.xml', + + /*--- Others ---*/ + + '{{ "/assets/js/data/search.json" | relative_url }}', + '{{ "/404.html" | relative_url }}', + + '{{ "/app.js" | relative_url }}', + '{{ "/sw.js" | relative_url }}' +]; + +const exclude = [ + {%- if site.google_analytics.pv.proxy_url and site.google_analytics.pv.enabled -%} + '{{ site.google_analytics.pv.proxy_url }}', + {%- endif -%} + '/assets/js/data/pageviews.json', + '/img.shields.io/' +]; diff --git a/assets/js/data/search.json b/assets/js/data/search.json new file mode 100644 index 000000000000..87badbac3a64 --- /dev/null +++ b/assets/js/data/search.json @@ -0,0 +1,17 @@ +--- +layout: compress +--- + +[ + {% for post in site.posts %} + { + "title": "{{ post.title | escape }}", + "url": "{{ site.baseurl }}{{ post.url }}", + "categories": "{{ post.categories | join: ', '}}", + "tags": "{{ post.tags | join: ', ' }}", + "date": "{{ post.date }}", + {% include no-linenos.html content=post.content %} + "snippet": "{{ content | strip_html | strip_newlines | remove_chars | escape | truncate: 300 | replace: '\', '\\\\' }}" + }{% unless forloop.last %},{% endunless %} + {% endfor %} +] diff --git a/assets/js/home.min.js b/assets/js/home.min.js new file mode 100644 index 000000000000..c8b59e5bf672 --- /dev/null +++ b/assets/js/home.min.js @@ -0,0 +1,11 @@ +--- +layout: compress + +# JS for layout home. +# Chirpy v2.3 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT License +--- + +{% include_relative _home-post.js %} diff --git a/assets/js/lib/_bootstrap-toc.min.js b/assets/js/lib/_bootstrap-toc.min.js new file mode 100644 index 000000000000..c628326a8462 --- /dev/null +++ b/assets/js/lib/_bootstrap-toc.min.js @@ -0,0 +1,5 @@ +/*! + * Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ +!function(a){"use strict";window.Toc={helpers:{findOrFilter:function(e,t){var n=e.find(t);return e.filter(t).add(n).filter(":not([data-toc-skip])")},generateUniqueIdBase:function(e){return a(e).text().trim().replace(/\'/gi,"").replace(/[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\\n\t\b\v]/g,"-").replace(/-{2,}/g,"-").substring(0,64).replace(/^-+|-+$/gm,"").toLowerCase()||e.tagName.toLowerCase()},generateUniqueId:function(e){for(var t=this.generateUniqueIdBase(e),n=0;;n++){var r=t;if(0<n&&(r+="-"+n),!document.getElementById(r))return r}},generateAnchor:function(e){if(e.id)return e.id;var t=this.generateUniqueId(e);return e.id=t},createNavList:function(){return a('<ul class="nav navbar-nav"></ul>')},createChildNavList:function(e){var t=this.createNavList();return e.append(t),t},generateNavEl:function(e,t){var n=a('<a class="nav-link"></a>');n.attr("href","#"+e),n.text(t);var r=a("<li></li>");return r.append(n),r},generateNavItem:function(e){var t=this.generateAnchor(e),n=a(e),r=n.data("toc-text")||n.text();return this.generateNavEl(t,r)},getTopLevel:function(e){for(var t=1;t<=6;t++){if(1<this.findOrFilter(e,"h"+t).length)return t}return 1},getHeadings:function(e,t){var n="h"+t,r="h"+(t+1);return this.findOrFilter(e,n+","+r)},getNavLevel:function(e){return parseInt(e.tagName.charAt(1),10)},populateNav:function(r,a,e){var i,s=r,c=this;e.each(function(e,t){var n=c.generateNavItem(t);c.getNavLevel(t)===a?s=r:i&&s===r&&(s=c.createChildNavList(i)),s.append(n),i=n})},parseOps:function(e){var t;return(t=e.jquery?{$nav:e}:e).$scope=t.$scope||a(document.body),t}},init:function(e){(e=this.helpers.parseOps(e)).$nav.attr("data-toggle","toc");var t=this.helpers.createChildNavList(e.$nav),n=this.helpers.getTopLevel(e.$scope),r=this.helpers.getHeadings(e.$scope,n);this.helpers.populateNav(t,n,r)}},a(function(){a('nav[data-toggle="toc"]').each(function(e,t){var n=a(t);Toc.init(n)})})}(jQuery); \ No newline at end of file diff --git a/assets/js/lib/_countUp.min.js b/assets/js/lib/_countUp.min.js new file mode 100644 index 000000000000..cd2da4fd264b --- /dev/null +++ b/assets/js/lib/_countUp.min.js @@ -0,0 +1,2 @@ +/*! https://github.com/inorganik/countUp.js */ +var CountUp=function(h,b,i,e,g,n){var m=this;m.version=function(){return"1.9.3"};m.options={useEasing:true,useGrouping:true,separator:",",decimal:".",easingFn:c,formattingFn:d,prefix:"",suffix:"",numerals:[]};if(n&&typeof n==="object"){for(var k in m.options){if(n.hasOwnProperty(k)&&n[k]!==null){m.options[k]=n[k]}}}if(m.options.separator===""){m.options.useGrouping=false}else{m.options.separator=""+m.options.separator}var a=0;var l=["webkit","moz","ms","o"];for(var j=0;j<l.length&&!window.requestAnimationFrame;++j){window.requestAnimationFrame=window[l[j]+"RequestAnimationFrame"];window.cancelAnimationFrame=window[l[j]+"CancelAnimationFrame"]||window[l[j]+"CancelRequestAnimationFrame"]}if(!window.requestAnimationFrame){window.requestAnimationFrame=function(s,p){var o=new Date().getTime();var q=Math.max(0,16-(o-a));var r=window.setTimeout(function(){s(o+q)},q);a=o+q;return r}}if(!window.cancelAnimationFrame){window.cancelAnimationFrame=function(o){clearTimeout(o)}}function d(t){var v=(t<0),p,s,r,q,u,o;t=Math.abs(t).toFixed(m.decimals);t+="";p=t.split(".");s=p[0];r=p.length>1?m.options.decimal+p[1]:"";if(m.options.useGrouping){q="";for(u=0,o=s.length;u<o;++u){if(u!==0&&((u%3)===0)){q=m.options.separator+q}q=s[o-u-1]+q}s=q}if(m.options.numerals.length){s=s.replace(/[0-9]/g,function(x){return m.options.numerals[+x]});r=r.replace(/[0-9]/g,function(x){return m.options.numerals[+x]})}return(v?"-":"")+m.options.prefix+s+r+m.options.suffix}function c(p,o,r,q){return r*(-Math.pow(2,-10*p/q)+1)*1024/1023+o}function f(o){return(typeof o==="number"&&!isNaN(o))}m.initialize=function(){if(m.initialized){return true}m.error="";m.d=(typeof h==="string")?document.getElementById(h):h;if(!m.d){m.error="[CountUp] target is null or undefined";return false}m.startVal=Number(b);m.endVal=Number(i);if(f(m.startVal)&&f(m.endVal)){m.decimals=Math.max(0,e||0);m.dec=Math.pow(10,m.decimals);m.duration=Number(g)*1000||2000;m.countDown=(m.startVal>m.endVal);m.frameVal=m.startVal;m.initialized=true;return true}else{m.error="[CountUp] startVal ("+b+") or endVal ("+i+") is not a number";return false}};m.printValue=function(p){var o=m.options.formattingFn(p);if(m.d.tagName==="INPUT"){this.d.value=o}else{if(m.d.tagName==="text"||m.d.tagName==="tspan"){this.d.textContent=o}else{this.d.innerHTML=o}}};m.count=function(p){if(!m.startTime){m.startTime=p}m.timestamp=p;var o=p-m.startTime;m.remaining=m.duration-o;if(m.options.useEasing){if(m.countDown){m.frameVal=m.startVal-m.options.easingFn(o,0,m.startVal-m.endVal,m.duration)}else{m.frameVal=m.options.easingFn(o,m.startVal,m.endVal-m.startVal,m.duration)}}else{if(m.countDown){m.frameVal=m.startVal-((m.startVal-m.endVal)*(o/m.duration))}else{m.frameVal=m.startVal+(m.endVal-m.startVal)*(o/m.duration)}}if(m.countDown){m.frameVal=(m.frameVal<m.endVal)?m.endVal:m.frameVal}else{m.frameVal=(m.frameVal>m.endVal)?m.endVal:m.frameVal}m.frameVal=Math.round(m.frameVal*m.dec)/m.dec;m.printValue(m.frameVal);if(o<m.duration){m.rAF=requestAnimationFrame(m.count)}else{if(m.callback){m.callback()}}};m.start=function(o){if(!m.initialize()){return}m.callback=o;m.rAF=requestAnimationFrame(m.count)};m.pauseResume=function(){if(!m.paused){m.paused=true;cancelAnimationFrame(m.rAF)}else{m.paused=false;delete m.startTime;m.duration=m.remaining;m.startVal=m.frameVal;requestAnimationFrame(m.count)}};m.reset=function(){m.paused=false;delete m.startTime;m.initialized=false;if(m.initialize()){cancelAnimationFrame(m.rAF);m.printValue(m.startVal)}};m.update=function(o){if(!m.initialize()){return}o=Number(o);if(!f(o)){m.error="[CountUp] update() - new endVal is not a number: "+o;return}m.error="";if(o===m.frameVal){return}cancelAnimationFrame(m.rAF);m.paused=false;delete m.startTime;m.startVal=m.frameVal;m.endVal=o;m.countDown=(m.startVal>m.endVal);m.rAF=requestAnimationFrame(m.count)};if(m.initialize()){m.printValue(m.startVal)}}; \ No newline at end of file diff --git a/assets/js/lib/jquery.disqusloader.min.js b/assets/js/lib/jquery.disqusloader.min.js new file mode 100644 index 000000000000..b2cb0bec640d --- /dev/null +++ b/assets/js/lib/jquery.disqusloader.min.js @@ -0,0 +1,8 @@ +/*! + disqusLoader.js v1.0 + A JavaScript plugin for lazy-loading Disqus comments widget. + - + By Osvaldas Valutis, www.osvaldas.info + Available for use under the MIT License +*/ +(function(e,g,h,d){var a=e(g),k=function(o,n){var q,p;return function(){var t=this,s=arguments,r=+new Date;q&&r<q+o?(clearTimeout(p),p=setTimeout(function(){q=r,n.apply(t,s)},o)):(q=r,n.apply(t,s))}},m=false,j=false,i=false,c=false,f="unloaded",b=e(),l=function(){if(!b.length||b.data("disqusLoaderStatus")=="loaded"){return true}var n=a.scrollTop();if(b.offset().top-n>a.height()*j||n-b.offset().top-b.outerHeight()-(a.height()*j)>0){return true}e("#disqus_thread").removeAttr("id");b.attr("id","disqus_thread").data("disqusLoaderStatus","loaded");if(f=="loaded"){DISQUS.reset({reload:true,config:i})}else{g.disqus_config=i;if(f=="unloaded"){f="loading";e.ajax({url:c,async:true,cache:true,dataType:"script",success:function(){f="loaded"}})}}};a.on("scroll resize",k(m,l));e.disqusLoader=function(o,n){n=e.extend({},{laziness:1,throttle:250,scriptUrl:false,disqusConfig:false},n);j=n.laziness+1;m=n.throttle;i=n.disqusConfig;c=c===false?n.scriptUrl:c;b=(typeof o=="string"?e(o):o).eq(0);b.data("disqusLoaderStatus","unloaded");l()}})(jQuery,window,document); \ No newline at end of file diff --git a/assets/js/page.min.js b/assets/js/page.min.js new file mode 100644 index 000000000000..9dfa152962fb --- /dev/null +++ b/assets/js/page.min.js @@ -0,0 +1,11 @@ +--- +layout: compress + +# JS for layout page by default. +# Chirpy v2.3 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT License +--- + +{% include_relative _commons.js %} diff --git a/assets/js/post.min.js b/assets/js/post.min.js new file mode 100644 index 000000000000..c85f45259039 --- /dev/null +++ b/assets/js/post.min.js @@ -0,0 +1,17 @@ +--- +layout: compress + +# JS for layout post. +# Chirpy v2.3 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT License +--- + +{% include_relative _home-post.js %} + +{% include_relative lib/_bootstrap-toc.min.js %} + +{% include_relative _utils/toc-filter.js %} + +{% include_relative _utils/img-hyperlink.js %} diff --git a/categories/foudations.html b/categories/foudations.html new file mode 100644 index 000000000000..b90e1d0cd5fe --- /dev/null +++ b/categories/foudations.html @@ -0,0 +1,5 @@ +--- +layout: category +title: FOUDATIONS +category: FOUDATIONS +--- diff --git a/categories/introduction.html b/categories/introduction.html new file mode 100644 index 000000000000..40e704a669d5 --- /dev/null +++ b/categories/introduction.html @@ -0,0 +1,5 @@ +--- +layout: category +title: INTRODUCTION +category: INTRODUCTION +--- diff --git a/feed.xml b/feed.xml new file mode 100644 index 000000000000..30e01fc11b53 --- /dev/null +++ b/feed.xml @@ -0,0 +1,63 @@ +--- +layout: compress +# Atom Feed, reference: https://validator.w3.org/feed/docs/atom.html +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT License +--- + +{% capture source %} +<feed xmlns="http://www.w3.org/2005/Atom"> + <id>{{ site.url }}</id> + <title>{{ site.title }} + {{ site.description }} + {{ site.time | date_to_xmlschema }} + + {{ site.author }} + {{ site.url }} + + + + Jekyll + © {{ 'now' | date: '%Y' }} {{ site.author }} + {{ site.baseurl }}/assets/img/favicons/favicon.ico + {{ site.baseurl }}/assets/img/favicons/favicon-96x96.png + +{% for post in site.posts limit: 5 %} + {% assign post_absolute_url = site.url | append: post.url %} + + {{ post.title }} + + {{ post.date | date_to_xmlschema }} + {% if post.seo.date_modified %} + {{ post.seo.date_modified | date_to_xmlschema }} + {% else %} + {{ site.time | date_to_xmlschema }} + {% endif %} + {{ post_absolute_url }} + + + {{ site.author }} + + + {% if post.categories %} + {% for category in post.categories %} + + {% endfor %} + {% endif %} + + {% if post.summary %} + {{ post.summary | strip }} + {% else %} + + {% assign content = post.content %} + {% include no-linenos.html %} + {{ content | strip_html | truncate: 200 }} + {% endif %} + + +{% endfor %} + +{% endcapture %} +{{ source | replace: '&', '&' }} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 000000000000..e105ba92de3f --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ +--- +layout: home +breadcrumb: + - + label: Posts + +# Index page +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +--- \ No newline at end of file diff --git a/robots.txt b/robots.txt new file mode 100644 index 000000000000..ad4a840fdd7d --- /dev/null +++ b/robots.txt @@ -0,0 +1,15 @@ +--- +# The robots rules +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +layout: null +permalink: robots.txt +--- + +User-agent: * + +Disallow: /norobots/ + +Sitemap: {{ site.url | append: site.baseurl }}/sitemap.xml \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 000000000000..7b0bb70c6a21 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,91 @@ +--- +layout: compress + +# The Sitemap template +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +--- + + + + +{% for post in site.posts %} + + {{ site.url | append: site.baseurl | append: post.url }} + {{ site.time | date_to_xmlschema }} + + {% if post.sitemap.changefreq %} + {{ post.sitemap.changefreq }} + {% else %} + monthly + {% endif %} + + {% if post.sitemap.priority %} + {{ post.sitemap.priority }} + {% else %} + 0.5 + {% endif %} + +{% endfor %} + +{% for page in site.pages %} + + {% assign pass = false %} + + {% for fuzzy in site.sitemap_exclude.fuzzy %} + {% if page.url contains fuzzy %} + {% assign pass = true %} + {% break %} + {% endif %} + {% endfor %} + + {% unless pass %} + {% for accurate in site.sitemap_exclude.accurate %} + {% assign len = accurate | size %} + {% capture beg %}{{ 0 | minus: len }}{% endcapture %} + {% capture tail %}{{ page.url | slice: beg, len }}{% endcapture %} + + {% if tail == accurate %} + {% assign pass = true %} + {% break %} + {% endif %} + + {% endfor %} + {% endunless %} + + {% if pass %} + {% continue %} + {% endif %} + + {% capture lastmod %} + {% if page.lastmod %} + {{ page.lastmod }} + {% elsif page.date %} + {{ page.date }} + {% else %} + {{ site.time }} + {% endif %} + {% endcapture %} + + + {{ site.url | append: site.baseurl | append: page.url | remove: "index.html" }} + {{ lastmod | date_to_xmlschema }} + + {% if page.sitemap.changefreq %} + {{ page.sitemap.changefreq }} + {% else %} + monthly + {% endif %} + + {% if page.sitemap.priority %} + {{ page.sitemap.priority }} + {% else %} + 0.3 + {% endif %} + + +{% endfor %} + + \ No newline at end of file diff --git a/sw.js b/sw.js new file mode 100644 index 000000000000..91329e3e1a68 --- /dev/null +++ b/sw.js @@ -0,0 +1,63 @@ +--- +layout: compress + +# Chirpy v2.2 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed +--- + +self.importScripts('{{ "/assets/js/data/cache-list.js" | relative_url }}'); + +var cacheName = 'chirpy-{{ "now" | date: "%Y%m%d.%H%M" }}'; + + +function isExcluded(url) { + for (const rule of exclude) { + if (url.indexOf(rule) != -1) { + return true; + } + } + return false; +} + + +self.addEventListener('install', (e) => { + self.skipWaiting(); + e.waitUntil( + caches.open(cacheName).then((cache) => { + return cache.addAll(include); + }) + ); +}); + + +self.addEventListener('fetch', (e) => { + e.respondWith( + caches.match(e.request).then((r) => { + /* console.log('[Service Worker] Fetching resource: ' + e.request.url); */ + return r || fetch(e.request).then((response) => { + return caches.open(cacheName).then((cache) => { + if (!isExcluded(e.request.url)) { + /* console.log('[Service Worker] Caching new resource: ' + e.request.url); */ + cache.put(e.request, response.clone()); + } + return response; + }); + }); + }) + ); +}); + + +self.addEventListener('activate', (e) => { + e.waitUntil( + caches.keys().then((keyList) => { + return Promise.all(keyList.map((key) => { + if(key !== cacheName) { + return caches.delete(key); + } + })); + }) + ); +}); diff --git a/tabs/about.md b/tabs/about.md new file mode 100644 index 000000000000..cc68a893ffa4 --- /dev/null +++ b/tabs/about.md @@ -0,0 +1,15 @@ +--- +title: About + +# The About page +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +--- + +## About this site +This site was created to publish content about python and practical examples applied to real-life analytics problems. This is especially thought for people transitioning from other analytics tools like Stata, SAS, R or Excel, among others. I will be posting practical examples on how to solve issues as well as common and avanced knowledge in Python usage. We have identified that a transtion process is taking place in governmental organization like the one I work in, and we want to contribute in that transition. However, these resources are open to the public in general for obtaining practical knowledge in how to deal with real-life analytics problems. + +## About me +I have a master's degree in Information Technology with a specialization in Data Analytics and Business Intelligence. I coursed my studies in the US and Australia at Carnegie Mellon University (CMU). Currently, I am a Data Scientist at the Department of the Premier and Cabinet of South Australia. I am also a teaching assistant for courses in the US and Australia at CMU like Data Focused Python, Programming R, Unstructured Data Analytics, Internet of Things, among others. Additionally, I am giving back to the community as a volunteer for the State Emergency Service of South Australia. I am always happy to discuss any topic in general, but especially about Data Science and its usage in making our society better. You can reach out to my personal email egrodriguezal@gmail.com, and my LinkedIn profile is on this website. \ No newline at end of file diff --git a/tabs/archives.md b/tabs/archives.md new file mode 100644 index 000000000000..e4d434858133 --- /dev/null +++ b/tabs/archives.md @@ -0,0 +1,40 @@ +--- +title: Archives +type: archives +# The Archives of posts. +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +--- + +
+{% for post in site.posts %} + {% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %} + {% capture pre_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %} + {% if forloop.first %} + {% assign last_day = "" %} + {% assign last_month = "" %} + {{this_year}} +
    + {% endif %} +
  • +
    + {% capture this_day %}{{ post.date | date: "%d" }}{% endcapture %} + {% capture this_month %}{{ post.date | date: "%b" }}{% endcapture %} + {{ this_day }} + {{ this_month }} + {{ post.title }} +
    +
  • + {% if forloop.last %} +
+ {% elsif this_year != pre_year %} + + {{pre_year}} +
    + {% assign last_day = "" %} + {% assign last_month = "" %} + {% endif %} +{% endfor %} +
\ No newline at end of file diff --git a/tabs/categories.md b/tabs/categories.md new file mode 100644 index 000000000000..4287e342664c --- /dev/null +++ b/tabs/categories.md @@ -0,0 +1,104 @@ +--- +title: Categories +type: categories +# All the Categories of posts +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +--- + +{% assign HEAD_PREFIX = "h_" %} +{% assign LIST_PREFIX = "l_" %} + +{% assign group_index = 0 %} + +{% assign sort_categories = site.categories | sort %} + +{% for category in sort_categories %} + {% assign category_name = category | first %} + {% assign posts_of_category = category | last %} + {% assign first_post = posts_of_category | first %} + + {% if category_name == first_post.categories[0] %} + {% assign sub_categories = "" | split: "" %} + + {% for post in posts_of_category %} + {% assign second_category = post.categories[1] %} + {% if second_category %} + {% unless sub_categories contains second_category %} + {% assign sub_categories = sub_categories | push: second_category %} + {% endunless %} + {% endif %} + {% endfor %} + + {% assign sub_categories = sub_categories | sort %} + {% assign sub_categories_size = sub_categories | size %} + +
+ +
+ + {% if sub_categories_size > 0 %} + + {% else %} + + {% endif %} + + {{ category_name }} + + + + {% assign top_posts_size = site.categories[category_name] | size %} + + {% if sub_categories_size > 0 %} + {{ sub_categories_size }} + {% if sub_categories_size > 1 %}categories{% else %}category{% endif %}, + {% endif %} + {{ top_posts_size }} + post{% if top_posts_size > 1 %}s{% endif %} + + + + + {% if sub_categories_size > 0%} + + + + {% else %} + + + + {% endif %} + +
+ + + {% if sub_categories_size > 0 %} +
+
    + {% for sub_category in sub_categories %} +
  • + + {{ sub_category }} + {% assign posts_size = site.categories[sub_category] | size %} + {{ posts_size }} + post{% if posts_size > 1 %}s{% endif %} + +
  • + {% endfor %} +
+
+ {% endif %} + +
+ + {% assign group_index = group_index | plus: 1 %} + + {% endif %} +{% endfor %} diff --git a/tabs/tags.md b/tabs/tags.md new file mode 100644 index 000000000000..6a2152a7c061 --- /dev/null +++ b/tabs/tags.md @@ -0,0 +1,29 @@ +--- +title: Tags +type: tags +# All the Tags of posts. +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2017-2019 Cotes Chung +# MIT License +--- + +{% comment %} + 'site.tags' looks like a Map, e.g. site.tags.MyTag.[ Post0, Post1, ... ] + Print the {{ site.tags }} will help you to understand it. +{% endcomment %} +
+{% assign tags = "" | split: "" %} +{% for t in site.tags %} + {% assign tags = tags | push: t[0] %} +{% endfor %} + +{% assign sorted_tags = tags | sort_natural %} + +{% for t in sorted_tags %} + +{% endfor %} + +
diff --git a/tags/python.html b/tags/python.html new file mode 100644 index 000000000000..c068813da415 --- /dev/null +++ b/tags/python.html @@ -0,0 +1,5 @@ +--- +layout: tag +title: python +tag: python +--- diff --git a/tools/build.sh b/tools/build.sh new file mode 100755 index 000000000000..013cf15307dd --- /dev/null +++ b/tools/build.sh @@ -0,0 +1,147 @@ +#!/bin/bash +# +# Build jekyll site and store site files in ./_site +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# Published under MIT License + +set -eu + +WORK_DIR="$(dirname "$(dirname "$(realpath "$0")")")" + +CONTAINER="${WORK_DIR}/.container" + +dest="${WORK_DIR}/_site" + +cmd="JEKYLL_ENV=production bundle exec jekyll b" + +docker=false + +config="" + +_help() { + echo "Usage:" + echo + echo " bash build.sh [options]" + echo + echo "Options:" + echo " -b, --baseurl The site relative url that start with slash, e.g. '/project'" + echo " -h, --help Print the help information" + echo " -d, --destination destination directory (defaults to ./_site)" + echo " --docker Build site within docker" + echo " --config Specify config files" +} + +_install_tools() { + # docker image `jekyll/jekyll` based on Alpine Linux + echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories + apk update + apk add yq +} + +_init() { + cd "$WORK_DIR" + + if [[ -f Gemfile.lock ]]; then + rm -f Gemfile.lock + fi + + if [[ -d $CONTAINER ]]; then + rm -rf "$CONTAINER" + fi + + if [[ -d $dest ]]; then + bundle exec jekyll clean + fi + + local _temp="$(mktemp -d)" + cp -r ./* "$_temp" + cp -r ./.git "$_temp" + mv "$_temp" "$CONTAINER" +} + +_build() { + cd "$CONTAINER" + echo "$ cd $(pwd)" + + bash "_scripts/sh/create_pages.sh" + bash "_scripts/sh/dump_lastmod.sh" + + cmd+=" -d $dest" + + if [[ -n $config ]]; then + cmd+=" --config $config" + fi + + echo "\$ $cmd" + eval "$cmd" + echo -e "\nBuild success, the site files have been placed in '${dest}'." + + if [[ -d "${dest}/.git" ]]; then + if [[ -n $(git -C "$dest" status -s) ]]; then + git -C "$dest" add . + git -C "$dest" commit -m "[Automation] Update site files." -q + echo -e "\nPlease push the changes of $dest to remote master branch.\n" + fi + fi + + cd .. && rm -rf "$CONTAINER" +} + +_check_unset() { + if [[ -z ${1:+unset} ]]; then + _help + exit 1 + fi +} + +main() { + while [[ $# -gt 0 ]]; do + opt="$1" + case $opt in + -b | --baseurl) + local _baseurl="$2" + if [[ -z $_baseurl ]]; then + _baseurl='""' + fi + cmd+=" -b $_baseurl" + shift + shift + ;; + -d | --destination) + _check_unset "$2" + dest="$(realpath "$2")" + shift + shift + ;; + --docker) + docker=true + shift + ;; + --config) + _check_unset "$2" + config="$(realpath "$2")" + shift + shift + ;; + -h | --help) + _help + exit 0 + ;; + *) # unknown option + _help + exit 1 + ;; + esac + done + + if $docker; then + _install_tools + fi + + _init + _build +} + +main "$@" diff --git a/tools/bump-version.sh b/tools/bump-version.sh new file mode 100755 index 000000000000..e797f9bf80e6 --- /dev/null +++ b/tools/bump-version.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# +# Bump latest version to file `_data/meta.yml` +# +# v2.5.1 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# Published under MIT License + +set -eu + +META_FILE="_data/meta.yml" + +_latest_tag="$(git describe --abbrev=0)" + +_version_field="version: $_latest_tag" + +if [[ ! -f $META_FILE ]]; then + echo "name: Chirpy" > $META_FILE + echo "$_version_field" >> $META_FILE +else + sed -i "s/^version:.*/$_version_field/g" $META_FILE +fi + +if [[ -n $(git status $META_FILE -s) ]]; then + git add $META_FILE + git commit -m "Bump version to $_latest_tag" +fi diff --git a/tools/deploy.sh b/tools/deploy.sh new file mode 100755 index 000000000000..bdc6cd1adae1 --- /dev/null +++ b/tools/deploy.sh @@ -0,0 +1,67 @@ +#!/bin/bash +# +# Deploy the content of _site to 'origin/' +# +# v2.5 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# Published under MIT License + +set -eu + +PAGES_BRANCH="gh-pages" + +_no_branch=false +_backup_dir="$(mktemp -d)" + +init() { + if [[ -z $(git branch -av | grep "$PAGES_BRANCH") ]]; then + _no_branch=true + git checkout -b "$PAGES_BRANCH" + else + git checkout "$PAGES_BRANCH" + fi +} + +backup() { + mv _site/* "$_backup_dir" + mv .git "$_backup_dir" + + # When adding custom domain from Github website, + # the CANME only exist on `gh-pages` branch + if [[ -f CNAME ]]; then + mv CNAME "$_backup_dir" + fi +} + +flush() { + rm -rf ./* + rm -rf .[^.] .??* + + shopt -s dotglob nullglob + mv "$_backup_dir"/* . +} + +deploy() { + git config --global user.name "GitHub Actions" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + + git update-ref -d HEAD + git add -A + git commit -m "[Automation] Site update No.${GITHUB_RUN_NUMBER}" + + if $_no_branch; then + git push -u origin "$PAGES_BRANCH" + else + git push -f + fi +} + +main() { + init + backup + flush + deploy +} + +main diff --git a/tools/init.sh b/tools/init.sh new file mode 100755 index 000000000000..51393dd5ec74 --- /dev/null +++ b/tools/init.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# +# Init the evrionment for new user. +# +# v2.5 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# Published under MIT License + +set -eu + +ACTIONS_WORKFLOW=pages-deploy.yml + +help() { + echo "Usage:" + echo + echo " bash /path/to/init.sh [options]" + echo + echo "Options:" + echo " --no-gh Do not deploy to Github." + echo " -h, --help Print this help information." +} + +check_init() { + local _has_inited=false + + if [[ ! -d docs ]]; then + if [[ ! -d .github ]]; then + _has_inited=true # --no-gh + else + if [[ -f .github/workflows/$ACTIONS_WORKFLOW ]]; then + # on BSD, the `wc` could contains blank + local _count="$(find .github/workflows/ -type f -name "*.yml" | wc -l)" + if [[ ${_count//[[:blank:]]/} == 1 ]]; then + _has_inited=true + fi + fi + fi + fi + + if $_has_inited; then + echo "Already initialized." + exit 0 + fi +} + +init_files() { + + if $_no_gh; then + rm -rf .github + else + mv .github/workflows/$ACTIONS_WORKFLOW.hook . + rm -rf .github + mkdir -p .github/workflows + mv ./${ACTIONS_WORKFLOW}.hook .github/workflows/${ACTIONS_WORKFLOW} + fi + + rm -f .travis.yml + rm -rf _posts/* docs + + git add -A && git add .github -f + git commit -m "[Automation] Initialize the environment." -q + + echo "[INFO] Initialization successful!" +} + +check_init + +_no_gh=false + +while (($#)); do + opt="$1" + case $opt in + --no-gh) + _no_gh=true + shift + ;; + -h | --help) + help + exit 0 + ;; + *) + # unknown option + help + exit 1 + ;; + esac +done + +init_files diff --git a/tools/pv.sh b/tools/pv.sh new file mode 100755 index 000000000000..e26ba10d270d --- /dev/null +++ b/tools/pv.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# Fetch Google Analytics Pageviews reporting cache +# and save as 'assets/data/pagevies.json' +# +# Requirement: +# - jq +# - wget +# +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# MIT Licensed + + +set -eu + +WORK_DIR="$(dirname "$(dirname "$(realpath "$0")")")" +URL_FILE="${WORK_DIR}/_config.yml" +PV_CACHE="${WORK_DIR}/assets/js/data/pageviews.json" + +PROXY_URL="$(grep "proxy_endpoint:" "$URL_FILE" | sed "s/.*: '//g;s/'.*//")" + +wget "$PROXY_URL" -O "$PV_CACHE" + +echo "ls $PV_CACHE" diff --git a/tools/run.sh b/tools/run.sh new file mode 100755 index 000000000000..ca117332c332 --- /dev/null +++ b/tools/run.sh @@ -0,0 +1,188 @@ +#!/bin/bash + +# Run jekyll site at http://127.0.0.1:4000 +# +# Requirement: +# Option '-r, --realtime' needs fswatch › http://emcrisostomo.github.io/fswatch/ +# +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2019 Cotes Chung +# Published under MIT License + +set -eu + +WORK_DIR="$(dirname "$(dirname "$(realpath "$0")")")" + +CONTAINER="${WORK_DIR}/.container" +SYNC_TOOL=_scripts/sh/sync_monitor.sh + +cmd="bundle exec jekyll s" +JEKYLL_DOCKER_HOME="/srv/jekyll" + +realtime=false +docker=false + +_help() { + echo "Usage:" + echo + echo " bash run.sh [options]" + echo + echo "Options:" + echo " -H, --host Host to bind to" + echo " -P, --port Port to listen on" + echo " -b, --baseurl The site relative url that start with slash, e.g. '/project'" + echo " -h, --help Print the help information" + echo " -t, --trace Show the full backtrace when an error occurs" + echo " -r, --realtime Make the modified content updated in real time" + echo " --docker Run within docker" +} + +_cleanup() { + rm -rf "$CONTAINER" + ps aux | grep fswatch | awk '{print $2}' | xargs kill -9 > /dev/null 2>&1 +} + +_setup_docker() { + # docker image `jekyll/jekyll` based on Alpine Linux + echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories + ## CN Apline sources mirror + # sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories + apk update + apk add yq +} + +_init() { + cd "$WORK_DIR" + + if [[ -f Gemfile.lock ]]; then + rm -f Gemfile.lock + fi + + if [[ -d $CONTAINER ]]; then + rm -rf "$CONTAINER" + fi + + mkdir "$CONTAINER" + cp -r ./* "$CONTAINER" + cp -r ./.git "$CONTAINER" + + if $docker; then + local _image_user=$(stat -c "%U" "$JEKYLL_DOCKER_HOME"/.) + + if [[ $_image_user != $(whoami) ]]; then + # under Docker for Linux + chown -R "$(stat -c "%U:%G" "$JEKYLL_DOCKER_HOME"/.)" "$CONTAINER" + fi + + fi + + trap _cleanup INT +} + +_check_unset() { + if [[ -z ${1:+unset} ]]; then + _help + exit 1 + fi +} + +_check_command() { + if [[ -z $(command -v "$1") ]]; then + echo "Error: command '$1' not found !" + echo "Hint: Get '$1' on <$2>" + exit 1 + fi +} + +_run() { + cd "$CONTAINER" + bash _scripts/sh/create_pages.sh + bash _scripts/sh/dump_lastmod.sh + + if $realtime; then + + exclude_regex="\/\..*" + + if [[ $OSTYPE == "darwin"* ]]; then + exclude_regex="/\..*" # darwin gcc treat regex '/' as character '/' + fi + + fswatch -e "$exclude_regex" -0 -r \ + --event Created --event Removed \ + --event Updated --event Renamed \ + --event MovedFrom --event MovedTo \ + "$WORK_DIR" | xargs -0 -I {} bash "./${SYNC_TOOL}" {} "$WORK_DIR" . & + fi + + if $docker; then + cmd+=" -H 0.0.0.0" + else + cmd+=" -l -o" + fi + + echo "\$ $cmd" + eval "$cmd" +} + +main() { + if $docker; then + _setup_docker + fi + + _init + _run +} + +while (($#)); do + opt="$1" + case $opt in + -H | --host) + _check_unset "$2" + cmd+=" -H $2" + shift # past argument + shift # past value + ;; + -P | --port) + _check_unset "$2" + cmd+=" -P $2" + shift + shift + ;; + -b | --baseurl) + _check_unset "$2" + if [[ $2 == \/* ]]; then + cmd+=" -b $2" + else + _help + exit 1 + fi + shift + shift + ;; + -t | --trace) + cmd+=" -t" + shift + ;; + -r | --realtime) + _check_command fswatch "http://emcrisostomo.github.io/fswatch/" + realtime=true + shift + ;; + --docker) + docker=true + shift + ;; + -h | --help) + _help + exit 0 + ;; + *) + # unknown option + _help + exit 1 + ;; + esac +done + +main diff --git a/tools/test.sh b/tools/test.sh new file mode 100755 index 000000000000..90dd70165f66 --- /dev/null +++ b/tools/test.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# +# Using HTML-proofer to test site. +# +# Requirement: https://github.com/gjtorikian/html-proofer +# +# Usage: bash /path/to/test.sh [indicated path] +# +# v2.0 +# https://github.com/cotes2020/jekyll-theme-chirpy +# © 2020 Cotes Chung +# MIT Licensed + +DEST=_site +URL_IGNORE=cdn.jsdelivr.net + +if [[ -n $1 && -d $1 ]]; then + DEST=$1 +fi + +bundle exec htmlproofer $DEST \ + --disable-external \ + --check-html \ + --empty_alt_ignore \ + --allow_hash_href \ + --url_ignore $URL_IGNORE