mirror of https://github.com/vuejs/vitepress
refactor: migrate default theme to use script-setup (#137)
Co-authored-by: Kia King Ishii <kia.king.08@gmail.com>pull/156/head
parent
136a56e74d
commit
b127aeeaf1
@ -1,77 +0,0 @@
|
||||
import { defineComponent, computed, PropType } from 'vue'
|
||||
import { useRoute } from 'vitepress'
|
||||
import { withBase, isExternal } from '../utils'
|
||||
import { DefaultTheme } from '../config'
|
||||
import OutboundLink from './icons/OutboundLink.vue'
|
||||
|
||||
const normalizePath = (path: string): string => {
|
||||
path = path
|
||||
.replace(/#.*$/, '')
|
||||
.replace(/\?.*$/, '')
|
||||
.replace(/\.html$/, '')
|
||||
if (path.endsWith('/')) {
|
||||
path += 'index'
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
OutboundLink
|
||||
},
|
||||
|
||||
props: {
|
||||
item: {
|
||||
type: Object as PropType<DefaultTheme.NavItemWithLink>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
setup(props) {
|
||||
const item = props.item
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const classes = computed(() => ({
|
||||
active: isActiveLink.value,
|
||||
external: isExternalLink.value
|
||||
}))
|
||||
|
||||
const isActiveLink = computed(() => {
|
||||
return normalizePath(withBase(item.link)) === normalizePath(route.path)
|
||||
})
|
||||
|
||||
const isExternalLink = computed(() => {
|
||||
return isExternal(item.link)
|
||||
})
|
||||
|
||||
const href = computed(() => {
|
||||
return isExternalLink.value ? item.link : withBase(item.link)
|
||||
})
|
||||
|
||||
const target = computed(() => {
|
||||
if (item.target) {
|
||||
return item.target
|
||||
}
|
||||
|
||||
return isExternalLink.value ? '_blank' : ''
|
||||
})
|
||||
|
||||
const rel = computed(() => {
|
||||
if (item.rel) {
|
||||
return item.rel
|
||||
}
|
||||
|
||||
return isExternalLink.value ? 'noopener noreferrer' : ''
|
||||
})
|
||||
|
||||
return {
|
||||
classes,
|
||||
isActiveLink,
|
||||
isExternalLink,
|
||||
href,
|
||||
target,
|
||||
rel
|
||||
}
|
||||
}
|
||||
})
|
@ -1,101 +0,0 @@
|
||||
import { computed } from 'vue'
|
||||
import { useSiteData, useSiteDataByRoute, useRoute } from 'vitepress'
|
||||
import { inBrowser } from '/@app/utils'
|
||||
import NavBarLink from './NavBarLink.vue'
|
||||
import NavDropdownLink from './NavDropdownLink.vue'
|
||||
import { DefaultTheme } from '../config'
|
||||
|
||||
const platforms = ['GitHub', 'GitLab', 'Bitbucket'].map(
|
||||
(platform) => [platform, new RegExp(platform, 'i')] as const
|
||||
)
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NavBarLink,
|
||||
NavDropdownLink
|
||||
},
|
||||
|
||||
setup() {
|
||||
const siteDataByRoute = useSiteDataByRoute()
|
||||
const siteData = useSiteData()
|
||||
const route = useRoute()
|
||||
const repoInfo = computed(() => {
|
||||
const theme = siteData.value.themeConfig as DefaultTheme.Config
|
||||
const repo = theme.docsRepo || theme.repo
|
||||
let text: string | undefined = theme.repoLabel
|
||||
|
||||
if (repo) {
|
||||
const link = /^https?:/.test(repo) ? repo : `https://github.com/${repo}`
|
||||
if (!text) {
|
||||
// if no label is provided, deduce it from the repo url
|
||||
const repoHosts = link.match(/^https?:\/\/[^/]+/)
|
||||
if (repoHosts) {
|
||||
const repoHost = repoHosts[0]
|
||||
const foundPlatform = platforms.find(([_platform, re]) =>
|
||||
re.test(repoHost)
|
||||
)
|
||||
text = foundPlatform && foundPlatform[0]
|
||||
}
|
||||
}
|
||||
|
||||
return { link, text: text || 'Source' }
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const localeCandidates = computed(() => {
|
||||
const locales = siteData.value.themeConfig.locales
|
||||
if (!locales) {
|
||||
return null
|
||||
}
|
||||
const localeKeys = Object.keys(locales)
|
||||
if (localeKeys.length <= 1) {
|
||||
return null
|
||||
}
|
||||
|
||||
// handle site base
|
||||
const siteBase = inBrowser ? siteData.value.base : '/'
|
||||
const siteBaseWithoutSuffix = siteBase.endsWith('/')
|
||||
? siteBase.slice(0, -1)
|
||||
: siteBase
|
||||
// remove site base in browser env
|
||||
const routerPath = route.path.slice(siteBaseWithoutSuffix.length)
|
||||
|
||||
const currentLangBase = localeKeys.find((v) => {
|
||||
if (v === '/') {
|
||||
return false
|
||||
}
|
||||
return routerPath.startsWith(v)
|
||||
})
|
||||
const currentContentPath = currentLangBase
|
||||
? routerPath.substring(currentLangBase.length - 1)
|
||||
: routerPath
|
||||
const candidates = localeKeys.map((v) => {
|
||||
const localePath = v.endsWith('/') ? v.slice(0, -1) : v
|
||||
return {
|
||||
text: locales[v].label || locales[v].lang,
|
||||
link: `${localePath}${currentContentPath}`
|
||||
}
|
||||
})
|
||||
|
||||
const currentLangKey = currentLangBase ? currentLangBase : '/'
|
||||
const selectText = locales[currentLangKey].selectText
|
||||
? locales[currentLangKey].selectText
|
||||
: 'Languages'
|
||||
return {
|
||||
text: selectText,
|
||||
items: candidates
|
||||
}
|
||||
})
|
||||
|
||||
const navData = computed(() => {
|
||||
return siteDataByRoute.value.themeConfig.nav
|
||||
})
|
||||
|
||||
return {
|
||||
navData,
|
||||
repoInfo,
|
||||
localeCandidates
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
import NavBarLink from './NavBarLink.vue'
|
||||
import { defineComponent, ref, watch, PropType } from 'vue'
|
||||
import { useRoute } from 'vitepress'
|
||||
import { DefaultTheme } from '../config'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DropdownLink',
|
||||
components: {
|
||||
NavBarLink
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object as PropType<DefaultTheme.NavItemWithChildren>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const open = ref(false)
|
||||
const route = useRoute()
|
||||
|
||||
watch(
|
||||
() => route.path,
|
||||
() => {
|
||||
open.value = false
|
||||
}
|
||||
)
|
||||
|
||||
const setOpen = (value: boolean) => {
|
||||
open.value = value
|
||||
}
|
||||
|
||||
const isLastItemOfArray = <T>(item: T, array: T[]) => {
|
||||
return array.length && array.indexOf(item) === array.length - 1
|
||||
}
|
||||
|
||||
return {
|
||||
open,
|
||||
setOpen,
|
||||
isLastItemOfArray
|
||||
}
|
||||
}
|
||||
})
|
@ -1,29 +1,12 @@
|
||||
<template>
|
||||
<ul v-if="items.length > 0" class="sidebar-links">
|
||||
<SideBarLink
|
||||
v-for="item of items"
|
||||
:key="item.text"
|
||||
:item="item"
|
||||
/>
|
||||
<SideBarLink v-for="item of items" :key="item.text" :item="item" />
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
<script setup lang="ts">
|
||||
import { useSideBar } from '../composables/sideBar'
|
||||
import { SideBarLink } from './SideBarLink'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SideBarLink
|
||||
},
|
||||
|
||||
setup() {
|
||||
const items = useSideBar()
|
||||
|
||||
return {
|
||||
items
|
||||
}
|
||||
}
|
||||
})
|
||||
const items = useSideBar()
|
||||
</script>
|
||||
|
Loading…
Reference in new issue