Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 502f99c

Browse files
authored
fix: markdown format export (#2077)
1 parent 6d2fd55 commit 502f99c

File tree

3 files changed

+53
-59
lines changed

3 files changed

+53
-59
lines changed

packages/slidev/node/cli.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ cli.command(
481481
port,
482482
...getExportOptions({ ...args, entry: entryFile }, options),
483483
})
484-
console.log(`${green(' ✓ ')}${dim('exported to ')}./${result}\n`)
484+
console.log(`${green(' ✓ ')}${dim('exported to ')}${result}\n`)
485485
server.close()
486486
}
487487

@@ -542,7 +542,7 @@ cli.command(
542542
timeout,
543543
wait,
544544
})
545-
console.log(`${green(' ✓ ')}${dim('exported to ')}./${result}\n`)
545+
console.log(`${green(' ✓ ')}${dim('exported to ')}${result}\n`)
546546

547547
server.close()
548548
}

packages/slidev/node/commands/build.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { InlineConfig, ResolvedConfig } from 'vite'
33
import { existsSync } from 'node:fs'
44
import fs from 'node:fs/promises'
55
import http from 'node:http'
6-
import { resolve } from 'node:path'
6+
import { join, resolve } from 'node:path'
77
import connect from 'connect'
88
import sirv from 'sirv'
99
import { build as viteBuild } from 'vite'
@@ -79,7 +79,7 @@ export async function build(
7979
await exportSlides({
8080
port,
8181
base: config.base,
82-
...getExportOptions(args, options, outDir, 'slidev-exported.pdf'),
82+
...getExportOptions(args, options, join(outDir, 'slidev-exported.pdf')),
8383
})
8484
server.close()
8585
}

packages/slidev/node/commands/export.ts

+49-55
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { ExportArgs, ResolvedSlidevOptions, SlideInfo, TocItem } from '@slidev/types'
22
import { Buffer } from 'node:buffer'
33
import fs from 'node:fs/promises'
4-
import path from 'node:path'
4+
import path, { dirname, relative } from 'node:path'
55
import process from 'node:process'
6-
import { clearUndefined, slash } from '@antfu/utils'
6+
import { clearUndefined, ensureSuffix, slash } from '@antfu/utils'
77
import { outlinePdfFactory } from '@lillallol/outline-pdf'
88
import { parseRangeString } from '@slidev/parser/core'
99
import { blue, cyan, dim, green, yellow } from 'ansis'
@@ -43,6 +43,7 @@ export interface ExportOptions {
4343
interface ExportPngResult {
4444
slideIndex: number
4545
buffer: Buffer
46+
filename: string
4647
}
4748

4849
function addToTree(tree: TocItem[], info: SlideInfo, slideIndexes: Record<number, number>, level = 1) {
@@ -199,6 +200,30 @@ export async function exportSlides({
199200
})
200201
const page = await context.newPage()
201202
const progress = createSlidevProgress(!perSlide)
203+
progress.start(pages.length)
204+
205+
if (format === 'pdf') {
206+
await genPagePdf()
207+
}
208+
else if (format === 'png') {
209+
await genPagePng(output)
210+
}
211+
else if (format === 'md') {
212+
await genPageMd()
213+
}
214+
else if (format === 'pptx') {
215+
const buffers = await genPagePng(false)
216+
await genPagePptx(buffers)
217+
}
218+
else {
219+
throw new Error(`[slidev] Unsupported exporting format "${format}"`)
220+
}
221+
222+
progress.stop()
223+
browser.close()
224+
225+
const relativeOutput = slash(relative('.', output))
226+
return relativeOutput.startsWith('.') ? relativeOutput : `./${relativeOutput}`
202227

203228
async function go(no: number | string, clicks?: string) {
204229
const query = new URLSearchParams()
@@ -390,11 +415,9 @@ export async function exportSlides({
390415
await fs.writeFile(output, pdfData)
391416
}
392417

393-
async function genPagePngOnePiece(writeToDisk: boolean) {
418+
async function genPagePngOnePiece(writeToDisk: string | false) {
394419
const result: ExportPngResult[] = []
395420
await go('print')
396-
await fs.rm(output, { force: true, recursive: true })
397-
await fs.mkdir(output, { recursive: true })
398421
const slideContainers = page.locator('.print-slide-container')
399422
const count = await slideContainers.count()
400423
for (let i = 0; i < count; i++) {
@@ -404,24 +427,26 @@ export async function exportSlides({
404427
const buffer = await slideContainers.nth(i).screenshot({
405428
omitBackground,
406429
})
407-
result.push({ slideIndex: slideNo - 1, buffer })
430+
const filename = `${withClicks ? id : slideNo}.png`
431+
result.push({ slideIndex: slideNo - 1, buffer, filename })
408432
if (writeToDisk)
409-
await fs.writeFile(path.join(output, `${withClicks ? id : slideNo}.png`), buffer)
433+
await fs.writeFile(path.join(writeToDisk, filename), buffer)
410434
}
411435
return result
412436
}
413437

414-
async function genPagePngPerSlide(writeToDisk: boolean) {
438+
async function genPagePngPerSlide(writeToDisk: string | false) {
415439
const result: ExportPngResult[] = []
416440
const genScreenshot = async (no: number, clicks?: string) => {
417441
await go(no, clicks)
418442
const buffer = await page.screenshot({
419443
omitBackground,
420444
})
421-
result.push({ slideIndex: no - 1, buffer })
445+
const filename = `${no.toString().padStart(2, '0')}${clicks ? `-${clicks}` : ''}.png`
446+
result.push({ slideIndex: no - 1, buffer, filename })
422447
if (writeToDisk) {
423448
await fs.writeFile(
424-
path.join(output, `${no.toString().padStart(2, '0')}${clicks ? `-${clicks}` : ''}.png`),
449+
path.join(writeToDisk, filename),
425450
buffer,
426451
)
427452
}
@@ -439,25 +464,25 @@ export async function exportSlides({
439464
: genPagePdfOnePiece()
440465
}
441466

442-
function genPagePng(writeToDisk = true) {
467+
async function genPagePng(writeToDisk: string | false) {
468+
if (writeToDisk) {
469+
await fs.rm(writeToDisk, { force: true, recursive: true })
470+
await fs.mkdir(writeToDisk, { recursive: true })
471+
}
443472
return perSlide
444473
? genPagePngPerSlide(writeToDisk)
445474
: genPagePngOnePiece(writeToDisk)
446475
}
447476

448477
async function genPageMd() {
449-
const files = await fs.readdir(output)
450-
const mds: string[] = files.map((file, i, files) => {
451-
const slideIndex = getSlideIndex(file)
452-
const mdImg = `![${slides[slideIndex]?.title}](./${slash(path.join(output, file))})\n\n`
453-
if ((i + 1 === files.length || getSlideIndex(files[i + 1]) !== slideIndex) && slides[slideIndex]?.note)
454-
return `${mdImg}${slides[slideIndex]?.note}\n\n`
455-
return mdImg
456-
})
457-
458-
if (!output.endsWith('.md'))
459-
output = `${output}.md`
460-
await fs.writeFile(output, mds.join(''))
478+
const pngs = await genPagePng(dirname(output))
479+
const content = slides.map(({ title, index, note }) =>
480+
pngs.filter(({ slideIndex }) => slideIndex === index)
481+
.map(({ filename }) => `![${title || (index + 1)}](./${filename})\n\n`)
482+
.join('')
483+
+ (note ? `${note.trim()}\n\n` : ''),
484+
).join('---\n\n')
485+
await fs.writeFile(ensureSuffix('.md', output), content)
461486
}
462487

463488
// Ported from https://github.com/marp-team/marp-cli/blob/main/src/converter.ts
@@ -500,11 +525,6 @@ export async function exportSlides({
500525
await fs.writeFile(output, buffer)
501526
}
502527

503-
function getSlideIndex(file: string): number {
504-
const slideId = file.substring(0, file.indexOf('.')).split('-')[0]
505-
return Number(slideId) - 1
506-
}
507-
508528
// Adds metadata (title, author, keywords) to PDF document, mutating it
509529
function addPdfMetadata(pdf: PDFDocument): void {
510530
const titleSlide = slides[0]
@@ -536,33 +556,9 @@ export async function exportSlides({
536556

537557
return await outlinePdf({ outline, pdf })
538558
}
539-
540-
progress.start(pages.length)
541-
542-
if (format === 'pdf') {
543-
await genPagePdf()
544-
}
545-
else if (format === 'png') {
546-
await genPagePng()
547-
}
548-
else if (format === 'md') {
549-
await genPagePng()
550-
await genPageMd()
551-
}
552-
else if (format === 'pptx') {
553-
const buffers = await genPagePng(false)
554-
await genPagePptx(buffers)
555-
}
556-
else {
557-
throw new Error(`Unsupported exporting format "${format}"`)
558-
}
559-
560-
progress.stop()
561-
browser.close()
562-
return output
563559
}
564560

565-
export function getExportOptions(args: ExportArgs, options: ResolvedSlidevOptions, outDir?: string, outFilename?: string): Omit<ExportOptions, 'port' | 'base'> {
561+
export function getExportOptions(args: ExportArgs, options: ResolvedSlidevOptions, outFilename?: string): Omit<ExportOptions, 'port' | 'base'> {
566562
const config = {
567563
...options.data.config.export,
568564
...args,
@@ -592,8 +588,6 @@ export function getExportOptions(args: ExportArgs, options: ResolvedSlidevOption
592588
omitBackground,
593589
} = config
594590
outFilename = output || options.data.config.exportFilename || outFilename || `${path.basename(entry, '.md')}-export`
595-
if (outDir)
596-
outFilename = path.join(outDir, outFilename)
597591
return {
598592
output: outFilename,
599593
slides: options.data.slides,

0 commit comments

Comments
 (0)