@slidev/client 52.18.0 → 52.19.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 +3 -2
- package/builtin/Monaco.vue +5 -2
- package/builtin/ShikiMagicMove.vue +4 -3
- package/composables/useNav.test.ts +88 -4
- package/composables/useNav.ts +23 -4
- package/internals/Goto.vue +1 -1
- package/internals/TitleIcon.vue +1 -1
- package/package.json +18 -18
- package/setup/monaco.ts +8 -8
|
@@ -51,8 +51,9 @@ const props = defineProps({
|
|
|
51
51
|
default: '',
|
|
52
52
|
},
|
|
53
53
|
})
|
|
54
|
+
const { $frontmatter, $clicksContext: clicks } = useSlideContext()
|
|
55
|
+
const isCodeCopy = computed(() => $frontmatter?.codeCopy ?? configs.codeCopy)
|
|
54
56
|
|
|
55
|
-
const { $clicksContext: clicks } = useSlideContext()
|
|
56
57
|
const el = ref<HTMLDivElement>()
|
|
57
58
|
const id = makeId()
|
|
58
59
|
|
|
@@ -152,7 +153,7 @@ const isBlockTitleShow = computed(() => {
|
|
|
152
153
|
</div>
|
|
153
154
|
<slot />
|
|
154
155
|
<button
|
|
155
|
-
v-if="
|
|
156
|
+
v-if="isCodeCopy"
|
|
156
157
|
class="slidev-code-copy absolute right-0 transition opacity-0 group-hover:opacity-20 hover:!opacity-100"
|
|
157
158
|
:class="isBlockTitleShow ? 'top-10' : 'top-0'"
|
|
158
159
|
:title="copied ? 'Copied' : 'Copy'" @click="copyCode()"
|
package/builtin/Monaco.vue
CHANGED
|
@@ -20,6 +20,7 @@ import lz from 'lz-string'
|
|
|
20
20
|
import { computed, defineAsyncComponent, nextTick, onMounted, ref } from 'vue'
|
|
21
21
|
import { useNav } from '../composables/useNav'
|
|
22
22
|
import { useSlideContext } from '../context'
|
|
23
|
+
import { configs } from '../env'
|
|
23
24
|
import { makeId } from '../logic/utils'
|
|
24
25
|
|
|
25
26
|
const props = withDefaults(
|
|
@@ -28,6 +29,7 @@ const props = withDefaults(
|
|
|
28
29
|
diffLz?: string
|
|
29
30
|
lang?: string
|
|
30
31
|
readonly?: boolean
|
|
32
|
+
lines?: boolean
|
|
31
33
|
lineNumbers?: 'on' | 'off' | 'relative' | 'interval'
|
|
32
34
|
height?: number | string // Posible values: 'initial', 'auto', '100%', '200px', etc.
|
|
33
35
|
editorOptions?: monaco.editor.IEditorOptions
|
|
@@ -44,7 +46,7 @@ const props = withDefaults(
|
|
|
44
46
|
codeLz: '',
|
|
45
47
|
lang: 'typescript',
|
|
46
48
|
readonly: false,
|
|
47
|
-
|
|
49
|
+
lines: configs.lineNumbers,
|
|
48
50
|
height: 'initial',
|
|
49
51
|
ata: true,
|
|
50
52
|
runnable: false,
|
|
@@ -58,6 +60,7 @@ const CodeRunner = defineAsyncComponent(() => import('../internals/CodeRunner.vu
|
|
|
58
60
|
const code = ref(lz.decompressFromBase64(props.codeLz).trimEnd())
|
|
59
61
|
const diff = props.diffLz && ref(lz.decompressFromBase64(props.diffLz).trimEnd())
|
|
60
62
|
const isWritable = computed(() => props.writable && !props.readonly && __DEV__)
|
|
63
|
+
const lineNumbers = props.lineNumbers ?? (props.lines ? 'on' : 'off')
|
|
61
64
|
|
|
62
65
|
const langMap: Record<string, string> = {
|
|
63
66
|
ts: 'typescript',
|
|
@@ -106,7 +109,7 @@ onMounted(async () => {
|
|
|
106
109
|
const commonOptions = {
|
|
107
110
|
automaticLayout: true,
|
|
108
111
|
readOnly: props.readonly,
|
|
109
|
-
lineNumbers
|
|
112
|
+
lineNumbers,
|
|
110
113
|
minimap: { enabled: false },
|
|
111
114
|
overviewRulerBorder: false,
|
|
112
115
|
overviewRulerLanes: 0,
|
|
@@ -41,7 +41,7 @@ const props = defineProps({
|
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
const steps = JSON.parse(lz.decompressFromBase64(props.stepsLz)) as KeyedTokensInfo[]
|
|
44
|
-
const { $clicksContext: clicks, $scale: scale, $zoom: zoom } = useSlideContext()
|
|
44
|
+
const { $clicksContext: clicks, $scale: scale, $zoom: zoom, $frontmatter } = useSlideContext()
|
|
45
45
|
const { isPrintMode } = useNav()
|
|
46
46
|
const id = makeId()
|
|
47
47
|
|
|
@@ -51,10 +51,11 @@ const isFirstTick = ref(true)
|
|
|
51
51
|
const container = ref<HTMLElement>()
|
|
52
52
|
|
|
53
53
|
const showCopyButton = computed(() => {
|
|
54
|
-
|
|
54
|
+
const codeCopy = $frontmatter?.codeCopy ?? configs.codeCopy
|
|
55
|
+
if (!codeCopy)
|
|
55
56
|
return false
|
|
56
57
|
|
|
57
|
-
const magicCopy = configs.magicMoveCopy
|
|
58
|
+
const magicCopy = $frontmatter?.magicMoveCopy ?? configs.magicMoveCopy
|
|
58
59
|
if (!magicCopy)
|
|
59
60
|
return false
|
|
60
61
|
|
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
import type { ClicksContext, SlideRoute } from '@slidev/types'
|
|
2
|
+
import type { SlidevContextNav } from './useNav'
|
|
3
|
+
import { renderToString } from '@vue/server-renderer'
|
|
4
|
+
import { provideLocal } from '@vueuse/core'
|
|
2
5
|
import { describe, expect, it, vi } from 'vitest'
|
|
3
|
-
import { computed, ref } from 'vue'
|
|
4
|
-
import {
|
|
6
|
+
import { computed, createSSRApp, defineComponent, h, reactive, ref } from 'vue'
|
|
7
|
+
import { injectionSlidevContext } from '../constants'
|
|
8
|
+
import { useNav, useNavBase } from './useNav'
|
|
5
9
|
|
|
6
10
|
vi.mock('#slidev/slides', async () => {
|
|
7
11
|
const { ref } = await import('vue')
|
|
8
|
-
return {
|
|
12
|
+
return {
|
|
13
|
+
slides: ref([
|
|
14
|
+
{
|
|
15
|
+
no: 1,
|
|
16
|
+
meta: {
|
|
17
|
+
slide: { frontmatter: { title: 'First' } },
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
no: 2,
|
|
22
|
+
meta: {
|
|
23
|
+
slide: { frontmatter: { title: 'Second' } },
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
]),
|
|
27
|
+
}
|
|
9
28
|
})
|
|
10
29
|
|
|
11
30
|
vi.mock('../env', async () => {
|
|
12
31
|
const { ref } = await import('vue')
|
|
13
32
|
return {
|
|
14
|
-
configs: {},
|
|
33
|
+
configs: { remote: false },
|
|
15
34
|
slideAspect: ref(16 / 9),
|
|
16
35
|
}
|
|
17
36
|
})
|
|
@@ -21,6 +40,24 @@ vi.mock('../state', async () => {
|
|
|
21
40
|
return { hmrSkipTransition: ref(false) }
|
|
22
41
|
})
|
|
23
42
|
|
|
43
|
+
vi.mock('vue-router', async () => {
|
|
44
|
+
const { reactive, ref } = await import('vue')
|
|
45
|
+
const route = reactive({
|
|
46
|
+
name: 'export',
|
|
47
|
+
params: { no: '1' },
|
|
48
|
+
query: {},
|
|
49
|
+
})
|
|
50
|
+
const router = {
|
|
51
|
+
currentRoute: ref(route),
|
|
52
|
+
push: vi.fn(),
|
|
53
|
+
replace: vi.fn(),
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
useRoute: () => route,
|
|
57
|
+
useRouter: () => router,
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
24
61
|
function route(no: number, frontmatter: Record<string, any>): SlideRoute {
|
|
25
62
|
return {
|
|
26
63
|
no,
|
|
@@ -53,4 +90,51 @@ describe('useNavBase', () => {
|
|
|
53
90
|
section: 'body',
|
|
54
91
|
})
|
|
55
92
|
})
|
|
93
|
+
|
|
94
|
+
it('uses the slide-local navigation context while rendering exported slides', async () => {
|
|
95
|
+
vi.stubGlobal('location', { search: '' })
|
|
96
|
+
let observedNav: SlidevContextNav | undefined
|
|
97
|
+
const localNav = {
|
|
98
|
+
currentSlideNo: computed(() => 2),
|
|
99
|
+
currentPage: computed(() => 2),
|
|
100
|
+
currentSlideRoute: computed(() => route(2, { title: 'Second' })),
|
|
101
|
+
tocTree: computed(() => [
|
|
102
|
+
{ no: 1, active: false },
|
|
103
|
+
{ no: 2, active: true },
|
|
104
|
+
]),
|
|
105
|
+
} as unknown as SlidevContextNav
|
|
106
|
+
|
|
107
|
+
const Child = defineComponent({
|
|
108
|
+
setup() {
|
|
109
|
+
observedNav = useNav()
|
|
110
|
+
return () => h('span')
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
const App = defineComponent({
|
|
114
|
+
setup() {
|
|
115
|
+
provideLocal(injectionSlidevContext, reactive({
|
|
116
|
+
nav: localNav,
|
|
117
|
+
configs: {},
|
|
118
|
+
themeConfigs: {},
|
|
119
|
+
}) as any)
|
|
120
|
+
return () => h(Child)
|
|
121
|
+
},
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
await renderToString(createSSRApp(App))
|
|
125
|
+
|
|
126
|
+
expect(observedNav?.currentSlideNo.value).toBe(2)
|
|
127
|
+
expect(observedNav?.currentSlideRoute.value.meta.slide.frontmatter.title).toBe('Second')
|
|
128
|
+
expect(observedNav?.tocTree.value[1].active).toBe(true)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('falls back to the shared nav when there is no injection context', () => {
|
|
132
|
+
// Directive hooks such as `v-motion`'s and `v-mark`'s `mounted` call
|
|
133
|
+
// `useNav()` while no component instance is current. There is no
|
|
134
|
+
// slide-local context to read there, so the shared nav is the answer.
|
|
135
|
+
vi.stubGlobal('location', { search: '' })
|
|
136
|
+
|
|
137
|
+
expect(() => useNav()).not.toThrow()
|
|
138
|
+
expect(useNav().currentSlideNo.value).toBe(1)
|
|
139
|
+
})
|
|
56
140
|
})
|
package/composables/useNav.ts
CHANGED
|
@@ -3,11 +3,11 @@ import type { ComputedRef, Ref, TransitionGroupProps, WritableComputedRef } from
|
|
|
3
3
|
import type { RouteLocationNormalized, Router } from 'vue-router'
|
|
4
4
|
import { clamp } from '@antfu/utils'
|
|
5
5
|
import { parseRangeString } from '@slidev/parser/utils'
|
|
6
|
-
import { createSharedComposable } from '@vueuse/core'
|
|
7
|
-
import { computed, ref, watch } from 'vue'
|
|
6
|
+
import { createSharedComposable, injectLocal } from '@vueuse/core'
|
|
7
|
+
import { computed, hasInjectionContext, ref, toRaw, watch } from 'vue'
|
|
8
8
|
import { useRoute, useRouter } from 'vue-router'
|
|
9
9
|
import { slides } from '#slidev/slides'
|
|
10
|
-
import { CLICKS_MAX } from '../constants'
|
|
10
|
+
import { CLICKS_MAX, injectionSlidevContext } from '../constants'
|
|
11
11
|
import { configs } from '../env'
|
|
12
12
|
import { useRouteQuery } from '../logic/route'
|
|
13
13
|
import { getSlide, getSlidePath } from '../logic/slides'
|
|
@@ -365,7 +365,7 @@ const useNavState = createSharedComposable((): SlidevContextNavState => {
|
|
|
365
365
|
}
|
|
366
366
|
})
|
|
367
367
|
|
|
368
|
-
|
|
368
|
+
const useSharedNav = createSharedComposable((): SlidevContextNavFull => {
|
|
369
369
|
const state = useNavState()
|
|
370
370
|
const router = useRouter()
|
|
371
371
|
|
|
@@ -401,3 +401,22 @@ export const useNav = createSharedComposable((): SlidevContextNavFull => {
|
|
|
401
401
|
...state,
|
|
402
402
|
}
|
|
403
403
|
})
|
|
404
|
+
|
|
405
|
+
export function useNav(): SlidevContextNavFull {
|
|
406
|
+
const nav = useSharedNav()
|
|
407
|
+
// `useNav()` is also called outside of `setup()`, most notably from the
|
|
408
|
+
// `mounted`/`created` hooks of the `v-motion` and `v-mark` directives.
|
|
409
|
+
// `injectLocal` throws there, and there is no slide-local context to read
|
|
410
|
+
// anyway, so fall back to the shared nav.
|
|
411
|
+
const context = hasInjectionContext()
|
|
412
|
+
? injectLocal(injectionSlidevContext, undefined)
|
|
413
|
+
: undefined
|
|
414
|
+
if (!context)
|
|
415
|
+
return nav
|
|
416
|
+
|
|
417
|
+
const localNav = toRaw(context).nav as unknown as SlidevContextNav
|
|
418
|
+
return {
|
|
419
|
+
...nav,
|
|
420
|
+
...localNav,
|
|
421
|
+
}
|
|
422
|
+
}
|
package/internals/Goto.vue
CHANGED
|
@@ -111,7 +111,7 @@ watch(activeElement, () => {
|
|
|
111
111
|
ref="container"
|
|
112
112
|
class="fixed right-5 transition-all"
|
|
113
113
|
w-90 max-w-90 min-w-90
|
|
114
|
-
:class="showGotoDialog ? 'top-5' : '-top-20'"
|
|
114
|
+
:class="showGotoDialog ? 'top-5' : '-top-20 op0 pointer-events-none'"
|
|
115
115
|
>
|
|
116
116
|
<div
|
|
117
117
|
class="bg-main transform"
|
package/internals/TitleIcon.vue
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "52.
|
|
4
|
+
"version": "52.19.0",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -30,45 +30,45 @@
|
|
|
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.25",
|
|
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.
|
|
36
|
+
"@shikijs/engine-javascript": "^4.4.1",
|
|
37
|
+
"@shikijs/magic-move": "^4.4.1",
|
|
38
|
+
"@shikijs/monaco": "^4.4.1",
|
|
39
|
+
"@shikijs/vitepress-twoslash": "^4.4.1",
|
|
40
40
|
"@slidev/rough-notation": "^0.1.0",
|
|
41
41
|
"@typescript/ata": "^0.9.8",
|
|
42
|
-
"@unhead/vue": "^3.
|
|
42
|
+
"@unhead/vue": "^3.2.3",
|
|
43
43
|
"@unocss/extractor-mdc": "^66.7.5",
|
|
44
44
|
"@unocss/preset-mini": "^66.7.5",
|
|
45
45
|
"@unocss/reset": "^66.7.5",
|
|
46
|
-
"@vueuse/core": "^14.
|
|
47
|
-
"@vueuse/math": "^14.
|
|
46
|
+
"@vueuse/core": "^14.4.0",
|
|
47
|
+
"@vueuse/math": "^14.4.0",
|
|
48
48
|
"@vueuse/motion": "^3.0.3",
|
|
49
49
|
"ansis": "^4.3.1",
|
|
50
50
|
"drauu": "^1.0.0",
|
|
51
51
|
"file-saver": "^2.0.5",
|
|
52
52
|
"fitty": "^2.4.2",
|
|
53
53
|
"floating-vue": "^5.2.2",
|
|
54
|
-
"fuse.js": "^7.
|
|
55
|
-
"katex": "^0.
|
|
54
|
+
"fuse.js": "^7.5.0",
|
|
55
|
+
"katex": "^0.18.1",
|
|
56
56
|
"lz-string": "^1.5.0",
|
|
57
57
|
"mermaid": "^11.16.0",
|
|
58
|
-
"monaco-editor": "^0.
|
|
58
|
+
"monaco-editor": "^0.56.0",
|
|
59
59
|
"nanotar": "^0.3.0",
|
|
60
60
|
"pptxgenjs": "^4.0.1",
|
|
61
61
|
"recordrtc": "^5.6.2",
|
|
62
|
-
"shiki": "^4.
|
|
62
|
+
"shiki": "^4.4.1",
|
|
63
63
|
"typescript": "^6.0.3",
|
|
64
64
|
"unocss": "^66.7.5",
|
|
65
|
-
"vue": "^3.5.
|
|
66
|
-
"vue-router": "^5.
|
|
65
|
+
"vue": "^3.5.40",
|
|
66
|
+
"vue-router": "^5.2.0",
|
|
67
67
|
"yaml": "^2.9.0",
|
|
68
|
-
"@slidev/parser": "52.
|
|
69
|
-
"@slidev/types": "52.
|
|
68
|
+
"@slidev/parser": "52.19.0",
|
|
69
|
+
"@slidev/types": "52.19.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"vite": "^8.
|
|
72
|
+
"vite": "^8.2.0"
|
|
73
73
|
}
|
|
74
74
|
}
|
package/setup/monaco.ts
CHANGED
|
@@ -3,18 +3,18 @@ import { createSingletonPromise } from '@antfu/utils'
|
|
|
3
3
|
import { shikiToMonaco } from '@shikijs/monaco'
|
|
4
4
|
import { setupTypeAcquisition } from '@typescript/ata'
|
|
5
5
|
import * as monaco from 'monaco-editor'
|
|
6
|
-
import EditorWorker from 'monaco-editor/
|
|
6
|
+
import EditorWorker from 'monaco-editor/editor/editor.worker?worker'
|
|
7
7
|
// @ts-expect-error missing types
|
|
8
|
-
import { StandaloneServices } from 'monaco-editor/
|
|
8
|
+
import { StandaloneServices } from 'monaco-editor/editor/standalone/browser/standaloneServices'
|
|
9
9
|
|
|
10
|
-
import CssWorker from 'monaco-editor/
|
|
11
|
-
import HtmlWorker from 'monaco-editor/
|
|
12
|
-
import JsonWorker from 'monaco-editor/
|
|
13
|
-
import TsWorker from 'monaco-editor/
|
|
10
|
+
import CssWorker from 'monaco-editor/language/css/css.worker?worker'
|
|
11
|
+
import HtmlWorker from 'monaco-editor/language/html/html.worker?worker'
|
|
12
|
+
import JsonWorker from 'monaco-editor/language/json/json.worker?worker'
|
|
13
|
+
import TsWorker from 'monaco-editor/language/typescript/ts.worker?worker'
|
|
14
14
|
// @ts-expect-error missing types
|
|
15
|
-
import { ContextViewService } from 'monaco-editor/
|
|
15
|
+
import { ContextViewService } from 'monaco-editor/platform/contextview/browser/contextViewService'
|
|
16
16
|
// @ts-expect-error missing types
|
|
17
|
-
import { SyncDescriptor } from 'monaco-editor/
|
|
17
|
+
import { SyncDescriptor } from 'monaco-editor/platform/instantiation/common/descriptors'
|
|
18
18
|
import ts from 'typescript'
|
|
19
19
|
import { watchEffect } from 'vue'
|
|
20
20
|
|