@slidev/client 0.48.0-beta.24 → 0.48.0-beta.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builtin/Link.vue +3 -1
- package/builtin/TocList.vue +2 -2
- package/composables/useClicks.ts +13 -50
- package/composables/useDarkMode.ts +9 -0
- package/composables/useDrawings.ts +181 -0
- package/composables/useNav.ts +167 -7
- package/composables/useSwipeControls.ts +5 -2
- package/composables/useTocTree.ts +25 -7
- package/composables/useViewTransition.ts +1 -1
- package/context.ts +5 -0
- package/index.ts +12 -0
- package/internals/CodeRunner.vue +4 -1
- package/internals/DrawingControls.vue +11 -10
- package/internals/DrawingLayer.vue +4 -2
- package/internals/DrawingPreview.vue +4 -2
- package/internals/Goto.vue +4 -2
- package/internals/NavControls.vue +21 -3
- package/internals/PrintContainer.vue +3 -1
- package/internals/PrintSlide.vue +3 -3
- package/internals/QuickOverview.vue +5 -4
- package/internals/SideEditor.vue +4 -2
- package/internals/SlideContainer.vue +3 -1
- package/internals/SlidesShow.vue +16 -4
- package/logic/overview.ts +1 -1
- package/logic/route.ts +6 -9
- package/logic/slides.ts +5 -4
- package/main.ts +1 -16
- package/modules/context.ts +0 -40
- package/package.json +5 -3
- package/pages/notes.vue +3 -1
- package/pages/overview.vue +6 -3
- package/pages/play.vue +6 -3
- package/pages/presenter/print.vue +3 -1
- package/pages/presenter.vue +19 -6
- package/pages/print.vue +3 -1
- package/routes.ts +0 -8
- package/setup/code-runners.ts +6 -11
- package/setup/main.ts +39 -9
- package/setup/mermaid.ts +5 -6
- package/setup/monaco.ts +7 -9
- package/setup/root.ts +56 -11
- package/setup/shortcuts.ts +14 -12
- package/styles/shiki-twoslash.css +1 -1
- package/composables/useContext.ts +0 -12
- package/logic/drawings.ts +0 -161
- package/logic/nav-state.ts +0 -20
- package/logic/nav.ts +0 -71
- package/setup/prettier.ts +0 -43
- /package/{composables → logic}/hmr.ts +0 -0
- /package/{setup → modules}/codemirror.ts +0 -0
package/pages/print.vue
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { watchEffect } from 'vue'
|
|
3
3
|
import { windowSize } from '../state'
|
|
4
|
-
import { isPrintMode } from '../logic/nav'
|
|
5
4
|
import PrintContainer from '../internals/PrintContainer.vue'
|
|
6
5
|
import PrintStyle from '../internals/PrintStyle.vue'
|
|
6
|
+
import { useNav } from '../composables/useNav'
|
|
7
|
+
|
|
8
|
+
const { isPrintMode } = useNav()
|
|
7
9
|
|
|
8
10
|
watchEffect(() => {
|
|
9
11
|
if (isPrintMode)
|
package/routes.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'
|
|
2
|
-
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
|
|
3
2
|
import configs from '#slidev/configs'
|
|
4
3
|
|
|
5
4
|
export const routes: RouteRecordRaw[] = [
|
|
@@ -67,10 +66,3 @@ routes.push({
|
|
|
67
66
|
path: '/:no',
|
|
68
67
|
component: () => import('./pages/play.vue'),
|
|
69
68
|
})
|
|
70
|
-
|
|
71
|
-
export const router = createRouter({
|
|
72
|
-
history: __SLIDEV_HASH_ROUTE__
|
|
73
|
-
? createWebHashHistory(import.meta.env.BASE_URL)
|
|
74
|
-
: createWebHistory(import.meta.env.BASE_URL),
|
|
75
|
-
routes,
|
|
76
|
-
})
|
package/setup/code-runners.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
/* __imports__ */
|
|
2
1
|
import { createSingletonPromise } from '@antfu/utils'
|
|
3
|
-
import type { CodeRunner, CodeRunnerContext, CodeRunnerOutput, CodeRunnerOutputText, CodeRunnerOutputs
|
|
2
|
+
import type { CodeRunner, CodeRunnerContext, CodeRunnerOutput, CodeRunnerOutputText, CodeRunnerOutputs } from '@slidev/types'
|
|
4
3
|
import type { CodeToHastOptions } from 'shiki'
|
|
5
4
|
import { isDark } from '../logic/dark'
|
|
5
|
+
import setups from '#slidev/setups/code-runners'
|
|
6
6
|
|
|
7
7
|
export default createSingletonPromise(async () => {
|
|
8
8
|
const runners: Record<string, CodeRunner> = {
|
|
@@ -48,15 +48,10 @@ export default createSingletonPromise(async () => {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
let injection_return: CodeRunnerProviders = {}
|
|
56
|
-
|
|
57
|
-
/* __async_injections__ */
|
|
58
|
-
|
|
59
|
-
Object.assign(runners, injection_return)
|
|
51
|
+
for (const setup of setups) {
|
|
52
|
+
const result = await setup(runners)
|
|
53
|
+
Object.assign(runners, result)
|
|
54
|
+
}
|
|
60
55
|
|
|
61
56
|
return {
|
|
62
57
|
highlight,
|
package/setup/main.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
|
-
/* __imports__ */
|
|
2
|
-
|
|
3
1
|
import type { AppContext } from '@slidev/types'
|
|
4
2
|
import { MotionPlugin } from '@vueuse/motion'
|
|
5
3
|
import TwoSlashFloatingVue from '@shikijs/vitepress-twoslash/client'
|
|
4
|
+
import type { App } from 'vue'
|
|
5
|
+
import { nextTick } from 'vue'
|
|
6
|
+
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
|
|
7
|
+
import { createHead } from '@unhead/vue'
|
|
8
|
+
import { routeForceRefresh } from '../logic/route'
|
|
9
|
+
import { createVClickDirectives } from '../modules/v-click'
|
|
10
|
+
import { createVMarkDirective } from '../modules/v-mark'
|
|
11
|
+
import { routes } from '../routes'
|
|
12
|
+
import setups from '#slidev/setups/main'
|
|
13
|
+
|
|
14
|
+
import '#slidev/styles'
|
|
15
|
+
import 'shiki-magic-move/style.css'
|
|
6
16
|
|
|
7
|
-
export default function setupMain(
|
|
17
|
+
export default async function setupMain(app: App) {
|
|
8
18
|
function setMaxHeight() {
|
|
9
19
|
// disable the mobile navbar scroll
|
|
10
20
|
// see https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
|
|
@@ -13,12 +23,32 @@ export default function setupMain(context: AppContext) {
|
|
|
13
23
|
setMaxHeight()
|
|
14
24
|
window.addEventListener('resize', setMaxHeight)
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
const router = createRouter({
|
|
27
|
+
history: __SLIDEV_HASH_ROUTE__
|
|
28
|
+
? createWebHashHistory(import.meta.env.BASE_URL)
|
|
29
|
+
: createWebHistory(import.meta.env.BASE_URL),
|
|
30
|
+
routes,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
app.use(router)
|
|
34
|
+
app.use(createHead())
|
|
35
|
+
app.use(createVClickDirectives())
|
|
36
|
+
app.use(createVMarkDirective())
|
|
37
|
+
app.use(MotionPlugin)
|
|
38
|
+
app.use(TwoSlashFloatingVue as any, { container: '#slideshow' })
|
|
39
|
+
|
|
40
|
+
const context: AppContext = {
|
|
41
|
+
app,
|
|
42
|
+
router,
|
|
43
|
+
}
|
|
18
44
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
45
|
+
nextTick(() => {
|
|
46
|
+
router.afterEach(async () => {
|
|
47
|
+
await nextTick()
|
|
48
|
+
routeForceRefresh.value += 1
|
|
49
|
+
})
|
|
50
|
+
})
|
|
22
51
|
|
|
23
|
-
|
|
52
|
+
for (const setup of setups)
|
|
53
|
+
await setup(context)
|
|
24
54
|
}
|
package/setup/mermaid.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
/* __imports__ */
|
|
2
|
-
|
|
3
1
|
import type { MermaidOptions } from '@slidev/types'
|
|
4
2
|
import { defineMermaidSetup } from '@slidev/types'
|
|
3
|
+
import setups from '#slidev/setups/mermaid'
|
|
5
4
|
|
|
6
5
|
export default defineMermaidSetup(() => {
|
|
7
|
-
|
|
8
|
-
let injection_return: MermaidOptions = {
|
|
6
|
+
const setupReturn: MermaidOptions = {
|
|
9
7
|
theme: 'default',
|
|
10
8
|
}
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
for (const setup of setups)
|
|
11
|
+
Object.assign(setupReturn, setup())
|
|
13
12
|
|
|
14
|
-
return
|
|
13
|
+
return setupReturn
|
|
15
14
|
})
|
package/setup/monaco.ts
CHANGED
|
@@ -22,8 +22,8 @@ import { StandaloneServices } from 'monaco-editor/esm/vs/editor/standalone/brows
|
|
|
22
22
|
|
|
23
23
|
import { isDark } from '../logic/dark'
|
|
24
24
|
import configs from '#slidev/configs'
|
|
25
|
+
import setups from '#slidev/setups/monaco'
|
|
25
26
|
|
|
26
|
-
/* __imports__ */
|
|
27
27
|
window.MonacoEnvironment = {
|
|
28
28
|
getWorker(_, label) {
|
|
29
29
|
if (label === 'json')
|
|
@@ -98,13 +98,11 @@ const setup = createSingletonPromise(async () => {
|
|
|
98
98
|
const { shiki, themes, shikiToMonaco } = await import('#slidev/shiki')
|
|
99
99
|
const highlighter = await shiki
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
/* __async_injections__ */
|
|
101
|
+
const setupReturn: MonacoSetupReturn = {}
|
|
102
|
+
for (const setup of setups) {
|
|
103
|
+
const result = await setup(monaco)
|
|
104
|
+
Object.assign(setupReturn, result)
|
|
105
|
+
}
|
|
108
106
|
|
|
109
107
|
// Use Shiki to highlight Monaco
|
|
110
108
|
shikiToMonaco(highlighter, monaco)
|
|
@@ -122,7 +120,7 @@ const setup = createSingletonPromise(async () => {
|
|
|
122
120
|
return {
|
|
123
121
|
monaco,
|
|
124
122
|
ata,
|
|
125
|
-
...
|
|
123
|
+
...setupReturn,
|
|
126
124
|
}
|
|
127
125
|
})
|
|
128
126
|
|
package/setup/root.ts
CHANGED
|
@@ -1,27 +1,71 @@
|
|
|
1
|
-
|
|
2
|
-
import { watch } from 'vue'
|
|
1
|
+
import { computed, getCurrentInstance, reactive, ref, shallowRef, watch } from 'vue'
|
|
3
2
|
import { useHead } from '@unhead/vue'
|
|
3
|
+
import { useRouter } from 'vue-router'
|
|
4
4
|
import { configs } from '../env'
|
|
5
5
|
import { initSharedState, onPatch, patch } from '../state/shared'
|
|
6
6
|
import { initDrawingState } from '../state/drawings'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { TRUST_ORIGINS } from '../constants'
|
|
10
|
-
import { skipTransition } from '../composables/hmr'
|
|
7
|
+
import { TRUST_ORIGINS, injectionClicksContext, injectionCurrentPage, injectionRenderContext, injectionSlidevContext } from '../constants'
|
|
8
|
+
import { skipTransition } from '../logic/hmr'
|
|
11
9
|
import { makeId } from '../logic/utils'
|
|
10
|
+
import { getSlidePath } from '../logic/slides'
|
|
11
|
+
import { createFixedClicks } from '../composables/useClicks'
|
|
12
|
+
import { isDark } from '../logic/dark'
|
|
13
|
+
import { useNav } from '../composables/useNav'
|
|
14
|
+
import setups from '#slidev/setups/root'
|
|
12
15
|
|
|
13
16
|
export default function setupRoot() {
|
|
14
|
-
|
|
15
|
-
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
16
|
-
const injection_arg = undefined
|
|
17
|
+
const app = getCurrentInstance()!.appContext.app
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
const context = reactive({
|
|
20
|
+
nav: useNav(),
|
|
21
|
+
configs,
|
|
22
|
+
themeConfigs: computed(() => configs.themeConfig),
|
|
23
|
+
})
|
|
24
|
+
app.provide(injectionRenderContext, ref('none'))
|
|
25
|
+
app.provide(injectionSlidevContext, context)
|
|
26
|
+
app.provide(injectionCurrentPage, computed(() => context.nav.currentSlideNo))
|
|
27
|
+
app.provide(injectionClicksContext, shallowRef(createFixedClicks()))
|
|
28
|
+
|
|
29
|
+
// allows controls from postMessages
|
|
30
|
+
if (__DEV__) {
|
|
31
|
+
// @ts-expect-error expose global
|
|
32
|
+
window.__slidev__ = context
|
|
33
|
+
window.addEventListener('message', ({ data }) => {
|
|
34
|
+
if (data && data.target === 'slidev') {
|
|
35
|
+
if (data.type === 'navigate') {
|
|
36
|
+
context.nav.go(+data.no, +data.clicks || 0)
|
|
37
|
+
}
|
|
38
|
+
else if (data.type === 'css-vars') {
|
|
39
|
+
const root = document.documentElement
|
|
40
|
+
for (const [key, value] of Object.entries(data.vars || {}))
|
|
41
|
+
root.style.setProperty(key, value as any)
|
|
42
|
+
}
|
|
43
|
+
else if (data.type === 'color-schema') {
|
|
44
|
+
isDark.value = data.color === 'dark'
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// User Setups
|
|
51
|
+
for (const setup of setups)
|
|
52
|
+
setup()
|
|
19
53
|
|
|
20
54
|
const title = configs.titleTemplate.replace('%s', configs.title || 'Slidev')
|
|
55
|
+
|
|
56
|
+
const {
|
|
57
|
+
clicksContext,
|
|
58
|
+
currentSlideNo,
|
|
59
|
+
hasPrimarySlide,
|
|
60
|
+
isNotesViewer,
|
|
61
|
+
isPresenter,
|
|
62
|
+
} = useNav()
|
|
63
|
+
|
|
21
64
|
useHead({
|
|
22
65
|
title,
|
|
23
66
|
htmlAttrs: configs.htmlAttrs,
|
|
24
67
|
})
|
|
68
|
+
|
|
25
69
|
initSharedState(`${title} - shared`)
|
|
26
70
|
initDrawingState(`${title} - drawings`)
|
|
27
71
|
|
|
@@ -51,6 +95,7 @@ export default function setupRoot() {
|
|
|
51
95
|
time: new Date().getTime(),
|
|
52
96
|
})
|
|
53
97
|
}
|
|
98
|
+
const router = useRouter()
|
|
54
99
|
router.afterEach(updateSharedState)
|
|
55
100
|
watch(clicksContext, updateSharedState)
|
|
56
101
|
|
|
@@ -60,7 +105,7 @@ export default function setupRoot() {
|
|
|
60
105
|
if (state.lastUpdate?.type === 'presenter' && (+state.page !== +currentSlideNo.value || +clicksContext.value.current !== +state.clicks)) {
|
|
61
106
|
skipTransition.value = false
|
|
62
107
|
router.replace({
|
|
63
|
-
path: getSlidePath(state.page),
|
|
108
|
+
path: getSlidePath(state.page, isPresenter.value),
|
|
64
109
|
query: {
|
|
65
110
|
...router.currentRoute.value.query,
|
|
66
111
|
clicks: state.clicks || 0,
|
package/setup/shortcuts.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
/* __imports__ */
|
|
2
1
|
import { and, not, or } from '@vueuse/math'
|
|
3
2
|
import type { NavOperations, ShortcutOptions } from '@slidev/types'
|
|
4
3
|
import { downloadPDF } from '../utils'
|
|
5
|
-
import { go, goFirst, goLast, next, nextSlide, prev, prevSlide } from '../logic/nav'
|
|
6
4
|
import { toggleDark } from '../logic/dark'
|
|
7
5
|
import { magicKeys, showGotoDialog, showOverview, toggleOverview } from '../state'
|
|
8
|
-
import {
|
|
6
|
+
import { useNav } from '../composables/useNav'
|
|
7
|
+
import { useDrawings } from '../composables/useDrawings'
|
|
9
8
|
import { currentOverviewPage, downOverviewPage, nextOverviewPage, prevOverviewPage, upOverviewPage } from './../logic/overview'
|
|
9
|
+
import setups from '#slidev/setups/shortcuts'
|
|
10
10
|
|
|
11
11
|
export default function setupShortcuts() {
|
|
12
|
+
const { go, goFirst, goLast, next, nextSlide, prev, prevSlide } = useNav()
|
|
13
|
+
const { drawingEnabled } = useDrawings()
|
|
12
14
|
const { escape, space, shift, left, right, up, down, enter, d, g, o, '`': backtick } = magicKeys
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
16
|
-
const injection_arg: NavOperations = {
|
|
16
|
+
const context: NavOperations = {
|
|
17
17
|
next,
|
|
18
18
|
prev,
|
|
19
19
|
nextSlide,
|
|
@@ -29,8 +29,7 @@ export default function setupShortcuts() {
|
|
|
29
29
|
showGotoDialog: () => showGotoDialog.value = !showGotoDialog.value,
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
let injection_return: ShortcutOptions[] = [
|
|
32
|
+
let shortcuts: ShortcutOptions[] = [
|
|
34
33
|
{ name: 'next_space', key: and(space, not(shift)), fn: next, autoRepeat: true },
|
|
35
34
|
{ name: 'prev_space', key: and(space, shift), fn: prev, autoRepeat: true },
|
|
36
35
|
{ name: 'next_right', key: and(right, not(shift), not(showOverview)), fn: next, autoRepeat: true },
|
|
@@ -59,11 +58,14 @@ export default function setupShortcuts() {
|
|
|
59
58
|
},
|
|
60
59
|
]
|
|
61
60
|
|
|
62
|
-
const baseShortcutNames = new Set(
|
|
61
|
+
const baseShortcutNames = new Set(shortcuts.map(s => s.name))
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
for (const setup of setups) {
|
|
64
|
+
const result = setup(context, shortcuts)
|
|
65
|
+
shortcuts = shortcuts.concat(result)
|
|
66
|
+
}
|
|
65
67
|
|
|
66
|
-
const remainingBaseShortcutNames =
|
|
68
|
+
const remainingBaseShortcutNames = shortcuts.filter(s => s.name && baseShortcutNames.has(s.name))
|
|
67
69
|
if (remainingBaseShortcutNames.length === 0) {
|
|
68
70
|
const message = [
|
|
69
71
|
'========== WARNING ==========',
|
|
@@ -77,5 +79,5 @@ export default function setupShortcuts() {
|
|
|
77
79
|
console.warn(message)
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
return
|
|
82
|
+
return shortcuts
|
|
81
83
|
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { computed } from 'vue'
|
|
2
|
-
import { configs } from '../env'
|
|
3
|
-
import type { SlidevContext } from '../modules/context'
|
|
4
|
-
import * as nav from '../logic/nav'
|
|
5
|
-
|
|
6
|
-
export function useContext(): SlidevContext {
|
|
7
|
-
return {
|
|
8
|
-
nav: { ...nav }, // Convert the module to a plain object
|
|
9
|
-
configs,
|
|
10
|
-
themeConfigs: computed(() => configs.themeConfig),
|
|
11
|
-
}
|
|
12
|
-
}
|
package/logic/drawings.ts
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import { computed, markRaw, nextTick, reactive, ref, watch } from 'vue'
|
|
2
|
-
import type { Brush, Options as DrauuOptions, DrawingMode } from 'drauu'
|
|
3
|
-
import { createDrauu } from 'drauu'
|
|
4
|
-
import { toReactive, useLocalStorage } from '@vueuse/core'
|
|
5
|
-
import { drawingState, onPatch, patch } from '../state/drawings'
|
|
6
|
-
import { configs } from '../env'
|
|
7
|
-
import { isInputting } from '../state'
|
|
8
|
-
import { currentSlideNo, isPresenter } from './nav'
|
|
9
|
-
|
|
10
|
-
export const brushColors = [
|
|
11
|
-
'#ff595e',
|
|
12
|
-
'#ffca3a',
|
|
13
|
-
'#8ac926',
|
|
14
|
-
'#1982c4',
|
|
15
|
-
'#6a4c93',
|
|
16
|
-
'#ffffff',
|
|
17
|
-
'#000000',
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
export const drawingEnabled = useLocalStorage('slidev-drawing-enabled', false)
|
|
21
|
-
export const drawingPinned = useLocalStorage('slidev-drawing-pinned', false)
|
|
22
|
-
export const canUndo = ref(false)
|
|
23
|
-
export const canRedo = ref(false)
|
|
24
|
-
export const canClear = ref(false)
|
|
25
|
-
export const isDrawing = ref(false)
|
|
26
|
-
|
|
27
|
-
export const brush = toReactive(useLocalStorage<Brush>('slidev-drawing-brush', {
|
|
28
|
-
color: brushColors[0],
|
|
29
|
-
size: 4,
|
|
30
|
-
mode: 'stylus',
|
|
31
|
-
}))
|
|
32
|
-
|
|
33
|
-
const _mode = ref<DrawingMode | 'arrow'>('stylus')
|
|
34
|
-
const syncUp = computed(() => configs.drawings.syncAll || isPresenter.value)
|
|
35
|
-
let disableDump = false
|
|
36
|
-
|
|
37
|
-
export const drawingMode = computed({
|
|
38
|
-
get() {
|
|
39
|
-
return _mode.value
|
|
40
|
-
},
|
|
41
|
-
set(v: DrawingMode | 'arrow') {
|
|
42
|
-
_mode.value = v
|
|
43
|
-
if (v === 'arrow') {
|
|
44
|
-
// eslint-disable-next-line ts/no-use-before-define
|
|
45
|
-
drauu.mode = 'line'
|
|
46
|
-
brush.arrowEnd = true
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
// eslint-disable-next-line ts/no-use-before-define
|
|
50
|
-
drauu.mode = v
|
|
51
|
-
brush.arrowEnd = false
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
export const drauuOptions: DrauuOptions = reactive({
|
|
57
|
-
brush,
|
|
58
|
-
acceptsInputTypes: computed(() => (drawingEnabled.value && (!configs.drawings.presenterOnly || isPresenter.value)) ? undefined : ['pen' as const]),
|
|
59
|
-
coordinateTransform: false,
|
|
60
|
-
})
|
|
61
|
-
export const drauu = markRaw(createDrauu(drauuOptions))
|
|
62
|
-
|
|
63
|
-
export function clearDrauu() {
|
|
64
|
-
drauu.clear()
|
|
65
|
-
if (syncUp.value)
|
|
66
|
-
patch(currentSlideNo.value, '')
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function updateState() {
|
|
70
|
-
canRedo.value = drauu.canRedo()
|
|
71
|
-
canUndo.value = drauu.canUndo()
|
|
72
|
-
canClear.value = !!drauu.el?.children.length
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function loadCanvas(page?: number) {
|
|
76
|
-
disableDump = true
|
|
77
|
-
const data = drawingState[page || currentSlideNo.value]
|
|
78
|
-
if (data != null)
|
|
79
|
-
drauu.load(data)
|
|
80
|
-
else
|
|
81
|
-
drauu.clear()
|
|
82
|
-
updateState()
|
|
83
|
-
disableDump = false
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
drauu.on('changed', () => {
|
|
87
|
-
updateState()
|
|
88
|
-
if (!disableDump) {
|
|
89
|
-
const dump = drauu.dump()
|
|
90
|
-
const key = currentSlideNo.value
|
|
91
|
-
if ((drawingState[key] || '') !== dump && syncUp.value)
|
|
92
|
-
patch(key, drauu.dump())
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
onPatch((state) => {
|
|
97
|
-
disableDump = true
|
|
98
|
-
if (state[currentSlideNo.value] != null)
|
|
99
|
-
drauu.load(state[currentSlideNo.value] || '')
|
|
100
|
-
disableDump = false
|
|
101
|
-
updateState()
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
nextTick(() => {
|
|
105
|
-
watch(currentSlideNo, () => {
|
|
106
|
-
if (!drauu.mounted)
|
|
107
|
-
return
|
|
108
|
-
loadCanvas()
|
|
109
|
-
}, { immediate: true })
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
drauu.on('start', () => isDrawing.value = true)
|
|
113
|
-
drauu.on('end', () => isDrawing.value = false)
|
|
114
|
-
|
|
115
|
-
window.addEventListener('keydown', (e) => {
|
|
116
|
-
if (!drawingEnabled.value || isInputting.value)
|
|
117
|
-
return
|
|
118
|
-
|
|
119
|
-
const noModifier = !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey
|
|
120
|
-
let handled = true
|
|
121
|
-
if (e.code === 'KeyZ' && (e.ctrlKey || e.metaKey)) {
|
|
122
|
-
if (e.shiftKey)
|
|
123
|
-
drauu.redo()
|
|
124
|
-
else
|
|
125
|
-
drauu.undo()
|
|
126
|
-
}
|
|
127
|
-
else if (e.code === 'Escape') {
|
|
128
|
-
drawingEnabled.value = false
|
|
129
|
-
}
|
|
130
|
-
else if (e.code === 'KeyL' && noModifier) {
|
|
131
|
-
drawingMode.value = 'line'
|
|
132
|
-
}
|
|
133
|
-
else if (e.code === 'KeyA' && noModifier) {
|
|
134
|
-
drawingMode.value = 'arrow'
|
|
135
|
-
}
|
|
136
|
-
else if (e.code === 'KeyS' && noModifier) {
|
|
137
|
-
drawingMode.value = 'stylus'
|
|
138
|
-
}
|
|
139
|
-
else if (e.code === 'KeyR' && noModifier) {
|
|
140
|
-
drawingMode.value = 'rectangle'
|
|
141
|
-
}
|
|
142
|
-
else if (e.code === 'KeyE' && noModifier) {
|
|
143
|
-
drawingMode.value = 'ellipse'
|
|
144
|
-
}
|
|
145
|
-
else if (e.code === 'KeyC' && noModifier) {
|
|
146
|
-
clearDrauu()
|
|
147
|
-
}
|
|
148
|
-
else if (e.code.startsWith('Digit') && noModifier && +e.code[5] <= brushColors.length) {
|
|
149
|
-
brush.color = brushColors[+e.code[5] - 1]
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
handled = false
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (handled) {
|
|
156
|
-
e.preventDefault()
|
|
157
|
-
e.stopPropagation()
|
|
158
|
-
}
|
|
159
|
-
}, false)
|
|
160
|
-
|
|
161
|
-
export { drawingState }
|
package/logic/nav-state.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { computed } from 'vue'
|
|
2
|
-
import { logicOr } from '@vueuse/math'
|
|
3
|
-
import { configs } from '../env'
|
|
4
|
-
import { router } from '../routes'
|
|
5
|
-
import { getSlide, slides } from './slides'
|
|
6
|
-
|
|
7
|
-
export const currentRoute = computed(() => router.currentRoute.value)
|
|
8
|
-
|
|
9
|
-
export const isPrintMode = computed(() => currentRoute.value.query.print !== undefined)
|
|
10
|
-
export const isPrintWithClicks = computed(() => currentRoute.value.query.print === 'clicks')
|
|
11
|
-
export const isEmbedded = computed(() => currentRoute.value.query.embedded !== undefined)
|
|
12
|
-
export const isPlaying = computed(() => currentRoute.value.name === 'play')
|
|
13
|
-
export const isPresenter = computed(() => currentRoute.value.name === 'presenter')
|
|
14
|
-
export const isNotesViewer = computed(() => currentRoute.value.name === 'notes')
|
|
15
|
-
export const isPresenterAvailable = computed(() => !isPresenter.value && (!configs.remote || currentRoute.value.query.password === configs.remote))
|
|
16
|
-
|
|
17
|
-
export const hasPrimarySlide = logicOr(isPlaying, isPresenter)
|
|
18
|
-
|
|
19
|
-
export const currentSlideNo = computed(() => hasPrimarySlide.value ? getSlide(currentRoute.value.params.no as string)?.no ?? 1 : 1)
|
|
20
|
-
export const currentSlideRoute = computed(() => slides.value[currentSlideNo.value - 1])
|
package/logic/nav.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { computed, watch } from 'vue'
|
|
2
|
-
import { router } from '../routes'
|
|
3
|
-
import { usePrimaryClicks } from '../composables/useClicks'
|
|
4
|
-
import { CLICKS_MAX } from '../constants'
|
|
5
|
-
import { useNavBase } from '../composables/useNav'
|
|
6
|
-
import { useRouteQuery } from './route'
|
|
7
|
-
import { currentRoute, currentSlideRoute, hasPrimarySlide } from './nav-state'
|
|
8
|
-
import { getSlide } from './slides'
|
|
9
|
-
|
|
10
|
-
export * from './slides'
|
|
11
|
-
export * from './nav-state'
|
|
12
|
-
|
|
13
|
-
export const clicksContext = computed(() => usePrimaryClicks(currentSlideRoute.value))
|
|
14
|
-
|
|
15
|
-
const queryClicksRaw = useRouteQuery('clicks', '0')
|
|
16
|
-
export const queryClicks = computed({
|
|
17
|
-
get() {
|
|
18
|
-
if (clicksContext.value.disabled)
|
|
19
|
-
return CLICKS_MAX
|
|
20
|
-
let v = +(queryClicksRaw.value || 0)
|
|
21
|
-
if (Number.isNaN(v))
|
|
22
|
-
v = 0
|
|
23
|
-
return v
|
|
24
|
-
},
|
|
25
|
-
set(v) {
|
|
26
|
-
queryClicksRaw.value = v.toString()
|
|
27
|
-
},
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
export const {
|
|
31
|
-
slides,
|
|
32
|
-
total,
|
|
33
|
-
currentPath,
|
|
34
|
-
currentSlideNo,
|
|
35
|
-
currentPage,
|
|
36
|
-
currentLayout,
|
|
37
|
-
currentTransition,
|
|
38
|
-
clicksDirection,
|
|
39
|
-
nextRoute,
|
|
40
|
-
prevRoute,
|
|
41
|
-
clicks,
|
|
42
|
-
clicksTotal,
|
|
43
|
-
hasNext,
|
|
44
|
-
hasPrev,
|
|
45
|
-
tocTree,
|
|
46
|
-
navDirection,
|
|
47
|
-
openInEditor,
|
|
48
|
-
next,
|
|
49
|
-
prev,
|
|
50
|
-
go,
|
|
51
|
-
goLast,
|
|
52
|
-
goFirst,
|
|
53
|
-
nextSlide,
|
|
54
|
-
prevSlide,
|
|
55
|
-
} = useNavBase(
|
|
56
|
-
currentSlideRoute,
|
|
57
|
-
clicksContext,
|
|
58
|
-
queryClicks,
|
|
59
|
-
router,
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
watch(
|
|
63
|
-
[total, currentRoute],
|
|
64
|
-
async () => {
|
|
65
|
-
if (hasPrimarySlide.value && !getSlide(currentRoute.value.params.no as string)) {
|
|
66
|
-
// The current slide may has been removed. Redirect to the last slide.
|
|
67
|
-
await goLast()
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
{ flush: 'pre', immediate: true },
|
|
71
|
-
)
|
package/setup/prettier.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { format } from 'prettier'
|
|
2
|
-
|
|
3
|
-
export async function formatCode(code: string, lang: string) {
|
|
4
|
-
try {
|
|
5
|
-
let parser = 'babel'
|
|
6
|
-
let plugins: any[] = []
|
|
7
|
-
|
|
8
|
-
switch (lang) {
|
|
9
|
-
case 'ts':
|
|
10
|
-
case 'typescript':
|
|
11
|
-
parser = 'typescript'
|
|
12
|
-
plugins = [
|
|
13
|
-
(await import('prettier/plugins/babel')).default,
|
|
14
|
-
(await import('prettier/plugins/typescript')).default,
|
|
15
|
-
]
|
|
16
|
-
break
|
|
17
|
-
case 'html':
|
|
18
|
-
parser = 'html'
|
|
19
|
-
plugins = [
|
|
20
|
-
(await import('prettier/plugins/html')).default,
|
|
21
|
-
]
|
|
22
|
-
break
|
|
23
|
-
default:
|
|
24
|
-
parser = 'babel'
|
|
25
|
-
plugins = [
|
|
26
|
-
(await import('prettier/plugins/babel')).default,
|
|
27
|
-
]
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return format(code, {
|
|
31
|
-
semi: false,
|
|
32
|
-
singleQuote: true,
|
|
33
|
-
tabWidth: 2,
|
|
34
|
-
useTabs: false,
|
|
35
|
-
parser,
|
|
36
|
-
plugins,
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
catch (e) {
|
|
40
|
-
console.error(e)
|
|
41
|
-
return code
|
|
42
|
-
}
|
|
43
|
-
}
|
|
File without changes
|
|
File without changes
|