This commit is contained in:
xugaoyi 2020-09-26 13:59:34 +08:00
parent 35eba2ecb8
commit e14d02f952
54 changed files with 1145 additions and 1374 deletions

View File

@ -8,7 +8,7 @@
<a href="https://www.npmjs.com/package/vuepress-theme-vdoing"><img alt="npm" src="https://img.shields.io/npm/v/vuepress-theme-vdoing"></a> <a href="https://www.npmjs.com/package/vuepress-theme-vdoing"><img alt="npm" src="https://img.shields.io/npm/v/vuepress-theme-vdoing"></a>
<a href="https://github.com/xugaoyi/vuepress-theme-vdoing/stargazers"><img src="https://img.shields.io/github/stars/xugaoyi/vuepress-theme-vdoing?logo=ReverbNation&logoColor=rgba(255,255,255,.6)" alt="GitHub stars"></a> <a href="https://github.com/xugaoyi/vuepress-theme-vdoing/stargazers"><img src="https://img.shields.io/github/stars/xugaoyi/vuepress-theme-vdoing?logo=ReverbNation&logoColor=rgba(255,255,255,.6)" alt="GitHub stars"></a>
</p> </p>
@ -16,7 +16,7 @@
[文档 (github源)](https://xugaoyi.github.io/vuepress-theme-vdoing-doc/) | [文档 (国内源)](https://doc.xugaoyi.com/vuepress-theme-vdoing-doc/) | [效果Evan's blog](https://xugaoyi.com/) [文档 (github源)](https://xugaoyi.github.io/vuepress-theme-vdoing-doc/) | [文档 (国内源)](https://doc.xugaoyi.com/vuepress-theme-vdoing-doc/) | [效果Evan's blog](https://xugaoyi.com/)
## 介绍 ## 介绍
1. 这个主题的初衷是打造一个好用的、面向程序员的`知识管理工具` 1. 这个主题的初衷是打造一个好用的、面向程序员的`知识管理工具`
@ -57,8 +57,7 @@ npm run dev # or yarn dev
## :sparkling_heart:支持这个项目 ## :sparkling_heart:支持这个项目
我尽己所能地进行开源,并且我尽量回复每个在使用项目时需要帮助的人。很明显,这需要时间,但你可以免费享受这些。 如果你正在使用这个项目并感觉良好,或只是想要支持我继续开发,你可以通过如下任意方式支持我:
然而, 如果你正在使用这个项目并感觉良好,或只是想要支持我继续开发,你可以通过如下方式支持我:
- **Star** 并 分享这个项目 :rocket: - **Star** 并 分享这个项目 :rocket:
- 保留主题 footer(页脚) 的主题链接 :D - 保留主题 footer(页脚) 的主题链接 :D

View File

@ -174,7 +174,7 @@ module.exports = {
options: { options: {
clientID: 'a6e1355287947096b88b', clientID: 'a6e1355287947096b88b',
clientSecret: 'f0e77d070fabfcd5af95bebb82b2d574d7248d71', clientSecret: 'f0e77d070fabfcd5af95bebb82b2d574d7248d71',
repo: 'vuepress-theme-vdoing', // GitHub 仓库 repo: 'blog-gitalk-comment', // GitHub 仓库
owner: 'xugaoyi', // GitHub仓库所有者 owner: 'xugaoyi', // GitHub仓库所有者
admin: ['xugaoyi'], // 对仓库有写权限的人 admin: ['xugaoyi'], // 对仓库有写权限的人
// distractionFreeMode: true, // distractionFreeMode: true,

View File

@ -23,7 +23,8 @@ article: false
### 🐼Me ### 🐼Me
落魄Web前端工程师 web前端小学生
#### 技能 #### 技能
* 熟悉 JavaScript、HTML、CSS、Vue 的拼写 * 熟悉 JavaScript、HTML、CSS、Vue 的拼写
* 了解 Linux、windows、macOS 的开关机方式 * 了解 Linux、windows、macOS 的开关机方式
@ -39,7 +40,8 @@ article: false
- **WeChat or QQ**: <a :href="qqUrl" class='qq'>894072666</a> - **WeChat or QQ**: <a :href="qqUrl" class='qq'>894072666</a>
- **Email**: <a href="mailto:894072666@qq.com">894072666@qq.com</a> - **Email**: <a href="mailto:894072666@qq.com">894072666@qq.com</a>
- **GitHub**: <https://github.com/xugaoyi> - **GitHub**: <https://github.com/xugaoyi>
- **Vdoing官方交流QQ群**694387113 - **Vdoing主题文档**<https://doc.xugaoyi.com/vuepress-theme-vdoing-doc/>
- **Vdoing交流QQ群**694387113
<script> <script>
export default { export default {

View File

@ -21,7 +21,7 @@
"vuepress-plugin-one-click-copy": "^1.0.2", "vuepress-plugin-one-click-copy": "^1.0.2",
"vuepress-plugin-thirdparty-search": "^1.0.2", "vuepress-plugin-thirdparty-search": "^1.0.2",
"vuepress-plugin-zooming": "^1.1.7", "vuepress-plugin-zooming": "^1.1.7",
"vuepress-theme-vdoing": "^1.4.4", "vuepress-theme-vdoing": "^1.5.0",
"yamljs": "^0.3.0" "yamljs": "^0.3.0"
}, },
"dependencies": { "dependencies": {

View File

@ -8,7 +8,7 @@
id="algolia-search-input" id="algolia-search-input"
class="search-query" class="search-query"
:placeholder="placeholder" :placeholder="placeholder"
> />
</form> </form>
</template> </template>
@ -34,7 +34,7 @@ export default {
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css') import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css')
]).then(([docsearch]) => { ]).then(([docsearch]) => {
docsearch = docsearch.default docsearch = docsearch.default
const { algoliaOptions = {}} = userOptions const { algoliaOptions = {} } = userOptions
docsearch(Object.assign( docsearch(Object.assign(
{}, {},
userOptions, userOptions,
@ -127,8 +127,7 @@ export default {
.ds-cursor .algolia-docsearch-suggestion--content .ds-cursor .algolia-docsearch-suggestion--content
background-color #e7edf3 !important background-color #e7edf3 !important
color var(--textColor) color var(--textColor)
@media (min-width $MQMobile)
@media (min-width: $MQMobile)
.algolia-search-wrapper .algolia-search-wrapper
.algolia-autocomplete .algolia-autocomplete
.algolia-docsearch-suggestion .algolia-docsearch-suggestion
@ -144,8 +143,7 @@ export default {
vertical-align top vertical-align top
.ds-dropdown-menu .ds-dropdown-menu
min-width 515px !important min-width 515px !important
@media (max-width $MQMobile)
@media (max-width: $MQMobile)
.algolia-search-wrapper .algolia-search-wrapper
.ds-dropdown-menu .ds-dropdown-menu
min-width calc(100vw - 4rem) !important min-width calc(100vw - 4rem) !important
@ -156,12 +154,11 @@ export default {
padding 0 !important padding 0 !important
background white !important background white !important
.algolia-docsearch-suggestion--subcategory-column-text:after .algolia-docsearch-suggestion--subcategory-column-text:after
content " > " content ' > '
font-size 10px font-size 10px
line-height 14.4px line-height 14.4px
display inline-block display inline-block
width 5px width 5px
margin -3px 3px 0 margin -3px 3px 0
vertical-align middle vertical-align middle
</style> </style>

View File

@ -2,13 +2,14 @@
<div class="custom-page archives-page"> <div class="custom-page archives-page">
<div class="theme-vdoing-wrapper"> <div class="theme-vdoing-wrapper">
<h1> <h1>
<img :src="currentBadge" v-if="$themeConfig.titleBadge === false ? false : true"> <img
:src="currentBadge"
v-if="$themeConfig.titleBadge === false ? false : true"
/>
{{this.$page.title}} {{this.$page.title}}
</h1> </h1>
<ul> <ul>
<template <template v-for="(item, index) in postsList">
v-for="(item, index) in postsList"
>
<li <li
class="year" class="year"
v-if="(year = getYear(index)) !== getYear(index-1)" v-if="(year = getYear(index)) !== getYear(index-1)"
@ -16,13 +17,9 @@
> >
<h2>{{year}}</h2> <h2>{{year}}</h2>
</li> </li>
<li <li :key="index">
:key="index"
>
<router-link :to="item.path"> <router-link :to="item.path">
<span> <span>{{ getDate(item) }}</span>
{{ getDate(item) }}
</span>
{{item.title}} {{item.title}}
</router-link> </router-link>
</li> </li>
@ -39,7 +36,7 @@ import TitleBadgeMixin from '../mixins/titleBadge'
export default { export default {
mixins: [TitleBadgeMixin], mixins: [TitleBadgeMixin],
data() { data () {
return { return {
postsList: [], postsList: [],
@ -47,48 +44,48 @@ export default {
currentPage: 1// currentPage: 1//
} }
}, },
created() { created () {
this.getPageData() this.getPageData()
}, },
mounted() { mounted () {
window.addEventListener('scroll', debounce(() => { window.addEventListener('scroll', debounce(() => {
if(this.postsList.length < this.$sortPostsByDate.length) { if (this.postsList.length < this.$sortPostsByDate.length) {
const docEl = document.documentElement const docEl = document.documentElement
const docBody = document.body const docBody = document.body
const scrollTop = docEl.scrollTop || docBody.scrollTop; const scrollTop = docEl.scrollTop || docBody.scrollTop;
const clientHeight = docEl.clientHeight || docBody.clientHeight; const clientHeight = docEl.clientHeight || docBody.clientHeight;
const scrollHeight = docEl.scrollHeight || docBody.scrollHeight; const scrollHeight = docEl.scrollHeight || docBody.scrollHeight;
if(scrollHeight > clientHeight && scrollTop + clientHeight >= scrollHeight-250) { if (scrollHeight > clientHeight && scrollTop + clientHeight >= scrollHeight - 250) {
this.loadmore() this.loadmore()
} }
} }
}, 200)) }, 200))
}, },
methods: { methods: {
getPageData() { getPageData () {
const currentPage = this.currentPage const currentPage = this.currentPage
const perPage = this.perPage const perPage = this.perPage
this.postsList = this.postsList.concat(this.$sortPostsByDate.slice((currentPage-1)*perPage, currentPage*perPage)) this.postsList = this.postsList.concat(this.$sortPostsByDate.slice((currentPage - 1) * perPage, currentPage * perPage))
}, },
loadmore() { loadmore () {
this.currentPage = this.currentPage+1 this.currentPage = this.currentPage + 1
this.getPageData() this.getPageData()
}, },
getYear(index) { getYear (index) {
const item = this.postsList[index] const item = this.postsList[index]
if (!item) { if (!item) {
return return
} }
const {frontmatter: { date }} = item const { frontmatter: { date } } = item
if (date && type(date) === 'string') { if (date && type(date) === 'string') {
return date.split(" ")[0].slice(0, 4) return date.split(" ")[0].slice(0, 4)
} }
}, },
getDate(item) { getDate (item) {
const {frontmatter: { date }} = item const { frontmatter: { date } } = item
if (date && type(date) === 'string') { if (date && type(date) === 'string') {
return date.split(" ")[0].slice(5, 10) return date.split(" ")[0].slice(5, 10)
} }
@ -100,14 +97,13 @@ export default {
<style lang='stylus'> <style lang='stylus'>
@require '../styles/wrapper.styl' @require '../styles/wrapper.styl'
.archives-page .archives-page
.theme-vdoing-wrapper .theme-vdoing-wrapper
@extend $vdoing-wrapper @extend $vdoing-wrapper
position relative position relative
@media (min-width $contentWidth + 80) @media (min-width $contentWidth + 80)
margin-top 1.5rem!important margin-top 1.5rem !important
ul,li ul, li
margin 0 margin 0
padding 0 padding 0
li li
@ -120,39 +116,35 @@ export default {
&.year:not(:first-child) &.year:not(:first-child)
margin-top 3.5rem margin-top 3.5rem
h2 h2
margin-bottom .8rem margin-bottom 0.8rem
font-weight 400 font-weight 400
padding .5rem 0 padding 0.5rem 0
a a
display block display block
color var(--textColor) color var(--textColor)
transition padding .3s transition padding 0.3s
padding .5rem 2rem padding 0.5rem 2rem
line-height 1.2rem line-height 1.2rem
&:hover &:hover
padding-left 2.5rem padding-left 2.5rem
color $accentColor color $accentColor
background lighten($accentColor, 90%) background #f9f9f9
@media (max-width $contentWidth + 80) @media (max-width $contentWidth + 80)
padding .5rem 1rem padding 0.5rem 1rem
font-weight: normal; font-weight normal
&:hover &:hover
padding-left 1.5rem padding-left 1.5rem
span span
opacity .6 opacity 0.6
font-size .85rem font-size 0.85rem
font-weight 400 font-weight 400
margin-right .3rem margin-right 0.3rem
.loadmore .loadmore
text-align center text-align center
margin-top 1rem margin-top 1rem
opacity .5 opacity 0.5
.theme-mode-dark .archives-page .theme-vdoing-wrapper li a:hover, .theme-mode-read .archives-page .theme-vdoing-wrapper li a:hover
.theme-mode-dark .archives-page .theme-vdoing-wrapper li a:hover,
.theme-mode-read .archives-page .theme-vdoing-wrapper li a:hover
background var(--customBlockBg) background var(--customBlockBg)
.hide-navbar .hide-navbar
.archives-page .archives-page
.theme-vdoing-wrapper .theme-vdoing-wrapper

View File

@ -1,59 +1,102 @@
<template> <template>
<div class="articleInfo-wrap"> <div class="articleInfo-wrap">
<div class="articleInfo"> <div class="articleInfo">
<ul class="breadcrumbs" v-if="articleInfo.classify1 && articleInfo.classify1 !== '_posts'"> <ul
class="breadcrumbs"
v-if="articleInfo.classify1 && articleInfo.classify1 !== '_posts'"
>
<li> <li>
<router-link to="/" class="iconfont icon-home" title="首页" /> <router-link
to="/"
class="iconfont icon-home"
title="首页"
/>
</li> </li>
<li> <li>
<router-link v-if="articleInfo.cataloguePermalink" :to="articleInfo.cataloguePermalink" :title="articleInfo.classify1+'-目录页'">{{articleInfo.classify1}}</router-link> <router-link
<router-link v-else-if="$themeConfig.category !== false" :to="`/categories/?category=${articleInfo.classify1}`" title="分类">{{articleInfo.classify1}}</router-link> v-if="articleInfo.cataloguePermalink"
:to="articleInfo.cataloguePermalink"
:title="articleInfo.classify1+'-目录页'"
>{{articleInfo.classify1}}</router-link>
<router-link
v-else-if="$themeConfig.category !== false"
:to="`/categories/?category=${encodeURIComponent(articleInfo.classify1)}`"
title="分类"
>{{articleInfo.classify1}}</router-link>
<span v-else>{{ articleInfo.classify1 }}</span> <span v-else>{{ articleInfo.classify1 }}</span>
</li> </li>
<li v-if="articleInfo.classify2"> <li v-if="articleInfo.classify2">
<router-link v-if="articleInfo.cataloguePermalink" :to="articleInfo.cataloguePermalink + '/#' + encodeUrl(articleInfo.classify2)" :title="articleInfo.classify1+'#'+articleInfo.classify2">{{articleInfo.classify2}}</router-link> <router-link
<router-link v-else-if="$themeConfig.category !== false" :to="`/categories/?category=${articleInfo.classify2}`" title="分类">{{articleInfo.classify2}}</router-link> v-if="articleInfo.cataloguePermalink"
:to="articleInfo.cataloguePermalink + '/#' + articleInfo.classify2"
:title="articleInfo.classify1+'#'+articleInfo.classify2"
>{{articleInfo.classify2}}</router-link>
<router-link
v-else-if="$themeConfig.category !== false"
:to="`/categories/?category=${encodeURIComponent(articleInfo.classify2)}`"
title="分类"
>{{articleInfo.classify2}}</router-link>
<span v-else>{{articleInfo.classify2}}</span> <span v-else>{{articleInfo.classify2}}</span>
</li> </li>
</ul> </ul>
<div class="info"> <div class="info">
<div class="author iconfont icon-touxiang" title="作者" v-if="articleInfo.author"> <div
<a :href="articleInfo.author.href || articleInfo.author.link" v-if="articleInfo.author.href || articleInfo.author.link && typeof(articleInfo.author.link) === 'string'" target="_blank" class="beLink" title="作者">{{articleInfo.author.name}}</a> class="author iconfont icon-touxiang"
<a v-else href="javascript:;">{{articleInfo.author.name || articleInfo.author}}</a> title="作者"
v-if="articleInfo.author"
>
<a
:href="articleInfo.author.href || articleInfo.author.link"
v-if="articleInfo.author.href || articleInfo.author.link && typeof(articleInfo.author.link) === 'string'"
target="_blank"
class="beLink"
title="作者"
>{{articleInfo.author.name}}</a>
<a
v-else
href="javascript:;"
>{{articleInfo.author.name || articleInfo.author}}</a>
</div> </div>
<div class="date iconfont icon-riqi" title="创建时间" v-if="articleInfo.date"> <div
<a href="javascript:;" >{{articleInfo.date}}</a> class="date iconfont icon-riqi"
title="创建时间"
v-if="articleInfo.date"
>
<a href="javascript:;">{{articleInfo.date}}</a>
</div> </div>
<div class="date iconfont icon-wenjian" title="分类" v-if="$themeConfig.category !== false && !(articleInfo.classify1 && articleInfo.classify1 !== '_posts') && articleInfo.categories"> <div
<router-link :to="`/categories/?category=${item}`" v-for="(item, index) in articleInfo.categories" :key="index"> class="date iconfont icon-wenjian"
{{item}} title="分类"
</router-link> v-if="$themeConfig.category !== false && !(articleInfo.classify1 && articleInfo.classify1 !== '_posts') && articleInfo.categories"
>
<router-link
:to="`/categories/?category=${encodeURIComponent(item)}`"
v-for="(item, index) in articleInfo.categories"
:key="index"
>{{item + ' '}}</router-link>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script>
import encodeMixin from '../mixins/encodeUrl'
<script>
export default { export default {
mixins: [encodeMixin], data () {
data() {
return { return {
articleInfo: {} articleInfo: {}
} }
}, },
created() { created () {
this.articleInfo = this.getPageInfo() this.articleInfo = this.getPageInfo()
}, },
watch: { watch: {
'$route.path'() { '$route.path' () {
this.articleInfo = this.getPageInfo() this.articleInfo = this.getPageInfo()
} }
}, },
methods: { methods: {
getPageInfo() { getPageInfo () {
const pageInfo = this.$page const pageInfo = this.$page
const { relativePath } = pageInfo const { relativePath } = pageInfo
const { sidebar } = this.$themeConfig const { sidebar } = this.$themeConfig
@ -65,7 +108,7 @@ export default {
const classify2 = relativePathArr.length > 2 ? relativePathArr[1].split('.')[1] : undefined// const classify2 = relativePathArr.length > 2 ? relativePathArr[1].split('.')[1] : undefined//
const cataloguePermalink = sidebar && sidebar.catalogue ? sidebar.catalogue[classify1] : undefined// const cataloguePermalink = sidebar && sidebar.catalogue ? sidebar.catalogue[classify1] : undefined//
const author = this.$frontmatter.author || this.$themeConfig.author // const author = this.$frontmatter.author || this.$themeConfig.author //
let date = (pageInfo.frontmatter.date || '').split(' ')[0] // let date = (pageInfo.frontmatter.date || '').split(' ')[0] //
@ -90,19 +133,19 @@ export default {
.articleInfo-wrap .articleInfo-wrap
@extend $wrapper @extend $wrapper
position: relative position relative
z-index: 1 z-index 1
color #888 color #888
.articleInfo .articleInfo
overflow hidden overflow hidden
font-size .92rem font-size 0.92rem
.breadcrumbs .breadcrumbs
margin 0 margin 0
padding 0 padding 0
overflow hidden overflow hidden
display inline-block display inline-block
line-height 2rem line-height 2rem
@media (max-width: 960px) @media (max-width 960px)
width 100% width 100%
li li
list-style-type none list-style-type none
@ -118,7 +161,7 @@ export default {
a a
color #888 color #888
&:before &:before
font-size .92rem font-size 0.92rem
&:hover &:hover
color $accentColor color $accentColor
.icon-home .icon-home
@ -126,13 +169,13 @@ export default {
.info .info
float right float right
line-height 32px line-height 32px
@media (max-width: 960px) @media (max-width 960px)
float left float left
div div
float left float left
margin-left 20px margin-left 20px
font-size .8rem font-size 0.8rem
@media (max-width: 960px) @media (max-width 960px)
margin 0 20px 0 0 margin 0 20px 0 0
&:before &:before
margin-right 3px margin-right 3px

View File

@ -1,9 +1,16 @@
<template> <template>
<aside class="blogger-wrapper card-box"> <aside class="blogger-wrapper card-box">
<div class="avatar"> <div class="avatar">
<img :src="blogger.avatar" alt="头像" title="我好看吗"> <img
:src="blogger.avatar"
alt="头像"
title="我好看吗"
/>
</div> </div>
<div class="icons" v-if="social"> <div
class="icons"
v-if="social"
>
<a <a
v-for="(item, index) in social.icons" v-for="(item, index) in social.icons"
:key="index" :key="index"
@ -15,12 +22,8 @@
/> />
</div> </div>
<div class="blogger"> <div class="blogger">
<span class="name"> <span class="name">{{blogger.name}}</span>
{{blogger.name}} <span class="slogan">{{blogger.slogan}}</span>
</span>
<span class="slogan">
{{blogger.slogan}}
</span>
</div> </div>
</aside> </aside>
</template> </template>
@ -28,10 +31,10 @@
<script> <script>
export default { export default {
computed: { computed: {
blogger() { blogger () {
return this.$themeConfig.blogger return this.$themeConfig.blogger
}, },
social() { social () {
return this.$themeConfig.social return this.$themeConfig.social
} }
} }
@ -64,15 +67,14 @@ export default {
display block display block
float left float left
text-align center text-align center
opacity .8 opacity 0.8
&:hover &:hover
color $accentColor color $accentColor
.blogger .blogger
margin 12px 0 2px 0 margin 12px 0 2px 0
.name .name
font-size 1.4rem font-size 1.4rem
display: block display block
margin-bottom 6px margin-bottom 6px
.slogan .slogan
color var(--textColor) color var(--textColor)

View File

@ -1,17 +1,20 @@
<template> <template>
<div class="body-bg" :style="`background: url(${bgImg}) center center / cover no-repeat;opacity:${opacity}`"></div> <div
class="body-bg"
:style="`background: url(${bgImg}) center center / cover no-repeat;opacity:${opacity}`"
></div>
</template> </template>
<script> <script>
import { type } from '../util' import { type } from '../util'
export default { export default {
data() { data () {
return { return {
bgImg: '', bgImg: '',
opacity: 0.5 opacity: 0.5
} }
}, },
mounted() { mounted () {
let { bodyBgImg, bodyBgImgOpacity } = this.$themeConfig let { bodyBgImg, bodyBgImgOpacity } = this.$themeConfig
if (type(bodyBgImg) === 'string') { if (type(bodyBgImg) === 'string') {
@ -23,7 +26,7 @@ export default {
this.bgImg = bodyBgImg[count] this.bgImg = bodyBgImg[count]
clearInterval(timer) clearInterval(timer)
timer = setInterval(() => { timer = setInterval(() => {
if (++count >= bodyBgImg.length ) { if (++count >= bodyBgImg.length) {
count = 0 count = 0
} }
this.bgImg = bodyBgImg[count] this.bgImg = bodyBgImg[count]
@ -46,5 +49,5 @@ export default {
z-index -999999 z-index -999999
height 100vh height 100vh
width 100vw width 100vw
transition background .5s transition background 0.5s
</style> </style>

View File

@ -22,16 +22,20 @@
@click="showModeBox = true" @click="showModeBox = true"
> >
<transition name="mode"> <transition name="mode">
<ul class="select-box" ref="modeBox" v-show="showModeBox" @click.stop @touchstart.stop> <ul
class="select-box"
ref="modeBox"
v-show="showModeBox"
@click.stop
@touchstart.stop
>
<li <li
v-for="item in modeList" v-for="item in modeList"
:key="item.KEY" :key="item.KEY"
class="iconfont" class="iconfont"
:class="[item.icon, {active: item.KEY === currentMode}]" :class="[item.icon, {active: item.KEY === currentMode}]"
@click="toggleMode(item.KEY)" @click="toggleMode(item.KEY)"
> >{{item.name}}</li>
{{item.name}}
</li>
</ul> </ul>
</transition> </transition>
</div> </div>
@ -44,7 +48,7 @@ import storage from 'good-storage' // 本地存储
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
export default { export default {
data() { data () {
return { return {
threshold: 100, threshold: 100,
scrollTop: null, scrollTop: null,
@ -101,27 +105,27 @@ export default {
this.showModeBox = false this.showModeBox = false
} }
window.addEventListener('scroll', debounce(() => { window.addEventListener('scroll', debounce(() => {
if(this.showModeBox) { if (this.showModeBox) {
this.showModeBox = false this.showModeBox = false
} }
}, 100)) }, 100))
} }
// :hover // :hover
const buttons = document.querySelectorAll('.buttons .button') const buttons = document.querySelectorAll('.buttons .button')
for (let i = 0; i < buttons.length; i++) { for (let i = 0; i < buttons.length; i++) {
const button = buttons[i] const button = buttons[i]
button.addEventListener('touchstart', function(){ button.addEventListener('touchstart', function () {
button.classList.add('hover') button.classList.add('hover')
}) })
button.addEventListener('touchend', function(){ button.addEventListener('touchend', function () {
setTimeout(() => { setTimeout(() => {
button.classList.remove('hover') button.classList.remove('hover')
}, 150) }, 150)
}) })
} }
}, },
computed: { computed: {
showToTop () { showToTop () {
@ -129,7 +133,7 @@ export default {
} }
}, },
methods: { methods: {
toggleMode(key){ toggleMode (key) {
this.currentMode = key this.currentMode = key
this.$emit('toggle-theme-mode', key) this.$emit('toggle-theme-mode', key)
}, },
@ -151,21 +155,21 @@ export default {
this.showCommentBut = this.$frontmatter.comment !== false && this.$frontmatter.home !== true this.showCommentBut = this.$frontmatter.comment !== false && this.$frontmatter.home !== true
this.commentTop = commentEl.offsetTop - 58 this.commentTop = commentEl.offsetTop - 58
} }
},500) }, 500)
}, },
scrollToComment() { scrollToComment () {
window.scrollTo({ top: this.commentTop, behavior: 'smooth' }) window.scrollTo({ top: this.commentTop, behavior: 'smooth' })
this._textareaEl = document.querySelector(this.COMMENT_SELECTOR_1 + ' textarea') || document.querySelector(this.COMMENT_SELECTOR_2 + ' input') || document.querySelector(this.COMMENT_SELECTOR_3 + ' textarea') this._textareaEl = document.querySelector(this.COMMENT_SELECTOR_1 + ' textarea') || document.querySelector(this.COMMENT_SELECTOR_2 + ' input') || document.querySelector(this.COMMENT_SELECTOR_3 + ' textarea')
if( this._textareaEl && this.getScrollTop() !== this._recordScrollTop) { if (this._textareaEl && this.getScrollTop() !== this._recordScrollTop) {
document.addEventListener("scroll", this._handleListener) document.addEventListener("scroll", this._handleListener)
} else if (this._textareaEl && this.getScrollTop() === this._recordScrollTop) { } else if (this._textareaEl && this.getScrollTop() === this._recordScrollTop) {
this._handleFocus() this._handleFocus()
} }
}, },
_handleListener() { _handleListener () {
clearTimeout(this._scrollTimer) clearTimeout(this._scrollTimer)
this._scrollTimer = setTimeout(() => { this._scrollTimer = setTimeout(() => {
document.removeEventListener('scroll', this._handleListener) document.removeEventListener('scroll', this._handleListener)
@ -174,7 +178,7 @@ export default {
}, 30) }, 30)
}, },
_handleFocus() { _handleFocus () {
this._textareaEl.focus() this._textareaEl.focus()
this._textareaEl.classList.add('yellowBorder') this._textareaEl.classList.add('yellowBorder')
setTimeout(() => { setTimeout(() => {
@ -183,7 +187,7 @@ export default {
} }
}, },
watch: { watch: {
'$route.path'() { '$route.path' () {
this.showCommentBut = false this.showCommentBut = false
this.getCommentTop() this.getCommentTop()
} }
@ -192,69 +196,67 @@ export default {
</script> </script>
<style lang='stylus'> <style lang='stylus'>
.yellowBorder .yellowBorder
// border: #FFE089 1px solid!important // border: #FFE089 1px solid!important
border-radius 5px border-radius 5px
box-shadow 0 0 15px #FFE089!important box-shadow 0 0 15px #FFE089 !important
.buttons .buttons
position fixed position fixed
right 2rem right 2rem
bottom 2.5rem bottom 2.5rem
z-index 11 z-index 11
@media (max-width: $MQNarrow) @media (max-width $MQNarrow)
right 1rem right 1rem
bottom 1.5rem bottom 1.5rem
.button .button
width 2.2rem width 2.2rem
height 2.2rem height 2.2rem
line-height 2.2rem line-height 2.2rem
border-radius 50% border-radius 50%
box-shadow 0 2px 6px rgba(0,0,0,.15) box-shadow 0 2px 6px rgba(0, 0, 0, 0.15)
margin-top .9rem margin-top 0.9rem
text-align center text-align center
cursor pointer cursor pointer
transition all .5s transition all 0.5s
background var(--blurBg) background var(--blurBg)
&.hover &.hover
background $accentColor
box-shadow 0 0 15px $accentColor
&:before
color #fff
@media (any-hover hover)
&:hover
background $accentColor background $accentColor
box-shadow 0 0 15px $accentColor box-shadow 0 0 15px $accentColor
&:before &:before
color #fff color #fff
@media (any-hover: hover) .select-box
margin 0
padding 0.8rem 0
position absolute
bottom 0rem
right 1.5rem
background var(--mainBg)
border 1px solid var(--borderColor)
width 120px
border-radius 6px
box-shadow 0 0 15px rgba(255, 255, 255, 0.2)
li
list-style none
line-height 2rem
font-size 0.95rem
&:hover &:hover
background $accentColor color $accentColor
box-shadow 0 0 15px $accentColor &.active
&:before background-color rgba(150, 150, 150, 0.2)
color #fff color $accentColor
.select-box .mode-enter-active, .mode-leave-active
margin 0 transition all 0.3s
padding .8rem 0 .mode-enter, .mode-leave-to
position absolute opacity 0
bottom 0rem transform scale(0.8)
right 1.5rem .fade-enter-active, .fade-leave-active
background var(--mainBg) transition opacity 0.2s
border 1px solid var(--borderColor) .fade-enter, .fade-leave-to
width 120px opacity 0
border-radius 6px
box-shadow 0 0 15px rgba(255,255,255,.2)
li
list-style none
line-height 2rem
font-size .95rem
&:hover
color $accentColor
&.active
background-color rgba(150,150,150,.2)
color $accentColor
.mode-enter-active, .mode-leave-active
transition all .3s
.mode-enter, .mode-leave-to
opacity 0
transform scale(.8)
.fade-enter-active, .fade-leave-active
transition opacity .2s
.fade-enter, .fade-leave-to
opacity 0
</style> </style>

View File

@ -4,27 +4,45 @@
<img :src="$withBase(pageData.imgUrl)" /> <img :src="$withBase(pageData.imgUrl)" />
<dl class="column-info"> <dl class="column-info">
<dt class="title">{{pageData.title}}</dt> <dt class="title">{{pageData.title}}</dt>
<dd class="description" v-html="pageData.description"></dd> <dd
class="description"
v-html="pageData.description"
></dd>
</dl> </dl>
</div> </div>
<div class="catalogue-wrapper" v-if="isStructuring"> <div
class="catalogue-wrapper"
v-if="isStructuring"
>
<div class="catalogue-title">目录</div> <div class="catalogue-title">目录</div>
<div class="catalogue-content"> <div class="catalogue-content">
<template v-for="(item, index) in getCatalogueList()"> <template v-for="(item, index) in getCatalogueList()">
<dl v-if="type(item) === 'array'" :key="index" class="inline"> <dl
v-if="type(item) === 'array'"
:key="index"
class="inline"
>
<dt> <dt>
<router-link :to="item[2]">{{`${index+1}. ${item[1]}`}}</router-link> <router-link :to="item[2]">{{`${index+1}. ${item[1]}`}}</router-link>
</dt> </dt>
</dl> </dl>
<dl v-else-if="type(item) === 'object'" :key="index"> <dl
<dt :id="anchorText = encodeUrl(item.title)"> v-else-if="type(item) === 'object'"
<a :href="`#${anchorText}`" class="header-anchor">#</a> :key="index"
>
<dt :id="anchorText = item.title">
<a
:href="`#${anchorText}`"
class="header-anchor"
>#</a>
{{`${index+1}. ${item.title}`}} {{`${index+1}. ${item.title}`}}
</dt> </dt>
<dd> <dd>
<router-link :to="s[2]" v-for="(s, i) in item.children" :key="i"> <router-link
{{`${index+1}-${i+1}. ${s[1]}`}} :to="s[2]"
</router-link> v-for="(s, i) in item.children"
:key="i"
>{{`${index+1}-${i+1}. ${s[1]}`}}</router-link>
</dd> </dd>
</dl> </dl>
</template> </template>
@ -34,16 +52,14 @@
</template> </template>
<script> <script>
import encodeMixin from '../mixins/encodeUrl'
export default { export default {
mixins: [encodeMixin], data () {
data() {
return { return {
pageData: null, pageData: null,
isStructuring: true isStructuring: true
} }
}, },
created() { created () {
this.getPageData() this.getPageData()
const sidebar = this.$themeConfig.sidebar const sidebar = this.$themeConfig.sidebar
@ -53,7 +69,7 @@ export default {
} }
}, },
methods: { methods: {
getPageData() { getPageData () {
const pageComponent = this.$frontmatter.pageComponent const pageComponent = this.$frontmatter.pageComponent
if (pageComponent && pageComponent.data) { if (pageComponent && pageComponent.data) {
this.pageData = { this.pageData = {
@ -64,23 +80,23 @@ export default {
console.error('请在front matter中设置pageComponent和pageComponent.data数据') console.error('请在front matter中设置pageComponent和pageComponent.data数据')
} }
}, },
getCatalogueList() { getCatalogueList () {
const { sidebar } = this.$site.themeConfig const { sidebar } = this.$site.themeConfig
const key = this.$frontmatter.pageComponent.data.key const key = this.$frontmatter.pageComponent.data.key
const catalogueList = sidebar[`/${key}/`] const catalogueList = sidebar[`/${key}/`]
if(!catalogueList) { if (!catalogueList) {
console.error('未获取到目录数据请查看front matter中设置的key是否正确。') console.error('未获取到目录数据请查看front matter中设置的key是否正确。')
} }
return catalogueList return catalogueList
}, },
type(o) { // type (o) { //
return Object.prototype.toString.call(o).match(/\[object (.*?)\]/)[1].toLowerCase() return Object.prototype.toString.call(o).match(/\[object (.*?)\]/)[1].toLowerCase()
} }
}, },
watch: { watch: {
'$route.path'() { '$route.path' () {
this.getPageData() this.getPageData()
} }
} }
@ -88,7 +104,7 @@ export default {
</script> </script>
<style scoped lang="stylus" rel="stylesheet/stylus"> <style scoped lang="stylus" rel="stylesheet/stylus">
dl,dd dl, dd
margin 0 margin 0
.column-wrapper .column-wrapper
margin-top 1rem margin-top 1rem
@ -105,8 +121,8 @@ dl,dd
font-size 1.6rem font-size 1.6rem
.description .description
color var(--textColor) color var(--textColor)
opacity .8 opacity 0.8
margin .5rem 0 margin 0.5rem 0
.catalogue-wrapper .catalogue-wrapper
.catalogue-title .catalogue-title
font-size 1.45rem font-size 1.45rem
@ -118,7 +134,7 @@ dl,dd
display inline-block display inline-block
width 50% width 50%
margin-bottom 1rem margin-bottom 1rem
@media (max-width: $MQMobileNarrow) @media (max-width $MQMobileNarrow)
width 100% width 100%
a a
width 100% width 100%
@ -131,11 +147,11 @@ dl,dd
&:hover .header-anchor &:hover .header-anchor
opacity 1 opacity 1
dd dd
margin-top .7rem margin-top 0.7rem
a:not(.header-anchor) a:not(.header-anchor)
margin-bottom .5rem margin-bottom 0.5rem
display inline-block display inline-block
width 50% width 50%
@media (max-width: $MQMobileNarrow) @media (max-width $MQMobileNarrow)
width 100% width 100%
</style> </style>

View File

@ -1,12 +1,14 @@
<template> <template>
<div class="categories-wrapper card-box"> <div class="categories-wrapper card-box">
<router-link to="/categories/" class="title iconfont icon-wenjianjia" title="全部分类"> <router-link
{{ length === 'all' ? '全部分类' : '文章分类' }} to="/categories/"
</router-link> class="title iconfont icon-wenjianjia"
title="全部分类"
>{{ length === 'all' ? '全部分类' : '文章分类' }}</router-link>
<div class="categories"> <div class="categories">
<router-link <router-link
:to="`/categories/?category=${item.key}`" :to="`/categories/?category=${encodeURIComponent(item.key)}`"
v-for="(item, index) in categories" v-for="(item, index) in categories"
:key="index" :key="index"
:class="{active: item.key === category}" :class="{active: item.key === category}"
@ -14,9 +16,11 @@
{{item.key}} {{item.key}}
<span>{{item.length}}</span> <span>{{item.length}}</span>
</router-link> </router-link>
<router-link to="/categories/" v-if="length !== 'all' && length < categoriesData.length" class="more"> <router-link
更多... to="/categories/"
</router-link> v-if="length !== 'all' && length < categoriesData.length"
class="more"
>更多...</router-link>
</div> </div>
</div> </div>
</template> </template>
@ -38,7 +42,7 @@ export default {
} }
}, },
computed: { computed: {
categories() { categories () {
if (this.length === 'all') { if (this.length === 'all') {
return this.categoriesData return this.categoriesData
} else { } else {
@ -50,54 +54,53 @@ export default {
</script> </script>
<style lang='stylus'> <style lang='stylus'>
.categories-wrapper .categories-wrapper
.title .title
color var(--textColor) color var(--textColor)
opacity 0.9 opacity 0.9
font-size 1.2rem font-size 1.2rem
.categories .categories
margin-top .6rem margin-top 0.6rem
a a
display block display block
padding 8px .3rem 7px .3rem padding 8px 0.3rem 7px 0.3rem
color var(--textColor) color var(--textColor)
opacity .8 opacity 0.8
font-size .95rem font-size 0.95rem
line-height .95rem line-height 0.95rem
position relative position relative
transition all .3s transition all 0.3s
border-bottom 1px solid var(--borderColor) border-bottom 1px solid var(--borderColor)
margin-top -1px margin-top -1px
overflow: hidden; overflow hidden
white-space: nowrap; white-space nowrap
text-overflow: ellipsis; text-overflow ellipsis
@media (max-width: $MQMobile) @media (max-width $MQMobile)
font-weight 400 font-weight 400
&.more &.more
color $accentColor color $accentColor
&:hover &:hover
color $accentColor color $accentColor
padding-left .6rem padding-left 0.6rem
span span
opacity .8 opacity 0.8
span span
float right float right
background-color var(--textColor) background-color var(--textColor)
color var(--mainBg) color var(--mainBg)
border-radius 8px border-radius 8px
padding 0 .13rem padding 0 0.13rem
min-width 1rem min-width 1rem
height 1rem height 1rem
line-height 1rem line-height 1rem
font-size .6rem font-size 0.6rem
text-align center text-align center
opacity .6 opacity 0.6
transition opacity .3s transition opacity 0.3s
&.active &.active
background $accentColor background $accentColor
color var(--mainBg) color var(--mainBg)
padding-left .8rem padding-left 0.8rem
border-radius 1px border-radius 1px
border-color transparent border-color transparent
</style> </style>

View File

@ -38,7 +38,7 @@ import Pagination from '@theme/components/Pagination'
import CategoriesBar from '@theme/components/CategoriesBar' import CategoriesBar from '@theme/components/CategoriesBar'
export default { export default {
data(){ data () {
return { return {
category: '', category: '',
total: 0, // total: 0, //
@ -47,7 +47,7 @@ export default {
} }
}, },
components: { MainLayout, PostList, Pagination, CategoriesBar }, components: { MainLayout, PostList, Pagination, CategoriesBar },
mounted() { mounted () {
const queryCategory = this.$route.query.category const queryCategory = this.$route.query.category
if (queryCategory) { if (queryCategory) {
this.category = queryCategory this.category = queryCategory
@ -70,12 +70,12 @@ export default {
} }
}, },
methods: { methods: {
handlePagination(i) { // handlePagination (i) { //
this.currentPage = i this.currentPage = i
} }
}, },
watch: { watch: {
'$route.query.category'() { '$route.query.category' () {
this.category = this.$route.query.category this.category = this.$route.query.category
if (this.category) { if (this.category) {
this.total = this.$groupPosts.categories[this.category].length this.total = this.$groupPosts.categories[this.category].length
@ -91,41 +91,40 @@ export default {
<style lang='stylus'> <style lang='stylus'>
.categories-page .categories-page
.categories-wrapper .categories-wrapper
position sticky position sticky
top ($navbarHeight + .9rem) top ($navbarHeight + 0.9rem)
max-height calc(100vh - 10rem) max-height calc(100vh - 10rem)
min-height 4.2rem min-height 4.2rem
@media (max-width: $MQMobile) @media (max-width $MQMobile)
display none display none
.categories .categories
padding-right .5rem padding-right 0.5rem
max-height calc(100vh - 14rem) max-height calc(100vh - 14rem)
min-height 2.2rem min-height 2.2rem
overflow-y auto overflow-y auto
transition all .2s transition all 0.2s
position relative position relative
&::-webkit-scrollbar-track-piece &::-webkit-scrollbar-track-piece
background-color:rgba(0,0,0,.05) background-color rgba(0, 0, 0, 0.05)
&::-webkit-scrollbar-thumb:vertical &::-webkit-scrollbar-thumb:vertical
background-color:rgba(0,0,0,.15) background-color rgba(0, 0, 0, 0.15)
&:hover &:hover
&::-webkit-scrollbar-track-piece &::-webkit-scrollbar-track-piece
background-color:rgba(0,0,0,.1) background-color rgba(0, 0, 0, 0.1)
&::-webkit-scrollbar-thumb:vertical &::-webkit-scrollbar-thumb:vertical
background-color:rgba(0,0,0,.25) background-color rgba(0, 0, 0, 0.25)
.categories-page .categories-page
.main-left .main-left
.categories-wrapper .categories-wrapper
position relative position relative
top 0 top 0
padding .9rem 1.5rem padding 0.9rem 1.5rem
margin-bottom .9rem margin-bottom 0.9rem
max-height 15rem max-height 15rem
border-radius 0 border-radius 0
display none display none
@media (max-width: $MQMobile) @media (max-width $MQMobile)
display block display block
.categories .categories
max-height 12.3rem max-height 12.3rem

View File

@ -8,9 +8,16 @@
type="button" type="button"
:aria-label="dropdownAriaLabel" :aria-label="dropdownAriaLabel"
@click="toggle" @click="toggle"
> >
<router-link v-if="item.link" :to="item.link" class="link-title">{{ item.text }}</router-link> <router-link
<span class="title" v-show="!item.link">{{ item.text }}</span> v-if="item.link"
:to="item.link"
class="link-title"
>{{ item.text }}</router-link>
<span
class="title"
v-show="!item.link"
>{{ item.text }}</span>
<span <span
class="arrow" class="arrow"
:class="open ? 'down' : 'right'" :class="open ? 'down' : 'right'"
@ -44,7 +51,8 @@
isLastItemOfArray(subItem, item.items) && isLastItemOfArray(subItem, item.items) &&
toggle() toggle()
" "
:item="childSubItem"/> :item="childSubItem"
/>
</li> </li>
</ul> </ul>
@ -85,18 +93,18 @@ export default {
return this.item.ariaLabel || this.item.text return this.item.ariaLabel || this.item.text
} }
}, },
beforeMount(){ beforeMount () {
this.isMQMobile = window.innerWidth < 720 ? true : false; this.isMQMobile = window.innerWidth < 720 ? true : false;
window.addEventListener('resize', () => { window.addEventListener('resize', () => {
this.isMQMobile = window.innerWidth < 720 ? true : false; this.isMQMobile = window.innerWidth < 720 ? true : false;
}) })
}, },
methods: { methods: {
toggle () { toggle () {
if(this.isMQMobile){ if (this.isMQMobile) {
this.open = !this.open this.open = !this.open
} }
}, },
isLastItemOfArray (item, array) { isLastItemOfArray (item, array) {
@ -158,7 +166,7 @@ export default {
&.router-link-active &.router-link-active
color $accentColor color $accentColor
&::after &::after
content "" content ''
width 0 width 0
height 0 height 0
border-left 5px solid $accentColor border-left 5px solid $accentColor
@ -171,8 +179,7 @@ export default {
margin-top 0 margin-top 0
padding-top 0 padding-top 0
border-top 0 border-top 0
@media (max-width $MQMobile)
@media (max-width: $MQMobile)
.dropdown-wrapper .dropdown-wrapper
&.open .dropdown-title &.open .dropdown-title
margin-bottom 0.5rem margin-bottom 0.5rem
@ -182,11 +189,11 @@ export default {
&:hover &:hover
color $accentColor color $accentColor
.link-title .link-title
display none display none
.title .title
display inline-block!important display inline-block !important
.nav-dropdown .nav-dropdown
transition height .1s ease-out transition height 0.1s ease-out
overflow hidden overflow hidden
.dropdown-item .dropdown-item
h4 h4
@ -199,12 +206,10 @@ export default {
.dropdown-subitem .dropdown-subitem
font-size 14px font-size 14px
padding-left 1rem padding-left 1rem
@media (min-width $MQMobile)
@media (min-width: $MQMobile)
.dropdown-wrapper .dropdown-wrapper
height 1.8rem height 1.8rem
&:hover .nav-dropdown, &:hover .nav-dropdown, &.open .nav-dropdown
&.open .nav-dropdown
// override the inline style. // override the inline style.
display block !important display block !important
&.open:blur &.open:blur
@ -219,7 +224,7 @@ export default {
display none display none
// Avoid height shaked by clicking // Avoid height shaked by clicking
height auto !important height auto !important
box-sizing border-box; box-sizing border-box
max-height calc(100vh - 2.7rem) max-height calc(100vh - 2.7rem)
overflow-y auto overflow-y auto
position absolute position absolute

View File

@ -5,7 +5,7 @@
@after-enter="unsetHeight" @after-enter="unsetHeight"
@before-leave="setHeight" @before-leave="setHeight"
> >
<slot/> <slot />
</transition> </transition>
</template> </template>
@ -29,5 +29,4 @@ export default {
<style lang="stylus"> <style lang="stylus">
.dropdown-enter, .dropdown-leave-to .dropdown-enter, .dropdown-leave-to
height 0 !important height 0 !important
</style> </style>

View File

@ -1,6 +1,9 @@
<template> <template>
<div class="footer"> <div class="footer">
<div class="icons" v-if="social && social.icons"> <div
class="icons"
v-if="social && social.icons"
>
<a <a
:href="item.link" :href="item.link"
:title="item.title" :title="item.title"
@ -8,15 +11,21 @@
v-for="(item, index) in social.icons" v-for="(item, index) in social.icons"
:key="index" :key="index"
target="_blank" target="_blank"
> ></a>
</a>
</div> </div>
<!--Vdoing主题遵循MIT协议完全开源且免费如果您对主题的修改并不大希望您保留主题的链接--> <!--Vdoing主题遵循MIT协议完全开源且免费如果您对主题的修改并不大希望您保留主题的链接-->
Theme by <a href="https://github.com/xugaoyi/vuepress-theme-vdoing" target="_blank" title="本站主题">Vdoing</a> Theme by
<a
href="https://github.com/xugaoyi/vuepress-theme-vdoing"
target="_blank"
title="本站主题"
>Vdoing</a>
<template v-if="footer"> <template v-if="footer">
| Copyright © {{ footer.createYear }}-{{ new Date().getFullYear() }} | Copyright © {{ footer.createYear }}-{{ new Date().getFullYear() }}
<span v-html="footer.copyrightInfo"></span> <span
v-html="footer.copyrightInfo"
></span>
</template> </template>
</div> </div>
</template> </template>
@ -24,10 +33,10 @@
<script> <script>
export default { export default {
computed: { computed: {
social() { social () {
return this.$themeConfig.social return this.$themeConfig.social
}, },
footer() { footer () {
return this.$themeConfig.footer return this.$themeConfig.footer
} }
} }
@ -36,14 +45,13 @@ export default {
<style lang='stylus'> <style lang='stylus'>
// $mobileSidebarWidth = $sidebarWidth * 0.82 // $mobileSidebarWidth = $sidebarWidth * 0.82
.footer .footer
padding 5rem 1.5rem 2.5rem padding 5rem 1.5rem 2.5rem
text-align center text-align center
color #666 color #666
box-sizing border-box box-sizing border-box
font-size .85rem font-size 0.85rem
transition all .2s ease transition all 0.2s ease
.icons .icons
margin-bottom 12px margin-bottom 12px
.iconfont .iconfont
@ -53,18 +61,14 @@ export default {
color inherit color inherit
&:hover &:hover
color $accentColor color $accentColor
@media (min-width ($MQMobile + 1px))
@media (min-width: ($MQMobile + 1px))
.sidebar-open .footer .sidebar-open .footer
width auto width auto
padding-left ($sidebarWidth + 1.5rem) padding-left ($sidebarWidth + 1.5rem)
@media (min-width 1520px) @media (min-width 1520px)
.have-rightmenu .footer .have-rightmenu .footer
padding-right ($rightMenuWidth + 1.5rem) padding-right ($rightMenuWidth + 1.5rem)
.no-sidebar .footer .no-sidebar .footer
width auto width auto
padding-left 1.5rem padding-left 1.5rem
</style> </style>

View File

@ -377,12 +377,11 @@ export default {
font-size 3.2rem font-size 3.2rem
.description, .action .description, .action
margin 1.5rem auto margin 1.5rem auto
.description .description
max-width 40rem max-width 40rem
font-size 1.1rem font-size 1.1rem
line-height 1.3 line-height 1.3
opacity .9 opacity 0.9
.action-button .action-button
display inline-block display inline-block
font-size 1.2rem font-size 1.2rem
@ -424,17 +423,15 @@ export default {
padding-bottom 0 padding-bottom 0
p p
opacity 0.8 opacity 0.8
padding 0 .8rem padding 0 0.8rem
.feature:hover .feature:hover
.feature-img .feature-img
animation-play-state: running animation-play-state running
h2,p h2, p
color $accentColor color $accentColor
// //
.slide-banner .slide-banner
margin-top: 2rem; margin-top 2rem
.banner-wrapper .banner-wrapper
position relative position relative
.slide-banner-scroll .slide-banner-scroll
@ -460,7 +457,7 @@ export default {
padding-bottom 0 padding-bottom 0
p p
opacity 0.8 opacity 0.8
padding 0 .8rem padding 0 0.8rem
.docs-wrapper .docs-wrapper
position absolute position absolute
bottom 25px bottom 25px
@ -473,22 +470,20 @@ export default {
height 8px height 8px
border-radius 50% border-radius 50%
background var(--textColor) background var(--textColor)
opacity .9 opacity 0.9
&.active &.active
opacity .5 opacity 0.5
// banner // banner
.main-wrapper .main-wrapper
margin-top 2rem margin-top 2rem
.banner.hide-banner .banner.hide-banner
display none display none
& + .main-wrapper & + .main-wrapper
margin-top ($navbarHeight + .9rem) margin-top ($navbarHeight + 0.9rem)
.main-wrapper .main-wrapper
.main-left .main-left
.card-box .card-box
margin-bottom .9rem margin-bottom 0.9rem
.pagination .pagination
margin-bottom 4rem margin-bottom 4rem
.theme-vdoing-content .theme-vdoing-content
@ -498,13 +493,13 @@ export default {
padding-top 2rem padding-top 2rem
&>:last-child &>:last-child
padding-bottom 2rem padding-bottom 2rem
@keyframes heart @keyframes heart
from{transform:translate(0,0)} from
to{transform:translate(0,8px)} transform translate(0, 0)
to
transform translate(0, 8px)
// 1025px // 1025px
@media (max-width: 1025px) @media (max-width 1025px)
.home-wrapper .home-wrapper
.banner .banner
.banner-conent .banner-conent
@ -520,38 +515,33 @@ export default {
.feature-img .feature-img
width 9rem width 9rem
height 9rem height 9rem
// 719px // 719px
@media (max-width: $MQMobile) @media (max-width $MQMobile)
.home-wrapper .home-wrapper
.banner .banner
.banner-conent .banner-conent
.features .features
display none!important display none !important
// 419px // 419px
@media (max-width: $MQMobileNarrow) @media (max-width $MQMobileNarrow)
.home-wrapper .home-wrapper
.banner-conent .banner-conent
padding-left 1.5rem padding-left 1.5rem
padding-right 1.5rem padding-right 1.5rem
.hero .hero
img img
max-height 210px max-height 210px
margin 2rem auto 1.2rem margin 2rem auto 1.2rem
h1 h1
font-size: 2rem font-size 2rem
h1, .description, .action h1, .description, .action
margin: 1.2rem auto margin 1.2rem auto
.description .description
font-size: 1.2rem font-size 1.2rem
.action-button .action-button
font-size 1rem font-size 1rem
padding 0.6rem 1.2rem padding 0.6rem 1.2rem
.feature .feature
h2 h2
font-size: 1.25rem font-size 1.25rem
</style> </style>

View File

@ -13,7 +13,7 @@
.main-wrapper .main-wrapper
margin 1.5rem auto 0 auto margin 1.5rem auto 0 auto
max-width $homePageWidth max-width $homePageWidth
padding 0 .9rem padding 0 0.9rem
box-sizing border-box box-sizing border-box
position relative position relative
display flex display flex
@ -22,23 +22,22 @@
width 72% width 72%
.theme-vdoing-content.card-box .theme-vdoing-content.card-box
padding 1rem 1.5rem padding 1rem 1.5rem
margin-bottom .9rem margin-bottom 0.9rem
.home-content .home-content
padding 1rem 1.5rem 0 padding 1rem 1.5rem 0
.main-right .main-right
>* >*
width 265px width 265px
box-sizing border-box box-sizing border-box
@media (max-width 900px) @media (max-width 900px)
width 235px width 235px
.card-box .card-box
margin 0 0 .9rem .9rem margin 0 0 0.9rem 0.9rem
padding .95rem padding 0.95rem
// 719px // 719px
@media (max-width: $MQMobile) @media (max-width $MQMobile)
.main-wrapper .main-wrapper
margin .9rem 0 margin 0.9rem 0
padding 0 padding 0
display block display block
.main-left .main-left
@ -53,7 +52,7 @@
.blogger-wrapper .blogger-wrapper
display none display none
.card-box .card-box
margin 0 0 .9rem 0 margin 0 0 0.9rem 0
border-radius 0 border-radius 0
width 100% width 100%
</style> </style>

View File

@ -15,7 +15,7 @@
:rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'" :rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'"
> >
{{ item.text }} {{ item.text }}
<OutboundLink/> <OutboundLink />
</a> </a>
</template> </template>

View File

@ -28,7 +28,7 @@
rel="noopener noreferrer" rel="noopener noreferrer"
> >
{{ repoLabel }} {{ repoLabel }}
<OutboundLink/> <OutboundLink />
</a> </a>
</nav> </nav>
</template> </template>
@ -134,19 +134,16 @@ export default {
margin-left 0 margin-left 0
.repo-link .repo-link
margin-left 1.5rem margin-left 1.5rem
// 959 // 959
@media (max-width: $MQNarrow) @media (max-width $MQNarrow)
.nav-links .nav-links
.nav-item .nav-item
margin-left 1.2rem margin-left 1.2rem
@media (max-width $MQMobile)
@media (max-width: $MQMobile)
.nav-links .nav-links
.nav-item, .repo-link .nav-item, .repo-link
margin-left 0 margin-left 0
@media (min-width $MQMobile)
@media (min-width: $MQMobile)
.nav-links a .nav-links a
&:hover, &.router-link-active &:hover, &.router-link-active
color var(--textColor) color var(--textColor)

View File

@ -1,6 +1,6 @@
<template> <template>
<header class="navbar blur"> <header class="navbar blur">
<SidebarButton @toggle-sidebar="$emit('toggle-sidebar')"/> <SidebarButton @toggle-sidebar="$emit('toggle-sidebar')" />
<router-link <router-link
:to="$localePath" :to="$localePath"
@ -11,7 +11,7 @@
v-if="$site.themeConfig.logo" v-if="$site.themeConfig.logo"
:src="$withBase($site.themeConfig.logo)" :src="$withBase($site.themeConfig.logo)"
:alt="$siteTitle" :alt="$siteTitle"
> />
<span <span
ref="siteName" ref="siteName"
class="site-name" class="site-name"
@ -30,8 +30,10 @@
v-if="isAlgoliaSearch" v-if="isAlgoliaSearch"
:options="algolia" :options="algolia"
/> />
<SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false"/> <SearchBox
<NavLinks class="can-hide"/> v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false"
/>
<NavLinks class="can-hide" />
</div> </div>
</header> </header>
</template> </template>
@ -88,7 +90,6 @@ function css (el, property) {
<style lang="stylus"> <style lang="stylus">
$navbar-vertical-padding = 0.7rem $navbar-vertical-padding = 0.7rem
$navbar-horizontal-padding = 1.5rem $navbar-horizontal-padding = 1.5rem
.navbar .navbar
padding $navbar-vertical-padding $navbar-horizontal-padding padding $navbar-vertical-padding $navbar-horizontal-padding
line-height $navbarHeight - 1.4rem line-height $navbarHeight - 1.4rem
@ -115,20 +116,17 @@ $navbar-horizontal-padding = 1.5rem
top $navbar-vertical-padding top $navbar-vertical-padding
display flex display flex
.search-box .search-box
flex: 0 0 auto flex 0 0 auto
vertical-align top vertical-align top
.hide-navbar .hide-navbar
.navbar .navbar
transform translateY(-100%) transform translateY(-100%)
// 959 // 959
@media (max-width: $MQNarrow) @media (max-width $MQNarrow)
.navbar .navbar
.site-name .site-name
display none display none
@media (max-width $MQMobile)
@media (max-width: $MQMobile)
.navbar .navbar
padding-left 4rem padding-left 4rem
.can-hide .can-hide

View File

@ -2,21 +2,26 @@
<div> <div>
<main class="page"> <main class="page">
<slot name="top" /> <slot name="top" />
<div :class="`theme-vdoing-wrapper ${bgStyle}`" > <div :class="`theme-vdoing-wrapper ${bgStyle}`">
<ArticleInfo v-if="isArticle()" /> <ArticleInfo v-if="isArticle()" />
<component class="theme-vdoing-content" v-if="pageComponent" :is="pageComponent" /> <component
class="theme-vdoing-content"
v-if="pageComponent"
:is="pageComponent"
/>
<div class="content-wrapper"> <div class="content-wrapper">
<RightMenu v-if="showRightMenu"/> <RightMenu v-if="showRightMenu" />
<h1 v-if="showTitle"> <h1 v-if="showTitle">
<img :src="currentBadge" v-if="$themeConfig.titleBadge === false ? false : true"> <img
:src="currentBadge"
v-if="$themeConfig.titleBadge === false ? false : true"
/>
{{this.$page.title}} {{this.$page.title}}
</h1> </h1>
<Content class="theme-vdoing-content" /> <Content class="theme-vdoing-content" />
</div> </div>
<PageEdit /> <PageEdit />
<PageNav v-bind="{ sidebarItems }" /> <PageNav v-bind="{ sidebarItems }" />
@ -30,7 +35,6 @@
<slot name="bottom" /> <slot name="bottom" />
</main> </main>
</div> </div>
</template> </template>
@ -46,28 +50,28 @@ import TitleBadgeMixin from '../mixins/titleBadge'
export default { export default {
mixins: [TitleBadgeMixin], mixins: [TitleBadgeMixin],
data() { data () {
return { return {
updateBarConfig: null updateBarConfig: null
} }
}, },
props: ['sidebarItems'], props: ['sidebarItems'],
components: { PageEdit, PageNav, ArticleInfo, Catalogue, UpdateArticle, RightMenu}, components: { PageEdit, PageNav, ArticleInfo, Catalogue, UpdateArticle, RightMenu },
created() { created () {
this.updateBarConfig = this.$themeConfig.updateBar this.updateBarConfig = this.$themeConfig.updateBar
}, },
computed: { computed: {
bgStyle(){ bgStyle () {
const { contentBgStyle } = this.$themeConfig const { contentBgStyle } = this.$themeConfig
return contentBgStyle ? 'bg-style-' + contentBgStyle : '' return contentBgStyle ? 'bg-style-' + contentBgStyle : ''
}, },
isShowUpdateBar() { isShowUpdateBar () {
return this.updateBarConfig && this.updateBarConfig.showToArticle === false ? false : true return this.updateBarConfig && this.updateBarConfig.showToArticle === false ? false : true
}, },
showTitle() { showTitle () {
return !this.$frontmatter.pageComponent return !this.$frontmatter.pageComponent
}, },
showRightMenu(){ showRightMenu () {
return this.$page.headers && (this.$frontmatter && this.$frontmatter.sidebar && this.$frontmatter.sidebar !== false) !== false return this.$page.headers && (this.$frontmatter && this.$frontmatter.sidebar && this.$frontmatter.sidebar !== false) !== false
}, },
pageComponent () { pageComponent () {
@ -75,7 +79,7 @@ export default {
} }
}, },
methods: { methods: {
isArticle() { isArticle () {
return this.$frontmatter.article !== false return this.$frontmatter.article !== false
} }
} }
@ -88,13 +92,12 @@ export default {
.page .page
padding-bottom 2rem padding-bottom 2rem
display block display block
@media (max-width $MQMobile) @media (max-width $MQMobile)
padding-top ($navbarHeight) padding-top $navbarHeight
@media (min-width $MQMobile) @media (min-width $MQMobile)
padding-top ($navbarHeight + 1.5rem) padding-top ($navbarHeight + 1.5rem)
>* >*
@extend $vdoing-wrapper @extend $vdoing-wrapper
.theme-vdoing-wrapper .theme-vdoing-wrapper
.content-wrapper .content-wrapper
position relative position relative
@ -102,48 +105,42 @@ export default {
margin-bottom -0.2rem margin-bottom -0.2rem
max-width 2.2rem max-width 2.2rem
max-height 2.2rem max-height 2.2rem
.theme-vdoing-wrapper .theme-vdoing-wrapper
--linesColor: rgba(50, 0, 0, 0.05) --linesColor rgba(50, 0, 0, 0.05)
&.bg-style-1 // &.bg-style-1 //
background-image: linear-gradient(90deg, var(--linesColor) 3%, transparent 3%), linear-gradient(0deg, var(--linesColor) 3%, transparent 3%) background-image linear-gradient(90deg, var(--linesColor) 3%, transparent 3%), linear-gradient(0deg, var(--linesColor) 3%, transparent 3%)
background-position: center center background-position center center
background-size: 20px 20px background-size 20px 20px
&.bg-style-2 // 线 &.bg-style-2 // 线
background-image: repeating-linear-gradient(0, var(--linesColor) 0, var(--linesColor) 1px, transparent 0, transparent 50%); background-image repeating-linear-gradient(0, var(--linesColor) 0, var(--linesColor) 1px, transparent 0, transparent 50%)
background-size: 30px 30px background-size 30px 30px
&.bg-style-3 // 线 &.bg-style-3 // 线
background-image: repeating-linear-gradient(90deg, var(--linesColor) 0, var(--linesColor) 1px, transparent 0, transparent 50%); background-image repeating-linear-gradient(90deg, var(--linesColor) 0, var(--linesColor) 1px, transparent 0, transparent 50%)
background-size: 30px 30px background-size 30px 30px
&.bg-style-4 // 线 &.bg-style-4 // 线
background-image: repeating-linear-gradient(-45deg, var(--linesColor) 0, var(--linesColor) 1px, transparent 0, transparent 50%); background-image repeating-linear-gradient(-45deg, var(--linesColor) 0, var(--linesColor) 1px, transparent 0, transparent 50%)
background-size: 20px 20px background-size 20px 20px
&.bg-style-5 // 线 &.bg-style-5 // 线
background-image: repeating-linear-gradient(45deg, var(--linesColor) 0, var(--linesColor) 1px, transparent 0, transparent 50%); background-image repeating-linear-gradient(45deg, var(--linesColor) 0, var(--linesColor) 1px, transparent 0, transparent 50%)
background-size: 20px 20px background-size 20px 20px
&.bg-style-6 // &.bg-style-6 //
background-image: radial-gradient(var(--linesColor) 1px, transparent 1px); background-image radial-gradient(var(--linesColor) 1px, transparent 1px)
background-size: 10px 10px background-size 10px 10px
// //
.theme-mode-dark .theme-mode-dark
.theme-vdoing-wrapper .theme-vdoing-wrapper
--linesColor: rgba(125,125,125, 0.05) --linesColor rgba(125, 125, 125, 0.05)
/** /**
* 右侧菜单的自适应 * 右侧菜单的自适应
*/ */
@media (min-width: 720px) and (max-width: 1279px) @media (min-width 720px) and (max-width 1279px)
.have-rightmenu .have-rightmenu
.page .page
padding-right .8rem!important padding-right 0.8rem !important
@media (max-width 1279px)
@media (max-width: 1279px)
.right-menu-wrapper .right-menu-wrapper
display none display none
@media (min-width: 1280px) @media (min-width 1280px)
.sidebar .sidebar-sub-headers .sidebar .sidebar-sub-headers
display none display none
</style> </style>

View File

@ -1,17 +1,33 @@
<template> <template>
<div class="page-edit"> <div class="page-edit">
<div class="edit-link" v-if="editLink"> <div
<a :href="editLink" target="_blank" rel="noopener noreferrer">{{ editLinkText }}</a> class="edit-link"
v-if="editLink"
>
<a
:href="editLink"
target="_blank"
rel="noopener noreferrer"
>{{ editLinkText }}</a>
<OutboundLink /> <OutboundLink />
</div> </div>
<div class="tags" v-if="$themeConfig.tag !== false && tags && tags[0]"> <div
<router-link :to="`/tags/?tag=${encodeUrl(item)}`" v-for="(item, index) in tags" :key="index" title="标签"> class="tags"
#{{item}} v-if="$themeConfig.tag !== false && tags && tags[0]"
</router-link> >
<router-link
:to="`/tags/?tag=${encodeURIComponent(item)}`"
v-for="(item, index) in tags"
:key="index"
title="标签"
>#{{item}}</router-link>
</div> </div>
<div class="last-updated" v-if="lastUpdated"> <div
class="last-updated"
v-if="lastUpdated"
>
<span class="prefix">{{ lastUpdatedText }}:</span> <span class="prefix">{{ lastUpdatedText }}:</span>
<span class="time">{{ lastUpdated }}</span> <span class="time">{{ lastUpdated }}</span>
</div> </div>
@ -20,16 +36,14 @@
<script> <script>
import isNil from 'lodash/isNil' import isNil from 'lodash/isNil'
import { endingSlashRE, outboundRE } from '../util' import { endingSlashRE, outboundRE } from '../util'
import encodeMixin from '../mixins/encodeUrl'
export default { export default {
mixins: [encodeMixin],
name: 'PageEdit', name: 'PageEdit',
computed: { computed: {
tags() { tags () {
return this.$frontmatter.tags return this.$frontmatter.tags
}, },
lastUpdated () { lastUpdated () {
return this.$page.lastUpdated return this.$page.lastUpdated
}, },
@ -114,43 +128,39 @@ export default {
padding-top 1rem padding-top 1rem
padding-bottom 1rem padding-bottom 1rem
overflow auto overflow auto
.edit-link .edit-link
display inline-block display inline-block
float left float left
margin 0 2rem .5rem 0 margin 0 2rem 0.5rem 0
a a
margin-right 0.25rem margin-right 0.25rem
.tags .tags
float left float left
a a
margin 0 .8rem .5rem 0 margin 0 0.8rem 0.5rem 0
display inline-block display inline-block
color var(--textLightenColor) color var(--textLightenColor)
padding 0.2rem 0.7rem padding 0.2rem 0.7rem
font-size 0.9em font-size 0.9em
background-color rgba(128,128,128,0.08) background-color rgba(128, 128, 128, 0.08)
border-radius 3px border-radius 3px
opacity .8 opacity 0.8
.last-updated .last-updated
float right float right
font-size 0.9em font-size 0.9em
.prefix .prefix
font-weight 500 font-weight 500
color var(--textColor) color var(--textColor)
opacity .8 opacity 0.8
.time .time
font-weight 400 font-weight 400
color #aaa color #aaa
@media (max-width $MQMobile)
@media (max-width: $MQMobile)
.page-edit .page-edit
.edit-link,.tags .edit-link, .tags
margin-bottom .5rem margin-bottom 0.5rem
.last-updated .last-updated
width 100% width 100%
font-size 0.8em font-size 0.8em
text-align left text-align left
</style> </style>

View File

@ -1,7 +1,10 @@
<template> <template>
<div class="page-nav-wapper"> <div class="page-nav-wapper">
<!-- 页面中间左右翻页 --> <!-- 页面中间左右翻页 -->
<div class="page-nav-centre-wrap" v-if="$themeConfig.pageButton !== false && (prev || next)"> <div
class="page-nav-centre-wrap"
v-if="$themeConfig.pageButton !== false && (prev || next)"
>
<router-link <router-link
class="page-nav-centre page-nav-centre-prev" class="page-nav-centre page-nav-centre-prev"
v-if="prev" v-if="prev"
@ -9,12 +12,9 @@
@mouseenter.native="showTooltip($event)" @mouseenter.native="showTooltip($event)"
@mousemove.native="showTooltip($event)" @mousemove.native="showTooltip($event)"
> >
<div class="tooltip"> <div class="tooltip">{{ prev.title || prev.path }}</div>
{{ prev.title || prev.path }}
</div>
</router-link> </router-link>
<router-link <router-link
class="page-nav-centre page-nav-centre-next" class="page-nav-centre page-nav-centre-next"
v-if="next" v-if="next"
@ -22,23 +22,36 @@
@mouseenter.native="showTooltip($event)" @mouseenter.native="showTooltip($event)"
@mousemove.native="showTooltip($event)" @mousemove.native="showTooltip($event)"
> >
<div class="tooltip"> <div class="tooltip">{{ next.title || next.path }}</div>
{{ next.title || next.path }}
</div>
</router-link> </router-link>
</div> </div>
<!-- 底部翻页按钮 --> <!-- 底部翻页按钮 -->
<div class="page-nav" v-if="prev || next"> <div
class="page-nav"
v-if="prev || next"
>
<p class="inner"> <p class="inner">
<span v-if="prev" class="prev"> <span
v-if="prev"
class="prev"
>
<router-link v-if="prev" class="prev" :to="prev.path">{{ prev.title || prev.path }}</router-link> <router-link
v-if="prev"
class="prev"
:to="prev.path"
>{{ prev.title || prev.path }}</router-link>
</span> </span>
<span v-if="next" class="next"> <span
<router-link v-if="next" :to="next.path">{{ next.title || next.path }}</router-link> v-if="next"
class="next"
>
<router-link
v-if="next"
:to="next.path"
>{{ next.title || next.path }}</router-link>
</span> </span>
</p> </p>
</div> </div>
@ -62,7 +75,7 @@ export default {
} }
}, },
methods: { methods: {
showTooltip(e) { showTooltip (e) {
const clientW = document.body.clientWidth const clientW = document.body.clientWidth
const X = e.clientX const X = e.clientX
@ -72,7 +85,7 @@ export default {
} }
const tooltipEleStyle = tooltipEle.style const tooltipEleStyle = tooltipEle.style
if (X < clientW/2) { if (X < clientW / 2) {
tooltipEleStyle.right = null tooltipEleStyle.right = null
tooltipEleStyle.left = X + 10 + 'px' tooltipEleStyle.left = X + 10 + 'px'
} else { } else {
@ -165,8 +178,6 @@ function flatten (items, res) {
overflow auto // clear float overflow auto // clear float
.next .next
float right float right
.page-nav-centre-wrap .page-nav-centre-wrap
.page-nav-centre .page-nav-centre
position fixed position fixed
@ -175,21 +186,21 @@ function flatten (items, res) {
height 70px height 70px
margin-top -35px margin-top -35px
outline 0 outline 0
transition all .2s transition all 0.2s
border-radius 3px border-radius 3px
opacity .55 opacity 0.55
z-index 99 z-index 99
@media (max-width: 1340px) @media (max-width 1340px)
width 50px width 50px
@media (max-width: 960px) @media (max-width 960px)
display none display none
&:hover &:hover
background rgba(153, 153, 153, .15) background rgba(153, 153, 153, 0.15)
opacity 1 opacity 1
.tooltip .tooltip
display block display block
&:before &:before
content: "" content ''
display block display block
width 10px width 10px
height 10px height 10px
@ -203,7 +214,7 @@ function flatten (items, res) {
margin auto margin auto
.tooltip .tooltip
display none display none
background rgba(0, 0, 0, .5) background rgba(0, 0, 0, 0.5)
color #fff color #fff
padding 4px 8px padding 4px 8px
font-size 13px font-size 13px
@ -211,19 +222,16 @@ function flatten (items, res) {
position fixed position fixed
max-width 200px max-width 200px
z-index 99 z-index 99
.page-nav-centre-prev .page-nav-centre-prev
left 0 left 0
&:before &:before
transform rotate(-135deg) transform rotate(-135deg)
.page-nav-centre-next .page-nav-centre-next
right: 0 right 0
&:before &:before
transform rotate(45deg) transform rotate(45deg)
.sidebar-open .page-nav-centre-wrap .page-nav-centre-prev .sidebar-open .page-nav-centre-wrap .page-nav-centre-prev
left $sidebarWidth left $sidebarWidth
.no-sidebar .page-nav-centre-wrap .page-nav-centre-prev .no-sidebar .page-nav-centre-wrap .page-nav-centre-prev
left 0 left 0
</style> </style>

View File

@ -1,80 +1,86 @@
<template> <template>
<div class="pagination"> <div class="pagination">
<span class="card-box prev iconfont icon-jiantou-zuo" <span
:class="{disabled: currentPage === 1}" class="card-box prev iconfont icon-jiantou-zuo"
@click="goPrex()" :class="{disabled: currentPage === 1}"
@click="goPrex()"
> >
<p>上一页</p> <p>上一页</p>
</span> </span>
<!-- 分页在5页及以下时 --> <!-- 分页在5页及以下时 -->
<div class="pagination-list" v-if="pages <= 5"> <div
<span class="card-box" class="pagination-list"
v-for="item in pages" v-if="pages <= 5"
:key="item" >
:class="{active: currentPage === item}" <span
@click="goIndex(item)" class="card-box"
> v-for="item in pages"
{{item}} :key="item"
</span> :class="{active: currentPage === item}"
@click="goIndex(item)"
>{{item}}</span>
</div> </div>
<!-- 分页在5页以上 --> <!-- 分页在5页以上 -->
<div class="pagination-list" v-else> <div
class="pagination-list"
v-else
>
<!-- 一号位 --> <!-- 一号位 -->
<span class="card-box" <span
:class="{active: currentPage === 1}" class="card-box"
@click="goIndex(1)" :class="{active: currentPage === 1}"
> @click="goIndex(1)"
1 >1</span>
</span>
<!-- 二号位 --> <!-- 二号位 -->
<span class="ellipsis ell-two" <span
v-show="currentPage > 3" class="ellipsis ell-two"
@click="goIndex(currentPage - 2)" v-show="currentPage > 3"
title="上两页" @click="goIndex(currentPage - 2)"
title="上两页"
/> />
<!--这里没有使用v-if的原因是因为部署版本在当前页大于3时刷新页面出现了一些bug--> <!--这里没有使用v-if的原因是因为部署版本在当前页大于3时刷新页面出现了一些bug-->
<span class="card-box" <span
v-show="currentPage <= 3" class="card-box"
:class="{active: currentPage === 2}" v-show="currentPage <= 3"
@click="goIndex(2)" :class="{active: currentPage === 2}"
@click="goIndex(2)"
>2</span> >2</span>
<!-- 三号位 --> <!-- 三号位 -->
<span class="card-box" <span
:class="{active: currentPage >= 3 && currentPage <= (pages - 2)}" class="card-box"
@click="goIndex(threeNum())" :class="{active: currentPage >= 3 && currentPage <= (pages - 2)}"
> @click="goIndex(threeNum())"
{{ threeNum() }} >{{ threeNum() }}</span>
</span>
<!-- 四号位 --> <!-- 四号位 -->
<span class="ellipsis ell-four" <span
v-show="currentPage < (pages - 2)" class="ellipsis ell-four"
@click="goIndex(currentPage + 2)" v-show="currentPage < (pages - 2)"
title="下两页" @click="goIndex(currentPage + 2)"
title="下两页"
/> />
<span class="card-box" <span
v-show="currentPage >= (pages - 2)" class="card-box"
:class="{active: currentPage === pages-1}" v-show="currentPage >= (pages - 2)"
@click="goIndex(pages-1)" :class="{active: currentPage === pages-1}"
> @click="goIndex(pages-1)"
{{ pages-1 }} >{{ pages-1 }}</span>
</span>
<!-- 五号位 --> <!-- 五号位 -->
<span class="card-box" <span
:class="{active: currentPage === pages}" class="card-box"
@click="goIndex(pages)" :class="{active: currentPage === pages}"
> @click="goIndex(pages)"
{{pages}} >{{pages}}</span>
</span>
</div> </div>
<span class="card-box next iconfont icon-jiantou-you" <span
:class="{disabled: currentPage === pages}" class="card-box next iconfont icon-jiantou-you"
@click="goNext()" :class="{disabled: currentPage === pages}"
@click="goNext()"
> >
<p>下一页</p> <p>下一页</p>
</span> </span>
@ -98,12 +104,12 @@ export default {
} }
}, },
computed: { computed: {
pages() { // pages () { //
return Math.ceil(this.total / this.perPage) return Math.ceil(this.total / this.perPage)
} }
}, },
methods: { methods: {
threeNum() { // threeNum () { //
let num = 3 let num = 3
const currentPage = this.currentPage const currentPage = this.currentPage
const pages = this.pages const pages = this.pages
@ -116,19 +122,19 @@ export default {
} }
return num return num
}, },
goPrex() { goPrex () {
let currentPage = this.currentPage let currentPage = this.currentPage
if (currentPage > 1) { if (currentPage > 1) {
this.handleEmit(--currentPage) this.handleEmit(--currentPage)
} }
}, },
goNext() { goNext () {
let currentPage = this.currentPage let currentPage = this.currentPage
if (currentPage < this.pages) { if (currentPage < this.pages) {
this.handleEmit(++currentPage) this.handleEmit(++currentPage)
} }
}, },
goIndex(i) { goIndex (i) {
if (i !== this.currentPage) { if (i !== this.currentPage) {
this.handleEmit(i) this.handleEmit(i)
} }
@ -145,18 +151,18 @@ export default {
position relative position relative
height 60px height 60px
text-align center text-align center
span span
line-height 1rem line-height 1rem
opacity .9 opacity 0.9
cursor pointer cursor pointer
&:hover &:hover
color $accentColor color $accentColor
&.ellipsis &.ellipsis
opacity .5 opacity 0.5
&::before &::before
content '...' content '...'
font-size 1.2rem font-size 1.2rem
@media (any-hover: hover) @media (any-hover hover)
&.ell-two &.ell-two
&:hover &:hover
&::before &::before
@ -165,14 +171,13 @@ export default {
&:hover &:hover
&::before &::before
content '»' content '»'
> span > span
position absolute position absolute
top 0 top 0
padding 1rem 1.2rem padding 1rem 1.2rem
font-size .95rem font-size 0.95rem
&.disabled &.disabled
color rgba(125,125,125,.5) color rgba(125, 125, 125, 0.5)
&.prev &.prev
left 0 left 0
border-top-right-radius 32px border-top-right-radius 32px
@ -182,50 +187,47 @@ export default {
border-top-left-radius 32px border-top-left-radius 32px
border-bottom-left-radius 32px border-bottom-left-radius 32px
&::before &::before
float right float right
margin-left .3rem margin-left 0.3rem
p p
display inline display inline
line-height .95rem line-height 0.95rem
.pagination-list .pagination-list
span span
display inline-block display inline-block
width 2.5rem width 2.5rem
height 2.5rem height 2.5rem
line-height 2.5rem line-height 2.5rem
margin .3rem margin 0.3rem
&.active &.active
background $accentColor background $accentColor
color var(--mainBg) color var(--mainBg)
@media (max-width 800px)
@media (max-width: 800px)
.pagination .pagination
> span > span
padding 1rem 1.5rem padding 1rem 1.5rem
p p
display none display none
// 719px // 719px
@media (max-width: $MQMobile) @media (max-width $MQMobile)
.pagination .pagination
> span // > span //
padding .9rem 1.5rem padding 0.9rem 1.5rem
.pagination-list .pagination-list
span span
width 2.3rem width 2.3rem
height 2.3rem height 2.3rem
line-height 2.3rem line-height 2.3rem
margin .25rem margin 0.25rem
@media (max-width 390px)
@media (max-width: 390px)
.pagination .pagination
> span // > span //
padding .8rem 1.3rem padding 0.8rem 1.3rem
.pagination-list .pagination-list
span span
width 2rem width 2rem
height 2rem height 2rem
line-height 2rem line-height 2rem
margin .1rem margin 0.1rem
margin-top .3rem margin-top 0.3rem
</style> </style>

View File

@ -1,46 +1,77 @@
<template> <template>
<div class="post-list" ref="postList"> <div
class="post-list"
<transition-group tag="div" name="post"> ref="postList"
<div class="post card-box" :class="item.frontmatter.sticky && 'iconfont icon-zhiding'" v-for="item in sortPosts" :key="item.key"> >
<transition-group
tag="div"
name="post"
>
<div
class="post card-box"
:class="item.frontmatter.sticky && 'iconfont icon-zhiding'"
v-for="item in sortPosts"
:key="item.key"
>
<div class="title-wrapper"> <div class="title-wrapper">
<h2> <h2>
<router-link :to="item.path">{{item.title}}</router-link> <router-link :to="item.path">{{item.title}}</router-link>
</h2> </h2>
<div class="article-info"> <div class="article-info">
<a title="作者" class="iconfont icon-touxiang" target="_blank" <a
v-if="item.author && item.author.href" title="作者"
:href="item.author.href" class="iconfont icon-touxiang"
> target="_blank"
{{ item.author.name ? item.author.name : item.author }} v-if="item.author && item.author.href"
</a> :href="item.author.href"
<span title="作者" class="iconfont icon-touxiang" >{{ item.author.name ? item.author.name : item.author }}</a>
<span
title="作者"
class="iconfont icon-touxiang"
v-else-if="item.author" v-else-if="item.author"
> >{{ item.author.name ? item.author.name : item.author }}</span>
{{ item.author.name ? item.author.name : item.author }}
</span>
<span title="创建时间" class="iconfont icon-riqi" v-if="item.frontmatter.date"> <span
{{ item.frontmatter.date.split(' ')[0]}} title="创建时间"
class="iconfont icon-riqi"
v-if="item.frontmatter.date"
>{{ item.frontmatter.date.split(' ')[0]}}</span>
<span
title="分类"
class="iconfont icon-wenjian"
v-if="$themeConfig.category !== false && item.frontmatter.categories"
>
<router-link
:to="`/categories/?category=${encodeURIComponent(c)}`"
v-for="(c, index) in item.frontmatter.categories"
:key="index"
>{{c}}</router-link>
</span> </span>
<span title="分类" class="iconfont icon-wenjian" v-if="$themeConfig.category !== false && item.frontmatter.categories"> <span
<router-link :to="`/categories/?category=${encodeUrl(c)}`" v-for="(c, index) in item.frontmatter.categories" :key="index"> title="标签"
{{c}} class="iconfont icon-biaoqian tags"
</router-link> v-if="$themeConfig.tag !== false && item.frontmatter.tags && item.frontmatter.tags[0]"
</span> >
<span title="标签" class="iconfont icon-biaoqian tags" v-if="$themeConfig.tag !== false && item.frontmatter.tags && item.frontmatter.tags[0]"> <router-link
<router-link :to="`/tags/?tag=${encodeUrl(t)}`" v-for="(t, index) in item.frontmatter.tags" :key="index"> :to="`/tags/?tag=${encodeURIComponent(t)}`"
{{t}} v-for="(t, index) in item.frontmatter.tags"
</router-link> :key="index"
>{{t}}</router-link>
</span> </span>
</div> </div>
</div> </div>
<div class="excerpt-wrapper" v-if="item.excerpt"> <div
<div class="excerpt" v-html="item.excerpt"> class="excerpt-wrapper"
</div> v-if="item.excerpt"
<router-link :to="item.path" class="readmore iconfont icon-jiantou-you"> >
阅读全文 <div
</router-link> class="excerpt"
v-html="item.excerpt"
></div>
<router-link
:to="item.path"
class="readmore iconfont icon-jiantou-you"
>阅读全文</router-link>
</div> </div>
</div> </div>
</transition-group> </transition-group>
@ -48,10 +79,7 @@
</template> </template>
<script> <script>
import encodeMixin from '../mixins/encodeUrl'
export default { export default {
mixins: [encodeMixin],
props: { props: {
category: { category: {
type: String, type: String,
@ -70,20 +98,20 @@ export default {
default: 10 default: 10
} }
}, },
data() { data () {
return { return {
sortPosts: [], sortPosts: [],
postListOffsetTop: 0 postListOffsetTop: 0
} }
}, },
created() { created () {
this.setPosts() this.setPosts()
}, },
mounted() { mounted () {
// this.postListOffsetTop = this.getElementToPageTop(this.$refs.postList) - 240 // this.postListOffsetTop = this.getElementToPageTop(this.$refs.postList) - 240
}, },
watch: { watch: {
currentPage() { currentPage () {
if (this.$route.query.p != this.currentPage) { // 退 if (this.$route.query.p != this.currentPage) { // 退
this.$router.push({ this.$router.push({
query: { query: {
@ -97,28 +125,28 @@ export default {
// },0) // },0)
this.setPosts() this.setPosts()
}, },
category() { category () {
this.setPosts() this.setPosts()
}, },
tag() { tag () {
this.setPosts() this.setPosts()
} }
}, },
methods: { methods: {
setPosts() { setPosts () {
const currentPage = this.currentPage const currentPage = this.currentPage
const perPage = this.perPage const perPage = this.perPage
let posts = [] let posts = []
if (this.category) { if (this.category) {
posts = this.$groupPosts.categories[this.category] posts = this.$groupPosts.categories[this.category]
} else if(this.tag){ } else if (this.tag) {
posts = this.$groupPosts.tags[this.tag] posts = this.$groupPosts.tags[this.tag]
}else { } else {
posts = this.$sortPosts posts = this.$sortPosts
} }
this.sortPosts = posts.slice((currentPage-1)*perPage, currentPage*perPage) this.sortPosts = posts.slice((currentPage - 1) * perPage, currentPage * perPage)
}, },
// getElementToPageTop(el) { // getElementToPageTop(el) {
// if(el && el.parentElement) { // if(el && el.parentElement) {
@ -137,39 +165,39 @@ export default {
position relative position relative
padding 1rem 1.5rem padding 1rem 1.5rem
margin-bottom 0.9rem margin-bottom 0.9rem
transition: all 0.3s transition all 0.3s
&.post-leave-active &.post-leave-active
display none display none
&.post-enter &.post-enter
opacity: 0 opacity 0
transform: translateX(-20px) transform translateX(-20px)
&::before &::before
position absolute position absolute
top -1px top -1px
right 0 right 0
font-size 2.5rem font-size 2.5rem
color $accentColor color $accentColor
opacity .85 opacity 0.85
.title-wrapper .title-wrapper
a a
color var(--textColor) color var(--textColor)
&:hover &:hover
color $accentColor color $accentColor
h2 h2
margin .5rem 0 margin 0.5rem 0
font-size 1.4rem font-size 1.4rem
border none border none
a a
@media (max-width: $MQMobile) @media (max-width $MQMobile)
font-weight 400 font-weight 400
.article-info .article-info
> a, > span > a, > span
opacity .7 opacity 0.7
font-size .8rem font-size 0.8rem
margin-right 1rem margin-right 1rem
cursor pointer cursor pointer
&::before &::before
margin-right .3rem margin-right 0.3rem
a a
margin 0 margin 0
&:not(:first-child) &:not(:first-child)
@ -177,26 +205,25 @@ export default {
content '/' content '/'
.tags a:not(:first-child)::before .tags a:not(:first-child)::before
content '、' content '、'
.excerpt-wrapper .excerpt-wrapper
border-top 1px solid var(--borderColor) border-top 1px solid var(--borderColor)
margin .5rem 0 margin 0.5rem 0
overflow hidden overflow hidden
.excerpt .excerpt
margin-bottom .3rem margin-bottom 0.3rem
font-size 0.92rem font-size 0.92rem
h1,h2,h3 h1, h2, h3
display none display none
img img
max-height 280px max-height 280px
max-width 100%!important max-width 100% !important
margin 0 auto margin 0 auto
.readmore .readmore
float right float right
margin-right 1rem margin-right 1rem
line-height 1rem line-height 1rem
&::before &::before
float right float right
font-size .8rem font-size 0.8rem
margin .1rem 0 0 .2rem margin 0.1rem 0 0 0.2rem
</style> </style>

View File

@ -3,12 +3,12 @@
<div class="right-menu-margin"> <div class="right-menu-margin">
<div class="right-menu-content"> <div class="right-menu-content">
<div <div
:class="['right-menu-item', 'level'+item.level, { active: item.slug === hashText }]" :class="['right-menu-item', 'level'+item.level, { active: item.slug === hashText }]"
v-for="(item, i) in headers" v-for="(item, i) in headers"
:key="i" :key="i"
> >
<a :href="'#'+item.slug">{{item.title}}</a> <a :href="'#'+item.slug">{{item.title}}</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@ -16,27 +16,27 @@
<script> <script>
export default { export default {
data() { data () {
return { return {
headers: [], headers: [],
hashText: '' hashText: ''
} }
}, },
mounted() { mounted () {
this.getHeadersData() this.getHeadersData()
this.getHashText() this.getHashText()
}, },
watch: { watch: {
$route() { $route () {
this.headers = this.$page.headers this.headers = this.$page.headers
this.getHashText() this.getHashText()
} }
}, },
methods: { methods: {
getHeadersData() { getHeadersData () {
this.headers = this.$page.headers this.headers = this.$page.headers
}, },
getHashText() { getHashText () {
this.hashText = decodeURIComponent(window.location.hash.slice(1)) this.hashText = decodeURIComponent(window.location.hash.slice(1))
} }
} }
@ -44,14 +44,13 @@ export default {
</script> </script>
<style lang='stylus'> <style lang='stylus'>
.right-menu-wrapper .right-menu-wrapper
width $rightMenuWidth width $rightMenuWidth
float right float right
margin-right -($rightMenuWidth + 60px) margin-right -($rightMenuWidth + 60px)
position sticky position sticky
top 0 top 0
font-size .9rem font-size 0.9rem
.right-menu-margin .right-menu-margin
margin-top ($navbarHeight + 1rem) margin-top ($navbarHeight + 1rem)
.right-menu-content .right-menu-content
@ -61,12 +60,12 @@ export default {
&::-webkit-scrollbar-track-piece &::-webkit-scrollbar-track-piece
background none background none
&::-webkit-scrollbar-thumb:vertical &::-webkit-scrollbar-thumb:vertical
background-color hsla(0,0%,49%,.3) background-color hsla(0, 0%, 49%, 0.3)
&:hover &:hover
overflow-y auto overflow-y auto
.right-menu-item .right-menu-item
padding 4px 15px padding 4px 15px
border-left .15rem solid var(--borderColor) border-left 0.15rem solid var(--borderColor)
&.level3 &.level3
padding-left 28px padding-left 28px
&.active &.active
@ -81,17 +80,16 @@ export default {
width ($rightMenuWidth - 30px) width ($rightMenuWidth - 30px)
&:hover &:hover
color $accentColor color $accentColor
.have-body-img
.have-body-img
.right-menu-wrapper .right-menu-wrapper
.right-menu-margin .right-menu-margin
padding .3rem 0 padding 0.3rem 0
background var(--sidebarBg) background var(--sidebarBg)
border-radius 5px border-radius 5px
.right-menu-item .right-menu-item
border-color transparent border-color transparent
&.active &.active
border-left .2rem solid $accentColor border-left 0.2rem solid $accentColor
&:hover &:hover
border-left .2rem solid $accentColor border-left 0.2rem solid $accentColor
</style> </style>

View File

@ -1,11 +1,17 @@
<template> <template>
<aside class="sidebar"> <aside class="sidebar">
<div class="blogger" v-if="blogger"> <div
<img :src="blogger.avatar"> class="blogger"
v-if="blogger"
>
<img :src="blogger.avatar" />
<div class="blogger-info"> <div class="blogger-info">
<h3>{{blogger.name}}</h3> <h3>{{blogger.name}}</h3>
<div class="icons" v-if="blogger.social"> <div
class="icons"
v-if="blogger.social"
>
<a <a
:href="item.link" :href="item.link"
:title="item.title" :title="item.title"
@ -13,18 +19,18 @@
v-for="(item, index) in blogger.social.icons" v-for="(item, index) in blogger.social.icons"
:key="index" :key="index"
target="_blank" target="_blank"
> ></a>
</a>
</div> </div>
<span v-else> <span v-else>{{blogger.slogan}}</span>
{{blogger.slogan}}
</span>
</div> </div>
</div> </div>
<NavLinks/> <NavLinks />
<slot name="top"/> <slot name="top" />
<SidebarLinks :depth="0" :items="items"/> <SidebarLinks
<slot name="bottom"/> :depth="0"
:items="items"
/>
<slot name="bottom" />
</aside> </aside>
</template> </template>
@ -38,9 +44,9 @@ export default {
components: { SidebarLinks, NavLinks }, components: { SidebarLinks, NavLinks },
props: ['items'], props: ['items'],
computed: { computed: {
blogger() { blogger () {
return this.$themeConfig.blogger return this.$themeConfig.blogger
} }
} }
@ -73,7 +79,7 @@ export default {
line-height 1.7 line-height 1.7
font-weight bold font-weight bold
& > li:not(:first-child) & > li:not(:first-child)
margin-top .75rem margin-top 0.75rem
.blogger .blogger
display none display none
border-bottom 1px solid var(--borderColor) border-bottom 1px solid var(--borderColor)
@ -81,17 +87,17 @@ export default {
width 60px width 60px
height 60px height 60px
border-radius 5px border-radius 5px
margin .75rem 1rem margin 0.75rem 1rem
.blogger-info .blogger-info
flex 1 flex 1
h3 h3
margin .95rem 0 .7rem margin 0.95rem 0 0.7rem
font-size 1.1rem font-size 1.1rem
.icons .iconfont .icons .iconfont
font-size 1.2rem font-size 1.2rem
padding-right .6rem padding-right 0.6rem
color #777 color #777
@media (max-width: $MQMobile) @media (max-width $MQMobile)
.sidebar .sidebar
.blogger .blogger
display flex display flex

View File

@ -1,7 +1,21 @@
<template> <template>
<div class="sidebar-button" @click="$emit('toggle-sidebar')" title="目录"> <div
<svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512"> class="sidebar-button"
<path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class=""></path> @click="$emit('toggle-sidebar')"
title="目录"
>
<svg
class="icon"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
role="img"
viewBox="0 0 448 512"
>
<path
fill="currentColor"
d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"
class
/>
</svg> </svg>
</div> </div>
</template> </template>
@ -16,14 +30,13 @@
padding 0.6rem padding 0.6rem
top 0.6rem top 0.6rem
left 1rem left 1rem
@media (max-width: $MQMobile) @media (max-width $MQMobile)
display block display block
.icon .icon
display block display block
width 1.25rem width 1.25rem
height 1.25rem height 1.25rem
@media (min-width ($MQMobile + 1px))
@media (min-width: ($MQMobile + 1px))
$mobileSidebarWidth = $sidebarWidth * 0.82 $mobileSidebarWidth = $sidebarWidth * 0.82
.sidebar-button .sidebar-button
width 40px width 40px
@ -38,7 +51,7 @@
color #888 color #888
border-radius 50% border-radius 50%
padding 0 padding 0
transition left .2s ease transition left 0.2s ease
&:hover &:hover
background $accentColor background $accentColor
color #fff color #fff

View File

@ -23,8 +23,8 @@
<span <span
class="arrow" class="arrow"
v-if="collapsable" v-if="collapsable"
:class="open ? 'down' : 'right'"> :class="open ? 'down' : 'right'"
</span> ></span>
</router-link> </router-link>
<p <p
@ -37,8 +37,8 @@
<span <span
class="arrow" class="arrow"
v-if="collapsable" v-if="collapsable"
:class="open ? 'down' : 'right'"> :class="open ? 'down' : 'right'"
</span> ></span>
</p> </p>
<DropdownTransition> <DropdownTransition>
@ -90,15 +90,14 @@ export default {
& > .sidebar-group-items & > .sidebar-group-items
padding-left 1rem padding-left 1rem
& > li > .sidebar-link & > li > .sidebar-link
font-size: 0.95em; font-size 0.95em
border-left none border-left none
&.depth-2 &.depth-2
& > .sidebar-heading & > .sidebar-heading
border-left none border-left none
.sidebar-heading .sidebar-heading
color var(--textColor) color var(--textColor)
transition color .15s ease transition color 0.15s ease
cursor pointer cursor pointer
font-size 1.1em font-size 1.1em
font-weight bold font-weight bold
@ -121,9 +120,8 @@ export default {
border-left-color $accentColor border-left-color $accentColor
&:hover &:hover
color $accentColor color $accentColor
.sidebar-group-items .sidebar-group-items
transition height .1s ease-out transition height 0.1s ease-out
font-size 0.95em font-size 0.95em
overflow hidden overflow hidden
</style> </style>

View File

@ -97,7 +97,6 @@ function renderExternal (h, to, text) {
.sidebar .sidebar-sub-headers .sidebar .sidebar-sub-headers
padding-left 1rem padding-left 1rem
font-size 0.95em font-size 0.95em
a.sidebar-link a.sidebar-link
font-size 1em font-size 1em
font-weight 400 font-weight 400
@ -106,8 +105,8 @@ a.sidebar-link
border-left 0.25rem solid transparent border-left 0.25rem solid transparent
padding 0.35rem 1rem 0.35rem 1.25rem padding 0.35rem 1rem 0.35rem 1.25rem
line-height 1.4 line-height 1.4
width: 100% width 100%
box-sizing: border-box box-sizing border-box
&:hover &:hover
color $accentColor color $accentColor
&.active &.active

View File

@ -3,7 +3,10 @@
class="sidebar-links" class="sidebar-links"
v-if="items.length" v-if="items.length"
> >
<li v-for="(item, i) in items" :key="i"> <li
v-for="(item, i) in items"
:key="i"
>
<SidebarGroup <SidebarGroup
v-if="item.type === 'group'" v-if="item.type === 'group'"
:item="item" :item="item"

View File

@ -1,23 +1,24 @@
<template> <template>
<div class="tags-wrapper card-box"> <div class="tags-wrapper card-box">
<router-link to="/tags/" class="title iconfont icon-biaoqian1" title="全部标签"> <router-link
{{ length === 'all' ? '全部标签' : '热门标签' }} to="/tags/"
</router-link> class="title iconfont icon-biaoqian1"
title="全部标签"
>{{ length === 'all' ? '全部标签' : '热门标签' }}</router-link>
<div class="tags"> <div class="tags">
<template v-for="(item, index) in tags" > <template v-for="(item, index) in tags">
<router-link <router-link
:to="`/tags/?tag=${item.key}`" :to="`/tags/?tag=${encodeURIComponent(item.key)}`"
:key="index" :key="index"
:style="tagStyleList[index]" :style="tagStyleList[index]"
:class="{active: item.key === tag}" :class="{active: item.key === tag}"
> >{{item.key}}</router-link>
{{item.key}} <span :key="index+tags.length" />
</router-link>
<span :key="index+tags.length"/>
</template> </template>
<router-link to="/tags/" v-if="length !== 'all' && tagsData.length > length"> <router-link
更多... to="/tags/"
</router-link> v-if="length !== 'all' && tagsData.length > length"
>更多...</router-link>
</div> </div>
</div> </div>
</template> </template>
@ -38,19 +39,19 @@ export default {
default: 'all' default: 'all'
} }
}, },
data() { data () {
return { return {
tagBgColor: ['#11a8cd', '#F8B26A', '#67CC86', '#E15B64', '#F47E60', '#849B87'], tagBgColor: ['#11a8cd', '#F8B26A', '#67CC86', '#E15B64', '#F47E60', '#849B87'],
tagStyleList: [] tagStyleList: []
} }
}, },
created() { created () {
for (let i = 0, tagH = this.tags.length; i < tagH; i++) { for (let i = 0, tagH = this.tags.length; i < tagH; i++) {
this.tagStyleList.push(this.getTagStyle()) this.tagStyleList.push(this.getTagStyle())
} }
}, },
computed: { computed: {
tags() { tags () {
if (this.length === 'all') { if (this.length === 'all') {
return this.tagsData return this.tagsData
} else { } else {
@ -59,7 +60,7 @@ export default {
} }
}, },
methods: { methods: {
getTagStyle() { getTagStyle () {
const tagBgColor = this.tagBgColor const tagBgColor = this.tagBgColor
const randomColor = tagBgColor[Math.floor(Math.random() * tagBgColor.length)] const randomColor = tagBgColor[Math.floor(Math.random() * tagBgColor.length)]
return `background: ${randomColor};--randomColor:${randomColor};` return `background: ${randomColor};--randomColor:${randomColor};`
@ -69,36 +70,36 @@ export default {
</script> </script>
<style lang='stylus'> <style lang='stylus'>
.tags-wrapper .tags-wrapper
.title .title
color var(--textColor) color var(--textColor)
opacity 0.9 opacity 0.9
font-size 1.2rem font-size 1.2rem
.tags .tags
text-align justify text-align justify
padding .8rem .5rem .5rem .5rem padding 0.8rem 0.5rem 0.5rem 0.5rem
margin 0 -0.5rem -0.5rem -0.5rem margin 0 -0.5rem -0.5rem -0.5rem
a a
opacity .8 opacity 0.8
display inline-block display inline-block
padding .2rem .4rem padding 0.2rem 0.4rem
transition all .4s transition all 0.4s
background-color var(--textColor) background-color var(--textColor)
color var(--mainBg) color var(--mainBg)
border-radius 3px border-radius 3px
margin 0 .3rem .5rem 0 margin 0 0.3rem 0.5rem 0
min-width 2rem min-width 2rem
height 1rem height 1rem
line-height 1rem line-height 1rem
font-size .8rem font-size 0.8rem
text-align center text-align center
@media (max-width: $MQMobile) @media (max-width $MQMobile)
font-weight 400 font-weight 400
&:hover &:hover
opacity 1 opacity 1
transform scale(1.1) transform scale(1.1)
&.active &.active
box-shadow: 0 5px 10px -5px var(--randomColor, rgba(0,0,0,0.15)); box-shadow 0 5px 10px -5px var(--randomColor, rgba(0, 0, 0, 0.15))
transform scale(1.22) transform scale(1.22)
opacity 1 opacity 1
&:hover &:hover

View File

@ -38,7 +38,7 @@ import Pagination from '@theme/components/Pagination'
import TagsBar from '@theme/components/TagsBar' import TagsBar from '@theme/components/TagsBar'
export default { export default {
data(){ data () {
return { return {
tag: '', tag: '',
total: 0, // total: 0, //
@ -47,9 +47,9 @@ export default {
} }
}, },
components: { MainLayout, PostList, Pagination, TagsBar }, components: { MainLayout, PostList, Pagination, TagsBar },
mounted() { mounted () {
const queryTag = this.$route.query.tag const queryTag = this.$route.query.tag
if (queryTag) { if (queryTag) {
this.tag = queryTag this.tag = queryTag
this.total = this.$groupPosts.tags[queryTag].length this.total = this.$groupPosts.tags[queryTag].length
@ -61,13 +61,13 @@ export default {
} }
}, },
methods: { methods: {
handlePagination(i) { // handlePagination (i) { //
this.currentPage = i this.currentPage = i
} }
}, },
watch: { watch: {
'$route.query.tag'() { '$route.query.tag' () {
this.tag = this.$route.query.tag this.tag = decodeURIComponent(this.$route.query.tag)
if (this.tag) { if (this.tag) {
this.total = this.$groupPosts.tags[this.tag].length this.total = this.$groupPosts.tags[this.tag].length
} else { } else {
@ -82,42 +82,40 @@ export default {
<style lang='stylus'> <style lang='stylus'>
.tags-page .tags-page
.tags-wrapper .tags-wrapper
position sticky position sticky
top ($navbarHeight + .9rem) top ($navbarHeight + 0.9rem)
max-height calc(100vh - 10rem) max-height calc(100vh - 10rem)
min-height 4.2rem min-height 4.2rem
@media (max-width: $MQMobile) @media (max-width $MQMobile)
display none display none
.tags .tags
max-height calc(100vh - 14rem) max-height calc(100vh - 14rem)
min-height 2.2rem min-height 2.2rem
overflow-x hidden overflow-x hidden
overflow-y auto overflow-y auto
transition all .2s transition all 0.2s
&::-webkit-scrollbar-track-piece &::-webkit-scrollbar-track-piece
background-color:rgba(0,0,0,.05) background-color rgba(0, 0, 0, 0.05)
&::-webkit-scrollbar-thumb:vertical &::-webkit-scrollbar-thumb:vertical
background-color:rgba(0,0,0,.15) background-color rgba(0, 0, 0, 0.15)
&:hover &:hover
&::-webkit-scrollbar-track-piece &::-webkit-scrollbar-track-piece
background-color:rgba(0,0,0,.1) background-color rgba(0, 0, 0, 0.1)
&::-webkit-scrollbar-thumb:vertical &::-webkit-scrollbar-thumb:vertical
background-color:rgba(0,0,0,.25) background-color rgba(0, 0, 0, 0.25)
.tags-page .tags-page
.main-left .main-left
.tags-wrapper .tags-wrapper
position relative position relative
top 0 top 0
padding .9rem 1.5rem padding 0.9rem 1.5rem
margin-bottom .9rem margin-bottom 0.9rem
max-height 15rem max-height 15rem
border-radius 0 border-radius 0
display none display none
@media (max-width: $MQMobile) @media (max-width $MQMobile)
display block display block
.tags .tags
max-height 11.5rem max-height 11.5rem
</style> </style>

View File

@ -1,226 +0,0 @@
<template>
<div class="timeline-wrapper theme-vdoing-content">
<div class="tags">
<a href="#全部" :class="{active: currentTag === '全部'}" :style="randomBgcolor()" @click="toggleTag('全部')">全部</a>
<a
:class="{active: currentTag === key}"
v-for="(item, key) of getPages.tagGroup"
:style="randomBgcolor()"
@click="toggleTag(key)"
:key="key"
:href="'#'+key"
>
{{key}}
</a>
</div>
<div class="timeline">
<transition-group tag="ul">
<li class="desc" key="0">{{pageData.slogan}}</li>
<template v-for="yearItem in tagPages()">
<li :key="yearItem.year">
<h3 class="year">{{yearItem.year}}</h3>
<div class="year-wrapper">
<transition-group tag="span">
<router-link :to="item.path" v-for="item in yearItem.pageList" :key="item.path.slice(-6)">
<span class="date">{{item.formatDay}}</span>
<span class="title">{{item.title}}</span>
</router-link>
</transition-group>
</div>
</li>
</template>
</transition-group>
</div>
</div>
</template>
<script>
import { getPagesList } from '../util/getArticleDate'
export default {
data() {
return {
pageData: {
tagBgColor: ['#11a8cd', '#F8B26A', '#67CC86', '#E15B64', '#F47E60', '#849B87'],
slogan: '只争朝夕,不负韶华!( •̀ ω •́ )✧'
},
currentTag: "",
posts: [],
}
},
created() {
},
mounted() {
const fmData = this.$frontmatter.pageComponent.data
if(fmData && fmData.slogan) {
this.pageData.slogan = fmData.slogan
}
this.posts = this.$site.pages
document.body.style="overflow-y: scroll;" // tag
this.handleHashTag()
window.onhashchange = () => {
this.handleHashTag()
}
},
computed: {
getPages() {
return getPagesList(this.posts)
}
},
watch: {
currentTag(tag) {
document.body.setAttribute('id', tag); // vue-router
}
},
methods: {
handleHashTag() {
const hashTag = decodeURIComponent(window.location.hash.slice(1))
this.currentTag = hashTag ? hashTag : '全部'
},
//
tagPages() {
if (this.currentTag === "全部") {
return this.getPages.allPage
} else {
return this.getPages.tagGroup[this.currentTag]
}
},
//
toggleTag(tag) {
this.currentTag = tag
},
//
randomBgcolor() {
const tagBgColor = this.pageData.tagBgColor
return { background: `${tagBgColor[Math.floor(Math.random() * tagBgColor.length)]}`}
},
}
}
</script>
<style scoped lang="stylus" rel="stylesheet/stylus">
.timeline-wrapper
padding-top 1rem
.tags
margin-bottom 30px
a
vertical-align: middle;
margin: 4px 4px 10px;
padding: 5px 8px;
display: inline-block;
cursor: pointer;
border-radius: .25rem;
background: #E15B64;
color: #fff;
line-height: 13px;
font-size: 13px;
transition: all .5s;
opacity: 0.9;
box-shadow: 0px 0px 8px rgba(80,80,80,.3);
&.active
transform: scale(1.2);
opacity: 1;
&:hover
text-decoration: none!important;
&:not(.active):hover
transform: scale(1.05);
.v-enter{
opacity: 0;
transform: translateY(-30px);
}
.v-leave-active{
display:none;
}
.v-leave{
opacity: 0;
}
ul
list-style: none;
.timeline ul
box-sizing: border-box;
margin: 4rem auto;
position: relative;
&:after
content: " ";
position: absolute;
top: 14px;
left: 0;
// z-index: -1;
margin-left: -2px;
width: 4px;
height: 100%;
background: var(--borderColor);
>li
transition: all .25s ease-in-out;
margin-bottom: 55px;
.year
margin: 0;
font-weight: 700;
font-size: 26px;
.desc,.year
position: relative;
.desc:before,.year:before
content: " ";
position: absolute;
z-index: 2;
left: -20px;
top: 50%;
margin-left: -4px;
margin-top: -4px;
width: 8px;
height: 8px;
background: #fff;
border: 1px solid var(--borderColor);
border-radius: 50%;
.year-wrapper
padding-left: 0!important;
a
display: flex;
padding: 30px 0 10px;
list-style: none;
border-bottom: 1px dashed var(--borderColor);
position: relative;
color: var(--textColor)
transition: all 0.25s ease-in-out;
.title
opacity .9
.date
min-width: 40px;
line-height: 30px;
font-size: 13px;
margin-right: 5px;
color: #999;
&:before
content: " ";
position: absolute;
left: -19px;
top: 41px;
width: 6px;
height: 6px;
margin-left: -4px;
background: #fff;
border-radius: 50%;
border: 1px solid var(--borderColor);
z-index: 2;
&:hover
text-decoration:none
color: $accentColor
.date
color: $accentColor
.date:before
background: $accentColor
</style>

View File

@ -1,25 +1,35 @@
<template> <template>
<div :class="['article-list',{'no-article-list': isShowArticle}]"> <div :class="['article-list',{'no-article-list': isShowArticle}]">
<div class="article-title"> <div class="article-title">
<router-link :to="moreArticle || '/archives/'" class="iconfont icon-bi">最近更新</router-link> <router-link
:to="moreArticle || '/archives/'"
class="iconfont icon-bi"
>最近更新</router-link>
</div> </div>
<div class="article-wrapper"> <div class="article-wrapper">
<dl v-for="(item, index) in topPublishPosts" :key="index"> <dl
v-for="(item, index) in topPublishPosts"
:key="index"
>
<dd>{{getNum(index)}}</dd> <dd>{{getNum(index)}}</dd>
<dt> <dt>
<router-link :to="item.path"><div>{{item.title}}</div></router-link> <router-link :to="item.path">
<div>{{item.title}}</div>
</router-link>
<span>{{getDate(item)}}</span> <span>{{getDate(item)}}</span>
</dt> </dt>
</dl> </dl>
<dl> <dl>
<dd></dd> <dd></dd>
<dt> <dt>
<router-link :to="moreArticle || '/archives/'" class="more">更多文章></router-link> <router-link
:to="moreArticle || '/archives/'"
class="more"
>更多文章></router-link>
</dt> </dt>
</dl> </dl>
</div> </div>
</div> </div>
</template> </template>
@ -34,19 +44,19 @@ export default {
}, },
moreArticle: String moreArticle: String
}, },
data() { data () {
return { return {
posts: [], posts: [],
currentPath: '' currentPath: ''
} }
}, },
created() { created () {
this.posts = this.$site.pages this.posts = this.$site.pages
this.currentPath = this.$page.path this.currentPath = this.$page.path
}, },
computed: { computed: {
topPublishPosts() { topPublishPosts () {
return this.$sortPostsByDate ? this.$sortPostsByDate.filter( post => { return this.$sortPostsByDate ? this.$sortPostsByDate.filter(post => {
const { path } = post const { path } = post
return path !== this.currentPath return path !== this.currentPath
}).slice(0, this.length) : [] }).slice(0, this.length) : []
@ -58,15 +68,15 @@ export default {
} }
}, },
methods: { methods: {
getNum(index) { getNum (index) {
return index < 9 ? '0' + (index + 1) : index + 1 return index < 9 ? '0' + (index + 1) : index + 1
}, },
getDate(item) { getDate (item) {
return item.frontmatter.date ? item.frontmatter.date.split(" ")[0].slice(5,10) : '' return item.frontmatter.date ? item.frontmatter.date.split(" ")[0].slice(5, 10) : ''
} }
}, },
watch: { watch: {
$route() { $route () {
this.currentPath = this.$page.path this.currentPath = this.$page.path
} }
} }
@ -74,68 +84,68 @@ export default {
</script> </script>
<style lang='stylus'> <style lang='stylus'>
// @require '../styles/wrapper.styl' // @require '../styles/wrapper.styl'
.article-list .article-list
// @extend $wrapper // @extend $wrapper
padding 1rem 2rem padding 1rem 2rem
@media (max-width: $MQNarrow) @media (max-width $MQNarrow)
padding 1rem 1.5rem padding 1rem 1.5rem
&.no-article-list &.no-article-list
display none display none
.article-title .article-title
border-bottom 1px solid var(--borderColor) border-bottom 1px solid var(--borderColor)
font-size 1.3rem font-size 1.3rem
padding 1rem padding 1rem
a a
font-size 1.2rem font-size 1.2rem
color var(--textColor) color var(--textColor)
opacity 0.9 opacity 0.9
&:before &:before
margin-right .4rem margin-right 0.4rem
font-size 1.1rem font-size 1.1rem
.article-wrapper .article-wrapper
overflow hidden overflow hidden
dl dl
border-bottom 1px dotted var(--borderColor) border-bottom 1px dotted var(--borderColor)
float left float left
display flex display flex
padding 8px 0 padding 8px 0
margin 0
height 50px
width 100%
dd
font-size 1.1rem
color #F17229
width 50px
text-align center
margin 0 margin 0
height 50px line-height 50px
width 100% dt
dd flex 1
font-size 1.1rem display flex
color #F17229 a
width 50px color var(--textColor)
text-align center
margin 0
line-height 50px
dt
flex 1 flex 1
display flex display flex
a height 50px
color var(--textColor) align-items center
flex 1 font-weight normal
display flex div
height 50px overflow hidden
align-items center white-space normal
font-weight normal text-overflow ellipsis
div display -webkit-box
overflow hidden -webkit-line-clamp 2
white-space normal -webkit-box-orient vertical
text-overflow ellipsis &:hover
display -webkit-box text-decoration underline
-webkit-line-clamp 2 &.more
-webkit-box-orient vertical color $accentColor
&:hover span
text-decoration underline width 50px
&.more margin-right 15px
color $accentColor color #999
span text-align right
width 50px font-size 0.9rem
margin-right 15px line-height 50px
color #999
text-align right
font-size .9rem
line-height 50px
</style> </style>

View File

@ -9,7 +9,7 @@ export default ({
// 修复ISO8601时间格式为普通时间格式以及添加作者信息 // 修复ISO8601时间格式为普通时间格式以及添加作者信息
siteData.pages.map(item => { siteData.pages.map(item => {
const { frontmatter: { date, author } } = item const { frontmatter: { date, author } } = item
if (typeof date === 'string' && date.charAt(date.length-1) === 'Z') { if (typeof date === 'string' && date.charAt(date.length - 1) === 'Z') {
item.frontmatter.date = repairUTCDate(date) item.frontmatter.date = repairUTCDate(date)
} }
if (author) { if (author) {
@ -26,14 +26,14 @@ export default ({
} }
// 修复ISO8601时间格式为普通时间格式 // 修复ISO8601时间格式为普通时间格式
function repairUTCDate(date) { function repairUTCDate (date) {
if (!(date instanceof Date)) { if (!(date instanceof Date)) {
date = new Date(date) date = new Date(date)
} }
return `${date.getUTCFullYear()}-${zero(date.getUTCMonth()+1)}-${zero(date.getUTCDate())} ${zero(date.getUTCHours())}:${zero(date.getUTCMinutes())}:${zero(date.getUTCSeconds())}`; return `${date.getUTCFullYear()}-${zero(date.getUTCMonth() + 1)}-${zero(date.getUTCDate())} ${zero(date.getUTCHours())}:${zero(date.getUTCMinutes())}:${zero(date.getUTCSeconds())}`;
} }
// 小于10补0 // 小于10补0
function zero(d){ function zero (d) {
return d.toString().padStart(2,'0') return d.toString().padStart(2, '0')
} }

View File

@ -36,7 +36,7 @@ export default {
&.tip, &.green &.tip, &.green
background-color #42b983 background-color #42b983
&.error &.error
background-color #DA5961 //#f66 background-color #DA5961 // #f66
&.warning, &.warn, &.yellow &.warning, &.warn, &.yellow
background-color darken(#ffe564, 35%) background-color darken(#ffe564, 35%)
& + & & + &

View File

@ -1,28 +1,28 @@
const path = require('path') const path = require('path')
const setFrontmatter = require('./node_utils/setFrontmatter') const setFrontmatter = require('./node_utils/setFrontmatter')
const getSidebarData = require('./node_utils/getSidebarData') const getSidebarData = require('./node_utils/getSidebarData')
const {createPage, deletePage} = require('./node_utils/handlePage') const { createPage, deletePage } = require('./node_utils/handlePage')
const chalk = require('chalk') // 命令行打印美化 const chalk = require('chalk') // 命令行打印美化
const yaml = require('js-yaml') // yaml转js const yaml = require('js-yaml') // yaml转js
const log = console.log const log = console.log
// md容器名 // md容器名
const CARD_LIST = 'cardList' const CARD_LIST = 'cardList'
const CARD_IMG_LIST = 'cardImgList' const CARD_IMG_LIST = 'cardImgList'
// Theme API. // Theme API.
module.exports = (options, ctx) => { module.exports = (options, ctx) => {
const { sourceDir, themeConfig, siteConfig } = ctx const { sourceDir, themeConfig, siteConfig } = ctx
// 自动设置front matter // 自动设置front matter
setFrontmatter(sourceDir, themeConfig) setFrontmatter(sourceDir, themeConfig)
// 自动生成结构化侧边栏 // 自动生成结构化侧边栏
const sidebar = themeConfig.sidebar const sidebar = themeConfig.sidebar
if(sidebar === 'structuring' || sidebar && sidebar.mode === 'structuring') { if (sidebar === 'structuring' || sidebar && sidebar.mode === 'structuring') {
const collapsable = themeConfig.sidebar.collapsable === false ? false : true const collapsable = themeConfig.sidebar.collapsable === false ? false : true
const sidebarData = getSidebarData(sourceDir, collapsable) const sidebarData = getSidebarData(sourceDir, collapsable)
if(sidebarData) { if (sidebarData) {
themeConfig.sidebar = sidebarData themeConfig.sidebar = sidebarData
log(chalk.blue('tip ') + chalk.green('add sidebar data. 侧边栏数据成功生成。')) log(chalk.blue('tip ') + chalk.green('add sidebar data. 侧边栏数据成功生成。'))
} else { } else {
@ -44,7 +44,7 @@ module.exports = (options, ctx) => {
} else { } else {
deletePage(sourceDir, 'tagsPage') deletePage(sourceDir, 'tagsPage')
} }
// 归档页 // 归档页
if (themeConfig.archive !== false) { if (themeConfig.archive !== false) {
createPage(sourceDir, 'archivesPage') createPage(sourceDir, 'archivesPage')
@ -56,8 +56,8 @@ module.exports = (options, ctx) => {
const isAlgoliaSearch = ( const isAlgoliaSearch = (
themeConfig.algolia themeConfig.algolia
|| Object || Object
.keys(siteConfig.locales && themeConfig.locales || {}) .keys(siteConfig.locales && themeConfig.locales || {})
.some(base => themeConfig.locales[base].algolia) .some(base => themeConfig.locales[base].algolia)
) )
const enableSmoothScroll = themeConfig.smoothScroll === true const enableSmoothScroll = themeConfig.smoothScroll === true
@ -77,6 +77,13 @@ module.exports = (options, ctx) => {
'@vuepress/plugin-nprogress', '@vuepress/plugin-nprogress',
['smooth-scroll', enableSmoothScroll], ['smooth-scroll', enableSmoothScroll],
['container', {
type: 'note',
defaultTitle: {
'/': '笔记',
'/en/': 'NOTE'
}
}],
['container', { ['container', {
type: 'tip', type: 'tip',
defaultTitle: { defaultTitle: {
@ -129,7 +136,7 @@ module.exports = (options, ctx) => {
'container', 'container',
{ {
type: CARD_LIST, type: CARD_LIST,
render: (tokens, idx) => { render: (tokens, idx) => {
// tokens 是整个md文件的虚拟dom结构数组 // tokens 是整个md文件的虚拟dom结构数组
// idx 是tokens中':::' 所在的索引而且是当前指定type的':::'分别有开始和结束两次的idx // idx 是tokens中':::' 所在的索引而且是当前指定type的':::'分别有开始和结束两次的idx
// if (tokens[idx].nesting === 1) { // 开头的 ':::' 标记 // if (tokens[idx].nesting === 1) { // 开头的 ':::' 标记
@ -146,33 +153,33 @@ module.exports = (options, ctx) => {
'container', 'container',
{ {
type: CARD_IMG_LIST, type: CARD_IMG_LIST,
render: (tokens, idx) => { render: (tokens, idx) => {
return renderCardList(tokens, idx, CARD_IMG_LIST) return renderCardList(tokens, idx, CARD_IMG_LIST)
} }
}, },
], ],
] ]
} }
} }
// 渲染md容器的卡片列表 // 渲染md容器的卡片列表
function renderCardList(tokens, idx, type) { function renderCardList (tokens, idx, type) {
const END_TYPE = `container_${type}_close`, const END_TYPE = `container_${type}_close`,
_tokens$idx = tokens[idx], _tokens$idx = tokens[idx],
nesting = _tokens$idx.nesting, nesting = _tokens$idx.nesting,
info = _tokens$idx.info; info = _tokens$idx.info;
if (nesting === 1) { // 渲染开头的 ':::' 标记 if (nesting === 1) { // 渲染开头的 ':::' 标记
let yamlStr = ''; let yamlStr = '';
for (let i = idx; i < tokens.length; i++) { for (let i = idx; i < tokens.length; i++) {
let _tokens$i = tokens[i], let _tokens$i = tokens[i],
type = _tokens$i.type, type = _tokens$i.type,
content = _tokens$i.content, content = _tokens$i.content,
_info = _tokens$i.info; _info = _tokens$i.info;
if (type === END_TYPE) break; // 遇到结束的 ':::' 时 if (type === END_TYPE) break; // 遇到结束的 ':::' 时
if (!content) continue; if (!content) continue;
if (type === 'fence' && _info === 'yaml') { // 是代码块类型并且是yaml代码 if (type === 'fence' && _info === 'yaml') { // 是代码块类型并且是yaml代码
@ -188,7 +195,7 @@ function renderCardList(tokens, idx, type) {
dataList = Array.isArray(dataObj) ? dataObj : dataObj.list dataList = Array.isArray(dataObj) ? dataObj : dataObj.list
} }
if (dataList && dataList.length) { // 有列表数据 if (dataList && dataList.length) { // 有列表数据
// 每行显示几个 // 每行显示几个
let row = Number(info.split(' ').pop()) let row = Number(info.split(' ').pop())
@ -198,12 +205,12 @@ function renderCardList(tokens, idx, type) {
let listDOM = '' let listDOM = ''
if (type === CARD_LIST) { // 普通卡片列表 if (type === CARD_LIST) { // 普通卡片列表
listDOM = getCardListDOM(dataList, row) listDOM = getCardListDOM(dataList, row)
} else if (type === CARD_IMG_LIST) { // 卡片图片列表 } else if (type === CARD_IMG_LIST) { // 卡片图片列表
listDOM = getCardImgListDOM(dataList, row) listDOM = getCardImgListDOM(dataList, row)
} }
return `<div class="${type}Container"><div class="card-list">${ listDOM }</div>` return `<div class="${type}Container"><div class="card-list">${listDOM}</div>`
} }
} }
} else { // 渲染':::' 结尾 } else { // 渲染':::' 结尾
@ -213,14 +220,14 @@ function renderCardList(tokens, idx, type) {
// 将数据解析成DOM结构 - 普通卡片列表 // 将数据解析成DOM结构 - 普通卡片列表
function getCardListDOM(dataList, row) { function getCardListDOM (dataList, row) {
let listDOM = '' let listDOM = ''
dataList.forEach(item => { dataList.forEach(item => {
listDOM += ` listDOM += `
<${item.link ? 'a href="' + item.link +'" target="_blank"' : 'span' } class="card-item ${ row ? 'row-' + row : '' }" <${item.link ? 'a href="' + item.link + '" target="_blank"' : 'span'} class="card-item ${row ? 'row-' + row : ''}"
style="${ item.bgColor ? 'background-color:' + item.bgColor + ';--randomColor:'+ item.bgColor +';': '--randomColor: var(--bodyBg);' }${ item.textColor ? 'color:' + item.textColor + ';': '' }" style="${item.bgColor ? 'background-color:' + item.bgColor + ';--randomColor:' + item.bgColor + ';' : '--randomColor: var(--bodyBg);'}${item.textColor ? 'color:' + item.textColor + ';' : ''}"
> >
${ item.avatar ? '<img src="'+ item.avatar +'" class="no-zoom">' : '' } ${item.avatar ? '<img src="' + item.avatar + '" class="no-zoom">' : ''}
<div> <div>
<p class="name">${item.name}</p> <p class="name">${item.name}</p>
<p class="desc">${item.desc}</p> <p class="desc">${item.desc}</p>
@ -233,34 +240,27 @@ function getCardListDOM(dataList, row) {
// 将数据解析成DOM结构 - 图文卡片列表 // 将数据解析成DOM结构 - 图文卡片列表
function getCardImgListDOM(dataList, row) { function getCardImgListDOM (dataList, row) {
let listDOM = '' let listDOM = ''
dataList.forEach(item => { dataList.forEach(item => {
listDOM += ` listDOM += `
<div class="card-item ${ row ? 'row-' + row : '' }" > <div class="card-item ${row ? 'row-' + row : ''}" >
<div class="box-img"> <a href="${item.link}" target="_blank">
<a href="${item.link}" target="_blank"> <div class="box-img">
<img src="${item.img}" class="no-zoom"> <img src="${item.img}" class="no-zoom">
</a> </div>
</div> <div class="box-info">
<div class="box-info"> <p class="name">${item.name}</p>
<a href="${item.link}" target="_blank"> ${item.desc ? `<p class="desc">${item.desc}</p>` : ''}
<p class="name">${item.name}</p> </div>
${item.desc ? `<p class="desc">${item.desc}</p>` : ''}
</a> ${item.avatar || item.author ? `<div class="box-footer">
</div> ${item.avatar ? `<img src="${item.avatar}" class="no-zoom">` : ''}
${item.author ? `<span>${item.author}</span>` : ''}
${item.avatar || item.author </div>`: ''}
? `<div class="box-footer"> </a>
<a href="${item.link}" target="_blank">
${item.avatar ? `<img src="${item.avatar}" class="no-zoom">` : ''}
${item.author ? `<span>${item.author}</span>` : ''}
</a>
</div>`
: ''
}
</div> </div>
` `
}) })
return listDOM return listDOM
} }

View File

@ -29,18 +29,18 @@
#bottom #bottom
/> />
</Sidebar> </Sidebar>
<!-- 首页 --> <!-- 首页 -->
<Home v-if="$page.frontmatter.home"/> <Home v-if="$page.frontmatter.home" />
<!-- 分类页 --> <!-- 分类页 -->
<CategoriesPage v-else-if="$page.frontmatter.categoriesPage"/> <CategoriesPage v-else-if="$page.frontmatter.categoriesPage" />
<!-- 标签页 --> <!-- 标签页 -->
<TagsPage v-else-if="$page.frontmatter.tagsPage"/> <TagsPage v-else-if="$page.frontmatter.tagsPage" />
<!-- 归档页 --> <!-- 归档页 -->
<ArchivesPage v-else-if="$page.frontmatter.archivesPage"/> <ArchivesPage v-else-if="$page.frontmatter.archivesPage" />
<!-- 文章页或其他页 --> <!-- 文章页或其他页 -->
<Page <Page
@ -59,7 +59,7 @@
<Footer /> <Footer />
<Buttons <Buttons
ref="buttons" ref="buttons"
@toggle-theme-mode="toggleThemeMode" @toggle-theme-mode="toggleThemeMode"
/> />
@ -97,10 +97,10 @@ export default {
themeMode: 'light' themeMode: 'light'
} }
}, },
beforeMount(){ beforeMount () {
// //
const social = this.$themeConfig.social const social = this.$themeConfig.social
if(social && social.iconfontCssFile ) { if (social && social.iconfontCssFile) {
let linkElm = document.createElement("link") let linkElm = document.createElement("link")
linkElm.setAttribute('rel', 'stylesheet'); linkElm.setAttribute('rel', 'stylesheet');
linkElm.setAttribute("type", "text/css") linkElm.setAttribute("type", "text/css")
@ -109,7 +109,7 @@ export default {
} }
}, },
computed: { computed: {
showRightMenu() { showRightMenu () {
const { headers } = this.$page const { headers } = this.$page
return ( return (
!this.$frontmatter.home !this.$frontmatter.home
@ -169,16 +169,16 @@ export default {
] ]
} }
}, },
created() { created () {
const sidebarOpen = this.$themeConfig.sidebarOpen const sidebarOpen = this.$themeConfig.sidebarOpen
if (sidebarOpen === false) { if (sidebarOpen === false) {
this.isSidebarOpen = sidebarOpen this.isSidebarOpen = sidebarOpen
} }
}, },
beforeMount() { beforeMount () {
this.isSidebarOpenOfclientWidth() this.isSidebarOpenOfclientWidth()
const mode = storage.get('mode') // createdvuepresscreated访apiwindow const mode = storage.get('mode') // createdvuepresscreated访apiwindow
if(!mode || mode === 'auto') { // '' if (!mode || mode === 'auto') { // ''
this._autoMode() this._autoMode()
} else { } else {
this.themeMode = mode this.themeMode = mode
@ -196,7 +196,7 @@ export default {
} }
// //
this.showSidebar = true this.showSidebar = true
this.$router.afterEach(() => { this.$router.afterEach(() => {
this.isSidebarOpenOfclientWidth() this.isSidebarOpenOfclientWidth()
}) })
@ -204,30 +204,30 @@ export default {
// //
let p = 0, t = 0; let p = 0, t = 0;
window.addEventListener('scroll', _.throttle(() => { window.addEventListener('scroll', _.throttle(() => {
if(!this.isSidebarOpen) { // if (!this.isSidebarOpen) { //
p = this.getScrollTop() p = this.getScrollTop()
if(t < p && p > NAVBAR_HEIGHT) { // if (t < p && p > NAVBAR_HEIGHT) { //
this.hideNavbar = true this.hideNavbar = true
} else { // } else { //
this.hideNavbar = false this.hideNavbar = false
} }
setTimeout(() => {t = p},0) setTimeout(() => { t = p }, 0)
} }
}, 300)) }, 300))
}, },
watch: { watch: {
isSidebarOpen() { isSidebarOpen () {
if(this.isSidebarOpen) { // if (this.isSidebarOpen) { //
this.hideNavbar = false this.hideNavbar = false
} }
}, },
themeMode() { themeMode () {
this.setBodyClass() this.setBodyClass()
} }
}, },
methods: { methods: {
setBodyClass() { setBodyClass () {
document.body.className = 'theme-mode-' + this.themeMode document.body.className = 'theme-mode-' + this.themeMode
}, },
getScrollTop () { getScrollTop () {
@ -235,7 +235,7 @@ export default {
|| document.documentElement.scrollTop || document.documentElement.scrollTop
|| document.body.scrollTop || 0 || document.body.scrollTop || 0
}, },
isSidebarOpenOfclientWidth() { isSidebarOpenOfclientWidth () {
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) { if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
this.isSidebarOpen = false this.isSidebarOpen = false
} }
@ -245,21 +245,21 @@ export default {
this.$emit('toggle-sidebar', this.isSidebarOpen) this.$emit('toggle-sidebar', this.isSidebarOpen)
}, },
_autoMode () { _autoMode () {
if(window.matchMedia('(prefers-color-scheme: dark)').matches){ // if (window.matchMedia('(prefers-color-scheme: dark)').matches) { //
this.themeMode = 'dark' this.themeMode = 'dark'
} else { } else {
this.themeMode = 'light' this.themeMode = 'light'
} }
}, },
toggleThemeMode (key) { toggleThemeMode (key) {
if(key === 'auto') { if (key === 'auto') {
this._autoMode() this._autoMode()
} else { } else {
this.themeMode = key this.themeMode = key
} }
storage.set('mode', key) storage.set('mode', key)
}, },
// side swipe // side swipe
onTouchStart (e) { onTouchStart (e) {
this.touchStart = { this.touchStart = {

View File

@ -1,9 +0,0 @@
export default {
methods: {
encodeUrl(str) {
str = str + ''
str = str.replace(/ |((?=[\x21-\x7e]+)[^A-Za-z0-9])/g, '-')
return str
},
}
}

View File

@ -2,20 +2,20 @@ import { filterPosts, sortPosts, sortPostsByDate, groupPosts, categoriesAndTags
export default { export default {
computed: { computed: {
$filterPosts() { // 过滤非文章页和首页的文章数据 $filterPosts () { // 过滤非文章页和首页的文章数据
return filterPosts(this.$site.pages) return filterPosts(this.$site.pages)
}, },
$sortPosts() { // 按置顶和时间排序的文章数据 $sortPosts () { // 按置顶和时间排序的文章数据
return sortPosts(this.$filterPosts) return sortPosts(this.$filterPosts)
}, },
$sortPostsByDate() { // 仅按时间排序的文章数据 $sortPostsByDate () { // 仅按时间排序的文章数据
return sortPostsByDate(this.$filterPosts) return sortPostsByDate(this.$filterPosts)
}, },
$groupPosts() { // 按分类和标签分组的文章数据 $groupPosts () { // 按分类和标签分组的文章数据
return groupPosts(this.$sortPosts) return groupPosts(this.$sortPosts)
}, },
$categoriesAndTags() { // 所有分类和标签数据 $categoriesAndTags () { // 所有分类和标签数据
return categoriesAndTags(this.$groupPosts) return categoriesAndTags(this.$groupPosts)
} }
} }
} }

View File

@ -1,5 +1,5 @@
export default { export default {
data() { data () {
return { return {
badges: [ badges: [
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAABGpJREFUSA3tVVtoXFUU3fvOI53UlmCaKIFmwEhsE7QK0ipFEdHEKpXaZGrp15SINsXUWvBDpBgQRKi0+KKoFeJHfZA+ED9KKoIU2gYD9UejTW4rVIzm0VSTziPzuNu1z507dibTTjL4U/DAzLn3nL3X2o91ziX6f9wMFdh6Jvbm9nNSV0msViVO6tN1Rm7NMu2OpeJ9lWBUTDxrJbYTS0hInuwciu9eLHlFxCLCZEk3MegsJmZ5K/JD6t7FkFdEvGUo1g7qJoG3MHImqRIn8/nzY1K9UPKKiJmtnUqHVE3Gbuay6vJE/N2FEmuxFjW2nUuE0yQXRRxLiTUAzs36zhZvOXJPdX850EVnnLZkB8prodQoM5JGj7Xk2mvC7JB8tG04Ef5PiXtG0UtxupRQSfTnBoCy554x18yJHI6I+G5Eru4LHmPJZEQsrvPUbMiA8G/WgMK7w7I+ez7++o2ANfbrjvaOl1tFMs+htG3IrZH9/hDX1Pr8Tc0UvH8tcX29KzAgIGcEkINyW5BF9x891hw6VYqgJHEk0huccS7vh3C6gTiODL+26huuBtbct8eZnqLML8PkxGYpuPZBqtqwkSjgc4mB5gbgig5i+y0UDK35LMxXisn9xQtK+nd26gTIHsHe/oblK/b29fUmN/8Y+9jAQrnBp56m1LcDlDp9irKTExSKduXJVWSqdBMA08pEJnEIOB3FPPMybu/oeV8zFeYN3xx576Q6RH+VmplE4ncQV5v+5rzSoyOU7PuEAg8g803PwBJ0CExno/jcMbN8tONYeOmHiuUNryvm3fRUy4tMPVLdAGkUhNWuggGrJcXPv+ouCjz0MKUHz1J2/E8IC9nqTabcxgaBYM0hPhD5Y65FsbxRQKxCQrDjDctW7PUM3HuZunFyifSAqEfuzCp48Il24luWUWZoyJCaPR82jE0+kFA643wRFVni4RYSq3ohJO2pZ7B5dO4xkDWbEpossJPLSrPjYID8rS2UHTlvyNxqIGsg674XJJ7vnh5L7PNwC4hh2sjCI96mzszOTpxLF0T7l88Yz7lAuK6OnL8gXLOnTvpzSb22YG8W7us3jSebFHeeqnXRG1vt+MoUM84LQIBmMsCTAcOauTh0T0l0neQK7m2bLMt2mGxU3HYssS0J2cdv5wljlPsrIuZLAG/2DOZIXgCYT8uMGZN+e2kSirfxZOPCsC0f24nTZzspnVn9VePS1Z5vubmAGGXG8ZFno9Hel0yfA5ZPhF7Dh972BQJ2qCpgH67lmWtBYbvk6sz02wjky2vXyz0XErP/kFB619js1BtwfOV4OPRqOQBjy3Qbk18vigUPPSD5ceHnwck7W9bhAqZdd7SuG7w4/P2F/GaJh8c7e9qgow+Q7cGBo+98WsLkuktFqiZabtXuQTu/Y5ETbR0v7tNSFnvrmu6pjdoan2KjMu8q/Hmj1EfCO2ZGfEIbIXKUlw8qaX9/b2oeSJmFksSeT/Fn0V3nSypChh4Gjh74ybO9aeZ/AN2dwciu2/MhAAAAAElFTkSuQmCC', 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAAXNSR0IArs4c6QAABGpJREFUSA3tVVtoXFUU3fvOI53UlmCaKIFmwEhsE7QK0ipFEdHEKpXaZGrp15SINsXUWvBDpBgQRKi0+KKoFeJHfZA+ED9KKoIU2gYD9UejTW4rVIzm0VSTziPzuNu1z507dibTTjL4U/DAzLn3nL3X2o91ziX6f9wMFdh6Jvbm9nNSV0msViVO6tN1Rm7NMu2OpeJ9lWBUTDxrJbYTS0hInuwciu9eLHlFxCLCZEk3MegsJmZ5K/JD6t7FkFdEvGUo1g7qJoG3MHImqRIn8/nzY1K9UPKKiJmtnUqHVE3Gbuay6vJE/N2FEmuxFjW2nUuE0yQXRRxLiTUAzs36zhZvOXJPdX850EVnnLZkB8prodQoM5JGj7Xk2mvC7JB8tG04Ef5PiXtG0UtxupRQSfTnBoCy554x18yJHI6I+G5Eru4LHmPJZEQsrvPUbMiA8G/WgMK7w7I+ez7++o2ANfbrjvaOl1tFMs+htG3IrZH9/hDX1Pr8Tc0UvH8tcX29KzAgIGcEkINyW5BF9x891hw6VYqgJHEk0huccS7vh3C6gTiODL+26huuBtbct8eZnqLML8PkxGYpuPZBqtqwkSjgc4mB5gbgig5i+y0UDK35LMxXisn9xQtK+nd26gTIHsHe/oblK/b29fUmN/8Y+9jAQrnBp56m1LcDlDp9irKTExSKduXJVWSqdBMA08pEJnEIOB3FPPMybu/oeV8zFeYN3xx576Q6RH+VmplE4ncQV5v+5rzSoyOU7PuEAg8g803PwBJ0CExno/jcMbN8tONYeOmHiuUNryvm3fRUy4tMPVLdAGkUhNWuggGrJcXPv+ouCjz0MKUHz1J2/E8IC9nqTabcxgaBYM0hPhD5Y65FsbxRQKxCQrDjDctW7PUM3HuZunFyifSAqEfuzCp48Il24luWUWZoyJCaPR82jE0+kFA643wRFVni4RYSq3ohJO2pZ7B5dO4xkDWbEpossJPLSrPjYID8rS2UHTlvyNxqIGsg674XJJ7vnh5L7PNwC4hh2sjCI96mzszOTpxLF0T7l88Yz7lAuK6OnL8gXLOnTvpzSb22YG8W7us3jSebFHeeqnXRG1vt+MoUM84LQIBmMsCTAcOauTh0T0l0neQK7m2bLMt2mGxU3HYssS0J2cdv5wljlPsrIuZLAG/2DOZIXgCYT8uMGZN+e2kSirfxZOPCsC0f24nTZzspnVn9VePS1Z5vubmAGGXG8ZFno9Hel0yfA5ZPhF7Dh972BQJ2qCpgH67lmWtBYbvk6sz02wjky2vXyz0XErP/kFB619js1BtwfOV4OPRqOQBjy3Qbk18vigUPPSD5ceHnwck7W9bhAqZdd7SuG7w4/P2F/GaJh8c7e9qgow+Q7cGBo+98WsLkuktFqiZabtXuQTu/Y5ETbR0v7tNSFnvrmu6pjdoan2KjMu8q/Hmj1EfCO2ZGfEIbIXKUlw8qaX9/b2oeSJmFksSeT/Fn0V3nSypChh4Gjh74ybO9aeZ/AN2dwciu2/MhAAAAAElFTkSuQmCC',
@ -9,20 +9,20 @@ export default {
currentBadge: '' currentBadge: ''
} }
}, },
created() { created () {
if (this.$themeConfig.titleBadgeIcons) { if (this.$themeConfig.titleBadgeIcons) {
this.badges = this.$themeConfig.titleBadgeIcons this.badges = this.$themeConfig.titleBadgeIcons
} }
this.currentBadge = this.getBadge() this.currentBadge = this.getBadge()
}, },
watch: { watch: {
'$route.path'() { '$route.path' () {
this.currentBadge = this.getBadge() this.currentBadge = this.getBadge()
} }
}, },
methods: { methods: {
getBadge() { getBadge () {
return this.badges[Math.floor(Math.random() * this.badges.length)] return this.badges[Math.floor(Math.random() * this.badges.length)]
} }
} }
} }

View File

@ -11,14 +11,14 @@ let catalogueData = {}; // 目录页数据
* @param {String} sourceDir .md文件所在源目录(一般是docs目录) * @param {String} sourceDir .md文件所在源目录(一般是docs目录)
* @param {Boolean} collapsable 是否可折叠 * @param {Boolean} collapsable 是否可折叠
*/ */
function createSidebarData(sourceDir, collapsable){ function createSidebarData (sourceDir, collapsable) {
const sidebarData = {}; const sidebarData = {};
const tocs = readTocs(sourceDir); const tocs = readTocs(sourceDir);
tocs.forEach(toc => { // toc是每个目录的绝对路径 tocs.forEach(toc => { // toc是每个目录的绝对路径
const tocArr = toc.split('\\') const tocArr = toc.split('\\')
if (tocArr[tocArr.length -1] === '_posts') { // 碎片化文章 if (tocArr[tocArr.length - 1] === '_posts') { // 碎片化文章
// 注释说明:碎片化文章不需要生成结构化侧边栏 2020.05.01 // 注释说明:碎片化文章不需要生成结构化侧边栏 2020.05.01
// const sidebarArr = mapTocToPostSidebar(toc); // const sidebarArr = mapTocToPostSidebar(toc);
// sidebarData[`/${path.basename(toc)}/`] = sidebarArr // sidebarData[`/${path.basename(toc)}/`] = sidebarArr
@ -44,7 +44,7 @@ module.exports = createSidebarData;
* 读取指定目录下的文件绝对路径 * 读取指定目录下的文件绝对路径
* @param {String} root 指定的目录 * @param {String} root 指定的目录
*/ */
function readTocs(root){ function readTocs (root) {
const result = []; const result = [];
const files = fs.readdirSync(root); // 读取目录,返回数组成员是root底下所有的目录名 (包含文件夹和文件) const files = fs.readdirSync(root); // 读取目录,返回数组成员是root底下所有的目录名 (包含文件夹和文件)
files.forEach(name => { files.forEach(name => {
@ -59,9 +59,9 @@ function readTocs(root){
/** /**
* 将碎片化文章目录(_posts)映射为对应的侧边栏配置数据 * 将碎片化文章目录(_posts)映射为对应的侧边栏配置数据
* @param {String} root * @param {String} root
*/ */
function mapTocToPostSidebar(root){ function mapTocToPostSidebar (root) {
let postSidebar = [] // 碎片化文章数据 let postSidebar = [] // 碎片化文章数据
const files = fs.readdirSync(root); // 读取目录(文件和文件夹),返回数组 const files = fs.readdirSync(root); // 读取目录(文件和文件夹),返回数组
@ -74,10 +74,10 @@ function mapTocToPostSidebar(root){
log(chalk.yellow(`warning: 该文件 "${file}" 在_posts文件夹中不应有序号且文件名中间不应有'.'`)) log(chalk.yellow(`warning: 该文件 "${file}" 在_posts文件夹中不应有序号且文件名中间不应有'.'`))
return return
} }
if(stat.isDirectory()){ // 是文件夹目录 if (stat.isDirectory()) { // 是文件夹目录
// log(chalk.yellow(`warning: 该目录 "${file}" 内文件无法生成侧边栏_posts文件夹里面不能有二级目录。`)) // log(chalk.yellow(`warning: 该目录 "${file}" 内文件无法生成侧边栏_posts文件夹里面不能有二级目录。`))
return return
} }
let [title, type] = filename.split('.'); let [title, type] = filename.split('.');
if (type !== 'md') { if (type !== 'md') {
@ -88,7 +88,7 @@ function mapTocToPostSidebar(root){
const contentStr = fs.readFileSync(file, 'utf8') // 读取md文件内容返回字符串 const contentStr = fs.readFileSync(file, 'utf8') // 读取md文件内容返回字符串
const { data } = matter(contentStr) // 解析出front matter数据 const { data } = matter(contentStr) // 解析出front matter数据
const permalink = data.permalink || '' const permalink = data.permalink || ''
postSidebar.push([filename, title, permalink ]); // [<路径>, <文件标题>, <永久链接>] postSidebar.push([filename, title, permalink]); // [<路径>, <文件标题>, <永久链接>]
}) })
return postSidebar return postSidebar
@ -97,12 +97,12 @@ function mapTocToPostSidebar(root){
/** /**
* 将目录映射为对应的侧边栏配置数据 * 将目录映射为对应的侧边栏配置数据
* @param {String} root * @param {String} root
* @param {Boolean} collapsable * @param {Boolean} collapsable
* @param {String} prefix * @param {String} prefix
*/ */
function mapTocToSidebar(root, collapsable, prefix){ function mapTocToSidebar (root, collapsable, prefix) {
prefix = prefix || ''; prefix = prefix || '';
let sidebar = []; let sidebar = [];
const files = fs.readdirSync(root); // 读取目录(文件和文件夹),返回数组 const files = fs.readdirSync(root); // 读取目录(文件和文件夹),返回数组
@ -119,7 +119,7 @@ function mapTocToSidebar(root, collapsable, prefix){
if (sidebar[order]) { // 判断序号是否已经存在 if (sidebar[order]) { // 判断序号是否已经存在
log(chalk.yellow(`warning: 该文件 "${file}" 的序号在同一级别中重复出现,将会被覆盖`)) log(chalk.yellow(`warning: 该文件 "${file}" 的序号在同一级别中重复出现,将会被覆盖`))
} }
if(stat.isDirectory()){ // 是文件夹目录 if (stat.isDirectory()) { // 是文件夹目录
sidebar[order] = { sidebar[order] = {
title, title,
collapsable, // 是否可折叠默认true collapsable, // 是否可折叠默认true
@ -133,7 +133,7 @@ function mapTocToSidebar(root, collapsable, prefix){
const contentStr = fs.readFileSync(file, 'utf8') // 读取md文件内容返回字符串 const contentStr = fs.readFileSync(file, 'utf8') // 读取md文件内容返回字符串
const { data } = matter(contentStr) // 解析出front matter数据 const { data } = matter(contentStr) // 解析出front matter数据
const permalink = data.permalink || '' const permalink = data.permalink || ''
sidebar[order] = [prefix + filename, title, permalink ]; // [<路径>, <文件标题>, <永久链接>] sidebar[order] = [prefix + filename, title, permalink]; // [<路径>, <文件标题>, <永久链接>]
// 目录页和永久链接,用于给面包屑提供数据 // 目录页和永久链接,用于给面包屑提供数据
const pageComponent = data.pageComponent const pageComponent = data.pageComponent
@ -148,4 +148,4 @@ function mapTocToSidebar(root, collapsable, prefix){
sidebar, sidebar,
catalogueData catalogueData
}; };
} }

View File

@ -6,7 +6,7 @@ const chalk = require('chalk') // 命令行打印美化
const { type } = require('./modules/fn'); const { type } = require('./modules/fn');
const log = console.log const log = console.log
function createPage(sourceDir, page) { function createPage (sourceDir, page) {
const dirPath = path.join(sourceDir, '@pages') // 生成的文件夹路径 const dirPath = path.join(sourceDir, '@pages') // 生成的文件夹路径
// 文件夹不存在时 // 文件夹不存在时
@ -21,30 +21,30 @@ function createPage(sourceDir, page) {
return return
} }
// 注意:反引号字符串的格式会映射到文件 // 注意:反引号字符串的格式会映射到文件
let content = '' let content = ''
if (page.indexOf('categories') > -1) { if (page.indexOf('categories') > -1) {
content = `--- content = `---
categoriesPage: true categoriesPage: true
title: 分类 title: 分类
permalink: /categories/ permalink: /categories/
article: false article: false
---` ---`
} else if (page.indexOf('tags') > -1){ } else if (page.indexOf('tags') > -1) {
content = `--- content = `---
tagsPage: true tagsPage: true
title: 标签 title: 标签
permalink: /tags/ permalink: /tags/
article: false article: false
---` ---`
} else if (page.indexOf('archives') > -1){ } else if (page.indexOf('archives') > -1) {
content = `--- content = `---
archivesPage: true archivesPage: true
title: 归档 title: 归档
permalink: /archives/ permalink: /archives/
article: false article: false
---` ---`
} }
if (content) { if (content) {
fs.writeFileSync(pagePath, content) fs.writeFileSync(pagePath, content)
@ -53,7 +53,7 @@ article: false
} }
// 删除页面文件 // 删除页面文件
function deletePage(sourceDir, page) { function deletePage (sourceDir, page) {
const dirPath = path.join(sourceDir, '@pages') // 文件夹路径 const dirPath = path.join(sourceDir, '@pages') // 文件夹路径
const pagePath = path.join(dirPath, `${page}.md`) // 文件路径 const pagePath = path.join(dirPath, `${page}.md`) // 文件路径
@ -66,10 +66,10 @@ function deletePage(sourceDir, page) {
} }
// 删除文件夹 // 删除文件夹
function deleteDir(dirPath) { function deleteDir (dirPath) {
if (fs.existsSync(dirPath)) { if (fs.existsSync(dirPath)) {
const files = fs.readdirSync(dirPath) const files = fs.readdirSync(dirPath)
if( type(files) === 'array' && files.length === 0) { if (type(files) === 'array' && files.length === 0) {
fs.rmdirSync(dirPath) fs.rmdirSync(dirPath)
log(chalk.blue('tip ') + chalk.green(`delete dir(删除目录): ${dirPath}`)) log(chalk.blue('tip ') + chalk.green(`delete dir(删除目录): ${dirPath}`))
} }
@ -79,4 +79,4 @@ function deleteDir(dirPath) {
module.exports = { module.exports = {
createPage, createPage,
deletePage deletePage
} }

View File

@ -1,21 +1,21 @@
// 类型判断 // 类型判断
exports.type = function (o){ exports.type = function (o) {
var s = Object.prototype.toString.call(o) var s = Object.prototype.toString.call(o)
return s.match(/\[object (.*?)\]/)[1].toLowerCase() return s.match(/\[object (.*?)\]/)[1].toLowerCase()
} }
// 修复date时区格式的问题 // 修复date时区格式的问题
exports.repairDate = function (date) { exports.repairDate = function (date) {
date = new Date(date); date = new Date(date);
return `${date.getUTCFullYear()}-${zero(date.getUTCMonth()+1)}-${zero(date.getUTCDate())} ${zero(date.getUTCHours())}:${zero(date.getUTCMinutes())}:${zero(date.getUTCSeconds())}`; return `${date.getUTCFullYear()}-${zero(date.getUTCMonth() + 1)}-${zero(date.getUTCDate())} ${zero(date.getUTCHours())}:${zero(date.getUTCMinutes())}:${zero(date.getUTCSeconds())}`;
} }
// 日期的格式 // 日期的格式
exports.dateFormat = function (date) { exports.dateFormat = function (date) {
return `${date.getFullYear()}-${zero(date.getMonth()+1)}-${zero(date.getDate())} ${zero(date.getHours())}:${zero(date.getMinutes())}:${zero(date.getSeconds())}` return `${date.getFullYear()}-${zero(date.getMonth() + 1)}-${zero(date.getDate())} ${zero(date.getHours())}:${zero(date.getMinutes())}:${zero(date.getSeconds())}`
} }
// 小于10补0 // 小于10补0
function zero(d){ function zero (d) {
return d.toString().padStart(2,'0') return d.toString().padStart(2, '0')
} }

View File

@ -6,38 +6,38 @@ const path = require('path'); // 路径模块
const chalk = require('chalk') // 命令行打印美化 const chalk = require('chalk') // 命令行打印美化
const log = console.log const log = console.log
function readFileList(dir, filesList = []) { function readFileList (dir, filesList = []) {
const files = fs.readdirSync(dir); const files = fs.readdirSync(dir);
files.forEach( (item, index) => { files.forEach((item, index) => {
let filePath = path.join(dir, item); let filePath = path.join(dir, item);
const stat = fs.statSync(filePath); const stat = fs.statSync(filePath);
if (stat.isDirectory() && item !== '.vuepress' && item !== '@pages') { if (stat.isDirectory() && item !== '.vuepress' && item !== '@pages') {
readFileList(path.join(dir, item), filesList); //递归读取文件 readFileList(path.join(dir, item), filesList); //递归读取文件
} else { } else {
if(path.basename(dir) !== 'docs'){ // 过滤docs目录级下的文件 if (path.basename(dir) !== 'docs') { // 过滤docs目录级下的文件
const fileNameArr = path.basename(filePath).split('.') const fileNameArr = path.basename(filePath).split('.')
let name = null, type = null; let name = null, type = null;
if (fileNameArr.length === 2) { // 没有序号的文件 if (fileNameArr.length === 2) { // 没有序号的文件
name = fileNameArr[0] name = fileNameArr[0]
type = fileNameArr[1] type = fileNameArr[1]
} else if (fileNameArr.length === 3) { // 有序号的文件 } else if (fileNameArr.length === 3) { // 有序号的文件
name = fileNameArr[1] name = fileNameArr[1]
type = fileNameArr[2] type = fileNameArr[2]
} else { // 超过两个‘.’的 } else { // 超过两个‘.’的
log(chalk.yellow(`warning: 该文件 "${filePath}" 没有按照约定命名,将忽略生成相应数据。`)) log(chalk.yellow(`warning: 该文件 "${filePath}" 没有按照约定命名,将忽略生成相应数据。`))
return return
}
if(type === 'md'){ // 过滤非md文件
filesList.push({
name,
filePath
});
}
} }
} if (type === 'md') { // 过滤非md文件
filesList.push({
name,
filePath
});
}
}
}
}); });
return filesList; return filesList;
} }
module.exports = readFileList; module.exports = readFileList;

View File

@ -4,7 +4,7 @@ const jsonToYaml = require('json2yaml')
const chalk = require('chalk') // 命令行打印美化 const chalk = require('chalk') // 命令行打印美化
// const arg = process.argv.splice(2)[0]; // 获取命令行传入的参数 // const arg = process.argv.splice(2)[0]; // 获取命令行传入的参数
const readFileList = require('./modules/readFileList'); const readFileList = require('./modules/readFileList');
const { type, repairDate, dateFormat} = require('./modules/fn'); const { type, repairDate, dateFormat } = require('./modules/fn');
const log = console.log const log = console.log
const path = require('path'); const path = require('path');
@ -14,7 +14,7 @@ const PREFIX = '/pages/'
/** /**
* .md文件设置frontmatter(标题日期永久链接等数据) * .md文件设置frontmatter(标题日期永久链接等数据)
*/ */
function setFrontmatter(sourceDir, themeConfig) { function setFrontmatter (sourceDir, themeConfig) {
const isCategory = themeConfig.category const isCategory = themeConfig.category
const isTag = themeConfig.tag const isTag = themeConfig.tag
@ -33,16 +33,16 @@ function setFrontmatter(sourceDir, themeConfig) {
const dateStr = dateFormat(getBirthtime(stat));// 文件的创建时间 const dateStr = dateFormat(getBirthtime(stat));// 文件的创建时间
const categories = getCategories(file, categoryText) const categories = getCategories(file, categoryText)
// 注意下面这些反引号字符串的格式会映射到文件 // 注意下面这些反引号字符串的格式会映射到文件
const cateStr = isCategory === false ? '' : ` const cateStr = isCategory === false ? '' : `
categories: categories:
- ${categories[0]}${categories[1] ? '\r\n - '+ categories[1] : ''}`; - ${categories[0]}${categories[1] ? '\r\n - ' + categories[1] : ''}`;
const tagsStr = isTag === false ? '' : ` const tagsStr = isTag === false ? '' : `
tags: tags:
- `; - `;
const fmData = `--- const fmData = `---
title: ${file.name} title: ${file.name}
date: ${dateStr} date: ${dateStr}
permalink: ${getPermalink()}${file.filePath.indexOf('_posts') > -1 ? '\r\nsidebar: auto' : ''}${cateStr}${tagsStr} permalink: ${getPermalink()}${file.filePath.indexOf('_posts') > -1 ? '\r\nsidebar: auto' : ''}${cateStr}${tagsStr}
@ -71,18 +71,18 @@ permalink: ${getPermalink()}${file.filePath.indexOf('_posts') > -1 ? '\r\nsideba
matterData.permalink = getPermalink(); matterData.permalink = getPermalink();
mark = true; mark = true;
} }
if (file.filePath.indexOf('_posts') > -1 && !matterData.hasOwnProperty('sidebar')) { // auto侧边栏_posts文件夹特有 if (file.filePath.indexOf('_posts') > -1 && !matterData.hasOwnProperty('sidebar')) { // auto侧边栏_posts文件夹特有
matterData.sidebar = "auto"; matterData.sidebar = "auto";
mark = true; mark = true;
} }
if ( !matterData.hasOwnProperty('pageComponent') && matterData.article !== false ) { // 是文章页才添加分类和标签 if (!matterData.hasOwnProperty('pageComponent') && matterData.article !== false) { // 是文章页才添加分类和标签
if (isCategory !== false && !matterData.hasOwnProperty('categories')) { // 分类 if (isCategory !== false && !matterData.hasOwnProperty('categories')) { // 分类
matterData.categories = getCategories(file, categoryText) matterData.categories = getCategories(file, categoryText)
mark = true; mark = true;
} }
if (isTag !== false && !matterData.hasOwnProperty('tags')) { // 标签 if (isTag !== false && !matterData.hasOwnProperty('tags')) { // 标签
matterData.tags = ['']; matterData.tags = [''];
mark = true; mark = true;
@ -90,20 +90,20 @@ permalink: ${getPermalink()}${file.filePath.indexOf('_posts') > -1 ? '\r\nsideba
} }
if (mark) { if (mark) {
if(matterData.date && type(matterData.date) === 'date') { if (matterData.date && type(matterData.date) === 'date') {
matterData.date = repairDate(matterData.date) // 修复时间格式 matterData.date = repairDate(matterData.date) // 修复时间格式
} }
const newData = jsonToYaml.stringify(matterData).replace(/\n\s{2}/g,"\n").replace(/"/g,"") + '---\r\n' + fileMatterObj.content; const newData = jsonToYaml.stringify(matterData).replace(/\n\s{2}/g, "\n").replace(/"/g, "") + '---\r\n' + fileMatterObj.content;
fs.writeFileSync(file.filePath, newData); // 写入 fs.writeFileSync(file.filePath, newData); // 写入
log(chalk.blue('tip ') + chalk.green(`write frontmatter(写入frontmatter)${file.filePath} `)) log(chalk.blue('tip ') + chalk.green(`write frontmatter(写入frontmatter)${file.filePath} `))
} }
} }
}) })
} }
// 获取分类数据 // 获取分类数据
function getCategories(file, categoryText) { function getCategories (file, categoryText) {
let categories = [] let categories = []
if (file.filePath.indexOf('_posts') === -1) { // 不在_posts文件夹 if (file.filePath.indexOf('_posts') === -1) { // 不在_posts文件夹
@ -120,13 +120,13 @@ function getCategories(file, categoryText) {
} }
// 获取文件创建时间 // 获取文件创建时间
function getBirthtime(stat){ function getBirthtime (stat) {
// 在一些系统下无法获取birthtime属性的正确时间使用atime代替 // 在一些系统下无法获取birthtime属性的正确时间使用atime代替
return stat.birthtime.getFullYear() != 1970 ? stat.birthtime : stat.atime return stat.birthtime.getFullYear() != 1970 ? stat.birthtime : stat.atime
} }
// 定义永久链接数据 // 定义永久链接数据
function getPermalink() { function getPermalink () {
return `${PREFIX + (Math.random() + Math.random()).toString(16).slice(2, 8)}/` return `${PREFIX + (Math.random() + Math.random()).toString(16).slice(2, 8)}/`
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "vuepress-theme-vdoing", "name": "vuepress-theme-vdoing",
"version": "1.4.4", "version": "1.5.0",
"description": "Vdoing theme for VuePress. 一个基于VuePress的知识管理兼博客主题。", "description": "Vdoing theme for VuePress. 一个基于VuePress的知识管理兼博客主题。",
"author": { "author": {
"name": "gaoyi(Evan) Xu" "name": "gaoyi(Evan) Xu"
@ -19,7 +19,7 @@
"@vuepress/plugin-active-header-links": "^1.2.0", "@vuepress/plugin-active-header-links": "^1.2.0",
"@vuepress/plugin-nprogress": "^1.2.0", "@vuepress/plugin-nprogress": "^1.2.0",
"@vuepress/plugin-search": "^1.2.0", "@vuepress/plugin-search": "^1.2.0",
"chalk": "^4.0.0", "chalk": "^4.0.0",
"json2yaml": "^1.1.0", "json2yaml": "^1.1.0",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"docsearch.js": "^2.5.2", "docsearch.js": "^2.5.2",
@ -40,10 +40,8 @@
], ],
"license": "MIT", "license": "MIT",
"main": "index.js", "main": "index.js",
"maintainers": [ "maintainers": [{
{ "name": "Evan xu",
"name": "Evan xu", "email": "894072666@qq.com"
"email": "894072666@qq.com" }]
}
]
} }

View File

@ -4,7 +4,7 @@
margin-bottom .2rem margin-bottom .2rem
p p
margin 0 margin 0
&.tip, &.warning, &.danger &.tip, &.warning, &.danger, &.note
padding .5rem 1.5rem padding .5rem 1.5rem
border-left-width .5rem border-left-width .5rem
border-left-style solid border-left-style solid
@ -29,6 +29,10 @@
color darken(red, 40%) color darken(red, 40%)
a a
color var(--textColor) color var(--textColor)
&.note
background-color #E8F5FA
border-color #157BAE
color darken(#157BAE, 40%)
&.right &.right
color var(--textColor) color var(--textColor)
font-size 0.9rem font-size 0.9rem
@ -66,7 +70,7 @@
.theme-mode-dark .theme-mode-dark
.custom-block .custom-block
&.warning &.warning
background-color rgba(255, 247, 208, .2) background-color rgba(255, 247, 208, .2)
color darken(#ffe564, 35%) color darken(#ffe564, 35%)
.custom-block-title .custom-block-title
color darken(#ffe564, 15%) color darken(#ffe564, 15%)
@ -77,4 +81,7 @@
background-color rgba(255, 230, 230, .4) background-color rgba(255, 230, 230, .4)
color darken(red, 50%) color darken(red, 50%)
a a
color $accentColor color $accentColor
&.note
background-color rgba(243, 245, 247, .2)
color darken(#157BAE, 0%)

View File

@ -13,7 +13,7 @@ h1, h2, h3, h4, h5, h6
float none float none
padding-right: 0 padding-right: 0
margin-left: -.9rem margin-left: -.9rem
// //
.cardListContainer .cardListContainer
@ -31,14 +31,14 @@ h1, h2, h3, h4, h5, h6
background var(--bodyBg) background var(--bodyBg)
border-radius 3px border-radius 3px
color var(--textColor) color var(--textColor)
display flex display flex
box-shadow 1px 1px 2px 0 rgba(0,0,0,.06) box-shadow 1px 1px 2px 0 rgba(0,0,0,.06)
transition all .4s transition all .4s
&:hover &:hover
text-decoration none text-decoration none
box-shadow: 0 10px 20px -10px var(--randomColor, rgba(0,0,0,0.15)); box-shadow: 0 10px 20px -10px var(--randomColor, rgba(0,0,0,0.15));
transform: translateY(-5px) transform: translateY(-3px) scale(1.01, 1.01)
img img
// transform rotate(8deg) scale(1.1, 1.1) // transform rotate(8deg) scale(1.1, 1.1)
box-shadow 3px 2px 7px rgba(0, 0, 0, 0.15) box-shadow 3px 2px 7px rgba(0, 0, 0, 0.15)
div p div p
@ -55,7 +55,7 @@ h1, h2, h3, h4, h5, h6
div div
flex 1 flex 1
display inline-block display inline-block
float right float right
padding 1rem 0 padding 1rem 0
p p
margin 0 margin 0
@ -96,20 +96,21 @@ h1, h2, h3, h4, h5, h6
width calc(100%/3 - 1rem) width calc(100%/3 - 1rem)
margin .5rem margin .5rem
background var(--mainBg) background var(--mainBg)
border 1px solid rgba(0,0,0,0.08) border 1px solid rgba(0,0,0,0.1)
box-sizing: border-box box-sizing: border-box
border-radius 3px border-radius 3px
overflow hidden overflow hidden
color var(--textColor) color var(--textColor)
box-shadow 2px 2px 10px rgba(0,0,0,.04) box-shadow 2px 2px 10px rgba(0,0,0,.04)
display flex display flex
flex-direction: column; flex-direction: column;
justify-content: flex-start; justify-content: flex-start;
align-items: stretch; align-items: stretch;
align-content: stretch; align-content: stretch;
transition: box-shadow .3s transition: all .4s
&:hover &:hover
box-shadow 1px 1px 20px rgba(0,0,0,.07) box-shadow 1px 1px 20px rgba(0,0,0,.1)
transform: translateY(-3px)
.box-img .box-img
overflow hidden overflow hidden
position relative position relative
@ -119,15 +120,15 @@ h1, h2, h3, h4, h5, h6
width 100% width 100%
height auto height auto
transition: all .3s transition: all .3s
&:hover // &:hover
img // img
transform: scale(1.1, 1.1) // transform: scale(1.1, 1.1)
opacity .75 // opacity .75
a a
color var(--textColor) color var(--textColor)
transition: color .3s transition: color .3s
&:hover &:hover
color $accentColor // color $accentColor
text-decoration none text-decoration none
.box-info .box-info
padding: .8rem 1rem padding: .8rem 1rem
@ -141,13 +142,13 @@ h1, h2, h3, h4, h5, h6
.box-footer .box-footer
overflow hidden overflow hidden
padding: .8rem 1rem padding: .8rem 1rem
border-top: 1px solid rgba(0,0,0,0.05) border-top: 1px solid rgba(0,0,0,0.1)
img img
width 1.8rem width 1.8rem
height 1.8rem height 1.8rem
border-radius 50% border-radius 50%
float left float left
span span
line-height 1.8rem line-height 1.8rem
float left float left
margin-left: .6rem margin-left: .6rem
@ -168,9 +169,9 @@ h1, h2, h3, h4, h5, h6
border-color: var(--borderColor) border-color: var(--borderColor)
.box-footer .box-footer
border-color: var(--borderColor) border-color: var(--borderColor)
// //
@media (max-width: 900px) @media (max-width: 900px)
.cardListContainer .cardListContainer
.card-list .card-list
.card-item.row-4 .card-item.row-4
@ -180,7 +181,7 @@ h1, h2, h3, h4, h5, h6
.card-item.row-4 .card-item.row-4
width calc(100%/3 - 1rem) width calc(100%/3 - 1rem)
@media (max-width: 720px) @media (max-width: 720px)
.cardListContainer .cardListContainer
.card-list .card-list
.card-item.row-3, .card-item.row-4 .card-item.row-3, .card-item.row-4
@ -191,8 +192,8 @@ h1, h2, h3, h4, h5, h6
.card-list .card-list
.card-item.row-3, .card-item.row-4 .card-item.row-3, .card-item.row-4
width calc(100%/2 - 1rem) width calc(100%/2 - 1rem)
@media (max-width: 500px) @media (max-width: 500px)
.cardListContainer .cardListContainer
.card-list .card-list
.card-item.row-1, .card-item.row-2, .card-item.row-3, .card-item.row-4 .card-item.row-1, .card-item.row-2, .card-item.row-3, .card-item.row-4
@ -202,4 +203,4 @@ h1, h2, h3, h4, h5, h6
.cardImgListContainer .cardImgListContainer
.card-list .card-list
.card-item.row-1, .card-item.row-2, .card-item.row-3, .card-item.row-4 .card-item.row-1, .card-item.row-2, .card-item.row-3, .card-item.row-4
width calc(100% - 1rem) width calc(100% - 1rem)

View File

@ -1,118 +0,0 @@
const re = /.*\/(.*?)\.(html|md)/
export function getPagesList(posts) {
let pagesList = {}
let tagGroup = {}
// 过滤非文章页
posts = filterNotArticle(posts)
// 对页面数据二次处理和排序
const pages = posts.map(post => {
// const execs = re.exec(post.relativePath)
const date = new Date(post.frontmatter.date || post.lastUpdated)
const pathArr = post.relativePath.split('/')
return {
// ...post,
title: post.title,
path: post.path,
// lastUpdated: post.lastUpdated,
updateTimestamp: date.getTime(), // 更新日期的时间戳
// filename: execs ? execs['1'] : '',
formatDay: formatDate(date),
year: date.getFullYear(),
tag: /\./g.test(pathArr[0]) ? pathArr[1].split('.')[1] : pathArr[0] // 区分是单独合集的笔记还是文章
}
}).sort((a, b) => b.updateTimestamp - a.updateTimestamp)
// 根据年份对数据分组
let pageYearArr = []
let pageYearObj = {}
pages.forEach( page => {
// 全部
if (!pageYearObj[page.year]){
pageYearArr.push({
year: page.year,
pageList: [page]
})
pageYearObj[page.year] = page
} else {
pageYearArr.forEach(ele => {
if (ele.year == page.year){
ele.pageList.push(page)
}
})
}
// 加入标签属性
if (!tagGroup[page.tag]) {
tagGroup[page.tag] = []
}
})
// 根据标签分组
for (let item in tagGroup) { // 循环标签
for(let i in pageYearArr) { // 循环全部
const filterTag = pageYearArr[i].pageList.filter(page => { // 按标签过滤
return page.tag === item
})
if (filterTag.length) { // 该年份中有数据才加入
tagGroup[item].push({
year: pageYearArr[i].year,
pageList: filterTag
})
}
}
}
pagesList.tagGroup = tagGroup
pagesList.allPage = pageYearArr // 加入全部
return pagesList
}
export function getTopKPosts(posts, len, currentPath) {
return filterNotArticle(posts, currentPath)
.map(post => {
const execs = re.exec(post.relativePath)
return {
...post,
updateTimestamp: (new Date(post.frontmatter.date || post.lastUpdated)).getTime(), // 更新日期的时间戳
filename: execs ? execs['1'] : '',
formatDay: formatDate(new Date(post.frontmatter.date || post.lastUpdated))
}
})
.sort((a, b) => b.updateTimestamp - a.updateTimestamp)
.slice(0,len)
}
// 过滤没有frontmatter数据的 和 非文章页面的,
function filterNotArticle(posts, currentPath){
return posts.filter(post => {
const { frontmatter, path } = post;
if (currentPath) { // 过滤是当前页面的
return frontmatter && frontmatter.permalink && frontmatter.title && frontmatter.article !== false && path !== currentPath;
} else {
return frontmatter && frontmatter.permalink && frontmatter.title && frontmatter.article !== false;
}
})
}
// 日期格式化
function formatDate(date) {
if (!(date instanceof Date)) {
return
}
// return `${date.getFullYear()}/${zero(date.getMonth() + 1)}/${zero(date.getDate())}`
return `${zero(date.getMonth() + 1)}-${zero(date.getDate())}`
}
// 补0
function zero(d) {
return d.toString().padStart(2,'0')
}

View File

@ -246,22 +246,22 @@ function resolveItem (item, pages, base, groupDepth = 1) {
// 类型判断 // 类型判断
export function type(o){ export function type (o) {
const s = Object.prototype.toString.call(o) const s = Object.prototype.toString.call(o)
return s.match(/\[object (.*?)\]/)[1].toLowerCase() return s.match(/\[object (.*?)\]/)[1].toLowerCase()
} }
// 日期格式化(只获取年月日) // 日期格式化(只获取年月日)
export function dateFormat(date) { export function dateFormat (date) {
if (!(date instanceof Date)) { if (!(date instanceof Date)) {
date = new Date(date) date = new Date(date)
} }
return `${date.getUTCFullYear()}-${zero(date.getUTCMonth()+1)}-${zero(date.getUTCDate())}` return `${date.getUTCFullYear()}-${zero(date.getUTCMonth() + 1)}-${zero(date.getUTCDate())}`
} }
// 小于10补0 // 小于10补0
export function zero(d){ export function zero (d) {
return d.toString().padStart(2,'0') return d.toString().padStart(2, '0')
} }
// 获取时间的时间戳 // 获取时间的时间戳
@ -280,8 +280,8 @@ export function compareDate (a, b) {
} }
// 将特殊符号编码应用于url // 将特殊符号编码应用于url
export function encodeUrl(str) { export function encodeUrl (str) {
str = str + '' str = str + ''
str = str.replace(/ |((?=[\x21-\x7e]+)[^A-Za-z0-9])/g, '-') str = str.replace(/ |((?=[\x21-\x7e]+)[^A-Za-z0-9])/g, '-')
return str return str
} }

View File

@ -1,4 +1,4 @@
import { type, compareDate, encodeUrl } from './index' import { type, compareDate } from './index'
/** /**
* 过滤非文章页 * 过滤非文章页
@ -6,7 +6,7 @@ import { type, compareDate, encodeUrl } from './index'
*/ */
export function filterPosts (posts) { export function filterPosts (posts) {
posts = posts.filter(item => { posts = posts.filter(item => {
const { frontmatter: { pageComponent, article, home }} = item const { frontmatter: { pageComponent, article, home } } = item
return !(pageComponent || article === false || home === true) // 存在页面组件、article字段为false以及首页 return !(pageComponent || article === false || home === true) // 存在页面组件、article字段为false以及首页
}) })
return posts return posts
@ -47,31 +47,29 @@ export function sortPostsByDate (posts) {
* 按分类和标签分组 * 按分类和标签分组
* @param {Array} posts 按时间排序之后的文章数据 * @param {Array} posts 按时间排序之后的文章数据
*/ */
export function groupPosts(posts) { export function groupPosts (posts) {
const categoriesObj = {} const categoriesObj = {}
const tagsObj = {} const tagsObj = {}
for (let i = 0, postsL = posts.length; i < postsL; i++) { for (let i = 0, postsL = posts.length; i < postsL; i++) {
const { frontmatter: { categories, tags }} = posts[i] const { frontmatter: { categories, tags } } = posts[i]
if (type(categories) === 'array') { if (type(categories) === 'array') {
categories.forEach(item => { categories.forEach(item => {
if (item) { // 分类值是有效的 if (item) { // 分类值是有效的
const encodeItem = encodeUrl(item) if (!categoriesObj[item]) {
if (!categoriesObj[encodeItem]) { categoriesObj[item] = []
categoriesObj[encodeItem] = []
} }
categoriesObj[encodeItem].push(posts[i]) categoriesObj[item].push(posts[i])
} }
}) })
} }
if (type(tags) === 'array') { if (type(tags) === 'array') {
tags.forEach(item => { tags.forEach(item => {
if (item) { // 标签值是有效的 if (item) { // 标签值是有效的
const encodeItem = encodeUrl(item) if (!tagsObj[item]) {
if (!tagsObj[encodeItem]) { tagsObj[item] = []
tagsObj[encodeItem] = []
} }
tagsObj[encodeItem].push(posts[i]) tagsObj[item].push(posts[i])
} }
}) })
} }
@ -86,18 +84,18 @@ export function groupPosts(posts) {
* 获取所有分类和标签 * 获取所有分类和标签
* @param {Object} groupPosts 按分类和标签分组之后的文章数据 * @param {Object} groupPosts 按分类和标签分组之后的文章数据
*/ */
export function categoriesAndTags(groupPosts) { export function categoriesAndTags (groupPosts) {
const categoriesArr = [] const categoriesArr = []
const tagsArr = [] const tagsArr = []
for(let key in groupPosts.categories) { for (let key in groupPosts.categories) {
categoriesArr.push({ categoriesArr.push({
key, key,
length: groupPosts.categories[key].length length: groupPosts.categories[key].length
}) })
} }
for(let key in groupPosts.tags) { for (let key in groupPosts.tags) {
tagsArr.push({ tagsArr.push({
key, key,
length: groupPosts.tags[key].length length: groupPosts.tags[key].length