@slidev/client 52.15.2 → 52.16.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/KaTexBlockWrapper.test.ts +41 -0
- package/builtin/KaTexBlockWrapper.vue +4 -19
- package/builtin/ShikiMagicMove.vue +2 -2
- package/builtin/TocList.vue +1 -1
- package/builtin/katex-lines.ts +22 -0
- package/composables/useEmbeddedCtrl.ts +4 -2
- package/composables/useNav.ts +1 -1
- package/composables/usePreloadImages.ts +1 -1
- package/env.ts +1 -1
- package/internals/ClicksSlider.vue +99 -48
- package/internals/CodeRunner.vue +2 -2
- package/internals/Goto.vue +2 -2
- package/internals/NavControls.vue +1 -1
- package/internals/NoteDisplay.vue +5 -0
- package/internals/NoteEditable.vue +2 -3
- package/internals/PrintSlideClick.vue +1 -1
- package/internals/SideEditor.vue +2 -7
- package/internals/SlideWrapper.vue +1 -1
- package/internals/SlidesShow.vue +1 -1
- package/logic/sideEditor.ts +14 -0
- package/logic/slides.ts +3 -2
- package/modules/mermaid.ts +1 -1
- package/package.json +25 -25
- package/pages/overview.vue +293 -64
- package/pages/presenter.vue +1 -4
- package/setup/code-runners.ts +2 -2
- package/setup/context-menu.ts +1 -1
- package/setup/main.ts +1 -1
- package/setup/mermaid.ts +1 -1
- package/setup/monaco.ts +4 -4
- package/setup/root.ts +1 -1
- package/setup/shiki.ts +1 -1
- package/setup/shortcuts.ts +1 -1
- package/shim-vue.d.ts +1 -0
- package/styles/index.ts +1 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { collectKatexEquationLines } from './katex-lines'
|
|
3
|
+
|
|
4
|
+
function fakeElement(options: {
|
|
5
|
+
parent?: Element | null
|
|
6
|
+
closest?: Element | null
|
|
7
|
+
children?: Element[]
|
|
8
|
+
} = {}) {
|
|
9
|
+
const el = {
|
|
10
|
+
parentElement: options.parent ?? null,
|
|
11
|
+
closest: () => options.closest ?? null,
|
|
12
|
+
querySelectorAll: () => options.children ?? [],
|
|
13
|
+
}
|
|
14
|
+
return el as unknown as Element
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('collectKatexEquationLines', () => {
|
|
18
|
+
it('ignores nested KaTeX tables when mapping equation lines', () => {
|
|
19
|
+
const rowA1 = fakeElement()
|
|
20
|
+
const rowA2 = fakeElement()
|
|
21
|
+
const rowB1 = fakeElement()
|
|
22
|
+
const rowB2 = fakeElement()
|
|
23
|
+
const nestedRow = fakeElement()
|
|
24
|
+
|
|
25
|
+
const outerLeftParent = fakeElement({ children: [rowA1, rowA2] })
|
|
26
|
+
const outerRightParent = fakeElement({ children: [rowB1, rowB2] })
|
|
27
|
+
const nestedParent = fakeElement({
|
|
28
|
+
parent: fakeElement({ closest: outerLeftParent }),
|
|
29
|
+
children: [nestedRow],
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
const root = fakeElement({
|
|
33
|
+
children: [outerLeftParent, nestedParent, outerRightParent],
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
expect(collectKatexEquationLines(root)).toEqual([
|
|
37
|
+
[rowA1, rowB1],
|
|
38
|
+
[rowA2, rowB2],
|
|
39
|
+
])
|
|
40
|
+
})
|
|
41
|
+
})
|
|
@@ -26,6 +26,7 @@ import { computed, onMounted, onUnmounted, ref, watchEffect } from 'vue'
|
|
|
26
26
|
import { CLASS_VCLICK_HIDDEN, CLASS_VCLICK_TARGET, CLICKS_MAX } from '../constants'
|
|
27
27
|
import { useSlideContext } from '../context'
|
|
28
28
|
import { makeId } from '../logic/utils'
|
|
29
|
+
import { collectKatexEquationLines } from './katex-lines'
|
|
29
30
|
|
|
30
31
|
const props = defineProps({
|
|
31
32
|
ranges: {
|
|
@@ -77,26 +78,10 @@ onMounted(() => {
|
|
|
77
78
|
if (hide)
|
|
78
79
|
rangeStr = props.ranges[index.value + 1] ?? finallyRange.value
|
|
79
80
|
|
|
80
|
-
// KaTeX equations have col-align-XXX as parent
|
|
81
|
-
const equationParents = el.value.querySelectorAll('.mtable > [class*=col-align]')
|
|
82
|
-
if (!equationParents)
|
|
83
|
-
return
|
|
84
|
-
|
|
85
|
-
// For each row we extract the individual equation rows
|
|
86
|
-
const equationRowsOfEachParent = Array.from(equationParents)
|
|
87
|
-
.map(item => Array.from(item.querySelectorAll(':scope > .vlist-t > .vlist-r > .vlist > span > .mord')))
|
|
88
81
|
// This list maps rows from different parents to line them up
|
|
89
|
-
const lines
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (!equationRow)
|
|
93
|
-
return
|
|
94
|
-
if (Array.isArray(lines[idx]))
|
|
95
|
-
lines[idx].push(equationRow)
|
|
96
|
-
else
|
|
97
|
-
lines[idx] = [equationRow]
|
|
98
|
-
})
|
|
99
|
-
}
|
|
82
|
+
const lines = collectKatexEquationLines(el.value)
|
|
83
|
+
if (!lines.length)
|
|
84
|
+
return
|
|
100
85
|
|
|
101
86
|
const startLine = props.startLine
|
|
102
87
|
const highlights: number[] = parseRangeString(lines.length + startLine - 1, rangeStr)
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type { KeyedTokensInfo } from '
|
|
2
|
+
import type { KeyedTokensInfo } from '@shikijs/magic-move/types'
|
|
3
3
|
import type { PropType } from 'vue'
|
|
4
4
|
import { sleep } from '@antfu/utils'
|
|
5
|
+
import { ShikiMagicMovePrecompiled } from '@shikijs/magic-move/vue'
|
|
5
6
|
import { useClipboard } from '@vueuse/core'
|
|
6
7
|
import lz from 'lz-string'
|
|
7
|
-
import { ShikiMagicMovePrecompiled } from 'shiki-magic-move/vue'
|
|
8
8
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
9
9
|
import { useNav } from '../composables/useNav'
|
|
10
10
|
import { CLICKS_MAX } from '../constants'
|
package/builtin/TocList.vue
CHANGED
|
@@ -8,9 +8,9 @@ Usage:
|
|
|
8
8
|
-->
|
|
9
9
|
<script setup lang="ts">
|
|
10
10
|
import type { TocItem } from '@slidev/types'
|
|
11
|
-
import TitleRenderer from '#slidev/title-renderer'
|
|
12
11
|
import { toArray } from '@antfu/utils'
|
|
13
12
|
import { computed } from 'vue'
|
|
13
|
+
import TitleRenderer from '#slidev/title-renderer'
|
|
14
14
|
import { useNav } from '../composables/useNav'
|
|
15
15
|
|
|
16
16
|
const props = withDefaults(
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const KATEX_EQUATION_PARENT_SELECTOR = '.mtable > [class*=col-align]'
|
|
2
|
+
const KATEX_EQUATION_ROW_SELECTOR = ':scope > .vlist-t > .vlist-r > .vlist > span > .mord'
|
|
3
|
+
|
|
4
|
+
export function collectKatexEquationLines(el: Element): Element[][] {
|
|
5
|
+
const equationParents = Array.from(el.querySelectorAll(KATEX_EQUATION_PARENT_SELECTOR))
|
|
6
|
+
.filter(parent => !parent.parentElement?.closest(KATEX_EQUATION_PARENT_SELECTOR))
|
|
7
|
+
|
|
8
|
+
const lines: Element[][] = []
|
|
9
|
+
for (const equationRowParent of equationParents) {
|
|
10
|
+
const equationRows = Array.from(equationRowParent.querySelectorAll(KATEX_EQUATION_ROW_SELECTOR))
|
|
11
|
+
equationRows.forEach((equationRow, idx) => {
|
|
12
|
+
if (!equationRow)
|
|
13
|
+
return
|
|
14
|
+
if (Array.isArray(lines[idx]))
|
|
15
|
+
lines[idx].push(equationRow)
|
|
16
|
+
else
|
|
17
|
+
lines[idx] = [equationRow]
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return lines
|
|
22
|
+
}
|
|
@@ -31,8 +31,10 @@ export function useEmbeddedControl() {
|
|
|
31
31
|
|
|
32
32
|
if (nav.isEmbedded.value) {
|
|
33
33
|
throttledWatch(
|
|
34
|
-
[nav.currentSlideNo, nav.clicks, nav.hasNext, nav.hasPrev],
|
|
35
|
-
([no, clicks, hasNext, hasPrev]) => {
|
|
34
|
+
[nav.currentSlideNo, nav.clicks, nav.hasNext, nav.hasPrev, nav.hasPrimarySlide],
|
|
35
|
+
([no, clicks, hasNext, hasPrev, hasPrimarySlide]) => {
|
|
36
|
+
if (!hasPrimarySlide)
|
|
37
|
+
return
|
|
36
38
|
window.parent.postMessage(
|
|
37
39
|
{
|
|
38
40
|
target: 'slidev',
|
package/composables/useNav.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ClicksContext, SlideRoute, TocItem } from '@slidev/types'
|
|
2
2
|
import type { ComputedRef, Ref, TransitionGroupProps, WritableComputedRef } from 'vue'
|
|
3
3
|
import type { RouteLocationNormalized, Router } from 'vue-router'
|
|
4
|
-
import { slides } from '#slidev/slides'
|
|
5
4
|
import { clamp } from '@antfu/utils'
|
|
6
5
|
import { parseRangeString } from '@slidev/parser/utils'
|
|
7
6
|
import { createSharedComposable } from '@vueuse/core'
|
|
8
7
|
import { computed, ref, watch } from 'vue'
|
|
9
8
|
import { useRoute, useRouter } from 'vue-router'
|
|
9
|
+
import { slides } from '#slidev/slides'
|
|
10
10
|
import { CLICKS_MAX } from '../constants'
|
|
11
11
|
import { configs } from '../env'
|
|
12
12
|
import { useRouteQuery } from '../logic/route'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SlideRoute } from '@slidev/types'
|
|
2
2
|
import type { ComputedRef, Ref } from 'vue'
|
|
3
|
-
import configs from '#slidev/configs'
|
|
4
3
|
import { watchEffect } from 'vue'
|
|
4
|
+
import configs from '#slidev/configs'
|
|
5
5
|
|
|
6
6
|
const loaded = new Set<string>()
|
|
7
7
|
const loading = new Set<string>()
|
package/env.ts
CHANGED
|
@@ -1,70 +1,146 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { ClicksContext } from '@slidev/types'
|
|
3
3
|
import { clamp, range } from '@antfu/utils'
|
|
4
|
-
import { computed } from 'vue'
|
|
4
|
+
import { computed, ref } from 'vue'
|
|
5
5
|
import { CLICKS_MAX } from '../constants'
|
|
6
6
|
|
|
7
7
|
const props = withDefaults(defineProps<{
|
|
8
8
|
clicksContext: ClicksContext
|
|
9
9
|
readonly?: boolean
|
|
10
10
|
active?: boolean
|
|
11
|
+
resettable?: boolean
|
|
12
|
+
compact?: boolean
|
|
13
|
+
attached?: boolean
|
|
11
14
|
}>(), {
|
|
12
15
|
active: true,
|
|
13
16
|
})
|
|
14
17
|
|
|
18
|
+
const emit = defineEmits<{
|
|
19
|
+
(type: 'activate'): void
|
|
20
|
+
(type: 'reset'): void
|
|
21
|
+
}>()
|
|
22
|
+
|
|
15
23
|
const total = computed(() => props.clicksContext.total)
|
|
16
24
|
const start = computed(() => clamp(0, props.clicksContext.clicksStart, total.value))
|
|
17
25
|
const length = computed(() => total.value - start.value + 1)
|
|
18
26
|
const current = computed({
|
|
19
27
|
get() {
|
|
28
|
+
if (props.resettable && !props.active)
|
|
29
|
+
return -1
|
|
20
30
|
return props.clicksContext.current > total.value ? -1 : props.clicksContext.current
|
|
21
31
|
},
|
|
22
32
|
set(value: number) {
|
|
33
|
+
if (props.resettable && value < 0) {
|
|
34
|
+
emit('reset')
|
|
35
|
+
// eslint-disable-next-line vue/no-mutating-props
|
|
36
|
+
props.clicksContext.current = CLICKS_MAX
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
emit('activate')
|
|
23
40
|
// eslint-disable-next-line vue/no-mutating-props
|
|
24
41
|
props.clicksContext.current = value
|
|
25
42
|
},
|
|
26
43
|
})
|
|
27
44
|
|
|
45
|
+
const isReset = computed(() => props.resettable && current.value < 0)
|
|
28
46
|
const clicksRange = computed(() => range(start.value, total.value + 1))
|
|
47
|
+
const sliderEl = ref<HTMLElement>()
|
|
48
|
+
let pointerDown: { id: number, x: number, y: number } | undefined
|
|
49
|
+
|
|
50
|
+
function getPointerRatio(event: PointerEvent) {
|
|
51
|
+
const rect = sliderEl.value!.getBoundingClientRect()
|
|
52
|
+
return (event.clientX - rect.left) / Math.max(1, rect.width)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Presses snap to a cell; drags switch only after crossing half a cell.
|
|
56
|
+
function setCurrentFromPointer(event: PointerEvent, snap: boolean) {
|
|
57
|
+
if (props.readonly || !sliderEl.value || (!snap && !(event.buttons & 1)))
|
|
58
|
+
return
|
|
59
|
+
const ratio = getPointerRatio(event)
|
|
60
|
+
// In resettable mode, dragging left of the rail restores the inactive state.
|
|
61
|
+
if (props.resettable && ratio < 0) {
|
|
62
|
+
current.value = -1
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
// Keep press-at-right-edge inside the last cell.
|
|
66
|
+
const position = clamp(0, ratio, snap ? 0.999999 : 1) * length.value
|
|
67
|
+
const currentOffset = clamp(0, current.value - start.value, length.value - 1)
|
|
68
|
+
let next = snap ? start.value + Math.floor(position) : current.value
|
|
69
|
+
if (!snap && position >= currentOffset + 1.5)
|
|
70
|
+
next = start.value + Math.floor(position - 0.5)
|
|
71
|
+
else if (!snap && position < currentOffset - 0.5)
|
|
72
|
+
next = start.value + Math.ceil(position - 0.5)
|
|
73
|
+
current.value = clamp(start.value, next, total.value)
|
|
74
|
+
}
|
|
29
75
|
|
|
30
|
-
function
|
|
76
|
+
function onPointerDown(event: PointerEvent) {
|
|
31
77
|
if (props.readonly)
|
|
32
78
|
return
|
|
33
|
-
|
|
34
|
-
|
|
79
|
+
sliderEl.value?.setPointerCapture(event.pointerId)
|
|
80
|
+
pointerDown = { id: event.pointerId, x: event.clientX, y: event.clientY }
|
|
81
|
+
setCurrentFromPointer(event, true)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function onPointerMove(event: PointerEvent) {
|
|
85
|
+
if (pointerDown?.id === event.pointerId) {
|
|
86
|
+
// Treat tiny movement after pointerdown as part of the click.
|
|
87
|
+
if (Math.abs(event.clientX - pointerDown.x) <= 3 && Math.abs(event.clientY - pointerDown.y) <= 3)
|
|
88
|
+
return
|
|
89
|
+
pointerDown = undefined
|
|
90
|
+
}
|
|
91
|
+
setCurrentFromPointer(event, false)
|
|
35
92
|
}
|
|
36
93
|
</script>
|
|
37
94
|
|
|
38
95
|
<template>
|
|
39
96
|
<div
|
|
40
|
-
class="flex gap-1
|
|
97
|
+
class="flex gap-1 select-none"
|
|
41
98
|
:title="`Clicks in this slide: ${length}`"
|
|
42
|
-
:class="length && props.clicksContext.isMounted ? '' : 'op50'"
|
|
99
|
+
:class="[attached ? 'items-end' : 'items-center', length && props.clicksContext.isMounted ? '' : 'op50']"
|
|
43
100
|
>
|
|
44
|
-
<div
|
|
45
|
-
|
|
101
|
+
<div
|
|
102
|
+
class="flex items-center font-mono"
|
|
103
|
+
:class="[compact ? 'gap-1 min-w-0 mr0' : 'gap-0.2 min-w-16 mr1', attached ? 'h-[22px]' : '']"
|
|
104
|
+
>
|
|
105
|
+
<div class="i-carbon:cursor-1 text-sm op50" :class="compact ? 'ml-1' : ''" />
|
|
46
106
|
<template v-if="current >= 0 && current !== CLICKS_MAX && active">
|
|
47
|
-
<div flex-auto />
|
|
48
|
-
<span
|
|
49
|
-
|
|
50
|
-
|
|
107
|
+
<div v-if="!compact" flex-auto />
|
|
108
|
+
<span>
|
|
109
|
+
<span text-primary>{{ current }}</span>
|
|
110
|
+
<span op25 text-sm>/</span>
|
|
111
|
+
<span op50 text-sm>{{ total }}</span>
|
|
112
|
+
</span>
|
|
51
113
|
</template>
|
|
52
114
|
<div
|
|
53
115
|
v-else
|
|
54
|
-
op50
|
|
116
|
+
op50
|
|
117
|
+
:class="compact ? '' : 'flex-auto pl1'"
|
|
55
118
|
>
|
|
56
|
-
|
|
119
|
+
<span
|
|
120
|
+
:class="compact ? 'inline-block text-center' : ''"
|
|
121
|
+
:style="compact ? { width: `${String(total).length * 2 + 1}ch`, marginLeft: '-0.25ch' } : undefined"
|
|
122
|
+
>{{ total }}</span>
|
|
57
123
|
</div>
|
|
58
124
|
</div>
|
|
59
125
|
<div
|
|
60
|
-
|
|
126
|
+
ref="sliderEl"
|
|
127
|
+
relative flex-auto font-mono flex="~"
|
|
128
|
+
touch-none
|
|
129
|
+
:class="[attached ? 'h-[22px]' : 'h5', isReset ? 'op80' : '']"
|
|
130
|
+
@pointerdown.capture="onPointerDown"
|
|
131
|
+
@pointermove="onPointerMove"
|
|
132
|
+
@pointerup="pointerDown = undefined"
|
|
133
|
+
@pointercancel="pointerDown = undefined"
|
|
61
134
|
>
|
|
62
135
|
<div
|
|
63
136
|
v-for="i of clicksRange" :key="i"
|
|
64
137
|
border="y main" of-hidden relative
|
|
65
138
|
:class="[
|
|
66
|
-
i === 0 ? '
|
|
67
|
-
i ===
|
|
139
|
+
i === 0 ? 'border-l' : '',
|
|
140
|
+
i === 0 ? attached ? 'rounded-tl' : 'rounded-l' : '',
|
|
141
|
+
i === total ? 'border-r' : '',
|
|
142
|
+
i === total && +i !== +current ? attached ? 'rounded-tr' : 'rounded-r' : '',
|
|
143
|
+
attached ? 'border-b-0' : '',
|
|
68
144
|
]"
|
|
69
145
|
:style="{ width: length > 0 ? `${1 / length * 100}%` : '100%' }"
|
|
70
146
|
>
|
|
@@ -72,45 +148,20 @@ function onMousedown() {
|
|
|
72
148
|
absolute inset-0
|
|
73
149
|
:class="(i <= current && active) ? 'bg-primary op15' : ''"
|
|
74
150
|
/>
|
|
151
|
+
<div
|
|
152
|
+
v-if="+i === +current && active"
|
|
153
|
+
absolute inset-y-0 right-0 w-0.5 bg-primary z-1
|
|
154
|
+
/>
|
|
75
155
|
<div
|
|
76
156
|
:class="[
|
|
77
|
-
(+i === +current && active) ? 'text-primary font-bold op100
|
|
78
|
-
i
|
|
79
|
-
i === total ? 'rounded-r' : 'border-r-2',
|
|
157
|
+
(+i === +current && active) ? 'text-primary font-bold op100' : 'op30',
|
|
158
|
+
i !== total ? 'border-r-2 border-main' : '',
|
|
80
159
|
]"
|
|
81
160
|
w-full h-full text-xs flex items-center justify-center z-1
|
|
82
161
|
>
|
|
83
162
|
{{ i }}
|
|
84
163
|
</div>
|
|
85
164
|
</div>
|
|
86
|
-
<input
|
|
87
|
-
v-model="current"
|
|
88
|
-
class="range"
|
|
89
|
-
type="range" :min="start" :max="total" :step="1"
|
|
90
|
-
absolute inset-0 z-label op0
|
|
91
|
-
:class="readonly ? 'pointer-events-none' : ''"
|
|
92
|
-
:style="{ '--thumb-width': `${1 / (length + 1) * 100}%` }"
|
|
93
|
-
@mousedown="onMousedown"
|
|
94
|
-
@focus="event => (event.currentTarget as HTMLElement)?.blur()"
|
|
95
|
-
>
|
|
96
165
|
</div>
|
|
97
166
|
</div>
|
|
98
167
|
</template>
|
|
99
|
-
|
|
100
|
-
<style scoped>
|
|
101
|
-
.range {
|
|
102
|
-
-webkit-appearance: none;
|
|
103
|
-
appearance: none;
|
|
104
|
-
background: transparent;
|
|
105
|
-
}
|
|
106
|
-
.range::-webkit-slider-thumb {
|
|
107
|
-
-webkit-appearance: none;
|
|
108
|
-
height: 100%;
|
|
109
|
-
width: var(--thumb-width, 0.5rem);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.range::-moz-range-thumb {
|
|
113
|
-
height: 100%;
|
|
114
|
-
width: var(--thumb-width, 0.5rem);
|
|
115
|
-
}
|
|
116
|
-
</style>
|
package/internals/CodeRunner.vue
CHANGED
|
@@ -22,12 +22,12 @@ const props = defineProps<{
|
|
|
22
22
|
|
|
23
23
|
const emit = defineEmits(['update:modelValue'])
|
|
24
24
|
|
|
25
|
-
const { isPrintMode } = useNav()
|
|
25
|
+
const { isEmbedded, isPrintMode } = useNav()
|
|
26
26
|
|
|
27
27
|
const code = useVModel(props, 'modelValue', emit)
|
|
28
28
|
|
|
29
29
|
const { $renderContext, $clicksContext } = useSlideContext()
|
|
30
|
-
const disabled = computed(() => !['slide', 'presenter'].includes($renderContext.value))
|
|
30
|
+
const disabled = computed(() => !['slide', 'presenter'].includes($renderContext.value) && !($renderContext.value === 'overview' && isEmbedded.value))
|
|
31
31
|
|
|
32
32
|
const autorun = isPrintMode.value ? 'once' : props.autorun
|
|
33
33
|
const isRunning = ref(autorun)
|
package/internals/Goto.vue
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import TitleRenderer from '#slidev/title-renderer'
|
|
3
2
|
import Fuse from 'fuse.js'
|
|
4
3
|
import { computed, ref, watch } from 'vue'
|
|
4
|
+
import TitleRenderer from '#slidev/title-renderer'
|
|
5
5
|
import { useNav } from '../composables/useNav'
|
|
6
6
|
import { activeElement, showGotoDialog } from '../state'
|
|
7
7
|
|
|
@@ -136,7 +136,7 @@ watch(activeElement, () => {
|
|
|
136
136
|
>
|
|
137
137
|
</div>
|
|
138
138
|
<div
|
|
139
|
-
v-if="result.length > 0"
|
|
139
|
+
v-if="showGotoDialog && result.length > 0"
|
|
140
140
|
ref="list"
|
|
141
141
|
class="autocomplete-list"
|
|
142
142
|
shadow="~"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import CustomNavControls from '#slidev/custom-nav-controls'
|
|
3
2
|
import { computed, ref, shallowRef } from 'vue'
|
|
3
|
+
import CustomNavControls from '#slidev/custom-nav-controls'
|
|
4
4
|
import { useDrawings } from '../composables/useDrawings'
|
|
5
5
|
import { useNav } from '../composables/useNav'
|
|
6
6
|
import { configs } from '../env'
|
|
@@ -131,10 +131,9 @@ watch(
|
|
|
131
131
|
v-else
|
|
132
132
|
ref="inputEl"
|
|
133
133
|
v-model="note"
|
|
134
|
-
class="prose dark:prose-invert resize-none overflow-auto outline-none bg-transparent block border-primary border-2"
|
|
135
|
-
style="line-height: 1.75;"
|
|
134
|
+
class="prose dark:prose-invert resize-none overflow-auto outline-none bg-transparent block border-primary border-2 slidev-note placeholder:op25"
|
|
136
135
|
:style="[props.style, inputHeight != null ? { height: `${inputHeight}px` } : {}]"
|
|
137
|
-
:class="props.class"
|
|
136
|
+
:class="[props.class, note ? '' : 'italic']"
|
|
138
137
|
:placeholder="placeholder"
|
|
139
138
|
@keydown.esc="editing = false"
|
|
140
139
|
@keydown="onKeyDown"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { SlidevContextNav } from '../composables/useNav'
|
|
3
|
-
import { GlobalBottom, GlobalTop } from '#slidev/global-layers'
|
|
4
3
|
import { provideLocal } from '@vueuse/core'
|
|
5
4
|
import { computed, reactive, shallowRef, useTemplateRef } from 'vue'
|
|
5
|
+
import { GlobalBottom, GlobalTop } from '#slidev/global-layers'
|
|
6
6
|
import { injectionSlideElement, injectionSlidevContext } from '../constants'
|
|
7
7
|
import { configs, slideHeight, slideWidth } from '../env'
|
|
8
8
|
import { getSlideClass } from '../utils'
|
package/internals/SideEditor.vue
CHANGED
|
@@ -3,6 +3,7 @@ import { throttledWatch, useEventListener } from '@vueuse/core'
|
|
|
3
3
|
import { computed, ref, watch } from 'vue'
|
|
4
4
|
import { useNav } from '../composables/useNav'
|
|
5
5
|
import { useDynamicSlideInfo } from '../composables/useSlideInfo'
|
|
6
|
+
import { parseSideEditorContent } from '../logic/sideEditor'
|
|
6
7
|
import { activeElement, editorHeight, editorWidth, isInputting, showEditor, isEditorVertical as vertical } from '../state'
|
|
7
8
|
import IconButton from './IconButton.vue'
|
|
8
9
|
import ShikiEditor from './ShikiEditor.vue'
|
|
@@ -11,8 +12,6 @@ const props = defineProps<{
|
|
|
11
12
|
resize?: boolean
|
|
12
13
|
}>()
|
|
13
14
|
|
|
14
|
-
const RE_FRONTMATTER_BLOCK = /^---\n([\s\S]*?)\n---\n/
|
|
15
|
-
|
|
16
15
|
const { currentSlideNo, openInEditor } = useNav()
|
|
17
16
|
|
|
18
17
|
const tab = ref<'content' | 'note'>('content')
|
|
@@ -38,11 +37,7 @@ watch(
|
|
|
38
37
|
async function save() {
|
|
39
38
|
dirty.value = false
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
const contentOnly = content.value.trim().replace(RE_FRONTMATTER_BLOCK, (_, f) => {
|
|
43
|
-
frontmatterRaw = f
|
|
44
|
-
return ''
|
|
45
|
-
})
|
|
40
|
+
const { content: contentOnly, frontmatterRaw } = parseSideEditorContent(content.value)
|
|
46
41
|
|
|
47
42
|
await update({
|
|
48
43
|
note: note.value || undefined,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { ClicksContext, RenderContext, SlideRoute } from '@slidev/types'
|
|
3
3
|
import type { CSSProperties, PropType } from 'vue'
|
|
4
|
-
import { SlideBottom, SlideTop } from '#slidev/global-layers'
|
|
5
4
|
import { provideLocal } from '@vueuse/core'
|
|
6
5
|
import { computed, ref, toRef } from 'vue'
|
|
6
|
+
import { SlideBottom, SlideTop } from '#slidev/global-layers'
|
|
7
7
|
import { injectionClicksContext, injectionCurrentPage, injectionFrontmatter, injectionRenderContext, injectionRoute, injectionSlideZoom } from '../constants'
|
|
8
8
|
import { configs } from '../env'
|
|
9
9
|
import { getSlideClass } from '../utils'
|
package/internals/SlidesShow.vue
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { SlideRoute } from '@slidev/types'
|
|
3
|
-
import { GlobalBottom, GlobalTop } from '#slidev/global-layers'
|
|
4
3
|
import { recomputeAllPoppers } from 'floating-vue'
|
|
5
4
|
import { computed, shallowRef, TransitionGroup, watchEffect } from 'vue'
|
|
5
|
+
import { GlobalBottom, GlobalTop } from '#slidev/global-layers'
|
|
6
6
|
import { createFixedClicks } from '../composables/useClicks'
|
|
7
7
|
import { useNav } from '../composables/useNav'
|
|
8
8
|
import { usePreloadImages } from '../composables/usePreloadImages'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const RE_FRONTMATTER_BLOCK = /^---\n([\s\S]*?)\n---(?:\n|$)/
|
|
2
|
+
|
|
3
|
+
export function parseSideEditorContent(content: string) {
|
|
4
|
+
let frontmatterRaw: string | undefined
|
|
5
|
+
const contentOnly = content.trim().replace(RE_FRONTMATTER_BLOCK, (_, f) => {
|
|
6
|
+
frontmatterRaw = f
|
|
7
|
+
return ''
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
content: contentOnly,
|
|
12
|
+
frontmatterRaw,
|
|
13
|
+
}
|
|
14
|
+
}
|
package/logic/slides.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SlideRoute } from '@slidev/types'
|
|
2
|
-
import { slides } from '#slidev/slides'
|
|
3
2
|
import { tryOnMounted } from '@vueuse/core'
|
|
4
3
|
import { computed, watch } from 'vue'
|
|
4
|
+
import { slides } from '#slidev/slides'
|
|
5
5
|
import { useSlideContext } from '../context'
|
|
6
6
|
|
|
7
7
|
export { slides }
|
|
@@ -20,7 +20,8 @@ export function getSlidePath(
|
|
|
20
20
|
if (typeof route === 'number' || typeof route === 'string')
|
|
21
21
|
route = getSlide(route)!
|
|
22
22
|
const no = route.meta.slide?.frontmatter.routeAlias ?? route.no
|
|
23
|
-
|
|
23
|
+
const path = exporting ? `export/${no}` : presenter ? `presenter/${no}` : `${no}`
|
|
24
|
+
return `${import.meta.env.BASE_URL}${path}`
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export function useIsSlideActive() {
|
package/modules/mermaid.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import mermaidRenderers from '#slidev/setups/mermaid-renderer'
|
|
2
1
|
import { clearUndefined } from '@antfu/utils'
|
|
3
2
|
import lz from 'lz-string'
|
|
4
3
|
import mermaid from 'mermaid/dist/mermaid.esm.mjs'
|
|
4
|
+
import mermaidRenderers from '#slidev/setups/mermaid-renderer'
|
|
5
5
|
import { makeId } from '../logic/utils'
|
|
6
6
|
import setupMermaid from '../setup/mermaid'
|
|
7
7
|
|
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.16.0",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -30,44 +30,44 @@
|
|
|
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.22",
|
|
34
34
|
"@iconify-json/ph": "^1.2.2",
|
|
35
35
|
"@iconify-json/svg-spinners": "^1.2.4",
|
|
36
|
-
"@shikijs/engine-javascript": "^4.0
|
|
37
|
-
"@shikijs/
|
|
38
|
-
"@shikijs/
|
|
36
|
+
"@shikijs/engine-javascript": "^4.2.0",
|
|
37
|
+
"@shikijs/magic-move": "^4.2.0",
|
|
38
|
+
"@shikijs/monaco": "^4.2.0",
|
|
39
|
+
"@shikijs/vitepress-twoslash": "^4.2.0",
|
|
39
40
|
"@slidev/rough-notation": "^0.1.0",
|
|
40
41
|
"@typescript/ata": "^0.9.8",
|
|
41
|
-
"@unhead/vue": "^
|
|
42
|
-
"@unocss/extractor-mdc": "^66.
|
|
43
|
-
"@unocss/preset-mini": "^66.
|
|
44
|
-
"@unocss/reset": "^66.
|
|
45
|
-
"@vueuse/core": "^14.
|
|
46
|
-
"@vueuse/math": "^14.
|
|
42
|
+
"@unhead/vue": "^3.1.1",
|
|
43
|
+
"@unocss/extractor-mdc": "^66.7.0",
|
|
44
|
+
"@unocss/preset-mini": "^66.7.0",
|
|
45
|
+
"@unocss/reset": "^66.7.0",
|
|
46
|
+
"@vueuse/core": "^14.3.0",
|
|
47
|
+
"@vueuse/math": "^14.3.0",
|
|
47
48
|
"@vueuse/motion": "^3.0.3",
|
|
48
|
-
"ansis": "^4.
|
|
49
|
+
"ansis": "^4.3.1",
|
|
49
50
|
"drauu": "^1.0.0",
|
|
50
51
|
"file-saver": "^2.0.5",
|
|
51
52
|
"floating-vue": "^5.2.2",
|
|
52
|
-
"fuse.js": "^7.
|
|
53
|
-
"katex": "^0.
|
|
53
|
+
"fuse.js": "^7.4.1",
|
|
54
|
+
"katex": "^0.17.0",
|
|
54
55
|
"lz-string": "^1.5.0",
|
|
55
|
-
"mermaid": "^11.
|
|
56
|
+
"mermaid": "^11.15.0",
|
|
56
57
|
"monaco-editor": "^0.55.1",
|
|
57
58
|
"nanotar": "^0.3.0",
|
|
58
59
|
"pptxgenjs": "^4.0.1",
|
|
59
60
|
"recordrtc": "^5.6.2",
|
|
60
|
-
"shiki": "^4.0
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"vue": "^
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"@slidev/types": "52.
|
|
68
|
-
"@slidev/parser": "52.15.2"
|
|
61
|
+
"shiki": "^4.2.0",
|
|
62
|
+
"typescript": "^6.0.3",
|
|
63
|
+
"unocss": "^66.7.0",
|
|
64
|
+
"vue": "^3.5.35",
|
|
65
|
+
"vue-router": "^5.1.0",
|
|
66
|
+
"yaml": "^2.9.0",
|
|
67
|
+
"@slidev/parser": "52.16.0",
|
|
68
|
+
"@slidev/types": "52.16.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"vite": "^8.0.
|
|
71
|
+
"vite": "^8.0.16"
|
|
72
72
|
}
|
|
73
73
|
}
|