264 lines
5.4 KiB
Vue
264 lines
5.4 KiB
Vue
|
<template>
|
||
|
<div class="page">
|
||
|
<slot name="top"/>
|
||
|
|
||
|
<Content :custom="false"/>
|
||
|
|
||
|
<div 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>
|
||
|
</div>
|
||
|
|
||
|
<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"/>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script>
|
||
|
import { resolvePage, normalize, outboundRE, endingSlashRE } from './util'
|
||
|
|
||
|
export default {
|
||
|
props: ['sidebarItems'],
|
||
|
|
||
|
computed: {
|
||
|
lastUpdated () {
|
||
|
if (this.$page.lastUpdated) {
|
||
|
return new Date(this.$page.lastUpdated).toLocaleString(this.$lang)
|
||
|
}
|
||
|
},
|
||
|
|
||
|
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
|
||
|
|
||
|
let path = normalize(this.$page.path)
|
||
|
if (endingSlashRE.test(path)) {
|
||
|
path += 'README.md'
|
||
|
} else {
|
||
|
path += '.md'
|
||
|
}
|
||
|
if (docsRepo && editLinks) {
|
||
|
return this.createEditLink(repo, docsRepo, docsDir, docsBranch, path)
|
||
|
}
|
||
|
},
|
||
|
|
||
|
editLinkText () {
|
||
|
return (
|
||
|
this.$themeLocaleConfig.editLinkText ||
|
||
|
this.$site.themeConfig.editLinkText ||
|
||
|
`Edit this page`
|
||
|
)
|
||
|
}
|
||
|
},
|
||
|
|
||
|
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, '') +
|
||
|
`/${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 = []
|
||
|
items.forEach(item => {
|
||
|
if (item.type === 'group') {
|
||
|
res.push(...item.children || [])
|
||
|
} else {
|
||
|
res.push(item)
|
||
|
}
|
||
|
})
|
||
|
for (let i = 0; i < res.length; i++) {
|
||
|
const cur = res[i]
|
||
|
if (cur.type === 'page' && cur.path === page.path) {
|
||
|
return res[i + offset]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style lang="less">
|
||
|
@import './styles/config.less';
|
||
|
@import './styles/wrapper.less';
|
||
|
|
||
|
.page {
|
||
|
padding-bottom: 2rem;
|
||
|
}
|
||
|
|
||
|
.page-edit {
|
||
|
.wrapper();
|
||
|
padding-top: 1rem;
|
||
|
padding-bottom: 1rem;
|
||
|
overflow: auto;
|
||
|
.edit-link {
|
||
|
display: inline-block;
|
||
|
a, a:visited {
|
||
|
color: var(--LClr);
|
||
|
margin-right: 0.25rem;
|
||
|
&:hover {
|
||
|
color: var(--LHClr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
.last-updated {
|
||
|
float: right;
|
||
|
font-size: 0.9em;
|
||
|
.prefix {
|
||
|
font-weight: 500;
|
||
|
color: var(--TClr);
|
||
|
}
|
||
|
.time {
|
||
|
font-weight: 400;
|
||
|
color: var(--TClr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.page-nav {
|
||
|
.wrapper();
|
||
|
padding-top: 1rem;
|
||
|
padding-bottom: 0;
|
||
|
.inner {
|
||
|
min-height: 2rem;
|
||
|
margin-top: 0;
|
||
|
border-top: 0.1em solid var(--BClr);
|
||
|
padding-top: 1rem;
|
||
|
overflow: auto // clear float;
|
||
|
}
|
||
|
.next {
|
||
|
float: right;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@media (max-width: @MQMobile) {
|
||
|
.page-edit {
|
||
|
.edit-link {
|
||
|
margin-bottom: .5rem;
|
||
|
}
|
||
|
.last-updated {
|
||
|
font-size: .8em;
|
||
|
float: none;
|
||
|
text-align: left;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
</style>
|