├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── zh-cn-1-help.yaml │ ├── zh-cn-5-feature-request.yaml │ ├── zh-cn-8-bug-report.yaml │ └── zh-cn-9-other-issue.yaml ├── PULL_REQUEST_TEMPLATE.md ├── config.yml ├── dependabot.yml ├── label-commenter-config.yml ├── labeler.yml ├── publish.sh └── workflows │ ├── label-commenter.yml │ ├── labeler.yml │ ├── merge-conflicts.yml │ ├── merge-squash-main.yml │ ├── npm-publish.yml │ ├── pr-updater.yml │ ├── release-please.yml │ ├── sync-coding.yml │ └── test-deploy.yml ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── _cdn.yml ├── _config.yml ├── languages ├── en.yml ├── zh-CN.yml └── zh-TW.yml ├── layout ├── 404.ejs ├── _meta │ ├── artalkcount.ejs │ ├── author.ejs │ ├── category.ejs │ ├── counter.ejs │ ├── date.ejs │ ├── music.ejs │ ├── share.ejs │ ├── tags.ejs │ ├── thumbnail.ejs │ ├── updated.ejs │ ├── walinecount.ejs │ └── wordcount.ejs ├── _partial │ ├── _cover │ │ ├── blank.ejs │ │ ├── dock.ejs │ │ ├── featured.ejs │ │ ├── focus.ejs │ │ ├── layout.ejs │ │ └── search.ejs │ ├── archive.ejs │ ├── article.ejs │ ├── categories.ejs │ ├── cover.ejs │ ├── footer.ejs │ ├── head.ejs │ ├── header.ejs │ ├── meta.ejs │ ├── post.ejs │ ├── scripts │ │ ├── _ctrl.ejs │ │ ├── config.ejs │ │ ├── global.ejs │ │ └── index.ejs │ └── side.ejs ├── _plugins │ ├── _page_plugins │ │ ├── artitalk │ │ │ └── index.ejs │ │ ├── bbtalk │ │ │ └── index.ejs │ │ ├── fcircle │ │ │ └── index.ejs │ │ ├── fcircle_lite │ │ │ └── index.ejs │ │ ├── gitter │ │ │ └── index.ejs │ │ ├── indent │ │ │ └── index.ejs │ │ ├── index.ejs │ │ ├── katex │ │ │ └── index.ejs │ │ ├── mathjax │ │ │ └── index.ejs │ │ ├── memos │ │ │ └── index.ejs │ │ └── snackbar │ │ │ └── index.ejs │ ├── analytics │ │ └── script.ejs │ ├── aplayer │ │ ├── layout.ejs │ │ └── script.ejs │ ├── chat │ │ ├── gitter │ │ │ └── script.ejs │ │ ├── index.ejs │ │ └── tidio │ │ │ └── script.ejs │ ├── comments │ │ ├── artalk │ │ │ └── script.ejs │ │ ├── beaudar │ │ │ └── script.ejs │ │ ├── discuss │ │ │ └── script.ejs │ │ ├── disqus │ │ │ └── script.ejs │ │ ├── disqusjs │ │ │ └── script.ejs │ │ ├── giscus │ │ │ └── script.ejs │ │ ├── gitalk │ │ │ └── script.ejs │ │ ├── hashover │ │ │ └── script.ejs │ │ ├── index.ejs │ │ ├── isso │ │ │ └── script.ejs │ │ ├── livere │ │ │ └── script.ejs │ │ ├── twikoo │ │ │ └── script.ejs │ │ ├── utterances │ │ │ └── script.ejs │ │ ├── vssue │ │ │ └── script.ejs │ │ ├── waline │ │ │ └── script.ejs │ │ └── z-custom │ │ │ └── script.ejs │ ├── content-visibility │ │ └── script.ejs │ ├── darkmode │ │ └── script.ejs │ ├── end-of-support │ │ └── script.ejs │ ├── github-api │ │ └── script.ejs │ ├── highlight │ │ ├── highlightjs │ │ │ └── script.ejs │ │ ├── prismjs │ │ │ └── script.ejs │ │ └── script.ejs │ ├── lazyload │ │ └── script.ejs │ ├── nodewaves │ │ └── script.ejs │ ├── pace │ │ └── script.ejs │ ├── parallax │ │ └── script.ejs │ ├── preload │ │ └── script.ejs │ ├── rightmenus │ │ └── layout.ejs │ ├── scrollreveal │ │ └── script.ejs │ ├── search │ │ └── script.ejs │ ├── share │ │ └── layout.ejs │ ├── slow-network │ │ └── script.ejs │ ├── swiper │ │ └── script.ejs │ ├── tianligpt │ │ └── script.ejs │ └── toc │ │ └── script.ejs ├── _pre.ejs ├── _widget │ ├── _pre.ejs │ ├── blogger.ejs │ ├── category.ejs │ ├── copyright.ejs │ ├── grid.ejs │ ├── group.ejs │ ├── header.ejs │ ├── lastupdate.ejs │ ├── list.ejs │ ├── load.ejs │ ├── memos_carousel.ejs │ ├── music.ejs │ ├── page.ejs │ ├── qrcode.ejs │ ├── references.ejs │ ├── related_posts.ejs │ ├── tagcloud.ejs │ ├── text.ejs │ ├── toc.ejs │ └── webinfo.ejs ├── archive.ejs ├── category.ejs ├── docs.ejs ├── friends.ejs ├── index.ejs ├── layout.ejs ├── list.ejs ├── page.ejs ├── post.ejs └── tag.ejs ├── package.json ├── scripts ├── events │ ├── index.js │ └── lib │ │ ├── cdn.js │ │ ├── check-configuration.js │ │ ├── check-environment.js │ │ ├── config.js │ │ ├── render-stylus.js │ │ └── stellar-tag-utils.js ├── filters │ ├── content-visibility.js │ ├── img.js │ ├── replace.js │ └── z-lazyload.js ├── helpers │ ├── custom-files.js │ ├── first-style.js │ ├── getList.js │ ├── head │ │ ├── autoCanonical.js │ │ ├── generate_preload_fontfamily.js │ │ ├── generate_seo.js │ │ └── generate_title__keywords__description.js │ ├── related-posts.js │ ├── structured-data │ │ ├── index.js │ │ └── lib │ │ │ ├── blogposting.js │ │ │ ├── breadcrumblist.js │ │ │ ├── config.js │ │ │ ├── index.js │ │ │ ├── organization.js │ │ │ ├── person.js │ │ │ └── website.js │ └── 文章推荐.js └── tags │ ├── btn.js │ ├── btns.js │ ├── checkbox.js │ ├── contributors.js │ ├── dropmenu.js │ ├── fancybox.js │ ├── folding.js │ ├── frame.js │ ├── friends.js │ ├── ghcard.js │ ├── image.js │ ├── inline-labels.js │ ├── link.js │ ├── md.js │ ├── media.js │ ├── note.js │ ├── pandown.js │ ├── site.js │ ├── span.js │ ├── swiper.js │ ├── table.js │ ├── tabs.js │ └── timeline.js └── source ├── css ├── Readme.md ├── _defines │ ├── AutoPrefixCSS.styl │ ├── Readme.md │ ├── color.styl │ ├── effect.styl │ ├── fonts.styl │ ├── func.styl │ └── layout.styl ├── _first │ ├── base_first.styl │ ├── cover_first.styl │ ├── dark_first.styl │ ├── fontfamily_first.styl │ ├── navbar_first.styl │ └── search_first.styl ├── _style │ ├── _base │ │ ├── base.styl │ │ └── fontfamily_async.styl │ ├── _layout │ │ ├── archive.styl │ │ ├── article.styl │ │ ├── footer.styl │ │ ├── friends-simpleuser.styl │ │ ├── friends-traditional.styl │ │ ├── img.styl │ │ ├── loading.styl │ │ ├── main.styl │ │ ├── md.styl │ │ ├── pagination.styl │ │ ├── posts.styl │ │ ├── search.styl │ │ ├── sidebar.styl │ │ ├── snackbar.styl │ │ ├── toc.styl │ │ └── video.styl │ ├── _plugins │ │ ├── _dark │ │ │ ├── dark_async.styl │ │ │ └── dark_plugins.styl │ │ ├── _highlight │ │ │ ├── highlightjs │ │ │ │ ├── clipboard.styl │ │ │ │ ├── color.styl │ │ │ │ ├── index.styl │ │ │ │ └── language.styl │ │ │ ├── index.styl │ │ │ └── prismjs │ │ │ │ ├── clipboard.styl │ │ │ │ ├── index.styl │ │ │ │ └── language.styl │ │ ├── _rightmenu │ │ │ ├── reading.styl │ │ │ └── rightmenu.styl │ │ ├── aplayer.styl │ │ ├── cursor.styl │ │ ├── fancybox.styl │ │ ├── fontcolor.styl │ │ ├── gitalk.styl │ │ ├── index.styl │ │ ├── mathjax.styl │ │ ├── message.styl │ │ └── tianliGPT.styl │ ├── _tag-plugins │ │ ├── Readme.md │ │ ├── btns.styl │ │ ├── checkbox.styl │ │ ├── dropmenu.styl │ │ ├── fancybox.styl │ │ ├── folding.styl │ │ ├── frame.styl │ │ ├── friends.styl │ │ ├── ghcard.styl │ │ ├── image.styl │ │ ├── link.styl │ │ ├── media.styl │ │ ├── note.styl │ │ ├── sites.styl │ │ ├── span.styl │ │ ├── swiper.styl │ │ ├── table.styl │ │ ├── tabs.styl │ │ ├── tag.json │ │ ├── text.styl │ │ └── timeline.styl │ └── index.styl ├── first.styl └── style.styl └── js ├── app.js ├── plugins ├── aplayer.js ├── parallax.js ├── rightMenus.js └── tags │ ├── contributors.js │ ├── friends.js │ └── sites.js └── search ├── algolia.js ├── hexo.js └── meilisearch.js /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 提问一个关于Volantis的问题或者寻求支持 4 | url: https://github.com/volantis-x/hexo-theme-volantis/discussions/new 5 | about: Ask a question about volantis or get support 6 | - name: 提问的智慧 7 | url: https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md 8 | about: How To Ask Questions The Smart Way -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/zh-cn-1-help.yaml: -------------------------------------------------------------------------------- 1 | name: 问题:使用遇到问题(报错、样式与示例不一致等) 2 | description: 此模板适用于解决使用主题搭建博客遇到的问题。 3 | title: "【问题】:" 4 | labels: help 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | 请务必认真填写,足够的信息能帮助我们快速定位问题并及时修复。 10 | - type: checkboxes 11 | id: checks 12 | attributes: 13 | label: 检查清单 14 | description: 请认真检查以下清单中的每一项,并在相符的项前打勾。 15 | options: 16 | - label: 已经搜索过,没有发现类似 issue。 17 | - label: 已经搜索过[主题文档](https://volantis.js.org/),没有发现相关内容。 18 | - label: 已经尝试使用过[最新版](https://github.com/volantis-x/hexo-theme-volantis/releases),问题依旧存在。 19 | - type: dropdown 20 | id: theme-version 21 | attributes: 22 | label: 主题版本 23 | description: 请选择您所使用的主题版本。 24 | options: 25 | - 6.x 26 | - 5.x 27 | - 4.x 28 | - Other 29 | validations: 30 | required: true 31 | - type: input 32 | id: bug-url 33 | attributes: 34 | label: 复现地址 35 | description: 请输入可供复现的访问地址。 36 | placeholder: "如: https://volantis.js.org/v5/getting-started/" 37 | validations: 38 | required: true 39 | - type: textarea 40 | id: description 41 | attributes: 42 | label: 问题描述 43 | description: 请告诉我们发生了什么? 44 | placeholder: 请详细描述您所遇到的情况:复现步骤、操作过程、主题安装方式、仓库地址、截图等内容。 45 | validations: 46 | required: true 47 | - type: textarea 48 | id: config-file 49 | attributes: 50 | label: 配置文件 51 | description: 请提供您的配置文件。 52 | value: | 53 |
站点配置文件

54 | 55 | ```yml 56 | 在这里粘贴替换 `blog/_config.yml` 中修改过的部分 57 | ``` 58 | 59 |

60 | 61 |
主题配置文件

62 | 63 | ```yml 64 | 在这里粘贴替换 `themes/volantis/_config.yml` 中修改过的部分 65 | ``` 66 | 67 |

68 | - type: textarea 69 | id: environment 70 | attributes: 71 | label: 环境信息 72 | description: 请提供您的环境信息,打开终端在博客目录下执行命令获取内容。 73 | value: | 74 |
node.js & npm

75 | 76 | ``` 77 | 在这里粘贴替换 `node -v && npm -v` 输出的信息 78 | ``` 79 | 80 |

81 | 82 |
package.json

83 | 84 | ``` 85 | 在这里粘贴替换 `npm ls --depth 0` 输出的信息 86 | ``` 87 | 88 |

89 | 90 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/zh-cn-5-feature-request.yaml: -------------------------------------------------------------------------------- 1 | name: 建议:新增或优化某一项功能 2 | description: 此模板适用于建议以及讨论是否新增功能或者对现有功能作出调整。 3 | title: "【建议】:" 4 | labels: feature-request 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | 请务必认真填写,足够的信息能帮助我们了解具体的需求。 10 | - type: checkboxes 11 | id: checks 12 | attributes: 13 | label: 检查清单 14 | description: 请认真检查以下清单中的每一项,并在相符的项前打勾。 15 | options: 16 | - label: 已经搜索过,没有发现类似 issue。 17 | - label: 已经阅读 hexo 官方文档,未发现原生支持。 18 | - type: textarea 19 | id: description 20 | attributes: 21 | label: 需求描述 22 | description: 请告诉我们您期望添加什么功能? 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: link 27 | attributes: 28 | label: 参考链接 29 | description: 请提供可供我们参考的链接。 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/zh-cn-8-bug-report.yaml: -------------------------------------------------------------------------------- 1 | name: 反馈:主题的代码错误 2 | description: 此模板适用于您已经定位到了问题的具体所在,不需要协助定位问题。报告给开发者予以修复。 3 | title: "【反馈】:" 4 | labels: bug-report 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | 请务必认真填写,足够的信息能帮助我们更快的解决问题。 10 | - type: checkboxes 11 | id: checks 12 | attributes: 13 | label: 检查清单 14 | description: 请认真检查以下清单中的每一项,并在相符的项前打勾。 15 | options: 16 | - label: 已经搜索过,没有发现类似 issue。 17 | - label: 已经将主题升级到最新版本。 18 | - label: 主题官网也存在这个问题。 19 | - type: input 20 | id: bug-url 21 | attributes: 22 | label: 复现地址 23 | description: 请输入可供复现的访问地址。 24 | - type: textarea 25 | id: description 26 | attributes: 27 | label: 复现步骤 28 | description: 请告诉我们发生了什么? 29 | validations: 30 | required: true 31 | - type: textarea 32 | id: config-file 33 | attributes: 34 | label: 配置文件 35 | description: 请提供您的配置文件。 36 | value: | 37 |
站点配置文件

38 | 39 | ```yml 40 | 在这里粘贴替换 `blog/_config.yml` 中修改过的部分 41 | ``` 42 | 43 |

44 | 45 |
主题配置文件

46 | 47 | ```yml 48 | 在这里粘贴替换 `themes/volantis/_config.yml` 中修改过的部分 49 | ``` 50 | 51 |

52 | - type: textarea 53 | id: environment 54 | attributes: 55 | label: 环境信息 56 | description: 请提供您的环境信息,打开终端在博客目录下执行命令获取内容。 57 | value: | 58 |
node.js & npm

59 | 60 | ``` 61 | 在这里粘贴替换 `node -v && npm -v` 输出的信息 62 | ``` 63 | 64 |

65 | 66 |
package.json

67 | 68 | ``` 69 | 在这里粘贴替换 `npm ls --depth 0` 输出的信息 70 | ``` 71 | 72 |

-------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/zh-cn-9-other-issue.yaml: -------------------------------------------------------------------------------- 1 | name: 其它:额外议题 2 | description: 使用此模板意味着您不需要帮助,也不需要开发者优先关注此话题。 3 | title: "【其它】:" 4 | body: 5 | - type: textarea 6 | id: description 7 | attributes: 8 | label: 议题内容 9 | validations: 10 | required: true -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## PR Type 2 | 3 | 4 | 5 | 6 | 7 | - [ ] Bugfix. 8 | - [ ] Feature. 9 | - [ ] Code style update (formatting, local variables). 10 | - [ ] Refactoring (no functional changes, no api changes). 11 | - [ ] Build & CI related changes. 12 | - [ ] Documentation. 13 | - [ ] Translation. 14 | - [ ] Other... Please describe: 15 | 16 | ## Description 17 | 18 | 19 | 20 | 21 | ## Others 22 | 23 | - Issue resolved: 24 | 25 | - Screenshots with this changes: 26 | 27 | - Link to demo site with this changes: 28 | 29 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration for request-info - https://github.com/behaviorbot/request-info 2 | 3 | # *OPTIONAL* Comment to reply with 4 | # Can be either a string : 5 | requestInfoReplyComment: > 6 | We would appreciate it if you could provide us with more info about this issue/pr! 7 | 8 | # Or an array: 9 | # requestInfoReplyComment: 10 | # - Ah no! young blade! That was a trifle short! 11 | # - Tell me more ! 12 | # - I am sure you can be more effusive 13 | 14 | 15 | # *OPTIONAL* default titles to check against for lack of descriptiveness 16 | # MUST BE ALL LOWERCASE 17 | requestInfoDefaultTitles: 18 | - update readme.md 19 | - updates 20 | 21 | # *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given 22 | requestInfoLabelToAdd: 'need more info' 23 | 24 | # *OPTIONAL* Require Issues to contain more information than what is provided in the issue templates 25 | # Will fail if the issue's body is equal to a provided template 26 | checkIssueTemplate: true 27 | 28 | # *OPTIONAL* Require Pull Requests to contain more information than what is provided in the PR template 29 | # Will fail if the pull request's body is equal to the provided template 30 | checkPullRequestTemplate: true 31 | 32 | # *OPTIONAL* Only warn about insufficient information on these events type 33 | # Keys must be lowercase. Valid values are 'issue' and 'pullRequest' 34 | requestInfoOn: 35 | pullRequest: true 36 | issue: true 37 | 38 | # *OPTIONAL* Add a list of people whose Issues/PRs will not be commented on 39 | # keys must be GitHub usernames 40 | requestInfoUserstoExclude: 41 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # daily update for deps 4 | - package-ecosystem: npm 5 | directory: / 6 | schedule: 7 | interval: daily 8 | time: '08:00' 9 | timezone: Asia/Shanghai 10 | open-pull-requests-limit: 50 11 | 12 | # daily update for github actions 13 | - package-ecosystem: github-actions 14 | directory: / 15 | schedule: 16 | interval: daily 17 | time: '08:00' 18 | timezone: Asia/Shanghai -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # Configuration for labeler - https://github.com/actions/labeler 2 | 3 | Actions: 4 | - changed-files: 5 | - any-glob-to-any-file: .github/workflows/**/* 6 | Dependencies: 7 | - changed-files: 8 | - any-glob-to-any-file: package.json 9 | Configurations: 10 | - changed-files: 11 | - any-glob-to-any-file: _config.yml 12 | CSS: 13 | - changed-files: 14 | - any-glob-to-any-file: source/css/**/* 15 | JS: 16 | - changed-files: 17 | - any-glob-to-any-file: source/js/**/* 18 | Layout: 19 | - changed-files: 20 | - any-glob-to-any-file: layout/**/* 21 | Scripts: 22 | - changed-files: 23 | - any-glob-to-any-file: scripts/**/* 24 | i18n: 25 | - changed-files: 26 | - any-glob-to-any-file: languages/**/* 27 | -------------------------------------------------------------------------------- /.github/publish.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # https://volantis.js.org 4 | # 5 | # 只有 rc 阶段的测试版本和正式版本发布到 npm 6 | # 7 | # 1. 输入要发布的版本号 8 | # 2. 修改主题 _config.yml 中的 info.theme_version 9 | # 3. 修改主题 package.json 中的 version 10 | # 4. 提交 commit 11 | 12 | # 版本号 例如 4.0.0-rc.1 13 | VERSION=$1 14 | 15 | # 替换版本号 16 | function prepare() { 17 | text="'"${VERSION}"'"" # This is theme's version." 18 | sed -i "" "s/^ theme_version:\([^\"]\{1,\}\)/ theme_version: ${text}/g" '_config.yml' 19 | sed -i "" "s/^ \"version\":\([^,]\{1,\}\)/ \"version\": \"${VERSION}\"/g" 'package.json' 20 | } 21 | 22 | # 提交 23 | function commit() { 24 | msg="release: ${VERSION}" 25 | 26 | printf "\n\n> \033[32m%s\033[0m" 'git add --all' 27 | printf "\n" 28 | git add --all 29 | 30 | printf "\n\n> \033[32m%s\033[0m" 'git commit -m' 31 | printf " \033[35m%s\033[0m" ${msg} 32 | printf "\n" 33 | git commit -m "${msg}" 34 | 35 | # 变基到 main 分支 36 | git checkout main 37 | git rebase dev 38 | # 切换回 dev 开发分支 39 | git checkout dev 40 | 41 | # 推送 42 | printf "\n\n> \033[32m%s\033[0m" 'git push origin --all' 43 | printf "\n" 44 | git push origin --all 45 | 46 | # done 47 | printf "\n\n> \033[32m%s\033[0m\n" 'Congratulations!' 48 | } 49 | 50 | 51 | while : 52 | do 53 | case $VERSION in 54 | '') 55 | read -p "请输入要发布的版本号: " VERSION 56 | ;; 57 | *) 58 | break 59 | ;; 60 | esac 61 | done 62 | 63 | prepare && commit 64 | -------------------------------------------------------------------------------- /.github/workflows/label-commenter.yml: -------------------------------------------------------------------------------- 1 | name: Label Commenter 2 | 3 | on: 4 | issues: 5 | types: 6 | - labeled 7 | - unlabeled 8 | pull_request_target: 9 | types: 10 | - labeled 11 | - unlabeled 12 | 13 | jobs: 14 | comment: 15 | if: github.repository == 'volantis-x/hexo-theme-volantis' 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Label Commenter 20 | uses: peaceiris/actions-label-commenter@v1 21 | with: 22 | github_token: ${{ secrets.GITHUB_TOKEN }} 23 | config_file: .github/label-commenter-config.yml 24 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Labeler 2 | 3 | on: 4 | - pull_request_target 5 | 6 | jobs: 7 | triage: 8 | if: github.repository == 'volantis-x/hexo-theme-volantis' 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/labeler@v5 12 | with: 13 | repo-token: "${{ secrets.GITHUB_TOKEN }}" -------------------------------------------------------------------------------- /.github/workflows/merge-conflicts.yml: -------------------------------------------------------------------------------- 1 | name: Merge conflicts 2 | on: 3 | push: 4 | branches: 5 | - main 6 | - dev 7 | jobs: 8 | triage: 9 | if: github.repository == 'volantis-x/hexo-theme-volantis' 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: mschilde/auto-label-merge-conflicts@master 13 | with: 14 | CONFLICT_LABEL_NAME: "has conflicts" 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | -------------------------------------------------------------------------------- /.github/workflows/merge-squash-main.yml: -------------------------------------------------------------------------------- 1 | name: merge-squash-main 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | merge: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: merge-to-main 10 | run: | 11 | git config --global user.email "github-actions[bot]@users.noreply.github.com" 12 | git config --global user.name "github-actions[bot]" 13 | git clone https://github.com/volantis-x/hexo-theme-volantis.git hexo-theme-volantis 14 | cd hexo-theme-volantis 15 | git fetch origin 16 | git checkout main 17 | git reset --hard dc9134662502ed2aa8d39dfa09ffe81650a2b024 18 | git merge dev 19 | git push --force "https://github-actions[bot]:${{ secrets.GITHUB_TOKEN }}@github.com/volantis-x/hexo-theme-volantis.git" main:main 20 | - name: sync-coding 21 | run: | 22 | curl -u ${{ secrets.CODING_TOKEN_API }} \ 23 | -v -X POST 'https://volantis-x.coding.net/api/cci/job/387490/trigger' \ 24 | -H 'Content-Type: application/json' \ 25 | -d ' 26 | { 27 | "envs": [ 28 | { 29 | "name": "BRANCH", 30 | "value": "main", 31 | "sensitive": 0 32 | } 33 | ] 34 | }' 35 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: npm-publish 2 | on: 3 | workflow_dispatch: 4 | # release: 5 | # types: [published] 6 | 7 | jobs: 8 | npm-publish: 9 | name: npm-publish 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v4 14 | - name: Set up Node.js 15 | uses: actions/setup-node@v4 16 | with: 17 | node-version: 12 18 | registry-url: https://registry.npmjs.org 19 | - name: Publish 20 | run: | 21 | npm publish 22 | env: 23 | NODE_AUTH_TOKEN: ${{ secrets.npm_token }} 24 | -------------------------------------------------------------------------------- /.github/workflows/pr-updater.yml: -------------------------------------------------------------------------------- 1 | name: PR update 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | jobs: 9 | autoupdate: 10 | if: github.repository == 'volantis-x/hexo-theme-volantis' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - name: update all prs 15 | uses: maxkomarychev/pr-updater-action@v1.0.1 16 | with: 17 | token: ${{ secrets.GITHUB_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/sync-coding.yml: -------------------------------------------------------------------------------- 1 | name: Sync Coding 2 | 3 | on: 4 | push: 5 | release: 6 | types: [published] 7 | 8 | jobs: 9 | sync: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Run Curl 14 | run: | 15 | curl -u ${{ secrets.CODING_TOKEN_API }} \ 16 | -v -X POST 'https://volantis-x.coding.net/api/cci/job/387490/trigger' \ 17 | -H 'Content-Type: application/json' \ 18 | -d ' 19 | { 20 | "envs": [ 21 | { 22 | "name": "BRANCH", 23 | "value": "${{ github.ref_name }}", 24 | "sensitive": 0 25 | } 26 | ] 27 | }' 28 | -------------------------------------------------------------------------------- /.github/workflows/test-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Test to deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - 6.0 7 | - dev 8 | - test 9 | jobs: 10 | dev: 11 | runs-on: ubuntu-latest 12 | name: A job to Test deploying for dev. 13 | strategy: 14 | matrix: 15 | node_version: ['18', '16'] 16 | steps: 17 | - name: Setup Node.js 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: ${{ matrix.node_version }} 21 | - name: Clone 22 | run: | 23 | git clone https://github.com/volantis-x/volantis-x.github.io 24 | cd volantis-x.github.io 25 | git clone -b ${{ github.ref_name }} https://github.com/volantis-x/hexo-theme-volantis themes/volantis 26 | - name: Generate Public Files 27 | run: | 28 | cd volantis-x.github.io 29 | npm i 30 | npm install hexo-cli -g 31 | npm run start 32 | - name: Deploy 33 | if: ${{ matrix.node_version == '16' }} 34 | uses: peaceiris/actions-gh-pages@v4 35 | with: 36 | deploy_key: ${{ secrets.MHUIG_DEPLOY_KEY }} 37 | external_repository: volantis-x/volantis-x.github.io 38 | publish_branch: gh-pages 39 | force_orphan: true 40 | publish_dir: ./volantis-x.github.io/public 41 | user_name: 'github-actions[bot]' 42 | user_email: 'github-actions[bot]@users.noreply.github.com' 43 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _site/ 2 | .sass-cache/ 3 | .jekyll-metadata 4 | .DS_Store 5 | node_modules 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .github/ 2 | publish.sh 3 | node_modules 4 | node_modules 5 | package-lock.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 xaoxuu 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | [![](https://img.shields.io/npm/v/hexo-theme-volantis.svg?style=flat-square)](https://www.npmjs.com/package/hexo-theme-volantis) 6 | [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=white)](https://www.conventionalcommits.org/zh-hans/v1.0.0/) 7 | 8 | ## Getting Started 9 | 10 | Check your environment: 11 | 12 | ```yaml 13 | Hexo: 5.4 ~ 6.x 14 | hexo-cli: 4.3 ~ latest 15 | node.js: 16.x LTS ~ latest LTS 16 | npm: 8.x ~ latest LTS 17 | ``` 18 | 19 | Edit your `_config.yml`: 20 | 21 | ```yaml 22 | theme: volantis 23 | ``` 24 | 25 | Install Volantis in terminal: 26 | 27 | ```bash 28 | npm i hexo-theme-volantis 29 | ``` 30 | 31 | ## Usage 32 | 33 | See docs: https://volantis.js.org 34 | 35 | or: https://volantis.vercel.app 36 | 37 | ## Examples 38 | 39 | See examples: https://volantis.js.org/examples/ 40 | 41 | Add your blog to examples page: https://github.com/volantis-x/examples/issues/ 42 | 43 | ## Feedback 44 | 45 | Feedback to developer: https://github.com/volantis-x/hexo-theme-volantis/issues/ 46 | 47 | Discuss with other users: https://github.com/volantis-x/hexo-theme-volantis/discussions/ 48 | 49 | ## Screenshot 50 | 51 | ![](https://i.loli.net/2020/03/18/f5PQlWisvm9zbgK.jpg) 52 | 53 | ![](https://i.loli.net/2020/03/18/XWBGf95E2t1bdnl.jpg) 54 | 55 | ![](https://i.loli.net/2020/03/18/1TpiUwhuskGm5SV.png) 56 | 57 | ![](https://i.loli.net/2020/03/18/LZwBtR5YO4zQH9A.png) 58 | 59 | ![](https://i.loli.net/2020/03/18/ySw8zGHRBrDtUg7.png) 60 | 61 | ![](https://i.loli.net/2020/03/18/5QTMYsScOz41Vhg.png) 62 | -------------------------------------------------------------------------------- /languages/en.yml: -------------------------------------------------------------------------------- 1 | navbar: 2 | archive: Archive 3 | category: Category 4 | tag: Tag 5 | 6 | post: 7 | pin: Top 8 | readmore: Read More 9 | readoriginal: Read Original 10 | wordcount: '%s words' 11 | duration: '%s min' 12 | comments: Comments 13 | comments_load: Load %s 14 | comments_check: Checking if %s is accessible... 15 | comments_placeholder: Unable to load %s, please make sure your network can access. 16 | copy_button: Copy 17 | copy_success: Copied 18 | copy_failure: Copy failed 19 | updated: updated at 20 | prev_page: Previous 21 | next_page: Next 22 | copyright: 23 | author: Post author 24 | link: Post link 25 | license_title: Copyright Notice 26 | license_content: "All articles in this blog are licensed under %s unless stating additionally." 27 | date: Posted on 28 | updated: Update 29 | references: References 30 | license: License 31 | 32 | footer: 33 | license: 'Blog content follows the [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) License](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en)' 34 | use: Use 35 | theme: as theme 36 | total_views: total visits 37 | total_visitors: total visitors 38 | times: times 39 | site_source: Uses %s as theme. You can find [source](%s) in %s. 40 | site_views: The visits is about %s, and the visitors is about %s. 41 | 42 | symbol: 43 | comma: ", " 44 | period: ". " 45 | colon: ": " 46 | brackets_l: "(" 47 | brackets_r: ")" 48 | 49 | kill: 50 | title: "Sorry, your browser cannot access this site" 51 | more: "Learn more >" 52 | noscript: "This page requires browser support (enable) JavaScript" 53 | ie: "Microsoft has terminated support for Internet Explorer (IE) 10 and earlier versions in 2016.
There are great security risks to continue using it. Please use contemporary mainstream browsers to access." 54 | 55 | search: 56 | title: Search 57 | load_data: Loading the Database 58 | hits_empty: "We didn't find any results for the search: ${query}." 59 | hits_stats: '${hits} results found in ${time} ms' 60 | -------------------------------------------------------------------------------- /languages/zh-CN.yml: -------------------------------------------------------------------------------- 1 | navbar: 2 | archive: 归档 3 | category: 分类 4 | tag: 标签 5 | 6 | post: 7 | pin: 置顶 8 | readmore: 阅读全文 9 | readoriginal: 去源站阅读 10 | wordcount: '字数:%s 字' 11 | duration: '时长:%s 分钟' 12 | comments: 评论 13 | comments_load: 点击加载 %s 评论 14 | comments_check: 正在检查 %s 能否访问... 15 | comments_placeholder: 无法加载 %s 评论系统,请确保您的网络能够正常访问。 16 | copy_button: 复制 17 | copy_success: 复制成功 18 | copy_failure: 复制失败 19 | updated: 更新于 20 | prev_page: 上一页 21 | next_page: 下一页 22 | copyright: 23 | author: 本文作者 24 | link: 本文链接 25 | license_title: 版权声明 26 | license_content: "本博客所有文章除特别声明外,均采用 %s 许可协议。转载请注明出处!" 27 | date: 发布于 28 | updated: 更新于 29 | references: 原文出处 30 | license: 许可协议 31 | 32 | footer: 33 | license: '博客内容遵循 [署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hans)' 34 | use: 本站使用 35 | theme: 作为主题 36 | total_views: 总访问量为 37 | page_views: 本页总访客量为 38 | total_visitors: 总访客量 39 | times: 次 40 | peoples: 人 41 | site_source: 本站使用 %s 作为主题,您可以在 %s 找到[本站源码](%s)。 42 | site_views: 总访问量约为 %s 次,访问人数约为 %s 人。 43 | 44 | symbol: 45 | comma: "," 46 | period: "。" 47 | colon: ":" 48 | brackets_l: "(" 49 | brackets_r: ")" 50 | 51 | kill: 52 | title: "抱歉,您的浏览器无法访问本站" 53 | more: "了解详情 >" 54 | noscript: "本页面需要浏览器支持(启用)JavaScript" 55 | ie: "微软已经于2016年终止了对 Internet Explorer (IE) 10 及更早版本的支持,
继续使用存在极大的安全隐患,请使用当代主流的浏览器进行访问。" 56 | 57 | search: 58 | title: 搜索 59 | load_data: 数据库加载中 60 | hits_empty: '找不到您查询的内容:${query}' 61 | hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒' 62 | 63 | -------------------------------------------------------------------------------- /languages/zh-TW.yml: -------------------------------------------------------------------------------- 1 | navbar: 2 | archive: 歸檔 3 | category: 分類 4 | tag: 標籤 5 | 6 | post: 7 | pin: 置頂 8 | readmore: 閱讀全文 9 | readoriginal: 去源站閱讀 10 | wordcount: '字數:%s字' 11 | duration: '時長:%s分鐘' 12 | comments: 評論 13 | comments_load: 點擊加載 %s 評論 14 | comments_check: 正在檢查 %s 能否訪問... 15 | comments_placeholder: 無法加載 %s 評論系統,請確保您的網絡能夠正常訪問。 16 | copy_button: 複製 17 | copy_success: 複製成功 18 | copy_failure: 複製失敗 19 | updated: 更新於 20 | prev_page: 上一頁 21 | next_page: 下一頁 22 | copyright: 23 | author: 本文作者 24 | link: 文章連結 25 | license_title: 版權聲明 26 | license_content: "本網誌所有文章除特別聲明外,均採用 %s 許可協議。轉載請註明出處!" 27 | 28 | footer: 29 | license: '博客內容遵循 [姓名標示-非商業性-相同方式分享 4.0 國際 (CC BY-NC-SA 4.0) 協議](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-hant)' 30 | use: 本站使用 31 | theme: 作為主題 32 | total_views: 總訪問量為 33 | total_visitors: 總訪客量為 34 | times: 次 35 | site_source: 本站使用 %s 作為主題,您可以在 %s 找到[本站源碼](%s)。 36 | site_views: 總訪問量約為 %s 次,訪問人數約為 %s 人。 37 | 38 | symbol: 39 | comma: "," 40 | period: "。" 41 | colon: ":" 42 | brackets_l: "(" 43 | brackets_r: ")" 44 | 45 | kill: 46 | title: "抱歉,您的瀏覽器無法訪問本站" 47 | more: "了解詳情 >" 48 | noscript: "本頁面需要瀏覽器支持(啟用)JavaScript" 49 | ie: "微軟已經於2016年終止了對 Internet Explorer (IE) 10 及更早版本的支持,
繼續使用存在極大的安全隱患,請使用當代主流的瀏覽器進行訪問。" 50 | 51 | search: 52 | title: 搜尋 53 | load_data: 資料庫載入中 54 | hits_empty: '找不到您查詢的內容:${query}' 55 | hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒' 56 | -------------------------------------------------------------------------------- /layout/404.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
3 | <%- partial('_partial/article', {post: page, index: false}) %> 4 |
5 | -------------------------------------------------------------------------------- /layout/_meta/artalkcount.ejs: -------------------------------------------------------------------------------- 1 | <% if (theme.comments.service == 'artalk' && page.comments !== false) { %> 2 |
3 | <% 4 | let commentPath; 5 | let path = post.path || page.path; 6 | if (theme.comments.service && theme.comments.service.length > 0) { 7 | let service = theme.comments.service; 8 | if (page.comments == undefined || page.comments != false) { 9 | if (service in page && page[service].path) { 10 | commentPath = page[service].path; 11 | } 12 | } 13 | } 14 | if(!!theme.comments.artalk.path) path = theme.comments.artalk.path 15 | if(commentPath) path = commentPath; 16 | path = path.replaceAll('/index.html', '/').replaceAll('.html', '') 17 | %> 18 | 19 | 20 |

21 | 22 | 23 | 24 | <% if(theme.article.body.meta_library.artalkcount.desc) { %> 25 |  <%- theme.article.body.meta_library.artalkcount.desc %> 26 | <% } %> 27 |

28 |
29 |
30 | <% } %> -------------------------------------------------------------------------------- /layout/_meta/author.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | let author = theme.article.body.meta_library.author; 3 | let aid = post.author; 4 | if (aid && site.data && site.data.author && (aid in site.data.author)) { 5 | author = site.data.author[aid]; 6 | } 7 | %> 8 | 14 | -------------------------------------------------------------------------------- /layout/_meta/category.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.categories && post.categories.length){ %> 2 | <% try { %> 3 | <%# 在 _posts/ 外使用 categories 会报错 %> 4 | <% const show_categories = list_categories(post.categories, { 5 | show_count: false, 6 | separator: '', 7 | style: 'none' 8 | }) %> 9 |
10 | 11 | <%- show_categories %> 12 | <% for(cat of post.categories.toArray()){ %> 13 | 16 | <% } %> 17 |
18 | <% }catch (error) {} %> 19 | <% } %> 20 | 21 | -------------------------------------------------------------------------------- /layout/_meta/date.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

<%- theme.article.body.meta_library.date.title + date(post.date, theme.article.body.meta_library.date.format) %>

5 |
6 |
7 | -------------------------------------------------------------------------------- /layout/_meta/music.ejs: -------------------------------------------------------------------------------- 1 | <% if(post.music && post.music.enable != false){ %> 2 | <%- partial('../_plugins/aplayer/layout', {post: post, where: 'meta'}) %> 3 | <% } %> 4 | -------------------------------------------------------------------------------- /layout/_meta/share.ejs: -------------------------------------------------------------------------------- 1 | <% if (theme.article.body.meta_library.share) { %> 2 | <%- partial('../_plugins/share/layout') %> 3 | <% } %> 4 | -------------------------------------------------------------------------------- /layout/_meta/tags.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.tags && post.tags.length) { %> 2 | <% try { %> 3 | <%# 在 _posts/ 外使用 tags 会报错 %> 4 | <% 5 | var items = []; 6 | var hidden_items = []; 7 | post.tags.each(function(item){ 8 | items.push('

' + item.name + '

'); 9 | hidden_items.push(item.name); 10 | }); 11 | %> 12 | <%- items.join(' ') %> 13 | 14 | <% }catch (error) {} %> 15 | <% } %> 16 | -------------------------------------------------------------------------------- /layout/_meta/thumbnail.ejs: -------------------------------------------------------------------------------- 1 | <% if(post.thumbnail && post.thumbnail.length){ %> 2 | 3 | 4 | 5 | <% } %> 6 | -------------------------------------------------------------------------------- /layout/_meta/updated.ejs: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

<%- theme.article.body.meta_library.updated.title + date(post.updated, theme.article.body.meta_library.updated.format) %>

5 |
6 |
7 | -------------------------------------------------------------------------------- /layout/_meta/walinecount.ejs: -------------------------------------------------------------------------------- 1 | <% if (theme.comments.service == 'waline' && theme.comments.waline.comment && page.comments !== false){ %> 2 |
3 | <% 4 | let commentPath; 5 | let path = post.path || page.path; 6 | if (theme.comments.service && theme.comments.service.length > 0) { 7 | let service = theme.comments.service; 8 | if (page.comments == undefined || page.comments != false) { 9 | if (service in page && page[service].path) { 10 | commentPath = page[service].path; 11 | } 12 | } 13 | } 14 | if(!!theme.comments.waline.path) path = theme.comments.waline.path 15 | if(commentPath) path = commentPath; 16 | path = path.replaceAll('/index.html', '/').replaceAll('.html', '') 17 | %> 18 | 19 | 20 | 21 |

22 | 23 | 24 | 25 | <% if(theme.article.body.meta_library.walinecount.desc) { %> 26 |  <%- theme.article.body.meta_library.walinecount.desc %> 27 | <% } %> 28 |

29 |
30 |
31 | <% } %> 32 | -------------------------------------------------------------------------------- /layout/_meta/wordcount.ejs: -------------------------------------------------------------------------------- 1 | <% if (theme.plugins.wordcount.enable) { %> 2 |
3 | 4 | 5 |

<%- __('post.wordcount', wordcount(post.content))%>

6 |
7 |
8 |
9 | 10 | 11 |

<%- __('post.duration', min2read(post.content))%>

12 |
13 |
14 | <% } %> 15 | -------------------------------------------------------------------------------- /layout/_partial/_cover/blank.ejs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volantis-x/hexo-theme-volantis/600d46538a2c7cf7dec7899d321b0e6798038f64/layout/_partial/_cover/blank.ejs -------------------------------------------------------------------------------- /layout/_partial/_cover/dock.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | <% if (theme.cover.logo) { %> 4 | 5 | <% } %> 6 | <% if (theme.cover.title) { %> 7 |

<%- theme.cover.title ? theme.cover.title : config.title %>

8 | <% } %> 9 | <% if (theme.cover.subtitle) { %> 10 |

<%- theme.cover.subtitle%>

11 | <% } %> 12 |
13 |
14 | 32 |
33 |
34 | -------------------------------------------------------------------------------- /layout/_partial/_cover/featured.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | <% if (theme.cover.logo) { %> 4 | 5 | <% } %> 6 | <% if (theme.cover.title) { %> 7 |

<%- theme.cover.title ? theme.cover.title : config.title %>

8 | <% } %> 9 | <% if (theme.cover.subtitle) { %> 10 |

<%- theme.cover.subtitle%>

11 | <% } %> 12 |
13 |
14 | 32 |
33 |
34 | -------------------------------------------------------------------------------- /layout/_partial/_cover/focus.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | <% if (theme.cover.logo) { %> 4 | 5 | <% } %> 6 | <% if (theme.cover.title) { %> 7 |

<%- theme.cover.title ? theme.cover.title : config.title %>

8 | <% } %> 9 | <% if (theme.cover.subtitle) { %> 10 |

<%- theme.cover.subtitle%>

11 | <% } %> 12 |
13 |
14 | 32 |
33 |
34 | -------------------------------------------------------------------------------- /layout/_partial/_cover/layout.ejs: -------------------------------------------------------------------------------- 1 | <% if (theme.plugins.parallax.enable) { %> 2 |
3 | <% } else if (theme.plugins.lazyload && theme.plugins.lazyload.enable) { %> 4 |
5 | <% } else { %> 6 |
7 | <% } %> 8 | <%- partial(theme.cover.layout_scheme) %> -------------------------------------------------------------------------------- /layout/_partial/_cover/search.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | <% if (theme.cover.logo) { %> 4 | 5 | <% } %> 6 | <% if (theme.cover.title) { %> 7 |

<%- theme.cover.title ? theme.cover.title : config.title %>

8 | <% } %> 9 | <% if (theme.cover.subtitle) { %> 10 |

<%- theme.cover.subtitle%>

11 | <% } %> 12 |
13 |
14 | <% if (theme.search.enable === true) { %> 15 | 21 | <% } %> 22 | 40 |
41 |
42 | -------------------------------------------------------------------------------- /layout/_partial/categories.ejs: -------------------------------------------------------------------------------- 1 | <% if (post.categories && post.categories.length && post.categories.forEach){ %> 2 | <% 3 | var cats = []; 4 | post.categories.forEach(function(cat){ 5 | cats.push('' + cat.name + ''); 6 | }); 7 | %> 8 |
9 |  <%- cats.join(' / ') %> 10 |
11 | <% } %> 12 | -------------------------------------------------------------------------------- /layout/_partial/cover.ejs: -------------------------------------------------------------------------------- 1 |
2 | <% if (page.cover == true) { %> 3 | <% if (is_home() && page.prev == 0 && theme.cover.height_scheme == 'full') { %> 4 |
5 | <%- partial("./_cover/layout") %> 6 | 7 |
8 | <% } else { %> 9 |
10 | <%- partial("./_cover/layout") %> 11 |
12 | <% } %> 13 | <% } %> 14 |
15 | -------------------------------------------------------------------------------- /layout/_partial/meta.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | var topMetas = theme.article.body.top_meta || []; 3 | if (post.top_meta == false) { 4 | topMetas = []; 5 | } 6 | var bottomMetas = theme.article.body.bottom_meta || []; 7 | if (post.bottom_meta == false) { 8 | bottomMetas = []; 9 | } 10 | %> 11 | 12 | <% if (position == 'top') { %> 13 | <% if (post.headimg) { %> 14 |
15 | 16 | 17 | 18 |
19 | <% } else { %> 20 | 23 | <% } %> 24 |
25 | <% if (post.music && post.music.enable != false) { %> 26 | <%- partial('../_plugins/aplayer/layout', {post: post, where: 'meta'}) %> 27 | <% } %> 28 | <% if (post.thumbnail && post.thumbnail.length){ %> 29 | 30 | 31 | 32 | <% } %> 33 | <% if (post.title) { %> 34 |

35 | <%- post.title %> 36 |

37 |
38 | <% getList(topMetas).forEach(function(meta) { %> 39 | <% if (meta in theme.article.body.meta_library){ %> 40 | <%- partial('../_meta/' + meta, {post: post}) %> 41 | <% } %> 42 | <% }) %> 43 | 44 | <%- volantis_inject('topMeta') %> 45 | 46 |
47 | <% } else { %> 48 | 51 | <% } %> 52 |
53 | <% } else if (position == 'bottom') { %> 54 |
55 |
56 | <% getList(bottomMetas).forEach(function(meta){ %> 57 | <% if (meta in theme.article.body.meta_library) { %> 58 | <%- partial('../_meta/' + meta, {post: post}) %> 59 | <% } %> 60 | <% }) %> 61 |
62 | 63 | <%- volantis_inject('bottomMeta') %> 64 | 65 |
66 | <% } %> 67 | -------------------------------------------------------------------------------- /layout/_partial/scripts/_ctrl.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | // 为保证初次进入页面流畅,要求浏览器禁用Javascript时(仅HTML渲染)封面控制正常 3 | // layout/_partial/cover.ejs 4 | // layout/_partial/header.ejs 5 | theme.cover_ctrl={} 6 | theme.cover_ctrl.enableCover = false; // 封面是否开启 7 | theme.cover_ctrl.frontMatterCover = 'none'; // 封面控制 8 | theme.cover_ctrl.coverWrapperDisplay = 'none'; 9 | theme.cover_ctrl.scrollDownDisplay = 'none'; 10 | theme.cover_ctrl.headerShow = 'show'; 11 | if(theme.cover && theme.cover.height_scheme) { 12 | theme.cover_ctrl.enableCover = true; 13 | } 14 | if (theme.cover_ctrl.enableCover && page && page.cover) { 15 | theme.cover_ctrl.frontMatterCover = page.cover; 16 | if (is_home() && page.prev == 0 && theme.cover.height_scheme == 'full') { 17 | theme.cover_ctrl.frontMatterCover = 'full'; 18 | } else { 19 | theme.cover_ctrl.frontMatterCover = 'half'; 20 | } 21 | } 22 | /*cover*/ 23 | if (theme.cover_ctrl.frontMatterCover == "full") { 24 | theme.cover_ctrl.coverWrapperDisplay= ""; 25 | theme.cover_ctrl.scrollDownDisplay = ""; 26 | } else if (theme.cover_ctrl.frontMatterCover == "half"){ 27 | theme.cover_ctrl.coverWrapperDisplay= ""; 28 | theme.cover_ctrl.scrollDownDisplay = "none"; 29 | } else if (theme.cover_ctrl.frontMatterCover == "none"){ 30 | theme.cover_ctrl.coverWrapperDisplay= "none"; 31 | theme.cover_ctrl.scrollDownDisplay = "none"; 32 | } 33 | /*header*/ 34 | if (theme.cover_ctrl.frontMatterCover == "none") { 35 | theme.cover_ctrl.headerShow="show"; 36 | } else { 37 | theme.cover_ctrl.headerShow=""; 38 | } 39 | _%> 40 | -------------------------------------------------------------------------------- /layout/_partial/side.ejs: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/artitalk/index.ejs: -------------------------------------------------------------------------------- 1 | 4 | 11 | 16 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/bbtalk/index.ejs: -------------------------------------------------------------------------------- 1 | 4 | 11 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/fcircle/index.ejs: -------------------------------------------------------------------------------- 1 | 4 | 14 | 15 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/fcircle_lite/index.ejs: -------------------------------------------------------------------------------- 1 | 4 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/gitter/index.ejs: -------------------------------------------------------------------------------- 1 | <%- partial( "../../chat/gitter/script") %> 2 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/indent/index.ejs: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/index.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | getList(page.plugins).forEach(function(item){ 3 | try { 4 | if (typeof item == "string") { _%> 5 | <%- partial( item + "/index") %> 6 | <%_ }else if(typeof item == "object"){ _%> 7 | <%- partial( Object.keys(item)[0] + "/index", { pagePlugin:item }) %> 8 | <%_ } 9 | } catch (error) { 10 | // error friendly 11 | console.log(` 12 | =============================================================================== 13 | 没有找到页面插件:${item} 14 | 请检查是否存在该插件,或者检查插件名称是否正确:${item} 15 | 出问题的页面:${page.path} 16 | see: https://volantis.js.org/v6/page-settings/#页面插件-page-plugins 17 | ================================================================================ 18 | There is no page plugin: ${item} 19 | Please check if the plugin exists, or check the plugin name is correct: ${item} 20 | The page that has problem: ${page.path} 21 | see: https://volantis.js.org/v6/page-settings/#页面插件-page-plugins 22 | =================================================================================`); 23 | } 24 | 25 | }) 26 | 27 | _%> 28 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/katex/index.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/mathjax/index.ejs: -------------------------------------------------------------------------------- 1 | 52 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/memos/index.ejs: -------------------------------------------------------------------------------- 1 | 4 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /layout/_plugins/_page_plugins/snackbar/index.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.data.notification && (pagePlugin.snackbar in site.data.notification)) { %> 2 | <% let snackbar = site.data.notification[pagePlugin.snackbar] %> 3 | <% if (snackbar.position == 'bottom') { %> 4 |
5 | 30 | <% } else if (snackbar.position == 'right') { %> 31 | <% if (snackbar.buttons && snackbar.buttons.length > 0) { %> 32 | 42 | <% } %> 43 | <% } %> 44 | 45 | 55 | <% } %> 56 | -------------------------------------------------------------------------------- /layout/_plugins/aplayer/layout.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | let aplayer = theme.plugins.aplayer; 3 | %> 4 | <% if (theme.plugins.aplayer.enable == true) { %> 5 | <% if (aplayer.source == "meting") { %> 6 | <% if (post && post.music) { %> 7 | 15 | 16 | <% } else { %> 17 | 29 | 30 | <% } %> 31 | <% } else { %> 32 | <% if (post && post.music) { %> 33 |
34 | <% } else { %> 35 |
36 | <% } %> 37 | <% } %> 38 | <% } %> 39 | -------------------------------------------------------------------------------- /layout/_plugins/chat/gitter/script.ejs: -------------------------------------------------------------------------------- 1 | 8 | 9 | -------------------------------------------------------------------------------- /layout/_plugins/chat/index.ejs: -------------------------------------------------------------------------------- 1 | <%- partial( theme.plugins.chat_service + "/script") %> 2 | -------------------------------------------------------------------------------- /layout/_plugins/chat/tidio/script.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /layout/_plugins/comments/beaudar/script.ejs: -------------------------------------------------------------------------------- 1 | 53 | -------------------------------------------------------------------------------- /layout/_plugins/comments/discuss/script.ejs: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /layout/_plugins/comments/disqusjs/script.ejs: -------------------------------------------------------------------------------- 1 | 35 | -------------------------------------------------------------------------------- /layout/_plugins/comments/giscus/script.ejs: -------------------------------------------------------------------------------- 1 | 47 | -------------------------------------------------------------------------------- /layout/_plugins/comments/gitalk/script.ejs: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /layout/_plugins/comments/hashover/script.ejs: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /layout/_plugins/comments/index.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | var checkComment = true; 3 | if (page.comments && page.comments == false) { 4 | checkComment = false; 5 | } 6 | %> 7 | <% if (checkComment&&(theme.comments.service && theme.comments.service.length > 0)) { %> 8 | 9 |
10 | 13 |

<%- theme.comments && theme.comments.title %>

14 | <% if (theme.comments && theme.comments.subtitle) { %> 15 |

<%- theme.comments.subtitle %>

16 | <% } %> 17 | 18 |
19 | 20 |
21 | 22 | <% } else { %> 23 | <% page.comments = false; %> 24 | <% } %> 25 | -------------------------------------------------------------------------------- /layout/_plugins/comments/isso/script.ejs: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /layout/_plugins/comments/livere/script.ejs: -------------------------------------------------------------------------------- 1 | 6 | 16 | -------------------------------------------------------------------------------- /layout/_plugins/comments/twikoo/script.ejs: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /layout/_plugins/comments/utterances/script.ejs: -------------------------------------------------------------------------------- 1 | 43 | -------------------------------------------------------------------------------- /layout/_plugins/comments/vssue/script.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 31 | -------------------------------------------------------------------------------- /layout/_plugins/comments/waline/script.ejs: -------------------------------------------------------------------------------- 1 | 58 | -------------------------------------------------------------------------------- /layout/_plugins/comments/z-custom/script.ejs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /layout/_plugins/end-of-support/script.ejs: -------------------------------------------------------------------------------- 1 | <% if (theme.plugins.killOldVersionsOfIE.enable) { %> 2 | 32 | <% } %> 33 | <% if (theme.plugins.killNoScript.enable) { %> 34 | 62 | <% } %> 63 | -------------------------------------------------------------------------------- /layout/_plugins/github-api/script.ejs: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /layout/_plugins/highlight/highlightjs/script.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /layout/_plugins/highlight/prismjs/script.ejs: -------------------------------------------------------------------------------- 1 | <% getList(theme.plugins.prismjs.js).forEach(function(item) { %> 2 | <%- js(item) %> 3 | <% }) %> 4 | <% getList(theme.plugins.prismjs.css).forEach(function(item) { %> 5 | <%- css(item) %> 6 | <% }) %> 7 | -------------------------------------------------------------------------------- /layout/_plugins/highlight/script.ejs: -------------------------------------------------------------------------------- 1 | <%- partial(theme.plugins.code_highlight + '/script') %> 2 | -------------------------------------------------------------------------------- /layout/_plugins/lazyload/script.ejs: -------------------------------------------------------------------------------- 1 | 2 | 23 | -------------------------------------------------------------------------------- /layout/_plugins/nodewaves/script.ejs: -------------------------------------------------------------------------------- 1 | <%- js({src: theme.cdn.nodewaves_js}) %> 2 | -------------------------------------------------------------------------------- /layout/_plugins/pace/script.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /layout/_plugins/parallax/script.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | theme.plugins.parallax.images = theme.plugins.parallax.images || page.images; 3 | if (theme.plugins.parallax.shuffle) { 4 | // shuffle 只一次 防止 hash 变化 5 | if (typeof theme.plugins.parallax.shuffle_end==='undefined') { 6 | shuffle(theme.plugins.parallax.images); 7 | theme.plugins.parallax.shuffle_end=1; 8 | } 9 | } 10 | function shuffle(arr){ 11 | var n = arr.length; 12 | while(n--) { 13 | var index = Math.floor(Math.random() * n); 14 | var temp = arr[index]; 15 | arr[index] = arr[n]; 16 | arr[n] = temp; 17 | } 18 | } 19 | _%> 20 | 71 | -------------------------------------------------------------------------------- /layout/_plugins/preload/script.ejs: -------------------------------------------------------------------------------- 1 | <% let preload = theme.plugins.preload; %> 2 | <% if (preload.service == 'instant_page') { %> 3 | 4 | <% } else if (preload.service == 'flying_pages') { %> 5 | 13 | 14 | <% } %> 15 | -------------------------------------------------------------------------------- /layout/_plugins/scrollreveal/script.ejs: -------------------------------------------------------------------------------- 1 | 21 | -------------------------------------------------------------------------------- /layout/_plugins/search/script.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /layout/_plugins/share/layout.ejs: -------------------------------------------------------------------------------- 1 |
2 |
3 | <% getList(theme.article.body.meta_library.share).forEach(function(item){ %> 4 | <% if (item.id == 'qrcode' && (item.img || item.icon)){ %> 5 | <% var src = qrcode(url,{margin:1,size:8}); %> 6 |
7 | 8 |
9 | 10 |
11 |
12 | <% } else if (item.id && item.img) { %> 13 | 15 | href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=<%- post.permalink %>&title=<%- (post.seo_title || post.title) + ' - ' + config.title %><%- (post.thumbnail) ? '&pics=' + (post.thumbnail) : '' %>&summary=<%- strip_html(post.excerpt) %>" 16 | <% } else if (item.id == 'qq'){ %> 17 | href="http://connect.qq.com/widget/shareqq/index.html?url=<%- post.permalink %>&title=<%- (post.seo_title || post.title) + ' - ' + config.title %><%- (post.thumbnail) ? '&pics=' + (post.thumbnail) : '' %>&summary=<%- strip_html(post.excerpt) %>" 18 | <% } else if (item.id == 'weibo'){ %> 19 | href="http://service.weibo.com/share/share.php?url=<%- post.permalink %>&title=<%- (post.seo_title || post.title) + ' - ' + config.title %><%- (post.thumbnail) ? '&pics=' + (post.thumbnail) : '' %>&summary=<%- strip_html(post.excerpt) %>" 20 | <% } else if (item.id == 'telegram'){ %> 21 | href="https://t.me/share/url?url=<%- post.permalink %>&text=<%- (post.seo_title || post.title) + ' - ' + config.title %>" 22 | <% } %> 23 | > 24 | <% if (item.img){ %> 25 | 26 | <% } else if (item.icon){ %> 27 | 28 | <% } %> 29 | 30 | <% } %> 31 | <% }) %> 32 |
33 |
34 | -------------------------------------------------------------------------------- /layout/_plugins/slow-network/script.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /layout/_plugins/swiper/script.ejs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /layout/_pre.ejs: -------------------------------------------------------------------------------- 1 | <%_ 2 | if (page.cover == undefined && theme.cover) { 3 | if (is_home() && page.prev == 0) { 4 | page.cover = theme.cover.display.home; 5 | } else if (is_archive()) { 6 | page.cover = theme.cover.display.archive; 7 | } else { 8 | page.cover = theme.cover.display.others; 9 | } 10 | } 11 | if (is_home() || is_category() || is_archive() || is_tag() || page.layout == 'list') { 12 | if (page.sidebar == undefined) { 13 | if (theme.sidebar.for_page.length == 0) { 14 | page.sidebar = []; 15 | } else { 16 | page.sidebar = theme.sidebar.for_page; 17 | } 18 | } 19 | } else { 20 | if (page.sidebar == undefined) { 21 | if (theme.sidebar.for_post.length == 0) { 22 | page.sidebar = []; 23 | } else { 24 | page.sidebar = theme.sidebar.for_post; 25 | } 26 | } 27 | } 28 | if (page.sidebar == false) { 29 | page.sidebar = []; 30 | } 31 | 32 | if (config.theme_config && config.theme_config.style) { 33 | let style = config.theme_config.style; 34 | if (style.navbar && style.navbar.effect) { 35 | theme.custom_css.navbar.effect = style.navbar.effect; 36 | } 37 | if (style.sidebar && style.sidebar.effect) { 38 | theme.custom_css.sidebar.effect = style.sidebar.effect; 39 | } 40 | if (style.body && style.body.effect) { 41 | theme.custom_css.body.effect = style.body.effect; 42 | } 43 | } 44 | 45 | _%> 46 | -------------------------------------------------------------------------------- /layout/_widget/_pre.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | var pf = []; 3 | if (item.display) { 4 | getList(item.display).forEach(function(p){ 5 | pf.push(p); 6 | }); 7 | } else { 8 | pf = ['desktop', 'mobile']; 9 | } 10 | if (where == 'sidebar') { 11 | page.widget_style += theme.custom_css.sidebar.effect.join(' '); 12 | } else if (where == 'body') { 13 | page.widget_style += theme.custom_css.body.effect.join(' '); 14 | } 15 | page.widget_platform = pf.join(' '); 16 | %> -------------------------------------------------------------------------------- /layout/_widget/blogger.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
3 |
4 | <% if (item.avatar) { %> 5 | <% if (item.url) { %> 6 | 7 | 8 | 9 | <% } else { %> 10 |
11 | 12 |
13 | <% } %> 14 | <% } %> 15 | <% if (item.title || item.subtitle || item.jinrishici) { %> 16 |
17 | <% if (item.title){ %> 18 |

<%- item.title %>

19 | <% } %> 20 | <% if (item.subtitle){ %> 21 | <%- markdown(item.subtitle) %> 22 | <% } %> 23 | <% if (item.jinrishici){ %> 24 |

<%- item.jinrishici != true ? item.jinrishici : config.title %>

25 | 26 | <% } %> 27 |
28 | <% } %> 29 | <% if (item.social && item.social.length > 0) { %> 30 | 46 | <% } %> 47 |
48 |
49 | -------------------------------------------------------------------------------- /layout/_widget/category.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.categories.length){ %> 2 | <%- partial('_pre') %> 3 |
4 | <%- partial('header', {item: item}) %> 5 |
6 | 14 |
15 |
16 | <% } %> 17 | -------------------------------------------------------------------------------- /layout/_widget/copyright.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
3 |
4 | <% if (item.blockquote == true) { %> 5 |
6 | <% getList(item.content).forEach(function(row){ %> 7 | <% if (row == 'permalink') { %> 8 |

<%- item.permalink %>><%- page.permalink %>

9 | <% } else { %> 10 | <%- markdown(row) %> 11 | <% } %> 12 | <% }) %> 13 |
14 | <% } else { %> 15 | <% getList(item.content).forEach(function(row){ %> 16 | <% if (row == 'permalink') { %> 17 |

<%- item.permalink %>><%- page.permalink %>

18 | <% } else { %> 19 | <%- markdown(row) %> 20 | <% } %> 21 | <% }) %> 22 | <% } %> 23 |
24 |
25 | -------------------------------------------------------------------------------- /layout/_widget/grid.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
3 | <%- partial('header', {item: item}) %> 4 |
5 | 26 |
27 |
28 | -------------------------------------------------------------------------------- /layout/_widget/group.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | if (page.layout == 'page' || page.layout == 'docs' || page.layout == 'post') { 3 | var rows = new Array(); 4 | site.posts.each(function(p){ 5 | if (p.path && (p.group == item.id)) { 6 | if ((p.short_title != false || (p.short_title == undefined && p.title))) { 7 | rows.push({name: p.short_title || p.title, url: p.path, order: (p.order || 0)}) 8 | } 9 | } 10 | }) 11 | site.pages.each(function(p){ 12 | if (p.path && (p.group == item.id)) { 13 | if ((p.short_title != false || (p.short_title == undefined && p.title))) { 14 | rows.push({name: p.short_title || p.title, url: p.path, order: (p.order || 0)}) 15 | } 16 | } 17 | }) 18 | rows.sort(function(a,b){ 19 | return a.order - b.order; 20 | }); 21 | item.rows = rows; 22 | } 23 | %> 24 | 25 | <% if (item.rows && item.rows.length > 0) { %> 26 | <%- partial('list', {item: item, where: where}) %> 27 | <% } %> 28 | -------------------------------------------------------------------------------- /layout/_widget/header.ejs: -------------------------------------------------------------------------------- 1 | <% if (item.header) { %> 2 |
3 | <% if (item.header.url) { %> 4 | <%- item.header.title %> 5 | <% } else { %> 6 | <%- item.header.title %> 7 | <% } %> 8 |
9 | <% } %> 10 | -------------------------------------------------------------------------------- /layout/_widget/lastupdate.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | function genList() { 3 | let content = ''; 4 | site.posts.filter(p => { 5 | return p.title && p.title.length > 0; 6 | }).sort("updated", -1).limit(5).each(item => { 7 | content += `
  • `; 8 | content += '
    '; 9 | content += ``; 10 | item.categories.limit(1).forEach((cat, i) => { 11 | content += `${cat.name}`; 12 | }); 13 | content += '
    '; 14 | content += `${item.title}`; 15 | content += '
  • '; 16 | content += ''; 17 | }) 18 | return ``; 19 | } 20 | %> 21 | <%- partial('_pre') %> 22 |
    23 | <%- partial('header', {item: item}) %> 24 |
    25 | <%- genList() %> 26 |
    27 |
    28 | -------------------------------------------------------------------------------- /layout/_widget/list.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    3 | <%- partial('header', {item: item}) %> 4 |
    5 | 32 |
    33 |
    34 | -------------------------------------------------------------------------------- /layout/_widget/load.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | let widget_library_temp = []; 3 | %> 4 | <% getList(widgets).forEach(function(widget){ %> 5 | <% if (theme.sidebar.widget_library && (widget in theme.sidebar.widget_library)){ %> 6 | <% let w = theme.sidebar.widget_library[widget]; w.id = widget; %> 7 | <% if(w.sticky) { %> 8 | <% widget_library_temp.push(w) %> 9 | <% } else { %> 10 | <%- partial(w.class, {item: w, where: where}) %> 11 | <% } %> 12 | <% } %> 13 | <% }) %> 14 | 15 |
    16 | <% if(widget_library_temp.length !== 0) { %> 17 | <% widget_library_temp.forEach( w => { %> 18 | <%- partial(w.class, {item: w, where: where}) %> 19 | <% }) %> 20 | <% } %> 21 |
    22 | -------------------------------------------------------------------------------- /layout/_widget/memos_carousel.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    3 | <%- partial('header', {item: item}) %> 4 |
    5 |
    6 |
      <%- item.placeholder %>
    7 |
    8 |
    9 | 21 | 22 |
    23 | -------------------------------------------------------------------------------- /layout/_widget/music.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 | <% if (theme.plugins.aplayer.enable == true) { %> 3 |
    4 | <%- partial('header', {item: item}) %> 5 |
    6 | <%- partial('../_plugins/aplayer/layout', {post: null, where: 'widget'}) %> 7 |
    8 |
    9 | <% } %> 10 | -------------------------------------------------------------------------------- /layout/_widget/page.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    3 | <%- partial('header', {item: item}) %> 4 |
    5 | <% site.pages.forEach(function(post){ %> 6 | <% if (post.pid == item.pid) { %> 7 |
    8 |
    9 |
    10 | <% if (item.content in post) { %> 11 | <%- post[item.content] %> 12 | <% } %> 13 |
    14 |
    15 |
    16 | <% } %> 17 | <% }) %> 18 | <% site.posts.forEach(function(post){ %> 19 | <% if (post.pid == item.pid) { %> 20 |
    21 |
    22 |
    23 | <% if (item.content in post) { %> 24 | <%- post[item.content] %> 25 | <% } %> 26 |
    27 |
    28 |
    29 | <% } %> 30 | <% }) %> 31 |
    32 |
    33 | -------------------------------------------------------------------------------- /layout/_widget/qrcode.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    3 | <%- partial('header', {item: item}) %> 4 |
    5 | <% getList(item.images).forEach(function(url){ %> 6 | 8 | height='<%- item.height %>' 9 | <% } %>/> 10 | <% }) %> 11 |
    12 |
    13 | -------------------------------------------------------------------------------- /layout/_widget/references.ejs: -------------------------------------------------------------------------------- 1 | <% 2 | if (item.rows == undefined) { 3 | item.rows = new Array(); 4 | var itms = new Array(); 5 | let id = item.id || 'references'; 6 | if (id in page) { 7 | getList(page[id]).forEach(function(ref) { 8 | if (ref.name || ref.url) { 9 | item.rows.push(ref); 10 | } 11 | }) 12 | } 13 | } 14 | %> 15 | 16 | <% if (item.rows && item.rows.length > 0) { %> 17 | <%- partial('list', {item: item, where: where}) %> 18 | <% } %> 19 | -------------------------------------------------------------------------------- /layout/_widget/related_posts.ejs: -------------------------------------------------------------------------------- 1 | <% if(page.layout == 'post' && page.content && page.path != undefined){ %> 2 | <%- partial('_pre') %> 3 |
    4 | <%- partial('header', {item: item}) %> 5 |
    6 | <%- popular_posts( { maxCount: item.max_count , ulClass: 'popular-posts' , PPMixingRate: 0.2 } , page ) %> 7 |
    8 |
    9 | <% } %> 10 | -------------------------------------------------------------------------------- /layout/_widget/tagcloud.ejs: -------------------------------------------------------------------------------- 1 | <% if (site.tags.length){ %> 2 | <%- partial('_pre') %> 3 |
    4 | <%- partial('header', {item: item}) %> 5 |
    6 | <%- tagcloud(site.tags, { 7 | min_font: item.min_font, 8 | max_font: item.max_font, 9 | color: item.color, 10 | start_color: item.start_color, 11 | end_color: item.end_color, 12 | }) %> 13 |
    14 |
    15 | <% } %> 16 | -------------------------------------------------------------------------------- /layout/_widget/text.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    3 | <%- partial('header', {item: item}) %> 4 |
    5 | <% getList(item.content).forEach(function(row){ %> 6 | <%- markdown(row) %> 7 | <% }) %> 8 |
    9 |
    10 | -------------------------------------------------------------------------------- /layout/_widget/toc.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 | <% var realcontent = (page.encrypt == true) ? page.origin : page.content; %> 3 | <% if (realcontent && page.toc != false && toc(realcontent).length > 0) { %> 4 |
    style="display:none" <% } %>> 5 | <%- partial('header', {item: item}) %> 6 |
    7 | <%- toc(realcontent, {list_number: item.list_number, min_depth: item.min_depth, max_depth: item.max_depth}) %> 8 |
    9 |
    10 | <% } %> -------------------------------------------------------------------------------- /layout/_widget/webinfo.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    3 | <%- partial('header', {item: item}) %> 4 |
    5 |
    6 | <% if (item.type.article.enable) { %> 7 |
    8 |
    <%= item.type.article.text %>
    9 |
    <%= site.posts.length %> <%= item.type.article.unit %>
    10 |
    11 | <% } %> 12 | 13 | <% if (item.type.runtime.enable) { %> 14 |
    15 |
    <%= item.type.runtime.text %>
    16 |
    17 |
    18 | <% } %> 19 | 20 | 21 | <% if (item.type.wordcount.enable && theme.plugins.wordcount.enable) { %> 22 |
    23 |
    <%= item.type.wordcount.text %>
    24 |
    <%= totalcount(site) %> <%= item.type.wordcount.unit %>
    25 |
    26 | <% } %> 27 | 28 | <% if (item.type.visitcounter.enable && theme.plugins.busuanzi.enable) { %> 29 |
    30 |
    <%= item.type.visitcounter.siteuv.text %>
    31 |
    32 | 33 | 34 | 35 | <%= item.type.visitcounter.siteuv.unit %> 36 |
    37 |
    38 |
    39 |
    <%= item.type.visitcounter.sitepv.text %>
    40 |
    41 | 42 | 43 | 44 | <%= item.type.visitcounter.sitepv.unit %> 45 |
    46 |
    47 | <% } %> 48 | 49 | <% if (item.type.lastupd.enable) { %> 50 |
    51 |
    <%= item.type.lastupd.text %>
    52 |
    <%- date(Date.now()) %> <%= item.type.lastupd.unit %>
    53 |
    54 | <% } %> 55 |
    56 |
    57 |
    58 | -------------------------------------------------------------------------------- /layout/archive.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    '> 3 | <% if (page.year || page.month) { %> 4 | <%- partial('_partial/archive') %> 5 | <% } else { %> 6 |
    7 | <% var year = -1, postid = -1; %> 8 | <% site.posts.sort('date', -1).each(function(post) { %> 9 | <% post.year = date(post.date, 'YYYY'); %> 10 | <% if (post.archive == undefined || post.archive == true) { %> 11 | <% if (post.year && post.year !== year) { %> 12 | <% year = post.year; %> 13 |

    <%= year %>

    14 | <% } %> 15 | 34 | <% } %> 35 | <% }); %> 36 |
    37 | <% } %> 38 |
    39 | <%- partial('_partial/side') %> 40 | -------------------------------------------------------------------------------- /layout/category.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 | <% 3 | page.comments = false; 4 | if (!page.robots) { 5 | page.robots = 'noindex,follow'; 6 | } 7 | %> 8 |
    '> 9 | <% if (site.posts && site.posts.length > 0) { %> 10 | <% if ((page.layout == 'category')||(page.layout == 'categories') ) { %> 11 |
    12 | 29 |
    30 | <% } else { %> 31 | <%- partial('_partial/archive') %> 32 | <% } %> 33 | <% } %> 34 |
    35 | <%- partial('_partial/side') %> 36 | -------------------------------------------------------------------------------- /layout/docs.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    '> 3 | <%- partial('_partial/article', {post: page, index: false}) %> 4 |
    5 | <%- partial('_partial/side') %> 6 | 7 | -------------------------------------------------------------------------------- /layout/index.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    '> 3 | <%- partial('_partial/archive') %> 4 |
    5 | <%- partial('_partial/side') %> 6 | 7 | -------------------------------------------------------------------------------- /layout/layout.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | <%- partial('_partial/scripts/_ctrl') _%> 4 | <%- partial('_partial/head') _%> 5 | 6 | 7 | <%_ if (config.import && config.import.body_begin){ _%> 8 | <%_ getList(config.import.body_begin).forEach(function(item){ _%> 9 | <%- item %> 10 | <%_ }) _%> 11 | <%_ } _%> 12 | 13 | 14 | <%- volantis_inject('bodyBegin') %> 15 | 16 | <%- partial('_partial/header', null, {cache: false, path: path}) %> 17 |
    18 | <%- partial('_partial/cover') %> 19 |
    20 |
    21 | <%- body %> 22 |
    23 | <%- partial('_partial/footer', null, {cache: !config.relative_link}) %> 24 | 25 |
    26 |
    27 |
    28 | <%- partial('_partial/scripts/index') %> 29 |
    30 | 31 | <%_ if (config.import && config.import.body_end){ _%> 32 | <%_ getList(config.import.body_end).forEach(function(item){ _%> 33 | <%- item %> 34 | <%_ }) _%> 35 | <%_ } _%> 36 | 37 | 38 | <%- volantis_inject('bodyEnd') %> 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /layout/list.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 | <% page.comments = false; %> 3 |
    '> 4 | <% if (site.pages && site.pages.length > 0) { %> 5 |
    6 | <% site.pages.sort("-date").each(function(post){ %> 7 | <% if (post.group && post.group == page.group && post.layout != 'list') { %> 8 |
    9 | <%- partial('_partial/post', {post: post, index: false}) %> 10 |
    11 | <% } %> 12 | <% }) %> 13 | <% site.posts.sort("-date").each(function(post){ %> 14 | <% if (post.group && post.group == page.group && post.layout != 'list') { %> 15 |
    16 | <%- partial('_partial/post', {post: post, index: false}) %> 17 |
    18 | <% } %> 19 | <% }) %> 20 |
    21 | <% } %> 22 |
    23 | <%- partial('_partial/side') %> 24 | -------------------------------------------------------------------------------- /layout/page.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    '> 3 | <%- partial('_partial/article', {post: page, index: false}) %> 4 |
    5 | <%- partial('_partial/side') %> 6 | 7 | -------------------------------------------------------------------------------- /layout/post.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 |
    '> 3 | <%- partial('_partial/article', {post: page, index: false}) %> 4 |
    5 | <%- partial('_partial/side') %> 6 | 7 | -------------------------------------------------------------------------------- /layout/tag.ejs: -------------------------------------------------------------------------------- 1 | <%- partial('_pre') %> 2 | <% 3 | page.comments = false; 4 | if (!page.robots) { 5 | page.robots = 'noindex,follow'; 6 | } 7 | %> 8 |
    '> 9 | <% if (site.posts && site.posts.length > 0) { %> 10 | <% if ((page.layout == 'tag')||(page.layout == 'tags')) { %> 11 |
    12 |
    13 |

    <%- page.title %>

    14 |
    15 | <% let tc = theme.sidebar.widget_library.tagcloud; %> 16 | <%- list_tags({}) %> 17 |
    18 |
    19 | <%- page.content %> 20 |
    21 |
    22 | <% } else { %> 23 | <%- partial('_partial/archive') %> 24 | <% } %> 25 | <% } %> 26 |
    27 | <%- partial('_partial/side') %> 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hexo-theme-volantis", 3 | "version": "6.0.0-alpha.1", 4 | "description": "Elegant and powerful theme for Hexo.", 5 | "main": "package.json", 6 | "scripts": { 7 | "test": "echo test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/volantis-x/hexo-theme-volantis.git" 12 | }, 13 | "keywords": [ 14 | "hexo", 15 | "theme", 16 | "volantis" 17 | ], 18 | "author": "Volantis X (https://github.com/volantis-x/)", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/volantis-x/hexo-theme-volantis/issues" 22 | }, 23 | "homepage": "https://volantis.js.org", 24 | "dependencies": { 25 | "hexo": "^7.0.0", 26 | "hexo-renderer-stylus": "^3.0.0", 27 | "hexo-renderer-ejs": "^2.0.0", 28 | "hexo-generator-json-content": "^4.2.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scripts/events/index.js: -------------------------------------------------------------------------------- 1 | /* global hexo */ 2 | 3 | 'use strict'; 4 | 5 | const configLib = require('./lib/config'); 6 | const stellarTagUtilsLib = require('./lib/stellar-tag-utils'); 7 | const renderStylusLib = require('./lib/render-stylus'); 8 | const checkEnvironmentLib = require('./lib/check-environment'); 9 | const { version } = require('../../package.json'); 10 | 11 | hexo.on('generateBefore', () => { 12 | // Merge config. 13 | configLib(hexo); 14 | stellarTagUtilsLib(hexo); 15 | renderStylusLib(hexo); 16 | if (hexo.theme.config.debug === "env") { 17 | checkEnvironmentLib(hexo); 18 | } 19 | }); 20 | 21 | hexo.on('ready', () => { 22 | hexo.log.info(` 23 | ============================================================ 24 | Volantis ${version} 25 | Docs: https://volantis.js.org/ 26 | Repo: https://github.com/volantis-x/hexo-theme-volantis/ 27 | ============================================================`); 28 | }); -------------------------------------------------------------------------------- /scripts/events/lib/check-configuration.js: -------------------------------------------------------------------------------- 1 | module.exports =(hexo) => { 2 | try { 3 | let config = hexo.config; 4 | let themeConfig = hexo.theme.config; 5 | if (!config.title) { 6 | config.title = `Volantis` 7 | hexo.log.warn(`title 未配置! 8 | 请在站点配置 _config.yml 中配置 title 9 | see: https://hexo.io/zh-cn/docs/configuration 10 | title is not configured!`) 11 | } 12 | if (!config.description) { 13 | config.description = `Volantis 是一个功能丰富、高度模块化的 Hexo 博客主题。得益于其强大的模块化特性,您可以轻松搭建一个极简风格的博客,也可以仿照官网搭建一个多人协作的、包含文档模块的大体量综合型博客。` 14 | hexo.log.warn(`description 未配置! 15 | 请在站点配置 _config.yml 中配置 description 16 | description主要用于SEO,告诉搜索引擎一个关于您站点的简单描述,通常建议在其中包含您网站的关键词。 17 | see: https://hexo.io/zh-cn/docs/configuration 18 | description is not configured!`); 19 | } 20 | if (themeConfig?.search?.service===`google`||themeConfig?.search?.service===`azure`||themeConfig?.search?.service===`baidu`) { 21 | return `原 google, azure, baidu 站内搜索 系祖传代码, 且文档丢失, 不便后续维护 在 5.0 版本被移除 22 | The google, azure, baidu site search is ancestral code, and the document is lost, which is inconvenient for subsequent maintenance. It was removed in version 5.0 23 | see: https://volantis.js.org/v5/theme-settings/#站内搜索` 24 | } 25 | if (`backstretch` in themeConfig?.plugins) { 26 | return `jquery.backstretch 在 5.0 版本被移除, 被 parallax 替代 27 | jquery.backstretch was removed in version 5.0, replaced by parallax 28 | see: https://volantis.js.org/v5/theme-settings/#幻灯片背景-视差滚动效果` 29 | } 30 | if ("valinecount" in themeConfig?.article?.body?.top_meta||"valinecount" in themeConfig?.article?.body?.bottom_meta||"valinecount" in themeConfig?.article?.body?.meta_library) { 31 | return `ValineCount 在 5.0 版本被移除 32 | ValineCount has been removed in version 5.0 33 | see: https://volantis.js.org/v5/theme-settings/#文章布局配置` 34 | } 35 | if (themeConfig?.comments?.service=="valine"||themeConfig?.comments?.service=="minivaline") { 36 | return `Valine 在 5.0 版本被移除 37 | Valine has been removed in version 5.0 38 | see: https://volantis.js.org/v5/theme-settings/#选择评论系统` 39 | } 40 | if (config?.highlight?.hljs) { 41 | return `主题不兼容 hljs ,请在 config.highlight.hljs 处修改为 false 关闭。` 42 | } 43 | } catch (error) {} 44 | hexo.log.info(`Check environment configuration success!`); 45 | return true; 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /scripts/events/lib/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { version } = require('../../../package.json'); 4 | 5 | function isObject(item) { 6 | return item && typeof item === 'object' && !Array.isArray(item); 7 | } 8 | 9 | function merge(target, source) { 10 | for (const key in source) { 11 | if (isObject(target[key]) && isObject(source[key])) { 12 | merge(target[key], source[key]); 13 | } else { 14 | target[key] = source[key]; 15 | } 16 | } 17 | return target; 18 | } 19 | 20 | module.exports = hexo => { 21 | if (!hexo.locals.get) return; 22 | 23 | var data = hexo.locals.get('data'); 24 | if (!data) return; 25 | 26 | /** 27 | * Merge configs from _data/volantis.yml into hexo.theme.config. 28 | * If `override`, configs in volantis.yml will rewrite configs in hexo.theme.config. 29 | * If volantis.yml not exists, merge all `theme_config.*` into hexo.theme.config. 30 | */ 31 | 32 | if (data.volantis) { 33 | if (data.volantis.override) { 34 | hexo.theme.config = data.volantis; 35 | } else { 36 | merge(hexo.config, data.volantis); 37 | merge(hexo.theme.config, data.volantis); 38 | } 39 | } else { 40 | merge(hexo.theme.config, hexo.config.theme_config); 41 | } 42 | 43 | if (hexo.theme.config.cache && hexo.theme.config.cache.enable && hexo.config.relative_link) { 44 | hexo.log.warn('Since caching is turned on, the `relative_link` option in Hexo `_config.yml` is set to `false` to avoid potential hazards.'); 45 | hexo.config.relative_link = false; 46 | } 47 | hexo.config.meta_generator = false; 48 | hexo.theme.config.getStartTime = Date.now(); 49 | // Custom languages support. Introduced in NexT v6.3.0. 50 | if (data.languages) { 51 | var { language } = hexo.config; 52 | var { i18n } = hexo.theme; 53 | 54 | var mergeLang = lang => { 55 | i18n.set(lang, merge(i18n.get([lang]), data.languages[lang])); 56 | }; 57 | 58 | if (Array.isArray(language)) { 59 | for (const lang of language) { 60 | mergeLang(lang); 61 | } 62 | } else { 63 | mergeLang(language); 64 | } 65 | } 66 | hexo.theme.config.info.theme_version = version; 67 | }; 68 | -------------------------------------------------------------------------------- /scripts/events/lib/stellar-tag-utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * utils.js v1 | https://github.com/xaoxuu/hexo-theme-stellar/ 3 | */ 4 | 5 | // stellar 标签插件 命令解析器 6 | 7 | 8 | 'use strict'; 9 | 10 | module.exports = hexo => { 11 | hexo.args = { 12 | map: (args, keys, others) => { 13 | if (Array.isArray(args) == false) { 14 | return args; 15 | } 16 | var map = {others: Array()}; 17 | args.forEach((arg, i) => { 18 | let kv = arg.trim(); 19 | if (kv.includes('://') && kv.split(':').length == 2) { 20 | // 纯 url 21 | map.others.push(kv); 22 | } else { 23 | kv = kv.split(':'); 24 | if (kv.length > 1) { 25 | if (keys.includes(kv[0]) == true) { 26 | map[kv.shift()] = kv.join(':'); 27 | } else { 28 | map.others.push(kv.join(':')); 29 | } 30 | } else if (kv.length == 1) { 31 | map.others.push(kv[0]); 32 | } 33 | } 34 | }); 35 | // 解析不带 key 的参数 36 | if (others && others.length > 0 && map.others.length > 0) { 37 | if (Array.isArray(others) == false) { 38 | others = [others]; 39 | } 40 | others.forEach((arg, i) => { 41 | map[arg] = map.others.shift(); 42 | }); 43 | // 最后一段合并到最后一个参数中 44 | if (map.others.length > 0) { 45 | map[others[others.length-1]] += ' ' + map.others.join(' '); 46 | map.others = []; 47 | } 48 | } 49 | return map; 50 | }, 51 | joinTags: (args, keys) => { 52 | if (Array.isArray(keys) == false) { 53 | keys = [keys]; 54 | } 55 | var ret = []; 56 | keys.forEach((key, i) => { 57 | if (args[key] && args[key].length > 0) { 58 | ret.push(key + '="' + args[key] + '"'); 59 | } 60 | }); 61 | return ret; 62 | }, 63 | joinURLParams: (args, keys) => { 64 | if (Array.isArray(keys) == false) { 65 | keys = [keys]; 66 | } 67 | var ret = []; 68 | keys.forEach((key, i) => { 69 | if (args[key] && args[key].length > 0) { 70 | ret.push(key + '=' + args[key]); 71 | } 72 | }); 73 | return ret.join('&'); 74 | } 75 | }; 76 | }; 77 | -------------------------------------------------------------------------------- /scripts/filters/content-visibility.js: -------------------------------------------------------------------------------- 1 | // https://web.dev/content-visibility/ 2 | // https://www.caniuse.com/?search=content-visibility 3 | // 在文章内容渲染时将每两个

    之间的内容分为一块 用
    包裹起来。然后为 .post-story 声明 content-visibility: auto 4 | hexo.extend.filter.register('after_post_render', function (data) { 5 | if (this.theme.config.content_visibility) { 6 | let dataList = data.content.split('\n') 7 | let mydata = `` 8 | let flag = 1 9 | dataList.forEach(e => { 10 | let yy = e.replace(/.*?<\/h2>/, function (str) { 11 | if (flag) { 12 | flag = 0 13 | return `
    ` + str 14 | } else { 15 | return `
    ` + str 16 | } 17 | }) 18 | mydata += yy 19 | mydata += "\n" 20 | }); 21 | if (!flag) { 22 | mydata += `
    ` 23 | } 24 | data.content = mydata 25 | } 26 | return data; 27 | }); -------------------------------------------------------------------------------- /scripts/filters/img.js: -------------------------------------------------------------------------------- 1 | /* global hexo */ 2 | 3 | 'use strict'; 4 | 5 | const imgRegex = /

    (.*?)<\/p>/g; 6 | const imgReplacement = '

    $2<\/div>$2<\/span><\/div>'; 7 | 8 | hexo.extend.filter.register('after_post_render', function(data) { 9 | data.content = data.content.replace(imgRegex, imgReplacement); 10 | return data; 11 | }); -------------------------------------------------------------------------------- /scripts/filters/replace.js: -------------------------------------------------------------------------------- 1 | /* global hexo */ 2 | 3 | 'use strict'; 4 | 5 | hexo.extend.filter.register('after_render:html', function(data) { 6 | if (hexo.theme.config.replace) { 7 | const replacements = hexo.theme.config.replace.map(e => { 8 | const [a, b] = e.split(" => "); 9 | return { regex: new RegExp(a, "g"), replacement: b }; 10 | }); 11 | 12 | replacements.forEach(({ regex, replacement }) => { 13 | data = data.replace(regex, replacement); 14 | }); 15 | } 16 | return data; 17 | }, 999999999999); -------------------------------------------------------------------------------- /scripts/filters/z-lazyload.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('hexo-fs'); 4 | 5 | function lazyProcess(htmlContent, target) { 6 | const cfg = this.theme.config.plugins.lazyload; 7 | if (cfg == undefined || cfg.enable != true) { 8 | return htmlContent; 9 | } 10 | if (cfg.onlypost == true) { 11 | if (target != 'post') { 12 | return htmlContent; 13 | } 14 | } 15 | const loadingImg = cfg.loadingImg; 16 | return htmlContent.replace(//gi, function(str, p1, p2) { 17 | // might be duplicate 18 | if (/data-srcset/gi.test(str)) { 19 | return str; 20 | } 21 | if (/src="data:image(.*?)/gi.test(str)) { 22 | return str; 23 | } 24 | if (/no-lazy/gi.test(str)) { 25 | return str; 26 | } 27 | let cls = ''; 28 | if (str.indexOf('class=') > -1) { 29 | cls = str.substring(str.indexOf('class=')); 30 | if (cls.length > 7) { 31 | const c = cls.substring(6, 7); 32 | cls = cls.split(c); 33 | if (cls.length > 1) { 34 | cls = cls[0] + '"' + cls[1] + '"'; 35 | } 36 | } 37 | } 38 | let result = str; 39 | let newCls = ''; 40 | if (cls.length > 0 && result.includes('class=')) { 41 | newCls = cls.replace(/(class=|[\"]*)/g, '') + ' '; 42 | } 43 | const oldCls = newCls.trim(); 44 | if (loadingImg) { 45 | newCls += 'lazyload placeholder'; 46 | } else { 47 | newCls += 'lazyload'; 48 | } 49 | if (cls.length > 0) { 50 | result = result.replace('"' + oldCls + '"', '"' + newCls + '"'); 51 | } 52 | if (loadingImg) { 53 | return result.replace(p2, p2 + '" class="lazyload placeholder" ' + 'data-srcset="' + p2 + '" srcset="' + loadingImg); 54 | } 55 | return result.replace(p2, p2 + '" class="lazyload" ' + 'data-srcset="' + p2 + '" srcset="' + 'data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='); 56 | 57 | }); 58 | } 59 | 60 | let processPost = function(data) { 61 | data.content = lazyProcess.call(this, data.content, 'post'); 62 | return data; 63 | }; 64 | 65 | let processSite = function(htmlContent) { 66 | return lazyProcess.call(this, htmlContent, 'site'); 67 | }; 68 | 69 | hexo.extend.filter.register('after_post_render', processPost); 70 | hexo.extend.filter.register('after_render:html', processSite); 71 | -------------------------------------------------------------------------------- /scripts/helpers/first-style.js: -------------------------------------------------------------------------------- 1 | // 将首屏样式 first.styl 硬编码到HTML页面 2 | "use strict"; 3 | const fs = require("hexo-fs"); 4 | 5 | function generateFirstCSS() { 6 | let s = fs.readFileSync( 7 | hexo.theme.context.theme_dir + "source/css/first.styl" 8 | ); 9 | hexo.renderStylus(s).then((css)=>{ 10 | hexo.locals.set('FirstCSS', function(){ 11 | return css 12 | }); 13 | }) 14 | } 15 | function getFirstCSS() { 16 | return hexo.locals.get('FirstCSS'); 17 | } 18 | hexo.extend.filter.register("before_generate", generateFirstCSS); 19 | hexo.extend.helper.register("FirstCSS", getFirstCSS); 20 | -------------------------------------------------------------------------------- /scripts/helpers/getList.js: -------------------------------------------------------------------------------- 1 | // yml string to list 2 | // yml 太烂了 3 | 4 | hexo.extend.helper.register('getList', function (list) { 5 | return list ? (typeof list === "string" ? [list] : [...list]) : []; 6 | }); -------------------------------------------------------------------------------- /scripts/helpers/head/autoCanonical.js: -------------------------------------------------------------------------------- 1 | /** 2 | * hexo-auto-canonical 3 | * https://github.com/hyunseob/hexo-auto-canonical.git 4 | * Copyright (c) 2015, HyunSeob 5 | * Licensed under the MIT license. 6 | */ 7 | 8 | 'use strict'; 9 | 10 | hexo.extend.helper.register('autoCanonical', function (config, page) { 11 | var base_url = config.url; 12 | if (config.url.charAt(config.url.length - 1) !== '/') base_url += '/'; 13 | 14 | return ''; 15 | }); -------------------------------------------------------------------------------- /scripts/helpers/head/generate_preload_fontfamily.js: -------------------------------------------------------------------------------- 1 | function getType(file) { 2 | var filename = file; 3 | var index1 = filename.lastIndexOf("."); 4 | var index2 = filename.length; 5 | var type = filename.substring(index1 + 1, index2); 6 | return type; 7 | } 8 | function getLink_preload(Url) { 9 | return `\n` 10 | } 11 | 12 | hexo.extend.helper.register("generate_preload_fontfamily", function (theme) { 13 | const hexo = this; 14 | let preload = ""; 15 | if (theme.custom_css.fontfamily.logofont && theme.custom_css.fontfamily.logofont.url) { 16 | preload += getLink_preload(theme.custom_css.fontfamily.logofont.url) 17 | } 18 | if (theme.custom_css.fontfamily.bodyfont && theme.custom_css.fontfamily.bodyfont.url) { 19 | preload += getLink_preload(theme.custom_css.fontfamily.bodyfont.url) 20 | } 21 | return preload 22 | }); 23 | -------------------------------------------------------------------------------- /scripts/helpers/head/generate_seo.js: -------------------------------------------------------------------------------- 1 | hexo.extend.helper.register('generate_seo', function (theme, page) { 2 | const hexo = this; 3 | let robots_content=""; 4 | if (page.robots) { 5 | robots_content = page.robots 6 | } else if (theme.seo && theme.seo.robots) { 7 | if (hexo.is_home()) { 8 | if (page.prev == 0) { 9 | robots_content=theme.seo.robots.home_first_page 10 | }else{ 11 | robots_content=theme.seo.robots.home_other_pages 12 | } 13 | } else if (hexo.is_archive()) { 14 | robots_content=theme.seo.robots.archive 15 | } else if (hexo.is_category()) { 16 | robots_content=theme.seo.robots.category 17 | } else if (hexo.is_tag()) { 18 | robots_content=theme.seo.robots.tag 19 | } 20 | } 21 | if(robots_content){ 22 | return `` 23 | } 24 | }); -------------------------------------------------------------------------------- /scripts/helpers/related-posts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://github.com/tea3/hexo-related-popular-posts/wiki/More-Settings#customize-html 3 | */ 4 | 5 | 'use strict'; 6 | var util = require('hexo-util'); 7 | 8 | // Examples of helper 9 | hexo.extend.helper.register('htmlGenerator', function(args) { 10 | if (!args || !args.json || args.json.length == 0) return ''; 11 | const cfg = hexo.theme.config.article.body.footer_widget.related_posts; 12 | var returnHTML = ''; 13 | var div = ` 14 | '; 53 | return div; 54 | }); 55 | -------------------------------------------------------------------------------- /scripts/helpers/structured-data/index.js: -------------------------------------------------------------------------------- 1 | /*globals hexo */ 2 | hexo.extend.helper.register("structured_data", require('./lib/')); 3 | -------------------------------------------------------------------------------- /scripts/helpers/structured-data/lib/blogposting.js: -------------------------------------------------------------------------------- 1 | module.exports = (hexo, option) => { 2 | const { config, page: post } = hexo; 3 | 4 | const blogposting = { 5 | "@context": "https://schema.org.cn", 6 | "@type": "BlogPosting", 7 | headline: post.title || post.seo_title, 8 | description: post.description || hexo.strip_html(post.excerpt) || config.description, 9 | inLanguage: config.language, 10 | mainEntityOfPage: { 11 | "@type": "WebPage", 12 | "@id": post.permalink, 13 | }, 14 | author: { 15 | "@type": "Person", 16 | name: option.person.name, 17 | image: { 18 | "@type": "ImageObject", 19 | url: option.logo.path, 20 | }, 21 | url: option.person.url, 22 | }, 23 | publisher: { 24 | "@type": "Organization", 25 | name: option.organization.name, 26 | logo: { 27 | "@type": "ImageObject", 28 | url: option.logo.path, 29 | width: option.logo.width, 30 | height: option.logo.height, 31 | }, 32 | }, 33 | url: post.permalink, 34 | }; 35 | 36 | blogposting.wordCount = hexo.strip_html(post.excerpt).length; 37 | 38 | if (post.date) { 39 | blogposting.datePublished = post.date.toISOString(); 40 | } 41 | if (post.updated) { 42 | blogposting.dateModified = post.updated.toISOString(); 43 | } 44 | if (post.categories && post.categories.length) { 45 | if (post.categories.data) { 46 | blogposting.articleSection = post.categories.data[0].name; 47 | } else { 48 | blogposting.articleSection = post.categories[0]; 49 | } 50 | } 51 | 52 | if (post.tags && post.tags.length) { 53 | if (post.tags.data) { 54 | blogposting.keywords = post.tags.map((tag) => tag.name).join(","); 55 | } else { 56 | blogposting.keywords = post.tags.map((tag) => tag).join(","); 57 | } 58 | } 59 | let image = post.headimg || ""; 60 | if (image) { 61 | blogposting.image = { 62 | "@type": "ImageObject", 63 | url: image, 64 | width: 1024, 65 | height: 768, 66 | }; 67 | }else{ 68 | blogposting.image = { 69 | "@type": "ImageObject", 70 | url: option.logo.path, 71 | width: option.logo.width, 72 | height: option.logo.height, 73 | }; 74 | } 75 | 76 | return blogposting; 77 | }; 78 | -------------------------------------------------------------------------------- /scripts/helpers/structured-data/lib/config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (hexo) { 2 | const {config} = hexo; 3 | return { 4 | person: { 5 | name: config.author, 6 | url: config.url + config.root, 7 | sns: [], 8 | description: config.description, 9 | }, 10 | logo: { 11 | path: /404/, 12 | width: 192, 13 | height: 192, 14 | }, 15 | organization: { 16 | name: config.title, 17 | url: config.url + config.root, 18 | }, 19 | website: { 20 | name: config.title, 21 | url: config.url + config.root, 22 | keywords: config.keywords, 23 | description: config.description, 24 | search: { 25 | name: "Site Search", 26 | url: config.url + "?s={search_term_string}", 27 | query: "required name=search_term_string", 28 | }, 29 | }, 30 | }; 31 | }; 32 | -------------------------------------------------------------------------------- /scripts/helpers/structured-data/lib/index.js: -------------------------------------------------------------------------------- 1 | const config = require("./config"); 2 | 3 | const WebSite = require("./website"); 4 | const Organization = require("./organization"); 5 | const Person = require("./person"); 6 | const BlogPosting = require("./blogposting"); 7 | const BreadcrumbList = require("./breadcrumblist"); 8 | 9 | function isObject(item) { 10 | return item && typeof item === 'object' && !Array.isArray(item); 11 | } 12 | 13 | function merge(target, source) { 14 | for (const key in source) { 15 | if (isObject(target[key]) && isObject(source[key])) { 16 | merge(target[key], source[key]); 17 | } else { 18 | target[key] = source[key]; 19 | } 20 | } 21 | return target; 22 | } 23 | 24 | module.exports = function () { 25 | const hexo = this; 26 | const option = merge(config(hexo), hexo.theme.structured_data.data); 27 | const builder = [Organization, Person, BreadcrumbList, WebSite, BlogPosting]; 28 | const jsonld = JSON.stringify(builder.map((f) => f(hexo, option))); 29 | return ``; 30 | }; 31 | -------------------------------------------------------------------------------- /scripts/helpers/structured-data/lib/organization.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = (hexo, option) => { 3 | return { 4 | "@context": "https://schema.org.cn", 5 | "@type": "Organization", 6 | "name": option.organization.name, 7 | "url": option.organization.url, 8 | "logo": { 9 | "@type": "ImageObject", 10 | "url": option.logo.path, 11 | "width": option.logo.width, 12 | "height": option.logo.height 13 | } 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /scripts/helpers/structured-data/lib/person.js: -------------------------------------------------------------------------------- 1 | module.exports = (hexo, option) => { 2 | const { config } = hexo; 3 | 4 | return { 5 | "@context": "https://schema.org.cn", 6 | "@type": "Person", 7 | name: option.person.name, 8 | image: { 9 | "@type": "ImageObject", 10 | url: option.logo.path, 11 | }, 12 | url: option.person.url, 13 | sameAs: option.person.sns, 14 | description: option.person.description, 15 | }; 16 | }; 17 | -------------------------------------------------------------------------------- /scripts/helpers/structured-data/lib/website.js: -------------------------------------------------------------------------------- 1 | module.exports = (hexo,option) => { 2 | const { config } = hexo; 3 | 4 | return { 5 | "@context": "https://schema.org.cn", 6 | "@type": "WebSite", 7 | name: option.website.name, 8 | url: option.website.url, 9 | keywords: option.website.keywords, 10 | description: option.website.description, 11 | author: { 12 | "@type": "Person", 13 | name: option.person.name, 14 | image: { 15 | "@type": "ImageObject", 16 | url: option.logo.path, 17 | }, 18 | url: option.person.url, 19 | description: option.person.description, 20 | }, 21 | publisher: { 22 | "@type": "Organization", 23 | name: option.organization.name, 24 | url: option.organization.url, 25 | logo: { 26 | "@type": "ImageObject", 27 | url: option.logo.path, 28 | width: option.logo.width, 29 | height: option.logo.height, 30 | }, 31 | }, 32 | potentialAction: { 33 | "@type": "SearchAction", 34 | name: option.website.search.name, 35 | target: { 36 | "@type": "EntryPoint", 37 | urlTemplate: option.website.search.url, 38 | }, 39 | "query-input": option.website.search.query, 40 | }, 41 | }; 42 | }; 43 | -------------------------------------------------------------------------------- /scripts/tags/btn.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function postBtn(args) { 4 | if(/::/g.test(args)){ 5 | args = args.join(' ').split('::'); 6 | } 7 | else{ 8 | args = args.join(' ').split(','); 9 | } 10 | let cls = ''; 11 | let text = ''; 12 | let url = ''; 13 | let icon = ''; 14 | if (args.length > 3) { 15 | cls = args[0]; 16 | text = args[1]; 17 | url = args[2]; 18 | icon = args[3]; 19 | } else if (args.length > 2) { 20 | if (args[2].indexOf(' fa-') > -1) { 21 | // text, url, icon 22 | text = args[0]; 23 | url = args[1]; 24 | icon = args[2]; 25 | } else { 26 | cls = args[0]; 27 | text = args[1]; 28 | url = args[2]; 29 | } 30 | } else if (args.length > 1) { 31 | text = args[0]; 32 | url = args[1]; 33 | } else if (args.length > 0) { 34 | text = args[0]; 35 | } 36 | 37 | cls = cls.trim(); 38 | icon = icon.trim(); 39 | text = text.trim(); 40 | url = url.trim(); 41 | if (url.length > 0) { 42 | url = 'href=\'' + url + '\''; 43 | } 44 | if (cls.length > 0) { 45 | cls = ' ' + cls; 46 | } 47 | if (icon.length > 0) { 48 | return `${text}`; 49 | } 50 | return `${text}`; 51 | 52 | } 53 | 54 | hexo.extend.tag.register('btn', postBtn); 55 | -------------------------------------------------------------------------------- /scripts/tags/btns.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function postBtns(args, content) { 4 | return `
    5 | ${content} 6 |
    `; 7 | } 8 | 9 | function postCell(args, content) { 10 | if(/::/g.test(args)){ 11 | args = args.join(' ').split('::'); 12 | } 13 | else{ 14 | args = args.join(' ').split(','); 15 | } 16 | let text = args[0] || ''; 17 | let url = args[1] || ''; 18 | text = text.trim(); 19 | url = url.trim(); 20 | if (url.length > 0) { 21 | url = 'href=\'' + url + '\''; 22 | } 23 | let icon = ''; 24 | let img = hexo.theme.config.default.image; 25 | if (args.length > 2) { 26 | if (args[2].indexOf(' fa-') > -1) { 27 | icon = args[2].trim(); 28 | } else { 29 | img = args[2].trim(); 30 | } 31 | } 32 | if (icon.length > 0) { 33 | return `${text}`; 34 | } 35 | return `${text}`; 36 | 37 | } 38 | 39 | hexo.extend.tag.register('btns', postBtns, {ends: true}); 40 | hexo.extend.tag.register('cell', postCell); 41 | -------------------------------------------------------------------------------- /scripts/tags/checkbox.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function postCheckbox(args) { 4 | if(/::/g.test(args)){ 5 | args = args.join(' ').split('::'); 6 | } 7 | else{ 8 | args = args.join(' ').split(','); 9 | } 10 | var cls = ''; 11 | var text = ''; 12 | var checked = false; 13 | if (args.length > 1) { 14 | cls = (args[0] || '').trim(); 15 | if (cls.length > 0) { 16 | cls = ' ' + cls; 17 | } 18 | if (cls.indexOf('checked') > -1) { 19 | checked = true; 20 | } 21 | text = (args[1] || '').trim(); 22 | } else if (args.length > 0) { 23 | text = (args[0] || '').trim(); 24 | } 25 | if (text.length > 0) { 26 | return `
    27 | ${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')} 28 |
    `; 29 | } 30 | } 31 | function postRadio(args) { 32 | if(/::/g.test(args)){ 33 | args = args.join(' ').split('::'); 34 | } 35 | else{ 36 | args = args.join(' ').split(','); 37 | } 38 | var cls = ''; 39 | var text = ''; 40 | var checked = false; 41 | if (args.length > 1) { 42 | cls = (args[0] || '').trim(); 43 | if (cls.length > 0) { 44 | cls = ' ' + cls; 45 | } 46 | if (cls.indexOf('checked') > -1) { 47 | checked = true; 48 | } 49 | text = (args[1] || '').trim(); 50 | } else if (args.length > 0) { 51 | text = (args[0] || '').trim(); 52 | } 53 | if (text.length > 0) { 54 | return `
    55 | ${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')} 56 |
    `; 57 | } 58 | } 59 | // {% checkbox text %} 60 | // {% checkbox checked, text %} 61 | // {% checkbox color checked, text %} 62 | hexo.extend.tag.register('checkbox', postCheckbox); 63 | hexo.extend.tag.register('radio', postRadio); 64 | -------------------------------------------------------------------------------- /scripts/tags/fancybox.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function renderImg(content) { 4 | return `${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}`; 5 | } 6 | 7 | function buidAlt(alt) { 8 | if (!!alt && alt !== 'image') { 9 | return `${alt}` 10 | } else { 11 | return ''; 12 | } 13 | } 14 | 15 | function buidImgFancybox(content, group) { 16 | let html = renderImg(content).trim(); 17 | if(html.startsWith('

    ') && html.endsWith('

    ')) { // 去除无用的 p 标签包裹 18 | html=html.substring(0, html.length-4).substring(3); 19 | } 20 | 21 | let imageTags = html.includes('image-caption') ? 'image' : undefined; 22 | let imgList = html.match(//g) || []; 23 | imgList.forEach(item => { 24 | const url = (item.match(/\ssrc=['"](.*?)['"]/) || [])[1]; 25 | const alt = (item.match(/\salt=['"](.*?)['"]/) || [])[1] || ''; 26 | const newItem = item.replace('img', 'img fancybox itemprop="contentUrl"'); // 避免出现重复替换,打个标 27 | const result = `
    ${buidAlt(imageTags || alt)}
    `; 28 | html = html.replace(item, result.trim()); 29 | }) 30 | return html; 31 | } 32 | 33 | function postFancybox(args, content) { 34 | if(/::/g.test(args)){ 35 | args = args.join(' ').split('::'); 36 | } 37 | else{ 38 | args = args.join(' ').split(','); 39 | } 40 | const cls = args[0]; 41 | const col = Number(args[1]) || 0; 42 | const group = (args[2] || 'default').trim(); 43 | 44 | if (col > 0) { 45 | return ``; 46 | } 47 | return ``; 48 | } 49 | 50 | 51 | 52 | hexo.extend.tag.register('gallery', postFancybox, {ends: true}); 53 | -------------------------------------------------------------------------------- /scripts/tags/folding.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function postFolding(args, content) { 4 | if(/::/g.test(args)){ 5 | args = args.join(' ').split('::'); 6 | } 7 | else{ 8 | args = args.join(' ').split(','); 9 | } 10 | let style = ''; 11 | let title = ''; 12 | if (args.length > 1) { 13 | style = args[0].trim(); 14 | title = args[1].trim(); 15 | } else if (args.length > 0) { 16 | title = args[0].trim(); 17 | } 18 | if (style != undefined) { 19 | return `
    ${title} 20 |
    21 | ${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')} 22 |
    23 |
    `; 24 | } 25 | return `
    ${title} 26 |
    27 | ${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')} 28 |
    29 |
    `; 30 | 31 | 32 | } 33 | 34 | hexo.extend.tag.register('folding', postFolding, {ends: true}); 35 | -------------------------------------------------------------------------------- /scripts/tags/ghcard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * https://github.com/anuraghazra/github-readme-stats 3 | */ 4 | 5 | 'use strict'; 6 | 7 | // {% ghcard volantis-x %} 8 | // {% ghcard volantis-x/hexo-theme-volantis %} 9 | hexo.extend.tag.register('ghcard', function(args) { 10 | if(/::/g.test(args)){ 11 | args = args.join(' ').split('::'); 12 | } 13 | else{ 14 | args = args.join(' ').split(','); 15 | } 16 | const path = args[0].trim(); 17 | let card = ''; 18 | card += ''; 19 | let url = ''; 20 | if (path.includes('/')) { 21 | // is repo 22 | const ps = path.split('/'); 23 | url += 'https://github-readme-stats.xaoxuu.com/api/pin/?username=' + ps[0] + '&repo=' + ps[1]; 24 | } else { 25 | // is user 26 | url += 'https://github-readme-stats.xaoxuu.com/api/?username=' + path; 27 | } 28 | if (args.length > 1) { 29 | for (let i = 1; i < args.length; i++) { 30 | const tmp = args[i].trim(); 31 | url += '&' + tmp; 32 | } 33 | } 34 | if (!url.includes('&show_owner=')) { 35 | url += '&show_owner=true'; 36 | } 37 | card += ''; 38 | card += ''; 39 | return card; 40 | }); 41 | 42 | hexo.extend.tag.register('ghcardgroup', function(args, content) { 43 | let ret = ''; 44 | // wrap 45 | ret += '
    '; 46 | ret += content; 47 | ret += '
    '; 48 | return ret; 49 | }, {ends: true}); 50 | -------------------------------------------------------------------------------- /scripts/tags/inline-labels.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function createTag(tagName) { 4 | return function(args) { 5 | return `<${tagName}>${args.join(' ')}`; 6 | }; 7 | } 8 | 9 | hexo.extend.tag.register('u', createTag('u')); 10 | hexo.extend.tag.register('emp', createTag('emp')); 11 | hexo.extend.tag.register('wavy', createTag('wavy')); 12 | hexo.extend.tag.register('del', createTag('del')); 13 | hexo.extend.tag.register('kbd', createTag('kbd')); 14 | hexo.extend.tag.register('psw', createTag('psw')); -------------------------------------------------------------------------------- /scripts/tags/link.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // {% link title, url %} 4 | // {% link title, url, img %} 5 | hexo.extend.tag.register('link', function(args) { 6 | if(/::/g.test(args)){ 7 | args = args.join(' ').split('::'); 8 | } 9 | else{ 10 | args = args.join(' ').split(','); 11 | } 12 | let text = ''; 13 | let url = ''; 14 | let img = ''; 15 | if (args.length < 2) { 16 | return; 17 | } else if (args.length == 2) { 18 | text = args[0].trim(); 19 | url = args[1].trim(); 20 | } else if (args.length == 3) { 21 | text = args[0].trim(); 22 | url = args[1].trim(); 23 | img = args[2].trim(); 24 | } 25 | let result = ''; 26 | // 发现如果不套一层 div 在其它可渲染 md 的容器中容易被分解 27 | result += ''; 35 | 36 | return result; 37 | }); 38 | 39 | hexo.extend.tag.register('linkgroup', function(args, content) { 40 | let ret = ''; 41 | ret += ''; 44 | return ret; 45 | }, {ends: true}); 46 | -------------------------------------------------------------------------------- /scripts/tags/md.js: -------------------------------------------------------------------------------- 1 | 2 | hexo.extend.tag.register('md', function(args) { 3 | const {config} = hexo; 4 | const md_path = args[0].trim(); 5 | let md_id = "md-" + hexo.createUuid() 6 | let mat = ` 7 |
    8 | 56 | ` 57 | 58 | return mat 59 | }); 60 | -------------------------------------------------------------------------------- /scripts/tags/media.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function postAudio(args) { 4 | const src = args[0].trim(); 5 | return `
    `; 6 | } 7 | 8 | function postVideo(args) { 9 | const {config} = hexo; 10 | const src = args[0].trim(); 11 | // m3u8 https://github.com/volantis-x/hexo-theme-volantis/issues/606 12 | // 文件扩展名为 .m3u8 13 | if (hexo.getType(src) === "m3u8") { 14 | let video_id = `video-${hexo.createUuid()}` 15 | return `
    16 | `; 28 | } 29 | return `
    `; 30 | } 31 | 32 | function postVideos(args, content) { 33 | if(/::/g.test(args)){ 34 | args = args.join(' ').split('::'); 35 | } 36 | else{ 37 | args = args.join(' ').split(','); 38 | } 39 | var cls = args[0]; 40 | if (cls.length > 0) { 41 | cls = ' ' + cls; 42 | } 43 | var col = Number(args[1]) || 0; 44 | if (col > 0) { 45 | return `
    ${content}
    `; 46 | } 47 | return `
    ${content}
    `; 48 | 49 | } 50 | 51 | hexo.extend.tag.register('audio', postAudio); 52 | hexo.extend.tag.register('video', postVideo); 53 | hexo.extend.tag.register('videos', postVideos, {ends: true}); 54 | -------------------------------------------------------------------------------- /scripts/tags/pandown.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // {% pandown type, url, pwd, fname %} 4 | hexo.extend.tag.register('pandown', function(args) { 5 | if(/::/g.test(args)){ 6 | args = args.join(' ').split('::'); 7 | } 8 | else{ 9 | args = args.join(' ').split(','); 10 | } 11 | let type = ''; 12 | let url = ''; 13 | let pwd = ''; 14 | let fname = ''; 15 | if (args.length < 4) { 16 | return; 17 | } else if (args[0].trim() === 'yun') { 18 | return '

    对不起,pandown-tags不支持自定义


    Sorry, pandown-tags does not support customization

    ' 19 | } else { 20 | type = args[0].trim(); 21 | url = args[1].trim(); 22 | pwd = args[2].trim(); 23 | fname = args[3].trim(); 24 | } 25 | let result = ''; 26 | // js 27 | result += '
    '; 28 | //pandown 29 | result += '' 30 | //调用 31 | result += '
    ' 32 | return result; 33 | }); 34 | -------------------------------------------------------------------------------- /scripts/tags/span.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function postP(args) { 4 | if(/::/g.test(args)){ 5 | args = args.join(' ').split('::'); 6 | } 7 | else{ 8 | args = args.join(' ').split(','); 9 | } 10 | const p0 = args[0].trim(); 11 | const p1 = args[1].trim(); 12 | return `

    ${p1}

    `; 13 | } 14 | function postSpan(args) { 15 | if(/::/g.test(args)){ 16 | args = args.join(' ').split('::'); 17 | } 18 | else{ 19 | args = args.join(' ').split(','); 20 | } 21 | const p0 = args[0].trim(); 22 | const p1 = args[1].trim(); 23 | return `${p1}`; 24 | } 25 | 26 | hexo.extend.tag.register('p', postP); 27 | hexo.extend.tag.register('span', postSpan); 28 | -------------------------------------------------------------------------------- /scripts/tags/swiper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * swiper.js v1 | https://github.com/xaoxuu/hexo-theme-stellar/ 3 | * 格式与官方标签插件一致使用空格分隔,中括号内的是可选参数(中括号不需要写出来) 4 | * 5 | * {% swiper %} 6 | * ![img](src) 7 | * {% endswiper %} 8 | */ 9 | 10 | 'use strict'; 11 | 12 | hexo.extend.tag.register('swiper', function (args, content) { 13 | args = hexo.args.map(args, ['width']); 14 | var el = ''; 15 | function slide() { 16 | let imgs = hexo.render.renderSync({ text: content, engine: 'markdown' }); 17 | imgs = imgs.match(//gi); 18 | if (imgs && imgs.length > 0) { 19 | imgs.forEach((img, i) => { 20 | img = img.replace(''; 22 | }); 23 | } 24 | } 25 | el += '
    0) { 27 | el += ' ' + hexo.args.joinTags(args, 'width').join(' '); 28 | } 29 | el += '>'; 30 | el += '
    '; 31 | slide(); 32 | el += '
    '; 33 | el += '
    '; 34 | el += '
    '; 35 | el += '
    '; 36 | el += '
    '; 37 | return el; 38 | }, { ends: true }); -------------------------------------------------------------------------------- /scripts/tags/table.js: -------------------------------------------------------------------------------- 1 | /** 2 | * table.js | https://github.com/volantis-x/hexo-theme-volantis 3 | */ 4 | 5 | 'use strict'; 6 | 7 | // {% table title %} 8 | // table markdown 9 | // {% endtable %} 10 | 11 | function postTable(args, content) { 12 | let ret = ''; 13 | ret += '
    '; 14 | ret += hexo.render.renderSync({text: content, engine: 'markdown'}); 15 | ret += '
    '; 16 | return ret; 17 | } 18 | 19 | hexo.extend.tag.register('table', postTable, {ends: true}); 20 | -------------------------------------------------------------------------------- /scripts/tags/timeline.js: -------------------------------------------------------------------------------- 1 | /** 2 | * timeline.js | https://volantis.js.org/v3/tag-plugins/#Timeline 3 | */ 4 | 5 | 'use strict'; 6 | 7 | function postTimeline(args, content) { 8 | if (args.length > 0) { 9 | return `

    ${args}

    ${content}
    `; 10 | } 11 | return `
    ${content}
    `; 12 | 13 | } 14 | 15 | function postTimenode(args, content) { 16 | if(/::/g.test(args)){ 17 | args = args.join(' ').split('::'); 18 | } 19 | else{ 20 | args = args.join(' ').split(','); 21 | } 22 | var time = args[0]; 23 | return `

    ${hexo.render.renderSync({text: time, engine: 'markdown'})}

    ${hexo.render.renderSync({text: content, engine: 'markdown'}).split('\n').join('')}
    `; 24 | } 25 | 26 | 27 | // {% timeline %} 28 | // ... timenode ... 29 | // {% endtimeline %} 30 | hexo.extend.tag.register('timeline', postTimeline, {ends: true}); 31 | 32 | // {% timenode time %} 33 | // what happened 34 | // {% endtimenode %} 35 | hexo.extend.tag.register('timenode', postTimenode, {ends: true}); 36 | -------------------------------------------------------------------------------- /source/css/Readme.md: -------------------------------------------------------------------------------- 1 | # 样式文件说明 2 | 3 | ## 样式拆分说明 4 | 5 | 方案是对 https://blog.skk.moe/post/improve-fcp-for-my-blog/ 的开源实现 6 | 7 | ### first.styl 8 | 9 | 首屏样式, 内含 首屏基础样式、 cover、 navbar、 首屏search、首屏暗黑模式、首屏字体 等样式, 首屏样式采用硬编码的方式写在HTML中. 10 | 11 | 内联硬编码自动化方案 see:scripts/helpers/first-style/index.js 12 | 13 | ### style.styl 14 | 15 | 异步加载样式, 除首屏样式外的其他样式, 最终生成 /css/style.css 异步加载. 16 | 17 | ## 暗黑模式样式说明 18 | 19 | 暗黑模式样式被拆分为首屏暗黑模式样式和异步暗黑模式样式,其中在 source/css/ 文件夹下: 20 | 21 | _first/dark_first.styl : 包含 首屏暗黑模式样式 的 暗黑模式 CSS 变量 和 强制覆盖样式 22 | 23 | _style/_plugins/_dark : 异步暗黑模式样式文件夹 24 | 25 | _style/_plugins/_dark/dark_async.styl : 包含 异步暗黑模式样式 的 暗黑模式 CSS 变量 26 | 27 | _style/_plugins/_dark/dark_plugins.styl : 包含 异步暗黑模式样式 的 强制覆盖样式 28 | 29 | -------------------------------------------------------------------------------- /source/css/_defines/Readme.md: -------------------------------------------------------------------------------- 1 | # 定义变量 2 | 3 | 这里存放一些 变量 或 工具函数 ,不建议存放样式 -------------------------------------------------------------------------------- /source/css/_defines/effect.styl: -------------------------------------------------------------------------------- 1 | @require('func') 2 | // shadow 3 | $boxshadow-card = 0 1px 2px 0px rgba(0, 0, 0, 0.1) 4 | $boxshadow-card-float = 0 2px 4px 0px rgba(0, 0, 0, 0.1), 0 4px 8px 0px rgba(0, 0, 0, 0.1), 0 8px 16px 0px rgba(0, 0, 0, 0.1) 5 | 6 | $boxshadow-float = 0 4px 8px 0px rgba(0, 0, 0, 0.1) 7 | 8 | $boxshadow-dropmenu = 0 2px 4px 0px rgba(0, 0, 0, 0.08), 0 4px 8px 0px rgba(0, 0, 0, 0.08), 0 8px 16px 0px rgba(0, 0, 0, 0.08) 9 | 10 | $textshadow = 0 1px 2px 0px rgba(0, 0, 0, 0.1) 11 | 12 | -------------------------------------------------------------------------------- /source/css/_defines/func.styl: -------------------------------------------------------------------------------- 1 | // 为1个属性设置动画 2 | trans1($op, $time = 0.2s) 3 | transition: $op $time ease-out 4 | 5 | // 为2个属性设置动画 6 | trans2($op1, $op2) 7 | transition: $op1 0.2s ease-out, $op2 0.2s ease-out 8 | 9 | trans2pro($op1, $t1, $op2, $t2) 10 | transition: $op1 $t1 ease-out, $op2 $t2 ease-out 11 | 12 | trans3($op1, $op2, $op3) 13 | transition: $op1 0.2s ease-out, $op2 0.2s ease-out, $op3 0.2s ease-out 14 | 15 | trans($time = 0.28s) 16 | transition: all $time ease 17 | 18 | hoverable-card() 19 | trans() 20 | &:hover 21 | box-shadow: 0 0 4px rgba(0,0,0,.1), 0 0 8px rgba(0,0,0,.08) 22 | 23 | txt-ellipsis() 24 | white-space: nowrap 25 | overflow: hidden 26 | text-overflow: ellipsis 27 | 28 | placeholder(rules) 29 | &::-webkit-input-placeholder 30 | rules() 31 | &:-moz-placeholder 32 | rules() 33 | &::-moz-placeholder 34 | rules() 35 | &:-ms-input-placeholder 36 | rules() 37 | 38 | disable-user-select() 39 | user-select: none 40 | 41 | scrollbar($w = 4px, $b = 2px, $c = $color-theme, $h = $color-hover) 42 | &::-webkit-scrollbar 43 | height: $w 44 | width: $w 45 | &::-webkit-scrollbar-track-piece 46 | background: transparent 47 | &::-webkit-scrollbar-thumb 48 | background: $c 49 | cursor: pointer 50 | border-radius: $b 51 | &:hover 52 | background: $h 53 | 54 | 55 | scrollbar-codeblock() 56 | &::-webkit-scrollbar 57 | height: 4px 58 | width: 4px 59 | &::-webkit-scrollbar-track-piece 60 | background: transparent 61 | &::-webkit-scrollbar-thumb 62 | background: transparent 63 | cursor: pointer 64 | border-radius: $border-codeblock 65 | &:hover 66 | &::-webkit-scrollbar-thumb 67 | background: alpha($color-text, .5) 68 | &:hover 69 | background: $color-hover 70 | -------------------------------------------------------------------------------- /source/css/_defines/layout.styl: -------------------------------------------------------------------------------- 1 | // device defines 2 | $device-mobile-s = 320px 3 | $device-mobile-m = 375px 4 | $device-mobile-l = 425px 5 | $device-mobile = 500px 6 | $device-tablet = 768px 7 | $device-laptop = 1024px 8 | $device-desktop = 1440px 9 | $device-2k = 2048px 10 | $device-4k = 2560px 11 | 12 | 13 | // site layout 14 | $layout-width = convert(hexo-config('custom_css.max_width')) || 1080px 15 | $sidebar = 240px 16 | $modal-threshold = 680px 17 | $navbar-height = convert(hexo-config('custom_css.navbar.height')) || 64px 18 | 19 | // gap 20 | $gap = convert(hexo-config('custom_css.gap.base')) || 16px // base gap 21 | $gap-h2 = convert(hexo-config('custom_css.gap.h2')) || 48px 22 | $gap-h3 = convert(hexo-config('custom_css.gap.h3')) || 32px 23 | $gap-h4 = convert(hexo-config('custom_css.gap.h4')) || 16px 24 | // 新的段落间距,以实际字体大小为基准 25 | $gap-p = convert(hexo-config('custom_css.gap.p')) || 1em 26 | 27 | 28 | 29 | // border width 30 | $border-line = 2px 31 | 32 | // border radius 33 | $border-card = convert(hexo-config('custom_css.border_radius.card')) || 12px 34 | $border-codeblock = convert(hexo-config('custom_css.border_radius.codeblock')) || 4px 35 | $border-searchbar = convert(hexo-config('custom_css.border_radius.searchbar')) || 8px 36 | $border-button = convert(hexo-config('custom_css.border_radius.button')) || 2px 37 | 38 | // text align 39 | $textalign-h1 = convert(hexo-config('custom_css.body.text_align.h1')) || left 40 | $textalign-h2 = convert(hexo-config('custom_css.body.text_align.h2')) || left 41 | $textalign-h3 = convert(hexo-config('custom_css.body.text_align.h3')) || left 42 | $textalign-h4 = convert(hexo-config('custom_css.body.text_align.h4')) || left 43 | $textalign-p = convert(hexo-config('custom_css.body.text_align.p')) || justify 44 | -------------------------------------------------------------------------------- /source/css/_first/fontfamily_first.styl: -------------------------------------------------------------------------------- 1 | if hexo-config('custom_css.fontfamily.bodyfont') 2 | if hexo-config('custom_css.fontfamily.bodyfont.name') 3 | @font-face 4 | font-family: hexo-config('custom_css.fontfamily.bodyfont.name') 5 | src: url(hexo-config('custom_css.fontfamily.bodyfont.url')) 6 | font-weight: hexo-config('custom_css.fontfamily.bodyfont.weight') 7 | font-style: hexo-config('custom_css.fontfamily.bodyfont.style') 8 | font-display: swap 9 | 10 | if hexo-config('custom_css.fontfamily.logofont') 11 | if hexo-config('custom_css.fontfamily.logofont.name') 12 | @font-face 13 | font-family: hexo-config('custom_css.fontfamily.logofont.name') 14 | src: url(hexo-config('custom_css.fontfamily.logofont.url')) 15 | font-weight: hexo-config('custom_css.fontfamily.logofont.weight') 16 | font-style: hexo-config('custom_css.fontfamily.logofont.style') 17 | font-display: swap -------------------------------------------------------------------------------- /source/css/_first/search_first.styl: -------------------------------------------------------------------------------- 1 | #u-search 2 | $border-card = 4px 3 | display: none 4 | position: fixed 5 | top: 0 6 | left: 0 7 | width: 100% 8 | height: 100% 9 | padding: 60px 20px 10 | z-index: 1001 11 | @media screen and (max-width: $modal-threshold) 12 | padding: 0px 13 | -------------------------------------------------------------------------------- /source/css/_style/_base/fontfamily_async.styl: -------------------------------------------------------------------------------- 1 | if hexo-config('custom_css.fontfamily.codefont') 2 | if hexo-config('custom_css.fontfamily.codefont.name') 3 | @font-face 4 | font-family: hexo-config('custom_css.fontfamily.codefont.name') 5 | src: url(hexo-config('custom_css.fontfamily.codefont.url')) 6 | font-weight: hexo-config('custom_css.fontfamily.codefont.weight') 7 | font-style: hexo-config('custom_css.fontfamily.codefont.style') 8 | font-display: swap 9 | -------------------------------------------------------------------------------- /source/css/_style/_layout/footer.styl: -------------------------------------------------------------------------------- 1 | footer.footer 2 | position: relative 3 | padding: 40px 10px 120px 10px 4 | width: 100% 5 | color: var(--color-site-footer) 6 | margin: 0px auto 7 | &,p 8 | font-size: $fontsize-code 9 | overflow: hidden 10 | text-align: center 11 | .licenses 12 | color: fade(@color_text_main, 50%) 13 | .social-wrapper 14 | display: flex 15 | justify-content: center 16 | flex-wrap: wrap 17 | margin: 4px $gap * 0.5 18 | 19 | a 20 | color: var(--color-site-footer) 21 | padding: 0 22 | trans() 23 | &:hover 24 | color: $color-hover 25 | &:not(.social):hover 26 | text-decoration: underline 27 | &.social 28 | position: relative 29 | display: inline-block 30 | text-align: center 31 | display: flex 32 | justify-content: center 33 | align-items: center 34 | min-width: 36px 35 | min-height: 36px 36 | margin: 4px 37 | opacity: .75 38 | border-radius: 4px 39 | font-size: 1rem 40 | img 41 | margin: 8px 42 | height: 24px 43 | &:hover 44 | color: $color-hover 45 | background: alpha(@color, 0.1) 46 | 47 | 48 | 49 | .copyright 50 | margin-top: $gap 51 | p 52 | font-size: $fontsize-footnote 53 | 54 | @media screen and (max-width: $device-tablet) 55 | justify-content: center 56 | -------------------------------------------------------------------------------- /source/css/_style/_layout/friends-simpleuser.styl: -------------------------------------------------------------------------------- 1 | // layout/friends.ejs 2 | if hexo-config('pages.friends.layout_scheme') != 'traditional' 3 | .md .simpleuser-group 4 | margin: 0 5 | display: grid 6 | grid-template-columns: repeat(auto-fill, 112px) 7 | .md .simpleuser 8 | text-align: center 9 | padding: 1em .5em 10 | border-radius: 4px 11 | img 12 | display: block 13 | width: 50px 14 | height 50px 15 | border-radius: 50px 16 | object-fit: cover 17 | img+span 18 | display: block 19 | font-size: $fontsize-meta 20 | line-height: 1.2 21 | color: var(--color-text) 22 | &:hover 23 | background: var(--color-site-bg) 24 | -------------------------------------------------------------------------------- /source/css/_style/_layout/img.styl: -------------------------------------------------------------------------------- 1 | .md 2 | img 3 | position: relative 4 | trans() 5 | @media screen and (max-width: $device-mobile) 6 | box-shadow: none 7 | div>img,p>img 8 | display: block 9 | margin: auto 10 | border-radius: 4px 11 | @media screen and (max-width: $device-mobile) 12 | border-radius: 2px 13 | span 14 | img 15 | display: inline 16 | margin: auto 17 | 18 | 19 | // image 20 | .md .img-wrap 21 | margin: 1.5rem auto 22 | text-align: center 23 | border-radius: 2px 24 | overflow: hidden 25 | .img-bg 26 | width: 100% 27 | .image-caption 28 | display: block 29 | margin: .75rem auto 30 | font-size: $fontsize-code 31 | color: var(--color-meta) 32 | &:empty 33 | display: none 34 | -------------------------------------------------------------------------------- /source/css/_style/_layout/loading.styl: -------------------------------------------------------------------------------- 1 | svg.loading 2 | display: block 3 | position: absolute 4 | color: var(--text-p3) 5 | width: 100% 6 | height: 2rem 7 | margin: auto 8 | animation: spin infinite 2s 9 | animation-timing-function: linear 10 | @keyframes spin 11 | from 12 | transform:rotate(0deg) 13 | to 14 | transform:rotate(360deg) 15 | -------------------------------------------------------------------------------- /source/css/_style/_layout/md.styl: -------------------------------------------------------------------------------- 1 | // 以后关于 md 渲染方面的都写到这里 2 | .md 3 | >p 4 | padding-top: 4px 5 | h1,h2,h3,h4,h5,h6 6 | position: relative 7 | pointer-events: none 8 | margin-top: 0 9 | font-weight: 500 10 | >a 11 | color: inherit 12 | pointer-events: auto 13 | &:hover 14 | color: $color-hover 15 | &:before 16 | content: '' 17 | display: block 18 | margin-top: 0 - $navbar-height + $gap 19 | height: $navbar-height + $gap * 2 20 | visibility: hidden 21 | pointer-events: none 22 | h1,h2 23 | &:before 24 | margin-top: $gap-h2 - $navbar-height - $gap * 1 25 | .article-meta+h1,.article-meta+h2 26 | margin-top: $gap-h2 - $navbar-height - $gap * 4 27 | h3,h4,h5,h6 28 | margin-bottom: $gap-p 29 | h3 30 | &:before 31 | margin-top: $gap-h3 - $navbar-height - $gap 32 | h4 33 | &:before 34 | margin-top: $gap-h4 - $navbar-height - $gap 35 | h5 36 | font-weight: bold 37 | h2+h3:before 38 | margin-top: $gap-h2 - $navbar-height - $gap * 4 39 | ul,ol 40 | font-size: $fontsize-list 41 | list-style: initial 42 | padding-left: 8px 43 | margin-left: $gap 44 | margin-top: $gap-p 45 | margin-bottom: $gap-p 46 | ul,ol 47 | margin-top: 0 48 | margin-bottom: 0 49 | li 50 | margin-top: 0px 51 | margin-bottom: 0px 52 | li 53 | margin-top: 0 54 | margin-bottom: 0 55 | p 56 | margin-top: 4px 57 | margin-bottom: 0 58 | &.task-list 59 | padding-left: 0 60 | margin-left: 4px 61 | li 62 | list-style: none 63 | input 64 | margin-right: 4px 65 | 66 | 67 | ul>li 68 | list-style: initial 69 | ol>li 70 | list-style: decimal 71 | 72 | .div-ori-link 73 | display: block 74 | text-align: center 75 | margin: 4rem 0 76 | .ori-link 77 | margin: auto 78 | padding: 1em 3em 79 | border: 1px solid $color-theme 80 | border-radius: $border-button 81 | color: $color-theme 82 | font-weight: 500 83 | &:hover 84 | color: $color-hover 85 | border-color: $color-hover 86 | -------------------------------------------------------------------------------- /source/css/_style/_layout/pagination.styl: -------------------------------------------------------------------------------- 1 | #l_main 2 | .prev-next 3 | width: 100% 4 | display: flex 5 | justify-content: space-between 6 | align-items: baseline 7 | color: var(--color-meta) 8 | margin: 0 9 | font-weight: 600 10 | .prev 11 | text-align: left 12 | border-top-right-radius: 32px 13 | border-bottom-right-radius: 32px 14 | 15 | .next 16 | text-align: right 17 | border-top-left-radius: 32px 18 | border-bottom-left-radius: 32px 19 | 20 | p 21 | margin: $gap 22 | 23 | section 24 | color: var(--color-meta) 25 | padding: $gap 26 | border-radius: $border-card 27 | &:hover 28 | color: $color-hover 29 | 30 | 31 | // 文章中 32 | .article 33 | .prev-next 34 | width: 100% 35 | display: flex 36 | justify-content: space-between 37 | align-content: flex-start 38 | margin-top: $gap * 0.5 39 | >a 40 | width: 100% 41 | padding: $gap * 0.5 42 | color: var(--color-meta) 43 | background: var(--color-block) 44 | border-radius: $border-codeblock 45 | &:hover 46 | background: bgcolor($color-hover) 47 | p.title 48 | color: $color-hover 49 | p 50 | margin: $gap * 0.5 .5rem 51 | p.title 52 | font-weight: 600 53 | font-size: $fontsize-h5 54 | >i 55 | width: 1rem 56 | p.content 57 | font-size: $fontsize-meta 58 | font-weight: 400 59 | text-align: justify 60 | word-break: break-all 61 | &:only-child 62 | margin-left: 0 63 | margin-right: 0 64 | .prev 65 | p.title 66 | text-align: left 67 | margin-left: 0 68 | margin-right: $gap * 0.5 69 | 70 | .next 71 | p.title 72 | text-align: right 73 | margin-left: $gap * 0.5 74 | margin-right: 0 75 | -------------------------------------------------------------------------------- /source/css/_style/_layout/snackbar.styl: -------------------------------------------------------------------------------- 1 | .snackbar-wrap 2 | position: fixed 3 | width: 100% 4 | left: 0 5 | bottom: 0 6 | background: $color-theme 7 | padding: $gap 8 | z-index: 2 9 | 10 | .snackbar-content 11 | max-width: $layout-width 12 | margin: $gap auto 13 | @media screen and (max-width: $layout-width) 14 | max-width: 100% 15 | 16 | .snackbar-content 17 | p 18 | margin-top: .5rem 19 | margin-bottom: .5rem 20 | color: $color-inner 21 | .title 22 | font-size: $fontsize-h2 23 | font-weight: 600 24 | .action 25 | display: block 26 | margin: 1.5rem 0 - $gap * 0.25 27 | a 28 | margin: $gap * 0.25 29 | cursor: pointer 30 | color: $color-inner 31 | display: inline-block 32 | padding: .4em 2em 33 | font-weight: 600 34 | border-radius: 2px 35 | border: 1px solid $color-inner 36 | &:hover 37 | color: $color-theme 38 | background: $color-inner 39 | 40 | .snackbar-wrap 41 | &[theme='warning'] 42 | background: #F7E751 43 | .snackbar-content 44 | p 45 | color: black 46 | a 47 | color: black 48 | border-color: black 49 | &:hover 50 | color: #F7E751 51 | background: black 52 | -------------------------------------------------------------------------------- /source/css/_style/_layout/video.styl: -------------------------------------------------------------------------------- 1 | .md .video-wrap 2 | margin: 1.5rem auto 3 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/_dark/dark_async.styl: -------------------------------------------------------------------------------- 1 | // 异步加载的暗黑模式 暗黑模式 CSS 变量 2 | 3 | async_dark() 4 | // tag plugin from stellar 5 | --block-hover: mix($c-block-dark, $c-text-dark, 95) 6 | --text-p1: $c-text-dark 7 | --text-p3: mix($c-text-light, $c-site-bg-light, 60) 8 | --card: $c-card-light 9 | 10 | // waline Dark Color https://github.com/volantis-x/hexo-theme-volantis/issues/633 11 | if hexo-config('comments.service')=='waline' 12 | --waline-white: #000 !important 13 | --waline-light-grey: #666 !important 14 | --waline-dark-grey: #999 !important 15 | --waline-text-color: #888 !important 16 | --waline-bg-color: #1e1e1e !important 17 | --waline-bg-color-light: #272727 !important 18 | --waline-border-color: #333 !important 19 | --waline-disable-bgcolor: #444 !important 20 | --waline-disable-color: #272727 !important 21 | --waline-bq-color: #272727 !important 22 | --waline-info-bgcolor: #272727 !important 23 | --waline-info-color: #666 !important 24 | 25 | 26 | // Custom Files 27 | for $injects_darkVar in hexo-config('injects.darkVar') 28 | @import $injects_darkVar; 29 | // eg: 30 | // body 31 | // --color-site-body: blue !important 32 | 33 | @media (prefers-color-scheme: dark) 34 | :root 35 | --color-mode: 'dark' 36 | :root:not([color-scheme]) 37 | async_dark() 38 | @import 'dark_plugins' 39 | [color-scheme='dark'] 40 | async_dark() 41 | @import 'dark_plugins' 42 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/_highlight/highlightjs/clipboard.styl: -------------------------------------------------------------------------------- 1 | //代码块复制按钮 2 | .highlight 3 | //方便copy代码按钮(btn-copy)的定位 4 | position: relative 5 | 6 | .btn-copy 7 | z-index: 1 8 | display: inline-block 9 | cursor: pointer 10 | border: none 11 | disable-user-select() 12 | -webkit-appearance: none 13 | font-family: Menlo, $fontfamily-code 14 | font-size: 11px 15 | font-weight: bold 16 | padding: $gap * 0.25 $gap * 0.5 17 | >i 18 | margin-right: 4px 19 | color: var(--color-meta) 20 | background: var(--color-block) 21 | border-radius: 3px 22 | box-shadow: $boxshadow-card 23 | position: absolute 24 | top: 1px 25 | right: 1px 26 | opacity: 0 27 | trans() 28 | &:hover 29 | color: $color-hover 30 | background: bgcolor($color-hover) 31 | 32 | .highlight:hover .btn-copy 33 | opacity: 1 34 | 35 | .article pre:hover .btn-copy 36 | opacity: 1 37 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/_highlight/highlightjs/language.styl: -------------------------------------------------------------------------------- 1 | if hexo-config('custom_css.body.highlight.language') == true 2 | .hljs,.highlight 3 | &:before 4 | position: absolute 5 | top: 0 6 | right: 0 7 | color: var(--color-meta) 8 | font-size: 13px 9 | padding: 4px 8px 10 | &.md:before,&.markdown:before 11 | content: "md" 12 | &.yaml:before 13 | content: "YAML" 14 | &.json:before 15 | content: "JSON" 16 | 17 | &.html:before 18 | content: "HTML" 19 | &.js:before,&.javascript:before 20 | content: "JS" 21 | &.css:before 22 | content: "CSS" 23 | &.less:before 24 | content: "Less" 25 | &.stylus:before 26 | content: "Stylus" 27 | 28 | &.bash:before 29 | content: "bash" 30 | &.shell:before 31 | content: "shell" 32 | &.sh:before 33 | content: "sh" 34 | &.ini:before 35 | content: "ini" 36 | 37 | &.c:before 38 | content: "C" 39 | &.cpp:before 40 | content: "C++" 41 | &.objc:before,&.objectivec:before 42 | content: "Objective-C" 43 | &.swift:before 44 | content: "Swift" 45 | 46 | &.java:before 47 | content: "Java" 48 | &.python:before 49 | content: "Python" 50 | &.php:before 51 | content: "PHP" 52 | &.rust:before 53 | content: "Rust" 54 | &.sql:before 55 | content: "SQL" 56 | &.ruby:before 57 | content: "Ruby" 58 | &.makefile:before 59 | content: "Makefile" 60 | &.go:before 61 | content: "Go" 62 | &.typescript:before 63 | content: "TypeScript" -------------------------------------------------------------------------------- /source/css/_style/_plugins/_highlight/index.styl: -------------------------------------------------------------------------------- 1 | @import hexo-config('plugins.code_highlight') 2 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/_highlight/prismjs/clipboard.styl: -------------------------------------------------------------------------------- 1 | //代码块复制按钮 2 | .code-toolbar 3 | //方便copy代码按钮(btn-copy)的定位 4 | position: relative 5 | 6 | .btn-copy 7 | z-index: 1 8 | display: inline-block 9 | cursor: pointer 10 | border: none 11 | disable-user-select() 12 | -webkit-appearance: none 13 | font-family: Menlo, $fontfamily-code 14 | font-size: 11px 15 | font-weight: bold 16 | padding: $gap * 0.25 $gap * 0.5 17 | >i 18 | margin-right: 4px 19 | color: var(--color-meta) 20 | background: var(--color-card) 21 | border-radius: 3px 22 | box-shadow: $boxshadow-card 23 | position: absolute 24 | top: 5px 25 | right: 5px 26 | opacity: 0 27 | trans() 28 | &:hover 29 | color: $color-hover 30 | background: bgcolor($color-hover) 31 | 32 | .code-toolbar:hover .btn-copy 33 | opacity: 1 -------------------------------------------------------------------------------- /source/css/_style/_plugins/_highlight/prismjs/index.styl: -------------------------------------------------------------------------------- 1 | @import 'clipboard' 2 | @import 'language' 3 | 4 | pre 5 | position: relative 6 | -webkit-font-smoothing: auto 7 | -moz-osx-font-smoothing: auto 8 | scrollbar() 9 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/_highlight/prismjs/language.styl: -------------------------------------------------------------------------------- 1 | if hexo-config('custom_css.body.highlight.language') == true 2 | pre 3 | &:before 4 | position: absolute 5 | top: 0 6 | right: 0 7 | color: var(--color-meta) 8 | font-size: 13px 9 | padding: 4px 8px 10 | &.language-md:before,&.markdown:before 11 | content: "md" 12 | &.language-yaml:before 13 | content: "YAML" 14 | &.language-json:before 15 | content: "JSON" 16 | 17 | &.language-html:before 18 | content: "HTML" 19 | &.language-js:before,&.language-javascript:before 20 | content: "JS" 21 | &.language-css:before 22 | content: "CSS" 23 | &.language-less:before 24 | content: "Less" 25 | &.language-stylus:before 26 | content: "Stylus" 27 | 28 | &.language-bash:before 29 | content: "bash" 30 | &.language-shell:before 31 | content: "shell" 32 | &.language-sh:before 33 | content: "sh" 34 | &.language-ini:before 35 | content: "ini" 36 | 37 | &.language-c:before 38 | content: "C" 39 | &.language-cpp:before 40 | content: "C++" 41 | &.language-objc:before,&.language-objectivec:before 42 | content: "Objective-C" 43 | &.language-swift:before 44 | content: "Swift" 45 | 46 | &.language-java:before 47 | content: "Java" 48 | &.language-python:before 49 | content: "Python" 50 | &.language-php:before 51 | content: "PHP" 52 | &.language-rust:before 53 | content: "Rust" 54 | &.language-sql:before 55 | content: "SQL" 56 | &.language-ruby:before 57 | content: "Ruby" 58 | &.language-makefile:before 59 | content: "Makefile" 60 | &.language-go:before 61 | content: "Go" 62 | &.language-typescript:before 63 | content: "TypeScript" 64 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/_rightmenu/reading.styl: -------------------------------------------------------------------------------- 1 | .common_read 2 | z-index: auto !important 3 | opacity: 1 !important 4 | overflow: visible !important 5 | transform: none !important 6 | animation: none !important 7 | position: relative !important 8 | 9 | .body-wrapper.common_read 10 | display: block 11 | 12 | #safearea.common_read 13 | padding-bottom: 16px 14 | @media screen and (max-width: 900px) 15 | padding: 0 16 | margin: 0 17 | 18 | #l_body.common_read 19 | z-index: 2147483646 !important; 20 | 21 | .read_cover 22 | min-height: 10px !important 23 | @media screen and (max-width: 900px) 24 | min-height: 0 !important 25 | 26 | .common_read_bkg 27 | background-color: var(--color-read-bkg) !important 28 | opacity: 1 !important 29 | display: block !important 30 | position: fixed !important 31 | top: 0 !important 32 | left: 0 !important 33 | right: 0 !important 34 | bottom: 0 !important 35 | z-index: 2147483645 !important 36 | transition: opacity 1s cubic-bezier(.23,1,.32,1) 0ms !important 37 | 38 | .common_read_hide 39 | opacity: 0 !important 40 | z-index: -2147483645 !important 41 | 42 | .common_read_main 43 | width: 840px !important; 44 | padding: 0 !important; 45 | margin: 0 auto; 46 | float: initial !important; 47 | @media screen and (max-width: 900px) 48 | width: auto !important; 49 | 50 | .post_read 51 | background-color: var(--color-read-post) !important 52 | z-index: 2147483646 !important 53 | overflow: visible !important 54 | font-size: 1.15rem !important 55 | border-radius: 0 !important; 56 | box-shadow: 0 6px 12px 3px #00000033 -------------------------------------------------------------------------------- /source/css/_style/_plugins/aplayer.styl: -------------------------------------------------------------------------------- 1 | @media screen and (max-width: $device-mobile) 2 | .l_header 3 | .list-v 4 | .aplayer,.aplayer-pic 5 | border-radius: $border-card * 0.5 6 | width: 64px 7 | height: 64px 8 | 9 | .aplayer-container 10 | display: flex 11 | justify-content: center 12 | min-height: 100px 13 | meting-js 14 | max-width: 100% 15 | 16 | 17 | .aplayer 18 | max-width: 500px 19 | border-radius: 4px 20 | color: var(--color-text) 21 | font-family: $fontfamily 22 | .aplayer-list 23 | text-align: left 24 | @media screen and (max-width: $device-mobile) 25 | border-radius: $border-card 26 | 27 | .l_header 28 | .aplayer-volume-wrap 29 | display: none !important // 隐藏导航栏播放器音量调节 see: https://github.com/volantis-x/hexo-theme-volantis/issues/328 30 | 31 | 32 | if hexo-config('plugins.aplayer.autoHide') 33 | .aplayer.aplayer-fixed.aplayer-narrow .aplayer-body 34 | left: -66px !important 35 | &:hover 36 | left: 0px !important 37 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/fancybox.styl: -------------------------------------------------------------------------------- 1 | .fancybox__container 2 | padding 10px !important 3 | .fancybox__slide 4 | padding 2.5rem !important 5 | .f-button 6 | &:first-child 7 | border-radius 12px 0 0 12px 8 | &:last-child 9 | border-radius 0 12px 12px 0 10 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/fontcolor.styl: -------------------------------------------------------------------------------- 1 | // Icon 颜色 2 | // https://flatuicolors.com/palette/defo 3 | .fa, 4 | .fas, 5 | .far, 6 | .fad, 7 | .fal, 8 | .fa-solid, 9 | .fa-regular, 10 | .fa-duotone, 11 | .fa-light, 12 | .fa-thin, 13 | // 图标颜色自定义 14 | .iziToast>.iziToast-body .iziToast-icon 15 | &.red 16 | color: $color-md-red 17 | &.pink 18 | color: $color-md-pink 19 | &.purple 20 | color: $color-md-purple 21 | &.indigo 22 | color: $color-md-indigo 23 | &.light-blue 24 | color: $color-md-light-blue 25 | &.deep-blue 26 | color: $color-md-deep-blue 27 | &.teal 28 | color: $color-md-teal 29 | &.light-green 30 | color: $color-md-light-green 31 | &.orange 32 | color: $color-md-orange 33 | &.deep-orange 34 | color: $color-md-deep-orange 35 | &.brown 36 | color: $color-md-brown 37 | &.blue-grey 38 | color: $color-md-blue-grey 39 | &.yellow 40 | color: $color-md-yellow 41 | 42 | &.TURQUOISE 43 | color: #1abc9c 44 | &.EMERALD 45 | color: #2ecc71 46 | &.PETERRIVE 47 | color: #3498db 48 | &.AMETHYST 49 | color: #9b59b6 50 | &.WETASPHALT 51 | color: #34495e 52 | 53 | &.GREENSEA 54 | color: #16a085 55 | &.NEPHRITIS 56 | color: #27ae60 57 | &.BELIZEHOLE 58 | color: #2980b9 59 | &.WISTERIA 60 | color: #8e44ad 61 | &.MIDNIGHTBLUE 62 | color: #2c3e50 63 | 64 | &.SUNFLOWER 65 | color: #f1c40f 66 | &.CARROT 67 | color: #e67e22 68 | &.ALIZARIN 69 | color: #e74c3c 70 | &.CLOUDS 71 | color: #ecf0f1 72 | &.CONCRETE 73 | color: #95a5a6 74 | 75 | &.ORANGE 76 | color: #f39c12 77 | &.PUMPKIN 78 | color: #d35400 79 | &.POMEGRANATE 80 | color: #c0392b 81 | &.SILVER 82 | color: #bdc3c7 83 | &.ASBESTOS 84 | color: #7f8c8d -------------------------------------------------------------------------------- /source/css/_style/_plugins/index.styl: -------------------------------------------------------------------------------- 1 | @import 'mathjax' 2 | @import 'fontcolor' 3 | 4 | 5 | if hexo-config('plugins.code_highlight') 6 | @import '_highlight' 7 | if hexo-config('plugins.message.enable') 8 | @import 'message' 9 | if hexo-config('plugins.aplayer.enable') 10 | @import 'aplayer' 11 | if hexo-config('plugins.tianliGPT.enable') 12 | @import 'tianliGPT' 13 | if hexo-config('comments.service')=='gitalk' 14 | @import 'gitalk' 15 | if hexo-config('custom_css.cursor.enable') 16 | @import 'cursor' 17 | if hexo-config('rightmenus.enable') 18 | @import '_rightmenu/*' 19 | 20 | @import 'fancybox' 21 | 22 | // 暗黑模式样式放到最后加载 23 | if hexo-config('plugins.darkmode.enable') 24 | @import '_dark/dark_async' -------------------------------------------------------------------------------- /source/css/_style/_plugins/mathjax.styl: -------------------------------------------------------------------------------- 1 | .article 2 | mjx-container 3 | font-family: $fontfamily-code 4 | padding: $gap $gap * 0.5 5 | border-radius: $border-codeblock 6 | min-width: 0 !important 7 | mjx-container[jax="CHTML"][display="true"], .has-jax 8 | overflow: auto hidden 9 | mjx-container + br 10 | display: none 11 | -------------------------------------------------------------------------------- /source/css/_style/_plugins/message.styl: -------------------------------------------------------------------------------- 1 | // 覆盖消息提示的样式 2 | //.iziToast-wrapper 3 | // z-index: 2147483647 !important 4 | .iziToast-texts 5 | max-width: 300px !important 6 | min-width: 200px !important 7 | @media screen and (max-width: 500px) 8 | max-width: unset !important 9 | min-width: unset !important 10 | .iziToast-title 11 | margin-bottom: 6px !important 12 | font-size: 1rem !important 13 | .iziToast-message 14 | word-break: break-all !important 15 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/Readme.md: -------------------------------------------------------------------------------- 1 | 这里存放 tag 标签 的样式 2 | 3 | 为便于管理样式, 文件名使用 tag 名称命名 4 | 5 | tag.json 索引 tag 标签名称和使用的样式文件的对应关系 6 | 7 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/dropmenu.styl: -------------------------------------------------------------------------------- 1 | div.dropmenu-wrapper 2 | display: inline-block 3 | 4 | div.dropmenu 5 | position: relative 6 | display: inline-block 7 | trans() 8 | color: $color-link 9 | &:hover 10 | color: inherit 11 | >ul 12 | display: block 13 | left: 0 14 | margin-left: 0 15 | margin-top: 0px 16 | ul>li 17 | list-style: none 18 | >a 19 | &:hover 20 | text-decoration: none !important 21 | .list-v .list-v 22 | left: "calc(100% - 0.5 * %s)" % $gap 23 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/frame.styl: -------------------------------------------------------------------------------- 1 | .md .frame-wrap 2 | position: relative 3 | overflow: hidden 4 | margin: 0 auto 5 | max-width: 100% 6 | display: flex 7 | flex-direction: column 8 | align-items: center 9 | img,video 10 | border-radius: 0 11 | .md .frame-wrap .frame 12 | z-index: 1 13 | display: block 14 | position: absolute; 15 | background-size: 100%; 16 | background-repeat: no-repeat; 17 | overflow: hidden; 18 | 19 | .md .img-wrap .frame-wrap 20 | &[part] 21 | height: auto 22 | 23 | .md .frame-wrap 24 | &#iphone11 25 | img,video 26 | width: 287px 27 | margin-top: 19px 28 | margin-bottom: 20px 29 | .frame 30 | background-image: url(https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@3/img/frame/iphone11.svg); 31 | width: 329px 32 | height: 658px 33 | &[part='top'] 34 | img,video 35 | margin-bottom: 0 !important 36 | &:not([part='bottom']) 37 | .frame 38 | top: 0 39 | &[part='bottom'] 40 | img,video 41 | bottom: 0 42 | margin-top: 0 !important 43 | .frame 44 | bottom: 0 45 | 46 | @media screen and (max-width: $device-mobile) 47 | .md .frame-wrap 48 | &#iphone11 49 | img,video 50 | width: 208px 51 | margin-top: 13px 52 | margin-bottom: 14px 53 | .frame 54 | width: 238px 55 | height: 476px 56 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/friends.styl: -------------------------------------------------------------------------------- 1 | .users-wrap 2 | overflow: hidden 3 | .group-header 4 | margin: 0 0 1rem 5 | p 6 | margin: 0 7 | font-size: $fs-14 8 | &:first-child 9 | font-size: 1.25rem 10 | font-weight: 500 11 | .group-body 12 | width: 100% 13 | display: flex 14 | flex-wrap: wrap 15 | align-items: stretch 16 | margin-bottom: 2rem 17 | .friendsjs-wrap 18 | display: block 19 | .loading-wrap 20 | min-height: 50px 21 | margin: 2rem 0 22 | text-align: center 23 | 24 | .users-wrap .user-card 25 | flex-shrink: 1 26 | display: flex 27 | align-items: stretch 28 | width: 12.5% 29 | @media screen and (max-width: 980px) 30 | width: 14.28% 31 | @media screen and (max-width: 900px) 32 | width: 16.66% 33 | @media screen and (max-width: 820px) 34 | width: 20% 35 | @media screen and (max-width: $device-tablet) 36 | width: 16.66% 37 | @media screen and (max-width: $device-mobile) 38 | width: 25% 39 | .card-link 40 | margin: 0 41 | width: 100% 42 | color: var(--text-p1) 43 | font-size: 10px 44 | font-weight: 500 45 | display: flex 46 | justify-content: flex-start 47 | flex-direction: column 48 | align-items: center 49 | text-align: center 50 | line-height: 1.2 51 | border-radius: 4px 52 | overflow: hidden 53 | position: relative 54 | padding: 1rem 0.5rem 55 | img 56 | object-fit: cover 57 | display: block 58 | width: 48px 59 | height: 48px 60 | background: var(--card) 61 | border-radius: 64px 62 | margin: 0 0 0.5rem 63 | 64 | // transform 65 | .users-wrap .user-card .card-link 66 | >img 67 | trans2 transform box-shadow 68 | &:hover 69 | background: var(--block-hover) 70 | img 71 | transform: scale(1.2) rotate(8deg) 72 | box-shadow: $boxshadow-card-float 73 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/ghcard.styl: -------------------------------------------------------------------------------- 1 | a.ghcard 2 | display: inline-block 3 | line-height: 0 4 | 5 | .md .ghcard-group 6 | column-count: 2 7 | column-gap: 0 8 | margin: 0 0 - $gap * 0.5 9 | .ghcard 10 | margin: $gap * 0.5 11 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/image.styl: -------------------------------------------------------------------------------- 1 | .md .img 2 | object-fit: contain 3 | 4 | img.inline 5 | display: inline !important 6 | vertical-align: middle 7 | transform: translateY(-4px) 8 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/link.styl: -------------------------------------------------------------------------------- 1 | .md .tag.link 2 | margin-top: $gap-p 3 | margin-bottom: $gap-p 4 | 5 | .md .link-card 6 | margin-right: $gap-p 7 | background: var(--color-block) 8 | display: inline-flex 9 | align-items: center 10 | cursor: pointer 11 | text-align: center 12 | width: $device-mobile-l - 4 * $gap 13 | max-width: 100% 14 | box-shadow: $boxshadow-card 15 | @media screen and (max-width: $device-mobile-l) 16 | max-width: 100% 17 | width: 100% 18 | color: var(--color-p) 19 | border-radius: $border-card 20 | &:hover 21 | box-shadow: $boxshadow-float, $boxshadow-card-float 22 | 23 | 24 | .md .link-card 25 | div.left,div.right 26 | pointer-events: none 27 | div.left 28 | width: 54px 29 | height: 54px 30 | margin: 12px 31 | overflow: hidden 32 | flex-shrink: 0 33 | position: relative 34 | i 35 | font-size: 32px 36 | line-height: 48px 37 | margin-left: 4px 38 | img 39 | display: block 40 | position: absolute 41 | border-radius: $border-card / 4 42 | top: 50% 43 | left: 50% 44 | transform: translate(-50%, -50%) 45 | div.right 46 | overflow: hidden 47 | margin-right: 16px 48 | p 49 | margin: 0 50 | txt-ellipsis() 51 | p.text 52 | font-weight: bold 53 | p.url 54 | flex-shrink: 0 55 | color: var(--color-meta) 56 | font-size: $fontsize-code 57 | 58 | .md .link-group 59 | display: grid 60 | grid-template-columns: 1fr 1fr 61 | @media screen and (max-width: $device-mobile-l * 2) 62 | grid-template-columns: 1fr 63 | grid-gap: $gap 64 | .tag.link 65 | margin: 0 66 | .link-card 67 | width: 100% 68 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/media.styl: -------------------------------------------------------------------------------- 1 | $sp = 4px 2 | 3 | audio,video 4 | border-radius: $border-codeblock 5 | max-width: 100% 6 | video 7 | z-index: 1 8 | trans() 9 | &:hover 10 | box-shadow: 0 4px 8px 0px rgba(0, 0, 0, 0.24), 0 8px 16px 0px rgba(0, 0, 0, 0.24) 11 | 12 | div.video 13 | line-height: 0 14 | text-align: center 15 | 16 | div.videos 17 | max-width: "calc(100% + 2 * %s)" % $sp 18 | display: flex 19 | flex-wrap: wrap 20 | justify-content: flex-start 21 | align-items: flex-end 22 | margin: $gap-p 0 - $sp 23 | .video,iframe 24 | width: 100% 25 | margin: $sp 26 | 27 | iframe 28 | border-radius: $border-codeblock 29 | width: 100% 30 | min-height: 300px 31 | &.left 32 | justify-content: flex-start 33 | &.center 34 | justify-content: center 35 | &.right 36 | justify-content: flex-end 37 | &.stretch 38 | align-items: stretch 39 | &[col='1'] 40 | .video,iframe 41 | width: 100% 42 | &[col='2'] 43 | .video,iframe 44 | width: "calc(50% - 2 * %s)" % $sp 45 | &[col='3'] 46 | .video,iframe 47 | width: "calc(33.33% - 2 * %s)" % $sp 48 | &[col='4'] 49 | .video,iframe 50 | width: "calc(25% - 2 * %s)" % $sp 51 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/span.styl: -------------------------------------------------------------------------------- 1 | p.p.subtitle 2 | font-weight: bold 3 | color: mix($color-theme, $color-text, 75) 4 | font-size: 1.25rem !important 5 | padding-top: 1.5rem 6 | &:first-child 7 | padding-top: 1rem 8 | 9 | span.p,p.p 10 | &.logo 11 | font-family: $fontfamily-logo 12 | &.code 13 | font-family: $fontfamily-code 14 | &.left 15 | display: block 16 | text-align: left 17 | &.center 18 | display: block 19 | text-align: center 20 | &.right 21 | display: block 22 | text-align: right 23 | 24 | span.p,p.p 25 | &.small 26 | font-size: $fontsize-meta 27 | &.large 28 | font-size: $fontsize-large 29 | line-height: 1.4 30 | &.huge 31 | font-size: $fontsize-huge 32 | line-height: 1.4 33 | &.ultra 34 | font-size: $fontsize-ultra 35 | line-height: 1.4 36 | &.small,&.large,&.huge,&.ultra 37 | margin: 0 38 | padding: 0 39 | &.bold 40 | font-weight: bold 41 | &.h1,&.h2 42 | padding-bottom: .2rem 43 | font-weight: 500 44 | &.h1 45 | font-size: $fontsize-h1 46 | color: var(--color-h1) 47 | padding-top: $gap-p * 2 48 | &.h2 49 | font-size: $fontsize-h2 50 | color: var(--color-h2) 51 | padding-top: $gap-p * 2 52 | border-bottom: 1px solid alpha($color-text, .1) 53 | &.h3 54 | font-size: $fontsize-h3 55 | color: var(--color-h3) 56 | padding-top: $gap-p * 2 57 | &.h4 58 | font-size: $fontsize-h4 59 | color: var(--color-h4) 60 | padding-top: $gap-p * 2 61 | &.h5 62 | font-size: $fontsize-h5 63 | color: var(--color-h5) 64 | padding-top: $gap-p * 1.5 65 | 66 | span.p,p.p 67 | &.red 68 | color: $color-mac-red 69 | &.yellow 70 | color: $color-mac-yellow 71 | &.green 72 | color: $color-mac-green 73 | &.cyan 74 | color: $color-mac-cyan 75 | &.blue 76 | color: $color-md-blue 77 | &.purple 78 | color: $color-md-purple 79 | &.gray 80 | color: #999 81 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/swiper.styl: -------------------------------------------------------------------------------- 1 | .swiper-container 2 | width: 100% 3 | border-radius: 4px 4 | --gap-p: 2rem 5 | .swiper-container:not(.swiper-container-initialized) 6 | display: none 7 | div.swiper-slide 8 | text-align: center 9 | display: -webkit-box 10 | display: -ms-flexbox 11 | display: -webkit-flex 12 | display: flex 13 | align-self: center 14 | -webkit-box-pack: center 15 | -ms-flex-pack: center 16 | -webkit-justify-content: center 17 | justify-content: center 18 | -webkit-box-align: center 19 | -ms-flex-align: center 20 | -webkit-align-items: center 21 | align-items: center 22 | width: 50% 23 | img 24 | border-radius: 4px 25 | 26 | .swiper-container[width='max'] div.swiper-slide 27 | width: 100% 28 | 29 | .swiper-container[width='min'] div.swiper-slide 30 | width: 25% 31 | 32 | .swiper-button-prev,.swiper-button-next 33 | padding: 1rem 0.5rem 34 | margin-top: -2rem !important 35 | border-radius: 4px 36 | background: alpha(white, 0.25) 37 | trans1 background 38 | --swiper-theme-color: black !important 39 | &:after 40 | font-size: 1.2rem !important 41 | font-weight: 700 !important 42 | &:hover 43 | background: white !important 44 | --swiper-theme-color: $color-hover !important -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/table.styl: -------------------------------------------------------------------------------- 1 | .md 2 | .table 3 | overflow: auto 4 | margin-top: $gap-p 5 | margin-bottom: $gap-p 6 | table 7 | display: table 8 | width: 100% 9 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/tabs.styl: -------------------------------------------------------------------------------- 1 | $border-color = alpha($color-p, .2) 2 | $tbr = 4px 3 | 4 | div.tabs 5 | display: block 6 | position: relative 7 | margin-top: $gap-p 8 | margin-bottom: $gap-p 9 | border-radius: $tbr 10 | background: var(--color-card) 11 | border: 1px solid $border-color 12 | font-size: $fontsize-list 13 | .highlight,p,ul,ol,div.note,details 14 | margin-top: $gap-p 15 | margin-bottom: $gap-p 16 | 17 | div.tabs 18 | ul.nav-tabs 19 | display: flex 20 | overflow-x: auto 21 | white-space: nowrap 22 | justify-content: flex-start 23 | margin: 0 !important 24 | padding: 8px 8px 0 8px 25 | background: var(--color-block) 26 | border-radius: $tbr $tbr 0 0 27 | line-height: 1.5 28 | li.tab 29 | list-style-type: none 30 | margin-top: 0 31 | margin-bottom: 0 32 | &:last-child 33 | padding-right: $gap 34 | a 35 | display: block 36 | cursor: pointer 37 | border-radius: $tbr $tbr 0 0 38 | padding: $gap * 0.5 39 | text-align: center 40 | font-size: $fontsize-meta 41 | line-height: inherit 42 | font-weight: bold 43 | color: var(--color-meta) 44 | border: 1px solid transparent 45 | &:hover 46 | color: var(--color-p) 47 | i 48 | pointer-events: none 49 | &.active a 50 | cursor: default 51 | color: var(--color-p) 52 | background: $color-card 53 | border: 1px solid $border-color 54 | border-bottom: 1px solid var(--color-card) 55 | 56 | .tab-content 57 | border-top: 1px solid $border-color 58 | margin-top: -1px 59 | .tab-pane 60 | padding: $gap 61 | &:not(.active) 62 | display: none 63 | &.active 64 | display: block 65 | > 66 | p,.tabs,ul,ol,.highlight,.note 67 | &:first-child 68 | margin-top: 0 69 | &:last-child 70 | margin-bottom: 0 71 | -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/tag.json: -------------------------------------------------------------------------------- 1 | { 2 | "note": ["note.styl"], 3 | "tabs": ["tabs.styl"], 4 | "u": ["text.styl"], 5 | "emp": ["text.styl"], 6 | "wavy": ["text.styl"], 7 | "del": ["text.styl"], 8 | "kbd": ["text.styl"], 9 | "psw": ["text.styl"], 10 | "span": ["span.styl"], 11 | "p": ["span.styl"], 12 | "noteblock": ["note.styl"], 13 | "folding": ["folding.styl"], 14 | "checkbox": ["checkbox.styl"], 15 | "radio": ["checkbox.styl"], 16 | "timeline": ["timeline.styl"], 17 | "timenode": ["timeline.styl"], 18 | "link": ["link.styl"], 19 | "btn": ["btns.styl"], 20 | "btns": ["btns.styl"], 21 | "table": ["table.styl"], 22 | "ghcard": ["ghcard.styl"], 23 | "sites": ["sites.styl"], 24 | "menu": ["dropmenu.styl"], 25 | "inlineimage": ["image.styl"], 26 | "image": ["image.styl"], 27 | "gallery": ["fancybox.styl"], 28 | "audio": ["media.styl"], 29 | "video": ["media.styl"], 30 | "videos": ["media.styl"], 31 | "frame": ["frame.styl"], 32 | "contributors": ["friends.styl"], 33 | "friends": ["friends.styl"], 34 | "swiper": ["swiper.styl"] 35 | } -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/text.styl: -------------------------------------------------------------------------------- 1 | .article 2 | del 3 | color: mix($color-p, $color-card, 60) 4 | text-decoration-color: @color 5 | u 6 | color: var(--color-text) 7 | text-decoration: none 8 | border-bottom: 1px solid $color-mac-red 9 | emp 10 | color: var(--color-text) 11 | border-bottom: 4px dotted $color-mac-red 12 | wavy 13 | color: var(--color-text) 14 | text-decoration-style: wavy 15 | text-decoration-line: underline 16 | text-decoration-color: $color-mac-red 17 | psw 18 | color: transparent 19 | background: mix($color-text, $color-card, 50) 20 | border-radius: 2px 21 | trans() 22 | &:hover 23 | color: var(--color-p) 24 | background: none 25 | kbd 26 | border-radius: 4px 27 | border: 1px solid mix($color-block, $color-text, 80) 28 | border-bottom-width: 2px 29 | background: mix($color-block, $color-card, 50) 30 | padding-left: 4px 31 | padding-right: 4px -------------------------------------------------------------------------------- /source/css/_style/_tag-plugins/timeline.styl: -------------------------------------------------------------------------------- 1 | div.timenode 2 | position: relative 3 | &:before, &:after 4 | content: '' 5 | z-index: 1 6 | position: absolute 7 | background: alpha($color-theme, .5) 8 | width: 2px 9 | left: 7px 10 | &:before 11 | top: 0px 12 | height: 6px 13 | &:after 14 | top: 26px 15 | height: "calc(100% - %s)" % 26px 16 | &:last-child 17 | &:after 18 | height: "calc(100% - 26px - %s)" % $gap 19 | border-bottom-left-radius: 2px 20 | border-bottom-right-radius: 2px 21 | .meta,.body 22 | max-width: "calc(100% - %s)" % (16px + 8px) 23 | .meta 24 | position: relative 25 | color: var(--color-meta) 26 | font-size: $fontsize-meta 27 | line-height: 32px 28 | height: 32px 29 | &:before, &:after 30 | content: '' 31 | position: absolute 32 | top: 8px 33 | z-index: 2 34 | &:before 35 | background: alpha($color-theme, .5) 36 | width: 16px 37 | height: 16px 38 | border-radius: 8px 39 | &:after 40 | background: $color-theme 41 | margin-left: 2px 42 | margin-top: 2px 43 | width: 12px 44 | height: 12px 45 | border-radius: 6px 46 | transform: scale(0.5) 47 | trans() 48 | p 49 | font-weight: bold 50 | margin: 0 0 0 16px + 8px 51 | .body 52 | margin: 4px 0 $gap 16px + 8px 53 | padding: $gap 54 | border-radius: $border-card 55 | background: var(--color-block) 56 | display: inline-block 57 | &:empty 58 | display: none 59 | >* 60 | &:first-child 61 | margin-top: $gap-p * 0.25 62 | &:last-child 63 | margin-bottom: $gap-p * 0.25 64 | .highlight 65 | border: 1px solid mix($color-block, $color-text, 90) 66 | 67 | 68 | div.timenode:hover 69 | .meta 70 | color: var(--color-text) 71 | &:before 72 | background: alpha($color-hover, .5) 73 | &:after 74 | background: $color-hover 75 | transform: scale(1) 76 | -------------------------------------------------------------------------------- /source/css/_style/index.styl: -------------------------------------------------------------------------------- 1 | @import '_base/*' 2 | 3 | @import '_layout/*' 4 | 5 | @import '_tag-plugins/*' 6 | 7 | // 暗黑模式样式放到最后加载 8 | @import '_plugins/index' -------------------------------------------------------------------------------- /source/css/first.styl: -------------------------------------------------------------------------------- 1 | #safearea { 2 | display: none 3 | } 4 | 5 | if hexo-config('content_visibility') 6 | // https://web.dev/content-visibility/ 7 | // https://www.caniuse.com/?search=content-visibility 8 | /* 9 | * Workaround for Chrome bug, part 1 10 | * Chunk rendering for all but the first article. 11 | * /layout/_partial/scripts/content-visibility-scroll-fix.ejs 12 | */ 13 | .post-story + .post-story{ 14 | content-visibility: auto; 15 | contain-intrinsic-size: 10px 500px; 16 | } 17 | 18 | @import '_defines/*' 19 | 20 | // Project 21 | @import '_first/*' 22 | 23 | // Custom Files 24 | for $injects_first in hexo-config('injects.first') 25 | @import $injects_first; -------------------------------------------------------------------------------- /source/css/style.styl: -------------------------------------------------------------------------------- 1 | #safearea{ 2 | display: block 3 | } 4 | 5 | @import '_defines/*' 6 | 7 | // Project 8 | @import '_style' 9 | 10 | // Custom Files 11 | for $injects_style in hexo-config('injects.style') 12 | @import $injects_style; 13 | 14 | --------------------------------------------------------------------------------