├── source
├── css
│ ├── _custom
│ │ ├── custom.styl
│ │ ├── font.css
│ │ ├── flink.css
│ │ ├── sidebar.css
│ │ ├── tag.styl
│ │ ├── snackbar.css
│ │ ├── animations.css
│ │ ├── comment.styl
│ │ └── bar.css
│ ├── _layout
│ │ ├── relatedposts.styl
│ │ ├── chat.styl
│ │ ├── rightside.styl
│ │ ├── loading.styl
│ │ ├── footer.styl
│ │ ├── comments.styl
│ │ ├── reward.styl
│ │ ├── sidebar.styl
│ │ ├── pagination.styl
│ │ └── third-party.styl
│ ├── _tags
│ │ ├── inlineImg.styl
│ │ ├── ghcard.styl
│ │ ├── label.styl
│ │ ├── span.styl
│ │ ├── hexo.styl
│ │ ├── poem.styl
│ │ ├── hide.styl
│ │ ├── link.styl
│ │ ├── media.styl
│ │ ├── button.styl
│ │ ├── progress.styl
│ │ ├── card.styl
│ │ ├── tabs.styl
│ │ ├── timeline.styl
│ │ ├── gallery.styl
│ │ └── folding.styl
│ ├── _page
│ │ ├── tags.styl
│ │ ├── categories.styl
│ │ ├── common.styl
│ │ ├── 404.styl
│ │ ├── flink.styl
│ │ ├── archives.styl
│ │ └── homepage.styl
│ ├── _highlight
│ │ ├── prismjs
│ │ │ ├── index.styl
│ │ │ └── line-number.styl
│ │ └── highlight
│ │ │ ├── index.styl
│ │ │ └── diff.styl
│ ├── index.styl
│ ├── _search
│ │ ├── index.styl
│ │ ├── local-search.styl
│ │ └── algolia.styl
│ └── post-double-row.css
├── img
│ ├── 404.jpg
│ ├── favicon.png
│ └── friend_404.gif
├── font
│ ├── alifangyuan.ttf
│ └── iconfont.woff2
└── js
│ ├── sub.js
│ ├── swiper.js
│ └── scroll.js
├── layout
├── includes
│ ├── page
│ │ ├── categories.pug
│ │ ├── default-page.pug
│ │ ├── tags.pug
│ │ ├── comments.pug
│ │ └── flink.pug
│ ├── head
│ │ ├── site_verification.pug
│ │ ├── noscript.pug
│ │ ├── google_adsense.pug
│ │ ├── Open_Graph.pug
│ │ ├── pwa.pug
│ │ ├── preconnect.pug
│ │ ├── config_site.pug
│ │ └── analytics.pug
│ ├── third-party
│ │ ├── search
│ │ │ ├── index.pug
│ │ │ ├── algolia.pug
│ │ │ └── local-search.pug
│ │ ├── share
│ │ │ ├── add-this.pug
│ │ │ ├── share-js.pug
│ │ │ ├── index.pug
│ │ │ └── addtoany.pug
│ │ ├── aplayer.pug
│ │ ├── prismjs.pug
│ │ ├── math
│ │ │ ├── katex.pug
│ │ │ ├── index.pug
│ │ │ ├── mermaid.pug
│ │ │ └── mathjax.pug
│ │ ├── card-post-count
│ │ │ ├── index.pug
│ │ │ ├── disqus.pug
│ │ │ ├── remark42.pug
│ │ │ ├── waline.pug
│ │ │ ├── artalk.pug
│ │ │ ├── valine.pug
│ │ │ ├── fb.pug
│ │ │ └── twikoo.pug
│ │ ├── chat
│ │ │ ├── index.pug
│ │ │ ├── chatra.pug
│ │ │ ├── crisp.pug
│ │ │ ├── gitter.pug
│ │ │ ├── tidio.pug
│ │ │ ├── messenger.pug
│ │ │ └── daovoice.pug
│ │ ├── pangu.pug
│ │ ├── effect.pug
│ │ ├── comments
│ │ │ ├── livere.pug
│ │ │ ├── js.pug
│ │ │ ├── valine.pug
│ │ │ ├── waline.pug
│ │ │ ├── index.pug
│ │ │ ├── utterances.pug
│ │ │ ├── gitalk.pug
│ │ │ ├── artalk.pug
│ │ │ ├── twikoo.pug
│ │ │ ├── disqus.pug
│ │ │ ├── facebook_comments.pug
│ │ │ ├── giscus.pug
│ │ │ ├── remark42.pug
│ │ │ └── disqusjs.pug
│ │ ├── newest-comments
│ │ │ └── index.pug
│ │ └── subtitle.pug
│ ├── header
│ │ ├── social.pug
│ │ ├── menu_item.pug
│ │ ├── nav.pug
│ │ └── index.pug
│ ├── pagination.pug
│ ├── 404.pug
│ ├── post
│ │ ├── reward.pug
│ │ └── post-copyright.pug
│ ├── waves.pug
│ ├── widget
│ │ ├── card_post_toc.pug
│ │ ├── card_author.pug
│ │ ├── index.pug
│ │ ├── card_webinfo.pug
│ │ └── card_tags.pug
│ ├── sidebar.pug
│ ├── mixins
│ │ └── article-sort.pug
│ ├── swiper.pug
│ ├── loading
│ │ └── index.pug
│ ├── footer.pug
│ ├── additional-js.pug
│ └── rightside.pug
├── index.pug
├── archive.pug
├── tag.pug
├── category.pug
├── page.pug
└── post.pug
├── theme.png
├── scripts
├── events
│ ├── 404.js
│ ├── comment.js
│ ├── stylus.js
│ ├── init.js
│ ├── welcome.js
│ └── cdn.js
├── tag
│ ├── label.js
│ ├── mermaid.js
│ ├── inlineImg.js
│ ├── poem.js
│ ├── progress.js
│ ├── button.js
│ ├── gh.js
│ ├── span.js
│ ├── note.js
│ ├── gallery.js
│ ├── folding.js
│ ├── btns.js
│ ├── reference.js
│ ├── flink.js
│ ├── ghcard.js
│ ├── timeline.js
│ ├── card.js
│ ├── msgbox.js
│ ├── media.js
│ ├── hide.js
│ └── tabs.js
├── helpers
│ ├── random.js
│ ├── get_arrays.js
│ ├── findArchiveLength.js
│ └── page.js
└── filters
│ ├── post_lazyload.js
│ └── random_cover.js
├── .github
├── ISSUE_TEMPLATE
│ ├── config.yml
│ ├── feature_request.yml
│ └── bug_report.yml
└── workflows
│ ├── publish.yml
│ └── stale.yml
├── package.json
├── README.md
└── languages
├── zh-CN.yml
└── zh-TW.yml
/source/css/_custom/custom.styl:
--------------------------------------------------------------------------------
1 | nav#pagination
2 | margin: auto
--------------------------------------------------------------------------------
/layout/includes/page/categories.pug:
--------------------------------------------------------------------------------
1 | .category-lists!= list_categories()
--------------------------------------------------------------------------------
/source/css/_layout/relatedposts.styl:
--------------------------------------------------------------------------------
1 | .relatedPosts
2 | display: none
--------------------------------------------------------------------------------
/layout/includes/page/default-page.pug:
--------------------------------------------------------------------------------
1 | #article-container
2 | != page.content
--------------------------------------------------------------------------------
/theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ezgx/hexo-theme-Dynasty/HEAD/theme.png
--------------------------------------------------------------------------------
/source/img/404.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ezgx/hexo-theme-Dynasty/HEAD/source/img/404.jpg
--------------------------------------------------------------------------------
/layout/includes/page/tags.pug:
--------------------------------------------------------------------------------
1 | .tag-cloud-list.is-center
2 | !=cloudTags({source: site.tags, limit: 0})
--------------------------------------------------------------------------------
/source/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ezgx/hexo-theme-Dynasty/HEAD/source/img/favicon.png
--------------------------------------------------------------------------------
/source/font/alifangyuan.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ezgx/hexo-theme-Dynasty/HEAD/source/font/alifangyuan.ttf
--------------------------------------------------------------------------------
/source/font/iconfont.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ezgx/hexo-theme-Dynasty/HEAD/source/font/iconfont.woff2
--------------------------------------------------------------------------------
/source/img/friend_404.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ezgx/hexo-theme-Dynasty/HEAD/source/img/friend_404.gif
--------------------------------------------------------------------------------
/layout/includes/head/site_verification.pug:
--------------------------------------------------------------------------------
1 | if theme.site_verification
2 | each item in theme.site_verification
3 | meta(name=item.name content=item.content)
--------------------------------------------------------------------------------
/source/css/_custom/font.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | font-family: "PingFang SC","Hiragino Sans GB","Microsoft YaHei";
4 | font-size: 16px;
5 | font-weight: 600;
6 | }
--------------------------------------------------------------------------------
/source/js/sub.js:
--------------------------------------------------------------------------------
1 | var mySwiper = new Swiper ('.swiper-container', {
2 | direction: 'vertical',
3 | loop: true,
4 | autoplay: true,
5 | delay: 1500,
6 | })
--------------------------------------------------------------------------------
/layout/includes/third-party/search/index.pug:
--------------------------------------------------------------------------------
1 | if theme.algolia_search.enable
2 | include ./algolia.pug
3 | else if theme.local_search.enable
4 | include ./local-search.pug
--------------------------------------------------------------------------------
/layout/includes/third-party/share/add-this.pug:
--------------------------------------------------------------------------------
1 | .addthis_inline_share_toolbox
2 | script(src=`//s7.addthis.com/js/300/addthis_widget.js#pubid=${theme.addThis.pubid}` async)
--------------------------------------------------------------------------------
/source/css/_tags/inlineImg.styl:
--------------------------------------------------------------------------------
1 | #article-container
2 | .inline-img
3 | display: inline
4 | margin: 0 3px
5 | height: 1.1em
6 | vertical-align: text-bottom
--------------------------------------------------------------------------------
/layout/index.pug:
--------------------------------------------------------------------------------
1 | extends includes/layout.pug
2 |
3 | block content
4 | include ./includes/mixins/post-ui.pug
5 | #recent-posts.recent-posts.maininner
6 | +postUI
7 | include includes/pagination.pug
--------------------------------------------------------------------------------
/layout/includes/third-party/aplayer.pug:
--------------------------------------------------------------------------------
1 | link(rel='stylesheet' href=url_for(theme.asset.aplayer_css) media="print" onload="this.media='all'")
2 | script(src=url_for(theme.asset.aplayer_js))
3 | script(src=url_for(theme.asset.meting_js))
--------------------------------------------------------------------------------
/layout/includes/header/social.pug:
--------------------------------------------------------------------------------
1 | each url, icon in theme.social
2 | a.social-icon(href=url_for(trim(url.split('||')[0])) target="_blank"
3 | title=url.split('||')[1] === undefined ? '' : trim(url.split('||')[1]))
4 | i(class=icon)
--------------------------------------------------------------------------------
/source/css/_tags/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 - 10px * 0.5
9 | .ghcard
10 | margin: 10px * 0.5
11 |
--------------------------------------------------------------------------------
/layout/includes/third-party/share/share-js.pug:
--------------------------------------------------------------------------------
1 | .social-share(data-image=url_for(page.cover|| theme.avatar.img) data-sites= theme.sharejs.sites)
2 | link(rel='stylesheet' href=url_for(theme.asset.sharejs_css) media="print" onload="this.media='all'")
3 | script(src=url_for(theme.asset.sharejs) defer)
--------------------------------------------------------------------------------
/source/css/_tags/label.styl:
--------------------------------------------------------------------------------
1 | .hl-label
2 | padding: 2px 4px
3 | border-radius: 3px
4 | color: $btn-color
5 |
6 | &.default
7 | background-color: $btn-default-color
8 |
9 | for $type in $color-types
10 | &.{$type}
11 | background-color: lookup('$tagsP-' + $type + '-color')
12 |
--------------------------------------------------------------------------------
/layout/includes/head/noscript.pug:
--------------------------------------------------------------------------------
1 | noscript.
2 |
--------------------------------------------------------------------------------
/layout/includes/third-party/prismjs.pug:
--------------------------------------------------------------------------------
1 | if config.prismjs && config.prismjs.enable && !config.prismjs.preprocess
2 | script(src=url_for(theme.asset.prismjs_js))
3 | script(src=url_for(theme.asset.prismjs_autoloader))
4 | if config.prismjs.line_number
5 | script(src=url_for(theme.asset.prismjs_lineNumber_js))
6 |
--------------------------------------------------------------------------------
/layout/includes/third-party/share/index.pug:
--------------------------------------------------------------------------------
1 | .post_share
2 | if theme.addThis.enable
3 | !=partial('includes/third-party/share/add-this', {}, {cache: true})
4 | else if theme.sharejs.enable
5 | include ./share-js.pug
6 | else if theme.addtoany.enable
7 | !=partial('includes/third-party/share/addtoany', {}, {cache: true})
8 |
--------------------------------------------------------------------------------
/layout/archive.pug:
--------------------------------------------------------------------------------
1 | extends includes/layout.pug
2 |
3 | block content
4 | include ./includes/mixins/article-sort.pug
5 | #archive
6 | - const archiveLength = findArchiveLength(fragment_cache)
7 | .article-sort-title= _p('page.articles') + ' - ' + archiveLength
8 | +articleSort(page.posts)
9 | include includes/pagination.pug
--------------------------------------------------------------------------------
/layout/includes/third-party/math/katex.pug:
--------------------------------------------------------------------------------
1 | link(rel="stylesheet" type="text/css" href=url_for(theme.asset.katex))
2 | script(src=url_for(theme.asset.katex_copytex))
3 | script.
4 | (() => {
5 | document.querySelectorAll('#article-container span.katex-display').forEach(item => {
6 | btf.wrap(item, 'div', { class: 'katex-wrap'})
7 | })
8 | })()
9 |
--------------------------------------------------------------------------------
/layout/includes/third-party/share/addtoany.pug:
--------------------------------------------------------------------------------
1 | .addtoany
2 | .a2a_kit.a2a_kit_size_32.a2a_default_style
3 | - let addtoanyItem = theme.addtoany.item.split(',')
4 | each name in addtoanyItem
5 | a(class="a2a_button_" + name)
6 |
7 | a.a2a_dd(href="https://www.addtoany.com/share")
8 | script(async src='https://static.addtoany.com/menu/page.js')
9 |
10 |
11 |
--------------------------------------------------------------------------------
/scripts/events/404.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * 404 error page
4 | */
5 |
6 | 'use strict'
7 |
8 | hexo.extend.generator.register('404', function (locals) {
9 | if (!hexo.theme.config.error_404.enable) return
10 | return {
11 | path: '404.html',
12 | layout: ['page'],
13 | data: {
14 | type: '404',
15 | top_img: false
16 | }
17 | }
18 | })
19 |
--------------------------------------------------------------------------------
/source/css/_page/tags.styl:
--------------------------------------------------------------------------------
1 | .tag-cloud
2 | &-list
3 | a
4 | display: inline-block
5 | padding: 0 8px
6 | transition: all .3s
7 |
8 | +maxWidth768()
9 | zoom: .85
10 |
11 | &-title
12 | font-size: 2.57em
13 |
14 | +maxWidth768()
15 | font-size: 2em
16 |
17 | h1.page-title
18 | & + .tag-cloud-list
19 | text-align: left
20 |
--------------------------------------------------------------------------------
/scripts/tag/label.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * label
4 | * {% label text color %}
5 | */
6 |
7 | 'use strict'
8 |
9 | function addLabel (args, content) {
10 | const text = args[0]
11 | const className = args[1] || 'default'
12 |
13 | return `${text} `
14 | }
15 |
16 | hexo.extend.tag.register('label', addLabel, { ends: false })
17 |
--------------------------------------------------------------------------------
/layout/includes/pagination.pug:
--------------------------------------------------------------------------------
1 | -
2 | var options = {
3 | prev_text: '',
4 | next_text: '',
5 | mid_size: 1,
6 | escape: false
7 | }
8 |
9 | if is_post()
10 | block content
11 | else
12 | nav#pagination
13 | .pagination
14 | if is_home()
15 | - options.format = 'page/%d/'
16 | !=paginator(options)
--------------------------------------------------------------------------------
/layout/includes/head/google_adsense.pug:
--------------------------------------------------------------------------------
1 | if (theme.google_adsense && theme.google_adsense.enable)
2 | script(async src=theme.google_adsense.js)
3 |
4 | if theme.google_adsense.auto_ads
5 | script.
6 | (adsbygoogle = window.adsbygoogle || []).push({
7 | google_ad_client: '!{theme.google_adsense.client}',
8 | enable_page_level_ads: '!{theme.google_adsense.enable_page_level_ads}'
9 | });
--------------------------------------------------------------------------------
/layout/includes/404.pug:
--------------------------------------------------------------------------------
1 | - var top_img_404 = theme.error_404.background || theme.default_top_img
2 |
3 | #body-wrap.error404
4 | include ./header/index.pug
5 |
6 | #error-wrap
7 | .error-content
8 | .error-img
9 | img(src=url_for(top_img_404) alt='Page not found')
10 | .error-info
11 | h1.error_title= '404'
12 | .error_subtitle= theme.error_404.subtitle || _p('error404')
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: QQ 2群
4 | url: http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=qk2lHfzjy1zxBBH4Gzpdby_D5l5BBRTy&authKey=e4gai6kHIffsLOnjR5hP6U%2BuU5JX%2B8LoU3LM%2BVmSjJCkuyBj1NqDjGtEgpUpFSV4&noverify=0&group_code=741440379
5 | about: 群号741440379
6 | - name: 作者QQ
7 | url: http://wpa.qq.com/msgrd?v=3&uin=3387251845&site=qq&menu=yes
8 | about: 添加主题作者qq
--------------------------------------------------------------------------------
/scripts/tag/mermaid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * mermaid
4 | * https://github.com/mermaid-js/mermaid
5 | */
6 |
7 | 'use strict'
8 |
9 | const { escapeHTML } = require('hexo-util')
10 |
11 | function mermaid (args, content) {
12 | return `
13 | ${escapeHTML(content)}
14 | `
15 | }
16 |
17 | hexo.extend.tag.register('mermaid', mermaid, { ends: true })
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: Feature request
2 | description: Suggest an idea for this project
3 | title: '[Feature]: '
4 |
5 | body:
6 | - type: textarea
7 | id: feature-request
8 | attributes:
9 | label: 想要的功能 | What feature do you want?
10 | description: 請描述你需要的新功能 | A clear and concise description of what the feature is.
11 | placeholder:
12 | value:
13 | validations:
14 | require: true
--------------------------------------------------------------------------------
/layout/includes/third-party/card-post-count/index.pug:
--------------------------------------------------------------------------------
1 | case theme.comments.use[0]
2 | when 'Twikoo'
3 | include ./twikoo.pug
4 | when 'Disqus'
5 | when 'Disqusjs'
6 | include ./disqus.pug
7 | when 'Valine'
8 | include ./valine.pug
9 | when 'Waline'
10 | include ./waline.pug
11 | when 'Facebook Comments'
12 | include ./fb.pug
13 | when 'Remark42'
14 | include ./remark42.pug
15 | when 'Artalk'
16 | include ./artalk.pug
--------------------------------------------------------------------------------
/layout/tag.pug:
--------------------------------------------------------------------------------
1 | extends includes/layout.pug
2 |
3 | block content
4 | if theme.tag_ui == 'index'
5 | include ./includes/mixins/post-ui.pug
6 | #recent-posts.recent-posts
7 | +postUI
8 | include includes/pagination.pug
9 | else
10 | include ./includes/mixins/article-sort.pug
11 | #tag
12 | .article-sort-title= _p('page.tag') + ' - ' + page.tag
13 | +articleSort(page.posts)
14 | include includes/pagination.pug
--------------------------------------------------------------------------------
/source/js/swiper.js:
--------------------------------------------------------------------------------
1 | var mySwiper = new Swiper ('.hometop-swiper', {
2 | direction: 'vertical', // 垂直切换选项
3 | loop: true, // 循环模式选项
4 | effect: 'creative',
5 | mousewheel: true,
6 | autoplay:true,
7 | // 如果需要分页器
8 | pagination: {
9 | el: '.swiper-pagination',
10 | },
11 | // 如果需要前进后退按钮
12 | navigation: {
13 | nextEl: '.hometop-swiper-button-next',
14 | prevEl: '.hometop-swiper-button-prev',
15 | },
16 | })
--------------------------------------------------------------------------------
/scripts/tag/inlineImg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * inlineImg 圖片
3 | * {% inlineImg src height %}
4 | */
5 |
6 | 'use strict'
7 |
8 | const urlFor = require('hexo-util').url_for.bind(hexo)
9 |
10 | function inlineImg (args) {
11 | const img = args[0]
12 | const height = args[1] ? `style="height:${args[1]}"` : ''
13 |
14 | return `
`
15 | }
16 |
17 | hexo.extend.tag.register('inlineImg', inlineImg, { ends: false })
18 |
--------------------------------------------------------------------------------
/layout/includes/post/reward.pug:
--------------------------------------------------------------------------------
1 | .post-reward
2 | .reward-button
3 | i.fas.fa-qrcode
4 | = ' ' + _p('donate')
5 | .reward-main
6 | ul.reward-all
7 | each item in theme.reward.QR_code
8 | - var clickTo = item.link ? item.link : item.img
9 | li.reward-item
10 | a(href=url_for(clickTo) target='_blank')
11 | img.post-qr-code-img(src=url_for(item.img) alt=item.text)
12 | .post-qr-code-desc=item.text
13 |
14 |
--------------------------------------------------------------------------------
/scripts/events/comment.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Capitalize the first letter of comment name
3 | */
4 |
5 | hexo.extend.filter.register('before_generate', () => {
6 | const themeConfig = hexo.theme.config
7 | let { use } = themeConfig.comments
8 | if (!use) return
9 | if (typeof use === 'string') {
10 | use = use.split(',')
11 | }
12 | const newArray = use.map(item => item.toLowerCase().replace(/\b[a-z]/g, s => s.toUpperCase()))
13 | themeConfig.comments.use = newArray
14 | })
--------------------------------------------------------------------------------
/layout/includes/third-party/chat/index.pug:
--------------------------------------------------------------------------------
1 | if theme.chatra && theme.chatra.enable
2 | include ./chatra.pug
3 | else if theme.tidio && theme.tidio.enable
4 | include ./tidio.pug
5 | else if theme.daovoice && theme.daovoice.enable
6 | include ./daovoice.pug
7 | else if theme.gitter && theme.gitter.enable
8 | include ./gitter.pug
9 | else if theme.crisp && theme.crisp.enable
10 | include ./crisp.pug
11 | else if theme.messenger && theme.messenger.enable
12 | include ./messenger.pug
--------------------------------------------------------------------------------
/layout/category.pug:
--------------------------------------------------------------------------------
1 | extends includes/layout.pug
2 |
3 | block content
4 | if theme.category_ui == 'index'
5 | include ./includes/mixins/post-ui.pug
6 | #recent-posts.recent-posts.category_ui
7 | +postUI
8 | include includes/pagination.pug
9 | else
10 | include ./includes/mixins/article-sort.pug
11 | #category
12 | .article-sort-title= _p('page.category') + ' - ' + page.category
13 | +articleSort(page.posts)
14 | include includes/pagination.pug
--------------------------------------------------------------------------------
/source/css/_tags/span.styl:
--------------------------------------------------------------------------------
1 | span.p.center.logo.large
2 | font-size 2.5rem
3 | text-align center
4 | display block
5 |
6 | span.p.center.small
7 | text-align center
8 | display block
9 | font-size 1rem
10 |
11 | span.p.red
12 | color #fe5f58
13 |
14 | span.p.yellow
15 | color #ffbd2b
16 |
17 | span.p.green
18 | color #3dc550
19 |
20 | span.p.cyan
21 | color #1bcdfc
22 |
23 | span.p.blue
24 | color #2196f3
25 |
26 | span.p.gray
27 | color #999
--------------------------------------------------------------------------------
/layout/includes/third-party/math/index.pug:
--------------------------------------------------------------------------------
1 | if theme.mathjax && theme.mathjax.enable
2 | if theme.mathjax.per_page
3 | if is_post() || is_page()
4 | include ./mathjax.pug
5 | else
6 | if page.mathjax
7 | include ./mathjax.pug
8 |
9 | if theme.katex && theme.katex.enable
10 | if theme.katex.per_page
11 | if is_post() || is_page()
12 | include ./katex.pug
13 | else
14 | if page.katex
15 | include ./katex.pug
16 |
17 | if theme.mermaid.enable
18 | include ./mermaid.pug
--------------------------------------------------------------------------------
/layout/includes/third-party/search/algolia.pug:
--------------------------------------------------------------------------------
1 | #algolia-search
2 | .search-dialog
3 | nav.search-nav
4 | span.search-dialog-title= _p('search.title')
5 | button.search-close-button
6 | i.fas.fa-times
7 |
8 | .search-wrap
9 | #algolia-search-input
10 | hrl.line
11 | #algolia-search-results
12 | #algolia-hits
13 | #algolia-pagination
14 | #algolia-info
15 | .algolia-stats
16 | .algolia-poweredBy
17 |
18 | #search-mask
19 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: npm publish
2 |
3 | on:
4 | release:
5 | types: [created]
6 | jobs:
7 | build:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 | # Setup .npmrc file to publish to npm
12 | - uses: actions/setup-node@v1
13 | with:
14 | node-version: '12.x'
15 | registry-url: 'https://registry.npmjs.org'
16 | - run: npm install
17 | - run: npm publish
18 | env:
19 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
--------------------------------------------------------------------------------
/layout/includes/head/Open_Graph.pug:
--------------------------------------------------------------------------------
1 | if theme.Open_Graph_meta.enable
2 | -
3 | let ogOption = Object.assign({
4 | type: is_post() ? 'article' : 'website',
5 | image: (page.cover || theme.avatar.img) ? full_url_for(page.cover || theme.avatar.img) : '',
6 | fb_admins: theme.facebook_comments.user_id || '',
7 | fb_app_id: theme.facebook_comments.app_id || '',
8 | }, theme.Open_Graph_meta.option)
9 | -
10 | != open_graph(ogOption)
11 | else
12 | meta(name="description" content=page_description())
13 |
14 |
--------------------------------------------------------------------------------
/layout/includes/third-party/pangu.pug:
--------------------------------------------------------------------------------
1 | script.
2 | function panguFn () {
3 | if (typeof pangu === 'object') pangu.autoSpacingPage()
4 | else {
5 | getScript('!{url_for(theme.asset.pangu)}')
6 | .then(() => {
7 | pangu.autoSpacingPage()
8 | })
9 | }
10 | }
11 |
12 | function panguInit () {
13 | if (!{theme.pangu.field === 'post'}){
14 | GLOBAL_CONFIG_SITE.isPost && panguFn()
15 | } else {
16 | panguFn()
17 | }
18 | }
19 |
20 | document.addEventListener('DOMContentLoaded', panguInit)
21 |
--------------------------------------------------------------------------------
/layout/includes/waves.pug:
--------------------------------------------------------------------------------
1 | section.main-hero-waves-area.waves-area
2 | svg.waves-svg(xmlns='http://www.w3.org/2000/svg', xlink='http://www.w3.org/1999/xlink', viewBox='0 24 150 28', preserveAspectRatio='none', shape-rendering='auto')
3 | defs
4 | path#gentle-wave(d='M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z')
5 | g.parallax
6 | use(href='#gentle-wave', x='48', y='0')
7 | use(href='#gentle-wave', x='48', y='3')
8 | use(href='#gentle-wave', x='48', y='5')
9 | use(href='#gentle-wave', x='48', y='7')
--------------------------------------------------------------------------------
/scripts/events/stylus.js:
--------------------------------------------------------------------------------
1 | /**
2 | * stylus
3 | */
4 |
5 | 'use strict'
6 |
7 | hexo.extend.filter.register('stylus:renderer', function (style) {
8 | const { highlight, prismjs } = hexo.config
9 | style
10 | .define('$highlight_enable', highlight && highlight.enable)
11 | .define('$highlight_line_number', highlight && highlight.line_number)
12 | .define('$prismjs_enable', prismjs && prismjs.enable)
13 | .define('$prismjs_line_number', prismjs && prismjs.line_number)
14 | // .import(this.source_dir.replace(/\\/g, '/') + '_data/css/*')
15 | })
16 |
--------------------------------------------------------------------------------
/source/css/_custom/flink.css:
--------------------------------------------------------------------------------
1 | .flink .btns a.button {
2 | height: auto !important;
3 | }
4 | .flink .btns #text {
5 | font-size: 18px;
6 | font-weight: 700;
7 | }
8 | .flink .btns p {
9 | font-weight: 700;
10 | font-size: 15px;
11 | border-top: 3px dashed var(--heo-theme);
12 | padding-top: 5px;
13 | }
14 | @media screen and (min-width: 1024px) {
15 | .flink .btns a {
16 | width: 24% !important;
17 | }
18 | }
19 | @media screen and (max-width: 450px) {
20 | .flink .btns a {
21 | width: 100% !important;
22 | }
23 | }
--------------------------------------------------------------------------------
/source/css/_highlight/prismjs/index.styl:
--------------------------------------------------------------------------------
1 | if $prismjs_line_number
2 | @require 'line-number'
3 |
4 | if $highlight_theme != false
5 | @require 'diff'
6 |
7 | #article-container
8 | pre[class*='language-']
9 | scrollbar-color: var(--hlscrollbar-bg) transparent
10 |
11 | &::-webkit-scrollbar-thumb
12 | background: var(--hlscrollbar-bg)
13 |
14 | &:not(.line-numbers)
15 | padding: 10px 20px
16 |
17 | .caption
18 | margin-left: -3.8em
19 | padding: 4px 16px !important
20 |
21 | a
22 | padding: 0 !important
23 |
--------------------------------------------------------------------------------
/layout/includes/third-party/card-post-count/disqus.pug:
--------------------------------------------------------------------------------
1 | script.
2 | (() => {
3 | const getCount = () => {
4 | if (window.DISQUSWIDGETS === undefined) {
5 | var d = document, s = d.createElement('script');
6 | s.src = 'https://!{theme.disqus.shortname}.disqus.com/count.js';
7 | s.id = 'dsq-count-scr';
8 | (d.head || d.body).appendChild(s);
9 | } else {
10 | DISQUSWIDGETS.getCount({reset: true});
11 | }
12 | }
13 |
14 | window.pjax ? getCount() : window.addEventListener('load', getCount)
15 |
16 | })()
17 |
--------------------------------------------------------------------------------
/source/css/_layout/chat.styl:
--------------------------------------------------------------------------------
1 | // chat
2 | if hexo-config('chat_btn') == true && hexo-config('chatra.enable')
3 | #chatra:not(.chatra--expanded)
4 | visibility: hidden !important
5 | width: 1px !important
6 | height: 1px !important
7 | opacity: 0 !important
8 | pointer-events: none
9 |
10 | if hexo-config('chat_btn') == true && hexo-config('messenger.enable')
11 | .fb_dialog,
12 | .fb-customerchat
13 | visibility: hidden !important
14 | width: 1px !important
15 | height: 1px !important
16 | opacity: 0 !important
17 | pointer-events: none
--------------------------------------------------------------------------------
/layout/includes/third-party/card-post-count/remark42.pug:
--------------------------------------------------------------------------------
1 | - const { host, siteId, option } = theme.remark42
2 |
3 | script.
4 | (()=>{
5 | window.remark_config = Object.assign({
6 | host: '!{host}',
7 | site_id: '!{siteId}',
8 | },!{JSON.stringify(option)})
9 |
10 | function getCount () {
11 | const s = document.createElement('script')
12 | s.src = remark_config.host + '/web/counter.js'
13 | s.defer = true
14 | document.head.appendChild(s)
15 | }
16 |
17 | window.pjax ? getCount() : window.addEventListener('load', getCount)
18 | })()
--------------------------------------------------------------------------------
/layout/includes/third-party/card-post-count/waline.pug:
--------------------------------------------------------------------------------
1 | script.
2 | (() => {
3 | function loadWaline () {
4 | function initWaline () {
5 | let initData = {
6 | el: null,
7 | serverURL: '!{theme.waline.serverURL}',
8 | comment: true
9 | }
10 | const waline = Waline.init(initData)
11 | }
12 |
13 | if (typeof Waline === 'function') initWaline()
14 | else getScript('!{url_for(theme.asset.waline_js)}').then(initWaline)
15 | }
16 |
17 | window.pjax ? loadWaline() : window.addEventListener('load', loadWaline)
18 | })()
19 |
--------------------------------------------------------------------------------
/source/css/_tags/hexo.styl:
--------------------------------------------------------------------------------
1 | // pullquote
2 | blockquote
3 | &.pullquote
4 | position: relative
5 | max-width: 45%
6 | font-size: 110%
7 |
8 | &.left
9 | float: left
10 | margin: 1em .5em 0 0
11 |
12 | &.right
13 | float: right
14 | margin: 1em 0 0 .5em
15 |
16 | // hexo tag video
17 | .video-container
18 | position: relative
19 | overflow: hidden
20 | margin-bottom: 16px
21 | padding-top: 56.25%
22 | height: 0
23 |
24 | iframe
25 | position: absolute
26 | top: 0
27 | left: 0
28 | margin-top: 0
29 | width: 100%
30 | height: 100%
31 |
--------------------------------------------------------------------------------
/scripts/tag/poem.js:
--------------------------------------------------------------------------------
1 | // 'use strict'
2 | //
3 | // function poem (args, content) {
4 | // return `${content}
`
5 | // }
6 | //
7 | // hexo.extend.tag.register('poem', poem, { ends: true })
8 |
9 | 'use strict'
10 |
11 | function poem (args, content) {
12 | args = args.join(' ').split(',')
13 | let p0 = args[0]
14 | let p1 = args[1]?args[1]:''
15 | return `${p0}
${p1}
${hexo.render.renderSync({ text: content, engine: 'markdown' })}
`
16 | }
17 |
18 | hexo.extend.tag.register('poem',poem,{ ends: true });
19 |
--------------------------------------------------------------------------------
/scripts/tag/progress.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | function postprogress(args) {
3 | args = args.join(',').split(',')
4 | if (args.length > 1) {
5 | let pwidth = args[0].trim()
6 | let pcolor = args[1].trim()
7 | let text = args[2].trim()
8 | return `${hexo.render.renderSync({text: text, engine: 'markdown'}).split('\n').join('')}
`;
9 | }
10 | }
11 | hexo.extend.tag.register('progress', postprogress);
12 |
--------------------------------------------------------------------------------
/layout/includes/third-party/card-post-count/artalk.pug:
--------------------------------------------------------------------------------
1 | - const { server, site } = theme.artalk
2 |
3 | script.
4 | (() => {
5 | const getArtalkCount = () => {
6 | const runWidget = () => {
7 | Artalk.LoadCountWidget({
8 | server: '!{server}',
9 | site: '!{site}',
10 | countEl: '.artalk-count'
11 | })
12 | }
13 |
14 | if (typeof Artalk === 'function') runWidget()
15 | else getScript('!{theme.asset.artalk_js}').then(runWidget)
16 | }
17 |
18 |
19 | window.pjax ? getArtalkCount() : window.addEventListener('load', getArtalkCount)
20 | })()
--------------------------------------------------------------------------------
/scripts/helpers/random.js:
--------------------------------------------------------------------------------
1 | hexo.extend.generator.register('random', function (locals) {
2 | const config = hexo.config.random || {}
3 | const posts = []
4 | for (const post of locals.posts.data) {
5 | if (post.random !== false) posts.push(post.path)
6 | }
7 | return {
8 | path: 'js/random.js',
9 | data: `var posts=${JSON.stringify(posts)};
10 | function toRandomPost() {
11 | window.open('/'+posts[Math.floor(Math.random() * posts.length)],"_self");
12 | nav.randompost()
13 | };`
14 | }
15 | })
--------------------------------------------------------------------------------
/layout/includes/widget/card_post_toc.pug:
--------------------------------------------------------------------------------
1 | - let tocNumber = page.toc_number !== undefined ? page.toc_number : theme.toc.number
2 | - let tocExpand = page.toc_expand !== undefined ? page.toc_expand : theme.toc.expand
3 | - let tocExpandClass = tocExpand ? 'is-expand' : ''
4 |
5 | #card-toc.card-widget
6 | .item-headline
7 | i.dys.categroy
8 | span= _p('aside.card_toc')
9 | span.toc-percentage
10 |
11 | if (page.encrypt == true)
12 | .toc-content.toc-div-class(class=tocExpandClass style="display:none")!=toc(page.origin, {list_number: tocNumber})
13 | else
14 | .toc-content(class=tocExpandClass)!=toc(page.content, {list_number: tocNumber})
--------------------------------------------------------------------------------
/layout/includes/head/pwa.pug:
--------------------------------------------------------------------------------
1 | link(rel="manifest" href=url_for(theme.pwa.manifest))
2 | if(theme.pwa.theme_color)
3 | meta(name="msapplication-TileColor" content=theme.pwa.theme_color)
4 | if(theme.pwa.apple_touch_icon)
5 | link(rel="apple-touch-icon" sizes="180x180" href=url_for(theme.pwa.apple_touch_icon))
6 | if(theme.pwa.favicon_32_32)
7 | link(rel="icon" type="image/png" sizes="32x32" href=url_for(theme.pwa.favicon_32_32))
8 | if(theme.pwa.favicon_16_16)
9 | link(rel="icon" type="image/png" sizes="16x16" href=url_for(theme.pwa.favicon_16_16))
10 | if(theme.pwa.mask_icon)
11 | link(rel="mask-icon" href=url_for(theme.pwa.mask_icon) color="#5bbad5")
12 |
--------------------------------------------------------------------------------
/layout/includes/third-party/card-post-count/valine.pug:
--------------------------------------------------------------------------------
1 | script.
2 | (() => {
3 | function loadValine () {
4 | function initValine () {
5 | let initData = {
6 | el: '#vcomment',
7 | appId: '#{theme.valine.appId}',
8 | appKey: '#{theme.valine.appKey}',
9 | serverURLs: '#{theme.valine.serverURLs}'
10 | }
11 |
12 | const valine = new Valine(initData)
13 | }
14 |
15 | if (typeof Valine === 'function') initValine()
16 | else getScript('!{url_for(theme.asset.valine)}').then(initValine)
17 | }
18 |
19 | window.pjax ? loadValine() : window.addEventListener('load', loadValine)
20 | })()
21 |
--------------------------------------------------------------------------------
/scripts/events/init.js:
--------------------------------------------------------------------------------
1 | hexo.extend.filter.register('before_generate', () => {
2 | // Get first two digits of the Hexo version number
3 | const { version, log, locals } = hexo
4 | const hexoVer = version.replace(/(^.*\..*)\..*/, '$1')
5 |
6 | if (hexoVer < 5.3) {
7 | log.error('Please update Hexo to V5.3.0 or higher!')
8 | log.error('請把 Hexo 升級到 V5.3.0 或更高的版本!')
9 | process.exit(-1)
10 | }
11 |
12 | if (locals.get) {
13 | const data = locals.get('data')
14 | if (data && data.butterfly) {
15 | log.error("'butterfly.yml' is deprecated. Please use '_config.butterfly.yml'")
16 | log.error("'butterfly.yml' 已經棄用,請使用 '_config.butterfly.yml'")
17 | process.exit(-1)
18 | }
19 | }
20 | })
--------------------------------------------------------------------------------
/layout/includes/third-party/effect.pug:
--------------------------------------------------------------------------------
1 | if theme.fireworks && theme.fireworks.enable
2 | canvas.fireworks(mobile=`${theme.fireworks.mobile}`)
3 | script(src=url_for(theme.asset.fireworks))
4 |
5 | //- 鼠標特效
6 | if theme.click_heart && theme.click_heart.enable
7 | script#click-heart(src=url_for(theme.asset.click_heart) async mobile=`${theme.click_heart.mobile}`)
8 |
9 | if theme.ClickShowText && theme.ClickShowText.enable
10 | script#click-show-text(
11 | src= url_for(theme.asset.ClickShowText)
12 | data-mobile= `${theme.ClickShowText.mobile}`
13 | data-text= theme.ClickShowText.text.join(",")
14 | data-fontsize= theme.ClickShowText.fontSize
15 | data-random= `${theme.ClickShowText.random}`
16 | async
17 | )
--------------------------------------------------------------------------------
/source/css/_page/categories.styl:
--------------------------------------------------------------------------------
1 | .category-lists
2 | .category-title
3 | font-size: 2.57em
4 |
5 | +maxWidth768()
6 | font-size: 2em
7 |
8 | .category-list
9 | margin-bottom: 0
10 |
11 | a
12 | color: var(--font-color)
13 |
14 | &:hover
15 | color: $text-hover
16 |
17 | .category-list-count
18 | margin-left: 8px
19 | color: $theme-meta-color
20 |
21 | &:before
22 | content: '('
23 |
24 | &:after
25 | content: ')'
26 |
27 | ul
28 | padding: 0 0 0 20px
29 | @extend .list-beauty
30 |
31 | ul
32 | padding-left: 4px
33 |
34 | li
35 | position: relative
36 | margin: 6px 0
37 | padding: .12em .4em .12em 1.4em
38 |
--------------------------------------------------------------------------------
/layout/page.pug:
--------------------------------------------------------------------------------
1 | extends includes/layout.pug
2 |
3 | block content
4 | #page
5 | h1.page-title= page.title
6 |
7 | case page.type
8 | when 'tags'
9 | include includes/page/tags.pug
10 | when 'link'
11 | include includes/page/flink.pug
12 | when 'categories'
13 | include includes/page/categories.pug
14 | when 'about'
15 | include includes/page/about.pug
16 | when 'comments'
17 | include includes/page/comments.pug
18 | default
19 | include includes/page/default-page.pug
20 |
21 | if page.comments !== false && theme.comments && theme.comments.use
22 | - var commentsJsLoad = true
23 | !=partial('includes/third-party/comments/index', {}, {cache: true})
--------------------------------------------------------------------------------
/layout/includes/sidebar.pug:
--------------------------------------------------------------------------------
1 | #sidebar
2 | #menu-mask
3 | #sidebar-menus
4 | .avatar-img.is-center
5 | img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar")
6 | .sidebar-site-data.site-data.is-center
7 | a(href=url_for(config.archive_dir) + '/')
8 | .headline= _p('aside.articles')
9 | .length-num= site.posts.length
10 | a(href=url_for(config.tag_dir) + '/' )
11 | .headline= _p('aside.tags')
12 | .length-num= site.tags.length
13 | a(href=url_for(config.category_dir) + '/')
14 | .headline= _p('aside.categories')
15 | .length-num= site.categories.length
16 |
17 | hr
18 | !=partial('includes/header/menu_item', {}, {cache: true})
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hexo-theme-dynasty",
3 | "version": "1.0.3",
4 | "description": "新一代简洁华美hexo主题",
5 | "main": "package.json",
6 | "keywords": [
7 | "hexo",
8 | "theme",
9 | "butterfly",
10 | "Aegcbx",
11 | "hexo-theme-dimension",
12 | "hexo主题"
13 | ],
14 | "repository": {
15 | "type" : "git",
16 | "url" : "https://github.com/ezgx/hexo-theme-Dynasty.git"
17 | },
18 | "bugs": {
19 | "url": "https://github.com/ezgx/hexo-theme-Dynasty/issues",
20 | "email": "liusx0619@qq.com"
21 | },
22 | "dependencies": {
23 | "hexo-renderer-stylus": "^2.1.0",
24 | "hexo-renderer-pug": "^3.0.0"
25 | },
26 | "homepage": "https://uu.sssu.us/",
27 | "author": "Aegcbx",
28 | "license": "GPL-V3"
29 | }
30 |
--------------------------------------------------------------------------------
/layout/includes/third-party/search/local-search.pug:
--------------------------------------------------------------------------------
1 | #local-search
2 | .search-dialog
3 | nav.search-nav
4 | span#loading-status
5 | button.search-close-button
6 | i.fas.fa-times
7 |
8 | #loading-database.is-center
9 | i.dys.spinner3.spin.ani.fa-pulse
10 | span= ' ' + _p("search.load_data")
11 |
12 | .search-wrap
13 | #local-search-input
14 | .local-search-box
15 | input(placeholder=_p("search.local_search.input_placeholder") type="text").local-search-box--input
16 | hrl.line(style='margin-top:15px; border: 2px dashed var(--search-border-color) !important;')
17 | #local-search-results
18 | hrl.line(style='border: 2px dashed var(--search-border-color) !important;')
19 |
20 | #search-mask
--------------------------------------------------------------------------------
/source/css/_custom/sidebar.css:
--------------------------------------------------------------------------------
1 | #sidebar #sidebar-menus .menus_items .menus_item_child {
2 | margin: 0;
3 | list-style: none;
4 | display: flex;
5 | flex-direction: row;
6 | flex-wrap: wrap
7 | }
8 |
9 | #sidebar #sidebar-menus .menus_item_child li {
10 | width: calc(50% - 8px);
11 | margin: 4px
12 | }
13 |
14 | #sidebar #sidebar-menus .menus_item_child .site-page.child {
15 | display: flex;
16 | flex-direction: column;
17 | align-items: center;
18 | padding: 8px;
19 | border-radius: 12px;
20 | border: var(--style-border-always);
21 | background: var(--zhsher-card-bg);
22 | font-size: 14px
23 | }
24 |
25 | #sidebar #sidebar-menus .menus_items a.site-page, #sidebar .menus_item ul {
26 | padding-left: 0
27 | }
28 |
--------------------------------------------------------------------------------
/layout/includes/widget/card_author.pug:
--------------------------------------------------------------------------------
1 | if theme.aside.card_author.enable
2 | .card-widget.card-info
3 | .card-content
4 | .card-info-avatar.is-center
5 | .author-info__sayhi#author-info__sayhi 晚上好!我是
6 | .author-info__name= config.author
7 | .avatar-img
8 | img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar")
9 | .loading-image-dot
10 | img(src="https://pic.imgdb.cn/item/65032bf5661c6c8e542969ff.webp", alt="")
11 | .banner-button-group
12 | a.banner-button(href="/about/")
13 | i.dys.caozuo-wailian
14 | span.banner-button-te
15 | xt 了解更多
16 | hrl.line(style="margin-top: 10px")
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: 'Close stale issues and PRs'
2 | on:
3 | schedule:
4 | - cron: '30 1 * * *'
5 |
6 | jobs:
7 | stale:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/stale@v5
11 | with:
12 | days-before-issue-stale: 30
13 | days-before-pr-stale: -1
14 | days-before-close: 7
15 | stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.'
16 | close-pr-message: 'This issue has not seen any activity since it was marked stale. Closing.'
17 | stale-issue-label: 'Stale'
18 | exempt-issue-labels: 'pinned,bug,enhancement,documentation,Plan'
19 | operations-per-run: 1000
--------------------------------------------------------------------------------
/layout/includes/page/comments.pug:
--------------------------------------------------------------------------------
1 | #article-container
2 | #maincontent
3 | #form-wrap
4 | img#beforeimg(src='https://pic.imgdb.cn/item/64a3021e1ddac507ccbe96d8.png')
5 | #envelope
6 | form
7 | .formmain
8 | img.headerimg(src=url_for(theme.envelope_comment.cover))
9 | .comments-main
10 | h3.title3=`这里是` + config.author + `的留言板`
11 | .comments
12 | each i in theme.envelope_comment.message
13 | div=`${i}`
14 | .bottomcontent
15 | img.bottomimg(src='https://ae01.alicdn.com/kf/U0968ee80fd5c4f05a02bdda9709b041eE.png')
16 | p.bottomhr=`${theme.envelope_comment.bottom}`
17 | img#afterimg(src='https://pic.imgdb.cn/item/64a3021e1ddac507ccbe968a.png')
18 | != page.content
--------------------------------------------------------------------------------
/source/css/index.styl:
--------------------------------------------------------------------------------
1 | if hexo-config('css_prefix')
2 | @import 'nib'
3 |
4 | @import '_third-party/normalize.min.css'
5 | // project
6 | @import 'var'
7 | @import '_global/*'
8 | @import '_highlight/highlight'
9 | @import '_page/*'
10 | @import '_layout/*'
11 | @import '_tags/*'
12 | @import '_mode/*'
13 | @import '_custom/*'
14 | @import '_custom/*.css'
15 |
16 | // search
17 | if hexo-config('algolia_search.enable')
18 | @import '_search/index'
19 | @import '_search/algolia'
20 |
21 | if hexo-config('local_search') && hexo-config('local_search.enable')
22 | @import '_search/index'
23 | @import '_search/local-search'
24 |
25 | if hexo-config('post_double_row') == true
26 | @import 'post-double-row.css'
27 | else
28 | #recent-posts>.recent-post-item
29 | height: 223px
30 | +maxwidth768()
31 | height: 350px
--------------------------------------------------------------------------------
/scripts/tag/button.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Button
3 | * {% btn url text icon option %}
4 | * option: color outline center block larger
5 | * color : default/blue/pink/red/purple/orange/green
6 | */
7 |
8 | 'use strict'
9 |
10 | const urlFor = require('hexo-util').url_for.bind(hexo)
11 |
12 | function btn (args) {
13 | args = args.join(' ').split(',')
14 | let url = args[0] || ''
15 | let text = args[1] || ''
16 | let icon = args[2] || ''
17 | let option = args[3] || ''
18 |
19 | url = url.trim()
20 | text = text.trim()
21 | icon = icon.trim()
22 | option = option.trim()
23 |
24 | return `${icon.length ? `` : ''}${text.length ? `${text}` : ''}`
26 | }
27 |
28 | hexo.extend.tag.register('btn', btn, { ends: false })
29 |
--------------------------------------------------------------------------------
/source/css/_tags/poem.styl:
--------------------------------------------------------------------------------
1 | @media (min-width: 1200px)
2 | .poem
3 | margin 0 auto
4 | height auto
5 | writing-mode vertical-rl
6 | writing-mode tb-rl
7 | p
8 | text-decoration underline
9 | text-decoration-color rgba(193, 11, 11, 0.72)
10 | text-decoration-style dashed
11 | @font-face
12 | font-family 'Poem'
13 | src url('https://unpkg.zhimg.com/akilar-candyassets/fonts/Poem.ttf')
14 | font-display swap
15 |
16 | .poem
17 | p
18 | font-family 'Poem','KaiTi',sans-serif!important
19 | font-size 25px
20 | text-align center
21 |
22 | .poem-title
23 | font-family 'Poem','KaiTi',sans-serif!important
24 | font-size 2.5em
25 | text-align center
26 |
27 | .poem-author
28 | text-align center!important
29 | font-family 'Poem','KaiTi',sans-serif!important
30 | font-size 16px
31 | color rgb(66, 66, 66)
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # hexo-theme-dynasty
2 |
3 | 
4 | 
5 | 
6 | 
7 |
8 | Demo: 👍 [dynasty](https://uu.sssu.us)
9 |
10 | Docs: 📖 [dynasty Docs](https://dynasty.uu.sssu.us)
11 |
12 | Based on [hexo-theme-butterfly](https://github.com/jerryc127/hexo-theme-butterfly).
13 |
14 | 
15 |
16 |
--------------------------------------------------------------------------------
/scripts/tag/gh.js:
--------------------------------------------------------------------------------
1 | function gh(ghp) {
2 | ghp = ghp.join(' ').split(',');
3 | const p0 = ghp[0].trim();
4 | const p1 = ghp[1].trim();
5 | return `
`;
6 | }
7 | hexo.extend.tag.register('ghp', gh);
8 | function ghp(ghpt) {
9 | ghpt = ghpt.join(' ').split(',');
10 | const p0 = ghpt[0].trim();
11 | const p1 = ghpt[1].trim();
12 | const p2 = ghpt[2].trim();
13 | const p3 = ghpt[3].trim();
14 | return `
`;
15 | }
16 | hexo.extend.tag.register('ghpt', ghp);
--------------------------------------------------------------------------------
/scripts/tag/span.js:
--------------------------------------------------------------------------------
1 | //- 移植自volantis
2 |
3 | 'use strict';
4 |
5 | function postP(args) {
6 | if(/::/g.test(args)){
7 | args = args.join(' ').split('::');
8 | }
9 | else{
10 | args = args.join(' ').split(',');
11 | }
12 | const p0 = args[0].trim();
13 | const p1 = args[1].trim();
14 | return `${p1}
`;
15 | }
16 | function postSpan(args) {
17 | if(/::/g.test(args)){
18 | args = args.join(' ').split('::');
19 | }
20 | else{
21 | args = args.join(' ').split(',');
22 | }
23 | const p0 = args[0].trim();
24 | const p1 = args[1].trim();
25 | return `${p1}`;
26 | }
27 |
28 | hexo.extend.tag.register('p', postP);
29 | hexo.extend.tag.register('span', postSpan);
30 |
31 | function sj(tab) {
32 | tab = tab.join(' ').split(',');
33 | return ``;
34 | }
35 | hexo.extend.tag.register('tab', sj);
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/livere.pug:
--------------------------------------------------------------------------------
1 | script.
2 | function loadLivere () {
3 | if (typeof LivereTower === 'object') {
4 | window.LivereTower.init()
5 | }
6 | else {
7 | (function(d, s) {
8 | var j, e = d.getElementsByTagName(s)[0];
9 | if (typeof LivereTower === 'function') { return; }
10 | j = d.createElement(s);
11 | j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
12 | j.async = true;
13 | e.parentNode.insertBefore(j, e);
14 | })(document, 'script');
15 | }
16 | }
17 |
18 | if ('!{theme.comments.use[0]}' === 'Livere' || !!{theme.comments.lazyload}) {
19 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('lv-container'), loadLivere)
20 | else loadLivere()
21 | }
22 | else {
23 | function loadOtherComment () {
24 | loadLivere()
25 | }
26 | }
--------------------------------------------------------------------------------
/layout/includes/head/preconnect.pug:
--------------------------------------------------------------------------------
1 | link(rel="preconnect" href="//cdn.jsdelivr.net")
2 |
3 | if theme.google_analytics
4 | link(rel="preconnect" href="//www.google-analytics.com" crossorigin='')
5 |
6 | if theme.baidu_analytics
7 | link(rel="preconnect" href="//hm.baidu.com")
8 |
9 | if theme.cnzz_analytics
10 | link(rel="preconnect" href="//s4.cnzz.com")
11 |
12 | if theme.cloudflare_analytics
13 | link(rel="preconnect" href="//static.cloudflareinsights.com")
14 |
15 | if theme.microsoft_clarity
16 | link(rel="preconnect" href="//www.clarity.ms")
17 |
18 | if theme.blog_title_font && theme.blog_title_font.font_link && theme.blog_title_font.font_link.indexOf('//fonts.googleapis.com') != -1
19 | link(rel="preconnect" href="//fonts.googleapis.com" crossorigin='')
20 |
21 | if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv
22 | link(rel="preconnect" href="//busuanzi.ibruce.info")
--------------------------------------------------------------------------------
/layout/includes/page/flink.pug:
--------------------------------------------------------------------------------
1 | #article-container
2 | .flink
3 | if site.data.link
4 | each i in site.data.link
5 | if i.class_name
6 | .flink-name!=i.class_name
7 | .flink-list
8 | .btns.circle.grid5
9 | each item in i.link_list
10 | - var snapshot = item.snapshot ? url_for(item.snapshot) : 'https://s0.wp.com/mshots/v1/' + item.link + '?w=800&h=500'
11 | a.button(href=url_for(item.link) title=item.name target="_blank")
12 | img.no-lightbox(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
13 | #text= item.name
14 | if item.descr
15 | p=item.descr
16 | else
17 | p 博主很懒,未填写网站描述
18 | img.no-lightbox(src=snapshot)
19 | hrl.line
20 |
21 | != page.content
--------------------------------------------------------------------------------
/layout/includes/third-party/card-post-count/fb.pug:
--------------------------------------------------------------------------------
1 | - const fbSDKVer = 'v15.0'
2 | - const fbSDK = theme.messenger.enable ? `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk/xfbml.customerchat.js#xfbml=1&version=${fbSDKVer}` : `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}`
3 |
4 | script.
5 | (()=>{
6 | function loadFBComment () {
7 | if (typeof FB === 'object') FB.XFBML.parse(document.getElementById('recent-posts'))
8 | else {
9 | let ele = document.createElement('script')
10 | ele.setAttribute('src','!{fbSDK}')
11 | ele.setAttribute('async', 'true')
12 | ele.setAttribute('defer', 'true')
13 | ele.setAttribute('crossorigin', 'anonymous')
14 | document.body.appendChild(ele)
15 | }
16 | }
17 | window.pjax ? loadFBComment() : window.addEventListener('load', loadFBComment)
18 | })()
19 |
--------------------------------------------------------------------------------
/source/css/_tags/hide.styl:
--------------------------------------------------------------------------------
1 | // tag-hide
2 | .hide-inline,
3 | .hide-block
4 | & > .hide-button
5 | display: inline-block
6 | padding: 5px 18px
7 | background: $tag-hide-bg
8 | color: var(--white)
9 |
10 | &:hover
11 | background-color: var(--btn-hover-color)
12 |
13 | &.open
14 | display: none
15 |
16 | & + div
17 | display: block
18 |
19 | & + span
20 | display: inline
21 |
22 | & > .hide-content
23 | display: none
24 |
25 | .hide-inline
26 | & > .hide-button
27 | margin: 0 6px
28 |
29 | & > .hide-content
30 | margin: 0 6px
31 |
32 | .hide-block
33 | margin: 0 0 16px
34 |
35 | .toggle
36 | margin-bottom: 20px
37 | border: 1px solid $tag-hide-toggle-bg
38 |
39 | & > .toggle-button
40 | padding: 6px 15px
41 | background: $tag-hide-toggle-bg
42 | color: #1F2D3D
43 |
44 | & > .toggle-content
45 | margin: 30px 24px
46 |
--------------------------------------------------------------------------------
/scripts/tag/note.js:
--------------------------------------------------------------------------------
1 | /**
2 | * note.js
3 | * transplant from hexo-theme-next
4 | * Modify by Jerry
5 | */
6 |
7 | 'use strict'
8 |
9 | function postNote (args, content) {
10 | const styleConfig = hexo.theme.config.note.style
11 | const lastArgs = args[args.length - 1]
12 | if (!(lastArgs === 'flat' || lastArgs === 'modern' || lastArgs === 'simple' || lastArgs === 'disabled')) {
13 | args.push(styleConfig)
14 | }
15 |
16 | let icon = ''
17 | const iconArray = args[args.length - 2]
18 | if (iconArray && iconArray.startsWith('fa')) {
19 | icon = ``
20 | args[args.length - 2] = 'icon-padding'
21 | }
22 |
23 | return `${icon + hexo.render.renderSync({ text: content, engine: 'markdown' })}
`
24 | }
25 |
26 | hexo.extend.tag.register('note', postNote, { ends: true })
27 | hexo.extend.tag.register('subnote', postNote, { ends: true })
28 |
--------------------------------------------------------------------------------
/layout/includes/third-party/chat/chatra.pug:
--------------------------------------------------------------------------------
1 | //- https://chatra.io/help/api/
2 | script.
3 | (function(d, w, c) {
4 | w.ChatraID = '#{theme.chatra.id}';
5 | var s = d.createElement('script');
6 | w[c] = w[c] || function() {
7 | (w[c].q = w[c].q || []).push(arguments);
8 | };
9 | s.async = true;
10 | s.src = 'https://call.chatra.io/chatra.js';
11 | if (d.head) d.head.appendChild(s);
12 | })(document, window, 'Chatra');
13 |
14 | if (!{theme.chat_btn}) {
15 | var chatBtnFn = () => {
16 | var chatBtn = document.getElementById("chat_btn")
17 | chatBtn.addEventListener("click", function(){
18 | Chatra('openChat')
19 | });
20 | }
21 | chatBtnFn()
22 | } else {
23 | if (!{theme.chat_hide_show}) {
24 | function chatBtnHide () {
25 | Chatra('hide')
26 | }
27 | function chatBtnShow () {
28 | Chatra('show')
29 | }
30 | }
31 | }
32 |
33 |
34 |
--------------------------------------------------------------------------------
/layout/includes/third-party/newest-comments/index.pug:
--------------------------------------------------------------------------------
1 | - let { use } = theme.comments
2 |
3 | if use
4 | - let forum,apiKey,userRepo
5 | case use[0]
6 | when 'Valine'
7 | include ./valine.pug
8 | when 'Waline'
9 | include ./waline.pug
10 | when 'Twikoo'
11 | include ./twikoo-comment.pug
12 | when 'Disqus'
13 | - forum = theme.disqus.shortname
14 | - apiKey = theme.disqus.apikey
15 | include ./disqus-comment.pug
16 | when 'Disqusjs'
17 | - forum = theme.disqusjs.shortname
18 | - apiKey = theme.disqusjs.apikey
19 | include ./disqus-comment.pug
20 | when 'Gitalk'
21 | - let { repo,owner } = theme.gitalk
22 | - userRepo = owner + '/' + repo
23 | include ./github-issues.pug
24 | when 'Utterances'
25 | - userRepo = theme.utterances.repo
26 | include ./github-issues.pug
27 | when 'Remark42'
28 | include ./remark42.pug
29 | when 'Artalk'
30 | include ./artalk.pug
--------------------------------------------------------------------------------
/scripts/tag/gallery.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * galleryGroup and allery
4 | */
5 |
6 | 'use strict'
7 |
8 | const urlFor = require('hexo-util').url_for.bind(hexo)
9 |
10 | function gallery (args, content) {
11 | return `${hexo.render.renderSync({ text: content, engine: 'markdown' }).split('\n').join('')}
12 |
`
13 | }
14 |
15 | function galleryGroup (args) {
16 | const name = args[0]
17 | const desrc = args[1]
18 | const url = urlFor(args[2])
19 | const img = urlFor(args[3])
20 |
21 | return `
22 |
23 |
24 |
25 | ${name}
26 | ${desrc}
27 |
28 |
29 |
30 | `
31 | }
32 |
33 | hexo.extend.tag.register('gallery', gallery, { ends: true })
34 | hexo.extend.tag.register('galleryGroup', galleryGroup)
35 |
--------------------------------------------------------------------------------
/source/css/_highlight/highlight/index.styl:
--------------------------------------------------------------------------------
1 | if $highlight_theme != false
2 | @require 'diff'
3 |
4 | #article-container
5 | figure.highlight
6 | .line
7 | if wordWrap
8 | &:before
9 | display: inline-block
10 | padding: 0 6px 0 0
11 | min-width: 30px
12 | color: var(--hlnumber-color)
13 | content: counter(line)
14 | counter-increment: line
15 | text-align: left
16 |
17 | &.marked
18 | background-color: $highlight-selection
19 |
20 | table
21 | display: block
22 | overflow: auto
23 | border: none
24 |
25 | td
26 | padding: 0
27 | border: none
28 |
29 | .gutter pre
30 | padding-right: 10px
31 | padding-left: 10px
32 | background-color: var(--hlnumber-bg)
33 | color: var(--hlnumber-color)
34 | text-align: right
35 |
36 | .code pre
37 | padding-right: 10px
38 | padding-left: 10px
39 | width: 100%
40 |
--------------------------------------------------------------------------------
/layout/includes/widget/index.pug:
--------------------------------------------------------------------------------
1 | #aside-content.aside-content
2 | //- post
3 | if is_post()
4 | - const tocStyle = page.toc_style_simple
5 | - const tocStyleVal = tocStyle === true || tocStyle === false ? tocStyle : theme.toc.style_simple
6 | if showToc && tocStyleVal
7 | .sticky_layout
8 | include ./card_post_toc.pug
9 | else
10 | !=partial('includes/widget/card_author', {}, {cache: true})
11 | .sticky_layout
12 | if showToc
13 | include ./card_post_toc.pug
14 | else
15 | #card-toc.card-widget
16 | .item-headline
17 | i.dys.categroy
18 | span 抱歉,该文章无目录
19 | hrl.line
20 | !=partial('includes/widget/card_tags', {}, {cache: true})
21 | else
22 | //- page
23 | !=partial('includes/widget/card_author', {}, {cache: true})
24 |
25 | .sticky_layout
26 | if showToc
27 | include ./card_post_toc.pug
28 | !=partial('includes/widget/card_tags', {}, {cache: true})
--------------------------------------------------------------------------------
/scripts/events/welcome.js:
--------------------------------------------------------------------------------
1 | hexo.on('ready', () => {
2 | const { version } = require('../../package.json')
3 | hexo.log.info(`╔═════════════════════════════════════════════════════════════════════════════╗
4 |
5 | ██████╗ ██╗ ██╗ ███══╗ ██║ █████╗ ██████╗ █████████╗ ██╗ ██╗
6 | ██╔═══██║ ╚██╗ ██╔╝ ██║██║ ██║ ██╔════██║ ██╔════╝ ██╔═══╝ ╚██╗ ██╔╝
7 | ██║ ██║ ╚████╔╝ ██║██╚╗ ██║ ██║ ██║ ██║ ██║ ╚████╔╝
8 | ██║ ██║ ╚██╔╝ ██║ ██╚╗██║ █████████║ ███████╗ ██║ ╚██╔╝
9 | ██║ ██║ ██║ ██║ ██║██║ ██╔════██║ ╚════██║ ██║ ██║
10 | ██║ ██║ ██║ ██║ ██║██║ ██║ ██║ ██║ ██║ ██║
11 | ██████╔═╝ ██║ ██║ ███║ ██║ ██║ ██████╔╝ ██║ ██║
12 | ╚═════╝ ╚═╝ ╚═╝ ╚══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
13 | ${version}
14 | ╚═════════════════════════════════════════════════════════════════════════════╝`)
15 | })
16 |
--------------------------------------------------------------------------------
/scripts/filters/post_lazyload.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * lazyload
4 | * replace src to data-lazy-src
5 | */
6 |
7 | 'use strict'
8 |
9 | const urlFor = require('hexo-util').url_for.bind(hexo)
10 |
11 | function lazyload (htmlContent) {
12 | const bg = hexo.theme.config.lazyload.placeholder ? urlFor(hexo.theme.config.lazyload.placeholder) : 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
13 | return htmlContent.replace(/( {
24 | const config = hexo.theme.config.lazyload
25 | if (!config.enable) return
26 | if (config.field !== 'post') return
27 | data.content = lazyload.call(this, data.content)
28 | return data
29 | })
30 |
--------------------------------------------------------------------------------
/source/css/_search/index.styl:
--------------------------------------------------------------------------------
1 | .search-dialog
2 | position: fixed
3 | top: 0
4 | left: 0
5 | z-index: 1001
6 | display: none
7 | padding: 20px
8 | width: 100%
9 | border-radius: 8px
10 |
11 | hr
12 | margin: 20px auto
13 |
14 | .search-nav
15 | margin: 0 0 14px
16 | color: var(--heo-theme)
17 | font-size: 1.4em
18 | line-height: 1
19 |
20 | .search-dialog-title
21 | margin-right: 10px
22 |
23 | .search-close-button
24 | float: right
25 | color: $grey
26 | transition: color .2s ease-in-out
27 |
28 | &:hover
29 | color: var(--heo-theme)
30 |
31 | #search-mask
32 | position: fixed
33 | top: 0
34 | right: 0
35 | bottom: 0
36 | left: 0
37 | z-index: 1000
38 | display: none
39 | background: #ffffff7a
40 |
41 | [data-theme="dark"]
42 | #search-mask
43 | background: #0000007a
44 |
45 | div#search-mask::after
46 | content: '-- 点击空白处关闭 --'
47 | position: fixed
48 | bottom: 0
49 | font-weight: 100
50 | text-align: center
51 | width: 100%
--------------------------------------------------------------------------------
/scripts/tag/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 |
--------------------------------------------------------------------------------
/layout/includes/third-party/subtitle.pug:
--------------------------------------------------------------------------------
1 | - const { effect,loop,source,sub,startDelay,typeSpeed,backSpeed } = theme.subtitle
2 | - let subContent = sub || new Array()
3 | - subContent = subContent.length ? subContent : new Array(config.subtitle)
4 | //- script.
5 | function subtitleType () {
6 | if (!{effect}) {
7 | window.typed = new Typed("#subtitle", {
8 | strings: !{JSON.stringify(subContent)},
9 | startDelay: 10,
10 | typeSpeed: 80,
11 | loop: !{loop},
12 | showCursor: false,
13 | backSpeed: 70
14 | })
15 | }
16 | }
17 | if (!{effect}) {
18 | if (typeof Typed === 'function') {
19 | subtitleType()
20 | } else {
21 | getScript('!{url_for(theme.asset.typed)}').then(subtitleType)
22 | }
23 | }
24 |
25 | script(src="/js/typed.js")
26 | script.
27 | var typed = new Typed("#subtitle", {
28 | strings: !{JSON.stringify(subContent)},
29 | startDelay: 10,
30 | typeSpeed: 80,
31 | loop: !{loop},
32 | showCursor: false,
33 | backSpeed: 70
34 | });
35 |
36 | //- !{JSON.stringify(subContent)}
--------------------------------------------------------------------------------
/source/css/_layout/rightside.styl:
--------------------------------------------------------------------------------
1 | #rightside
2 | position: fixed
3 | right: -48px
4 | bottom: $rightside-bottom
5 | z-index: 100
6 | opacity: 0
7 | transition: all .5s
8 |
9 | #rightside-config-hide
10 | height: 0
11 | opacity: 0
12 | transition: transform .4s
13 | transform: translate(45px, 0)
14 |
15 | &.show
16 | height: auto
17 | opacity: 1
18 | transform: translate(0, 0)
19 |
20 | &.status
21 | height: auto
22 | opacity: 1
23 |
24 | & > div
25 | & > button,
26 | & > a
27 | display: block
28 | margin-bottom: 5px
29 | width: w = 35px
30 | height: w
31 | border-radius: 5px
32 | background-color: var(--btn-bg)
33 | color: var(--btn-color)
34 | text-align: center
35 | font-size: 16px
36 | line-height: w
37 |
38 | &:hover
39 | background-color: var(--btn-hover-color)
40 |
41 | #mobile-toc-button
42 | display: none
43 |
44 | +maxWidth900()
45 | display: block
46 |
47 | +maxWidth900()
48 | #hide-aside-btn
49 | display: none
50 |
--------------------------------------------------------------------------------
/layout/includes/widget/card_webinfo.pug:
--------------------------------------------------------------------------------
1 | .card-widget.card-webinfo
2 | .item-headline(style='width:fit-content;margin:auto;')
3 | i.dys.shujukanban(style='font-size:20px;margin-right:5px')
4 | span= _p('aside.card_webinfo.headline')
5 | .webinfo
6 | .webinfo-item
7 | .item-name
8 | i.dys.-disk(style='font-size:20px')
9 | .text 文章总数
10 | .item-count= site.posts.length
11 | .webinfo-item
12 | .item-name
13 | i.dys.view(style='font-size:20px')
14 | .text 总访问量
15 | .item-count#busuanzi_value_site_pv
16 | .webinfo-item
17 | .item-name
18 | i.dys.groupico(style='font-size:20px')
19 | .text 访问人次
20 | .item-count#busuanzi_value_site_uv
21 | .webinfo-item
22 | .item-name
23 | i.dys.postico(style='font-size:20px')
24 | .text 全站字数
25 | .item-count=totalcount(site)
26 | .webinfo-item
27 | .item-name
28 | i.dys.upload(style='font-size:20px')
29 | .text 最后更新
30 | .item-count#last-push-date(data-lastPushDate=date_xml(Date.now()))
31 | i.dys.spinner3.spin.ani
32 |
33 |
--------------------------------------------------------------------------------
/layout/includes/head/config_site.pug:
--------------------------------------------------------------------------------
1 | -
2 | const titleVal = pageTitle.replace(/'/ig,"\\'")
3 |
4 | let isHighlightShrink
5 | if (theme.highlight_shrink == 'none') isHighlightShrink = 'undefined'
6 | else if (page.highlight_shrink === true || page.highlight_shrink === false) isHighlightShrink = page.highlight_shrink
7 | else isHighlightShrink = theme.highlight_shrink
8 |
9 | var showToc = false
10 | if (theme.aside.enable && page.aside !== false) {
11 | let tocEnable = false
12 | if (is_post()) {
13 | if (theme.toc.post) tocEnable = true
14 | } else if (is_page()) {
15 | if (theme.toc.page) tocEnable = true
16 | }
17 | const pageToc = page.toc === true || page.toc === false ? page.toc : tocEnable
18 | showToc = pageToc && (toc(page.content) !== '' || page.encrypt == true )
19 | }
20 | -
21 |
22 | script#config-diff.
23 | var GLOBAL_CONFIG_SITE = {
24 | title: '!{titleVal}',
25 | isPost: !{is_post()},
26 | isHome: !{is_home()},
27 | isHighlightShrink: !{isHighlightShrink},
28 | isToc: !{showToc},
29 | postUpdate: '!{full_date(page.updated)}'
30 | }
31 |
--------------------------------------------------------------------------------
/layout/includes/third-party/chat/crisp.pug:
--------------------------------------------------------------------------------
1 | script.
2 | window.$crisp = [];
3 | window.CRISP_WEBSITE_ID = "!{theme.crisp.website_id}";
4 | (function () {
5 | d = document;
6 | s = d.createElement("script");
7 | s.src = "https://client.crisp.chat/l.js";
8 | s.async = 1;
9 | d.getElementsByTagName("head")[0].appendChild(s);
10 | })();
11 | $crisp.push(["safe", true])
12 |
13 | if (!{theme.chat_btn}) {
14 | $crisp.push(["do", "chat:hide"])
15 | $crisp.push(["on", "chat:closed", function() {
16 | $crisp.push(["do", "chat:hide"])
17 | }])
18 | var chatBtnFn = () => {
19 | var chatBtn = document.getElementById("chat_btn")
20 | chatBtn.addEventListener("click", function(){
21 | $crisp.push(["do", "chat:show"])
22 | $crisp.push(["do", "chat:open"])
23 |
24 | });
25 | }
26 | chatBtnFn()
27 | } else {
28 | if (!{theme.chat_hide_show}) {
29 | function chatBtnHide () {
30 | $crisp.push(["do", "chat:hide"])
31 | }
32 | function chatBtnShow () {
33 | $crisp.push(["do", "chat:show"])
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/scripts/tag/btns.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function postBtns(args, content) {
4 | return `
5 | ${content}
6 |
`;
7 | }
8 |
9 | function postCell(args, content) {
10 | args = args.join(' ').split(',')
11 | let text = args[0] || ''
12 | let url = args[1] || ''
13 | text = text.trim()
14 | url = url.trim()
15 | if (url.length > 0) {
16 | url = "href='" + url + "'"
17 | }
18 | let icon = ''
19 | let img = 'https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@3/img/placeholder/d570170f4f12e1ee829ca0e85a7dffeb77343a.svg'
20 | if (args.length > 2) {
21 | if (args[2].indexOf(' fa-') > -1) {
22 | icon = args[2].trim()
23 | } else {
24 | img = args[2].trim()
25 | }
26 | }
27 | if (icon.length > 0) {
28 | return `${text}`
29 | } else {
30 | return `
${text}`
31 | }
32 | }
33 |
34 | hexo.extend.tag.register('btns', postBtns, {ends: true});
35 | hexo.extend.tag.register('cell', postCell);
36 |
--------------------------------------------------------------------------------
/source/css/_tags/link.styl:
--------------------------------------------------------------------------------
1 | .link_card
2 | display: flex
3 | margin: 10px 0
4 | color: var(--font-color) !important
5 | text-decoration: none !important
6 | background: var(--reward-pop)
7 | border-radius: 10px
8 | padding: 12px
9 | &:hover
10 | background: #4976f5
11 | color: white !important
12 | .link_icon,.link_content
13 | height: 4rem
14 | .link_icon
15 | img,svg
16 | height: 4rem
17 | width: 4rem
18 | .link_content
19 | margin-left: 1rem
20 | width: calc(100% - 6rem)
21 | overflow: hidden
22 | line-height: 1.5
23 | display: flex
24 | flex-direction: column
25 | justify-content: center
26 | .link_title
27 | font-weight: bold
28 | font-size: 1.2rem
29 | .link_title,.link_desc
30 | word-break: break-all
31 | overflow:hidden
32 | text-overflow: ellipsis
33 | &:not(:has(.link_desc)) .link_title
34 | display:-webkit-box
35 | -webkit-box-orient:vertical
36 | -webkit-line-clamp:2
37 | .link_desc
38 | opacity: .6
39 | .link_desc,&:has(.link_desc) .link_title
40 | white-space: nowrap
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/js.pug:
--------------------------------------------------------------------------------
1 | each name in theme.comments.use
2 | case name
3 | when 'Valine'
4 | !=partial('includes/third-party/comments/valine', {}, {cache: true})
5 | when 'Disqus'
6 | include ./disqus.pug
7 | when 'Disqusjs'
8 | include ./disqusjs.pug
9 | when 'Livere'
10 | !=partial('includes/third-party/comments/livere', {}, {cache: true})
11 | when 'Gitalk'
12 | include ./gitalk.pug
13 | when 'Utterances'
14 | !=partial('includes/third-party/comments/utterances', {}, {cache: true})
15 | when 'Twikoo'
16 | !=partial('includes/third-party/comments/twikoo', {}, {cache: true})
17 | when 'Waline'
18 | !=partial('includes/third-party/comments/waline', {}, {cache: true})
19 | when 'Giscus'
20 | !=partial('includes/third-party/comments/giscus', {}, {cache: true})
21 | when 'Facebook Comments'
22 | include ./facebook_comments.pug
23 | when 'Remark42'
24 | !=partial('includes/third-party/comments/remark42', {}, {cache: true})
25 | when 'Artalk'
26 | !=partial('includes/third-party/comments/artalk', {}, {cache: true})
--------------------------------------------------------------------------------
/layout/includes/mixins/article-sort.pug:
--------------------------------------------------------------------------------
1 | mixin articleSort(posts)
2 | .article-sort
3 | - var year
4 | - posts.each(function (article) {
5 | - let tempYear = date(article.date, 'YYYY')
6 | - let no_cover = article.cover === false || !theme.cover.archives_enable ? 'no-article-cover' : ''
7 | - let title = article.title || _p('no_title')
8 | if tempYear !== year
9 | - year = tempYear
10 | .article-sort-item.year= year
11 | .article-sort-item(class=no_cover)
12 | if article.cover && theme.cover.archives_enable
13 | a.article-sort-item-img(href=url_for(article.path) title=title)
14 | img(src=url_for(article.cover) alt=title onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'`)
15 | .article-sort-item-info
16 | .article-sort-item-time
17 | i.dys.time
18 | time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))= date(article.date, config.date_format)
19 | a.article-sort-item-title(href=url_for(article.path) title=title)= title
20 | - })
--------------------------------------------------------------------------------
/source/css/_custom/tag.styl:
--------------------------------------------------------------------------------
1 | .tag-cloud-list a
2 | color: #fff
3 | width: 47%
4 | border-radius: 10px
5 | padding: 2px 10px
6 | margin-bottom: 10px
7 | font-size: 20px !important
8 | margin-right: 3%
9 | background: var(--heo-theme)
10 |
11 | .card-tag-cloud a
12 | color: var(--heo-font) !important
13 | border-bottom: 2px dashed var(--border)
14 | padding: 3px 10px !important
15 | margin-bottom: 2%
16 | font-size: 16px !important
17 |
18 | .card-tag-cloud, #aside-cat-list, .card-archive-list
19 | max-height: 135px
20 | overflow-y: scroll
21 | font-weight: 600
22 |
23 | .card-tag-cloud, #aside-cat-list, .card-archive-list
24 | &::-webkit-scrollbar
25 | display: none
26 |
27 | li.card-category-list-item, li.card-archive-list-item
28 | width: 48%
29 | border-bottom: 2px dashed var(--border)
30 | margin-bottom: 2%
31 | margin-right: 2%
32 | display: inline-block
33 |
34 | #aside-content .card-archives ul.card-archive-list>.card-archive-list-item a, #aside-content .card-categories ul.card-category-list>.card-category-list-item a
35 | color: var(--heo-font) !important
--------------------------------------------------------------------------------
/layout/post.pug:
--------------------------------------------------------------------------------
1 | extends includes/layout.pug
2 |
3 | block content
4 | #post.maininner
5 | if top_img === false
6 | include includes/header/post-info.pug
7 |
8 | article#article-container.post-content!=page.content
9 | include includes/post/post-copyright.pug
10 | .tag_share
11 | if (theme.post_meta.post.tags)
12 | .post-meta__tag-list
13 | each item, index in page.tags.data
14 | a(href=url_for(item.path)).post-meta__tags #[=item.name]
15 | include includes/third-party/share/index.pug
16 |
17 | if theme.reward.enable && theme.reward.QR_code
18 | !=partial('includes/post/reward', {}, {cache: true})
19 |
20 | //- ad
21 | if theme.ad && theme.ad.post
22 | .ads-wrap!=theme.ad.post
23 |
24 | if theme.post_pagination
25 | include includes/pagination.pug
26 | if theme.related_post && theme.related_post.enable
27 | != related_posts(page,site.posts)
28 |
29 | if page.comments !== false && theme.comments && theme.comments.use
30 | - var commentsJsLoad = true
31 | !=partial('includes/third-party/comments/index', {}, {cache: true})
32 |
--------------------------------------------------------------------------------
/layout/includes/header/menu_item.pug:
--------------------------------------------------------------------------------
1 | if theme.nav.menu
2 | .menus_items#menus-items
3 | each value, label in theme.nav.menu
4 | if typeof value !== 'object'
5 | .menus_item
6 | - const valueArray = value.split('||')
7 | a.site-page(href=url_for(trim(valueArray[0])))
8 | if valueArray[1]
9 | i(class=trim(valueArray[1]))
10 | span=' '+label
11 | else
12 | .menus_item
13 | - const labelArray = label.split('||')
14 | - const hideClass = labelArray[2] && trim(labelArray[2]) === 'hide' ? 'hide' : ''
15 | a.site-page.group(class=`${hideClass}` href='javascript:void(0);')
16 | if labelArray[1]
17 | i(class=trim(labelArray[1]))
18 | span=' '+ trim(labelArray[0])
19 | i.dys.arrowdown
20 | ul.menus_item_child
21 | each val,lab in value
22 | - const valArray = val.split('||')
23 | li
24 | a.site-page.child(href=url_for(trim(valArray[0])))
25 | if valArray[1]
26 | i(class=trim(valArray[1]))
27 | span=' '+ lab
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/valine.pug:
--------------------------------------------------------------------------------
1 | - let emojiMaps = '""'
2 | if site.data.valine
3 | - emojiMaps = JSON.stringify(site.data.valine)
4 |
5 | script.
6 | function loadValine () {
7 | function initValine () {
8 | const valine = new Valine(Object.assign({
9 | el: '#vcomment',
10 | appId: '#{theme.valine.appId}',
11 | appKey: '#{theme.valine.appKey}',
12 | avatar: '#{theme.valine.avatar}',
13 | serverURLs: '#{theme.valine.serverURLs}',
14 | emojiMaps: !{emojiMaps},
15 | path: window.location.pathname,
16 | visitor: #{theme.valine.visitor}
17 | }, !{JSON.stringify(theme.valine.option)}))
18 | }
19 |
20 | if (typeof Valine === 'function') initValine()
21 | else getScript('!{url_for(theme.asset.valine)}').then(initValine)
22 | }
23 |
24 | if ('!{theme.comments.use[0]}' === 'Valine' || !!{theme.comments.lazyload}) {
25 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('vcomment'),loadValine)
26 | else setTimeout(loadValine, 0)
27 | } else {
28 | function loadOtherComment () {
29 | loadValine()
30 | }
31 | }
32 |
33 |
34 |
--------------------------------------------------------------------------------
/layout/includes/swiper.pug:
--------------------------------------------------------------------------------
1 | - var fposts = theme.hometop.featured_posts
2 |
3 | .recent-post-item#swiperBar(style='border:none!important;')
4 | #ark-swiper-container
5 | .swiper-wrapper.dht-swiper-wrapper
6 | each item, i in fposts.posts
7 | //- 内容版块
8 | .swiper-slide.dht-swiper-item(onclick=`pjax.loadUrl('${url_for(item.link)}')`)
9 | //- 封面
10 | .dht-swiper-item-cover(onclick=`pjax.loadUrl('${url_for(item.link)}')`)
11 | img.article-cover(src=item.cover title='')
12 | //- 标题和描述
13 | .dht-swiper-item-info(onclick=`pjax.loadUrl('${url_for(item.link)}')`)
14 | a.dht-swiper-item-title
15 | .dht-swiper-item-title-link= item.title
16 | a.dht-swiper-item-description
17 | .dht-swiper-item-description-text=item.descr
18 | .swiper-scrollbar
19 | .swiper-button-prev
20 | .swiper-button-next
21 |
22 | style.
23 | #ark-swiper-container .swiper-scrollbar-drag {
24 | background: linear-gradient(to left, #ff4500, #ffa500, #ffd700, #90ee90, #0ff, #1e90ff, #9370db, #ff69b4, #ff4500);
25 | box-shadow: 0 0 0 2px #fff
26 | }
--------------------------------------------------------------------------------
/source/css/_tags/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/_highlight/prismjs/line-number.styl:
--------------------------------------------------------------------------------
1 | #article-container
2 | pre[class*='language-']
3 | &.line-numbers
4 | position: relative
5 | padding-left: 3.8em
6 | counter-reset: linenumber
7 | line-height: $line-height-code-block
8 |
9 | > code
10 | position: relative
11 | line-height: $line-height-code-block
12 |
13 | if hexo-config('code_word_wrap')
14 | white-space: pre-wrap
15 | else
16 | white-space: inherit
17 | word-wrap: normal
18 | word-break: normal
19 | overflow-wrap: normal
20 |
21 | .line-numbers-rows
22 | position: absolute
23 | top: 0
24 | left: -3.8em
25 | width: 3em
26 | letter-spacing: -1px
27 | font-size: 100%
28 | pointer-events: none
29 | user-select: none
30 |
31 | & > span
32 | display: block
33 | counter-increment: linenumber
34 | pointer-events: none
35 |
36 | &:before
37 | display: block
38 | padding-right: .8em
39 | color: var(--hlnumber-color)
40 | content: counter(linenumber)
41 | text-align: right
42 |
--------------------------------------------------------------------------------
/source/css/_page/common.styl:
--------------------------------------------------------------------------------
1 | #body-wrap
2 | display: flex
3 | flex-direction: column
4 | min-height: 100vh
5 |
6 | .layout
7 | display: flex
8 | flex: 1 auto
9 | margin: 0 auto
10 | padding: 40px 15px
11 | max-width: 1200px
12 | width: 100%
13 |
14 | +maxWidth900()
15 | flex-direction: column
16 |
17 | +maxWidth768()
18 | padding: 20px 15px
19 |
20 | & > div:first-child:not(.recent-posts)
21 | @extend .cardHover
22 | align-self: flex-start
23 | padding: 50px 40px
24 |
25 | +maxWidth768()
26 | padding: 36px 14px
27 |
28 | & > div:first-child
29 | width: 74%
30 | transition: all .3s
31 |
32 | +maxWidth900()
33 | width: 100% !important
34 |
35 | if hexo-config('aside.position') == 'left'
36 | +minWidth900()
37 | order: 2
38 |
39 | // 隱藏aside
40 | &.hide-aside
41 | max-width: 1000px
42 |
43 | +minWidth2000()
44 | max-width: 1300px
45 |
46 | & > div
47 | width: 100% !important
48 |
49 | // for apple device
50 | .apple
51 | #page-header.full_page
52 | background-attachment: scroll !important
53 |
54 | .recent-post-item,
55 | .avatar-img,
56 | .flink-item-icon
57 | transform: translateZ(0)
58 |
--------------------------------------------------------------------------------
/layout/includes/third-party/card-post-count/twikoo.pug:
--------------------------------------------------------------------------------
1 | script.
2 | (() => {
3 | const getCommentUrl = () => {
4 | const eleGroup = document.querySelectorAll('#recent-posts .article-title')
5 | let urlArray = []
6 | eleGroup.forEach(i=>{
7 | urlArray.push(i.getAttribute('href'))
8 | })
9 | return urlArray
10 | }
11 |
12 | const getCount = () => {
13 | const runTwikoo = () => {
14 | twikoo.getCommentsCount({
15 | envId: '!{theme.twikoo.envId}',
16 | region: '!{theme.twikoo.region}',
17 | urls: getCommentUrl(),
18 | includeReply: false
19 | }).then(function (res) {
20 | document.querySelectorAll('#recent-posts .twikoo-count').forEach((item,index) => {
21 | item.innerText = res[index].count
22 | })
23 | }).catch(function (err) {
24 | console.log(err)
25 | })
26 | }
27 |
28 | if (typeof twikoo === 'object') {
29 | runTwikoo()
30 | } else {
31 | getScript('!{url_for(theme.asset.twikoo)}').then(runTwikoo)
32 | }
33 | }
34 |
35 | window.pjax ? getCount() : window.addEventListener('load', getCount)
36 |
37 | })()
--------------------------------------------------------------------------------
/layout/includes/third-party/chat/gitter.pug:
--------------------------------------------------------------------------------
1 | if theme.chat_btn
2 | script.
3 | ((window.gitter = {}).chat = {}).options = {
4 | disableDefaultChat: true,
5 | };
6 | document.addEventListener('gitter-sidecar-ready', (e) => {
7 | const GitterChat = e.detail.Chat
8 | let chat
9 |
10 | function initGitter () {
11 | chat = new GitterChat({
12 | room: '#{theme.gitter.room}',
13 | activationElement: '#chat_btn'
14 | });
15 | }
16 |
17 | initGitter()
18 |
19 | document.addEventListener('pjax:complete', () => {
20 | chat.destroy()
21 | initGitter()
22 | })
23 |
24 | })
25 | else
26 | script.
27 | ((window.gitter = {}).chat = {}).options = {
28 | room: '#{theme.gitter.room}',
29 | };
30 |
31 | if (!{theme.chat_hide_show}) {
32 | function chatBtnHide () {
33 | document.getElementsByClassName('gitter-open-chat-button')[0].style.display= 'none'
34 | }
35 |
36 | function chatBtnShow () {
37 | document.getElementsByClassName('gitter-open-chat-button')[0].style.display= 'block'
38 | }
39 | }
40 |
41 | script(src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer)
42 |
--------------------------------------------------------------------------------
/layout/includes/third-party/math/mermaid.pug:
--------------------------------------------------------------------------------
1 | script.
2 | (() => {
3 | const $mermaidWrap = document.querySelectorAll('#article-container .mermaid-wrap')
4 | if ($mermaidWrap.length) {
5 | window.runMermaid = () => {
6 | window.loadMermaid = true
7 | const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{theme.mermaid.theme.dark}' : '!{theme.mermaid.theme.light}'
8 |
9 | Array.from($mermaidWrap).forEach((item, index) => {
10 | const mermaidSrc = item.firstElementChild
11 | const mermaidThemeConfig = '%%{init:{ \'theme\':\'' + theme + '\'}}%%\n'
12 | const mermaidID = 'mermaid-' + index
13 | const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent
14 | mermaid.mermaidAPI.render(mermaidID, mermaidDefinition, (svgCode) => {
15 | mermaidSrc.insertAdjacentHTML('afterend', svgCode)
16 | })
17 | })
18 | }
19 |
20 | const loadMermaid = () => {
21 | window.loadMermaid ? runMermaid() : getScript('!{url_for(theme.asset.mermaid)}').then(runMermaid)
22 | }
23 |
24 | window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
25 | }
26 | })()
--------------------------------------------------------------------------------
/scripts/tag/reference.js:
--------------------------------------------------------------------------------
1 | /*
2 | {% referto 'id','literature' %}
3 | {% referfrom 'id','literature','url' %}
4 | */
5 | 'use strict'
6 | const urlFor = require('hexo-util').url_for.bind(hexo)
7 |
8 | function referto (args) {
9 | args = args.join(' ').split(',')
10 | let referid = args[0]
11 | let literature = args[1]
12 | return `${referid}${literature}参考资料`;
13 | }
14 |
15 |
16 | function referfrom (args) {
17 | args = args.join(' ').split(',')
18 | let fromid = args[0]
19 | let fromliterature = args[1]
20 | let referurl = args[2] ? urlFor(args[2]) : 'javascript:void'
21 | return ``;
22 |
23 | }
24 |
25 | hexo.extend.tag.register('referto',referto);
26 | hexo.extend.tag.register('referfrom',referfrom);
27 |
--------------------------------------------------------------------------------
/layout/includes/third-party/chat/tidio.pug:
--------------------------------------------------------------------------------
1 | script(src=`//code.tidio.co/${theme.tidio.public_key}.js` async)
2 |
3 | if theme.chat_btn
4 | script.
5 | function onTidioChatApiReady() {
6 | window.tidioChatApi.hide();
7 | window.tidioChatApi.on("close", function() {
8 | window.tidioChatApi.hide();
9 | });
10 | }
11 | if (window.tidioChatApi) {
12 | window.tidioChatApi.on("ready", onTidioChatApiReady);
13 | } else {
14 | document.addEventListener("tidioChat-ready", onTidioChatApiReady);
15 | }
16 |
17 | var chatBtnFn = () => {
18 | document.getElementById("chat_btn").addEventListener("click", function(){
19 | window.tidioChatApi.show();
20 | window.tidioChatApi.open();
21 | });
22 | }
23 | chatBtnFn()
24 |
25 | else if theme.chat_hide_show
26 | script.
27 | function chatBtnHide () {
28 | if (window.tidioChatApi) {
29 | //- window.tidioChatApi.hide();
30 | document.getElementById('tidio-chat').style.display= 'none'
31 | }
32 | }
33 |
34 | function chatBtnShow () {
35 | if (window.tidioChatApi) {
36 | //- window.tidioChatApi.show();
37 | document.getElementById('tidio-chat').style.display= 'block'
38 | }
39 | }
40 |
41 |
42 |
--------------------------------------------------------------------------------
/layout/includes/loading/index.pug:
--------------------------------------------------------------------------------
1 | if theme.preloader.enable
2 | #loading-box(onclick='document.getElementById("loading-box").classList.add("loaded")')
3 | .loading-bg
4 | div.loading-img
5 | .loading-image-dot
6 |
7 | script.
8 | const preloader = {
9 | endLoading: () => {
10 | document.body.style.overflow = 'auto';
11 | document.getElementById('loading-box').classList.add("loaded")
12 | new Vue({
13 | data: function () {
14 | this.$notify({
15 | title: "请发表合法评论",
16 | message: "在评论发表违法内容者后果自负,站长概不负责,最终解释权归站长所有,发表评论即代表同意上述内容",
17 | position: 'top-left',
18 | offset: 50,
19 | showClose: true,
20 | type: "warning",
21 | duration: 4000
22 | });
23 | }
24 | })
25 | },
26 | initLoading: () => {
27 | document.body.style.overflow = '';
28 | document.getElementById('loading-box').classList.remove("loaded")
29 |
30 | }
31 | }
32 | window.addEventListener('load',()=> { preloader.endLoading() })
33 | document.addEventListener('pjax:send', () => { preloader.initLoading() })
34 | document.addEventListener('pjax:complete', () => { preloader.endLoading() })
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/waline.pug:
--------------------------------------------------------------------------------
1 | - const { serverURL, option, pageview } = theme.waline
2 | - const { lazyload, count, use } = theme.comments
3 |
4 | script.
5 | function loadWaline () {
6 | function insertCSS () {
7 | const link = document.createElement("link")
8 | link.rel = "stylesheet"
9 | link.href = "!{url_for(theme.asset.waline_css)}"
10 | document.head.appendChild(link)
11 | }
12 |
13 | function initWaline () {
14 | const waline = Waline.init(Object.assign({
15 | el: '#waline-wrap',
16 | serverURL: '!{serverURL}',
17 | pageview: !{lazyload ? false : pageview},
18 | dark: 'html[data-theme="dark"]',
19 | path: window.location.pathname,
20 | comment: !{lazyload ? false : count},
21 | }, !{JSON.stringify(option)}))
22 | }
23 |
24 | if (typeof Waline === 'function') initWaline()
25 | else {
26 | insertCSS()
27 | getScript('!{url_for(theme.asset.waline_js)}').then(initWaline)
28 | }
29 | }
30 |
31 | if ('!{use[0]}' === 'Waline' || !!{lazyload}) {
32 | if (!{lazyload}) btf.loadComment(document.getElementById('waline-wrap'),loadWaline)
33 | else setTimeout(loadWaline, 0)
34 | } else {
35 | function loadOtherComment () {
36 | loadWaline()
37 | }
38 | }
39 |
40 |
41 |
--------------------------------------------------------------------------------
/layout/includes/widget/card_tags.pug:
--------------------------------------------------------------------------------
1 | if theme.aside.card_tags.enable
2 | if site.tags.length
3 | .card-widget.card-tags
4 | .item-headline
5 | i.dys.tag
6 | span= _p('aside.card_tags')
7 |
8 | - let tagLimit = theme.aside.card_tags.limit === 0 ? 0 : theme.aside.card_tags.limit || 40
9 | if theme.aside.card_tags.color
10 | .card-tag-cloud!= cloudTags({source: site.tags, minfontsize: 1.15, maxfontsize: 1.45, limit: tagLimit, unit: 'em'})
11 | else
12 | .card-tag-cloud!= tagcloud({min_font: 1.1, max_font: 1.5, amount: tagLimit , color: true, start_color: '#999', end_color: '#99a9bf', unit: 'em'})
13 | if theme.aside.card_categories.enable
14 | if site.categories.length
15 | .card-widget.card-categories
16 | !=aside_categories({ limit: theme.aside.card_categories.limit === 0 ? 0 : theme.aside.card_categories.limit || 8 , expand: theme.aside.card_categories.expand })
17 | if theme.aside.card_archives.enable
18 | .card-widget.card-archives
19 | - let type = theme.aside.card_archives.type || 'monthly'
20 | - let format = theme.aside.card_archives.format || 'MMMM YYYY'
21 | - let order = theme.aside.card_archives.order || -1
22 | - let limit = theme.aside.card_archives.limit === 0 ? 0 : theme.aside.card_archives.limit || 8
23 | != aside_archives({ type:type, format: format, order: order, limit: limit })
24 |
25 |
--------------------------------------------------------------------------------
/scripts/tag/flink.js:
--------------------------------------------------------------------------------
1 | /**
2 | * flink
3 | */
4 |
5 | 'use strict'
6 |
7 | const urlFor = require('hexo-util').url_for.bind(hexo)
8 |
9 | const flinkFn = (args, content) => {
10 | content = hexo.render.renderSync({ text: content, engine: 'yaml' })
11 |
12 | let result = ''
13 |
14 | content.forEach(i => {
15 | const className = i.class_name ? `${i.class_name}
` : ''
16 | const classDesc = i.class_desc ? `${i.class_desc}
` : ''
17 |
18 | let listResult = ''
19 |
20 | i.link_list.forEach(j => {
21 | listResult += `
22 | `
31 | })
32 |
33 | result += `${className}${classDesc} ${listResult}
`
34 | })
35 |
36 | return `${result}
`
37 | }
38 |
39 | hexo.extend.tag.register('flink', flinkFn, { ends: true })
40 |
--------------------------------------------------------------------------------
/scripts/filters/random_cover.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * ramdom cover
4 | */
5 |
6 | 'use strict'
7 |
8 | hexo.extend.filter.register('before_post_render', function (data) {
9 | const { config } = this
10 | if (config.post_asset_folder) {
11 | const imgTestReg = /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/
12 | const topImg = data.top_img
13 | const cover = data.cover
14 | if (topImg && topImg.indexOf('/') === -1 && imgTestReg.test(topImg)) data.top_img = data.path + topImg
15 | if (cover && cover.indexOf('/') === -1) data.cover = data.path + cover
16 | }
17 |
18 | if (data.cover === false) {
19 | data.randomcover = randomCover()
20 | return data
21 | }
22 |
23 | data.cover = data.cover || randomCover()
24 | return data
25 | })
26 |
27 | function randomCover () {
28 | const theme = hexo.theme.config
29 | let cover
30 | let num
31 |
32 | if (theme.cover && theme.cover.default_cover) {
33 | if (!Array.isArray(theme.cover.default_cover)) {
34 | cover = theme.cover.default_cover
35 | return cover
36 | } else {
37 | num = Math.floor(Math.random() * theme.cover.default_cover.length)
38 | cover = theme.cover.default_cover[num]
39 | return cover
40 | }
41 | } else {
42 | cover = theme.default_top_img || 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
43 | return cover
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/layout/includes/third-party/chat/messenger.pug:
--------------------------------------------------------------------------------
1 | - let { pageID, lang } = theme.messenger
2 | - lang = theme.comments.use && theme.comments.use.includes('Facebook Comments') ? theme.facebook_comments.lang : lang
3 |
4 | #fb-customer-chat.fb-customerchat(page_id=pageID attribution='biz_inbox')
5 |
6 | script.
7 | document.getElementById('fb-root') ? '' : document.body.insertAdjacentHTML('afterend', '')
8 |
9 | window.fbAsyncInit = function() {
10 | FB.init({
11 | xfbml: true,
12 | version: 'v15.0'
13 | });
14 | };
15 |
16 | (function(d, s, id) {
17 | var js, fjs = d.getElementsByTagName(s)[0];
18 | if (d.getElementById(id)) return;
19 | js = d.createElement(s); js.id = id;
20 | js.src = 'https://connect.facebook.net/!{lang}/sdk/xfbml.customerchat.js';
21 | fjs.parentNode.insertBefore(js, fjs);
22 | }(document, 'script', 'facebook-jssdk'));
23 |
24 | if (!{theme.chat_btn}) {
25 | var chatBtnFn = () => {
26 | var chatBtn = document.getElementById("chat_btn")
27 | chatBtn.addEventListener("click", function(){
28 | FB.CustomerChat.show();
29 | });
30 | }
31 | chatBtnFn()
32 | } else {
33 | if (!{theme.chat_hide_show}) {
34 | function chatBtnHide () {
35 | FB.CustomerChat.hide()
36 | }
37 | function chatBtnShow () {
38 | FB.CustomerChat.show(false)
39 | }
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/source/css/_layout/loading.styl:
--------------------------------------------------------------------------------
1 | if hexo-config('preloader')
2 | .loading-bg
3 | display: flex;
4 | width: 100%;
5 | height: 100%;
6 | position: fixed;
7 | background: var(--loading-bg);
8 | backdrop-filter: saturate(180%) blur(20px)
9 | -webkit-backdrop-filter: blur(20px) saturate(180%)
10 | z-index: 99999;
11 | opacity: 1;
12 | transition: .3s;
13 |
14 | #loading-box
15 | .loading-img
16 | background: url(hexo-config('avatar.img')) no-repeat center center
17 | background-size: cover
18 | width: 100px;
19 | height: 100px;
20 | border-radius: 50%;
21 | margin: auto;
22 | border: 4px solid #f0f0f2;
23 | animation-duration: .3s;
24 | animation-name: loadingAction;
25 | animation-iteration-count: infinite;
26 | animation-direction: alternate;
27 | &.loaded
28 | .loading-bg
29 | opacity: 0;
30 | z-index: -1000;
31 | .loading-image-dot
32 | width: 30px;
33 | height: 30px;
34 | display: flex
35 | align-items: center
36 | justify-content: center
37 | position: absolute;
38 | border-radius: 50%;
39 | border: 6px solid #fff;
40 | top: 50%;
41 | left: 50%;
42 | transform: translate(18px, 24px);
43 | img
44 | height: 26px
45 | width: 26px
46 |
47 | @keyframes loadingAction
48 | 0% {
49 | opacity: 1;
50 | }
51 |
52 | 100% {
53 | opacity: .4;
54 | }
--------------------------------------------------------------------------------
/layout/includes/head/analytics.pug:
--------------------------------------------------------------------------------
1 | if theme.baidu_analytics
2 | script.
3 | var _hmt = _hmt || [];
4 | (function() {
5 | var hm = document.createElement("script");
6 | hm.src = "https://hm.baidu.com/hm.js?!{theme.baidu_analytics}";
7 | var s = document.getElementsByTagName("script")[0];
8 | s.parentNode.insertBefore(hm, s);
9 | })();
10 |
11 | if theme.google_analytics
12 | script(async src=`https://www.googletagmanager.com/gtag/js?id=${theme.google_analytics}`)
13 | script.
14 | window.dataLayer = window.dataLayer || [];
15 | function gtag(){dataLayer.push(arguments);}
16 | gtag('js', new Date());
17 | gtag('config', '!{theme.google_analytics}');
18 |
19 | if theme.cnzz_analytics
20 | script(async data-pjax src=`https://s4.cnzz.com/z_stat.php?id=${theme.cnzz_analytics}&web_id=${theme.cnzz_analytics}`)
21 |
22 | if theme.cloudflare_analytics
23 | script(defer data-pjax src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon=`{"token": "${theme.cloudflare_analytics}"}`)
24 |
25 | if theme.microsoft_clarity
26 | script.
27 | (function(c,l,a,r,i,t,y){
28 | c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
29 | t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
30 | y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
31 | })(window, document, "clarity", "script", "!{theme.microsoft_clarity}");
--------------------------------------------------------------------------------
/source/css/_layout/footer.styl:
--------------------------------------------------------------------------------
1 | .footer
2 | padding: 15px
3 | #in
4 | background: var(--footer-bg)
5 | width 100%
6 | padding 0 15px 15px 15px
7 | text-align: center
8 | border: 1px solid var(--border)
9 | max-width: 1200px
10 | margin: 0 auto 20px
11 | border-radius: 18px
12 | @media screen and (max-width: 768px)
13 | margin: auto !important
14 | border-radius: 18px 18px 0 0
15 | .title
16 | display flex
17 | flex-direction: column-reverse
18 | text-align: center
19 | img
20 | position: relative
21 | height: 66px
22 | width 66px
23 | border-radius: 100vh
24 | top: -33px
25 | left: calc(50% - 33px)
26 | .author
27 | margin-top -33px
28 | text-align: center
29 | span.name
30 | font-weight: bolder
31 | font-size: 25px
32 | .links
33 | margin-bottom: 20px
34 | display flex
35 | flex-wrap: wrap
36 | justify-content: center
37 | a
38 | color: var(--heo-font)
39 | font-size: 25px
40 | .frame
41 | margin-top: 20px
42 | font-size: 18px
43 | font-weight: bolder
44 | i
45 | margin: 0 3px
46 | about.about
47 | a.footer-button
48 | padding: 15px
49 | margin: 6px
50 | color: #fff
51 | i
52 | line-height: 2
53 | margin-right: 2px
--------------------------------------------------------------------------------
/source/css/_tags/button.styl:
--------------------------------------------------------------------------------
1 | #article-container
2 | .btn-center
3 | margin: 0 0 20px
4 | text-align: center
5 |
6 | .btn-beautify
7 | display: inline-block
8 | margin: 0 4px 6px
9 | padding: 0 15px
10 | background-color: var(--btn-beautify-color, $btn-default-color)
11 | color: $btn-color
12 | line-height: 2
13 |
14 | for $type in $color-types
15 | &.{$type}
16 | --btn-beautify-color: lookup('$tagsP-' + $type + '-color')
17 |
18 | &:hover
19 | background-color: var(--btn-hover-color)
20 |
21 | i + span
22 | margin-left: 6px
23 |
24 | &:not(.block) + .btn-beautify:not(.block)
25 | margin: 0 4px 20px
26 |
27 | &.block
28 | display: block
29 | margin: 0 0 20px
30 | width: fit-content
31 | width: -moz-fit-content
32 |
33 | &.center
34 | margin: 0 auto 20px
35 |
36 | &.right
37 | margin: 0 0 20px auto
38 |
39 | &.larger
40 | padding: 6px 15px
41 |
42 | &:hover
43 | text-decoration: none
44 |
45 | &.outline
46 | border: 1px solid transparent
47 | border-color: var(--btn-beautify-color, $btn-default-color)
48 | background-color: transparent
49 | color: var(--btn-beautify-color, $btn-default-color)
50 |
51 | &:hover
52 | background-color: var(--btn-beautify-color, $btn-default-color)
53 |
54 | &:hover
55 | color: white !important
56 |
--------------------------------------------------------------------------------
/scripts/tag/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/tag/timeline.js:
--------------------------------------------------------------------------------
1 | /**
2 | * timeline
3 | * by Jerry
4 | */
5 |
6 | 'use strict'
7 |
8 | function timeLineFn (args, content) {
9 | const tlBlock = /\n([\w\W\s\S]*?)/g
10 |
11 | let result = ''
12 | let color = ''
13 | if (args.length) {
14 | args = args.join(' ').split(',')
15 | color = args[1]
16 | const mdContent = hexo.render.renderSync({ text: args[0], engine: 'markdown' })
17 | result += ``
18 | }
19 |
20 | const matches = []
21 | let match
22 |
23 | while ((match = tlBlock.exec(content)) !== null) {
24 | matches.push(match[1])
25 | matches.push(match[2])
26 | }
27 |
28 | for (let i = 0; i < matches.length; i += 2) {
29 | const tlChildTitle = hexo.render.renderSync({ text: matches[i], engine: 'markdown' })
30 | const tlChildContent = hexo.render.renderSync({ text: matches[i + 1], engine: 'markdown' })
31 |
32 | const tlTitleHtml = ``
33 | const tlContentHtml = `${tlChildContent}
`
34 |
35 | result += `${tlTitleHtml + tlContentHtml}
`
36 | }
37 |
38 | return `${result}
`
39 | }
40 |
41 | hexo.extend.tag.register('timeline', timeLineFn, { ends: true })
42 |
--------------------------------------------------------------------------------
/layout/includes/third-party/chat/daovoice.pug:
--------------------------------------------------------------------------------
1 | //- https://guide.daocloud.io/daovoice/javascript-api-5869833.html
2 | script.
3 | (function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/!{theme.daovoice.app_id}.js","daovoice")
4 |
5 | script.
6 | var isChatBtn = !{theme.chat_btn}
7 | daovoice('init', {
8 | app_id: '!{theme.daovoice.app_id}',},{
9 | launcher: {
10 | disableLauncherIcon: isChatBtn // 悬浮 ICON 是否显示
11 | },
12 | });
13 | daovoice('update');
14 |
15 | if (isChatBtn) {
16 | var chatBtnFn = () => {
17 | var chatBtn = document.getElementById("chat_btn")
18 | chatBtn.addEventListener("click", function(){
19 | daovoice('show')
20 | });
21 | }
22 | chatBtnFn()
23 | } else {
24 | if (!{theme.chat_hide_show}) {
25 | function chatBtnHide () {
26 | daovoice('update', {},{
27 | launcher: {
28 | disableLauncherIcon: true // 悬浮 ICON 是否显示
29 | },
30 | });
31 | }
32 | function chatBtnShow () {
33 | daovoice('update', {},{
34 | launcher: {
35 | disableLauncherIcon: false // 悬浮 ICON 是否显示
36 | },
37 | });
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/source/css/_tags/progress.styl:
--------------------------------------------------------------------------------
1 | .progress
2 | display flex
3 | font-size var(--global-font-size)
4 | background-color rgba(88,88,88,0.6)
5 | border-radius .25rem
6 | margin 1rem 0
7 | height 2rem
8 | overflow hidden
9 | p
10 | margin 0 0 0 10px !important
11 |
12 | .progress-bar-animated
13 | background-color #a7b5fd !important
14 | animation progress-bar-stripes 1s linear infinite
15 |
16 | .progress-bar-striped
17 | background-image linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent)
18 | background-size 1rem 1rem
19 |
20 | .progress-bar
21 | display flex
22 | flex-direction column
23 | justify-content center
24 | overflow visible
25 | color #fff
26 | text-align center
27 | white-space nowrap
28 | background-color #0d6efd
29 | transition width .6s ease
30 |
31 | @media (prefers-reduced-motion:reduce)
32 | .progress-bar
33 | transition none
34 |
35 | .bg-green
36 | background-color #28a745 !important
37 |
38 | .bg-yellow
39 | background-color #ffc107 !important
40 |
41 | .bg-red
42 | background-color #dc3545 !important
43 |
44 | .bg-cyan
45 | background-color #17a2b8 !important
46 |
47 | .bg-blue
48 | background-color #0d6efd !important
49 |
50 | .bg-gray
51 | background-color #7f838a !important
52 |
53 | @keyframes progress-bar-stripes
54 | 0%
55 | background-position-x 1rem
56 |
--------------------------------------------------------------------------------
/layout/includes/post/post-copyright.pug:
--------------------------------------------------------------------------------
1 | if theme.post_copyright.enable && page.copyright !== false
2 | - let author = page.copyright_author ? page.copyright_author : config.author
3 | - let url = page.copyright_url ? page.copyright_url : page.permalink
4 | .post-copyright
5 | .post-copyright__title
6 | span.post-copyright-info
7 | h #[=page.title]
8 | .post-copyright__type
9 | span.post-copyright-info
10 | a(href=url_for(url))= theme.post_copyright.decode ? decodeURI(url) : url
11 | .post-copyright-m
12 | .post-copyright-m-info
13 | .post-copyright-a(style="display: inline-block;width: 120px")
14 | h 作者
15 | .post-copyright-cc-info
16 | h=author
17 | .post-copyright-c(style="display: inline-block;width: 120px")
18 | h 发布于
19 | .post-copyright-cc-info
20 | h=date(page.date, config.date_format)
21 | .post-copyright-u(style="display: inline-block;width: 120px")
22 | h 更新于
23 | .post-copyright-cc-info
24 | h=date(page.updated, config.date_format)
25 | .post-copyright-c(style="display: inline-block;width: 120px")
26 | h 许可协议
27 | .post-copyright-cc-info
28 | a.icon(rel='noopener' target='_blank' title='Creative Commons' href='https://creativecommons.org/')
29 | i.dys.creativecommons
30 | a(rel='noopener' target='_blank' title='CC BY 4.0' href='https://creativecommons.org/licenses/by/4.0/deed.zh') CC BY 4.0
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/index.pug:
--------------------------------------------------------------------------------
1 | - let defaultComment = theme.comments.use[0]
2 | hr
3 | #post-comment
4 | .comment-head
5 | .comment-headline
6 | i.fas.fa-comments.
7 | span= ' ' + _p('comment')
8 |
9 | if theme.comments.use.length > 1
10 | #comment-switch
11 | span.first-comment=defaultComment
12 | span.switch-btn
13 | span.second-comment=theme.comments.use[1]
14 |
15 |
16 | .comment-wrap
17 | each name in theme.comments.use
18 | div
19 | case name
20 | when 'Disqus'
21 | #disqus_thread
22 | when 'Valine'
23 | #vcomment.vcomment
24 | when 'Disqusjs'
25 | #disqusjs
26 | when 'Livere'
27 | #lv-container(data-id="city" data-uid=theme.livere.uid)
28 | when 'Gitalk'
29 | #gitalk-container
30 | when 'Utterances'
31 | #utterances-wrap
32 | when 'Twikoo'
33 | #twikoo-wrap
34 | when 'Waline'
35 | #waline-wrap
36 | when 'Giscus'
37 | #giscus-wrap
38 | when 'Facebook Comments'
39 | .fb-comments(data-colorscheme = theme.display_mode === 'dark' ? 'dark' : 'light'
40 | data-numposts= theme.facebook_comments.pageSize || 10
41 | data-order-by= theme.facebook_comments.order_by || 'social'
42 | data-width="100%")
43 | when 'Remark42'
44 | #remark42
45 | when 'Artalk'
46 | #artalk-wrap
47 |
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/utterances.pug:
--------------------------------------------------------------------------------
1 | script.
2 | function loadUtterances () {
3 | let ele = document.createElement('script')
4 | ele.setAttribute('id', 'utterances_comment')
5 | ele.setAttribute('src', 'https://utteranc.es/client.js')
6 | ele.setAttribute('repo', '!{theme.utterances.repo}')
7 | ele.setAttribute('issue-term', '!{theme.utterances.issue_term}')
8 | let nowTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? '#{theme.utterances.dark_theme}' : '#{theme.utterances.light_theme}'
9 | ele.setAttribute('theme', nowTheme)
10 | ele.setAttribute('crossorigin', 'anonymous')
11 | ele.setAttribute('async', 'true')
12 | document.getElementById('utterances-wrap').insertAdjacentElement('afterbegin',ele)
13 | }
14 |
15 | function utterancesTheme () {
16 | const iframe = document.querySelector('.utterances-frame')
17 | if (iframe) {
18 | const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '#{theme.utterances.dark_theme}' : '#{theme.utterances.light_theme}'
19 | const message = {
20 | type: 'set-theme',
21 | theme: theme
22 | };
23 | iframe.contentWindow.postMessage(message, 'https://utteranc.es');
24 | }
25 | }
26 |
27 | if ('!{theme.comments.use[0]}' === 'Utterances' || !!{theme.comments.lazyload}) {
28 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('utterances-wrap'), loadUtterances)
29 | else loadUtterances()
30 | } else {
31 | function loadOtherComment () {
32 | loadUtterances()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/gitalk.pug:
--------------------------------------------------------------------------------
1 | script.
2 | function addGitalkSource () {
3 | const ele = document.createElement('link')
4 | ele.rel = 'stylesheet'
5 | ele.href= '!{url_for(theme.asset.gitalk_css)}'
6 | document.getElementsByTagName('head')[0].appendChild(ele)
7 | }
8 |
9 | function loadGitalk () {
10 | function initGitalk () {
11 | var gitalk = new Gitalk(Object.assign({
12 | clientID: '!{theme.gitalk.client_id}',
13 | clientSecret: '!{theme.gitalk.client_secret}',
14 | repo: '!{theme.gitalk.repo}',
15 | owner: '!{theme.gitalk.owner}',
16 | admin: ['!{theme.gitalk.admin}'],
17 | id: '!{md5(page.path)}',
18 | updateCountCallback: commentCount
19 | },!{JSON.stringify(theme.gitalk.option)}))
20 |
21 | gitalk.render('gitalk-container')
22 | }
23 |
24 | if (typeof Gitalk === 'function') initGitalk()
25 | else {
26 | addGitalkSource()
27 | getScript('!{url_for(theme.asset.gitalk)}').then(initGitalk)
28 | }
29 | }
30 |
31 | function commentCount(n){
32 | let isCommentCount = document.querySelector('#post-meta .gitalk-comment-count')
33 | if (isCommentCount) {
34 | isCommentCount.innerHTML= n
35 | }
36 | }
37 |
38 | if ('!{theme.comments.use[0]}' === 'Gitalk' || !!{theme.comments.lazyload}) {
39 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('gitalk-container'), loadGitalk)
40 | else loadGitalk()
41 | } else {
42 | function loadOtherComment () {
43 | loadGitalk()
44 | }
45 | }
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/source/css/_custom/snackbar.css:
--------------------------------------------------------------------------------
1 | /* 消息弹窗 */
2 | .snackbar-container {
3 | background: var(--heo-main) !important;
4 | color: var(--heo-white) !important;
5 | border-radius: 0 !important;
6 | display: flex;
7 | justify-content: center !important;
8 | max-width: none !important;
9 | min-width: 100% !important;
10 | margin: 0px !important;
11 | left: 0px !important;
12 | height: 60px !important;
13 | transform: none !important;
14 | }
15 | .snackbar-container p {
16 | font-weight: 600 !important;
17 | text-align: center !important;
18 | color: var(--heo-font) !important;
19 | font-size: 18px !important;
20 | display: flex !important;
21 | justify-content: center !important;
22 | }
23 | .snackbar-container .action {
24 | color: var(--heo-white) !important;
25 | padding: 4px 6px !important;
26 | font-weight: bold;
27 | border-radius: 8px !important;
28 | transition: 0.3s;
29 | border: var(--style-border) !important;
30 | }
31 | .snackbar-container .action:hover {
32 | color: var(--heo-main) !important;
33 | background: var(--heo-white) !important;
34 | }
35 | .snackbar-container::after {
36 | position: absolute;
37 | width: 0;
38 | height: 100%;
39 | left: 0;
40 | top: 0;
41 | background: var(--heo-white);
42 | opacity: 0.1;
43 | content: "";
44 | animation: snackbar-progress 2s linear forwards;
45 | pointer-events: none;
46 | }
47 | @keyframes snackbar-progress {
48 | from {
49 | width: 0;
50 | }
51 | to {
52 | width: 100%;
53 | }
54 | }
--------------------------------------------------------------------------------
/layout/includes/footer.pug:
--------------------------------------------------------------------------------
1 | .footer
2 | #in
3 | .title
4 | img(src=url_for(theme.footer.footer_logo.url) style='border-radius:100vh;box-shadow:0 8px 12px -3px #4259ef23')
5 | .author
6 | span.name=config.author
7 | .descr=config.subtitle
8 | if theme.footer.footer_icons.enable
9 | .links
10 | each i in theme.footer.footer_icons.icons
11 | if i.class == "in"
12 | a.deal_link(href=`${i.link}`, title=`${i.desrc}`)
13 | i(class=`${i.icon}` style='font-size:25px')
14 | else if i.class == "out"
15 | a.deal_link(target='_blank', rel='noopener external nofollow', href=`${i.link}`, title=`${i.desrc}`)
16 | i(class=`${i.icon}` style='font-size:25px')
17 | else
18 | a.deal_link(href=`${i.link}`, title=`${i.desrc}`)
19 | i(class=`${i.icon}` style='font-size:25px')
20 | about.about
21 | a.footer-button(href="/about/" style='box-shadow:0 8px 12px -3px #ee7d7936;background:#F04A63;border-radius:100vh;')
22 | i.dys.caozuo-wailian
23 | span 了解更多
24 | a.footer-button(href="/cc/" style='box-shadow:0 8px 12px -3px #87ee7936;background:#57BD6A;border-radius:100vh;')
25 | i.dys.creativecommons
26 | span 转载协议
27 | div.frame
28 | span HEXO
29 | i.dys.heart-beat(style='font-size:20px')
30 | span Dynasty
31 | //- p(style="margin:5px 10px 5px 10px;height:20px")
32 | a.active(href="https://cdnnb.cn")
33 | img(src="https://img.shields.io/badge/本站由失控的防御系统提供加速防御支持-green?style=flat&logo=Claris")
--------------------------------------------------------------------------------
/scripts/helpers/get_arrays.js:
--------------------------------------------------------------------------------
1 | hexo.extend.helper.register('getarray_bar', function (types) {
2 | if (!types) {
3 | types = "category"
4 | }
5 | const categoriesBar = function (categories) {
6 | if (!categories || !categories.length) return ``
7 | const categoryArr = []
8 | hexo.locals.get('categories').map(function (category) {
9 | categoryArr.push({ name: category.name, value: category.length })
10 | })
11 | categoryArr.sort((a, b) => { return b.value - a.value })
12 | let strCategoriesBar = ``
13 | for (let i = 0; i < categories.length; i++) {
14 | strTemp=`
15 | `
18 | strCategoriesBar+=strTemp
19 | }
20 | return strCategoriesBar
21 | }
22 | const tagsBar = function(tags) {
23 | if (!tags || !tags.length) return ``
24 | const tagArr = []
25 | hexo.locals.get('tags').map(function (tag) {
26 | tagArr.push({ name: tag.name, value: tag.length })
27 | })
28 | tagArr.sort((a, b) => { return b.value - a.value })
29 | let strTagsBar = ``
30 | for (let i = 0; i < tags.length; i++) {
31 | strTemp=`
32 | `
35 | strTagsBar+=strTemp
36 | }
37 | return strTagsBar
38 | }
39 | if (types == "category"){
40 | return categoriesBar(this.site.categories)
41 | }
42 | if (types == "tag"){
43 | return tagsBar(this.site.tags)
44 | }
45 | })
--------------------------------------------------------------------------------
/scripts/tag/card.js:
--------------------------------------------------------------------------------
1 | /**
2 | * card
3 | * {% card name,url,bg,star,text,icon,tag,w,h %}
4 | * {% card 标题,链接,背景,评分,评价,图标,标签,宽度,高度 %}
5 | */
6 |
7 | 'use strict'
8 |
9 | // 分数转成星星
10 | function tostar(num) {
11 | let tmp = ''
12 | for (let i = 0; i < Math.floor(num); i++) { tmp += '' } // 整数部分加实心星星
13 | if (num - Math.floor(num) != 0) tmp += '' // 小数部分转成半星
14 | for (let i = 0; i < 5 - Math.ceil(num); i++) { tmp += '' } // 不够5个补空心星星
15 | return tmp
16 | }
17 |
18 | function card(args) {
19 | args = args.join(' ').split(',')
20 |
21 | // 获取参数
22 | let name = (args[0] || '未知').trim()
23 | let url = (args[1] || '').trim()
24 | let bg = (args[2] ? `background-image: url(${args[2]});` : 'background-color: #333;').trim()
25 | let star = tostar(Number(args[3]) || 0)
26 | let text = (args[4] || '此作品博主暂未作出评价').trim()
27 | let icon = (args[5] || '').trim()
28 | let tag = (args[6] || '').trim()
29 | let w = args[7] || '200px'
30 | let h = args[8] || '275px'
31 |
32 | return `
33 |
34 |
${text}
35 | ${url?'
查看详情':''}
36 |
37 |
38 |
39 | ${tag}
40 |
41 |
42 |
${name}
43 |
${star}
44 |
45 |
`
46 | }
47 |
48 | hexo.extend.tag.register('card', card, { ends: false })
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/artalk.pug:
--------------------------------------------------------------------------------
1 | - const { server, site, option } = theme.artalk
2 |
3 | script.
4 | function addArtalkSource () {
5 | const ele = document.createElement('link')
6 | ele.rel = 'stylesheet'
7 | ele.href= '!{theme.asset.artalk_css}'
8 | document.getElementsByTagName('head')[0].appendChild(ele)
9 | }
10 |
11 | function loadArtalk () {
12 | function initArtalk () {
13 | window.artalkItem = new Artalk(Object.assign({
14 | el: '#artalk-wrap',
15 | server: '!{server}',
16 | site: '!{site}',
17 | pageKey: location.pathname,
18 | darkMode: document.documentElement.getAttribute('data-theme') === 'dark',
19 | countEl: '.artalk-count'
20 | },!{JSON.stringify(option)}))
21 | }
22 |
23 | if (typeof window.artalkItem === 'object') setTimeout(()=>{initArtalk()},200)
24 | else {
25 | addArtalkSource()
26 | typeof Artalk !== 'function' ? getScript('!{theme.asset.artalk_js}').then(initArtalk)
27 | : setTimeout(()=>{initArtalk()},200)
28 | }
29 | }
30 |
31 | document.getElementById('darkmode').addEventListener('click',()=> {
32 | if (typeof window.artalkItem !== 'object') return
33 | let isDark = document.documentElement.getAttribute('data-theme') === 'dark'
34 | window.artalkItem.setDarkMode(!isDark)
35 | })
36 |
37 |
38 | if ('!{theme.comments.use[0]}' === 'Artalk' || !!{theme.comments.lazyload}) {
39 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('artalk-wrap'), loadArtalk)
40 | else loadArtalk()
41 | } else {
42 | function loadOtherComment () {
43 | loadArtalk()
44 | }
45 | }
--------------------------------------------------------------------------------
/source/css/_layout/comments.styl:
--------------------------------------------------------------------------------
1 | #post-comment
2 | .comment-head
3 | margin-bottom: 20px
4 |
5 | .comment-headline
6 | display: inline-block
7 | vertical-align: middle
8 | font-weight: 700
9 | font-size: 1.43em
10 |
11 | #comment-switch
12 | display: inline-block
13 |
14 | if hexo-config('comments.text')
15 | float: right
16 | margin: 2px auto 0
17 | padding: 4px 16px
18 | width: max-content
19 | border-radius: 8px
20 | background: $comments-switch-bg
21 | else
22 | vertical-align: middle
23 |
24 | > span
25 | display: none
26 |
27 | .first-comment
28 | color: $comments-switch-first-text
29 |
30 | .second-comment
31 | color: $comments-switch-second-text
32 |
33 | .switch-btn
34 | position: relative
35 | display: inline-block
36 | margin: -4px 8px 0
37 | width: 42px
38 | height: 22px
39 | border-radius: 34px
40 | background-color: $comments-switch-first-text
41 | vertical-align: middle
42 | cursor: pointer
43 | transition: .4s
44 |
45 | &:before
46 | position: absolute
47 | bottom: 4px
48 | left: 4px
49 | width: 14px
50 | height: 14px
51 | border-radius: 50%
52 | background-color: $comments-switch-round
53 | content: ''
54 | transition: .4s
55 |
56 | &.move
57 | background-color: $comments-switch-second-text
58 |
59 | &:before
60 | transform: translateX(20px)
61 |
62 | .comment-wrap
63 | > div:nth-child(2)
64 | display: none
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/twikoo.pug:
--------------------------------------------------------------------------------
1 | - const { envId, region, option } = theme.twikoo
2 | - const { use, lazyload, count } = theme.comments
3 |
4 | script.
5 | (()=>{
6 | const init = () => {
7 | twikoo.init(Object.assign({
8 | el: '#twikoo-wrap',
9 | envId: '!{envId}',
10 | region: '!{region}',
11 | onCommentLoaded: function () {
12 | btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)'))
13 | }
14 | }, !{JSON.stringify(option)}))
15 | }
16 |
17 | const getCount = () => {
18 | const countELement = document.getElementById('twikoo-count')
19 | if(!countELement) return
20 | twikoo.getCommentsCount({
21 | envId: '!{envId}',
22 | region: '!{region}',
23 | urls: [window.location.pathname],
24 | includeReply: false
25 | }).then(function (res) {
26 | countELement.innerText = res[0].count
27 | }).catch(function (err) {
28 | console.error(err);
29 | });
30 | }
31 |
32 | const runFn = () => {
33 | init()
34 | !{count ? 'GLOBAL_CONFIG_SITE.isPost && getCount()' : ''}
35 | }
36 |
37 | const loadTwikoo = () => {
38 | if (typeof twikoo === 'object') {
39 | setTimeout(runFn,0)
40 | return
41 | }
42 | getScript('!{url_for(theme.asset.twikoo)}').then(runFn)
43 | }
44 |
45 | if ('!{use[0]}' === 'Twikoo' || !!{lazyload}) {
46 | if (!{lazyload}) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo)
47 | else loadTwikoo()
48 | } else {
49 | window.loadOtherComment = () => {
50 | loadTwikoo()
51 | }
52 | }
53 | })()
--------------------------------------------------------------------------------
/source/css/_search/local-search.styl:
--------------------------------------------------------------------------------
1 | #local-search
2 | .search-dialog
3 | .local-search-box
4 | margin: 0 auto
5 | max-width: 100%
6 | width: 100%
7 |
8 | input
9 | padding: 15px
10 | width: 100%
11 | outline: none
12 | border: 1px solid var(--search-border-color)
13 | border-radius: 100vh
14 | background: transparent
15 | font-size: 27px
16 | text-align: center
17 | font-weight: 600
18 | color: var(--search-input-color)
19 | -webkit-appearance: none
20 |
21 | .search-wrap
22 | display: none
23 |
24 | .local-search__hit-item
25 | position: relative
26 | padding: 15px
27 | line-height: 1.7
28 |
29 | a
30 | display: block
31 | font-weight: 800
32 | cursor: pointer
33 | font-size: 20px
34 | color: var(--search-border-color)
35 |
36 | .search-result
37 | margin: 0 8px 8px 0
38 | word-break: break-all
39 | font-size: 17px !important
40 |
41 | .search-keyword
42 | color: $search-keyword-highlight
43 | font-weight: bold
44 |
45 | .search-result-list
46 | overflow-y: auto
47 | max-height: calc(80vh - 130px)
48 |
49 | +maxWidth768()
50 | padding-bottom: 40px
51 | max-height: 75vh !important
52 |
53 | .local-search__hit-item
54 | height: 90px
55 | text-align: center
56 | overflow: hidden
57 | transition: all .5s
58 | border-bottom: 1px dashed var(--search-border-color)
59 |
60 | &:hover
61 | background: var(--search-border-color)
62 | color: var(--global-bg)
63 |
64 | a
65 | color: var(--global-bg) !important
--------------------------------------------------------------------------------
/source/css/_tags/card.styl:
--------------------------------------------------------------------------------
1 | .card_box
2 | display: flex
3 | justify-content: space-between
4 | flex-direction: column
5 | background-position: center
6 | background-size: cover
7 | border-radius: 12px
8 | position: relative
9 | overflow: hidden
10 | padding: 10px
11 | color: #fff !important
12 | margin: 10px auto
13 | &::after
14 | content: ''
15 | position: absolute
16 | height: 100%
17 | width: 100%
18 | left: 0
19 | top: 0
20 | background: rgba(0,0,0,0.1)
21 | transition: .5s
22 | z-index: 0
23 | &:hover
24 | .card_mask
25 | opacity: 1
26 | pointer-events: auto
27 | .card_top
28 | display: flex
29 | z-index: 1
30 | align-items: center
31 | justify-content: space-between
32 | .card_mask
33 | position: absolute
34 | pointer-events: none
35 | z-index: 2
36 | transition: .5s
37 | opacity: 0
38 | width: 100%
39 | height: 100%
40 | left: 0
41 | top: 0
42 | padding: 20px
43 | background: #333
44 | span
45 | display: block
46 | height: calc(100% - 40px)
47 | overflow: auto
48 | a
49 | text-align: center
50 | background: #fff
51 | color: #333 !important
52 | border-radius: 5px
53 | position: absolute
54 | width: calc(100% - 40px)
55 | bottom: 20px
56 | left: 20px
57 | &:hover
58 | text-decoration: none !important
59 | color: white !important
60 | background: #71e5ff
61 |
62 | .card_content
63 | z-index: 1
64 | span
65 | font-size: 18px
66 | font-weight: bold
67 |
68 | [data-theme='dark']
69 | .card_box
70 | color: #ddd !important
71 | &::after
72 | background: rgba(0,0,0,0.4)
--------------------------------------------------------------------------------
/source/css/_highlight/highlight/diff.styl:
--------------------------------------------------------------------------------
1 | figure.highlight
2 | table
3 | scrollbar-color: var(--hlscrollbar-bg) transparent
4 |
5 | &::-webkit-scrollbar-thumb
6 | background: var(--hlscrollbar-bg)
7 |
8 | pre .deletion
9 | color: $highlight-deletion
10 |
11 | pre .addition
12 | color: $highlight-addition
13 |
14 | pre .meta
15 | color: $highlight-purple
16 |
17 | pre
18 | .comment
19 | color: $highlight-comment
20 |
21 | .variable,
22 | .attribute,
23 | .regexp,
24 | .ruby .constant,
25 | .xml .tag .title,
26 | .xml .pi,
27 | .xml .doctype,
28 | .html .doctype,
29 | .css .id,
30 | .tag .name,
31 | .css .class,
32 | .css .pseudo
33 | color: $highlight-red
34 |
35 | .tag
36 | color: $highlight-aqua
37 |
38 | .number,
39 | .preprocessor,
40 | .literal,
41 | .params,
42 | .constant,
43 | .command
44 | color: $highlight-orange
45 |
46 | .built_in
47 | color: $highlight-yellow
48 |
49 | .ruby .class .title,
50 | .css .rules .attribute,
51 | .string,
52 | .value,
53 | .inheritance,
54 | .header,
55 | .ruby .symbol,
56 | .xml .cdata,
57 | .special,
58 | .number,
59 | .formula
60 | color: $highlight-green
61 |
62 | .keyword,
63 | .title,
64 | .css .hexcolor
65 | color: $highlight-aqua
66 |
67 | .function,
68 | .python .decorator,
69 | .python .title,
70 | .ruby .function .title,
71 | .ruby .title .keyword,
72 | .perl .sub,
73 | .javascript .title,
74 | .coffeescript .title
75 | color: $highlight-blue
76 |
77 | .tag .attr,
78 | .javascript .function
79 | color: $highlight-purple
80 |
--------------------------------------------------------------------------------
/layout/includes/header/nav.pug:
--------------------------------------------------------------------------------
1 | - const { darkmode } = theme
2 |
3 | nav#nav
4 | #navbar
5 | if theme.nav.title.type === text
6 | span#blog_name
7 | a#site-name(href=url_for('/'))
8 | .title #[=theme.nav.title.title]
9 | i.dys.home
10 | else
11 | span#blog_name(style="margin-left:-5px;height:30px;width:30px")
12 | a#site-name(href=url_for('/'))
13 | img(src=url_for(theme.nav.title.title) style="width:30px;height:30px;border-radius:100vh;")
14 |
15 | .nav-menus#nav-menus
16 | #toggle-menu(style='margin:0 10px 0 5px;')
17 | a.site-page(style='display:flex; align-items:center; height:35px;')
18 | i.dys.apps(style='font-size: 25px;')
19 | | 菜单
20 |
21 | !=partial('includes/header/menu_item', {}, {cache: true})
22 |
23 | .notebar#notebar
24 |
25 | a.link(href="https://travellings.cn/go.html" style='margin-right:10px')
26 | i.dys.tower(style='font-size: 22px;')
27 |
28 | if (theme.algolia_search.enable || theme.local_search.enable)
29 | div.nav-button#search-button
30 | a.site-page.social-icon.search
31 | .search-button-text
32 | i.dys.searchico(style='font-size:25px')
33 | //- span 搜索
34 | else
35 | div.nav-button
36 | a.site-page.social-icon.search
37 | .search-button-text
38 | i.dys.searchico(style='font-size:25px')
39 | span 未开启
40 | //- div.nav-button
41 | a.link(onclick='showconsolebtn()')
42 | i.dys.apps(style='font-size: 26px;')
43 |
44 | #buttons.conbtn(onclick='btf.scrollToDest(0,500)')
45 | a.link
46 | i.dys.arrowup(style='font-size: 26px;')
47 | span#percent
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/layout/includes/third-party/math/mathjax.pug:
--------------------------------------------------------------------------------
1 | //- Mathjax 3
2 | script.
3 | if (!window.MathJax) {
4 | window.MathJax = {
5 | tex: {
6 | inlineMath: [ ['$','$'], ["\\(","\\)"]],
7 | tags: 'ams'
8 | },
9 | chtml: {
10 | scale: 1.1
11 | },
12 | options: {
13 | renderActions: {
14 | findScript: [10, doc => {
15 | for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
16 | const display = !!node.type.match(/; *mode=display/)
17 | const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display)
18 | const text = document.createTextNode('')
19 | node.parentNode.replaceChild(text, node)
20 | math.start = {node: text, delim: '', n: 0}
21 | math.end = {node: text, delim: '', n: 0}
22 | doc.math.push(math)
23 | }
24 | }, ''],
25 | insertScript: [200, () => {
26 | document.querySelectorAll('mjx-container').forEach(node => {
27 | if (node.hasAttribute('display')) {
28 | btf.wrap(node, 'div', { class: 'mathjax-overflow' })
29 | } else {
30 | btf.wrap(node, 'span', { class: 'mathjax-overflow' })
31 | }
32 | });
33 | }, '', false]
34 | }
35 | }
36 | }
37 |
38 | const script = document.createElement('script')
39 | script.src = '!{url_for(theme.asset.mathjax)}'
40 | script.id = 'MathJax-script'
41 | script.async = true
42 | document.head.appendChild(script)
43 | } else {
44 | MathJax.startup.document.state(0)
45 | MathJax.texReset()
46 | MathJax.typeset()
47 | }
--------------------------------------------------------------------------------
/source/css/_layout/reward.styl:
--------------------------------------------------------------------------------
1 | .post-reward
2 | position: relative
3 | margin-top: 80px
4 | width: 100%
5 | text-align: center
6 | pointer-events: none
7 |
8 | & > *
9 | pointer-events: auto
10 |
11 | .reward-button
12 | display: inline-block
13 | padding: 4px 24px
14 | background: var(--btn-bg)
15 | color: var(--btn-color)
16 | cursor: pointer
17 |
18 | &:hover
19 | .reward-button
20 | background: var(--btn-hover-color)
21 |
22 | & > .reward-main
23 | display: block
24 |
25 | .reward-main
26 | position: absolute
27 | bottom: 40px
28 | left: 0
29 | z-index: 100
30 | display: none
31 | padding: 0 0 15px
32 | width: 100%
33 |
34 | .reward-all
35 | display: inline-block
36 | margin: 0
37 | padding: 20px 10px
38 | border-radius: 4px
39 | background: var(--reward-pop)
40 |
41 | &:before
42 | position: absolute
43 | bottom: -10px
44 | left: 0
45 | width: 100%
46 | height: 20px
47 | content: ''
48 |
49 | &:after
50 | position: absolute
51 | right: 0
52 | bottom: 2px
53 | left: 0
54 | margin: 0 auto
55 | width: 0
56 | height: 0
57 | border-top: 13px solid var(--reward-pop)
58 | border-right: 13px solid transparent
59 | border-left: 13px solid transparent
60 | content: ''
61 |
62 | .reward-item
63 | display: inline-block
64 | padding: 0 8px
65 | list-style-type: none
66 | vertical-align: top
67 |
68 | img
69 | width: 130px
70 | height: 130px
71 |
72 | .post-qr-code-desc
73 | width: 130px
74 | color: $reward-pop-up-color
75 |
--------------------------------------------------------------------------------
/source/css/_page/404.styl:
--------------------------------------------------------------------------------
1 | if hexo-config('error_404.enable')
2 | .error404
3 | #error-wrap
4 | position: absolute
5 | top: 50%
6 | right: 0
7 | left: 0
8 | margin: 0 auto
9 | padding: 60px 20px 0
10 | max-width: 1000px
11 | transform: translate(0, -50%)
12 |
13 | .error-content
14 | @extend .cardHover
15 | overflow: hidden
16 | margin: 0 20px
17 | height: 360px
18 |
19 | +maxWidth768()
20 | margin: 0
21 | height: 500px
22 |
23 | .error-img
24 | display: inline-block
25 | overflow: hidden
26 | width: 50%
27 | height: 100%
28 |
29 | +maxWidth768()
30 | width: 100%
31 | height: 45%
32 |
33 | img
34 | @extend .imgHover
35 | background-color: $theme-color
36 |
37 | .error-info
38 | display: inline-flex
39 | flex-direction: column
40 | justify-content: center
41 | align-content: center
42 | width: 50%
43 | height: 100%
44 | vertical-align: top
45 | text-align: center
46 |
47 | if $site-name-font
48 | font-family: $site-name-font
49 |
50 | +maxWidth768()
51 | width: 100%
52 | height: 55%
53 |
54 | .error_title
55 | margin-top: -.6em
56 | font-size: 9em
57 |
58 | +maxWidth768()
59 | font-size: 8em
60 |
61 | .error_subtitle
62 | @extend .limit-more-line
63 | margin-top: -3em
64 | word-break: break-word
65 | font-size: 1.6em
66 | -webkit-line-clamp: 2
67 |
68 | & + #rightside
69 | display: none
--------------------------------------------------------------------------------
/source/css/_layout/sidebar.styl:
--------------------------------------------------------------------------------
1 | #sidebar
2 | #menu-mask
3 | position: fixed
4 | z-index: 102
5 | display: none
6 | width: 100%
7 | height: 100%
8 | background: #ffffff7a
9 | backdrop-filter: blur(20px) saturate(180%)
10 | -webkit-backdrop-filter: blur(20px) saturate(180%)
11 |
12 | #sidebar-menus
13 | position: fixed
14 | top: 0
15 | right: -($sidebar-width)
16 | z-index: 100000
17 | border: 1.5px solid #e3e8f7
18 | border-radius: 20px 0 0 20px
19 | overflow-x: hidden
20 | overflow-y: auto
21 | width: $sidebar-width
22 | height: 100%
23 | background: var(--sidebar-bg)
24 | transition: all .5s
25 |
26 | &.open
27 | transform: translate3d(-100%, 0, 0)
28 |
29 | & > .avatar-img
30 | margin: 20px auto
31 |
32 | .sidebar-site-data
33 | padding: 0 10px
34 |
35 | hr
36 | margin: 20px auto
37 |
38 | .menus_items
39 | padding: 0 10px 40px
40 |
41 | .site-page
42 | @extend .limit-one-line
43 | position: relative
44 | display: block
45 | padding: 6px 30px 6px 22px
46 | color: var(--font-color)
47 | font-size: 1.15em
48 |
49 | &:hover
50 | background: var(--text-bg-hover)
51 |
52 | i:first-child
53 | font-size: 20px
54 | text-align: left
55 |
56 | &.group
57 | & > i:last-child
58 | position: absolute
59 | top: .78em
60 | right: 18px
61 | transition: transform .3s
62 |
63 | &.hide
64 | & > i:last-child
65 | transform: rotate(90deg)
66 |
67 | & + .menus_item_child
68 | display: none
69 |
70 | .menus_item_child
71 | margin: 0
72 | list-style: none
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/disqus.pug:
--------------------------------------------------------------------------------
1 | - let disqusPageTitle = page.title.replace(/'/ig,"\\'")
2 |
3 | script.
4 | function loadDisqus () {
5 | var disqus_config = function () {
6 | this.page.url = '!{ page.permalink }'
7 | this.page.identifier = '!{ url_for(page.path) }'
8 | this.page.title = '!{ disqusPageTitle }'
9 | };
10 |
11 | window.disqusReset = () => {
12 | DISQUS.reset({
13 | reload: true,
14 | config: disqus_config
15 | })
16 | }
17 |
18 | if (window.DISQUS) disqusReset()
19 | else {
20 | (function() {
21 | var d = document, s = d.createElement('script');
22 | s.src = 'https://!{theme.disqus.shortname}.disqus.com/embed.js';
23 | s.setAttribute('data-timestamp', +new Date());
24 | (d.head || d.body).appendChild(s);
25 | })();
26 | }
27 |
28 | document.getElementById('darkmode').addEventListener('click', () => {
29 | setTimeout(() => window.disqusReset(), 200)
30 | })
31 | }
32 |
33 | if ('!{theme.comments.use[0]}' === 'Disqus' || !!{theme.comments.lazyload}) {
34 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('disqus_thread'), loadDisqus)
35 | else loadDisqus()
36 | } else {
37 | function loadOtherComment () {
38 | loadDisqus()
39 | }
40 | }
41 |
42 | if is_post() && !theme.comments.lazyload && theme.comments.count && theme.comments.use[0] === 'Disqus'
43 | script.
44 | if (window.DISQUSWIDGETS === undefined) {
45 | var d = document, s = d.createElement('script');
46 | s.src = 'https://!{theme.disqus.shortname}.disqus.com/count.js';
47 | s.id = 'dsq-count-scr';
48 | (d.head || d.body).appendChild(s);
49 | } else {
50 | DISQUSWIDGETS.getCount({reset: true});
51 | }
52 |
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/facebook_comments.pug:
--------------------------------------------------------------------------------
1 | - const fbSDKVer = 'v15.0'
2 | - const fbSDK = theme.messenger.enable ? `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk/xfbml.customerchat.js#xfbml=1&version=${fbSDKVer}` : `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}`
3 |
4 | script.
5 | function loadFBComment () {
6 | document.getElementById('fb-root') ? '' : document.body.insertAdjacentHTML('afterend', '')
7 |
8 | const themeNow = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
9 | const $fbComment = document.getElementsByClassName('fb-comments')[0]
10 | $fbComment.setAttribute('data-colorscheme',themeNow)
11 | $fbComment.setAttribute('data-href', '!{urlNoIndex(page.permalink)}')
12 |
13 | if (typeof FB === 'object') {
14 | FB.XFBML.parse(document.getElementsByClassName('post-meta-commentcount')[0])
15 | FB.XFBML.parse(document.getElementById('post-comment'))
16 | }
17 | else {
18 | let ele = document.createElement('script')
19 | ele.setAttribute('src','!{fbSDK}')
20 | ele.setAttribute('async', 'true')
21 | ele.setAttribute('defer', 'true')
22 | ele.setAttribute('crossorigin', 'anonymous')
23 | ele.setAttribute('id', 'facebook-jssdk')
24 | document.getElementById('fb-root').insertAdjacentElement('afterbegin',ele)
25 | }
26 | }
27 |
28 | if ('!{theme.comments.use[0]}' === 'Facebook Comments' || !!{theme.comments.lazyload}) {
29 | if (!{theme.comments.lazyload}) btf.loadComment(document.querySelector('#post-comment .fb-comments'), loadFBComment)
30 | else loadFBComment()
31 | } else {
32 | function loadOtherComment () {
33 | loadFBComment()
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/giscus.pug:
--------------------------------------------------------------------------------
1 | - const { repo, repo_id, category_id, option } = theme.giscus
2 | - const themes = theme.giscus.theme
3 | script.
4 | function loadGiscus () {
5 | let nowTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{themes.dark}' : '!{themes.light}'
6 |
7 | const config = Object.assign({
8 | src: 'https://giscus.app/client.js',
9 | 'data-repo': '!{repo}',
10 | 'data-repo-id': '!{repo_id}',
11 | 'data-category-id': '!{category_id}',
12 | 'data-mapping': 'pathname',
13 | 'data-theme': nowTheme,
14 | 'data-reactions-enabled': '1',
15 | crossorigin: 'anonymous',
16 | async: true
17 | },!{JSON.stringify(option)})
18 |
19 | let ele = document.createElement('script')
20 | for (let key in config) {
21 | ele.setAttribute(key, config[key])
22 | }
23 | document.getElementById('giscus-wrap').insertAdjacentElement('afterbegin',ele)
24 | }
25 |
26 | function changeGiscusTheme () {
27 | const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{themes.dark}' : '!{themes.light}'
28 |
29 | function sendMessage(message) {
30 | const iframe = document.querySelector('iframe.giscus-frame');
31 | if (!iframe) return;
32 | iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
33 | }
34 |
35 | sendMessage({
36 | setConfig: {
37 | theme: theme
38 | }
39 | });
40 | }
41 |
42 | if ('!{theme.comments.use[0]}' === 'Giscus' || !!{theme.comments.lazyload}) {
43 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('giscus-wrap'), loadGiscus)
44 | else loadGiscus()
45 | } else {
46 | function loadOtherComment () {
47 | loadGiscus()
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/scripts/tag/msgbox.js:
--------------------------------------------------------------------------------
1 | /**
2 | {% msgbox %}
3 | {% msgguest name,avatar %}
4 | 对话内容
5 | {% endmsgguest %}
6 | {% msgadmin name,avatar %}
7 | 对话内容
8 | {% endmsgadmin %}
9 | {% endmsgbox %}
10 | */
11 |
12 | 'use strict'
13 |
14 | const urlFor = require('hexo-util').url_for.bind(hexo)
15 |
16 | function msgbox (args, content) {
17 | return `${hexo.render.renderSync({ text: content, engine: 'markdown' }).split('\n').join('')}
18 |
`
19 | }
20 |
21 | function msgguest (args, content) {
22 | args = args.join(' ').split(',')
23 | let guestname = args[0]?args[0].trim():'noname' //默认无名
24 | let guestavatar = args[1]?args[1].trim():hexo.theme.config.error_img.flink //默认友链错误头像
25 |
26 | return `${guestname}
${hexo.render.renderSync({ text: content, engine: 'markdown' }).split('\n').join('')}
`
27 | }
28 | function msgadmin (args, content) {
29 | args = args.join(' ').split(',')
30 | let adminname = args[0]?args[0].trim():hexo.config.author //默认作者
31 | let adminavatar = args[1]?args[1].trim():hexo.theme.config.avatar.img //默认作者头像
32 |
33 | return `${adminname}
${hexo.render.renderSync({ text: content, engine: 'markdown' }).split('\n').join('')}
`
34 | }
35 |
36 |
37 | hexo.extend.tag.register('msgbox', msgbox, { ends: true })
38 | hexo.extend.tag.register('msgguest', msgguest, { ends: true })
39 | hexo.extend.tag.register('msgadmin', msgadmin, { ends: true })
--------------------------------------------------------------------------------
/source/js/scroll.js:
--------------------------------------------------------------------------------
1 | PostActive()
2 | topPostScroll()
3 |
4 | //分类条
5 | function PostActive(){
6 | var urlinfo = window.location.pathname;
7 | urlinfo = decodeURIComponent(urlinfo)
8 | console.log(urlinfo);
9 | }
10 |
11 | //鼠标控制横向滚动
12 | function topPostScroll(){
13 | if (document.getElementById("recent-post-top")){
14 | let xscroll = document.getElementById("recent-post-top");
15 | xscroll.addEventListener("mousewheel", function (e) {
16 | //计算鼠标滚轮滚动的距离
17 | let v = -e.wheelDelta / 2;
18 | xscroll.scrollLeft += v;
19 | //阻止浏览器默认方法
20 | e.preventDefault();
21 | }, false);
22 | }
23 | }
24 |
25 | tagBarActive()
26 | toptagBarScroll()
27 |
28 | //分类条
29 | function tagBarActive(){
30 | var urlinfo = window.location.pathname;
31 | urlinfo = decodeURIComponent(urlinfo)
32 | console.log(urlinfo);
33 | }
34 |
35 | //鼠标控制横向滚动
36 | function toptagBarScroll(){
37 | if (document.getElementById("tag-bar-items")){
38 | let xscroll = document.getElementById("tag-bar-items");
39 | xscroll.addEventListener("mousewheel", function (e) {
40 | //计算鼠标滚轮滚动的距离
41 | let v = -e.wheelDelta / 2;
42 | xscroll.scrollLeft += v;
43 | //阻止浏览器默认方法
44 | e.preventDefault();
45 | }, false);
46 | }
47 | }
48 |
49 | categoryBarActive()
50 | topcategoryBarScroll()
51 |
52 | //分类条
53 | function categoryBarActive(){
54 | var urlinfo = window.location.pathname;
55 | urlinfo = decodeURIComponent(urlinfo)
56 | console.log(urlinfo);
57 | }
58 |
59 | //鼠标控制横向滚动
60 | function topcategoryBarScroll(){
61 | if (document.getElementById("category-bar-items")){
62 | let xscroll = document.getElementById("category-bar-items");
63 | xscroll.addEventListener("mousewheel", function (e) {
64 | //计算鼠标滚轮滚动的距离
65 | let v = -e.wheelDelta / 2;
66 | xscroll.scrollLeft += v;
67 | //阻止浏览器默认方法
68 | e.preventDefault();
69 | }, false);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/source/css/_layout/pagination.styl:
--------------------------------------------------------------------------------
1 | #pagination
2 | .pagination
3 | margin-top: 20px
4 | text-align: center
5 |
6 | .page-number
7 | box-shadow: none !important
8 | border: 1px solid #e3e8f7
9 | &.current
10 | background: var(--heo-theme) right
11 | color: var(--heo-font)
12 |
13 | .pagination-info
14 | position: absolute
15 | top: 50%
16 | padding: 20px 40px
17 | width: 100%
18 | transform: translate(0, -50%)
19 |
20 | .prev_info,
21 | .next_info
22 | @extend .limit-one-line
23 | color: var(--white)
24 | font-weight: 500
25 |
26 | .next-post
27 | .pagination-info
28 | text-align: right
29 |
30 | .pull-full
31 | width: 100% !important
32 |
33 | .prev-post .label,
34 | .next-post .label
35 | color: var(--light-grey)
36 | text-transform: uppercase
37 | font-size: 90%
38 |
39 | .prev-post,
40 | .next-post
41 | @extend .postImgHover
42 | width: 50%
43 |
44 | +maxWidth768()
45 | width: 100%
46 |
47 | a
48 | position: relative
49 | display: block
50 | overflow: hidden
51 | height: 150px
52 |
53 | .layout
54 | & > .recent-posts
55 | .pagination
56 | & > *
57 | display: inline-block
58 | margin: 0 6px
59 | width: w = 2.5em
60 | height: w
61 | line-height: w
62 |
63 | & > *:not(.space)
64 | @extend .cardHover
65 |
66 | &:hover
67 | background: var(--btn-hover-color)
68 | color: var(--btn-color)
69 |
70 | & > div:not(.recent-posts)
71 | .pagination
72 | .page-number
73 | display: inline-block
74 | margin: 0 4px
75 | min-width: w = 24px
76 | height: w
77 | text-align: center
78 | line-height: w
79 | cursor: pointer
80 |
81 | .extend
82 | &.prev, &.next
83 | box-shadow: none !important
84 | border: 1px solid #e3e8f7
--------------------------------------------------------------------------------
/layout/includes/header/index.pug:
--------------------------------------------------------------------------------
1 | if !theme.disable_top_img && page.top_img !== false
2 | if is_post()
3 | - var top_img = page.top_img || page.cover || page.randomcover
4 | else if is_page()
5 | - var top_img = false
6 | else if is_tag()
7 | - var top_img = false
8 | else if is_category()
9 | - var top_img = false
10 | else if is_home()
11 | - var top_img = false
12 | else if is_archive()
13 | - var top_img = false
14 | else
15 | - var top_img = page.top_img || theme.default_top_img
16 |
17 | if top_img !== false
18 | - var imgSource = top_img && top_img.indexOf('/') !== -1 ? `background-image: url('${url_for(top_img)}')` : `background: ${top_img}`
19 | - var bg_img = top_img ? imgSource : ''
20 | - var site_title = page.title || page.tag || page.category || config.title
21 | - var isHomeClass = is_home() ? 'full_page nav-fixed nav-visible' : 'not-home-page'
22 | - is_post() ? isHomeClass = 'post-bg' : isHomeClass
23 | else
24 | - var isHomeClass = 'not-top-img'
25 | else
26 | - var top_img = false
27 | - var isHomeClass = 'not-top-img'
28 |
29 | header#page-header(class=isHomeClass style=bg_img)
30 | !=partial('includes/header/nav', {}, {cache: true})
31 | if is_post()
32 | include ./post-info.pug
33 | section.main-hero-waves-area.waves-area
34 | svg.waves-svg(xmlns='http://www.w3.org/2000/svg', xlink='http://www.w3.org/1999/xlink', viewBox='0 24 150 28', preserveAspectRatio='none', shape-rendering='auto')
35 | defs
36 | path#gentle-wave(d='M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z')
37 | g.parallax
38 | use(href='#gentle-wave', x='48', y='0')
39 | use(href='#gentle-wave', x='48', y='3')
40 | use(href='#gentle-wave', x='48', y='5')
41 | use(href='#gentle-wave', x='48', y='7')
42 | else if is_home()
43 | else
44 | #page-site-info
45 | h1#site-title=site_title
--------------------------------------------------------------------------------
/source/css/_tags/tabs.styl:
--------------------------------------------------------------------------------
1 |
2 | #article-container
3 | .tabs
4 | position: relative
5 | margin: 0 0 20px
6 | border-right: 1px solid var(--tab-border-color)
7 | border-bottom: 1px solid var(--tab-border-color)
8 | border-left: 1px solid var(--tab-border-color)
9 |
10 | > .nav-tabs
11 | display: flex
12 | flex-wrap: wrap
13 | margin: 0
14 | padding: 0
15 | background: var(--tab-botton-bg)
16 |
17 | > .tab
18 | margin: 0
19 | padding: 0
20 | list-style: none
21 |
22 | +maxWidth768()
23 | flex-grow: 1
24 |
25 | button
26 | display: block
27 | padding: 8px 18px
28 | width: 100%
29 | border-top: 2px solid var(--tab-border-color)
30 | background: var(--tab-botton-bg)
31 | color: var(--tab-botton-color)
32 | line-height: 2
33 | transition: all .4s
34 |
35 | i
36 | width: 1.5em
37 |
38 | &.active
39 | button
40 | border-top: 2px solid $tab-active-border-color
41 | background: var(--tab-button-active-bg)
42 | cursor: default
43 |
44 | &:not(.active)
45 | button
46 | &:hover
47 | border-top: 2px solid var(--tab-button-hover-bg)
48 | background: var(--tab-button-hover-bg)
49 |
50 | > .tab-contents
51 | .tab-item-content
52 | position: relative
53 | display: none
54 | padding: 36px 24px
55 |
56 | +maxWidth768()
57 | padding: 24px 14px
58 |
59 | &.active
60 | display: block
61 | animation: tabshow .5s
62 |
63 | .tab-to-top
64 | position: relative
65 | display: block
66 | margin: 0 0 0 auto
67 | color: $tab-to-top-color
68 |
69 | @keyframes tabshow
70 | 0%
71 | transform: translateY(15px)
72 |
73 | 100%
74 | transform: translateY(0)
75 |
--------------------------------------------------------------------------------
/scripts/tag/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 |
--------------------------------------------------------------------------------
/source/css/post-double-row.css:
--------------------------------------------------------------------------------
1 | #recent-posts{
2 | align-content:flex-start;
3 | display: flex;
4 | flex-wrap: wrap; /*规定灵活的项目在必要的时候拆行或拆列。*/
5 | justify-content: space-between; /*。*/
6 | }
7 | #recent-posts > .recent-post-item {
8 | /*max-height:324px;*/ /*文章容器最大高度*/
9 | margin-top: 1rem; /*最小间距*/
10 | display: inline-block;
11 | height:auto; /*高度自动*/
12 | width:49%;/*文章容器容器宽度*/
13 | }
14 | #recent-posts > .recent-post-item .post_cover {
15 | width: 100%; /*图片封面宽度*/
16 | height: 200px;/*图片封面高度*/
17 | }
18 | #recent-posts > .recent-post-item .post_cover img.post_bg {
19 | width: 100%;/*图片宽度*/
20 | height: 100%;/*图片高度*/
21 | }
22 |
23 |
24 | #recent-posts > .recent-post-item >.recent-post-info > .content {
25 | display:none;/*隐藏文章详情*/
26 | }
27 | #recent-posts > .recent-post-item {
28 |
29 | -webkit-flex-direction: column; /*容器内部纵向排列*/
30 | -ms-flex-direction: column; /*容器内部纵向排列*/
31 | flex-direction: column; /*容器内部纵向排列*/
32 |
33 | }
34 | #recent-posts > .recent-post-item .left_radius {
35 | border-radius: 8px 8px 0 0;/*圆角修改*/
36 | }
37 | #recent-posts > .recent-post-item .right_radius {
38 | border-radius: 8px 8px 0 0;/*圆角修改*/
39 | }
40 | .recent-post-item{
41 | height:auto !important;/*容器高度自动*/
42 | }
43 |
44 | .recent-post-info {
45 |
46 | padding: 0 40px;/*容器内部文字左右间距*/
47 | margin-top: 1em;/*容器内部文字上间距*/
48 | width: 100%!important;/*容器宽度*/
49 | }
50 | #recent-posts > .recent-post-item > .recent-post-info > .article-title {
51 | -webkit-line-clamp: 1;/*控制标题的行数*/
52 | margin-top: 0.3rem; /*控制标题的上间距*/
53 | margin-bottom: 0.3rem;/*控制标题的下间距*/
54 | color: var(--text-highlight-color);
55 | font-size: 1.2em; /*控制标题的字体大小*/
56 | line-height: 1.4;/*控制标题的行高*/
57 |
58 | }
59 | #recent-posts > .recent-post-item >.recent-post-info > .article-meta-wrap {
60 | margin-bottom: 1rem;/*控制标题meta信息的底部间距*/
61 | }
62 | @media screen and (max-width: 768px) {
63 | #recent-posts > .recent-post-item {
64 | width:100%;/*控制手机自适应*/
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/source/css/_custom/animations.css:
--------------------------------------------------------------------------------
1 | /* 波浪css */
2 | .main-hero-waves-area {
3 | width: 100%;
4 | left: 0;
5 | position: relative;
6 | bottom: -11px;
7 | top: 12px;
8 | z-index: 0;
9 | }
10 | .waves-area .waves-svg {
11 | width: 100%;
12 | height: 5rem;
13 | }
14 | /* Animation */
15 |
16 | .parallax > use {
17 | animation: move-forever 25s cubic-bezier(0.55, 0.5, 0.45, 0.5) infinite;
18 | }
19 | .parallax > use:nth-child(1) {
20 | animation-delay: -2s;
21 | animation-duration: 7s;
22 | fill: #f7f9febd;
23 | }
24 | .parallax > use:nth-child(2) {
25 | animation-delay: -3s;
26 | animation-duration: 10s;
27 | fill: #f7f9fe82;
28 | }
29 | .parallax > use:nth-child(3) {
30 | animation-delay: -4s;
31 | animation-duration: 13s;
32 | fill: #f7f9fe36;
33 | }
34 | .parallax > use:nth-child(4) {
35 | animation-delay: -5s;
36 | animation-duration: 20s;
37 | fill: #f7f9fe;
38 | }
39 | /* 黑色模式背景 */
40 | [data-theme="dark"] .parallax > use:nth-child(1) {
41 | animation-delay: -2s;
42 | animation-duration: 7s;
43 | fill: #18171dc8;
44 | }
45 | [data-theme="dark"] .parallax > use:nth-child(2) {
46 | animation-delay: -3s;
47 | animation-duration: 10s;
48 | fill: #18171d80;
49 | }
50 | [data-theme="dark"] .parallax > use:nth-child(3) {
51 | animation-delay: -4s;
52 | animation-duration: 13s;
53 | fill: #18171d3e;
54 | }
55 | [data-theme="dark"] .parallax > use:nth-child(4) {
56 | animation-delay: -5s;
57 | animation-duration: 20s;
58 | fill: #18171d;
59 | }
60 |
61 | @keyframes move-forever {
62 | 0% {
63 | transform: translate3d(-90px, 0, 0);
64 | }
65 | 100% {
66 | transform: translate3d(85px, 0, 0);
67 | }
68 | }
69 |
70 | .post-bg .main-hero-waves-area {
71 | top: 470px !important;
72 | }
73 |
74 | /* 旋转动画-class-spin */
75 | @keyframes rotate {
76 | 0% {
77 | transform: rotate(0deg);
78 | }
79 | 100% {
80 | transform: rotate(1turn);
81 | }
82 | }
83 |
84 | .spin {
85 | display: block;
86 | animation: rotate 2s linear infinite;
87 | }
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: Bug report
2 | description: Create a report to help us improve
3 | title: '[Bug]: '
4 |
5 | body:
6 | - type: markdown
7 | attributes:
8 | value: |
9 | 重要:請依照該模板來提交
10 | Please follow the template to create a new issue
11 | - type: input
12 | id: butterfly-ver
13 | attributes:
14 | label: 使用的 Butterfly 版本? | What version of Butterfly are you use?
15 | description: 檢視主題的 package.json | Check the theme's package.json
16 | validations:
17 | required: true
18 |
19 | - type: dropdown
20 | id: modify
21 | attributes:
22 | label: 是否修改过主题文件? || Has the theme files been modified?
23 | options:
24 | - 是 (Yes)
25 | - 不是 (No)
26 | validations:
27 | required: true
28 |
29 | - type: dropdown
30 | id: browser
31 | attributes:
32 | label: 使用的瀏覽器? || What browse are you using?
33 | options:
34 | - Chrome
35 | - Edge
36 | - Safari
37 | - Opera
38 | - Other
39 | validations:
40 | required: true
41 |
42 | - type: dropdown
43 | id: platform
44 | attributes:
45 | label: 使用的系統? || What operating system are you using?
46 | options:
47 | - Windows
48 | - macOS
49 | - Linux
50 | - Android
51 | - iOS
52 | - Other
53 | validations:
54 | required: true
55 |
56 | - type: textarea
57 | id: description
58 | attributes:
59 | label: 問題描述 | Describe the bug
60 | description: 請描述你的問題現象 | A clear and concise description of what the bug is.
61 | placeholder: 請儘量提供截圖來定位問題 | If applicable, add screenshots to help explain your problem
62 | value:
63 | validations:
64 | required: true
65 |
66 | - type: input
67 | id: website
68 | attributes:
69 | label: 出現問題網站 | Website
70 | description: 請提供下可復現網站地址 | Please supply a website url which can reproduce problem.
71 | placeholder:
72 | validations:
73 | required: true
74 |
--------------------------------------------------------------------------------
/source/css/_tags/timeline.styl:
--------------------------------------------------------------------------------
1 | #article-container
2 | .timeline
3 | margin: 0 0 20px 10px
4 | padding: 14px 20px 5px
5 | border-left: 2px solid var(--timeline-color, $theme-color)
6 |
7 | for $type in $color-types
8 | &.{$type}
9 | --timeline-color: lookup('$tagsP-' + $type + '-color')
10 | --timeline-bg: s('rgba(%s,%s,%s, 0.2)', red(lookup('$tagsP-' + $type + '-color')), green(lookup('$tagsP-' + $type + '-color')), blue(lookup('$tagsP-' + $type + '-color')))
11 |
12 | .timeline-item
13 | margin: 0 0 15px
14 |
15 | &:hover
16 | .item-circle
17 | &:before
18 | border-color: var(--timeline-color, $theme-color)
19 |
20 | &.headline
21 | .timeline-item-title
22 | .item-circle
23 | > p
24 | font-weight: 600
25 | font-size: 1.2em
26 |
27 | &:before
28 | left: -28px
29 | border: 4px solid var(--timeline-color, $theme-color)
30 |
31 | &:hover
32 | .item-circle
33 | &:before
34 | border-color: var(--pseudo-hover)
35 |
36 | .timeline-item-title
37 | position: relative
38 |
39 | .item-circle
40 | &:before
41 | position: absolute
42 | top: 50%
43 | left: -27px
44 | width: 6px
45 | height: 6px
46 | border: 3px solid var(--pseudo-hover)
47 | border-radius: 50%
48 | background: var(--card-bg)
49 | content: ''
50 | transition: all .3s
51 | transform: translate(0, -50%)
52 |
53 | > p
54 | margin: 0 0 8px
55 | font-weight: 500
56 |
57 | .timeline-item-content
58 | position: relative
59 | padding: 12px 15px
60 | border-radius: 8px
61 | background: var(--timeline-bg, lighten($theme-color, 85%))
62 | font-size: .93em
63 |
64 | & > :last-child
65 | margin-bottom: 0
66 |
67 | & + .timeline
68 | margin-top: -20px
--------------------------------------------------------------------------------
/scripts/helpers/findArchiveLength.js:
--------------------------------------------------------------------------------
1 | hexo.extend.helper.register('findArchiveLength', function (func) {
2 | const allPostsLength = this.site.posts.length;
3 | if (hexo.config.archive_generator && hexo.config.archive_generator.enable === false ) return allPostsLength
4 | const { yearly, monthly, daily } = hexo.config.archive_generator
5 | const { year, month, day } = this.page
6 | if (yearly === false || !year) return allPostsLength
7 |
8 | const posts = this.site.posts.sort('date')
9 |
10 | const compareFunc = (type,y1,m1,d1,y2,m2,d2) => {
11 | if (type === 'year') {
12 | return y1 === y2
13 | } else if (type === 'month') {
14 | return y1 === y2 && m1 === m2
15 | } else if (type === 'day') {
16 | return y1 === y2 && m1 === m2 && d1 === d2
17 | }
18 | }
19 |
20 | const generateDateObj = (type) => {
21 | let dateObj = []
22 | let length = 0
23 |
24 | posts.forEach(post => {
25 | let date = post.date.clone()
26 | const year = date.year()
27 | const month = date.month() + 1
28 | const day = date.date()
29 | let lastData = dateObj[length - 1]
30 |
31 | if (!lastData || !compareFunc(type, lastData.year, lastData.month, lastData.day, year, month, day)) {
32 | const name = type === 'year' ? year : type === 'month' ? `${year}-${month}` : `${year}-${month}-${day}`
33 | length = dateObj.push({
34 | name,
35 | year,
36 | month,
37 | day,
38 | count: 1
39 | })
40 | } else {
41 | lastData.count++
42 | }
43 | });
44 |
45 | return dateObj
46 | }
47 |
48 | const data = func('createArchiveObj', ()=> {
49 | const yearObj = yearly ? generateDateObj('year') : []
50 | const monthObj = monthly ? generateDateObj('month') : []
51 | const dayObj = daily ? generateDateObj('day') : []
52 | const fullObj = [...yearObj, ...monthObj, ...dayObj]
53 | return fullObj
54 | })
55 |
56 | const name = month ? day ? `${year}-${month}-${day}` : `${year}-${month}` : year
57 | return data.find(item => item.name === name).count
58 | })
--------------------------------------------------------------------------------
/source/css/_search/algolia.styl:
--------------------------------------------------------------------------------
1 | #algolia-search
2 | .search-dialog
3 | .ais-SearchBox
4 | input
5 | padding: 5px 14px
6 | width: 100%
7 | outline: none
8 | border: 2px solid var(--heo-theme)
9 | border-radius: 40px
10 | background: var(--search-bg)
11 | color: var(--search-input-color)
12 |
13 | .ais-Hits-list
14 | margin: 0
15 | padding: 0
16 | @extend .list-beauty
17 |
18 | a
19 | color: var(--search-result-title)
20 |
21 | &:hover
22 | color: var(--heo-theme)
23 |
24 | mark
25 | background: transparent
26 | color: $search-keyword-highlight
27 | font-weight: bold
28 |
29 | .algolia-hit-item-content
30 | margin: 0 0 8px
31 | word-break: break-all
32 |
33 | .ais-Pagination
34 | margin: 20px 0 0
35 | padding: 0
36 | text-align: center
37 |
38 | .ais-Pagination-list
39 | margin: 0
40 | padding: 0
41 | list-style: none
42 |
43 | .ais-Pagination-item
44 | display: inline
45 | margin: 0 4px
46 | padding: 0
47 |
48 | .ais-Pagination-link
49 | display: inline-block
50 | min-width: 24px
51 | height: 24px
52 | text-align: center
53 | line-height: 24px
54 |
55 | .ais-Pagination-item--selected
56 | a
57 | background: $theme-paginator-color
58 | color: #eee
59 | cursor: default
60 |
61 | .ais-Pagination-item--disabled
62 | visibility: hidden
63 |
64 | .algolia-logo
65 | padding-top: 2px
66 | width: 80px
67 | height: 30px
68 |
69 | #algolia-hits
70 | > div
71 | overflow-y: scroll
72 |
73 | +minWidth768()
74 | max-height: calc(80vh - 240px)
75 |
76 | +maxWidth768()
77 | height: calc(100vh - 260px)
78 |
79 | #algolia-info
80 | div
81 | display: inline
82 |
83 | .algolia-poweredBy
84 | float: right
85 |
86 | .apple
87 | #algolia-search
88 | #algolia-hits
89 | > div
90 | +maxWidth768()
91 | height: calc(90vh - 260px)
92 |
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/remark42.pug:
--------------------------------------------------------------------------------
1 | - const { host, siteId, option } = theme.remark42
2 | script.
3 | var remark_config = Object.assign({
4 | host: '!{host}',
5 | site_id: '!{siteId}',
6 | components: ['embed'],
7 | theme: document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
8 | },!{JSON.stringify(option)})
9 |
10 | function addRemark42(){
11 | for (let i = 0; i < remark_config.components.length; i++) {
12 | const s = document.createElement('script')
13 | s.src = remark_config.host + '/web/' + remark_config.components[i] + '.js'
14 | s.defer = true
15 | document.head.appendChild(s)
16 | }
17 | }
18 |
19 | function initRemark42() {
20 | if (window.REMARK42) {
21 | if (this.remark42Instance) {
22 | this.remark42Instance.destroy()
23 | }
24 |
25 | this.remark42Instance = window.REMARK42.createInstance({
26 | ...remark_config
27 | })
28 | }
29 | }
30 |
31 | function getCount () {
32 | const ele = document.querySelector('.remark42__counter')
33 | if (ele) {
34 | const s = document.createElement('script')
35 | s.src = remark_config.host + '/web/counter.js'
36 | s.defer = true
37 | document.head.appendChild(s)
38 | }
39 | }
40 |
41 | function loadRemark42 () {
42 | if (window.REMARK42) {
43 | this.initRemark42()
44 | getCount()
45 | } else {
46 | addRemark42()
47 | window.addEventListener('REMARK42::ready', () => {
48 | this.initRemark42()
49 | getCount()
50 | })
51 | }
52 | }
53 |
54 | document.getElementById('darkmode').addEventListener('click',()=>{
55 | if (!window.REMARK42) return
56 | let theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'
57 | window.REMARK42.changeTheme(theme)
58 | })
59 |
60 | if ('!{theme.comments.use[0]}' === 'Remark42' || !!{theme.comments.lazyload}) {
61 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('remark42'), loadRemark42)
62 | else loadRemark42()
63 | } else {
64 | function loadOtherComment () {
65 | loadRemark42()
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/layout/includes/additional-js.pug:
--------------------------------------------------------------------------------
1 | div
2 | script(src=url_for(theme.asset.utils))
3 | script(src=url_for(theme.asset.main))
4 |
5 | if theme.translate.enable
6 | script(src=url_for(theme.asset.translate))
7 |
8 | if theme.medium_zoom
9 | script(src=url_for(theme.asset.medium_zoom))
10 | else if theme.fancybox
11 | script(src=url_for(theme.asset.fancybox_v4))
12 |
13 | if theme.instantpage
14 | script(src=url_for(theme.asset.instantpage), type='module')
15 |
16 | if theme.lazyload.enable
17 | script(src=url_for(theme.asset.lazyload))
18 |
19 | if theme.snackbar.enable
20 | script(src=url_for(theme.asset.snackbar))
21 |
22 | if theme.pangu.enable
23 | != partial("includes/third-party/pangu.pug", {}, { cache: true })
24 |
25 | //- search
26 | if theme.algolia_search.enable
27 | script(src=url_for(theme.asset.algolia_search_v4))
28 | script(src=url_for(theme.asset.instantsearch_v4))
29 | script(src=url_for(theme.asset.algolia_js))
30 | else if theme.local_search.enable
31 | script(src=url_for(theme.asset.local_search))
32 |
33 | .js-pjax
34 | if needLoadCountJs
35 | != partial("includes/third-party/card-post-count/index", {}, { cache: true })
36 |
37 | if loadSubJs
38 | include ./third-party/subtitle.pug
39 |
40 | include ./third-party/math/index.pug
41 |
42 | if commentsJsLoad
43 | include ./third-party/comments/js.pug
44 |
45 | != partial("includes/third-party/prismjs", {}, { cache: true })
46 |
47 | != fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)})
48 |
49 | != partial("includes/third-party/effect", {}, { cache: true })
50 |
51 | != partial("includes/third-party/chat/index", {}, { cache: true })
52 |
53 | if theme.aplayerInject && theme.aplayerInject.enable
54 | if theme.aplayerInject.per_page
55 | include ./third-party/aplayer.pug
56 | else if page.aplayer
57 | include ./third-party/aplayer.pug
58 |
59 | != partial("includes/third-party/pjax", {}, { cache: true })
60 |
61 | if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv
62 | script(async data-pjax src='//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js')
63 |
--------------------------------------------------------------------------------
/layout/includes/third-party/comments/disqusjs.pug:
--------------------------------------------------------------------------------
1 | - let disqusjsPageTitle = page.title.replace(/'/ig,"\\'")
2 |
3 | script.
4 | function loadDisqusjs () {
5 | function addDisqusjsCSS () {
6 | const ele = document.createElement('link')
7 | ele.rel = 'stylesheet'
8 | ele.href= '!{url_for(theme.asset.disqusjs_css)}'
9 | document.getElementsByTagName('head')[0].appendChild(ele)
10 | }
11 |
12 | function initDisqusjs () {
13 | window.disqusjs = null
14 | disqusjs = new DisqusJS(Object.assign({
15 | shortname: '!{theme.disqusjs.shortname}',
16 | identifier: '!{ url_for(page.path) }',
17 | url: '!{ page.permalink }',
18 | title: '!{ disqusjsPageTitle }',
19 | apikey: '!{theme.disqusjs.apikey}',
20 | },!{JSON.stringify(theme.disqusjs.option)}))
21 |
22 | disqusjs.render(document.getElementById('disqusjs'))
23 | }
24 |
25 | const themeChange = () => {
26 | const ele = document.getElementById('disqus_thread')
27 | if(!ele) return
28 | disqusjs.destroy()
29 | initDisqusjs()
30 | }
31 |
32 |
33 | document.getElementById('darkmode').addEventListener('click', themeChange)
34 |
35 | if (window.disqusJsLoad) initDisqusjs()
36 | else {
37 | addDisqusjsCSS()
38 | getScript('!{url_for(theme.asset.disqusjs)}').then(initDisqusjs)
39 | window.disqusJsLoad = true
40 | }
41 | }
42 |
43 | if ('!{theme.comments.use[0]}' === 'Disqusjs' || !!{theme.comments.lazyload}) {
44 | if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('disqusjs'), loadDisqusjs)
45 | else loadDisqusjs()
46 | }
47 | else {
48 | function loadOtherComment () {
49 | loadDisqusjs()
50 | }
51 | }
52 |
53 |
54 | if is_post() && !theme.comments.lazyload && theme.comments.count && theme.comments.use[0] === 'Disqusjs'
55 | script.
56 | if (window.DISQUSWIDGETS === undefined) {
57 | var d = document, s = d.createElement('script');
58 | s.src = 'https://!{theme.disqus.shortname}.disqus.com/count.js';
59 | s.id = 'dsq-count-scr';
60 | (d.head || d.body).appendChild(s);
61 | } else {
62 | DISQUSWIDGETS.getCount({reset: true});
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/source/css/_page/flink.styl:
--------------------------------------------------------------------------------
1 | #article-container
2 | .flink
3 | margin-bottom: 20px
4 |
5 | .flink-list
6 | overflow: auto
7 | padding: 10px 10px 0
8 | text-align: center
9 |
10 | & > .flink-list-item
11 | position: relative
12 | float: left
13 | overflow: hidden
14 | margin: 15px 7px
15 | width: calc(100% / 3 - 15px)
16 | height: 90px
17 | border-radius: 8px
18 | line-height: 17px
19 | -webkit-transform: translateZ(0)
20 |
21 | +maxWidth1024()
22 | width: calc(50% - 15px) !important
23 |
24 | +maxWidth600()
25 | width: calc(100% - 15px) !important
26 |
27 | &:hover
28 | .flink-item-icon
29 | margin-left: -10px
30 | width: 0
31 |
32 | &:before
33 | position: absolute
34 | top: 0
35 | right: 0
36 | bottom: 0
37 | left: 0
38 | z-index: -1
39 | background: var(--text-bg-hover)
40 | content: ''
41 | transition: transform .3s ease-out
42 | transform: scale(0)
43 |
44 | &:hover:before,
45 | &:focus:before,
46 | &:active:before
47 | transform: scale(1)
48 |
49 | a
50 | color: var(--font-color)
51 | text-decoration: none
52 |
53 | .flink-item-icon
54 | float: left
55 | overflow: hidden
56 | margin: 15px 10px
57 | width: 60px
58 | height: 60px
59 | border-radius: 35px
60 | transition: width .3s ease-out
61 |
62 | img
63 | width: 100%
64 | height: 100%
65 | transition: filter 375ms ease-in .2s, transform .3s
66 | object-fit: cover
67 |
68 | .img-alt
69 | display: none
70 |
71 | .flink-item-name
72 | @extend .limit-one-line
73 | padding: 16px 10px 0 0
74 | height: 40px
75 | font-weight: bold
76 | font-size: 1.43em
77 |
78 | .flink-item-desc
79 | @extend .limit-one-line
80 | padding: 16px 10px 16px 0
81 | height: 50px
82 | font-size: .93em
83 |
84 | .flink-name
85 | margin-bottom: 5px
86 | font-weight: bold
87 | font-size: 1.5em
--------------------------------------------------------------------------------
/scripts/tag/hide.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * @example
4 | * hideInline
5 | * {% hideInline content,display,bg,color %}
6 | * content不能包含當引號,可用 '
7 | * hideBlock
8 | * {% hideBlock display,bg,color %}
9 | * content
10 | * {% endhideBlock %}
11 | * hideToggle
12 | * {% hideToggle display,bg,color %}
13 | * content
14 | * {% endhideToggle %}
15 | */
16 |
17 | 'use strict'
18 |
19 | function hideInline (args) {
20 | args = args.join(' ').split(',')
21 | const content = args[0]
22 | const display = args[1] || 'Click'
23 | const bg = args[2] || false
24 | const color = args[3] || false
25 | let group = 'style="'
26 |
27 | if (bg) group += `background-color: ${bg};`
28 | if (color) group += `color: ${color}`
29 | group += '"'
30 |
31 | return `${content}`
33 | }
34 |
35 | function hideBlock (args, content) {
36 | args = args.join(' ').split(',')
37 | const display = args[0] || 'Click'
38 | const bg = args[1] || false
39 | const color = args[2] || false
40 | let group = 'style="'
41 |
42 | if (bg) group += `background-color: ${bg};`
43 | if (color) group += `color: ${color}`
44 | group += '"'
45 |
46 | return `${hexo.render.renderSync({ text: content, engine: 'markdown' })}
`
48 | }
49 |
50 | function hideToggle (args, content) {
51 | args = args.join(' ').split(',')
52 | const display = args[0]
53 | const bg = args[1] || false
54 | const color = args[2] || false
55 | let group = 'style="'
56 | let border = ''
57 |
58 | if (bg) {
59 | border = `style="border: 1px solid ${bg}"`
60 | group += `background-color: ${bg};`
61 | }
62 | if (color) group += `color: ${color}`
63 | group += '"'
64 |
65 | return `${display}
${hexo.render.renderSync({ text: content, engine: 'markdown' })}
`
66 | }
67 |
68 | hexo.extend.tag.register('hideInline', hideInline)
69 | hexo.extend.tag.register('hideBlock', hideBlock, { ends: true })
70 | hexo.extend.tag.register('hideToggle', hideToggle, { ends: true })
71 |
--------------------------------------------------------------------------------
/scripts/tag/tabs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Tabs
3 | * transplant from hexo-theme-next
4 | * modify by Jerry
5 | */
6 |
7 | 'use strict'
8 |
9 | function postTabs (args, content) {
10 | const tabBlock = /\n([\w\W\s\S]*?)/g
11 |
12 | args = args.join(' ').split(',')
13 | const tabName = args[0]
14 | const tabActive = Number(args[1]) || 0
15 |
16 | const matches = []
17 | let match
18 | let tabId = 0
19 | let tabNav = ''
20 | let tabContent = ''
21 |
22 | !tabName && hexo.log.warn('Tabs block must have unique name!')
23 |
24 | while ((match = tabBlock.exec(content)) !== null) {
25 | matches.push(match[1])
26 | matches.push(match[2])
27 | }
28 |
29 | for (let i = 0; i < matches.length; i += 2) {
30 | const tabParameters = matches[i].split('@')
31 | let postContent = matches[i + 1]
32 | let tabCaption = tabParameters[0] || ''
33 | let tabIcon = tabParameters[1] || ''
34 | let tabHref = ''
35 |
36 | postContent = hexo.render.renderSync({ text: postContent, engine: 'markdown' }).trim()
37 |
38 | tabId += 1
39 | tabHref = (tabName + ' ' + tabId).toLowerCase().split(' ').join('-');
40 |
41 | ((tabCaption.length === 0) && (tabIcon.length === 0)) && (tabCaption = tabName + ' ' + tabId)
42 |
43 | const isOnlyicon = tabIcon.length > 0 && tabCaption.length === 0 ? ' style="text-align: center;"' : ''
44 | const icon = tabIcon.trim()
45 | tabIcon.length > 0 && (tabIcon = ``)
46 |
47 | const toTop = ''
48 |
49 | const isActive = (tabActive > 0 && tabActive === tabId) || (tabActive === 0 && tabId === 1) ? ' active' : ''
50 | tabNav += ``
51 | tabContent += `${postContent + toTop}
`
52 | }
53 |
54 | tabNav = ``
55 | tabContent = `${tabContent}
`
56 |
57 | return `${tabNav + tabContent}
`
58 | }
59 |
60 | hexo.extend.tag.register('tabs', postTabs, { ends: true })
61 | hexo.extend.tag.register('subtabs', postTabs, { ends: true })
62 | hexo.extend.tag.register('subsubtabs', postTabs, { ends: true })
63 |
--------------------------------------------------------------------------------
/layout/includes/rightside.pug:
--------------------------------------------------------------------------------
1 | - const { readmode, translate, darkmode, aside, chat_btn } = theme
2 | mixin rightsideItem(array)
3 | each item in array
4 | case item
5 | //-when 'readmode'
6 | if is_post() && readmode
7 | button#readmode(type="button" title=_p('rightside.readmode_title'))
8 | i.fas.fa-book-open
9 | //-when 'translate'
10 | if translate.enable
11 | button#translateLink(type="button" title=_p('rightside.translate_title'))= translate.default
12 | //-when 'darkmode'
13 | if darkmode.enable && darkmode.button
14 | button#darkmode(type="button" title=_p('rightside.night_mode_title'))
15 | i.fas.fa-adjust
16 | //-when 'hideAside'
17 | if aside.enable && aside.button && page.aside !== false
18 | button#hide-aside-btn(type="button" title=_p('rightside.aside'))
19 | i.fas.fa-arrows-alt-h
20 | when 'toc'
21 | if showToc
22 | button#mobile-toc-button.close(type="button" title=_p("rightside.toc"))
23 | i.dys.shujuwj
24 | //-when 'chat'
25 | if chat_btn
26 | button#chat_btn(type="button" title=_p("rightside.chat"))
27 | i.fas.fa-sms
28 | //-when 'comment'
29 | if commentsJsLoad
30 | a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment"))
31 | i.fas.fa-comments
32 |
33 | #rightside
34 | - const { enable, hide, show } = theme.rightside_item_order
35 | - const hideArray = enable ? hide && hide.split(',') : ['readmode','translate','darkmode','hideAside']
36 | - const showArray = enable ? show && show.split(',') : ['toc','chat','comment']
37 |
38 |
39 | #rightside-config-hide
40 | if hideArray
41 | +rightsideItem(hideArray)
42 | //-#rightside-config-show
43 | if enable
44 | if hide
45 | button#rightside_config(type="button" title=_p("rightside.setting"))
46 | i.fas.fa-cog.fa-spin
47 | else
48 | if is_post()
49 | if (readmode || translate.enable || (darkmode.enable && darkmode.button))
50 | button#rightside_config(type="button" title=_p("rightside.setting"))
51 | i.fas.fa-cog.fa-spin
52 | else if translate.enable || (darkmode.enable && darkmode.button)
53 | button#rightside_config(type="button" title=_p("rightside.setting"))
54 | i.fas.fa-cog.fa-spin
55 |
56 | if showArray
57 | +rightsideItem(showArray)
58 |
59 | //-button#go-up(type="button" title=_p("rightside.back_to_top"))
60 | i.fas.fa-arrow-up
--------------------------------------------------------------------------------
/source/css/_layout/third-party.styl:
--------------------------------------------------------------------------------
1 | #vcomment
2 | font-size: 1.1em
3 |
4 | .vbtn
5 | border: none
6 | background: var(--btn-bg)
7 | color: var(--btn-color)
8 |
9 | &:hover
10 | background: var(--btn-hover-color)
11 |
12 | .vimg
13 | transition: all .3s
14 |
15 | &:hover
16 | transform: rotate(360deg)
17 |
18 | .vcards .vcard .vcontent.expand
19 | &:before,
20 | &:after
21 | z-index: 22
22 |
23 | #waline-wrap
24 | --waline-font-size: 1.1em
25 | --waline-theme-color: $button-bg
26 | --waline-active-color: $button-hover-color
27 |
28 | .wl-comment-actions > button:not(last-child)
29 | padding-right: 4px
30 |
31 | if hexo-config('valine.bg')
32 | #vcomment
33 | textarea
34 | background: url(hexo-config('valine.bg')) 100% 100% no-repeat
35 |
36 | &:focus
37 | background-image: none
38 |
39 | if hexo-config('waline.bg')
40 | #waline-wrap
41 | textarea
42 | background: url(hexo-config('waline.bg')) 100% 100% no-repeat
43 |
44 | &:focus
45 | background-image: none
46 |
47 | .fireworks
48 | position: fixed
49 | top: 0
50 | left: 0
51 | z-index: $fireworks-zIndex
52 | pointer-events: none
53 |
54 | .medium-zoom-image--opened
55 | z-index: 99999 !important
56 | margin: 0 !important
57 |
58 | .medium-zoom-overlay
59 | z-index: 99999 !important
60 |
61 | .mermaid-wrap
62 | margin: 0 0 20px
63 | text-align: center
64 |
65 | & > svg
66 | height: 100%
67 |
68 | .utterances,
69 | .fb-comments iframe
70 | width: 100% !important
71 |
72 | #gitalk-container
73 | .gt-meta
74 | margin: 0 0 .8em
75 | padding: 6px 0 16px
76 |
77 | .katex-wrap
78 | overflow: auto
79 |
80 | if hexo-config('katex') && hexo-config('katex.hide_scrollbar')
81 | &::-webkit-scrollbar
82 | display: none
83 |
84 | // Mathjax
85 | .mathjax-overflow
86 | overflow-x: auto
87 | overflow-y: hidden
88 |
89 | span.mathjax-overflow
90 | display: inline-block
91 | padding: 0 2px
92 | max-width: 100%
93 | vertical-align: bottom
94 |
95 | .aplayer
96 | color: $font-black
97 |
98 | #article-container
99 | .aplayer
100 | margin: 0 0 20px
101 |
102 | if hexo-config('beautify.enable')
103 | ol,
104 | ul
105 | margin: 0
106 | padding: 0
107 |
108 | li
109 | margin: 0
110 | padding: 0 15px
111 |
112 | &:before
113 | content: none
114 |
115 | .snackbar-css
116 | border-radius: 5px !important
--------------------------------------------------------------------------------
/languages/zh-CN.yml:
--------------------------------------------------------------------------------
1 | footer:
2 | framework: 框架
3 | theme: 主题
4 |
5 | copy:
6 | success: 复制成功
7 | error: 复制错误
8 | noSupport: 浏览器不支持
9 |
10 | page:
11 | articles: 文章总览
12 | tag: 标签
13 | category: 分类
14 | archives: 归档
15 |
16 | card_post_count: 条评论
17 |
18 | sticky: 置顶
19 | no_title: 无题
20 |
21 | post:
22 | created: 发表于
23 | updated: 更新于
24 | wordcount: 字数总计
25 | min2read: 阅读时长
26 | min2read_unit: 分钟
27 | page_pv: 阅读量
28 | comments: 评论数
29 | copyright:
30 | author: 文章作者
31 | link: 文章链接
32 | copyright_notice: 版权声明
33 | copyright_content: '本博客所有文章除特别声明外,均采用
34 | %s 许可协议。转载请注明来自 %s!'
35 | recommend: 相关推荐
36 | edit: 编辑
37 |
38 | search:
39 | title: 搜索
40 | load_data: 数据库加载中
41 | algolia_search:
42 | input_placeholder: 搜索文章
43 | hits_empty: '找不到您查询的内容:${query}'
44 | hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒'
45 |
46 | local_search:
47 | input_placeholder: 搜索文章
48 | hits_empty: '找不到您查询的内容:${query}'
49 |
50 | pagination:
51 | prev: 上一篇
52 | next: 下一篇
53 |
54 | comment: 评论
55 |
56 | aside:
57 | articles: 文章
58 | tags: 标签
59 | categories: 分类
60 | card_announcement: 公告
61 | card_categories: 分类
62 | card_tags: 标签
63 | card_archives: 归档
64 | card_recent_post: 最新文章
65 | card_webinfo:
66 | headline: 网站资讯
67 | article_name: 文章数目
68 | runtime:
69 | name: 已运行时间
70 | unit: 天
71 | last_push_date:
72 | name: 最后更新时间
73 | site_wordcount: 本站总字数
74 | site_uv_name: 本站访客数
75 | site_pv_name: 本站总访问量
76 | more_button: 查看更多
77 | card_newest_comments:
78 | headline: 最新评论
79 | loading_text: 正在加载中...
80 | error: 无法获取评论,请确认相关配置是否正确
81 | zero: 没有评论
82 | image: 图片
83 | link: 链接
84 | code: 代码
85 | card_toc: 目录
86 |
87 | date_suffix:
88 | just: 刚刚
89 | min: 分钟前
90 | hour: 小时前
91 | day: 天前
92 | month: 个月前
93 |
94 | donate: 打赏
95 | share: 分享
96 |
97 | rightside:
98 | readmode_title: 阅读模式
99 | translate_title: 简繁转换
100 | night_mode_title: 浅色和深色模式转换
101 | back_to_top: 回到顶部
102 | toc: 目录
103 | scroll_to_comment: 直达评论
104 | setting: 设置
105 | aside: 单栏和双栏切换
106 | chat: 聊天
107 |
108 | copy_copyright:
109 | author: 作者
110 | link: 链接
111 | source: 来源
112 | info: 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
113 |
114 | Snackbar:
115 | chs_to_cht: 你已切换为繁体
116 | cht_to_chs: 你已切换为简体
117 | day_to_night: 你已切换为深色模式
118 | night_to_day: 你已切换为浅色模式
119 |
120 | loading: 加载中...
121 |
122 | error404: 页面没有找到
123 |
--------------------------------------------------------------------------------
/languages/zh-TW.yml:
--------------------------------------------------------------------------------
1 | footer:
2 | framework: 框架
3 | theme: 主題
4 |
5 | copy:
6 | success: 複製成功
7 | error: 複製錯誤
8 | noSupport: 瀏覽器不支援
9 |
10 | page:
11 | articles: 文章總覽
12 | tag: 標籤
13 | category: 分類
14 | archives: 歸檔
15 |
16 | card_post_count: 條評論
17 |
18 | sticky: 置頂
19 | no_title: 無題
20 |
21 | post:
22 | created: 發表於
23 | updated: 更新於
24 | wordcount: 字數總計
25 | min2read: 閱讀時長
26 | min2read_unit: 分鐘
27 | page_pv: 閱讀量
28 | comments: 評論數
29 | copyright:
30 | author: 文章作者
31 | link: 文章連結
32 | copyright_notice: 版權聲明
33 | copyright_content: '本部落格所有文章除特別聲明外,均採用
34 | %s 許可協議。轉載請註明來自 %s!'
35 | recommend: 相關推薦
36 | edit: 編輯
37 |
38 | search:
39 | title: 搜尋
40 | load_data: 資料庫載入中
41 | algolia_search:
42 | input_placeholder: 搜尋文章
43 | hits_empty: '找不到您查詢的內容:${query}'
44 | hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒'
45 |
46 | local_search:
47 | input_placeholder: 搜尋文章
48 | hits_empty: '找不到您查詢的內容:${query}'
49 |
50 | pagination:
51 | prev: 上一篇
52 | next: 下一篇
53 |
54 | comment: 評論
55 |
56 | aside:
57 | articles: 文章
58 | tags: 標籤
59 | categories: 分類
60 | card_announcement: 公告
61 | card_categories: 分類
62 | card_tags: 標籤
63 | card_archives: 歸檔
64 | card_recent_post: 最新文章
65 | card_webinfo:
66 | headline: 網站資訊
67 | article_name: 文章數目
68 | runtime:
69 | name: 已執行時間
70 | unit: 天
71 | last_push_date:
72 | name: 最後更新時間
73 | site_wordcount: 本站總字數
74 | site_uv_name: 本站訪客數
75 | site_pv_name: 本站總訪問量
76 | more_button: 檢視更多
77 | card_newest_comments:
78 | headline: 最新評論
79 | loading_text: 正在載入中...
80 | error: 無法獲取評論,請確認相關配置是否正確
81 | zero: 沒有評論
82 | image: 圖片
83 | link: 連結
84 | code: 程式碼
85 | card_toc: 目錄
86 |
87 | date_suffix:
88 | just: 剛剛
89 | min: 分鐘前
90 | hour: 小時前
91 | day: 天前
92 | month: 個月前
93 |
94 | donate: 打賞
95 | share: 分享
96 |
97 | rightside:
98 | readmode_title: 閱讀模式
99 | translate_title: 簡繁轉換
100 | night_mode_title: 淺色和深色模式轉換
101 | back_to_top: 回到頂部
102 | toc: 目錄
103 | scroll_to_comment: 直達評論
104 | setting: 設定
105 | aside: 單欄和雙欄切換
106 | chat: 聊天
107 |
108 | copy_copyright:
109 | author: 作者
110 | link: 連結
111 | source: 來源
112 | info: 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。
113 |
114 | Snackbar:
115 | chs_to_cht: 你已切換為繁體
116 | cht_to_chs: 你已切換為簡體
117 | day_to_night: 你已切換為深色模式
118 | night_to_day: 你已切換為淺色模式
119 |
120 | loading: 載入中...
121 |
122 | error404: 頁面沒有找到
123 |
--------------------------------------------------------------------------------
/scripts/helpers/page.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * @example
4 | * page_description()
5 | * cloudTags(source, minfontsize, maxfontsize, limit)
6 | */
7 |
8 | 'use strict'
9 |
10 | const { stripHTML, escapeHTML, prettyUrls } = require('hexo-util')
11 | const crypto = require('crypto')
12 |
13 | hexo.extend.helper.register('page_description', function () {
14 | const { config, page } = this
15 | let description = page.description || page.content || page.title || config.description
16 |
17 | if (description) {
18 | description = escapeHTML(stripHTML(description).substring(0, 150)
19 | .trim()
20 | ).replace(/\n/g, ' ')
21 | return description
22 | }
23 | })
24 |
25 | hexo.extend.helper.register('cloudTags', function (options = {}) {
26 | const env = this
27 | let source = options.source
28 | const limit = options.limit
29 |
30 | let result = ''
31 | if (limit > 0) {
32 | source = source.limit(limit)
33 | }
34 |
35 | const sizes = []
36 | source.sort('length').forEach(tag => {
37 | const { length } = tag
38 | if (sizes.includes(length)) return
39 | sizes.push(length)
40 | })
41 |
42 | source.forEach(tag => {
43 | let style = `20px;`
44 | style
45 | result += `${tag.name}`
46 | })
47 | return result
48 | })
49 |
50 | hexo.extend.helper.register('urlNoIndex', function (url = null) {
51 | return prettyUrls(url || this.url, { trailing_index: false, trailing_html: false })
52 | })
53 |
54 | hexo.extend.helper.register('md5', function (path) {
55 | return crypto.createHash('md5').update(decodeURI(this.url_for(path))).digest('hex')
56 | })
57 |
58 | hexo.extend.helper.register('injectHtml', function (data) {
59 | let result = ''
60 | if (!data) return ''
61 | for (let i = 0; i < data.length; i++) {
62 | result += data[i]
63 | }
64 | return result
65 | })
66 |
67 | hexo.extend.helper.register('findArchivesTitle', function (page, menu, date) {
68 | if (page.year) {
69 | const dateStr = page.month ? `${page.year}-${page.month}` : `${page.year}`
70 | const date_format = page.month ? hexo.theme.config.aside.card_archives.format : 'YYYY'
71 | return date(dateStr, date_format)
72 | }
73 |
74 | const defaultTitle = this._p('page.archives')
75 | if (!menu) return defaultTitle
76 |
77 | const loop = (m) => {
78 | for (const key in m) {
79 | if (typeof m[key] === 'object') {
80 | loop(m[key])
81 | }
82 |
83 | if (/\/archives\//.test(m[key])) {
84 | return key
85 | }
86 | }
87 | }
88 |
89 | return loop(menu) || defaultTitle
90 | })
91 |
--------------------------------------------------------------------------------
/source/css/_tags/gallery.styl:
--------------------------------------------------------------------------------
1 | #article-container
2 | figure.gallery-group
3 | position: relative
4 | float: left
5 | overflow: hidden
6 | margin: 6px 4px
7 | width: calc(50% - 8px)
8 | height: 250px
9 | border-radius: 8px
10 | background: $dark-black
11 | -webkit-transform: translate3d(0, 0, 0)
12 |
13 | +maxWidth600()
14 | width: calc(100% - 8px)
15 |
16 | &:hover
17 | img
18 | opacity: .4
19 | transform: translate3d(0, 0, 0)
20 |
21 | .gallery-group-name::after
22 | transform: translate3d(0, 0, 0)
23 |
24 | p
25 | opacity: 1
26 | transform: translate3d(0, 0, 0)
27 |
28 | img
29 | position: relative
30 | margin: 0
31 | max-width: none
32 | width: calc(100% + 20px)
33 | height: 250px
34 | backface-visibility: hidden
35 | opacity: .8
36 | transition: all .3s, filter 375ms ease-in .2s
37 | transform: translate3d(-10px, 0, 0)
38 | object-fit: cover
39 |
40 | figcaption
41 | position: absolute
42 | top: 0
43 | left: 0
44 | padding: 30px
45 | width: 100%
46 | height: 100%
47 | color: $gallery-color
48 | text-transform: uppercase
49 | backface-visibility: hidden
50 |
51 | & > a
52 | position: absolute
53 | top: 0
54 | right: 0
55 | bottom: 0
56 | left: 0
57 | z-index: 1000
58 | opacity: 0
59 |
60 | p
61 | @extend .limit-more-line
62 | margin: 0
63 | padding: 8px 0 0
64 | letter-spacing: 1px
65 | font-size: 1.1em
66 | line-height: 1.5
67 | opacity: 0
68 | transition: opacity .35s, transform .35s
69 | transform: translate3d(100%, 0, 0)
70 | -webkit-line-clamp: 4
71 |
72 | .gallery-group-name
73 | @extend .limit-more-line
74 | position: relative
75 | margin: 0
76 | padding: 8px 0
77 | font-weight: bold
78 | font-size: 1.65em
79 | line-height: 1.5
80 | -webkit-line-clamp: 2
81 |
82 | &:after
83 | position: absolute
84 | bottom: 0
85 | left: 0
86 | width: 100%
87 | height: 2px
88 | background: $gallery-color
89 | content: ''
90 | transition: transform .35s
91 | transform: translate3d(-100%, 0, 0)
92 |
93 | .gallery-group-main
94 | overflow: auto
95 | padding: 0 0 16px
96 |
97 | .fj-gallery
98 | margin: 0 0 16px
99 | opacity: 0
100 |
101 | .img-alt
102 | display: none
--------------------------------------------------------------------------------
/source/css/_page/archives.styl:
--------------------------------------------------------------------------------
1 | .article-sort
2 | margin-left: 10px
3 | padding-left: 20px
4 | border-left: 2px solid lighten($light-blue, 20)
5 |
6 | &-title
7 | position: relative
8 | margin-left: 10px
9 | padding-bottom: 20px
10 | padding-left: 20px
11 | font-size: 1.72em
12 |
13 | &:hover
14 | &:before
15 | border-color: var(--pseudo-hover)
16 |
17 | &:before
18 | position: absolute
19 | top: calc(((100% - 36px) / 2))
20 | left: -9px
21 | z-index: 1
22 | width: w = 10px
23 | height: h = w
24 | border: .5 * w solid $light-blue
25 | border-radius: w
26 | background: var(--card-bg)
27 | content: ''
28 | line-height: h
29 | transition: all .2s ease-in-out
30 |
31 | &:after
32 | position: absolute
33 | bottom: 0
34 | left: 0
35 | z-index: 0
36 | width: 2px
37 | height: 1.5em
38 | background: lighten($light-blue, 20)
39 | content: ''
40 |
41 | &-item
42 | position: relative
43 | display: flex
44 | align-items: center
45 | margin: 0 0 20px 10px
46 | transition: all .2s ease-in-out
47 |
48 | &:hover
49 | &:before
50 | border-color: var(--pseudo-hover)
51 |
52 | &:before
53 | $w = 6px
54 | position: absolute
55 | left: calc(-20px - 17px)
56 | width: w = $w
57 | height: h = w
58 | border: .5 * w solid $light-blue
59 | border-radius: w
60 | background: var(--card-bg)
61 | content: ''
62 | transition: all .2s ease-in-out
63 |
64 | &.no-article-cover
65 | height: 80px
66 |
67 | .article-sort-item-info
68 | padding: 0
69 |
70 | &.year
71 | font-size: 1.43em
72 |
73 | &:hover
74 | &:before
75 | border-color: $light-blue
76 |
77 | &:before
78 | border-color: var(--pseudo-hover)
79 |
80 | &-time
81 | color: $theme-meta-color
82 | font-size: 95%
83 |
84 | time
85 | padding-left: 6px
86 | cursor: default
87 |
88 | &-title
89 | @extend .limit-more-line
90 | color: var(--font-color)
91 | font-size: 1.1em
92 | transition: all .3s
93 | -webkit-line-clamp: 2
94 |
95 | &:hover
96 | color: $text-hover
97 | transform: translateX(10px)
98 |
99 | &-img
100 | overflow: hidden
101 | width: 80px
102 | height: 80px
103 |
104 | img
105 | @extend .imgHover
106 |
107 | &-info
108 | flex: 1
109 | padding: 0 16px
110 |
--------------------------------------------------------------------------------
/source/css/_tags/folding.styl:
--------------------------------------------------------------------------------
1 | details
2 | display: block
3 | padding: 10px
4 | margin: 10px-p 0
5 | border-radius: 15px
6 | background: var(--color-card)
7 | font-size: $fontsize-list
8 | trans()
9 | summary
10 | cursor: pointer
11 | padding: 10px
12 | margin: 0 - 10px
13 | border-radius: 15px
14 | color: black
15 | font-size: 1rem
16 | font-weight: bold
17 | position: relative
18 | line-height: normal
19 | >
20 | p,h1,h2,h3,h4,h5,h6
21 | display: inline
22 | border-bottom: none !important
23 | &:hover
24 | color: var(--color-p)
25 | &:after
26 | position: absolute
27 | content: '+'
28 | text-align: center
29 | top: 50%
30 | transform: translateY(-50%)
31 | right: 10px
32 |
33 | border: 1px solid var(--color-block)
34 | >summary
35 | background: var(--color-block)
36 | &[blue]
37 | border-color: #2196f3
38 | >summary
39 | background: #2196f3
40 | &[cyan]
41 | border-color: #1bcdfc
42 | >summary
43 | background: #1bcdfc
44 | &[green]
45 | border-color: #3dc550
46 | >summary
47 | background: #3dc550
48 | &[yellow]
49 | border-color: #ffbd2b
50 | >summary
51 | background: #ffbd2b
52 | &[red]
53 | border-color: #fe5f58
54 | >summary
55 | background: #fe5f58
56 |
57 | details[open]
58 | border-color: alpha(blue, .2)
59 | >summary
60 | border-bottom: 1px solid alpha(blue, .2)
61 | border-bottom-left-radius: 0
62 | border-bottom-right-radius: 0
63 | &[blue]
64 | border-color: #2196f3
65 | >summary
66 | border-bottom-color: #2196f3
67 | &[cyan]
68 | border-color: #1bcdfc
69 | >summary
70 | border-bottom-color: #1bcdfc
71 | &[green]
72 | border-color: #3dc550
73 | >summary
74 | border-bottom-color: #3dc550
75 | &[yellow]
76 | border-color: #ffbd2b
77 | >summary
78 | border-bottom-color: #ffbd2b
79 | &[red]
80 | border-color: #fe5f58
81 | >summary
82 | border-bottom-color: #fe5f58
83 | >summary
84 | color: black
85 | margin-bottom: 0
86 | &:hover
87 | &:after
88 | content: '-'
89 | >div.content
90 | padding: 10px
91 | margin: 0 - 10px
92 | margin-top: 0
93 | p>a:hover
94 | text-decoration: underline
95 | >
96 | p,.tabs,ul,ol,.highlight,.note,details
97 | &:first-child
98 | margin-top: 0
99 | &:last-child
100 | margin-bottom: 0
101 |
102 | details
103 | margin-bottom 20px
104 | box-shadow 0 0 0 1px #aaa
--------------------------------------------------------------------------------
/source/css/_custom/comment.styl:
--------------------------------------------------------------------------------
1 | if hexo-config('envelope_comment.enable')
2 | $hoverHeight = hexo-config('envelope_comment.height') ? convert(hexo-config('envelope_comment.height')) : 1050px
3 | @media screen and (max-width: 600px)
4 | #beforeimg,
5 | #afterimg
6 | display none !important
7 |
8 | @media screen and (min-width: 600px)
9 | #article-container
10 | img
11 | margin 0 auto 0rem
12 | #form-wrap
13 | overflow hidden
14 | height 447px
15 | position relative
16 | top 0px
17 | transition all 1s ease-in-out .3s
18 | z-index 0
19 | &:hover
20 | height $hoverHeight
21 | top -200px
22 | #maincontent
23 | width 530px
24 | margin 20px auto 0
25 | #beforeimg
26 | position absolute
27 | bottom 126px
28 | left 0px
29 | background-repeat no-repeat
30 | width 530px
31 | height 317px
32 | z-index -100
33 | pointer-events none
34 | #afterimg
35 | position absolute
36 | bottom -2px
37 | left 0
38 | background-repeat no-repeat
39 | width 530px
40 | height 259px
41 | z-index 100
42 | pointer-events none
43 | #envelope
44 | position relative
45 | overflow visible
46 | width 500px
47 | margin 0px auto
48 | transition all 1s ease-in-out .3s
49 | padding-top 200px
50 |
51 | .headerimg
52 | width 100%
53 | overflow hidden
54 | pointer-events none
55 |
56 | .formmain
57 | background white
58 | width 95%
59 | max-width 800px
60 | margin auto auto
61 | border-radius 5px
62 | border 1px solid
63 | overflow hidden
64 | -webkit-box-shadow 0px 0px 20px 0px rgba(0, 0, 0, 0.12)
65 | box-shadow 0px 0px 20px 0px rgba(0, 0, 0, 0.18)
66 | .comments-main
67 | padding 5px 20px
68 | .title3
69 | text-decoration none
70 | color $theme-color
71 | text-align center
72 | .comments
73 | text-align center
74 | border-bottom #ddd 1px solid
75 | border-left #ddd 1px solid
76 | padding-bottom 20px
77 | background-color #eee
78 | margin 15px 0px
79 | padding-left 20px
80 | padding-right 20px
81 | border-top #ddd 1px solid
82 | border-right #ddd 1px solid
83 | padding-top 20px
84 |
85 | .bottomcontent
86 | text-align center
87 | margin-top 40px
88 |
89 | .bottomimg
90 | width 100%
91 | margin 5px auto 5px auto
92 | display block
93 | pointer-events none
94 |
95 | .bottomhr
96 | font-size 12px
97 | text-align center
98 | color #999
99 |
100 | [data-theme='dark']
101 | .formmain
102 | background rgb(50, 50, 50)
103 | .comments
104 | background rgba(90, 90, 90, 0.8)
--------------------------------------------------------------------------------
/source/css/_custom/bar.css:
--------------------------------------------------------------------------------
1 | /* 首页分类条展示 */
2 | #tag-bar{
3 | padding: 0.4rem 1rem 0.4rem 0.5rem;
4 | background: var(--heo-card-bg);
5 | border-radius: 12px;
6 | display: flex;
7 | white-space: nowrap;
8 | overflow: hidden;
9 | margin-bottom: 1rem;
10 | border: var(--style-border);
11 | }
12 |
13 | @media screen and (max-width: 768px){
14 | #tag-bar{
15 | border-radius: 0;
16 | }
17 | }
18 |
19 | #tag #tag-bar{
20 | padding: 0;
21 | border: none;
22 | }
23 |
24 | #tag a.tag-bar-item.select a{
25 | display: none;
26 | }
27 |
28 | .tag-in-bar{
29 | display: flex;
30 | white-space: nowrap;
31 | }
32 |
33 | .tag-in-bar-tips{
34 | margin-right: 1rem;
35 | }
36 |
37 | .tag-bar-items{
38 | white-space: nowrap;
39 | overflow-x: scroll;
40 | display: flex;
41 | }
42 |
43 | .tag-bar-items::-webkit-scrollbar{
44 | display: none;
45 | }
46 |
47 | .tag-bar-item a{
48 | padding: 0.1rem 0.5rem;
49 | margin: 0 0.25rem;
50 | font-weight: bold;
51 | border-radius: 12px;
52 | }
53 |
54 | .tag-bar-item:hover a{
55 | background: var(--heo-main);
56 | color: var(--heo-white);
57 | }
58 |
59 | .tag-bar-item.select a {
60 | background: var(--heo-main);
61 | color: var(--heo-white);
62 | border-radius: 12px;
63 | }
64 |
65 | .tag-bar-more{
66 | margin-left: 1rem;
67 | font-weight: bold;
68 | }
69 |
70 | /* 首页分类条展示 */
71 | #category-bar{
72 | padding: 0.4rem 1rem 0.4rem 0.5rem;
73 | background: var(--heo-card-bg);
74 | border-radius: 12px;
75 | display: flex;
76 | white-space: nowrap;
77 | overflow: hidden;
78 | margin-bottom: 1rem;
79 | border: var(--style-border);
80 | }
81 |
82 | @media screen and (max-width: 768px){
83 | #category-bar{
84 | border-radius: 0;
85 | }
86 | }
87 |
88 | #category #category-bar{
89 | padding: 0;
90 | border: none;
91 | }
92 |
93 | #category a.category-bar-item.select a{
94 | display: none;
95 | }
96 |
97 | .category-in-bar{
98 | display: flex;
99 | white-space: nowrap;
100 | }
101 |
102 | .category-in-bar-tips{
103 | margin-right: 1rem;
104 | }
105 |
106 | .category-bar-items{
107 | white-space: nowrap;
108 | overflow-x: scroll;
109 | display: flex;
110 | }
111 |
112 |
113 |
114 | .category-bar-items::-webkit-scrollbar{
115 | display: none;
116 | }
117 |
118 | .category-bar-item a{
119 | padding: 0.1rem 0.5rem;
120 | margin: 0 0.25rem;
121 | font-weight: bold;
122 | border-radius: 12px;
123 | }
124 |
125 | .category-bar-item:hover a{
126 | background: var(--heo-main);
127 | color: var(--heo-white);
128 | }
129 |
130 | .category-bar-item.select a {
131 | background: var(--heo-main);
132 | color: var(--heo-white);
133 | border-radius: 12px;
134 | }
135 |
136 | .category-bar-more{
137 | margin-left: 1rem;
138 | font-weight: bold;
139 | }
--------------------------------------------------------------------------------
/scripts/events/cdn.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Butterfly
3 | * Merge CDN
4 | */
5 |
6 | 'use strict'
7 |
8 | const { version } = require('../../package.json')
9 | const path = require('path')
10 |
11 | hexo.extend.filter.register('before_generate', () => {
12 | const themeConfig = hexo.theme.config
13 | const { CDN } = themeConfig
14 |
15 | const thirdPartySrc = hexo.render.renderSync({ path: path.join(hexo.theme_dir,'/plugins.yml'), engine: 'yaml'})
16 | const internalSrc = {
17 | main: {
18 | name: 'hexo-theme-butterfly',
19 | file: 'js/main.js',
20 | version
21 | },
22 | utils: {
23 | name: 'hexo-theme-butterfly',
24 | file: 'js/utils.js',
25 | version
26 | },
27 | translate: {
28 | name: 'hexo-theme-butterfly',
29 | file: 'js/tw_cn.js',
30 | version
31 | },
32 | local_search: {
33 | name: 'hexo-theme-butterfly',
34 | file: 'js/search/local-search.js',
35 | version
36 | },
37 | algolia_js: {
38 | name: 'hexo-theme-butterfly',
39 | file: 'js/search/algolia.js',
40 | version
41 | }
42 | }
43 |
44 | const minFile = (file) => {
45 | return file.replace(/(? '.min' + ext)
46 | }
47 |
48 | const createCDNLink = (data, type, cond = '') => {
49 | Object.keys(data).map(key => {
50 | let { name, version, file, other_name } = data[key]
51 |
52 | const min_file = minFile(file)
53 | const cdnjs_name = other_name || name
54 | const cdnjs_file = file.replace(/^[lib|dist]*\/|browser\//g, '')
55 | const min_cdnjs_file = minFile(cdnjs_file)
56 | if (cond === 'internal') file = `source/${file}`
57 | const verType = CDN.version ? `@${version}` : ''
58 |
59 | const value = {
60 | version,
61 | name,
62 | file,
63 | cdnjs_file,
64 | min_file,
65 | min_cdnjs_file,
66 | cdnjs_name
67 | }
68 | const cdnSource = {
69 | local: cond === 'internal' ? cdnjs_file : `/pluginsSrc/${name}/${file}`,
70 | jsdelivr: `https://cdn.jsdelivr.net/npm/${name}${verType}/${min_file}`,
71 | unpkg: `https://unpkg.com/${name}${verType}/${file}`,
72 | cdnjs: `https://cdnjs.cloudflare.com/ajax/libs/${cdnjs_name}/${version}/${min_cdnjs_file}`,
73 | custom: (CDN.custom_format || '').replace(/\$\{(.+?)\}/g, (match, $1) => value[$1])
74 | }
75 |
76 | data[key] = cdnSource[type]
77 | })
78 |
79 | if (cond === 'internal') data['main_css'] = 'css/index.css'
80 | return data
81 | }
82 |
83 | // delete null value
84 | const deleteNullValue = obj => {
85 | if (!obj) return
86 | for (const i in obj) {
87 | obj[i] === null && delete obj[i]
88 | }
89 | return obj
90 | }
91 |
92 | themeConfig.asset = Object.assign(createCDNLink(internalSrc,CDN.internal_provider,'internal'),
93 | createCDNLink(thirdPartySrc,CDN.third_party_provider), deleteNullValue(CDN.option))
94 | })
95 |
--------------------------------------------------------------------------------
/source/css/_page/homepage.styl:
--------------------------------------------------------------------------------
1 | #recent-posts
2 | & > .recent-post-item
3 | margin-top: 20px
4 |
5 | & > .recent-post-item
6 | @extend .cardHover
7 | display: flex
8 | flex-direction: row
9 | align-items: center
10 | overflow: hidden
11 | height: 18em
12 |
13 | if hexo-config('post_double_row') == false
14 | &::after
15 | position: relative
16 | height: 100%
17 | width: 4px
18 | background: #909DF3
19 | content: ''
20 | bottom: 0
21 | border-radius: 100vh
22 | left: 0
23 | right: -99%
24 | animation: glow 10s linear infinite
25 |
26 | +maxWidth768()
27 | height: 4px
28 | width: 100%
29 |
30 | +maxWidth768()
31 | flex-direction: column
32 | height: 350px !important
33 |
34 | &:hover
35 | img.post_bg
36 | transform: scale(1.1)
37 |
38 | &.ads-wrap
39 | display: block !important
40 | height: auto !important
41 |
42 | .post_cover
43 | overflow: hidden
44 | width: 50%
45 | height: 100%
46 |
47 | +maxWidth768()
48 | width: 100%
49 | height: 230px
50 |
51 | img.post_bg
52 | @extend .imgHover
53 |
54 | &.right
55 | order: 1
56 |
57 | +maxWidth768()
58 | order: 0
59 |
60 | & >.recent-post-info
61 | padding: 0 40px
62 | width: 57%
63 | height 100%
64 | max-height: 150px
65 |
66 | +maxWidth768()
67 | padding: 20px 20px 30px
68 | width: 100%
69 |
70 | &.no-cover
71 | width: 100%
72 |
73 | +maxWidth768()
74 | padding: 30px 20px
75 |
76 | & > .article-title
77 | @extend .limit-more-line
78 | color: var(--text-highlight-color)
79 | font-size: 1.72em
80 | line-height: 1.4
81 | transition: all .2s ease-in-out
82 | -webkit-line-clamp: 2
83 |
84 | +maxWidth768()
85 | font-size: 1.43em
86 |
87 | &:hover
88 | color: $text-hover
89 |
90 | & > .article-meta-wrap
91 | margin: 6px 0
92 | color: $theme-meta-color
93 | font-size: 90%
94 |
95 | & > .post-meta-date
96 | cursor: default
97 |
98 | .sticky
99 | color: $sticky-color
100 |
101 | i
102 | margin: 0 4px 0 0
103 |
104 | .fa-spinner
105 | margin: 0
106 |
107 | .article-meta-separator
108 | margin: 0 6px
109 |
110 | .article-meta-link
111 | margin: 0 4px
112 |
113 | if hexo-config('post_meta.page.date_format') == 'relative'
114 | time
115 | display: none
116 |
117 | a
118 | color: $theme-meta-color
119 |
120 | &:hover
121 | color: $text-hover
122 | text-decoration: underline
123 |
124 | & > .content
125 | @extend .limit-more-line
126 | -webkit-line-clamp: 2
--------------------------------------------------------------------------------