@slidev/client 0.27.20 → 0.28.3
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/AutoFitText.vue +4 -3
- package/builtin/CodeHighlightController.vue +1 -1
- package/builtin/Monaco.vue +1 -1
- package/builtin/Toc.vue +83 -0
- package/builtin/TocList.vue +25 -0
- package/builtin/Tweet.vue +3 -3
- package/env.ts +1 -1
- package/internals/Controls.vue +1 -1
- package/internals/DevicesList.vue +1 -1
- package/internals/Draggable.vue +2 -2
- package/internals/DrawingControls.vue +3 -3
- package/internals/DrawingLayer.vue +1 -1
- package/internals/DrawingPreview.vue +1 -1
- package/internals/Editor.vue +6 -6
- package/internals/InfoDialog.vue +1 -1
- package/internals/Modal.vue +1 -1
- package/internals/NavControls.vue +4 -4
- package/internals/Play.vue +8 -8
- package/internals/Presenter.vue +3 -3
- package/internals/RecordingDialog.vue +1 -1
- package/internals/SlideContainer.vue +1 -1
- package/internals/SlideWrapper.ts +1 -1
- package/internals/SlidesShow.vue +3 -3
- package/internals/WebCamera.vue +1 -1
- package/logic/drawings.ts +3 -3
- package/logic/nav.ts +67 -2
- package/logic/recording.ts +2 -2
- package/logic/shortcuts.ts +2 -2
- package/logic/utils.ts +1 -1
- package/modules/context.ts +2 -2
- package/modules/directives.ts +8 -8
- package/modules/mermaid.ts +1 -1
- package/package.json +17 -16
- package/routes.ts +4 -2
- package/setup/main.ts +1 -1
- package/setup/monaco.ts +2 -2
- package/setup/prettier.ts +4 -5
- package/setup/root.ts +2 -2
- package/setup/shortcuts.ts +4 -4
- package/state/index.ts +1 -1
package/builtin/AutoFitText.vue
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
[Expiremental]
|
|
3
3
|
|
|
4
4
|
Think this component as the TextBox you that will see
|
|
5
|
-
in PowerPoint or Keynote. It will
|
|
5
|
+
in PowerPoint or Keynote. It will automatically resize
|
|
6
6
|
the font size based on it's content to fit them in.
|
|
7
7
|
|
|
8
8
|
Usage:
|
|
@@ -18,7 +18,9 @@ or
|
|
|
18
18
|
import { useElementSize, useVModel } from '@vueuse/core'
|
|
19
19
|
import { computed, ref, watch } from 'vue'
|
|
20
20
|
|
|
21
|
-
const emit = defineEmits<{
|
|
21
|
+
const emit = defineEmits<{
|
|
22
|
+
(e: any): void
|
|
23
|
+
}>()
|
|
22
24
|
const props = defineProps({
|
|
23
25
|
modelValue: {
|
|
24
26
|
default: '',
|
|
@@ -34,7 +36,6 @@ const props = defineProps({
|
|
|
34
36
|
const container = ref<HTMLDivElement>()
|
|
35
37
|
const inner = ref<HTMLDivElement>()
|
|
36
38
|
const size = ref(100)
|
|
37
|
-
// @ts-ignore
|
|
38
39
|
const fontSize = computed(() => `${size.value}px`)
|
|
39
40
|
const value = useVModel(props, 'modelValue', emit)
|
|
40
41
|
|
|
@@ -15,7 +15,7 @@ Learn more: https://sli.dev/guide/syntax.html#line-highlighting
|
|
|
15
15
|
import { range, remove } from '@antfu/utils'
|
|
16
16
|
import { parseRangeString } from '@slidev/parser/core'
|
|
17
17
|
import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, watchEffect } from 'vue'
|
|
18
|
-
import {
|
|
18
|
+
import { CLASS_VCLICK_TARGET, injectionClicks, injectionClicksDisabled, injectionClicksElements } from '../constants'
|
|
19
19
|
|
|
20
20
|
const props = defineProps({
|
|
21
21
|
ranges: {
|
package/builtin/Monaco.vue
CHANGED
|
@@ -16,7 +16,7 @@ Learn more: https://sli.dev/guide/syntax.html#monaco-editor
|
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
18
|
<script setup lang="ts">
|
|
19
|
-
import {
|
|
19
|
+
import { computed, onMounted, ref, watchEffect } from 'vue'
|
|
20
20
|
import { useEventListener } from '@vueuse/core'
|
|
21
21
|
import { decode } from 'js-base64'
|
|
22
22
|
import { nanoid } from 'nanoid'
|
package/builtin/Toc.vue
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Table Of content
|
|
3
|
+
|
|
4
|
+
`mode` can be either 'all', 'onlyCurrentTree' or 'onlySiblings'
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
|
|
8
|
+
<Toc columns='2' maxDepth='3' mode='onlySiblings'/>
|
|
9
|
+
-->
|
|
10
|
+
<script setup lang='ts'>
|
|
11
|
+
import { computed } from 'vue'
|
|
12
|
+
import type { TocItem } from '../logic/nav'
|
|
13
|
+
import { tree } from '../logic/nav'
|
|
14
|
+
|
|
15
|
+
const props = withDefaults(
|
|
16
|
+
defineProps<{
|
|
17
|
+
columns?: string | number
|
|
18
|
+
maxDepth?: string | number
|
|
19
|
+
minDepth?: string | number
|
|
20
|
+
mode?: 'all' | 'onlyCurrentTree' | 'onlySiblings'
|
|
21
|
+
}>(),
|
|
22
|
+
{
|
|
23
|
+
columns: 1,
|
|
24
|
+
maxDepth: Infinity,
|
|
25
|
+
minDepth: 1,
|
|
26
|
+
mode: 'all',
|
|
27
|
+
},
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
function filterTreeDepth(tree: TocItem[], level = 1): TocItem[] {
|
|
31
|
+
if (level > Number(props.maxDepth)) {
|
|
32
|
+
return []
|
|
33
|
+
}
|
|
34
|
+
else if (level < Number(props.minDepth)) {
|
|
35
|
+
const activeItem = tree.find((item: TocItem) => item.active || item.activeParent)
|
|
36
|
+
return activeItem ? filterTreeDepth(activeItem.children, level + 1) : []
|
|
37
|
+
}
|
|
38
|
+
return tree
|
|
39
|
+
.map((item: TocItem) => ({
|
|
40
|
+
...item,
|
|
41
|
+
children: filterTreeDepth(item.children, level + 1),
|
|
42
|
+
}))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function filterOnlyCurrentTree(tree: TocItem[]): TocItem[] {
|
|
46
|
+
return tree
|
|
47
|
+
.filter(
|
|
48
|
+
(item: TocItem) =>
|
|
49
|
+
item.active || item.activeParent || item.hasActiveParent,
|
|
50
|
+
)
|
|
51
|
+
.map((item: TocItem) => ({
|
|
52
|
+
...item,
|
|
53
|
+
children: filterOnlyCurrentTree(item.children),
|
|
54
|
+
}))
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function filterOnlySiblings(tree: TocItem[]): TocItem[] {
|
|
58
|
+
const treehasActiveItem = tree.some(
|
|
59
|
+
(item: TocItem) => item.active || item.activeParent || item.hasActiveParent,
|
|
60
|
+
)
|
|
61
|
+
return tree
|
|
62
|
+
.filter(() => treehasActiveItem)
|
|
63
|
+
.map((item: TocItem) => ({
|
|
64
|
+
...item,
|
|
65
|
+
children: filterOnlySiblings(item.children),
|
|
66
|
+
}))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const toc = computed(() => {
|
|
70
|
+
let tocTree = filterTreeDepth(tree.value)
|
|
71
|
+
if (props.mode === 'onlyCurrentTree')
|
|
72
|
+
tocTree = filterOnlyCurrentTree(tocTree)
|
|
73
|
+
else if (props.mode === 'onlySiblings')
|
|
74
|
+
tocTree = filterOnlySiblings(tocTree)
|
|
75
|
+
return tocTree
|
|
76
|
+
})
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<template>
|
|
80
|
+
<div class="slidev-toc" :style="`column-count:${columns}`">
|
|
81
|
+
<TocList :level="1" :list="toc" />
|
|
82
|
+
</div>
|
|
83
|
+
</template>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
TOC list
|
|
3
|
+
(used by Toc component, you don't need to use this component directly)
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
|
|
7
|
+
<TocList :list="list"/>
|
|
8
|
+
-->
|
|
9
|
+
<script setup lang="ts">
|
|
10
|
+
import type { TocItem } from '../logic/nav'
|
|
11
|
+
|
|
12
|
+
withDefaults(defineProps<{
|
|
13
|
+
level: number
|
|
14
|
+
list: TocItem[]
|
|
15
|
+
}>(), { level: 1 })
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<ul v-if="list && list.length > 0" :class="['slidev-toc-list', `slidev-toc-list-level-${level}`]">
|
|
20
|
+
<li v-for="item in list" :key="item.path" :class="['slidev-toc-item', {'slidev-toc-item-active': item.active}, {'slidev-toc-item-parent-active': item.activeParent}]">
|
|
21
|
+
<RouterLink :to="item.path" v-html="item.title" />
|
|
22
|
+
<TocList :level="level + 1" :list="item.children" />
|
|
23
|
+
</li>
|
|
24
|
+
</ul>
|
|
25
|
+
</template>
|
package/builtin/Tweet.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
A simple wrapper for
|
|
2
|
+
A simple wrapper for embedded Tweet
|
|
3
3
|
|
|
4
4
|
Usage:
|
|
5
5
|
|
|
@@ -23,7 +23,7 @@ const vm = getCurrentInstance()!
|
|
|
23
23
|
const loaded = ref(false)
|
|
24
24
|
|
|
25
25
|
async function create() {
|
|
26
|
-
// @ts-
|
|
26
|
+
// @ts-expect-error global
|
|
27
27
|
await window.twttr.widgets.createTweet(
|
|
28
28
|
props.id.toString(),
|
|
29
29
|
tweet.value,
|
|
@@ -35,7 +35,7 @@ async function create() {
|
|
|
35
35
|
loaded.value = true
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
// @ts-
|
|
38
|
+
// @ts-expect-error global
|
|
39
39
|
if (window?.twttr?.widgets) {
|
|
40
40
|
onMounted(create)
|
|
41
41
|
}
|
package/env.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SlidevConfig } from '@slidev/types'
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import { objectMap } from '@antfu/utils'
|
|
4
|
-
// @ts-expect-error
|
|
4
|
+
// @ts-expect-error missing types
|
|
5
5
|
import _configs from '/@slidev/configs'
|
|
6
6
|
import _serverState from 'server-reactive:nav'
|
|
7
7
|
import _serverDrawingState from 'server-reactive:drawings?diff'
|
package/internals/Controls.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { shallowRef } from 'vue'
|
|
3
|
-
import { showOverview, showRecordingDialog
|
|
3
|
+
import { showInfoDialog, showOverview, showRecordingDialog } from '../state'
|
|
4
4
|
import { configs } from '../env'
|
|
5
5
|
import SlidesOverview from './SlidesOverview.vue'
|
|
6
6
|
import InfoDialog from './InfoDialog.vue'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import { currentCamera, currentMic } from '../state'
|
|
4
|
-
import { cameras,
|
|
4
|
+
import { cameras, ensureDevicesListPermissions, microphones } from '../logic/recording'
|
|
5
5
|
import SelectList from './SelectList.vue'
|
|
6
6
|
import type { SelectionItem } from './types'
|
|
7
7
|
|
package/internals/Draggable.vue
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref } from 'vue'
|
|
3
|
-
import {
|
|
3
|
+
import { useDraggable, useStorage } from '@vueuse/core'
|
|
4
4
|
|
|
5
5
|
const props = defineProps<{
|
|
6
6
|
storageKey?: string
|
|
7
|
-
initial?: {x: number; y: number}
|
|
7
|
+
initial?: { x: number; y: number }
|
|
8
8
|
}>()
|
|
9
9
|
|
|
10
10
|
const el = ref<HTMLElement | null>(null)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
brush, brushColors, canClear,
|
|
4
|
+
canRedo, canUndo, clearDrauu,
|
|
5
|
+
drauu, drawingEnabled, drawingMode, drawingPinned,
|
|
6
6
|
} from '../logic/drawings'
|
|
7
7
|
import VerticalDivider from './VerticalDivider.vue'
|
|
8
8
|
import Draggable from './Draggable.vue'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { inject, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
3
3
|
import { drauu, loadCanvas } from '../logic/drawings'
|
|
4
4
|
import { injectionSlideScale } from '../constants'
|
|
5
5
|
|
package/internals/Editor.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import { computed,
|
|
4
|
-
import { activeElement,
|
|
2
|
+
import { throttledWatch, useEventListener } from '@vueuse/core'
|
|
3
|
+
import { computed, onMounted, ref, watch } from 'vue'
|
|
4
|
+
import { activeElement, editorWidth, isInputting, showEditor } from '../state'
|
|
5
5
|
import { useCodeMirror } from '../setup/codemirror'
|
|
6
6
|
import { currentSlideId, openInEditor } from '../logic/nav'
|
|
7
7
|
import { useDynamicSlideInfo } from '../logic/note'
|
|
@@ -66,7 +66,7 @@ onMounted(() => {
|
|
|
66
66
|
{
|
|
67
67
|
mode: 'markdown',
|
|
68
68
|
lineWrapping: true,
|
|
69
|
-
// @ts-
|
|
69
|
+
// @ts-expect-error missing types
|
|
70
70
|
highlightFormatting: true,
|
|
71
71
|
fencedCodeBlockDefaultMode: 'javascript',
|
|
72
72
|
},
|
|
@@ -84,7 +84,7 @@ onMounted(() => {
|
|
|
84
84
|
{
|
|
85
85
|
mode: 'markdown',
|
|
86
86
|
lineWrapping: true,
|
|
87
|
-
// @ts-
|
|
87
|
+
// @ts-expect-error missing types
|
|
88
88
|
highlightFormatting: true,
|
|
89
89
|
fencedCodeBlockDefaultMode: 'javascript',
|
|
90
90
|
},
|
|
@@ -100,7 +100,7 @@ function updateWidth(v: number) {
|
|
|
100
100
|
}
|
|
101
101
|
function switchTab(newTab: typeof tab.value) {
|
|
102
102
|
tab.value = newTab
|
|
103
|
-
// @ts-expect-error
|
|
103
|
+
// @ts-expect-error force cast
|
|
104
104
|
document.activeElement?.blur?.()
|
|
105
105
|
}
|
|
106
106
|
useEventListener('pointermove', (e) => {
|
package/internals/InfoDialog.vue
CHANGED
|
@@ -4,7 +4,7 @@ import { computed } from 'vue'
|
|
|
4
4
|
import { configs } from '../env'
|
|
5
5
|
import Modal from './Modal.vue'
|
|
6
6
|
|
|
7
|
-
const emit = defineEmits<{(name: 'modelValue', v: boolean): void}>()
|
|
7
|
+
const emit = defineEmits<{ (name: 'modelValue', v: boolean): void }>()
|
|
8
8
|
const props = defineProps({
|
|
9
9
|
modelValue: {
|
|
10
10
|
default: false,
|
package/internals/Modal.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useVModel } from '@vueuse/core'
|
|
3
3
|
|
|
4
|
-
const emit = defineEmits<{(name: 'modelValue', v: boolean): void}>()
|
|
4
|
+
const emit = defineEmits<{ (name: 'modelValue', v: boolean): void }>()
|
|
5
5
|
const props = defineProps({
|
|
6
6
|
modelValue: {
|
|
7
7
|
default: false,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, ref, shallowRef } from 'vue'
|
|
3
|
-
import { isDark, toggleDark
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { isColorSchemaConfigured, isDark, toggleDark } from '../logic/dark'
|
|
4
|
+
import { currentPage, downloadPDF, hasNext, hasPrev, isEmbedded, isPresenter, next, prev, total } from '../logic/nav'
|
|
5
|
+
import { activeElement, breakpoints, fullscreen, showEditor, showInfoDialog, showPresenterCursor, toggleOverview } from '../state'
|
|
6
|
+
import { brush, drawingEnabled } from '../logic/drawings'
|
|
7
7
|
import { configs } from '../env'
|
|
8
8
|
import Settings from './Settings.vue'
|
|
9
9
|
import MenuButton from './MenuButton.vue'
|
package/internals/Play.vue
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { isPrintMode, next, prev, useSwipeControls
|
|
2
|
+
import { computed, ref, shallowRef } from 'vue'
|
|
3
|
+
import { isScreenVertical, showEditor, slideScale, windowSize } from '../state'
|
|
4
|
+
import { isEmbedded, isPrintMode, next, prev, useSwipeControls } from '../logic/nav'
|
|
5
5
|
import { isDrawing } from '../logic/drawings'
|
|
6
6
|
import { registerShortcuts } from '../logic/shortcuts'
|
|
7
|
-
import {
|
|
7
|
+
import { configs, themeVars } from '../env'
|
|
8
8
|
import Controls from './Controls.vue'
|
|
9
9
|
import SlideContainer from './SlideContainer.vue'
|
|
10
10
|
import NavControls from './NavControls.vue'
|
|
@@ -18,7 +18,7 @@ function onClick(e: MouseEvent) {
|
|
|
18
18
|
return
|
|
19
19
|
|
|
20
20
|
if ((e.target as HTMLElement)?.id === 'slide-container') {
|
|
21
|
-
// click right to next, left to
|
|
21
|
+
// click right to next, left to previous
|
|
22
22
|
if ((e.screenX / window.innerWidth) > 0.6)
|
|
23
23
|
next()
|
|
24
24
|
else
|
|
@@ -28,7 +28,7 @@ function onClick(e: MouseEvent) {
|
|
|
28
28
|
|
|
29
29
|
useSwipeControls(root)
|
|
30
30
|
|
|
31
|
-
const
|
|
31
|
+
const persistNav = computed(() => isScreenVertical.value || showEditor.value)
|
|
32
32
|
|
|
33
33
|
const Editor = shallowRef<any>()
|
|
34
34
|
if (__DEV__)
|
|
@@ -55,11 +55,11 @@ if (__SLIDEV_FEATURE_DRAWINGS__)
|
|
|
55
55
|
<div
|
|
56
56
|
class="absolute bottom-0 left-0 transition duration-300 opacity-0 hover:opacity-100"
|
|
57
57
|
:class="[
|
|
58
|
-
|
|
58
|
+
persistNav ? 'opacity-100 right-0' : 'oapcity-0 p-2',
|
|
59
59
|
isDrawing ? 'pointer-events-none': ''
|
|
60
60
|
]"
|
|
61
61
|
>
|
|
62
|
-
<NavControls class="m-auto" :persist="
|
|
62
|
+
<NavControls class="m-auto" :persist="persistNav" />
|
|
63
63
|
</div>
|
|
64
64
|
<template v-if="__SLIDEV_FEATURE_DRAWINGS__ && !configs.drawings.presenterOnly && !isEmbedded && DrawingControls">
|
|
65
65
|
<DrawingControls class="ml-0" />
|
package/internals/Presenter.vue
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useHead } from '@vueuse/head'
|
|
3
|
-
import {
|
|
3
|
+
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
|
4
4
|
import { useMouse, useWindowFocus } from '@vueuse/core'
|
|
5
|
-
import {
|
|
5
|
+
import { clicks, clicksTotal, currentPage, currentRoute, hasNext, nextRoute, total, useSwipeControls } from '../logic/nav'
|
|
6
6
|
import { showOverview, showPresenterCursor } from '../state'
|
|
7
|
-
import { configs,
|
|
7
|
+
import { configs, serverState, themeVars } from '../env'
|
|
8
8
|
import { registerShortcuts } from '../logic/shortcuts'
|
|
9
9
|
import { getSlideClass } from '../utils'
|
|
10
10
|
import { useTimer } from '../logic/utils'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useVModel } from '@vueuse/core'
|
|
3
3
|
import { nextTick } from 'vue'
|
|
4
|
-
import {
|
|
4
|
+
import { getFilename, recordCamera, recorder, recordingName } from '../logic/recording'
|
|
5
5
|
import Modal from './Modal.vue'
|
|
6
6
|
import DevicesList from './DevicesList.vue'
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { useElementSize } from '@vueuse/core'
|
|
3
3
|
import { computed, provide, ref, watchEffect } from 'vue'
|
|
4
|
-
import {
|
|
4
|
+
import { configs, slideAspect, slideHeight, slideWidth } from '../env'
|
|
5
5
|
import { injectionSlideScale } from '../constants'
|
|
6
6
|
|
|
7
7
|
const props = defineProps({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useVModel } from '@vueuse/core'
|
|
2
|
-
import {
|
|
2
|
+
import { defineComponent, h, provide } from 'vue'
|
|
3
3
|
import { injectionClicks, injectionClicksDisabled, injectionClicksElements, injectionOrderMap } from '../constants'
|
|
4
4
|
|
|
5
5
|
export default defineComponent({
|
package/internals/SlidesShow.vue
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { shallowRef, watch } from 'vue'
|
|
3
|
-
import {
|
|
3
|
+
import { clicks, currentRoute, isPresenter, nextRoute, rawRoutes } from '../logic/nav'
|
|
4
4
|
import { getSlideClass } from '../utils'
|
|
5
5
|
import SlideWrapper from './SlideWrapper'
|
|
6
|
-
// @ts-
|
|
6
|
+
// @ts-expect-error virtual module
|
|
7
7
|
import GlobalTop from '/@slidev/global-components/top'
|
|
8
|
-
// @ts-
|
|
8
|
+
// @ts-expect-error virtual module
|
|
9
9
|
import GlobalBottom from '/@slidev/global-components/bottom'
|
|
10
10
|
import PresenterMouse from './PresenterMouse.vue'
|
|
11
11
|
|
package/internals/WebCamera.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { useEventListener, useStorage
|
|
2
|
+
import { useDraggable, useEventListener, useStorage } from '@vueuse/core'
|
|
3
3
|
import { computed, onMounted, ref, watchEffect } from 'vue'
|
|
4
4
|
import { currentCamera } from '../state'
|
|
5
5
|
import { recorder } from '../logic/recording'
|
package/logic/drawings.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { computed, markRaw, nextTick, reactive, ref, watch, watchEffect } from 'vue'
|
|
2
|
-
import type { Brush,
|
|
2
|
+
import type { Brush, Options as DrauuOptions, DrawingMode } from 'drauu'
|
|
3
3
|
import { createDrauu } from 'drauu'
|
|
4
|
-
import {
|
|
5
|
-
import { serverDrawingState as drawingState
|
|
4
|
+
import { toReactive, useStorage } from '@vueuse/core'
|
|
5
|
+
import { configs, serverDrawingState as drawingState } from '../env'
|
|
6
6
|
import { currentPage, isPresenter } from './nav'
|
|
7
7
|
|
|
8
8
|
export const brushColors = [
|
package/logic/nav.ts
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import type { Ref } from 'vue'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import type { RouteRecordRaw } from 'vue-router'
|
|
3
|
+
import { computed, nextTick, ref } from 'vue'
|
|
4
|
+
import { SwipeDirection, isString, timestamp, usePointerSwipe } from '@vueuse/core'
|
|
4
5
|
import { rawRoutes, router } from '../routes'
|
|
5
6
|
import { configs } from '../env'
|
|
6
7
|
import { useRouteQuery } from './route'
|
|
7
8
|
import { isDrawing } from './drawings'
|
|
8
9
|
|
|
10
|
+
export interface TocItem {
|
|
11
|
+
active?: boolean
|
|
12
|
+
activeParent?: boolean
|
|
13
|
+
children: TocItem[]
|
|
14
|
+
hasActiveParent?: boolean
|
|
15
|
+
level: number
|
|
16
|
+
path: string
|
|
17
|
+
hideInToc?: boolean
|
|
18
|
+
title?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
9
21
|
export { rawRoutes, router }
|
|
10
22
|
|
|
11
23
|
// force update collected elements when the route is fully resolved
|
|
@@ -62,6 +74,15 @@ export const clicksTotal = computed(() => +(currentRoute.value?.meta?.clicks ??
|
|
|
62
74
|
export const hasNext = computed(() => currentPage.value < rawRoutes.length - 1 || clicks.value < clicksTotal.value)
|
|
63
75
|
export const hasPrev = computed(() => currentPage.value > 1 || clicks.value > 0)
|
|
64
76
|
|
|
77
|
+
export const rawTree = computed(() => rawRoutes
|
|
78
|
+
.filter((route: RouteRecordRaw) => route.meta?.slide?.title)
|
|
79
|
+
.reduce((acc: TocItem[], route: RouteRecordRaw) => {
|
|
80
|
+
addToTree(acc, route)
|
|
81
|
+
return acc
|
|
82
|
+
}, []))
|
|
83
|
+
export const treeWithActiveStatuses = computed(() => getTreeWithActiveStatuses(rawTree.value))
|
|
84
|
+
export const tree = computed(() => filterTree(treeWithActiveStatuses.value))
|
|
85
|
+
|
|
65
86
|
export function next() {
|
|
66
87
|
if (clicksTotal.value <= clicks.value)
|
|
67
88
|
nextSlide()
|
|
@@ -152,3 +173,47 @@ export async function openInEditor(url?: string) {
|
|
|
152
173
|
await fetch(`/__open-in-editor?file=${encodeURIComponent(url)}`)
|
|
153
174
|
return true
|
|
154
175
|
}
|
|
176
|
+
|
|
177
|
+
export function addToTree(tree: TocItem[], route: RouteRecordRaw, level = 1) {
|
|
178
|
+
const titleLevel = route.meta?.slide?.level
|
|
179
|
+
if (titleLevel && titleLevel > level && tree.length > 0) {
|
|
180
|
+
addToTree(tree[tree.length - 1].children, route, level + 1)
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
tree.push({
|
|
184
|
+
children: [],
|
|
185
|
+
level,
|
|
186
|
+
path: route.path,
|
|
187
|
+
hideInToc: Boolean(route.meta?.hideInToc),
|
|
188
|
+
title: route.meta?.slide?.title,
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function getTreeWithActiveStatuses(
|
|
194
|
+
tree: TocItem[],
|
|
195
|
+
hasActiveParent = false,
|
|
196
|
+
parent?: TocItem,
|
|
197
|
+
): TocItem[] {
|
|
198
|
+
return tree.map((item: TocItem) => {
|
|
199
|
+
const clone = {
|
|
200
|
+
...item,
|
|
201
|
+
active: item.path === currentRoute.value?.path,
|
|
202
|
+
hasActiveParent,
|
|
203
|
+
}
|
|
204
|
+
if (clone.children.length > 0)
|
|
205
|
+
clone.children = getTreeWithActiveStatuses(clone.children, clone.active || clone.hasActiveParent, clone)
|
|
206
|
+
if (parent && (clone.active || clone.activeParent))
|
|
207
|
+
parent.activeParent = true
|
|
208
|
+
return clone
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function filterTree(tree: TocItem[], level = 1): TocItem[] {
|
|
213
|
+
return tree
|
|
214
|
+
.filter((item: TocItem) => !item.hideInToc)
|
|
215
|
+
.map((item: TocItem) => ({
|
|
216
|
+
...item,
|
|
217
|
+
children: filterTree(item.children, level + 1),
|
|
218
|
+
}))
|
|
219
|
+
}
|
package/logic/recording.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Ref } from 'vue'
|
|
2
2
|
import { nextTick, ref, shallowRef, watch } from 'vue'
|
|
3
|
-
import {
|
|
3
|
+
import { useDevicesList, useEventListener } from '@vueuse/core'
|
|
4
4
|
import { isTruthy } from '@antfu/utils'
|
|
5
5
|
import type RecorderType from 'recordrtc'
|
|
6
6
|
import type { Options as RecorderOptions } from 'recordrtc'
|
|
@@ -124,7 +124,7 @@ export function useRecording() {
|
|
|
124
124
|
frameRate: 15,
|
|
125
125
|
width: 3840,
|
|
126
126
|
height: 2160,
|
|
127
|
-
// @ts-expect-error
|
|
127
|
+
// @ts-expect-error missing types
|
|
128
128
|
cursor: 'motion',
|
|
129
129
|
resizeMode: 'crop-and-scale',
|
|
130
130
|
},
|
package/logic/shortcuts.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Fn, KeyFilter } from '@vueuse/core'
|
|
2
|
-
import {
|
|
2
|
+
import { and, not, onKeyStroke } from '@vueuse/core'
|
|
3
3
|
import type { Ref } from 'vue'
|
|
4
4
|
import { watch } from 'vue'
|
|
5
5
|
import type { ShortcutOptions } from '@slidev/types'
|
|
6
|
-
import { fullscreen,
|
|
6
|
+
import { fullscreen, isInputting, isOnFocus, magicKeys, shortcutsEnabled, showGotoDialog, showOverview, toggleOverview } from '../state'
|
|
7
7
|
import setupShortcuts from '../setup/shortcuts'
|
|
8
8
|
import { toggleDark } from './dark'
|
|
9
9
|
import { next, nextSlide, prev, prevSlide } from './nav'
|
package/logic/utils.ts
CHANGED
package/modules/context.ts
CHANGED
|
@@ -23,7 +23,7 @@ export default function createSlidevContext() {
|
|
|
23
23
|
// need to copy over to get rid of the "Module" object type (will not unwrap)
|
|
24
24
|
for (const key of objectKeys(nav)) {
|
|
25
25
|
if (typeof key === 'string')
|
|
26
|
-
// @ts-expect-error
|
|
26
|
+
// @ts-expect-error I know :)
|
|
27
27
|
navObj[key] = nav[key]
|
|
28
28
|
}
|
|
29
29
|
const context = reactive({
|
|
@@ -35,7 +35,7 @@ export default function createSlidevContext() {
|
|
|
35
35
|
|
|
36
36
|
// allows controls from postMessages
|
|
37
37
|
if (__DEV__) {
|
|
38
|
-
// @ts-expect-error
|
|
38
|
+
// @ts-expect-error expose global
|
|
39
39
|
window.__slidev__ = context
|
|
40
40
|
window.addEventListener('message', ({ data }) => {
|
|
41
41
|
if (data && data.target === 'slidev') {
|
package/modules/directives.ts
CHANGED
|
@@ -3,16 +3,16 @@ import { watch } from 'vue'
|
|
|
3
3
|
import { remove } from '@antfu/utils'
|
|
4
4
|
import { isClicksDisabled } from '../logic/nav'
|
|
5
5
|
import {
|
|
6
|
-
injectionClicksDisabled,
|
|
7
|
-
injectionClicksElements,
|
|
8
|
-
injectionClicks,
|
|
9
|
-
injectionOrderMap,
|
|
10
6
|
CLASS_VCLICK_CURRENT,
|
|
7
|
+
CLASS_VCLICK_FADE,
|
|
11
8
|
CLASS_VCLICK_HIDDEN,
|
|
12
9
|
CLASS_VCLICK_HIDDEN_EXP,
|
|
13
10
|
CLASS_VCLICK_PRIOR,
|
|
14
11
|
CLASS_VCLICK_TARGET,
|
|
15
|
-
|
|
12
|
+
injectionClicks,
|
|
13
|
+
injectionClicksDisabled,
|
|
14
|
+
injectionClicksElements,
|
|
15
|
+
injectionOrderMap,
|
|
16
16
|
} from '../constants'
|
|
17
17
|
|
|
18
18
|
function dirInject<T = unknown>(dir: DirectiveBinding<any>, key: InjectionKey<T> | string, defaultValue?: T): T | undefined {
|
|
@@ -23,7 +23,7 @@ export default function createDirectives() {
|
|
|
23
23
|
return {
|
|
24
24
|
install(app: App) {
|
|
25
25
|
app.directive('click', {
|
|
26
|
-
// @ts-expect-error
|
|
26
|
+
// @ts-expect-error extra prop
|
|
27
27
|
name: 'v-click',
|
|
28
28
|
|
|
29
29
|
mounted(el: HTMLElement, dir) {
|
|
@@ -109,7 +109,7 @@ export default function createDirectives() {
|
|
|
109
109
|
})
|
|
110
110
|
|
|
111
111
|
app.directive('after', {
|
|
112
|
-
// @ts-expect-error
|
|
112
|
+
// @ts-expect-error extra prop
|
|
113
113
|
name: 'v-after',
|
|
114
114
|
|
|
115
115
|
mounted(el: HTMLElement, dir) {
|
|
@@ -160,7 +160,7 @@ export default function createDirectives() {
|
|
|
160
160
|
})
|
|
161
161
|
|
|
162
162
|
app.directive('click-hide', {
|
|
163
|
-
// @ts-expect-error
|
|
163
|
+
// @ts-expect-error extra prop
|
|
164
164
|
name: 'v-click-hide',
|
|
165
165
|
|
|
166
166
|
mounted(el: HTMLElement, dir) {
|
package/modules/mermaid.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.3",
|
|
4
4
|
"description": "Presentation slides for developers",
|
|
5
5
|
"homepage": "https://sli.dev",
|
|
6
6
|
"bugs": "https://github.com/slidevjs/slidev/issues",
|
|
@@ -12,30 +12,31 @@
|
|
|
12
12
|
"funding": "https://github.com/sponsors/antfu",
|
|
13
13
|
"author": "antfu <anthonyfu117@hotmail.com>",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@antfu/utils": "^0.
|
|
16
|
-
"@slidev/parser": "0.
|
|
17
|
-
"@slidev/types": "0.
|
|
18
|
-
"@vueuse/core": "^7.
|
|
19
|
-
"@vueuse/head": "^0.7.
|
|
20
|
-
"@vueuse/motion": "^2.0.0-beta.
|
|
21
|
-
"codemirror": "^5.
|
|
15
|
+
"@antfu/utils": "^0.5.0",
|
|
16
|
+
"@slidev/parser": "0.28.3",
|
|
17
|
+
"@slidev/types": "0.28.3",
|
|
18
|
+
"@vueuse/core": "^7.6.0",
|
|
19
|
+
"@vueuse/head": "^0.7.5",
|
|
20
|
+
"@vueuse/motion": "^2.0.0-beta.9",
|
|
21
|
+
"codemirror": "^5.65.1",
|
|
22
22
|
"drauu": "^0.2.1",
|
|
23
23
|
"file-saver": "^2.0.5",
|
|
24
24
|
"js-base64": "^3.7.2",
|
|
25
25
|
"js-yaml": "^4.1.0",
|
|
26
|
-
"katex": "^0.15.
|
|
26
|
+
"katex": "^0.15.2",
|
|
27
27
|
"mermaid": "8.13.0",
|
|
28
|
-
"monaco-editor": "^0.
|
|
29
|
-
"nanoid": "^3.
|
|
28
|
+
"monaco-editor": "^0.32.1",
|
|
29
|
+
"nanoid": "^3.2.0",
|
|
30
30
|
"prettier": "^2.5.1",
|
|
31
31
|
"recordrtc": "^5.6.2",
|
|
32
|
-
"resolve": "^1.
|
|
33
|
-
"vite-plugin-windicss": "^1.
|
|
34
|
-
"vue": "^3.2.
|
|
32
|
+
"resolve": "^1.22.0",
|
|
33
|
+
"vite-plugin-windicss": "^1.7.0",
|
|
34
|
+
"vue": "^3.2.30",
|
|
35
35
|
"vue-router": "^4.0.12",
|
|
36
|
-
"windicss": "^3.3
|
|
36
|
+
"windicss": "^3.4.3"
|
|
37
37
|
},
|
|
38
38
|
"engines": {
|
|
39
39
|
"node": ">=14.0.0"
|
|
40
|
-
}
|
|
40
|
+
},
|
|
41
|
+
"readme": "# @slidev/client\n\n[](https://www.npmjs.com/package/@slidev/client)\n\nClient code for [Slidev](https://sli.dev). Shipped with [`@slidev/cli`](https://www.npmjs.com/package/@slidev/cli).\n\n## License\n\nMIT License © 2021 [Anthony Fu](https://github.com/antfu)\n\n"
|
|
41
42
|
}
|
package/routes.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RouteRecordRaw } from 'vue-router'
|
|
2
|
-
import { createRouter,
|
|
2
|
+
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
|
|
3
3
|
import Play from './internals/Play.vue'
|
|
4
|
-
// @ts-expect-error
|
|
4
|
+
// @ts-expect-error missing types
|
|
5
5
|
import _rawRoutes from '/@slidev/routes'
|
|
6
6
|
|
|
7
7
|
export const rawRoutes = _rawRoutes as RouteRecordRaw[]
|
|
@@ -51,6 +51,8 @@ declare module 'vue-router' {
|
|
|
51
51
|
id: number
|
|
52
52
|
no: number
|
|
53
53
|
filepath: string
|
|
54
|
+
title?: string
|
|
55
|
+
level?: number
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
// private fields
|
package/setup/main.ts
CHANGED
|
@@ -14,7 +14,7 @@ export default function setupMain(context: AppContext) {
|
|
|
14
14
|
|
|
15
15
|
context.app.use(MotionPlugin)
|
|
16
16
|
|
|
17
|
-
// @ts-expect-error
|
|
17
|
+
// @ts-expect-error inject in runtime
|
|
18
18
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
19
19
|
const injection_arg = context
|
|
20
20
|
|
package/setup/monaco.ts
CHANGED
|
@@ -31,7 +31,7 @@ const setup = createSingletonPromise(async() => {
|
|
|
31
31
|
import('monaco-editor/esm/vs/language/typescript/ts.worker?worker'),
|
|
32
32
|
])
|
|
33
33
|
|
|
34
|
-
// @ts-expect-error
|
|
34
|
+
// @ts-expect-error global config for monaca
|
|
35
35
|
window.MonacoEnvironment = {
|
|
36
36
|
getWorker(_: any, label: string) {
|
|
37
37
|
if (label === 'json')
|
|
@@ -48,7 +48,7 @@ const setup = createSingletonPromise(async() => {
|
|
|
48
48
|
})(),
|
|
49
49
|
])
|
|
50
50
|
|
|
51
|
-
// @ts-expect-error
|
|
51
|
+
// @ts-expect-error injected in runtime
|
|
52
52
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
53
53
|
const injection_arg = monaco
|
|
54
54
|
// eslint-disable-next-line prefer-const
|
package/setup/prettier.ts
CHANGED
|
@@ -11,23 +11,23 @@ export async function formatCode(code: string, lang: string) {
|
|
|
11
11
|
case 'typescript':
|
|
12
12
|
parser = 'typescript'
|
|
13
13
|
plugins = [
|
|
14
|
-
// @ts-expect-error
|
|
14
|
+
// @ts-expect-error missing types
|
|
15
15
|
(await import('prettier/esm/parser-babel')).default,
|
|
16
|
-
// @ts-expect-error
|
|
16
|
+
// @ts-expect-error missing types
|
|
17
17
|
(await import('prettier/esm/parser-typescript')).default,
|
|
18
18
|
]
|
|
19
19
|
break
|
|
20
20
|
case 'html':
|
|
21
21
|
parser = 'html'
|
|
22
22
|
plugins = [
|
|
23
|
-
// @ts-expect-error
|
|
23
|
+
// @ts-expect-error missing types
|
|
24
24
|
(await import('prettier/esm/parser-html')).default,
|
|
25
25
|
]
|
|
26
26
|
break
|
|
27
27
|
default:
|
|
28
28
|
parser = 'babel'
|
|
29
29
|
plugins = [
|
|
30
|
-
// @ts-expect-error
|
|
30
|
+
// @ts-expect-error missing types
|
|
31
31
|
(await import('prettier/esm/parser-babel')).default,
|
|
32
32
|
]
|
|
33
33
|
}
|
|
@@ -42,7 +42,6 @@ export async function formatCode(code: string, lang: string) {
|
|
|
42
42
|
})
|
|
43
43
|
}
|
|
44
44
|
catch (e) {
|
|
45
|
-
// eslint-disable-next-line no-console
|
|
46
45
|
console.error(e)
|
|
47
46
|
return code
|
|
48
47
|
}
|
package/setup/root.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* __imports__ */
|
|
2
2
|
import { useHead } from '@vueuse/head'
|
|
3
3
|
import { watch } from 'vue'
|
|
4
|
-
import { currentPage, getPath,
|
|
4
|
+
import { clicks, currentPage, getPath, isPresenter } from '../logic/nav'
|
|
5
5
|
import { router } from '../routes'
|
|
6
6
|
import { configs, serverState } from '../env'
|
|
7
7
|
|
|
8
8
|
export default function setupRoot() {
|
|
9
|
-
// @ts-expect-error
|
|
9
|
+
// @ts-expect-error injected in runtime
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
11
|
const injection_arg = undefined
|
|
12
12
|
|
package/setup/shortcuts.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/* __imports__ */
|
|
2
2
|
|
|
3
|
-
import type {
|
|
4
|
-
import {
|
|
3
|
+
import type { NavOperations, ShortcutOptions } from '@slidev/types'
|
|
4
|
+
import { downloadPDF, next, nextSlide, prev, prevSlide } from '../logic/nav'
|
|
5
5
|
import { toggleDark } from '../logic/dark'
|
|
6
|
-
import {
|
|
6
|
+
import { showGotoDialog, showOverview, toggleOverview } from '../state'
|
|
7
7
|
import { drawingEnabled } from '../logic/drawings'
|
|
8
8
|
|
|
9
9
|
export default function setupShortcuts() {
|
|
10
|
-
// @ts-expect-error
|
|
10
|
+
// @ts-expect-error injected in runtime
|
|
11
11
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
12
12
|
const injection_arg: NavOperations = {
|
|
13
13
|
next,
|
package/state/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { breakpointsTailwind, isClient, useActiveElement, useBreakpoints, useFullscreen, useMagicKeys, useStorage, useToggle, useWindowSize } from '@vueuse/core'
|
|
2
2
|
import { computed, ref } from 'vue'
|
|
3
3
|
import { slideAspect } from '../env'
|
|
4
4
|
|