slidev icon indicating copy to clipboard operation
slidev copied to clipboard

useNav() property currentSlideNo is not reactive when exporting the slides to pdf

Open johannchopin opened this issue 1 year ago • 4 comments

First of all thanks for the work put on this project 👏

Context

I wanted to create a vue computed function useBreadcrumb that based on tocTree and currentSlideNo from useNav() give back the array of titles to be able to render a breadcrumb on each slides. Final goal was to release an add-on.

Describe the bug

When I use the following approach to display the current slide number, it's working well in the webview but during the export to pdf the value is always 1:

<script>
import {  useNav } from '@slidev/client'
const { currentSlideNo } = useNav()
</script>

<template>
  {{ currentSlideNo }}
</template>

I don't have this issue when I use directly $nav.currentSlideNo.

Minimal reproduction

I created a minimal reproductible example at https://github.com/johannchopin/slidev-currentSlideNo-bug-in-pdf. In the global-bottom.vue file I display the value of $nav.currentSlideNo and the SlideNo.vue component render the currentSlideNo value. The result can be see in the exported PDF slides-export.pdf.

Environment

  • Slidev version: Used @slidev/cli@^0.49.20 to generate the dummy repo
  • Browser: Chrome
  • OS: Windows

johannchopin avatar Jul 23 '24 09:07 johannchopin

How about move global-bottom.vue to layouts/slide-bottom.vue (a slide layer, described in https://sli.dev/features/global-layers)?

Global layers are considered singleton, which may cause problems when exporting.

Or try the following code instead:

import { useSlideContext } from '@slidev/client'
const { $nav } = useSlideContext()
$nav.value.currentSlideNo

kermanx avatar Jul 23 '24 09:07 kermanx

@KermanX Thanks for the fast reply. In my real case issue it's not related to the global-bottom.vue component so it didn't change anything. I tried using $nav.value.currentSlideNo but then the value was not reactive in the webview and invalid during the export. However I tried using the --per-slide option during the export and doing so const { currentSlideNo } = useNav() is working as expected.

I still found a bit weird that currentSlideNo from useNav() is not working the same way as the one from $nav 🤔 What's your opinion?

johannchopin avatar Jul 23 '24 10:07 johannchopin

I still found a bit weird that currentSlideNo from useNav() is not working the same way as the one from $nav 🤔 What's your opinion?

In fact, this has been a long-standing problem. The root cause is that there are different navigation states for each slide when exporting without the --per-slide flag, while useNav is a singleton composable that returns the same value wherever it's called.

However, we can improve this by using the same way as useSlideContext() - Vue's provide & inject in the future.

kermanx avatar Jul 23 '24 10:07 kermanx

That would be nice yes 👍 As there is a "solid" workaround I don't think it's a critical bug, but maybe it would be nice to add a Tip note in the composable usage documentation (something equivalent to https://sli.dev/features/global-layers#global-layers). What do you think?

johannchopin avatar Jul 23 '24 11:07 johannchopin