Merge branch 'main' into zh

pull/1593/head
Xavi Lee 4 years ago committed by GitHub
commit 8c23c0e742
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,3 +1,27 @@
# [1.0.0-alpha.46](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.45...v1.0.0-alpha.46) (2023-02-12)
### Bug Fixes
* **build:** prepend base to all internal non-relative links ([#1908](https://github.com/vuejs/vitepress/issues/1908)) ([dcf2941](https://github.com/vuejs/vitepress/commit/dcf29419f24bfb0fe99e424771be931bf77b9961))
* **theme-default:** avoid preconnect without algolia ([#1902](https://github.com/vuejs/vitepress/issues/1902)) ([616fe5b](https://github.com/vuejs/vitepress/commit/616fe5b636050caa338cabede3794e658baa0ed6))
* **theme-default:** remove duplicate judgments in `preconnect()` ([#1903](https://github.com/vuejs/vitepress/issues/1903)) ([48c9b11](https://github.com/vuejs/vitepress/commit/48c9b113161823133276198ebeb15131b83a7a75))
* **theme:** make features support line wrapping ([#1913](https://github.com/vuejs/vitepress/issues/1913)) ([ea43076](https://github.com/vuejs/vitepress/commit/ea430760f507e3ba381c4ab01ec89a2111f35e8c))
### Features
* **build:** use vite logger ([#1899](https://github.com/vuejs/vitepress/issues/1899)) ([a00bb62](https://github.com/vuejs/vitepress/commit/a00bb621439b2571b3d33da6aa67c74ecd13d3c6))
* **shiki:** support `ansi` code highlight ([#1878](https://github.com/vuejs/vitepress/issues/1878)) ([f974381](https://github.com/vuejs/vitepress/commit/f9743816a55503c387b9c71793a92eb38817650d))
* **theme:** support disabling aside globally ([#1925](https://github.com/vuejs/vitepress/issues/1925)) ([dd0c4c6](https://github.com/vuejs/vitepress/commit/dd0c4c698c26d3e249d353c3baff568a8f406e8f))
### BREAKING CHANGES
* **build:** `base` is now prepended to all internal (non-relative) links, including any reference to a file present in the public directory. If you want the earlier behavior for such links, use absolute links.
# [1.0.0-alpha.45](https://github.com/vuejs/vitepress/compare/v1.0.0-alpha.44...v1.0.0-alpha.45) (2023-01-31)

@ -157,6 +157,13 @@ export type SidebarItem = {
}
```
## aside
- Type: `boolean`
- Default: `true`
Setting this value to `false` prevents rendering of aside container.
## outline
- Type: `number | [number, number] | 'deep' | false`
@ -300,17 +307,17 @@ An option to support searching your docs site using [Algolia DocSearch](https://
```ts
export interface AlgoliaSearchOptions extends DocSearchProps {
locales?: Record<string, Partial<DocSearchProps>>
locales?: Record<string, Partial<DocSearchProps>>
}
```
View full options [here](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts).
## carbonAds {#carbon-ads}
## carbonAds
- Type: `CarbonAds`
- Type: `CarbonAdsOptions`
A option to display [Carbon Ads](https://www.carbonads.net/).
An option to display [Carbon Ads](https://www.carbonads.net/).
```ts
export default {
@ -324,7 +331,7 @@ export default {
```
```ts
export interface CarbonAds {
export interface CarbonAdsOptions {
code: string
placement: string
}
@ -375,4 +382,4 @@ Can be used to customize the sidebar menu label. This label is only displayed in
- Type: `string`
- Default: `Return to top`
Can be used to customize the label of the returnToTop. This label is only displayed in the mobile view.
Can be used to customize the label of the returnToTop. This label is only displayed in the mobile view.

@ -73,15 +73,20 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
```yaml
name: Deploy
on:
workflow_dispatch: {}
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v3
with:
@ -91,16 +96,15 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
node-version: 16
cache: yarn
- run: yarn install --frozen-lockfile
- name: Build
run: yarn docs:build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
- uses: actions/configure-pages@v2
- uses: actions/upload-pages-artifact@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/.vitepress/dist
# cname: example.com # if wanna deploy to custom domain
path: docs/.vitepress/dist
- name: Deploy
id: deployment
uses: actions/deploy-pages@v1
```
::: tip
@ -139,6 +143,25 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
- main
```
4. Alternatively, if you want to use an _alpine_ version of node, you have to install `git` manually. In that case, the code above modifies to this:
```yaml
image: node:16-alpine
pages:
cache:
paths:
- node_modules/
before_script:
- apk add git
script:
- yarn install
- yarn docs:build
artifacts:
paths:
- public
only:
- main
```
## Azure Static Web Apps
1. Follow the [official documentation](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration).
@ -200,6 +223,6 @@ Don't enable options like _Auto Minify_ for HTML code. It will remove comments f
}
```
## Layer0
## Edgio
Refer [Creating and Deploying a VitePress App with Layer0](https://docs.layer0.co/guides/vitepress).
Refer [Creating and Deploying a VitePress App To Edgio](https://docs.edg.io/guides/vitepress).

@ -18,18 +18,42 @@ $ mkdir vitepress-starter && cd vitepress-starter
Then, initialize with your preferred package manager.
```sh
::: code-group
```sh [npm]
$ npm init
```
```sh [yarn]
$ yarn init
```
```sh [pnpm]
$ pnpm init
```
:::
## Step 2: Install VitePress
Add VitePress and Vue as dev dependencies for the project.
```sh
$ yarn add --dev vitepress vue
::: code-group
```sh [npm]
$ npm install -D vitepress vue
```
```sh [yarn]
$ yarn add -D vitepress vue
```
```sh [pnpm]
$ pnpm add -D vitepress vue
```
:::
::: details Getting missing peer deps warnings?
`@docsearch/js` has certain issues with its peer dependencies. If you see some commands failing due to them, you can try this workaround for now:
@ -71,10 +95,21 @@ Add some scripts to `package.json`.
Serve the documentation site in the local server.
```sh
::: code-group
```sh [npm]
$ npm run docs:dev
```
```sh [yarn]
$ yarn docs:dev
```
```sh [pnpm]
$ pnpm run docs:dev
```
:::
VitePress will start a hot-reloading development server at `http://localhost:5173`.
## Step 4: Add more pages

@ -651,6 +651,34 @@ export default config
:::
You can also [import snippets](#import-code-snippets) in code groups:
**Input**
```md
::: code-group
<!-- filename is used as title by default -->
<<< @/snippets/snippet.js
<!-- you can provide a custom one too -->
<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region]
:::
```
**Output**
::: code-group
<<< @/snippets/snippet.js
<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [snippet with region]
:::
## Markdown File Inclusion
You can include a markdown file in another markdown file like this:

@ -125,8 +125,8 @@ You may configure the mapping via [`rewrites`](/config/app-configs#rewrites) opt
```ts
export default {
rewrites: {
'packages/pkg-a/src/pkg-a-code.md': 'pkg-a/pkg-a-code',
'packages/pkg-b/src/pkg-b-code.md': 'pkg-b/pkg-b-code'
'packages/pkg-a/src/pkg-a-code.md': 'pkg-a/pkg-a-code.md',
'packages/pkg-b/src/pkg-b-code.md': 'pkg-b/pkg-b-code.md'
}
}
```
@ -156,8 +156,8 @@ export default {
The above will create mapping as below.
```
packages/pkg-a/src/pkg-a-code.md -> /pkg-a/pkg-a-code
packages/pkg-b/src/folder/file.md -> /pkg-b/folder/file
packages/pkg-a/src/pkg-a-code.md -> /pkg-a/pkg-a-code.md
packages/pkg-b/src/folder/file.md -> /pkg-b/folder/file.md
```
::: warning You need server restart on page addition

@ -1,9 +1,9 @@
{
"name": "vitepress",
"version": "1.0.0-alpha.45",
"version": "1.0.0-alpha.46",
"description": "Vite & Vue powered static site generator",
"type": "module",
"packageManager": "pnpm@7.26.1",
"packageManager": "pnpm@7.27.0",
"main": "dist/node/index.js",
"types": "types/index.d.ts",
"exports": {
@ -51,7 +51,7 @@
"scripts": {
"dev": "rimraf dist && run-s dev-shared dev-start",
"dev-start": "run-p dev-client dev-node dev-watch",
"dev-client": "tsc -w -p src/client",
"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",
@ -80,24 +80,24 @@
"docs-preview": "node ./bin/vitepress preview docs"
},
"dependencies": {
"@docsearch/css": "^3.3.2",
"@docsearch/js": "^3.3.2",
"@docsearch/css": "^3.3.3",
"@docsearch/js": "^3.3.3",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/devtools-api": "^6.5.0",
"@vueuse/core": "^9.12.0",
"body-scroll-lock": "4.0.0-beta.0",
"shiki": "^0.14.0",
"vite": "^4.0.4",
"vue": "^3.2.45"
"shiki": "^0.14.1",
"vite": "^4.1.1",
"vue": "^3.2.47"
},
"devDependencies": {
"@mdit-vue/plugin-component": "^0.11.2",
"@mdit-vue/plugin-frontmatter": "^0.11.1",
"@mdit-vue/plugin-headers": "^0.11.2",
"@mdit-vue/plugin-sfc": "^0.11.1",
"@mdit-vue/plugin-title": "^0.11.2",
"@mdit-vue/plugin-toc": "^0.11.2",
"@mdit-vue/shared": "^0.11.2",
"@mdit-vue/plugin-component": "^0.12.0",
"@mdit-vue/plugin-frontmatter": "^0.12.0",
"@mdit-vue/plugin-headers": "^0.12.0",
"@mdit-vue/plugin-sfc": "^0.12.0",
"@mdit-vue/plugin-title": "^0.12.0",
"@mdit-vue/plugin-toc": "^0.12.0",
"@mdit-vue/shared": "^0.12.0",
"@rollup/plugin-alias": "^4.0.3",
"@rollup/plugin-commonjs": "23.0.4",
"@rollup/plugin-json": "^6.0.0",
@ -117,7 +117,7 @@
"@types/markdown-it-emoji": "^2.0.2",
"@types/micromatch": "^4.0.2",
"@types/minimist": "^1.2.2",
"@types/node": "^18.11.18",
"@types/node": "^18.13.0",
"@types/prompts": "^2.4.2",
"chokidar": "^3.5.3",
"compression": "^1.7.4",
@ -125,13 +125,13 @@
"cross-spawn": "^7.0.3",
"debug": "^4.3.4",
"enquirer": "^2.3.6",
"esbuild": "^0.17.5",
"esbuild": "^0.17.7",
"escape-html": "^1.0.3",
"execa": "^6.1.0",
"execa": "^7.0.0",
"fast-glob": "^3.2.12",
"fs-extra": "^11.1.0",
"get-port": "^6.1.2",
"lint-staged": "^13.1.0",
"lint-staged": "^13.1.1",
"lru-cache": "^7.14.1",
"markdown-it": "^13.0.1",
"markdown-it-anchor": "^8.6.6",
@ -139,7 +139,7 @@
"markdown-it-container": "^3.0.0",
"markdown-it-emoji": "^2.0.2",
"micromatch": "^4.0.5",
"minimist": "^1.2.7",
"minimist": "^1.2.8",
"nanoid": "3.3.4",
"npm-run-all": "^4.1.5",
"ora": "5.4.1",
@ -148,20 +148,20 @@
"pkg-dir": "5.0.0",
"playwright-chromium": "^1.30.0",
"polka": "1.0.0-next.22",
"prettier": "^2.8.3",
"prettier": "^2.8.4",
"prompts": "^2.4.2",
"punycode": "^2.3.0",
"rimraf": "^4.1.2",
"rollup": "^3.12.0",
"rollup": "^3.15.0",
"rollup-plugin-dts": "^5.1.1",
"rollup-plugin-esbuild": "^5.0.0",
"semver": "^7.3.8",
"shiki-processor": "^0.1.2",
"shiki-processor": "^0.1.3",
"simple-git-hooks": "^2.8.1",
"sirv": "^2.0.2",
"supports-color": "^9.3.1",
"typescript": "~4.9.5",
"vitest": "^0.28.3",
"vitest": "^0.28.4",
"vue-tsc": "^1.0.24",
"wait-on": "^7.0.1"
},

File diff suppressed because it is too large Load Diff

@ -52,7 +52,8 @@ const esmBuild: RollupOptions = {
format: 'esm',
entryFileNames: `[name].js`,
chunkFileNames: 'serve-[hash].js',
dir: r('dist/node')
dir: r('dist/node'),
sourcemap: DEV
},
external,
plugins,

@ -24,8 +24,8 @@ defineProps<{
:width="icon.width"
/>
<div v-else-if="icon" class="icon">{{ icon }}</div>
<h2 class="title">{{ title }}</h2>
<p class="details">{{ details }}</p>
<h2 class="title" v-html="title"></h2>
<p class="details" v-html="details"></p>
<div v-if="linkText" class="link-text">
<p class="link-text-value">

@ -20,7 +20,7 @@ const hasExtraContent = computed(
<template>
<VPFlyout v-if="hasExtraContent" class="VPNavBarExtra" label="extra navigation">
<div v-if="localeLinks.length && currentLang.label" class="group">
<div v-if="localeLinks.length && currentLang.label" class="group translations">
<p class="trans-title">{{ currentLang.label }}</p>
<template v-for="locale in localeLinks" :key="locale.link">

@ -29,11 +29,27 @@ const buttonText = computed(
'Search'
)
const preconnect = () => {
const id = 'VPAlgoliaPreconnect'
const rIC = window.requestIdleCallback || setTimeout
rIC(() => {
const preconnect = document.createElement('link')
preconnect.id = id
preconnect.rel = 'preconnect'
preconnect.href = `https://${theme.value.algolia!.appId}-dsn.algolia.net`
preconnect.crossOrigin = ''
document.head.appendChild(preconnect)
})
}
onMounted(() => {
if (!theme.value.algolia) {
return
}
preconnect()
// meta key detect (same logic as in @docsearch/js)
metaKey.value = /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)
? `'⌘'`
@ -78,22 +94,6 @@ function poll() {
}
}, 16)
}
onMounted(() => {
const id = 'VPAlgoliaPreconnect'
const rIC = window.requestIdleCallback || setTimeout
rIC(() => {
if (!theme.value.algolia || document.head.querySelector(`#${id}`)) return
const preconnect = document.createElement('link')
preconnect.id = id
preconnect.rel = 'preconnect'
preconnect.href = `https://${theme.value.algolia.appId}-dsn.algolia.net`
preconnect.crossOrigin = ''
document.head.appendChild(preconnect)
})
})
</script>
<template>

@ -50,9 +50,10 @@ export function useSidebar() {
})
const hasAside = computed(() => {
return (
frontmatter.value.layout !== 'home' && frontmatter.value.aside !== false
)
if (frontmatter.value.layout === 'home') return false
if (frontmatter.value.aside != null) return !!frontmatter.value.aside
if (theme.value.aside === false) return false
return true
})
const isSidebarEnabled = computed(() => hasSidebar.value && is960.value)

@ -106,7 +106,9 @@ export async function build(
await siteConfig.buildEnd?.(siteConfig)
console.log(`build complete in ${((Date.now() - start) / 1000).toFixed(2)}s.`)
siteConfig.logger.info(
`build complete in ${((Date.now() - start) / 1000).toFixed(2)}s.`
)
}
function linkVue() {

@ -1,11 +1,16 @@
import c from 'picocolors'
import minimist from 'minimist'
import { createServer, build, serve } from '.'
import c from 'picocolors'
import { createLogger } from 'vite'
import { build, createServer, serve } from '.'
import { version } from '../../package.json'
const argv: any = minimist(process.argv.slice(2))
console.log(c.cyan(`vitepress v${version}`))
const logVersion = (logger = createLogger()) => {
logger.info(`\n ${c.green(`${c.bold('vitepress')} v${version}`)}\n`, {
clear: !logger.hasWarned
})
}
const command = argv._[0]
const root = argv._[command ? 1 : 0]
@ -20,24 +25,27 @@ if (!command || command === 'dev') {
await createDevServer()
})
await server.listen()
console.log()
logVersion(server.config.logger)
server.printUrls()
}
createDevServer().catch((err) => {
console.error(c.red(`failed to start server. error:\n`), err)
process.exit(1)
})
} else if (command === 'build') {
build(root, argv).catch((err) => {
console.error(c.red(`build error:\n`), err)
process.exit(1)
})
} else if (command === 'serve' || command === 'preview') {
serve(argv).catch((err) => {
console.error(c.red(`failed to start server. error:\n`), err)
createLogger().error(c.red(`failed to start server. error:\n`), err)
process.exit(1)
})
} else {
console.log(c.red(`unknown command "${command}".`))
process.exit(1)
logVersion()
if (command === 'build') {
build(root, argv).catch((err) => {
createLogger().error(c.red(`build error:\n`), err)
process.exit(1)
})
} else if (command === 'serve' || command === 'preview') {
serve(argv).catch((err) => {
createLogger().error(c.red(`failed to start server. error:\n`), err)
process.exit(1)
})
} else {
createLogger().error(c.red(`unknown command "${command}".`))
process.exit(1)
}
}

@ -3,12 +3,14 @@ import _debug from 'debug'
import fg from 'fast-glob'
import fs from 'fs-extra'
import path from 'path'
import { match, compile } from 'path-to-regexp'
import { compile, match } from 'path-to-regexp'
import c from 'picocolors'
import {
createLogger,
loadConfigFromFile,
mergeConfig as mergeViteConfig,
normalizePath,
type Logger,
type UserConfig as ViteConfig
} from 'vite'
import { DEFAULT_THEME_PATH } from './alias'
@ -180,6 +182,7 @@ export interface SiteConfig<ThemeConfig = any>
map: Record<string, string | undefined>
inv: Record<string, string | undefined>
}
logger: Logger
}
const resolve = (root: string, file: string) =>
@ -211,6 +214,13 @@ export async function resolveConfig(
command,
mode
)
const logger =
userConfig.vite?.customLogger ??
createLogger(userConfig.vite?.logLevel, {
prefix: '[vitepress]',
allowClearScreen: userConfig.vite?.clearScreen
})
const site = await resolveSiteData(root, userConfig)
const srcDir = path.resolve(root, userConfig.srcDir || '.')
const outDir = userConfig.outDir
@ -264,6 +274,7 @@ export async function resolveConfig(
configDeps,
outDir,
cacheDir,
logger,
tempDir: resolve(root, '.temp'),
markdown: userConfig.markdown,
lastUpdated: userConfig.lastUpdated,

@ -1,7 +1,3 @@
import MarkdownIt from 'markdown-it'
import anchorPlugin from 'markdown-it-anchor'
import attrsPlugin from 'markdown-it-attrs'
import emojiPlugin from 'markdown-it-emoji'
import { componentPlugin } from '@mdit-vue/plugin-component'
import {
frontmatterPlugin,
@ -15,15 +11,20 @@ import { sfcPlugin, type SfcPluginOptions } from '@mdit-vue/plugin-sfc'
import { titlePlugin } from '@mdit-vue/plugin-title'
import { tocPlugin, type TocPluginOptions } from '@mdit-vue/plugin-toc'
import { slugify } from '@mdit-vue/shared'
import MarkdownIt from 'markdown-it'
import anchorPlugin from 'markdown-it-anchor'
import attrsPlugin from 'markdown-it-attrs'
import emojiPlugin from 'markdown-it-emoji'
import type { IThemeRegistration } from 'shiki'
import type { Logger } from 'vite'
import { containerPlugin } from './plugins/containers'
import { highlight } from './plugins/highlight'
import { highlightLinePlugin } from './plugins/highlightLines'
import { imagePlugin } from './plugins/image'
import { lineNumberPlugin } from './plugins/lineNumbers'
import { containerPlugin } from './plugins/containers'
import { snippetPlugin } from './plugins/snippet'
import { preWrapperPlugin } from './plugins/preWrapper'
import { linkPlugin } from './plugins/link'
import { imagePlugin } from './plugins/image'
import { preWrapperPlugin } from './plugins/preWrapper'
import { snippetPlugin } from './plugins/snippet'
export type { Header } from '../shared'
@ -55,14 +56,15 @@ export type MarkdownRenderer = MarkdownIt
export const createMarkdownRenderer = async (
srcDir: string,
options: MarkdownOptions = {},
base = '/'
base = '/',
logger: Pick<Logger, 'warn'> = console
): Promise<MarkdownRenderer> => {
const md = MarkdownIt({
html: true,
linkify: true,
highlight:
options.highlight ||
(await highlight(options.theme, options.defaultHighlightLang)),
(await highlight(options.theme, options.defaultHighlightLang, logger)),
...options
}) as MarkdownRenderer

@ -11,6 +11,7 @@ import {
getHighlighter,
type Processor
} from 'shiki-processor'
import type { Logger } from 'vite'
import type { ThemeOptions } from '../markdown'
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10)
@ -57,7 +58,8 @@ const errorLevelProcessor = defineProcessor({
export async function highlight(
theme: ThemeOptions = 'material-theme-palenight',
defaultLang: string = ''
defaultLang: string = '',
logger: Pick<Logger, 'warn'> = console
): Promise<(str: string, lang: string, attrs: string) => string> {
const hasSingleTheme = typeof theme === 'string' || 'name' in theme
const getThemeName = (themeValue: IThemeRegistration) =>
@ -89,9 +91,9 @@ export async function highlight(
if (lang) {
const langLoaded = highlighter.getLoadedLanguages().includes(lang as any)
if (!langLoaded && lang !== 'ansi') {
console.warn(
logger.warn(
c.yellow(
`The language '${lang}' is not loaded, falling back to '${
`\nThe language '${lang}' is not loaded, falling back to '${
defaultLang || 'txt'
}' for syntax highlighting.`
)

@ -24,8 +24,13 @@ export const lineNumberPlugin = (md: MarkdownIt, enable = false) => {
)
const lines = code.split('\n')
const lineNumbersCode = [...Array(lines.length - 1)]
.map((line, index) => `<span class="line-number">${index + 1}</span><br>`)
const lineNumbersCode = [
...Array(
lines.length - (lines.at(-1) === `<span class="line"></span>` ? 1 : 0)
)
]
.map((_, index) => `<span class="line-number">${index + 1}</span><br>`)
.join('')
const lineNumbersWrapperCode = `<div class="line-numbers-wrapper" aria-hidden="true">${lineNumbersCode}</div>`

@ -36,15 +36,22 @@ export const linkPlugin = (
pushLink(url, env)
}
hrefAttr[1] = url.replace(PATHNAME_PROTOCOL_RE, '')
} else if (
// internal anchor links
!url.startsWith('#') &&
// mail links
!url.startsWith('mailto:') &&
// links to files (other than html/md)
!/\.(?!html|md)\w+($|\?)/i.test(url)
) {
normalizeHref(hrefAttr, env)
} else {
if (
// internal anchor links
!url.startsWith('#') &&
// mail links
!url.startsWith('mailto:') &&
// links to files (other than html/md)
!/\.(?!html|md)\w+($|\?)/i.test(url)
) {
normalizeHref(hrefAttr, env)
}
// append base to internal (non-relative) urls
if (hrefAttr[1].startsWith('/')) {
hrefAttr[1] = `${base}${hrefAttr[1]}`.replace(/\/+/g, '/')
}
}
// encode vite-specific replace strings in case they appear in URLs
@ -90,11 +97,6 @@ export const linkPlugin = (
// export it for existence check
pushLink(url.replace(/\.html$/, ''), env)
// append base to internal (non-relative) urls
if (url.startsWith('/')) {
url = `${base}${url}`.replace(/\/+/g, '/')
}
// markdown-it encodes the uri
hrefAttr[1] = decodeURI(url)
}

@ -3,11 +3,15 @@ import type MarkdownIt from 'markdown-it'
export function preWrapperPlugin(md: MarkdownIt) {
const fence = md.renderer.rules.fence!
md.renderer.rules.fence = (...args) => {
const { info } = args[0][args[1]]
const lang = extractLang(info)
const [tokens, idx] = args
const token = tokens[idx]
// remove title from info
token.info = token.info.replace(/\[.*\]/, '')
const lang = extractLang(token.info)
const rawCode = fence(...args)
return `<div class="language-${lang}${
/ active( |$)/.test(info) ? ' active' : ''
/ active( |$)/.test(token.info) ? ' active' : ''
}"><button title="Copy Code" class="copy"></button><span class="lang">${lang}</span>${rawCode}</div>`
}
}
@ -19,7 +23,7 @@ export function extractTitle(info: string) {
const extractLang = (info: string) => {
return info
.trim()
.replace(/:(no-)?line-numbers$/, '')
.replace(/:(no-)?line-numbers({| |$).*/, '')
.replace(/(-vue|{| ).*$/, '')
.replace(/^vue-html$/, 'template')
}

@ -95,10 +95,10 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => {
* where #region and {meta} are optional
* and meta can be like '1,2,4-6 lang', 'lang' or '1,2,4-6'
*
* captures: ['/path/to/file.extension', 'extension', '#region', '{meta}']
* captures: ['/path/to/file.extension', 'extension', '#region', '{meta}', '[title]']
*/
const rawPathRegexp =
/^(.+(?:\.([a-z0-9]+)))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)?}))?$/
/^(.+(?:\.([a-z0-9]+)))(?:(#[\w-]+))?(?: ?(?:{(\d+(?:[,-]\d+)*)? ?(\S+)?}))? ?(?:\[(.+)\])?$/
const rawPath = state.src
.slice(start, end)
@ -106,13 +106,23 @@ export const snippetPlugin = (md: MarkdownIt, srcDir: string) => {
.replace(/^@/, srcDir)
.trim()
const [filename = '', extension = '', region = '', lines = '', lang = ''] =
(rawPathRegexp.exec(rawPath) || []).slice(1)
const [
filename = '',
extension = '',
region = '',
lines = '',
lang = '',
rawTitle = ''
] = (rawPathRegexp.exec(rawPath) || []).slice(1)
const title = rawTitle || filename.split('/').at(-1) || ''
state.line = startLine + 1
const token = state.push('fence', 'code', 0)
token.info = `${lang || extension}${lines ? `{${lines}}` : ''}`
token.info = `${lang || extension}${lines ? `{${lines}}` : ''}${
title ? `[${title}]` : ''
}`
// @ts-ignore
token.src = path.resolve(filename) + region

@ -1,19 +1,19 @@
import { resolveTitleFromToken } from '@mdit-vue/shared'
import _debug from 'debug'
import fs from 'fs'
import LRUCache from 'lru-cache'
import path from 'path'
import c from 'picocolors'
import LRUCache from 'lru-cache'
import { resolveTitleFromToken } from '@mdit-vue/shared'
import type { SiteConfig } from './config'
import { type PageData, type HeadConfig, EXTERNAL_URL_RE } from './shared'
import { slash } from './utils/slash'
import { getGitTimestamp } from './utils/getGitTimestamp'
import {
createMarkdownRenderer,
type MarkdownEnv,
type MarkdownOptions,
type MarkdownRenderer
} from './markdown'
import _debug from 'debug'
import { EXTERNAL_URL_RE, type HeadConfig, type PageData } from './shared'
import { getGitTimestamp } from './utils/getGitTimestamp'
import { slash } from './utils/slash'
const debug = _debug('vitepress:md')
const cache = new LRUCache<string, MarkdownCompileResult>({ max: 1024 })
@ -41,7 +41,12 @@ export async function createMarkdownToVueRenderFn(
cleanUrls = false,
siteConfig: SiteConfig | null = null
) {
const md = await createMarkdownRenderer(srcDir, options, base)
const md = await createMarkdownRenderer(
srcDir,
options,
base,
siteConfig?.logger
)
pages = pages.map((p) => slash(p.replace(/\.md$/, '')))
const replaceRegex = genReplaceRegexp(userDefines, isBuild)
@ -95,7 +100,7 @@ export async function createMarkdownToVueRenderFn(
// validate data.links
const deadLinks: string[] = []
const recordDeadLink = (url: string) => {
console.warn(
;(siteConfig?.logger ?? console).warn(
c.yellow(
`\n(!) Found dead link ${c.cyan(url)} in file ${c.white(
c.dim(file)

@ -1,5 +1,6 @@
import path from 'path'
import c from 'picocolors'
import type { OutputAsset, OutputChunk } from 'rollup'
import {
defineConfig,
mergeConfig,
@ -7,20 +8,25 @@ import {
type Plugin,
type ResolvedConfig
} from 'vite'
import type { SiteConfig } from './config'
import { createMarkdownToVueRenderFn, clearCache } from './markdownToVue'
import {
DIST_CLIENT_PATH,
APP_PATH,
SITE_DATA_REQUEST_PATH,
resolveAliases
DIST_CLIENT_PATH,
resolveAliases,
SITE_DATA_REQUEST_PATH
} from './alias'
import { slash } from './utils/slash'
import type { OutputAsset, OutputChunk } from 'rollup'
import { staticDataPlugin } from './staticDataPlugin'
import type { SiteConfig } from './config'
import { clearCache, createMarkdownToVueRenderFn } from './markdownToVue'
import type { PageDataPayload } from './shared'
import { staticDataPlugin } from './staticDataPlugin'
import { slash } from './utils/slash'
import { webFontsPlugin } from './webFontsPlugin'
declare module 'vite' {
interface UserConfig {
vitepress?: SiteConfig
}
}
const hashRE = /\.(\w+)\.js$/
const staticInjectMarkerRE =
/\b(const _hoisted_\d+ = \/\*(?:#|@)__PURE__\*\/\s*createStaticVNode)\("(.*)", (\d+)\)/g
@ -131,7 +137,6 @@ export async function createVitePressPlugin(
]
}
},
// @ts-ignore
vitepress: siteConfig
})
return userViteConfig
@ -290,19 +295,22 @@ export async function createVitePressPlugin(
async handleHotUpdate(ctx) {
const { file, read, server } = ctx
if (file === configPath || configDeps.includes(file)) {
console.log(
siteConfig.logger.info(
c.green(
`\n${path.relative(
`${path.relative(
process.cwd(),
file
)} changed, restarting server...`
)
)} changed, restarting server...\n`
),
{ clear: true, timestamp: true }
)
try {
clearCache()
await recreateServer?.()
} catch (err) {
console.error(c.red(`failed to restart server. error:\n`), err)
siteConfig.logger.error(
c.red(`\nfailed to restart server. error:\n${err}`)
)
}
return
}

@ -1,6 +1,6 @@
import compression from 'compression'
import fs from 'fs'
import path from 'path'
import compression from 'compression'
import polka, { type IOptions } from 'polka'
import sirv, { type RequestHandler } from 'sirv'
import { resolveConfig } from '../config'
@ -54,13 +54,15 @@ export async function serve(options: ServeOptions = {}) {
return polka({ onNoMatch })
.use(base, compress, serve)
.listen(port, () => {
console.log(`Built site served at http://localhost:${port}/${base}/\n`)
site.logger.info(
`Built site served at http://localhost:${port}/${base}/`
)
})
} else {
return polka({ onNoMatch })
.use(compress, serve)
.listen(port, () => {
console.log(`Built site served at http://localhost:${port}/\n`)
site.logger.info(`Built site served at http://localhost:${port}/`)
})
}
}

@ -21,8 +21,8 @@ export async function createServer(
root: config.srcDir,
base: config.site.base,
cacheDir: config.cacheDir,
// logLevel: 'warn',
plugins: await createVitePressPlugin(config, false, {}, {}, recreateServer),
server: serverOptions
server: serverOptions,
customLogger: config.logger
})
}

@ -47,6 +47,13 @@ export namespace DefaultTheme {
*/
sidebar?: Sidebar
/**
* Set to `false` to prevent rendering of aside container.
*
* @default true
*/
aside?: boolean
/**
* Info for the edit link. If it's undefined, the edit link feature will
* be disabled.

Loading…
Cancel
Save