Merge branch 'vuejs:main' into main

pull/714/head
zRains 3 years ago committed by GitHub
commit 26ee6f24aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -16,8 +16,7 @@ export default defineConfig({
},
editLink: {
repo: 'vuejs/vitepress',
dir: 'docs',
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'Edit this page on GitHub'
},

@ -76,6 +76,19 @@ type Head =
| [string, Record<string, string>, string]
```
## lastUpdated
- Type: `boolean`
- Default: `true`
Whether to display [Last Updated](../guide/theme-last-updated) text in the current page.
```yaml
---
lastUpdated: false
---
```
## layout
- Type: `doc | home | page`

@ -188,6 +188,30 @@ export interface Footer {
}
```
## editLink
- Type: `EditLink`
Edit Link lets you display a link to edit the page on Git management services such as GitHub, or GitLab. See [Theme: Edit Link](../guide/theme-edit-link) for more details.
```js
export default {
themeConfig: {
editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'Edit this page on GitHub'
}
}
}
```
```ts
export interface EditLink {
pattern: string
text?: string
}
```
## lastUpdatedText
- Type: `string`

@ -1,3 +1,28 @@
# Edit Link
Documentation coming soon...
Edit Link lets you display a link to edit the page on Git management services such as GitHub, or GitLab. To enable it, add `themeConfig.editLink` options to your config.
```js
export default {
themeConfig: {
editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path'
}
}
}
```
The `pattern` option defines the URL structure for the link, and `:path` is going to be replaced with the page path.
By default, this will add the link text "Edit this page" at the bottom of the doc page. You may customize this text by defining the `text` option.
```js
export default {
themeConfig: {
editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'Edit this page on GitHub'
}
}
}
```

@ -68,7 +68,7 @@ export default {
## Multiple Sidebars
You may show different sidebar depending on the page path. For example, as shown on this site, you might want to create a separate sections of content in your documentation like "Guide" page and `Config` page.
You may show different sidebar depending on the page path. For example, as shown on this site, you might want to create a separate sections of content in your documentation like "Guide" page and "Config" page.
To do so, first organize your pages into directories for each desired section:
@ -92,7 +92,8 @@ export default {
sidebar: {
// This sidebar gets displayed when user is
// under `guide` directory.
'/guide/': {
'/guide/': [
{
text: 'Guide',
items: [
// This shows `/guide/index.md` page.
@ -100,19 +101,22 @@ export default {
{ text: 'One', link: '/guide/one' }, // /guide/one.md
{ text: 'Two', link: '/guide/two' } // /guide/two.md
]
},
}
],
// This sidebar gets displayed when user is
// under `config` directory.
'/config/': {
'/config/': [
{
text: 'Config',
items: [
// This shows `/guide/index.md` page.
{ text: 'Index', link: '/config/' }, // /config/index.mdasdfasdfasdfasdfaf
{ text: 'Index', link: '/config/' }, // /config/index.md
{ text: 'Three', link: '/config/three' }, // /config/three.md
{ text: 'Four', link: '/config/four' } // /config/four.md
]
}
]
}
}
}

@ -1,5 +1,6 @@
<script setup lang="ts">
import { computed } from 'vue'
import { withBase } from 'vitepress'
const props = defineProps<{
tag?: string
@ -30,7 +31,7 @@ const component = computed(() => {
:is="component"
class="VPButton"
:class="classes"
:href="href"
:href="href ? withBase(href) : undefined"
:target="isExternal ? '_blank' : undefined"
:rel="isExternal ? 'noopener noreferrer' : undefined"
>

@ -1,16 +1,13 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useData } from 'vitepress'
import { useRoute } from 'vitepress'
import { useSidebar } from '../composables/sidebar'
import VPDocAside from './VPDocAside.vue'
import VPDocFooter from './VPDocFooter.vue'
const { page } = useData()
const { path } = useRoute()
const { hasSidebar } = useSidebar()
const pageName = computed(() => {
return page.value.relativePath.slice(0, page.value.relativePath.indexOf('/'))
})
const pageName = path.replace(/[./]+/g, '_').replace(/_html$/, '')
</script>
<template>

@ -7,7 +7,7 @@ import {
useActiveAnchor
} from '../composables/outline'
const { page, frontmatter } = useData()
const { page, frontmatter, theme } = useData()
const { hasOutline } = useOutline()
@ -32,7 +32,9 @@ function handleClick({ target: el }: Event) {
<div class="content">
<div class="outline-marker" ref="marker" />
<div class="outline-title">On this page</div>
<div class="outline-title">
{{ theme.outlineTitle || 'On this page' }}
</div>
<nav aria-labelledby="doc-outline-aria-label">
<span class="visually-hidden" id="doc-outline-aria-label">

@ -1,4 +1,5 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useData } from 'vitepress'
import { normalizeLink } from '../support/utils'
import { useEditLink } from '../composables/edit-link'
@ -11,6 +12,10 @@ const { theme, page, frontmatter } = useData()
const editLink = useEditLink()
const control = usePrevNext()
const hasLastUpdated = computed(() => {
return page.value.lastUpdated && frontmatter.value.lastUpdated !== false
})
</script>
<template>
@ -23,7 +28,7 @@ const control = usePrevNext()
</VPLink>
</div>
<div v-if="page.lastUpdated" class="last-updated">
<div v-if="hasLastUpdated" class="last-updated">
<VPDocFooterLastUpdated />
</div>
</div>
@ -58,21 +63,18 @@ const control = usePrevNext()
.edit-info {
display: flex;
justify-content: space-between;
align-items: baseline;
align-items: center;
padding-bottom: 14px;
}
}
.edit-link {
line-height: 32px;
font-size: 14px;
font-weight: 500;
}
.edit-link-button {
display: flex;
align-items: center;
border: 0;
line-height: 32px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-brand);
transition: color 0.25s;
}

@ -98,7 +98,7 @@ function onBlur() {
display: flex;
align-items: center;
line-height: var(--vp-nav-height-mobile);
font-size: 13px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-1);
transition: color 0.25s;

@ -12,6 +12,8 @@ import VPHomeFeatures from './VPHomeFeatures.vue'
<slot name="home-features-before" />
<VPHomeFeatures />
<slot name="home-features-after" />
<Content />
</div>
</template>

@ -33,8 +33,13 @@ provide('close-screen', closeScreen)
}
.VPNav.no-sidebar {
backdrop-filter: saturate(50%) blur(8px);
-webkit-backdrop-filter: saturate(50%) blur(8px);
backdrop-filter: saturate(50%) blur(8px);
background: rgba(255, 255, 255, 0.7);
}
.dark .VPNav.no-sidebar {
background: rgba(36, 36, 36, 0.7);
}
@supports not (backdrop-filter: saturate(50%) blur(8px)) {

@ -65,8 +65,15 @@ const { hasSidebar } = useSidebar()
}
.VPNavBar.has-sidebar .content {
backdrop-filter: saturate(50%) blur(8px);
margin-right: -32px;
padding-right: 32px;
-webkit-backdrop-filter: saturate(50%) blur(8px);
backdrop-filter: saturate(50%) blur(8px);
background: rgba(255, 255, 255, 0.7);
}
.dark .VPNavBar.has-sidebar .content {
background: rgba(36, 36, 36, 0.7);
}
@supports not (backdrop-filter: saturate(50%) blur(8px)) {

@ -8,7 +8,7 @@ const { hasSidebar } = useSidebar()
<template>
<div class="VPNavBarTitle" :class="{ 'has-sidebar': hasSidebar }">
<a class="title" href="/">
<a class="title" :href="site.base">
<img v-if="theme.logo" class="logo" :src="theme.logo">
<template v-if="theme.siteTitle">{{ theme.siteTitle }}</template>
<template v-else-if="theme.siteTitle === undefined">{{ site.title }}</template>

@ -6,7 +6,7 @@ import VPIconMinusSquare from './icons/VPIconMinusSquare.vue'
import VPSidebarLink from './VPSidebarLink.vue'
const props = defineProps<{
text: string
text?: string
items: DefaultTheme.SidebarItem[]
collapsible?: boolean
collapsed?: boolean
@ -23,7 +23,12 @@ function toggle() {
<template>
<section class="VPSidebarGroup" :class="{ collapsible, collapsed }">
<div class="title" :role="collapsible ? 'button' : undefined" @click="toggle">
<div
v-if="text"
class="title"
:role="collapsible ? 'button' : undefined"
@click="toggle"
>
<h2 class="title-text">{{ text }}</h2>
<div class="action">
<VPIconMinusSquare class="icon minus" />

@ -3,6 +3,7 @@ import { inject } from 'vue'
import { useData } from 'vitepress'
import { DefaultTheme } from '../config'
import { isActive, normalizeLink } from '../support/utils'
import VPLink from './VPLink.vue'
defineProps<{
item: DefaultTheme.SidebarItem
@ -14,37 +15,40 @@ const closeSideBar = inject('close-sidebar') as () => void
</script>
<template>
<a
class="link"
<VPLink
:class="{ active: isActive(page.relativePath, item.link) }"
:href="normalizeLink(item.link)"
@click="closeSideBar"
>
<p class="link-text">{{ item.text }}</p>
</a>
<span class="link-text">{{ item.text }}</span>
</VPLink>
</template>
<style scoped>
.link {
display: block;
padding: 6px 0;
padding: 4px 0;
color: var(--vp-c-text-2);
transition: color 0.5s;
}
.link:hover .link-text {
.link:hover {
color: var(--vp-c-text-1);
transition: color 0.25s;
}
.link.active .link-text {
.link.active {
color: var(--vp-c-brand);
transition: color 0.25s;
}
.link :deep(.icon) {
width: 12px;
height: 12px;
fill: currentColor;
}
.link-text {
line-height: 20px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-2);
transition: color 0.5s;
}
</style>

@ -5,22 +5,10 @@ export function useEditLink() {
const { theme, page } = useData()
return computed(() => {
const url = [
'https://github.com',
theme.value.editLink?.repo || '???',
'edit',
theme.value.editLink?.branch || 'main',
theme.value.editLink?.dir || null,
page.value.relativePath
]
.filter((v) => v)
.join('/')
const { text = 'Edit this page', pattern } = theme.value.editLink || {}
const { relativePath } = page.value
const url = pattern.replace(/:path/g, relativePath)
const text = theme.value.editLink?.text ?? 'Edit this page'
return {
url,
text
}
return { url, text }
})
}

@ -102,11 +102,10 @@ export async function renderPage(
const title: string = createTitle(siteData, pageData)
const description: string = pageData.description || siteData.description
const head = addSocialTags(
title,
const head = [
...siteData.head,
...filterOutHeadDescription(pageData.frontmatter.head)
)
]
let inlinedScript = ''
if (config.mpa && result) {
@ -219,20 +218,3 @@ function isMetaDescription(headConfig: HeadConfig) {
function filterOutHeadDescription(head: HeadConfig[] | undefined) {
return head ? head.filter((h) => !isMetaDescription(h)) : []
}
function hasTag(head: HeadConfig[], tag: HeadConfig) {
const [tagType, tagAttrs] = tag
const [attr, value] = Object.entries(tagAttrs)[0] // First key
return head.some(([type, attrs]) => type === tagType && attrs[attr] === value)
}
function addSocialTags(title: string, ...head: HeadConfig[]) {
const tags: HeadConfig[] = [
['meta', { name: 'twitter:title', content: title }],
['meta', { property: 'og:title', content: title }]
]
tags.filter((tagAttrs) => {
if (!hasTag(head, tagAttrs)) head.push(tagAttrs)
})
return head
}

@ -162,8 +162,9 @@ export async function createMarkdownToVueRenderFn(
}
const scriptRE = /<\/script>/
const scriptLangTsRE = /<\s*script[^>]*\blang=['"]ts['"][^>]*/
const scriptSetupRE = /<\s*script[^>]*\bsetup\b[^>]*/
const scriptClientRe = /<\s*script[^>]*\bclient\b[^>]*/
const scriptClientRE = /<\s*script[^>]*\bclient\b[^>]*/
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
@ -176,10 +177,12 @@ function genPageDataCode(tags: string[], data: PageData) {
return (
scriptRE.test(tag) &&
!scriptSetupRE.test(tag) &&
!scriptClientRe.test(tag)
!scriptClientRE.test(tag)
)
})
const isUsingTS = tags.findIndex((tag) => scriptLangTsRE.test(tag)) > -1
if (existingScriptIndex > -1) {
const tagSrc = tags[existingScriptIndex]
// user has <script> tag inside markdown
@ -196,7 +199,9 @@ function genPageDataCode(tags: string[], data: PageData) {
)
} else {
tags.unshift(
`<script>${code}\nexport default {name:'${data.relativePath}'}</script>`
`<script ${isUsingTS ? 'lang="ts"' : ''}>${code}\nexport default {name:'${
data.relativePath
}'}</script>`
)
}

@ -13,6 +13,13 @@ export namespace DefaultTheme {
*/
siteTitle?: string | false
/**
* Custom outline title in the aside component.
*
* @default 'On this page'
*/
outlineTitle?: string
/**
* The nav items.
*/
@ -96,7 +103,7 @@ export namespace DefaultTheme {
}
export interface SidebarGroup {
text: string
text?: string
items: SidebarItem[]
/**
@ -123,25 +130,11 @@ export namespace DefaultTheme {
export interface EditLink {
/**
* Repo of the site.
*
* @example 'vuejs/docs'
*/
repo: string
/**
* Branch of the repo.
*
* @default 'main'
*/
branch?: string
/**
* If your docs are not at the root of the repo.
* Pattern for edit link.
*
* @example 'docs'
* @example 'https://github.com/vuejs/vitepress/edit/main/docs/:path'
*/
dir?: string
pattern: string
/**
* Custom text for edit link.

Loading…
Cancel
Save