+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_:
+ 
+
+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 @@
+
+
+
+
+
+
\ 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 %}
+
+ {% 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 @@
+
+
+
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 @@
+
+
+
+
{{ site.data.share.label }}
+
+ {% capture title %}{{ page.title }} - {{ site.title }}{% endcapture %}
+ {% assign url = page.url | relative_url | prepend: site.url %}
+
+ {% for share in site.data.share.platforms %}
+ {% assign link = share.link | replace: 'TITLE', title | replace: 'URL', url %}
+
+
+
+ {% endfor %}
+
+
+
+
+
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 %}
+
+
{{ site.data.label.post.relate_posts }}
+
+ {% for entry in index_list %}
+ {% assign index = entry | plus: 0 %}
+ {% assign post = site.posts[index] %}
+
+ {% endfor %}
+
+
+{% 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}
+
+
{categories}
+
{tags}
+
+
{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 %}
+
{{ tag | replace: '-', ' ' }}
+ {% 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 @@
+
+
+
+
+
+
+
+
+
{{- site.tagline -}}
+
+
+
+
+ {% assign page_urls = page.url | split: "/" %}
+
+ {% for item in site.data.tabs %}
+ {% assign ref = site.baseurl | append: "/" %}
+
+ {% if item.path %}
+ {% assign ref = ref | append: item.path | append: "/" %}
+ {% if item.url %}
+ {% assign ref = ref | append: item.url | append: "/" %}
+ {% endif %}
+ {% endif %}
+
+
+
+
+ {{ item.name | upcase }}
+
+
+ {% endfor %}
+
+
+
+
+
+
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 %}{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "" %}{% 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 sidebar.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 %}
+
+
+
+
+ {% if post.pin == true %}
+
+ {% endif %}
+
+
+
+ {% include no-linenos.html content=post.content %}
+ {{ content | markdownify | strip_html | truncate: 200 }}
+
+
+
+
+
+
+ {% include timeago.html date=post.date tooltip=true %}
+
+
+ {% if site.google_analytics.pv.enabled %}
+
+
+
+
+ {% endif %}
+
+
+
+{% 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 }}
+
+
+
+
+ Posted
+ {% include timeago.html date=page.date tooltip=true %}
+ by
+
+ {% if page.author %}
+ {{ page.author }}
+ {% else %}
+ {{ site.author }}
+ {% endif %}
+
+
+
+
+ {%- capture filename -%}
+ {{ page.url | split: "/" | last }}
+ {%- endcapture -%}
+
+ {% for item in site.data.updates %}
+ {% assign encode_filename = item.filename | url_encode %}
+ {% if filename == encode_filename %}
+ {% assign lastmod = item.lastmod %}
+ {% break %}
+ {% endif %}
+ {% endfor %}
+
+ {% if lastmod %}
+
+ Updated
+ {% include timeago.html date=lastmod class="lastmod" tooltip=true %}
+
+ {% endif %}
+
+
+ {% if site.google_analytics.pv.enabled %}
+
+
+ views
+
+ {% endif %}
+
+
+
+
+
+ {%- 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 %}
+
+ {% 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.
+
+
+*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!
+
+---
+
+1 GitHub 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/)
+
+2 ETL 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 " " */
+ 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 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
+ *
+ * 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')},createChildNavList:function(e){var t=this.createNavList();return e.append(t),t},generateNavEl:function(e,t){var n=a(' ');n.attr("href","#"+e),n.text(t);var r=a(" ");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(11?m.options.decimal+p[1]:"";if(m.options.useGrouping){q="";for(u=0,o=s.length;um.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.frameValm.endVal)?m.endVal:m.frameVal}m.frameVal=Math.round(m.frameVal*m.dec)/m.dec;m.printValue(m.frameVal);if(om.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&&ra.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 %}
+
+ {{ site.url }}
+ {{ 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 %}
+
+
+ {% 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 %}
+
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