├── settings.gradle ├── src ├── css │ ├── patch │ │ ├── index.scss │ │ ├── commons.scss │ │ └── links.scss │ ├── variables-hook.scss │ ├── style.scss │ ├── layout │ │ ├── tags.scss │ │ ├── category-tag.scss │ │ ├── categories.scss │ │ └── archives.scss │ ├── jekyll-theme-chirpy.scss │ ├── addon │ │ ├── variables.scss │ │ └── module.scss │ └── colors │ │ ├── syntax-dark.scss │ │ └── syntax-light.scss ├── _layouts │ ├── _includes │ │ ├── metadata-hook.html │ │ ├── comments.html │ │ ├── embed │ │ │ ├── twitch.html │ │ │ └── youtube.html │ │ ├── lang.html │ │ ├── search-results.html │ │ ├── origin-type.html │ │ ├── toc.html │ │ ├── no-linenos.html │ │ ├── google-analytics.html │ │ ├── datetime.html │ │ ├── notification.html │ │ ├── jsdelivr-combine.html │ │ ├── favicons.html │ │ ├── post-nav.html │ │ ├── read-time.html │ │ ├── footer.html │ │ ├── update-list.html │ │ ├── post-sharing.html │ │ ├── search-loader.html │ │ ├── trending-tags.html │ │ ├── comments │ │ │ ├── disqus.html │ │ │ ├── utterances.html │ │ │ └── giscus.html │ │ ├── mermaid.html │ │ ├── language-alias.html │ │ ├── topbar.html │ │ ├── related-posts.html │ │ ├── post-paginator.html │ │ ├── js-selector.html │ │ └── head.html │ ├── tags.html │ ├── page.html │ ├── tag.html │ ├── category.html │ ├── archives.html │ └── default.html ├── js │ ├── _copyright │ ├── modules │ │ ├── layouts │ │ │ ├── topbar.js │ │ │ ├── basic.js │ │ │ └── sidebar.js │ │ ├── layouts.js │ │ ├── components │ │ │ ├── search-display.js │ │ │ ├── tooltip-loader.js │ │ │ ├── toc.js │ │ │ ├── back-to-top.js │ │ │ ├── img-popup.js │ │ │ ├── mode-watcher.js │ │ │ ├── img-lazyload.js │ │ │ ├── sidebar.js │ │ │ ├── category-collapse.js │ │ │ ├── locale-datetime.js │ │ │ └── clipboard.js │ │ ├── plugins.js │ │ └── halo.js │ ├── pwa │ │ ├── unregister.js │ │ ├── app.js │ │ └── sw.js │ └── patch │ │ ├── index.js │ │ ├── sidebar.js │ │ ├── table.js │ │ ├── pre-img.js │ │ └── codeClass.js ├── _data │ ├── authors.yml │ ├── share.yml │ ├── contact.yml │ ├── origin │ │ ├── basic.yml │ │ └── cors.yml │ └── locales │ │ ├── zh-CN.yml │ │ ├── zh-TW.yml │ │ ├── ko-KR.yml │ │ ├── uk-UA.yml │ │ ├── id-ID.yml │ │ ├── pt-BR.yml │ │ ├── hu-HU.yml │ │ ├── fr-FR.yml │ │ ├── ru-RU.yml │ │ ├── tr-TR.yml │ │ ├── vi-VN.yml │ │ ├── es-ES.yml │ │ ├── bg-BG.yml │ │ ├── de-DE.yml │ │ ├── my-MM.yml │ │ ├── ar.yml │ │ ├── th.yml │ │ ├── cs-CZ.yml │ │ ├── en.yml │ │ ├── fi-FI.yml │ │ ├── sv-SE.yml │ │ ├── it-IT.yml │ │ ├── el-GR.yml │ │ └── sl-SI.yml └── main.js ├── .github ├── FUNDING.yml ├── auto_assign.yml └── workflows │ ├── build.yml │ └── release.yml ├── .prettierrc ├── prettier.config.js ├── templates ├── assets │ ├── img │ │ └── favicons │ │ │ ├── favicon.ico │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── mstile-150x150.png │ │ │ ├── apple-touch-icon.png │ │ │ ├── android-chrome-192x192.png │ │ │ ├── android-chrome-512x512.png │ │ │ ├── browserconfig.xml │ │ │ └── site.webmanifest │ └── 404.html ├── modules │ ├── widgets │ │ ├── update-list.html │ │ ├── trending-tags.html │ │ └── post-paginator.html │ ├── panel.html │ ├── footer.html │ ├── head.html │ ├── post │ │ ├── postShaing.html │ │ └── relatedPosts.html │ ├── topbar.html │ ├── sidebar.html │ └── layout.html ├── error │ └── error.html ├── page.html ├── tags.html ├── archives.html ├── links.html ├── tag.html ├── category.html └── index.html ├── .eslintrc.cjs ├── SECURITY.md ├── .editorconfig ├── .gitignore ├── annotation-setting.yaml ├── theme.yaml ├── i18n ├── en.properties └── default.properties ├── mode.js ├── .stylelintrc.json ├── LICENSE ├── export-zip.js ├── vite.config.js ├── package.json ├── settings.yaml └── gradlew.bat /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'halo-theme-chirpy' 2 | -------------------------------------------------------------------------------- /src/css/patch/index.scss: -------------------------------------------------------------------------------- 1 | @import 'commons'; 2 | @import 'links'; -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ["https://afdian.net/a/airbozh"] 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none", 3 | "endOfLine": "crlf" 4 | } 5 | -------------------------------------------------------------------------------- /src/_layouts/_includes/metadata-hook.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/js/_copyright: -------------------------------------------------------------------------------- 1 | Chirpy v<%= pkg.version %> | © 2019 <%= pkg.author %> | <%= pkg.license %> Licensed | <%= pkg.homepage %> 2 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | tabWidth: 2, 4 | useTabs: false, 5 | endOfLine: "lf", 6 | }; 7 | -------------------------------------------------------------------------------- /src/css/variables-hook.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Appending custom SCSS variables will override the default ones in `_sass/addon/variables.scsss` 3 | */ 4 | -------------------------------------------------------------------------------- /templates/assets/img/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AirboZH/halo-theme-chirpy/HEAD/templates/assets/img/favicons/favicon.ico -------------------------------------------------------------------------------- /templates/assets/img/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AirboZH/halo-theme-chirpy/HEAD/templates/assets/img/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /templates/assets/img/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AirboZH/halo-theme-chirpy/HEAD/templates/assets/img/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /templates/assets/img/favicons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AirboZH/halo-theme-chirpy/HEAD/templates/assets/img/favicons/mstile-150x150.png -------------------------------------------------------------------------------- /templates/assets/img/favicons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AirboZH/halo-theme-chirpy/HEAD/templates/assets/img/favicons/apple-touch-icon.png -------------------------------------------------------------------------------- /src/js/modules/layouts/topbar.js: -------------------------------------------------------------------------------- 1 | import { displaySearch } from '../components/search-display'; 2 | 3 | export function initTopbar() { 4 | displaySearch(); 5 | } 6 | -------------------------------------------------------------------------------- /templates/assets/img/favicons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AirboZH/halo-theme-chirpy/HEAD/templates/assets/img/favicons/android-chrome-192x192.png -------------------------------------------------------------------------------- /templates/assets/img/favicons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AirboZH/halo-theme-chirpy/HEAD/templates/assets/img/favicons/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/js/modules/layouts.js: -------------------------------------------------------------------------------- 1 | export { basic } from './layouts/basic'; 2 | export { initSidebar } from './layouts/sidebar'; 3 | export { initTopbar } from './layouts/topbar'; 4 | -------------------------------------------------------------------------------- /src/_layouts/_includes/comments.html: -------------------------------------------------------------------------------- 1 | 2 | {% if page.comments and site.comments.active %} 3 | {% capture path %}comments/{{ site.comments.active }}.html{% endcapture %} 4 | {% include {{ path }} %} 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /src/js/pwa/unregister.js: -------------------------------------------------------------------------------- 1 | if ('serviceWorker' in navigator) { 2 | navigator.serviceWorker.getRegistrations().then((registrations) => { 3 | for (let reg of registrations) { 4 | reg.unregister(); 5 | } 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /src/_layouts/_includes/embed/twitch.html: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /src/_layouts/_includes/lang.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Detect appearance language and return it through variable "lang" 3 | {% endcomment %} 4 | {% if site.data.locales[site.lang] %} 5 | {% assign lang = site.lang %} 6 | {% else %} 7 | {% assign lang = 'en' %} 8 | {% endif %} 9 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: [ 4 | "eslint:recommended", 5 | "plugin:prettier/recommended" 6 | ], 7 | env: { 8 | node: true, 9 | }, 10 | parserOptions: { 11 | ecmaVersion: 6, 12 | sourceType: "module" 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /src/js/modules/layouts/basic.js: -------------------------------------------------------------------------------- 1 | import { back2top } from '../components/back-to-top'; 2 | import { loadTooptip } from '../components/tooltip-loader'; 3 | import { patch } from '../../patch'; 4 | 5 | export function basic() { 6 | back2top(); 7 | loadTooptip(); 8 | patch.codeClass(); 9 | } 10 | -------------------------------------------------------------------------------- /src/js/modules/layouts/sidebar.js: -------------------------------------------------------------------------------- 1 | import { modeWatcher } from '../components/mode-watcher'; 2 | import { sidebarExpand } from '../components/sidebar'; 3 | import halo from '../halo'; 4 | 5 | export function initSidebar() { 6 | modeWatcher(); 7 | sidebarExpand(); 8 | window.halo = halo; 9 | } 10 | -------------------------------------------------------------------------------- /src/_layouts/_includes/embed/youtube.html: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /templates/assets/404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: "404: Page not found" 4 | permalink: /404.html 5 | 6 | redirect_from: 7 | - /norobots/ 8 | - /assets/ 9 | - /posts/ 10 | --- 11 | 12 | {% include lang.html %} 13 | 14 |
15 |

{{ site.data.locales[lang].not_found.statment }}

16 |
17 | -------------------------------------------------------------------------------- /src/js/modules/components/search-display.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This script make #search-result-wrapper switch to unloaded or shown automatically. 3 | */ 4 | const $btnSearchTrigger = $('#search-trigger'); 5 | 6 | export function displaySearch() { 7 | $btnSearchTrigger.on('click', function () { 8 | SearchWidget.open(); 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /src/css/style.scss: -------------------------------------------------------------------------------- 1 | @import 'jekyll-theme-chirpy'; 2 | 3 | //append your custom style below 4 | 5 | @import "patch"; 6 | 7 | //import third-party css 8 | @import "bootstrap/dist/css/bootstrap.css"; 9 | @import "@fortawesome/fontawesome-free/css/all.css"; 10 | @import "tocbot/dist/tocbot.css"; 11 | @import "magnific-popup/dist/magnific-popup.css"; 12 | -------------------------------------------------------------------------------- /src/js/modules/components/tooltip-loader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Initial Bootstrap Tooltip. 3 | */ 4 | export function loadTooptip() { 5 | const tooltipTriggerList = document.querySelectorAll( 6 | '[data-bs-toggle="tooltip"]' 7 | ); 8 | 9 | [...tooltipTriggerList].map( 10 | (tooltipTriggerEl) => new bootstrap.Tooltip(tooltipTriggerEl) 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/js/modules/plugins.js: -------------------------------------------------------------------------------- 1 | export { categoryCollapse } from './components/category-collapse'; 2 | export { initClipboard } from './components/clipboard'; 3 | export { imgLazy } from './components/img-lazyload'; 4 | export { imgPopup } from './components/img-popup'; 5 | export { initLocaleDatetime } from './components/locale-datetime'; 6 | export { toc } from './components/toc'; 7 | -------------------------------------------------------------------------------- /src/js/patch/index.js: -------------------------------------------------------------------------------- 1 | import {codeClass, codeBlock} from './codeClass'; 2 | import {addClassToTable} from "./table"; 3 | import {activeSidebar} from "./sidebar"; 4 | import {preImg} from "./pre-img"; 5 | 6 | export const patch = { 7 | codeClass: codeClass, 8 | codeBlock: codeBlock, 9 | addTableClass: addClassToTable, 10 | activeSidebar: activeSidebar, 11 | preImg: preImg, 12 | }; 13 | -------------------------------------------------------------------------------- /templates/assets/img/favicons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | --- 2 | layout: compress 3 | --- 4 | 5 | 6 | 7 | 8 | 9 | 10 | #da532c 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 1.x | :white_check_mark: | 11 | ## Reporting a Vulnerability 12 | 13 | https://github.com/AirboZH/halo-theme-chirpy/issues 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | trim_trailing_whitespace = true 8 | # Unix-style newlines with a newline ending every file 9 | end_of_line = lf 10 | insert_final_newline = true 11 | 12 | [*.{js,css,scss}] 13 | quote_type = single 14 | 15 | [*.{yml,yaml}] 16 | quote_type = double 17 | 18 | [*.md] 19 | trim_trailing_whitespace = false 20 | -------------------------------------------------------------------------------- /src/_layouts/_includes/search-results.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 | {% include_cached trending-tags.html %} 7 |
8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /src/js/patch/sidebar.js: -------------------------------------------------------------------------------- 1 | export function activeSidebar() { 2 | const navLinks = document.querySelectorAll('#sidebar .nav-item'); 3 | const { href } = location; 4 | 5 | for (let i = 0; i < navLinks.length; i++) { 6 | const navLink = navLinks[i]; 7 | const navLinkHref = navLink.querySelector('a').href; 8 | 9 | if (navLinkHref === href) { 10 | navLink.classList.add('active'); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/_layouts/_includes/origin-type.html: -------------------------------------------------------------------------------- 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 %} 14 | -------------------------------------------------------------------------------- /src/css/layout/tags.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Styles for Tab Tags 3 | */ 4 | 5 | .tag { 6 | border-radius: 0.7em; 7 | padding: 6px 8px 7px; 8 | margin-right: 0.8rem; 9 | line-height: 3rem; 10 | letter-spacing: 0; 11 | border: 1px solid var(--tag-border) !important; 12 | box-shadow: 0 0 3px 0 var(--tag-shadow); 13 | 14 | span { 15 | margin-left: 0.6em; 16 | font-size: 0.7em; 17 | font-family: Oswald, sans-serif; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | *.local 12 | 13 | # Editor directories and files 14 | .vscode/* 15 | !.vscode/extensions.json 16 | .idea 17 | .DS_Store 18 | *.suo 19 | *.ntvs* 20 | *.njsproj 21 | *.sln 22 | *.sw? 23 | 24 | .gradle 25 | build 26 | gradle 27 | dist/ 28 | /halo-theme-chirpy*.zip 29 | /templates/modules/import.html 30 | -------------------------------------------------------------------------------- /src/js/modules/components/toc.js: -------------------------------------------------------------------------------- 1 | import tocbot from "tocbot"; 2 | 3 | export function toc() { 4 | if (document.querySelector('.content h2')) { 5 | // see: https://github.com/tscanlin/tocbot#usage 6 | tocbot.init({ 7 | tocSelector: '#toc', 8 | contentSelector: '.content', 9 | ignoreSelector: '[data-toc-skip]', 10 | headingSelector: 'h2, h3, h4', 11 | orderedList: false, 12 | scrollSmooth: false 13 | }); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/js/modules/halo.js: -------------------------------------------------------------------------------- 1 | export default { 2 | flipMode: () => { 3 | if (document.querySelector('#comment div div')) { 4 | let commentDOMclass = document 5 | .querySelector('#comment div div') 6 | .shadowRoot.querySelector('.halo-comment-widget').classList; 7 | if (commentDOMclass.contains('light')) 8 | commentDOMclass.replace('light', 'dark'); 9 | else commentDOMclass.replace('dark', 'light'); 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /src/js/modules/components/back-to-top.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Reference: https://bootsnipp.com/snippets/featured/link-to-top-page 3 | */ 4 | 5 | export function back2top() { 6 | const $window = $(window); 7 | const $btn = $('#back-to-top'); 8 | 9 | $window.on('scroll', () => { 10 | if ($window.scrollTop() > 50) { 11 | $btn.fadeIn(); 12 | } else { 13 | $btn.fadeOut(); 14 | } 15 | }); 16 | 17 | $btn.on('click', () => { 18 | $window.scrollTop(0); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /src/_layouts/_includes/toc.html: -------------------------------------------------------------------------------- 1 | {% assign enable_toc = false %} 2 | {% if site.toc and page.toc %} 3 | {% if page.content contains ' 10 |

{{- site.data.locales[include.lang].panel.toc -}}

11 | 12 | 13 | {% endif %} 14 | -------------------------------------------------------------------------------- /src/_layouts/_includes/no-linenos.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Remove the line number of the code snippet. 3 | {% endcomment %} 4 | 5 | {% assign content = include.content %} 6 | 7 | {% if content contains '
' %}
 8 |   {% assign content = content | replace: '
', '' %}
10 | {% endif %}
11 | 


--------------------------------------------------------------------------------
/src/_layouts/_includes/google-analytics.html:
--------------------------------------------------------------------------------
 1 | 
 4 | 
 5 | 
 6 | 
15 | 


--------------------------------------------------------------------------------
/src/js/modules/components/img-popup.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Set up image popup
 3 |  *
 4 |  * See: https://github.com/dimsemenov/Magnific-Popup
 5 |  */
 6 | import {preImg} from "../../patch/pre-img";
 7 | 
 8 | export function imgPopup() {
 9 |   preImg();
10 | 
11 |   if ($(".popup").length <= 0) {
12 |     return;
13 |   }
14 | 
15 |   $('.popup').magnificPopup({
16 |     type: 'image',
17 |     closeOnContentClick: true,
18 |     showCloseBtn: false,
19 |     zoom: {
20 |       enabled: true,
21 |       duration: 300,
22 |       easing: 'ease-in-out'
23 |     }
24 |   });
25 | }
26 | 


--------------------------------------------------------------------------------
/src/css/jekyll-theme-chirpy.scss:
--------------------------------------------------------------------------------
 1 | /*!
 2 |  * Chirpy v6.1.0 (https://github.com/cotes2020/jekyll-theme-chirpy)
 3 |  * © 2019 Cotes Chung
 4 |  * MIT Licensed
 5 |  */
 6 | 
 7 | @import 'colors/typography-light';
 8 | @import 'colors/typography-dark';
 9 | @import 'addon/variables';
10 | @import 'variables-hook';
11 | @import 'addon/module';
12 | @import 'addon/syntax';
13 | @import 'addon/commons';
14 | @import 'layout/home';
15 | @import 'layout/post';
16 | @import 'layout/tags';
17 | @import 'layout/archives';
18 | @import 'layout/categories';
19 | @import 'layout/category-tag';
20 | 


--------------------------------------------------------------------------------
/src/_data/authors.yml:
--------------------------------------------------------------------------------
 1 | ## Template › https://github.com/jekyll/jekyll-seo-tag/blob/master/docs/advanced-usage.md#setting-author-url
 2 | # -------------------------------------
 3 | # {author_id}:
 4 | #   name: {full name}
 5 | #   twitter: {twitter_of_author}
 6 | #   url: {homepage_of_author}
 7 | # -------------------------------------
 8 | 
 9 | cotes:
10 |   name: Cotes Chung
11 |   twitter: cotes2020
12 |   url: https://github.com/cotes2020/
13 | 
14 | sille_bille:
15 |   name: Dinesh Prasanth Moluguwan Krishnamoorthy
16 |   twitter: dinesh_MKD
17 |   url: https://github.com/SilleBille/
18 | 


--------------------------------------------------------------------------------
/src/js/patch/table.js:
--------------------------------------------------------------------------------
 1 | export function addClassToTable() {
 2 |   // 获取所有 content 下的 table 元素
 3 |   const tables = document.querySelectorAll('.content table');
 4 | 
 5 |   // 遍历所有 table 元素
 6 |   tables.forEach((table) => {
 7 |     // 创建一个 div 元素
 8 |     const wrapper = document.createElement('div');
 9 |     // 添加 class 属性
10 |     wrapper.classList.add('table-wrapper');
11 |     // 添加 text-align: cneter
12 |     wrapper.style.textAlign = 'center';
13 |     // 将 table 元素包裹在 div 元素内
14 |     table.parentNode.insertBefore(wrapper, table);
15 |     wrapper.appendChild(table);
16 |   });
17 | }
18 | 


--------------------------------------------------------------------------------
/src/js/modules/components/mode-watcher.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Add listener for theme mode toggle
 3 |  */
 4 | const $toggleElem = $('.mode-toggle');
 5 | 
 6 | export function modeWatcher() {
 7 |   if ($toggleElem.length === 0) {
 8 |     return;
 9 |   }
10 | 
11 |   $toggleElem.off().on('click', (e) => {
12 |     const $target = $(e.target);
13 |     let $btn =
14 |       $target.prop('tagName') === 'button'.toUpperCase()
15 |         ? $target
16 |         : $target.parent();
17 | 
18 |     modeToggle.flipMode(); // modeToggle: `_includes/mode-toggle.html`
19 |     $btn.trigger('blur'); // remove the clicking outline
20 |   });
21 | }
22 | 


--------------------------------------------------------------------------------
/src/_layouts/tags.html:
--------------------------------------------------------------------------------
 1 | ---
 2 | layout: page
 3 | # All the Tags of posts.
 4 | ---
 5 | 
 6 | 
7 | {% assign tags = '' | split: '' %} 8 | {% for t in site.tags %} 9 | {% assign tags = tags | push: t[0] %} 10 | {% endfor %} 11 | 12 | {% assign sorted_tags = tags | sort_natural %} 13 | 14 | {% for t in sorted_tags %} 15 |
16 | 17 | {{ t -}} 18 | {{ site.tags[t].size }} 19 | 20 |
21 | {% endfor %} 22 |
23 | -------------------------------------------------------------------------------- /templates/modules/widgets/update-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |

[[#{panel.recently_updated}]]

6 | 14 |
15 | 16 | -------------------------------------------------------------------------------- /src/js/modules/components/img-lazyload.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Set up image lazy-load 3 | */ 4 | 5 | function stopShimmer($node) { 6 | $node.parent().removeClass('shimmer'); 7 | } 8 | 9 | export function imgLazy() { 10 | const $images = $('main img[data-src]'); 11 | 12 | if ($images.length <= 0) { 13 | return; 14 | } 15 | 16 | /* Stop shimmer when image loaded */ 17 | document.addEventListener('lazyloaded', function (e) { 18 | stopShimmer($(e.target)); 19 | }); 20 | 21 | /* Stop shimmer from cached images */ 22 | $images.each(function () { 23 | if ($(this).hasClass('ls-is-cached')) { 24 | stopShimmer($(this)); 25 | } 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /src/js/modules/components/sidebar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Expand or close the sidebar in mobile screens. 3 | */ 4 | 5 | const $body = $('body'); 6 | const ATTR_DISPLAY = 'sidebar-display'; 7 | 8 | class SidebarUtil { 9 | static isExpanded = false; 10 | 11 | static toggle() { 12 | if (SidebarUtil.isExpanded === false) { 13 | $body.attr(ATTR_DISPLAY, ''); 14 | } else { 15 | $body.removeAttr(ATTR_DISPLAY); 16 | } 17 | 18 | SidebarUtil.isExpanded = !SidebarUtil.isExpanded; 19 | } 20 | } 21 | 22 | export function sidebarExpand() { 23 | $('#sidebar-trigger').on('click', SidebarUtil.toggle); 24 | $('#mask').on('click', SidebarUtil.toggle); 25 | } 26 | -------------------------------------------------------------------------------- /src/_layouts/_includes/datetime.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | {% assign df_strftime = site.data.locales[include.lang].df.post.strftime | default: '%d/%m/%Y' %} 7 | {% assign df_dayjs = site.data.locales[include.lang].df.post.dayjs | default: 'DD/MM/YYYY' %} 8 | 9 | 21 | -------------------------------------------------------------------------------- /templates/modules/widgets/trending-tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |

[[#{panel.trending_tags}]]

6 |
10 | 11 | 16 | 17 |
18 |
19 | 20 | -------------------------------------------------------------------------------- /src/_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {% capture _content %} 6 | {% if layout.refactor or page.layout == 'page' %} 7 | {% include refactor-content.html content=content lang=lang %} 8 | {% else %} 9 | {{ content }} 10 | {% endif %} 11 | {% endcapture %} 12 | 13 |
14 | {% if page.layout == 'page' or page.collection == 'tabs' %} 15 | {% assign tab_key = page.title | downcase %} 16 | {% assign title = site.data.locales[lang].tabs[tab_key] | default: page.title %} 17 |

18 | {{ title }} 19 |

20 |
21 | {{ _content }} 22 |
23 | {% else %} 24 | {{ _content }} 25 | {% endif %} 26 |
27 | -------------------------------------------------------------------------------- /src/_layouts/tag.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | # The layout for Tag page 4 | --- 5 | 6 | {% include lang.html %} 7 | 8 |
9 |

10 | 11 | {{ page.title }} 12 | {{ page.posts | size }} 13 |

14 |
    15 | {% for post in page.posts %} 16 |
  • 17 | {{ post.title }} 18 | 19 | {% include datetime.html date=post.date class='text-muted small text-nowrap' lang=lang %} 20 |
  • 21 | {% endfor %} 22 |
23 |
24 | -------------------------------------------------------------------------------- /templates/assets/img/favicons/site.webmanifest: -------------------------------------------------------------------------------- 1 | --- 2 | layout: compress 3 | --- 4 | 5 | {% assign favicon_path = "/assets/img/favicons" | relative_url %} 6 | 7 | { 8 | "name": "{{ site.title }}", 9 | "short_name": "{{ site.title }}", 10 | "description": "{{ site.description }}", 11 | "icons": [ 12 | { 13 | "src": "{{ favicon_path }}/android-chrome-192x192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "{{ favicon_path }}/android-chrome-512x512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }], 22 | "start_url": "{{ '/index.html' | relative_url }}", 23 | "theme_color": "#2a1e6b", 24 | "background_color": "#ffffff", 25 | "display": "fullscreen" 26 | } 27 | -------------------------------------------------------------------------------- /src/_layouts/_includes/notification.html: -------------------------------------------------------------------------------- 1 | 25 | -------------------------------------------------------------------------------- /src/_layouts/category.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | # The Category layout 4 | --- 5 | 6 | {% include lang.html %} 7 | 8 |
9 |

10 | 11 | {{ page.title }} 12 | {{ page.posts | size }} 13 |

14 | 15 |
    16 | {% for post in page.posts %} 17 |
  • 18 | {{ post.title }} 19 | 20 | {% include datetime.html date=post.date class='text-muted small text-nowrap' lang=lang %} 21 |
  • 22 | {% endfor %} 23 |
24 |
25 | -------------------------------------------------------------------------------- /annotation-setting.yaml: -------------------------------------------------------------------------------- 1 | # nonk8s 2 | apiVersion: v1alpha1 3 | kind: AnnotationSetting 4 | metadata: 5 | generateName: annotation-setting-chirpy 6 | spec: 7 | targetRef: 8 | group: "" 9 | kind: MenuItem 10 | formSchema: 11 | - $formkit: "text" 12 | name: "icon" 13 | label: "图标" 14 | 15 | #--- 16 | # 17 | #apiVersion: v1alpha1 18 | #kind: AnnotationSetting 19 | #metadata: 20 | # generateName: annotation-setting- 21 | #spec: 22 | # targetRef: 23 | # group: content.halo.run 24 | # kind: Post 25 | # formSchema: 26 | # - $formkit: "radio" 27 | # name: "showInIndex" 28 | # label: "在首页显示" 29 | # value: "show" 30 | # options: 31 | # - label: 显示 32 | # value: "show" 33 | # - label: 不显示 34 | # value: "hide" 35 | -------------------------------------------------------------------------------- /theme.yaml: -------------------------------------------------------------------------------- 1 | # nonk8s 2 | apiVersion: theme.halo.run/v1alpha1 3 | kind: Theme 4 | metadata: 5 | name: halo-theme-chirpy 6 | annotations: 7 | # Add supports for Halo App Store 8 | # https://halo.run/store/apps/app-vGuQB 9 | "store.halo.run/app-id": "app-vGuQB" 10 | spec: 11 | displayName: Chirpy 12 | author: 13 | name: AirboZH 14 | website: https://airbozh.cn 15 | description: A minimal, responsive and feature-rich Halo theme for technical writing. 16 | logo: https://chirpy-img.netlify.app/commons/avatar.jpg 17 | website: https://github.com/AirboZH/halo-theme-chirpy 18 | repo: https://github.com/AirboZH/halo-theme-chirpy.git 19 | settingName: "halo-theme-chirpy-setting" 20 | configMapName: "halo-theme-chirpy-configMap" 21 | version: 1.4.9 22 | require: ">=2.0.0" 23 | -------------------------------------------------------------------------------- /src/_data/share.yml: -------------------------------------------------------------------------------- 1 | # Sharing options at the bottom of the post. 2 | # Icons from 3 | 4 | platforms: 5 | - type: Twitter 6 | icon: "fab fa-twitter" 7 | link: "https://twitter.com/intent/tweet?text=TITLE&url=URL" 8 | 9 | - type: Facebook 10 | icon: "fab fa-facebook-square" 11 | link: "https://www.facebook.com/sharer/sharer.php?title=TITLE&u=URL" 12 | 13 | - type: Telegram 14 | icon: "fab fa-telegram" 15 | link: "https://t.me/share/url?url=URL&text=TITLE" 16 | 17 | # Uncomment below if you need to. 18 | # 19 | # - type: Linkedin 20 | # icon: "fab fa-linkedin" 21 | # link: "https://www.linkedin.com/sharing/share-offsite/?url=URL" 22 | # 23 | # - type: Weibo 24 | # icon: "fab fa-weibo" 25 | # link: "http://service.weibo.com/share/share.php?title=TITLE&url=URL" 26 | -------------------------------------------------------------------------------- /src/css/patch/commons.scss: -------------------------------------------------------------------------------- 1 | #sidebar { 2 | #avatar { 3 | font-size: 50px; 4 | text-align: center; 5 | display: flex; 6 | justify-content: center; 7 | align-items: center; 8 | 9 | p { 10 | margin: auto; 11 | } 12 | } 13 | } 14 | .access-sticky { 15 | position: -webkit-sticky; 16 | position: sticky; 17 | top: 4rem; 18 | } 19 | .access-links { 20 | padding-left: 1rem; 21 | border-left: 1px solid var(--main-border-color); 22 | 23 | ul { 24 | padding-left: 0; 25 | 26 | li { 27 | margin-bottom: 8px; 28 | list-style: none; 29 | 30 | a { 31 | color: inherit; 32 | } 33 | 34 | a:hover { 35 | @extend %link-hover; 36 | } 37 | } 38 | } 39 | } 40 | 41 | #comment { 42 | margin: 2rem 0; 43 | } 44 | 45 | .content p img { 46 | @extend %rounded; 47 | } 48 | -------------------------------------------------------------------------------- /src/css/patch/links.scss: -------------------------------------------------------------------------------- 1 | .page-links-item { 2 | position: relative; 3 | display: flex; 4 | flex-direction: row; 5 | min-width: 0; 6 | height: var(--bs-card-height); 7 | color: var(--bs-body-color); 8 | word-wrap: break-word; 9 | background-color: var(--bs-card-bg); 10 | background-clip: border-box; 11 | border: var(--bs-card-border-width) solid var(--bs-card-border-color); 12 | border-radius: 10px; 13 | } 14 | 15 | .page-links-img { 16 | width: 50px; 17 | height: 50px; 18 | border-radius: 10px; 19 | } 20 | 21 | .page-links-content { 22 | display: -webkit-box; 23 | -webkit-box-orient: vertical; 24 | -webkit-line-clamp: 2; 25 | overflow: hidden; 26 | 27 | span { 28 | display: -webkit-box; 29 | -webkit-box-orient: vertical; 30 | -webkit-line-clamp: 1; 31 | overflow: hidden; 32 | text-overflow: ellipsis; 33 | } 34 | } -------------------------------------------------------------------------------- /src/_layouts/_includes/jsdelivr-combine.html: -------------------------------------------------------------------------------- 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 | 19 | {% else %} 20 | 21 | {% endif %} 22 | {% endfor %} 23 | 24 | {% if combined_urls %} 25 | 26 | {% endif %} 27 | -------------------------------------------------------------------------------- /templates/error/error.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 首页 10 | 11 | [[${error.status} + ': ' + ${#strings.defaultString(error.title, 13 | 'Internal server error')}]] 15 | 16 | 17 |
18 |

19 | Sorry, we have a slight error, please try again later. 20 |
21 | Click here to back home. 22 |

23 |
24 |
25 | 26 | -------------------------------------------------------------------------------- /templates/page.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | [[#{breadcrumb.home}]] 10 | 11 | [[${singlePage.spec.title}]] 12 | 13 | 14 | 15 |

[[${singlePage.spec.title}]]

16 |
17 | 18 |
19 |
20 | 25 |
26 |
27 | 28 | -------------------------------------------------------------------------------- /i18n/en.properties: -------------------------------------------------------------------------------- 1 | breadcrumb.home=Home 2 | breadcrumb.archive=Archives 3 | breadcrumb.tags=Tags 4 | breadcrumb.categories=Categories 5 | date.recently=recently 6 | data.yesterday=yesterday 7 | date.days_ago=\u0020days ago 8 | panel.recently_updated=Recently Updated 9 | panel.trending_tags=Trending Tags 10 | panel.site_info=Site Info 11 | footer.right=Some rights reserved. 12 | footer.using=Using the 13 | footer.theme=theme 14 | related_posts.further_reading=Further Reading 15 | related_posts.older=OLDER 16 | related_posts.newer=NEWER 17 | post_sharing.share=Share 18 | words_count.words=words 19 | words_count.min=min 20 | words_count.read=read 21 | post.posted=Posted 22 | post.updated=Updated 23 | post.by=By 24 | post.license=License 25 | post.button.copy_link.succeed=Link copied successfully! 26 | top_bar.search=Search 27 | top_bar.need_search_plugin=You need to install the search plugin first. 28 | cancel=Cancel 29 | panel.contents=Contents 30 | -------------------------------------------------------------------------------- /src/_data/contact.yml: -------------------------------------------------------------------------------- 1 | # The contact options. 2 | 3 | - type: github 4 | icon: "fab fa-github" 5 | 6 | - type: twitter 7 | icon: "fab fa-twitter" 8 | 9 | - type: email 10 | icon: "fas fa-envelope" 11 | noblank: true # open link in current tab 12 | 13 | - type: rss 14 | icon: "fas fa-rss" 15 | noblank: true 16 | # Uncomment and complete the url below to enable more contact options 17 | # 18 | # - type: mastodon 19 | # icon: 'fab fa-mastodon' # icons powered by 20 | # url: '' # Fill with your Mastodon account page, rel="me" will be applied for verification 21 | # 22 | # - type: linkedin 23 | # icon: 'fab fa-linkedin' # icons powered by 24 | # url: '' # Fill with your Linkedin homepage 25 | # 26 | # - type: stack-overflow 27 | # icon: 'fab fa-stack-overflow' 28 | # url: '' # Fill with your stackoverflow homepage 29 | -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | # Set to true to add reviewers to pull requests 2 | addReviewers: true 3 | 4 | # Set to true to add assignees to pull requests 5 | addAssignees: false 6 | 7 | # A list of reviewers to be added to pull requests (GitHub user name) 8 | reviewers: 9 | - AirboZH 10 | 11 | # A number of reviewers added to the pull request 12 | # Set 0 to add all the reviewers (default: 0) 13 | numberOfReviewers: 0 14 | 15 | # A list of assignees, overrides reviewers if set 16 | # assignees: 17 | # - assigneeA 18 | 19 | # A number of assignees to add to the pull request 20 | # Set to 0 to add all of the assignees. 21 | # Uses numberOfReviewers if unset. 22 | # numberOfAssignees: 2 23 | 24 | # A list of keywords to be skipped the process that add reviewers if pull requests include it 25 | skipKeywords: 26 | - wip 27 | 28 | # A list of users to be skipped by both the add reviewers and add assignees processes 29 | # skipUsers: 30 | # - dependabot[bot] 31 | -------------------------------------------------------------------------------- /mode.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | const mode = process.env.NODE_ENV || 'dev'; 4 | 5 | const preHTML = ` 6 | 7 | ` 8 | 9 | const postHTML = ` 10 | `; 11 | 12 | const productionImport = ` 13 | 17 | 21 | ` 22 | 23 | const developmentImport = ` 24 | 28 | ` 29 | 30 | const outHTML = preHTML + (mode === 'prod' ? productionImport : developmentImport) + postHTML 31 | 32 | fs.writeFileSync('templates/modules/import.html', outHTML) 33 | -------------------------------------------------------------------------------- /templates/modules/panel.html: -------------------------------------------------------------------------------- 1 | 2 | 7 |
8 | 9 | 10 |
11 |
12 | 13 |
14 |

[[#{panel.contents}]]

15 | 16 |
17 |
18 | 27 |
28 | 29 | -------------------------------------------------------------------------------- /src/js/patch/pre-img.js: -------------------------------------------------------------------------------- 1 | export function preImg() { 2 | const imgSelector = '.content p img'; 3 | const images = document.querySelectorAll(imgSelector); 4 | images.forEach((img) => { 5 | let anchorElement = document.createElement('a') 6 | let divElement = document.createElement('div') 7 | anchorElement.setAttribute('href', img.getAttribute('src')); 8 | anchorElement.classList.add('popup'); 9 | anchorElement.classList.add('img-link') 10 | setWidth(img, anchorElement) 11 | 12 | img.parentNode.insertBefore(divElement, img); 13 | divElement.appendChild(anchorElement); 14 | anchorElement.appendChild(img); 15 | }) 16 | } 17 | 18 | const setWidth = (img, anchorElement) => { 19 | if (img.getAttribute('width')) 20 | anchorElement.style.width = img.getAttribute('width') 21 | if (img.getAttribute('height')) 22 | anchorElement.style.height = img.getAttribute('height') 23 | img.removeAttribute('width') 24 | img.removeAttribute('height') 25 | } 26 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery' 2 | window.jQuery = $ 3 | window.$ = $ 4 | import 'bootstrap'; 5 | window.bootstrap = bootstrap 6 | import 'magnific-popup'; 7 | import 'tocbot'; 8 | import './css/style.scss'; 9 | 10 | import {basic} from "./js/modules/layouts/basic"; 11 | import {initSidebar} from "./js/modules/layouts/sidebar"; 12 | import {initTopbar} from "./js/modules/layouts/topbar"; 13 | import {categoryCollapse} from "./js/modules/components/category-collapse"; 14 | import {imgLazy} from "./js/modules/components/img-lazyload"; 15 | import {toc} from "./js/modules/components/toc"; 16 | import {imgPopup, initClipboard} from "./js/modules/plugins"; 17 | // 因为 patch/index 中有内容且没有引用, 所有没有在 index 中引入 18 | import { patch } from "./js/patch/"; 19 | 20 | basic(); 21 | initSidebar(); 22 | initTopbar(); 23 | patch.codeClass(); 24 | patch.codeBlock(); 25 | patch.addTableClass(); 26 | patch.activeSidebar(); 27 | categoryCollapse(); 28 | imgLazy(); 29 | imgPopup(); 30 | initClipboard(); 31 | toc(); 32 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard-scss", "stylelint-config-prettier-scss"], 3 | "rules": { 4 | "no-descending-specificity": null, 5 | "shorthand-property-no-redundant-values": null, 6 | "at-rule-no-vendor-prefix": null, 7 | "property-no-vendor-prefix": null, 8 | "selector-no-vendor-prefix": null, 9 | "value-no-vendor-prefix": null, 10 | "color-function-notation": "legacy", 11 | "alpha-value-notation": "number", 12 | "selector-not-notation": "simple", 13 | "color-hex-length": "long", 14 | "declaration-block-single-line-max-declarations": 3, 15 | "scss/operator-no-newline-after": null, 16 | "rule-empty-line-before": [ 17 | "always", 18 | { "ignore": ["after-comment", "first-nested", "inside-block"] } 19 | ], 20 | "value-keyword-case": ["lower", { "ignoreProperties": ["/^\\$/"] }], 21 | "media-feature-range-notation": "prefix", 22 | "declaration-block-no-duplicate-properties":true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/css/addon/variables.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * The SCSS variables 3 | */ 4 | 5 | /* sidebar */ 6 | 7 | $sidebar-width: 260px !default; /* the basic width */ 8 | $sidebar-width-large: 300px !default; /* screen width: >= 1650px */ 9 | 10 | /* other framework sizes */ 11 | 12 | $topbar-height: 3rem !default; 13 | $search-max-width: 200px !default; 14 | $footer-height: 5rem !default; 15 | $footer-height-large: 6rem !default; /* screen width: < 850px */ 16 | $main-content-max-width: 1250px !default; 17 | $bottom-min-height: 35rem !default; 18 | $base-radius: 0.5rem !default; 19 | $back2top-size: 2.75rem !default; 20 | 21 | /* syntax highlight */ 22 | 23 | $code-font-size: 0.85rem !default; 24 | $code-header-height: 2.25rem !default; 25 | $code-dot-size: 0.75rem !default; 26 | $code-dot-gap: 0.5rem !default; 27 | $code-icon-width: 1.75rem !default; 28 | 29 | /* fonts */ 30 | 31 | $font-family-base: 'Source Sans Pro', 'Microsoft Yahei', sans-serif !default; 32 | $font-family-heading: Lato, 'Microsoft Yahei', sans-serif !default; 33 | -------------------------------------------------------------------------------- /src/_layouts/_includes/favicons.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | {% capture favicon_path %}{{ '/assets/img/favicons' | relative_url }}{% endcapture %} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /templates/tags.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | [[#{breadcrumb.home}]] 10 | 11 | [[#{breadcrumb.tags}]] 12 | 13 | 14 | 15 |

[[#{breadcrumb.tags}]]

16 | 30 |
31 | 32 | -------------------------------------------------------------------------------- /templates/modules/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
8 |

9 | [['©' + ${#dates.format(new java.util.Date().getTime(), 'yyyy')}]] 10 | [[${site.title}]]. 11 | 12 | 17 | [[#{footer.right}]] 18 | 19 |

20 |

21 | [[#{footer.using}]] 22 | Halo 23 | [[#{footer.theme}]] 24 | Chirpy 30 |

31 |
32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 AirboZH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/_layouts/_includes/post-nav.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 35 | -------------------------------------------------------------------------------- /i18n/default.properties: -------------------------------------------------------------------------------- 1 | breadcrumb.home=\u4e3b\u9875 2 | breadcrumb.archive=\u5f52\u6863 3 | breadcrumb.tags=\u6807\u7b7e 4 | breadcrumb.categories=\u5206\u7c7b 5 | date.recently=\u6700\u8fd1 6 | date.yesterday=\u6628\u5929 7 | date.days_ago=\u5929\u524d 8 | panel.recently_updated=\u6700\u8fd1\u66f4\u65b0 9 | panel.trending_tags=\u70ed\u95e8\u6807\u7b7e 10 | panel.site_info=\u7ad9\u70b9\u4fe1\u606f 11 | footer.right=\u4fdd\u7559\u90e8\u5206\u6743\u5229\u3002 12 | footer.using=\u4f7f\u7528 13 | footer.theme=\u4e3b\u9898 14 | related_posts.further_reading=\u76f8\u5173\u6587\u7ae0 15 | related_posts.older=\u4e0b\u4e00\u7bc7 16 | related_posts.newer=\u4e0a\u4e00\u7bc7 17 | post_sharing.share=\u5206\u4eab 18 | words_count.words=\u5b57 19 | words_count.min=\u5206\u949f 20 | words_count.read=\u9605\u8bfb 21 | post.posted=\u53d1\u8868\u4e8e 22 | post.updated=\u66f4\u65b0\u4e8e 23 | post.by=\u4f5c\u8005 24 | post.license=\u8bb8\u53ef\u534f\u8bae 25 | post.button.copy_link.succeeded=\u590d\u5236\u6210\u529f 26 | top_bar.search=\u641c\u7d22 27 | top_bar.need_search_plugin=\u9700\u8981\u5b89\u88c5\u641c\u7d22\u63d2\u4ef6 28 | cancel=\u53d6\u6d88 29 | panel.contents=\u76ee\u5f55 30 | -------------------------------------------------------------------------------- /src/_layouts/_includes/read-time.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% assign words = include.content | strip_html | number_of_words: 'auto' %} 4 | 5 | 6 | 7 | {% assign wpm = 180 %} 8 | {% assign min_time = 1 %} 9 | 10 | {% assign read_time = words | divided_by: wpm %} 11 | 12 | {% unless read_time > 0 %} 13 | {% assign read_time = min_time %} 14 | {% endunless %} 15 | 16 | {% capture read_prompt %} 17 | {{- site.data.locales[include.lang].post.read_time.prompt -}} 18 | {% endcapture %} 19 | 20 | 21 | 27 | 28 | {{- read_time -}} 29 | {{ ' ' }} 30 | {{- site.data.locales[include.lang].post.read_time.unit -}} 31 | 32 | {%- if include.prompt -%} 33 | {%- assign _prompt_words = read_prompt | number_of_words: 'auto' -%} 34 | {%- unless _prompt_words > 1 -%}{{ ' ' }}{%- endunless -%} 35 | {{ read_prompt }} 36 | {%- endif -%} 37 | 38 | -------------------------------------------------------------------------------- /export-zip.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const archiver = require('archiver'); 3 | 4 | const homedir = __dirname; 5 | const mode = process.env.NODE_ENV || 'dev'; 6 | 7 | //const timeString = new Date().toLocaleDateString().replace(/\//g, '-'); // 日期充当hash值防止覆盖之前的压缩包 8 | 9 | const outputName = mode === 'prod' ? 'halo-theme-chirpy.zip' : 'halo-theme-chirpy-dev.zip'; 10 | const output = fs.createWriteStream(homedir + '/' + outputName); 11 | const archive = archiver('zip', { 12 | zlib: {level: 9} // 设置压缩级别 13 | }); 14 | 15 | archive.on('error', function (err) { 16 | throw err; 17 | }); 18 | 19 | output.on('close', function () { 20 | console.log(` 21 | --------- ---------压缩完毕--------- --------- 22 | ${homedir}\\${outputName} - ${(archive.pointer() / 1024 / 1024).toFixed(1)}MB 23 | --------- -------------------------- --------- 24 | `); 25 | }); 26 | 27 | archive.pipe(output); 28 | archive.directory('i18n/', true); 29 | archive.directory('templates/', true); 30 | archive.file('settings.yaml', {name: 'settings.yaml'}); 31 | archive.file('annotation-setting.yaml', {name: 'annotation-setting.yaml'}); 32 | archive.file('theme.yaml', {name: 'theme.yaml'}); 33 | archive.finalize(); 34 | -------------------------------------------------------------------------------- /src/js/modules/components/category-collapse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tab 'Categories' expand/close effect. 3 | */ 4 | const childPrefix = 'l_'; 5 | const parentPrefix = 'h_'; 6 | const collapse = $('.collapse'); 7 | 8 | export function categoryCollapse() { 9 | /* close up top-category */ 10 | collapse.on('hide.bs.collapse', function () { 11 | /* Bootstrap collapse events. */ const parentId = 12 | parentPrefix + $(this).attr('id').substring(childPrefix.length); 13 | if (parentId) { 14 | $(`#${parentId} .far.fa-folder-open`).attr( 15 | 'class', 16 | 'far fa-folder fa-fw' 17 | ); 18 | $(`#${parentId} i.fas`).addClass('rotate'); 19 | $(`#${parentId}`).removeClass('hide-border-bottom'); 20 | } 21 | }); 22 | 23 | /* expand the top category */ 24 | collapse.on('show.bs.collapse', function () { 25 | const parentId = 26 | parentPrefix + $(this).attr('id').substring(childPrefix.length); 27 | if (parentId) { 28 | $(`#${parentId} .far.fa-folder`).attr( 29 | 'class', 30 | 'far fa-folder-open fa-fw' 31 | ); 32 | $(`#${parentId} i.fas`).removeClass('rotate'); 33 | $(`#${parentId}`).addClass('hide-border-bottom'); 34 | } 35 | }); 36 | } 37 | -------------------------------------------------------------------------------- /templates/modules/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 15 | 16 | 20 | 24 | 25 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/_layouts/archives.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | # The Archives of posts. 4 | --- 5 | 6 | {% include lang.html %} 7 | 8 | {% assign df_strftime_m = site.data.locales[lang].df.archives.strftime | default: '/ %m' %} 9 | {% assign df_dayjs_m = site.data.locales[lang].df.archives.dayjs | default: '/ MM' %} 10 | 11 |
12 | {% for post in site.posts %} 13 | {% assign cur_year = post.date | date: '%Y' %} 14 | 15 | {% if cur_year != last_year %} 16 | {% unless forloop.first %}{% endunless %} 17 | 18 | 19 | {{ '
    ' }} 20 | 21 | {% assign last_year = cur_year %} 22 | {% endif %} 23 | 24 |
  • 25 | {% assign ts = post.date | date: '%s' %} 26 | {{ post.date | date: '%d' }} 27 | 28 | {{ post.date | date: df_strftime_m }} 29 | 30 | {{ post.title }} 31 |
  • 32 | 33 | {% if forloop.last %}
{% endif %} 34 | {% endfor %} 35 |
36 | -------------------------------------------------------------------------------- /templates/archives.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | [[#{breadcrumb.home}]] 10 | 11 | [[#{breadcrumb.archive}]] 12 | 13 |
14 | 15 |
[[${archive.year}]]
16 |
    17 | 18 |
  • 19 | [[${#dates.format(post.spec.publishTime,'dd')}]] 22 | [[${#dates.format(post.spec.publishTime,'MM月')}]] 25 | [[${post.spec.title}]] 26 |
  • 27 |
    28 |
29 |
30 |
31 | 32 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vite'; 2 | import {fileURLToPath} from 'url'; 3 | import inject from '@rollup/plugin-inject'; 4 | 5 | import path from 'path'; 6 | 7 | export default defineConfig({ 8 | root: 'src', 9 | base: '/themes/halo-theme-chirpy/assets/dist/', 10 | build: { 11 | outDir: fileURLToPath(new URL('./templates/assets/dist/', import.meta.url)), 12 | emptyOutDir: true, 13 | minify: true, 14 | cssMinify: true, 15 | rollupOptions: { 16 | input: path.resolve(__dirname, 'src/main.js'), 17 | output: { 18 | entryFileNames: `[name].js`, 19 | assetFileNames: '[name][extname]', 20 | chunkFileNames: `[name].[hash].js`, 21 | manualChunks: { 22 | bootstrap: ['bootstrap'], 23 | jquery: ['jquery'], 24 | magnific_popup: ['magnific-popup'], 25 | tocbot: ['tocbot'], 26 | } 27 | } 28 | }, 29 | sourcemap: true 30 | }, 31 | plugins: [ 32 | inject({ 33 | $: 'jquery', 34 | jQuery: 'jquery', 35 | bootstrap: ['bootstrap', '*'] 36 | }) 37 | ], 38 | optimizeDeps: { 39 | include: ['jquery', 'bootstrap'] 40 | }, 41 | server: { 42 | origin: 'http://localhost:5173' 43 | } 44 | }); 45 | -------------------------------------------------------------------------------- /src/_layouts/_includes/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
10 |

11 | {{ '©' }} 12 | 13 | {{ site.social.name }}. 14 | {% if site.data.locales[include.lang].copyright.brief %} 15 | 20 | {{- site.data.locales[include.lang].copyright.brief -}} 21 | 22 | {% endif %} 23 |

24 | 25 |

26 | {%- capture _platform -%} 27 | Jekyll 28 | {%- endcapture -%} 29 | 30 | {%- capture _theme -%} 31 | Chirpy 32 | {%- endcapture -%} 33 | 34 | {{ site.data.locales[include.lang].meta | replace: ':PLATFORM', _platform | replace: ':THEME', _theme }} 35 |

36 |
37 | -------------------------------------------------------------------------------- /src/_data/origin/basic.yml: -------------------------------------------------------------------------------- 1 | # fonts 2 | 3 | webfonts: /assets/lib/fonts/main.css 4 | 5 | # Libraries 6 | 7 | jquery: 8 | js: /assets/lib/jquery/jquery.min.js 9 | 10 | bootstrap: 11 | css: /assets/lib/bootstrap/bootstrap.min.css 12 | js: /assets/lib/bootstrap/bootstrap.bundle.min.js 13 | 14 | toc: 15 | css: /assets/lib/tocbot/tocbot.min.css 16 | js: /assets/lib/tocbot/tocbot.min.js 17 | 18 | fontawesome: 19 | css: /assets/lib/fontawesome-free/css/all.min.css 20 | 21 | search: 22 | js: /assets/lib/simple-jekyll-search/simple-jekyll-search.min.js 23 | 24 | mermaid: 25 | js: /assets/lib/mermaid/mermaid.min.js 26 | 27 | dayjs: 28 | js: 29 | common: /assets/lib/dayjs/dayjs.min.js 30 | locale: /assets/lib/dayjs/locale/en.min.js 31 | relativeTime: /assets/lib/dayjs/plugin/relativeTime.min.js 32 | localizedFormat: /assets/lib/dayjs/plugin/localizedFormat.min.js 33 | 34 | magnific-popup: 35 | css: /assets/lib/magnific-popup/magnific-popup.css 36 | js: /assets/lib/magnific-popup/jquery.magnific-popup.min.js 37 | 38 | lazysizes: 39 | js: /assets/lib/lazysizes/lazysizes.min.js 40 | 41 | clipboard: 42 | js: /assets/lib/clipboard/clipboard.min.js 43 | 44 | polyfill: 45 | js: /assets/lib/polyfill-v3-es6/polyfill.min.js 46 | 47 | mathjax: 48 | js: /assets/lib/mathjax/tex-chtml.js 49 | -------------------------------------------------------------------------------- /templates/links.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | [[#{breadcrumb.home}]] 8 | 9 | 友情链接 10 | 11 | 12 | 13 |

友情链接

14 | 30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /src/css/layout/category-tag.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Style for page Category and Tag 3 | */ 4 | 5 | .dash { 6 | margin: 0 0.5rem 0.6rem 0.5rem; 7 | border-bottom: 2px dotted var(--dash-color); 8 | } 9 | 10 | #page-category, 11 | #page-tag { 12 | ul > li { 13 | line-height: 1.5rem; 14 | padding: 0.6rem 0; 15 | 16 | /* dot */ 17 | &::before { 18 | background: #999999; 19 | width: 5px; 20 | height: 5px; 21 | border-radius: 50%; 22 | display: block; 23 | content: ''; 24 | position: relative; 25 | top: 0.6rem; 26 | margin-right: 0.5rem; 27 | } 28 | 29 | /* post's title */ 30 | > a { 31 | @extend %no-bottom-border; 32 | 33 | font-size: 1.1rem; 34 | } 35 | } 36 | } 37 | 38 | /* tag icon */ 39 | #page-tag h1 > i { 40 | font-size: 1.2rem; 41 | } 42 | 43 | #page-category h1 > i { 44 | font-size: 1.25rem; 45 | } 46 | 47 | #page-category, 48 | #page-tag, 49 | #access-lastmod { 50 | a:hover { 51 | @extend %link-hover; 52 | 53 | margin-bottom: -1px; /* Avoid jumping */ 54 | } 55 | } 56 | 57 | @media all and (max-width: 576px) { 58 | #page-category, 59 | #page-tag { 60 | ul > li { 61 | &::before { 62 | margin: 0 0.5rem; 63 | } 64 | 65 | > a { 66 | white-space: nowrap; 67 | overflow: hidden; 68 | text-overflow: ellipsis; 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/_layouts/_includes/update-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% assign MAX_SIZE = 5 %} 4 | 5 | {% assign all_list = '' | split: '' %} 6 | 7 | {% for post in site.posts %} 8 | {% if post.last_modified_at and post.last_modified_at != post.date %} 9 | {% capture elem %} 10 | {{- post.last_modified_at | date: "%Y%m%d%H%M%S" -}}::{{- forloop.index0 -}} 11 | {% endcapture %} 12 | {% assign all_list = all_list | push: elem %} 13 | {% endif %} 14 | {% endfor %} 15 | 16 | {% assign all_list = all_list | sort | reverse %} 17 | 18 | {% assign update_list = '' | split: '' %} 19 | 20 | {% for entry in all_list limit: MAX_SIZE %} 21 | {% assign update_list = update_list | push: entry %} 22 | {% endfor %} 23 | 24 | {% if update_list.size > 0 %} 25 |
26 |

{{- site.data.locales[include.lang].panel.lastmod -}}

27 |
    28 | {% for item in update_list %} 29 | {% assign index = item | split: '::' | last | plus: 0 %} 30 | {% assign post = site.posts[index] %} 31 | {% assign url = post.url | relative_url %} 32 |
  • 33 | {{ post.title }} 34 |
  • 35 | {% endfor %} 36 |
37 |
38 | 39 | {% endif %} 40 | -------------------------------------------------------------------------------- /src/_layouts/_includes/post-sharing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 38 | -------------------------------------------------------------------------------- /templates/tag.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | [[#{breadcrumb.home}]] 10 | 11 | 12 | [[#{breadcrumb.tags}]] 13 | 14 | [[${tag.spec.displayName}]] 15 | 16 | 17 |
18 |

19 | 20 | [[${tag.spec.displayName}]] 21 | [[${tag.status.visiblePostCount}]] 24 |

25 |
    29 |
  • 33 | [[${post.spec.title}]] 34 | 35 | [[${#dates.format(post.spec.publishTime,'yyyy-MM-d')}]] 38 |
  • 39 |
40 |
41 | 42 | -------------------------------------------------------------------------------- /templates/category.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | [[#{breadcrumb.home}]] 10 | 11 | 12 | [[#{breadcrumb.categories}]] 13 | 14 | [[${category.spec.displayName}]] 15 | 16 | 17 |
18 |

19 | 20 | [[${category.spec.displayName}]] 21 | [[${category.status.postCount}]] 22 |

23 | 24 |
    28 |
  • 32 | [[${post.spec.title}]] 33 | 34 | [[${#dates.format(post.spec.publishTime,'yyyy年MM月d日')}]] 37 |
  • 38 |
39 |
40 | 41 | -------------------------------------------------------------------------------- /src/js/pwa/app.js: -------------------------------------------------------------------------------- 1 | const $notification = $('#notification'); 2 | const $btnRefresh = $('#notification .toast-body>button'); 3 | 4 | if ('serviceWorker' in navigator) { 5 | /* Registering Service Worker */ 6 | navigator.serviceWorker.register('{{ "/sw.js" | relative_url }}') 7 | .then(registration => { 8 | 9 | /* in case the user ignores the notification */ 10 | if (registration.waiting) { 11 | $notification.toast('show'); 12 | } 13 | 14 | registration.addEventListener('updatefound', () => { 15 | registration.installing.addEventListener('statechange', () => { 16 | if (registration.waiting) { 17 | if (navigator.serviceWorker.controller) { 18 | $notification.toast('show'); 19 | } 20 | } 21 | }); 22 | }); 23 | 24 | $btnRefresh.click(() => { 25 | if (registration.waiting) { 26 | registration.waiting.postMessage('SKIP_WAITING'); 27 | } 28 | $notification.toast('hide'); 29 | }); 30 | }); 31 | 32 | let refreshing = false; 33 | 34 | /* Detect controller change and refresh all the opened tabs */ 35 | navigator.serviceWorker.addEventListener('controllerchange', () => { 36 | if (!refreshing) { 37 | window.location.reload(); 38 | refreshing = true; 39 | } 40 | }); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /templates/modules/post/postShaing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 44 | 45 | -------------------------------------------------------------------------------- /src/js/modules/components/locale-datetime.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Update month/day to locale datetime 3 | * 4 | * Requirement: 5 | */ 6 | 7 | /* A tool for locale datetime */ 8 | class LocaleHelper { 9 | static get attrTimestamp() { 10 | return 'data-ts'; 11 | } 12 | 13 | static get attrDateFormat() { 14 | return 'data-df'; 15 | } 16 | 17 | static get locale() { 18 | return $('html').attr('lang').substring(0, 2); 19 | } 20 | 21 | static getTimestamp(elem) { 22 | return Number(elem.attr(LocaleHelper.attrTimestamp)); // unix timestamp 23 | } 24 | 25 | static getDateFormat(elem) { 26 | return elem.attr(LocaleHelper.attrDateFormat); 27 | } 28 | } 29 | 30 | export function initLocaleDatetime() { 31 | dayjs.locale(LocaleHelper.locale); 32 | dayjs.extend(window.dayjs_plugin_localizedFormat); 33 | 34 | $(`[${LocaleHelper.attrTimestamp}]`).each(function () { 35 | const date = dayjs.unix(LocaleHelper.getTimestamp($(this))); 36 | const text = date.format(LocaleHelper.getDateFormat($(this))); 37 | $(this).text(text); 38 | $(this).removeAttr(LocaleHelper.attrTimestamp); 39 | $(this).removeAttr(LocaleHelper.attrDateFormat); 40 | 41 | // setup tooltips 42 | const tooltip = $(this).attr('data-bs-toggle'); 43 | if (typeof tooltip === 'undefined' || tooltip !== 'tooltip') { 44 | return; 45 | } 46 | 47 | const tooltipText = date.format('llll'); // see: https://day.js.org/docs/en/display/format#list-of-localized-formats 48 | $(this).attr('data-bs-title', tooltipText); 49 | new bootstrap.Tooltip($(this)); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/_layouts/_includes/search-loader.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | {% capture result_elem %} 7 |
8 |
9 |

{title}

10 | 14 |
15 |

{snippet}

16 |
17 | {% endcapture %} 18 | 19 | {% capture not_found %}

{{ site.data.locales[include.lang].search.no_results }}

{% endcapture %} 20 | 21 | 48 | -------------------------------------------------------------------------------- /src/_layouts/_includes/trending-tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% assign MAX = 10 %} 4 | 5 | {% assign size_list = '' | split: '' %} 6 | {% assign tag_list = '' | split: '' %} 7 | 8 | {% for tag in site.tags %} 9 | {% assign size = tag | last | size %} 10 | {% assign size_list = size_list | push: size %} 11 | 12 | {% assign tag_str = tag | first | append: '::' | append: size %} 13 | {% assign tag_list = tag_list | push: tag_str %} 14 | {% endfor %} 15 | 16 | {% assign size_list = size_list | sort | reverse %} 17 | 18 | {% assign tag_list = tag_list | sort_natural %} 19 | 20 | {% assign trending_tags = '' | split: '' %} 21 | 22 | {% for size in size_list limit: MAX %} 23 | {% for tag_str in tag_list %} 24 | {% assign tag = tag_str | split: '::' %} 25 | {% assign tag_name = tag | first %} 26 | {% assign tag_size = tag | last | plus: 0 %} 27 | {% if tag_size == size %} 28 | {% unless trending_tags contains tag_name %} 29 | {% assign trending_tags = trending_tags | push: tag_name %} 30 | {% break %} 31 | {% endunless %} 32 | {% endif %} 33 | {% endfor %} 34 | {% endfor %} 35 | 36 | {% if trending_tags.size > 0 %} 37 |
38 |

{{- site.data.locales[include.lang].panel.trending_tags -}}

39 |
40 | {% for tag_name in trending_tags %} 41 | {% assign url = tag_name | slugify | url_encode | prepend: '/tags/' | append: '/' %} 42 | 43 | {% endfor %} 44 |
45 |
46 | {% endif %} 47 | -------------------------------------------------------------------------------- /src/_layouts/_includes/comments/disqus.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |

Comments powered by Disqus.

5 |
6 | 7 | 51 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build-action 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - dev 8 | pull_request: 9 | branches: 10 | - master 11 | - dev 12 | workflow_call: 13 | 14 | jobs: 15 | build: 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout Repo 19 | uses: actions/checkout@v3 20 | 21 | - name: Setup Node.js 22 | uses: actions/setup-node@v3 23 | with: 24 | node-version: "18" 25 | 26 | - name: Setup pnpm 27 | uses: pnpm/action-setup@v4 28 | with: 29 | version: 9 30 | run_install: false 31 | 32 | - name: Get pnpm store directory 33 | id: pnpm-cache 34 | run: echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT 35 | 36 | - name: Setup pnpm cache 37 | uses: actions/cache@v3 38 | with: 39 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 40 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} 41 | restore-keys: | 42 | ${{ runner.os }}-pnpm-store- 43 | 44 | - name: Install Dependencies 45 | run: pnpm install 46 | 47 | - name: Build Theme 48 | run: | 49 | pnpm build 50 | 51 | - name: Make Build Directory 52 | run: | 53 | BUILD_DIR=dist/ 54 | mkdir $BUILD_DIR 55 | cp -r theme.yaml settings.yaml i18n templates LICENSE $BUILD_DIR/ 56 | 57 | - name: Upload artifact 58 | uses: actions/upload-artifact@v4 59 | with: 60 | name: halo-theme-chirpy-${{ github.sha }} 61 | path: dist/ 62 | retention-days: 7 63 | -------------------------------------------------------------------------------- /src/css/layout/categories.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Style for Tab Categories 3 | */ 4 | 5 | %category-icon-color { 6 | color: gray; 7 | } 8 | 9 | .categories { 10 | margin-bottom: 2rem; 11 | border-color: var(--categories-border); 12 | 13 | &.card, 14 | .list-group { 15 | @extend %rounded; 16 | } 17 | 18 | .card-header { 19 | $radius: calc($base-radius - 1px); 20 | 21 | padding: 0.75rem; 22 | border-radius: $radius; 23 | border-bottom: 0; 24 | 25 | &.hide-border-bottom { 26 | border-bottom-left-radius: 0; 27 | border-bottom-right-radius: 0; 28 | } 29 | } 30 | 31 | i { 32 | @extend %category-icon-color; 33 | 34 | font-size: 86%; /* fontawesome icons */ 35 | } 36 | 37 | .list-group-item { 38 | border-left: none; 39 | border-right: none; 40 | padding-left: 2rem; 41 | 42 | &:first-child { 43 | border-top-left-radius: 0; 44 | border-top-right-radius: 0; 45 | } 46 | 47 | &:last-child { 48 | border-bottom: 0; 49 | } 50 | } 51 | } /* .categories */ 52 | 53 | .category-trigger { 54 | width: 1.7rem; 55 | height: 1.7rem; 56 | border-radius: 50%; 57 | text-align: center; 58 | color: #6c757d !important; 59 | 60 | i { 61 | position: relative; 62 | height: 0.7rem; 63 | width: 1rem; 64 | transition: transform 300ms ease; 65 | } 66 | 67 | &:hover { 68 | i { 69 | color: var(--categories-icon-hover-color); 70 | } 71 | } 72 | } 73 | 74 | /* only works on desktop */ 75 | @media (hover: hover) { 76 | .category-trigger:hover { 77 | background-color: var(--categories-hover-bg); 78 | } 79 | } 80 | 81 | .rotate { 82 | transform: rotate(-90deg); 83 | } 84 | -------------------------------------------------------------------------------- /src/_layouts/_includes/comments/utterances.html: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 52 | -------------------------------------------------------------------------------- /templates/modules/topbar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
9 | 12 | 13 | 16 | 17 |
[[${title}]]
18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 41 | 42 | 43 | 46 | 47 |
48 |
49 | 50 | -------------------------------------------------------------------------------- /src/_data/locales/zh-CN.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: 文章 7 | category: 分类 8 | tag: 标签 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: 首页 14 | categories: 分类 15 | tags: 标签 16 | archives: 归档 17 | about: 关于 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: 搜索 22 | cancel: 取消 23 | no_results: 搜索结果为空 24 | 25 | panel: 26 | lastmod: 最近更新 27 | trending_tags: 热门标签 28 | toc: 文章内容 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: 本文由作者按照 :LICENSE_NAME 进行授权 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: 保留部分权利。 39 | verbose: >- 40 | 除非另有说明,本网站上的博客文章均由作者按照知识共享署名 4.0 国际 (CC BY 4.0) 许可协议进行授权。 41 | 42 | meta: 本站采用 :PLATFORM 主题 :THEME 43 | 44 | not_found: 45 | statment: 抱歉,我们放错了该 URL,或者它指向了不存在的内容。 46 | 47 | notification: 48 | update_found: 发现新版本的内容。 49 | update: 更新 50 | 51 | # ----- Posts related labels ----- 52 | 53 | post: 54 | written_by: 作者 55 | posted: 发表于 56 | updated: 更新于 57 | words: 字 58 | pageview_measure: 次浏览 59 | read_time: 60 | unit: 分钟 61 | prompt: 阅读 62 | relate_posts: 相关文章 63 | share: 分享 64 | button: 65 | next: 下一篇 66 | previous: 上一篇 67 | copy_code: 68 | succeed: 已复制! 69 | share_link: 70 | title: 分享链接 71 | succeed: 链接已复制! 72 | 73 | # Date time format. 74 | # See: , 75 | df: 76 | post: 77 | strftime: "%Y/%m/%d" 78 | dayjs: "YYYY/MM/DD" 79 | 80 | # categories page 81 | categories: 82 | category_measure: 个分类 83 | post_measure: 篇文章 84 | -------------------------------------------------------------------------------- /src/_data/locales/zh-TW.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: 文章 7 | category: 分類 8 | tag: 標籤 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: 首頁 14 | categories: 分類 15 | tags: 標籤 16 | archives: 封存 17 | about: 關於 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: 搜尋 22 | cancel: 取消 23 | no_results: 沒有搜尋結果 24 | 25 | panel: 26 | lastmod: 最近更新 27 | trending_tags: 熱門標籤 28 | toc: 文章摘要 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: 本文章以 :LICENSE_NAME 授權 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: 保留部份權利。 39 | verbose: >- 40 | 除非另有說明,否則本網誌的文章均由作者按照姓名標示 4.0 國際 (CC BY 4.0) 授權條款進行授權。 41 | 42 | meta: 本網站使用 :PLATFORM 產生,採用 :THEME 主題 43 | 44 | not_found: 45 | statment: 抱歉,您可能正在存取一個已被移動的 URL,或者它從未存在。 46 | 47 | notification: 48 | update_found: 發現新版本更新。 49 | update: 更新 50 | 51 | # ----- Posts related labels ----- 52 | 53 | post: 54 | written_by: 作者 55 | posted: 發布於 56 | updated: 更新於 57 | words: 字 58 | pageview_measure: 次瀏覽 59 | read_time: 60 | unit: 分鐘 61 | prompt: 閱讀 62 | relate_posts: 相關文章 63 | share: 分享 64 | button: 65 | next: 下一篇 66 | previous: 上一篇 67 | copy_code: 68 | succeed: 已複製! 69 | share_link: 70 | title: 分享連結 71 | succeed: 已複製連結! 72 | 73 | # Date time format. 74 | # See: , 75 | df: 76 | post: 77 | strftime: "%Y/%m/%d" 78 | dayjs: "YYYY/MM/DD" 79 | 80 | # categories page 81 | categories: 82 | category_measure: 個分類 83 | post_measure: 篇文章 84 | -------------------------------------------------------------------------------- /src/_data/locales/ko-KR.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: 포스트 7 | category: 카테고리 8 | tag: 태그 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: 홈 14 | categories: 카테고리 15 | tags: 태그 16 | archives: 아카이브 17 | about: 정보 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: 검색 22 | cancel: 취소 23 | no_results: 검색 결과가 없습니다. 24 | 25 | panel: 26 | lastmod: 최근 업데이트 27 | trending_tags: 인기 태그 28 | toc: 바로가기 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: 이 기사는 저작권자의 :LICENSE_NAME 라이센스를 따릅니다. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: 일부 권리 보유 39 | verbose: >- 40 | 명시되지 않는 한 이 사이트의 블로그 게시물은 작성자의 41 | Creative Commons Attribution 4.0 International(CC BY 4.0) 라이선스에 따라 사용이 허가되었습니다. 42 | 43 | meta: Powered by :PLATFORM with :THEME theme 44 | 45 | not_found: 46 | statment: 해당 URL은 존재하지 않습니다. 47 | 48 | notification: 49 | update_found: 새 버전의 콘텐츠를 사용할 수 있습니다. 50 | update: 업데이트 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: By 56 | posted: 게시 57 | updated: 업데이트 58 | words: 단어 59 | pageview_measure: 조회 60 | read_time: 61 | unit: 분 62 | prompt: 읽는 시간 63 | relate_posts: 관련된 글 64 | share: 공유하기 65 | button: 66 | next: 다음 글 67 | previous: 이전 글 68 | copy_code: 69 | succeed: 복사되었습니다! 70 | share_link: 71 | title: 링크 복사하기 72 | succeed: 링크가 복사되었습니다! 73 | 74 | # Date time format. 75 | # See: , 76 | df: 77 | post: 78 | strftime: "%Y/%m/%d" 79 | dayjs: "YYYY/MM/DD" 80 | 81 | # categories page 82 | categories: 83 | category_measure: 카테고리 84 | post_measure: 포스트 85 | -------------------------------------------------------------------------------- /src/_data/locales/uk-UA.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Публікація 7 | category: Категорія 8 | tag: Тег 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Домашня сторінка 14 | categories: Категорії 15 | tags: Теги 16 | archives: Архів 17 | about: Про сайт 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: пошук 22 | cancel: Скасувати 23 | no_results: Ох! Нічого не знайдено. 24 | 25 | panel: 26 | lastmod: Нещодавно оновлено 27 | trending_tags: Популярні теги 28 | toc: Зміст 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Публікація захищена ліцензією :LICENSE_NAME. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Деякі права захищено. 39 | verbose: >- 40 | Публікації на сайті захищено ліцензією Creative Commons Attribution 4.0 International (CC BY 4.0), 41 | якщо інше не вказано в тексті. 42 | 43 | meta: Powered by :PLATFORM with :THEME theme 44 | 45 | not_found: 46 | statment: Вибачте, це посилання вказує на ресурс, що не існує. 47 | 48 | notification: 49 | update_found: Доступна нова версія вмісту. 50 | update: Оновлення 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Автор 56 | posted: Час публікації 57 | updated: Оновлено 58 | words: слів 59 | pageview_measure: переглядів 60 | read_time: 61 | unit: хвилин 62 | prompt: читання 63 | relate_posts: Вас також може зацікавити 64 | share: Поділитися 65 | button: 66 | next: Попередня публікація 67 | previous: Наступна публікація 68 | copy_code: 69 | succeed: Успішно скопійовано! 70 | share_link: 71 | title: Скопіювати посилання 72 | succeed: Посилання успішно скопійовано! 73 | 74 | # categories page 75 | categories: 76 | category_measure: категорії 77 | post_measure: публікації 78 | -------------------------------------------------------------------------------- /src/_data/locales/id-ID.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Postingan 7 | category: Kategori 8 | tag: Tagar 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Beranda 14 | categories: Kategori 15 | tags: Tagar 16 | archives: Arsip 17 | about: Tentang 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: Cari 22 | cancel: Batal 23 | no_results: Ups! Tidak ada hasil yang ditemukan. 24 | 25 | panel: 26 | lastmod: Postingan Terbaru 27 | trending_tags: Tagar Terpopuler 28 | toc: Konten 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Postingan ini dilisensikan di bawah :LICENSE_NAME oleh penulis. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Sebagian konten dilindungi. 39 | verbose: >- 40 | Kecuali jika dinyatakan, Postingan blog di situs ini dilisensikan 41 | di bawah Lisensi Creative Commons Attribution 4.0 International (CC BY 4.0) oleh penulis. 42 | 43 | meta: Didukung oleh :PLATFORM dengan tema :THEME 44 | 45 | not_found: 46 | statment: Maaf, kami gagal menemukan URL itu atau memang mengarah ke sesuatu yang tidak ada. 47 | 48 | notification: 49 | update_found: Versi konten baru tersedia. 50 | update: Perbarui 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Oleh 56 | posted: Diterbitkan 57 | updated: Diperbarui 58 | words: kata 59 | pageview_measure: dilihat 60 | read_time: 61 | unit: menit 62 | prompt: baca 63 | relate_posts: Postingan Lainya 64 | share: Bagikan 65 | button: 66 | next: Terbaru 67 | previous: Terlama 68 | copy_code: 69 | succeed: Disalin! 70 | share_link: 71 | title: Salin tautan 72 | succeed: Tautan berhasil disalin! 73 | 74 | # categories page 75 | categories: 76 | category_measure: kategori 77 | post_measure: Postingan 78 | -------------------------------------------------------------------------------- /src/_data/locales/pt-BR.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Post 7 | category: Categoria 8 | tag: Tag 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Home 14 | categories: Categorias 15 | tags: Tags 16 | archives: Arquivos 17 | about: Sobre 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: Buscar 22 | cancel: Cancelar 23 | no_results: Oops! Nenhum resultado encontrado. 24 | 25 | panel: 26 | lastmod: Atualizados recentemente 27 | trending_tags: Trending Tags 28 | toc: Conteúdo 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Esta postagem está licenciada sob :LICENSE_NAME pelo autor. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Alguns direitos reservados. 39 | verbose: >- 40 | Exceto onde indicado de outra forma, as postagens do blog neste site são licenciadas sob a 41 | Creative Commons Attribution 4.0 International (CC BY 4.0) License pelo autor. 42 | 43 | meta: Feito com :PLATFORM usando o tema :THEME 44 | 45 | not_found: 46 | statment: Desculpe, a página não foi encontrada. 47 | 48 | notification: 49 | update_found: Uma nova versão do conteúdo está disponível. 50 | update: atualização 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Por 56 | posted: Postado em 57 | updated: Atualizado 58 | words: palavras 59 | pageview_measure: visualizações 60 | read_time: 61 | unit: min 62 | prompt: " de leitura" 63 | relate_posts: Leia também 64 | share: Compartilhar 65 | button: 66 | next: Próximo 67 | previous: Anterior 68 | copy_code: 69 | succeed: Copiado! 70 | share_link: 71 | title: Copie o link 72 | succeed: Link copiado com sucesso! 73 | 74 | # categories page 75 | categories: 76 | category_measure: categorias 77 | post_measure: posts 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "halo-theme-chirpy", 3 | "version": "1.4.9", 4 | "description": "A minimal, responsive and feature-rich Halo theme for technical writing.", 5 | "scripts": { 6 | "build": "cross-env NODE_ENV=prod node mode.js && vite build", 7 | "dev": "cross-env NODE_ENV=dev node mode.js && node export-zip.js && vite", 8 | "lint": "eslint ./src --ext .js --ignore-path .gitignore", 9 | "stylelint": "stylelint ./src/css/patch/**/*.scss", 10 | "prettier": "prettier --write './src/css/patch/**/*.scss' './templates/**/*.html'", 11 | "prettier-win": "prettier --write \"./src/css/patch/**/*.scss\" \"./templates/**/*.html\"", 12 | "zip": "npm run build && cross-env NODE_ENV=prod node export-zip.js" 13 | }, 14 | "keywords": [ 15 | "halo", 16 | "halo-theme" 17 | ], 18 | "author": { 19 | "name": "AirboZH", 20 | "url": "https://airbozh.cn", 21 | "email": "i@airbozh.cn" 22 | }, 23 | "license": "GPL-3.0", 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/AirboZH/halo-theme-chirpy.git" 27 | }, 28 | "bugs": { 29 | "url": "https://github.com/AirboZH/halo-theme-chirpy/issues" 30 | }, 31 | "homepage": "https://github.com/AirboZH/halo-theme-chirpy", 32 | "devDependencies": { 33 | "@rollup/plugin-inject": "^5.0.3", 34 | "archiver": "^6.0.1", 35 | "cross-env": "^7.0.3", 36 | "eslint": "^8.28.0", 37 | "eslint-config-prettier": "^8.5.0", 38 | "eslint-plugin-prettier": "^4.2.1", 39 | "prettier": "^2.7.1", 40 | "sass": "^1.63.6", 41 | "stylelint": "^15.3.0", 42 | "stylelint-config-prettier-scss": "^1.0.0", 43 | "stylelint-config-standard-scss": "^9.0.0", 44 | "vite": "^5.1.1" 45 | }, 46 | "dependencies": { 47 | "@fortawesome/fontawesome-free": "^6.4.2", 48 | "@popperjs/core": "^2.11.8", 49 | "bootstrap": "^5.3.2", 50 | "clipboard": "^2.0.11", 51 | "glob": "^10.3.3", 52 | "highlight.js": "^11.9.0", 53 | "jquery": "^3.7.1", 54 | "magnific-popup": "^1.1.0", 55 | "tocbot": "^4.21.2" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/_data/locales/hu-HU.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Bejegyzés 7 | category: Kategória 8 | tag: Címke 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Kezdőlap 14 | categories: Kategóriák 15 | tags: Címkék 16 | archives: Archívum 17 | about: Rólam 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: keresés 22 | cancel: Mégse 23 | no_results: Oops! Nincs találat a keresésre. 24 | 25 | panel: 26 | lastmod: Legutóbb frissítve 27 | trending_tags: Népszerű Címkék 28 | toc: Tartalom 29 | links: Blog linkek 30 | 31 | copyright: 32 | # Shown at the bottom of the post 33 | license: 34 | template: A bejegyzés :LICENSE_NAME licenccel rendelkezik. 35 | name: CC BY 4.0 36 | link: https://creativecommons.org/licenses/by/4.0/ 37 | 38 | # Displayed in the footer 39 | brief: Néhány jog fenntartva. 40 | verbose: >- 41 | Az oldalon található tartalmak 42 | Creative Commons Attribution 4.0 International (CC BY 4.0) licenccel rendelkeznek, 43 | hacsak másképp nincs jelezve. 44 | 45 | meta: Készítve :PLATFORM motorral :THEME témával 46 | 47 | not_found: 48 | statment: Sajnáljuk, az URL-t rosszul helyeztük el, vagy valami nem létezőre mutat. 49 | 50 | notification: 51 | update_found: Elérhető a tartalom új verziója. 52 | update: Frissítés 53 | 54 | # ----- Posts related labels ----- 55 | 56 | post: 57 | written_by: Szerző 58 | posted: Létrehozva 59 | updated: Frissítve 60 | words: szó 61 | pageview_measure: látogató 62 | read_time: 63 | unit: perc 64 | prompt: elolvasni 65 | relate_posts: További olvasnivaló 66 | share: Megosztás 67 | button: 68 | next: Újabb 69 | previous: Régebbi 70 | copy_code: 71 | succeed: Másolva! 72 | share_link: 73 | title: Link másolása 74 | succeed: Link sikeresen másolva! 75 | 76 | # categories page 77 | categories: 78 | category_measure: kategória 79 | post_measure: bejegyzés 80 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release-action 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | uses: ./.github/workflows/build.yml 10 | release: 11 | needs: build 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout Repo 15 | uses: actions/checkout@v3 16 | 17 | - name: Download Artifact 18 | uses: actions/download-artifact@v4 19 | with: 20 | name: halo-theme-chirpy-${{ github.sha }} 21 | path: dist/ 22 | 23 | - name: Compress zip 24 | run: | 25 | PACKAGE_VERSION=$(sed -nE 's/^\s*"version": "(.*?)",$/\1/p' package.json) 26 | PRE_ZIP_FOLDER=halo-theme-chirpy-${PACKAGE_VERSION} 27 | ARTIFACT_NAME=${PRE_ZIP_FOLDER}.zip 28 | ARTIFACT_PATHNAME=dist/${ARTIFACT_NAME} 29 | echo "halo-theme-chirpy@$PACKAGE_VERSION" 30 | echo "RELEASE_ID=${{ github.event.release.id }}" >> $GITHUB_ENV 31 | echo "ARTIFACT_PATHNAME=${ARTIFACT_PATHNAME}" >> $GITHUB_ENV 32 | echo "ARTIFACT_NAME=${ARTIFACT_NAME}" >> $GITHUB_ENV 33 | cd dist 34 | zip -r $ARTIFACT_NAME templates i18n theme.yaml settings.yaml LICENSE 35 | 36 | - name: Upload a release asset 37 | uses: actions/github-script@v2.1.0 38 | with: 39 | github-token: ${{secrets.GITHUB_TOKEN}} 40 | script: | 41 | const fs = require('fs').promises; 42 | const { repo: { owner, repo }, sha } = context; 43 | console.log({ owner, repo, sha }); 44 | const releaseId = process.env.RELEASE_ID 45 | const artifactPathName = process.env.ARTIFACT_PATHNAME 46 | const artifactName = process.env.ARTIFACT_NAME 47 | console.log('Releasing', releaseId, artifactPathName, artifactName) 48 | await github.repos.uploadReleaseAsset({ 49 | owner, repo, 50 | release_id: releaseId, 51 | name: artifactName, 52 | data: await fs.readFile(artifactPathName) 53 | }); 54 | -------------------------------------------------------------------------------- /src/_data/locales/fr-FR.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Post 7 | category: Catégorie 8 | tag: Tag 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Accueil 14 | categories: Catégories 15 | tags: Tags 16 | archives: Archives 17 | about: A propos de 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: recherche 22 | cancel: Annuler 23 | no_results: Oups ! Aucun résultat trouvé. 24 | 25 | panel: 26 | lastmod: Récemment mis à jour 27 | trending_tags: Tags tendance 28 | toc: Contenu 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Cet article est sous licence :LICENSE_NAME par l'auteur. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Certains droits réservés. 39 | verbose: >- 40 | Sauf mention contraire, les articles de ce site sont publiés sous licence 41 | sous la licence Creative Commons Attribution 4.0 International (CC BY 4.0) par l'auteur. 42 | 43 | meta: Propulsé par :PLATFORM avec le thème :THEME 44 | 45 | not_found: 46 | statment: Désolé, nous avons égaré cette URL ou elle pointe vers quelque chose qui n'existe pas. 47 | 48 | notification: 49 | update_found: Une nouvelle version du contenu est disponible. 50 | update: Mise à jour 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Par 56 | posted: Posté 57 | updated: Mis à jour 58 | words: mots 59 | pageview_measure: vues 60 | read_time: 61 | unit: min 62 | prompt: lire 63 | relate_posts: Autres lectures 64 | share: Partager 65 | button: 66 | next: Plus récent 67 | previous: Plus ancien 68 | copy_code: 69 | succeed: Copié ! 70 | share_link: 71 | title: Copier le lien 72 | succeed: Lien copié avec succès ! 73 | 74 | # categories page 75 | categories: 76 | category_measure: catégories 77 | post_measure: posts 78 | -------------------------------------------------------------------------------- /src/_data/locales/ru-RU.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Публикация 7 | category: Категория 8 | tag: Тег 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Домашняя страница 14 | categories: Категории 15 | tags: Теги 16 | archives: Архив 17 | about: О сайте 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: поиск 22 | cancel: Отменить 23 | no_results: Ох! Ничего не найдено. 24 | 25 | panel: 26 | lastmod: Недавно обновлено 27 | trending_tags: Популярные теги 28 | toc: Содержание 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Публикация защищена лицензией :LICENSE_NAME. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Некоторые права защищены. 39 | verbose: >- 40 | Публикации на сайте защищены лицензией Creative Commons Attribution 4.0 International (CC BY 4.0), 41 | если в тексте публикации не указано иное. 42 | 43 | meta: Powered by :PLATFORM with :THEME theme 44 | 45 | not_found: 46 | statment: Извините, эта ссылка указывает на ресурс который не существует. 47 | 48 | notification: 49 | update_found: Доступна новая версия контента. 50 | update: Обновлять 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Автор 56 | posted: Время публикации 57 | updated: Обновлено 58 | words: слов 59 | pageview_measure: просмотров 60 | read_time: 61 | unit: минут 62 | prompt: чтения 63 | relate_posts: Вам также может быть интересно 64 | share: Поделиться 65 | button: 66 | next: Предыдущая публикация 67 | previous: Следующая публикация 68 | copy_code: 69 | succeed: Скопировано успешно! 70 | share_link: 71 | title: Скопировать ссылку 72 | succeed: Ссылка успешно скопирована! 73 | 74 | # categories page 75 | categories: 76 | category_measure: категории 77 | post_measure: публикации 78 | -------------------------------------------------------------------------------- /src/_data/locales/tr-TR.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Gönderi 7 | category: Kategori 8 | tag: Etiket 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Ana Sayfa 14 | categories: Kategoriler 15 | tags: Etiketler 16 | archives: Arşiv 17 | about: Hakkında 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: Ara... 22 | cancel: İptal 23 | no_results: Hop! Öyle bir şey bulamadım. 24 | 25 | panel: 26 | lastmod: Yeni Güncellendi 27 | trending_tags: Yükselen Etiketler 28 | toc: İçindekiler 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Bu gönderi :LICENSE_NAME lisansı altındadır. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/deed.tr 36 | 37 | # Displayed in the footer 38 | brief: Bazı hakları saklıdır. 39 | verbose: >- 40 | Aksi belirtilmediği sürece, bu sitedeki gönderiler Creative Commons Atıf 4.0 Uluslararası (CC BY 4.0) Lisansı altındadır. 41 | Kısaca sayfa linkini de vererek paylaşabilir veya düzenleyip paylaşabilirsin. 42 | 43 | meta: :PLATFORM ve :THEME teması 44 | 45 | not_found: 46 | statment: Üzgünüz, bu linki yanlış yerleştirdik veya var olmayan bir şeye işaret ediyor. 47 | 48 | notification: 49 | update_found: İçeriğin yeni bir sürümü mevcut. 50 | update: Güncelle 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Yazan 56 | posted: Gönderilme Tarihi 57 | updated: Güncellenme Tarihi 58 | words: sözcük 59 | pageview_measure: görüntülenme 60 | read_time: 61 | unit: dakikada 62 | prompt: okunabilir 63 | relate_posts: Benzer Gönderiler 64 | share: Paylaş 65 | button: 66 | next: İleri 67 | previous: Geri 68 | copy_code: 69 | succeed: Kopyalandı. 70 | share_link: 71 | title: Linki kopyala 72 | succeed: Link kopyalandı. 73 | 74 | # categories page 75 | categories: 76 | category_measure: kategori 77 | post_measure: gönderi 78 | -------------------------------------------------------------------------------- /src/_data/locales/vi-VN.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Bài viết 7 | category: Danh mục 8 | tag: Thẻ 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Trang chủ 14 | categories: Các danh mục 15 | tags: Các thẻ 16 | archives: Lưu trữ 17 | about: Giới thiệu 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: tìm kiếm 22 | cancel: Hủy 23 | no_results: Không có kết quả tìm kiếm. 24 | 25 | panel: 26 | lastmod: Mới cập nhật 27 | trending_tags: Các thẻ thịnh hành 28 | toc: Mục lục 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Bài viết này được cấp phép bởi tác giả theo giấy phép :LICENSE_NAME. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Một số quyền được bảo lưu. 39 | verbose: >- 40 | Trừ khi có ghi chú khác, các bài viết đăng trên trang này được cấp phép bởi tác giả theo giấy phép Creative Commons Attribution 4.0 International (CC BY 4.0). 41 | 42 | meta: Trang web này được tạo bởi :PLATFORM với chủ đề :THEME 43 | 44 | not_found: 45 | statment: Xin lỗi, chúng tôi đã đặt nhầm URL hoặc đường dẫn trỏ đến một trang nào đó không tồn tại. 46 | 47 | notification: 48 | update_found: Đã có phiên bản mới của nội dung. 49 | update: Cập nhật 50 | 51 | # ----- Posts related labels ----- 52 | 53 | post: 54 | written_by: Viết bởi 55 | posted: Đăng lúc 56 | updated: Cập nhật lúc 57 | words: từ 58 | pageview_measure: lượt xem 59 | read_time: 60 | unit: phút 61 | prompt: đọc 62 | relate_posts: Bài viết liên quan 63 | share: Chia sẻ 64 | button: 65 | next: Mới hơn 66 | previous: Cũ hơn 67 | copy_code: 68 | succeed: Đã sao chép! 69 | share_link: 70 | title: Sao chép đường dẫn 71 | succeed: Đã sao chép đường dẫn thành công! 72 | 73 | # categories page 74 | categories: 75 | category_measure: danh mục 76 | post_measure: bài viết 77 | -------------------------------------------------------------------------------- /src/_layouts/_includes/mermaid.html: -------------------------------------------------------------------------------- 1 | 2 | 59 | -------------------------------------------------------------------------------- /src/_data/locales/es-ES.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Entrada 7 | category: Categoría 8 | tag: Etiqueta 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Inicio 14 | categories: Categorías 15 | tags: Etiquetas 16 | archives: Archivo 17 | about: Acerca de 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: Buscar 22 | cancel: Cancelar 23 | no_results: ¡Oops! No se encuentran resultados. 24 | 25 | panel: 26 | lastmod: Actualizado recientemente 27 | trending_tags: Etiquetas populares 28 | toc: Contenido 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Esta entrada está licenciada bajo :LICENSE_NAME por el autor. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Algunos derechos reservados. 39 | verbose: >- 40 | Salvo que se indique explícitamente, las entradas de este blog están licenciadas 41 | bajo la Creative Commons Attribution 4.0 International (CC BY 4.0) License por el autor. 42 | 43 | meta: Hecho con :PLATFORM usando el tema :THEME 44 | 45 | not_found: 46 | statment: Lo sentimos, hemos perdido esa URL o apunta a algo que no existe. 47 | 48 | notification: 49 | update_found: Hay una nueva versión de contenido disponible. 50 | update: Actualizar 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Por 56 | posted: Publicado 57 | updated: Actualizado 58 | words: palabras 59 | pageview_measure: visitas 60 | read_time: 61 | unit: min 62 | prompt: " de lectura" 63 | relate_posts: Lecturas adicionales 64 | share: Compartir 65 | button: 66 | next: Nuevo 67 | previous: Anterior 68 | copy_code: 69 | succeed: ¡Copiado! 70 | share_link: 71 | title: Copiar enlace 72 | succeed: ¡Enlace copiado! 73 | 74 | # categories page 75 | categories: 76 | category_measure: categorias 77 | post_measure: entradas 78 | -------------------------------------------------------------------------------- /src/_data/locales/bg-BG.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Публикация 7 | category: Категория 8 | tag: Таг 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Начало 14 | categories: Категории 15 | tags: Тагове 16 | archives: Архив 17 | about: За мен 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: търси 22 | cancel: Отмени 23 | no_results: Упс! Не са намерени резултати. 24 | 25 | panel: 26 | lastmod: Наскоро обновени 27 | trending_tags: Популярни тагове 28 | toc: Съдържание 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Тази публикация е лицензирана под :LICENSE_NAME от автора. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Някои права запазени. 39 | verbose: >- 40 | Освен ако не е посочено друго, публикациите в блога на този сайт са лицензирани 41 | под лиценза Creative Commons Attribution 4.0 (CC BY 4.0) от автора. 42 | 43 | meta: Създадено чрез :PLATFORM и :THEME тема 44 | 45 | not_found: 46 | statment: Съжалявам, но на този URL адрес няма налично съдържание. 47 | 48 | notification: 49 | update_found: Налична е нова версия на съдържанието. 50 | update: Обнови 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Автор 56 | posted: Публикувана 57 | updated: Обновена 58 | words: думи 59 | pageview_measure: преглеждания 60 | read_time: 61 | unit: мин 62 | prompt: четиво 63 | relate_posts: Още за четене 64 | share: Споделете 65 | button: 66 | next: По-нови 67 | previous: По-стари 68 | copy_code: 69 | succeed: Копирано! 70 | share_link: 71 | title: Копирай линк 72 | succeed: Линкът е копиран успешно! 73 | 74 | # categories page 75 | categories: 76 | category_measure: 77 | singular: категория 78 | plural: категории 79 | post_measure: 80 | singular: публикация 81 | plural: публикации 82 | -------------------------------------------------------------------------------- /src/_data/locales/de-DE.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Eintrag 7 | category: Kategorie 8 | tag: Tag 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Startseite 14 | categories: Kategorien 15 | tags: Tags 16 | archives: Archiv 17 | about: Über 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: Suche 22 | cancel: Abbrechen 23 | no_results: Ups! Keine Einträge gefunden. 24 | 25 | panel: 26 | lastmod: Kürzlich aktualisiert 27 | trending_tags: Beliebte Tags 28 | toc: Inhalt 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Dieser Eintrag ist vom Autor unter :LICENSE_NAME lizensiert. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Einige Rechte vorbehalten. 39 | verbose: >- 40 | Alle Einträge auf dieser Seite stehen, soweit nicht anders angegeben, unter der Lizenz Creative Commons Attribution 4.0 (CC BY 4.0). 41 | 42 | meta: Powered by :PLATFORM with :THEME theme 43 | 44 | not_found: 45 | statment: Entschuldigung, dieser Link verweist auf keine vorhandene Ressource. 46 | 47 | notification: 48 | update_found: Eine neue Version ist verfügbar. 49 | update: Neue Version 50 | 51 | # ----- Posts related labels ----- 52 | 53 | post: 54 | written_by: Von 55 | posted: Veröffentlicht 56 | updated: Aktualisiert 57 | words: Wörter 58 | pageview_measure: Aufrufe 59 | read_time: 60 | unit: Minuten 61 | prompt: lesen 62 | relate_posts: Weiterlesen 63 | share: Teilen 64 | button: 65 | next: Nächster Eintrag 66 | previous: Eintrag vorher 67 | copy_code: 68 | succeed: Kopiert! 69 | share_link: 70 | title: Link kopieren 71 | succeed: Link erfolgreich kopiert! 72 | 73 | # categories page 74 | categories: 75 | category_measure: 76 | singular: Kategorie 77 | plural: Kategorien 78 | post_measure: 79 | singular: Eintrag 80 | plural: Einträge 81 | -------------------------------------------------------------------------------- /src/_data/origin/cors.yml: -------------------------------------------------------------------------------- 1 | # CDNs 2 | 3 | cdns: 4 | # Google Fonts 5 | - url: https://fonts.googleapis.com 6 | - url: https://fonts.gstatic.com 7 | args: crossorigin 8 | - url: https://fonts.googleapis.com 9 | # jsDelivr CDN 10 | - url: https://cdn.jsdelivr.net 11 | 12 | # fonts 13 | 14 | webfonts: https://fonts.googleapis.com/css2?family=Lato&family=Source+Sans+Pro:wght@400;600;700;900&display=swap 15 | 16 | # Libraries 17 | 18 | jquery: 19 | js: https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js 20 | 21 | bootstrap: 22 | css: https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css 23 | js: https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js 24 | 25 | toc: 26 | css: https://cdn.jsdelivr.net/npm/tocbot@4.21.0/dist/tocbot.min.css 27 | js: https://cdn.jsdelivr.net/npm/tocbot@4.21.0/dist/tocbot.min.js 28 | 29 | fontawesome: 30 | css: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/css/all.min.css 31 | 32 | search: 33 | js: https://cdn.jsdelivr.net/npm/simple-jekyll-search@1.10.0/dest/simple-jekyll-search.min.js 34 | 35 | mermaid: 36 | js: https://cdn.jsdelivr.net/npm/mermaid@9.4.3/dist/mermaid.min.js 37 | 38 | dayjs: 39 | js: 40 | common: https://cdn.jsdelivr.net/npm/dayjs@1.11.7/dayjs.min.js 41 | locale: https://cdn.jsdelivr.net/npm/dayjs@1.11.7/locale/:LOCALE.min.js 42 | relativeTime: https://cdn.jsdelivr.net/npm/dayjs@1.11.7/plugin/relativeTime.min.js 43 | localizedFormat: https://cdn.jsdelivr.net/npm/dayjs@1.11.7/plugin/localizedFormat.min.js 44 | 45 | magnific-popup: 46 | css: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/magnific-popup.min.css 47 | js: https://cdn.jsdelivr.net/npm/magnific-popup@1.1.0/dist/jquery.magnific-popup.min.js 48 | 49 | lazysizes: 50 | js: https://cdn.jsdelivr.net/npm/lazysizes@5.3.2/lazysizes.min.js 51 | 52 | clipboard: 53 | js: https://cdn.jsdelivr.net/npm/clipboard@2.0.11/dist/clipboard.min.js 54 | 55 | polyfill: 56 | js: https://polyfill.io/v3/polyfill.min.js?features=es6 57 | 58 | mathjax: 59 | js: https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-chtml.js 60 | -------------------------------------------------------------------------------- /src/_layouts/_includes/language-alias.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | 3 | Convert the alias of the syntax language to the official name 4 | 5 | See: 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 %} 71 | -------------------------------------------------------------------------------- /src/_data/locales/my-MM.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: ပို့စ် 7 | category: ကဏ္ဍ 8 | tag: နာမ(တက်ဂ်) 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: အဓိကစာမျက်နှာ 14 | categories: ကဏ္ဍများ 15 | tags: နာမ(တက်ဂ်)များ 16 | archives: မှတ်တမ်း​တိုက် 17 | about: အကြောင်းအရာ 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: ရှာဖွေမည် 22 | cancel: ဖျက်သိမ်းမည် 23 | no_results: အိုး! ဘာမှမရှိပါ 24 | 25 | panel: 26 | lastmod: မကြာသေးမီကမွမ်းမံထားသည် 27 | trending_tags: ခေတ်စားနေသည့်တက်ဂ်များ 28 | toc: အကြောင်းအရာများ 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: ဤပို့စ်သည်စာရေးသူ၏ :LICENSE_NAME လိုင်စင်ရထားသည်။ 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: မူပိုင်ခွင့်အချို့ကို လက်ဝယ်ထားသည်။ 39 | verbose: >- 40 | အခြားမှတ်သားထားချက်များမှလွဲ၍ ဤဆိုက်ရှိ ဘလော့ဂ်ပို့စ်များသည် စာရေးသူ၏ 41 | Creative Commons Attribution 4.0 International (CC BY 4.0) အောက်တွင် လိုင်စင်ရထားပါသည်။ 42 | 43 | meta: Powered by :PLATFORM with :THEME theme 44 | 45 | not_found: 46 | statment: ဝမ်းနည်းပါသည်၊ ကျွန်ုပ်တို့သည် အဆိုပါ URL ကို မှားယွင်းစွာ နေရာချထားခြင်း သို့မဟုတ် ၎င်းသည် မရှိသောအရာကို ညွှန်ပြနေပါသည်။ 47 | 48 | notification: 49 | update_found: အကြောင်းအရာဗားရှင်းအသစ်ကို ရနိုင်ပါပြီ။ 50 | update: အပ်ဒိတ် 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: ကရေးသားခဲ့သည်။ 56 | posted: တင်ထားခဲ့သည်။ 57 | updated: မွမ်းမံထားခဲ့သည်။ 58 | words: စကားလုံးများ 59 | pageview_measure: အမြင်များ 60 | read_time: 61 | unit: မိနစ် 62 | prompt: ဖတ်ပါမည် 63 | relate_posts: နောက်ထပ်ဖတ်ရန် 64 | share: မျှဝေရန် 65 | button: 66 | next: အသစ်များ 67 | previous: အဟောင်းများ 68 | copy_code: 69 | succeed: ကူးယူလိုက်ပြီ။ 70 | share_link: 71 | title: လင့်ခ်ကို ကူးယူရန် 72 | succeed: လင့်ခ်ကို ကူးယူလိုက်ပြီ။ 73 | 74 | # categories page 75 | categories: 76 | category_measure: ကဏ္ဍများ 77 | post_measure: ပို့စ်များ 78 | -------------------------------------------------------------------------------- /src/_data/locales/ar.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: منشور 7 | category: فئة 8 | tag: وسم 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: الرئيسية 14 | categories: الفئات 15 | tags: الوسوم 16 | archives: الأرشيف 17 | about: حول 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: بحث 22 | cancel: إلغاء 23 | no_results: نأسف! لا يوجد نتائج. 24 | 25 | panel: 26 | lastmod: المحدثة مؤخرا 27 | trending_tags: الوسوم الشائعة 28 | toc: محتويات 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: هذا المنشور تحت ترخيص :LICENSE_NAME بواسطة المؤلف. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: بعض الحقوق محفوظة. 39 | verbose: >- 40 | ما لم يذكر خلاف ذلك ، يتم ترخيص منشورات المدونة على هذا الموقع 41 | بموجب ترخيص Creative Commons Attribution 4.0 International (CC BY 4.0) من قبل المؤلف. 42 | 43 | meta: باستخدام :PLATFORM السمة :THEME 44 | 45 | not_found: 46 | statment: عذرا, الرابط التالي غير صالح أو انه يشير إلى صفحة غير موجودة. 47 | 48 | notification: 49 | update_found: يتوفر اصدار جديد للمحتوى. 50 | update: تحديث 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: بواسطة 56 | posted: نشّر 57 | updated: حدّث 58 | words: كلمات 59 | pageview_measure: مشاهدات 60 | read_time: 61 | unit: دقيقة 62 | prompt: قراءة 63 | relate_posts: إقرأ المزيد 64 | share: شارك 65 | button: 66 | next: الأجدد 67 | previous: الأقدم 68 | copy_code: 69 | succeed: تم النسخ! 70 | share_link: 71 | title: أنسخ الرابط 72 | succeed: تم نسخ الرابط بنجاح! 73 | 74 | # Date time format. 75 | # See: , 76 | df: 77 | post: 78 | strftime: "%b %e, %Y" 79 | dayjs: "ll" 80 | archives: 81 | strftime: "%b" 82 | dayjs: "MMM" 83 | 84 | # categories page 85 | categories: 86 | category_measure: 87 | singular: فئة 88 | plural: فئات 89 | post_measure: 90 | singular: منشور 91 | plural: منشورات 92 | -------------------------------------------------------------------------------- /src/_data/locales/th.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: โพสต์ 7 | category: หมวดหมู่ 8 | tag: แท็ก 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: หน้าแรก 14 | categories: หมวดหมู่ 15 | tags: แท็ก 16 | archives: คลังเก็บ 17 | about: เกี่ยวกับ 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: ค้นหา 22 | cancel: ยกเลิก 23 | no_results: โอ๊ะ! ไม่พบผลลัพธ์ 24 | 25 | panel: 26 | lastmod: อัปเดตล่าสุด 27 | trending_tags: แท็กยอดนิยม 28 | toc: เนื้อหา 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: โพสต์นี้อยู่ภายใต้การอนุญาต :LICENSE_NAME โดยผู้เขียน 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: สงวนลิขสิทธิ์เป็นบางส่วน 39 | verbose: >- 40 | เว้นแต่ว่าจะระบุเป็นอย่างอื่น โพสต์บนเว็บไซต์นี้อยู่ภายใต้ 41 | สัญญาอนุญาตครีเอทีฟคอมมอนส์แบบ 4.0 นานาชาติ (CC BY 4.0) โดยผู้เขียน 42 | 43 | meta: กำลังใช้ธีมของ :PLATFORM ชื่อ :THEME 44 | 45 | not_found: 46 | statment: ขออภัย เราวาง URL นั้นไว้ผิดที่ หรือมันชี้ไปยังสิ่งที่ไม่มีอยู่ 47 | 48 | notification: 49 | update_found: มีเวอร์ชันใหม่ของเนื้อหา 50 | update: อัปเดต 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: โดย 56 | posted: โพสต์เมื่อ 57 | updated: อัปเดตเมื่อ 58 | words: คำ 59 | pageview_measure: ครั้ง 60 | read_time: 61 | unit: นาที 62 | prompt: อ่าน 63 | relate_posts: อ่านต่อ 64 | share: แชร์ 65 | button: 66 | next: ใหม่กว่า 67 | previous: เก่ากว่า 68 | copy_code: 69 | succeed: คัดลอกแล้ว! 70 | share_link: 71 | title: คัดลอกลิงก์ 72 | succeed: คัดลอกลิงก์เรียบร้อยแล้ว! 73 | 74 | # Date time format. 75 | # See: , 76 | df: 77 | post: 78 | strftime: "%b %e, %Y" 79 | dayjs: "ll" 80 | archives: 81 | strftime: "%b" 82 | dayjs: "MMM" 83 | 84 | # categories page 85 | categories: 86 | category_measure: 87 | singular: หมวดหมู่ 88 | plural: หมวดหมู่ 89 | post_measure: 90 | singular: โพสต์ 91 | plural: โพสต์ 92 | -------------------------------------------------------------------------------- /src/_data/locales/cs-CZ.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Příspěvek 7 | category: Kategorie 8 | tag: Štítek 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Domů 14 | categories: Kategorie 15 | tags: Štítky 16 | archives: Archivy 17 | about: O mně 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: hledat 22 | cancel: Zrušit 23 | no_results: Ups! Žádný výsledek nenalezen. 24 | 25 | panel: 26 | lastmod: Nedávno aktualizováno 27 | trending_tags: Trendy štítky 28 | toc: Obsah 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Tento příspěvek je licencován pod :LICENSE_NAME autorem. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Některá práva vyhrazena. 39 | verbose: >- 40 | Pokud není uvedeno jinak, jsou příspěvky na tomto webu licencovány 41 | pod licencí Creative Commons Attribution 4.0 International (CC BY 4.0) Licence autora. 42 | 43 | meta: Použití :PLATFORM s motivem :THEME 44 | 45 | not_found: 46 | statment: Omlouváme se, adresu URL jsme špatně umístili nebo odkazuje na něco, co neexistuje. 47 | 48 | notification: 49 | update_found: Je k dispozici nová verze obsahu. 50 | update: Aktualizace 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Od 56 | posted: Zveřejněno 57 | updated: Aktualizováno 58 | words: slova 59 | pageview_measure: zhlednutí 60 | read_time: 61 | unit: minut 62 | prompt: čtení 63 | relate_posts: Další čtení 64 | share: Sdílet 65 | button: 66 | next: Novější 67 | previous: Starší 68 | copy_code: 69 | succeed: Zkopírováno! 70 | share_link: 71 | title: Kopírovat odkaz 72 | succeed: Zkopírováno! 73 | 74 | # Date time format. 75 | # See: , 76 | df: 77 | post: 78 | strftime: "%b %e, %Y" 79 | dayjs: "ll" 80 | archives: 81 | strftime: "%b" 82 | dayjs: "MMM" 83 | 84 | # categories page 85 | categories: 86 | category_measure: kategorie 87 | post_measure: 88 | singular: příspěvěk 89 | plural: příspěvky 90 | -------------------------------------------------------------------------------- /src/_data/locales/en.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Post 7 | category: Category 8 | tag: Tag 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Home 14 | categories: Categories 15 | tags: Tags 16 | archives: Archives 17 | about: About 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: search 22 | cancel: Cancel 23 | no_results: Oops! No results found. 24 | 25 | panel: 26 | lastmod: Recently Updated 27 | trending_tags: Trending Tags 28 | toc: Contents 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: This post is licensed under :LICENSE_NAME by the author. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Some rights reserved. 39 | verbose: >- 40 | Except where otherwise noted, the blog posts on this site are licensed 41 | under the Creative Commons Attribution 4.0 International (CC BY 4.0) License by the author. 42 | 43 | meta: Using the :PLATFORM theme :THEME 44 | 45 | not_found: 46 | statment: Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. 47 | 48 | notification: 49 | update_found: A new version of content is available. 50 | update: Update 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: By 56 | posted: Posted 57 | updated: Updated 58 | words: words 59 | pageview_measure: views 60 | read_time: 61 | unit: min 62 | prompt: read 63 | relate_posts: Further Reading 64 | share: Share 65 | button: 66 | next: Newer 67 | previous: Older 68 | copy_code: 69 | succeed: Copied! 70 | share_link: 71 | title: Copy link 72 | succeed: Link copied successfully! 73 | 74 | # Date time format. 75 | # See: , 76 | df: 77 | post: 78 | strftime: "%b %e, %Y" 79 | dayjs: "ll" 80 | archives: 81 | strftime: "%b" 82 | dayjs: "MMM" 83 | 84 | # categories page 85 | categories: 86 | category_measure: 87 | singular: category 88 | plural: categories 89 | post_measure: 90 | singular: post 91 | plural: posts 92 | -------------------------------------------------------------------------------- /templates/modules/widgets/post-paginator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/_data/locales/fi-FI.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Julkaisu 7 | category: Kateogoria 8 | tag: Tagi 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Koti 14 | categories: Kateogoriat 15 | tags: Tagit 16 | archives: Arkistot 17 | about: Minusta 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: etsi 22 | cancel: Peruuta 23 | no_results: Hups! Ei tuloksia. 24 | 25 | panel: 26 | lastmod: Viimeksi päivitetty 27 | trending_tags: Trendaavat tagit 28 | toc: Sisältö 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Tämä julkaisu on lisenssoitu :LICENSE_NAME julkaisijan toimesta. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Jotkut oikeudet pidätetään. 39 | verbose: >- 40 | Paitsi jos erikseen mainitaan on kaikki sisältö Creative Commons Attribution 4.0 International (CC BY 4.0) Lisensoitu kirjoittajan toimesta. 41 | 42 | meta: Käytetään :PLATFORM iä Teema :THEME 43 | 44 | not_found: 45 | statment: Valitettavasti tällä URL-osoitteella ei ole saatavilla sisältöä. 46 | 47 | notification: 48 | update_found: Uusi versio sisällöstä on saatavilla. 49 | update: Päivitä 50 | 51 | # ----- Posts related labels ----- 52 | 53 | post: 54 | written_by: Kirjoittaja 55 | posted: Julkaistu 56 | updated: Päivitetty 57 | words: sanaa 58 | pageview_measure: katselukertoja 59 | read_time: 60 | unit: minuuttia 61 | prompt: lukea 62 | relate_posts: Jatka lukemista 63 | share: Jaa 64 | button: 65 | next: Uudempi 66 | previous: Vanhempi 67 | copy_code: 68 | succeed: Kopiotu! 69 | share_link: 70 | title: Kopioi linkki 71 | succeed: Linkki kopioitu onnistuneesti! 72 | 73 | # Date time format. 74 | # See: , 75 | df: 76 | post: 77 | strftime: "%b %e, %Y" 78 | dayjs: "ll" 79 | archives: 80 | strftime: "%b" 81 | dayjs: "MMM" 82 | 83 | # categories page 84 | categories: 85 | category_measure: 86 | singular: kategoria 87 | plural: kategoriat 88 | post_measure: 89 | singular: julkaisu 90 | plural: julkaisut 91 | -------------------------------------------------------------------------------- /src/_data/locales/sv-SE.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Inlägg #Post 7 | category: Kategori #Category 8 | tag: Tagga #Tag 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Hem #Home 14 | categories: Kategorier #Categories 15 | tags: Taggar #Tags 16 | archives: Arkiv #Archives 17 | about: Om #About 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: sök 22 | cancel: Avbryt 23 | no_results: Hoppsan! Hittade inga sökträffar. 24 | 25 | panel: 26 | lastmod: Senast uppdaterad 27 | trending_tags: Trendande taggar 28 | toc: Innehåll 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Den här posten är publicerad under licensen :LICENSE_NAME av författaren. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Vissa rättigheter är reserverade. 39 | verbose: >- 40 | Om inte annat anges är blogginläggen på denna webbplats licensierade 41 | under Creative Commons Attribution 4.0 International (CC BY 4.0) av författaren. 42 | 43 | meta: Byggd med :PLATFORM och temat :THEME 44 | 45 | not_found: 46 | statment: Ursäkta, vi har tappat bort den här webbadressen eller så pekar den på något som inte längre finns. 47 | 48 | notification: 49 | update_found: Det finns en ny version av innehållet. 50 | update: Uppdatera sidan 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Av 56 | posted: Postad 57 | updated: Uppdaterad 58 | words: ord 59 | pageview_measure: visningar 60 | read_time: 61 | unit: min 62 | prompt: läsning 63 | relate_posts: Mer läsning 64 | share: Dela 65 | button: 66 | next: Nyare 67 | previous: Äldre 68 | copy_code: 69 | succeed: Kopierat! 70 | share_link: 71 | title: Kopiera länk 72 | succeed: Länken har kopierats! 73 | 74 | # Date time format. 75 | # See: , 76 | df: 77 | post: 78 | strftime: "%b %e, %Y" 79 | dayjs: "ll" 80 | archives: 81 | strftime: "%b" 82 | dayjs: "MMM" 83 | 84 | # categories page 85 | categories: 86 | category_measure: 87 | singular: kategori 88 | plural: kategorier 89 | post_measure: 90 | singular: inlägg 91 | plural: inlägg 92 | -------------------------------------------------------------------------------- /src/_layouts/_includes/comments/giscus.html: -------------------------------------------------------------------------------- 1 | 2 | 65 | -------------------------------------------------------------------------------- /src/js/pwa/sw.js: -------------------------------------------------------------------------------- 1 | const cacheName = 'chirpy-{{ "now" | date: "%Y%m%d.%H%M%S" }}'; 2 | 3 | function verifyDomain(url) { 4 | for (const domain of allowedDomains) { 5 | const regex = RegExp(`^http(s)?:\/\/${domain}\/`); 6 | if (regex.test(url)) { 7 | return true; 8 | } 9 | } 10 | 11 | return false; 12 | } 13 | 14 | function isExcluded(url) { 15 | for (const item of denyUrls) { 16 | if (url === item) { 17 | return true; 18 | } 19 | } 20 | return false; 21 | } 22 | 23 | self.addEventListener('install', event => { 24 | event.waitUntil( 25 | caches.open(cacheName).then(cache => { 26 | return cache.addAll(resource); 27 | }) 28 | ); 29 | }); 30 | 31 | self.addEventListener('activate', event => { 32 | event.waitUntil( 33 | caches.keys().then(keyList => { 34 | return Promise.all( 35 | keyList.map(key => { 36 | if (key !== cacheName) { 37 | return caches.delete(key); 38 | } 39 | }) 40 | ); 41 | }) 42 | ); 43 | }); 44 | 45 | self.addEventListener('message', (event) => { 46 | if (event.data === 'SKIP_WAITING') { 47 | self.skipWaiting(); 48 | } 49 | }); 50 | 51 | self.addEventListener('fetch', event => { 52 | event.respondWith( 53 | caches.match(event.request).then(response => { 54 | if (response) { 55 | return response; 56 | } 57 | 58 | return fetch(event.request).then(response => { 59 | const url = event.request.url; 60 | 61 | if (event.request.method !== 'GET' || 62 | !verifyDomain(url) || 63 | isExcluded(url)) { 64 | return response; 65 | } 66 | 67 | /* 68 | see: 69 | */ 70 | let responseToCache = response.clone(); 71 | 72 | caches.open(cacheName).then(cache => { 73 | /* console.log('[sw] Caching new resource: ' + event.request.url); */ 74 | cache.put(event.request, responseToCache); 75 | }); 76 | 77 | return response; 78 | }); 79 | }) 80 | ); 81 | }); 82 | 83 | -------------------------------------------------------------------------------- /src/_data/locales/it-IT.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Post 7 | category: Categoria 8 | tag: Tag 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Pagina principale 14 | categories: Categorie 15 | tags: Tags 16 | archives: Archivio 17 | about: Informazioni 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: ricerca 22 | cancel: Cancella 23 | no_results: Oops! La ricerca non ha fornito risultati. 24 | 25 | panel: 26 | lastmod: Aggiornati recentemente 27 | trending_tags: Tags più cliccati 28 | toc: Contenuti 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Questo post è sotto licenza :LICENSE_NAME a nome dell'autore. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Alcuni diritti riservati. 39 | verbose: >- 40 | Eccetto quando esplicitamente menzionato, i post di questo blog sono da ritenersi sotto 41 | i termini di licenza Creative Commons Attribution 4.0 International (CC BY 4.0). 42 | 43 | meta: Servizio offerto da :PLATFORM con tema :THEME 44 | not_found: 45 | statment: Ci scusiamo, non è stato possibile trovare l'URL in questione. Potrebbe puntare ad una pagina non esistente. 46 | 47 | notification: 48 | update_found: Nuova versione del contenuto disponibile. 49 | update: Aggiornamento 50 | 51 | # ----- Posts related labels ----- 52 | 53 | post: 54 | written_by: Da 55 | posted: Postato 56 | updated: Aggiornato 57 | words: parole 58 | pageview_measure: visioni 59 | read_time: 60 | unit: min 61 | prompt: lettura 62 | relate_posts: Continua a leggere 63 | share: Condividi 64 | button: 65 | next: Più recenti 66 | previous: Meno recenti 67 | copy_code: 68 | succeed: Copiato! 69 | share_link: 70 | title: Copia link 71 | succeed: Link copiato con successo! 72 | 73 | # Date time format. 74 | # See: , 75 | df: 76 | post: 77 | strftime: "%b %e, %Y" 78 | dayjs: "ll" 79 | archives: 80 | strftime: "%b" 81 | dayjs: "MMM" 82 | 83 | # categories page 84 | categories: 85 | category_measure: 86 | singular: categoria 87 | plural: categorie 88 | post_measure: 89 | singular: post 90 | plural: posts 91 | -------------------------------------------------------------------------------- /src/_data/locales/el-GR.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Δημοσίευση 7 | category: Κατηγορία 8 | tag: Ετικέτα 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Home 14 | categories: Κατηγορίες 15 | tags: Ετικέτες 16 | archives: Αρχεία 17 | about: Σχετικά 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: αναζήτηση 22 | cancel: Ακύρωση 23 | no_results: Oops! Κανένα αποτέλεσμα δεν βρέθηκε. 24 | 25 | panel: 26 | lastmod: Σχετικά ενημερωμένα 27 | trending_tags: Ετικέτες τάσης 28 | toc: Περιεχόμενα 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Η δημοσίευση αυτή βρίσκεται υπο την άδεια :LICENSE_NAME Greekforce1821. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Ορισμένα δικαιώματα reserved. 39 | verbose: >- 40 | Εκτός αλλού ή οπουδήποτε αλλού, τα blog posts σε αυτήν την σελίδα βρίσκονται υπο την άδεια 41 | Creative Commons Attribution 4.0 International (CC BY 4.0) του δημιουργού. 42 | 43 | meta: Αξιοποιώντας την :PLATFORM theme :THEME 44 | 45 | not_found: 46 | statment: Συγνώμη, έχουμε τοποθετήσει λάθος αυτήν την διεύθυνση URL ή υποδεικνύει κάτι που δεν υπάρχει. 47 | 48 | notification: 49 | update_found: Υπάρχει διαθέσιμη μια νέα έκδοση του περιεχομένου. 50 | update: Ενημέρωση 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Από 56 | posted: Δημοσιεύθηκε 57 | updated: Ενημερώθηκε 58 | words: λέξεις 59 | pageview_measure: προβολές 60 | read_time: 61 | unit: Λεπτά 62 | prompt: διαβάσματος 63 | relate_posts: Περισσότερα 64 | share: Κοινοποιήστε 65 | button: 66 | next: Νεότερα 67 | previous: Παλαιότερα 68 | copy_code: 69 | succeed: Αντιγράφθηκε! 70 | share_link: 71 | title: Αντιγραφή συνδέσμου 72 | succeed: Η διεύθυνση αντιγράφθηκε με επιτυχία! 73 | 74 | # Date time format. 75 | # See: , 76 | df: 77 | post: 78 | strftime: "%b %e, %Y" 79 | dayjs: "ll" 80 | archives: 81 | strftime: "%b" 82 | dayjs: "MMM" 83 | 84 | # categories page 85 | categories: 86 | category_measure: 87 | singular: Κατηγορία 88 | plural: Κατηγορίες 89 | post_measure: 90 | singular: Δημοσίευση 91 | plural: Δημοσιεύσεις 92 | -------------------------------------------------------------------------------- /templates/modules/post/relatedPosts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 39 | 40 | 41 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /templates/modules/sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /src/_data/locales/sl-SI.yml: -------------------------------------------------------------------------------- 1 | # The layout text of site 2 | 3 | # ----- Commons label ----- 4 | 5 | layout: 6 | post: Objava #Post 7 | category: Kategorija #Category 8 | tag: Oznaka #Tag 9 | 10 | # The tabs of sidebar 11 | tabs: 12 | # format: : 13 | home: Domov #Home 14 | categories: Kategorije #Categories 15 | tags: Oznake #Tags 16 | archives: Arhiv #Archives 17 | about: O meni #About 18 | 19 | # the text displayed in the search bar & search results 20 | search: 21 | hint: išči #search 22 | cancel: Prekliči #Cancel 23 | no_results: Ups! Vsebina ni bila najdena #Oops! No results found. 24 | 25 | panel: 26 | lastmod: Nedavno Posodobljeno #Recently Updated 27 | trending_tags: Priljubljene Oznake #Trending Tags 28 | toc: Vsebina #Contents 29 | 30 | copyright: 31 | # Shown at the bottom of the post 32 | license: 33 | template: Ta objava je licencirana pod :LICENCE_NAME s strani avtorja. #This post is licensed under :LICENSE_NAME by the author. 34 | name: CC BY 4.0 35 | link: https://creativecommons.org/licenses/by/4.0/ 36 | 37 | # Displayed in the footer 38 | brief: Nekatere pravice pridržane. #Some rights reserved. 39 | verbose: >- 40 | Razen kjer navedeno drugače, vse objave spletnega dnevnika so licencirane 41 | pod Creative Commons Attribution 4.0 International (CC BY 4.0) s strani avtorja. 42 | 43 | meta: Uporabljena :PLATFORM tema :THEME #Using the :PLATFORM theme :THEME 44 | 45 | not_found: 46 | statment: Oprostite, hiperpovezava je neustrezna ali vsebina ne obstajata. #Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. 47 | 48 | notification: 49 | update_found: Novejša različica vsebine je na voljo. #A new version of content is available. 50 | update: Posodobi #Update 51 | 52 | # ----- Posts related labels ----- 53 | 54 | post: 55 | written_by: Od #By 56 | posted: Objavljeno #Posted 57 | updated: Posodobljeno #Updated 58 | words: besede #words 59 | pageview_measure: ogledi #views 60 | read_time: 61 | unit: min 62 | prompt: beri #read 63 | relate_posts: Nadaljnje branje #Further Reading 64 | share: Deli #Share 65 | button: 66 | next: Novejše #Newer 67 | previous: Starejše #Older 68 | copy_code: 69 | succeed: Kopirano! #Copied! 70 | share_link: 71 | title: Kopiraj povezavo #Copy link 72 | succeed: Povezava uspešno kopirana! #Link copied successfully! 73 | 74 | # Date time format. 75 | # See: , 76 | df: 77 | post: 78 | strftime: "%e %b, %Y" 79 | dayjs: "ll" 80 | archives: 81 | strftime: "%b" 82 | dayjs: "MMM" 83 | 84 | # categories page 85 | categories: 86 | category_measure: 87 | singular: kategorija #category 88 | plural: kategorije #categories 89 | post_measure: 90 | singular: objava #post 91 | plural: objave #posts 92 | -------------------------------------------------------------------------------- /src/_layouts/default.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: compress 3 | # Default layout 4 | --- 5 | 6 | 7 | 8 | {% include origin-type.html %} 9 | 10 | {% include lang.html %} 11 | 12 | {% capture prefer_mode %} 13 | {% if site.theme_mode %} 14 | data-mode="{{ site.theme_mode }}" 15 | {% endif %} 16 | {% endcapture %} 17 | 18 | {% if layout.tail_includes %} 19 | {% assign has_tail = true %} 20 | {% endif %} 21 | 22 | 23 | 24 | {% include head.html %} 25 | 26 | 27 | {% include sidebar.html lang=lang %} 28 | 29 |
30 |
31 | {% include topbar.html lang=lang %} 32 | 33 |
34 |
38 | {{ content }} 39 |
40 | 41 | 42 | 53 |
54 | 55 |
56 | 57 |
58 | {% if has_tail %} 59 | {% for _include in layout.tail_includes %} 60 | {% assign _include_path = _include | append: '.html' %} 61 | {% include {{ _include_path }} lang=lang %} 62 | {% endfor %} 63 | {% endif %} 64 | 65 | {% include_cached footer.html lang=lang %} 66 |
67 |
68 | 69 | {% include_cached search-results.html lang=lang %} 70 |
71 | 72 | 77 |
78 | 79 |
80 | 81 | {% if site.pwa.enabled %} 82 | {% include_cached notification.html lang=lang %} 83 | {% endif %} 84 | 85 | 86 | 87 | {% include js-selector.html %} 88 | 89 | {% if page.mermaid %} 90 | {% include mermaid.html %} 91 | {% endif %} 92 | 93 | {% include_cached search-loader.html %} 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/_layouts/_includes/topbar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
8 | 41 | 42 | 43 | 46 | 47 |
48 | {% if page.layout == 'home' %} 49 | {{- site.data.locales[include.lang].title | default: site.title -}} 50 | {% elsif page.collection == 'tabs' or page.layout == 'page' %} 51 | {%- capture tab_key -%}{{ page.url | split: '/' }}{%- endcapture -%} 52 | {{- site.data.locales[include.lang].tabs[tab_key] | default: page.title -}} 53 | {% else %} 54 | {{- site.data.locales[include.lang].layout[page.layout] | default: page.layout | capitalize -}} 55 | {% endif %} 56 |
57 | 58 | 61 | 62 | 63 | 64 | 72 | 73 | 76 |
77 |
78 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | [[#{breadcrumb.home}]] 9 | 10 | 11 | 12 |
13 | 70 |
71 | 72 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /settings.yaml: -------------------------------------------------------------------------------- 1 | # nonk8s 2 | apiVersion: v1alpha1 3 | kind: Setting 4 | metadata: 5 | name: halo-theme-chirpy-setting 6 | spec: 7 | forms: 8 | - group: basics 9 | label: 全局设置 10 | formSchema: 11 | - $formkit: radio 12 | name: enable_site_info 13 | label: 站点信息开关 14 | value: false 15 | help: 右侧侧栏下方是否显示站点信息(halo中定义的页脚) 16 | options: 17 | - label: 开启 18 | value: true 19 | - label: 关闭 20 | value: false 21 | - $formkit: text 22 | name: copyrightAgreement 23 | label: 版权协议 24 | value: "CC BY 4.0" 25 | - $formkit: url 26 | name: copyrightAgreementUrl 27 | label: 版权协议地址 28 | placeholder: 请输入版权协议地址 29 | value: "https://creativecommons.org/licenses/by/4.0/" 30 | - $formkit: text 31 | name: footerCopyrightAgreement 32 | label: 页脚版权协议 33 | value: "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." 34 | help: 页脚 "All rights reserved" 浮现时显示的版权协议 35 | 36 | - group: sidebar 37 | label: 侧栏 38 | formSchema: 39 | - $formkit: repeater 40 | name: socials 41 | label: 社交链接 42 | value: 43 | - icon: fab fa-github 44 | url: https://github.com/airbozh 45 | - icon: fab fa-twitter 46 | url: https://twitter.com/ 47 | - icon: fas fa-envelope 48 | url: mailto:i@airbozh.cn 49 | - icon: fas fa-rss 50 | url: /feed.xml 51 | max: 5 52 | children: 53 | - $formkit: text 54 | name: icon 55 | label: 图标 56 | value: "" 57 | required: true 58 | - $formkit: text 59 | name: url 60 | label: 链接 61 | value: "" 62 | required: true 63 | 64 | - group: post 65 | label: 文章 66 | formSchema: 67 | - $formkit: repeater 68 | name: share 69 | label: 分享设置 70 | value: 71 | - name: Telegram 72 | icon: fa-fw fab fa-telegram 73 | url: https://t.me/share/url?url=@URL 74 | - name: Facebook 75 | icon: fa-fw fab fa-facebook-square 76 | url: https://www.facebook.com/sharer/sharer.php?u=@URL 77 | - name: Twitter 78 | icon: fa-fw fa-brands fa-square-x-twitter 79 | url: https://twitter.com/intent/tweet?&url=@URL 80 | max: 5 81 | children: 82 | - $formkit: text 83 | name: name 84 | label: 名称 85 | value: "" 86 | required: true 87 | - $formkit: text 88 | name: icon 89 | label: 图标 90 | value: "" 91 | required: true 92 | - $formkit: text 93 | name: url 94 | label: 链接 95 | value: "" 96 | required: true 97 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 1>&2 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 48 | echo. 1>&2 49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 50 | echo location of your Java installation. 1>&2 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 1>&2 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 62 | echo. 1>&2 63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 64 | echo location of your Java installation. 1>&2 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /src/css/layout/archives.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Style for Archives 3 | */ 4 | 5 | #archives { 6 | letter-spacing: 0.03rem; 7 | 8 | $timeline-width: 4px; 9 | 10 | %timeline { 11 | content: ''; 12 | width: $timeline-width; 13 | position: relative; 14 | float: left; 15 | background-color: var(--timeline-color); 16 | } 17 | 18 | .year { 19 | height: 3.5rem; 20 | font-size: 1.5rem; 21 | position: relative; 22 | left: 2px; 23 | margin-left: -$timeline-width; 24 | 25 | &::before { 26 | @extend %timeline; 27 | 28 | height: 72px; 29 | left: 79px; 30 | bottom: 16px; 31 | } 32 | 33 | &:first-child::before { 34 | @extend %timeline; 35 | 36 | height: 32px; 37 | top: 24px; 38 | } 39 | 40 | /* Year dot */ 41 | &::after { 42 | content: ''; 43 | display: inline-block; 44 | position: relative; 45 | border-radius: 50%; 46 | width: 12px; 47 | height: 12px; 48 | left: 21.5px; 49 | border: 3px solid; 50 | background-color: var(--timeline-year-dot-color); 51 | border-color: var(--timeline-node-bg); 52 | box-shadow: 0 0 2px 0 #c2c6cc; 53 | z-index: 1; 54 | } 55 | } 56 | 57 | ul { 58 | li { 59 | font-size: 1.1rem; 60 | line-height: 3rem; 61 | white-space: nowrap; 62 | overflow: hidden; 63 | text-overflow: ellipsis; 64 | 65 | &:nth-child(odd) { 66 | background-color: var(--main-bg, #ffffff); 67 | background-image: linear-gradient( 68 | to left, 69 | #ffffff, 70 | #fbfbfb, 71 | #fbfbfb, 72 | #fbfbfb, 73 | #ffffff 74 | ); 75 | } 76 | 77 | &::before { 78 | @extend %timeline; 79 | 80 | top: 0; 81 | left: 77px; 82 | height: 3.1rem; 83 | } 84 | } 85 | 86 | &:last-child li:last-child::before { 87 | height: 1.5rem; 88 | } 89 | } /* #archives ul */ 90 | 91 | .date { 92 | white-space: nowrap; 93 | display: inline-block; 94 | position: relative; 95 | right: 0.5rem; 96 | 97 | &.month { 98 | width: 1.4rem; 99 | text-align: center; 100 | } 101 | 102 | &.day { 103 | font-size: 85%; 104 | font-family: Lato, sans-serif; 105 | } 106 | } 107 | 108 | a { 109 | /* post title in Archvies */ 110 | margin-left: 2.5rem; 111 | position: relative; 112 | top: 0.1rem; 113 | 114 | &:hover { 115 | border-bottom: none; 116 | } 117 | 118 | &::before { 119 | /* the dot before post title */ 120 | content: ''; 121 | display: inline-block; 122 | position: relative; 123 | border-radius: 50%; 124 | width: 8px; 125 | height: 8px; 126 | float: left; 127 | top: 1.35rem; 128 | left: 71px; 129 | background-color: var(--timeline-node-bg); 130 | box-shadow: 0 0 3px 0 #c2c6cc; 131 | z-index: 1; 132 | } 133 | } 134 | } /* #archives */ 135 | 136 | @media all and (max-width: 576px) { 137 | #archives { 138 | margin-top: -1rem; 139 | 140 | ul { 141 | letter-spacing: 0; 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/_layouts/_includes/related-posts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% assign TOTAL_SIZE = 3 %} 5 | 6 | 7 | {% assign TAG_SCORE = 1 %} 8 | 9 | 10 | {% assign CATEGORY_SCORE = 0.5 %} 11 | 12 | {% assign SEPARATOR = ':' %} 13 | 14 | {% assign match_posts = '' | split: '' %} 15 | 16 | {% for category in page.categories %} 17 | {% assign match_posts = match_posts | push: site.categories[category] | uniq %} 18 | {% endfor %} 19 | 20 | {% for tag in page.tags %} 21 | {% assign match_posts = match_posts | push: site.tags[tag] | uniq %} 22 | {% endfor %} 23 | 24 | {% assign last_index = match_posts.size | minus: 1 %} 25 | {% assign score_list = '' | split: '' %} 26 | 27 | {% for i in (0..last_index) %} 28 | {% assign post = match_posts[i] %} 29 | 30 | {% if post.url == page.url %} 31 | {% continue %} 32 | {% endif %} 33 | 34 | {% assign score = 0 %} 35 | 36 | {% for tag in post.tags %} 37 | {% if page.tags contains tag %} 38 | {% assign score = score | plus: TAG_SCORE %} 39 | {% endif %} 40 | {% endfor %} 41 | 42 | {% for category in post.categories %} 43 | {% if page.categories contains category %} 44 | {% assign score = score | plus: CATEGORY_SCORE %} 45 | {% endif %} 46 | {% endfor %} 47 | 48 | {% if score > 0 %} 49 | {% capture score_item %}{{ score }}{{ SEPARATOR }}{{ i }}{% endcapture %} 50 | {% assign score_list = score_list | push: score_item %} 51 | {% endif %} 52 | {% endfor %} 53 | 54 | {% assign index_list = '' | split: '' %} 55 | 56 | {% if score_list.size > 0 %} 57 | {% assign score_list = score_list | sort | reverse %} 58 | {% for entry in score_list limit: TOTAL_SIZE %} 59 | {% assign index = entry | split: SEPARATOR | last %} 60 | {% assign index_list = index_list | push: index %} 61 | {% endfor %} 62 | {% endif %} 63 | 64 | {% assign relate_posts = '' | split: '' %} 65 | 66 | {% for index in index_list %} 67 | {% assign i = index | to_integer %} 68 | {% assign relate_posts = relate_posts | push: match_posts[i] %} 69 | {% endfor %} 70 | 71 | {% if relate_posts.size > 0 %} 72 | 95 | 96 | {% endif %} 97 | -------------------------------------------------------------------------------- /src/_layouts/_includes/post-paginator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 91 | 92 | -------------------------------------------------------------------------------- /templates/modules/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | 18 | 19 | 20 | 23 | 24 | 25 | 28 | 29 | 30 | 33 | 34 | 35 | 38 | 39 | 40 | 43 | 44 | 45 | 48 | 49 | 50 | 53 | 54 | 55 |
56 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
69 | 70 |
71 |
72 |
73 | 74 | 75 | 82 |
83 |
84 | 85 |
86 | 87 |
88 |
89 |
90 | 91 | 100 |
101 |
102 | 103 | 104 | -------------------------------------------------------------------------------- /src/css/colors/syntax-dark.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * The syntax dark mode styles. 3 | */ 4 | 5 | @mixin dark-syntax { 6 | --language-border-color: #2d2d2d; 7 | --highlight-bg-color: #151515; 8 | --highlighter-rouge-color: #c9def1; 9 | --highlight-lineno-color: #808080; 10 | --inline-code-bg: #323238; 11 | --code-color: #b0b0b0; 12 | --code-header-text-color: #6a6a6a; 13 | --code-header-muted-color: #353535; 14 | --code-header-icon-color: #565656; 15 | --clipboard-checked-color: #2bcc2b; 16 | --filepath-text-color: #cacaca; 17 | 18 | .highlight .gp { 19 | color: #87939d; 20 | } 21 | 22 | .highlight table td { 23 | padding: 5px; 24 | } 25 | .highlight table pre { 26 | margin: 0; 27 | } 28 | 29 | /*! 30 | Theme: GitHub Dark 31 | Description: Dark theme as seen on github.com 32 | Author: github.com 33 | Maintainer: @Hirse 34 | Updated: 2021-05-15 35 | 36 | Outdated base version: https://github.com/primer/github-syntax-dark 37 | Current colors taken from GitHub's CSS 38 | */ 39 | .hljs { 40 | color: #c9d1d9; 41 | background: #0d1117 42 | } 43 | .hljs-doctag, 44 | .hljs-keyword, 45 | .hljs-meta .hljs-keyword, 46 | .hljs-template-tag, 47 | .hljs-template-variable, 48 | .hljs-type, 49 | .hljs-variable.language_ { 50 | /* prettylights-syntax-keyword */ 51 | color: #ff7b72 52 | } 53 | .hljs-title, 54 | .hljs-title.class_, 55 | .hljs-title.class_.inherited__, 56 | .hljs-title.function_ { 57 | /* prettylights-syntax-entity */ 58 | color: #d2a8ff 59 | } 60 | .hljs-attr, 61 | .hljs-attribute, 62 | .hljs-literal, 63 | .hljs-meta, 64 | .hljs-number, 65 | .hljs-operator, 66 | .hljs-variable, 67 | .hljs-selector-attr, 68 | .hljs-selector-class, 69 | .hljs-selector-id { 70 | /* prettylights-syntax-constant */ 71 | color: #79c0ff 72 | } 73 | .hljs-regexp, 74 | .hljs-string, 75 | .hljs-meta .hljs-string { 76 | /* prettylights-syntax-string */ 77 | color: #a5d6ff 78 | } 79 | .hljs-built_in, 80 | .hljs-symbol { 81 | /* prettylights-syntax-variable */ 82 | color: #ffa657 83 | } 84 | .hljs-comment, 85 | .hljs-code, 86 | .hljs-formula { 87 | /* prettylights-syntax-comment */ 88 | color: #8b949e 89 | } 90 | .hljs-name, 91 | .hljs-quote, 92 | .hljs-selector-tag, 93 | .hljs-selector-pseudo { 94 | /* prettylights-syntax-entity-tag */ 95 | color: #7ee787 96 | } 97 | .hljs-subst { 98 | /* prettylights-syntax-storage-modifier-import */ 99 | color: #c9d1d9 100 | } 101 | .hljs-section { 102 | /* prettylights-syntax-markup-heading */ 103 | color: #1f6feb; 104 | font-weight: bold 105 | } 106 | .hljs-bullet { 107 | /* prettylights-syntax-markup-list */ 108 | color: #f2cc60 109 | } 110 | .hljs-emphasis { 111 | /* prettylights-syntax-markup-italic */ 112 | color: #c9d1d9; 113 | font-style: italic 114 | } 115 | .hljs-strong { 116 | /* prettylights-syntax-markup-bold */ 117 | color: #c9d1d9; 118 | font-weight: bold 119 | } 120 | .hljs-addition { 121 | /* prettylights-syntax-markup-inserted */ 122 | color: #aff5b4; 123 | background-color: #033a16 124 | } 125 | .hljs-deletion { 126 | /* prettylights-syntax-markup-deleted */ 127 | color: #ffdcd7; 128 | background-color: #67060c 129 | } 130 | .hljs-char.escape_, 131 | .hljs-link, 132 | .hljs-params, 133 | .hljs-property, 134 | .hljs-punctuation, 135 | .hljs-tag { 136 | /* purposely ignored */ 137 | 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/_layouts/_includes/js-selector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 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 | 13 | 14 | {% if page.layout == 'post' or page.layout == 'page' or page.layout == 'home' %} 15 | {% assign urls = urls | append: ',' | append: site.data.origin[type].lazysizes.js %} 16 | 17 | {% unless page.layout == 'home' %} 18 | 19 | {% assign urls = urls 20 | | append: ',' 21 | | append: site.data.origin[type]['magnific-popup'].js 22 | | append: ',' 23 | | append: site.data.origin[type].clipboard.js 24 | %} 25 | {% endunless %} 26 | {% endif %} 27 | 28 | {% if page.layout == 'home' 29 | or page.layout == 'post' 30 | or page.layout == 'archives' 31 | or page.layout == 'category' 32 | or page.layout == 'tag' 33 | %} 34 | {% assign locale = site.lang | split: '-' | first %} 35 | 36 | {% assign urls = urls 37 | | append: ',' 38 | | append: site.data.origin[type].dayjs.js.common 39 | | append: ',' 40 | | append: site.data.origin[type].dayjs.js.locale 41 | | replace: ':LOCALE', locale 42 | | append: ',' 43 | | append: site.data.origin[type].dayjs.js.relativeTime 44 | | append: ',' 45 | | append: site.data.origin[type].dayjs.js.localizedFormat 46 | %} 47 | {% endif %} 48 | 49 | {% if page.content contains ' 70 | 71 | {% if page.math %} 72 | 73 | 90 | 91 | 92 | {% endif %} 93 | 94 | {% if jekyll.environment == 'production' %} 95 | 96 | {% if site.pwa.enabled %} 97 | 98 | {% else %} 99 | 100 | {% endif %} 101 | 102 | 103 | {% if site.google_analytics.id != empty and site.google_analytics.id %} 104 | {% include google-analytics.html %} 105 | {% endif %} 106 | {% endif %} 107 | -------------------------------------------------------------------------------- /src/css/colors/syntax-light.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * The syntax light mode code snippet colors. 3 | */ 4 | 5 | @mixin light-syntax { 6 | /* --- custom light colors --- */ 7 | --language-border-color: #ececec; 8 | --highlight-bg-color: #f6f8fa; 9 | --highlighter-rouge-color: #3f596f; 10 | --highlight-lineno-color: #9e9e9e; 11 | --inline-code-bg: #f6f6f7; 12 | --code-color: #3a3a3a; 13 | --code-header-text-color: #a3a3a3; 14 | --code-header-muted-color: #e5e5e5; 15 | --code-header-icon-color: #c9c8c8; 16 | --clipboard-checked-color: #43c743; 17 | 18 | [class^='prompt-'] { 19 | --inline-code-bg: #fbfafa; 20 | } 21 | 22 | .highlight table td { 23 | padding: 5px; 24 | } 25 | .highlight table pre { 26 | margin: 0; 27 | } 28 | 29 | /*! 30 | Theme: GitHub 31 | Description: Light theme as seen on github.com 32 | Author: github.com 33 | Maintainer: @Hirse 34 | Updated: 2021-05-15 35 | 36 | Outdated base version: https://github.com/primer/github-syntax-light 37 | Current colors taken from GitHub's CSS 38 | */ 39 | .hljs { 40 | color: #24292e; 41 | background: #ffffff 42 | } 43 | .hljs-doctag, 44 | .hljs-keyword, 45 | .hljs-meta .hljs-keyword, 46 | .hljs-template-tag, 47 | .hljs-template-variable, 48 | .hljs-type, 49 | .hljs-variable.language_ { 50 | /* prettylights-syntax-keyword */ 51 | color: #d73a49 52 | } 53 | .hljs-title, 54 | .hljs-title.class_, 55 | .hljs-title.class_.inherited__, 56 | .hljs-title.function_ { 57 | /* prettylights-syntax-entity */ 58 | color: #6f42c1 59 | } 60 | .hljs-attr, 61 | .hljs-attribute, 62 | .hljs-literal, 63 | .hljs-meta, 64 | .hljs-number, 65 | .hljs-operator, 66 | .hljs-variable, 67 | .hljs-selector-attr, 68 | .hljs-selector-class, 69 | .hljs-selector-id { 70 | /* prettylights-syntax-constant */ 71 | color: #005cc5 72 | } 73 | .hljs-regexp, 74 | .hljs-string, 75 | .hljs-meta .hljs-string { 76 | /* prettylights-syntax-string */ 77 | color: #032f62 78 | } 79 | .hljs-built_in, 80 | .hljs-symbol { 81 | /* prettylights-syntax-variable */ 82 | color: #e36209 83 | } 84 | .hljs-comment, 85 | .hljs-code, 86 | .hljs-formula { 87 | /* prettylights-syntax-comment */ 88 | color: #6a737d 89 | } 90 | .hljs-name, 91 | .hljs-quote, 92 | .hljs-selector-tag, 93 | .hljs-selector-pseudo { 94 | /* prettylights-syntax-entity-tag */ 95 | color: #22863a 96 | } 97 | .hljs-subst { 98 | /* prettylights-syntax-storage-modifier-import */ 99 | color: #24292e 100 | } 101 | .hljs-section { 102 | /* prettylights-syntax-markup-heading */ 103 | color: #005cc5; 104 | font-weight: bold 105 | } 106 | .hljs-bullet { 107 | /* prettylights-syntax-markup-list */ 108 | color: #735c0f 109 | } 110 | .hljs-emphasis { 111 | /* prettylights-syntax-markup-italic */ 112 | color: #24292e; 113 | font-style: italic 114 | } 115 | .hljs-strong { 116 | /* prettylights-syntax-markup-bold */ 117 | color: #24292e; 118 | font-weight: bold 119 | } 120 | .hljs-addition { 121 | /* prettylights-syntax-markup-inserted */ 122 | color: #22863a; 123 | background-color: #f0fff4 124 | } 125 | .hljs-deletion { 126 | /* prettylights-syntax-markup-deleted */ 127 | color: #b31d28; 128 | background-color: #ffeef0 129 | } 130 | .hljs-char.escape_, 131 | .hljs-link, 132 | .hljs-params, 133 | .hljs-property, 134 | .hljs-punctuation, 135 | .hljs-tag { 136 | /* purposely ignored */ 137 | 138 | } 139 | 140 | } /* light-syntax */ 141 | -------------------------------------------------------------------------------- /src/_layouts/_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | {% capture seo_tags %} 15 | {% seo title=false %} 16 | {% endcapture %} 17 | 18 | {% if page.image %} 19 | {% assign img = page.image.path | default: page.image %} 20 | 21 | {% unless img contains '://' %} 22 | {% assign img_path = page.img_path | append: '/' | append: img | replace: '//', '/' %} 23 | {% capture target %}"{{ img | absolute_url }}"{% endcapture %} 24 | 25 | {% if site.img_cdn contains '//' %} 26 | 27 | {% capture replacement %}"{{ site.img_cdn }}{{ img_path }}"{% endcapture %} 28 | {% else %} 29 | 30 | {%- capture replacement -%} 31 | "{{ site.img_cdn | append: '/' | append: img_path | replace: '//', '/' | absolute_url }}" 32 | {%- endcapture -%} 33 | {% endif %} 34 | 35 | {% assign seo_tags = seo_tags | replace: target, replacement %} 36 | {% endunless %} 37 | {% endif %} 38 | 39 | {{ seo_tags }} 40 | 41 | 42 | {%- unless page.layout == 'home' -%} 43 | {{ page.title | append: ' | ' }} 44 | {%- endunless -%} 45 | {{ site.title }} 46 | 47 | 48 | {% include_cached favicons.html %} 49 | 50 | {% if site.resources.ignore_env != jekyll.environment and site.resources.self_hosted %} 51 | 52 | 53 | {% else %} 54 | {% for cdn in site.data.origin[type].cdns %} 55 | 56 | 57 | {% endfor %} 58 | 59 | 60 | {% endif %} 61 | 62 | 63 | {% if jekyll.environment == 'production' and site.google_analytics.id != empty and site.google_analytics.id %} 64 | 65 | 66 | 67 | 68 | 69 | {% endif %} 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | {% if site.toc and page.toc %} 80 | 81 | {% endif %} 82 | 83 | {% if page.layout == 'page' or page.layout == 'post' %} 84 | 85 | 86 | {% endif %} 87 | 88 | 89 | 90 | {% unless site.theme_mode %} 91 | {% include mode-toggle.html %} 92 | {% endunless %} 93 | 94 | {% include metadata-hook.html %} 95 | 96 | -------------------------------------------------------------------------------- /src/js/patch/codeClass.js: -------------------------------------------------------------------------------- 1 | import hljs from 'highlight.js'; 2 | import 'highlight.js' 3 | 4 | export function codeClass() { 5 | document.addEventListener('DOMContentLoaded', function () { 6 | const codeElements = document.querySelectorAll('p code'); 7 | 8 | codeElements.forEach(function (codeElement) { 9 | codeElement.classList.add('language-plaintext', 'highlighter-rouge'); 10 | }); 11 | }); 12 | } 13 | 14 | export function codeBlock() { 15 | document.addEventListener('DOMContentLoaded', function () { 16 | const codeElements = document.querySelectorAll('pre code'); 17 | codeElements.forEach(function (codeElement) { 18 | let len = codeElement.innerHTML.split('\n').length + 1 19 | if (codeElement.innerHTML.at(-1) === '\n') len -= 1; 20 | buildCodeBlock(codeElement); 21 | hljs.highlightBlock(codeElement); 22 | codeElement.removeAttribute('class'); 23 | buildCodeTable(len, codeElement); 24 | }); 25 | }); 26 | } 27 | 28 | let buildCodeBlock = (codeElement) => { 29 | let language = codeElement.classList[0]? codeElement.classList[0] : 'language-plaintext'; 30 | 31 | let parentDivElement = document.createElement('div'); 32 | let headerDivElement = buildCodeBlockHeader(); 33 | let codeDivElement = document.createElement('div'); 34 | 35 | parentDivElement.classList.add(language, 'highlighter-rouge'); 36 | codeDivElement.classList.add('highlight'); 37 | parentDivElement.appendChild(headerDivElement); 38 | parentDivElement.appendChild(codeDivElement); 39 | codeElement.parentNode.appendChild(parentDivElement); 40 | codeDivElement.appendChild(codeElement); 41 | } 42 | 43 | let buildCodeTable = (len, codeElement) => { 44 | let table = document.createElement('table'); 45 | table.classList.add('rouge-table'); 46 | let tbody = document.createElement('tbody'); 47 | let tr = document.createElement('tr'); 48 | let lineNumTd = document.createElement('td'); 49 | lineNumTd.classList.add('rouge-gutter', 'gl'); 50 | let codeTd = document.createElement('td'); 51 | codeTd.classList.add('rouge-code'); 52 | let codePre = document.createElement('pre'); 53 | 54 | codePre.innerHTML = codeElement.innerHTML; 55 | codeElement.innerHTML = ''; 56 | 57 | lineNumTd.appendChild(buildLineNum(len)); 58 | tr.appendChild(lineNumTd); 59 | 60 | codeTd.appendChild(codePre); 61 | tr.appendChild(codeTd); 62 | 63 | tbody.appendChild(tr); 64 | table.appendChild(tbody); 65 | 66 | codeElement.appendChild(table); 67 | } 68 | 69 | let buildLineNum = (len) => { 70 | let lineNumPre = document.createElement('pre'); 71 | lineNumPre.classList.add('lineno'); 72 | for (let i = 1; i < len; i++) { 73 | lineNumPre.innerHTML += i + '\n'; 74 | } 75 | return lineNumPre; 76 | } 77 | 78 | let buildCodeBlockHeader = () => { 79 | let headerDivElement = document.createElement('div'); 80 | headerDivElement.classList.add('code-header'); 81 | 82 | let headSpan = document.createElement('span'); 83 | headSpan.setAttribute('data-label-text', 'Code'); 84 | let codeIcon = document.createElement('i'); 85 | codeIcon.classList.add('fas', 'fa-code', 'fa-fw', 'small'); 86 | headSpan.appendChild(codeIcon); 87 | let copyButton = document.createElement('button'); 88 | copyButton.setAttribute('aria-label', 'copy'); 89 | new bootstrap.Tooltip(copyButton, { 90 | placement: 'left', 91 | trigger: 'manual' 92 | }); 93 | copyButton.setAttribute('data-title-succeed', 'Copied!'); 94 | let clipboardIcon = document.createElement('i'); 95 | clipboardIcon.classList.add('far', 'fa-clipboard'); 96 | copyButton.appendChild(clipboardIcon); 97 | 98 | headerDivElement.appendChild(headSpan); 99 | headerDivElement.appendChild(copyButton); 100 | 101 | return headerDivElement; 102 | } 103 | -------------------------------------------------------------------------------- /src/js/modules/components/clipboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Clipboard functions 3 | * 4 | * Dependencies: 5 | * - popper.js (https://github.com/popperjs/popper-core) 6 | * - clipboard.js (https://github.com/zenorocha/clipboard.js) 7 | */ 8 | import ClipboardJS from "clipboard"; 9 | 10 | const clipboardSelector = '.code-header>button'; 11 | const ICON_SUCCESS = 'fas fa-check'; 12 | const ATTR_TIMEOUT = 'timeout'; 13 | const ATTR_TITLE_SUCCEED = 'data-title-succeed'; 14 | const ATTR_TITLE_ORIGIN = 'data-bs-original-title'; 15 | const TIMEOUT = 2000; // in milliseconds 16 | const ICON_DEFAULT = 'far fa-clipboard'; 17 | 18 | function isLocked(node) { 19 | if ($(node)[0].hasAttribute(ATTR_TIMEOUT)) { 20 | let timeout = $(node).attr(ATTR_TIMEOUT); 21 | if (Number(timeout) > Date.now()) { 22 | return true; 23 | } 24 | } 25 | return false; 26 | } 27 | 28 | function lock(node) { 29 | $(node).attr(ATTR_TIMEOUT, Date.now() + TIMEOUT); 30 | } 31 | 32 | function unlock(node) { 33 | $(node).removeAttr(ATTR_TIMEOUT); 34 | } 35 | 36 | function showTooltip(btn) { 37 | const succeedTitle = $(btn).attr(ATTR_TITLE_SUCCEED); 38 | $(btn).attr(ATTR_TITLE_ORIGIN, succeedTitle) 39 | bootstrap.Tooltip.getInstance(btn).show(); 40 | } 41 | 42 | function hideTooltip(btn) { 43 | bootstrap.Tooltip.getInstance(btn).hide(); 44 | $(btn).removeAttr(ATTR_TITLE_ORIGIN); 45 | } 46 | 47 | function setSuccessIcon(btn) { 48 | let btnNode = $(btn); 49 | let iconNode = btnNode.children(); 50 | iconNode.attr('class', ICON_SUCCESS); 51 | } 52 | 53 | function resumeIcon(btn) { 54 | let btnNode = $(btn); 55 | let iconNode = btnNode.children(); 56 | iconNode.attr('class', ICON_DEFAULT); 57 | } 58 | 59 | export function initClipboard() { 60 | // Initial the clipboard.js object 61 | if ($(clipboardSelector)) { 62 | const clipboard = new ClipboardJS(clipboardSelector, { 63 | target(trigger) { 64 | let codeBlock = trigger.parentNode.nextElementSibling; 65 | return codeBlock.querySelector('code .rouge-code'); 66 | } 67 | }); 68 | 69 | const clipboardList = document.querySelectorAll(clipboardSelector); 70 | [...clipboardList].map( 71 | (elem) => 72 | new bootstrap.Tooltip(elem, { 73 | placement: 'left' 74 | }) 75 | ); 76 | 77 | clipboard.on('success', (e) => { 78 | e.clearSelection(); 79 | 80 | const trigger = e.trigger; 81 | if (isLocked(trigger)) { 82 | return; 83 | } 84 | 85 | setSuccessIcon(trigger); 86 | showTooltip(trigger); 87 | lock(trigger); 88 | 89 | setTimeout(() => { 90 | hideTooltip(trigger); 91 | resumeIcon(trigger); 92 | unlock(trigger); 93 | }, TIMEOUT); 94 | }); 95 | } 96 | 97 | /* --- Post link sharing --- */ 98 | 99 | const btnCopyLink = $('#copy-link'); 100 | 101 | btnCopyLink.on('click', (e) => { 102 | let target = $(e.target); 103 | 104 | if (isLocked(target)) { 105 | return; 106 | } 107 | 108 | // Copy URL to clipboard 109 | navigator.clipboard.writeText(window.location.href).then(() => { 110 | const defaultTitle = target.attr(ATTR_TITLE_ORIGIN); 111 | const succeedTitle = target.attr(ATTR_TITLE_SUCCEED); 112 | // Switch tooltip title 113 | target.attr(ATTR_TITLE_ORIGIN, succeedTitle); 114 | bootstrap.Tooltip.getInstance(target).show(); 115 | lock(target); 116 | 117 | setTimeout(() => { 118 | target.attr(ATTR_TITLE_ORIGIN, defaultTitle); 119 | unlock(target); 120 | }, TIMEOUT); 121 | }); 122 | }); 123 | 124 | btnCopyLink.on('mouseleave', function (e) { 125 | const target = $(e.target); 126 | bootstrap.Tooltip.getInstance(target).hide(); 127 | }); 128 | } 129 | -------------------------------------------------------------------------------- /src/css/addon/module.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * Mainly scss modules, only imported to `assets/css/main.scss` 3 | */ 4 | 5 | /* ---------- scss placeholder --------- */ 6 | 7 | %heading { 8 | color: var(--heading-color); 9 | font-weight: 400; 10 | font-family: $font-family-heading; 11 | } 12 | 13 | %section { 14 | main & { 15 | margin-top: 2.5rem; 16 | margin-bottom: 1.25rem; 17 | 18 | &:focus { 19 | outline: none; /* avoid outline in Safari */ 20 | } 21 | } 22 | } 23 | 24 | %anchor { 25 | .anchor { 26 | font-size: 80%; 27 | } 28 | 29 | @media (hover: hover) { 30 | .anchor { 31 | visibility: hidden; 32 | opacity: 0; 33 | transition: opacity 0.25s ease-in, visibility 0s ease-in 0.25s; 34 | } 35 | 36 | &:hover { 37 | .anchor { 38 | visibility: visible; 39 | opacity: 1; 40 | transition: opacity 0.25s ease-in, visibility 0s ease-in 0s; 41 | } 42 | } 43 | } 44 | } 45 | 46 | %tag-hover { 47 | background: var(--tag-hover); 48 | transition: background 0.35s ease-in-out; 49 | } 50 | 51 | %table-cell { 52 | padding: 0.4rem 1rem; 53 | font-size: 95%; 54 | white-space: nowrap; 55 | } 56 | 57 | %link-hover { 58 | color: #d2603a !important; 59 | border-bottom: 1px solid #d2603a; 60 | text-decoration: none; 61 | } 62 | 63 | %link-color { 64 | color: var(--link-color); 65 | } 66 | 67 | %link-underline { 68 | border-bottom: 1px solid var(--link-underline-color); 69 | } 70 | 71 | %clickable-transition { 72 | transition: all 0.3s ease-in-out; 73 | } 74 | 75 | %no-cursor { 76 | -webkit-user-select: none; 77 | -moz-user-select: none; 78 | -ms-user-select: none; 79 | user-select: none; 80 | } 81 | 82 | %no-bottom-border { 83 | border-bottom: none; 84 | } 85 | 86 | %cursor-pointer { 87 | cursor: pointer; 88 | } 89 | 90 | %normal-font-style { 91 | font-style: normal; 92 | } 93 | 94 | %rounded { 95 | border-radius: $base-radius; 96 | } 97 | 98 | %img-caption { 99 | + em { 100 | display: block; 101 | text-align: center; 102 | font-style: normal; 103 | font-size: 80%; 104 | padding: 0; 105 | color: #6d6c6c; 106 | } 107 | } 108 | 109 | %sidebar-links { 110 | color: var(--sidebar-muted-color); 111 | -webkit-user-select: none; 112 | -moz-user-select: none; 113 | -ms-user-select: none; 114 | user-select: none; 115 | } 116 | 117 | %text-clip { 118 | display: -webkit-box; 119 | overflow: hidden; 120 | text-overflow: ellipsis; 121 | -webkit-line-clamp: 2; 122 | -webkit-box-orient: vertical; 123 | } 124 | 125 | %text-highlight { 126 | color: inherit; 127 | font-weight: 600; 128 | } 129 | 130 | /* ---------- scss mixin --------- */ 131 | 132 | @mixin mt-mb($value) { 133 | margin-top: $value; 134 | margin-bottom: $value; 135 | } 136 | 137 | @mixin ml-mr($value) { 138 | margin-left: $value; 139 | margin-right: $value; 140 | } 141 | 142 | @mixin pt-pb($val) { 143 | padding-top: $val; 144 | padding-bottom: $val; 145 | } 146 | 147 | @mixin pl-pr($val) { 148 | padding-left: $val; 149 | padding-right: $val; 150 | } 151 | 152 | @mixin placeholder { 153 | color: var(--text-muted-color) !important; 154 | } 155 | 156 | @mixin placeholder-focus { 157 | opacity: 0.6; 158 | } 159 | 160 | @mixin label($font-size: 1rem, $font-weight: 600, $color: var(--label-color)) { 161 | color: $color; 162 | font-size: $font-size; 163 | font-weight: $font-weight; 164 | } 165 | 166 | @mixin align-center { 167 | position: relative; 168 | left: 50%; 169 | transform: translateX(-50%); 170 | } 171 | 172 | @mixin prompt($type, $fa-content, $fa-style: 'solid') { 173 | &.prompt-#{$type} { 174 | background-color: var(--prompt-#{$type}-bg); 175 | 176 | &::before { 177 | content: $fa-content; 178 | color: var(--prompt-#{$type}-icon-color); 179 | font: var(--fa-font-#{$fa-style}); 180 | } 181 | } 182 | } 183 | --------------------------------------------------------------------------------