Skip to content

Commit

Permalink
fix(export): export with --per-slide
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Mar 22, 2024
1 parent a00a301 commit 2ae4325
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 22 deletions.
20 changes: 15 additions & 5 deletions packages/client/composables/useNav.ts
Expand Up @@ -86,6 +86,7 @@ export function useNavBase(
clicksContext: ComputedRef<ClicksContext>,
queryClicks: Ref<number> = ref(0),
isPresenter: Ref<boolean>,
isPrint: Ref<boolean>,
router?: Router,
): SlidevContextNav {
const total = computed(() => slides.value.length)
Expand Down Expand Up @@ -157,7 +158,9 @@ export function useNavBase(
await go(
next,
lastClicks
? getSlide(next)?.meta.__clicksContext?.total ?? CLICKS_MAX
? isPrint.value
? undefined
: getSlide(next)?.meta.__clicksContext?.total ?? CLICKS_MAX
: undefined,
)
}
Expand Down Expand Up @@ -226,6 +229,7 @@ export function useFixedNav(
computed(() => clicksContext),
ref(CLICKS_MAX),
ref(false),
ref(false),
),
next: noop,
prev: noop,
Expand All @@ -241,13 +245,18 @@ const useNavState = createSharedComposable((): SlidevContextNavState => {
const router = useRouter()

const currentRoute = computed(() => router.currentRoute.value)
const isPrintMode = computed(() => currentRoute.value.query.print !== undefined)
const isPrintWithClicks = computed(() => currentRoute.value.query.print === 'clicks')
const isEmbedded = computed(() => currentRoute.value.query.embedded !== undefined)
const query = computed(() => {
// eslint-disable-next-line no-unused-expressions
router.currentRoute.value.query
return new URLSearchParams(location.search)
})
const isPrintMode = computed(() => query.value.has('print'))
const isPrintWithClicks = computed(() => query.value.get('print') === 'clicks')
const isEmbedded = computed(() => query.value.has('embedded'))
const isPlaying = computed(() => currentRoute.value.name === 'play')
const isPresenter = computed(() => currentRoute.value.name === 'presenter')
const isNotesViewer = computed(() => currentRoute.value.name === 'notes')
const isPresenterAvailable = computed(() => !isPresenter.value && (!configs.remote || currentRoute.value.query.password === configs.remote))
const isPresenterAvailable = computed(() => !isPresenter.value && (!configs.remote || query.value.get('password') === configs.remote))
const hasPrimarySlide = logicOr(isPlaying, isPresenter)

const currentSlideNo = computed(() => hasPrimarySlide.value ? getSlide(currentRoute.value.params.no as string)?.no ?? 1 : 1)
Expand Down Expand Up @@ -335,6 +344,7 @@ export const useNav = createSharedComposable((): SlidevContextNavFull => {
state.clicksContext,
state.queryClicks,
state.isPresenter,
state.isPrintMode,
router,
)

Expand Down
3 changes: 2 additions & 1 deletion packages/client/internals/SlideWrapper.vue
Expand Up @@ -55,7 +55,7 @@ const SlideComponent = defineAsyncComponent({
return defineComponent({
setup(_, { attrs }) {
onMounted(() => {
props.clicksContext.onMounted()
props.clicksContext?.onMounted?.()
})
return () => h(component.default, attrs)
},
Expand All @@ -70,6 +70,7 @@ const SlideComponent = defineAsyncComponent({
<component
:is="SlideComponent"
:style="style"
:data-slidev-no="props.route.no"
:class="{ 'disable-view-transition': !['slide', 'presenter'].includes(props.renderContext) }"
/>
</template>
Expand Down
6 changes: 5 additions & 1 deletion packages/client/internals/SlidesShow.vue
Expand Up @@ -5,6 +5,8 @@ import { useNav } from '../composables/useNav'
import { getSlideClass } from '../utils'
import { useViewTransition } from '../composables/useViewTransition'
import { skipTransition } from '../logic/hmr'
import { createFixedClicks } from '../composables/useClicks'
import { CLICKS_MAX } from '../constants'
import SlideWrapper from './SlideWrapper.vue'
import PresenterMouse from './PresenterMouse.vue'
Expand All @@ -22,6 +24,8 @@ const {
isPresenter,
nextRoute,
slides,
isPrintMode,
isPrintWithClicks,
} = useNav()
// preload next route
Expand Down Expand Up @@ -68,7 +72,7 @@ function onAfterLeave() {
>
<SlideWrapper
:is="route.component!"
:clicks-context="getPrimaryClicks(route)"
:clicks-context="isPrintMode && !isPrintWithClicks ? createFixedClicks(route, CLICKS_MAX) : getPrimaryClicks(route)"
:class="getSlideClass(route)"
:route="route"
:render-context="renderContext"
Expand Down
5 changes: 3 additions & 2 deletions packages/client/pages/play.vue
Expand Up @@ -63,6 +63,7 @@ if (__SLIDEV_FEATURE_DRAWINGS__)
</template>
<template #controls>
<div
v-if="!isPrintMode"
class="absolute bottom-0 left-0 transition duration-300 opacity-0 hover:opacity-100"
:class="[
persistNav ? '!opacity-100 right-0' : 'opacity-0 p-2',
Expand All @@ -81,5 +82,5 @@ if (__SLIDEV_FEATURE_DRAWINGS__)
<SideEditor :resize="true" />
</template>
</div>
<Controls />
</template>../composables/drawings
<Controls v-if="!isPrintMode" />
</template>
48 changes: 35 additions & 13 deletions packages/slidev/node/commands/export.ts
@@ -1,5 +1,6 @@
import path from 'node:path'
import { Buffer } from 'node:buffer'
import process from 'node:process'
import fs from 'fs-extra'
import { blue, cyan, dim, green, yellow } from 'kolorist'
import { Presets, SingleBar } from 'cli-progress'
Expand Down Expand Up @@ -183,7 +184,17 @@ export async function exportSlides({
const progress = createSlidevProgress(!perSlide)

async function go(no: number | string, clicks?: string) {
const path = `${no}?print${withClicks ? '=clicks' : ''}${clicks ? `&clicks=${clicks}` : ''}${range ? `&range=${range}` : ''}`
const query = new URLSearchParams()
if (withClicks)
query.set('print', 'clicks')
else
query.set('print', 'true')
if (range)
query.set('range', range)
if (clicks)
query.set('clicks', clicks)

const path = `${no}?${query.toString()}`
const url = routerMode === 'hash'
? `http://localhost:${port}${base}#${path}`
: `http://localhost:${port}${base}${path}`
Expand All @@ -193,22 +204,30 @@ export async function exportSlides({
})
await page.waitForLoadState('networkidle')
await page.emulateMedia({ colorScheme: dark ? 'dark' : 'light', media: 'screen' })
const slide = page.locator(`[data-slidev-no="${no}"]`)
await slide.waitFor({ state: 'visible' })

// Wait for slides to be loaded
{
const elements = page.locator('.slidev-slide-loading')
const elements = slide.locator('.slidev-slide-loading')
const count = await elements.count()
for (let index = 0; index < count; index++)
await elements.nth(index).waitFor({ state: 'detached' })
}
// Check for "data-waitfor" attribute and wait for given element to be loaded
{
const elements = page.locator('[data-waitfor]')
const elements = slide.locator('[data-waitfor]')
const count = await elements.count()
for (let index = 0; index < count; index++) {
const element = elements.nth(index)
const attribute = await element.getAttribute('data-waitfor')
if (attribute)
await element.locator(attribute).waitFor()
if (attribute) {
await element.locator(attribute).waitFor({ state: 'visible' })
.catch((e) => {
console.error(e)
process.exitCode = 1
})
}
}
}
// Wait for frames to load
Expand All @@ -218,18 +237,21 @@ export async function exportSlides({
}
// Wait for Mermaid graphs to be rendered
{
const container = page.locator('#mermaid-rendering-container')
while (true) {
const element = container.locator('div').first()
if (await element.count() === 0)
break
await element.waitFor({ state: 'detached' })
const container = slide.locator('#mermaid-rendering-container')
const count = await container.count()
if (count > 0) {
while (true) {
const element = container.locator('div').first()
if (await element.count() === 0)
break
await element.waitFor({ state: 'detached' })
}
await container.evaluate(node => node.style.display = 'none')
}
await container.evaluate(node => node.style.display = 'none')
}
// Hide Monaco aria container
{
const elements = page.locator('.monaco-aria-container')
const elements = slide.locator('.monaco-aria-container')
const count = await elements.count()
for (let index = 0; index < count; index++) {
const element = elements.nth(index)
Expand Down

0 comments on commit 2ae4325

Please sign in to comment.