├── .all-contributorsrc ├── .editorconfig ├── .env ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ └── issue.yaml └── workflows │ └── build.yaml ├── .gitignore ├── .husky └── pre-commit ├── LICENSE ├── README.md ├── annotation-setting.yaml ├── docs └── image.png ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── prettier.config.js ├── screenshot.png ├── settings.yaml ├── src ├── css │ ├── common │ │ ├── architecture │ │ │ ├── base.css │ │ │ ├── buttons.css │ │ │ ├── iconify.css │ │ │ ├── index.css │ │ │ ├── inputs.css │ │ │ ├── links.css │ │ │ ├── normalize.css │ │ │ ├── scrollbar.css │ │ │ └── tables.css │ │ ├── components │ │ │ ├── aplayer.css │ │ │ ├── back-to-top.css │ │ │ ├── card.css │ │ │ ├── change-skin.css │ │ │ ├── clearer.css │ │ │ ├── highlight │ │ │ │ ├── copy-code.css │ │ │ │ ├── highlight.css │ │ │ │ └── index.css │ │ │ ├── index.css │ │ │ ├── lazyload.css │ │ │ ├── loading.css │ │ │ ├── nprogress.css │ │ │ ├── page-header.css │ │ │ ├── pagination │ │ │ │ ├── index.css │ │ │ │ ├── pagination-list.css │ │ │ │ └── pagination-post.css │ │ │ ├── post │ │ │ │ ├── index.css │ │ │ │ ├── layout.css │ │ │ │ ├── post-author-profile.css │ │ │ │ ├── post-body.css │ │ │ │ ├── post-content-toast.css │ │ │ │ ├── post-footer.css │ │ │ │ ├── post-list-standard.css │ │ │ │ ├── post-list-thumb.css │ │ │ │ ├── post-meta.css │ │ │ │ └── post-none.css │ │ │ ├── screen │ │ │ │ ├── img-box │ │ │ │ │ ├── focus-tou.css │ │ │ │ │ ├── index.css │ │ │ │ │ ├── info.css │ │ │ │ │ ├── layout.css │ │ │ │ │ └── social.css │ │ │ │ ├── index.css │ │ │ │ ├── top-down.css │ │ │ │ ├── video-box │ │ │ │ │ ├── index.css │ │ │ │ │ └── layout.css │ │ │ │ └── wave.css │ │ │ ├── search-form.css │ │ │ ├── sharelike.css │ │ │ └── toc.css │ │ ├── index.css │ │ └── outline │ │ │ ├── comment.css │ │ │ ├── content │ │ │ ├── index.css │ │ │ ├── layout.css │ │ │ ├── main.css │ │ │ └── sidebar.css │ │ │ ├── footer │ │ │ ├── copyright.css │ │ │ ├── device.css │ │ │ ├── index.css │ │ │ ├── layout.css │ │ │ └── logo.css │ │ │ ├── header │ │ │ ├── brand.css │ │ │ ├── index.css │ │ │ ├── layout.css │ │ │ ├── menu.css │ │ │ ├── nav-toggle.css │ │ │ ├── search.css │ │ │ └── user.css │ │ │ ├── index.css │ │ │ └── sidebar │ │ │ ├── index.css │ │ │ ├── layout.css │ │ │ └── mobile-sidebar.css │ ├── main.css │ ├── mixins.css │ ├── theme │ │ ├── archives │ │ │ ├── content.css │ │ │ └── index.css │ │ ├── author │ │ │ ├── header.css │ │ │ └── index.css │ │ ├── categories │ │ │ ├── content.css │ │ │ └── index.css │ │ ├── category │ │ │ ├── header.css │ │ │ └── index.css │ │ ├── error │ │ │ ├── 404.css │ │ │ └── index.css │ │ ├── home │ │ │ ├── content.css │ │ │ ├── header.css │ │ │ ├── index.css │ │ │ ├── notice.css │ │ │ └── top-feature.css │ │ ├── index.css │ │ ├── link │ │ │ ├── content.css │ │ │ └── index.css │ │ ├── moments │ │ │ ├── content.css │ │ │ └── index.css │ │ ├── page │ │ │ ├── header.css │ │ │ └── index.css │ │ ├── photos │ │ │ ├── content.css │ │ │ ├── index.css │ │ │ ├── style-justify.css │ │ │ └── style-masonry.css │ │ ├── post │ │ │ ├── header.css │ │ │ └── index.css │ │ ├── search │ │ │ ├── index.css │ │ │ ├── search-box.css │ │ │ └── search-moment.css │ │ ├── tag │ │ │ ├── header.css │ │ │ └── index.css │ │ └── tags │ │ │ ├── content.css │ │ │ └── index.css │ └── variables │ │ ├── aplayer.css │ │ ├── index.css │ │ ├── layout.css │ │ └── moments.css ├── env.d.ts ├── languages │ ├── README.md │ ├── en.json │ ├── ja.json │ └── zh.json ├── libs │ ├── highlight │ │ ├── highlight-AndroidStudio.css │ │ ├── highlight-Dark.css │ │ ├── highlight-Docco.css │ │ ├── highlight-Dracula.css │ │ ├── highlight-Far.css │ │ ├── highlight-Github.css │ │ └── highlight-Tomorrow Night.css │ ├── highlightjs-line-numbers.js │ ├── lazysizes.ts │ └── pjax.ts ├── main.ts ├── module │ ├── events.ts │ ├── index.ts │ └── utils.ts ├── page │ ├── archives.ts │ ├── categories.ts │ ├── category.ts │ ├── index.ts │ ├── moments.ts │ ├── photos.ts │ ├── post.ts │ ├── search.ts │ └── tags.ts └── utils │ ├── eventProxy.ts │ ├── haloApi.ts │ ├── i18nFormat.ts │ ├── toast.ts │ └── util.ts ├── templates ├── .DS_Store ├── archives.html ├── assets │ ├── .DS_Store │ ├── cursor │ │ ├── No_Disponible.cur │ │ ├── ayuda.cur │ │ ├── normal.cur │ │ ├── texto.cur │ │ └── work.cur │ ├── dist │ │ ├── assets │ │ │ ├── APlayer.min-1b5a4167.js │ │ │ ├── Axis-725f4b2a.js │ │ │ ├── _commonjsHelpers-042e6b4d.js │ │ │ ├── browser-21db0a97.js │ │ │ ├── charts-f05d9f95.js │ │ │ ├── clipboard-8ef9d310.js │ │ │ ├── components-6d07079e.js │ │ │ ├── core-72662ce9.js │ │ │ ├── createSeriesData-c8f251b5.js │ │ │ ├── customGraphicKeyframeAnimation-c31f2f6f.js │ │ │ ├── en-7f095189.js │ │ │ ├── graphic-ce8bd673.js │ │ │ ├── index-5fe31283.js │ │ │ ├── index-bd7fc044.js │ │ │ ├── index-c0aec26a.js │ │ │ ├── index.esm-e5442572.js │ │ │ ├── isotope-c78448f5.js │ │ │ ├── ja-2b96dfd8.js │ │ │ ├── nprogress-2b5a08a9.js │ │ │ ├── renderers-f58e1b15.js │ │ │ ├── video.es-db0fa9e7.js │ │ │ └── zh-1c561d08.js │ │ ├── css │ │ │ ├── APlayer.min-2.4.3.min.css │ │ │ ├── fancybox-2.4.3.min.css │ │ │ ├── font-awesome-animation.min-2.4.3.min.css │ │ │ ├── highlight-AndroidStudio-2.4.3.min.css │ │ │ ├── highlight-Dark-2.4.3.min.css │ │ │ ├── highlight-Docco-2.4.3.min.css │ │ │ ├── highlight-Dracula-2.4.3.min.css │ │ │ ├── highlight-Far-2.4.3.min.css │ │ │ ├── highlight-Github-2.4.3.min.css │ │ │ ├── highlight-Tomorrow Night-2.4.3.min.css │ │ │ └── main-2.4.3.min.css │ │ ├── libs │ │ │ ├── highlightjs-line-numbers-2.4.3.min.js │ │ │ ├── lazysizes-2.4.3.min.js │ │ │ └── pjax-2.4.3.min.js │ │ ├── main-2.4.3.min.js │ │ └── page │ │ │ ├── archives-2.4.3.min.js │ │ │ ├── categories-2.4.3.min.js │ │ │ ├── category-2.4.3.min.js │ │ │ ├── index-2.4.3.min.js │ │ │ ├── moments-2.4.3.min.js │ │ │ ├── photos-2.4.3.min.js │ │ │ ├── post-2.4.3.min.js │ │ │ ├── search-2.4.3.min.js │ │ │ └── tags-2.4.3.min.js │ ├── images │ │ ├── default │ │ │ ├── avatar.webp │ │ │ ├── hd.webp │ │ │ └── temp.webp │ │ ├── email │ │ │ ├── head.webp │ │ │ └── hr.png │ │ ├── footer │ │ │ ├── gongan.png │ │ │ └── sakura.svg │ │ ├── load │ │ │ ├── load.gif │ │ │ ├── orange.progress-bar-stripe-loader.svg │ │ │ ├── rotating-ball-o.svg │ │ │ └── trans.ajax-spinner-preloader.svg │ │ ├── next-b.svg │ │ ├── scroll.png │ │ ├── search │ │ │ └── iloli.gif │ │ ├── sns │ │ │ ├── bilibili.png │ │ │ ├── csdn.png │ │ │ ├── douban.png │ │ │ ├── email.svg │ │ │ ├── facebook.png │ │ │ ├── github.png │ │ │ ├── googleplus.png │ │ │ ├── heart.png │ │ │ ├── jianshu.png │ │ │ ├── linkedin.png │ │ │ ├── lofter.png │ │ │ ├── qq.png │ │ │ ├── qzone.png │ │ │ ├── rss.png │ │ │ ├── sina.png │ │ │ ├── stackoverflow.svg │ │ │ ├── telegram.svg │ │ │ ├── twitter.png │ │ │ ├── wangyiyun.png │ │ │ ├── wechat.png │ │ │ ├── weibo.png │ │ │ ├── youku.png │ │ │ └── zhihu.png │ │ ├── themes │ │ │ ├── gribs.jpg │ │ │ ├── grid.png │ │ │ ├── kyotoanimation.png │ │ │ ├── little-monster.png │ │ │ ├── sakura.png │ │ │ └── star02.png │ │ ├── video │ │ │ ├── pause@32x32.png │ │ │ └── play@32x32.png │ │ └── wave │ │ │ ├── wave1.png │ │ │ └── wave2.png │ └── js │ │ └── 404.js ├── author.html ├── categories.html ├── category.html ├── error │ └── 404.html ├── index.html ├── layout.html ├── links.html ├── macro │ ├── content-links.html │ ├── content-masonry-photos.html │ ├── content-none.html │ ├── content-page.html │ ├── content-post.html │ ├── content-thumb.html │ ├── content.html │ ├── page-header.html │ └── sidebar.html ├── module │ ├── authorprofile.html │ ├── comment.html │ ├── feature.html │ ├── footer.html │ ├── head │ │ ├── fonts.html │ │ └── index.html │ ├── header │ │ ├── brand.html │ │ ├── index.html │ │ ├── menu-item.html │ │ ├── menu.html │ │ ├── nav-toggle.html │ │ ├── search.html │ │ └── user.html │ ├── home │ │ ├── focus_tou.html │ │ ├── go_down.html │ │ ├── img_box.html │ │ ├── index.html │ │ ├── notice.html │ │ ├── top_social.html │ │ ├── video_box.html │ │ └── wave.html │ ├── list-pagination.html │ ├── photo │ │ └── group.html │ ├── post-pagination.html │ ├── post │ │ └── post-meta.html │ ├── search │ │ ├── search-item.html │ │ └── search-moment.html │ ├── sharelike.html │ ├── sidebar │ │ ├── index.html │ │ └── mobile-sidebar.html │ ├── variables │ │ ├── index.html │ │ ├── layout.html │ │ ├── moments.html │ │ ├── photos.html │ │ └── post.html │ └── widgets │ │ ├── cd-top.html │ │ ├── index.html │ │ ├── search-modal.html │ │ └── theme-change.html ├── moment.html ├── moments.html ├── page.html ├── page_links.html ├── photos.html ├── post.html ├── scripts │ ├── index.html │ └── noscript.html ├── search.html ├── tag.html └── tags.html ├── theme.yaml ├── tsconfig.json ├── vite-env.d.ts └── vite.config.ts /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "projectName": "halo-theme-sakura", 3 | "projectOwner": "LIlGG", 4 | "repoType": "github", 5 | "repoHost": "https://github.com", 6 | "files": [ 7 | "README.md" 8 | ], 9 | "imageSize": 100, 10 | "contributorsPerLine": 7, 11 | "contributors": [ 12 | { 13 | "login": "LIlGG", 14 | "name": "Takagi", 15 | "avatar_url": "https://avatars2.githubusercontent.com/u/31335418?v=4", 16 | "profile": "https://lixingyong.com", 17 | "contributions": [ 18 | "code", 19 | "doc", 20 | "example" 21 | ] 22 | }, 23 | { 24 | "login": "ruibaby", 25 | "name": "Ryan Wang", 26 | "avatar_url": "https://avatars2.githubusercontent.com/u/21301288?v=4", 27 | "profile": "https://ryanc.cc", 28 | "contributions": [ 29 | "design", 30 | "ideas" 31 | ] 32 | }, 33 | { 34 | "login": "parasomn1a", 35 | "name": "Parasomnia", 36 | "avatar_url": "https://avatars2.githubusercontent.com/u/22992947?v=4", 37 | "profile": "https://mashiro.best", 38 | "contributions": [ 39 | "code", 40 | "design" 41 | ] 42 | }, 43 | { 44 | "login": "mashirozx", 45 | "name": "Mashiro", 46 | "avatar_url": "https://avatars2.githubusercontent.com/u/16148054?v=4", 47 | "profile": "https://2heng.xin", 48 | "contributions": [ 49 | "design", 50 | "ideas" 51 | ] 52 | }, 53 | { 54 | "login": "ShiinaKin", 55 | "name": "mashirot", 56 | "avatar_url": "https://avatars.githubusercontent.com/u/52254895?v=4", 57 | "profile": "https://github.com/ShiinaKin", 58 | "contributions": [ 59 | "code" 60 | ] 61 | }, 62 | { 63 | "login": "Terryisthebest", 64 | "name": "Terryliu", 65 | "avatar_url": "https://avatars.githubusercontent.com/u/140528909?v=4", 66 | "profile": "https://github.com/Terryisthebest", 67 | "contributions": [ 68 | "financial" 69 | ] 70 | }, 71 | { 72 | "login": "Yaklo", 73 | "name": "Yaklo", 74 | "avatar_url": "https://avatars.githubusercontent.com/u/50908861?v=4", 75 | "profile": "http://yaklo.skyesc.com", 76 | "contributions": [ 77 | "code" 78 | ] 79 | }, 80 | { 81 | "login": "AR-26710", 82 | "name": "流萤", 83 | "avatar_url": "https://avatars.githubusercontent.com/u/172995357?v=4", 84 | "profile": "http://houxiongxiong.icu", 85 | "contributions": [ 86 | "code" 87 | ] 88 | } 89 | ], 90 | "commitType": "docs", 91 | "commitConvention": "angular" 92 | } 93 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | [*] 7 | indent_style = space 8 | indent_size = 2 9 | tab_width = 2 10 | end_of_line = lf 11 | charset = utf-8 12 | trim_trailing_whitespace = false 13 | insert_final_newline = false 14 | max_line_length = 120 15 | 16 | [{*.htm, *.html, *.sht, *.shtm, *.shtml}] 17 | ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3 18 | ij_html_align_attributes = true 19 | ij_html_align_text = false 20 | ij_html_attribute_wrap = normal 21 | ij_html_block_comment_at_first_column = true 22 | ij_html_do_not_align_children_of_min_lines = 0 23 | ij_html_do_not_break_if_inline_tags = title, h1, h2, h3, h4, h5, h6, p 24 | ij_html_do_not_indent_children_of_tags = html, body, thead, tbody, tfoot 25 | ij_html_enforce_quotes = false 26 | ij_html_inline_tags = a, abbr, acronym, b, basefont, bdo, big, br, cite, cite, code, dfn, em, font, i, img, input, kbd, label, q, s, samp, select, small, span, strike, strong, sub, sup, textarea, tt, u, var 27 | ij_html_keep_blank_lines = 2 28 | ij_html_keep_indents_on_empty_lines = false 29 | ij_html_keep_line_breaks = true 30 | ij_html_keep_line_breaks_in_text = true 31 | ij_html_keep_whitespaces = false 32 | ij_html_keep_whitespaces_inside = span, pre, textarea 33 | ij_html_line_comment_at_first_column = true 34 | ij_html_new_line_after_last_attribute = never 35 | ij_html_new_line_before_first_attribute = never 36 | ij_html_quote_style = double 37 | ij_html_remove_new_line_before_tags = br 38 | ij_html_space_after_tag_name = false 39 | ij_html_space_around_equality_in_attribute = false 40 | ij_html_space_inside_empty_tag = false 41 | ij_html_text_wrap = normal -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | VITE_THEME_VERSION=2.4.3 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue.yaml: -------------------------------------------------------------------------------- 1 | name: 问题或建议 2 | description: 提交一个新的 ISSUE 3 | body: 4 | - type: markdown 5 | id: environment 6 | attributes: 7 | value: "## 环境信息" 8 | - type: input 9 | id: version-sakura 10 | validations: 11 | required: true 12 | attributes: 13 | label: "目前使用的 Sakura 版本?" 14 | - type: input 15 | id: version-halo 16 | validations: 17 | required: true 18 | attributes: 19 | label: "目前使用的 halo 版本?" 20 | - type: input 21 | id: web_address 22 | attributes: 23 | label: "网站地址" 24 | description: "提交问题时尽量携带,方便进行排查。" 25 | - type: markdown 26 | id: details 27 | attributes: 28 | value: "## 详细信息" 29 | - type: textarea 30 | id: what-happened 31 | attributes: 32 | label: "建议/问题" 33 | description: "有建议或者问题可以写在这里" 34 | validations: 35 | required: true 36 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: resource-build-actions 2 | on: 3 | push: 4 | branches: 5 | - main 6 | paths-ignore: 7 | - 'docs/**' 8 | - '**.md' 9 | - 'templates/**' 10 | pull_request: 11 | branches: 12 | - main 13 | paths-ignore: 14 | - 'docs/**' 15 | - '**.md' 16 | - 'templates/**' 17 | 18 | jobs: 19 | build: 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - name: Check Out Repo 24 | uses: actions/checkout@v4 25 | 26 | - name: Setup Node.js 27 | uses: actions/setup-node@v4 28 | with: 29 | node-version: 22 30 | 31 | - name: Setup pnpm 32 | uses: pnpm/action-setup@v4 33 | with: 34 | run_install: false 35 | 36 | - name: Get pnpm store directory 37 | id: pnpm-cache 38 | run: echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT 39 | 40 | - name: Setup pnpm cache 41 | uses: actions/cache@v3 42 | with: 43 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 44 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('pnpm-lock.yaml') }} 45 | restore-keys: | 46 | ${{ runner.os }}-pnpm-store- 47 | 48 | - name: Install Dependencies 49 | run: pnpm install 50 | 51 | - name: Build Theme 52 | run: pnpm build 53 | 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .settings/ 3 | .classpath 4 | bin/ 5 | .mymetadata 6 | .project 7 | .externalToolBuilders/ 8 | .tern-project 9 | *.bak 10 | 11 | #IDEA 12 | .idea 13 | *.iml 14 | *rebel.xml 15 | .flattened-pom.xml 16 | .factorypath 17 | 18 | node_modules 19 | 20 | #VS Code 21 | .vscode -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm build 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) u3u (https://qwq.cat) 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 | -------------------------------------------------------------------------------- /annotation-setting.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1alpha1 2 | kind: AnnotationSetting 3 | metadata: 4 | generateName: annotation-setting- 5 | spec: 6 | targetRef: 7 | group: "" 8 | kind: MenuItem 9 | formSchema: 10 | - $formkit: "text" 11 | name: "icon" 12 | label: "图标" 13 | help: "图标名称,支持所有 iconify 图标。例如 https://icones.netlify.app/" 14 | - $formkit: "text" 15 | name: "animation" 16 | label: "动画" 17 | help: "对图标所使用的微动画,支持的类型查看 https://l-lin.github.io/font-awesome-animation/#animation-list" 18 | --- 19 | 20 | apiVersion: v1alpha1 21 | kind: AnnotationSetting 22 | metadata: 23 | generateName: annotation-setting- 24 | spec: 25 | targetRef: 26 | group: content.halo.run 27 | kind: Post 28 | formSchema: 29 | - $formkit: checkbox 30 | name: randomImage 31 | label: 使用随机封面 32 | value: "true" 33 | on-value: "true" 34 | off-value: "false" 35 | - $formkit: checkbox 36 | name: original 37 | label: 原创文章 38 | value: "false" 39 | on-value: "true" 40 | off-value: "false" 41 | - $formkit: checkbox 42 | name: toc 43 | label: 自动生成目录 44 | value: "true" 45 | on-value: "true" 46 | off-value: "false" 47 | - $formkit: checkbox 48 | name: post_license 49 | id: post_license 50 | label: 自定义授权协议 51 | value: "false" 52 | on-value: "true" 53 | off-value: "false" 54 | - $formkit: text 55 | if: "$get(post_license).value == 'true'" 56 | name: post_license_text 57 | label: 授权协议 58 | - $formkit: text 59 | if: "$get(post_license).value == 'true'" 60 | name: post_license_url 61 | label: 协议链接 62 | 63 | --- 64 | 65 | apiVersion: v1alpha1 66 | kind: AnnotationSetting 67 | metadata: 68 | generateName: annotation-setting- 69 | spec: 70 | targetRef: 71 | group: content.halo.run 72 | kind: SinglePage 73 | formSchema: 74 | - $formkit: checkbox 75 | name: randomImage 76 | label: 使用随机图 77 | value: "true" 78 | on-value: "true" 79 | off-value: "false" 80 | 81 | - $formkit: checkbox 82 | name: toc 83 | label: 自动生成目录 84 | value: "true" 85 | on-value: "true" 86 | off-value: "false" 87 | 88 | --- 89 | 90 | apiVersion: v1alpha1 91 | kind: AnnotationSetting 92 | metadata: 93 | generateName: annotation-setting- 94 | spec: 95 | targetRef: 96 | group: "" 97 | kind: User 98 | formSchema: 99 | - $formkit: attachment 100 | name: cover 101 | label: 用户详情页封面图 -------------------------------------------------------------------------------- /docs/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/docs/image.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "halo-theme-sakura", 3 | "private": true, 4 | "description": "Halo 版本的樱花🌸主题", 5 | "scripts": { 6 | "dev": "vite build --watch --mode development", 7 | "build": "tsc && vite build", 8 | "lint": "eslint ./src --ext .js,.cjs,.mjs,.ts,.cts,.mts --ignore-path .gitignore", 9 | "prettier": "prettier --write './src/**/*.{js,ts,css,json,ml,yaml,html}' './templates/**/*.html'", 10 | "prepare": "husky install" 11 | }, 12 | "keywords": [ 13 | "halo", 14 | "sakura", 15 | "LIlGG", 16 | "takagi", 17 | "theme-sakura", 18 | "halo-theme", 19 | "halo-theme-sakura" 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/LIlGG/halo-theme-sakura" 24 | }, 25 | "author": { 26 | "name": "LIlGG", 27 | "url": "https://github.com/LIlGG", 28 | "email": "mail@e.lixingyong.com" 29 | }, 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/LIlGG/halo-theme-sakura/issues" 33 | }, 34 | "homepage": "https://github.com/LIlGG/halo-theme-sakura#readme", 35 | "maintainers": [ 36 | { 37 | "name": "LIlGG", 38 | "url": "https://github.com/LIlGG", 39 | "email": "mail@e.lixingyong.com" 40 | } 41 | ], 42 | "devDependencies": { 43 | "@iconify/iconify": "^3.1.0", 44 | "@iconify/json": "^2.2.75", 45 | "@types/node": "^20.2.5", 46 | "@types/video.js": "^7.3.52", 47 | "all-contributors-cli": "^6.26.1", 48 | "autoprefixer": "^10.4.14", 49 | "colorguard": "^1.2.1", 50 | "glob": "^10.2.7", 51 | "husky": "^8.0.3", 52 | "pjax": "^0.2.8", 53 | "postcss": "^8.4.24", 54 | "postcss-custom-properties": "^13.2.0", 55 | "postcss-mixins": "^9.0.4", 56 | "postcss-nesting": "^10.2.0", 57 | "prettier": "^2.8.8", 58 | "typescript": "^5.1.3", 59 | "vite": "^4.3.9", 60 | "vite-plugin-purge-icons": "^0.9.2" 61 | }, 62 | "dependencies": { 63 | "@fancyapps/ui": "^5.0.19", 64 | "@types/nprogress": "^0.2.0", 65 | "aplayer": "^1.10.1", 66 | "clipboard": "^2.0.11", 67 | "d3": "^7.8.5", 68 | "d3-cloud": "^1.2.5", 69 | "echarts": "^5.4.2", 70 | "font-awesome-animation": "^1.1.1", 71 | "highlight.js": "^11.8.0", 72 | "i18next": "^22.5.1", 73 | "i18next-browser-languagedetector": "^7.0.2", 74 | "i18next-chained-backend": "^4.3.0", 75 | "i18next-localstorage-backend": "^4.1.1", 76 | "isotope-layout": "^3.0.6", 77 | "lazysizes": "^5.3.2", 78 | "loc-i18next": "^0.1.5", 79 | "lodash.clonedeep": "^4.5.0", 80 | "nprogress": "^0.2.0", 81 | "qrcode": "^1.5.3", 82 | "tocbot": "^4.21.0", 83 | "video.js": "^8.3.0" 84 | }, 85 | "packageManager": "pnpm@9.15.1+sha512.1acb565e6193efbebda772702950469150cf12bcc764262e7587e71d19dc98a423dff9536e57ea44c49bdf790ff694e83c27be5faa23d67e0c033b583be4bfcf" 86 | } 87 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Postcss 插件说明。 3 | * postcss-mixins (https://github.com/postcss/postcss-mixins) -- 用于书写通用的 css mixins,使响应式等操作更加通用化。 4 | * postcss-nesting (https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting) -- 基于 CSS Nesting 语法规范的嵌套语法。 5 | * postcss-custom-properties (https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-custom-properties) -- 支持自定义 css 变量。 6 | * colorguard (https://github.com/SlexAxton/css-colorguard) -- 检查是否具有相似的颜色 7 | * autoprefixer (https://github.com/postcss/autoprefixer) -- 添加浏览器前缀。 8 | * 9 | */ 10 | module.exports = { 11 | plugins: [ 12 | require('postcss-mixins'), 13 | require('postcss-nesting'), 14 | require('postcss-custom-properties'), 15 | // colorguard 对于透明度无法识别,所以在处理时需要注意。 16 | // require('colorguard'), 17 | require('autoprefixer') 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | tabWidth: 2, 4 | useTabs: false, 5 | endOfLine: "lf", 6 | }; 7 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/screenshot.png -------------------------------------------------------------------------------- /src/css/common/architecture/buttons.css: -------------------------------------------------------------------------------- 1 | button { 2 | margin: 0; 3 | overflow: visible; 4 | font: inherit; 5 | cursor: pointer; 6 | border: 1px solid; 7 | border-color: #ccc #ccc #b0b0b0; 8 | border-radius: 3px; 9 | background: #ddd; 10 | box-shadow: none; 11 | color: rgba(0, 0, 0, 0.8); 12 | font-size: 0.75rem; 13 | line-height: 1; 14 | padding: 0.6em 1em 0.4em; 15 | text-transform: none; 16 | -webkit-appearance: button; 17 | 18 | @mixin pc-hover { 19 | &:hover { 20 | border-color: #b0b0b0 #b0b0b0 #b0b0b0; 21 | box-shadow: none; 22 | } 23 | 24 | &:focus { 25 | border-color: #b0b0b0 #b0b0b0 #b0b0b0; 26 | box-shadow: none; 27 | } 28 | 29 | &:active { 30 | border-color: #b0b0b0 #b0b0b0 #b0b0b0; 31 | box-shadow: none; 32 | } 33 | } 34 | } 35 | 36 | button[disabled] { 37 | cursor: default; 38 | } 39 | 40 | button::-moz-focus-inner { 41 | border: 0; 42 | padding: 0; 43 | } 44 | -------------------------------------------------------------------------------- /src/css/common/architecture/iconify.css: -------------------------------------------------------------------------------- 1 | .iconify { 2 | display: inline-block; 3 | position: relative; 4 | vertical-align: middle; 5 | font-size: 1em; 6 | height: 1em; 7 | width: 1em; 8 | 9 | &.iconify--small { 10 | font-size: 0.875em; 11 | } 12 | 13 | &.iconify--large { 14 | font-size: 1.25em; 15 | } 16 | 17 | &.iconify--xlarge { 18 | font-size: 1.5em; 19 | } 20 | 21 | &.iconify--xxlarge { 22 | font-size: 2em; 23 | } 24 | } -------------------------------------------------------------------------------- /src/css/common/architecture/index.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Sakura 基础架构。规范化 CSS 及初始化各标签。只建议处理 HTML 自带标签的 CSS。 3 | */ 4 | /* 规范化 */ 5 | @import "normalize.css"; 6 | 7 | /* 基础,例如 body,html 等通用标签 */ 8 | @import "base.css"; 9 | 10 | @import "inputs.css"; 11 | 12 | @import "links.css"; 13 | 14 | /* 按钮 */ 15 | @import "buttons.css"; 16 | 17 | /* 表格 */ 18 | @import "tables.css"; 19 | 20 | @import "scrollbar.css"; 21 | 22 | @import "iconify.css"; -------------------------------------------------------------------------------- /src/css/common/architecture/inputs.css: -------------------------------------------------------------------------------- 1 | input { 2 | font-size: 1rem; 3 | font: inherit; 4 | margin: 0; 5 | line-height: normal; 6 | } 7 | 8 | input:-webkit-autofill { 9 | -webkit-box-shadow: 0 0 0px 1000px white inset; 10 | } 11 | 12 | input[type="button"], 13 | input[type="reset"], 14 | input[type="submit"] { 15 | cursor: pointer; 16 | border: 1px solid; 17 | border-color: #ccc #ccc #b0b0b0; 18 | border-radius: 3px; 19 | background: #ddd; 20 | box-shadow: none; 21 | color: rgba(0, 0, 0, 0.8); 22 | font-size: 0.75rem; 23 | line-height: 1; 24 | padding: 0.6em 1em 0.4em; 25 | -webkit-appearance: button; 26 | 27 | &:hover { 28 | border-color: #ccc #b0b0b0 #b0b0b0; 29 | box-shadow: none; 30 | } 31 | 32 | &:focus, 33 | &:active { 34 | border-color: #b0b0b0 #b0b0b0 #b0b0b0; 35 | box-shadow: none; 36 | } 37 | } 38 | 39 | input[disabled] { 40 | cursor: default; 41 | } 42 | 43 | input::-moz-focus-inner { 44 | border: 0; 45 | padding: 0; 46 | } 47 | 48 | input[type="checkbox"], 49 | input[type="radio"] { 50 | box-sizing: border-box; 51 | padding: 0; 52 | } 53 | 54 | input[type="number"]::-webkit-inner-spin-button, 55 | input[type="number"]::-webkit-outer-spin-button { 56 | height: auto; 57 | } 58 | 59 | input[type="search"]::-webkit-search-cancel-button, 60 | input[type="search"]::-webkit-search-decoration { 61 | -webkit-appearance: none; 62 | } 63 | 64 | input[type="text"], 65 | input[type="email"], 66 | input[type="url"], 67 | input[type="password"], 68 | input[type="search"], 69 | input[type="number"], 70 | input[type="tel"], 71 | input[type="range"], 72 | input[type="date"], 73 | input[type="month"], 74 | input[type="week"], 75 | input[type="time"], 76 | input[type="datetime"], 77 | input[type="datetime-local"], 78 | input[type="color"] { 79 | color: var(--color); 80 | border: 1px solid #ccc; 81 | border-radius: 3px; 82 | padding: 3px; 83 | 84 | &:focus { 85 | color: #000000; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/css/common/architecture/links.css: -------------------------------------------------------------------------------- 1 | a { 2 | background-color: transparent; 3 | text-decoration: none; 4 | color: #e67474; 5 | outline: none; 6 | cursor: var(--cursor-link); 7 | transition: color 0.2s ease-out, border 0.2s ease-out, opacity 0.2s ease-out; 8 | 9 | &:focus, 10 | &:active, 11 | &:hover { 12 | outline: none; 13 | color: var(--theme-color); 14 | } 15 | 16 | &:active { 17 | cursor: var(--cursor-link-active); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/css/common/architecture/scrollbar.css: -------------------------------------------------------------------------------- 1 | ::-webkit-scrollbar { 2 | width: 0.375rem; 3 | height: 0.375rem; 4 | background-color: #eee; 5 | } 6 | 7 | ::-webkit-scrollbar-track { 8 | background-color: #eee; 9 | } 10 | 11 | ::-webkit-scrollbar-thumb { 12 | background-color: var(--theme-color); 13 | } -------------------------------------------------------------------------------- /src/css/common/architecture/tables.css: -------------------------------------------------------------------------------- 1 | table { 2 | border-collapse: collapse; 3 | border-spacing: 0; 4 | width: 100%; 5 | } 6 | -------------------------------------------------------------------------------- /src/css/common/components/aplayer.css: -------------------------------------------------------------------------------- 1 | .aplayer { 2 | 3 | &.aplayer-fixed { 4 | background: var(--aplayer-background-color); 5 | color: var(--aplayer-color); 6 | 7 | & .aplayer-list { 8 | border: var(--aplayer-list-border) !important; 9 | 10 | & ol { 11 | & li { 12 | border-top: var(--aplayer-list-top-border); 13 | 14 | &:hover { 15 | background: var(--aplayer-list-hover-background-color); 16 | } 17 | 18 | &.aplayer-list-light { 19 | background: var(--aplayer-list-light-background-color) !important; 20 | } 21 | 22 | & .aplayer-list-author { 23 | color: var(--aplayer-list-author-color); 24 | } 25 | } 26 | } 27 | } 28 | 29 | & .aplayer-body { 30 | background: var(--aplayer-background-color) !important; 31 | color: var(--aplayer-color); 32 | 33 | & .aplayer-info { 34 | border-top: var(--aplayer-list-top-border); 35 | 36 | & .aplayer-controller { 37 | & .aplayer-time { 38 | & .aplayer-icon { 39 | &:hover { 40 | & path { 41 | fill: var(--theme-color); 42 | } 43 | } 44 | } 45 | } 46 | } 47 | } 48 | 49 | & .aplayer-miniswitcher { 50 | background: var(--aplayer-body-miniswitcher-background-color); 51 | color: var(--aplayer-color); 52 | 53 | &:hover { 54 | & path { 55 | fill: var(--theme-color); 56 | } 57 | } 58 | } 59 | } 60 | 61 | & .aplayer-lrc { 62 | text-shadow: var(--aplayer-lrc-text-shadow); 63 | } 64 | } 65 | 66 | & .aplayer-list { 67 | & ol { 68 | &::-webkit-scrollbar-thumb { 69 | background-color: var(--theme-color) !important; 70 | 71 | &:hover { 72 | background-color: var(--theme-color) !important; 73 | } 74 | } 75 | } 76 | } 77 | 78 | & .aplayer-lrc { 79 | pointer-events: none; 80 | 81 | &::before, 82 | &::after { 83 | background: rgba(255, 255, 255, 0); 84 | filter: none; 85 | } 86 | 87 | & .aplayer-lrc-current { 88 | color: var(--theme-color); 89 | font-size: 15px; 90 | font-weight: bold; 91 | } 92 | } 93 | 94 | & .aplayer-icon, 95 | & .aplayer-miniswitcher { 96 | border-radius: 0 6px 6px 0 !important; 97 | } 98 | } 99 | 100 | .aplayer-narrow { 101 | & .ap-hover { 102 | border-radius: 0 6px 6px 0 !important; 103 | left: -66px !important; 104 | 105 | @mixin pc-hover { 106 | &:hover { 107 | left: 0 !important; 108 | } 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /src/css/common/components/back-to-top.css: -------------------------------------------------------------------------------- 1 | .cd-top { 2 | display: var(--cd-top-display); 3 | z-index: 9; 4 | position: fixed; 5 | top: -900px; 6 | right: 1.5rem; 7 | width: 4.5rem; 8 | height: 900px; 9 | background-size: contain; 10 | transition: all 0.5s ease-in-out; 11 | opacity: 1; 12 | background: var(--cd-top-image); 13 | cursor: var(--cursor-hover); 14 | 15 | &.cd-is-visible { 16 | top: -326px; 17 | } 18 | 19 | &:hover, 20 | &.cd-fade-out, 21 | &.cd-is-visible { 22 | opacity: 1; 23 | } 24 | 25 | & span { 26 | display: none; 27 | color: #000; 28 | position: absolute; 29 | bottom: 0; 30 | height: 20px; 31 | width: 50px; 32 | text-align: center; 33 | } 34 | 35 | @media screen and (max-width: 860px) { 36 | display: none; 37 | height: 60px; 38 | width: 50px; 39 | 40 | & span { 41 | height: 10px; 42 | width: 50px; 43 | } 44 | } 45 | } 46 | 47 | .m-cd-top { 48 | display: var(--mobile-cd-top-display); 49 | bottom: var(--mobile-cd-top-bottom); 50 | opacity: 0; 51 | position: fixed; 52 | font-size: 1rem; 53 | right: 10px; 54 | width: 3rem; 55 | height: 3rem; 56 | z-index: 9; 57 | border: 0; 58 | outline: 0; 59 | background-color: var(--widget-background-color); 60 | color: var(--theme-color); 61 | cursor: pointer; 62 | padding: 1rem; 63 | border-radius: 8px; 64 | box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.12), 0px 2px 2px 0px rgba(0, 0, 0, 0.24); 65 | overflow: hidden; 66 | transition: all 0.3s ease; 67 | pointer-events: none; 68 | 69 | &.cd-is-visible { 70 | opacity: 1; 71 | pointer-events: auto; 72 | } 73 | 74 | @media screen and (max-width: 860px) { 75 | display: flex; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/css/common/components/card.css: -------------------------------------------------------------------------------- 1 | .card-container { 2 | position: relative; 3 | text-align: center; 4 | border: 0; 5 | border-radius: 10px; 6 | color: rgba(0, 0, 0, 0.87); 7 | background: var(--background-color); 8 | background-size: cover; 9 | box-shadow: var(--card-container-box-shadow); 10 | 11 | & .chip-container { 12 | & .card-content { 13 | padding: 1.5rem; 14 | border-radius: 0 0 2px 2px; 15 | 16 | & .chip { 17 | margin: 0.625rem; 18 | padding: 1.25rem; 19 | display: inline-flex; 20 | line-height: 0; 21 | font-size: 1rem; 22 | font-weight: 500; 23 | border-radius: 5px; 24 | cursor: pointer; 25 | box-shadow: 0 3px 5px rgba(0, 0, 0, 0.12); 26 | z-index: 0; 27 | 28 | &:hover { 29 | color: #fff; 30 | background: linear-gradient(to right, #4cbf30 0%, #0f9d58 100%); 31 | } 32 | 33 | &.chip-default { 34 | color: #34495e; 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/css/common/components/clearer.css: -------------------------------------------------------------------------------- 1 | .clearer { 2 | display: block; 3 | clear: both; 4 | } -------------------------------------------------------------------------------- /src/css/common/components/highlight/copy-code.css: -------------------------------------------------------------------------------- 1 | span { 2 | &.copy-code { 3 | color: #fff; 4 | position: absolute; 5 | right: 0.625em; 6 | display: inline-table; 7 | top: 0.375em; 8 | padding-right: 0.125em; 9 | font-size: 1rem; 10 | z-index: 1; 11 | 12 | &:hover { 13 | color: rgba(255, 255, 255, 0.5); 14 | } 15 | 16 | &::after { 17 | display: none; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/css/common/components/highlight/index.css: -------------------------------------------------------------------------------- 1 | @import "highlight.css"; 2 | 3 | @import "copy-code.css"; -------------------------------------------------------------------------------- /src/css/common/components/index.css: -------------------------------------------------------------------------------- 1 | @import "loading.css"; 2 | 3 | /* 分页 */ 4 | @import "pagination"; 5 | 6 | /* 回到顶部小工具 */ 7 | @import "back-to-top.css"; 8 | 9 | @import "aplayer.css"; 10 | 11 | @import "lazyload.css"; 12 | 13 | @import "change-skin.css"; 14 | 15 | @import "search-form.css"; 16 | 17 | @import "screen"; 18 | 19 | @import "post"; 20 | 21 | @import "highlight"; 22 | 23 | @import "page-header.css"; 24 | 25 | @import "sharelike.css"; 26 | 27 | @import "card.css"; 28 | 29 | @import "clearer.css"; 30 | 31 | @import "nprogress.css"; 32 | 33 | @import "toc.css"; 34 | -------------------------------------------------------------------------------- /src/css/common/components/lazyload.css: -------------------------------------------------------------------------------- 1 | .lazyload { 2 | filter: blur(0px); 3 | transition: 0.3s filter linear, 0.3s -webkit-filter linear; 4 | } 5 | 6 | .lazyload[src*="#lazyload-blur"], 7 | .lazyload[style*="#lazyload-blur"] { 8 | filter: blur(10px); 9 | } 10 | 11 | .blur-up { 12 | filter: blur(5px); 13 | transition: filter 400ms; 14 | 15 | &.lazyloaded { 16 | filter: blur(0); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/css/common/components/loading.css: -------------------------------------------------------------------------------- 1 | .loading { 2 | width: 1.75rem; 3 | height: 1.75rem; 4 | background-position: center; 5 | background-repeat: no-repeat; 6 | color: #504e4e; 7 | border: none; 8 | background-size: auto 100%; 9 | box-shadow: none; 10 | background-color: inherit; 11 | background-image: var(--loading-image); 12 | } -------------------------------------------------------------------------------- /src/css/common/components/nprogress.css: -------------------------------------------------------------------------------- 1 | #nprogress { 2 | pointer-events: none; 3 | z-index: 10; 4 | position: absolute; 5 | 6 | & .bar { 7 | background: var(--theme-color); 8 | position: fixed; 9 | z-index: 10; 10 | top: 0; 11 | left: 0; 12 | width: 100%; 13 | height: 3px; 14 | 15 | & .peg { 16 | display: block; 17 | position: absolute; 18 | right: 0; 19 | width: 100px; 20 | height: 100%; 21 | box-shadow: 0 0 10px var(--theme-color), 0 0 5px var(--theme-color); 22 | opacity: 1; 23 | transform: rotate(3deg) translate(0px, -4px); 24 | } 25 | } 26 | 27 | & .spinner { 28 | display: block; 29 | position: fixed; 30 | z-index: 10; 31 | top: 1.625rem; 32 | right: 1.5rem; 33 | left: inherit; 34 | width: auto; 35 | height: auto; 36 | margin: 0; 37 | 38 | & .spinner-icon { 39 | width: 1.25rem; 40 | height: 1.25rem; 41 | box-sizing: border-box; 42 | border: solid 3px transparent; 43 | border-top-color: var(--theme-color); 44 | border-left-color: var(--theme-color); 45 | border-radius: 50%; 46 | animation: nprogress-spinner 0.4s linear infinite; 47 | } 48 | } 49 | } 50 | 51 | .nprogress-custom-parent { 52 | overflow: hidden; 53 | position: relative; 54 | 55 | & #nprogress { 56 | & .spinner, 57 | & .bar { 58 | position: absolute; 59 | } 60 | } 61 | } 62 | 63 | @keyframes nprogress-spinner { 64 | 0% { 65 | transform: rotate(0deg); 66 | } 67 | 68 | 100% { 69 | transform: rotate(360deg); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/css/common/components/pagination/index.css: -------------------------------------------------------------------------------- 1 | @import "pagination-list.css"; 2 | 3 | @import "pagination-post.css"; -------------------------------------------------------------------------------- /src/css/common/components/pagination/pagination-list.css: -------------------------------------------------------------------------------- 1 | .list-pagination { 2 | width: 100%; 3 | text-align: center; 4 | display: inline-block; 5 | margin: 5rem 0; 6 | 7 | & a { 8 | padding: 0.6rem 2.5rem; 9 | border: 1px solid #ccc; 10 | border-radius: 3rem; 11 | color: #b0b0b0; 12 | display: inline-block; 13 | 14 | &:hover { 15 | border: 1px solid var(--theme-color); 16 | color: var(--theme-color); 17 | box-shadow: 0 0 4px var(--theme-color); 18 | } 19 | 20 | &.loading { 21 | border: none; 22 | box-shadow: none; 23 | } 24 | } 25 | 26 | & span { 27 | color: #999; 28 | font-size: 1rem; 29 | } 30 | } 31 | 32 | .list-navigator { 33 | text-align: center; 34 | margin: 4rem 0; 35 | display: block; 36 | 37 | & a { 38 | display: inline-flex; 39 | justify-content: center; 40 | align-items: center; 41 | height: 3rem; 42 | width: 3rem; 43 | padding: 0.625rem; 44 | border: 2px solid #ddd; 45 | border-radius: 50%; 46 | box-sizing: border-box; 47 | 48 | &:hover { 49 | color: #fff; 50 | background: var(--theme-color); 51 | border: 2px solid var(--theme-color); 52 | transition: all 0.2s ease-in-out; 53 | } 54 | } 55 | 56 | & .iconify { 57 | font-size: 1em; 58 | color: #ccc; 59 | } 60 | 61 | @mixin screens-md { 62 | margin: 0; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/css/common/components/pagination/pagination-post.css: -------------------------------------------------------------------------------- 1 | .post-pagination { 2 | overflow: hidden; 3 | width: 100%; 4 | margin: 3rem 0; 5 | background: #000; 6 | display: flex; 7 | 8 | & .pagination-container { 9 | position: relative; 10 | flex: 1; 11 | height: 10rem; 12 | 13 | & a { 14 | display: inline-block; 15 | height: 100%; 16 | width: 100%; 17 | } 18 | 19 | & img { 20 | width: 100%; 21 | height: 100%; 22 | object-fit: cover; 23 | opacity: 0.4; 24 | transition: opacity 0.15s ease-out; 25 | &:hover { 26 | opacity: 0.6; 27 | } 28 | } 29 | 30 | & .label, 31 | & .info { 32 | position: absolute; 33 | font-size: 0.875rem; 34 | } 35 | 36 | & .label { 37 | top: 2.5em; 38 | display: block; 39 | text-transform: uppercase; 40 | color: rgba(255, 255, 255, 0.7); 41 | } 42 | 43 | & .info { 44 | bottom: 2.5em; 45 | 46 | & h3 { 47 | font-size: 1rem; 48 | font-weight: 400; 49 | line-height: 2rem; 50 | margin: 2em 0; 51 | color: #fff; 52 | overflow: hidden; 53 | white-space: nowrap; 54 | text-overflow: ellipsis; 55 | } 56 | } 57 | } 58 | 59 | & .previous { 60 | & .label, 61 | & .info { 62 | left: 2.5em; 63 | } 64 | } 65 | 66 | & .next { 67 | & .label, 68 | & .info { 69 | right: 2.5em; 70 | } 71 | } 72 | 73 | @mixin screens-md { 74 | flex-direction: column; 75 | 76 | & .pagination-container { 77 | flex: auto; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/css/common/components/post/index.css: -------------------------------------------------------------------------------- 1 | @import "layout.css"; 2 | 3 | @import "post-list-standard.css"; 4 | 5 | @import "post-list-thumb.css"; 6 | 7 | @import "post-none.css"; 8 | 9 | @import "post-meta.css"; 10 | 11 | @import "post-body.css"; 12 | 13 | @import "post-footer.css"; 14 | 15 | @import "post-author-profile.css"; 16 | 17 | @import "post-content-toast.css"; 18 | 19 | @keyframes main { 20 | 0% { 21 | opacity: 0; 22 | transform: translateY(50px); 23 | } 24 | 25 | 100% { 26 | opacity: 1; 27 | transform: translateY(0); 28 | } 29 | } -------------------------------------------------------------------------------- /src/css/common/components/post/layout.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | & a { 3 | color: #504e4e; 4 | 5 | &:hover { 6 | color: var(--theme-color); 7 | } 8 | } 9 | } 10 | 11 | .entry-footer { 12 | list-style: none; 13 | } 14 | 15 | .hotpost { 16 | color: #ff3b00; 17 | } 18 | 19 | .page-header { 20 | position: relative; 21 | text-align: center; 22 | margin-bottom: 3rem; 23 | color: #999 24 | } 25 | 26 | @mixin screens-md { 27 | .page-header { 28 | margin-bottom: 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/css/common/components/post/post-author-profile.css: -------------------------------------------------------------------------------- 1 | .author-profile { 2 | margin: 3rem 0; 3 | text-align: center; 4 | 5 | & .info { 6 | overflow: hidden; 7 | text-align: center; 8 | 9 | & .profile { 10 | display: inline-block; 11 | 12 | & img { 13 | width: 4.375rem; 14 | height: 4.375rem; 15 | padding: 3px; 16 | border: 1px solid #ddd; 17 | border-radius: 100%; 18 | object-fit: cover; 19 | } 20 | } 21 | 22 | & .meta { 23 | display: block; 24 | text-align: center; 25 | 26 | & h3 { 27 | margin: 0.625rem 0 0; 28 | text-transform: none; 29 | 30 | & a { 31 | display: block; 32 | font-size: 1.125rem; 33 | font-weight: 400; 34 | line-height: normal; 35 | letter-spacing: 1px; 36 | color: #b0b0b0; 37 | } 38 | } 39 | } 40 | } 41 | 42 | & p { 43 | font-size: 0.815rem; 44 | margin: 1rem 0 0; 45 | color: #7d8588; 46 | letter-spacing: 0; 47 | display: inline-flex; 48 | padding: 1rem; 49 | border-top: 1px solid #eee; 50 | border-bottom: 1px solid #eee; 51 | 52 | & .iconify { 53 | color: var(--theme-color); 54 | } 55 | } 56 | 57 | @mixin screens-md { 58 | display: none; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/css/common/components/post/post-content-toast.css: -------------------------------------------------------------------------------- 1 | .word_count { 2 | margin: 0; 3 | } 4 | 5 | .minicode { 6 | box-shadow: 0 1px 2px rgb(0 0 0 / 20%); 7 | border-radius: 5px; 8 | margin: 0.625em 0; 9 | display: flex; 10 | align-items: center; 11 | color: var(--minicode-color); 12 | 13 | & a { 14 | padding: 5px; 15 | } 16 | 17 | & .content-toast { 18 | display: flex; 19 | padding: 0.25em 0.25em 0.25em 0.5em; 20 | word-break: keep-all; 21 | white-space: nowrap; 22 | overflow: hidden; 23 | width: 100%; 24 | transition: width, padding 0.5s ease; 25 | overflow-x: auto; 26 | } 27 | 28 | & .hide-minicode { 29 | line-height: inherit; 30 | cursor: pointer; 31 | padding-right: 5px; 32 | } 33 | 34 | &:hover { 35 | transform: scale(1.01); 36 | transition: all 0.5s ease; 37 | } 38 | 39 | &.hide { 40 | margin: 0; 41 | 42 | & .content-toast { 43 | height: 0; 44 | padding: 0; 45 | } 46 | 47 | & .hide-minicode { 48 | display: none; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/css/common/components/post/post-meta.css: -------------------------------------------------------------------------------- 1 | .meta-container { 2 | display: flex; 3 | margin: 0; 4 | font-size: 0.875rem; 5 | padding: 1.125rem 0 0; 6 | 7 | & .post-meta-item { 8 | display: flex; 9 | align-items: center; 10 | 11 | & img { 12 | width: 2.25rem; 13 | height: 2.25rem; 14 | border-radius: 100%; 15 | margin-right: 0.75rem; 16 | display: block; 17 | object-fit: cover; 18 | } 19 | 20 | &:not(:last-child) { 21 | &::after { 22 | content: "·"; 23 | margin: 0 0.3125rem; 24 | } 25 | } 26 | } 27 | 28 | @mixin screens-md { 29 | flex-wrap: wrap; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/css/common/components/post/post-none.css: -------------------------------------------------------------------------------- 1 | .page-none-content { 2 | margin: 1.5em 0 0; 3 | 4 | & .page-header { 5 | & .page-title { 6 | font-size: 1.25rem; 7 | font-weight: 400; 8 | border: 1px dashed #ddd; 9 | padding: 0.625rem 0.9375rem; 10 | color: #7d7d7d; 11 | margin-bottom: 1.875rem; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/css/common/components/screen/img-box/focus-tou.css: -------------------------------------------------------------------------------- 1 | .header-tou { 2 | & img { 3 | box-shadow: inset 0 0 10px #000; 4 | padding: 0.3125rem; 5 | opacity: 1; 6 | transform: rotate(0deg); 7 | transition: all ease 1s; 8 | 9 | &:hover { 10 | transform: rotate(360deg); 11 | } 12 | } 13 | } 14 | 15 | .center-text { 16 | margin: 0; 17 | font-family: "Ubuntu", sans-serif; 18 | font-size: 5rem; 19 | transition: background 1s; 20 | } 21 | 22 | .glitch { 23 | position: relative; 24 | color: #fff; 25 | mix-blend-mode: lighten; 26 | overflow: hidden; 27 | white-space: nowrap; 28 | 29 | &::before, 30 | &::after { 31 | content: attr(data-text); 32 | position: absolute; 33 | top: 0; 34 | width: 100%; 35 | background: rgba(0, 0, 0, 0); 36 | clip: rect(0, 0, 0, 0); 37 | } 38 | 39 | &::before { 40 | left: -1px; 41 | text-shadow: 1px 0 #ff3b00; 42 | } 43 | 44 | &::after { 45 | left: 1px; 46 | text-shadow: -1px 0 #00a1d6; 47 | } 48 | 49 | &:hover { 50 | &::before { 51 | text-shadow: 4px 0 #ff3b00; 52 | animation: glitch-loop-1 0.8s infinite ease-in-out alternate-reverse; 53 | } 54 | 55 | &::after { 56 | text-shadow: -5px 0 #00a1d6; 57 | animation: glitch-loop-2 0.8s infinite ease-in-out alternate-reverse; 58 | } 59 | } 60 | 61 | & + .header-info { 62 | &::before { 63 | top: -1.875rem; 64 | content: ""; 65 | } 66 | } 67 | } 68 | 69 | @keyframes glitch-loop-1 { 70 | 0% { 71 | clip: rect(36px, 9999px, 9px, 0); 72 | } 73 | 74 | 25% { 75 | clip: rect(25px, 9999px, 99px, 0); 76 | } 77 | 78 | 50% { 79 | clip: rect(50px, 9999px, 102px, 0); 80 | } 81 | 82 | 75% { 83 | clip: rect(30px, 9999px, 92px, 0); 84 | } 85 | 86 | 100% { 87 | clip: rect(91px, 9999px, 98px, 0); 88 | } 89 | } 90 | 91 | @keyframes glitch-loop-2 { 92 | 0% { 93 | top: -1px; 94 | left: 1px; 95 | clip: rect(65px, 9999px, 119px, 0); 96 | } 97 | 98 | 25% { 99 | top: -6px; 100 | left: 4px; 101 | clip: rect(79px, 9999px, 19px, 0); 102 | } 103 | 104 | 50% { 105 | top: -3px; 106 | left: 2px; 107 | clip: rect(68px, 9999px, 11px, 0); 108 | } 109 | 110 | 75% { 111 | top: 0; 112 | left: -4px; 113 | clip: rect(95px, 9999px, 53px, 0); 114 | } 115 | 116 | 100% { 117 | top: -1px; 118 | left: -1px; 119 | clip: rect(31px, 9999px, 149px, 0); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/css/common/components/screen/img-box/index.css: -------------------------------------------------------------------------------- 1 | @import "layout"; 2 | 3 | @import "focus-tou"; 4 | 5 | @import "info"; 6 | 7 | @import "social"; -------------------------------------------------------------------------------- /src/css/common/components/screen/img-box/info.css: -------------------------------------------------------------------------------- 1 | .header-info { 2 | max-width: 30%; 3 | position: relative; 4 | margin: 0; 5 | font-size: 1rem; 6 | color: var(--first-screen-header-info-text-color); 7 | background: var(--first-screen-header-info-background-color); 8 | padding: 1rem; 9 | letter-spacing: 0; 10 | line-height: 2rem; 11 | border-radius: 10px; 12 | box-sizing: initial; 13 | white-space: nowrap; 14 | margin-top: 1.25rem; 15 | 16 | &::before { 17 | position: absolute; 18 | left: 30%; 19 | border-width: 15px; 20 | border-style: solid; 21 | border-color: transparent; 22 | border-bottom-color: var(--first-screen-header-info-background-color); 23 | } 24 | 25 | & p { 26 | margin: 0; 27 | font-family: "Ubuntu", sans-serif; 28 | font-weight: 700; 29 | overflow: hidden; 30 | white-space: nowrap; 31 | transition: color 0.4s; 32 | } 33 | 34 | & .desc { 35 | overflow: hidden; 36 | white-space: normal; 37 | text-overflow: clip; 38 | word-break: keep-all; 39 | display: inline; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/css/common/components/screen/img-box/layout.css: -------------------------------------------------------------------------------- 1 | .centerbg { 2 | width: 100%; 3 | height: var(--first-screen-height); 4 | margin: 0; 5 | padding: 0; 6 | position: relative; 7 | 8 | @mixin screens-md { 9 | height: 18.75rem; 10 | background-attachment: scroll; 11 | } 12 | 13 | & .cover-bg { 14 | position: absolute; 15 | width: 100%; 16 | height: 100%; 17 | object-fit: cover; 18 | } 19 | 20 | & .blend-overlay { 21 | position: absolute; 22 | top: 0; 23 | right: 0; 24 | bottom: 0; 25 | left: 0; 26 | opacity: 0.3; 27 | mix-blend-mode: hard-light; 28 | background: var(--first-screen-background-blend-overlay); 29 | } 30 | } 31 | 32 | .focusinfo { 33 | position: relative; 34 | z-index: 2; 35 | text-align: center; 36 | height: 100%; 37 | width: 100%; 38 | display: flex; 39 | flex-direction: column; 40 | justify-content: center; 41 | align-items: center; 42 | transition: 0.4s ease all; 43 | 44 | & img { 45 | width: 8.125rem; 46 | height: 8.125rem; 47 | padding: 2px; 48 | border-radius: 100%; 49 | } 50 | 51 | @mixin screens-md { 52 | display: none; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/css/common/components/screen/img-box/social.css: -------------------------------------------------------------------------------- 1 | .top-social { 2 | display: flex; 3 | justify-content: center; 4 | height: 1.625rem; 5 | margin-top: 1rem; 6 | list-style: none; 7 | 8 | & img { 9 | height: 1.75rem; 10 | width: 1.75rem; 11 | padding: 0; 12 | background: 0 0; 13 | } 14 | 15 | & ul { 16 | list-style: none; 17 | margin: 0; 18 | padding: 0; 19 | display: flex; 20 | 21 | & li { 22 | float: left; 23 | margin-right: 10px; 24 | } 25 | } 26 | 27 | & .flipx { 28 | transform: scaleX(-1); 29 | filter: FlipH; 30 | } 31 | 32 | & .social-image { 33 | height: 2rem; 34 | width: 2rem; 35 | position: relative; 36 | 37 | & .social-image-inner { 38 | width: 8rem; 39 | height: 8rem; 40 | padding: 0.625rem; 41 | background: rgba(0, 0, 0, 0.4); 42 | left: -3.5rem; 43 | opacity: 0; 44 | position: absolute; 45 | border-radius: 8px; 46 | transition: 0.7s all ease; 47 | transform: translate3d(0, 3rem, 0); 48 | 49 | &::before { 50 | content: ""; 51 | position: absolute; 52 | top: -2rem; 53 | left: 50%; 54 | margin-left: -1rem; 55 | border-width: 1rem; 56 | border-style: solid; 57 | border-color: transparent transparent rgba(0, 0, 0, 0.4) transparent; 58 | } 59 | 60 | & img { 61 | border-radius: 0; 62 | width: 8rem; 63 | height: 8rem; 64 | padding: 0; 65 | background: 0 0; 66 | } 67 | } 68 | 69 | &:hover .social-image-inner { 70 | transform: translate3d(0, 16px, 0); 71 | opacity: 1; 72 | visibility: visible; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/css/common/components/screen/index.css: -------------------------------------------------------------------------------- 1 | @import "img-box"; 2 | 3 | @import "video-box"; 4 | 5 | @import "wave.css"; 6 | 7 | @import "top-down.css"; -------------------------------------------------------------------------------- /src/css/common/components/screen/top-down.css: -------------------------------------------------------------------------------- 1 | .headertop-down { 2 | position: absolute; 3 | bottom: 3.125rem; 4 | left: 50%; 5 | cursor: pointer; 6 | z-index: 3; 7 | 8 | & .iconify { 9 | font-size: 1.75em; 10 | color: #fff; 11 | transform: scale(1.5, 1) translateX(-33.34%); 12 | } 13 | 14 | @mixin screens-md { 15 | display: none; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/css/common/components/screen/video-box/index.css: -------------------------------------------------------------------------------- 1 | @import "layout.css"; -------------------------------------------------------------------------------- /src/css/common/components/screen/wave.css: -------------------------------------------------------------------------------- 1 | .home-wave { 2 | z-index: 1; 3 | position: relative; 4 | width: 400%; 5 | transition: 0.4s ease all; 6 | 7 | & > div { 8 | position: absolute; 9 | bottom: 0; 10 | width: 100%; 11 | } 12 | 13 | & .wave-1 { 14 | height: 65px; 15 | left: -236px; 16 | animation: wave 100s linear 0s infinite; 17 | } 18 | 19 | & .wave-2 { 20 | height: 80px; 21 | left: 0px; 22 | animation: wave 240s linear 0s infinite; 23 | } 24 | } 25 | 26 | @keyframes wave { 27 | 0% { 28 | transform: translateX(0%); 29 | } 30 | 100% { 31 | transform: translateX(-50.5%); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/css/common/components/search-form.css: -------------------------------------------------------------------------------- 1 | .search-form { 2 | &.is-visible { 3 | opacity: 0.99; 4 | visibility: visible; 5 | animation: search-visible 0.5s; 6 | background-repeat: no-repeat; 7 | background-position: bottom right; 8 | background-image: var(--search-form-background); 9 | } 10 | 11 | & .search-form-input { 12 | position: relative; 13 | } 14 | 15 | & svg { 16 | font-size: 2rem; 17 | line-height: 1; 18 | color: #ddd; 19 | position: absolute; 20 | top: 50%; 21 | transform: translateY(-50%); 22 | left: 1rem; 23 | } 24 | 25 | & input { 26 | font-size: 1.5rem; 27 | background: var(--background-color); 28 | padding: 0.75rem 1.5rem 0.75rem 4rem; 29 | width: 100%; 30 | outline: none; 31 | border-radius: 50px; 32 | box-sizing: border-box; 33 | transition: background 1s; 34 | 35 | &::-webkit-input-placeholder, 36 | &::-moz-placeholder, 37 | &:-ms-input-placeholder { 38 | color: #ddd; 39 | } 40 | 41 | &:focus { 42 | color: var(--color); 43 | } 44 | } 45 | 46 | & .search-close { 47 | position: absolute; 48 | width: 2.25rem; 49 | height: 2.25rem; 50 | background: 0 0; 51 | top: 20px; 52 | right: 15px; 53 | cursor: pointer; 54 | 55 | &::before, 56 | &::after { 57 | background-color: var(--color); 58 | position: absolute; 59 | content: ""; 60 | width: 1.875rem; 61 | height: 0.125rem; 62 | top: 17px; 63 | left: 2px; 64 | } 65 | 66 | &::after { 67 | transform: rotate(45deg); 68 | } 69 | 70 | &::before { 71 | transform: rotate(-45deg); 72 | } 73 | } 74 | } 75 | 76 | .search-form-modal { 77 | transition: visibility 0.25s ease, opacity 0.25s ease; 78 | overflow: hidden; 79 | z-index: 10; 80 | position: fixed; 81 | top: 0; 82 | right: 0; 83 | left: 0; 84 | bottom: 0; 85 | background: var(--background-color); 86 | visibility: hidden; 87 | opacity: 0; 88 | 89 | & .search-form-inner { 90 | display: flex; 91 | flex-direction: column; 92 | max-width: 640px; 93 | padding: 0 20px; 94 | margin: auto; 95 | text-align: left; 96 | position: absolute; 97 | width: 100%; 98 | left: 0; 99 | right: 0; 100 | height: 285px; 101 | top: 0; 102 | bottom: 0; 103 | 104 | & p { 105 | padding-left: 24px; 106 | } 107 | } 108 | } 109 | 110 | @keyframes search-visible { 111 | 0% { 112 | transform: scale(0); 113 | } 114 | 115 | 55% { 116 | transform: scale(1); 117 | } 118 | 119 | 70% { 120 | transform: scale(0.98); 121 | } 122 | 123 | 100% { 124 | transform: scale(1); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/css/common/components/toc.css: -------------------------------------------------------------------------------- 1 | .is-collapsible { 2 | overflow: hidden; 3 | transition: all 0.3s ease-in-out; 4 | } 5 | 6 | .is-collapsed { 7 | max-height: 0; 8 | } 9 | 10 | .is-position-fixed { 11 | position: fixed; 12 | top: 0; 13 | } 14 | 15 | .is-active-link { 16 | font-weight: bold; 17 | 18 | &::before { 19 | background-color: var(--theme-color) !important; 20 | } 21 | } -------------------------------------------------------------------------------- /src/css/common/index.css: -------------------------------------------------------------------------------- 1 | /* 2 | * 公共样式。 3 | */ 4 | 5 | /* HTML 标签样式规范化及默认处理 */ 6 | @import "architecture"; 7 | 8 | /* 主题网格轮廓样式 */ 9 | @import "outline"; 10 | 11 | /* 基础组件样式 */ 12 | @import "components"; -------------------------------------------------------------------------------- /src/css/common/outline/comment.css: -------------------------------------------------------------------------------- 1 | .comment { 2 | margin-top: 1em; 3 | position: relative; 4 | z-index: 1; 5 | } -------------------------------------------------------------------------------- /src/css/common/outline/content/index.css: -------------------------------------------------------------------------------- 1 | @import "layout.css"; 2 | 3 | @import "sidebar.css"; 4 | 5 | @import "main.css"; -------------------------------------------------------------------------------- /src/css/common/outline/content/layout.css: -------------------------------------------------------------------------------- 1 | .main { 2 | position: relative; 3 | } 4 | 5 | .wrapper { 6 | animation: fade-in; 7 | animation-duration: 0.5s; 8 | 9 | @mixin screens-md { 10 | transition-duration: 0.5s; 11 | width: 100%; 12 | height: auto; 13 | position: relative; 14 | 15 | & section { 16 | & h1 { 17 | font-weight: 300; 18 | font-size: 1.875rem; 19 | margin-bottom: 0.625rem; 20 | } 21 | 22 | & h2 { 23 | font-weight: 300; 24 | font-size: 1.25rem; 25 | margin-bottom: 2.5rem; 26 | } 27 | 28 | & p { 29 | margin-bottom: 2.5rem; 30 | } 31 | } 32 | } 33 | 34 | @media screen and (max-width: 860px) { 35 | & section .gallery-caption p { 36 | margin-bottom: 0; 37 | } 38 | } 39 | } 40 | 41 | @keyframes fade-in { 42 | 0% { 43 | opacity: 0; 44 | } 45 | 46 | 40% { 47 | opacity: 0; 48 | } 49 | 50 | 100% { 51 | opacity: 1; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/css/common/outline/content/main.css: -------------------------------------------------------------------------------- 1 | .site-content { 2 | max-width: var(--site-content-max-width); 3 | margin-left: auto; 4 | margin-right: auto; 5 | background-color: var(--site-content-background-color); 6 | padding: 0 10px; 7 | 8 | &::before, 9 | &::after { 10 | content: ""; 11 | display: table; 12 | table-layout: fixed; 13 | } 14 | 15 | &::after { 16 | clear: both; 17 | } 18 | 19 | @mixin screens-md { 20 | padding: 0 4%; 21 | } 22 | } 23 | 24 | .main-inner { 25 | position: relative; 26 | z-index: 1; 27 | } 28 | -------------------------------------------------------------------------------- /src/css/common/outline/content/sidebar.css: -------------------------------------------------------------------------------- 1 | .sidebar { 2 | position: absolute; 3 | height: 100%; 4 | top: 0; 5 | right: -20px; 6 | 7 | & .sidebar-inner { 8 | & .toc-container { 9 | max-width: 20rem; 10 | width: max-content; 11 | height: 100%; 12 | background-color: rgba(255, 255, 255, 0); 13 | transform: translateX(0); 14 | position: absolute; 15 | padding-top: 10px; 16 | padding-bottom: 10px; 17 | 18 | & .toc { 19 | overflow-y: auto; 20 | position: sticky; 21 | top: 6.25rem; 22 | max-height: 80vh; 23 | transition: background 1s; 24 | 25 | & > .toc-list { 26 | overflow: hidden; 27 | position: relative; 28 | margin: 0; 29 | padding-left: 10px; 30 | 31 | & li { 32 | list-style: none; 33 | } 34 | } 35 | 36 | & .toc-list { 37 | margin: 0; 38 | padding-left: 10px; 39 | font-size: 0.9375em; 40 | 41 | & .toc-list-item { 42 | line-height: 1.8; 43 | } 44 | } 45 | 46 | & a { 47 | &.toc-link { 48 | color: var(--entry-content-list-color); 49 | height: 100%; 50 | 51 | &::before { 52 | background-color: #eee; 53 | content: " "; 54 | display: inline-block; 55 | height: inherit; 56 | left: 0; 57 | margin-top: -1px; 58 | position: absolute; 59 | width: 2px; 60 | } 61 | } 62 | } 63 | } 64 | 65 | @mixin screens-md { 66 | display: none; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/css/common/outline/footer/copyright.css: -------------------------------------------------------------------------------- 1 | .footer-copyright { 2 | & p { 3 | font-family: "Ubuntu", sans-serif; 4 | 5 | & span { 6 | & .iconify { 7 | font-size: inherit; 8 | color: #e74c3c; 9 | } 10 | 11 | & a { 12 | text-decoration: none; 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/css/common/outline/footer/device.css: -------------------------------------------------------------------------------- 1 | .footer-device { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | 6 | & .footer-beian { 7 | display: flex; 8 | align-items: center; 9 | 10 | & a { 11 | display: flex; 12 | text-decoration: none; 13 | 14 | & img { 15 | object-fit: contain; 16 | } 17 | } 18 | } 19 | 20 | & p { 21 | margin: 0; 22 | margin-right: 8px; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/css/common/outline/footer/index.css: -------------------------------------------------------------------------------- 1 | @import "layout.css"; 2 | 3 | @import "logo.css"; 4 | 5 | @import "copyright.css"; 6 | 7 | @import "device.css"; -------------------------------------------------------------------------------- /src/css/common/outline/footer/layout.css: -------------------------------------------------------------------------------- 1 | .site-footer { 2 | background-color: var(--site-content-background-color); 3 | max-width: var(--site-content-max-width); 4 | padding: 0 10px; 5 | margin: auto; 6 | padding-bottom: 2%; 7 | position: relative; 8 | 9 | &::before, 10 | &::after { 11 | content: ""; 12 | display: table; 13 | table-layout: fixed; 14 | } 15 | 16 | &::after { 17 | clear: both; 18 | } 19 | 20 | & .site-info { 21 | margin: 2rem auto; 22 | text-align: center; 23 | font-size: 0.8125rem; 24 | color: #b0b0b0; 25 | 26 | & a { 27 | color: #b0b0b0; 28 | 29 | &:hover { 30 | color: var(--theme-color); 31 | } 32 | } 33 | } 34 | 35 | @mixin screens-lg { 36 | padding: 30px; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/css/common/outline/footer/logo.css: -------------------------------------------------------------------------------- 1 | .footer-logo { 2 | & p { 3 | margin-bottom: 8px; 4 | width: 2rem; 5 | height: 2rem; 6 | opacity: 0.8; 7 | margin: 0 auto; 8 | background-size: cover; 9 | background-position: center center; 10 | background-repeat: no-repeat; 11 | animation: poi-deg 12s infinite linear; 12 | } 13 | } 14 | 15 | @keyframes poi-deg { 16 | 0% { 17 | transform: rotate(0deg); 18 | } 19 | 20 | 100% { 21 | transform: rotate(360deg); 22 | } 23 | } -------------------------------------------------------------------------------- /src/css/common/outline/header/brand.css: -------------------------------------------------------------------------------- 1 | .site-branding { 2 | position: relative; 3 | animation: sitetop 1s; 4 | 5 | & .site-title { 6 | display: flex; 7 | margin: 0; 8 | 9 | & a { 10 | color: var(--body-color); 11 | font-weight: 400; 12 | 13 | &:hover { 14 | color: var(--theme-color); 15 | } 16 | } 17 | 18 | & img { 19 | height: 2.5rem; 20 | width: 2.5rem; 21 | object-fit: cover; 22 | 23 | &:hover { 24 | opacity: 1; 25 | } 26 | } 27 | 28 | & a, 29 | & img { 30 | display: inline-block; 31 | transition: color 0.2s ease-out, border 0.2s ease-out, opacity 0.2s ease-out; 32 | } 33 | } 34 | 35 | @mixin screens-md { 36 | & .site-title { 37 | font-size: 1.25rem; 38 | margin-right: 0.625rem; 39 | 40 | & img { 41 | height: 2rem; 42 | width: 2rem; 43 | border-radius: 100%; 44 | margin: 0; 45 | vertical-align: middle; 46 | } 47 | } 48 | } 49 | } 50 | 51 | @keyframes sitetop { 52 | 0% { 53 | opacity: 0; 54 | transform: translateX(-30px); 55 | } 56 | 57 | 100% { 58 | opacity: 1; 59 | transform: translateX(0); 60 | } 61 | } -------------------------------------------------------------------------------- /src/css/common/outline/header/index.css: -------------------------------------------------------------------------------- 1 | @import "layout.css"; 2 | 3 | @import "nav-toggle.css"; 4 | 5 | @import "brand.css"; 6 | 7 | @import "user.css"; 8 | 9 | @import "search.css"; 10 | 11 | @import "menu.css"; -------------------------------------------------------------------------------- /src/css/common/outline/header/layout.css: -------------------------------------------------------------------------------- 1 | .site-header { 2 | position: relative; 3 | right: 0; 4 | height: var(--header-height); 5 | width: 100%; 6 | z-index: 10; 7 | 8 | &::before, 9 | &::after { 10 | content: ""; 11 | display: table; 12 | table-layout: fixed; 13 | } 14 | 15 | &::after { 16 | clear: both; 17 | } 18 | 19 | &.iconsearch { 20 | font-size: 1.125rem; 21 | position: relative; 22 | z-index: 10; 23 | 24 | &:hover { 25 | cursor: pointer; 26 | color: var(--theme-color); 27 | } 28 | } 29 | 30 | & .header-inner { 31 | display: flex; 32 | align-items: center; 33 | justify-content: center; 34 | height: var(--header-height); 35 | width: 100%; 36 | margin: 0 auto; 37 | position: fixed; 38 | box-sizing: border-box; 39 | top: 0; 40 | transition: top 0.3s ease-in-out; 41 | 42 | & .header-after, 43 | & .header-content, 44 | & .header-before { 45 | display: flex; 46 | align-items: center; 47 | justify-content: center; 48 | } 49 | 50 | & .header-after, 51 | & .header-before { 52 | position: absolute; 53 | } 54 | 55 | & .header-before { 56 | left: 1.25rem; 57 | } 58 | 59 | & .header-content { 60 | flex: 1; 61 | } 62 | 63 | & .header-after { 64 | right: 1.25rem; 65 | } 66 | } 67 | 68 | @mixin screens-md { 69 | &, 70 | & .header-inner { 71 | height: 2.5rem; 72 | position: absolute; 73 | } 74 | 75 | & .header-inner { 76 | padding: 0; 77 | 78 | & .header-after, 79 | & .header-before { 80 | position: initial; 81 | } 82 | 83 | & .header-before { 84 | flex: 1; 85 | justify-content: space-between; 86 | } 87 | 88 | & .header-content { 89 | display: none; 90 | } 91 | } 92 | } 93 | } 94 | 95 | /* 导航栏向下滚动样式 */ 96 | .yya { 97 | & .header-inner { 98 | position: fixed; 99 | top: var(--yya-header-top); 100 | background: var(--header-background); 101 | box-shadow: 0 1px 40px -8px #00000080; 102 | } 103 | 104 | &.sabit { 105 | & .header-inner { 106 | top: 0; 107 | } 108 | } 109 | 110 | @mixin screens-md { 111 | & .header-inner { 112 | background: transparent; 113 | box-shadow: none; 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/css/common/outline/header/nav-toggle.css: -------------------------------------------------------------------------------- 1 | .site-nav-toggle { 2 | display: none; 3 | 4 | @mixin screens-md { 5 | transition-duration: 0.5s; 6 | height: 2.5rem; 7 | display: block; 8 | z-index: 10; 9 | 10 | &.open { 11 | display: none; 12 | } 13 | 14 | & .nav-toggle { 15 | background: 0 0; 16 | width: 2.5rem; 17 | height: 2.5rem; 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | 22 | & .icon { 23 | transition-duration: 0.2s; 24 | width: 1.875rem; 25 | height: 3px; 26 | background-color: var(--mobile-nav-toggle-background-color); 27 | 28 | &::before, 29 | &::after { 30 | transition-duration: 0.5s; 31 | background-color: var(--mobile-nav-toggle-background-color); 32 | position: absolute; 33 | content: ""; 34 | width: 1.875rem; 35 | height: 3px; 36 | } 37 | 38 | &::before { 39 | top: 10px; 40 | } 41 | 42 | &::after { 43 | bottom: 10px; 44 | } 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/css/common/outline/header/search.css: -------------------------------------------------------------------------------- 1 | .searchbox { 2 | animation: fadeInRight 1s; 3 | 4 | & .iconsearch { 5 | color: var(--body-color); 6 | cursor: pointer; 7 | font-size: 1.875rem; 8 | transition: all 0.3s ease-in-out; 9 | } 10 | 11 | @mixin screens-md { 12 | display: none; 13 | } 14 | } -------------------------------------------------------------------------------- /src/css/common/outline/header/user.css: -------------------------------------------------------------------------------- 1 | .header-user-avatar { 2 | display: flex; 3 | position: relative; 4 | animation: fadeInRight 1s; 5 | margin-left: 1.25rem; 6 | 7 | & img { 8 | border-radius: 100%; 9 | cursor: pointer; 10 | height: 1.875rem; 11 | object-fit: cover; 12 | } 13 | 14 | &:hover .header-user-menu { 15 | display: block; 16 | } 17 | 18 | @mixin screens-md { 19 | display: none; 20 | } 21 | } 22 | 23 | .header-user-menu { 24 | position: absolute; 25 | right: -11px; 26 | top: 2.875rem; 27 | display: none; 28 | animation: header-user-menu 0.4s; 29 | box-shadow: 0 1px 40px -8px rgba(0, 0, 0, 0.5); 30 | border-radius: 5px; 31 | text-align: center; 32 | background: var(--widget-background-color); 33 | width: max-content; 34 | 35 | & .herder-user-name { 36 | font-size: 0.75rem; 37 | padding: 10px; 38 | border-radius: 4px 4px 0 0; 39 | 40 | & .herder-user-name-u { 41 | font-weight: 700; 42 | font-size: 0.875rem; 43 | overflow: hidden; 44 | text-overflow: ellipsis; 45 | white-space: nowrap; 46 | } 47 | } 48 | 49 | &::before { 50 | content: ""; 51 | position: absolute; 52 | top: -20px; 53 | right: 18px; 54 | border-width: 10px; 55 | border-style: solid; 56 | border-color: transparent transparent var(--widget-background-color); 57 | } 58 | 59 | & .user-menu-option { 60 | padding: 5px 0; 61 | border-radius: 0 0 4px 4px; 62 | 63 | & a:hover { 64 | background-color: var(--header-user-option-hover-background-color); 65 | } 66 | } 67 | 68 | & a { 69 | display: block; 70 | padding: 6px 10px; 71 | margin: 2px 0; 72 | width: 6.875rem; 73 | color: var(--color); 74 | font-size: 13px; 75 | } 76 | 77 | & .no-logged { 78 | font-size: 0.8125rem; 79 | padding: 15px 10px; 80 | border-radius: 4px; 81 | border: 0; 82 | 83 | & a { 84 | display: initial; 85 | font-size: 0.875rem; 86 | padding: 0 5px; 87 | font-weight: bold; 88 | text-decoration: none; 89 | } 90 | } 91 | } 92 | 93 | @keyframes header-user-menu { 94 | 0% { 95 | opacity: 0; 96 | transform: translateY(-20px); 97 | } 98 | 99 | 100% { 100 | opacity: 1; 101 | transform: translateY(0); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/css/common/outline/index.css: -------------------------------------------------------------------------------- 1 | @import "header"; 2 | 3 | @import "content"; 4 | 5 | @import "footer"; 6 | 7 | @import "sidebar"; 8 | 9 | @import "comment.css"; 10 | 11 | .container { 12 | transition: background 1s; 13 | 14 | @mixin screens-md { 15 | & { 16 | transition-duration: .5s; 17 | position: relative; 18 | overflow: hidden; 19 | z-index: 2 20 | } 21 | 22 | &.open { 23 | &::before { 24 | content: ""; 25 | width: 100%; 26 | height: 100%; 27 | position: fixed; 28 | background-color: rgba(0, 0, 0, .4); 29 | z-index: 9; 30 | } 31 | } 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/css/common/outline/sidebar/index.css: -------------------------------------------------------------------------------- 1 | @import "layout.css"; 2 | 3 | @import "mobile-sidebar.css"; -------------------------------------------------------------------------------- /src/css/common/outline/sidebar/layout.css: -------------------------------------------------------------------------------- 1 | .site-sidebar { 2 | width: 15.625rem; 3 | height: 100%; 4 | position: fixed; 5 | left: 0; 6 | top: 0; 7 | background-color: var(--background-color); 8 | overflow: hidden; 9 | z-index: 9; 10 | pointer-events: none; 11 | transform: translateX(-15.625rem); 12 | transition: transform 0.5s ease-out; 13 | 14 | & .sidebar-close { 15 | position: fixed; 16 | top: 20px; 17 | left: 16rem; 18 | pointer-events: auto; 19 | 20 | &::after, 21 | &::before { 22 | content: ""; 23 | display: inline-block; 24 | background: var(--theme-color); 25 | width: 1.875rem; 26 | height: 0.1875rem; 27 | position: absolute; 28 | } 29 | 30 | &::before { 31 | transform: rotate(-45deg); 32 | } 33 | 34 | &::after { 35 | transform: rotate(45deg); 36 | } 37 | } 38 | 39 | &.open { 40 | transform: none; 41 | } 42 | 43 | & .sidebar-inner { 44 | height: 100%; 45 | width: 100%; 46 | pointer-events: auto; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Sakura 框架样式 3 | * 4 | * 插件参见 postcss.config.js. 5 | * 使用 vite 自带的 postcss-import 功能。 6 | * @see https://github.com/postcss/postcss-import。 7 | */ 8 | 9 | /* mixins */ 10 | @import "mixins.css"; 11 | 12 | /* 变量 */ 13 | @import "variables"; 14 | 15 | /* 基础组件样式 */ 16 | @import "common"; 17 | 18 | /* 主题样式 */ 19 | @import "theme"; -------------------------------------------------------------------------------- /src/css/mixins.css: -------------------------------------------------------------------------------- 1 | /** 2 | * mixin 功能,为全局 CSS 提供公共的 mixin。 3 | * 使用 postcss 插件 postcss-mixins。https://github.com/postcss/postcss-mixins 4 | */ 5 | /** 设备分辨率 **/ 6 | @define-mixin screens-sm { 7 | @media (max-width: 640px) { 8 | @mixin-content; 9 | } 10 | } 11 | 12 | @define-mixin screens-md { 13 | @media (max-width: 768px) { 14 | @mixin-content; 15 | } 16 | } 17 | 18 | @define-mixin screens-lg { 19 | @media (max-width: 1024px) { 20 | @mixin-content; 21 | } 22 | } 23 | 24 | @define-mixin screens-xl { 25 | @media (max-width: 1280px) { 26 | @mixin-content; 27 | } 28 | } 29 | 30 | @define-mixin screens-2xl { 31 | @media (max-width: 1536px) { 32 | @mixin-content; 33 | } 34 | } 35 | 36 | @define-mixin dark { 37 | @media (prefers-color-scheme: dark) { 38 | @mixin-content; 39 | } 40 | } 41 | 42 | @define-mixin col $col: 3 { 43 | &.col-$(col) { 44 | width: calc((100% - ($(col) - 1) * 10px) / $(col)); 45 | } 46 | } 47 | 48 | /** 49 | * 解决 hover 在移动端的黏着触发问题 50 | * 51 | * @see https://issues.chromium.org/issues/40364091 52 | */ 53 | @define-mixin pc-hover { 54 | @media (any-hover: hover) { 55 | @mixin-content; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/css/theme/archives/index.css: -------------------------------------------------------------------------------- 1 | @import "content.css"; -------------------------------------------------------------------------------- /src/css/theme/author/header.css: -------------------------------------------------------------------------------- 1 | .author-header { 2 | & .page-header { 3 | & .pattern-title { 4 | display: flex; 5 | align-items: center; 6 | 7 | & h1 { 8 | display: inline-block; 9 | font-size: 25px; 10 | font-weight: 400; 11 | width: auto; 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/css/theme/author/index.css: -------------------------------------------------------------------------------- 1 | @import "header.css"; -------------------------------------------------------------------------------- /src/css/theme/categories/content.css: -------------------------------------------------------------------------------- 1 | .categories-container { 2 | & .card-container { 3 | margin: 36px auto; 4 | 5 | &.category-show { 6 | animation: card-show 1s ease-in-out; 7 | } 8 | 9 | & .categories-title { 10 | margin-bottom: 10px; 11 | color: var(--card-container-title-color); 12 | font-size: 1.75rem; 13 | font-weight: 400; 14 | } 15 | 16 | & .categories-chips { 17 | margin: 1rem auto 0.5rem; 18 | max-width: 850px; 19 | text-align: center; 20 | 21 | & .categories-length { 22 | color: #9b8b2a; 23 | margin-top: 0px; 24 | margin-left: 5px; 25 | margin-right: -2px; 26 | font-size: 0.9rem; 27 | } 28 | } 29 | 30 | & .category-echarts { 31 | width: 100%; 32 | height: 360px; 33 | } 34 | } 35 | } 36 | 37 | @keyframes card-show { 38 | 0% { 39 | opacity: 0; 40 | transform: translateY(50px); 41 | } 42 | 43 | 100% { 44 | opacity: 1; 45 | transform: translateY(0); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/css/theme/categories/index.css: -------------------------------------------------------------------------------- 1 | @import "content.css"; -------------------------------------------------------------------------------- /src/css/theme/category/header.css: -------------------------------------------------------------------------------- 1 | .category-header { 2 | & .page-header { 3 | & .pattern-title { 4 | display: flex; 5 | align-items: center; 6 | 7 | & h1 { 8 | display: inline-block; 9 | font-size: 25px; 10 | font-weight: 400; 11 | width: auto; 12 | 13 | &::before { 14 | content: ""; 15 | } 16 | 17 | &::after { 18 | content: ""; 19 | padding-right: 15px; 20 | border-right: 1px dashed #ddd; 21 | font-size: 30px; 22 | vertical-align: middle; 23 | } 24 | 25 | @mixin screens-md { 26 | &::after { 27 | border-right: none; 28 | } 29 | } 30 | } 31 | 32 | & .cat-des { 33 | display: block; 34 | text-align: center; 35 | color: #999; 36 | margin-left: 10px; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/css/theme/category/index.css: -------------------------------------------------------------------------------- 1 | @import "header.css"; -------------------------------------------------------------------------------- /src/css/theme/error/404.css: -------------------------------------------------------------------------------- 1 | .error-404 { 2 | margin-top: -100px; 3 | margin-bottom: 5px; 4 | 5 | & .error-img { 6 | text-align: center; 7 | width: 80%; 8 | margin: 0 auto; 9 | } 10 | 11 | & .err-button { 12 | text-align: center; 13 | 14 | &.back { 15 | & a { 16 | padding: 7px 30px; 17 | margin: 0 10px; 18 | border: 1px solid var(--theme-color); 19 | color: var(--theme-color); 20 | border-radius: 50px; 21 | 22 | &:hover { 23 | box-shadow: 0 0 4px var(--theme-color); 24 | } 25 | } 26 | 27 | & .gohome { 28 | background: var(--theme-color); 29 | color: #fff; 30 | } 31 | } 32 | } 33 | 34 | & .error-search { 35 | margin-top: 1.5em; 36 | 37 | & > p { 38 | text-align: center; 39 | font-size: 15px; 40 | margin-bottom: 1em; 41 | } 42 | 43 | & .search-box { 44 | position: relative; 45 | margin-bottom: 3.125em; 46 | 47 | & svg { 48 | font-size: 1.5em; 49 | line-height: 1; 50 | color: #ddd; 51 | position: absolute; 52 | top: 50%; 53 | transform: translateY(-50%); 54 | left: 1rem; 55 | } 56 | 57 | & input { 58 | font-size: 1rem; 59 | background: #fff; 60 | background: var(--background-color); 61 | padding: 0.75rem 1.5rem 0.75rem 4rem; 62 | width: 100%; 63 | outline: none; 64 | border-radius: 50px; 65 | box-sizing: border-box; 66 | transition: background 1s; 67 | } 68 | } 69 | } 70 | 71 | @mixin screens-md { 72 | margin-top: 0; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/css/theme/error/index.css: -------------------------------------------------------------------------------- 1 | @import "404"; -------------------------------------------------------------------------------- /src/css/theme/home/content.css: -------------------------------------------------------------------------------- 1 | .site-main { 2 | padding: 40px 0 0; 3 | 4 | & .main-title { 5 | width: 100%; 6 | color: var(--color); 7 | font-size: 1em; 8 | font-weight: 400; 9 | padding-bottom: 5px; 10 | margin-bottom: 30px; 11 | border-bottom: var(--home-divider-border); 12 | transition: border 1s; 13 | } 14 | 15 | @mixin screens-md { 16 | padding: 15px 0 0; 17 | } 18 | } 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/css/theme/home/header.css: -------------------------------------------------------------------------------- 1 | .headertop { 2 | position: relative; 3 | overflow: hidden; 4 | width: 100%; 5 | animation: header 1s; 6 | 7 | &::before { 8 | content: ""; 9 | position: absolute; 10 | top: 0; 11 | bottom: 0; 12 | left: 0; 13 | right: 0; 14 | z-index: 1; 15 | background-attachment: fixed; 16 | background: var(--first-screen-filter-images); 17 | } 18 | 19 | &::after { 20 | content: ""; 21 | display: var(--first-screen-after); 22 | width: 150%; 23 | height: 4.375rem; 24 | background: var(--background-color); 25 | left: -25%; 26 | bottom: -2.875rem; 27 | border-radius: 100%; 28 | position: absolute; 29 | z-index: 1; 30 | transition: background 1s; 31 | } 32 | 33 | @mixin screens-md { 34 | &::after { 35 | display: block; 36 | } 37 | } 38 | } 39 | 40 | @keyframes header { 41 | 0% { 42 | opacity: 0; 43 | transform: translateY(-50px); 44 | } 45 | 46 | 100% { 47 | opacity: 1; 48 | transform: translateY(0); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/css/theme/home/index.css: -------------------------------------------------------------------------------- 1 | @import "header.css"; 2 | 3 | @import "notice.css"; 4 | 5 | @import "top-feature.css"; 6 | 7 | @import "content.css"; 8 | 9 | .is-homepage { 10 | & .site-header { 11 | position: fixed; 12 | 13 | &.yya { 14 | & .header-inner .lower-container { 15 | display: block; 16 | } 17 | } 18 | 19 | & .header-inner { 20 | transition: background 1s; 21 | 22 | & .lower-container { 23 | display: none; 24 | } 25 | } 26 | 27 | &:hover { 28 | & .header-inner { 29 | position: fixed; 30 | top: 0; 31 | background: var(--header-background); 32 | 33 | & .lower-container { 34 | display: block; 35 | } 36 | } 37 | } 38 | } 39 | 40 | @mixin screens-md { 41 | & .site-header { 42 | &:hover { 43 | & .header-inner { 44 | background: transparent; 45 | } 46 | } 47 | } 48 | } 49 | } 50 | 51 | /* 非首页时 */ 52 | section:not(.is-homepage) .site-header .header-inner { 53 | box-shadow: 0 1px 40px -8px #00000080; 54 | 55 | @mixin screens-md { 56 | box-shadow: none; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/css/theme/home/notice.css: -------------------------------------------------------------------------------- 1 | .notice { 2 | padding: 20px; 3 | border: 1px dashed #ddd; 4 | color: var(--color); 5 | position: relative; 6 | display: flex; 7 | align-items: center; 8 | width: 100%; 9 | background: var(--notice-background-color); 10 | border-radius: 10px; 11 | animation: main 0.6s; 12 | 13 | & .notice-content { 14 | display: contents; 15 | vertical-align: middle; 16 | width: 100%; 17 | } 18 | 19 | & .iconify { 20 | color: #999; 21 | padding-right: 10px; 22 | } 23 | 24 | @mixin screens-md { 25 | margin-top: 40px; 26 | margin-bottom: 20px; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/css/theme/index.css: -------------------------------------------------------------------------------- 1 | /** 2 | * 主题各个页面的样式 3 | */ 4 | /* 首页 */ 5 | @import "home"; 6 | 7 | @import "post"; 8 | 9 | @import "page"; 10 | 11 | @import "link"; 12 | 13 | @import "archives"; 14 | 15 | @import "tags"; 16 | 17 | @import "tag"; 18 | 19 | @import "categories"; 20 | 21 | @import "category"; 22 | 23 | @import "moments"; 24 | 25 | @import "photos"; 26 | 27 | @import "author"; 28 | 29 | @import "search"; 30 | 31 | @import "error"; -------------------------------------------------------------------------------- /src/css/theme/link/index.css: -------------------------------------------------------------------------------- 1 | @import "content.css"; -------------------------------------------------------------------------------- /src/css/theme/moments/index.css: -------------------------------------------------------------------------------- 1 | @import "content.css"; -------------------------------------------------------------------------------- /src/css/theme/page/header.css: -------------------------------------------------------------------------------- 1 | .single-page-header { 2 | & .page-header { 3 | &.is-decorate { 4 | & .pattern-title { 5 | & h1 { 6 | font-size: 40px; 7 | } 8 | } 9 | } 10 | 11 | & .pattern-title { 12 | & h1 { 13 | font-size: 24px; 14 | font-weight: 700; 15 | text-transform: uppercase; 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/css/theme/page/index.css: -------------------------------------------------------------------------------- 1 | @import "header.css"; -------------------------------------------------------------------------------- /src/css/theme/photos/index.css: -------------------------------------------------------------------------------- 1 | @import "content.css"; 2 | 3 | @import "style-masonry"; 4 | 5 | @import "style-justify"; -------------------------------------------------------------------------------- /src/css/theme/photos/style-justify.css: -------------------------------------------------------------------------------- 1 | .justify-tools { 2 | text-align: center; 3 | } 4 | 5 | .justify-wrapper { 6 | max-width: 1024px; 7 | margin: 0 auto; 8 | } 9 | -------------------------------------------------------------------------------- /src/css/theme/photos/style-masonry.css: -------------------------------------------------------------------------------- 1 | .masonry-container { 2 | margin: auto 4vw; 3 | 4 | & .photos-content { 5 | margin: 1.5em auto; 6 | 7 | & .gallery { 8 | & .gallery-item { 9 | margin: 0; 10 | margin-bottom: 10px; 11 | 12 | @mixin col 3; 13 | @mixin col 4; 14 | @mixin col 5 { 15 | & .gallery-caption { 16 | font-size: 0.85em; 17 | } 18 | } 19 | @mixin col 6; 20 | @mixin col 7; 21 | @mixin col 8; 22 | 23 | & .gallery-icon { 24 | position: relative; 25 | z-index: 9; 26 | transition: opacity 0.2s ease; 27 | text-align: center; 28 | 29 | & a { 30 | display: block; 31 | width: 100%; 32 | height: 100%; 33 | position: relative; 34 | z-index: 9; 35 | } 36 | 37 | & img { 38 | width: 100%; 39 | height: auto; 40 | margin: 0 0 -5px 0; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | 47 | @mixin screens-md { 48 | & .photos-content { 49 | & .gallery { 50 | & .gallery-item { 51 | width: 100% !important; 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | .masonry-tools { 59 | display: flex; 60 | justify-content: space-between; 61 | 62 | & .grid-changer { 63 | float: right; 64 | 65 | & ul { 66 | list-style: none; 67 | padding: 0; 68 | margin: 0; 69 | font-size: 0.8em; 70 | 71 | & li { 72 | display: inline-block; 73 | margin-left: 0.2em; 74 | 75 | & span { 76 | display: block; 77 | width: 30px; 78 | height: 30px; 79 | text-align: center; 80 | color: var(--photo-group-change-color); 81 | position: relative; 82 | border: 2px solid var(--photo-group-change-color); 83 | transition: all 0.2s ease; 84 | 85 | &:hover { 86 | border-color: var(--theme-color); 87 | color: var(--theme-color); 88 | } 89 | 90 | &.active { 91 | &, 92 | &:hover { 93 | border-color: var(--photo-group-change-active-color); 94 | color: var(--photo-group-change-active-color);; 95 | } 96 | } 97 | 98 | & svg { 99 | fill: var(--photo-group-change-active-color);; 100 | } 101 | } 102 | } 103 | } 104 | } 105 | 106 | @mixin screens-md { 107 | justify-content: center; 108 | 109 | & .grid-changer { 110 | display: none; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/css/theme/post/header.css: -------------------------------------------------------------------------------- 1 | .post-header { 2 | position: relative; 3 | display: flex; 4 | justify-content: center; 5 | flex-wrap: wrap; 6 | 7 | & .post-meta, 8 | & .pattern-title { 9 | width: 780px; 10 | } 11 | 12 | & .page-header { 13 | width: 100%; 14 | } 15 | 16 | & .post-meta { 17 | & .meta-container { 18 | justify-content: center; 19 | } 20 | } 21 | 22 | & .is-decorate { 23 | & .pattern-title { 24 | bottom: 2em; 25 | 26 | & h1 { 27 | text-align: left; 28 | } 29 | } 30 | 31 | & .post-meta { 32 | & .meta-container { 33 | justify-content: inherit; 34 | padding: 0; 35 | 36 | & .post-meta-item { 37 | & *, 38 | &::after { 39 | color: #fff; 40 | } 41 | } 42 | } 43 | } 44 | } 45 | 46 | @mixin screens-md { 47 | & .post-meta, 48 | & .pattern-title { 49 | width: 100%; 50 | } 51 | 52 | & .is-decorate { 53 | & .pattern-title { 54 | bottom: auto; 55 | 56 | & h1 { 57 | text-align: inherit; 58 | } 59 | } 60 | 61 | & .post-meta { 62 | & .meta-container { 63 | justify-content: center; 64 | } 65 | } 66 | } 67 | 68 | & h1 { 69 | font-size: 26px; 70 | -webkit-line-clamp: 2; 71 | overflow: hidden; 72 | text-overflow: ellipsis; 73 | display: -webkit-box; 74 | -webkit-box-orient: vertical; 75 | text-align: center; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/css/theme/post/index.css: -------------------------------------------------------------------------------- 1 | @import "header.css"; -------------------------------------------------------------------------------- /src/css/theme/search/index.css: -------------------------------------------------------------------------------- 1 | @import "search-box.css"; 2 | 3 | @import "search-moment.css"; -------------------------------------------------------------------------------- /src/css/theme/search/search-box.css: -------------------------------------------------------------------------------- 1 | .search-container { 2 | margin-top: 3.5rem; 3 | 4 | & .search-box { 5 | position: relative; 6 | margin-bottom: 3.125rem; 7 | 8 | & svg { 9 | font-size: 1.5em; 10 | line-height: 1; 11 | color: #ddd; 12 | position: absolute; 13 | top: 50%; 14 | transform: translateY(-50%); 15 | left: 1rem; 16 | } 17 | 18 | & input { 19 | font-size: 1rem; 20 | background: #fff; 21 | background: var(--background-color); 22 | padding: 0.75rem 1.5rem 0.75rem 4rem; 23 | width: 100%; 24 | outline: none; 25 | border-radius: 50px; 26 | box-sizing: border-box; 27 | transition: background 1s; 28 | } 29 | } 30 | 31 | & h1.search-title { 32 | font-size: 20px; 33 | font-weight: 400; 34 | border: 1px dashed #ddd; 35 | padding: 10px 15px; 36 | color: #828282; 37 | margin-bottom: 30px; 38 | text-align: center; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/css/theme/search/search-moment.css: -------------------------------------------------------------------------------- 1 | .moment-list { 2 | margin: 0 0 4rem; 3 | position: relative; 4 | animation: main 0.6s; 5 | 6 | & .entry-header { 7 | display: flex; 8 | align-items: center; 9 | justify-content: space-between; 10 | 11 | & .entry-title { 12 | & a { 13 | color: var(--post-list-thumb-title-color); 14 | } 15 | } 16 | 17 | & .p-time { 18 | font-size: 0.75rem; 19 | color: #999; 20 | letter-spacing: 0; 21 | 22 | & .iconify { 23 | scale: 1.2; 24 | margin-right: 5px; 25 | } 26 | } 27 | } 28 | 29 | & p { 30 | min-height: 3.75rem; 31 | font-size: 0.9375em; 32 | color: rgba(0, 0, 0, 0.66); 33 | color: var(--post-list-thumb-abstract-color); 34 | letter-spacing: 0; 35 | line-height: 1.875rem; 36 | transition: color 1s; 37 | margin: 0; 38 | padding: 0; 39 | display: -webkit-box; 40 | } 41 | 42 | & .entry-footer { 43 | & .post-more { 44 | margin-top: 0.625rem; 45 | text-align: right; 46 | 47 | & .iconify { 48 | font-size: 1.875em; 49 | color: var(--post-list-thumb-more-color); 50 | } 51 | } 52 | } 53 | 54 | & hr { 55 | width: 30%; 56 | height: 1px; 57 | margin: 0 auto; 58 | border: 0; 59 | background: #eee; 60 | margin-top: 1.25rem; 61 | transition: background 1s; 62 | } 63 | 64 | @mixin screens-md { 65 | & .entry-header { 66 | flex-direction: column; 67 | align-items: baseline; 68 | margin-bottom: 0.67rem; 69 | 70 | & .entry-title { 71 | &h1 { 72 | font-size: 1rem; 73 | line-height: 1.875rem; 74 | max-width: 90%; 75 | margin-left: 1rem; 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/css/theme/tag/header.css: -------------------------------------------------------------------------------- 1 | .tag-header { 2 | & .page-header { 3 | & .pattern-title { 4 | & h1 { 5 | display: inline-block; 6 | font-size: 25px; 7 | font-weight: 400; 8 | color: var(--color); 9 | 10 | &::before { 11 | content: ""; 12 | } 13 | 14 | &::after { 15 | content: ""; 16 | padding-right: 15px; 17 | border-right: 1px dashed #ddd; 18 | font-size: 30px; 19 | vertical-align: middle; 20 | } 21 | 22 | @mixin screens-md { 23 | &::after { 24 | border-right: none; 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/css/theme/tag/index.css: -------------------------------------------------------------------------------- 1 | @import "header.css"; -------------------------------------------------------------------------------- /src/css/theme/tags/content.css: -------------------------------------------------------------------------------- 1 | .tag-wordcloud-container { 2 | position: relative; 3 | left: calc((100% - 100vw) / 2); 4 | 5 | & .wordcloud { 6 | width: 100vw; 7 | height: 500px; 8 | } 9 | } 10 | 11 | .tags-content { 12 | margin: 50px 0; 13 | 14 | & .tag-title { 15 | margin-bottom: 10px; 16 | color: var(--card-container-title-color); 17 | font-size: 1.75rem; 18 | font-weight: 400; 19 | } 20 | 21 | & .tag-chips { 22 | margin: 1rem auto 0.5rem; 23 | max-width: 850px; 24 | text-align: center; 25 | 26 | & .tag-length { 27 | color: #9b8b2a; 28 | margin-top: 0px; 29 | margin-left: 5px; 30 | margin-right: -2px; 31 | font-size: 0.9rem; 32 | } 33 | } 34 | 35 | @mixin screens-md { 36 | margin: 20px 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/css/theme/tags/index.css: -------------------------------------------------------------------------------- 1 | @import "content.css"; -------------------------------------------------------------------------------- /src/css/variables/aplayer.css: -------------------------------------------------------------------------------- 1 | .aplayer { 2 | --aplayer-color: #000; 3 | --aplayer-background-color: #fff; 4 | --aplayer-list-border: 1px solid #eee; 5 | --aplayer-list-light-background-color: #e9e9e9; 6 | --aplayer-list-top-border: 1px solid var(--aplayer-list-light-background-color); 7 | --aplayer-list-author-color: #666; 8 | --aplayer-body-miniswitcher-background-color: #e6e6e6; 9 | --aplayer-lrc-text-shadow: -1px -1px 0 #fff; 10 | --aplayer-list-hover-background-color: #efefef; 11 | } 12 | 13 | .dark { 14 | & .aplayer { 15 | --aplayer-color: #eee; 16 | --aplayer-background-color: #232629; 17 | --aplayer-list-border: none; 18 | --aplayer-list-light-background-color: #31363b; 19 | --aplayer-list-top-border: none; 20 | --aplayer-list-author-color: eee; 21 | --aplayer-body-miniswitcher-background-color: var(--aplayer-background-color); 22 | --aplayer-lrc-text-shadow: -1px -1px 0 #989898; 23 | --aplayer-list-hover-background-color: var(--theme-color); 24 | } 25 | } -------------------------------------------------------------------------------- /src/css/variables/index.css: -------------------------------------------------------------------------------- 1 | /** 2 | * 全局变量表,使用 w3c 标准语法。 3 | * 如果具有多个相同命名的变量,则依据变量作用域确定优先级。 4 | */ 5 | @import "layout.css"; 6 | 7 | @import "moments.css"; 8 | 9 | @import "aplayer.css"; -------------------------------------------------------------------------------- /src/css/variables/moments.css: -------------------------------------------------------------------------------- 1 | .moments-container { 2 | --single-bg-and-btn-color: #e6e6fa; 3 | --single-font-color: #000000; 4 | 5 | --double-bg-and-btn-color: #f0ffff; 6 | --double-font-color: #000000; 7 | 8 | --moments-content-background: #e6e6fa; 9 | } 10 | 11 | .dark { 12 | & .moments-container { 13 | --halo-comment-widget-base-color: #000000; 14 | --halo-comment-widget-component-form-button-login-bg-color: #f0ffff; 15 | --halo-comment-widget-component-form-button-login-bg-color-hover: #f0f8ff; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import { type Sakura } from "./main"; 4 | 5 | declare global { 6 | interface Window { 7 | sakura: Sakura; 8 | } 9 | } -------------------------------------------------------------------------------- /src/languages/README.md: -------------------------------------------------------------------------------- 1 |

国际化功能说明文档

2 | 3 | # 功能说明 4 | 目前本主题的国际化,属于前端国际化。因此与 [Halo](https://halo.run) 后台有关的文字无法使用本国际化进行处理,例如【菜单及后台设置项】。建议将菜单手动设置为其他语种。 5 | 6 | 本文档主要说明 Sakura 主题的国际化方式,便于贡献者或二次编码的开发者进行理解。 7 | 8 | # 国际化方案 9 | 10 | 本项目所使用的国际化方案为 [i18next](https://www.i18next.com/)。这是一款非常优秀的国际化框架,建议在开发之前了解一下。 11 | 12 | ## 所用插件 13 | - [i18next-browser-languagedetector](https://github.com/i18next/i18next-browser-languageDetector) - 语言检查插件,能够自动检测浏览器中的用户语言 14 | - [i18next-chained-backend](https://github.com/i18next/i18next-chained-backend) - 后端链接,可以链接多个后端和缓存。本主题使用其链接了 localstorage 缓存后端与基于 webpack 的数据后端。 15 | - [i18next-localstorage-backend](https://github.com/i18next/i18next-localstorage-backend) - 基于 localStorage 的缓存后端 16 | - [loc-i18next](https://github.com/mthh/loc-i18next) - 对 HTML5 进行国际化的插件 17 | 18 | # 开发前准备 19 | 20 | TODO 21 | 22 | ## 开发直达车 23 | 24 | - 如果你想添加新语种,可以从 [添加新语种](#添加新语种) 开始查看 25 | - 如果你想编辑现有的语种,可以从 [编辑现有语种](#编辑现有语种) 开始查看 26 | - 如果你想对 HTML 进行编辑,并对其进行国际化,可以从 [在 HTML 中使用](#在-html-中使用) 开始查看。 27 | - 如果你想在 JavaScript 代码中进行国际化处理,可以从 [在 JavaScript 中使用](#在-javascript-中使用) 开始查看。 28 | 29 | # 添加新语种 30 | 31 | TODO 32 | 33 | # 编辑现有语种 34 | 35 | 36 | # 在 HTML 中使用 37 | 38 | # 在 JavaScript 中使用 39 | 40 | # 高级功能 41 | ## 自定义模板 42 | 43 | TODO 44 | 45 | # 作者 46 | 47 | © [LIlGG](https://github.com/LIlGG),基于 [MIT](./LICENSE) 许可证发行。
48 | 作者及其贡献者共有版权 ([帮助维护列表](https://github.com/LIlGG/halo-theme-sakura/graphs/contributors))。 49 | 50 | > [lixingyong.com](https://lixingyong.com) · GitHub [@LIlGG](https://github.com/LIlGG) -------------------------------------------------------------------------------- /src/libs/highlight/highlight-AndroidStudio.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | color: #a9b7c6; 3 | background: #282b2e; 4 | display: block; 5 | overflow-x: auto; 6 | padding: 0.5em; 7 | } 8 | .hljs-ln-numbers { 9 | background: #282b2e; 10 | } 11 | .hljs-bullet, 12 | .hljs-literal, 13 | .hljs-number, 14 | .hljs-symbol { 15 | color: #6897bb; 16 | } 17 | .hljs-deletion, 18 | .hljs-keyword, 19 | .hljs-selector-tag { 20 | color: #cc7832; 21 | } 22 | .hljs-link, 23 | .hljs-template-variable, 24 | .hljs-variable { 25 | color: #629755; 26 | } 27 | .hljs-comment, 28 | .hljs-quote { 29 | color: grey; 30 | } 31 | .hljs-meta { 32 | color: #bbb529; 33 | } 34 | .hljs-addition, 35 | .hljs-attribute, 36 | .hljs-string { 37 | color: #6a8759; 38 | } 39 | .hljs-section, 40 | .hljs-title, 41 | .hljs-type { 42 | color: #ffc66d; 43 | } 44 | .hljs-name, 45 | .hljs-selector-class, 46 | .hljs-selector-id { 47 | color: #e8bf6a; 48 | } 49 | .hljs-emphasis { 50 | font-style: italic; 51 | } 52 | .hljs-strong { 53 | font-weight: 700; 54 | } 55 | -------------------------------------------------------------------------------- /src/libs/highlight/highlight-Dark.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #444; 6 | } 7 | .hljs-ln-numbers { 8 | background: #444; 9 | } 10 | .hljs-keyword, 11 | .hljs-link, 12 | .hljs-literal, 13 | .hljs-section, 14 | .hljs-selector-tag { 15 | color: #fff; 16 | } 17 | .hljs, 18 | .hljs-subst { 19 | color: #ddd; 20 | } 21 | .hljs-addition, 22 | .hljs-attribute, 23 | .hljs-built_in, 24 | .hljs-bullet, 25 | .hljs-name, 26 | .hljs-string, 27 | .hljs-symbol, 28 | .hljs-template-tag, 29 | .hljs-template-variable, 30 | .hljs-title, 31 | .hljs-type, 32 | .hljs-variable { 33 | color: #d88; 34 | } 35 | .hljs-comment, 36 | .hljs-deletion, 37 | .hljs-meta, 38 | .hljs-quote { 39 | color: #777; 40 | } 41 | .hljs-doctag, 42 | .hljs-keyword, 43 | .hljs-literal, 44 | .hljs-name, 45 | .hljs-section, 46 | .hljs-selector-tag, 47 | .hljs-strong, 48 | .hljs-title, 49 | .hljs-type { 50 | font-weight: 700; 51 | } 52 | .hljs-emphasis { 53 | font-style: italic; 54 | } 55 | -------------------------------------------------------------------------------- /src/libs/highlight/highlight-Docco.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #f0f0f0; 6 | } 7 | .hljs-ln-numbers { 8 | background: #f0f0f0; 9 | } 10 | .hljs, 11 | .hljs-subst { 12 | color: #444; 13 | } 14 | .hljs-comment { 15 | color: #888; 16 | } 17 | .hljs-attribute, 18 | .hljs-doctag, 19 | .hljs-keyword, 20 | .hljs-meta-keyword, 21 | .hljs-name, 22 | .hljs-selector-tag { 23 | font-weight: 700; 24 | } 25 | .hljs-deletion, 26 | .hljs-number, 27 | .hljs-quote, 28 | .hljs-selector-class, 29 | .hljs-selector-id, 30 | .hljs-string, 31 | .hljs-template-tag, 32 | .hljs-type { 33 | color: #800; 34 | } 35 | .hljs-section, 36 | .hljs-title { 37 | color: #800; 38 | font-weight: 700; 39 | } 40 | .hljs-link, 41 | .hljs-regexp, 42 | .hljs-selector-attr, 43 | .hljs-selector-pseudo, 44 | .hljs-symbol, 45 | .hljs-template-variable, 46 | .hljs-variable { 47 | color: #bc6060; 48 | } 49 | .hljs-literal { 50 | color: #78a960; 51 | } 52 | .hljs-addition, 53 | .hljs-built_in, 54 | .hljs-bullet, 55 | .hljs-code { 56 | color: #397300; 57 | } 58 | .hljs-meta { 59 | color: #1f7199; 60 | } 61 | .hljs-meta-string { 62 | color: #4d99bf; 63 | } 64 | .hljs-emphasis { 65 | font-style: italic; 66 | } 67 | .hljs-strong { 68 | font-weight: 700; 69 | } 70 | .hljs-ln-code .hljs-ln-line:hover { 71 | background-color: rgba(14, 12, 12, 0.1); 72 | } 73 | .hljs-ln-line span::-moz-selection, 74 | .hljs-ln-line::-moz-selection { 75 | background: #0b0c0c; 76 | color: #d7dfeb; 77 | } 78 | .hljs-ln-line span::selection, 79 | .hljs-ln-line::selection { 80 | background: #0b0c0c; 81 | color: #d7dfeb; 82 | } 83 | -------------------------------------------------------------------------------- /src/libs/highlight/highlight-Dracula.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #282a36; 6 | } 7 | .hljs-ln-numbers { 8 | background: #282a36; 9 | } 10 | .hljs-keyword, 11 | .hljs-link, 12 | .hljs-literal, 13 | .hljs-section, 14 | .hljs-selector-tag { 15 | color: #8be9fd; 16 | } 17 | .hljs-function .hljs-keyword { 18 | color: #ff79c6; 19 | } 20 | .hljs, 21 | .hljs-subst { 22 | color: #f8f8f2; 23 | } 24 | .hljs-addition, 25 | .hljs-attribute, 26 | .hljs-bullet, 27 | .hljs-name, 28 | .hljs-string, 29 | .hljs-symbol, 30 | .hljs-template-tag, 31 | .hljs-template-variable, 32 | .hljs-title, 33 | .hljs-type, 34 | .hljs-variable { 35 | color: #f1fa8c; 36 | } 37 | .hljs-comment, 38 | .hljs-deletion, 39 | .hljs-meta, 40 | .hljs-quote { 41 | color: #6272a4; 42 | } 43 | .hljs-doctag, 44 | .hljs-keyword, 45 | .hljs-literal, 46 | .hljs-name, 47 | .hljs-section, 48 | .hljs-selector-tag, 49 | .hljs-strong, 50 | .hljs-title, 51 | .hljs-type { 52 | font-weight: 700; 53 | } 54 | .hljs-emphasis { 55 | font-style: italic; 56 | } 57 | -------------------------------------------------------------------------------- /src/libs/highlight/highlight-Far.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: navy; 6 | } 7 | .hljs-ln-numbers { 8 | background: navy; 9 | } 10 | .hljs, 11 | .hljs-subst { 12 | color: #0ff; 13 | } 14 | .hljs-addition, 15 | .hljs-attribute, 16 | .hljs-built_in, 17 | .hljs-builtin-name, 18 | .hljs-bullet, 19 | .hljs-string, 20 | .hljs-symbol, 21 | .hljs-template-tag, 22 | .hljs-template-variable { 23 | color: #ff0; 24 | } 25 | .hljs-keyword, 26 | .hljs-name, 27 | .hljs-section, 28 | .hljs-selector-class, 29 | .hljs-selector-id, 30 | .hljs-selector-tag, 31 | .hljs-type, 32 | .hljs-variable { 33 | color: #fff; 34 | } 35 | .hljs-comment, 36 | .hljs-deletion, 37 | .hljs-doctag, 38 | .hljs-quote { 39 | color: #888; 40 | } 41 | .hljs-link, 42 | .hljs-literal, 43 | .hljs-number, 44 | .hljs-regexp { 45 | color: #0f0; 46 | } 47 | .hljs-meta { 48 | color: teal; 49 | } 50 | .hljs-keyword, 51 | .hljs-name, 52 | .hljs-section, 53 | .hljs-selector-tag, 54 | .hljs-strong, 55 | .hljs-title { 56 | font-weight: 700; 57 | } 58 | .hljs-emphasis { 59 | font-style: italic; 60 | } 61 | -------------------------------------------------------------------------------- /src/libs/highlight/highlight-Github.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | color: #333; 6 | background: #f8f8f8; 7 | } 8 | .hljs-ln-numbers { 9 | background: #f8f8f8; 10 | } 11 | .hljs-comment, 12 | .hljs-quote { 13 | color: #998; 14 | font-style: italic; 15 | } 16 | .hljs-keyword, 17 | .hljs-selector-tag, 18 | .hljs-subst { 19 | color: #333; 20 | font-weight: 700; 21 | } 22 | .hljs-literal, 23 | .hljs-number, 24 | .hljs-tag .hljs-attr, 25 | .hljs-template-variable, 26 | .hljs-variable { 27 | color: teal; 28 | } 29 | .hljs-doctag, 30 | .hljs-string { 31 | color: #d14; 32 | } 33 | .hljs-section, 34 | .hljs-selector-id, 35 | .hljs-title { 36 | color: #900; 37 | font-weight: 700; 38 | } 39 | .hljs-subst { 40 | font-weight: 400; 41 | } 42 | .hljs-class .hljs-title, 43 | .hljs-type { 44 | color: #458; 45 | font-weight: 700; 46 | } 47 | .hljs-attribute, 48 | .hljs-name, 49 | .hljs-tag { 50 | color: navy; 51 | font-weight: 400; 52 | } 53 | .hljs-link, 54 | .hljs-regexp { 55 | color: #009926; 56 | } 57 | .hljs-bullet, 58 | .hljs-symbol { 59 | color: #990073; 60 | } 61 | .hljs-built_in, 62 | .hljs-builtin-name { 63 | color: #0086b3; 64 | } 65 | .hljs-meta { 66 | color: #999; 67 | font-weight: 700; 68 | } 69 | .hljs-deletion { 70 | background: #fdd; 71 | } 72 | .hljs-addition { 73 | background: #dfd; 74 | } 75 | .hljs-emphasis { 76 | font-style: italic; 77 | } 78 | .hljs-strong { 79 | font-weight: 700; 80 | } 81 | .hljs-ln-line::-moz-selection { 82 | background: #0b0c0c; 83 | color: #d7dfeb; 84 | } 85 | .hljs-ln-line span::selection, 86 | .hljs-ln-line::selection { 87 | background: #0b0c0c; 88 | color: #d7dfeb; 89 | } 90 | -------------------------------------------------------------------------------- /src/libs/highlight/highlight-Tomorrow Night.css: -------------------------------------------------------------------------------- 1 | .hljs-comment, 2 | .hljs-quote { 3 | color: #969896; 4 | } 5 | .hljs-ln-numbers { 6 | background: #1d1f21; 7 | } 8 | .hljs-deletion, 9 | .hljs-name, 10 | .hljs-regexp, 11 | .hljs-selector-class, 12 | .hljs-selector-id, 13 | .hljs-tag, 14 | .hljs-template-variable, 15 | .hljs-variable { 16 | color: #c66; 17 | } 18 | .hljs-built_in, 19 | .hljs-builtin-name, 20 | .hljs-link, 21 | .hljs-literal, 22 | .hljs-meta, 23 | .hljs-number, 24 | .hljs-params, 25 | .hljs-type { 26 | color: #de935f; 27 | } 28 | .hljs-attribute { 29 | color: #f0c674; 30 | } 31 | .hljs-addition, 32 | .hljs-bullet, 33 | .hljs-string, 34 | .hljs-symbol { 35 | color: #b5bd68; 36 | } 37 | .hljs-section, 38 | .hljs-title { 39 | color: #81a2be; 40 | } 41 | .hljs-keyword, 42 | .hljs-selector-tag { 43 | color: #b294bb; 44 | } 45 | .hljs { 46 | display: block; 47 | overflow-x: auto; 48 | background: #1d1f21; 49 | color: #c5c8c6; 50 | padding: 0.5em; 51 | } 52 | .hljs-emphasis { 53 | font-style: italic; 54 | } 55 | .hljs-strong { 56 | font-weight: 700; 57 | } 58 | -------------------------------------------------------------------------------- /src/libs/lazysizes.ts: -------------------------------------------------------------------------------- 1 | import lazySizes from 'lazysizes'; 2 | 3 | lazySizes.cfg.lazyClass = 'lazyload'; -------------------------------------------------------------------------------- /src/module/index.ts: -------------------------------------------------------------------------------- 1 | export * from './events'; 2 | 3 | export * from './utils'; -------------------------------------------------------------------------------- /src/page/archives.ts: -------------------------------------------------------------------------------- 1 | import { documentFunction } from "../main"; 2 | 3 | //TODO 尝试使用 animate 来重构动画,去掉 jquery 某些过渡动画比较不方便。 4 | 5 | export default class Archives { 6 | 7 | @documentFunction() 8 | public initArchiveHeight() { 9 | const archiveActiveElements = document.querySelectorAll(".archive-item.active"); 10 | archiveActiveElements.forEach((element) => { 11 | const posts = element.querySelector(".archive-posts") as HTMLElement; 12 | var height = posts?.scrollHeight; 13 | posts.style.maxHeight = height + 'px'; 14 | }); 15 | } 16 | 17 | @documentFunction() 18 | public registerArchiveEvent() { 19 | const archiveTitleElements = document.querySelectorAll(".archives-article .archive-title h3"); 20 | archiveTitleElements.forEach((element) => { 21 | element.addEventListener("click", () => { 22 | const archiveElement = element.parentElement?.parentElement; 23 | const posts = archiveElement?.querySelector(".archive-posts") as HTMLElement; 24 | if (archiveElement?.classList.contains("active")) { 25 | var height = posts?.scrollHeight; 26 | posts.style.maxHeight = height + 'px'; 27 | posts.style.maxHeight = '0'; 28 | archiveElement.classList.remove("active"); 29 | } else { 30 | var height = posts?.scrollHeight; 31 | archiveElement?.classList.add("active"); 32 | posts.style.maxHeight = height + 'px'; 33 | } 34 | }); 35 | }); 36 | } 37 | } -------------------------------------------------------------------------------- /src/page/category.ts: -------------------------------------------------------------------------------- 1 | // 创建一个空的类,防止请求 category.min.js 时报错 2 | export default class Category {} 3 | -------------------------------------------------------------------------------- /src/page/search.ts: -------------------------------------------------------------------------------- 1 | import { documentFunction, sakura } from "../main"; 2 | 3 | export default class Search { 4 | /** 5 | * 注册搜索框点击事件 6 | */ 7 | @documentFunction() 8 | public registerSearchForm() { 9 | const searchElement = document.querySelector(".search-form-inner") as HTMLElement; 10 | if (!(searchElement && searchElement instanceof HTMLFormElement)) { 11 | return; 12 | } 13 | 14 | searchElement.addEventListener("submit", (event) => { 15 | if (!sakura.$pjax) { 16 | return; 17 | } 18 | event.preventDefault(); 19 | const form = event.target; 20 | if (!(form && form instanceof HTMLFormElement)) { 21 | return; 22 | } 23 | const action = form.action; 24 | const keyword = form.keyword; 25 | sakura.$pjax.loadUrl(`${action}?${keyword.name}=${keyword.value}`); 26 | sakura.$pjax.refresh(); 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/utils/eventProxy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * WindowEventProxy 3 | * 4 | * @description 代理 window 事件。使用节流处理事件,防止事件频繁触发 5 | */ 6 | export class WindowEventProxy { 7 | private static eventThrottles: Map> = new Map(); 8 | 9 | public static addEventListener(eventType: string, listener: EventListener, delay: number) { 10 | let throttle: EventListener | undefined = WindowEventProxy.throttle(listener, delay); 11 | let throttles = this.eventThrottles.get(eventType); 12 | if (!throttles) { 13 | throttles = new Set(); 14 | this.eventThrottles.set(eventType, throttles); 15 | } 16 | throttles.add(throttle); 17 | window.addEventListener(eventType, throttle); 18 | } 19 | 20 | public static throttle(fn: Function, delay: number) { 21 | let timer: number | null = null; 22 | return (...args: any[]) => { 23 | if (!timer) { 24 | fn.apply(this, args); 25 | timer = window.setTimeout(() => { 26 | timer = null; 27 | }, delay); 28 | } 29 | }; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/utils/haloApi.ts: -------------------------------------------------------------------------------- 1 | export class HaloApi { 2 | /** 3 | * 实现点赞功能 4 | * 5 | * @description: Like function 6 | * @param {string} group 7 | * @param {string} plural 8 | * @param {string} name 9 | */ 10 | public static async like(group: string, plural: string, name: string): Promise { 11 | const response = await fetch("/apis/api.halo.run/v1alpha1/trackers/upvote", { 12 | method: "POST", 13 | headers: { 14 | "Content-Type": "application/json", 15 | }, 16 | body: JSON.stringify({ 17 | group: group, 18 | plural: plural, 19 | name: name, 20 | }), 21 | }); 22 | if (response.status !== 200) { 23 | console.error("点赞失败,请求异常"); 24 | return; 25 | } 26 | return response; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /templates/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/.DS_Store -------------------------------------------------------------------------------- /templates/archives.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 |

14 |
15 | 16 | 17 |
18 |
19 |
20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 |

28 |
29 |
34 |
35 | 36 |
37 | 46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | 56 | -------------------------------------------------------------------------------- /templates/assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/.DS_Store -------------------------------------------------------------------------------- /templates/assets/cursor/No_Disponible.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/cursor/No_Disponible.cur -------------------------------------------------------------------------------- /templates/assets/cursor/ayuda.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/cursor/ayuda.cur -------------------------------------------------------------------------------- /templates/assets/cursor/normal.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/cursor/normal.cur -------------------------------------------------------------------------------- /templates/assets/cursor/texto.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/cursor/texto.cur -------------------------------------------------------------------------------- /templates/assets/cursor/work.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/cursor/work.cur -------------------------------------------------------------------------------- /templates/assets/dist/assets/_commonjsHelpers-042e6b4d.js: -------------------------------------------------------------------------------- 1 | var f=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function l(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function a(e){if(e.__esModule)return e;var r=e.default;if(typeof r=="function"){var o=function n(){if(this instanceof n){var t=[null];t.push.apply(t,arguments);var u=Function.bind.apply(r,t);return new u}return r.apply(this,arguments)};o.prototype=r.prototype}else o={};return Object.defineProperty(o,"__esModule",{value:!0}),Object.keys(e).forEach(function(n){var t=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(o,n,t.get?t:{enumerable:!0,get:function(){return e[n]}})}),o}export{a,f as c,l as g}; 2 | -------------------------------------------------------------------------------- /templates/assets/dist/css/highlight-AndroidStudio-2.4.3.min.css: -------------------------------------------------------------------------------- 1 | .hljs{color:#a9b7c6;background:#282b2e;display:block;overflow-x:auto;padding:.5em}.hljs-ln-numbers{background:#282b2e}.hljs-bullet,.hljs-literal,.hljs-number,.hljs-symbol{color:#6897bb}.hljs-deletion,.hljs-keyword,.hljs-selector-tag{color:#cc7832}.hljs-link,.hljs-template-variable,.hljs-variable{color:#629755}.hljs-comment,.hljs-quote{color:gray}.hljs-meta{color:#bbb529}.hljs-addition,.hljs-attribute,.hljs-string{color:#6a8759}.hljs-section,.hljs-title,.hljs-type{color:#ffc66d}.hljs-name,.hljs-selector-class,.hljs-selector-id{color:#e8bf6a}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} 2 | -------------------------------------------------------------------------------- /templates/assets/dist/css/highlight-Dark-2.4.3.min.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:.5em;background:#444}.hljs-ln-numbers{background:#444}.hljs-keyword,.hljs-link,.hljs-literal,.hljs-section,.hljs-selector-tag{color:#fff}.hljs,.hljs-subst{color:#ddd}.hljs-addition,.hljs-attribute,.hljs-built_in,.hljs-bullet,.hljs-name,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type,.hljs-variable{color:#d88}.hljs-comment,.hljs-deletion,.hljs-meta,.hljs-quote{color:#777}.hljs-doctag,.hljs-keyword,.hljs-literal,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-strong,.hljs-title,.hljs-type{font-weight:700}.hljs-emphasis{font-style:italic} 2 | -------------------------------------------------------------------------------- /templates/assets/dist/css/highlight-Docco-2.4.3.min.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:.5em;background:#f0f0f0}.hljs-ln-numbers{background:#f0f0f0}.hljs,.hljs-subst{color:#444}.hljs-comment{color:#888}.hljs-attribute,.hljs-doctag,.hljs-keyword,.hljs-meta-keyword,.hljs-name,.hljs-selector-tag{font-weight:700}.hljs-deletion,.hljs-number,.hljs-quote,.hljs-selector-class,.hljs-selector-id,.hljs-string,.hljs-template-tag,.hljs-type{color:#800}.hljs-section,.hljs-title{color:#800;font-weight:700}.hljs-link,.hljs-regexp,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-symbol,.hljs-template-variable,.hljs-variable{color:#bc6060}.hljs-literal{color:#78a960}.hljs-addition,.hljs-built_in,.hljs-bullet,.hljs-code{color:#397300}.hljs-meta{color:#1f7199}.hljs-meta-string{color:#4d99bf}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-ln-code .hljs-ln-line:hover{background-color:#0e0c0c1a}.hljs-ln-line span::-moz-selection,.hljs-ln-line::-moz-selection{background:#0b0c0c;color:#d7dfeb}.hljs-ln-line span::selection,.hljs-ln-line::selection{background:#0b0c0c;color:#d7dfeb} 2 | -------------------------------------------------------------------------------- /templates/assets/dist/css/highlight-Dracula-2.4.3.min.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:.5em;background:#282a36}.hljs-ln-numbers{background:#282a36}.hljs-keyword,.hljs-link,.hljs-literal,.hljs-section,.hljs-selector-tag{color:#8be9fd}.hljs-function .hljs-keyword{color:#ff79c6}.hljs,.hljs-subst{color:#f8f8f2}.hljs-addition,.hljs-attribute,.hljs-bullet,.hljs-name,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable,.hljs-title,.hljs-type,.hljs-variable{color:#f1fa8c}.hljs-comment,.hljs-deletion,.hljs-meta,.hljs-quote{color:#6272a4}.hljs-doctag,.hljs-keyword,.hljs-literal,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-strong,.hljs-title,.hljs-type{font-weight:700}.hljs-emphasis{font-style:italic} 2 | -------------------------------------------------------------------------------- /templates/assets/dist/css/highlight-Far-2.4.3.min.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:.5em;background:navy}.hljs-ln-numbers{background:navy}.hljs,.hljs-subst{color:#0ff}.hljs-addition,.hljs-attribute,.hljs-built_in,.hljs-builtin-name,.hljs-bullet,.hljs-string,.hljs-symbol,.hljs-template-tag,.hljs-template-variable{color:#ff0}.hljs-keyword,.hljs-name,.hljs-section,.hljs-selector-class,.hljs-selector-id,.hljs-selector-tag,.hljs-type,.hljs-variable{color:#fff}.hljs-comment,.hljs-deletion,.hljs-doctag,.hljs-quote{color:#888}.hljs-link,.hljs-literal,.hljs-number,.hljs-regexp{color:#0f0}.hljs-meta{color:teal}.hljs-keyword,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-strong,.hljs-title{font-weight:700}.hljs-emphasis{font-style:italic} 2 | -------------------------------------------------------------------------------- /templates/assets/dist/css/highlight-Github-2.4.3.min.css: -------------------------------------------------------------------------------- 1 | .hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8}.hljs-ln-numbers{background:#f8f8f8}.hljs-comment,.hljs-quote{color:#998;font-style:italic}.hljs-keyword,.hljs-selector-tag,.hljs-subst{color:#333;font-weight:700}.hljs-literal,.hljs-number,.hljs-tag .hljs-attr,.hljs-template-variable,.hljs-variable{color:teal}.hljs-doctag,.hljs-string{color:#d14}.hljs-section,.hljs-selector-id,.hljs-title{color:#900;font-weight:700}.hljs-subst{font-weight:400}.hljs-class .hljs-title,.hljs-type{color:#458;font-weight:700}.hljs-attribute,.hljs-name,.hljs-tag{color:navy;font-weight:400}.hljs-link,.hljs-regexp{color:#009926}.hljs-bullet,.hljs-symbol{color:#990073}.hljs-built_in,.hljs-builtin-name{color:#0086b3}.hljs-meta{color:#999;font-weight:700}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-ln-line::-moz-selection{background:#0b0c0c;color:#d7dfeb}.hljs-ln-line span::-moz-selection,.hljs-ln-line::-moz-selection{background:#0b0c0c;color:#d7dfeb}.hljs-ln-line span::selection,.hljs-ln-line::selection{background:#0b0c0c;color:#d7dfeb} 2 | -------------------------------------------------------------------------------- /templates/assets/dist/css/highlight-Tomorrow Night-2.4.3.min.css: -------------------------------------------------------------------------------- 1 | .hljs-comment,.hljs-quote{color:#969896}.hljs-ln-numbers{background:#1d1f21}.hljs-deletion,.hljs-name,.hljs-regexp,.hljs-selector-class,.hljs-selector-id,.hljs-tag,.hljs-template-variable,.hljs-variable{color:#c66}.hljs-built_in,.hljs-builtin-name,.hljs-link,.hljs-literal,.hljs-meta,.hljs-number,.hljs-params,.hljs-type{color:#de935f}.hljs-attribute{color:#f0c674}.hljs-addition,.hljs-bullet,.hljs-string,.hljs-symbol{color:#b5bd68}.hljs-section,.hljs-title{color:#81a2be}.hljs-keyword,.hljs-selector-tag{color:#b294bb}.hljs{display:block;overflow-x:auto;background:#1d1f21;color:#c5c8c6;padding:.5em}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700} 2 | -------------------------------------------------------------------------------- /templates/assets/dist/page/archives-2.4.3.min.js: -------------------------------------------------------------------------------- 1 | import{d as a}from"../main-2.4.3.min.js";import"../assets/_commonjsHelpers-042e6b4d.js";var h=Object.defineProperty,n=Object.getOwnPropertyDescriptor,v=(l,c,r,e)=>{for(var t=e>1?void 0:e?n(c,r):c,i=l.length-1,s;i>=0;i--)(s=l[i])&&(t=(e?s(c,r,t):s(t))||t);return e&&t&&h(c,r,t),t};class o{initArchiveHeight(){document.querySelectorAll(".archive-item.active").forEach(r=>{const e=r.querySelector(".archive-posts");var t=e==null?void 0:e.scrollHeight;e.style.maxHeight=t+"px"})}registerArchiveEvent(){document.querySelectorAll(".archives-article .archive-title h3").forEach(r=>{r.addEventListener("click",()=>{var s;const e=(s=r.parentElement)==null?void 0:s.parentElement,t=e==null?void 0:e.querySelector(".archive-posts");if(e!=null&&e.classList.contains("active")){var i=t==null?void 0:t.scrollHeight;t.style.maxHeight=i+"px",t.style.maxHeight="0",e.classList.remove("active")}else{var i=t==null?void 0:t.scrollHeight;e==null||e.classList.add("active"),t.style.maxHeight=i+"px"}})})}}v([a()],o.prototype,"initArchiveHeight",1);v([a()],o.prototype,"registerArchiveEvent",1); 2 | -------------------------------------------------------------------------------- /templates/assets/dist/page/categories-2.4.3.min.js: -------------------------------------------------------------------------------- 1 | import{d,U as y,_ as c,s as _}from"../main-2.4.3.min.js";import"../assets/_commonjsHelpers-042e6b4d.js";var m=Object.defineProperty,h=Object.getOwnPropertyDescriptor,u=(l,a,t,o)=>{for(var r=o>1?void 0:o?h(a,t):a,i=l.length-1,n;i>=0;i--)(n=l[i])&&(r=(o?n(a,t,r):n(r))||r);return o&&r&&m(a,t,r),r};class p{registerCategories(){document.querySelectorAll(".categories-container .chip").forEach(t=>{t.style.backgroundColor||(t.style.backgroundColor=y.generateColor())})}async registerCategoryRadarChart(){const a=document.getElementById("category-echarts");if(!a)return;const t=await c(()=>import("../assets/core-72662ce9.js"),["assets/core-72662ce9.js","assets/Axis-725f4b2a.js","assets/graphic-ce8bd673.js","assets/createSeriesData-c8f251b5.js"]);await c(()=>import("../assets/charts-f05d9f95.js"),["assets/charts-f05d9f95.js","assets/graphic-ce8bd673.js","assets/createSeriesData-c8f251b5.js","assets/Axis-725f4b2a.js","assets/customGraphicKeyframeAnimation-c31f2f6f.js"]).then(e=>{t.use([e.RadarChart])}),await c(()=>import("../assets/components-6d07079e.js"),["assets/components-6d07079e.js","assets/customGraphicKeyframeAnimation-c31f2f6f.js","assets/Axis-725f4b2a.js","assets/graphic-ce8bd673.js"]).then(e=>{t.use([e.TitleComponent,e.TooltipComponent])}),await c(()=>import("../assets/renderers-f58e1b15.js"),["assets/renderers-f58e1b15.js","assets/graphic-ce8bd673.js"]).then(e=>{t.use([e.CanvasRenderer])});const o=Object.values(categoryRadar),r=Object.keys(categoryRadar);if(r.length<3)return;a.classList.add("category-echarts");const i=Math.ceil(o.reduce((e,s)=>e>s?e:s)/5)*5,n=t.init(a),g=document.querySelectorAll(".dark").length>0?"#ccc":"black";n.setOption({title:{text:_.translate("page.categories.radar_title","文章分类雷达图"),left:"center",top:"25px",textStyle:{fontSize:22,fontWeight:"normal",color:g}},tooltip:{trigger:"item",textStyle:{align:"left"}},radar:[{indicator:function(){for(var e=[],s=0;s{for(var c=i>1?void 0:i?A(o,s):o,e=v.length-1,a;e>=0;e--)(a=v[e])&&(c=(i?a(o,s,c):a(c))||c);return i&&c&&q(o,s,c),c};class _{registerJustifyLayout(){}registerMasonryLayout(){const o=document.querySelector(".masonry-container");if(!o)return;const s=o.querySelector(".gallery");n(()=>import("../assets/isotope-c78448f5.js").then(i=>i.i),["assets/isotope-c78448f5.js","assets/_commonjsHelpers-042e6b4d.js"]).then(i=>{var L;const c=new i.default(s,{layoutMode:"masonry",masonry:{gutter:10},itemSelector:".gallery-item"});s==null||s.querySelectorAll("img.lazyload").forEach(t=>{t.addEventListener("load",()=>{c.layout()})}),c.once("layoutComplete",function(){var t;(t=o.querySelector(".photos-content"))==null||t.classList.remove("loading")});const e=o==null?void 0:o.querySelector("#gallery-filter"),a=e==null?void 0:e.querySelectorAll("li span"),y=(L=S.getThemeConfig("photos","default_group",String))==null?void 0:L.valueOf();a==null||a.forEach(t=>{const r=t.getAttribute("data-filter");y&&r==`.${y}`&&(a[0].classList.remove("active"),t.classList.add("active"),c.arrange({filter:r})),t.addEventListener("click",u=>{u.preventDefault(),!t.classList.contains("active")&&(a==null||a.forEach(f=>{f.classList.remove("active")}),t.classList.add("active"),c.arrange({filter:r}))})});const l=o==null?void 0:o.querySelectorAll("#grid-changer span");l==null||l.forEach(t=>{t==null||t.addEventListener("click",()=>{l.forEach(r=>{r.classList.remove("active")}),t.classList.add("active"),s==null||s.querySelectorAll("[class*='col-']").forEach(r=>{for(let u=0;u{r.classList.add("col-"+t.getAttribute("data-col")||"")}),c.layout()})})})}}p([d(!1)],_.prototype,"registerJustifyLayout",1);p([d()],_.prototype,"registerMasonryLayout",1); 2 | -------------------------------------------------------------------------------- /templates/assets/dist/page/search-2.4.3.min.js: -------------------------------------------------------------------------------- 1 | import{d as m,s as c}from"../main-2.4.3.min.js";import"../assets/_commonjsHelpers-042e6b4d.js";var f=Object.defineProperty,i=Object.getOwnPropertyDescriptor,p=(a,t,o,e)=>{for(var r=e>1?void 0:e?i(t,o):t,n=a.length-1,s;n>=0;n--)(s=a[n])&&(r=(e?s(t,o,r):s(r))||r);return e&&r&&f(t,o,r),r};class u{registerSearchForm(){const t=document.querySelector(".search-form-inner");t&&t instanceof HTMLFormElement&&t.addEventListener("submit",o=>{if(!c.$pjax)return;o.preventDefault();const e=o.target;if(!(e&&e instanceof HTMLFormElement))return;const r=e.action,n=e.keyword;c.$pjax.loadUrl(`${r}?${n.name}=${n.value}`),c.$pjax.refresh()})}}p([m()],u.prototype,"registerSearchForm",1); 2 | -------------------------------------------------------------------------------- /templates/assets/images/default/avatar.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/default/avatar.webp -------------------------------------------------------------------------------- /templates/assets/images/default/hd.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/default/hd.webp -------------------------------------------------------------------------------- /templates/assets/images/default/temp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/default/temp.webp -------------------------------------------------------------------------------- /templates/assets/images/email/head.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/email/head.webp -------------------------------------------------------------------------------- /templates/assets/images/email/hr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/email/hr.png -------------------------------------------------------------------------------- /templates/assets/images/footer/gongan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/footer/gongan.png -------------------------------------------------------------------------------- /templates/assets/images/load/load.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/load/load.gif -------------------------------------------------------------------------------- /templates/assets/images/load/orange.progress-bar-stripe-loader.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /templates/assets/images/load/rotating-ball-o.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /templates/assets/images/next-b.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/assets/images/scroll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/scroll.png -------------------------------------------------------------------------------- /templates/assets/images/search/iloli.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/search/iloli.gif -------------------------------------------------------------------------------- /templates/assets/images/sns/bilibili.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/bilibili.png -------------------------------------------------------------------------------- /templates/assets/images/sns/csdn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/csdn.png -------------------------------------------------------------------------------- /templates/assets/images/sns/douban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/douban.png -------------------------------------------------------------------------------- /templates/assets/images/sns/email.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/assets/images/sns/facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/facebook.png -------------------------------------------------------------------------------- /templates/assets/images/sns/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/github.png -------------------------------------------------------------------------------- /templates/assets/images/sns/googleplus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/googleplus.png -------------------------------------------------------------------------------- /templates/assets/images/sns/heart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/heart.png -------------------------------------------------------------------------------- /templates/assets/images/sns/jianshu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/jianshu.png -------------------------------------------------------------------------------- /templates/assets/images/sns/linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/linkedin.png -------------------------------------------------------------------------------- /templates/assets/images/sns/lofter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/lofter.png -------------------------------------------------------------------------------- /templates/assets/images/sns/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/qq.png -------------------------------------------------------------------------------- /templates/assets/images/sns/qzone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/qzone.png -------------------------------------------------------------------------------- /templates/assets/images/sns/rss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/rss.png -------------------------------------------------------------------------------- /templates/assets/images/sns/sina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/sina.png -------------------------------------------------------------------------------- /templates/assets/images/sns/stackoverflow.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/assets/images/sns/telegram.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/assets/images/sns/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/twitter.png -------------------------------------------------------------------------------- /templates/assets/images/sns/wangyiyun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/wangyiyun.png -------------------------------------------------------------------------------- /templates/assets/images/sns/wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/wechat.png -------------------------------------------------------------------------------- /templates/assets/images/sns/weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/weibo.png -------------------------------------------------------------------------------- /templates/assets/images/sns/youku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/youku.png -------------------------------------------------------------------------------- /templates/assets/images/sns/zhihu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/sns/zhihu.png -------------------------------------------------------------------------------- /templates/assets/images/themes/gribs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/themes/gribs.jpg -------------------------------------------------------------------------------- /templates/assets/images/themes/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/themes/grid.png -------------------------------------------------------------------------------- /templates/assets/images/themes/kyotoanimation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/themes/kyotoanimation.png -------------------------------------------------------------------------------- /templates/assets/images/themes/little-monster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/themes/little-monster.png -------------------------------------------------------------------------------- /templates/assets/images/themes/sakura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/themes/sakura.png -------------------------------------------------------------------------------- /templates/assets/images/themes/star02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/themes/star02.png -------------------------------------------------------------------------------- /templates/assets/images/video/pause@32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/video/pause@32x32.png -------------------------------------------------------------------------------- /templates/assets/images/video/play@32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/video/play@32x32.png -------------------------------------------------------------------------------- /templates/assets/images/wave/wave1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/wave/wave1.png -------------------------------------------------------------------------------- /templates/assets/images/wave/wave2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LIlGG/halo-theme-sakura/e9c2841bf2e3bf8800c803f64e643e14bbbfb5b6/templates/assets/images/wave/wave2.png -------------------------------------------------------------------------------- /templates/author.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 |
16 | 17 | 18 |

19 |
20 | 21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 |
29 |
30 | 31 | 32 | 33 |
34 | 35 |
36 |
37 | 38 | -------------------------------------------------------------------------------- /templates/categories.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 7 | 8 | 9 | 10 |

11 |
12 | 13 | 14 |
15 |
16 |
17 |
18 |
19 |
22 |    23 |
24 | 34 |
35 |
36 |
37 |
38 | 39 |
40 |
41 |
42 | 46 |
47 |
48 |
49 |
50 |
51 | 52 | -------------------------------------------------------------------------------- /templates/category.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 |
16 | 17 | 18 | 19 |

20 | 21 |
22 | 23 | 24 |
25 |
26 | 27 | 28 | 29 | 30 |
31 |
32 | 33 | 34 | 35 |
36 | 37 |
38 |
39 | 40 | -------------------------------------------------------------------------------- /templates/error/404.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |
15 |
16 |
17 | 24 | 32 |
33 | 34 | 51 | 52 |
53 | 56 | 57 | 62 |
63 |
64 | 65 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |
9 |
10 |
11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 |

28 | 29 | 30 |

31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 | 47 | 48 | 49 | 50 |
51 | 52 |
53 | 54 | -------------------------------------------------------------------------------- /templates/links.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 13 | 14 | 15 | 16 |

17 |
18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /templates/macro/content-links.html: -------------------------------------------------------------------------------- 1 | 2 | 34 | 35 | -------------------------------------------------------------------------------- /templates/macro/content-masonry-photos.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 27 |
28 | 29 |
30 | 55 |
56 |
57 |
58 | -------------------------------------------------------------------------------- /templates/macro/content-none.html: -------------------------------------------------------------------------------- 1 |
2 | 5 | 6 |
7 |

8 |
9 |
-------------------------------------------------------------------------------- /templates/macro/content-page.html: -------------------------------------------------------------------------------- 1 | 2 |
4 | 5 |
6 |
7 |
-------------------------------------------------------------------------------- /templates/macro/sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 12 | -------------------------------------------------------------------------------- /templates/module/authorprofile.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 19 |

20 | 21 | 22 | 23 |

24 |
25 |
26 | -------------------------------------------------------------------------------- /templates/module/comment.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 |
6 | -------------------------------------------------------------------------------- /templates/module/feature.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | 8 | 12 | 13 |

14 | 15 | 45 |
46 | -------------------------------------------------------------------------------- /templates/module/footer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 11 | 42 | 76 | 77 | -------------------------------------------------------------------------------- /templates/module/head/fonts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | -------------------------------------------------------------------------------- /templates/module/head/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 22 | 23 | 24 | 27 | 28 | 29 | 40 | -------------------------------------------------------------------------------- /templates/module/header/brand.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | 6 | 7 |
8 |

9 | 10 |

11 |
-------------------------------------------------------------------------------- /templates/module/header/index.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 |
6 |
7 |
8 |
9 | 10 |
11 |
12 |
13 |
14 | 15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /templates/module/header/menu-item.html: -------------------------------------------------------------------------------- 1 | 25 | -------------------------------------------------------------------------------- /templates/module/header/menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 11 | -------------------------------------------------------------------------------- /templates/module/header/nav-toggle.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/module/header/search.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/module/header/user.html: -------------------------------------------------------------------------------- 1 |
3 | 4 | user avatar 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 |
13 | 16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
-------------------------------------------------------------------------------- /templates/module/home/focus_tou.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 23 |

29 |
30 |
31 | -------------------------------------------------------------------------------- /templates/module/home/go_down.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | -------------------------------------------------------------------------------- /templates/module/home/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /templates/module/home/notice.html: -------------------------------------------------------------------------------- 1 | 2 |
7 | 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /templates/module/home/top_social.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
  • 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
  • 13 |
    14 | 15 | 16 | 17 | sns 18 | 19 | 20 | sns 21 | 22 | 25 | 26 |
    27 | -------------------------------------------------------------------------------- /templates/module/home/video_box.html: -------------------------------------------------------------------------------- 1 | 4 |
    5 |
    6 |
    7 |
    8 |
    9 |
    10 |
    11 |
    12 | -------------------------------------------------------------------------------- /templates/module/home/wave.html: -------------------------------------------------------------------------------- 1 | 4 |
    5 |
    6 |
    7 |
    8 |
    9 | -------------------------------------------------------------------------------- /templates/module/list-pagination.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /templates/module/photo/group.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 18 |
    19 |
    20 | -------------------------------------------------------------------------------- /templates/module/post/post-meta.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 | 25 | 26 | 40 | 41 | 52 | 53 | 56 |
    57 |
    58 | -------------------------------------------------------------------------------- /templates/module/search/search-item.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
    26 | -------------------------------------------------------------------------------- /templates/module/search/search-moment.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 8 | 9 | 13 | 14 |
    15 |

    16 | 22 |

    23 |
    24 | 25 | 35 |
    36 |
    37 | 38 |
    39 |

    40 |
    41 | 42 | 49 |
    50 |
    51 | -------------------------------------------------------------------------------- /templates/module/sidebar/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /templates/module/sidebar/mobile-sidebar.html: -------------------------------------------------------------------------------- 1 | 2 |
    3 |
    4 | site logo 10 |
    11 | 12 |

    17 | 18 | 21 | 37 | 38 | 39 | 40 | 51 | 52 | 53 | 54 | 61 |
    62 |
    63 | -------------------------------------------------------------------------------- /templates/module/variables/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /templates/module/variables/layout.html: -------------------------------------------------------------------------------- 1 | 60 | -------------------------------------------------------------------------------- /templates/module/variables/moments.html: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /templates/module/variables/photos.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /templates/module/variables/post.html: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /templates/module/widgets/cd-top.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /templates/module/widgets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /templates/module/widgets/search-modal.html: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | -------------------------------------------------------------------------------- /templates/module/widgets/theme-change.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
    4 |
    5 |   7 | 8 | 9 |
    10 |
    11 | 12 | 15 |
    16 |
    17 | 24 |
    25 |
    26 |
    27 |
    28 | -------------------------------------------------------------------------------- /templates/moments.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 |

    18 |
    19 | 20 | 21 |
    22 |
      23 |
    • 24 | 25 |
    • 26 |
    27 | 28 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 43 | -------------------------------------------------------------------------------- /templates/page.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 |
    12 | 13 |
    14 |
    15 | 16 | 17 |

    18 |
    19 | 20 | 21 |
    22 | 23 |
    24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /templates/page_links.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 |

    21 |
    22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /templates/photos.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 |

    21 |
    22 | 23 | 24 | 29 |
    30 |
    31 | 32 |
    33 |
    34 |
    35 | 36 | -------------------------------------------------------------------------------- /templates/post.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 |
    10 | 12 |
    13 |
    14 | 15 | 16 |

    17 | 20 |
    21 | 22 | 23 |
    24 | 25 | 26 | 27 |
    28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /templates/scripts/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | -------------------------------------------------------------------------------- /templates/scripts/noscript.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /templates/search.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 |
    12 | 13 |

    18 | 19 | 20 | 21 | 22 | 23 | 34 |
    35 |

    36 |
    37 | 38 | 39 |
    40 |
    41 | 42 | -------------------------------------------------------------------------------- /templates/tag.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 |
    13 | 16 |
    17 |
    18 | 19 | 20 |

    21 |
    22 | 23 | 24 |
    25 |
    26 | 27 | 28 | 29 | 30 |
    31 |
    32 | 33 | 34 | 35 |
    36 | 37 |
    38 |
    39 | 40 | -------------------------------------------------------------------------------- /templates/tags.html: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 12 | 13 |

    14 |
    15 | 16 | 17 |
    18 | 19 |
    20 | 32 |
    33 |
    34 |
    35 |
    36 |
    37 |
    38 |
    39 |
    43 | 44 | 45 |
    46 | 60 |
    61 |
    62 |
    63 |
    64 |
    65 |
    66 | 67 | -------------------------------------------------------------------------------- /theme.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: theme.halo.run/v1alpha1 2 | kind: Theme 3 | spec: 4 | customTemplates: 5 | page: 6 | - name: 友情链接 7 | description: 支持可预设文本的友链 8 | screenshot: 9 | file: page_links.html 10 | displayName: Sakura 11 | author: 12 | name: LIlGG 13 | website: https://lixingyong.com 14 | description: Halo 2.x 版本樱花🌸主题 15 | logo: /themes/theme-sakura/assets/images/search/iloli.gif 16 | website: https://github.com/LIlGG/halo-theme-sakura 17 | repo: https://github.com/LIlGG/halo-theme-sakura.git 18 | settingName: theme-sakura-setting 19 | configMapName: theme-sakura-configMap 20 | # 通过 vite 环境变量 (VITE_THEME_VERSION) 配置,这里不需要配置。 21 | version: 2.4.3 22 | require: ">=2.19.0" 23 | metadata: 24 | name: theme-sakura 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "lib": ["ESNext", "DOM", "DOM.Iterable"], 7 | "moduleResolution": "Node", 8 | "strict": true, 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "esModuleInterop": true, 13 | "noEmit": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "noImplicitReturns": true, 17 | "skipLibCheck": true, 18 | "experimentalDecorators": true, 19 | "emitDecoratorMetadata": true 20 | }, 21 | "include": ["src", "src/env.d.ts"] 22 | } -------------------------------------------------------------------------------- /vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_THEME_VERSION: string 5 | } 6 | 7 | interface ImportMeta { 8 | readonly env: ImportMetaEnv 9 | } -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { globSync } from "glob"; 2 | import { defineConfig } from "vite"; 3 | import { fileURLToPath } from "url"; 4 | import path from "path"; 5 | import PurgeIcons from 'vite-plugin-purge-icons'; 6 | import fs from 'fs'; 7 | import { loadEnv } from "vite"; 8 | 9 | const THEME_BASE = "/themes/theme-sakura"; 10 | const ASSETS_BASE = `/assets/dist/`; 11 | 12 | export default ({ mode }: { mode: string }) => { 13 | const env = loadEnv(mode, process.cwd()) 14 | 15 | return defineConfig({ 16 | plugins: [ 17 | PurgeIcons({ 18 | content: [ 19 | './templates/*/*.html', 20 | ], 21 | }), 22 | { 23 | name: 'write-version-plugin', 24 | closeBundle() { 25 | const version = env.VITE_THEME_VERSION; 26 | const yamlFilePath = path.resolve(__dirname, 'theme.yaml'); 27 | let yamlContent = fs.readFileSync(yamlFilePath, 'utf8'); 28 | yamlContent = yamlContent.replace(/version:\s*.*$/m, `version: ${version}`); 29 | fs.writeFileSync(yamlFilePath, yamlContent, 'utf8'); 30 | }, 31 | } 32 | ], 33 | base: THEME_BASE + ASSETS_BASE, 34 | build: { 35 | outDir: "templates" + ASSETS_BASE, 36 | minify: mode === 'development' ? false : true, 37 | rollupOptions: { 38 | input: Object.fromEntries( 39 | globSync(["src/main.ts", "src/libs/**/*.*", "src/page/**/*.*"]).map((file) => [ 40 | path.relative("src", file.slice(0, file.length - path.extname(file).length)), 41 | fileURLToPath(new URL(file, import.meta.url)), 42 | ]) 43 | ), 44 | output: { 45 | format: "es", 46 | entryFileNames: `[name]-${env.VITE_THEME_VERSION}.min.js`, 47 | assetFileNames: (assetInfo) => { 48 | if (assetInfo.name && assetInfo.name.endsWith(".css")) { 49 | return `css/[name]-${env.VITE_THEME_VERSION}.min.[ext]`; 50 | } 51 | return `[name].min.[ext]`; 52 | }, 53 | }, 54 | }, 55 | sourcemap: false, 56 | chunkSizeWarningLimit: 1024 57 | }, 58 | }); 59 | }; 60 | --------------------------------------------------------------------------------