@slidev/client 0.49.0-beta.2 → 0.49.0-beta.4
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/Monaco.vue +24 -4
- package/constants.ts +3 -0
- package/internals/QuickOverview.vue +6 -0
- package/package.json +8 -8
- package/setup/code-runners.ts +14 -25
- package/setup/main.ts +2 -2
- package/setup/monaco.ts +0 -3
- package/setup/routes.ts +80 -0
- package/routes.ts +0 -68
package/builtin/Monaco.vue
CHANGED
|
@@ -17,7 +17,10 @@ import lz from 'lz-string'
|
|
|
17
17
|
import type * as monaco from 'monaco-editor'
|
|
18
18
|
import { computed, nextTick, onMounted, ref } from 'vue'
|
|
19
19
|
import type { RawAtValue } from '@slidev/types'
|
|
20
|
+
import { whenever } from '@vueuse/core'
|
|
20
21
|
import { makeId } from '../logic/utils'
|
|
22
|
+
import { useSlideContext } from '../context'
|
|
23
|
+
import { useNav } from '../composables/useNav'
|
|
21
24
|
import CodeRunner from '../internals/CodeRunner.vue'
|
|
22
25
|
|
|
23
26
|
const props = withDefaults(defineProps<{
|
|
@@ -76,6 +79,19 @@ const height = computed(() => {
|
|
|
76
79
|
return props.height
|
|
77
80
|
})
|
|
78
81
|
|
|
82
|
+
const loadTypes = ref<() => void>()
|
|
83
|
+
const { $page: thisSlideNo, $renderContext: renderContext } = useSlideContext()
|
|
84
|
+
const { currentSlideNo } = useNav()
|
|
85
|
+
const stopWatchTypesLoading = whenever(
|
|
86
|
+
() => Math.abs(thisSlideNo.value - currentSlideNo.value) <= 1 && loadTypes.value,
|
|
87
|
+
(loadTypes) => {
|
|
88
|
+
if (['slide', 'presenter'].includes(renderContext.value))
|
|
89
|
+
loadTypes()
|
|
90
|
+
else
|
|
91
|
+
setTimeout(loadTypes, 5000)
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
|
|
79
95
|
onMounted(async () => {
|
|
80
96
|
// Lazy load monaco, so it will be bundled in async chunk
|
|
81
97
|
const { default: setup } = await import('../setup/monaco')
|
|
@@ -137,11 +153,15 @@ onMounted(async () => {
|
|
|
137
153
|
})
|
|
138
154
|
editableEditor = editor
|
|
139
155
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
loadTypes.value = () => {
|
|
157
|
+
stopWatchTypesLoading()
|
|
158
|
+
import('#slidev/monaco-types')
|
|
159
|
+
if (props.ata) {
|
|
143
160
|
ata(editableEditor.getValue())
|
|
144
|
-
|
|
161
|
+
editableEditor.onDidChangeModelContent(debounce(1000, () => {
|
|
162
|
+
ata(editableEditor.getValue())
|
|
163
|
+
}))
|
|
164
|
+
}
|
|
145
165
|
}
|
|
146
166
|
const originalLayoutContentWidget = editableEditor.layoutContentWidget.bind(editableEditor)
|
|
147
167
|
editableEditor.layoutContentWidget = (widget: any) => {
|
package/constants.ts
CHANGED
|
@@ -102,6 +102,11 @@ watchEffect(() => {
|
|
|
102
102
|
// Watch rowCount, make sure up and down shortcut work correctly.
|
|
103
103
|
overviewRowCount.value = rowCount.value
|
|
104
104
|
})
|
|
105
|
+
|
|
106
|
+
const activeSlidesLoaded = ref(false)
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
activeSlidesLoaded.value = true
|
|
109
|
+
}, 3000)
|
|
105
110
|
</script>
|
|
106
111
|
|
|
107
112
|
<template>
|
|
@@ -112,6 +117,7 @@ watchEffect(() => {
|
|
|
112
117
|
leave-to-class="opacity-0 scale-102 !backdrop-blur-0px"
|
|
113
118
|
>
|
|
114
119
|
<div
|
|
120
|
+
v-if="value || activeSlidesLoaded"
|
|
115
121
|
v-show="value"
|
|
116
122
|
class="bg-main !bg-opacity-75 p-16 py-20 overflow-y-auto backdrop-blur-5px fixed left-0 right-0 top-0 h-[calc(var(--vh,1vh)*100)]"
|
|
117
123
|
@click="close()"
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.49.0-beta.
|
|
4
|
+
"version": "0.49.0-beta.4",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "antfu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@slidev/rough-notation": "^0.1.0",
|
|
38
38
|
"@typescript/ata": "^0.9.4",
|
|
39
39
|
"@unhead/vue": "^1.9.5",
|
|
40
|
-
"@unocss/reset": "^0.59.
|
|
40
|
+
"@unocss/reset": "^0.59.3",
|
|
41
41
|
"@vueuse/core": "^10.9.0",
|
|
42
42
|
"@vueuse/math": "^10.9.0",
|
|
43
43
|
"@vueuse/motion": "^2.1.0",
|
|
@@ -53,17 +53,17 @@
|
|
|
53
53
|
"prettier": "^3.2.5",
|
|
54
54
|
"recordrtc": "^5.6.2",
|
|
55
55
|
"shiki": "^1.3.0",
|
|
56
|
-
"shiki-magic-move": "^0.3.
|
|
56
|
+
"shiki-magic-move": "^0.3.6",
|
|
57
57
|
"typescript": "^5.4.5",
|
|
58
|
-
"unocss": "^0.59.
|
|
59
|
-
"vue": "^3.4.
|
|
58
|
+
"unocss": "^0.59.3",
|
|
59
|
+
"vue": "^3.4.22",
|
|
60
60
|
"vue-demi": "^0.14.7",
|
|
61
61
|
"vue-router": "^4.3.0",
|
|
62
62
|
"yaml": "^2.4.1",
|
|
63
|
-
"@slidev/parser": "0.49.0-beta.
|
|
64
|
-
"@slidev/types": "0.49.0-beta.
|
|
63
|
+
"@slidev/parser": "0.49.0-beta.4",
|
|
64
|
+
"@slidev/types": "0.49.0-beta.4"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"vite": "^5.2.
|
|
67
|
+
"vite": "^5.2.9"
|
|
68
68
|
}
|
|
69
69
|
}
|
package/setup/code-runners.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { createSingletonPromise
|
|
2
|
-
import type { CodeRunner,
|
|
1
|
+
import { createSingletonPromise } from '@antfu/utils'
|
|
2
|
+
import type { CodeRunner, CodeRunnerOutput, CodeRunnerOutputText, CodeRunnerOutputs } from '@slidev/types'
|
|
3
3
|
import type { CodeToHastOptions } from 'shiki'
|
|
4
4
|
import type ts from 'typescript'
|
|
5
5
|
import { isDark } from '../logic/dark'
|
|
6
|
+
import deps from '#slidev/monaco-run-deps'
|
|
6
7
|
import setups from '#slidev/setups/code-runners'
|
|
7
8
|
|
|
8
9
|
export default createSingletonPromise(async () => {
|
|
@@ -25,18 +26,6 @@ export default createSingletonPromise(async () => {
|
|
|
25
26
|
...options,
|
|
26
27
|
})
|
|
27
28
|
|
|
28
|
-
const resolveId = async (specifier: string) => {
|
|
29
|
-
if (!'./'.includes(specifier[0]) && !/^(@[^\/:]+?\/)?[^\/:]+$/.test(specifier))
|
|
30
|
-
return specifier // this might be a url or something else
|
|
31
|
-
const res = await fetch(`/@slidev/resolve-id?specifier=${specifier}`)
|
|
32
|
-
if (!res.ok)
|
|
33
|
-
return null
|
|
34
|
-
const id = await res.text()
|
|
35
|
-
if (!id)
|
|
36
|
-
return null
|
|
37
|
-
return `/@fs${ensurePrefix('/', slash(id))}`
|
|
38
|
-
}
|
|
39
|
-
|
|
40
29
|
const run = async (code: string, lang: string, options: Record<string, unknown>): Promise<CodeRunnerOutputs> => {
|
|
41
30
|
try {
|
|
42
31
|
const runner = runners[lang]
|
|
@@ -47,7 +36,6 @@ export default createSingletonPromise(async () => {
|
|
|
47
36
|
{
|
|
48
37
|
options,
|
|
49
38
|
highlight,
|
|
50
|
-
resolveId,
|
|
51
39
|
run: async (code, lang) => {
|
|
52
40
|
return await run(code, lang, options)
|
|
53
41
|
},
|
|
@@ -85,16 +73,20 @@ async function runJavaScript(code: string): Promise<CodeRunnerOutputs> {
|
|
|
85
73
|
replace.clear = () => allLogs.length = 0
|
|
86
74
|
const vmConsole = Object.assign({}, console, replace)
|
|
87
75
|
try {
|
|
88
|
-
const safeJS = `return async (console) => {
|
|
89
|
-
window.console = console
|
|
76
|
+
const safeJS = `return async (console, __slidev_import) => {
|
|
90
77
|
${sanitizeJS(code)}
|
|
91
78
|
}`
|
|
92
79
|
// eslint-disable-next-line no-new-func
|
|
93
|
-
await (new Function(safeJS)())(vmConsole)
|
|
80
|
+
await (new Function(safeJS)())(vmConsole, (specifier: string) => {
|
|
81
|
+
const mod = deps[specifier]
|
|
82
|
+
if (!mod)
|
|
83
|
+
throw new Error(`Module not found: ${specifier}.\nAvailable modules: ${Object.keys(deps).join(', ')}. Please refer to https://sli.dev/custom/config-code-runners#additional-runner-dependencies`)
|
|
84
|
+
return mod
|
|
85
|
+
})
|
|
94
86
|
}
|
|
95
87
|
catch (error) {
|
|
96
88
|
return {
|
|
97
|
-
error:
|
|
89
|
+
error: String(error),
|
|
98
90
|
}
|
|
99
91
|
}
|
|
100
92
|
|
|
@@ -175,7 +167,7 @@ async function runJavaScript(code: string): Promise<CodeRunnerOutputs> {
|
|
|
175
167
|
|
|
176
168
|
let tsModule: typeof import('typescript') | undefined
|
|
177
169
|
|
|
178
|
-
export async function runTypeScript(code: string
|
|
170
|
+
export async function runTypeScript(code: string) {
|
|
179
171
|
tsModule ??= await import('typescript')
|
|
180
172
|
|
|
181
173
|
code = tsModule.transpileModule(code, {
|
|
@@ -188,11 +180,8 @@ export async function runTypeScript(code: string, context: CodeRunnerContext) {
|
|
|
188
180
|
},
|
|
189
181
|
}).outputText
|
|
190
182
|
|
|
191
|
-
const importRegex = /import\s*\(
|
|
192
|
-
|
|
193
|
-
for (const [,,specifier] of code.matchAll(importRegex)!)
|
|
194
|
-
idMap[specifier] = await context.resolveId(specifier) ?? specifier
|
|
195
|
-
code = code.replace(importRegex, (_full, quote, specifier) => `import(${quote}${idMap[specifier] ?? specifier}${quote})`)
|
|
183
|
+
const importRegex = /import\s*\((.+)\)/g
|
|
184
|
+
code = code.replace(importRegex, (_full, specifier) => `__slidev_import(${specifier})`)
|
|
196
185
|
|
|
197
186
|
return await runJavaScript(code)
|
|
198
187
|
}
|
package/setup/main.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { createVClickDirectives } from '../modules/v-click'
|
|
|
9
9
|
import { createVMarkDirective } from '../modules/v-mark'
|
|
10
10
|
import { createVDragDirective } from '../modules/v-drag'
|
|
11
11
|
import { createVMotionDirectives } from '../modules/v-motion'
|
|
12
|
-
import
|
|
12
|
+
import setupRoutes from '../setup/routes'
|
|
13
13
|
import setups from '#slidev/setups/main'
|
|
14
14
|
|
|
15
15
|
import '#slidev/styles'
|
|
@@ -28,7 +28,7 @@ export default async function setupMain(app: App) {
|
|
|
28
28
|
history: __SLIDEV_HASH_ROUTE__
|
|
29
29
|
? createWebHashHistory(import.meta.env.BASE_URL)
|
|
30
30
|
: createWebHistory(import.meta.env.BASE_URL),
|
|
31
|
-
routes,
|
|
31
|
+
routes: setupRoutes(),
|
|
32
32
|
})
|
|
33
33
|
|
|
34
34
|
app.use(router)
|
package/setup/monaco.ts
CHANGED
|
@@ -66,9 +66,6 @@ const setup = createSingletonPromise(async () => {
|
|
|
66
66
|
module: monaco.languages.typescript.ModuleKind.ESNext,
|
|
67
67
|
})
|
|
68
68
|
|
|
69
|
-
// Load types from server
|
|
70
|
-
import('#slidev/monaco-types')
|
|
71
|
-
|
|
72
69
|
const ata = configs.monacoTypesSource === 'cdn'
|
|
73
70
|
? setupTypeAcquisition({
|
|
74
71
|
projectName: 'TypeScript Playground',
|
package/setup/routes.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'
|
|
2
|
+
import configs from '#slidev/configs'
|
|
3
|
+
import setups from '#slidev/setups/routes'
|
|
4
|
+
|
|
5
|
+
export default function setupRoutes() {
|
|
6
|
+
const routes: RouteRecordRaw[] = []
|
|
7
|
+
|
|
8
|
+
if (__SLIDEV_FEATURE_PRESENTER__) {
|
|
9
|
+
function passwordGuard(to: RouteLocationNormalized) {
|
|
10
|
+
if (!configs.remote || configs.remote === to.query.password)
|
|
11
|
+
return true
|
|
12
|
+
if (configs.remote && to.query.password === undefined) {
|
|
13
|
+
// eslint-disable-next-line no-alert
|
|
14
|
+
const password = prompt('Enter password')
|
|
15
|
+
if (configs.remote === password)
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
if (to.params.no)
|
|
19
|
+
return { path: `/${to.params.no}` }
|
|
20
|
+
return { path: '' }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
routes.push(
|
|
24
|
+
{
|
|
25
|
+
name: 'entry',
|
|
26
|
+
path: '/entry',
|
|
27
|
+
component: () => import('../pages/entry.vue'),
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'overview',
|
|
31
|
+
path: '/overview',
|
|
32
|
+
component: () => import('../pages/overview.vue'),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'notes',
|
|
36
|
+
path: '/notes',
|
|
37
|
+
component: () => import('../pages/notes.vue'),
|
|
38
|
+
beforeEnter: passwordGuard,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'presenter',
|
|
42
|
+
path: '/presenter/:no',
|
|
43
|
+
component: () => import('../pages/presenter.vue'),
|
|
44
|
+
beforeEnter: passwordGuard,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
path: '/presenter',
|
|
48
|
+
redirect: { path: '/presenter/1' },
|
|
49
|
+
},
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (__SLIDEV_HAS_SERVER__) {
|
|
54
|
+
routes.push(
|
|
55
|
+
{
|
|
56
|
+
name: 'print',
|
|
57
|
+
path: '/print',
|
|
58
|
+
component: () => import('../pages/print.vue'),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
path: '/presenter/print',
|
|
62
|
+
component: () => import('../pages/presenter/print.vue'),
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
routes.push(
|
|
68
|
+
{
|
|
69
|
+
name: 'play',
|
|
70
|
+
path: '/:no',
|
|
71
|
+
component: () => import('../pages/play.vue'),
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
path: '',
|
|
75
|
+
redirect: { path: '/1' },
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
return setups.reduce((routes, setup) => setup(routes), routes)
|
|
80
|
+
}
|
package/routes.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import type { RouteLocationNormalized, RouteRecordRaw } from 'vue-router'
|
|
2
|
-
import configs from '#slidev/configs'
|
|
3
|
-
|
|
4
|
-
export const routes: RouteRecordRaw[] = [
|
|
5
|
-
{
|
|
6
|
-
name: 'print',
|
|
7
|
-
path: '/print',
|
|
8
|
-
component: () => import('./pages/print.vue'),
|
|
9
|
-
},
|
|
10
|
-
|
|
11
|
-
// Redirects
|
|
12
|
-
{ path: '', redirect: { path: '/1' } },
|
|
13
|
-
]
|
|
14
|
-
|
|
15
|
-
if (__SLIDEV_FEATURE_PRESENTER__) {
|
|
16
|
-
function passwordGuard(to: RouteLocationNormalized) {
|
|
17
|
-
if (!configs.remote || configs.remote === to.query.password)
|
|
18
|
-
return true
|
|
19
|
-
if (configs.remote && to.query.password === undefined) {
|
|
20
|
-
// eslint-disable-next-line no-alert
|
|
21
|
-
const password = prompt('Enter password')
|
|
22
|
-
if (configs.remote === password)
|
|
23
|
-
return true
|
|
24
|
-
}
|
|
25
|
-
if (to.params.no)
|
|
26
|
-
return { path: `/${to.params.no}` }
|
|
27
|
-
return { path: '' }
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
routes.push({
|
|
31
|
-
path: '/presenter/print',
|
|
32
|
-
component: () => import('./pages/presenter/print.vue'),
|
|
33
|
-
})
|
|
34
|
-
if (__SLIDEV_HAS_SERVER__) {
|
|
35
|
-
routes.push({
|
|
36
|
-
name: 'entry',
|
|
37
|
-
path: '/entry',
|
|
38
|
-
component: () => import('./pages/entry.vue'),
|
|
39
|
-
})
|
|
40
|
-
routes.push({
|
|
41
|
-
name: 'overview',
|
|
42
|
-
path: '/overview',
|
|
43
|
-
component: () => import('./pages/overview.vue'),
|
|
44
|
-
})
|
|
45
|
-
routes.push({
|
|
46
|
-
name: 'notes',
|
|
47
|
-
path: '/notes',
|
|
48
|
-
component: () => import('./pages/notes.vue'),
|
|
49
|
-
beforeEnter: passwordGuard,
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
routes.push({
|
|
53
|
-
name: 'presenter',
|
|
54
|
-
path: '/presenter/:no',
|
|
55
|
-
component: () => import('./pages/presenter.vue'),
|
|
56
|
-
beforeEnter: passwordGuard,
|
|
57
|
-
})
|
|
58
|
-
routes.push({
|
|
59
|
-
path: '/presenter',
|
|
60
|
-
redirect: { path: '/presenter/1' },
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
routes.push({
|
|
65
|
-
name: 'play',
|
|
66
|
-
path: '/:no',
|
|
67
|
-
component: () => import('./pages/play.vue'),
|
|
68
|
-
})
|