@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.
@@ -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 automaitcally resize
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 { injectionClicks, injectionClicksElements, injectionClicksDisabled, CLASS_VCLICK_TARGET } from '../constants'
18
+ import { CLASS_VCLICK_TARGET, injectionClicks, injectionClicksDisabled, injectionClicksElements } from '../constants'
19
19
 
20
20
  const props = defineProps({
21
21
  ranges: {
@@ -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 { ref, onMounted, watchEffect, computed } from 'vue'
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'
@@ -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 embeded Tweet
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-ignore
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-ignore
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'
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { shallowRef } from 'vue'
3
- import { showOverview, showRecordingDialog, showInfoDialog } from '../state'
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, microphones, ensureDevicesListPermissions } from '../logic/recording'
4
+ import { cameras, ensureDevicesListPermissions, microphones } from '../logic/recording'
5
5
  import SelectList from './SelectList.vue'
6
6
  import type { SelectionItem } from './types'
7
7
 
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { ref } from 'vue'
3
- import { useStorage, useDraggable } from '@vueuse/core'
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
- drawingMode, drauu, brush,
4
- brushColors, drawingEnabled, drawingPinned,
5
- canUndo, canRedo, canClear, clearDrauu,
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 { onMounted, ref, watch, inject, onBeforeUnmount } from 'vue'
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
 
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { drawingState } from '../logic/drawings'
3
3
 
4
- defineProps<{page: number}>()
4
+ defineProps<{ page: number }>()
5
5
  </script>
6
6
 
7
7
  <template>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { useEventListener, throttledWatch } from '@vueuse/core'
3
- import { computed, watch, ref, onMounted } from 'vue'
4
- import { activeElement, showEditor, editorWidth, isInputting } from '../state'
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-ignore
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-ignore
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) => {
@@ -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,
@@ -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, isColorSchemaConfigured } from '../logic/dark'
4
- import { hasNext, hasPrev, prev, next, total, isPresenter, currentPage, downloadPDF, isEmbedded } from '../logic/nav'
5
- import { toggleOverview, showEditor, showInfoDialog, fullscreen, breakpoints, activeElement, showPresenterCursor } from '../state'
6
- import { drawingEnabled, brush } from '../logic/drawings'
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'
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
- import { ref, computed, shallowRef } from 'vue'
3
- import { showEditor, windowSize, isScreenVertical, slideScale } from '../state'
4
- import { isPrintMode, next, prev, useSwipeControls, isEmbedded } from '../logic/nav'
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 { themeVars, configs } from '../env'
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 previouse
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 presistNav = computed(() => isScreenVertical.value || showEditor.value)
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
- presistNav ? 'opacity-100 right-0' : 'oapcity-0 p-2',
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="presistNav" />
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" />
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { useHead } from '@vueuse/head'
3
- import { ref, computed, reactive, watch, onMounted } from 'vue'
3
+ import { computed, onMounted, reactive, ref, watch } from 'vue'
4
4
  import { useMouse, useWindowFocus } from '@vueuse/core'
5
- import { total, currentPage, currentRoute, nextRoute, clicks, useSwipeControls, clicksTotal, hasNext } from '../logic/nav'
5
+ import { clicks, clicksTotal, currentPage, currentRoute, hasNext, nextRoute, total, useSwipeControls } from '../logic/nav'
6
6
  import { showOverview, showPresenterCursor } from '../state'
7
- import { configs, themeVars, serverState } from '../env'
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 { recorder, recordingName, recordCamera, getFilename } from '../logic/recording'
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 { slideAspect, slideWidth, slideHeight, configs } from '../env'
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 { provide, defineComponent, h } from 'vue'
2
+ import { defineComponent, h, provide } from 'vue'
3
3
  import { injectionClicks, injectionClicksDisabled, injectionClicksElements, injectionOrderMap } from '../constants'
4
4
 
5
5
  export default defineComponent({
@@ -1,11 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { shallowRef, watch } from 'vue'
3
- import { currentRoute, clicks, rawRoutes, nextRoute, isPresenter } from '../logic/nav'
3
+ import { clicks, currentRoute, isPresenter, nextRoute, rawRoutes } from '../logic/nav'
4
4
  import { getSlideClass } from '../utils'
5
5
  import SlideWrapper from './SlideWrapper'
6
- // @ts-ignore
6
+ // @ts-expect-error virtual module
7
7
  import GlobalTop from '/@slidev/global-components/top'
8
- // @ts-ignore
8
+ // @ts-expect-error virtual module
9
9
  import GlobalBottom from '/@slidev/global-components/bottom'
10
10
  import PresenterMouse from './PresenterMouse.vue'
11
11
 
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { useEventListener, useStorage, useDraggable } from '@vueuse/core'
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, DrawingMode, Options as DrauuOptions } from 'drauu'
2
+ import type { Brush, Options as DrauuOptions, DrawingMode } from 'drauu'
3
3
  import { createDrauu } from 'drauu'
4
- import { useStorage, toReactive } from '@vueuse/core'
5
- import { serverDrawingState as drawingState, configs } from '../env'
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 { computed, ref, nextTick } from 'vue'
3
- import { isString, SwipeDirection, timestamp, usePointerSwipe } from '@vueuse/core'
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
+ }
@@ -1,6 +1,6 @@
1
1
  import type { Ref } from 'vue'
2
2
  import { nextTick, ref, shallowRef, watch } from 'vue'
3
- import { useEventListener, useDevicesList } from '@vueuse/core'
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
  },
@@ -1,9 +1,9 @@
1
1
  import type { Fn, KeyFilter } from '@vueuse/core'
2
- import { not, and, onKeyStroke } from '@vueuse/core'
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, magicKeys, shortcutsEnabled, isInputting, toggleOverview, showGotoDialog, showOverview, isOnFocus } from '../state'
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
@@ -1,5 +1,5 @@
1
1
  import { useTimestamp } from '@vueuse/core'
2
- import { ref, computed } from 'vue'
2
+ import { computed, ref } from 'vue'
3
3
 
4
4
  export function useTimer() {
5
5
  const tsStart = ref(Date.now())
@@ -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') {
@@ -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
- CLASS_VCLICK_FADE,
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) {
@@ -1,4 +1,4 @@
1
- // @ts-ignore
1
+ // @ts-expect-error missing types
2
2
  import mermaid from 'mermaid/dist/mermaid.min'
3
3
  import { customAlphabet } from 'nanoid'
4
4
  import { decode } from 'js-base64'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slidev/client",
3
- "version": "0.27.20",
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.3.0",
16
- "@slidev/parser": "0.27.20",
17
- "@slidev/types": "0.27.20",
18
- "@vueuse/core": "^7.3.0",
19
- "@vueuse/head": "^0.7.4",
20
- "@vueuse/motion": "^2.0.0-beta.4",
21
- "codemirror": "^5.64.0",
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.1",
26
+ "katex": "^0.15.2",
27
27
  "mermaid": "8.13.0",
28
- "monaco-editor": "^0.31.0",
29
- "nanoid": "^3.1.30",
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.20.0",
33
- "vite-plugin-windicss": "^1.5.4",
34
- "vue": "^3.2.26",
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.0"
36
+ "windicss": "^3.4.3"
37
37
  },
38
38
  "engines": {
39
39
  "node": ">=14.0.0"
40
- }
40
+ },
41
+ "readme": "# @slidev/client\n\n[![NPM version](https://img.shields.io/npm/v/@slidev/client?color=3AB9D4&label=)](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, createWebHistory, createWebHashHistory } from 'vue-router'
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, clicks, isPresenter } from '../logic/nav'
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
 
@@ -1,13 +1,13 @@
1
1
  /* __imports__ */
2
2
 
3
- import type { ShortcutOptions, NavOperations } from '@slidev/types'
4
- import { next, prev, nextSlide, prevSlide, downloadPDF } from '../logic/nav'
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 { toggleOverview, showGotoDialog, showOverview } from '../state'
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 { useMagicKeys, useActiveElement, useStorage, useBreakpoints, breakpointsTailwind, useWindowSize, useFullscreen, useToggle, isClient } from '@vueuse/core'
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