mirror of https://github.com/YunYouJun/valaxy
feat: support client redirect (#314)
* feat: valaxy-addon-client-redirects * feat: move client redirect feature into valaxy
This commit is contained in:
parent
5d9b43a788
commit
615f0c5a89
|
@ -144,4 +144,11 @@ export default defineSiteConfig({
|
|||
encrypt: {
|
||||
enable: true,
|
||||
},
|
||||
|
||||
redirects: [
|
||||
{
|
||||
from: '/foo',
|
||||
to: '/about',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
|
|
@ -539,7 +539,15 @@ password: your_password
|
|||
:::
|
||||
|
||||
::: tip
|
||||
|
||||
<div lang="zh-CN">
|
||||
如果在文章的 Front Matter 中设置了 `password`,文章中的部分加密将被忽略。
|
||||
</div>
|
||||
|
||||
<div lang="en">
|
||||
If you set `password` in Front Matter, partial encryption will be ignored.
|
||||
</div>
|
||||
|
||||
:::
|
||||
|
||||
::: zh-CN
|
||||
|
@ -558,6 +566,62 @@ Wrap content to be encrypted in `<!-- valaxy-encrypt-start:your_password --><!--
|
|||
Examples can be found in [Partial Content Encryption](/examples/partial-content-encryption)。
|
||||
:::
|
||||
|
||||
### 客户端重定向 {lang="zh-CN"}
|
||||
|
||||
### Client Redirects {lang="en"}
|
||||
|
||||
::: zh-CN
|
||||
这会生成额外的 HTML 页面,用与跳转到 valaxy 中已有的页面。
|
||||
:::
|
||||
|
||||
::: en
|
||||
This will generate additional HTML pages, used to jump to the valaxy's existing pages.
|
||||
:::
|
||||
|
||||
::: tip
|
||||
|
||||
<div lang="zh-CN">
|
||||
客户端重定向只在 SSG build 时启用
|
||||
</div>
|
||||
|
||||
<div lang="en">
|
||||
Client redirects will only be enabled in SSG build
|
||||
</div>
|
||||
|
||||
:::
|
||||
|
||||
::: zh-CN
|
||||
例如:
|
||||
:::
|
||||
|
||||
::: en
|
||||
For example:
|
||||
:::
|
||||
|
||||
```ts
|
||||
// site.config.ts
|
||||
export default defineSiteConfig({
|
||||
redirects: [
|
||||
{
|
||||
from: ['/foo', '/bar'],
|
||||
to: '/about',
|
||||
},
|
||||
{
|
||||
from: '/v1/about',
|
||||
to: '/about',
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
::: zh-CN
|
||||
`/foo`, `/bar`, `/v1/about` 这些路由会被重定向到 `/about`。
|
||||
:::
|
||||
|
||||
::: en
|
||||
`/foo`, `/bar`, `/v1/about` these routes will be redirected to `/about`。
|
||||
:::
|
||||
|
||||
## 主题配置 {lang="zh-CN"}
|
||||
|
||||
## Theme Config {lang="en"}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { resolve } from 'node:path'
|
||||
import { join, resolve } from 'node:path'
|
||||
import type { InlineConfig } from 'vite'
|
||||
import { mergeConfig as mergeViteConfig, build as viteBuild } from 'vite'
|
||||
import { build as viteSsgBuild } from 'vite-ssg/node'
|
||||
|
@ -8,6 +8,7 @@ import fs from 'fs-extra'
|
|||
import consola from 'consola'
|
||||
import type { ResolvedValaxyOptions } from './options'
|
||||
import { ViteValaxyPlugins } from './plugins/preset'
|
||||
import { collectRedirects, writeRedirectFiles } from './utils/clientRedirects'
|
||||
|
||||
export async function build(
|
||||
options: ResolvedValaxyOptions,
|
||||
|
@ -55,6 +56,7 @@ export async function ssgBuild(
|
|||
|
||||
/**
|
||||
* post process for ssg fix extra string like `/html>` `ml>` `l>`
|
||||
* handle tasks after ssg build
|
||||
* todo find why
|
||||
* @param options
|
||||
*/
|
||||
|
@ -72,4 +74,22 @@ export async function postProcessForSSG(options: ResolvedValaxyOptions) {
|
|||
await fs.writeFile(indexPath, indexFile.slice(0, htmlTagStart + htmlTag.length), 'utf-8')
|
||||
}
|
||||
}
|
||||
|
||||
await generateClientRedirects(options)
|
||||
}
|
||||
|
||||
export async function generateClientRedirects(options: ResolvedValaxyOptions) {
|
||||
const outputPath = resolve(options.userRoot, 'dist')
|
||||
const redirectRules = collectRedirects(options.config.siteConfig?.redirects ?? [])
|
||||
|
||||
const task = redirectRules.map(async (rule) => {
|
||||
const fromPath = join(outputPath, `${rule.from}.html`)
|
||||
const toPath = join(outputPath, `${rule.to}.html`)
|
||||
const routeExist = await fs.pathExists(toPath)
|
||||
if (!routeExist)
|
||||
throw new Error(`the route of '${rule.to}' not exists`)
|
||||
await writeRedirectFiles(rule.to, fromPath)
|
||||
})
|
||||
|
||||
await Promise.all(task)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
import { writeFile } from 'node:fs/promises'
|
||||
import { ensureFile } from 'fs-extra'
|
||||
import type { RedirectRule } from '../../types'
|
||||
|
||||
function handleRoute(route: string) {
|
||||
if (route === '/')
|
||||
return '/index'
|
||||
if (route.endsWith('/'))
|
||||
return route.slice(0, -1)
|
||||
return route
|
||||
}
|
||||
|
||||
interface RedirectItem {
|
||||
from: string
|
||||
to: string
|
||||
}
|
||||
|
||||
export function collectRedirects(redirectRule: RedirectRule[]) {
|
||||
const redirects: RedirectItem[] = []
|
||||
for (const rule of redirectRule) {
|
||||
if (Array.isArray(rule.from)) {
|
||||
for (const from of rule.from) {
|
||||
redirects.push({
|
||||
from: handleRoute(from),
|
||||
to: handleRoute(rule.to),
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
redirects.push({
|
||||
from: handleRoute(rule.from),
|
||||
to: handleRoute(rule.to),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return redirects
|
||||
}
|
||||
|
||||
export async function writeRedirectFiles(route: string, filePath: string) {
|
||||
await ensureFile(filePath)
|
||||
await writeFile(filePath, `
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="refresh" content="0; url=${route}">
|
||||
<link rel="canonical" href="${route}">
|
||||
</head>
|
||||
<script>
|
||||
window.location.href = '${route}' + window.location.search + window.location.hash
|
||||
</script>
|
||||
</html>
|
||||
`)
|
||||
}
|
|
@ -22,6 +22,11 @@ export interface SocialLink {
|
|||
color: string
|
||||
}
|
||||
|
||||
export interface RedirectRule {
|
||||
to: string
|
||||
from: string | string[]
|
||||
}
|
||||
|
||||
// shared with valaxy node and client
|
||||
export interface SiteConfig {
|
||||
/**
|
||||
|
@ -313,6 +318,12 @@ export interface SiteConfig {
|
|||
* @description:zh-CN 限制代码块的高度,单位是 px
|
||||
*/
|
||||
codeHeightLimit?: number
|
||||
|
||||
/**
|
||||
* @description:en-US client redirect rules
|
||||
* @description:zh-CN 客户端重定向规则
|
||||
*/
|
||||
redirects?: RedirectRule[]
|
||||
}
|
||||
|
||||
export type PartialDeep<T> = {
|
||||
|
|
Loading…
Reference in New Issue