fix: fix edit link and prev and next links display (#97)

fix #97
pull/136/head
Kia King Ishii 4 years ago committed by Kia Ishii
parent 1ba209a4d2
commit c3b7172951

@ -0,0 +1,8 @@
import { computed } from 'vue'
import { useRoute } from '../router'
export function usePageData() {
const route = useRoute()
return computed(() => route.data)
}

@ -1,6 +1,9 @@
// exports in this file are exposed to themes and md files via 'vitepress'
// so the user can do `import { useRoute, useSiteData } from 'vitepress'`.
// generic types
export type { SiteData, PageData } from '/@types/shared'
// theme types
export * from './theme'
@ -8,6 +11,7 @@ export * from './theme'
export { useRouter, useRoute, Router, Route } from './router'
export { useSiteData } from './composables/siteData'
export { useSiteDataByRoute } from './composables/siteDataByRoute'
export { usePageData } from './composables/pageData'
// components
export { Content } from './components/Content'

@ -0,0 +1,53 @@
<template>
<div class="edit-link">
<a v-if="url" class="link" :href="url" target="_blank" rel="noopener noreferrer">
{{ text }} <OutboundLink class="icon" />
</a>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { useEditLink } from '../composables/editLink'
import OutboundLink from './icons/OutboundLink.vue'
export default defineComponent({
components: {
OutboundLink
},
setup() {
const { url, text } = useEditLink()
return {
url,
text
}
}
})
</script>
<style scoped>
.edit-link {
padding-top: 1rem;
padding-bottom: 1rem;
overflow: auto;
}
.link {
font-weight: 500;
color: var(--text-color-light);
}
.link:hover {
text-decoration: none;
color: var(--accent-color);
}
.icon {
display: inline-block;
margin-left: 4px;
width: 1rem;
height: 1rem;
}
</style>

@ -1,35 +1,92 @@
<template>
<div v-if="hasLinks" class="links-wrapper">
<div class="prev-link">
<div v-if="prev">
<a :href="prev.link">{{ prev.text }}</a>
</div>
<div v-if="hasLinks" class="next-and-prev-link">
<div class="prev">
<a v-if="prev" class="link" :href="prev.link">
<ArrowLeft class="icon icon-prev" />
<span class="text">{{ prev.text }}</span>
</a>
</div>
<div class="next-link">
<div v-if="next">
<a :href="next.link">{{ next.text }}</a>
</div>
<div class="next">
<a v-if="next" class="link" :href="next.link">
<span class="text">{{ next.text }}</span>
<ArrowRight class="icon icon-next" />
</a>
</div>
</div>
</template>
<script src="./NextAndPrevLinks"></script>
<script lang="ts">
import { defineComponent } from 'vue'
import { useNextAndPrevLinks } from '../composables/nextAndPrevLinks'
import ArrowLeft from './icons/ArrowLeft.vue'
import ArrowRight from './icons/ArrowRight.vue'
<style>
.links-wrapper {
export default defineComponent({
components: {
ArrowLeft,
ArrowRight
},
setup () {
const { hasLinks, prev, next } = useNextAndPrevLinks()
return {
hasLinks,
prev,
next
}
}
})
</script>
<style scoped>
.next-and-prev-link {
display: flex;
justify-content: space-between;
margin-top: 4rem;
border-top: 1px solid var(--border-color);
padding-top: 1rem;
padding-bottom: 2rem;
}
.links-wrapper a {
.prev,
.next {
display: flex;
flex-shrink: 0;
width: 50%;
}
.prev {
justify-content: flex-start;
padding-right: 12px;
}
.next {
justify-content: flex-end;
padding-left: 12px;
}
.link {
display: inline-flex;
align-items: center;
max-width: 100%;
font-size: 1rem;
font-weight: 500;
}
.links-wrapper a:hover {
text-decoration: none !important;
.text {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.icon {
display: block;
flex-shrink: 0;
width: 1rem;
height: 1rem;
fill: var(--text-color);
}
.icon-prev { margin-right: 8px; }
.icon-next { margin-left: 8px; }
</style>

@ -1,42 +1,39 @@
<template>
<div class="content">
<div class="page">
<slot name="top" />
<Content />
<div class="content">
<Content />
</div>
<EditLink />
<NextAndPrevLinks />
<PageEdit />
<slot name="bottom" />
</div>
</template>
<script>
<script lang="ts">
import { defineComponent } from 'vue'
import EditLink from './EditLink.vue'
import NextAndPrevLinks from './NextAndPrevLinks.vue'
import PageEdit from './PageEdit.vue'
export default {
components: { NextAndPrevLinks, PageEdit }
}
export default defineComponent({
components: {
EditLink,
NextAndPrevLinks
}
})
</script>
<style>
.content {
<style scoped>
.page {
margin: 0 auto;
padding: 0.025rem 2.5rem 2rem;
/* if this is moved to a variable, add it to BuySellAds.vue */
padding: 0 1.5rem 4rem;
max-width: 50rem;
}
.content a {
color: var(--accent-color);
}
.content a:hover {
text-decoration: underline;
}
.content img {
max-width: 100%;
.content {
padding-bottom: 1.5rem;
}
/*
.content div > h1:first-child, .content div > h2:first-child {
margin-top: 0;
} */
</style>

@ -1,83 +0,0 @@
import { computed } from 'vue'
import OutboundLink from './icons/OutboundLink.vue'
import { endingSlashRE, isExternal } from '../utils'
import { useRoute, useSiteData } from 'vitepress'
import { DefaultTheme } from '../config'
function createEditLink(
repo: string,
docsRepo: string,
docsDir: string,
docsBranch: string,
path: string
) {
const bitbucket = /bitbucket.org/
if (bitbucket.test(repo)) {
const base = isExternal(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 = isExternal(docsRepo)
? docsRepo
: `https://github.com/${docsRepo}`
return (
base.replace(endingSlashRE, '') +
`/edit` +
`/${docsBranch}/` +
(docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '') +
path
)
}
export default {
components: {
OutboundLink
},
setup() {
const route = useRoute()
const siteData = useSiteData<DefaultTheme.Config>()
const editLink = computed(() => {
const pageData = route.data
const showEditLink: boolean | undefined =
pageData.frontmatter.editLink == null
? siteData.value.themeConfig.editLinks
: pageData.frontmatter.editLink
const {
repo,
docsDir = '',
docsBranch = 'master',
docsRepo = repo
} = siteData.value.themeConfig
const { relativePath } = pageData
if (showEditLink && relativePath && repo) {
return createEditLink(
repo,
docsRepo || repo,
docsDir,
docsBranch,
relativePath
)
}
return null
})
const editLinkText = computed(
() => siteData.value.themeConfig.editLinkText || 'Edit this page'
)
return {
editLink,
editLinkText
}
}
}

@ -1,28 +0,0 @@
<template>
<footer class="page-edit">
<a
v-if="editLink"
:href="editLink"
target="_blank"
rel="noopener noreferrer"
>
{{ editLinkText }}
<OutboundLink />
</a>
</footer>
</template>
<script src="./PageEdit"></script>
<style>
.page-edit {
padding-top: 1rem;
padding-bottom: 1rem;
overflow: auto;
}
.page-edit a {
color: var(--text-color);
margin-right: 0.25rem;
}
</style>

@ -0,0 +1,5 @@
<template functional>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M19,11H7.4l5.3-5.3c0.4-0.4,0.4-1,0-1.4s-1-0.4-1.4,0l-7,7c-0.1,0.1-0.2,0.2-0.2,0.3c-0.1,0.2-0.1,0.5,0,0.8c0.1,0.1,0.1,0.2,0.2,0.3l7,7c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3c0.4-0.4,0.4-1,0-1.4L7.4,13H19c0.6,0,1-0.4,1-1S19.6,11,19,11z" />
</svg>
</template>

@ -0,0 +1,5 @@
<template functional>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M19.9,12.4c0.1-0.2,0.1-0.5,0-0.8c-0.1-0.1-0.1-0.2-0.2-0.3l-7-7c-0.4-0.4-1-0.4-1.4,0s-0.4,1,0,1.4l5.3,5.3H5c-0.6,0-1,0.4-1,1s0.4,1,1,1h11.6l-5.3,5.3c-0.4,0.4-0.4,1,0,1.4c0.2,0.2,0.5,0.3,0.7,0.3s0.5-0.1,0.7-0.3l7-7C19.8,12.6,19.9,12.5,19.9,12.4z" />
</svg>
</template>

@ -0,0 +1,91 @@
import { computed } from 'vue'
import { useSiteDataByRoute, usePageData } from 'vitepress'
import { endingSlashRE, isNullish, isExternal } from '../utils'
const bitbucketRE = /bitbucket.org/
export function useEditLink() {
const site = useSiteDataByRoute()
const page = usePageData()
const url = computed(() => {
const showEditLink = isNullish(page.value.frontmatter.editLink)
? site.value.themeConfig.editLinks
: page.value.frontmatter.editLink
const {
repo,
docsDir = '',
docsBranch = 'master',
docsRepo = repo
} = site.value.themeConfig
const { relativePath } = page.value
if (!showEditLink || !relativePath || !repo) {
return null
}
return createUrl(repo, docsRepo, docsDir, docsBranch, relativePath)
})
const text = computed(() => {
return site.value.themeConfig.editLinkText || 'Edit this page'
})
return {
url,
text
}
}
function createUrl(
repo: string,
docsRepo: string,
docsDir: string,
docsBranch: string,
path: string
): string {
return bitbucketRE.test(repo)
? createBitbucketUrl(repo, docsRepo, docsDir, docsBranch, path)
: createGitHubUrl(repo, docsRepo, docsDir, docsBranch, path)
}
function createGitHubUrl(
repo: string,
docsRepo: string,
docsDir: string,
docsBranch: string,
path: string
): string {
const base = isExternal(docsRepo)
? docsRepo
: `https://github.com/${docsRepo}`
return (
base.replace(endingSlashRE, '') +
`/edit` +
`/${docsBranch}/` +
(docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '') +
path
)
}
function createBitbucketUrl(
repo: string,
docsRepo: string,
docsDir: string,
docsBranch: string,
path: string
): string {
const base = isExternal(docsRepo) ? docsRepo : repo
return (
base.replace(endingSlashRE, '') +
`/src` +
`/${docsBranch}/` +
(docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '') +
path +
`?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
)
}

@ -0,0 +1,59 @@
import { computed } from 'vue'
import { useRoute, useSiteData } from 'vitepress'
import { DefaultTheme } from '../config'
export function useNextAndPrevLinks() {
const route = useRoute()
// TODO: could this be useSiteData<DefaultTheme.Config> or is the siteData
// resolved and has a different structure?
const siteData = useSiteData()
const resolveLink = (targetLink: string) => {
let target: DefaultTheme.SideBarLink | undefined
Object.keys(siteData.value.themeConfig.sidebar).some((k) => {
return siteData.value.themeConfig.sidebar[k].some(
(v: { children: any }) => {
if (Array.isArray(v.children)) {
target = v.children.find((value: any) => {
return value.link === targetLink
})
}
return !!target
}
)
})
return target
}
const next = computed(() => {
const pageData = route.data
if (pageData.frontmatter.next === false) {
return undefined
}
if (typeof pageData.frontmatter.next === 'string') {
return resolveLink(pageData.frontmatter.next)
}
return pageData.next
})
const prev = computed(() => {
const pageData = route.data
if (pageData.frontmatter.prev === false) {
return undefined
}
if (typeof pageData.frontmatter.prev === 'string') {
return resolveLink(pageData.frontmatter.prev)
}
return pageData.prev
})
const hasLinks = computed(() => {
return !!next.value || !!prev.value
})
return {
next,
prev,
hasLinks
}
}

@ -157,10 +157,6 @@ main {
}
}
a {
text-decoration: none;
}
h1,
h2,
h3,
@ -189,7 +185,13 @@ h6:focus .header-anchor {
}
h1 {
font-size: 2.2rem;
font-size: 1.9rem;
}
@media screen and (min-width: 420px) {
h1 {
font-size: 2.2rem;
}
}
h2 {
@ -206,12 +208,27 @@ h4 {
font-size: 1.15rem;
}
p,
ol,
ul {
line-height: 1.7;
}
a {
text-decoration: none;
color: var(--accent-color);
}
a:hover {
text-decoration: underline;
}
a.header-anchor {
font-size: 0.85em;
float: left;
margin-left: -0.87em;
padding-right: 0.23em;
margin-top: 0.125em;
margin-top: .125em;
margin-left: -.87em;
padding-right: .23em;
font-size: .85em;
opacity: 0;
}
@ -220,10 +237,8 @@ a.header-anchor:focus {
text-decoration: none;
}
p,
ol,
ul {
line-height: 1.7;
img {
max-width: 100%;
}
ul,

@ -5,6 +5,10 @@ export const extRE = /(index)?\.(md|html)$/
export const endingSlashRE = /\/$/
export const outboundRE = /^[a-z]+:/i
export function isNullish(value: any): value is null | undefined {
return value === null || value === undefined
}
export function withBase(path: string) {
return (useSiteData().value.base + path).replace(/\/+/g, '/')
}

Loading…
Cancel
Save