@slidev/client 53.0.0 → 53.1.0
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/CodeBlockWrapper.vue +6 -2
- package/builtin/KaTexBlockWrapper.test.ts +6 -2
- package/builtin/KaTexBlockWrapper.vue +6 -2
- package/builtin/Mermaid.vue +3 -1
- package/builtin/RenderWhen.vue +9 -3
- package/builtin/ShikiMagicMove.vue +6 -2
- package/builtin/Toc.vue +3 -1
- package/builtin/VAfter.ts +3 -1
- package/builtin/VClicks.ts +31 -14
- package/builtin/VSwitch.ts +10 -3
- package/composables/useClicks.ts +6 -2
- package/composables/useDragElements.ts +16 -6
- package/composables/useDrawings.ts +3 -1
- package/composables/useEmbeddedCtrl.ts +7 -1
- package/composables/useNav.test.ts +9 -3
- package/composables/useNav.ts +21 -7
- package/composables/usePreloadImages.ts +6 -2
- package/composables/useSlideInfo.ts +6 -2
- package/composables/useViewTransition.ts +7 -1
- package/context.ts +3 -1
- package/env.ts +3 -1
- package/internals/ClicksSlider.vue +6 -2
- package/internals/DragControl.vue +34 -9
- package/internals/Goto.vue +6 -2
- package/internals/NoteDisplay.vue +5 -2
- package/internals/NoteStatic.vue +2 -0
- package/internals/ShadowRoot.vue +3 -1
- package/internals/SideEditor.vue +3 -1
- package/internals/SlideContainer.vue +3 -1
- package/internals/SlideWrapper.vue +3 -1
- package/logic/route.ts +3 -1
- package/logic/screenshot.ts +3 -1
- package/logic/slidePath.ts +5 -1
- package/logic/snapshot.ts +3 -1
- package/modules/v-click.ts +10 -4
- package/modules/v-mark.ts +20 -10
- package/modules/v-motion.ts +34 -9
- package/package.json +23 -23
- package/pages/overview.vue +17 -5
- package/pages/presenter.vue +2 -5
- package/setup/code-runners.ts +18 -6
- package/setup/context-menu.ts +2 -0
- package/setup/shiki-options.ts +11 -2
- package/setup/shortcuts.ts +100 -18
- package/state/storage.ts +6 -2
- package/state/syncState.ts +7 -1
package/internals/SideEditor.vue
CHANGED
|
@@ -26,7 +26,9 @@ watch(
|
|
|
26
26
|
(v) => {
|
|
27
27
|
if (!isInputting.value) {
|
|
28
28
|
note.value = (v?.note || '').trim()
|
|
29
|
-
const frontmatterPart = v?.frontmatterRaw?.trim()
|
|
29
|
+
const frontmatterPart = v?.frontmatterRaw?.trim()
|
|
30
|
+
? `---\n${v.frontmatterRaw.trim()}\n---\n\n`
|
|
31
|
+
: ''
|
|
30
32
|
content.value = frontmatterPart + (v?.source.contentRaw || '').trim()
|
|
31
33
|
dirty.value = false
|
|
32
34
|
}
|
|
@@ -41,7 +41,9 @@ const containerSize = useElementSize(container)
|
|
|
41
41
|
const slideElement = ref<HTMLElement | null>(null)
|
|
42
42
|
|
|
43
43
|
const width = computed(() => props.width ?? containerSize.width.value)
|
|
44
|
-
const height = computed(() => props.width
|
|
44
|
+
const height = computed(() => props.width
|
|
45
|
+
? props.width / slideAspect.value
|
|
46
|
+
: containerSize.height.value)
|
|
45
47
|
|
|
46
48
|
const scale = computed(() => {
|
|
47
49
|
if (slideScale.value && !isPrintMode.value)
|
|
@@ -34,7 +34,9 @@ provideLocal(injectionSlideZoom, zoom)
|
|
|
34
34
|
|
|
35
35
|
const style = computed<CSSProperties>(() => ({
|
|
36
36
|
'user-select': configs.selectable ? undefined : 'none',
|
|
37
|
-
'--slidev-slide-zoom-scale': zoom.value === 1
|
|
37
|
+
'--slidev-slide-zoom-scale': zoom.value === 1
|
|
38
|
+
? undefined
|
|
39
|
+
: zoom.value,
|
|
38
40
|
}))
|
|
39
41
|
</script>
|
|
40
42
|
|
package/logic/route.ts
CHANGED
|
@@ -28,7 +28,9 @@ export function useRouteQuery<T extends string | string[]>(
|
|
|
28
28
|
router[unref(mode) as 'replace' | 'push']({
|
|
29
29
|
query: {
|
|
30
30
|
...router.currentRoute.value.query,
|
|
31
|
-
[name]: `${v}` === defaultValue
|
|
31
|
+
[name]: `${v}` === defaultValue
|
|
32
|
+
? undefined
|
|
33
|
+
: v,
|
|
32
34
|
},
|
|
33
35
|
})
|
|
34
36
|
})
|
package/logic/screenshot.ts
CHANGED
|
@@ -58,4 +58,6 @@ export async function startScreenshotSession(width: number, height: number) {
|
|
|
58
58
|
export type ScreenshotSession = Awaited<ReturnType<typeof startScreenshotSession>>
|
|
59
59
|
|
|
60
60
|
const chromeVersion = window.navigator.userAgent.match(/Chrome\/(\d+)/)?.[1]
|
|
61
|
-
export const isScreenshotSupported = chromeVersion
|
|
61
|
+
export const isScreenshotSupported = chromeVersion
|
|
62
|
+
? Number(chromeVersion) >= 94
|
|
63
|
+
: false
|
package/logic/slidePath.ts
CHANGED
|
@@ -6,5 +6,9 @@ export function getSlideRoutePath(
|
|
|
6
6
|
exporting: boolean = false,
|
|
7
7
|
) {
|
|
8
8
|
const no = route.meta.slide?.frontmatter.routeAlias ?? route.no
|
|
9
|
-
return exporting
|
|
9
|
+
return exporting
|
|
10
|
+
? `/export/${no}`
|
|
11
|
+
: presenter
|
|
12
|
+
? `/presenter/${no}`
|
|
13
|
+
: `/${no}`
|
|
10
14
|
}
|
package/logic/snapshot.ts
CHANGED
|
@@ -9,7 +9,9 @@ import { startScreenshotSession } from './screenshot'
|
|
|
9
9
|
import { getSlide } from './slides'
|
|
10
10
|
|
|
11
11
|
const chromeVersion = window.navigator.userAgent.match(/Chrome\/(\d+)/)?.[1]
|
|
12
|
-
export const isScreenshotSupported = chromeVersion
|
|
12
|
+
export const isScreenshotSupported = chromeVersion
|
|
13
|
+
? Number(chromeVersion) >= 94
|
|
14
|
+
: false
|
|
13
15
|
|
|
14
16
|
const initialWait = 100
|
|
15
17
|
|
package/modules/v-click.ts
CHANGED
|
@@ -165,14 +165,20 @@ export function resolveClick(el: Element | string, dir: DirectiveBinding<any>, v
|
|
|
165
165
|
|
|
166
166
|
ctx.register(el, info)
|
|
167
167
|
|
|
168
|
-
const isShown = computed(() => flagHide
|
|
168
|
+
const isShown = computed(() => flagHide
|
|
169
|
+
? !info.isActive.value
|
|
170
|
+
: info.isActive.value)
|
|
169
171
|
const visibilityState = computed(() => {
|
|
170
172
|
if (isShown.value)
|
|
171
173
|
return 'shown'
|
|
172
|
-
if (Number.isFinite(info.end))
|
|
173
|
-
return ctx.current < info.start
|
|
174
|
-
|
|
174
|
+
if (Number.isFinite(info.end)) {
|
|
175
|
+
return ctx.current < info.start
|
|
176
|
+
? 'before'
|
|
177
|
+
: 'after'
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
175
180
|
return flagHide ? 'after' : 'before'
|
|
181
|
+
}
|
|
176
182
|
})
|
|
177
183
|
|
|
178
184
|
const resolved = {
|
package/modules/v-mark.ts
CHANGED
|
@@ -55,17 +55,27 @@ const vMarkModifiers: Record<string, (options: RoughDirectiveOptions, value?: an
|
|
|
55
55
|
|
|
56
56
|
const vMarkModifiersDynamic: [RegExp, (match: RegExpMatchArray, options: RoughDirectiveOptions, value?: any) => RoughDirectiveOptions][] = [
|
|
57
57
|
// Support setting delay like `v-mark.delay300="1"`
|
|
58
|
-
[
|
|
59
|
-
|
|
60
|
-
options
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
[
|
|
59
|
+
/^delay-?(\d+)?$/,
|
|
60
|
+
(match, options, value) => {
|
|
61
|
+
const ms = (match[1]
|
|
62
|
+
? Number.parseInt(match[1])
|
|
63
|
+
: value) || 300
|
|
64
|
+
options.delay = ms
|
|
65
|
+
return options
|
|
66
|
+
},
|
|
67
|
+
],
|
|
63
68
|
// Support setting opacity like `v-mark.op50="1"`
|
|
64
|
-
[
|
|
65
|
-
|
|
66
|
-
options
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
[
|
|
70
|
+
/^(?:op|opacity)-?(\d+)?$/,
|
|
71
|
+
(match, options, value) => {
|
|
72
|
+
const opacity = (match[1]
|
|
73
|
+
? Number.parseInt(match[1])
|
|
74
|
+
: value) || 100
|
|
75
|
+
options.opacity = opacity / 100
|
|
76
|
+
return options
|
|
77
|
+
},
|
|
78
|
+
],
|
|
69
79
|
]
|
|
70
80
|
|
|
71
81
|
/**
|
package/modules/v-motion.ts
CHANGED
|
@@ -23,9 +23,18 @@ export function createVMotionDirectives() {
|
|
|
23
23
|
|
|
24
24
|
const props = node.props = { ...node.props }
|
|
25
25
|
|
|
26
|
-
const variantInitial = {
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const variantInitial = {
|
|
27
|
+
...props.initial,
|
|
28
|
+
...props.variants?.['slidev-initial'],
|
|
29
|
+
}
|
|
30
|
+
const variantEnter = {
|
|
31
|
+
...props.enter,
|
|
32
|
+
...props.variants?.['slidev-enter'],
|
|
33
|
+
}
|
|
34
|
+
const variantLeave = {
|
|
35
|
+
...props.leave,
|
|
36
|
+
...props.variants?.['slidev-leave'],
|
|
37
|
+
}
|
|
29
38
|
delete props.initial
|
|
30
39
|
delete props.enter
|
|
31
40
|
delete props.leave
|
|
@@ -41,7 +50,9 @@ export function createVMotionDirectives() {
|
|
|
41
50
|
for (const k of Object.keys(props)) {
|
|
42
51
|
if (k.startsWith('click-')) {
|
|
43
52
|
const s = k.slice(6)
|
|
44
|
-
const at = s.includes('-')
|
|
53
|
+
const at = s.includes('-')
|
|
54
|
+
? s.split('-').map(Number) as [number, number]
|
|
55
|
+
: +s
|
|
45
56
|
const id = idPrefix + s
|
|
46
57
|
clicks.push({
|
|
47
58
|
id,
|
|
@@ -53,7 +64,11 @@ export function createVMotionDirectives() {
|
|
|
53
64
|
}
|
|
54
65
|
}
|
|
55
66
|
|
|
56
|
-
clicks.sort((a, b) => (Array.isArray(a.at)
|
|
67
|
+
clicks.sort((a, b) => (Array.isArray(a.at)
|
|
68
|
+
? a.at[0]
|
|
69
|
+
: a.at) - (Array.isArray(b.at)
|
|
70
|
+
? b.at[0]
|
|
71
|
+
: b.at))
|
|
57
72
|
|
|
58
73
|
original.created!(el, binding, node, prevNode)
|
|
59
74
|
original.mounted!(el, binding, node, prevNode)
|
|
@@ -67,7 +82,10 @@ export function createVMotionDirectives() {
|
|
|
67
82
|
() => {
|
|
68
83
|
const visibility = resolvedClickMap.get(el)?.visibilityState.value ?? 'shown'
|
|
69
84
|
if (!clicksContext?.value || !['slide', 'presenter'].includes(renderContext?.value ?? '')) {
|
|
70
|
-
const mixedVariant: Record<string, unknown> = {
|
|
85
|
+
const mixedVariant: Record<string, unknown> = {
|
|
86
|
+
...variantInitial,
|
|
87
|
+
...variantEnter,
|
|
88
|
+
}
|
|
71
89
|
for (const { variant } of clicks)
|
|
72
90
|
Object.assign(mixedVariant, variant)
|
|
73
91
|
|
|
@@ -75,7 +93,10 @@ export function createVMotionDirectives() {
|
|
|
75
93
|
}
|
|
76
94
|
else if (isPrintMode.value || thisPage?.value === currentPage.value) {
|
|
77
95
|
if (visibility === 'shown') {
|
|
78
|
-
const mixedVariant: Record<string, unknown> = {
|
|
96
|
+
const mixedVariant: Record<string, unknown> = {
|
|
97
|
+
...variantInitial,
|
|
98
|
+
...variantEnter,
|
|
99
|
+
}
|
|
79
100
|
for (const { variant, info } of clicks) {
|
|
80
101
|
if (!info || info.isActive.value)
|
|
81
102
|
Object.assign(mixedVariant, variant)
|
|
@@ -86,11 +107,15 @@ export function createVMotionDirectives() {
|
|
|
86
107
|
motion.apply(mixedVariant)
|
|
87
108
|
}
|
|
88
109
|
else {
|
|
89
|
-
motion.apply(visibility === 'before'
|
|
110
|
+
motion.apply(visibility === 'before'
|
|
111
|
+
? variantInitial
|
|
112
|
+
: variantLeave)
|
|
90
113
|
}
|
|
91
114
|
}
|
|
92
115
|
else {
|
|
93
|
-
motion.apply((thisPage?.value ?? -1) > currentPage.value
|
|
116
|
+
motion.apply((thisPage?.value ?? -1) > currentPage.value
|
|
117
|
+
? variantInitial
|
|
118
|
+
: variantLeave)
|
|
94
119
|
}
|
|
95
120
|
},
|
|
96
121
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "53.
|
|
4
|
+
"version": "53.1.0",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -30,46 +30,46 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@antfu/utils": "^9.3.0",
|
|
32
32
|
"@fix-webm-duration/fix": "^1.0.1",
|
|
33
|
-
"@iconify-json/carbon": "^1.2.
|
|
33
|
+
"@iconify-json/carbon": "^1.2.29",
|
|
34
34
|
"@iconify-json/ph": "^1.2.2",
|
|
35
35
|
"@iconify-json/svg-spinners": "^1.2.4",
|
|
36
|
-
"@shikijs/engine-javascript": "^4.
|
|
37
|
-
"@shikijs/magic-move": "^4.
|
|
38
|
-
"@shikijs/monaco": "^4.
|
|
39
|
-
"@shikijs/vitepress-twoslash": "^4.
|
|
40
|
-
"@slidev/parser": "53.
|
|
36
|
+
"@shikijs/engine-javascript": "^4.6.0",
|
|
37
|
+
"@shikijs/magic-move": "^4.6.0",
|
|
38
|
+
"@shikijs/monaco": "^4.6.0",
|
|
39
|
+
"@shikijs/vitepress-twoslash": "^4.6.0",
|
|
40
|
+
"@slidev/parser": "53.1.0",
|
|
41
41
|
"@slidev/rough-notation": "^0.1.0",
|
|
42
|
-
"@slidev/types": "53.
|
|
42
|
+
"@slidev/types": "53.1.0",
|
|
43
43
|
"@typescript/ata": "^0.9.8",
|
|
44
|
-
"@unhead/vue": "^3.4.
|
|
45
|
-
"@unocss/extractor-mdc": "^66.
|
|
46
|
-
"@unocss/preset-mini": "^66.
|
|
47
|
-
"@unocss/reset": "^66.
|
|
48
|
-
"@vueuse/core": "^
|
|
49
|
-
"@vueuse/math": "^
|
|
44
|
+
"@unhead/vue": "^3.4.3",
|
|
45
|
+
"@unocss/extractor-mdc": "^66.12.0",
|
|
46
|
+
"@unocss/preset-mini": "^66.12.0",
|
|
47
|
+
"@unocss/reset": "^66.12.0",
|
|
48
|
+
"@vueuse/core": "^15.0.0",
|
|
49
|
+
"@vueuse/math": "^15.0.0",
|
|
50
50
|
"@vueuse/motion": "^3.0.3",
|
|
51
|
-
"ansis": "^4.
|
|
51
|
+
"ansis": "^4.5.0",
|
|
52
52
|
"drauu": "^1.0.0",
|
|
53
53
|
"file-saver": "^2.0.5",
|
|
54
54
|
"fitty": "^2.4.2",
|
|
55
55
|
"floating-vue": "^5.4.0",
|
|
56
56
|
"fuse.js": "^7.5.0",
|
|
57
|
-
"katex": "^0.
|
|
57
|
+
"katex": "^0.19.1",
|
|
58
58
|
"lz-string": "^1.5.0",
|
|
59
59
|
"markdown-it-github-alerts": "^1.0.1",
|
|
60
|
-
"mermaid": "^12.
|
|
61
|
-
"monaco-editor": "^0.
|
|
60
|
+
"mermaid": "^12.3.0",
|
|
61
|
+
"monaco-editor": "^0.57.0",
|
|
62
62
|
"nanotar": "^0.3.0",
|
|
63
63
|
"pptxgenjs": "^4.0.1",
|
|
64
64
|
"recordrtc": "^5.6.2",
|
|
65
|
-
"shiki": "^4.
|
|
65
|
+
"shiki": "^4.6.0",
|
|
66
66
|
"typescript": "^6.0.3",
|
|
67
|
-
"unocss": "^66.
|
|
68
|
-
"vue": "^3.5.
|
|
69
|
-
"vue-router": "^5.
|
|
67
|
+
"unocss": "^66.12.0",
|
|
68
|
+
"vue": "^3.5.44",
|
|
69
|
+
"vue-router": "^5.4.0",
|
|
70
70
|
"yaml": "^2.9.1"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"vite": "^8.3.
|
|
73
|
+
"vite": "^8.3.6"
|
|
74
74
|
}
|
|
75
75
|
}
|
package/pages/overview.vue
CHANGED
|
@@ -101,7 +101,11 @@ function checkActiveBlocks() {
|
|
|
101
101
|
active = { idx, visibleHeight }
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
activeBlocks.value = fullyVisible.length
|
|
104
|
+
activeBlocks.value = fullyVisible.length
|
|
105
|
+
? fullyVisible
|
|
106
|
+
: active
|
|
107
|
+
? [active.idx]
|
|
108
|
+
: []
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
function openSlideInNewTab(path: string) {
|
|
@@ -151,7 +155,9 @@ function scrollSlideNoIntoCenter(no: number) {
|
|
|
151
155
|
if (start == null)
|
|
152
156
|
return
|
|
153
157
|
const top = start
|
|
154
|
-
+ (end == null
|
|
158
|
+
+ (end == null
|
|
159
|
+
? 0
|
|
160
|
+
: (end - start) * progress)
|
|
155
161
|
- scroller.value.clientHeight * 0.5
|
|
156
162
|
if (Math.abs(scroller.value.scrollTop - top) < 1)
|
|
157
163
|
return
|
|
@@ -160,8 +166,12 @@ function scrollSlideNoIntoCenter(no: number) {
|
|
|
160
166
|
|
|
161
167
|
function getInitialSlideNo() {
|
|
162
168
|
const value = currentRoute.query.slideNo
|
|
163
|
-
const no = Number(Array.isArray(value)
|
|
164
|
-
|
|
169
|
+
const no = Number(Array.isArray(value)
|
|
170
|
+
? value[0]
|
|
171
|
+
: value)
|
|
172
|
+
return Number.isFinite(no) && no > 0
|
|
173
|
+
? no
|
|
174
|
+
: undefined
|
|
165
175
|
}
|
|
166
176
|
|
|
167
177
|
function updateSlideNoQuery(no: number) {
|
|
@@ -275,7 +285,9 @@ function openOverviewSlideSource(e: MouseEvent, route: SlideRoute) {
|
|
|
275
285
|
|
|
276
286
|
onMounted(() => {
|
|
277
287
|
window.addEventListener('message', onOverviewMessage)
|
|
278
|
-
const initialSlideNo = isEmbeddedPreviewMode.value
|
|
288
|
+
const initialSlideNo = isEmbeddedPreviewMode.value
|
|
289
|
+
? getInitialSlideNo()
|
|
290
|
+
: undefined
|
|
279
291
|
if (initialSlideNo != null) {
|
|
280
292
|
ignoreOverviewScrollUntil = Date.now() + 300
|
|
281
293
|
scrollSlideNoIntoCenter(initialSlideNo)
|
package/pages/presenter.vue
CHANGED
|
@@ -102,7 +102,6 @@ const resizeStartRowSize = ref(280)
|
|
|
102
102
|
|
|
103
103
|
const RESIZER_LIMITS = {
|
|
104
104
|
minNotesWidth: 240,
|
|
105
|
-
maxNotesWidth: 720,
|
|
106
105
|
minNotesRowSize: 160,
|
|
107
106
|
maxNotesWidthRatio: 0.7,
|
|
108
107
|
maxNotesRowHeightRatio: 0.75,
|
|
@@ -120,10 +119,7 @@ const isNotesOnBottom = computed(() => presenterLayout.value === 1 && !isLayout1
|
|
|
120
119
|
function clampNotesWidth(width: number) {
|
|
121
120
|
if (!Number.isFinite(width))
|
|
122
121
|
return RESIZER_LIMITS.minNotesWidth
|
|
123
|
-
return Math.max(
|
|
124
|
-
RESIZER_LIMITS.minNotesWidth,
|
|
125
|
-
Math.min(RESIZER_LIMITS.maxNotesWidth, Math.round(width)),
|
|
126
|
-
)
|
|
122
|
+
return Math.max(RESIZER_LIMITS.minNotesWidth, Math.round(width))
|
|
127
123
|
}
|
|
128
124
|
|
|
129
125
|
function updateNotesWidthFromPointer(clientX: number) {
|
|
@@ -395,6 +391,7 @@ onMounted(() => {
|
|
|
395
391
|
class="w-full max-w-full h-full overflow-auto p-2 lg:p-4"
|
|
396
392
|
:style="{ fontSize: `${presenterNotesFontSize}em` }"
|
|
397
393
|
:clicks-context="clicksContext"
|
|
394
|
+
auto-scroll
|
|
398
395
|
/>
|
|
399
396
|
<div border-t border-main />
|
|
400
397
|
<div class="py-1 px-2 text-sm transition" :class="inFocus ? '' : 'op25'">
|
package/setup/code-runners.ts
CHANGED
|
@@ -65,14 +65,18 @@ export default createSingletonPromise(async () => {
|
|
|
65
65
|
function runJavaScript(code: string): CodeRunnerOutputs {
|
|
66
66
|
const result = ref<CodeRunnerOutput[]>([])
|
|
67
67
|
|
|
68
|
-
const onError = (error: any) => result.value.push({
|
|
68
|
+
const onError = (error: any) => result.value.push({
|
|
69
|
+
error: String(error),
|
|
70
|
+
})
|
|
69
71
|
const logger = (...objs: any[]) => result.value.push(objs.map(printObject))
|
|
70
72
|
const vmConsole = Object.assign({}, console)
|
|
71
73
|
vmConsole.info = vmConsole.log = vmConsole.debug = vmConsole.warn = vmConsole.error = logger
|
|
72
74
|
vmConsole.clear = () => result.value.length = 0
|
|
73
75
|
try {
|
|
74
76
|
const wrappedCode = `return async (console, __slidev_import, __slidev_on_error) => {
|
|
75
|
-
${configs.monacoRunUseStrict
|
|
77
|
+
${configs.monacoRunUseStrict
|
|
78
|
+
? `"use strict";`
|
|
79
|
+
: ''}
|
|
76
80
|
try {
|
|
77
81
|
${fixupCode(code)}
|
|
78
82
|
} catch (e) {
|
|
@@ -119,7 +123,9 @@ function runJavaScript(code: string): CodeRunnerOutputs {
|
|
|
119
123
|
textRep = `Set (${arg.size}) {${setIter.map(objectToText).join(', ')}}`
|
|
120
124
|
}
|
|
121
125
|
else if (arg instanceof Map) {
|
|
122
|
-
const mapIter = [
|
|
126
|
+
const mapIter = [
|
|
127
|
+
...arg.entries(),
|
|
128
|
+
]
|
|
123
129
|
textRep
|
|
124
130
|
= `Map (${arg.size}) {${mapIter
|
|
125
131
|
.map(([k, v]) => `${objectToText(k)} => ${objectToText(v)}`)
|
|
@@ -135,13 +141,19 @@ function runJavaScript(code: string): CodeRunnerOutputs {
|
|
|
135
141
|
else if (typeof arg === 'object') {
|
|
136
142
|
const name = arg.constructor?.name ?? ''
|
|
137
143
|
// No one needs to know an obj is an obj
|
|
138
|
-
const nameWithoutObject = name && name === 'Object'
|
|
139
|
-
|
|
144
|
+
const nameWithoutObject = name && name === 'Object'
|
|
145
|
+
? ''
|
|
146
|
+
: name
|
|
147
|
+
const prefix = nameWithoutObject
|
|
148
|
+
? `${nameWithoutObject}: `
|
|
149
|
+
: ''
|
|
140
150
|
|
|
141
151
|
// JSON.stringify omits any keys with a value of undefined. To get around this, we replace undefined with the text __undefined__ and then do a global replace using regex back to keyword undefined
|
|
142
152
|
textRep
|
|
143
153
|
= prefix
|
|
144
|
-
+ JSON.stringify(arg, (_, value) => (value === undefined
|
|
154
|
+
+ JSON.stringify(arg, (_, value) => (value === undefined
|
|
155
|
+
? '__undefined__'
|
|
156
|
+
: value), 2).replace(
|
|
145
157
|
/"__undefined__"/g,
|
|
146
158
|
'undefined',
|
|
147
159
|
)
|
package/setup/context-menu.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { computed } from 'vue'
|
|
|
6
6
|
import setups from '#slidev/setups/context-menu'
|
|
7
7
|
import { useDrawings } from '../composables/useDrawings'
|
|
8
8
|
import { useNav } from '../composables/useNav'
|
|
9
|
+
import { configs } from '../env'
|
|
9
10
|
import { fullscreen, showEditor, toggleOverview } from '../state'
|
|
10
11
|
|
|
11
12
|
// @unocss-include
|
|
@@ -79,6 +80,7 @@ export default () => {
|
|
|
79
80
|
icon: 'i-carbon:pen',
|
|
80
81
|
label: drawingEnabled.value ? 'Hide drawing toolbar' : 'Show drawing toolbar',
|
|
81
82
|
action: () => (drawingEnabled.value = !drawingEnabled.value),
|
|
83
|
+
show: __SLIDEV_FEATURE_DRAWINGS__ && (!configs.drawings.presenterOnly || isPresenter.value),
|
|
82
84
|
},
|
|
83
85
|
{
|
|
84
86
|
icon: 'i-carbon:apps',
|
package/setup/shiki-options.ts
CHANGED
|
@@ -37,7 +37,9 @@ export function resolveShikiOptions(options: (ShikiSetupReturn | void)[]) {
|
|
|
37
37
|
mergedOptions.defaultColor = false
|
|
38
38
|
|
|
39
39
|
const themeOption = extractThemeName(mergedOptions.theme) || extractThemeNames(mergedOptions.themes || {})
|
|
40
|
-
const themeNames = typeof themeOption === 'string'
|
|
40
|
+
const themeNames = typeof themeOption === 'string'
|
|
41
|
+
? [themeOption]
|
|
42
|
+
: Object.values(themeOption)
|
|
41
43
|
|
|
42
44
|
const themeInput: Record<string, ThemeInput> = Object.assign({}, bundledThemes)
|
|
43
45
|
if (typeof mergedOptions.theme === 'object' && mergedOptions.theme?.name) {
|
|
@@ -51,7 +53,14 @@ export function resolveShikiOptions(options: (ShikiSetupReturn | void)[]) {
|
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
|
|
54
|
-
const languageNames = new Set<string>([
|
|
56
|
+
const languageNames = new Set<string>([
|
|
57
|
+
'markdown',
|
|
58
|
+
'vue',
|
|
59
|
+
'javascript',
|
|
60
|
+
'typescript',
|
|
61
|
+
'html',
|
|
62
|
+
'css',
|
|
63
|
+
])
|
|
55
64
|
const languageInput: Record<string, LanguageInput> = Object.assign({}, bundledLanguages)
|
|
56
65
|
for (const option of options) {
|
|
57
66
|
const langs = option?.langs
|
package/setup/shortcuts.ts
CHANGED
|
@@ -32,24 +32,106 @@ export default function setupShortcuts() {
|
|
|
32
32
|
const navViaArrowKeys = and(not(showOverview), not(activeDragElement))
|
|
33
33
|
|
|
34
34
|
let shortcuts: ShortcutOptions[] = [
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
{
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
{
|
|
36
|
+
name: 'next_space',
|
|
37
|
+
key: and(space, not(shift)),
|
|
38
|
+
fn: next,
|
|
39
|
+
autoRepeat: true,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'prev_space',
|
|
43
|
+
key: and(space, shift),
|
|
44
|
+
fn: prev,
|
|
45
|
+
autoRepeat: true,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: 'next_right',
|
|
49
|
+
key: and(right, not(shift), navViaArrowKeys),
|
|
50
|
+
fn: next,
|
|
51
|
+
autoRepeat: true,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: 'prev_left',
|
|
55
|
+
key: and(left, not(shift), navViaArrowKeys),
|
|
56
|
+
fn: prev,
|
|
57
|
+
autoRepeat: true,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'next_page_key',
|
|
61
|
+
key: 'pageDown',
|
|
62
|
+
fn: next,
|
|
63
|
+
autoRepeat: true,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'prev_page_key',
|
|
67
|
+
key: 'pageUp',
|
|
68
|
+
fn: prev,
|
|
69
|
+
autoRepeat: true,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'next_down',
|
|
73
|
+
key: and(down, navViaArrowKeys),
|
|
74
|
+
fn: nextSlide,
|
|
75
|
+
autoRepeat: true,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'prev_up',
|
|
79
|
+
key: and(up, navViaArrowKeys),
|
|
80
|
+
fn: prevSlide,
|
|
81
|
+
autoRepeat: true,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'next_shift',
|
|
85
|
+
key: and(right, shift),
|
|
86
|
+
fn: nextSlide,
|
|
87
|
+
autoRepeat: true,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'prev_shift',
|
|
91
|
+
key: and(left, shift),
|
|
92
|
+
fn: prevSlide,
|
|
93
|
+
autoRepeat: true,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'toggle_dark',
|
|
97
|
+
key: and(d, not(drawingEnabled)),
|
|
98
|
+
fn: toggleDark,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'toggle_overview',
|
|
102
|
+
key: and(or(o, backtick), not(drawingEnabled)),
|
|
103
|
+
fn: toggleOverview,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'hide_overview',
|
|
107
|
+
key: and(escape, not(drawingEnabled)),
|
|
108
|
+
fn: () => showOverview.value = false,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'goto',
|
|
112
|
+
key: and(g, not(drawingEnabled)),
|
|
113
|
+
fn: () => showGotoDialog.value = !showGotoDialog.value,
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'next_overview',
|
|
117
|
+
key: and(right, showOverview),
|
|
118
|
+
fn: nextOverviewPage,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'prev_overview',
|
|
122
|
+
key: and(left, showOverview),
|
|
123
|
+
fn: prevOverviewPage,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'up_overview',
|
|
127
|
+
key: and(up, showOverview),
|
|
128
|
+
fn: upOverviewPage,
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'down_overview',
|
|
132
|
+
key: and(down, showOverview),
|
|
133
|
+
fn: downOverviewPage,
|
|
134
|
+
},
|
|
53
135
|
{
|
|
54
136
|
name: 'goto_from_overview',
|
|
55
137
|
key: and(enter, showOverview),
|
package/state/storage.ts
CHANGED
|
@@ -64,8 +64,12 @@ export function togglePresenterCursor() {
|
|
|
64
64
|
|
|
65
65
|
export const showEditor = useLocalStorage('slidev-show-editor', false, { listenToStorageChanges: false })
|
|
66
66
|
export const isEditorVertical = useLocalStorage('slidev-editor-vertical', false, { listenToStorageChanges: false })
|
|
67
|
-
export const editorWidth = useLocalStorage('slidev-editor-width', isClient
|
|
68
|
-
|
|
67
|
+
export const editorWidth = useLocalStorage('slidev-editor-width', isClient
|
|
68
|
+
? window.innerWidth * 0.4
|
|
69
|
+
: 318, { listenToStorageChanges: false })
|
|
70
|
+
export const editorHeight = useLocalStorage('slidev-editor-height', isClient
|
|
71
|
+
? window.innerHeight * 0.4
|
|
72
|
+
: 300, { listenToStorageChanges: false })
|
|
69
73
|
|
|
70
74
|
export const activeDragElement = shallowRef<DragElementState | null>(null)
|
|
71
75
|
|
package/state/syncState.ts
CHANGED
|
@@ -118,5 +118,11 @@ export function createSyncState<State extends object>(serverState: State, defaul
|
|
|
118
118
|
watch(state, onStateChanged, { deep: true })
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
return {
|
|
121
|
+
return {
|
|
122
|
+
init,
|
|
123
|
+
onPatch,
|
|
124
|
+
onUpdate,
|
|
125
|
+
patch,
|
|
126
|
+
state,
|
|
127
|
+
}
|
|
122
128
|
}
|