doc-theme 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +50 -0
- data/_data/locales/ar.yml +91 -0
- data/_data/locales/bg-BG.yml +81 -0
- data/_data/locales/cs-CZ.yml +89 -0
- data/_data/locales/de-DE.yml +87 -0
- data/_data/locales/el-GR.yml +91 -0
- data/_data/locales/en.yml +91 -0
- data/_data/locales/es-ES.yml +77 -0
- data/_data/locales/fi-FI.yml +90 -0
- data/_data/locales/fr-FR.yml +77 -0
- data/_data/locales/hu-HU.yml +79 -0
- data/_data/locales/id-ID.yml +77 -0
- data/_data/locales/it-IT.yml +90 -0
- data/_data/locales/ko-KR.yml +84 -0
- data/_data/locales/my-MM.yml +77 -0
- data/_data/locales/pt-BR.yml +77 -0
- data/_data/locales/ru-RU.yml +87 -0
- data/_data/locales/sl-SI.yml +91 -0
- data/_data/locales/sv-SE.yml +91 -0
- data/_data/locales/th.yml +91 -0
- data/_data/locales/tr-TR.yml +77 -0
- data/_data/locales/uk-UA.yml +77 -0
- data/_data/locales/vi-VN.yml +76 -0
- data/_data/locales/zh-CN.yml +83 -0
- data/_data/locales/zh-TW.yml +83 -0
- data/_data/origin/basic.yml +46 -0
- data/_data/origin/cors.yml +59 -0
- data/_includes/.DS_Store +0 -0
- data/_includes/analytics/goatcounter.html +6 -0
- data/_includes/analytics/google.html +13 -0
- data/_includes/comments/disqus.html +50 -0
- data/_includes/comments/giscus.html +65 -0
- data/_includes/comments/utterances.html +50 -0
- data/_includes/comments.html +5 -0
- data/_includes/datetime.html +20 -0
- data/_includes/embed/bilibili.html +9 -0
- data/_includes/embed/twitch.html +8 -0
- data/_includes/embed/video.html +38 -0
- data/_includes/embed/youtube.html +9 -0
- data/_includes/favicons.html +19 -0
- data/_includes/footer.html +42 -0
- data/_includes/head.html +111 -0
- data/_includes/img-url.html +39 -0
- data/_includes/js-selector.html +126 -0
- data/_includes/jsdelivr-combine.html +26 -0
- data/_includes/lang.html +10 -0
- data/_includes/language-alias.html +70 -0
- data/_includes/mermaid.html +58 -0
- data/_includes/metadata-hook.html +1 -0
- data/_includes/mode-toggle.html +143 -0
- data/_includes/no-linenos.html +10 -0
- data/_includes/notification.html +24 -0
- data/_includes/origin-type.html +13 -0
- data/_includes/pageviews/goatcounter.html +18 -0
- data/_includes/post-nav.html +34 -0
- data/_includes/post-paginator.html +91 -0
- data/_includes/post-sharing.html +52 -0
- data/_includes/read-time.html +37 -0
- data/_includes/refactor-content.html +255 -0
- data/_includes/related-posts.html +96 -0
- data/_includes/search-loader.html +47 -0
- data/_includes/search-results.html +10 -0
- data/_includes/sidebar.html +99 -0
- data/_includes/toc.html +13 -0
- data/_includes/topbar.html +77 -0
- data/_includes/trending-tags.html +46 -0
- data/_includes/update-list.html +40 -0
- data/_layouts/archives.html +35 -0
- data/_layouts/categories.html +138 -0
- data/_layouts/category.html +24 -0
- data/_layouts/compress.html +10 -0
- data/_layouts/default.html +87 -0
- data/_layouts/home.html +118 -0
- data/_layouts/page.html +20 -0
- data/_layouts/post.html +149 -0
- data/_layouts/tag.html +23 -0
- data/_layouts/tags.html +22 -0
- data/_sass/.DS_Store +0 -0
- data/_sass/addon/commons.scss +1553 -0
- data/_sass/addon/module.scss +200 -0
- data/_sass/addon/syntax.scss +292 -0
- data/_sass/addon/variables.scss +33 -0
- data/_sass/colors/syntax-dark.scss +164 -0
- data/_sass/colors/syntax-light.scss +214 -0
- data/_sass/colors/typography-dark.scss +147 -0
- data/_sass/colors/typography-light.scss +112 -0
- data/_sass/layout/archives.scss +144 -0
- data/_sass/layout/categories.scss +83 -0
- data/_sass/layout/category-tag.scss +72 -0
- data/_sass/layout/home.scss +189 -0
- data/_sass/layout/post.scss +357 -0
- data/_sass/layout/tags.scss +19 -0
- data/_sass/main.scss +13 -0
- data/_sass/variables-hook.scss +3 -0
- data/assets/.DS_Store +0 -0
- data/assets/404.html +14 -0
- data/assets/css/doc-theme.scss +6 -0
- data/assets/feed.xml +61 -0
- data/assets/img/favicons/android-chrome-192x192.png +0 -0
- data/assets/img/favicons/android-chrome-512x512.png +0 -0
- data/assets/img/favicons/apple-touch-icon.png +0 -0
- data/assets/img/favicons/browserconfig.xml +13 -0
- data/assets/img/favicons/favicon-16x16.png +0 -0
- data/assets/img/favicons/favicon-32x32.png +0 -0
- data/assets/img/favicons/favicon.ico +0 -0
- data/assets/img/favicons/mstile-150x150.png +0 -0
- data/assets/img/favicons/site.webmanifest +26 -0
- data/assets/js/data/search.json +20 -0
- data/assets/js/data/swconf.js +51 -0
- data/assets/js/pwa/app.js +54 -0
- data/assets/js/pwa/sw.js +101 -0
- data/assets/robots.txt +10 -0
- metadata +260 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{%- comment -%}
|
|
2
|
+
Generate image final URL based on `site.img_cdn`, `page.img_path`
|
|
3
|
+
|
|
4
|
+
Arguments:
|
|
5
|
+
src - required, basic image path
|
|
6
|
+
img_path - optional, relative path of image
|
|
7
|
+
absolute - optional, boolean, if true, generate absolute URL
|
|
8
|
+
|
|
9
|
+
Return:
|
|
10
|
+
image URL
|
|
11
|
+
{%- endcomment -%}
|
|
12
|
+
|
|
13
|
+
{% assign url = include.src %}
|
|
14
|
+
|
|
15
|
+
{%- if url -%}
|
|
16
|
+
{% unless url contains ':' %}
|
|
17
|
+
{%- comment -%} CND URL {%- endcomment -%}
|
|
18
|
+
{% assign prefix = site.img_cdn | default: '' %}
|
|
19
|
+
|
|
20
|
+
{%- comment -%} Add page image path prefix {%- endcomment -%}
|
|
21
|
+
{% assign url = include.img_path | default: '' | append: '/' | append: url %}
|
|
22
|
+
|
|
23
|
+
{% assign url = prefix
|
|
24
|
+
| append: '/'
|
|
25
|
+
| append: url
|
|
26
|
+
| replace: '///', '/'
|
|
27
|
+
| replace: '//', '/'
|
|
28
|
+
| replace: ':', ':/'
|
|
29
|
+
%}
|
|
30
|
+
|
|
31
|
+
{% if include.absolute %}
|
|
32
|
+
{% assign url = site.url | append: site.baseurl | append: url %}
|
|
33
|
+
{% else %}
|
|
34
|
+
{% assign url = site.baseurl | append: url %}
|
|
35
|
+
{% endif %}
|
|
36
|
+
{% endunless %}
|
|
37
|
+
{%- endif -%}
|
|
38
|
+
|
|
39
|
+
{{- url -}}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
<!-- JS selector for site. -->
|
|
2
|
+
|
|
3
|
+
<!-- commons -->
|
|
4
|
+
|
|
5
|
+
{% assign urls = site.data.origin[type].jquery.js
|
|
6
|
+
| append: ','
|
|
7
|
+
| append: site.data.origin[type].bootstrap.js
|
|
8
|
+
| append: ','
|
|
9
|
+
| append: site.data.origin[type].search.js
|
|
10
|
+
%}
|
|
11
|
+
|
|
12
|
+
<!-- layout specified -->
|
|
13
|
+
|
|
14
|
+
{% assign js_dist = '/assets/js/dist/' %}
|
|
15
|
+
|
|
16
|
+
{% if page.layout == 'post' or page.layout == 'page' or page.layout == 'home' %}
|
|
17
|
+
{% assign urls = urls | append: ',' | append: site.data.origin[type]['lazy-polyfill'].js %}
|
|
18
|
+
|
|
19
|
+
{% unless page.layout == 'home' %}
|
|
20
|
+
<!-- image lazy-loading & popup & clipboard -->
|
|
21
|
+
{% assign urls = urls
|
|
22
|
+
| append: ','
|
|
23
|
+
| append: site.data.origin[type]['magnific-popup'].js
|
|
24
|
+
| append: ','
|
|
25
|
+
| append: site.data.origin[type].clipboard.js
|
|
26
|
+
%}
|
|
27
|
+
{% endunless %}
|
|
28
|
+
{% endif %}
|
|
29
|
+
|
|
30
|
+
{% if page.layout == 'home'
|
|
31
|
+
or page.layout == 'post'
|
|
32
|
+
or page.layout == 'archives'
|
|
33
|
+
or page.layout == 'category'
|
|
34
|
+
or page.layout == 'tag'
|
|
35
|
+
%}
|
|
36
|
+
{% assign locale = include.lang | split: '-' | first %}
|
|
37
|
+
|
|
38
|
+
{% assign urls = urls
|
|
39
|
+
| append: ','
|
|
40
|
+
| append: site.data.origin[type].dayjs.js.common
|
|
41
|
+
| append: ','
|
|
42
|
+
| append: site.data.origin[type].dayjs.js.locale
|
|
43
|
+
| replace: ':LOCALE', locale
|
|
44
|
+
| append: ','
|
|
45
|
+
| append: site.data.origin[type].dayjs.js.relativeTime
|
|
46
|
+
| append: ','
|
|
47
|
+
| append: site.data.origin[type].dayjs.js.localizedFormat
|
|
48
|
+
%}
|
|
49
|
+
{% endif %}
|
|
50
|
+
|
|
51
|
+
{% if page.content contains '<h2' or page.content contains '<h3' and site.toc and page.toc %}
|
|
52
|
+
{% assign urls = urls | append: ',' | append: site.data.origin[type].toc.js %}
|
|
53
|
+
{% endif %}
|
|
54
|
+
|
|
55
|
+
{% if page.mermaid %}
|
|
56
|
+
{% assign urls = urls | append: ',' | append: site.data.origin[type].mermaid.js %}
|
|
57
|
+
{% endif %}
|
|
58
|
+
|
|
59
|
+
{% include jsdelivr-combine.html urls=urls %}
|
|
60
|
+
|
|
61
|
+
{% case page.layout %}
|
|
62
|
+
{% when 'home', 'categories', 'post', 'page' %}
|
|
63
|
+
{% assign js = page.layout %}
|
|
64
|
+
{% when 'archives', 'category', 'tag' %}
|
|
65
|
+
{% assign js = 'misc' %}
|
|
66
|
+
{% else %}
|
|
67
|
+
{% assign js = 'commons' %}
|
|
68
|
+
{% endcase %}
|
|
69
|
+
|
|
70
|
+
{% capture script %}{{ js_dist }}{{ js }}.min.js{% endcapture %}
|
|
71
|
+
<script defer src="{{ script | relative_url }}"></script>
|
|
72
|
+
|
|
73
|
+
{% if page.math %}
|
|
74
|
+
<!-- MathJax -->
|
|
75
|
+
<script>
|
|
76
|
+
/* see: <https://docs.mathjax.org/en/latest/options/input/tex.html#tex-options> */
|
|
77
|
+
MathJax = {
|
|
78
|
+
tex: {
|
|
79
|
+
/* start/end delimiter pairs for in-line math */
|
|
80
|
+
inlineMath: [
|
|
81
|
+
['$', '$'],
|
|
82
|
+
['\\(', '\\)']
|
|
83
|
+
],
|
|
84
|
+
/* start/end delimiter pairs for display math */
|
|
85
|
+
displayMath: [
|
|
86
|
+
['$$', '$$'],
|
|
87
|
+
['\\[', '\\]']
|
|
88
|
+
],
|
|
89
|
+
/* equation numbering */
|
|
90
|
+
tags: 'ams'
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
</script>
|
|
94
|
+
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=es6"></script>
|
|
95
|
+
<script id="MathJax-script" async src="{{ site.data.origin[type].mathjax.js | relative_url }}"></script>
|
|
96
|
+
{% endif %}
|
|
97
|
+
|
|
98
|
+
<!-- Pageviews -->
|
|
99
|
+
{% if page.layout == 'post' %}
|
|
100
|
+
{% assign provider = site.pageviews.provider %}
|
|
101
|
+
|
|
102
|
+
{% if provider and provider != empty %}
|
|
103
|
+
{% case provider %}
|
|
104
|
+
{% when 'goatcounter' %}
|
|
105
|
+
{% if site.analytics[provider].id != empty and site.analytics[provider].id %}
|
|
106
|
+
{% include pageviews/{{ provider }}.html %}
|
|
107
|
+
{% endif %}
|
|
108
|
+
{% endcase %}
|
|
109
|
+
{% endif %}
|
|
110
|
+
{% endif %}
|
|
111
|
+
|
|
112
|
+
{% if jekyll.environment == 'production' %}
|
|
113
|
+
<!-- PWA -->
|
|
114
|
+
{% if site.pwa.enabled %}
|
|
115
|
+
<script defer src="{{ 'app.min.js' | prepend: js_dist | relative_url }}"></script>
|
|
116
|
+
{% endif %}
|
|
117
|
+
|
|
118
|
+
<!-- Web Analytics -->
|
|
119
|
+
{% for analytics in site.analytics %}
|
|
120
|
+
{% capture str %}{{ analytics }}{% endcapture %}
|
|
121
|
+
{% assign type = str | split: '{' | first %}
|
|
122
|
+
{% if site.analytics[type].id and site.analytics[type].id != empty %}
|
|
123
|
+
{% include analytics/{{ type }}.html %}
|
|
124
|
+
{% endif %}
|
|
125
|
+
{% endfor %}
|
|
126
|
+
{% endif %}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{% assign urls = include.urls | split: ',' %}
|
|
2
|
+
|
|
3
|
+
{% assign combined_urls = nil %}
|
|
4
|
+
|
|
5
|
+
{% assign domain = 'https://cdn.jsdelivr.net/' %}
|
|
6
|
+
|
|
7
|
+
{% for url in urls %}
|
|
8
|
+
{% if url contains domain %}
|
|
9
|
+
{% assign url_snippet = url | slice: domain.size, url.size %}
|
|
10
|
+
|
|
11
|
+
{% if combined_urls %}
|
|
12
|
+
{% assign combined_urls = combined_urls | append: ',' | append: url_snippet %}
|
|
13
|
+
{% else %}
|
|
14
|
+
{% assign combined_urls = domain | append: 'combine/' | append: url_snippet %}
|
|
15
|
+
{% endif %}
|
|
16
|
+
|
|
17
|
+
{% elsif url contains '//' %}
|
|
18
|
+
<script src="{{ url }}"></script>
|
|
19
|
+
{% else %}
|
|
20
|
+
<script src="{{ url | relative_url }}"></script>
|
|
21
|
+
{% endif %}
|
|
22
|
+
{% endfor %}
|
|
23
|
+
|
|
24
|
+
{% if combined_urls %}
|
|
25
|
+
<script src="{{ combined_urls }}"></script>
|
|
26
|
+
{% endif %}
|
data/_includes/lang.html
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Detect appearance language and return it through variable "lang"
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
{% if site.data.locales[page.lang] %}
|
|
5
|
+
{% assign lang = page.lang %}
|
|
6
|
+
{% elsif site.data.locales[site.lang] %}
|
|
7
|
+
{% assign lang = site.lang %}
|
|
8
|
+
{% else %}
|
|
9
|
+
{% assign lang = 'en' %}
|
|
10
|
+
{% endif %}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
|
|
3
|
+
Convert the alias of the syntax language to the official name
|
|
4
|
+
|
|
5
|
+
See: <https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers>
|
|
6
|
+
|
|
7
|
+
{% endcomment %}
|
|
8
|
+
|
|
9
|
+
{% assign _lang = include.language | default: '' %}
|
|
10
|
+
|
|
11
|
+
{% case _lang %}
|
|
12
|
+
{% when 'actionscript', 'as', 'as3' %}
|
|
13
|
+
{{ 'ActionScript' }}
|
|
14
|
+
{% when 'applescript' %}
|
|
15
|
+
{{ 'AppleScript' }}
|
|
16
|
+
{% when 'brightscript', 'bs', 'brs' %}
|
|
17
|
+
{{ 'BrightScript' }}
|
|
18
|
+
{% when 'cfscript', 'cfc' %}
|
|
19
|
+
{{ 'CFScript' }}
|
|
20
|
+
{% when 'coffeescript', 'coffee', 'coffee-script' %}
|
|
21
|
+
{{ 'CoffeeScript' }}
|
|
22
|
+
{% when 'cs', 'csharp' %}
|
|
23
|
+
{{ 'C#' }}
|
|
24
|
+
{% when 'erl' %}
|
|
25
|
+
{{ 'Erlang' }}
|
|
26
|
+
{% when 'graphql' %}
|
|
27
|
+
{{ 'GraphQL' }}
|
|
28
|
+
{% when 'haskell', 'hs' %}
|
|
29
|
+
{{ 'Haskell' }}
|
|
30
|
+
{% when 'javascript', 'js' %}
|
|
31
|
+
{{ 'JavaScript' }}
|
|
32
|
+
{% when 'make', 'mf', 'gnumake', 'bsdmake' %}
|
|
33
|
+
{{ 'Makefile' }}
|
|
34
|
+
{% when 'md', 'mkd' %}
|
|
35
|
+
{{ 'Markdown' }}
|
|
36
|
+
{% when 'm' %}
|
|
37
|
+
{{ 'Matlab' }}
|
|
38
|
+
{% when 'objective_c', 'objc', 'obj-c', 'obj_c', 'objectivec' %}
|
|
39
|
+
{{ 'Objective-C' }}
|
|
40
|
+
{% when 'perl', 'pl' %}
|
|
41
|
+
{{ 'Perl' }}
|
|
42
|
+
{% when 'php','php3','php4','php5' %}
|
|
43
|
+
{{ 'PHP' }}
|
|
44
|
+
{% when 'py' %}
|
|
45
|
+
{{ 'Python' }}
|
|
46
|
+
{% when 'rb' %}
|
|
47
|
+
{{ 'Ruby' }}
|
|
48
|
+
{% when 'rs','no_run','ignore','should_panic' %}
|
|
49
|
+
{{ 'Rust' }}
|
|
50
|
+
{% when 'bash', 'zsh', 'ksh', 'sh' %}
|
|
51
|
+
{{ 'Shell' }}
|
|
52
|
+
{% when 'st', 'squeak' %}
|
|
53
|
+
{{ 'Smalltalk' }}
|
|
54
|
+
{% when 'tex'%}
|
|
55
|
+
{{ 'TeX' }}
|
|
56
|
+
{% when 'latex' %}
|
|
57
|
+
{{ 'LaTex' }}
|
|
58
|
+
{% when 'ts', 'typescript' %}
|
|
59
|
+
{{ 'TypeScript' }}
|
|
60
|
+
{% when 'vb', 'visualbasic' %}
|
|
61
|
+
{{ 'Visual Basic' }}
|
|
62
|
+
{% when 'vue', 'vuejs' %}
|
|
63
|
+
{{ 'Vue.js' }}
|
|
64
|
+
{% when 'yml' %}
|
|
65
|
+
{{ 'YAML' }}
|
|
66
|
+
{% when 'css', 'html', 'scss', 'ssh', 'toml', 'xml', 'yaml', 'json' %}
|
|
67
|
+
{{ _lang | upcase }}
|
|
68
|
+
{% else %}
|
|
69
|
+
{{ _lang | capitalize }}
|
|
70
|
+
{% endcase %}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!-- mermaid-js loader -->
|
|
2
|
+
<script type="text/javascript">
|
|
3
|
+
(function () {
|
|
4
|
+
function updateMermaid(event) {
|
|
5
|
+
if (event.source === window && event.data && event.data.direction === ModeToggle.ID) {
|
|
6
|
+
const mode = event.data.message;
|
|
7
|
+
|
|
8
|
+
if (typeof mermaid === 'undefined') {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let expectedTheme = mode === ModeToggle.DARK_MODE ? 'dark' : 'default';
|
|
13
|
+
let config = { theme: expectedTheme };
|
|
14
|
+
|
|
15
|
+
/* Re-render the SVG › <https://github.com/mermaid-js/mermaid/issues/311#issuecomment-332557344> */
|
|
16
|
+
$('.mermaid').each(function () {
|
|
17
|
+
let svgCode = $(this).prev().children().html();
|
|
18
|
+
$(this).removeAttr('data-processed');
|
|
19
|
+
$(this).html(svgCode);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
mermaid.initialize(config);
|
|
23
|
+
mermaid.init(undefined, '.mermaid');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let initTheme = 'default';
|
|
28
|
+
const html = document.documentElement;
|
|
29
|
+
|
|
30
|
+
if (
|
|
31
|
+
(html.hasAttribute('data-mode') && html.getAttribute('data-mode') === 'dark') ||
|
|
32
|
+
(!html.hasAttribute('data-mode') && window.matchMedia('(prefers-color-scheme: dark)').matches)
|
|
33
|
+
) {
|
|
34
|
+
initTheme = 'dark';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let mermaidConf = {
|
|
38
|
+
theme: initTheme /* <default|dark|forest|neutral> */
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/* Create mermaid tag */
|
|
42
|
+
document.querySelectorAll('pre>code.language-mermaid').forEach((elem) => {
|
|
43
|
+
const svgCode = elem.textContent;
|
|
44
|
+
const backup = elem.parentElement;
|
|
45
|
+
backup.classList.add('unloaded');
|
|
46
|
+
/* create mermaid node */
|
|
47
|
+
let mermaid = document.createElement('pre');
|
|
48
|
+
mermaid.classList.add('mermaid');
|
|
49
|
+
const text = document.createTextNode(svgCode);
|
|
50
|
+
mermaid.appendChild(text);
|
|
51
|
+
backup.after(mermaid);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
mermaid.initialize(mermaidConf);
|
|
55
|
+
|
|
56
|
+
window.addEventListener('message', updateMermaid);
|
|
57
|
+
})();
|
|
58
|
+
</script>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!-- A placeholder to allow defining custom metadata -->
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<!-- Switch the mode between dark and light. -->
|
|
2
|
+
|
|
3
|
+
<script type="text/javascript">
|
|
4
|
+
class ModeToggle {
|
|
5
|
+
static get MODE_KEY() {
|
|
6
|
+
return 'mode';
|
|
7
|
+
}
|
|
8
|
+
static get MODE_ATTR() {
|
|
9
|
+
return 'data-mode';
|
|
10
|
+
}
|
|
11
|
+
static get DARK_MODE() {
|
|
12
|
+
return 'dark';
|
|
13
|
+
}
|
|
14
|
+
static get LIGHT_MODE() {
|
|
15
|
+
return 'light';
|
|
16
|
+
}
|
|
17
|
+
static get ID() {
|
|
18
|
+
return 'mode-toggle';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
constructor() {
|
|
22
|
+
if (this.hasMode) {
|
|
23
|
+
if (this.isDarkMode) {
|
|
24
|
+
if (!this.isSysDarkPrefer) {
|
|
25
|
+
this.setDark();
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
if (this.isSysDarkPrefer) {
|
|
29
|
+
this.setLight();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let self = this;
|
|
35
|
+
|
|
36
|
+
/* always follow the system prefers */
|
|
37
|
+
this.sysDarkPrefers.addEventListener('change', () => {
|
|
38
|
+
if (self.hasMode) {
|
|
39
|
+
if (self.isDarkMode) {
|
|
40
|
+
if (!self.isSysDarkPrefer) {
|
|
41
|
+
self.setDark();
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
if (self.isSysDarkPrefer) {
|
|
45
|
+
self.setLight();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
self.clearMode();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
self.notify();
|
|
53
|
+
});
|
|
54
|
+
} /* constructor() */
|
|
55
|
+
|
|
56
|
+
get sysDarkPrefers() {
|
|
57
|
+
return window.matchMedia('(prefers-color-scheme: dark)');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
get isSysDarkPrefer() {
|
|
61
|
+
return this.sysDarkPrefers.matches;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
get isDarkMode() {
|
|
65
|
+
return this.mode === ModeToggle.DARK_MODE;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get isLightMode() {
|
|
69
|
+
return this.mode === ModeToggle.LIGHT_MODE;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get hasMode() {
|
|
73
|
+
return this.mode != null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
get mode() {
|
|
77
|
+
return sessionStorage.getItem(ModeToggle.MODE_KEY);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* get the current mode on screen */
|
|
81
|
+
get modeStatus() {
|
|
82
|
+
if (this.isDarkMode || (!this.hasMode && this.isSysDarkPrefer)) {
|
|
83
|
+
return ModeToggle.DARK_MODE;
|
|
84
|
+
} else {
|
|
85
|
+
return ModeToggle.LIGHT_MODE;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
setDark() {
|
|
90
|
+
document.documentElement.setAttribute(ModeToggle.MODE_ATTR, ModeToggle.DARK_MODE);
|
|
91
|
+
sessionStorage.setItem(ModeToggle.MODE_KEY, ModeToggle.DARK_MODE);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
setLight() {
|
|
95
|
+
document.documentElement.setAttribute(ModeToggle.MODE_ATTR, ModeToggle.LIGHT_MODE);
|
|
96
|
+
sessionStorage.setItem(ModeToggle.MODE_KEY, ModeToggle.LIGHT_MODE);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
clearMode() {
|
|
100
|
+
document.documentElement.removeAttribute(ModeToggle.MODE_ATTR);
|
|
101
|
+
sessionStorage.removeItem(ModeToggle.MODE_KEY);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Notify another plugins that the theme mode has changed */
|
|
105
|
+
notify() {
|
|
106
|
+
window.postMessage(
|
|
107
|
+
{
|
|
108
|
+
direction: ModeToggle.ID,
|
|
109
|
+
message: this.modeStatus
|
|
110
|
+
},
|
|
111
|
+
'*'
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
flipMode() {
|
|
116
|
+
if (this.hasMode) {
|
|
117
|
+
if (this.isSysDarkPrefer) {
|
|
118
|
+
if (this.isLightMode) {
|
|
119
|
+
this.clearMode();
|
|
120
|
+
} else {
|
|
121
|
+
this.setLight();
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
if (this.isDarkMode) {
|
|
125
|
+
this.clearMode();
|
|
126
|
+
} else {
|
|
127
|
+
this.setDark();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
if (this.isSysDarkPrefer) {
|
|
132
|
+
this.setLight();
|
|
133
|
+
} else {
|
|
134
|
+
this.setDark();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
this.notify();
|
|
139
|
+
} /* flipMode() */
|
|
140
|
+
} /* ModeToggle */
|
|
141
|
+
|
|
142
|
+
const modeToggle = new ModeToggle();
|
|
143
|
+
</script>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{% comment %}
|
|
2
|
+
Remove the line number of the code snippet.
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
|
|
5
|
+
{% assign content = include.content %}
|
|
6
|
+
|
|
7
|
+
{% if content contains '<td class="rouge-gutter gl"><pre class="lineno">' %}
|
|
8
|
+
{% assign content = content | replace: '<td class="rouge-gutter gl"><pre class="lineno">', '<!-- <td class="rouge-gutter gl"><pre class="lineno">'%}
|
|
9
|
+
{% assign content = content | replace: '</td><td class="rouge-code">', '</td> --><td class="rouge-code">' %}
|
|
10
|
+
{% endif %}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<aside
|
|
2
|
+
id="notification"
|
|
3
|
+
class="toast"
|
|
4
|
+
role="alert"
|
|
5
|
+
aria-live="assertive"
|
|
6
|
+
aria-atomic="true"
|
|
7
|
+
data-bs-animation="true"
|
|
8
|
+
data-bs-autohide="false"
|
|
9
|
+
>
|
|
10
|
+
<div class="toast-header">
|
|
11
|
+
<button
|
|
12
|
+
type="button"
|
|
13
|
+
class="btn-close ms-auto"
|
|
14
|
+
data-bs-dismiss="toast"
|
|
15
|
+
aria-label="Close"
|
|
16
|
+
></button>
|
|
17
|
+
</div>
|
|
18
|
+
<div class="toast-body text-center pt-0">
|
|
19
|
+
<p class="px-2 mb-3">{{ site.data.locales[include.lang].notification.update_found }}</p>
|
|
20
|
+
<button type="button" class="btn btn-primary" aria-label="Update">
|
|
21
|
+
{{ site.data.locales[include.lang].notification.update }}
|
|
22
|
+
</button>
|
|
23
|
+
</div>
|
|
24
|
+
</aside>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{% comment %} Site static assets origin type {% endcomment %}
|
|
2
|
+
|
|
3
|
+
{% assign type = 'cors' %}
|
|
4
|
+
|
|
5
|
+
{% if site.assets.self_host.enabled %}
|
|
6
|
+
{% if site.assets.self_host.env %}
|
|
7
|
+
{% if site.assets.self_host.env == jekyll.environment %}
|
|
8
|
+
{% assign type = 'basic' %}
|
|
9
|
+
{% endif %}
|
|
10
|
+
{% else %}
|
|
11
|
+
{% assign type = 'basic' %}
|
|
12
|
+
{% endif %}
|
|
13
|
+
{% endif %}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!-- Display GoatCounter pageviews -->
|
|
2
|
+
<script>
|
|
3
|
+
let pv = document.getElementById('pageviews');
|
|
4
|
+
|
|
5
|
+
if (pv !== null) {
|
|
6
|
+
const uri = location.pathname.replace(/\/$/, '');
|
|
7
|
+
const url = `https://{{ site.analytics.goatcounter.id }}.goatcounter.com/counter/${encodeURIComponent(uri)}.json`;
|
|
8
|
+
|
|
9
|
+
fetch(url)
|
|
10
|
+
.then((response) => response.json())
|
|
11
|
+
.then((data) => {
|
|
12
|
+
pv.innerText = new Intl.NumberFormat().format(data.count);
|
|
13
|
+
})
|
|
14
|
+
.catch((error) => {
|
|
15
|
+
pv.innerText = '1';
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
</script>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<!-- Navigation buttons at the bottom of the post. -->
|
|
2
|
+
|
|
3
|
+
<nav class="post-navigation d-flex justify-content-between" aria-label="Post Navigation">
|
|
4
|
+
{% assign previous = site.data.locales[include.lang].post.button.previous %}
|
|
5
|
+
{% assign next = site.data.locales[include.lang].post.button.next %}
|
|
6
|
+
|
|
7
|
+
{% if page.previous.url %}
|
|
8
|
+
<a
|
|
9
|
+
href="{{ site.baseurl }}{{ page.previous.url }}"
|
|
10
|
+
class="btn btn-outline-primary"
|
|
11
|
+
aria-label="{{ previous }}"
|
|
12
|
+
>
|
|
13
|
+
<p>{{ page.previous.title }}</p>
|
|
14
|
+
</a>
|
|
15
|
+
{% else %}
|
|
16
|
+
<div class="btn btn-outline-primary disabled" aria-label="{{ previous }}">
|
|
17
|
+
<p>-</p>
|
|
18
|
+
</div>
|
|
19
|
+
{% endif %}
|
|
20
|
+
|
|
21
|
+
{% if page.next.url %}
|
|
22
|
+
<a
|
|
23
|
+
href="{{ site.baseurl }}{{page.next.url}}"
|
|
24
|
+
class="btn btn-outline-primary"
|
|
25
|
+
aria-label="{{ next }}"
|
|
26
|
+
>
|
|
27
|
+
<p>{{ page.next.title }}</p>
|
|
28
|
+
</a>
|
|
29
|
+
{% else %}
|
|
30
|
+
<div class="btn btn-outline-primary disabled" aria-label="{{ next }}">
|
|
31
|
+
<p>-</p>
|
|
32
|
+
</div>
|
|
33
|
+
{% endif %}
|
|
34
|
+
</nav>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<!-- The paginator for post list on HomgPage. -->
|
|
2
|
+
|
|
3
|
+
<nav aria-label="Page Navigation">
|
|
4
|
+
<ul class="pagination align-items-center mt-4 mb-0">
|
|
5
|
+
<!-- left arrow -->
|
|
6
|
+
{% if paginator.previous_page %}
|
|
7
|
+
{% assign prev_url = paginator.previous_page_path | relative_url %}
|
|
8
|
+
{% else %}
|
|
9
|
+
{% assign prev_url = '#' %}
|
|
10
|
+
{% endif %}
|
|
11
|
+
|
|
12
|
+
<li class="page-item {% unless paginator.previous_page %}disabled{% endunless %}">
|
|
13
|
+
<a class="page-link" href="{{ prev_url }}" aria-label="previous-page">
|
|
14
|
+
<i class="fas fa-angle-left"></i>
|
|
15
|
+
</a>
|
|
16
|
+
</li>
|
|
17
|
+
|
|
18
|
+
<!-- page numbers -->
|
|
19
|
+
{% assign left_ellipsis = false %}
|
|
20
|
+
{% assign right_ellipsis = false %}
|
|
21
|
+
|
|
22
|
+
{% for i in (1..paginator.total_pages) %}
|
|
23
|
+
{% assign pre = paginator.page | minus: 1 %}
|
|
24
|
+
{% assign next = paginator.page | plus: 1 %}
|
|
25
|
+
{% assign pre_less = pre | minus: 1 %}
|
|
26
|
+
{% assign next_more = next | plus: 1 %}
|
|
27
|
+
{% assign show = false %}
|
|
28
|
+
|
|
29
|
+
{% if paginator.page == 1 %}
|
|
30
|
+
{% if i <= 3 or i == paginator.total_pages %}
|
|
31
|
+
{% assign show = true %}
|
|
32
|
+
{% endif %}
|
|
33
|
+
{% elsif paginator.page == paginator.total_pages %}
|
|
34
|
+
{% if i == 1 or i >= pre_less %}
|
|
35
|
+
{% assign show = true %}
|
|
36
|
+
{% endif %}
|
|
37
|
+
{% else %}
|
|
38
|
+
{% if i == 1 or i == paginator.total_pages %}
|
|
39
|
+
{% assign show = true %}
|
|
40
|
+
{% elsif i >= pre and i <= next %}
|
|
41
|
+
{% assign show = true %}
|
|
42
|
+
{% endif %}
|
|
43
|
+
{% endif %}
|
|
44
|
+
|
|
45
|
+
{% if show %}
|
|
46
|
+
<!-- show number -->
|
|
47
|
+
<li class="page-item {% if i == paginator.page %} active{% endif %}">
|
|
48
|
+
<a
|
|
49
|
+
class="page-link"
|
|
50
|
+
href="{% if i > 1 %}{{ site.paginate_path | replace: ':num', i | relative_url }}{% else %}{{ '/' | relative_url }}{% endif %}"
|
|
51
|
+
>
|
|
52
|
+
{{- i -}}
|
|
53
|
+
</a>
|
|
54
|
+
</li>
|
|
55
|
+
{% else %}
|
|
56
|
+
<!-- hide number -->
|
|
57
|
+
{% if i < pre and left_ellipsis == false %}
|
|
58
|
+
<li class="page-item disabled">
|
|
59
|
+
<span class="page-link">...</span>
|
|
60
|
+
</li>
|
|
61
|
+
{% assign left_ellipsis = true %}
|
|
62
|
+
{% elsif i > next and right_ellipsis == false %}
|
|
63
|
+
<li class="page-item disabled">
|
|
64
|
+
<span class="page-link">...</span>
|
|
65
|
+
</li>
|
|
66
|
+
{% assign right_ellipsis = true %}
|
|
67
|
+
{% endif %}
|
|
68
|
+
{% endif %}
|
|
69
|
+
{% endfor %}
|
|
70
|
+
|
|
71
|
+
<!-- mobile pagination -->
|
|
72
|
+
<li class="page-index align-middle">
|
|
73
|
+
<span>{{ paginator.page }}</span>
|
|
74
|
+
<span class="text-muted">/ {{ paginator.total_pages }}</span>
|
|
75
|
+
</li>
|
|
76
|
+
|
|
77
|
+
<!-- right arrow -->
|
|
78
|
+
{% if paginator.next_page_path %}
|
|
79
|
+
{% assign next_url = paginator.next_page_path | relative_url %}
|
|
80
|
+
{% else %}
|
|
81
|
+
{% assign next_url = '#' %}
|
|
82
|
+
{% endif %}
|
|
83
|
+
|
|
84
|
+
<li class="page-item {% unless paginator.next_page_path %}disabled{% endunless %}">
|
|
85
|
+
<a class="page-link" href="{{ next_url }}" aria-label="next-page">
|
|
86
|
+
<i class="fas fa-angle-right"></i>
|
|
87
|
+
</a>
|
|
88
|
+
</li>
|
|
89
|
+
</ul>
|
|
90
|
+
</nav>
|
|
91
|
+
<!-- .pagination -->
|