Merge branch 'main' into update-macros

pull/2498/head
丶远方 3 years ago committed by GitHub
commit 53d82825c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -30,6 +30,8 @@ After cloning the repo, run:
```sh
# install the dependencies of the project
$ pnpm install
# setup git hooks
$ pnpm simple-git-hooks
```
### Setup VitePress Dev Environment

@ -5,3 +5,5 @@ pnpm-lock.yaml
cache
template
temp
!CHANGELOG.md
.temp

File diff suppressed because it is too large Load Diff

@ -180,3 +180,8 @@ export default config
## Markdown At File Inclusion
<!--@include: @/markdown-extensions/bar.md-->
## Markdown Nested File Inclusion
<!--@include: ./nested-include.md-->

@ -63,7 +63,7 @@ describe('Table of Contents', () => {
test('render toc', async () => {
const items = page.locator('#table-of-contents + nav ul li')
const count = await items.count()
expect(count).toBe(24)
expect(count).toBe(27)
})
})
@ -233,4 +233,8 @@ describe('Markdown File Inclusion', () => {
const h1 = page.locator('#markdown-at-file-inclusion + h1')
expect(await h1.getAttribute('id')).toBe('bar')
})
test('render markdown using nested inclusion', async () => {
const h1 = page.locator('#markdown-nested-file-inclusion + h1')
expect(await h1.getAttribute('id')).toBe('foo-1')
})
})

@ -0,0 +1,3 @@
<!--@include: ./foo.md-->
### After Foo

@ -1,6 +1,12 @@
{
"name": "tests-e2e",
"private": true,
"type": "module",
"scripts": {
"test": "vitest run",
"watch": "DEBUG=1 vitest",
"site": "vitepress"
},
"devDependencies": {
"vitepress": "workspace:*"
}

@ -5,7 +5,7 @@ const timeout = 60_000
export default defineConfig({
test: {
setupFiles: ['vitestSetup.ts'],
globalSetup: ['__tests__/e2e/vitestGlobalSetup.ts'],
globalSetup: ['vitestGlobalSetup.ts'],
testTimeout: timeout,
hookTimeout: timeout,
teardownTimeout: timeout,

@ -7,7 +7,7 @@ import type { Server } from 'net'
let browserServer: BrowserServer
let server: ViteDevServer | Server
const root = '__tests__/e2e'
const root = '.'
export async function setup() {
browserServer = await chromium.launchServer({

@ -1,57 +1,50 @@
import { chromium, type Browser, type Page } from 'playwright-chromium'
import { fileURLToPath } from 'url'
import path from 'path'
import fs from 'fs-extra'
import {
scaffold,
build,
createServer,
serve,
ScaffoldThemeType,
type ScaffoldOptions
} from 'vitepress'
import type { ViteDevServer } from 'vite'
import type { Server } from 'net'
import getPort from 'get-port'
import { chromium } from 'playwright-chromium'
import { fileURLToPath, URL } from 'url'
import { createServer, scaffold, ScaffoldThemeType } from 'vitepress'
let browser: Browser
let page: Page
const root = fileURLToPath(new URL('./.temp', import.meta.url))
beforeAll(async () => {
browser = await chromium.connect(process.env['WS_ENDPOINT']!)
page = await browser.newPage()
const browser = await chromium.launch({
headless: !process.env.DEBUG,
args: process.env.CI
? ['--no-sandbox', '--disable-setuid-sandbox']
: undefined
})
const page = await browser.newPage()
const themes = [
ScaffoldThemeType.Default,
ScaffoldThemeType.DefaultCustom,
ScaffoldThemeType.Custom
]
const usingTs = [false, true]
const variations = themes.flatMap((theme) =>
usingTs.map(
(useTs) => [`${theme}${useTs ? ' + ts' : ''}`, { theme, useTs }] as const
)
)
afterAll(async () => {
await page.close()
await browser.close()
})
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'temp')
async function testVariation(options: ScaffoldOptions) {
fs.removeSync(root)
scaffold({
...options,
root
})
test.each(variations)('init %s', async (_, { theme, useTs }) => {
await fs.remove(root)
scaffold({ root, theme, useTs, injectNpmScripts: false })
let server: ViteDevServer | Server
const port = await getPort()
const server = await createServer(root, { port })
await server.listen()
async function goto(path: string) {
await page.goto(`http://localhost:${port}${path}`)
await page.waitForSelector('#app div')
}
if (process.env['VITE_TEST_BUILD']) {
await build(root)
server = (await serve({ root, port })).server
} else {
server = await createServer(root, { port })
await server!.listen()
}
try {
await goto('/')
expect(await page.textContent('h1')).toMatch('My Awesome Project')
@ -66,33 +59,10 @@ async function testVariation(options: ScaffoldOptions) {
await page.click('a[href="/api-examples.html"]')
await page.waitForSelector('pre code')
expect(await page.textContent('h1')).toMatch('Runtime API Examples')
// teardown
} finally {
fs.removeSync(root)
if ('ws' in server) {
await fs.remove(root)
await server.close()
} else {
await new Promise<void>((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()))
})
}
}
}
const themes = [
ScaffoldThemeType.Default,
ScaffoldThemeType.DefaultCustom,
ScaffoldThemeType.Custom
]
const usingTs = [false, true]
for (const theme of themes) {
for (const useTs of usingTs) {
test(`${theme}${useTs ? ` + TypeScript` : ``}`, () =>
testVariation({
root: '.',
theme,
useTs,
injectNpmScripts: false
}))
}
}
})

@ -1,6 +1,11 @@
{
"name": "tests-init",
"private": true,
"type": "module",
"scripts": {
"test": "vitest run",
"watch": "DEBUG=1 vitest"
},
"devDependencies": {
"vitepress": "workspace:*"
}

@ -1,20 +1,9 @@
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
import { defineConfig } from 'vitest/config'
const dir = dirname(fileURLToPath(import.meta.url))
const timeout = 60_000
export default defineConfig({
resolve: {
alias: {
node: resolve(dir, '../../src/node')
}
},
test: {
watchExclude: ['**/node_modules/**', '**/temp/**'],
globalSetup: ['__tests__/init/vitestGlobalSetup.ts'],
testTimeout: timeout,
hookTimeout: timeout,
teardownTimeout: timeout,

@ -1,17 +0,0 @@
import { chromium, type BrowserServer } from 'playwright-chromium'
let browserServer: BrowserServer
export async function setup() {
browserServer = await chromium.launchServer({
headless: !process.env.DEBUG,
args: process.env.CI
? ['--no-sandbox', '--disable-setuid-sandbox']
: undefined
})
process.env['WS_ENDPOINT'] = browserServer.wsEndpoint()
}
export async function teardown() {
await browserServer.close()
}

@ -1,17 +1,26 @@
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
const dir = dirname(fileURLToPath(import.meta.url))
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@siteData': resolve(dir, './shims.ts'),
client: resolve(dir, '../../src/client'),
node: resolve(dir, '../../src/node'),
vitepress: resolve(dir, '../../src/client')
alias: [
{ find: '@siteData', replacement: resolve(dir, './shims.ts') },
{ find: 'client', replacement: resolve(dir, '../../src/client') },
{ find: 'node', replacement: resolve(dir, '../../src/node') },
{
find: /^vitepress$/,
replacement: resolve(dir, '../../src/client/index.js')
},
{
find: /^vitepress\/theme$/,
replacement: resolve(dir, '../../src/client/theme-default/index.js')
}
]
},
test: {
globals: true

@ -696,10 +696,10 @@ You can also [import snippets](#import-code-snippets) in code groups:
## Markdown File Inclusion
You can include a markdown file in another markdown file.
You can include a markdown file in another markdown file, even nested.
::: tip
You can also prefix the markdown path with `@`, it will act as the source root. By default it's the VitePress project root, unless `srcDir` is configured.
You can also prefix the markdown path with `@`, it will act as the source root. By default, it's the VitePress project root, unless `srcDir` is configured.
:::
For example, you can include a relative markdown file using this:

@ -327,7 +327,6 @@ Instead, you can pass such content to each page using the `content` property on
```js
export default {
paths() {
async paths() {
const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
@ -339,7 +338,6 @@ export default {
})
}
}
}
```
Then, use the following special syntax to render the content as part of the Markdown file itself:

@ -1,6 +1,12 @@
{
"name": "docs",
"private": true,
"type": "module",
"scripts": {
"dev": "vitepress",
"build": "vitepress build",
"preview": "vitepress preview"
},
"devDependencies": {
"vitepress": "workspace:*"
}

@ -180,3 +180,36 @@ export default {
}
}
```
## `useSidebar` <Badge type="info" text="composable" />
Returns sidebar-related data. The returned object has the following type:
```ts
export interface Sidebar {
isOpen: Ref<boolean>
sidebar: ComputedRef<DefaultTheme.SidebarItem[]>
sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]>
hasSidebar: ComputedRef<boolean>
hasAside: ComputedRef<boolean>
leftAside: ComputedRef<boolean>
isSidebarEnabled: ComputedRef<boolean>
open: () => void
close: () => void
toggle: () => void
}
```
**Example:**
```vue
<script setup>
import { useSidebar } from 'vitepress/theme'
const { hasSidebar } = useSidebar()
</script>
<template>
<div v-if="hasSidebar">Only show when sidebar exists</div>
</template>
```

@ -3,4 +3,4 @@
[build]
publish = "docs/.vitepress/dist"
command = "pnpm docs-build"
command = "pnpm docs:build"

@ -1,9 +1,9 @@
{
"name": "vitepress",
"version": "1.0.0-beta.2",
"version": "1.0.0-beta.3",
"description": "Vite & Vue powered static site generator",
"type": "module",
"packageManager": "pnpm@8.6.1",
"packageManager": "pnpm@8.6.5",
"main": "dist/node/index.js",
"types": "types/index.d.ts",
"exports": {
@ -55,51 +55,52 @@
"url": "https://github.com/vuejs/vitepress/issues"
},
"scripts": {
"dev": "rimraf dist && run-s dev-shared dev-start",
"dev-start": "run-p dev-client dev-node dev-watch",
"dev-client": "tsc --sourcemap -w -p src/client",
"dev-node": "DEV=true pnpm build-node -w",
"dev-shared": "node scripts/copyShared",
"dev-watch": "node scripts/watchAndCopy",
"build": "run-s build-prepare build-client build-node",
"build-prepare": "rimraf dist && node scripts/copyShared",
"build-client": "vue-tsc --noEmit -p src/client && tsc -p src/client && node scripts/copyClient",
"build-node": "tsc -p src/node --noEmit && rollup --config rollup.config.ts --configPlugin esbuild",
"dev": "rimraf dist && run-s dev:shared dev:start",
"dev:start": "run-p dev:client dev:node dev:watch",
"dev:client": "tsc --sourcemap -w -p src/client",
"dev:node": "DEV=true pnpm build:node -w",
"dev:shared": "node scripts/copyShared",
"dev:watch": "node scripts/watchAndCopy",
"build": "run-s build:prepare build:client build:node",
"build:prepare": "rimraf dist && node scripts/copyShared",
"build:client": "vue-tsc --noEmit -p src/client && tsc -p src/client && node scripts/copyClient",
"build:node": "tsc -p src/node --noEmit && rollup --config rollup.config.ts --configPlugin esbuild",
"test": "run-p --aggregate-output test:unit test:e2e test:init",
"test:unit": "vitest run -r __tests__/unit",
"test:unit:watch": "vitest -r __tests__/unit",
"test:e2e": "run-s test:e2e-dev test:e2e-build",
"test:e2e:site": "pnpm -F=tests-e2e site",
"test:e2e-dev": "pnpm -F=tests-e2e test",
"test:e2e-dev:watch": "pnpm -F=tests-e2e watch",
"test:e2e-build": "VITE_TEST_BUILD=1 pnpm test:e2e-dev",
"test:e2e-build:watch": "VITE_TEST_BUILD=1 pnpm test:e2e-dev:watch",
"test:init": "pnpm -F=tests-init test",
"test:init:watch": "pnpm -F=tests-init watch",
"docs": "run-p dev docs:dev",
"docs:dev": "wait-on -d 100 dist/node/cli.js && pnpm -F=docs dev",
"docs:debug": "NODE_OPTIONS='--inspect-brk' pnpm docs:dev",
"docs:build": "run-s build docs:build:only",
"docs:build:only": "pnpm -F=docs build",
"docs:preview": "pnpm -F=docs preview",
"format": "prettier --check --write .",
"format-fail": "prettier --check .",
"check": "run-s format-fail build test",
"test": "run-s test-unit test-e2e test-e2e-build",
"test-unit": "vitest run -r __tests__/unit",
"test-e2e": "vitest run -r __tests__/e2e",
"test-e2e-build": "VITE_TEST_BUILD=1 pnpm test-e2e",
"test-init": "vitest run -r __tests__/init",
"test-init-build": "VITE_TEST_BUILD=1 pnpm test-init",
"debug-e2e": "DEBUG=1 vitest -r __tests__/e2e",
"debug-e2e-build": "VITE_TEST_BUILD=1 pnpm debug-e2e",
"unit-dev": "vitest -r __tests__/unit",
"e2e-dev": "wait-on -d 100 dist/node/cli.js && node ./bin/vitepress dev __tests__/e2e",
"format:fail": "prettier --check .",
"check": "run-s format:fail build test",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"release": "node scripts/release.js",
"docs": "run-p dev docs-dev",
"docs-dev": "wait-on -d 100 dist/node/cli.js && node ./bin/vitepress dev docs",
"docs-debug": "node --inspect-brk ./bin/vitepress dev docs",
"docs-build": "run-s build docs-build-only",
"docs-build-only": "node ./bin/vitepress build docs",
"docs-preview": "node ./bin/vitepress preview docs"
"release": "node scripts/release.js"
},
"dependencies": {
"@docsearch/css": "^3.5.0",
"@docsearch/js": "^3.5.0",
"@docsearch/css": "^3.5.1",
"@docsearch/js": "^3.5.1",
"@vitejs/plugin-vue": "^4.2.3",
"@vue/devtools-api": "^6.5.0",
"@vueuse/core": "^10.1.2",
"@vueuse/integrations": "^10.1.2",
"@vueuse/core": "^10.2.0",
"@vueuse/integrations": "^10.2.0",
"body-scroll-lock": "4.0.0-beta.0",
"focus-trap": "^7.4.3",
"mark.js": "8.11.1",
"minisearch": "^6.1.0",
"shiki": "^0.14.2",
"vite": "^4.3.9",
"shiki": "^0.14.3",
"vite": "4.4.0-beta.2",
"vue": "^3.3.4"
},
"devDependencies": {
@ -112,7 +113,7 @@
"@mdit-vue/plugin-toc": "^0.12.0",
"@mdit-vue/shared": "^0.12.0",
"@rollup/plugin-alias": "^5.0.0",
"@rollup/plugin-commonjs": "^25.0.1",
"@rollup/plugin-commonjs": "^25.0.2",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.1.0",
"@rollup/plugin-replace": "^5.0.2",
@ -129,14 +130,14 @@
"@types/markdown-it-emoji": "^2.0.2",
"@types/micromatch": "^4.0.2",
"@types/minimist": "^1.2.2",
"@types/node": "^20.3.0",
"@types/node": "^20.3.2",
"@types/prompts": "^2.4.4",
"chokidar": "^3.5.3",
"compression": "^1.7.4",
"conventional-changelog-cli": "^3.0.0",
"conventional-changelog-cli": "^2",
"cross-spawn": "^7.0.3",
"debug": "^4.3.4",
"esbuild": "^0.18.0",
"esbuild": "^0.18.10",
"escape-html": "^1.0.3",
"execa": "^7.1.1",
"fast-glob": "^3.2.12",
@ -145,7 +146,7 @@
"gray-matter": "^4.0.3",
"lint-staged": "^13.2.2",
"lodash.template": "^4.5.0",
"lru-cache": "^9.1.2",
"lru-cache": "^10.0.0",
"markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.6.7",
"markdown-it-attrs": "^4.1.6",
@ -159,23 +160,23 @@
"path-to-regexp": "^6.2.1",
"picocolors": "^1.0.0",
"pkg-dir": "^7.0.0",
"playwright-chromium": "^1.35.0",
"playwright-chromium": "^1.35.1",
"polka": "1.0.0-next.22",
"prettier": "^2.8.8",
"prompts": "^2.4.2",
"punycode": "^2.3.0",
"rimraf": "^5.0.1",
"rollup": "^3.25.0",
"rollup": "^3.25.3",
"rollup-plugin-dts": "^5.3.0",
"rollup-plugin-esbuild": "^5.0.0",
"semver": "^7.5.1",
"semver": "^7.5.3",
"shiki-processor": "^0.1.3",
"simple-git-hooks": "^2.8.1",
"sirv": "^2.0.3",
"supports-color": "^9.3.1",
"typescript": "^5.1.3",
"vitest": "^0.32.0",
"vue-tsc": "^1.6.5",
"vitest": "^0.32.2",
"vue-tsc": "^1.8.2",
"wait-on": "^7.0.1"
},
"simple-git-hooks": {

File diff suppressed because it is too large Load Diff

@ -2,13 +2,12 @@ import { inBrowser } from 'vitepress'
export function useCopyCode() {
if (inBrowser) {
const timeoutIdMap: Map<HTMLElement, NodeJS.Timeout> = new Map()
const timeoutIdMap: WeakMap<HTMLElement, NodeJS.Timeout> = new WeakMap()
window.addEventListener('click', (e) => {
const el = e.target as HTMLElement
if (el.matches('div[class*="language-"] > button.copy')) {
const parent = el.parentElement
const sibling = el.nextElementSibling
?.nextElementSibling as HTMLPreElement | null
const sibling = el.nextElementSibling?.nextElementSibling
if (!parent || !sibling) {
return
}

@ -269,7 +269,11 @@ export function scrollTo(el: Element, hash: string, smooth = false) {
offset +
targetPadding
// only smooth scroll if distance is smaller than screen height.
if (!smooth || Math.abs(targetTop - window.scrollY) > window.innerHeight) {
function scrollToTarget() {
if (
!smooth ||
Math.abs(targetTop - window.scrollY) > window.innerHeight
) {
window.scrollTo(0, targetTop)
} else {
window.scrollTo({
@ -279,6 +283,8 @@ export function scrollTo(el: Element, hash: string, smooth = false) {
})
}
}
requestAnimationFrame(scrollToTarget)
}
}
function tryOffsetSelector(selector: string): number {

@ -12,7 +12,7 @@ export type { EnhanceAppContext, Theme } from './app/theme'
export type { HeadConfig, Header, PageData, SiteData } from '../../types/shared'
// composables
export { useData } from './app/data'
export { useData, dataSymbol } from './app/data'
export { useRoute, useRouter } from './app/router'
// utilities

@ -1,15 +1,16 @@
<script setup lang="ts">
import { computed, provide, useSlots, watch } from 'vue'
import { useRoute } from 'vitepress'
import { useData } from './composables/data'
import { useSidebar, useCloseSidebarOnEscape } from './composables/sidebar'
import VPSkipLink from './components/VPSkipLink.vue'
import { useSidebar } from 'vitepress/theme'
import { computed, provide, useSlots, watch } from 'vue'
import VPBackdrop from './components/VPBackdrop.vue'
import VPNav from './components/VPNav.vue'
import VPLocalNav from './components/VPLocalNav.vue'
import VPSidebar from './components/VPSidebar.vue'
import VPContent from './components/VPContent.vue'
import VPFooter from './components/VPFooter.vue'
import VPLocalNav from './components/VPLocalNav.vue'
import VPNav from './components/VPNav.vue'
import VPSidebar from './components/VPSidebar.vue'
import VPSkipLink from './components/VPSkipLink.vue'
import { useData } from './composables/data'
import { useCloseSidebarOnEscape } from './composables/sidebar'
const {
isOpen: isSidebarOpen,

@ -1,10 +1,10 @@
<script setup lang="ts">
import { useSidebar } from 'vitepress/theme'
import NotFound from '../NotFound.vue'
import { useData } from '../composables/data'
import { useSidebar } from '../composables/sidebar'
import VPPage from './VPPage.vue'
import VPHome from './VPHome.vue'
import VPDoc from './VPDoc.vue'
import NotFound from '../NotFound.vue'
import VPHome from './VPHome.vue'
import VPPage from './VPPage.vue'
const { page, frontmatter } = useData()
const { hasSidebar } = useSidebar()

@ -1,7 +1,7 @@
<script setup lang="ts">
import { useRoute } from 'vitepress'
import { useSidebar } from 'vitepress/theme'
import { computed } from 'vue'
import { useSidebar } from '../composables/sidebar'
import VPDocAside from './VPDocAside.vue'
import VPDocFooter from './VPDocFooter.vue'
import VPDocOutlineDropdown from './VPDocOutlineDropdown.vue'

@ -1,6 +1,6 @@
<script setup lang="ts">
import { useSidebar } from 'vitepress/theme'
import { useData } from '../composables/data'
import { useSidebar } from '../composables/sidebar'
const { theme } = useData()
const { hasSidebar } = useSidebar()

@ -1,10 +1,10 @@
<script lang="ts" setup>
import { useWindowScroll } from '@vueuse/core'
import { computed, shallowRef } from 'vue'
import { onContentUpdated } from 'vitepress'
import { useSidebar } from 'vitepress/theme'
import { computed, shallowRef } from 'vue'
import { useData } from '../composables/data'
import { getHeaders, type MenuItem } from '../composables/outline'
import { useSidebar } from '../composables/sidebar'
import VPLocalNavOutlineDropdown from './VPLocalNavOutlineDropdown.vue'
import VPIconAlignLeft from './icons/VPIconAlignLeft.vue'

@ -12,7 +12,7 @@ import {
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap'
import Mark from 'mark.js/src/vanilla.js'
import MiniSearch, { type SearchResult } from 'minisearch'
import { useRouter } from 'vitepress'
import { useRouter, dataSymbol } from 'vitepress'
import {
computed,
createApp,
@ -27,7 +27,6 @@ import {
type Ref
} from 'vue'
import type { ModalTranslations } from '../../../../types/local-search'
import { dataSymbol } from '../../app/data'
import { pathToFile } from '../../app/utils'
import { useData } from '../composables/data'
import { createTranslate } from '../support/translation'

@ -1,15 +1,15 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useWindowScroll } from '@vueuse/core'
import { useSidebar } from '../composables/sidebar'
import VPNavBarTitle from './VPNavBarTitle.vue'
import VPNavBarSearch from './VPNavBarSearch.vue'
import VPNavBarMenu from './VPNavBarMenu.vue'
import VPNavBarTranslations from './VPNavBarTranslations.vue'
import { useSidebar } from 'vitepress/theme'
import { computed } from 'vue'
import VPNavBarAppearance from './VPNavBarAppearance.vue'
import VPNavBarSocialLinks from './VPNavBarSocialLinks.vue'
import VPNavBarExtra from './VPNavBarExtra.vue'
import VPNavBarHamburger from './VPNavBarHamburger.vue'
import VPNavBarMenu from './VPNavBarMenu.vue'
import VPNavBarSearch from './VPNavBarSearch.vue'
import VPNavBarSocialLinks from './VPNavBarSocialLinks.vue'
import VPNavBarTitle from './VPNavBarTitle.vue'
import VPNavBarTranslations from './VPNavBarTranslations.vue'
defineProps<{
isScreenOpen: boolean

@ -26,6 +26,7 @@ const { theme, localeIndex } = useData()
// payload), we delay initializing it until the user has actually clicked or
// hit the hotkey to invoke it.
const loaded = ref(false)
const actuallyLoaded = ref(false)
const buttonText = computed(() => {
const options = theme.value.search?.options ?? theme.value.algolia
@ -169,9 +170,10 @@ const provider = __ALGOLIA__ ? 'algolia' : __VP_LOCAL_SEARCH__ ? 'local' : ''
<VPAlgoliaSearchBox
v-if="loaded"
:algolia="theme.search?.options ?? theme.algolia"
@vue:beforeMount="actuallyLoaded = true"
/>
<div v-else id="docsearch">
<div v-if="!actuallyLoaded" id="docsearch">
<VPNavBarSearchButton :placeholder="buttonText" @click="load" />
</div>
</template>

@ -1,6 +1,6 @@
<script setup lang="ts">
import { useSidebar } from 'vitepress/theme'
import { useData } from '../composables/data'
import { useSidebar } from '../composables/sidebar'
import { useLangs } from '../composables/langs'
import { normalizeLink } from '../support/utils'
import VPImage from './VPImage.vue'

@ -1,7 +1,7 @@
<script lang="ts" setup>
import { clearAllBodyScrollLocks, disableBodyScroll } from 'body-scroll-lock'
import { useSidebar } from 'vitepress/theme'
import { ref, watchPostEffect } from 'vue'
import { disableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock'
import { useSidebar } from '../composables/sidebar'
import VPSidebarItem from './VPSidebarItem.vue'
const { sidebarGroups, hasSidebar } = useSidebar()

@ -1,6 +1,6 @@
import { computed } from 'vue'
import { useMediaQuery } from '@vueuse/core'
import { useSidebar } from './sidebar'
import { useSidebar } from 'vitepress/theme'
import { computed } from 'vue'
export function useAside() {
const { hasSidebar } = useSidebar()

@ -23,6 +23,8 @@ export { default as VPTeamPageTitle } from './components/VPTeamPageTitle.vue'
export { default as VPTeamPageSection } from './components/VPTeamPageSection.vue'
export { default as VPTeamMembers } from './components/VPTeamMembers.vue'
export { useSidebar } from './composables/sidebar'
const theme: Theme = {
Layout,
enhanceApp: ({ app }) => {

@ -38,7 +38,7 @@ export type UserConfigExport<ThemeConfig> =
/**
* Type config helper
*/
export function defineConfig(config: UserConfigExport<DefaultTheme.Config>) {
export function defineConfig(config: UserConfig<DefaultTheme.Config>) {
return config
}
@ -46,7 +46,7 @@ export function defineConfig(config: UserConfigExport<DefaultTheme.Config>) {
* Type config helper for custom theme config
*/
export function defineConfigWithTheme<ThemeConfig>(
config: UserConfigExport<ThemeConfig>
config: UserConfig<ThemeConfig>
) {
return config
}

@ -86,23 +86,27 @@ export async function createMarkdownToVueRenderFn(
// resolve includes
let includes: string[] = []
src = src.replace(includesRE, (m, m1) => {
function processIncludes(src: string): string {
return src.replace(includesRE, (m, m1) => {
if (!m1.length) return m
const atPresent = m1[0] === '@'
try {
const dir = atPresent ? srcDir : path.dirname(fileOrig)
const includePath = path.join(
dir,
atPresent ? m1.slice(m1.length > 1 && m1[1] === '/' ? 2 : 1) : m1
)
const includePath = atPresent
? path.join(srcDir, m1.slice(m1[1] === '/' ? 2 : 1))
: path.join(path.dirname(fileOrig), m1)
const content = fs.readFileSync(includePath, 'utf-8')
includes.push(slash(includePath))
return content
// recursively process includes in the content
return processIncludes(content)
} catch (error) {
return m // silently ignore error if file is not present
}
})
}
src = processIncludes(src)
// reset env before render
const env: MarkdownEnv = {

@ -133,7 +133,7 @@ export async function createVitePressPlugin(
},
optimizeDeps: {
// force include vue to avoid duplicated copies when linked + optimized
include: ['vue'],
include: ['vue', 'vitepress > @vue/devtools-api'],
exclude: ['@docsearch/js', 'vitepress']
},
server: {

@ -7,8 +7,8 @@ export function resolveRewrites(
userRewrites: UserConfig['rewrites']
) {
const rewriteRules = Object.entries(userRewrites || {}).map(([from, to]) => ({
toPath: compile(to),
matchUrl: match(from)
toPath: compile(to, { validate: false }),
matchUrl: match(from.startsWith('^') ? new RegExp(from) : from)
}))
const pageToRewrite: Record<string, string> = {}

@ -24,12 +24,12 @@ export interface ServeOptions {
}
export async function serve(options: ServeOptions = {}) {
const port = options.port !== undefined ? options.port : 4173
const site = await resolveConfig(options.root, 'serve', 'production')
const base = trimChar(options?.base ?? site?.site?.base ?? '', '/')
const port = options.port ?? 4173
const config = await resolveConfig(options.root, 'serve', 'production')
const base = trimChar(options?.base ?? config?.site?.base ?? '', '/')
const notAnAsset = (pathname: string) => !pathname.includes('/assets/')
const notFound = fs.readFileSync(path.resolve(site.outDir, './404.html'))
const notFound = fs.readFileSync(path.resolve(config.outDir, './404.html'))
const onNoMatch: IOptions['onNoMatch'] = (req, res) => {
res.statusCode = 404
if (notAnAsset(req.path)) res.write(notFound.toString())
@ -37,7 +37,7 @@ export async function serve(options: ServeOptions = {}) {
}
const compress = compression() as RequestHandler
const serve = sirv(site.outDir, {
const serve = sirv(config.outDir, {
etag: true,
maxAge: 31536000,
immutable: true,
@ -54,7 +54,7 @@ export async function serve(options: ServeOptions = {}) {
return polka({ onNoMatch })
.use(base, compress, serve)
.listen(port, () => {
site.logger.info(
config.logger.info(
`Built site served at http://localhost:${port}/${base}/`
)
})
@ -62,7 +62,7 @@ export async function serve(options: ServeOptions = {}) {
return polka({ onNoMatch })
.use(compress, serve)
.listen(port, () => {
site.logger.info(`Built site served at http://localhost:${port}/`)
config.logger.info(`Built site served at http://localhost:${port}/`)
})
}
}

@ -5,7 +5,7 @@ import { createVitePressPlugin } from './plugin'
export async function createServer(
root: string = process.cwd(),
serverOptions: ServerOptions = {},
serverOptions: ServerOptions & { base?: string } = {},
recreateServer?: () => Promise<void>
) {
const config = await resolveConfig(root)

@ -13,7 +13,7 @@ import Theme from 'vitepress/theme'
import './style.css'
export default {
...Theme,
extends: Theme,
Layout: () => {
return h(Theme.Layout, null, {
// https://vitepress.dev/guide/extending-default-theme#layout-slots

3
theme.d.ts vendored

@ -14,9 +14,10 @@ export const VPTeamMembers: DefineComponent
declare const theme: {
Layout: DefineComponent
NotFound: DefineComponent
enhanceApp: (ctx: EnhanceAppContext) => void
}
export default theme
export type { DefaultTheme } from './types/default-theme.js'
export const useSidebar: () => DefaultTheme.SideBar

@ -209,6 +209,22 @@ export namespace DefaultTheme {
collapsed?: boolean
}
/**
* ReturnType of `useSidebar`
*/
export interface Sidebar {
isOpen: Ref<boolean>
sidebar: ComputedRef<SidebarItem[]>
sidebarGroups: ComputedRef<SidebarItem[]>
hasSidebar: ComputedRef<boolean>
hasAside: ComputedRef<boolean>
leftAside: ComputedRef<boolean>
isSidebarEnabled: ComputedRef<boolean>
open: () => void
close: () => void
toggle: () => void
}
// edit link -----------------------------------------------------------------
export interface EditLink {

Loading…
Cancel
Save