Skip to content

Commit 4468a50

Browse files
committed
feat: improve cli
1 parent e830f50 commit 4468a50

5 files changed

Lines changed: 194 additions & 85 deletions

File tree

packages/slidev/node/cli.ts

Lines changed: 108 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,115 @@
1-
/* eslint-disable @typescript-eslint/no-var-requires */
2-
import chalk from 'chalk'
3-
import minimist from 'minimist'
1+
import path from 'path'
2+
import fs from 'fs-extra'
3+
import yargs, { Argv } from 'yargs'
4+
import { prompt } from 'enquirer'
5+
import { blue } from 'kolorist'
6+
import { version } from '../package.json'
7+
import { build } from './build'
8+
import { createServer } from './server'
9+
import * as parser from './parser'
410

5-
const argv: any = minimist(process.argv.slice(2))
6-
7-
console.log(chalk.cyan`Slidev ` + chalk.yellow`v${require('../package.json').version}`)
8-
9-
const command = argv._[0]
10-
const entry = argv._[command ? 1 : 0] || 'slides.md'
11-
12-
if (!command || command === 'dev') {
13-
import('./server')
14-
.then(i => i.createServer(entry, argv))
15-
.then(server => server.listen())
16-
.catch((err) => {
17-
console.error(chalk.red('failed to start server. error:\n'), err)
18-
process.exit(1)
11+
function commonOptions(args: Argv<{}>) {
12+
return args
13+
.positional('entry', {
14+
default: 'slides.md',
15+
type: 'string',
16+
describe: 'path to the slides markdown entry',
1917
})
20-
}
21-
else if (command === 'build') {
22-
import('./build')
23-
.then(i => i.build(entry, argv))
24-
.catch((err) => {
25-
console.error(chalk.red('build error:\n'), err)
26-
process.exit(1)
18+
.option('template', {
19+
alias: 't',
20+
type: 'string',
21+
describe: 'overide theme',
2722
})
2823
}
29-
else if (command === 'export') {
30-
import('./export')
31-
.then(i => i.genratePDF(entry, argv))
32-
.catch((err) => {
33-
console.error(chalk.red('export error:\n'), err)
34-
process.exit(1)
24+
25+
const cli = yargs
26+
.scriptName('slidev')
27+
.usage('$0 [args]')
28+
.version(version)
29+
.showHelpOnFail(false)
30+
.alias('h', 'help')
31+
.alias('v', 'version')
32+
33+
cli.command(
34+
'* [entry]',
35+
'Start a local server for Slidev',
36+
args => commonOptions(args)
37+
.option('port', {
38+
alias: 'p',
39+
default: 3030,
40+
type: 'number',
41+
describe: 'port',
3542
})
36-
}
37-
else if (command === 'format') {
38-
import('./parser')
39-
.then(async({ load, prettify, save }) => {
40-
const data = await load(entry)
41-
prettify(data)
42-
await save(data)
43+
.option('open', {
44+
alias: 'o',
45+
default: true,
46+
type: 'boolean',
47+
describe: 'open in browser',
4348
})
44-
.catch((err) => {
45-
console.error(chalk.red('export error:\n'), err)
46-
process.exit(1)
49+
.help(),
50+
async({ entry, port, open }) => {
51+
if (!fs.existsSync(entry)) {
52+
const { create } = await prompt<{create: boolean}>({
53+
name: 'create',
54+
type: 'confirm',
55+
message: `Entry file ${entry} does not exist, do you want to create it?`,
56+
})
57+
if (create)
58+
await fs.copyFile(path.resolve(__dirname, '../template.md'), entry)
59+
else
60+
process.exit(0)
61+
}
62+
63+
const server = await createServer(entry, {
64+
server: {
65+
port,
66+
open,
67+
},
4768
})
48-
}
49-
else {
50-
console.log(chalk.red(`unknown command "${command}".`))
51-
process.exit(1)
52-
}
69+
server.listen()
70+
server.watcher.add(entry)
71+
},
72+
)
73+
74+
cli.command(
75+
'build [entry]',
76+
'Build hostable SPA',
77+
args => commonOptions(args)
78+
.help(),
79+
async({ entry }) => {
80+
await build(entry)
81+
},
82+
)
83+
84+
cli.command(
85+
'format [entry]',
86+
'Format the markdown file',
87+
args => commonOptions(args)
88+
.help(),
89+
async({ entry }) => {
90+
const data = await parser.load(entry)
91+
parser.prettify(data)
92+
await parser.save(data)
93+
},
94+
)
95+
96+
cli.command(
97+
'export [entry]',
98+
'Export slides to PDF',
99+
args => commonOptions(args)
100+
.option('output', {
101+
type: 'string',
102+
describe: 'path to the the port output',
103+
})
104+
.help(),
105+
async({ entry, output }) => {
106+
output = output || `${path.basename(entry, '.md')}.pdf`
107+
process.env.NODE_ENV = 'production'
108+
const { genratePDF } = await import('./export')
109+
await genratePDF(entry, output, { logLevel: 'error' })
110+
console.log(blue(`PDF Exported: ./${output}`))
111+
process.exit(0)
112+
},
113+
)
114+
115+
cli.help().parse()

packages/slidev/node/export.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { promises as fs } from 'fs'
22
import { chromium } from 'playwright'
33
import { InlineConfig } from 'vite'
44
import { PDFDocument } from 'pdf-lib'
5-
import { green } from 'chalk'
5+
import { yellow } from 'kolorist'
66
import { createServer } from './server'
77
import { filterDisabled, load } from './parser'
88

9-
export async function genratePDF(entry = 'slides.md', config: InlineConfig = {}) {
9+
export async function genratePDF(entry = 'slides.md', output = 'slides.pdf', config: InlineConfig = {}) {
1010
const { slides } = filterDisabled(await load(entry))
1111
const server = await createServer(entry, {
1212
...config,
@@ -29,7 +29,7 @@ export async function genratePDF(entry = 'slides.md', config: InlineConfig = {})
2929
const buffers: Buffer[] = []
3030
const pagesCount = slides.length
3131
for (let i = 0; i < pagesCount; i++) {
32-
console.log(`Exporting: ${i + 1} / ${pagesCount}`)
32+
console.log(yellow(`Rendering page ${i + 1} / ${pagesCount}`))
3333
await page.goto(`http://localhost:${port}/${i}?print`, {
3434
waitUntil: 'networkidle',
3535
})
@@ -60,10 +60,8 @@ export async function genratePDF(entry = 'slides.md', config: InlineConfig = {})
6060
}
6161

6262
const buffer = await mergedPdf.save()
63-
await fs.writeFile('slides.pdf', buffer)
64-
console.log(green`Exporting finished: ./slides.pdf`)
65-
63+
await fs.writeFile(output, buffer)
6664
browser.close()
6765
server.close()
68-
process.exit(0)
66+
return output
6967
}

packages/slidev/package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,37 +49,38 @@
4949
"@slidev/client": "workspace:*",
5050
"@vitejs/plugin-vue": "^1.2.2",
5151
"@vue/compiler-sfc": "^3.0.11",
52-
"chalk": "^4.1.1",
5352
"codemirror": "^5.61.0",
53+
"enquirer": "^2.3.6",
5454
"fast-glob": "^3.2.5",
55+
"fs-extra": "^9.1.0",
5556
"js-base64": "^3.6.0",
5657
"js-yaml": "^3.14.1",
58+
"kolorist": "^1.4.1",
5759
"markdown-it-prism": "^2.1.6",
58-
"minimist": "^1.2.5",
5960
"monaco-editor": "^0.23.0",
6061
"pdf-lib": "^1.16.0",
61-
"theme-vitesse": "^0.1.9",
6262
"vite": "^2.2.2",
6363
"vite-plugin-components": "^0.8.4",
6464
"vite-plugin-icons": "^0.5.0",
6565
"vite-plugin-md": "^0.6.3",
6666
"vite-plugin-remote-assets": "^0.1.3",
6767
"vite-plugin-windicss": "^0.15.7",
6868
"vue": "^3.0.11",
69-
"windicss": "^2.5.14"
69+
"windicss": "^2.5.14",
70+
"yargs": "^16.2.0"
7071
},
7172
"devDependencies": {
7273
"@antfu/eslint-config": "^0.6.4",
7374
"@antfu/ni": "^0.5.8",
74-
"@types/blueimp-md5": "^2.18.0",
7575
"@types/codemirror": "^0.0.109",
76+
"@types/fs-extra": "^9.0.11",
7677
"@types/js-yaml": "^3",
7778
"@types/minimist": "^1.2.1",
7879
"@types/node": "^14.14.41",
7980
"@types/prettier": "^2.2.3",
8081
"@types/recordrtc": "^5.6.5",
82+
"@types/yargs": "^16.0.1",
8183
"@typescript-eslint/eslint-plugin": "^4.22.0",
82-
"blueimp-md5": "^2.18.0",
8384
"cross-env": "^7.0.3",
8485
"eslint": "^7.25.0",
8586
"esno": "^0.5.0",

packages/slidev/template.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Slidev
2+
3+
Presentation slides for developers
4+
5+
> Press Space to next page
6+
7+
----
8+
9+
# Getting Started
10+
11+
Read the [documentations](https://slidev.antfu.me) to get started.

0 commit comments

Comments
 (0)