Skip to content

Commit c127632

Browse files
committed
feat: support hash router mode
1 parent 862eca7 commit c127632

File tree

13 files changed

+92
-23
lines changed

13 files changed

+92
-23
lines changed

packages/client/internals/Play.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script setup lang="ts">
22
import { ref, computed } from 'vue'
3-
import { isPrintMode, showEditor, windowSize, isScreenVertical, slideScale } from '../state'
4-
import { next, prev, useSwipeControls } from '../logic/nav'
3+
import { showEditor, windowSize, isScreenVertical, slideScale } from '../state'
4+
import { isPrintMode, next, prev, useSwipeControls } from '../logic/nav'
55
import { registerShotcuts } from '../logic/shortcuts'
66
import Controls from './Controls.vue'
77
import SlideContainer from './SlideContainer.vue'

packages/client/logic/nav.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import { computed, Ref, ref } from 'vue'
22
import { isString, SwipeDirection, timestamp, useSwipe } from '@vueuse/core'
3-
import { query } from '../state'
43
import { rawRoutes, router } from '../routes'
54
import { configs } from '../env'
5+
import { useRouteQuery } from './route'
66

77
export { rawRoutes }
88

99
export const route = computed(() => router.currentRoute.value)
1010

1111
export const isPresenter = computed(() => route.value.path.startsWith('/presenter'))
1212

13+
export const queryClicks = useRouteQuery('clicks', '0')
1314
export const total = computed(() => rawRoutes.length - 1)
1415
export const path = computed(() => route.value.path)
1516

@@ -25,13 +26,13 @@ export const nextRoute = computed(() => rawRoutes.find(i => i.path === `${Math.m
2526
export const clicksElements = computed<HTMLElement[]>(() => currentRoute.value?.meta?.__clicksElements || [])
2627
export const clicks = computed<number>({
2728
get() {
28-
let clicks = +query.clicks || 0
29+
let clicks = +(queryClicks.value || 0)
2930
if (isNaN(clicks))
3031
clicks = 0
3132
return clicks
3233
},
3334
set(v) {
34-
query.clicks = v.toString()
35+
queryClicks.value = v.toString()
3536
},
3637
})
3738

@@ -47,7 +48,6 @@ export function next() {
4748
export async function prev() {
4849
if (clicks.value <= 0)
4950
await prevSlide()
50-
5151
else
5252
clicks.value -= 1
5353
}
@@ -63,14 +63,11 @@ export function nextSlide() {
6363

6464
export async function prevSlide(lastClicks = true) {
6565
const next = Math.max(1, currentPage.value - 1)
66-
await go(next)
67-
if (lastClicks)
68-
clicks.value = clicksTotal.value
66+
await go(next, (lastClicks && clicksTotal.value) ? clicksTotal.value : undefined)
6967
}
7068

71-
export function go(page: number) {
72-
clicks.value = 0
73-
return router.push(getPath(page))
69+
export function go(page: number, clicks?: number) {
70+
return router.push({ path: getPath(page), query: { ...route.value.query, clicks } })
7471
}
7572

7673
export function useSwipeControls(root: Ref<HTMLElement | undefined>) {
@@ -109,3 +106,5 @@ export async function downloadPDF() {
109106
`${configs.title}.pdf`,
110107
)
111108
}
109+
110+
export const isPrintMode = computed(() => route.value.query.print !== undefined)

packages/client/logic/route.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { computed, nextTick, unref } from 'vue-demi'
2+
import { router } from '../routes'
3+
4+
export function useRouteQuery<T extends string | string[]>(
5+
name: string,
6+
defaultValue?: T,
7+
{
8+
mode = 'replace',
9+
} = {},
10+
) {
11+
return computed<any>({
12+
get() {
13+
const data = router.currentRoute.value.query[name]
14+
if (data == null)
15+
return defaultValue ?? null
16+
if (Array.isArray(data))
17+
return data.filter(Boolean)
18+
return data
19+
},
20+
set(v) {
21+
nextTick(() => {
22+
router[unref(mode) as 'replace' | 'push']({ query: { ...router.currentRoute.value.query, [name]: v } })
23+
})
24+
},
25+
})
26+
}

packages/client/modules/directives.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { App, DirectiveBinding, InjectionKey, Ref, watch } from 'vue'
22
import { remove } from '@antfu/utils'
3-
import { isPrintMode } from '../state'
3+
import { isPrintMode } from '../logic/nav'
44

55
export const injectionClicks: InjectionKey<Ref<number>> = Symbol('v-click-clicks')
66
export const injectionClicksElements: InjectionKey<Ref<(Element | string)[]>> = Symbol('v-click-clicks-elements')

packages/client/routes.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createRouter, RouteRecordRaw, createWebHistory } from 'vue-router'
1+
import { createRouter, RouteRecordRaw, createWebHistory, createWebHashHistory } from 'vue-router'
22
import Play from './internals/Play.vue'
33
// @ts-expect-error
44
import _rawRoutes from '/@slidev/routes'
@@ -33,7 +33,7 @@ if (import.meta.env.DEV) {
3333
}
3434

3535
export const router = createRouter({
36-
history: createWebHistory(import.meta.env.BASE_URL),
36+
history: __SLIDEV_HASH_ROUTE__ ? createWebHashHistory(import.meta.env.BASE_URL) : createWebHistory(import.meta.env.BASE_URL),
3737
routes,
3838
})
3939

packages/client/state/index.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useMagicKeys, useActiveElement, useStorage, useUrlSearchParams, useBreakpoints, breakpointsTailwind, useWindowSize, useFullscreen, useToggle, isClient } from '@vueuse/core'
1+
import { useMagicKeys, useActiveElement, useStorage, useBreakpoints, breakpointsTailwind, useWindowSize, useFullscreen, useToggle, isClient } from '@vueuse/core'
22
import { computed, ref } from 'vue'
33

44
export const showOverview = ref(false)
@@ -7,7 +7,6 @@ export const showInfoDialog = ref(false)
77
export const showGotoDialog = ref(false)
88

99
export const shortcutsEnabled = ref(true)
10-
export const query = useUrlSearchParams()
1110
export const breakpoints = useBreakpoints(breakpointsTailwind)
1211
export const windowSize = useWindowSize()
1312
export const magicKeys = useMagicKeys()
@@ -25,6 +24,4 @@ export const slideScale = useStorage<number>('slidev-scale', null)
2524
export const showEditor = useStorage('slidev-show-editor', false)
2625
export const editorWidth = useStorage('slidev-editor-width', isClient ? window.innerWidth * 0.4 : 100)
2726

28-
export const isPrintMode = computed(() => query.print != null)
29-
3027
export const toggleOverview = useToggle(showOverview)

packages/parser/src/core.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export function parse(
144144
info: false,
145145
highlighter: 'prism',
146146
colorSchema: 'auto',
147+
routerMode: 'history',
147148
}
148149
const config: SlidevConfig = Object.assign(
149150
defaultConfig,

packages/slidev/node/cli.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@ import prompts from 'prompts'
88
import { blue, bold, cyan, dim, gray, green, yellow } from 'kolorist'
99
import { LogLevel, ViteDevServer } from 'vite'
1010
import * as parser from '@slidev/parser/fs'
11+
import { SlidevConfig } from '@slidev/types'
1112
import { version } from '../package.json'
1213
import { createServer } from './server'
1314
import { getThemeRoots, isRelative, ResolvedSlidevOptions, resolveOptions } from './options'
1415
import { resolveThemeName } from './themes'
1516

17+
const CONFIG_RESTART_FIELDS: (keyof SlidevConfig)[] = [
18+
'highlighter',
19+
'monaco',
20+
'routerMode',
21+
]
22+
1623
const cli = yargs
1724
.scriptName('slidev')
1825
.usage('$0 [args]')
@@ -82,7 +89,7 @@ cli.command(
8289
console.log(yellow('\n restarting on theme change\n'))
8390
initServer()
8491
}
85-
else if (newData.config.monaco !== data.config.monaco || newData.config.highlighter !== data.config.highlighter) {
92+
else if (CONFIG_RESTART_FIELDS.some(i => newData.config[i] !== data.config[i])) {
8693
console.log(yellow('\n restarting on config change\n'))
8794
initServer()
8895
}
@@ -277,6 +284,7 @@ cli.command(
277284
output,
278285
timeout,
279286
dark,
287+
routerMode: options.data.config.routerMode,
280288
})
281289
console.log(`${green(' ✓ ')}${dim('exported to ')}./${output}\n`)
282290
server.close()

packages/slidev/node/export.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export interface ExportOptions {
1515
output?: string
1616
timeout?: number
1717
dark?: boolean
18+
routerMode?: 'hash' | 'history'
1819
}
1920

2021
function createSlidevProgress() {
@@ -62,6 +63,7 @@ export async function exportSlides({
6263
base = '/',
6364
timeout = 500,
6465
dark = false,
66+
routerMode = 'history',
6567
}: ExportOptions) {
6668
if (!packageExists('playwright-chromium'))
6769
throw new Error('The exporting for Slidev is powered by Playwright, please installed it via `npm i playwright-chromium`')
@@ -83,7 +85,10 @@ export async function exportSlides({
8385

8486
if (dark)
8587
await page.emulateMedia({ colorScheme: 'dark' })
86-
await page.goto(`http://localhost:${port}${base}${no}?print`, {
88+
const url = routerMode === 'hash'
89+
? `http://localhost:${port}/#${base}${no}?print`
90+
: `http://localhost:${port}${base}${no}?print`
91+
await page.goto(url, {
8792
waitUntil: 'networkidle',
8893
})
8994
await page.waitForTimeout(timeout)

packages/slidev/node/plugins/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export function createConfigPlugin(options: ResolvedSlidevOptions): Plugin {
1616
const injection: InlineConfig = {
1717
define: {
1818
__SLIDEV_CLIENT_ROOT__: JSON.stringify(toAtFS(options.clientRoot)),
19+
__SLIDEV_HASH_ROUTE__: options.data.config.routerMode === 'hash',
20+
__DEV__: options.mode === 'dev',
1921
},
2022
resolve: {
2123
alias: {

0 commit comments

Comments
 (0)