GitLab Commit is coming up on August 3-4. Learn how to innovate together using GitLab, the DevOps platform. Register for free: gitlabcommitvirtual2021.com

Unverified Commit 237b56af authored by Alex Lai's avatar Alex Lai 😊
Browse files

update git_objects_under_the_hood,asciinema working

add: asciinema shortcode
fix: asciinema background (delete background variable in _code.scss)
fix: toc problem which only starts from H2 (by config of markup)
add: toc using emacs
add: section "Tools to interact with git"
parent 368acc90
......@@ -106,11 +106,14 @@ copyright = "" # default: author.name ↓ # 默认为下面配
# Link custom CSS and JS assets
# (relative to /static/css and /static/js respectively)
customCSS = []
customJS = []
customCSS = [ ]
customJS = [ ]
uglyURLs = false # please keep same with uglyurls setting
asciinema = false
[params.publicCDN] # load these files from public cdn # 启用公共CDN,需自行定义
enable = true
jquery = '<script src="https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>'
......@@ -123,6 +126,7 @@ copyright = "" # default: author.name ↓ # 默认为下面配
sequenceDiagramsCSS = '<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/bramp/js-sequence-diagrams@2.0.1/dist/sequence-diagram-min.css" integrity="sha384-6QbLKJMz5dS3adWSeINZe74uSydBGFbnzaAYmp+tKyq60S7H2p6V7g1TysM5lAaF" crossorigin="anonymous">'
sequenceDiagramsJS = '<script src="https://cdn.jsdelivr.net/npm/webfontloader@1.6.28/webfontloader.js" integrity="sha256-4O4pS1SH31ZqrSO2A/2QJTVjTPqVe+jnYgOWUVr7EEc=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/snapsvg@0.5.1/dist/snap.svg-min.js" integrity="sha256-oI+elz+sIm+jpn8F/qEspKoKveTc5uKeFHNNVexe6d8=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/underscore@1.8.3/underscore-min.js" integrity="sha256-obZACiHd7gkOk9iIL/pimWMTJ4W/pBsKu+oZnSeBIek=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/gh/bramp/js-sequence-diagrams@2.0.1/dist/sequence-diagram-min.js" integrity="sha384-8748Vn52gHJYJI0XEuPB2QlPVNUkJlJn9tHqKec6J3q2r9l8fvRxrgn/E5ZHV0sP" crossorigin="anonymous"></script>'
# Display a message at the beginning of an article to warn the readers that it's content may be outdated.
# 在文章开头显示提示信息,提醒读者文章内容可能过时。
[params.outdatedInfoWarning]
......@@ -195,6 +199,12 @@ copyright = "" # default: author.name ↓ # 默认为下面配
n-gitlab = "https://gitlab.com/alexlai97"
# o-bilibili = "http://localhost:1313"
[markup]
[markup.tableOfContents]
endLevel = 5
ordered = false
startLevel = 1
# See https://gohugo.io/about/hugo-and-gdpr/
[privacy]
[privacy.googleAnalytics]
......
......@@ -11,8 +11,23 @@ summary: "You can setup a blog website like this. It's not that hard."
---
## Host locally
### hugo setup
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
- [Host locally](#host-locally)
- [hugo setup](#hugo-setup)
- [Get theme even](#get-theme-even)
- [Copy config.toml and posts from exampleSite](#copy-configtoml-and-posts-from-examplesite)
- [Host remotely](#host-remotely)
- [git push](#git-push)
- [push to netlify](#push-to-netlify)
- [Host under your domain name](#host-under-your-domain-name)
<!-- markdown-toc end -->
# Host locally
## hugo setup
Get [hugo](https://gohugo.io/) here or use your package manager to install.
Then let's make a empty site.
......@@ -22,14 +37,14 @@ $ cd my_site
$ git init
```
### Get theme even
## Get theme even
hugo-theme-even [github](https://github.com/olOwOlo/hugo-theme-even)
```sh
$ git submodule add https://github.com/olOwOlo/hugo-theme-even themes/even
```
### Copy config.toml and posts from exampleSite
## Copy config.toml and posts from exampleSite
```sh
$ cp -r themes/even/exampleSite/* .
......@@ -43,16 +58,16 @@ Your website is serving at the local address (default [http://localhost:1313/](h
Now you can play around by changing files. Immediate changes will be shown in your browser.
## Host remotely
### git push
# Host remotely
## git push
Go to your git server (gitlab or github or whatever you like), push it there.
### push to netlify
## push to netlify
I am using [netlify](https://www.netlify.com/) as a CI tool and web server.
Put below in `my_site/netlify.toml`
```toml
# netlify.toml
netlify.toml
[build]
publish = "public"
command = "hugo --gc --minify"
......@@ -68,7 +83,7 @@ Then you should be given a domain (you can change it) that hosts your website!
Alternatively, you can use [github pages](https://pages.github.com/) with [travis-ci](https://travis-ci.com/) or [gitlab pages](https://docs.gitlab.com/ee/user/project/pages/) with [gitlab CI](https://docs.gitlab.com/ee/ci/README.html).
## Host under your domain name
# Host under your domain name
First, you need to have a domain name. I bought one from [hover](https://www.hover.com/) for slightly above 10 bucks per year. You can buy it elsewhere.
I also uses [cloudflare](https://www.cloudflare.com/) as domain name server (DNS) instead of the default hover one.
......
......@@ -5,7 +5,7 @@ lastmod: 2020-04-08
draft: false
keywords: []
description: "my linux tool box"
categories : ["personal"]
categories : ["tools"]
tags : ["blog", "linux", "tools"]
summary: "simply a dump of applications I've used or am using. TL;DR -> [dotfiles](https://github.com/alexlai97/dotfiles)"
......@@ -23,18 +23,37 @@ The starred\* ones are my favorite(s).
Here is my [dotfiles](https://github.com/alexlai97/dotfiles).
<!-- more -->
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
## Linux Distribution
- [Linux Distribution](#linux-distribution)
- [Window Manager](#window-manager)
- [Text Editor](#text-editor)
- [Neovim/vim plugins](#neovimvim-plugins)
- [Other vim related stuff](#other-vim-related-stuff)
- [Shell](#shell)
- [Terminal Emulator](#terminal-emulator)
- [Email client](#email-client)
- [File managers](#file-managers)
- [pdf viewer](#pdf-viewer)
- [Minimalism](#minimalism)
- [Rusty](#rusty)
- [Terminal based](#terminal-based)
- [More resources](#more-resources)
<!-- markdown-toc end -->
# Linux Distribution
[mint](https://linuxmint.com/) -> [openSUSE](https://www.opensuse.org/) -> [ubuntu](https://ubuntu.com/) -> [kubuntu](https://kubuntu.org/) -> [arch](https://wiki.archlinux.org/) -> [gentoo](https://gentoo.org/)\* -> [arch](https://wiki.archlinux.org/)\*
## Window Manager
# Window Manager
[i3](https://i3wm.org/)\* -> [dwm](https://dwm.suckless.org/)\* -> [awesomewm](https://awesomewm.org/)\*
## Text Editor
# Text Editor
[vim](https://www.vim.org/) -> [neovim](https://github.com/neovim/neovim) -> [spacemacs](http://spacemacs.org/) -> [spacevim](https://spacevim.org/) -> [neovim](https://github.com/neovim/neovim)\* -> [doom-emacs](https://github.com/hlissner/doom-emacs)\*
### Neovim/vim plugins
## Neovim/vim plugins
* [dein](https://github.com/Shougo/dein.vim): plugin manager
* [tagbar](https://github.com/majutsushi/tagbar): displays tags in a window
* [vim-fugitive](https://github.com/tpope/vim-fugitive): git wrapper
......@@ -48,22 +67,22 @@ Here is my [dotfiles](https://github.com/alexlai97/dotfiles).
* [coc.nvim](https://github.com/neoclide/coc.nvim)
* ... more checkout [my config inside dein block](https://github.com/alexlai97/dotfiles/blob/master/vim/.vim/config/setup/dein_packages_setup.vim#L26)
### Other vim related stuff
## Other vim related stuff
* [fish](https://fishshell.com/) shell vim mode: enable by this function `fish_vi_keybindings`
* firefox [Vim Vixen](https://github.com/ueokande/vim-vixen)
## Shell
# Shell
[bash](https://www.gnu.org/software/bash/) -> [zsh](https://github.com/robbyrussell/oh-my-zsh) -> [ion](https://github.com/redox-os/ion) -> [fish](https://fishshell.com/)\*
more shells: [archwiki](https://wiki.archlinux.org/index.php/Command-line_shell)
## Terminal Emulator
# Terminal Emulator
[konsole](https://konsole.kde.org/) -> [xfce terminal](https://docs.xfce.org/apps/terminal/start) -> [xterm](https://invisible-island.net/xterm/) -> [urxvt](http://software.schmorp.de/pkg/rxvt-unicode.html) -> [st](http://st.suckless.org/)\* -> [termite](https://github.com/thestinger/termite) -> [alacritty](https://github.com/alacritty/alacritty)\*
more terminal emulators: [archwiki](https://wiki.archlinux.org/index.php/List_of_applications/Utilities#Terminal_emulators)
## Email client
# Email client
* graphical: [thunderbird](https://www.thunderbird.net/en-US/)
* terminal: [neomutt](https://github.com/neomutt/neomutt)\*
......@@ -72,7 +91,7 @@ tried notmuch in emacs, and watched videos about mu4e in emacs but I think I wil
more email clients: [archwiki](https://wiki.archlinux.org/index.php/Category:Email_clients)
## File managers
# File managers
* graphical: [natilus](https://wiki.gnome.org/Apps/Files) -> [dolphin](https://userbase.kde.org/Dolphin) -> [spacefm](http://ignorantguru.github.io/spacefm/) -> [thunar](https://docs.xfce.org/xfce/thunar/start)\*
* terminal: [ranger](https://ranger.github.io/)\* -> [vifm](https://vifm.info/)\*
......@@ -81,18 +100,18 @@ navigating in shell is also not bad ...
more file managers: [archwiki](https://wiki.archlinux.org/index.php/List_of_applications/Utilities#File_managers)
## pdf viewer
# pdf viewer
[okular](https://okular.kde.org/) -> [evince](https://wiki.gnome.org/Apps/Evince) -> [zathura](https://pwmt.org/projects/zathura/)\* | [emacs](https://www.gnu.org/software/emacs/)
more document viewers: [archwiki](https://wiki.archlinux.org/index.php/PDF,_PS_and_DjVu)
## Minimalism
# Minimalism
* [suckless tools](https://github.com/alexlai97/suckless_stuff)
* [zathura](https://git.pwmt.org/pwmt/zathura)
* [vimb](https://github.com/fanglingsu/vimb)
## Rusty
# Rusty
written in [rust](https://www.rust-lang.org/)
* [exa](https://github.com/ogham/exa): `ls` alternative
* [bat](https://github.com/sharkdp/bat)\*: `cat` alternative
......@@ -102,13 +121,13 @@ written in [rust](https://www.rust-lang.org/)
* [skim](https://github.com/lotabout/skim): `fzf` alternative
* [mdbook](https://github.com/rust-lang-nursery/mdBook): create book from markdown files
## Terminal based
# Terminal based
- [tuir](https://gitlab.com/ajak/tuir/): reddit in terminal
- [newsboat](https://newsboat.org/): rss reader
- [ncmpcpp](https://wiki.archlinux.org/index.php/Ncmpcpp): music player daemon client
- [neomutt](https://neomutt.org/): email client
## More resources
# More resources
- [suckless](http://suckless.org/)
- [archwiki: List of applications](https://wiki.archlinux.org/index.php/List_of_applications)
- my [dotfiles](https://github.com/alexlai97/dotfiles)
+++
title = "Git under the hood tutorial"
date = 2019-11-24
draft = true
[taxonomies]
categories = ["tutorial"]
tags = ["blog", "git", "advanced"]
+++
<!-- more -->
This post is highly inspired by [this talk](https://youtu.be/P6jD966jzlk) and [this talk](https://youtu.be/ig5E8CcdM9g).
# Git objects
## `git init`
When you `git init` inside a directory, you will find a `.git` directory.
```fish
$ find . # show files, subdirectories in current directory
.
./.git
./.git/description
./.git/objects
./.git/objects/info
./.git/objects/pack
./.git/HEAD
./.git/refs
./.git/refs/tags
./.git/refs/heads
./.git/info
./.git/info/exclude
./.git/config
./.git/hooks
./.git/hooks/*.sample # omited
```
## decompress compress objects
<script id="asciicast-73F0JU26fVyJDDw0JVJfTfpnX" src="https://asciinema.org/a/73F0JU26fVyJDDw0JVJfTfpnX.js" async></script>
In the [show case](https://asciinema.org/a/73F0JU26fVyJDDw0JVJfTfpnX) above, I decompressed the blob object and compress the byte string again and got the filename using `decompress` and `compress` functions below.
```python
import zlib # A compression / decompression library
def decompress(filename):
compressed_contents = open(filename, 'rb').read()
decompressed_contents = zlib.decompress(compressed_contents)
return decompressed_contents
from hashlib import sha1 # SHA1 hash algorithm
def compress(decompressed_contents):
return sha1(decompressed_contents).hexdigest()
```
```python
# In interactive python
[1]: content = decompress('.git/objects/d1/16b98e17c490ba139a2be4e6156646b904dade')
[2]: content
b'blob 33\x00I am the foo file, check me out!\n' # prints the content in byte string
[3]: compress(content)
'd116b98e17c490ba139a2be4e6156646b904dade' # prints the hash of the content
```
So a git object can be decompressed using [`zlib`](https://en.wikipedia.org/wiki/Zlib) library, and you can calculate the hash of the content using [`sha1`](https://en.wikipedia.org/wiki/SHA-1).
Notice that the hash is the filename almost.
## git cat-file
<script id="asciicast-C0OXpazEYSC7QNINK11O7baHN" src="https://asciinema.org/a/C0OXpazEYSC7QNINK11O7baHN.js" async></script>
In the above [show case](https://asciinema.org/a/C0OXpazEYSC7QNINK11O7baHN), `git cat-file` can replace the `decompress` function above.
Two parameters are useful to see the type and content of a given git object:
```fish
$ git cat-file -t d116b # show the type
blob
$ git cat-file -p d116b # pretty print
I am the foo file, check me out!
```
A blob stores the content of a file (note: it does not store the name or the [mode](https://en.wikipedia.org/wiki/Modes_(Unix)) of the file).
## inside commit, tree, blob object files
<script id="asciicast-EHS4x0z65g3LUzVaJtScEuefg" src="https://asciinema.org/a/EHS4x0z65g3LUzVaJtScEuefg.js" async></script>
[Recording](https://asciinema.org/a/EHS4x0z65g3LUzVaJtScEuefg) above shows that:
1. the content of the first commit is the hash of a tree, author, commiter, comments
2. the content of a tree is the hash a blob (actually it can have hashes of multiple trees and blobs)
3. the content of a blob is a file content
4. the content of a non-first commit also includes the hash of its parent
## using `git gc`
[short show case](https://asciinema.org/a/b4YDBG1S8g21Xj3dM4bUWdKvf)
<script id="asciicast-b4YDBG1S8g21Xj3dM4bUWdKvf" src="https://asciinema.org/a/b4YDBG1S8g21Xj3dM4bUWdKvf.js" async></script>
Note that you don't really need to do this manually, it is done automatically.
## create 100 files with same content
[show case](https://asciinema.org/a/DWUqj1ODLaxxLr1BCQ9F7MJoa)
<script id="asciicast-DWUqj1ODLaxxLr1BCQ9F7MJoa" src="https://asciinema.org/a/DWUqj1ODLaxxLr1BCQ9F7MJoa.js" async></script>
Note that if I created 100 files, only one git object is added.
## create some branches
[show case](https://asciinema.org/a/Sr5qTUXJ7Va2XWrrGlkqh44yg)
<script id="asciicast-Sr5qTUXJ7Va2XWrrGlkqh44yg" src="https://asciinema.org/a/Sr5qTUXJ7Va2XWrrGlkqh44yg.js" async></script>
- with no other branches commits is like a single linked list where child has a pointer (hash) to its parent
- with branches, commits will be like a [Directed acyclic graph](https://en.wikipedia.org/wiki/Directed_acyclic_graph)
## relation between git objects
![git basic objects relations](./git_basic_objects_relations.png)
Based on the knowledge previously, it is easier to understand:
- a blob is like a file, a tree is like a directory
- branch, remote are like pointers (store the hash of a particular commit)
# Collaboration
## fast forward
[show case](https://asciinema.org/a/BD77lZnqqhZTUlf9sRX4HABcv)
<script id="asciicast-cGSyUO5oTxYPMzaF5E0AkCgzI" src="https://asciinema.org/a/cGSyUO5oTxYPMzaF5E0AkCgzI.js" async></script>
## solve conflict
[show case](https://asciinema.org/a/BD77lZnqqhZTUlf9sRX4HABcv)
<script id="asciicast-BD77lZnqqhZTUlf9sRX4HABcv" src="https://asciinema.org/a/BD77lZnqqhZTUlf9sRX4HABcv.js" async></script>
## workflow
![git some commands workflow](./git_some_commands_workflow.png)
# more to come
- rebase
- reset
- squash
+++
title = "What are git objects under the hood"
date = 2019-11-24
[taxonomies]
categories = ["tutorial"]
tags = ["blog", "git", "advanced"]
+++
---
title : "What are git objects under the hood"
date : 2019-11-24
lastmod: 2020-04-08
draft: false
keywords: []
categories : ["explanation"]
tags : ["blog", "git", "explanation", "advanced"]
summary: "Have you ever looked at what's inside `.git/` ?"
asciinema: true
---
> "git - the stupid content tracker" – description of `man git` written by Linus Torvalds
<!-- more -->
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
- [What are under the hood ?](#what-are-under-the-hood-)
- [git objects and some "pointers"](#git-objects-and-some-pointers)
- [decompress and compress the object](#decompress-and-compress-the-object)
- [git cat-file](#git-cat-file)
- [inside tag, commit, tree, blob objects](#inside-tag-commit-tree-blob-objects)
- [blob object](#blob-object)
- [tree object](#tree-object)
- [commit object](#commit-object)
- [tag object](#tag-object)
- [Tools to interact with git](#tools-to-interact-with-git)
- [references and resources](#references-and-resources)
<!-- markdown-toc end -->
# What are under the hood ?
......@@ -31,7 +50,7 @@ How to see what's inside a git object ?
[demo of decompress and compress using zlib and sha1](https://asciinema.org/a/DAkrzbtGiu7UqoNouJvMnyuSa)
<script id="asciicast-DAkrzbtGiu7UqoNouJvMnyuSa" src="https://asciinema.org/a/DAkrzbtGiu7UqoNouJvMnyuSa.js" async></script>
{{< asciinema cast_path="git_objects_under_the_hood/decompress_compress_using_zlib_and_sha1.cast" cols="133" rows="39" theme="asciinema">}}
You can use `decompress` the filename to decompress the git object using [`zlib`](https://en.wikipedia.org/wiki/Zlib) and `compress` the byte string to get the [`sha1`](https://en.wikipedia.org/wiki/SHA-1) hash of the object, which is very similar to its filename.
......@@ -68,7 +87,7 @@ Instead of using the script above, `git cat-file` ([man](https://linux.die.net/m
[demo of git cat-file](https://asciinema.org/a/cuQdmq5JnfcakExw9YYrEiXxl)
<script id="asciicast-cuQdmq5JnfcakExw9YYrEiXxl" src="https://asciinema.org/a/cuQdmq5JnfcakExw9YYrEiXxl.js" async></script>
{{< asciinema cast_path="git_objects_under_the_hood/git_cat_file_demo.cast" cols="133" rows="39" theme="asciinema">}}
- `git cat-file -t` is to print the type of the object
- `git cat-file -p` is to pretty print the content of the object
......@@ -86,7 +105,7 @@ Let's take a look at them.
[demo of inside tag, commit, tree, blob](https://asciinema.org/a/ruaTNbFFh4QunRUKUQaAyw1Z2)
<script id="asciicast-ruaTNbFFh4QunRUKUQaAyw1Z2" src="https://asciinema.org/a/ruaTNbFFh4QunRUKUQaAyw1Z2.js" async></script>
{{< asciinema cast_path="git_objects_under_the_hood/inside_tag_commit_tree_blob_objects.cast" cols="133" rows="38" theme="asciinema">}}
```fish
### a summary of demo
......@@ -144,7 +163,7 @@ What do you think will happen to the `.git/objects/` directory if we create 100
[demo of creating 100 same files](https://asciinema.org/a/DWUqj1ODLaxxLr1BCQ9F7MJoa)
<script id="asciicast-DWUqj1ODLaxxLr1BCQ9F7MJoa" src="https://asciinema.org/a/DWUqj1ODLaxxLr1BCQ9F7MJoa.js" async></script>
{{< asciinema cast_path="git_objects_under_the_hood/create_100_same_files.cast" cols="133" rows="39" theme="asciinema">}}
Answer: only one blob object is created.
......@@ -199,7 +218,7 @@ child # ← comment/message
Let's take a look at an example ([rust repository](https://github.com/rust-lang/rust)) in the wild.
[demo of rust commits](https://asciinema.org/a/fsKYtvn2oMbXoRg2mlYQYboR7)
<script id="asciicast-fsKYtvn2oMbXoRg2mlYQYboR7" src="https://asciinema.org/a/fsKYtvn2oMbXoRg2mlYQYboR7.js" async></script>
{{< asciinema cast_path="git_objects_under_the_hood/commits_of_rust.cast" cols="133" rows="38" theme="asciinema">}}
You can think of commits as a [forest](http://mathworld.wolfram.com/Forest.html) where each child stores the hash of its parent (or it will be an abandoned child).
......@@ -225,9 +244,20 @@ Let's look at tags still in the [rust](https://github.com/rust-lang/rust) exampl
[demo of rust tag 1.39.0](https://asciinema.org/a/22OtLQi8wBiLD7XYLR38snz3B)
<script id="asciicast-22OtLQi8wBiLD7XYLR38snz3B" src="https://asciinema.org/a/22OtLQi8wBiLD7XYLR38snz3B.js" async></script>
{{< asciinema cast_path="git_objects_under_the_hood/rust_tag_1.39.0.cast" cols="133" rows="38" theme="asciinema">}}
The tag can also be GPG signed, ensuring the cryptographic integrity to a release or a version.
The tag (or commit) can also be signed by your pgp secret key, ensuring the cryptographic integrity to a release or a version.
# Tools to interact with git
Here are a list of tools I often use to interact with git:
- `git` commands in shell, which I feel safe most
- [vim-fugitive](https://github.com/tpope/vim-fugitive) (very powerful and interactive plugin, can replace the `git` commands in shell by `:Git` functions in vim)
- [emacs magit](https://github.com/tpope/vim-fugitive) I am still new to this, it's very interactive.
Here are some more gui tools I have tried:
- [gitk](https://git-scm.com/docs/gitk) not bad, I use it sometimes to visualize
- [git gui](https://git-scm.com/docs/git-gui) well, I already have vim-fugitive
- [gitkraken](https://www.gitkraken.com/) (very good but it's [not free](https://www.gitkraken.com/pricing#plan-comparison) for private repositories)
# references and resources
- youtube ["Git Internals - How Git Works - Fear Not The SHA!"](https://youtu.be/P6jD966jzlk)
......@@ -240,3 +270,4 @@ The tag can also be GPG signed, ensuring the cryptographic integrity to a releas
- man page: [`watch`](https://linux.die.net/man/1/watch)
- man page: [`git`](https://linux.die.net/man/1/git)
- shell: [`fish`](https://fishshell.com/)
{
"even": {
"css": "even.af98c776.min.css",
"css": "even.35784885.min.css",
"js": "even.da83905b.min.js"
}
}
\ No newline at end of file
<meta name="renderer" content="webkit" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta name="theme-color" content="#f8f5ec" />
<meta name="msapplication-navbutton-color" content="#f8f5ec">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="#f8f5ec">
<!-- author & description & keywords -->
<meta name="author" content="{{ if .Params.author }}{{ .Params.author | safeHTML }}{{ else }}{{ .Site.Author.name | safeHTML }}{{ end }}" />
{{- if .Description -}}
<meta name="description" content="{{ .Description | safeHTML }}" />
{{- else if .IsPage -}}
<meta name="description" content="{{ .Summary | plainify }}" />
{{- else if .Site.Params.description -}}
<meta name="description" content="{{ .Site.Params.description | safeHTML }}" />
{{- end -}}
{{- if .Keywords -}}
{{ $length := len .Keywords | add -1 -}}
<meta name="keywords" content="{{ range $index, $element := .Keywords }}{{ $element | safeHTML }}{{if ne $index $length }}, {{ end }}{{ end }}" />
{{- else if .Site.Params.keywords -}}
{{ $length := len .Site.Params.keywords | add -1 -}}
<meta name="keywords" content="{{ range $index, $element := .Site.Params.keywords }}{{ $element | safeHTML }}{{if ne $index $length }}, {{ end }}{{ end }}" />
{{- end }}
<!-- baidu & google verification -->
{{ with .Site.Params.baiduVerification }}<meta name="baidu-site-verification" content="{{.}}" />{{ end }}
{{ with .Site.Params.googleVerification }}<meta name="google-site-verification" content="{{.}}" />{{ end }}
<!-- Site Generator -->
<meta name="generator" content="Hugo {{ .Site.Hugo.Version }} with theme even" />
<!-- Permalink & RSSlink -->
<link rel="canonical" href="{{ .Permalink }}" />
{{- with .OutputFormats.Get "RSS" }}
<link href="{{ .Permalink }}" rel="alternate" type="application/rss+xml" title="{{ $.Site.Title }}" />
<link href="{{ .Permalink }}" rel="feed" type="application/rss+xml" title="{{ $.Site.Title }}" />
{{- end -}}
<!-- Favicon and Touch icons -->
<link rel="apple-touch-icon" sizes="180x180" href="{{ "apple-touch-icon.png" | relURL }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ "favicon-32x32.png" | relURL }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ "favicon-16x16.png" | relURL }}">
<link rel="manifest" href="{{ "manifest.json" | relURL }}">
<link rel="mask-icon" href="{{ "safari-pinned-tab.svg" | relURL }}" color="#5bbad5">
<!-- debug -->
{{- if .Site.Params.debug -}}
<script src="https://cdn.jsdelivr.net/npm/eruda@1.2.6/eruda.min.js" integrity="sha256-Jmz4bc3kp+rRrXX2tGadNBKFLwtzMapr8kHABxSAAP8=" crossorigin="anonymous"></script>
<script>eruda.init();</script>
{{- end -}}
<!-- busuanzi -->
{{- if .Site.Params.busuanzi.enable -}}
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
{{- end -}}
<!-- asciinema -->
{{- if .Params.asciinema -}}
<link rel="stylesheet" type="text/css" href="{{ "css/asciinema-player.css" | relURL }}" />
{{- end -}}
<!-- Styles -->
<link href="{{ print "dist/" .Site.Data.even.assets.even.css | relURL }}" rel="stylesheet">
{{ if .Site.Params.publicCDN.enable -}}
{{ if .Site.Params.fancybox }}{{ .Site.Params.publicCDN.fancyboxCSS | safeHTML }}{{ end }}
{{- else -}}
{{ if .Site.Params.fancybox }}<link href="{{ "lib/fancybox/jquery.fancybox-3.1.20.min.css" | relURL }}" rel="stylesheet">{{ end }}