Skip to content

Commit

Permalink
feat: add export options in frontmatter and to build args (#841)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
tonai and antfu committed Jan 25, 2023
1 parent 8a6b412 commit 3d40cfd
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 88 deletions.
3 changes: 2 additions & 1 deletion packages/parser/src/config.ts
@@ -1,5 +1,5 @@
import { toArray, uniq } from '@antfu/utils'
import type { DrawingsOptions, FontOptions, ResolvedDrawingsOptions, ResolvedFontOptions, SlidevConfig, SlidevThemeMeta } from '@slidev/types'
import type { DrawingsOptions, FontOptions, ResolvedDrawingsOptions, ResolvedExportOptions, ResolvedFontOptions, SlidevConfig, SlidevThemeMeta } from '@slidev/types'
import { parseAspectRatio } from './utils'

export function resolveConfig(headmatter: any, themeMeta: SlidevThemeMeta = {}, filepath?: string, verify = false) {
Expand All @@ -14,6 +14,7 @@ export function resolveConfig(headmatter: any, themeMeta: SlidevThemeMeta = {},
remoteAssets: false,
monaco: 'dev',
download: false,
export: {} as ResolvedExportOptions,
info: false,
highlighter: themeHightlighter || 'prism',
lineNumbers: false,
Expand Down
14 changes: 4 additions & 10 deletions packages/slidev/node/build.ts
Expand Up @@ -7,13 +7,15 @@ import { resolveConfig, build as viteBuild } from 'vite'
import connect from 'connect'
import sirv from 'sirv'
import { blue, yellow } from 'kolorist'
import type { BuildArgs } from '@slidev/types'
import { ViteSlidevPlugin } from './plugins/preset'
import { getIndexHtml, mergeViteConfigs } from './common'
import type { ResolvedSlidevOptions } from './options'

export async function build(
options: ResolvedSlidevOptions,
viteConfig: InlineConfig = {},
args: BuildArgs,
) {
const indexPath = resolve(options.userRoot, 'index.html')
const rawConfig = await resolveConfig({}, 'build', options.entry)
Expand Down Expand Up @@ -95,7 +97,6 @@ export async function build(
}

const outDir = resolve(options.userRoot, config.build.outDir)
const outFilename = options.data.config.exportFilename || 'slidev-exported.pdf'

// copy index.html to 404.html for GitHub Pages
await fs.copyFile(resolve(outDir, 'index.html'), resolve(outDir, '404.html'))
Expand All @@ -105,7 +106,7 @@ export async function build(
await fs.writeFile(redirectsPath, `${config.base}* ${config.base}index.html 200\n`, 'utf-8')

if ([true, 'true', 'auto'].includes(options.data.config.download)) {
const { exportSlides } = await import('./export')
const { exportSlides, getExportOptions } = await import('./export')

const port = 12445
const app = connect()
Expand All @@ -121,15 +122,8 @@ export async function build(
server.listen(port)
await exportSlides({
port,
slides: options.data.slides,
total: options.data.slides.length,
format: 'pdf',
output: join(outDir, outFilename),
base: config.base,
dark: options.data.config.colorSchema === 'dark',
width: options.data.config.canvasWidth,
height: Math.round(options.data.config.canvasWidth / options.data.config.aspectRatio),
routerMode: options.data.config.routerMode,
...getExportOptions(args, options, outDir, 'slidev-exported.pdf'),
})
server.close()
}
Expand Down
121 changes: 48 additions & 73 deletions packages/slidev/node/cli.ts
Expand Up @@ -201,7 +201,7 @@ cli.command(
cli.command(
'build [entry]',
'Build hostable SPA',
args => commonOptions(args)
args => exportOptions(commonOptions(args))
.option('watch', {
alias: 'w',
default: false,
Expand Down Expand Up @@ -229,7 +229,8 @@ cli.command(
})
.strict()
.help(),
async ({ entry, theme, watch, base, download, out, inspect }) => {
async (args) => {
const { entry, theme, watch, base, download, out, inspect } = args
const { build } = await import('./build')

const options = await resolveOptions({ entry, theme, inspect }, 'build')
Expand All @@ -243,7 +244,7 @@ cli.command(
watch: watch ? {} : undefined,
outDir: out,
},
})
}, args)
},
)

Expand Down Expand Up @@ -314,65 +315,15 @@ cli.command(
cli.command(
'export [entry]',
'Export slides to PDF',
args => commonOptions(args)
.option('output', {
type: 'string',
describe: 'path to the output',
})
.option('format', {
default: 'pdf',
type: 'string',
choices: ['pdf', 'png', 'md'],
describe: 'output format',
})
.option('timeout', {
default: 30000,
type: 'number',
describe: 'timeout for rendering the print page',
})
.option('range', {
type: 'string',
describe: 'page ranges to export, for example "1,4-5,6"',
})
.option('dark', {
default: false,
type: 'boolean',
describe: 'export as dark theme',
})
.option('with-clicks', {
alias: 'c',
default: false,
type: 'boolean',
describe: 'export pages for every clicks',
})
.option('executable-path', {
type: 'string',
describe: 'executable to override playwright bundled browser',
})
.option('with-toc', {
default: false,
type: 'boolean',
describe: 'export pages with outline',
})
args => exportOptions(commonOptions(args))
.strict()
.help(),
async ({
entry,
theme,
output,
format,
timeout,
range,
dark,
'with-clicks': withClicks,
'executable-path': executablePath,
'with-toc': withTOC,
}) => {
async (args) => {
const { entry, theme } = args
process.env.NODE_ENV = 'production'
const { exportSlides } = await import('./export')
const { exportSlides, getExportOptions } = await import('./export')
const port = await findFreePort(12445)
const options = await resolveOptions({ entry, theme }, 'export')
output = output || options.data.config.exportFilename || `${path.basename(entry, '.md')}-export`
const server = await createServer(
options,
{
Expand All @@ -383,23 +334,9 @@ cli.command(
await server.listen(port)
printInfo(options)
parser.filterDisabled(options.data)
const width = options.data.config.canvasWidth
const height = Math.round(width / options.data.config.aspectRatio)
output = await exportSlides({
const output = await exportSlides({
port,
slides: options.data.slides,
total: options.data.slides.length,
range,
format: format as any,
output,
timeout,
dark,
routerMode: options.data.config.routerMode,
width,
height,
withClicks,
executablePath,
withTOC,
...getExportOptions(args, options),
})
console.log(`${green(' ✓ ')}${dim('exported to ')}./${output}\n`)
server.close()
Expand Down Expand Up @@ -483,6 +420,44 @@ function commonOptions(args: Argv<{}>) {
})
}

function exportOptions<T>(args: Argv<T>) {
return args
.option('output', {
type: 'string',
describe: 'path to the output',
})
.option('format', {
type: 'string',
choices: ['pdf', 'png', 'md'],
describe: 'output format',
})
.option('timeout', {
type: 'number',
describe: 'timeout for rendering the print page',
})
.option('range', {
type: 'string',
describe: 'page ranges to export, for example "1,4-5,6"',
})
.option('dark', {
type: 'boolean',
describe: 'export as dark theme',
})
.option('with-clicks', {
alias: 'c',
type: 'boolean',
describe: 'export pages for every clicks',
})
.option('executable-path', {
type: 'string',
describe: 'executable to override playwright bundled browser',
})
.option('with-toc', {
type: 'boolean',
describe: 'export pages with outline',
})
}

function printInfo(options: ResolvedSlidevOptions, port?: number, remote?: string) {
console.log()
console.log()
Expand Down
48 changes: 44 additions & 4 deletions packages/slidev/node/export.ts
Expand Up @@ -3,10 +3,11 @@ import fs from 'fs-extra'
import { blue, cyan, dim, green, yellow } from 'kolorist'
import { Presets, SingleBar } from 'cli-progress'
import { parseRangeString } from '@slidev/parser/core'
import type { SlideInfo, TocItem } from '@slidev/types'
import type { ExportArgs, SlideInfo, TocItem } from '@slidev/types'
import { outlinePdfFactory } from '@lillallol/outline-pdf'
import * as pdfLib from 'pdf-lib'
import { PDFDocument } from 'pdf-lib'
import type { ResolvedSlidevOptions } from './options'
import { packageExists } from './utils'

export interface ExportOptions {
Expand All @@ -24,7 +25,7 @@ export interface ExportOptions {
height?: number
withClicks?: boolean
executablePath?: string
withTOC?: boolean
withToc?: boolean
}

function addToTree(tree: TocItem[], info: SlideInfo, slideIndexes: Record<number, number>, level = 1) {
Expand Down Expand Up @@ -155,7 +156,7 @@ export async function exportSlides({
height = 1080,
withClicks = false,
executablePath = undefined,
withTOC = false,
withToc = false,
}: ExportOptions) {
if (!packageExists('playwright-chromium'))
throw new Error('The exporting for Slidev is powered by Playwright, please installed it via `npm i -D playwright-chromium`')
Expand Down Expand Up @@ -249,7 +250,7 @@ export async function exportSlides({
if (titleSlide?.frontmatter?.info)
pdf.setSubject(titleSlide.frontmatter.info)

if (withTOC) {
if (withToc) {
const outlinePdf = outlinePdfFactory(pdfLib)

const tocTree = slides.filter(slide => slide.title)
Expand Down Expand Up @@ -321,3 +322,42 @@ export async function exportSlides({
browser.close()
return output
}

export function getExportOptions(args: ExportArgs, options: ResolvedSlidevOptions, outDir?: string, outFilename?: string): Omit<ExportOptions, 'port' | 'base'> {
const config = {
...options.data.config.export,
...args,
withClicks: args['with-clicks'],
executablePath: args['executable-path'],
withToc: args['with-toc'],
}
const {
entry,
output,
format,
timeout,
range,
dark,
withClicks,
executablePath,
withToc,
} = config
outFilename = output || options.data.config.exportFilename || outFilename || `${path.basename(entry, '.md')}-export`
if (outDir)
outFilename = path.join(outDir, outFilename)
return {
output: outFilename,
slides: options.data.slides,
total: options.data.slides.length,
range,
format: (format || 'pdf') as 'pdf' | 'png' | 'md',
timeout: timeout || 30000,
dark: dark || options.data.config.colorSchema === 'dark',
routerMode: options.data.config.routerMode,
width: options.data.config.canvasWidth,
height: Math.round(options.data.config.canvasWidth / options.data.config.aspectRatio),
withClicks: withClicks || false,
executablePath,
withToc: withToc || false,
}
}
23 changes: 23 additions & 0 deletions packages/types/src/cli.ts
@@ -0,0 +1,23 @@
export interface CommonArgs {
entry: string
theme?: string
}

export interface ExportArgs extends CommonArgs {
output?: string
format?: string
timeout?: number
range?: string
dark?: boolean
'with-clicks'?: boolean
'executable-path'?: string
'with-toc'?: boolean
}

export interface BuildArgs extends ExportArgs {
watch: boolean
out: string
base?: string
download?: boolean
inspect: boolean
}
13 changes: 13 additions & 0 deletions packages/types/src/config.ts
@@ -1,3 +1,4 @@
import type { ExportArgs } from './cli'
import type { SlidevThemeConfig } from './types'

export interface SlidevConfig {
Expand Down Expand Up @@ -42,6 +43,12 @@ export interface SlidevConfig {
* @default false
*/
download: boolean | string
/**
* Options for export
*
* @default {}
*/
export: ResolvedExportOptions
/**
* Show a copy button in code blocks
*
Expand Down Expand Up @@ -273,3 +280,9 @@ export interface ResolvedDrawingsOptions {
presenterOnly: boolean
syncAll: boolean
}

export interface ResolvedExportOptions extends Omit<ExportArgs, 'entry' | 'theme'> {
withClicks?: boolean
executablePath?: string
withToc?: boolean
}
1 change: 1 addition & 0 deletions packages/types/src/index.ts
Expand Up @@ -2,3 +2,4 @@ export * from './types'
export * from './setups'
export * from './config'
export * from './toc'
export * from './cli'
3 changes: 3 additions & 0 deletions test/__snapshots__/parser.test.ts.snap
Expand Up @@ -15,6 +15,7 @@ exports[`md parser > frontmatter.md > config 1`] = `
"presenterOnly": false,
"syncAll": true,
},
"export": {},
"exportFilename": "",
"favicon": "https://cdn.jsdelivr.net/gh/slidevjs/slidev/assets/favicon.png",
"fonts": {
Expand Down Expand Up @@ -250,6 +251,7 @@ exports[`md parser > minimal.md > config 1`] = `
"presenterOnly": false,
"syncAll": true,
},
"export": {},
"exportFilename": "",
"favicon": "https://cdn.jsdelivr.net/gh/slidevjs/slidev/assets/favicon.png",
"fonts": {
Expand Down Expand Up @@ -423,6 +425,7 @@ exports[`md parser > multi-entries.md > config 1`] = `
"presenterOnly": false,
"syncAll": true,
},
"export": {},
"exportFilename": "",
"favicon": "https://cdn.jsdelivr.net/gh/slidevjs/slidev/assets/favicon.png",
"fonts": {
Expand Down

0 comments on commit 3d40cfd

Please sign in to comment.