@slidev/client 52.13.0 → 52.14.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/constants.ts CHANGED
@@ -82,6 +82,7 @@ export const HEADMATTER_FIELDS = [
82
82
  'drawings',
83
83
  'htmlAttrs',
84
84
  'mdc',
85
+ 'comark',
85
86
  'contextMenu',
86
87
  'wakeLock',
87
88
  'seoMeta',
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@slidev/client",
3
3
  "type": "module",
4
- "version": "52.13.0",
4
+ "version": "52.14.0",
5
5
  "description": "Presentation slides for developers",
6
6
  "author": "Anthony Fu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -32,37 +32,39 @@
32
32
  "@iconify-json/carbon": "^1.2.18",
33
33
  "@iconify-json/ph": "^1.2.2",
34
34
  "@iconify-json/svg-spinners": "^1.2.4",
35
- "@shikijs/engine-javascript": "^3.21.0",
36
- "@shikijs/monaco": "^3.21.0",
37
- "@shikijs/vitepress-twoslash": "^3.21.0",
35
+ "@shikijs/engine-javascript": "^4.0.0",
36
+ "@shikijs/monaco": "^4.0.0",
37
+ "@shikijs/vitepress-twoslash": "^4.0.0",
38
38
  "@slidev/rough-notation": "^0.1.0",
39
39
  "@typescript/ata": "^0.9.8",
40
- "@unhead/vue": "^2.1.2",
41
- "@unocss/reset": "^66.6.0",
42
- "@vueuse/core": "^14.1.0",
43
- "@vueuse/math": "^14.1.0",
40
+ "@unhead/vue": "^2.1.9",
41
+ "@unocss/extractor-mdc": "^66.6.2",
42
+ "@unocss/preset-mini": "^66.6.2",
43
+ "@unocss/reset": "^66.6.2",
44
+ "@vueuse/core": "^14.2.1",
45
+ "@vueuse/math": "^14.2.1",
44
46
  "@vueuse/motion": "^3.0.3",
45
47
  "ansis": "^4.2.0",
46
48
  "drauu": "^1.0.0",
47
49
  "file-saver": "^2.0.5",
48
50
  "floating-vue": "^5.2.2",
49
51
  "fuse.js": "^7.1.0",
50
- "katex": "^0.16.28",
52
+ "katex": "^0.16.33",
51
53
  "lz-string": "^1.5.0",
52
- "mermaid": "^11.12.2",
54
+ "mermaid": "^11.12.3",
53
55
  "monaco-editor": "^0.55.1",
54
- "nanotar": "^0.2.0",
56
+ "nanotar": "^0.3.0",
55
57
  "pptxgenjs": "^4.0.1",
56
58
  "recordrtc": "^5.6.2",
57
- "shiki": "^3.21.0",
59
+ "shiki": "^4.0.0",
58
60
  "shiki-magic-move": "^1.2.1",
59
61
  "typescript": "^5.9.3",
60
- "unocss": "^66.6.0",
61
- "vue": "^3.5.27",
62
- "vue-router": "^4.6.4",
62
+ "unocss": "^66.6.2",
63
+ "vue": "^3.5.29",
64
+ "vue-router": "^5.0.3",
63
65
  "yaml": "^2.8.2",
64
- "@slidev/parser": "52.13.0",
65
- "@slidev/types": "52.13.0"
66
+ "@slidev/parser": "52.14.0",
67
+ "@slidev/types": "52.14.0"
66
68
  },
67
69
  "devDependencies": {
68
70
  "vite": "^7.3.1"
@@ -1,6 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { useHead } from '@unhead/vue'
3
- import { useLocalStorage, useMouse, useWindowFocus } from '@vueuse/core'
3
+ import { useEventListener, useLocalStorage, useMediaQuery, useMouse, useWindowFocus } from '@vueuse/core'
4
4
  import { computed, onMounted, reactive, ref, shallowRef, watch } from 'vue'
5
5
  import { createClicksContextBase } from '../composables/useClicks'
6
6
  import { useDrawings } from '../composables/useDrawings'
@@ -32,6 +32,9 @@ import { sharedState } from '../state/shared'
32
32
 
33
33
  const inFocus = useWindowFocus()
34
34
  const main = ref<HTMLDivElement>()
35
+ const gridContainer = ref<HTMLDivElement>()
36
+ const noteSection = ref<HTMLDivElement>()
37
+ const bottomSection = ref<HTMLDivElement>()
35
38
 
36
39
  registerShortcuts()
37
40
  useSwipeControls(main)
@@ -83,6 +86,158 @@ watch(
83
86
  )
84
87
 
85
88
  const mainSlideMode = useLocalStorage<'slides' | 'mirror'>('slidev-presenter-main-slide-mode', 'slides')
89
+
90
+ // Resize state (persisted)
91
+ const notesWidth = useLocalStorage('slidev-presenter-notes-width', 360)
92
+ const notesRowSize = useLocalStorage('slidev-presenter-notes-row-size', 280)
93
+ const bottomSectionHeight = ref(0)
94
+ const isResizingNotes = ref(false)
95
+ const isResizingNotesRow = ref(false)
96
+ const resizeStartX = ref(0)
97
+ const resizeStartWidth = ref(360)
98
+ const resizeStartY = ref(0)
99
+ const resizeStartRowSize = ref(280)
100
+
101
+ const RESIZER_LIMITS = {
102
+ minNotesWidth: 240,
103
+ maxNotesWidth: 720,
104
+ minNotesRowSize: 160,
105
+ maxNotesWidthRatio: 0.7,
106
+ maxNotesRowHeightRatio: 0.75,
107
+ }
108
+
109
+ const isLayout1Wide = useMediaQuery('(min-aspect-ratio: 1/1)')
110
+ const isLayout1Stacked = useMediaQuery('(max-aspect-ratio: 3/5)')
111
+ const isNotesOnRight = computed(() => presenterLayout.value === 1 && isLayout1Wide.value)
112
+ const isNotesResizable = computed(() => !(presenterLayout.value === 1 && isLayout1Stacked.value))
113
+ const isNotesRowResizable = computed(() =>
114
+ (presenterLayout.value === 1 && !isLayout1Stacked.value) || presenterLayout.value === 2 || presenterLayout.value === 3,
115
+ )
116
+ const isNotesOnBottom = computed(() => presenterLayout.value === 1 && !isLayout1Stacked.value)
117
+
118
+ function clampNotesWidth(width: number) {
119
+ if (!Number.isFinite(width))
120
+ return RESIZER_LIMITS.minNotesWidth
121
+ return Math.max(
122
+ RESIZER_LIMITS.minNotesWidth,
123
+ Math.min(RESIZER_LIMITS.maxNotesWidth, Math.round(width)),
124
+ )
125
+ }
126
+
127
+ function updateNotesWidthFromPointer(clientX: number) {
128
+ const container = gridContainer.value
129
+ if (!container)
130
+ return
131
+
132
+ const rect = container.getBoundingClientRect()
133
+ const deltaX = clientX - resizeStartX.value
134
+ const proposedWidth = isNotesOnRight.value
135
+ ? resizeStartWidth.value - deltaX
136
+ : resizeStartWidth.value + deltaX
137
+ const nextWidth = clampNotesWidth(proposedWidth)
138
+ const maxByViewport = Math.round(rect.width * RESIZER_LIMITS.maxNotesWidthRatio)
139
+ notesWidth.value = Math.min(nextWidth, Math.max(RESIZER_LIMITS.minNotesWidth, maxByViewport))
140
+ }
141
+
142
+ function onNotesResizeStart(e: PointerEvent) {
143
+ if (!isNotesResizable.value)
144
+ return
145
+ if (e.button !== 0)
146
+ return
147
+ e.preventDefault()
148
+ resizeStartX.value = e.clientX
149
+ resizeStartWidth.value = notesWidth.value
150
+ isResizingNotes.value = true
151
+ }
152
+
153
+ function clampNotesRowSize(size: number) {
154
+ if (!Number.isFinite(size))
155
+ return RESIZER_LIMITS.minNotesRowSize
156
+ return Math.max(RESIZER_LIMITS.minNotesRowSize, Math.round(size))
157
+ }
158
+
159
+ function updateNotesRowSizeFromPointer(clientY: number) {
160
+ const container = gridContainer.value
161
+ if (!container)
162
+ return
163
+
164
+ const rect = container.getBoundingClientRect()
165
+ const deltaY = clientY - resizeStartY.value
166
+ const proposed = isNotesOnBottom.value
167
+ ? resizeStartRowSize.value - deltaY
168
+ : resizeStartRowSize.value + deltaY
169
+ const maxByViewport = Math.round(rect.height * RESIZER_LIMITS.maxNotesRowHeightRatio)
170
+ notesRowSize.value = Math.min(clampNotesRowSize(proposed), Math.max(RESIZER_LIMITS.minNotesRowSize, maxByViewport))
171
+ }
172
+
173
+ function onNotesRowResizeStart(e: PointerEvent) {
174
+ if (!isNotesRowResizable.value)
175
+ return
176
+ if (e.button !== 0)
177
+ return
178
+ e.preventDefault()
179
+
180
+ // In layout 2, notesRowSize controls the top section (main slide) height
181
+ // In other layouts, it represents the notes area height
182
+ const currentHeight = presenterLayout.value === 2
183
+ ? main.value?.getBoundingClientRect().height
184
+ : noteSection.value?.getBoundingClientRect().height
185
+ resizeStartY.value = e.clientY
186
+ resizeStartRowSize.value = clampNotesRowSize(currentHeight ?? notesRowSize.value)
187
+ isResizingNotesRow.value = true
188
+ }
189
+
190
+ function updateBottomSectionHeight() {
191
+ const element = bottomSection.value
192
+ if (!element)
193
+ return
194
+ bottomSectionHeight.value = Math.round(element.getBoundingClientRect().height)
195
+ }
196
+
197
+ function stopResizing() {
198
+ isResizingNotes.value = false
199
+ isResizingNotesRow.value = false
200
+ }
201
+
202
+ function syncResizerLayoutState() {
203
+ updateBottomSectionHeight()
204
+ normalizeResizerState()
205
+ }
206
+
207
+ useEventListener(window, 'pointermove', (e) => {
208
+ if (isResizingNotes.value)
209
+ updateNotesWidthFromPointer(e.clientX)
210
+ if (isResizingNotesRow.value)
211
+ updateNotesRowSizeFromPointer(e.clientY)
212
+ })
213
+
214
+ useEventListener(window, 'pointerup', stopResizing)
215
+ useEventListener(window, 'pointercancel', stopResizing)
216
+
217
+ onMounted(() => {
218
+ syncResizerLayoutState()
219
+ })
220
+
221
+ useEventListener(window, 'resize', () => {
222
+ syncResizerLayoutState()
223
+ })
224
+
225
+ function normalizeResizerState() {
226
+ notesWidth.value = clampNotesWidth(notesWidth.value)
227
+ notesRowSize.value = clampNotesRowSize(notesRowSize.value)
228
+
229
+ const container = gridContainer.value
230
+ if (!container)
231
+ return
232
+
233
+ const rect = container.getBoundingClientRect()
234
+ const maxWidth = Math.round(rect.width * RESIZER_LIMITS.maxNotesWidthRatio)
235
+ const maxRowSize = Math.round(rect.height * RESIZER_LIMITS.maxNotesRowHeightRatio)
236
+
237
+ notesWidth.value = Math.min(notesWidth.value, Math.max(RESIZER_LIMITS.minNotesWidth, maxWidth))
238
+ notesRowSize.value = Math.min(notesRowSize.value, Math.max(RESIZER_LIMITS.minNotesRowSize, maxRowSize))
239
+ }
240
+
86
241
  const SideEditor = shallowRef<any>()
87
242
  if (__DEV__ && __SLIDEV_FEATURE_EDITOR__)
88
243
  import('../internals/SideEditor.vue').then(v => SideEditor.value = v.default)
@@ -120,7 +275,34 @@ onMounted(() => {
120
275
  <CurrentProgressBar />
121
276
  <TimerBar />
122
277
  </div>
123
- <div class="grid-container" :class="`layout${presenterLayout}`">
278
+ <div
279
+ ref="gridContainer"
280
+ class="grid-container"
281
+ :class="`layout${presenterLayout}`"
282
+ :style="{
283
+ '--slidev-presenter-notes-width': `${notesWidth}px`,
284
+ '--slidev-presenter-notes-row-size': `${notesRowSize}px`,
285
+ '--slidev-presenter-bottom-height': `${bottomSectionHeight}px`,
286
+ }"
287
+ >
288
+ <!-- Unified vertical resizer for wide layout -->
289
+ <div
290
+ v-if="isNotesResizable && isNotesOnRight"
291
+ class="notes-vertical-resizer"
292
+ role="separator"
293
+ aria-orientation="vertical"
294
+ title="Resize notes panel"
295
+ @pointerdown="onNotesResizeStart"
296
+ />
297
+ <!-- Unified vertical resizer for layout 3 -->
298
+ <div
299
+ v-if="isNotesResizable && presenterLayout === 3"
300
+ class="notes-vertical-resizer-left"
301
+ role="separator"
302
+ aria-orientation="vertical"
303
+ title="Resize notes panel"
304
+ @pointerdown="onNotesResizeStart"
305
+ />
124
306
  <div ref="main" class="relative grid-section main flex flex-col">
125
307
  <div flex="~ gap-4 items-center" border="b main" p1>
126
308
  <span op50 px2>Current</span>
@@ -155,6 +337,14 @@ onMounted(() => {
155
337
  />
156
338
  </div>
157
339
  <div class="relative grid-section next flex flex-col p-2 lg:p-4">
340
+ <div
341
+ v-if="isNotesRowResizable && presenterLayout === 2"
342
+ class="notes-row-resizer top-[-6px]"
343
+ role="separator"
344
+ aria-orientation="horizontal"
345
+ title="Resize notes panel height"
346
+ @pointerdown="onNotesRowResizeStart"
347
+ />
158
348
  <SlideContainer v-if="nextFrame && nextFrameClicksCtx" key="next">
159
349
  <SlideWrapper
160
350
  :key="nextFrame[0].no"
@@ -172,45 +362,64 @@ onMounted(() => {
172
362
  Next
173
363
  </div>
174
364
  </div>
175
- <div v-if="SideEditor && showEditor" class="grid-section note of-auto">
176
- <SideEditor />
177
- </div>
178
- <div v-else class="grid-section note grid grid-rows-[1fr_min-content] overflow-hidden">
179
- <NoteEditable
180
- v-if="__DEV__"
181
- :key="`edit-${currentSlideNo}`"
182
- v-model:editing="notesEditing"
183
- :no="currentSlideNo"
184
- class="w-full max-w-full h-full overflow-auto p-2 lg:p-4"
185
- :clicks-context="clicksContext"
186
- :style="{ fontSize: `${presenterNotesFontSize}em` }"
365
+ <div ref="noteSection" class="relative grid-section note overflow-hidden">
366
+ <div
367
+ v-if="isNotesResizable && !isNotesOnRight && presenterLayout !== 3"
368
+ class="notes-resizer right-[-6px]"
369
+ role="separator"
370
+ aria-orientation="vertical"
371
+ title="Resize notes panel"
372
+ @pointerdown="onNotesResizeStart"
187
373
  />
188
- <NoteStatic
189
- v-else
190
- :key="`static-${currentSlideNo}`"
191
- :no="currentSlideNo"
192
- class="w-full max-w-full h-full overflow-auto p-2 lg:p-4"
193
- :style="{ fontSize: `${presenterNotesFontSize}em` }"
194
- :clicks-context="clicksContext"
374
+ <div
375
+ v-if="isNotesRowResizable && presenterLayout !== 2"
376
+ class="notes-row-resizer"
377
+ :class="isNotesOnBottom ? 'top-[-6px]' : 'bottom-[-6px]'"
378
+ role="separator"
379
+ aria-orientation="horizontal"
380
+ title="Resize notes panel height"
381
+ @pointerdown="onNotesRowResizeStart"
195
382
  />
196
- <div border-t border-main />
197
- <div class="py-1 px-2 text-sm transition" :class="inFocus ? '' : 'op25'">
198
- <IconButton title="Increase font size" @click="increasePresenterFontSize">
199
- <div class="i-carbon:zoom-in" />
200
- </IconButton>
201
- <IconButton title="Decrease font size" @click="decreasePresenterFontSize">
202
- <div class="i-carbon:zoom-out" />
203
- </IconButton>
204
- <IconButton
383
+
384
+ <SideEditor v-if="SideEditor && showEditor" class="h-full" />
385
+
386
+ <div v-else class="h-full grid grid-rows-[1fr_min-content]">
387
+ <NoteEditable
205
388
  v-if="__DEV__"
206
- title="Edit Notes"
207
- @click="notesEditing = !notesEditing"
208
- >
209
- <div class="i-carbon:edit" />
210
- </IconButton>
389
+ :key="`edit-${currentSlideNo}`"
390
+ v-model:editing="notesEditing"
391
+ :no="currentSlideNo"
392
+ class="w-full max-w-full h-full overflow-auto p-2 lg:p-4"
393
+ :clicks-context="clicksContext"
394
+ :style="{ fontSize: `${presenterNotesFontSize}em` }"
395
+ />
396
+ <NoteStatic
397
+ v-else
398
+ :key="`static-${currentSlideNo}`"
399
+ :no="currentSlideNo"
400
+ class="w-full max-w-full h-full overflow-auto p-2 lg:p-4"
401
+ :style="{ fontSize: `${presenterNotesFontSize}em` }"
402
+ :clicks-context="clicksContext"
403
+ />
404
+ <div border-t border-main />
405
+ <div class="py-1 px-2 text-sm transition" :class="inFocus ? '' : 'op25'">
406
+ <IconButton title="Increase font size" @click="increasePresenterFontSize">
407
+ <div class="i-carbon:zoom-in" />
408
+ </IconButton>
409
+ <IconButton title="Decrease font size" @click="decreasePresenterFontSize">
410
+ <div class="i-carbon:zoom-out" />
411
+ </IconButton>
412
+ <IconButton
413
+ v-if="__DEV__"
414
+ title="Edit Notes"
415
+ @click="notesEditing = !notesEditing"
416
+ >
417
+ <div class="i-carbon:edit" />
418
+ </IconButton>
419
+ </div>
211
420
  </div>
212
421
  </div>
213
- <div class="grid-section bottom flex">
422
+ <div ref="bottomSection" class="grid-section bottom flex">
214
423
  <NavControls :persist="true" class="transition" :class="inFocus ? '' : 'op25'" />
215
424
  <div flex-auto />
216
425
  <TimerInlined />
@@ -229,14 +438,16 @@ onMounted(() => {
229
438
  }
230
439
 
231
440
  .grid-container {
441
+ --slidev-presenter-notes-width: 360px;
442
+ --slidev-presenter-notes-row-size: 280px;
232
443
  --uno: bg-gray/20 flex-1 of-hidden;
233
444
  display: grid;
234
445
  gap: 1px 1px;
235
446
  }
236
447
 
237
448
  .grid-container.layout1 {
238
- grid-template-columns: 1fr 1fr;
239
- grid-template-rows: 2fr 1fr min-content;
449
+ grid-template-columns: var(--slidev-presenter-notes-width) minmax(0, 1fr);
450
+ grid-template-rows: minmax(0, 2fr) minmax(0, var(--slidev-presenter-notes-row-size)) min-content;
240
451
  grid-template-areas:
241
452
  'main main'
242
453
  'note next'
@@ -244,27 +455,18 @@ onMounted(() => {
244
455
  }
245
456
 
246
457
  .grid-container.layout2 {
247
- grid-template-columns: 3fr 2fr;
248
- grid-template-rows: 2fr 1fr min-content;
458
+ grid-template-columns: var(--slidev-presenter-notes-width) minmax(0, 1fr);
459
+ grid-template-rows: minmax(0, var(--slidev-presenter-notes-row-size)) minmax(0, 1fr) min-content;
249
460
  grid-template-areas:
250
461
  'note main'
251
462
  'note next'
252
463
  'bottom bottom';
253
464
  }
254
465
 
255
- .grid-container.layout3 {
256
- grid-template-columns: 2fr 3fr;
257
- grid-template-rows: 1fr 1fr min-content;
258
- grid-template-areas:
259
- 'note next'
260
- 'main next'
261
- 'bottom bottom';
262
- }
263
-
264
466
  @media (max-aspect-ratio: 3/5) {
265
467
  .grid-container.layout1 {
266
468
  grid-template-columns: 1fr;
267
- grid-template-rows: 1fr 1fr 1fr min-content;
469
+ grid-template-rows: 2fr 1fr 1fr min-content;
268
470
  grid-template-areas:
269
471
  'main'
270
472
  'note'
@@ -275,8 +477,8 @@ onMounted(() => {
275
477
 
276
478
  @media (min-aspect-ratio: 1/1) {
277
479
  .grid-container.layout1 {
278
- grid-template-columns: 1fr 1.1fr 0.9fr;
279
- grid-template-rows: 1fr 2fr min-content;
480
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) var(--slidev-presenter-notes-width);
481
+ grid-template-rows: minmax(0, 1fr) minmax(0, var(--slidev-presenter-notes-row-size)) min-content;
280
482
  grid-template-areas:
281
483
  'main main next'
282
484
  'main main note'
@@ -284,6 +486,15 @@ onMounted(() => {
284
486
  }
285
487
  }
286
488
 
489
+ .grid-container.layout3 {
490
+ grid-template-columns: var(--slidev-presenter-notes-width) minmax(0, 1fr);
491
+ grid-template-rows: minmax(0, var(--slidev-presenter-notes-row-size)) minmax(0, 1fr) min-content;
492
+ grid-template-areas:
493
+ 'note next'
494
+ 'main next'
495
+ 'bottom bottom';
496
+ }
497
+
287
498
  .grid-section {
288
499
  --uno: bg-main;
289
500
  }
@@ -302,4 +513,96 @@ onMounted(() => {
302
513
  .grid-section.bottom {
303
514
  grid-area: bottom;
304
515
  }
516
+
517
+ .notes-resizer {
518
+ position: absolute;
519
+ top: 0;
520
+ width: 12px;
521
+ height: 100%;
522
+ cursor: col-resize;
523
+ z-index: 10;
524
+ touch-action: none;
525
+ }
526
+
527
+ .notes-resizer::before {
528
+ content: '';
529
+ position: absolute;
530
+ left: 50%;
531
+ top: 0;
532
+ width: 1px;
533
+ height: 100%;
534
+ background-color: currentColor;
535
+ opacity: 0.2;
536
+ transform: translateX(-50%);
537
+ }
538
+
539
+ .notes-row-resizer {
540
+ position: absolute;
541
+ left: 0;
542
+ width: 100%;
543
+ height: 12px;
544
+ cursor: row-resize;
545
+ z-index: 10;
546
+ touch-action: none;
547
+ }
548
+
549
+ .notes-row-resizer::before {
550
+ content: '';
551
+ position: absolute;
552
+ left: 0;
553
+ top: 50%;
554
+ width: 100%;
555
+ height: 1px;
556
+ background-color: currentColor;
557
+ opacity: 0.2;
558
+ transform: translateY(-50%);
559
+ }
560
+
561
+ .notes-vertical-resizer {
562
+ position: absolute;
563
+ right: var(--slidev-presenter-notes-width);
564
+ top: 0;
565
+ bottom: var(--slidev-presenter-bottom-height, 0px);
566
+ width: 12px;
567
+ cursor: col-resize;
568
+ z-index: 10;
569
+ touch-action: none;
570
+ transform: translateX(50%);
571
+ }
572
+
573
+ .notes-vertical-resizer::before {
574
+ content: '';
575
+ position: absolute;
576
+ left: 50%;
577
+ top: 0;
578
+ width: 1px;
579
+ height: 100%;
580
+ background-color: currentColor;
581
+ opacity: 0.2;
582
+ transform: translateX(-50%);
583
+ }
584
+
585
+ .notes-vertical-resizer-left {
586
+ position: absolute;
587
+ left: var(--slidev-presenter-notes-width);
588
+ top: 0;
589
+ bottom: var(--slidev-presenter-bottom-height, 0px);
590
+ width: 12px;
591
+ cursor: col-resize;
592
+ z-index: 10;
593
+ touch-action: none;
594
+ transform: translateX(-50%);
595
+ }
596
+
597
+ .notes-vertical-resizer-left::before {
598
+ content: '';
599
+ position: absolute;
600
+ left: 50%;
601
+ top: 0;
602
+ width: 1px;
603
+ height: 100%;
604
+ background-color: currentColor;
605
+ opacity: 0.2;
606
+ transform: translateX(-50%);
607
+ }
305
608
  </style>
package/setup/shiki.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import setups from '#slidev/setups/shiki'
2
2
  import { createSingletonPromise } from '@antfu/utils'
3
3
  import { createJavaScriptRegexEngine } from '@shikijs/engine-javascript'
4
- import { createdBundledHighlighter, createSingletonShorthands } from 'shiki/core'
4
+ import { createBundledHighlighter, createSingletonShorthands } from 'shiki/core'
5
5
  import { resolveShikiOptions, shikiContext } from './shiki-options'
6
6
 
7
7
  export default createSingletonPromise(async () => {
8
8
  const { options, languageNames, languageInput, themeOption, themeNames, themeInput } = resolveShikiOptions(await Promise.all(setups.map(setup => setup(shikiContext))))
9
9
 
10
- const createHighlighter = createdBundledHighlighter<string, string>({
10
+ const createHighlighter = createBundledHighlighter<string, string>({
11
11
  engine: createJavaScriptRegexEngine,
12
12
  langs: languageInput,
13
13
  themes: themeInput,