@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
|
@@ -72,10 +72,14 @@ onMounted(() => {
|
|
|
72
72
|
const clicksInfo = clicks.calculateSince(props.at, props.ranges.length - 1)
|
|
73
73
|
clicks.register(id, clicksInfo)
|
|
74
74
|
|
|
75
|
-
const index = computed(() => clicksInfo
|
|
75
|
+
const index = computed(() => clicksInfo
|
|
76
|
+
? Math.max(0, clicks.current - clicksInfo.start + 1)
|
|
77
|
+
: CLICKS_MAX)
|
|
76
78
|
|
|
77
79
|
const finallyRange = computed(() => {
|
|
78
|
-
return props.finally === 'last'
|
|
80
|
+
return props.finally === 'last'
|
|
81
|
+
? props.ranges.at(-1)
|
|
82
|
+
: props.finally.toString()
|
|
79
83
|
})
|
|
80
84
|
|
|
81
85
|
let hiddenByRange = false
|
|
@@ -22,8 +22,12 @@ describe('collectKatexEquationLines', () => {
|
|
|
22
22
|
const rowB2 = fakeElement()
|
|
23
23
|
const nestedRow = fakeElement()
|
|
24
24
|
|
|
25
|
-
const outerLeftParent = fakeElement({
|
|
26
|
-
|
|
25
|
+
const outerLeftParent = fakeElement({
|
|
26
|
+
children: [rowA1, rowA2],
|
|
27
|
+
})
|
|
28
|
+
const outerRightParent = fakeElement({
|
|
29
|
+
children: [rowB1, rowB2],
|
|
30
|
+
})
|
|
27
31
|
const nestedParent = fakeElement({
|
|
28
32
|
parent: fakeElement({ closest: outerLeftParent }),
|
|
29
33
|
children: [nestedRow],
|
|
@@ -62,10 +62,14 @@ onMounted(() => {
|
|
|
62
62
|
const clicksInfo = clicks.calculateSince(props.at, props.ranges.length - 1)
|
|
63
63
|
clicks.register(id, clicksInfo)
|
|
64
64
|
|
|
65
|
-
const index = computed(() => clicksInfo
|
|
65
|
+
const index = computed(() => clicksInfo
|
|
66
|
+
? Math.max(0, clicks.current - clicksInfo.start + 1)
|
|
67
|
+
: CLICKS_MAX)
|
|
66
68
|
|
|
67
69
|
const finallyRange = computed(() => {
|
|
68
|
-
return props.finally === 'last'
|
|
70
|
+
return props.finally === 'last'
|
|
71
|
+
? props.ranges.at(-1)
|
|
72
|
+
: props.finally.toString()
|
|
69
73
|
})
|
|
70
74
|
|
|
71
75
|
let hiddenByRange = false
|
package/builtin/Mermaid.vue
CHANGED
|
@@ -62,7 +62,9 @@ watchEffect(() => {
|
|
|
62
62
|
const svgEl = el.value?.children?.[0] as SVGElement | undefined
|
|
63
63
|
if (svgEl && svgEl.hasAttribute('viewBox') && actualHeight.value == null) {
|
|
64
64
|
const v = Number.parseFloat(svgEl.getAttribute('viewBox')?.split(' ')[3] || '')
|
|
65
|
-
actualHeight.value = Number.isNaN(v)
|
|
65
|
+
actualHeight.value = Number.isNaN(v)
|
|
66
|
+
? undefined
|
|
67
|
+
: v
|
|
66
68
|
}
|
|
67
69
|
}, { flush: 'post' })
|
|
68
70
|
|
package/builtin/RenderWhen.vue
CHANGED
|
@@ -15,13 +15,19 @@ const target = ref(null)
|
|
|
15
15
|
const targetVisible = useElementVisibility(target)
|
|
16
16
|
|
|
17
17
|
// When context has `visible`, we need to wrap the content with a div to track the visibility
|
|
18
|
-
const needsDomWrapper = Array.isArray(context)
|
|
18
|
+
const needsDomWrapper = Array.isArray(context)
|
|
19
|
+
? context.includes('visible')
|
|
20
|
+
: context === 'visible'
|
|
19
21
|
|
|
20
22
|
const { $renderContext: currentContext } = useSlideContext()
|
|
21
23
|
const { isPrintMode } = useNav()
|
|
22
24
|
const shouldRender = computed(() => {
|
|
23
|
-
const anyContext = Array.isArray(context)
|
|
24
|
-
|
|
25
|
+
const anyContext = Array.isArray(context)
|
|
26
|
+
? context.some(contextMatch)
|
|
27
|
+
: contextMatch(context)
|
|
28
|
+
const allConditions = Array.isArray(context)
|
|
29
|
+
? context.every(conditionsMatch)
|
|
30
|
+
: conditionsMatch(context)
|
|
25
31
|
return anyContext && allConditions
|
|
26
32
|
})
|
|
27
33
|
|
|
@@ -79,7 +79,9 @@ function copyCode() {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// Normalized the ranges, to at least have one range
|
|
82
|
-
const ranges = computed(() => props.stepRanges.map(i => i.length
|
|
82
|
+
const ranges = computed(() => props.stepRanges.map(i => i.length
|
|
83
|
+
? i
|
|
84
|
+
: ['all']))
|
|
83
85
|
|
|
84
86
|
onUnmounted(() => {
|
|
85
87
|
clicks?.unregister(id)
|
|
@@ -101,7 +103,9 @@ onMounted(() => {
|
|
|
101
103
|
() => clicks.current,
|
|
102
104
|
() => {
|
|
103
105
|
// Calculate the step and rangeStr based on the current click count
|
|
104
|
-
const clickCount = clickInfo
|
|
106
|
+
const clickCount = clickInfo
|
|
107
|
+
? clicks.current - clickInfo.start
|
|
108
|
+
: CLICKS_MAX
|
|
105
109
|
let step = steps.length - 1
|
|
106
110
|
let currentClickSum = 0
|
|
107
111
|
let rangeStr = 'all'
|
package/builtin/Toc.vue
CHANGED
|
@@ -42,7 +42,9 @@ function filterTreeDepth(tree: TocItem[], level = 1): TocItem[] {
|
|
|
42
42
|
}
|
|
43
43
|
else if (level < Number(props.minDepth)) {
|
|
44
44
|
const activeItem = tree.find((item: TocItem) => item.active || item.activeParent)
|
|
45
|
-
return activeItem
|
|
45
|
+
return activeItem
|
|
46
|
+
? filterTreeDepth(activeItem.children, level + 1)
|
|
47
|
+
: []
|
|
46
48
|
}
|
|
47
49
|
return tree
|
|
48
50
|
.map((item: TocItem) => ({
|
package/builtin/VAfter.ts
CHANGED
|
@@ -13,7 +13,9 @@ export default defineComponent({
|
|
|
13
13
|
const after = resolveDirective('after')!
|
|
14
14
|
|
|
15
15
|
function applyDirective(node: VNode, directive: Directive) {
|
|
16
|
-
return withDirectives(node, [
|
|
16
|
+
return withDirectives(node, [
|
|
17
|
+
[directive],
|
|
18
|
+
])
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
let defaults = this.$slots.default?.()
|
package/builtin/VClicks.ts
CHANGED
|
@@ -76,12 +76,14 @@ export default defineComponent({
|
|
|
76
76
|
if (this.fade)
|
|
77
77
|
modifiers.fade = true
|
|
78
78
|
|
|
79
|
-
return withDirectives(node, [
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
return withDirectives(node, [
|
|
80
|
+
[
|
|
81
|
+
click,
|
|
82
|
+
value,
|
|
83
|
+
'',
|
|
84
|
+
modifiers,
|
|
85
|
+
],
|
|
86
|
+
])
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
const openAllTopLevelSlots = <T extends VNodeArrayChildren | VNode[]>(children: T): T => {
|
|
@@ -130,7 +132,9 @@ export default defineComponent({
|
|
|
130
132
|
return applyDirective(
|
|
131
133
|
vNode,
|
|
132
134
|
isRelative
|
|
133
|
-
? delta >= 0
|
|
135
|
+
? delta >= 0
|
|
136
|
+
? `+${delta}`
|
|
137
|
+
: `${delta}`
|
|
134
138
|
: thisShowIdx,
|
|
135
139
|
)
|
|
136
140
|
})
|
|
@@ -143,24 +147,37 @@ export default defineComponent({
|
|
|
143
147
|
|
|
144
148
|
if (this.handleSpecialElements) {
|
|
145
149
|
// handle ul, ol list
|
|
146
|
-
if (elements.length === 1 && listTags.includes(elements[0].type as string) && Array.isArray(elements[0].children))
|
|
147
|
-
return h(elements[0], {}, [
|
|
150
|
+
if (elements.length === 1 && listTags.includes(elements[0].type as string) && Array.isArray(elements[0].children)) {
|
|
151
|
+
return h(elements[0], {}, [
|
|
152
|
+
...mapChildren(elements[0].children),
|
|
153
|
+
lastGap(),
|
|
154
|
+
])
|
|
155
|
+
}
|
|
148
156
|
|
|
149
157
|
if (elements.length === 1 && elements[0].type as string === 'table') {
|
|
150
158
|
const tableNode = elements[0]
|
|
151
159
|
if (Array.isArray(tableNode.children)) {
|
|
152
160
|
return h(tableNode, {}, tableNode.children.map((i) => {
|
|
153
|
-
if (!isVNode(i))
|
|
161
|
+
if (!isVNode(i)) {
|
|
154
162
|
return i
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
163
|
+
}
|
|
164
|
+
else if (i.type === 'tbody' && Array.isArray(i.children)) {
|
|
165
|
+
return h(i, {}, [
|
|
166
|
+
...mapChildren(i.children),
|
|
167
|
+
lastGap(),
|
|
168
|
+
])
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
158
171
|
return h(i)
|
|
172
|
+
}
|
|
159
173
|
}))
|
|
160
174
|
}
|
|
161
175
|
}
|
|
162
176
|
}
|
|
163
177
|
|
|
164
|
-
return [
|
|
178
|
+
return [
|
|
179
|
+
...mapChildren(elements),
|
|
180
|
+
lastGap(),
|
|
181
|
+
]
|
|
165
182
|
},
|
|
166
183
|
})
|
package/builtin/VSwitch.ts
CHANGED
|
@@ -41,13 +41,18 @@ export default defineComponent({
|
|
|
41
41
|
for (const [range, slot] of slotEntries) {
|
|
42
42
|
const elRef = ref<HTMLElement>()
|
|
43
43
|
if (Number.isFinite(+range)) {
|
|
44
|
-
contents.push([
|
|
44
|
+
contents.push([
|
|
45
|
+
+range,
|
|
46
|
+
lastStart ?? +range + 1,
|
|
47
|
+
slot,
|
|
48
|
+
elRef,
|
|
49
|
+
])
|
|
45
50
|
lastStart = +range
|
|
46
51
|
}
|
|
47
52
|
else {
|
|
48
53
|
const [start, end] = range.split('-').map(Number)
|
|
49
54
|
if (!Number.isFinite(start) || !Number.isFinite(end))
|
|
50
|
-
throw new
|
|
55
|
+
throw new TypeError(`Invalid range for v-switch: ${range}`)
|
|
51
56
|
contents.push([start, end, slot, elRef])
|
|
52
57
|
lastStart = start
|
|
53
58
|
}
|
|
@@ -107,7 +112,9 @@ export default defineComponent({
|
|
|
107
112
|
}, slot?.()))
|
|
108
113
|
}
|
|
109
114
|
return transitionProps
|
|
110
|
-
? h(TransitionGroup, hmrSkipTransition.value
|
|
115
|
+
? h(TransitionGroup, hmrSkipTransition.value
|
|
116
|
+
? {}
|
|
117
|
+
: transitionProps, () => children)
|
|
111
118
|
: h(tag, children)
|
|
112
119
|
}
|
|
113
120
|
},
|
package/composables/useClicks.ts
CHANGED
|
@@ -23,8 +23,12 @@ export function normalizeSingleAtValue(at: RawSingleAtValue): NormalizedSingleCl
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export function normalizeRangeAtValue(at: RawAtValue): NormalizedRangeClickValue {
|
|
26
|
-
if (Array.isArray(at))
|
|
27
|
-
return [
|
|
26
|
+
if (Array.isArray(at)) {
|
|
27
|
+
return [
|
|
28
|
+
normalizeSingleAtValue(at[0])!,
|
|
29
|
+
normalizeSingleAtValue(at[1])!,
|
|
30
|
+
]
|
|
31
|
+
}
|
|
28
32
|
return null
|
|
29
33
|
}
|
|
30
34
|
|
|
@@ -160,7 +160,9 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
160
160
|
const width = ref(pos[2])
|
|
161
161
|
const x0 = ref(pos[0] + pos[2] / 2)
|
|
162
162
|
|
|
163
|
-
const rotate = ref(isArrow
|
|
163
|
+
const rotate = ref(isArrow
|
|
164
|
+
? 0
|
|
165
|
+
: (pos[4] ?? 0))
|
|
164
166
|
const rotateRad = computed(() => rotate.value * Math.PI / 180)
|
|
165
167
|
const rotateSin = computed(() => Math.sin(rotateRad.value))
|
|
166
168
|
const rotateCos = computed(() => Math.cos(rotateRad.value))
|
|
@@ -189,7 +191,9 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
189
191
|
set: v => !autoHeight && (configuredHeight.value = v),
|
|
190
192
|
})
|
|
191
193
|
: configuredHeight
|
|
192
|
-
const configuredY0 = autoHeight
|
|
194
|
+
const configuredY0 = autoHeight
|
|
195
|
+
? ref(pos[1])
|
|
196
|
+
: ref(pos[1] + pos[3] / 2)
|
|
193
197
|
const y0 = autoHeight
|
|
194
198
|
? computed({
|
|
195
199
|
get: () => configuredY0.value + height.value / 2,
|
|
@@ -205,7 +209,9 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
205
209
|
left: `${x0.value - width.value / 2}px`,
|
|
206
210
|
top: `${y0.value - height.value / 2}px`,
|
|
207
211
|
width: `${width.value}px`,
|
|
208
|
-
height: autoHeight
|
|
212
|
+
height: autoHeight
|
|
213
|
+
? undefined
|
|
214
|
+
: `${height.value}px`,
|
|
209
215
|
transformOrigin: 'center center',
|
|
210
216
|
transform: `rotate(${rotate.value}deg)`,
|
|
211
217
|
} satisfies CSSProperties
|
|
@@ -220,10 +226,14 @@ export function useDragElement(directive: DirectiveBinding | null, posRaw?: stri
|
|
|
220
226
|
[x0, y0, width, height, rotate],
|
|
221
227
|
([x0, y0, w, h, r]) => {
|
|
222
228
|
let posStr = [x0 - w / 2, y0 - h / 2, w].map(Math.round).join()
|
|
223
|
-
if (autoHeight)
|
|
224
|
-
posStr += dataSource === 'directive'
|
|
225
|
-
|
|
229
|
+
if (autoHeight) {
|
|
230
|
+
posStr += dataSource === 'directive'
|
|
231
|
+
? ',NaN'
|
|
232
|
+
: ',_'
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
226
235
|
posStr += `,${Math.round(h)}`
|
|
236
|
+
}
|
|
227
237
|
if (Math.round(r) !== 0)
|
|
228
238
|
posStr += `,${Math.round(r)}`
|
|
229
239
|
|
|
@@ -58,7 +58,9 @@ export const useDrawings = createSharedComposable(() => {
|
|
|
58
58
|
|
|
59
59
|
const drauuOptions: DrauuOptions = reactive({
|
|
60
60
|
brush,
|
|
61
|
-
acceptsInputTypes: computed(() => (drawingEnabled.value && (!configs.drawings.presenterOnly || isPresenter.value))
|
|
61
|
+
acceptsInputTypes: computed(() => (drawingEnabled.value && (!configs.drawings.presenterOnly || isPresenter.value))
|
|
62
|
+
? undefined
|
|
63
|
+
: ['pen' as const]),
|
|
62
64
|
coordinateTransform: false,
|
|
63
65
|
})
|
|
64
66
|
|
|
@@ -31,7 +31,13 @@ export function useEmbeddedControl() {
|
|
|
31
31
|
|
|
32
32
|
if (nav.isEmbedded.value) {
|
|
33
33
|
throttledWatch(
|
|
34
|
-
[
|
|
34
|
+
[
|
|
35
|
+
nav.currentSlideNo,
|
|
36
|
+
nav.clicks,
|
|
37
|
+
nav.hasNext,
|
|
38
|
+
nav.hasPrev,
|
|
39
|
+
nav.hasPrimarySlide,
|
|
40
|
+
],
|
|
35
41
|
([no, clicks, hasNext, hasPrev, hasPrimarySlide]) => {
|
|
36
42
|
if (!hasPrimarySlide)
|
|
37
43
|
return
|
|
@@ -14,13 +14,17 @@ vi.mock('#slidev/slides', async () => {
|
|
|
14
14
|
{
|
|
15
15
|
no: 1,
|
|
16
16
|
meta: {
|
|
17
|
-
slide: {
|
|
17
|
+
slide: {
|
|
18
|
+
frontmatter: { title: 'First' },
|
|
19
|
+
},
|
|
18
20
|
},
|
|
19
21
|
},
|
|
20
22
|
{
|
|
21
23
|
no: 2,
|
|
22
24
|
meta: {
|
|
23
|
-
slide: {
|
|
25
|
+
slide: {
|
|
26
|
+
frontmatter: { title: 'Second' },
|
|
27
|
+
},
|
|
24
28
|
},
|
|
25
29
|
},
|
|
26
30
|
]),
|
|
@@ -37,7 +41,9 @@ vi.mock('../env', async () => {
|
|
|
37
41
|
|
|
38
42
|
vi.mock('../state', async () => {
|
|
39
43
|
const { ref } = await import('vue')
|
|
40
|
-
return {
|
|
44
|
+
return {
|
|
45
|
+
hmrSkipTransition: ref(false),
|
|
46
|
+
}
|
|
41
47
|
})
|
|
42
48
|
|
|
43
49
|
vi.mock('vue-router', async () => {
|
package/composables/useNav.ts
CHANGED
|
@@ -105,7 +105,9 @@ export function useNavBase(
|
|
|
105
105
|
|
|
106
106
|
const currentPath = computed(() => getSlidePath(currentSlideRoute.value, isPresenter.value))
|
|
107
107
|
const currentSlideNo = computed(() => currentSlideRoute.value.no)
|
|
108
|
-
const currentLayout = computed(() => currentSlideRoute.value.meta?.layout || (currentSlideNo.value === 1
|
|
108
|
+
const currentLayout = computed(() => currentSlideRoute.value.meta?.layout || (currentSlideNo.value === 1
|
|
109
|
+
? 'cover'
|
|
110
|
+
: 'default'))
|
|
109
111
|
const currentFrontmatter = computed(() => currentSlideRoute.value.meta.slide.frontmatter)
|
|
110
112
|
|
|
111
113
|
const clicks = computed(() => clicksContext.value.current)
|
|
@@ -116,7 +118,9 @@ export function useNavBase(
|
|
|
116
118
|
const hasNext = computed(() => currentSlideNo.value < slides.value.length || clicks.value < clicksTotal.value)
|
|
117
119
|
const hasPrev = computed(() => currentSlideNo.value > 1 || clicks.value > 0)
|
|
118
120
|
|
|
119
|
-
const currentTransition = computed(() => isPrint.value
|
|
121
|
+
const currentTransition = computed(() => isPrint.value
|
|
122
|
+
? undefined
|
|
123
|
+
: getCurrentTransition(navDirection.value, currentSlideRoute.value, prevRoute.value))
|
|
120
124
|
|
|
121
125
|
watch(currentSlideRoute, (next, prev) => {
|
|
122
126
|
navDirection.value = next.no - prev.no
|
|
@@ -162,7 +166,9 @@ export function useNavBase(
|
|
|
162
166
|
if (currentSlideNo.value < slides.value.length) {
|
|
163
167
|
await go(
|
|
164
168
|
currentSlideNo.value + 1,
|
|
165
|
-
lastClicks && !isPrint.value
|
|
169
|
+
lastClicks && !isPrint.value
|
|
170
|
+
? CLICKS_MAX
|
|
171
|
+
: undefined,
|
|
166
172
|
)
|
|
167
173
|
}
|
|
168
174
|
}
|
|
@@ -172,7 +178,9 @@ export function useNavBase(
|
|
|
172
178
|
if (currentSlideNo.value > 1) {
|
|
173
179
|
await go(
|
|
174
180
|
currentSlideNo.value - 1,
|
|
175
|
-
lastClicks && !isPrint.value
|
|
181
|
+
lastClicks && !isPrint.value
|
|
182
|
+
? CLICKS_MAX
|
|
183
|
+
: undefined,
|
|
176
184
|
)
|
|
177
185
|
}
|
|
178
186
|
}
|
|
@@ -197,8 +205,12 @@ export function useNavBase(
|
|
|
197
205
|
path: getSlidePath(no, isPresenter.value, router.currentRoute.value.name === 'export'),
|
|
198
206
|
query: {
|
|
199
207
|
...router.currentRoute.value.query,
|
|
200
|
-
clicks: clicks === 0
|
|
201
|
-
|
|
208
|
+
clicks: clicks === 0
|
|
209
|
+
? undefined
|
|
210
|
+
: clicks.toString(),
|
|
211
|
+
embedded: location.search.includes('embedded')
|
|
212
|
+
? 'true'
|
|
213
|
+
: undefined,
|
|
202
214
|
},
|
|
203
215
|
})
|
|
204
216
|
}
|
|
@@ -291,7 +303,9 @@ const useNavState = createSharedComposable((): SlidevContextNavState => {
|
|
|
291
303
|
const isNotesViewer = computed(() => currentRoute.name === 'notes')
|
|
292
304
|
const isPresenterAvailable = computed(() => !isPresenter.value && (!configs.remote || query.value.get('password') === configs.remote))
|
|
293
305
|
const hasPrimarySlide = computed(() => !!currentRoute.params.no)
|
|
294
|
-
const currentSlideNo = computed(() => hasPrimarySlide.value
|
|
306
|
+
const currentSlideNo = computed(() => hasPrimarySlide.value
|
|
307
|
+
? getSlide(currentRoute.params.no as string)?.no ?? 1
|
|
308
|
+
: 1)
|
|
295
309
|
const currentSlideRoute = computed(() => slides.value[currentSlideNo.value - 1])
|
|
296
310
|
const printRange = ref(parseRangeString(slides.value.length, currentRoute?.query?.range as string | undefined))
|
|
297
311
|
|
|
@@ -11,7 +11,9 @@ function resolveUrl(url: string): string {
|
|
|
11
11
|
if (url.startsWith('http') || url.startsWith('//'))
|
|
12
12
|
return url
|
|
13
13
|
const base = (import.meta.env.BASE_URL || '/').replace(RE_TRAILING_SLASH, '')
|
|
14
|
-
return `${base}${url.startsWith('/')
|
|
14
|
+
return `${base}${url.startsWith('/')
|
|
15
|
+
? url
|
|
16
|
+
: `/${url}`}`
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
const RETRY_LIMIT = 2
|
|
@@ -25,7 +27,9 @@ const totalImagesCount = ref(0)
|
|
|
25
27
|
* image in the deck has loaded, or when the deck has no images).
|
|
26
28
|
*/
|
|
27
29
|
export const preloadProgress = computed(() =>
|
|
28
|
-
totalImagesCount.value === 0
|
|
30
|
+
totalImagesCount.value === 0
|
|
31
|
+
? 1
|
|
32
|
+
: preloadedCount.value / totalImagesCount.value,
|
|
29
33
|
)
|
|
30
34
|
|
|
31
35
|
/** Whether all preloadable slide images have finished loading. */
|
|
@@ -41,8 +41,12 @@ export function useSlideInfo(no: number): UseSlideInfo {
|
|
|
41
41
|
info.value = payload.data
|
|
42
42
|
})
|
|
43
43
|
import.meta.hot?.on('slidev:update-note', (payload) => {
|
|
44
|
-
if (payload.no === no && info.value && info.value.note?.trim() !== payload.note?.trim())
|
|
45
|
-
info.value = {
|
|
44
|
+
if (payload.no === no && info.value && info.value.note?.trim() !== payload.note?.trim()) {
|
|
45
|
+
info.value = {
|
|
46
|
+
...info.value,
|
|
47
|
+
...payload,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
46
50
|
})
|
|
47
51
|
}
|
|
48
52
|
|
|
@@ -17,8 +17,14 @@ export function useViewTransition() {
|
|
|
17
17
|
const toMeta = getSlide(to.params.no as string)?.meta
|
|
18
18
|
const fromNo = fromMeta?.slide?.no
|
|
19
19
|
const toNo = toMeta?.slide?.no
|
|
20
|
+
// Navigating within the same slide (only `clicks` changed): keep the current mode.
|
|
21
|
+
// Resetting it swaps the wrapper in SlidesShow and remounts every slide.
|
|
22
|
+
if (fromNo != null && fromNo === toNo)
|
|
23
|
+
return
|
|
20
24
|
const transitionType = fromNo != null && toNo != null && fromNo !== toNo
|
|
21
|
-
&& ((fromNo < toNo
|
|
25
|
+
&& ((fromNo < toNo
|
|
26
|
+
? fromMeta?.transition
|
|
27
|
+
: toMeta?.transition) ?? configs.transition)
|
|
22
28
|
if (transitionType !== 'view-transition') {
|
|
23
29
|
isViewTransition.value = false
|
|
24
30
|
return
|
package/context.ts
CHANGED
|
@@ -52,7 +52,9 @@ export type SlideContext = ReturnType<typeof useSlideContext>
|
|
|
52
52
|
*/
|
|
53
53
|
export function frontmatterToProps(frontmatter: Record<string, any>, pageNo: number) {
|
|
54
54
|
return {
|
|
55
|
-
...objectOmit(frontmatter, pageNo === 0
|
|
55
|
+
...objectOmit(frontmatter, pageNo === 0
|
|
56
|
+
? HEADMATTER_FIELDS
|
|
57
|
+
: FRONTMATTER_FIELDS),
|
|
56
58
|
frontmatter,
|
|
57
59
|
}
|
|
58
60
|
}
|
package/env.ts
CHANGED
|
@@ -4,7 +4,9 @@ import configs from '#slidev/configs'
|
|
|
4
4
|
|
|
5
5
|
export { configs }
|
|
6
6
|
|
|
7
|
-
export const mode = import.meta.env.DEV
|
|
7
|
+
export const mode = import.meta.env.DEV
|
|
8
|
+
? 'dev'
|
|
9
|
+
: 'build'
|
|
8
10
|
|
|
9
11
|
export const slideAspect = computed(() => configs.aspectRatio)
|
|
10
12
|
export const slideWidth = computed(() => configs.canvasWidth)
|
|
@@ -27,7 +27,9 @@ const current = computed({
|
|
|
27
27
|
get() {
|
|
28
28
|
if (props.resettable && !props.active)
|
|
29
29
|
return -1
|
|
30
|
-
return props.clicksContext.current > total.value
|
|
30
|
+
return props.clicksContext.current > total.value
|
|
31
|
+
? -1
|
|
32
|
+
: props.clicksContext.current
|
|
31
33
|
},
|
|
32
34
|
set(value: number) {
|
|
33
35
|
if (props.resettable && value < 0) {
|
|
@@ -65,7 +67,9 @@ function setCurrentFromPointer(event: PointerEvent, snap: boolean) {
|
|
|
65
67
|
// Keep press-at-right-edge inside the last cell.
|
|
66
68
|
const position = clamp(0, ratio, snap ? 0.999999 : 1) * length.value
|
|
67
69
|
const currentOffset = clamp(0, current.value - start.value, length.value - 1)
|
|
68
|
-
let next = snap
|
|
70
|
+
let next = snap
|
|
71
|
+
? start.value + Math.floor(position)
|
|
72
|
+
: current.value
|
|
69
73
|
if (!snap && position >= currentOffset + 1.5)
|
|
70
74
|
next = start.value + Math.floor(position - 0.5)
|
|
71
75
|
else if (!snap && position < currentOffset - 0.5)
|
|
@@ -138,7 +138,10 @@ function getCornerProps(isLeft: boolean, isTop: boolean) {
|
|
|
138
138
|
return { w, h }
|
|
139
139
|
}
|
|
140
140
|
else {
|
|
141
|
-
return {
|
|
141
|
+
return {
|
|
142
|
+
w: Math.max(w1, minSize),
|
|
143
|
+
h: Math.max(h1, minSize),
|
|
144
|
+
}
|
|
142
145
|
}
|
|
143
146
|
}
|
|
144
147
|
|
|
@@ -209,11 +212,23 @@ function getCornerProps(isLeft: boolean, isTop: boolean) {
|
|
|
209
212
|
width: `${ctrlSize}px`,
|
|
210
213
|
height: `${ctrlSize}px`,
|
|
211
214
|
margin: `-${ctrlSize / 2}px`,
|
|
212
|
-
left: isLeft !== arrowRevX.value
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
215
|
+
left: isLeft !== arrowRevX.value
|
|
216
|
+
? '0'
|
|
217
|
+
: undefined,
|
|
218
|
+
right: isLeft !== arrowRevX.value
|
|
219
|
+
? undefined
|
|
220
|
+
: '0',
|
|
221
|
+
top: isTop !== arrowRevY.value
|
|
222
|
+
? '0'
|
|
223
|
+
: undefined,
|
|
224
|
+
bottom: isTop !== arrowRevY.value
|
|
225
|
+
? undefined
|
|
226
|
+
: '0',
|
|
227
|
+
cursor: isArrow
|
|
228
|
+
? 'move'
|
|
229
|
+
: +isLeft + +isTop === 1
|
|
230
|
+
? 'nesw-resize'
|
|
231
|
+
: 'nwse-resize',
|
|
217
232
|
borderRadius: isArrow ? '50%' : undefined,
|
|
218
233
|
},
|
|
219
234
|
class: ctrlClasses,
|
|
@@ -269,9 +284,19 @@ function getBorderProps(dir: 'l' | 'r' | 't' | 'b') {
|
|
|
269
284
|
width: `${ctrlSize}px`,
|
|
270
285
|
height: `${ctrlSize}px`,
|
|
271
286
|
margin: `-${ctrlSize / 2}px`,
|
|
272
|
-
left: dir === 'l'
|
|
273
|
-
|
|
274
|
-
|
|
287
|
+
left: dir === 'l'
|
|
288
|
+
? '0'
|
|
289
|
+
: dir === 'r'
|
|
290
|
+
? `100%`
|
|
291
|
+
: `50%`,
|
|
292
|
+
top: dir === 't'
|
|
293
|
+
? '0'
|
|
294
|
+
: dir === 'b'
|
|
295
|
+
? `100%`
|
|
296
|
+
: `50%`,
|
|
297
|
+
cursor: 'lr'.includes(dir)
|
|
298
|
+
? 'ew-resize'
|
|
299
|
+
: 'ns-resize',
|
|
275
300
|
borderRadius: '50%',
|
|
276
301
|
},
|
|
277
302
|
class: ctrlClasses,
|
package/internals/Goto.vue
CHANGED
|
@@ -25,8 +25,12 @@ const fuse = computed(() => new Fuse(slides.value.map(i => i.meta?.slide).filter
|
|
|
25
25
|
minMatchCharLength: 1,
|
|
26
26
|
}))
|
|
27
27
|
|
|
28
|
-
const path = computed(() => text.value.startsWith('/')
|
|
29
|
-
|
|
28
|
+
const path = computed(() => text.value.startsWith('/')
|
|
29
|
+
? text.value.substring(1)
|
|
30
|
+
: text.value)
|
|
31
|
+
const result = computed(() => path.value
|
|
32
|
+
? fuse.value.search(path.value).map(result => result.item)
|
|
33
|
+
: [])
|
|
30
34
|
const valid = computed(() => !!result.value.length)
|
|
31
35
|
|
|
32
36
|
function goTo() {
|
|
@@ -46,8 +46,11 @@ function processNote() {
|
|
|
46
46
|
let n = marker
|
|
47
47
|
let p = marker.parentElement
|
|
48
48
|
while (p && n !== noteDisplay.value) {
|
|
49
|
-
if (!parentsMap.has(p))
|
|
50
|
-
parentsMap.set(p, [
|
|
49
|
+
if (!parentsMap.has(p)) {
|
|
50
|
+
parentsMap.set(p, [
|
|
51
|
+
[null, lastClicks],
|
|
52
|
+
])
|
|
53
|
+
}
|
|
51
54
|
parentsMap.get(p)!.push([n, clicks])
|
|
52
55
|
n = p
|
|
53
56
|
p = p.parentElement
|
package/internals/NoteStatic.vue
CHANGED
|
@@ -7,6 +7,7 @@ const props = defineProps<{
|
|
|
7
7
|
no: number
|
|
8
8
|
class?: string
|
|
9
9
|
clicksContext?: ClicksContext
|
|
10
|
+
autoScroll?: boolean
|
|
10
11
|
}>()
|
|
11
12
|
|
|
12
13
|
const { info } = useSlideInfo(props.no)
|
|
@@ -18,5 +19,6 @@ const { info } = useSlideInfo(props.no)
|
|
|
18
19
|
:note="info?.note"
|
|
19
20
|
:note-html="info?.noteHTML"
|
|
20
21
|
:clicks-context="clicksContext"
|
|
22
|
+
:auto-scroll="autoScroll"
|
|
21
23
|
/>
|
|
22
24
|
</template>
|
package/internals/ShadowRoot.vue
CHANGED
|
@@ -10,7 +10,9 @@ const emit = defineEmits<{
|
|
|
10
10
|
}>()
|
|
11
11
|
|
|
12
12
|
const el = ref<HTMLDivElement>()
|
|
13
|
-
const shadow = computed(() => el.value
|
|
13
|
+
const shadow = computed(() => el.value
|
|
14
|
+
? (el.value.shadowRoot || el.value.attachShadow({ mode: 'open' }))
|
|
15
|
+
: null)
|
|
14
16
|
watchEffect(() => {
|
|
15
17
|
if (shadow.value && props.innerHtml) {
|
|
16
18
|
emit('shadow', shadow.value)
|