Merge branch 'main' into clean-urls-for-alpha

pull/869/head
Georges Gomes 3 years ago committed by GitHub
commit 95e7a83e97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,7 @@
import { defineConfig } from '../../src/node' import { defineConfig } from '../../src/node'
import { version } from '../../package.json'
export default defineConfig({ export default defineConfig({
lang: 'en-US', lang: 'en-US',
title: 'VitePress', title: 'VitePress',
@ -48,9 +50,18 @@ function nav() {
{ text: 'Guide', link: '/guide/what-is-vitepress', activeMatch: '/guide/' }, { text: 'Guide', link: '/guide/what-is-vitepress', activeMatch: '/guide/' },
{ text: 'Configs', link: '/config/introduction', activeMatch: '/config/' }, { text: 'Configs', link: '/config/introduction', activeMatch: '/config/' },
{ {
text: 'Changelog', text: version,
link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md' items: [
} {
text: 'Changelog',
link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md'
},
{
text: 'Contributing',
link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md'
},
],
},
] ]
} }

@ -247,9 +247,33 @@ export default {
```ts ```ts
export interface CarbonAds { export interface CarbonAds {
code: string, code: string
placement: string placement: string
} }
``` ```
Learn more in [Theme: Carbon Ads](../guide/theme-carbon-ads) Learn more in [Theme: Carbon Ads](../guide/theme-carbon-ads)
## docFooter
- Type: `DocFooter`
Can be used to customize text appearing above previous and next links. Helpful if not writing docs in English.
```js
export default {
themeConfig: {
docFooter: {
prev: 'Pagina prior',
next: 'Proxima pagina'
}
}
}
```
```ts
export interface DocFooter {
prev?: string
next?: string
}
```

@ -51,7 +51,7 @@ export default {
} }
``` ```
The `text` is the actual text displayed in nav, and the `link` is the link that will be navigated to when the text is clicked. For the link, set path to the actual file without `.md` prefix, and alsways start with `/`. The `text` is the actual text displayed in nav, and the `link` is the link that will be navigated to when the text is clicked. For the link, set path to the actual file without `.md` prefix, and always start with `/`.
Nav links can also be dropdown menus. To do this, set `items` key on link option. Nav links can also be dropdown menus. To do this, set `items` key on link option.

@ -1,3 +1,29 @@
# Prev Next Link # Prev Next Link
Documentation coming soon... You can customize the text of previous and next links. This is helpful if you want to show different text on previous/next links than what you have on your sidebar.
## prev
- Type: `string`
- Details:
Specify the text to show on the link to the previous page.
If you don't set this in frontmatter, the text will be inferred from the sidebar config.
- Example:
```yaml
---
prev: 'Get Started | Markdown'
---
```
## next
- Type: `string`
- Details:
Same as `prev` but for the next page.

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { provide } from 'vue' import { provide, watch } from 'vue'
import { useRoute } from 'vitepress'
import { useSidebar, useCloseSidebarOnEscape } from './composables/sidebar' import { useSidebar, useCloseSidebarOnEscape } from './composables/sidebar'
import VPSkipLink from './components/VPSkipLink.vue' import VPSkipLink from './components/VPSkipLink.vue'
import VPBackdrop from './components/VPBackdrop.vue' import VPBackdrop from './components/VPBackdrop.vue'
@ -15,6 +16,9 @@ const {
close: closeSidebar close: closeSidebar
} = useSidebar() } = useSidebar()
const route = useRoute()
watch(() => route.path, closeSidebar)
useCloseSidebarOnEscape(isSidebarOpen, closeSidebar) useCloseSidebarOnEscape(isSidebarOpen, closeSidebar)
provide('close-sidebar', closeSidebar) provide('close-sidebar', closeSidebar)

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

@ -36,13 +36,13 @@ const hasLastUpdated = computed(() => {
<div v-if="control.prev || control.next" class="prev-next"> <div v-if="control.prev || control.next" class="prev-next">
<div class="pager"> <div class="pager">
<a v-if="control.prev" class="pager-link prev" :href="normalizeLink(control.prev.link, site.cleanUrls)"> <a v-if="control.prev" class="pager-link prev" :href="normalizeLink(control.prev.link, site.cleanUrls)">
<span class="desc">Previous page</span> <span class="desc">{{ theme.docFooter?.prev ?? 'Previous page' }}</span>
<span class="title">{{ control.prev.text }} </span> <span class="title">{{ control.prev.text }} </span>
</a> </a>
</div> </div>
<div class="pager" :class="{ 'has-prev': control.prev }"> <div class="pager" :class="{ 'has-prev': control.prev }">
<a v-if="control.next" class="pager-link next" :href="normalizeLink(control.next.link, site.cleanUrls)"> <a v-if="control.next" class="pager-link next" :href="normalizeLink(control.next.link, site.cleanUrls)">
<span class="desc">Next page</span> <span class="desc">{{ theme.docFooter?.next ?? 'Next page' }}</span>
<span class="title">{{ control.next.text }}</span> <span class="title">{{ control.next.text }}</span>
</a> </a>
</div> </div>

@ -1,5 +1,5 @@
import type { DefaultTheme } from 'vitepress/theme' import type { DefaultTheme } from 'vitepress/theme'
import { ref, computed } from 'vue' import { ref, computed, watch } from 'vue'
import { useData, useRoute } from 'vitepress' import { useData, useRoute } from 'vitepress'
export function useNav() { export function useNav() {
@ -26,6 +26,9 @@ export function useNav() {
window.outerWidth >= 768 && closeScreen() window.outerWidth >= 768 && closeScreen()
} }
const route = useRoute()
watch(() => route.path, closeScreen)
return { return {
isScreenOpen, isScreenOpen,
openScreen, openScreen,

@ -4,7 +4,7 @@ import { isActive } from '../support/utils'
import { getSidebar, getFlatSideBarLinks } from '../support/sidebar' import { getSidebar, getFlatSideBarLinks } from '../support/sidebar'
export function usePrevNext() { export function usePrevNext() {
const { page, theme } = useData() const { page, theme, frontmatter } = useData()
return computed(() => { return computed(() => {
const sidebar = getSidebar(theme.value.sidebar, page.value.relativePath) const sidebar = getSidebar(theme.value.sidebar, page.value.relativePath)
@ -15,8 +15,12 @@ export function usePrevNext() {
}) })
return { return {
prev: candidates[index - 1], prev: frontmatter.value.prev
next: candidates[index + 1] ? { ...candidates[index - 1], text: frontmatter.value.prev }
: candidates[index - 1],
next: frontmatter.value.next
? { ...candidates[index + 1], text: frontmatter.value.next }
: candidates[index + 1]
} }
}) })
} }

@ -1,5 +1,5 @@
import { Ref, ref, computed, watchEffect, onMounted, onUnmounted } from 'vue' import { computed, onMounted, onUnmounted, Ref, ref, watchEffect } from 'vue'
import { useRoute, useData } from 'vitepress' import { useData, useRoute } from 'vitepress'
import { getSidebar } from '../support/sidebar' import { getSidebar } from '../support/sidebar'
export function useSidebar() { export function useSidebar() {
@ -10,9 +10,7 @@ export function useSidebar() {
const sidebar = computed(() => { const sidebar = computed(() => {
const sidebarConfig = theme.value.sidebar const sidebarConfig = theme.value.sidebar
const relativePath = route.data.relativePath return sidebarConfig ? getSidebar(sidebarConfig, route.path) : []
return sidebarConfig ? getSidebar(sidebarConfig, relativePath) : []
}) })
const hasSidebar = computed(() => { const hasSidebar = computed(() => {

@ -35,14 +35,7 @@ export async function createMarkdownToVueRenderFn(
pages = pages.map((p) => slash(p.replace(/\.md$/, ''))) pages = pages.map((p) => slash(p.replace(/\.md$/, '')))
const userDefineRegex = userDefines const replaceRegex = genReplaceRegexp(userDefines, isBuild)
? new RegExp(
`\\b(${Object.keys(userDefines)
.map((key) => key.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))
.join('|')})`,
'g'
)
: null
return async ( return async (
src: string, src: string,
@ -75,24 +68,9 @@ export async function createMarkdownToVueRenderFn(
md.__path = file md.__path = file
md.__relativePath = relativePath md.__relativePath = relativePath
let html = md.render(content) const html = md.render(content)
const data = md.__data const data = md.__data
if (isBuild) {
// avoid env variables being replaced by vite
html = html
.replace(/\bimport\.meta/g, 'import.<wbr/>meta')
.replace(/\bprocess\.env/g, 'process.<wbr/>env')
// also avoid replacing vite user defines
if (userDefineRegex) {
html = html.replace(
userDefineRegex,
(_) => `${_[0]}<wbr/>${_.slice(1)}`
)
}
}
// validate data.links // validate data.links
const deadLinks: string[] = [] const deadLinks: string[] = []
const recordDeadLink = (url: string) => { const recordDeadLink = (url: string) => {
@ -150,8 +128,14 @@ export async function createMarkdownToVueRenderFn(
} }
const vueSrc = const vueSrc =
genPageDataCode(data.hoistedTags || [], pageData).join('\n') + genPageDataCode(data.hoistedTags || [], pageData, replaceRegex).join(
`\n<template><div>${html}</div></template>` '\n'
) +
`\n<template><div>${replaceConstants(
html,
replaceRegex,
vueTemplateBreaker
)}</div></template>`
debug(`[render] ${file} in ${Date.now() - start}ms.`) debug(`[render] ${file} in ${Date.now() - start}ms.`)
@ -172,10 +156,42 @@ 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 defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/ const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
const jsStringBreaker = '\u200b'
const vueTemplateBreaker = '<wbr>'
function genReplaceRegexp(
userDefines: Record<string, any> = {},
isBuild: boolean
): RegExp {
// `process.env` need to be handled in both dev and build
// @see https://github.com/vitejs/vite/blob/cad27ee8c00bbd5aeeb2be9bfb3eb164c1b77885/packages/vite/src/node/plugins/clientInjections.ts#L57-L64
const replacements = ['process.env']
if (isBuild) {
replacements.push('import.meta', ...Object.keys(userDefines))
}
return new RegExp(
`\\b(${replacements
.map((key) => key.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))
.join('|')})`,
'g'
)
}
/**
* To avoid env variables being replaced by vite:
* - insert `'\u200b'` char into those strings inside js string (page data)
* - insert `<wbr>` tag into those strings inside html string (vue template)
*
* @see https://vitejs.dev/guide/env-and-mode.html#production-replacement
*/
function replaceConstants(str: string, replaceRegex: RegExp, breaker: string) {
return str.replace(replaceRegex, (_) => `${_[0]}${breaker}${_.slice(1)}`)
}
function genPageDataCode(tags: string[], data: PageData) { function genPageDataCode(tags: string[], data: PageData, replaceRegex: RegExp) {
const dataJson = JSON.stringify(data)
const code = `\nexport const __pageData = JSON.parse(${JSON.stringify( const code = `\nexport const __pageData = JSON.parse(${JSON.stringify(
JSON.stringify(data) replaceConstants(dataJson, replaceRegex, jsStringBreaker)
)})` )})`
const existingScriptIndex = tags.findIndex((tag) => { const existingScriptIndex = tags.findIndex((tag) => {

@ -43,6 +43,11 @@ export namespace DefaultTheme {
*/ */
lastUpdatedText?: string lastUpdatedText?: string
/**
* Set custom prev/next labels.
*/
docFooter?: DocFooter
/** /**
* The social links to be displayed at the end of the nav bar. Perfect for * The social links to be displayed at the end of the nav bar. Perfect for
* placing links to social services such as GitHub, Twitter, Facebook, etc. * placing links to social services such as GitHub, Twitter, Facebook, etc.
@ -157,6 +162,24 @@ export namespace DefaultTheme {
text?: string text?: string
} }
// prev-next -----------------------------------------------------------------
export interface DocFooter {
/**
* Custom label for previous page button.
*
* @default 'Previous page'
*/
prev?: string
/**
* Custom label for next page button.
*
* @default 'Next page'
*/
next?: string
}
// social link --------------------------------------------------------------- // social link ---------------------------------------------------------------
export interface SocialLink { export interface SocialLink {

Loading…
Cancel
Save