晴空项目

This commit is contained in:
reco_luan 2019-04-15 10:30:06 +08:00
commit c63b38b713
52 changed files with 3362 additions and 754 deletions

View File

@ -1,182 +0,0 @@
<template>
<div
class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd">
<Password v-if="!isHasKey"></Password>
<div v-else>
<Navbar v-if="shouldShowNavbar" @toggle-sidebar="toggleSidebar"/>
<div class="sidebar-mask" @click="toggleSidebar(false)"></div>
<Sidebar :items="sidebarItems" @toggle-sidebar="toggleSidebar">
<slot name="sidebar-top" slot="top"/>
<slot name="sidebar-bottom" slot="bottom"/>
</Sidebar>
<div class="custom-layout" v-if="$page.frontmatter.layout">
<component :is="$page.frontmatter.layout"/>
</div>
<Home v-else-if="$page.frontmatter.home"/>
<Page v-else :sidebar-items="sidebarItems" @tagChange="tagChange">
<slot name="page-top" slot="top"/>
<slot name="page-bottom" slot="bottom"/>
</Page>
<Valine :valineRefresh="valineRefresh"></Valine>
<router-view></router-view>
<SWUpdatePopup :updateEvent="swUpdateEvent"/>
<BackToTop></BackToTop>
</div>
</div>
</template>
<script>
import Vue from "vue";
import nprogress from "nprogress";
import Home from "./pages/Home/";
import Navbar from "./components/Navbar/";
import Page from "./pages/Page/";
import Sidebar from "./components/Sidebar/";
import SWUpdatePopup from "./components/SWUpdatePopup/";
import { resolveSidebarItems } from "./util/"
import BackToTop from "./components/BackToTop/"
import Valine from './components/Valine/'
import Password from './components/Password/'
export default {
components: { Home, Page, Sidebar, Navbar, SWUpdatePopup, BackToTop, Valine, Password },
data() {
return {
isSidebarOpen: false,
swUpdateEvent: null,
valineRefresh: false,
isHasKey: true
};
},
computed: {
shouldShowNavbar() {
const { themeConfig } = this.$site;
const { frontmatter } = this.$page;
if (frontmatter.navbar === false || themeConfig.navbar === false) {
return false;
}
return (
this.$title ||
themeConfig.logo ||
themeConfig.repo ||
themeConfig.nav ||
this.$themeLocaleConfig.nav
);
},
shouldShowSidebar() {
const { frontmatter } = this.$page;
return (
!frontmatter.layout &&
!frontmatter.home &&
frontmatter.sidebar !== false &&
this.sidebarItems.length
);
},
sidebarItems() {
return resolveSidebarItems(
this.$page,
this.$route,
this.$site,
this.$localePath
);
},
pageClasses() {
const userPageClass = this.$page.frontmatter.pageClass;
return [
{
"no-navbar": !this.shouldShowNavbar,
"sidebar-open": this.isSidebarOpen,
"no-sidebar": !this.shouldShowSidebar
},
userPageClass
];
}
},
mounted() {
window.addEventListener("scroll", this.onScroll);
// configure progress bar
nprogress.configure({ showSpinner: false });
this.$router.beforeEach((to, from, next) => {
if (to.path !== from.path && !Vue.component(to.name)) {
nprogress.start();
}
next();
});
this.$router.afterEach(() => {
nprogress.done();
this.isSidebarOpen = false;
});
this.$on("sw-updated", this.onSWUpdated);
const keyPage = this.$site.themeConfig.keyPage
if (!keyPage) {
this.isHasKey = true
return
}
const keys = keyPagekeys
this.isHasKey = keys && keys.indexOf(sessionStorage.getItem('key')) > -1
},
methods: {
tagChange () {
this.valineRefresh = true
setTimeout(() => {
this.valineRefresh = false
}, 300)
},
toggleSidebar(to) {
this.isSidebarOpen = typeof to === "boolean" ? to : !this.isSidebarOpen;
},
// side swipe
onTouchStart(e) {
this.touchStart = {
x: e.changedTouches[0].clientX,
y: e.changedTouches[0].clientY
};
},
onTouchEnd(e) {
const dx = e.changedTouches[0].clientX - this.touchStart.x;
const dy = e.changedTouches[0].clientY - this.touchStart.y;
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
if (dx > 0 && this.touchStart.x <= 80) {
this.toggleSidebar(true);
} else {
this.toggleSidebar(false);
}
}
},
onSWUpdated(e) {
this.swUpdateEvent = e;
}
}
};
</script>
<style src="prismjs/themes/prism-tomorrow.css"></style>
<style src="./styles/theme.styl" lang="stylus"></style>

View File

@ -0,0 +1,155 @@
<template>
<form
id="search-form"
class="algolia-search-wrapper search-box"
role="search"
>
<input
id="algolia-search-input"
class="search-query"
>
</form>
</template>
<script>
export default {
props: ['options'],
mounted () {
this.initialize(this.options, this.$lang)
},
methods: {
initialize (userOptions, lang) {
Promise.all([
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.js'),
import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css')
]).then(([docsearch]) => {
docsearch = docsearch.default
const { algoliaOptions = {}} = userOptions
docsearch(Object.assign(
{},
userOptions,
{
inputSelector: '#algolia-search-input',
// #697 Make docsearch work well at i18n mode.
algoliaOptions: Object.assign({
'facetFilters': [`lang:${lang}`].concat(algoliaOptions.facetFilters || [])
}, algoliaOptions)
}
))
})
},
update (options, lang) {
this.$el.innerHTML = '<input id="algolia-search-input" class="search-query">'
this.initialize(options, lang)
}
},
watch: {
$lang (newValue) {
this.update(this.options, newValue)
},
options (newValue) {
this.update(newValue, this.$lang)
}
}
}
</script>
<style lang="stylus">
.algolia-search-wrapper
& > span
vertical-align middle
.algolia-autocomplete
line-height normal
.ds-dropdown-menu
background-color #fff
border 1px solid #999
border-radius 4px
font-size 16px
margin 6px 0 0
padding 4px
text-align left
&:before
border-color #999
[class*=ds-dataset-]
border none
padding 0
.ds-suggestions
margin-top 0
.ds-suggestion
border-bottom 1px solid $borderColor
.algolia-docsearch-suggestion--highlight
color #2c815b
.algolia-docsearch-suggestion
border-color $borderColor
padding 0
.algolia-docsearch-suggestion--category-header
padding 5px 10px
margin-top 0
background $accentColor
color #fff
font-weight 600
.algolia-docsearch-suggestion--highlight
background rgba(255, 255, 255, 0.6)
.algolia-docsearch-suggestion--wrapper
padding 0
.algolia-docsearch-suggestion--title
font-weight 600
margin-bottom 0
color $textColor
.algolia-docsearch-suggestion--subcategory-column
vertical-align top
padding 5px 7px 5px 5px
border-color $borderColor
background #f1f3f5
&:after
display none
.algolia-docsearch-suggestion--subcategory-column-text
color #555
.algolia-docsearch-footer
border-color $borderColor
.ds-cursor .algolia-docsearch-suggestion--content
background-color #e7edf3 !important
color $textColor
@media (min-width: $MQMobile)
.algolia-search-wrapper
.algolia-autocomplete
.algolia-docsearch-suggestion
.algolia-docsearch-suggestion--subcategory-column
float none
width 150px
min-width 150px
display table-cell
.algolia-docsearch-suggestion--content
float none
display table-cell
width 100%
vertical-align top
.ds-dropdown-menu
min-width 515px !important
@media (max-width: $MQMobile)
.algolia-search-wrapper
.ds-dropdown-menu
min-width calc(100vw - 4rem) !important
max-width calc(100vw - 4rem) !important
.algolia-docsearch-suggestion--wrapper
padding 5px 7px 5px 5px !important
.algolia-docsearch-suggestion--subcategory-column
padding 0 !important
background white !important
.algolia-docsearch-suggestion--subcategory-column-text:after
content " > "
font-size 10px
line-height 14.4px
display inline-block
width 5px
margin -3px 3px 0
vertical-align middle
</style>

109
components/BackToTop.vue Normal file
View File

@ -0,0 +1,109 @@
<template>
<transition :name="transitionName">
<div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
<i class="iconfont reco-up"></i>
</div>
</transition>
</template>
<script>
export default {
name: 'BackToTop',
props: {
visibilityHeight: {
type: Number,
default: 400
},
backPosition: {
type: Number,
default: 0
},
customStyle: {
type: Object,
default: function() {
return {
right: '1rem',
bottom: '3rem',
width: '2.5rem',
height: '2.5rem',
'border-radius': '.25rem',
'line-height': '2.5rem',
backgroundColor: 'rgba(231, 234, 241,.5)'
}
}
},
transitionName: {
type: String,
default: 'fade'
}
},
data() {
return {
visible: false,
interval: null,
isMoving: false
}
},
mounted() {
window.addEventListener('scroll', this.handleScroll)
},
beforeDestroy() {
window.removeEventListener('scroll', this.handleScroll)
if (this.interval) {
clearInterval(this.interval)
}
},
methods: {
handleScroll() {
this.visible = window.pageYOffset > this.visibilityHeight
},
backToTop() {
if (this.isMoving) return
const start = window.pageYOffset
let i = 0
this.isMoving = true
this.interval = setInterval(() => {
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
if (next <= this.backPosition) {
window.scrollTo(0, this.backPosition)
clearInterval(this.interval)
this.isMoving = false
} else {
window.scrollTo(0, next)
}
i++
}, 16.7)
},
easeInOutQuad(t, b, c, d) {
if ((t /= d / 2) < 1) return c / 2 * t * t + b
return -c / 2 * (--t * (t - 2) - 1) + b
}
}
}
</script>
<style lang="stylus" scoped>
.back-to-ceiling
position: fixed;
display: inline-block;
text-align: center;
cursor: pointer;
i
font-size 1.6rem
color $accentColor
.back-to-ceiling:hover {
background: #d5dbe7;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity .5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0
}
.back-to-ceiling .Icon {
fill: #9aaabf;
background: none;
}
</style>

118
components/Background.vue Normal file
View File

@ -0,0 +1,118 @@
<template>
<div id="particles-oli-wrapper"></div>
</template>
<script>
export default {
mounted() {
const keyPage = this.$site.themeConfig.keyPage
let color = '#fb9b5f'
let lineColor = '#fb9b5f'
if (keyPage) {
color = keyPage.color || color
lineColor = keyPage.lineColor || lineColor
}
const script = document.createElement("script");
script.src = "https://cdn.jsdelivr.net/npm/particles.js@2.0.0/particles.min.js";
document.body.append(script);
script.onload = function() {
particlesJS("particles-oli-wrapper", {
particles: {
number: {
value: 40,
density: {
enable: true,
value_area: 800
}
},
color: {
value: color
},
shape: {
type: "circle",
stroke: {
width: 0,
color: "#000000"
},
polygon: {
nb_sides: 5
}
},
opacity: {
value: 0.3,
random: false,
anim: {
enable: false,
speed: 1,
opacity_min: 0.1,
sync: false
}
},
size: {
value: 20,
random: true,
anim: {
enable: false,
speed: 30,
size_min: 0.1,
sync: false
}
},
line_linked: {
enable: true,
distance: 250,
color: lineColor,
opacity: 0.2,
width: 1
},
move: {
enable: true,
speed: 3,
direction: "none",
random: true,
straight: false,
out_mode: "out",
bounce: true,
attract: {
enable: false,
rotateX: 600,
rotateY: 1200
}
}
},
interactivity: {
detect_on: "canvas",
events: {
onhover: {
enable: true,
mode: "grab"
},
onclick: {
enable: true,
mode: "push"
},
resize: true
},
modes: {
grab: {
distance: 100,
line_linked: {
opacity: 0.5
}
}
}
},
retina_detect: true
});
};
}
};
</script>
<style lang="stylus" scoped>
#particles-oli-wrapper {
height: 99vh;
}
</style>

152
components/Common.vue Normal file
View File

@ -0,0 +1,152 @@
<template>
<div
class="theme-container"
:class="pageClasses"
@touchstart="onTouchStart"
@touchend="onTouchEnd">
<Password v-if="!isHasKey"></Password>
<div v-else>
<Navbar
v-if="shouldShowNavbar"
@toggle-sidebar="toggleSidebar"/>
<div
class="sidebar-mask"
@click="toggleSidebar(false)"></div>
<Sidebar
:items="sidebarItems"
@toggle-sidebar="toggleSidebar">
<slot
name="sidebar-top"
slot="top"/>
<slot
name="sidebar-bottom"
slot="bottom"/>
</Sidebar>
<slot></slot>
<Valine :isComment="isComment"></Valine>
<BackToTop></BackToTop>
</div>
</div>
</template>
<script>
import Navbar from '@theme/components/Navbar.vue'
import Sidebar from '@theme/components/Sidebar.vue'
import { resolveSidebarItems } from '../util'
import Password from '@theme/components/Password'
import Valine from '@theme/components/Valine/'
import BackToTop from "@theme/components/BackToTop"
export default {
components: { Sidebar, Navbar, Password, Valine, BackToTop },
props: ['sidebar', 'isComment'],
data () {
return {
isSidebarOpen: false,
isHasKey: true,
nightMode: false
}
},
computed: {
shouldShowNavbar () {
const { themeConfig } = this.$site
const { frontmatter } = this.$page
if (
frontmatter.navbar === false
|| themeConfig.navbar === false) {
return false
}
return (
this.$title
|| themeConfig.logo
|| themeConfig.repo
|| themeConfig.nav
|| this.$themeLocaleConfig.nav
)
},
shouldShowSidebar () {
const { frontmatter } = this.$page
return (
this.sidebar !== false
&& !frontmatter.home
&& frontmatter.sidebar !== false
&& this.sidebarItems.length
)
},
sidebarItems () {
return resolveSidebarItems(
this.$page,
this.$page.regularPath,
this.$site,
this.$localePath
)
},
pageClasses () {
const userPageClass = this.$page.frontmatter.pageClass
return [
{
'no-navbar': !this.shouldShowNavbar,
'sidebar-open': this.isSidebarOpen,
'no-sidebar': !this.shouldShowSidebar,
'night-mode': this.nightMode
},
userPageClass
]
}
},
mounted () {
this.$router.afterEach(() => {
this.isSidebarOpen = false
})
if (localStorage.getItem('nightMode')) {
document.documentElement.style.background = "#000"
this.nightMode = true
}
const keyPage = this.$site.themeConfig.keyPage
if (!keyPage) {
this.isHasKey = true
return
}
const keys = keyPage.keys
this.isHasKey = keys && keys.indexOf(sessionStorage.getItem('key')) > -1
},
methods: {
toggleSidebar (to) {
this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
},
// side swipe
onTouchStart (e) {
this.touchStart = {
x: e.changedTouches[0].clientX,
y: e.changedTouches[0].clientY
}
},
onTouchEnd (e) {
const dx = e.changedTouches[0].clientX - this.touchStart.x
const dy = e.changedTouches[0].clientY - this.touchStart.y
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
if (dx > 0 && this.touchStart.x <= 80) {
this.toggleSidebar(true)
} else {
this.toggleSidebar(false)
}
}
}
}
}
</script>

181
components/DropdownLink.vue Normal file
View File

@ -0,0 +1,181 @@
<template>
<div
class="dropdown-wrapper"
:class="{ open }"
>
<a
class="dropdown-title"
@click="toggle"
>
<span class="title">
<i :class="`iconfont ${item.icon}`"></i>
{{ item.text }}
</span>
<span
class="arrow"
:class="open ? 'down' : 'right'"
></span>
</a>
<DropdownTransition>
<ul
class="nav-dropdown"
v-show="open"
>
<li
class="dropdown-item"
:key="subItem.link || index"
v-for="(subItem, index) in item.items"
>
<h4 v-if="subItem.type === 'links'">{{ subItem.text }}</h4>
<ul
class="dropdown-subitem-wrapper"
v-if="subItem.type === 'links'"
>
<li
class="dropdown-subitem"
:key="childSubItem.link"
v-for="childSubItem in subItem.items"
>
<NavLink :item="childSubItem"/>
</li>
</ul>
<NavLink
v-else
:item="subItem"
/>
</li>
</ul>
</DropdownTransition>
</div>
</template>
<script>
import NavLink from '@theme/components/NavLink.vue'
import DropdownTransition from '@theme/components/DropdownTransition.vue'
export default {
components: { NavLink, DropdownTransition },
data () {
return {
open: false
}
},
props: {
item: {
required: true
}
},
methods: {
toggle () {
this.open = !this.open
}
}
}
</script>
<style lang="stylus">
.dropdown-wrapper
cursor pointer
.dropdown-title
display block
&:hover
border-color transparent
.arrow
vertical-align middle
margin-top -1px
margin-left 0.4rem
.nav-dropdown
.dropdown-item
color inherit
line-height 1.7rem
h4
margin 0.45rem 0 0
border-top 1px solid #eee
padding 0.45rem 1.5rem 0 1.25rem
.dropdown-subitem-wrapper
padding 0
list-style none
.dropdown-subitem
font-size 0.9em
a
display block
line-height 1.7rem
position relative
border-bottom none
font-weight 400
margin-bottom 0
padding 0 1.5rem 0 1.25rem
&:hover
color $accentColor
&.router-link-active
color $accentColor
&::after
content ""
width 0
height 0
border-left 5px solid $accentColor
border-top 3px solid transparent
border-bottom 3px solid transparent
position absolute
top calc(50% - 2px)
left 9px
&:first-child h4
margin-top 0
padding-top 0
border-top 0
@media (max-width: $MQMobile)
.dropdown-wrapper
&.open .dropdown-title
margin-bottom 0.5rem
.nav-dropdown
transition height .1s ease-out
overflow hidden
.dropdown-item
h4
border-top 0
margin-top 0
padding-top 0
h4, & > a
font-size 15px
line-height 2rem
.dropdown-subitem
font-size 14px
padding-left 1rem
@media (min-width: $MQMobile)
.dropdown-wrapper
height 1.8rem
&:hover .nav-dropdown
// override the inline style.
display block !important
.dropdown-title .arrow
// make the arrow always down at desktop
border-left 4px solid transparent
border-right 4px solid transparent
border-top 6px solid $arrowBgColor
border-bottom 0
.nav-dropdown
display none
// Avoid height shaked by clicking
height auto !important
box-sizing border-box;
max-height calc(100vh - 2.7rem)
overflow-y auto
position absolute
top 100%
right 0
background-color #fff
padding 0.6rem 0
box-shadow: 0 4px 20px 0 rgba(0,0,0,.2);
text-align left
border-radius 0.25rem
white-space nowrap
margin 0
</style>

285
components/Home.vue Normal file
View File

@ -0,0 +1,285 @@
<template>
<div class="home" :class="recoShow?'reco-show': 'reco-hide'">
<div class="hero">
<img v-if="data.heroImage" :style="heroImageStyle" :src="$withBase(data.heroImage)" alt="hero">
<h1 v-if="data.isShowTitleInHome !== false">{{ data.heroText || $title || '午后南杂' }}</h1>
<p class="description">{{ data.tagline || $description || 'Welcome to your vuePress-theme-reco site' }}</p>
<p class="action" v-if="data.actionText && data.actionLink">
<NavLink class="action-button" :item="actionLink"/>
</p>
</div>
<div class="features" v-if="data.features && data.features.length">
<div v-for="(feature, index) in data.features" :key="index" class="feature">
<h2>{{ feature.title }}</h2>
<p>{{ feature.details }}</p>
</div>
</div>
<Content class="home-center" custom/>
<div class="footer">
<span>
<i class="iconfont reco-theme"></i>
<a target="blank" href="https://recoluan.gitlab.io/vuepress-theme-reco-doc/">VuePress-theme-reco</a>
</span>
<span>
<i class="iconfont reco-other"></i>
<a>{{ $site.themeConfig.author || $site.title }}</a>
</span>
<span>
<i class="iconfont reco-copyright"></i>
<a>{{ year }}</a>
</span>
<span>
<AccessNumber idVal="/"></AccessNumber>
</span>
</div>
</div>
</template>
<script>
import NavLink from "@theme/components/NavLink/";
import AccessNumber from '@theme/components/Valine/AccessNumber'
export default {
components: { NavLink, AccessNumber },
data () {
return {
recoShow: false
}
},
computed: {
year () {
return new Date().getFullYear()
},
data() {
return this.$page.frontmatter;
},
actionLink() {
return {
link: this.data.actionLink,
text: this.data.actionText
};
},
heroImageStyle () {
return this.data.heroImageStyle || {
maxHeight: '200px',
margin: '6rem auto 1.5rem'
}
}
},
mounted () {
this.recoShow = true
}
};
</script>
<style lang="stylus">
@require '../styles/loadMixin.styl'
.home {
padding: $navbarHeight 2rem 0;
max-width: 960px;
margin: 0px auto;
.hero {
text-align: center;
img {
background-color: $accentColor;
}
h1 {
font-size: 2.5rem;
}
h1, .description, .action {
margin: 1.8rem auto;
}
.description {
max-width: 35rem;
font-size: 1.6rem;
line-height: 1.3;
color: lighten($textColor, 20%);
}
.action-button {
display: inline-block;
font-size: 1.2rem;
color: #fff;
background-color: $accentColor;
padding: 0.6rem 1.2rem;
border-radius: 4px;
transition: background-color 0.1s ease;
box-sizing: border-box;
load-start()
&:hover {
background-color: lighten($accentColor, 10%);
}
}
}
.features {
border-top: 1px solid $borderColor;
padding: 1.2rem 0;
margin-top: 2.5rem;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
align-content: stretch;
justify-content: space-between;
}
.feature {
flex-grow: 1;
flex-basis: 30%;
max-width: 30%;
transition: all .5s
h2 {
font-size: 1.6rem;
font-weight: 500;
border-bottom: none;
padding-bottom: 0;
color: lighten($textColor, 10%);
}
p {
color: lighten($textColor, 20%);
}
&:hover {
transform scale(1.05)
}
}
.footer {
padding: 2.5rem;
border-top: 1px solid $borderColor;
text-align: center;
color: lighten($textColor, 25%);
load-start()
> span {
margin-left 1rem
> i {
margin-right .5rem
}
}
}
}
&.reco-hide {
.hero {
img {
load-start()
}
.h1 {
load-start()
}
.description {
load-start()
}
.action-button {
load-start()
}
}
.features {
load-start()
}
.home-center {
load-start()
}
.footer {
load-start()
}
}
&.reco-show {
.hero {
img {
load-end(0.08s)
}
.h1 {
load-end(0.16s)
}
.description {
load-end(0.24s)
}
.action-button {
load-end(0.32s)
}
}
.features {
load-end(0.40s)
}
.home-center {
load-end(0.48s)
}
.footer {
load-end(0.56s)
}
}
@media (max-width: $MQMobile) {
.home {
.features {
flex-direction: column;
}
.feature {
max-width: 100%;
padding: 0 2.5rem;
}
}
.footer {
text-align: left!important;
> span {
display block
margin-left 0
line-height 2rem
}
}
}
@media (max-width: $MQMobileNarrow) {
.home {
padding-left: 1.5rem;
padding-right: 1.5rem;
.hero {
img {
max-height: 210px;
margin: 2rem auto 1.2rem;
}
h1 {
font-size: 2rem;
}
h1, .description, .action {
margin: 1.2rem auto;
}
.description {
font-size: 1.2rem;
}
.action-button {
font-size: 1rem;
padding: 0.6rem 1.2rem;
}
}
.feature {
h2 {
font-size: 1.25rem;
}
}
}
}
</style>

View File

@ -12,7 +12,12 @@
:href="link"
class="nav-link external"
:target="isMailto(link) || isTel(link) ? null : '_blank'"
<<<<<<< HEAD:components/NavLink/index.vue
:rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'">
=======
:rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'"
>
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd:components/NavLink.vue
<i :class="`iconfont ${item.icon}`"></i>
{{ item.text }}
<!-- <OutboundLink/> -->
@ -20,7 +25,7 @@
</template>
<script>
import { isExternal, isMailto, isTel, ensureExt } from '../../util/'
import { isExternal, isMailto, isTel, ensureExt } from '../util'
export default {
props: {

View File

@ -29,9 +29,15 @@
</template>
<script>
<<<<<<< HEAD:components/NavLinks/index.vue
import DropdownLink from './components/DropdownLink/'
import { resolveNavLinkItem } from '../../util/'
import NavLink from '../NavLink/'
=======
import DropdownLink from '@theme/components/DropdownLink.vue'
import { resolveNavLinkItem } from '../util'
import NavLink from '@theme/components/NavLink.vue'
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd:components/NavLinks.vue
export default {
components: { NavLink, DropdownLink },
@ -69,6 +75,40 @@ export default {
}
return [...this.userNav, languageDropdown]
}
// blogConfig
const blogConfig = this.$themeConfig.blogConfig || {},
isHasCategory = this.userNav.some(item => {
return item.text === 'Category'
}),
isHasTag = this.userNav.some(item => {
return item.text === 'Tag'
})
if (!isHasCategory && blogConfig.hasOwnProperty('category')) {
const category = blogConfig.category
const $categories = this.$categories
this.userNav.splice( parseInt(category.location || 2) - 1, 0, {
items: $categories.list.map(item => {
item.link = item.path
item.text = item.name
return item
}),
text: category.text || '分类',
type: "links",
icon: "reco-category"
})
}
if (!isHasTag && blogConfig.hasOwnProperty('tag')) {
const tag = blogConfig.tag
this.userNav.splice(parseInt(tag.location || 3) - 1, 0, {
link: '/tag/',
text: tag.text || '标签',
type: "links",
icon: "reco-tag"
})
}
return this.userNav
},
@ -111,8 +151,6 @@ export default {
</script>
<style lang="stylus">
@import '../../styles/config.styl'
.nav-links
display inline-block
a
@ -121,7 +159,11 @@ export default {
&:hover, &.router-link-active
color $accentColor
.iconfont
<<<<<<< HEAD:components/NavLinks/index.vue
color $accentColor!important
=======
color $accentColor
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd:components/NavLinks.vue
.nav-item
position relative
display inline-block

125
components/Navbar.vue Normal file
View File

@ -0,0 +1,125 @@
<template>
<header class="navbar">
<SidebarButton @toggle-sidebar="$emit('toggle-sidebar')"/>
<router-link
:to="$localePath"
class="home-link">
<img
class="logo"
v-if="$site.themeConfig.logo"
:src="$withBase($site.themeConfig.logo)"
:alt="$siteTitle">
<span
ref="siteName"
class="site-name"
v-if="$siteTitle">{{ $siteTitle }}</span>
</router-link>
<div
class="links"
:style="linksWrapMaxWidth ? {
'max-width': linksWrapMaxWidth + 'px'
} : {}">
<Theme />
<AlgoliaSearchBox
v-if="isAlgoliaSearch"
:options="algolia"/>
<SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false"/>
<NavLinks class="can-hide"/>
</div>
</header>
</template>
<script>
import AlgoliaSearchBox from '@AlgoliaSearchBox'
import SearchBox from '@SearchBox'
import SidebarButton from '@theme/components/SidebarButton.vue'
import NavLinks from '@theme/components/NavLinks.vue'
import Theme from '@theme/components/Theme'
export default {
components: { SidebarButton, NavLinks, SearchBox, AlgoliaSearchBox, Theme },
data () {
return {
linksWrapMaxWidth: null
}
},
mounted () {
const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
const handleLinksWrapWidth = () => {
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
this.linksWrapMaxWidth = null
} else {
this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING
- (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
}
}
handleLinksWrapWidth()
window.addEventListener('resize', handleLinksWrapWidth, false)
},
computed: {
algolia () {
return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
},
isAlgoliaSearch () {
return this.algolia && this.algolia.apiKey && this.algolia.indexName
}
}
}
function css (el, property) {
// NOTE: Known bug, will return 'auto' if style value is 'auto'
const win = el.ownerDocument.defaultView
// null means not to return pseudo styles
return win.getComputedStyle(el, null)[property]
}
</script>
<style lang="stylus">
$navbar-vertical-padding = 0.7rem
$navbar-horizontal-padding = 1.5rem
.navbar
padding $navbar-vertical-padding $navbar-horizontal-padding
line-height $navbarHeight - 1.4rem
box-shadow 0 1px 6px 0 rgba(32,33,36,.28)
a, span, img
display inline-block
.logo
height $navbarHeight - 1.4rem
min-width $navbarHeight - 1.4rem
margin-right 0.8rem
vertical-align top
.site-name
font-size 1.2rem
font-weight 600
color $textColor
position relative
.links
padding-left 1.5rem
box-sizing border-box
background-color white
white-space nowrap
font-size 0.9rem
position absolute
right $navbar-horizontal-padding
top $navbar-vertical-padding
display flex
.search-box
flex: 0 0 auto
vertical-align top
@media (max-width: $MQMobile)
.navbar
padding-left 4rem
.can-hide
display none
.links
padding-left 1.5rem
</style>

View File

@ -1,177 +0,0 @@
<template>
<header class="navbar" id="navbarWrapper">
<SidebarButton @toggle-sidebar="$emit('toggle-sidebar')"/>
<router-link :to="$localePath" class="home-link">
<img
class="logo"
v-if="$site.themeConfig.logo"
:src="$withBase($site.themeConfig.logo)"
:alt="$siteTitle">
<span
ref="siteName"
class="site-name"
v-if="$siteTitle">{{ $siteTitle }}</span>
</router-link>
<div class="links" :style="{
'max-width': linksWrapMaxWidth + 'px'
}">
<Search class="side-search-wrapper"></Search>
<NavLinks class="can-hide"/>
</div>
</header>
</template>
<script>
import SidebarButton from "./components/SidebarButton/";
import Search from '../Search/'
import NavLinks from "../NavLinks/";
export default {
components: { SidebarButton, NavLinks, Search },
data() {
return {
linksWrapMaxWidth: null
};
},
mounted() {
const MOBILE_DESKTOP_BREAKPOINT = 719; // refer to config.styl
const NAVBAR_VERTICAL_PADDING =
parseInt(css(this.$el, "paddingLeft")) +
parseInt(css(this.$el, "paddingRight"));
const handleLinksWrapWidth = () => {
if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
this.linksWrapMaxWidth = null;
} else {
this.linksWrapMaxWidth =
this.$el.offsetWidth -
NAVBAR_VERTICAL_PADDING -
((this.$refs.siteName && this.$refs.siteName.offsetWidth) || 0);
}
};
handleLinksWrapWidth();
window.addEventListener("resize", handleLinksWrapWidth, false);
},
//
// updated () {
// this.$nextTick(() => {
// //
// let oldScrollY = 0
// let oldTransformHeight = 0
// window.addEventListener('scroll', (e) => {
// const newScrollY = window.scrollY
// //
// const scrollDirection = newScrollY - oldScrollY > 0 ? 'up' : 'down'
// // 使refdom
// const navbarWrapper = document.querySelector('#navbarWrapper')
// const height = navbarWrapper.offsetHeight == 58 ? 58 : 58
// const transformHeight = scrollDirection == 'up' ? height : 0
// if (oldTransformHeight != transformHeight) {
// navbarWrapper.style.top = `-${transformHeight}px`
// }
// oldScrollY = newScrollY
// oldTransformHeight = transformHeight
// })
// })
// },
computed: {
algolia() {
return (
this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
);
},
isAlgoliaSearch() {
return this.algolia && this.algolia.apiKey && this.algolia.indexName;
}
}
};
function css(el, property) {
// NOTE: Known bug, will return 'auto' if style value is 'auto'
const win = el.ownerDocument.defaultView;
// null means not to return pseudo styles
return win.getComputedStyle(el, null)[property];
}
</script>
<style lang="stylus">
@import '../../styles/config.styl';
$navbar-vertical-padding = 0.7rem;
$navbar-horizontal-padding = 1.5rem;
.navbar {
transition all .4s
padding: $navbar-vertical-padding $navbar-horizontal-padding;
position: relative;
-moz-user-select:none;/*火狐*/
-webkit-user-select:none;/*webkit浏览器*/
-ms-user-select:none;/*IE10*/
-khtml-user-select:none;/*早期浏览器*/
user-select:none;
a, span, img {
display: inline-block;
}
.home-link {
line-height $navbarHeight - 1.4rem
}
.logo {
height: $navbarHeight - 1.4rem;
min-width: $navbarHeight - 1.4rem;
margin-right: 0.8rem;
vertical-align: top;
}
.site-name {
font-size: 1.2rem;
color: $textColor;
position: relative;
}
.links {
padding-left: 1.5rem;
box-sizing: border-box;
background-color: $bgColor;
white-space: nowrap;
font-size: 0.9rem;
position: absolute;
right: $navbar-horizontal-padding;
top: $navbar-vertical-padding;
display: flex;
.nav-links {
flex: 1;
}
}
}
@media (max-width: $MQMobile) {
.navbar {
transition all .5s
.can-hide {
display: none;
}
.links {
padding-left: 1.5rem;
}
.side-search-wrapper {
display none
}
}
}
</style>

View File

@ -10,13 +10,21 @@
</div>
<div class="abstract" v-html="item.excerpt"></div>
<hr>
<<<<<<< HEAD:components/NoteAbstract/index.vue
<PageInfo :pageInfo="item" :currentTag="currentTag" @currentTag="getCurrentTag"></PageInfo>
=======
<PageInfo :pageInfo="item" :currentTag="currentTag"></PageInfo>
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd:components/NoteAbstract.vue
</div>
</div>
</template>
<script>
<<<<<<< HEAD:components/NoteAbstract/index.vue
import PageInfo from '../PageInfo/'
=======
import PageInfo from './PageInfo'
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd:components/NoteAbstract.vue
export default {
components: { PageInfo },
@ -26,18 +34,24 @@ export default {
const data = this.data
const currentPage = this.currentPage
return data.slice(currentPage * 10 - 10, currentPage * 10)
<<<<<<< HEAD:components/NoteAbstract/index.vue
}
},
methods: {
getCurrentTag (tag) {
this.$emit('currentTag', tag)
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd:components/NoteAbstract.vue
}
}
}
</script>
<style lang="stylus" scoped>
<<<<<<< HEAD:components/NoteAbstract/index.vue
@import '../../styles/config.styl'
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd:components/NoteAbstract.vue
.abstract-wrapper
width 100%

View File

@ -107,7 +107,10 @@ export default {
</script>
<style lang="stylus" scoped>
<<<<<<< HEAD:components/Pagation/index.vue
@import '../../styles/config.styl'
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd:components/Pagation.vue
.pagation
font-weight: 700;

284
components/Page.vue Normal file
View File

@ -0,0 +1,284 @@
<template>
<main class="page" :class="recoShow?'reco-show': 'reco-hide'">
<slot name="top"/>
<div class="page-title" v-if="!(isTimeLine)">
<h1>{{$page.title}}</h1>
<hr>
<PageInfo :pageInfo="$page"></PageInfo>
</div>
<Content/>
<TimeLine v-if="isTimeLine"></TimeLine>
<footer class="page-edit">
<div
class="edit-link"
v-if="editLink"
>
<a
:href="editLink"
target="_blank"
rel="noopener noreferrer"
>{{ editLinkText }}</a>
<OutboundLink/>
</div>
<div
class="last-updated"
v-if="lastUpdated"
>
<span class="prefix">{{ lastUpdatedText }}: </span>
<span class="time">{{ lastUpdated }}</span>
</div>
</footer>
<div class="page-nav" v-if="prev || next">
<p class="inner">
<span
v-if="prev"
class="prev"
>
<router-link
v-if="prev"
class="prev"
:to="prev.path"
>
{{ prev.title || prev.path }}
</router-link>
</span>
<span
v-if="next"
class="next"
>
<router-link
v-if="next"
:to="next.path"
>
{{ next.title || next.path }}
</router-link>
</span>
</p>
</div>
<slot name="bottom"/>
</main>
</template>
<script>
import PageInfo from '@theme/components/PageInfo'
import { resolvePage, outboundRE, endingSlashRE } from '../util'
import TimeLine from '@theme/components/TimeLine'
export default {
components: { PageInfo, TimeLine},
props: ['sidebarItems'],
data () {
return {
recoShow: false
}
},
computed: {
isTimeLine () {
return this.$page.frontmatter.isTimeLine
},
lastUpdated () {
return this.$page.lastUpdated
},
lastUpdatedText () {
if (typeof this.$themeLocaleConfig.lastUpdated === 'string') {
return this.$themeLocaleConfig.lastUpdated
}
if (typeof this.$site.themeConfig.lastUpdated === 'string') {
return this.$site.themeConfig.lastUpdated
}
return 'Last Updated'
},
prev () {
const prev = this.$page.frontmatter.prev
if (prev === false) {
return
} else if (prev) {
return resolvePage(this.$site.pages, prev, this.$route.path)
} else {
return resolvePrev(this.$page, this.sidebarItems)
}
},
next () {
const next = this.$page.frontmatter.next
if (next === false) {
return
} else if (next) {
return resolvePage(this.$site.pages, next, this.$route.path)
} else {
return resolveNext(this.$page, this.sidebarItems)
}
},
editLink () {
if (this.$page.frontmatter.editLink === false) {
return
}
const {
repo,
editLinks,
docsDir = '',
docsBranch = 'master',
docsRepo = repo
} = this.$site.themeConfig
if (docsRepo && editLinks && this.$page.relativePath) {
return this.createEditLink(repo, docsRepo, docsDir, docsBranch, this.$page.relativePath)
}
},
editLinkText () {
return (
this.$themeLocaleConfig.editLinkText
|| this.$site.themeConfig.editLinkText
|| `Edit this page`
)
}
},
mounted () {
this.recoShow = true
},
methods: {
createEditLink (repo, docsRepo, docsDir, docsBranch, path) {
const bitbucket = /bitbucket.org/
if (bitbucket.test(repo)) {
const base = outboundRE.test(docsRepo)
? docsRepo
: repo
return (
base.replace(endingSlashRE, '')
+ `/src`
+ `/${docsBranch}/`
+ (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
+ path
+ `?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
)
}
const base = outboundRE.test(docsRepo)
? docsRepo
: `https://github.com/${docsRepo}`
return (
base.replace(endingSlashRE, '')
+ `/edit`
+ `/${docsBranch}/`
+ (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
+ path
)
}
}
}
function resolvePrev (page, items) {
return find(page, items, -1)
}
function resolveNext (page, items) {
return find(page, items, 1)
}
function find (page, items, offset) {
const res = []
flatten(items, res)
for (let i = 0; i < res.length; i++) {
const cur = res[i]
if (cur.type === 'page' && cur.path === decodeURIComponent(page.path)) {
return res[i + offset]
}
}
}
function flatten (items, res) {
for (let i = 0, l = items.length; i < l; i++) {
if (items[i].type === 'group') {
flatten(items[i].children || [], res)
} else {
res.push(items[i])
}
}
}
</script>
<style lang="stylus">
@require '../styles/wrapper.styl'
@require '../styles/loadMixin.styl'
.page
padding-top 6rem
padding-bottom 2rem
display block
.page-title
max-width: 740px;
margin: 0 auto;
padding: 0rem 2.5rem;
.page-edit
@extend $wrapper
padding-top 1rem
padding-bottom 1rem
overflow auto
.edit-link
display inline-block
a
color lighten($textColor, 25%)
margin-right 0.25rem
.last-updated
float right
font-size 0.9em
.prefix
font-weight 500
color lighten($textColor, 25%)
.time
font-weight 400
color #aaa
.page-nav
@extend $wrapper
padding-top 1rem
padding-bottom 0
.inner
min-height 2rem
margin-top 0
border-top 1px solid $borderColor
padding-top 1rem
overflow auto // clear float
.next
float right
.reco-hide.page {
load-start()
}
.reco-show.page {
load-end(0.08s)
}
@media (max-width: $MQMobile)
.page-title
padding: 0 1rem;
.page-edit
.edit-link
margin-bottom .5rem
.last-updated
font-size .8em
float none
text-align left
</style>

68
components/PageInfo.vue Normal file
View File

@ -0,0 +1,68 @@
<template>
<div>
<i
class="iconfont reco-account"
v-if="pageInfo.frontmatter.author || $site.themeConfig.author || $site.title">
<span>{{ pageInfo.frontmatter.author || $site.themeConfig.author || $site.title }}</span>
</i>
<i class="iconfont reco-date" v-if="pageInfo.frontmatter.date"><span>{{ new Date(pageInfo.frontmatter.date).toLocaleDateString() }}</span></i>
<AccessNumber :idVal="pageInfo.path" :numStyle="numStyle"></AccessNumber>
<i class="iconfont reco-tag tags" v-if="pageInfo.frontmatter.tags">
<span
v-for="(subItem, subIndex) in pageInfo.frontmatter.tags"
:key="subIndex"
class="tag-item"
:class="{ 'active': currentTag == subItem }"
@click="goTags(subItem)">
{{subItem}}
</span>
</i>
</div>
</template>
<script>
import AccessNumber from './Valine/AccessNumber'
export default {
components: { AccessNumber },
props: ['pageInfo', 'currentTag'],
data () {
return {
numStyle: {
fontSize: '.9rem',
fontWeight: 'normal',
color: '#999'
}
}
},
methods: {
goTags (tag) {
window.location.href = `/tag/?tag=${tag}`
}
}
}
</script>
<style lang="stylus" scoped>
.iconfont
display inline-block
line-height 1.5rem
&:not(:last-child)
margin-right 1rem
span
margin-left .5rem
.tags
.tag-item
cursor: pointer;
&.active
color $accentColor
&:hover
color $accentColor
@media (max-width: $MQMobile)
.tags
display block
margin-left: 0!important;
</style>

283
components/Password.vue Normal file
View File

@ -0,0 +1,283 @@
<template>
<div class="password-shadow">
<Background></Background>
<h3 class="title">{{$site.title}}</h3>
<p class="description">{{$site.description}}</p>
<label class="inputBox" id="box">
<input
v-model="key"
type="password"
@keyup.enter="inter"
@focus="inputFocus"
@blur="inputBlur">
<span>{{warningText}}</span>
<button ref="passwordBtn" @click="inter">OK</button>
</label>
<div class="footer">
<span>
<i class="iconfont reco-theme"></i>
<a target="blank" href="https://www.npmjs.com/package/vuepress-theme-reco">vuePress-theme-reco</a>
</span>
<span>
<i class="iconfont reco-other"></i>
<a>{{ $site.themeConfig.author || $site.title }}</a>
</span>
<span>
<i class="iconfont reco-copyright"></i>
<a>{{ year }}</a>
</span>
</div>
</div>
</template>
<script>
import Background from '@theme/components/Background'
export default {
components: {Background},
name: 'Password',
data() {
return {
warningText: 'Konck! Knock!',
key: ''
}
},
computed: {
year () {
return new Date().getFullYear()
}
},
methods: {
inter () {
const keyVal = this.key.trim()
sessionStorage.setItem('key', keyVal)
if (!this.isHasKey()) {
this.warningText = 'Key Error'
return
}
const passwordBtn = this.$refs.passwordBtn
const width = document.getElementById('box').getClientRects()[0].width
passwordBtn.style.width = `${width - 2}px`
passwordBtn.style.opacity = 1
setTimeout(() => {
window.location.reload();
}, 800)
},
isHasKey () {
const keyPage = this.$site.themeConfig.keyPage
const keys = keyPage.keys
return keys && keys.indexOf(sessionStorage.getItem('key')) > -1
},
inputFocus () {
this.warningText = 'Input Your Key'
},
inputBlur () {
this.warningText = 'Konck! Knock!'
}
}
}
</script>
<style lang="stylus" scoped>
.password-shadow {
width 100vw;
height 100vh;
background #fff
position relative
.title {
position: absolute;
left 0
right 0
top 12%
margin auto
text-align center
color #666
font-size 30px
box-sizing: border-box;
padding: 0 10px;
}
.description {
position: absolute;
left 0
right 0
top 20%
margin auto
text-align center
color #999
font-size 22px
box-sizing: border-box;
padding: 0 10px;
}
.inputBox{
max-width:700px;
height: 100px;
background: $accentColor;
border-radius: 2px;
position: absolute;
left 0
right 0
top 36%
margin auto
padding-left 20px
box-sizing border-box
opacity 0.9
input{
width:600px;
height:100%;
border:none;
padding:0;
padding-left:5px;
color: #fff;
background: none;
outline: none;
position: absolute;
bottom:0;
opacity 0
font-size 50px
&:focus {
opacity 1
}
&:focus~span{
transform: translateY(-80px);
color $accentColor
font-size 30px
opacity:0.8;
}
&:focus~button{
opacity:1;
width:100px;
}
}
span{
width:200px;
height: 100%;
display: block;
position: absolute;
line-height:100px;
top:0;
left:20px;
color: #fff;
cursor: text;
transition: 0.5s;
transform-origin: left top;
font-size 30px
}
button{
width:0px;
height:98px;
border-radius: 2px;
position: absolute;
border 1px solid $accentColor
right:1px;
top 1px
border:0;
padding:0;
background: #fff;
color: $accentColor;
font-size:18px;
outline:none;
cursor: pointer;
opacity:0;
transition: 0.5s;
z-index: 1;
}
}
.footer {
position: absolute;
left 0
right 0
bottom 10%
margin auto
padding: 2.5rem;
text-align: center;
color: lighten($textColor, 25%);
> span {
margin-left 1rem
> i {
margin-right .5rem
}
}
}
@media (max-width: $MQMobile) {
.inputBox{
max-width:700px;
height: 60px;
background: $accentColor;
border-radius: 2px;
position: absolute;
left 0
right 0
top 43%
margin auto
padding-left 20px
box-sizing border-box
opacity 0.9
input{
width:600px;
height:100%;
border:none;
padding:0;
padding-left:5px;
color: #fff;
background: none;
outline: none;
position: absolute;
bottom:0;
opacity 0
font-size 30px
&:focus {
opacity 1
}
&:focus~span{
transform: translateY(-60px);
color $accentColor
font-size 20px
opacity:0.8;
}
&:focus~button{
opacity:1;
width:60px;
}
}
span{
width:200px;
height: 100%;
display: block;
position: absolute;
line-height:60px;
top:0;
left:20px;
color: #fff;
cursor: text;
transition: 0.5s;
transform-origin: left top;
font-size 20px
}
button{
width:0px;
height:58px;
border-radius: 2px;
position: absolute;
border 1px solid $accentColor
right:1px;
top 1px
border:0;
padding:0;
background: #fff;
color: $accentColor;
font-size:18px;
outline:none;
cursor: pointer;
opacity:0;
transition: 0.5s;
z-index: 1;
}
}
}
}
</style>

View File

@ -1,84 +0,0 @@
<template>
<transition name="sw-update-popup">
<div
v-if="enabled"
class="sw-update-popup">
{{message}}<br>
<button @click="reload">{{buttonText}}</button>
</div>
</transition>
</template>
<script>
export default {
props: {
updateEvent: {
type: Object,
default: null
}
},
computed: {
popupConfig () {
for (const config of [this.$themeLocaleConfig, this.$site.themeConfig]) {
const sw = config.serviceWorker
if (sw && sw.updatePopup) {
return typeof sw.updatePopup === 'object' ? sw.updatePopup : {}
}
}
return null
},
enabled () {
return Boolean(this.popupConfig && this.updateEvent)
},
message () {
const c = this.popupConfig
return (c && c.message) || 'New content is available.'
},
buttonText () {
const c = this.popupConfig
return (c && c.buttonText) || 'Refresh'
}
},
methods: {
reload () {
if (this.updateEvent) {
this.updateEvent.skipWaiting().then(() => {
location.reload(true)
})
this.updateEvent = null
}
}
}
}
</script>
<style lang="stylus">
@import '../../styles/config.styl'
.sw-update-popup
position fixed
right 1em
bottom 1em
padding 1em
border 1px solid $accentColor
border-radius 3px
background-color: $bgColor;
box-shadow 0 4px 16px rgba(0, 0, 0, 0.5)
text-align center
button
margin-top 0.5em
padding 0.25em 2em
.sw-update-popup-enter-active, .sw-update-popup-leave-active
transition opacity 0.3s, transform 0.3s
.sw-update-popup-enter, .sw-update-popup-leave-to
opacity 0
transform translate(0, 50%) scale(0.5)
</style>

59
components/Sidebar.vue Normal file
View File

@ -0,0 +1,59 @@
<template>
<aside class="sidebar">
<NavLinks/>
<slot name="top"/>
<SidebarLinks :depth="0" :items="items"/>
<slot name="bottom"/>
</aside>
</template>
<script>
import SidebarLinks from '@theme/components/SidebarLinks.vue'
import NavLinks from '@theme/components/NavLinks.vue'
export default {
name: 'Sidebar',
components: { SidebarLinks, NavLinks },
props: ['items']
}
</script>
<style lang="stylus">
.sidebar
ul
padding 0
margin 0
list-style-type none
a
display inline-block
.nav-links
display none
border-bottom 1px solid $borderColor
padding 0.5rem 0 0.75rem 0
a
font-weight 600
.nav-item, .repo-link
display block
line-height 1.25rem
font-size 1.1em
padding 0.5rem 0 0.5rem 1.5rem
& > .sidebar-links
padding 1.5rem 0
& > li > a.sidebar-link
font-size 1.1em
line-height 1.7
font-weight bold
& > li:not(:first-child)
margin-top .75rem
@media (max-width: $MQMobile)
.sidebar
.nav-links
display block
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
top calc(1rem - 2px)
& > .sidebar-links
padding 1rem 0
</style>

View File

@ -1,124 +0,0 @@
<template>
<div class="sidebar">
<Search class="side-search-wrapper"></Search>
<NavLinks/>
<slot name="top"/>
<ul class="sidebar-links" v-if="items.length">
<li v-for="(item, i) in items" :key="i">
<SidebarGroup
v-if="item.type === 'group'"
:item="item"
:first="i === 0"
:open="i === openGroupIndex"
:collapsable="item.collapsable || item.collapsible"
@toggle="toggleGroup(i)"/>
<SidebarLink v-else :item="item"/>
</li>
</ul>
<slot name="bottom"/>
</div>
</template>
<script>
import SidebarGroup from '../SidebarGroup/'
import SidebarLink from '../SidebarLink/'
import NavLinks from '../NavLinks/'
import Search from '../Search/'
import { isActive } from '../../util/'
export default {
components: { SidebarGroup, SidebarLink, NavLinks, Search },
props: ['items'],
data () {
return {
openGroupIndex: 0
}
},
created () {
this.refreshIndex()
},
watch: {
'$route' () {
this.refreshIndex()
}
},
methods: {
refreshIndex () {
const index = resolveOpenGroupIndex(
this.$route,
this.items
)
if (index > -1) {
this.openGroupIndex = index
}
},
toggleGroup (index) {
this.openGroupIndex = index === this.openGroupIndex ? -1 : index
},
isActive (page) {
return isActive(this.$route, page.path)
}
}
}
function resolveOpenGroupIndex (route, items) {
for (let i = 0; i < items.length; i++) {
const item = items[i]
if (item.type === 'group' && item.children.some(c => isActive(route, c.path))) {
return i
}
}
return -1
}
</script>
<style lang="stylus">
@import '../../styles/config.styl'
.sidebar
-moz-user-select:none;/*火狐*/
-webkit-user-select:none;/*webkit浏览器*/
-ms-user-select:none;/*IE10*/
-khtml-user-select:none;/*早期浏览器*/
user-select:none;
ul
padding 0
margin 0
list-style-type none
a
display inline-block
.nav-links
display none
border-bottom 1px solid $borderColor
padding 0.5rem 0 0.75rem 0
a
font-weight 600
.nav-item, .repo-link
display block
line-height 1.25rem
font-size 1.1em
padding 0.5rem 0 0.5rem 1.5rem
.sidebar-links
padding 1.5rem 0
.side-search-wrapper
padding: 0.5rem 0 0.5rem 1.5rem;
display none
@media (max-width: $MQMobile)
.sidebar
.nav-links
display block
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
top calc(1rem - 2px)
.sidebar-links
padding 1rem 0
.side-search-wrapper
display block
</style>

View File

@ -0,0 +1,27 @@
<template>
<div class="sidebar-button" @click="$emit('toggle-sidebar')">
<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=""></path>
</svg>
</div>
</template>
<style lang="stylus">
.sidebar-button
cursor pointer
display none
width 1.25rem
height 1.25rem
position absolute
padding 0.6rem
top 0.6rem
left 1rem
.icon
display block
width 1.25rem
height 1.25rem
@media (max-width: $MQMobile)
.sidebar-button
display block
</style>

129
components/SidebarGroup.vue Normal file
View File

@ -0,0 +1,129 @@
<template>
<section
class="sidebar-group"
:class="[
{
collapsable,
'is-sub-group': depth !== 0
},
`depth-${depth}`
]"
>
<router-link
v-if="item.path"
class="sidebar-heading clickable"
:class="{
open,
'active': isActive($route, item.path)
}"
:to="item.path"
@click.native="$emit('toggle')"
>
<span>{{ item.title }}</span>
<span
class="arrow"
v-if="collapsable"
:class="open ? 'down' : 'right'">
</span>
</router-link>
<p
v-else
class="sidebar-heading"
:class="{ open }"
@click="$emit('toggle')"
>
<span>{{ item.title }}</span>
<span
class="arrow"
v-if="collapsable"
:class="open ? 'down' : 'right'">
</span>
</p>
<DropdownTransition>
<SidebarLinks
class="sidebar-group-items"
:items="item.children"
v-if="open || !collapsable"
:sidebarDepth="item.sidebarDepth"
:depth="depth + 1"
/>
</DropdownTransition>
</section>
</template>
<script>
import { isActive } from '../util'
import DropdownTransition from '@theme/components/DropdownTransition.vue'
export default {
name: 'SidebarGroup',
props: ['item', 'open', 'collapsable', 'depth'],
components: { DropdownTransition },
// ref: https://vuejs.org/v2/guide/components-edge-cases.html#Circular-References-Between-Components
beforeCreate () {
this.$options.components.SidebarLinks = require('./SidebarLinks.vue').default
},
methods: { isActive }
}
</script>
<style lang="stylus">
.sidebar-group
.sidebar-group
padding-left 0.5em
&:not(.collapsable)
.sidebar-heading:not(.clickable)
cursor auto
color inherit
// refine styles of nested sidebar groups
&.is-sub-group
padding-left 0
& > .sidebar-heading
font-size 0.95em
line-height 1.4
font-weight normal
padding-left 2rem
&:not(.clickable)
opacity 0.5
& > .sidebar-group-items
padding-left 1rem
& > li > .sidebar-link
font-size: 0.95em;
border-left none
&.depth-2
& > .sidebar-heading
border-left none
.sidebar-heading
color $textColor
transition color .15s ease
cursor pointer
font-size 1.1em
font-weight bold
// text-transform uppercase
padding 0.35rem 1.5rem 0.35rem 1.25rem
width 100%
box-sizing border-box
margin 0
border-left 0.25rem solid transparent
&.open, &:hover
color inherit
.arrow
position relative
top -0.12em
left 0.5em
&.clickable
&.active
font-weight 600
color $accentColor
border-left-color $accentColor
&:hover
color $accentColor
.sidebar-group-items
transition height .1s ease-out
font-size 0.95em
overflow hidden
</style>

View File

@ -1,76 +0,0 @@
<template>
<div
class="sidebar-group"
:class="{ first, collapsable }">
<p
class="sidebar-heading"
:class="{ open }"
@click="$emit('toggle')">
<span>{{ item.title }}</span>
<span
class="arrow"
v-if="collapsable"
:class="open ? 'down' : 'right'">
</span>
</p>
<DropdownTransition>
<ul
ref="items"
class="sidebar-group-items"
v-if="open || !collapsable">
<li
v-for="(child, index) in item.children"
:key="index">
<SidebarLink :item="child"/>
</li>
</ul>
</DropdownTransition>
</div>
</template>
<script>
import SidebarLink from '../SidebarLink/'
import DropdownTransition from '../DropdownTransition/'
export default {
name: 'SidebarGroup',
props: ['item', 'first', 'open', 'collapsable'],
components: { SidebarLink, DropdownTransition }
}
</script>
<style lang="stylus">
.sidebar-group
&:not(.first)
margin-top 1em
.sidebar-group
padding-left 0.5em
&:not(.collapsable)
.sidebar-heading
cursor auto
color inherit
.sidebar-heading
color #999
transition color .15s ease
cursor pointer
font-size 1.1em
font-weight bold
// text-transform uppercase
padding 0 1.5rem
margin-top 0
margin-bottom 0.5rem
&.open, &:hover
color inherit
.arrow
position relative
top -0.12em
left 0.5em
&:.open .arrow
top -0.18em
.sidebar-group-items
transition height .1s ease-out
overflow hidden
</style>

View File

@ -1,12 +1,25 @@
<script>
import { isActive, hashRE, groupHeaders } from '../../util/'
import { isActive, hashRE, groupHeaders } from '../util'
export default {
functional: true,
props: ['item'],
props: ['item', 'sidebarDepth'],
render (h, { parent: { $page, $site, $route }, props: { item }}) {
render (h,
{
parent: {
$page,
$site,
$route,
$themeConfig,
$themeLocaleConfig
},
props: {
item,
sidebarDepth
}
}) {
// use custom active class matching logic
// due to edge case of paths ending with / + hash
const selfActive = isActive($route, item.path)
@ -16,11 +29,17 @@ export default {
? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug))
: selfActive
const link = renderLink(h, item.path, item.title || item.path, active)
const configDepth = $page.frontmatter.sidebarDepth != null
? $page.frontmatter.sidebarDepth
: $site.themeConfig.sidebarDepth
const configDepth = $page.frontmatter.sidebarDepth
|| sidebarDepth
|| $themeLocaleConfig.sidebarDepth
|| $themeConfig.sidebarDepth
const maxDepth = configDepth == null ? 1 : configDepth
const displayAllHeaders = !!$site.themeConfig.displayAllHeaders
const displayAllHeaders = $themeLocaleConfig.displayAllHeaders
|| $themeConfig.displayAllHeaders
if (item.type === 'auto') {
return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
} else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) {
@ -59,13 +78,12 @@ function renderChildren (h, children, path, route, maxDepth, depth = 1) {
</script>
<style lang="stylus">
@import '../../styles/config.styl'
.sidebar .sidebar-sub-headers
padding-left 1rem
font-size 0.95em
a.sidebar-link
font-size 1em
font-weight 400
display inline-block
color $textColor

View File

@ -0,0 +1,86 @@
<template>
<ul
class="sidebar-links"
v-if="items.length"
>
<li v-for="(item, i) in items" :key="i">
<SidebarGroup
v-if="item.type === 'group'"
:item="item"
:open="i === openGroupIndex"
:collapsable="item.collapsable || item.collapsible"
:depth="depth"
@toggle="toggleGroup(i)"
/>
<SidebarLink
v-else
:sidebarDepth="sidebarDepth"
:item="item"
/>
</li>
</ul>
</template>
<script>
import SidebarGroup from '@theme/components/SidebarGroup.vue'
import SidebarLink from '@theme/components/SidebarLink.vue'
import { isActive } from '../util'
export default {
name: 'SidebarLinks',
components: { SidebarGroup, SidebarLink },
props: [
'items',
'depth', // depth of current sidebar links
'sidebarDepth' // depth of headers to be extracted
],
data () {
return {
openGroupIndex: 0
}
},
created () {
this.refreshIndex()
},
watch: {
'$route' () {
this.refreshIndex()
}
},
methods: {
refreshIndex () {
const index = resolveOpenGroupIndex(
this.$route,
this.items
)
if (index > -1) {
this.openGroupIndex = index
}
},
toggleGroup (index) {
this.openGroupIndex = index === this.openGroupIndex ? -1 : index
},
isActive (page) {
return isActive(this.$route, page.regularPath)
}
}
}
function resolveOpenGroupIndex (route, items) {
for (let i = 0; i < items.length; i++) {
const item = items[i]
if (item.type === 'group' && item.children.some(c => c.type === 'page' && isActive(route, c.path))) {
return i
}
}
return -1
}
</script>

124
components/Theme/ThemeOptions.vue Executable file
View File

@ -0,0 +1,124 @@
<template>
<div class="theme-options">
<ul v-if="reco.hasThemes" class="color-theme-options">
<li>
<a href="#" class="default-theme" @click.prevent="setTheme()"></a>
</li>
<li v-for="color in reco.themes" :key="color">
<a href="#" :class="`${color}-theme`" :style="{background: colors[color]}" @click.prevent="setTheme(color)"></a>
</li>
</ul>
<div v-if="!reco.disableDarkTheme" class="dark-theme-options toggle-option">
<label for="dark-theme-toggle">Enable Dark Theme?</label>
<input id="dark-theme-toggle" v-model="darkTheme" type="checkbox" @change="toggleDarkTheme" />
</div>
</div>
</template>
<script>
import recoConfig from './recoConfig.js';
export default {
name: 'ThemeOptions',
mixins: [recoConfig],
data() {
return {
darkTheme: 'false'
};
},
mounted() {
const theme = localStorage.getItem('reco-theme')
const night = localStorage.getItem('reco-night')
const classes = document.body.classList;
this.darkTheme = night === 'true' ? true : false
if (night === 'true') classes.add(`reco-theme-night`)
if (theme) this.setTheme(theme)
},
methods: {
toggleDarkTheme() {
console.log(123, this.darkTheme)
localStorage.setItem('reco-night', this.darkTheme)
console.log(456, localStorage.getItem('reco-night'))
const classes = document.body.classList;
if (this.darkTheme) {
const oldColor = [...classes]
classes.value = ''
classes.add(`reco-theme-night`)
oldColor.forEach(item => {
classes.add(item)
})
}
else {
classes.remove(`reco-theme-night`)
}
},
setTheme(theme, moveClass = true) {
const colorThemes = this.reco.themes;
const classes = document.body.classList;
const themes = colorThemes.map(colorTheme => `reco-theme-${colorTheme}`);
if (!theme) {
if (moveClass) localStorage.removeItem('reco-theme');
classes.remove(...themes);
return
}
classes.remove(...themes.filter(t => t !== `reco-theme-${theme}`));
if (moveClass) {
classes.add(`reco-theme-${theme}`);
localStorage.setItem('reco-theme', theme);
} else {
localStorage.removeItem('reco-theme')
classes.remove(`reco-theme-${theme}`);
}
}
},
};
</script>
<style lang="stylus">
.color-theme-options {
display: flex;
justify-content: space-around;
li {
width: 33%;
text-align: center;
a {
width: 15px;
height: 15px;
border-radius: 2px;
&.default-theme {
background-color: $accentColor;
}
&.blue-theme {
background-color: $blueAccentColor;
}
&.red-theme {
background-color: $redAccentColor;
}
}
}
}
.toggle-option {
display: flex;
justify-content: space-between;
align-items: center;
label {
padding-right: 0.25em;
}
}
</style>

140
components/Theme/index.vue Executable file
View File

@ -0,0 +1,140 @@
<template>
<div v-if="showSettings" v-click-outside="hideMenu" class="color-picker">
<a class="color-button" href="#" @click.prevent="showMenu = !showMenu">
<i class="iconfont reco-color"></i>
</a>
<transition name="menu-transition" mode="out-in">
<div v-show="showMenu" class="color-picker-menu">
<ThemeOptions />
</div>
</transition>
</div>
</template>
<script>
import ClickOutside from 'vue-click-outside';
import ThemeOptions from './ThemeOptions.vue';
import recoConfig from './recoConfig.js';
export default {
name: 'UserSettings',
directives: {
'click-outside': ClickOutside,
},
components: {
ThemeOptions
},
mixins: [recoConfig],
data() {
return {
showMenu: false,
};
},
computed: {
showSettings() {
const { reco } = this;
return reco.hasThemes || reco.disableDarkTheme !== true || reco.disableThemeIgnore !== true;
},
},
methods: {
hideMenu() {
this.showMenu = false;
},
},
};
</script>
<style lang="stylus">
.color-picker {
position: relative;
margin-right: 1em;
.color-button {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
.iconfont {
font-size 1.4rem
color: $accentColor
}
.settings-icon {
width: 18px;
}
}
.color-picker-menu {
background-color: #fff;
position: absolute;
top: 40px;
left: 50%;
min-width: 100px;
margin: 0;
padding: 1em;
border: 1px solid $borderColor;
border-radius: 4px;
transform: translateX(-50%);
z-index: 150;
&::before {
content: '';
position: absolute;
top: -7px;
left: 50%;
border-style: solid;
border-color: transparent transparent $borderColor;
border-width: 0 7px 7px;
transform: translateX(-50%);
}
&.menu-transition-enter-active,
&.menu-transition-leave-active {
transition: all 0.25s ease-in-out;
}
&.menu-transition-enter,
&.menu-transition-leave-to {
top: 50px;
opacity: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
}
}
.reco-theme-dark {
.color-picker-menu {
background-color: $darkPrimaryBg;
border-color: $darkBorderColor;
&::before {
border-bottom-color: $darkBorderColor;
}
}
}
@media (max-width: $MQMobile) {
.color-picker {
margin-right: 0;
.color-picker-menu {
left: calc(50% - 35px);
&::before {
left: calc(50% + 35px);
}
}
}
}
</style>

22
components/Theme/recoConfig.js Executable file
View File

@ -0,0 +1,22 @@
export default {
data() {
return {
reco: {},
colors: {
blue: '#2196f3',
red: '#f26d6d',
green: '#3eaf7c',
orange: '#fb9b5f'
}
};
},
mounted() {
this.reco = {
themes: ['blue', 'red', 'green', 'orange'],
disableDarkTheme: false
};
this.reco.hasThemes = this.$site.themeConfig.themePicker || true
},
};

189
components/TimeLine.vue Normal file
View File

@ -0,0 +1,189 @@
<template>
<div>
<ul class="timeline-wrapper">
<li class="desc">Yesterday Once More!</li>
<li v-for="(item, index) in formatPagesArr" :key="index">
<h3 class="year">{{item.year}}</h3>
<ul class="year-wrapper">
<li v-for="(subItem, subIndex) in item.data" :key="subIndex">
<span class="date">{{dateFormat(new Date(subItem.frontmatter.date))}}</span>
<span class="title" @click="go(subItem.path)">{{subItem.title}}</span>
</li>
</ul>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'TimeLine',
data () {
return {
pages: [],
tags: [],
currentTag: '',
currentPage: 1,
formatPages: {},
formatPagesArr: []
}
},
props: {
tag: {
type: String,
default: ''
}
},
computed: {
trueCurrentTag () {
return this.currentTag
}
},
created () {
this.getPages()
},
methods: {
//
getPages (tag) {
let pages = this.$site.pages
pages = pages.filter(item => {
const { home, isTimeLine, date } = item.frontmatter
return !(home == true || isTimeLine == true || date === undefined)
})
// reverse()
this.pages = pages.length == 0 ? [] : pages
for (let i = 0, length = pages.length; i < length; i++) {
const page = pages[i]
const pageDateYear = this.dateFormat(page.frontmatter.date, 'year')
if (this.formatPages[pageDateYear]) this.formatPages[pageDateYear].push(page)
else {
this.formatPages[pageDateYear] = [page]
}
}
for(let key in this.formatPages) {
this.formatPagesArr.unshift({
year: key,
data: this.formatPages[key].sort((a, b) => {
return this._getTimeNum(b) - this._getTimeNum(a)
})
})
}
},
//
dateFormat (date, type) {
const dateObj = new Date(date)
const year = dateObj.getFullYear()
const mon = dateObj.getMonth() + 1
const day = dateObj.getDate()
if (type == 'year') return year
else return `${mon}-${day}`
},
//
go (url) {
this.$router.push({path: url})
},
//
_getTimeNum (date) {
return parseInt(new Date(date.frontmatter.date).getTime())
}
}
}
</script>
<style lang="stylus" scoped>
@require '../styles/wrapper.styl'
.timeline-wrapper
box-sizing border-box
max-width: 740px;
margin: 0 auto;
position relative
list-style none
&::after {
content: " ";
position: absolute;
top: 14px;
left: 0;
margin-left: -2px;
width: 4px;
height: 100%;
background: #f5f5f5;
}
.desc, .year {
position: relative;
color #666
font-size 16px
&:before {
content: " ";
position: absolute;
z-index 2;
left: -19px;
top: 50%;
margin-left: -4px;
margin-top: -4px;
width: 8px;
height: 8px;
background: #ddd;
border-radius: 50%;
}
}
.year {
margin: 80px 0 0px;
color #555
font-weight: 700;
font-size 26px
}
.year-wrapper {
padding-left 0!important
li {
display flex
padding 30px 0 10px
list-style none
border-bottom: 1px dashed #ccc;
position relative
&:hover {
.date {
color $accentColor
&::before {
background $accentColor
}
}
.title {
color $accentColor
}
}
.date {
width 40px
line-height 30px
color: #555;
font-size 12px
&::before {
content: " ";
position: absolute;
left: -19px;
top: 41px;
width: 6px;
height: 6px;
margin-left: -4px;
background: #ddd;
border-radius: 50%;
border: 1px solid #fff;
z-index 2
}
}
.title {
line-height 30px
color: #555;
font-size 16px
cursor pointer
}
}
}
@media (max-width: $MQMobile)
.timeline-wrapper
margin: 0 1.2rem;
</style>

View File

@ -1,5 +1,9 @@
<template>
<<<<<<< HEAD
<div class="valine-wrapper" v-show="isComment">
=======
<div class="valine-wrapper" v-show="isShowComment">
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
<div id="valine"></div>
</div>
</template>
@ -8,12 +12,21 @@
export default {
<<<<<<< HEAD
props: ['valineRefresh'],
computed: {
//
isComment () {
const frontmatter = this.$page.frontmatter
return frontmatter.isComment == false || frontmatter.home == true ? false : true
=======
props: ['isComment'],
computed: {
//
isShowComment () {
const frontmatter = this.$page.frontmatter
return this.isComment == false || frontmatter.isComment == false || frontmatter.home == true ? false : true
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
}
},
mounted: function(){
@ -28,7 +41,10 @@ export default {
if (typeof window !== 'undefined') {
this.window = window
window.AV = AV
<<<<<<< HEAD
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
}
new Valine({
@ -41,7 +57,10 @@ export default {
path: window.location.pathname,
placeholder: 'just go go'
});
<<<<<<< HEAD
this.valineRefresh = false
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
}
}
},
@ -55,6 +74,7 @@ export default {
}, 300)
}
<<<<<<< HEAD
},
'valineRefresh' (val) {
if (val) {
@ -62,12 +82,15 @@ export default {
this.createValine()
}, 300)
}
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
}
},
};
</script>
<style lang="stylus" scoped>
<<<<<<< HEAD
@import '../../styles/config.styl'
.valine-wrapper
@ -78,4 +101,27 @@ export default {
@media (max-width: $MQMobile)
.valine-wrapper
padding 1rem
=======
.theme-container.no-sidebar
.valine-wrapper
padding-left 0
.valine-wrapper
background-color $bgColor
padding-left: 20rem;
#valine
padding 2rem
max-width: 740px;
margin: 0 auto;
@media (max-width: $MQNarrow)
.theme-container.no-sidebar
.valine-wrapper
padding-left 0
.valine-wrapper
padding-left: 16.4rem;
@media (max-width: $MQMobile)
.valine-wrapper
padding-left: 0;
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
</style>

View File

@ -1,10 +1,19 @@
@font-face {font-family: "iconfont";
<<<<<<< HEAD
src: url('iconfont.eot?t=1548606483811'); /* IE9 */
src: url('iconfont.eot?t=1548606483811#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('iconfont.woff?t=1548606483811') format('woff'),
url('iconfont.ttf?t=1548606483811') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1548606483811#iconfont') format('svg'); /* iOS 4.1- */
=======
src: url('iconfont.eot?t=1555230336940'); /* IE9 */
src: url('iconfont.eot?t=1555230336940#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAA3kAAsAAAAAGEAAAA2VAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCGPAqeSJg+ATYCJANgCzIABCAFhG0HgWQbPBQzo8LGAQBRPg/Z/+lAC7nKrp+BQ65GtdFY67Wu2OkOR2Pn6WsdTQIS7RWsH8yaDghWQvqrhu4OgLBjp/bu8FcELrA+Bw+fzvKPZiQ2wQEQVWgfIHbEJQFo9yBJlS4v9nvXrAjCRqiSrOoRKLT30uwPLM12Mim0OSAz2/ncXu8Sv0ucDzGVt2NR3SrOAq8brPCjUjM7eR1bBDac0/6hKuEB/xs/X9/fEG3z7v7FigAxGp80ChMUE6MKXeHMBbGEZbOObkAAytAmO3IZcDMvLfbgtoOk1lcDBPPN/ap6/M04TEOT12nxtq/bDjn8ULEIoVLChqlEKjQakUZIkUrOWMS2mPUrLpJQD9qI2BgCcChKZUTr58+f1ggFYwXKTA5Ot0aZEFSBtcAKMAILKkdsQMfSVmoH1tuPF7+pKSzQ0CVsU93HPmWtg88/y2W5GCyzZLsjwNtCIIHKgAItHUwWUaRnKlvOCVVW+EBFitP5Oj6+yREUkVBUWeXV1khrg0wwz+q8/Py1v37+szw3VPNrC/iqVluwaEFF7rcyVX2qvn9IEMfCwyaAwkAniksYjQgpgvP2Dy9EEhNBDIQBlfYARGnkpMBHOiMBvumMOPi2MyzwHWd44AdYilAQLIMoAowCSgBjABUFRgcqC0wUqDwwLlAtYMJAtYHRgBqBpVvUGvLpRYPAMm40ARgJNA8YB2g1nBGCvHxnJCF/rTNM+PWTINiDFKhGDIA0FqgOtKWlToAxsMXM9sDovzSntzqiIcBJTSw0YjRwyrN2gLGZOBHzvIAoFhLhhJRtR5CorDoF3yp02LbLep6wOW+ZcAXbjdte1LNjcutlw57QyxYNR3VTt5pajtK5wy+s5/ZT85nmDJCBMuO88w8gyLGfgswzkHka/UR2/roRde5nStDGt1qs9sMXf6QHb/4eiFh12bqCA84l86L++R0GmQoLjW+dLnWKQKGmcurMNfD6JWcV7SsU9jT+dXpVgg71XJEGss8zdj3Pi9h/mhCw8iw38sKL5Kmsd8HeTZPTw7mtKFoUVvR77/Dq/E34itrBFNLTyiqK/g88WqbOhQ/5atYPTgXD1EO32lArPvyMo6OgiOBo47Y8eZP+tfdlVtcAm4kNK1/NMGnjIRNB84x9tCrvlsFf8Xo69AX+9nVL/NHq7F2i/A+d72mH9ir3GXoJhRhezevHl5pOaHQoaF8GqZcQmPmreo4kbZcgvPv+8WoxbdvjQ+lLn1e6VcxewqzM9AK9ZPphNXvpCs+l1X+BKM8AGZ/pefjVgFnGjOwrBQ3mIj9hggo5h0TxP1VdfQIu1T1a6v8K9kr1eDm+RiV+TbS+Czc4fMGz5xxKKwO95rSV9X2LnPcv8+6SksvfEZiGNZWQYJbTdSxS63/Cq66zvrv0zFv0PWbVN3j/PTKM9v5yLluX7AuT/s4Mbcp/374rzKxc93kH2PU8oIlobfQDDuXSkoSdC9LS5szyxRx0eBkK60o+PriUaEiFZV0g1ROuEmBmXbmXfKfd92I1T3pWufIgeWvmIsv8EgRf+sD6T/uSddm5ONBd4gOevrpRb9CY2H9YMLPSLJxd5RTPr7mRPKz4PXCxzECze6sTGHFzbFGTJsG1lb46QB9vxWA1g+RM2ni8NNiXN0OFNy7q9mURfkNDVq9IzULA7H75i+5aYVdwDXKUDZvavAl7o8uYKqC6PwVqPs8TlNn7op/1EQBU/UBp6cCnSszjT4l9rW1SEsHV9byuUcSeoJg2gUAVHx43OVsQtiyuXQNnNuyTQb0Lbq4K9r6w/zHH9VtL0oUbycmu400m5FaxXHHzUJbf/6ZD3tLakzvJ1gXsTmxd8a24dXVFt62KonvBmzSJsPwQOVn44IIkyQgYeQQtDE++6BqSkQraEAHcrReSoDbXgn13Pc5D7r4gCFdYfppjP05KwhLFXXm2jeIQ2Q8TlNnmjCQcSAFYufNFLl2QcKBXWJdZhjuzfr1dw8oCxaFrZ2z4OQtXymmC7KyFp65stM1WnbHIkC+yvHrV01JXZs5TXKMsEtmtJFZG7CB2NB+wXROxmseuuWLnqH5qKBORu2J3lQo8PlgyNlKa4TBsa5lk7SB22Pbv/8liJoIx832EI65hQuPe7qzk873kJuMauOGNfUF60Arq6eiIxU9SK3sSMLQyBM2hCMswu/FE675tdR3PIkjQz/DMNrmOZf1/HBwehzUEKb4cViQzVcBcBuTlQDZk8QQMQJB2AlmQzcthQEAAF4Hg1Km5YnISOKgAxA8Cg7JSEMxEZ/LQylOnnSc5DqHt21GkmU4U6ARCMwSIxQCAhtBBK0AJlLW0gB1q//++Xh3IPVWgqmoILeuOT58GpejUEWwQxMV3MPycqntopNWOhuBwOdSxWkFUN7wjv+eV3j2qs3hHeUeWM74ywGrXz+xBg2j1TFSL6vT8g0iZLRUGWvErWBUjJYaZThS7BQHPC0QAPIwQgQOo30AECLRX/F3+Ul2O0TvXxekCH7W1Qr4lZ5B0b1ZSwT7NUN/stQeYOt4YTCxsiNOfamNinFKRwoFVk/ziLQfZPosp2U5a/nXgVlDnzkkQqqQkSvSqQTAW8TNyxP7p3K8pMG5Yv9fi7IjMOHExfDbHaJbOlC2DKoZU/wwT0vUD9J9Jzk737Gjq5YJZy/dpyAK5GoZUA0ythClHwxFPx0LtyixpAqMME/mdZpP6gTxevSlhHXMwxurQivFxxYnPdLNNVpzofl5e42CT8eqoAQhJaq0a8oBDWisquHvF4r3cCwIaGK8EhHP/GKbFF1Dw2L+OZrdfZYeFSWgzHHXVYimBkzBKizar41Qge/Zr4hYl428T4NaaPbJ7VGPGbQJ/hfKK+D381WMxFaZ1gNEgsioB6VJaSytNmm5uEECYuRRbCYkW06M5KRP7OExsJsPPNfpDmU0pDrrh4xpzQJNNvQ+foejuUTCerKMDah21WH/o0fmcyHYePFKTq/OgRg2cpSd+PLC68g78yMfCMq0h3lCWmCde5VWmNScrvscsOYhMPV5VbPrvfYFnwZ12Id/fJZRsGqzco0n2pNIPooM16J6+mqczISbRXhkgroJ0ZviOwnOmf1J2xzhw+Dzn+XMhrfUMmO/MsOS3W+UH+a0TUmfI3/LZ+IioyH8rn0EVrvMLGjpPe6wmwxnMbz1jbK3O4vKC6/e7+2338pIrJuk8a/sM1HyspqE940tJgaAjusPEpJ2Y5gWdUrR01NUMlILbSauId04ScMCIvfifP2pvBDVUon34799z7P39n1Ny1kBv5dy+22jntspvuGKk6ZQfqLv41QKJXFhJFshVvuDMmcZ31c9VkDd795a1nqEejmILCzlA30mX+qAETpsGS3Bd5g4zPSc9NPv40VmYXoC208VN2Ovf2CbdOT3AAWu4hJub40pz6ZWCOnlZZhvN65Mq8AE0fxHshT2KhT2oBC+nm2Xqc7xZlYxpiOkpZMGkDDotPj8WLeH4ow5uJYXBMQBPFzVXuHdUek4usKqWgjI2teOY4GWD4lKJZzUaH4LlHGpSjap61qgchVSh/fBvy+gtuKkne3NoWkD8ARBjQR0moBQuF5G8VtkrShcHO9ce91adPuNpe4is568KLZq/r+eDm8pHYqF+Jkg4lwk5thMFn+aTjKy8iC3B6/LWrWE4LElZGzLueeHJ5bcTKC1r6QVyULgTYVJ+hpdLW4W7nUqanVQ1rjbJuEutyc/ydLajiCma6xLyoE/HqgeBKKojEOcfqGQTERfI1kAgo07lActKySCJZOIyQcHUkAEkW5QcuHZ1ru1cqUTeuFyAwmyUtzbqhGE5kiKxVDLXFtR5qG0a/0ViZUxzS3Vl6KY1hhkgutEd1llnRKb/mKinG/yYnkG8R6Wu1enzhHYZUQ25G6+64Pn/0Tmgbf9vALnTtmJBNvm73IldqwsqgHYCkHtAiTlA8s4vzDPqfpB1AFKGOjJHQqwFwpesxnL/m/OtHEDmbvdkLCQyNlif5KopGKnAfgcl/T9j+pvQVSQTPmANkg1kWCrzCNp2uSLprJu5y5+IlpsGq/9l4387fhiQ9vpNKItzupGPT36nQLMYAXfwWOUVaKX+VfVC0+q7NXJwTnakvJzF3d5MPjZZmiXYmRrg8AFw5x4f5eM0+ScqK55l+CcSoGFSBEgsSmsr/cpAx6U2MLBoBhwq0W5xlxgz6SKUDVRkaQQEYU4CjSCXgCTMA22l/wHoJPkLGISFBA59RWyFLmXFhEkrhhZk6nhTwVBtRbhMXNkvuFRqTqus+A8cQ5raVq3en/eCGtzFLPHsdiJWWaZKPUebQ1mSaphyGFl5kWa/rjY2NOvKUNWa0AoGaEQ7zFCM5OZ1Agaixg4vTAbe/wvgSJRouKDJH69/ACYSohU1HrA0WUH7hasrNTktlWdxxrFjNhGLkrUZokLRlggoeTahmB4eLwcYhBXjG2Q27KlGXY2tyq3G71/tEhwbX7NslekBoiQrqqYbJrPL3luxWG12h9Pl9nh9/lAMlcTDCjFqhy5uGERoNn5kVtZpO+Lb4ALjtXTrphrKJYiAeyZmda9CnQYuiE/HzunUJ/FBYU8VOqnpina9rPGJjI5U4JZ0PTbU3Dg4L0NtDKVahnnQdfSpHxFU0FkMtAAAAA==') format('woff2'),
url('iconfont.woff?t=1555230336940') format('woff'),
url('iconfont.ttf?t=1555230336940') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1555230336940#iconfont') format('svg'); /* iOS 4.1- */
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
}
.iconfont {
@ -15,6 +24,13 @@
-moz-osx-font-smoothing: grayscale;
}
<<<<<<< HEAD
=======
.reco-color:before {
content: "\eae9";
}
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
.reco-message:before {
content: "\e634";
}

View File

@ -20,6 +20,12 @@ Created by iconfont
/>
<missing-glyph />
<<<<<<< HEAD
=======
<glyph glyph-name="color" unicode="&#60137;" d="M778.22179555 384q29.56401778 0 51.21517 20.48606777t21.60260778 52.33171001-21.60260778 52.33171001-51.21517 20.48606776-51.21516998-20.48606776-21.60260779-52.33171001 21.60260779-52.33171001 51.21516998-20.48606777zM632.58624 577.40401778q29.56401778 0 51.21516999 21.60260779t21.60260779 51.21516998-21.60260779 51.21517-51.21516999 21.60260778-51.21516999-21.60260778-21.60260779-51.21517 21.60260779-51.21516998 51.21516999-21.60260779zM391.41376 577.40401778q29.56401778 0 51.21516999 21.60260779t21.60260779 51.21516998-21.60260779 51.21517-51.21516999 21.60260778-51.21516999-21.60260778-21.60260779-51.21517 21.60260779-51.21516998 51.21516999-21.60260779zM245.77820445 384q29.56401778 0 51.21516998 20.48606777t21.60260779 52.33171001-21.60260779 52.33171001-51.21516998 20.48606776-51.21517-20.48606776-21.60260778-52.33171001 21.60260778-52.33171001 51.21517-20.48606777zM512 820.90666667q179.76282112 0 308.35901667-113.78991446t128.54765-275.34828999q0-100.14871666-71.7012389-170.68487111t-171.80140999-70.53615445l-84.17735111 0q-31.8456411 0-52.33171001-21.60260779t-20.48606777-51.21516999q0-25.04931555 18.20444444-47.76846222t18.20444445-50.05008555q0-31.8456411-20.48606777-52.33171001t-52.33171001-20.48606777q-182.04444445 0-309.47555555 127.43111112t-127.43111112 309.47555555 127.43111112 309.47555555 309.47555555 127.43111112z" horiz-adv-x="1024" />
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
<glyph glyph-name="message" unicode="&#58932;" d="M864.227 791.373h-702c-48.988 0-88.732-39.621-88.732-88.487v-519.688c0-48.866 42.607-84.866 91.616-84.866h218.638l122.113-106.65 122.134 106.65h233.366c48.988 0 91.596 36.021 91.596 84.866v519.688c0 48.866-39.763 88.487-88.732 88.487zM685.393 342.72299999999996h-309.702c-17.202 0-31.152 13.95-31.152 31.152s13.95 31.152 31.152 31.152h309.702c17.223 0 31.152-13.95 31.152-31.152s-13.95-31.152-31.152-31.152zM759.029 505.848h-484.343c-17.202 0-31.152 13.95-31.152 31.152 0 17.223 13.95 31.173 31.152 31.173h484.343c17.202 0 31.152-13.95 31.152-31.173 0.021-17.202-13.95-31.152-31.152-31.152z" horiz-adv-x="1024" />
@ -80,7 +86,11 @@ Created by iconfont
<glyph glyph-name="jianshu" unicode="&#58880;" d="M0 384v-512h1024V896H0v-512z m356.864 331.776c-1.024-6.656-4.096-15.872-6.144-20.48-3.584-8.704 2.048-9.216 78.848-9.216H512v-51.2h-43.52c-24.064 0-43.52-0.512-43.52-1.024 0-1.024 4.608-16.384 10.24-34.816 5.632-18.432 10.24-33.792 10.24-34.304 0-1.024-18.432-1.536-40.448-1.536h-40.448l-3.584 16.896c-9.216 45.056-13.824 54.784-27.136 54.784-7.68 0-21.504-8.192-35.328-20.992-22.016-19.968-71.168-46.592-99.84-53.76-14.336-3.072-14.336-3.072-14.336 22.528 0 23.552 1.024 26.112 19.968 38.4 25.088 16.384 41.984 38.912 59.392 76.8l13.312 29.184h41.472c39.936 0 40.96-0.512 38.4-11.264z m306.688-6.656l-3.584-17.92h179.712v-56.32h-96.768l10.24-29.184c14.848-43.008 15.36-42.496-28.16-42.496h-37.888l-3.584 16.896c-2.048 8.704-6.144 25.088-8.704 35.84-5.12 17.92-7.168 18.944-25.6 18.944-16.384 0-23.552-3.584-41.472-20.992-19.456-18.944-76.288-50.176-104.448-58.368-10.752-3.072-11.776-1.536-11.776 18.944 0 20.992 2.048 24.576 27.648 46.592 25.6 22.016 49.152 59.392 61.44 97.28 2.048 7.168 9.216 8.704 44.544 8.704h41.472l-3.072-17.92z m-317.44-162.304c4.608-8.704 13.824-32.256 20.48-51.2 13.824-41.472 14.336-40.96-36.352-38.912l-34.816 1.536-11.264 35.84c-6.144 19.968-14.848 43.52-19.968 52.736L255.488 563.2h40.96c40.96 0 41.472 0 49.664-16.384z m462.848-225.792c0-200.192-0.512-217.6-9.216-233.984-15.872-28.672-40.448-37.888-103.424-38.4h-53.76l-1.536 29.696-1.536 29.184h33.792c29.184 0 35.328 1.536 46.08 12.8l12.8 12.288V476.16H384V537.6h424.96v-216.576zM291.84 243.2v-202.24h-76.8V445.44h76.8V243.2z m363.52 57.344c0-182.784 4.608-177.664-167.424-177.664H373.76V424.96h281.6v-124.416zM450.56 335.36v-33.28h128V368.64h-128v-33.28zM450.56 215.04v-35.84h55.808c65.024 0 69.12 2.56 69.632 43.008v26.112l-62.464 1.536-62.976 1.536v-36.352z" horiz-adv-x="1024" />
<<<<<<< HEAD
<glyph glyph-name="theme" unicode="&#59368;" d="M949.6 535.4s-0.1 0-0.1 0.1L755.1 729.4c-15.6 25.3-43.4 42.4-75.4 42.4h-55.5c-16.2 0-29.7-11.6-32.7-27l-0.6-0.9v1.2c-0.8-2-2-3.9-3.4-5.9-9.4-32.3-38.9-56-74.3-56-31 0-57.6 18.3-70.1 44.5l-0.4 0.3c-0.1 0.4-0.3 0.8-0.4 1.2-0.9 2-1.5 4.1-2.3 6.2-1.4 3.6-3 7.1-4.6 10.6v-5.3h-0.2c-0.2 3.6-1 7.1-2.2 10.3-0.7 1.5-1.5 3-2.3 4.5-5.8 9.8-16.3 16.4-28.5 16.4-2 0-3.9-0.3-5.9-0.7-1 0.5-2.1 0.7-3.2 0.7-0.7 0-1.4-0.2-2.1-0.4v0.4h-44.4c-28.9 0-54.3-14-70.6-35.3l-201.4-201s-0.1 0-0.1-0.1c-13-13-13-34 0-47l141.3-141c11.5-11.5 28.9-12.2 41.9-3.4v-325.6h2.2c4.6-12.9 16.6-22.2 31.1-22.2h444.2c14.5 0 26.5 9.3 31.1 22.2h2.2v324c12.7-7.2 28.9-5.9 39.7 4.9l141.3 141c13.1 13 13.1 34 0.1 47z" horiz-adv-x="1024" />
=======
<glyph glyph-name="theme" unicode="&#59368;" d="M978.77333333 545.49333333s-0.10666667 0-0.10666666 0.10666667L771.30666667 752.42666667c-16.64 26.98666667-46.29333333 45.22666667-80.42666667 45.22666666h-59.2c-17.28 0-31.68-12.37333333-34.88-28.8l-0.64-0.96v1.28c-0.85333333-2.13333333-2.13333333-4.16-3.62666667-6.29333333-10.02666667-34.45333333-41.49333333-59.73333333-79.25333333-59.73333333-33.06666667 0-61.44 19.52-74.77333333 47.46666666l-0.42666667 0.32c-0.10666667 0.42666667-0.32 0.85333333-0.42666667 1.28-0.96 2.13333333-1.6 4.37333333-2.45333333 6.61333334-1.49333333 3.84-3.2 7.57333333-4.90666667 11.30666666v-5.65333333h-0.21333333c-0.21333333 3.84-1.06666667 7.57333333-2.34666667 10.98666667-0.74666667 1.6-1.6 3.2-2.45333333 4.8-6.18666667 10.45333333-17.38666667 17.49333333-30.4 17.49333333-2.13333333 0-4.16-0.32-6.29333333-0.74666667-1.06666667 0.53333333-2.24 0.74666667-3.41333334 0.74666667-0.74666667 0-1.49333333-0.21333333-2.24-0.42666667v0.42666667h-47.36c-30.82666667 0-57.92-14.93333333-75.30666666-37.65333333l-214.82666667-214.4s-0.10666667 0-0.10666667-0.10666667c-13.86666667-13.86666667-13.86666667-36.26666667 0-50.13333333l150.72-150.4c12.26666667-12.26666667 30.82666667-13.01333333 44.69333334-3.62666667v-347.30666667h2.34666666c4.90666667-13.76 17.70666667-23.68 33.17333334-23.68h473.81333333c15.46666667 0 28.26666667 9.92 33.17333333 23.68h2.34666667v345.6c13.54666667-7.68 30.82666667-6.29333333 42.34666667 5.22666667l150.72 150.4c13.97333333 13.86666667 13.97333333 36.26666667 0.10666666 50.13333333z" horiz-adv-x="1024" />
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
<glyph glyph-name="three" unicode="&#58948;" d="M861.798876 266.798732C835.998959 320.998557 830.598976 331.29852400000004 806.999052 385.398351c-12.59996 28.799907-38.399877 46.79985-61.899801 52.69983l62.499799 294.499054c9.29997 43.899859-18.299941 86.99972-61.699801 96.39969-43.399861 9.39997-86.099723-18.59994-95.399694-62.499799l-58.099813-273.79912-3.699988 322.598963C587.999756 860.296825 551.599873 896.396709 507.200015 895.99671c-44.499857-0.299999-79.999743-36.999881-79.499744-81.799737l3.499989-304.299022-66.199788 248.999199c-11.499963 43.299861-55.599821 68.999778-98.499683 57.399816-42.899862-11.599963-68.299781-56.199819-56.799818-99.49968L295.000697 395.898317c-62.899798-21.69993-92.899702-43.899859-103.399668-72.899766l-37.999878-108.399652c-8.499973-23.399925 3.19999-75.299758 11.499964-98.799682 39.699872-112.799638 86.399722-187.699397 114.499632-226.699272 4.899984-6.799978 9.099971-12.29996 12.799959-16.899946H760.9992c1.699995 3.09999 3.19999 6.29998 4.499986 9.699969l94.999694 256.299177c22.099929 52.099833 10.799965 108.499651 1.299996 128.599587z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,44 @@
<script>
export default {
functional: true,
props: {
type: {
type: String,
default: 'tip'
},
text: String,
vertical: {
type: String,
default: 'top'
}
},
render (h, { props, slots }) {
return h('span', {
class: ['badge', props.type],
style: {
verticalAlign: props.vertical
}
}, props.text || slots().default)
}
}
</script>
<style lang="stylus" scoped>
.badge
display inline-block
font-size 14px
height 18px
line-height 18px
border-radius 3px
padding 0 6px
color white
background-color #42b983
&.tip, &.green
background-color #42b983
&.error
background-color #DA5961 //#f66
&.warning, &.warn, &.yellow
background-color darken(#ffe564, 35%)
& + &
margin-left 5px
</style>

46
index.js Normal file
View File

@ -0,0 +1,46 @@
const path = require('path')
// Theme API.
module.exports = (options, ctx) => ({
alias () {
const { themeConfig, siteConfig } = ctx
// resolve algolia
const isAlgoliaSearch = (
themeConfig.algolia
|| Object.keys(siteConfig.locales && themeConfig.locales || {})
.some(base => themeConfig.locales[base].algolia)
)
return {
'@AlgoliaSearchBox': isAlgoliaSearch
? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue')
: path.resolve(__dirname, 'noopModule.js')
}
},
plugins: [
'@vuepress/active-header-links',
['@vuepress/plugin-blog', {
permalink: '/:regular'
}],
'@vuepress/search',
'@vuepress/plugin-nprogress',
['container', {
type: 'tip',
defaultTitle: {
'/zh/': '提示'
}
}],
['container', {
type: 'warning',
defaultTitle: {
'/zh/': '注意'
}
}],
['container', {
type: 'danger',
defaultTitle: {
'/zh/': '警告'
}
}]
]
})

View File

@ -24,3 +24,5 @@ export default {
}
}
</script>
<style src="../styles/theme.styl" lang="stylus"></style>

93
layouts/Category.vue Normal file
View File

@ -0,0 +1,93 @@
<template>
<div class="categories-wrapper">
<!-- 公共布局 -->
<Common :sidebar="false" :isComment="false">
<!-- 页面标题 -->
<h2 class="title">{{ title }}</h2>
<!-- 博客列表 -->
<note-abstract
:data="posts"
:currentPage="currentPage"
@currentTag="getCurrentTag"></note-abstract>
<!-- 分页 -->
<pagation
:data="posts"
:currentPage="currentPage"
@getCurrentPage="getCurrentPage"></pagation>
</Common>
</div>
</template>
<script>
import Common from '@theme/components/Common.vue'
import NoteAbstract from '../components//NoteAbstract.vue'
import Pagation from '../components//Pagation.vue'
export default {
components: { Common, NoteAbstract, Pagation },
data () {
return {
//
currentPage: 1
}
},
computed: {
//
posts () {
let posts = this.$category.posts
posts.sort((a, b) => {
return this._getTimeNum(b) - this._getTimeNum(a)
})
return posts
},
//
title () {
return this.$page.frontmatter.title.split('|')[0]
}
},
methods: {
// tag
getCurrentTag (tag) {
this.$emit('currentTag', tag)
},
//
getCurrentPage (page) {
this.currentPage = page
this.$page.currentPage = page
},
//
_getTimeNum (date) {
return parseInt(new Date(date.frontmatter.date).getTime())
}
}
}
</script>
<style src="../styles/theme.styl" lang="stylus"></style>
<style lang="stylus" scoped>
.categories-wrapper
max-width: 740px;
margin: 0 auto;
padding: 4.6rem 2.5rem 0;
.title
margin-bottom 3rem
@media (max-width: $MQMobile)
.categories-wrapper
padding: 4.6rem 1rem 0;
.page-edit
.edit-link
margin-bottom .5rem
.last-updated
font-size .8em
float none
text-align left
</style>

42
layouts/Layout.vue Normal file
View File

@ -0,0 +1,42 @@
<template>
<div>
<Common>
<Home v-if="$page.frontmatter.home"/>
<Page
v-else
:sidebar-items="sidebarItems">
<slot
name="page-top"
slot="top"/>
<slot
name="page-bottom"
slot="bottom"/>
</Page>
</Common>
</div>
</template>
<script>
import Home from '@theme/components/Home.vue'
import Page from '@theme/components/Page.vue'
import Common from '@theme/components/Common.vue'
import { resolveSidebarItems } from '../util'
export default {
components: { Home, Page, Common },
computed: {
sidebarItems () {
return resolveSidebarItems(
this.$page,
this.$page.regularPath,
this.$site,
this.$localePath
)
}
}
}
</script>
<style src="prismjs/themes/prism-tomorrow.css"></style>
<style src="../styles/theme.styl" lang="stylus"></style>

129
layouts/Tags.vue Normal file
View File

@ -0,0 +1,129 @@
<template>
<div class="tags-wrapper">
<Common :sidebar="false" :isComment="false"></Common>
<div class="tags">
<span
v-for="(item, index) in tags"
:key="index"
:class="{'active': item.name == currentTag}"
:style="{ 'backgroundColor': item.color }"
@click="getPagesByTags(item.name)">{{item.name}}</span>
</div>
<note-abstract
:data="posts"
:currentPage="currentPage"
:currentTag="currentTag"
@currentTag="getCurrentTag"></note-abstract>
<pagation
:data="posts"
:currentPage="currentPage"
@getCurrentPage="getCurrentPage"></pagation>
</div>
</template>
<script>
import Common from '@theme/components/Common.vue'
import NoteAbstract from '../components//NoteAbstract.vue'
import Pagation from '../components//Pagation.vue'
export default {
components: { Common, NoteAbstract, Pagation },
data () {
return {
posts: [],
tags: [],
currentTag: '',
currentPage: 1
}
},
created () {
if (this.$tags.list.length > 0) {
const currentTag = this.$route.query.tag ? this.$route.query.tag : this.$tags.list[0].name
let tags = this.$tags.list
tags.map(item => {
const color = this._tagColor()
item.color = color
return tags
})
this.tags = tags
this.getPagesByTags(currentTag)
}
},
methods: {
//
getPagesByTags (currentTag) {
this.currentTag = currentTag
let posts = this.$tags.map[currentTag].posts
posts.sort((a, b) => {
return this._getTimeNum(b) - this._getTimeNum(a)
})
// reverse()
this.posts = posts.length == 0 ? [] : posts
this.getCurrentPage(1);
},
getCurrentTag (tag) {
this.$emit('currentTag', tag)
},
getCurrentPage (page) {
this.currentPage = page
this.$page.currentPage = page
},
_tagColor () {
// 绿
const tagColorArr = ['#f26d6d', '#3498db', '#67cc86', '#fb9b5f', '#838282']
const index = Math.floor(Math.random() * tagColorArr.length)
return tagColorArr[index]
},
//
_getTimeNum (date) {
return parseInt(new Date(date.frontmatter.date).getTime())
}
}
}
</script>
<style src="../styles/theme.styl" lang="stylus"></style>
<style lang="stylus" scoped>
.tags-wrapper
max-width: 740px;
margin: 0 auto;
padding: 4.6rem 2.5rem 0;
.tags
margin-bottom 30px
span
vertical-align: middle;
margin: 4px 4px 10px;
padding: 4px 8px;
display: inline-flex;
cursor: pointer;
border-radius: 2px;
background: #fff;
color: #fff;
font-size: 13px;
box-shadow 0 1px 4px 0 rgba(0,0,0,0.2)
transition: all .5s
&:hover
transform scale(1.04)
&.active
transform scale(1.2)
@media (max-width: $MQMobile)
.tags-wrapper
padding: 0 0.6rem;
</style>

1
noopModule.js Normal file
View File

@ -0,0 +1 @@
export default {}

View File

@ -1,6 +1,6 @@
{
"name": "vuepress-theme-reco",
"version": "0.3.11",
"version": "1.0.0-alpha.11",
"description": "this is a vuepress theme",
"main": "index.js",
"scripts": {
@ -24,7 +24,9 @@
"_from": "vuepress-theme-reco@0.2.1",
"_resolved": "http://registry.npm.taobao.org/vuepress-theme-reco/download/vuepress-theme-reco-0.2.1.tgz",
"dependencies": {
"leancloud-storage": "^3.12.0",
"valine": "^1.3.6"
"leancloud-storage": "^3.10.1",
"valine": "^1.3.4",
"@vuepress/plugin-blog": "^1.0.0-alpha.46",
"vue-click-outside": "^1.0.7"
}
}

View File

@ -1,5 +1,3 @@
@require './config'
.content
code
color lighten($textColor, 20%)
@ -8,6 +6,11 @@
font-size 0.85em
background-color rgba(27,31,35,0.05)
border-radius 3px
.token
&.deleted
color #EC5975
&.inserted
color $accentColor
.content
pre, pre[class*="language-"]
@ -127,3 +130,6 @@ div[class~="language-python"]:before
div[class~="language-bash"]:before
content "sh"
div[class~="language-php"]:before
content "php"

View File

@ -0,0 +1,55 @@
color-mode(accountColor , colorName)
.reco-theme-{colorName}
input
color accountColor!important;
.search-box input
border-color: accountColor!important;
&:focus
border-color: accountColor!important;
.navbar
box-shadow: 0 1px 6px 0 rgba(32,33,36,.28)
.nav-links a:hover,
.nav-links a.router-link-active,
.nav-links a:hover .iconfont,
.nav-links a.router-link-active .iconfont
color accountColor!important;
.home
.hero
.description
color accountColor!important;
.action-button, img
background-color accountColor!important;
color: #fff!important
.features
.feature
h2, p
color accountColor!important;
.footer
a
color accountColor!important;
.abstract-wrapper .abstract-item .title
a
color accountColor!important;
a:after
background-color accountColor!important;
.back-to-ceiling i
color accountColor!important;
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
border-left: 5px solid accountColor!important;
.tags
.tag-item.active, .tag-item:hover
color accountColor!important;
.timeline-wrapper .year-wrapper li:hover
.title
color accountColor!important;
.date::before
background: accountColor!important;
.date
color accountColor!important;
@media (min-width: 765px)
.nav-item > a:not(.external):hover,
.nav-item > a:not(.external).router-link-active
border-color: accountColor!important;
@media (max-width: 959px)
.search-box input
border-color: transparent!important;

View File

@ -0,0 +1,17 @@
@require './colorMixin.styl'
$fc-red = #f26d6d
$fc-red-name = 'red'
color-mode($fc-red, $fc-red-name)
$fc-blue = #2196f3
$fc-blue-name = 'blue'
color-mode($fc-blue, $fc-blue-name)
$fc-green = #3eaf7c
$fc-green-name = 'green'
color-mode($fc-green, $fc-green-name)
$fc-orange = #fb9b5f
$fc-orange-name = 'orange'
color-mode($fc-orange, $fc-orange-name)

View File

@ -0,0 +1,2 @@
@require './nightMode.styl'
@require './colorMode.styl'

View File

@ -0,0 +1,114 @@
$bc = #000
$fc = #9e9e9e
$bdc = #9e9e9e
$fcActive = #fff
bc() {
background-color: $bc!important
}
fc() {
color: $fc!important
}
bdc() {
border-color: $bdc!important
}
fc-active() {
color: $fcActive!important
}
.reco-theme-night
bc()
fc()
bdc()
h1, h2, h3, h4, h5, h6, a, hr
bdc()
fc()
input
bc()
fc()
.search-box input
bdc()
&:focus
bdc()
.navbar
bc()
box-shadow: 0 2px 20px 0 rgba(255,255,255,0.4);
border-bottom: 1px solid $bdc
.site-name, .links
bc()
fc()
.nav-links a:hover,
.nav-links a.router-link-active,
.nav-links a:hover .iconfont,
.nav-links a.router-link-active .iconfont
fc-active()
.tags .tag-item:hover
fc-active()
@media (min-width: 765px)
.nav-item > a:not(.external):hover,
.nav-item > a:not(.external).router-link-active
border-color: $fcActive;
.dropdown-wrapper .nav-dropdown
bc()
box-shadow: 0 2px 20px 0 rgba(255,255,255,0.4);
border: 1px solid $bdc
@media (min-width: 719px)
.nav-item > a:not(.external):hover,
.nav-item > a:not(.external).router-link-active
border-bottom: 2px solid $fcActive!important;
@media (max-width: 959px)
.search-box input
border-color: transparent!important;
.home
.hero
.description
fc()
.features
bdc()
.feature
h2, p
fc()
.footer
bdc()
a
fc()
.abstract-wrapper .abstract-item
background-color: lighten($bc, 20%)
.custom-block.tip, .custom-block.warning, .custom-block.danger
background-color: lighten($bc, 15%)
.pagation .pagation-list
bc()
.sidebar
bc()
bdc()
.valine-wrapper
bc()
.v .vbtn, .v .vwrap
bc()
bdc()
.v .vlist .vcard
.vhead .vsys, .vh
bdc()
bc()
.timeline-wrapper
&::after
background: $fc
.year-wrapper li
bdc()
.back-to-ceiling
background-color: lighten($bc, 15%)!important
i
fc()
.color-picker .color-button .iconfont
fc()
.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
border-left: 5px solid $fcActive
.timeline-wrapper .year-wrapper li:hover
.title
fc()
.date::before
background: $fcActive
.date
fc()

View File

@ -1,23 +0,0 @@
// colors
$accentColor = #424242
$textColor = #232321
$borderColor = #eaecef
$codeBgColor = #282c34
$arrowBgColor = #ccc
$bgColor = #fff
// layout
$navbarHeight = 3.4rem
$sidebarWidth = 20rem
$contentWidth = 740px
// // responsive breakpoints
$MQNarrow = 1024px
$MQMobile = 765px
$MQMobileNarrow = 419px
// code
$lineNumbersWrapperWidth = 3.5rem
$codeLang = js ts html md vue css sass scss less stylus go java c sh yaml py
@import '~@temp/override.styl'

View File

@ -10,7 +10,10 @@
&.tip
background-color #f3f5f7
border-color #67cc86
<<<<<<< HEAD
// color darken(#67cc86, 70%)
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
&.warning
background-color #fbf0ea
border-color #fb9b5f
@ -27,3 +30,5 @@
color darken(red, 40%)
a
color $textColor

View File

@ -1,4 +1,4 @@
@require './config'
// @require './config'
$mobileSidebarWidth = $sidebarWidth * 0.82

View File

@ -1,48 +0,0 @@
#nprogress
pointer-events none
.bar
background $accentColor
position fixed
z-index 1031
top 0
left 0
width 100%
height 2px
.peg
display block
position absolute
right 0px
width 100px
height 100%
box-shadow 0 0 10px $accentColor, 0 0 5px $accentColor
opacity 1.0
transform rotate(3deg) translate(0px, -4px)
.spinner
display block
position fixed
z-index 1031
top 15px
right 15px
.spinner-icon
width 18px
height 18px
box-sizing border-box
border solid 2px transparent
border-top-color $accentColor
border-left-color $accentColor
border-radius 50%
animation nprogress-spinner 400ms linear infinite
.nprogress-custom-parent
overflow hidden
position relative
.nprogress-custom-parent #nprogress .spinner,
.nprogress-custom-parent #nprogress .bar
position absolute
@keyframes nprogress-spinner
0%
transform rotate(0deg)
100%
transform rotate(360deg)

3
styles/recoConfig.styl Normal file
View File

@ -0,0 +1,3 @@
// colors
$accentColor = #424242
$textColor = #232321

View File

@ -1,29 +1,40 @@
@require './config'
@require './nprogress'
@require './recoConfig'
@require './code'
@require './custom-blocks'
@require './arrow'
@require './wrapper'
@require './toc'
<<<<<<< HEAD
// @require './common'
=======
@require './colorMode/index'
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
@require '../fonts/iconfont.css'
html, body
padding 0
margin 0
<<<<<<< HEAD
background-color: $bgColor
overflow-x: hidden
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
body
font-family -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
font-size 16px
<<<<<<< HEAD
color $textColor
input
background-color: $bgColor
-webkit-appearance: none;
=======
color $textColor
background-color #fff
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
.page
padding-left $sidebarWidth
@ -37,7 +48,6 @@ input
height $navbarHeight
background-color $bgColor
box-sizing border-box
box-shadow: 0 1px 6px 0 rgba(32,33,36,0.28)
.sidebar-mask
position fixed
@ -47,11 +57,19 @@ input
width 100vw
height 100vh
display none
<<<<<<< HEAD
background-color: rgba(0, 0, 0, .65)
.sidebar
font-size 15px
background-color $bgColor
=======
background-color: rgba(0,0,0,.65);
.sidebar
font-size 16px
background-color #fff
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
width $sidebarWidth
position fixed
z-index 10
@ -80,7 +98,7 @@ input
padding 0
margin 0
img
max-width 100%
max-width 100%
a
font-weight 500
@ -99,11 +117,13 @@ kbd
padding 0 0.15em
blockquote
font-size 1rem
font-size .9rem
color #999
border-left .25rem solid #dfe2e5
margin-left 0
padding-left 1rem
margin 0.5rem 0
padding .25rem 0 .25rem 1rem
& > p
margin 0
ul, ol
padding-left 1.2em
@ -172,9 +192,6 @@ th, td
border 1px solid #dfe2e5
padding .6em 1em
.custom-layout
padding-top $navbarHeight
.theme-container
&.sidebar-open
.sidebar-mask
@ -185,6 +202,7 @@ th, td
padding-top 0
.sidebar
top 0
<<<<<<< HEAD
.custom-layout
padding-top 0
@ -214,6 +232,8 @@ th, td
width: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;
=======
>>>>>>> 24c38eb010e47bfb4c4532c15a8d35e38c27adfd
@media (min-width: ($MQMobile + 1px))
.theme-container.no-sidebar
@ -222,4 +242,32 @@ th, td
.page
padding-left 0
@require './mobile.styl'
@require 'mobile.styl'
.iconfont
font-size: 0.9rem;
color: #999;
// &:not(:first-child)
// margin-left: 1rem
// span
// margin-left: .5rem
/************** **************/
::-webkit-scrollbar
width: 5px;
height: 5px;
::-webkit-scrollbar-track-piece
background-color: rgba(0, 0, 0, 0.2);
-webkit-border-radius: 6px;
::-webkit-scrollbar-thumb:vertical
height: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;
::-webkit-scrollbar-thumb:horizontal
width: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;

View File

@ -58,10 +58,10 @@ export function resolvePage (pages, rawPath, base) {
}
const path = normalize(rawPath)
for (let i = 0; i < pages.length; i++) {
if (normalize(pages[i].path) === path) {
if (normalize(pages[i].regularPath) === path) {
return Object.assign({}, pages[i], {
type: 'page',
path: ensureExt(rawPath)
path: ensureExt(pages[i].path)
})
}
}
@ -107,7 +107,14 @@ function resolvePath (relative, base, append) {
return stack.join('/')
}
export function resolveSidebarItems (page, route, site, localePath) {
/**
* @param { Page } page
* @param { string } regularPath
* @param { SiteData } site
* @param { string } localePath
* @returns { SidebarGroup }
*/
export function resolveSidebarItems (page, regularPath, site, localePath) {
const { pages, themeConfig } = site
const localeConfig = localePath && themeConfig.locales
@ -123,19 +130,24 @@ export function resolveSidebarItems (page, route, site, localePath) {
if (!sidebarConfig) {
return []
} else {
const { base, config } = resolveMatchingConfig(route, sidebarConfig)
const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
return config
? config.map(item => resolveItem(item, pages, base))
: []
}
}
/**
* @param { Page } page
* @returns { SidebarGroup }
*/
function resolveHeaders (page) {
const headers = groupHeaders(page.headers || [])
return [{
type: 'group',
collapsable: false,
title: page.title,
path: null,
children: headers.map(h => ({
type: 'auto',
title: h.title,
@ -166,7 +178,12 @@ export function resolveNavLinkItem (linkItem) {
})
}
export function resolveMatchingConfig (route, config) {
/**
* @param { Route } route
* @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config
* @returns { base: string, config: SidebarConfig }
*/
export function resolveMatchingConfig (regularPath, config) {
if (Array.isArray(config)) {
return {
base: '/',
@ -174,7 +191,7 @@ export function resolveMatchingConfig (route, config) {
}
}
for (const base in config) {
if (ensureEndingSlash(route.path).indexOf(base) === 0) {
if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
return {
base,
config: config[base]
@ -190,7 +207,7 @@ function ensureEndingSlash (path) {
: path + '/'
}
function resolveItem (item, pages, base, isNested) {
function resolveItem (item, pages, base, groupDepth = 1) {
if (typeof item === 'string') {
return resolvePage(pages, item, base)
} else if (Array.isArray(item)) {
@ -198,17 +215,23 @@ function resolveItem (item, pages, base, isNested) {
title: item[1]
})
} else {
if (isNested) {
if (groupDepth > 3) {
console.error(
'[vuepress] Nested sidebar groups are not supported. ' +
'Consider using navbar + categories instead.'
'[vuepress] detected a too deep nested sidebar group.'
)
}
const children = item.children || []
if (children.length === 0 && item.path) {
return Object.assign(resolvePage(pages, item.path, base), {
title: item.title
})
}
return {
type: 'group',
path: item.path,
title: item.title,
children: children.map(child => resolveItem(child, pages, base, true)),
sidebarDepth: item.sidebarDepth,
children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
collapsable: item.collapsable !== false
}
}