Skip to content

Commit

Permalink
feat: theme shorthand and auto installations
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Apr 26, 2021
1 parent 0da891b commit 13ffb69
Show file tree
Hide file tree
Showing 10 changed files with 550 additions and 62 deletions.
3 changes: 3 additions & 0 deletions demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@
"@slidev/cli": "workspace:*",
"@slidev/theme-default": "workspace:*",
"@slidev/theme-seriph": "workspace:*"
},
"devDependencies": {
"nodemon": "^2.0.7"
}
}
1 change: 0 additions & 1 deletion demo/slides.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
layout: cover
theme: '@slidev/theme-default'
---

# Composable Vue
Expand Down
4 changes: 2 additions & 2 deletions packages/create-app/template/slides.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
# try also '@slidev/theme-default' to start simple
theme: '@slidev/theme-seriph'
# try also 'default' to start simple
theme: seriph
# random image from a curated Unsplash collection by Anthony
background: 'https://source.unsplash.com/collection/94734566/1920x1080'
# apply any windi css classes to the current slide
Expand Down
14 changes: 5 additions & 9 deletions packages/slidev/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,21 @@ import { promises as fs } from 'fs'
import { build as viteBuild, InlineConfig, mergeConfig } from 'vite'
import { ViteSlidevPlugin } from './plugins/preset'
import { getIndexHtml } from './common'
import { resolveOptions, SlidevEntryOptions, SlidevPluginOptions } from './plugins/options'
import { ResolvedSlidevOptions, SlidevPluginOptions } from './plugins/options'

export async function build(
entry: SlidevEntryOptions = {},
pluginOptions: Omit<SlidevPluginOptions, 'slidev'> = {},
options: ResolvedSlidevOptions,
pluginOptions: SlidevPluginOptions = {},
viteConfig: InlineConfig = {},
) {
const resolved = await resolveOptions(entry)
await fs.writeFile('index.html', await getIndexHtml(resolved), 'utf-8')
await fs.writeFile('index.html', await getIndexHtml(options), 'utf-8')
try {
await viteBuild(
mergeConfig(
viteConfig,
{
plugins: [
ViteSlidevPlugin({
...pluginOptions,
slidev: resolved,
}),
ViteSlidevPlugin(options, pluginOptions),
],
},
),
Expand Down
65 changes: 40 additions & 25 deletions packages/slidev/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,13 @@ import path from 'path'
import fs from 'fs-extra'
import yargs, { Argv } from 'yargs'
import { prompt } from 'enquirer'
import { green, yellow } from 'kolorist'
import { blue, bold, cyan, dim, green, yellow } from 'kolorist'
import { ViteDevServer } from 'vite'
import { version } from '../package.json'
import { build } from './build'
import { createServer } from './server'
import * as parser from './parser'

function commonOptions(args: Argv<{}>) {
return args
.positional('entry', {
default: 'slides.md',
type: 'string',
describe: 'path to the slides markdown entry',
})
.option('theme', {
alias: 't',
type: 'string',
describe: 'overide theme',
})
}
import { ResolvedSlidevOptions, resolveOptions } from './plugins/options'

const cli = yargs
.scriptName('slidev')
Expand Down Expand Up @@ -67,11 +54,9 @@ cli.command(
async function initServer() {
if (server)
await server.close()
const options = await resolveOptions({ entry, theme })
server = (await createServer(
{
entry,
theme,
},
options,
{
onDataReload(newData, data) {
if (!theme && newData.config.theme !== data.config.theme) {
Expand All @@ -86,8 +71,9 @@ cli.command(
open,
},
},
)).server
))
await server.listen()
printVersion(options)
}

initServer()
Expand All @@ -100,7 +86,11 @@ cli.command(
args => commonOptions(args)
.help(),
async(args) => {
await build(args)
console.log(yellow('[Slidev] the SPA build is experimental, recommend to use dev server instead at this moment.'))

const options = await resolveOptions(args)
printVersion(options)
await build(options)
},
)

Expand Down Expand Up @@ -147,8 +137,9 @@ cli.command(
process.env.NODE_ENV = 'production'
const { exportSlides } = await import('./export')
const port = 12445
const { server, resolved } = await createServer(
{ entry, theme },
const options = await resolveOptions({ entry, theme })
const server = await createServer(
options,
{},
{
server: { port },
Expand All @@ -157,10 +148,10 @@ cli.command(
},
)
await server.listen()
parser.filterDisabled(resolved.data)
parser.filterDisabled(options.data)
output = await exportSlides({
port,
pages: resolved.data.slides.length,
pages: options.data.slides.length,
format: format as any,
output,
timeout,
Expand All @@ -172,3 +163,27 @@ cli.command(
)

cli.help().parse()

function commonOptions(args: Argv<{}>) {
return args
.positional('entry', {
default: 'slides.md',
type: 'string',
describe: 'path to the slides markdown entry',
})
.option('theme', {
alias: 't',
type: 'string',
describe: 'overide theme',
})
}

function printVersion(options: ResolvedSlidevOptions) {
console.log()
console.log(` ${cyan('●')}${blue('■')}${yellow('▲')}`)
console.log(`${bold(' Slidev')} ${blue(`v${version}`)}`)
console.log()
console.log(`${dim(' theme ')}${green(options.theme)}`)
console.log(`${dim(' entry ')}${dim(options.entry)}`)
console.log()
}
17 changes: 14 additions & 3 deletions packages/slidev/node/plugins/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import RemoteAssets from 'vite-plugin-remote-assets'
import { ArgumentsType } from '@antfu/utils'
import * as parser from '../parser'
import { SlidevMarkdown } from '../parser'
import { packageExists, promptForThemeInstallation, resolveThemeName } from '../themes'

export interface SlidevEntryOptions {
/**
Expand Down Expand Up @@ -47,7 +48,6 @@ export interface SlidevPluginOptions extends SlidevEntryOptions {
windicss?: ArgumentsType<typeof WindiCSS>[0]
icons?: ArgumentsType<typeof ViteIcons>[0]
remoteAssets?: ArgumentsType<typeof RemoteAssets>[0]
slidev: ResolvedSlidevOptions
onDataReload?: (newData: SlidevMarkdown, data: SlidevMarkdown) => void
}

Expand All @@ -63,13 +63,24 @@ export function getThemeRoot(name: string) {
return dirname(require.resolve(`${name}/package.json`))
}

export async function resolveOptions(options: SlidevEntryOptions): Promise<ResolvedSlidevOptions> {
export async function resolveOptions(options: SlidevEntryOptions, promptForInstallation = true): Promise<ResolvedSlidevOptions> {
const {
entry = 'slides.md',
userRoot = process.cwd(),
} = options
const data = await parser.load(entry)
const theme = options.theme || data.config.theme
const theme = resolveThemeName(options.theme || data.config.theme)

if (promptForInstallation) {
if (await promptForThemeInstallation(theme) === false)
process.exit(1)
}
else {
if (!packageExists(theme)) {
console.error(`Theme "${theme}" not found, have you installed it?`)
process.exit(1)
}
}

return {
data,
Expand Down
5 changes: 2 additions & 3 deletions packages/slidev/node/plugins/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@ import { createConfigPlugin } from './config'
import { createSlidesLoader } from './loaders'
import { createMonacoLoader, transformMarkdownMonaco } from './monaco'
import { createEntryPlugin } from './entry'
import { SlidevPluginOptions } from './options'
import { ResolvedSlidevOptions, SlidevPluginOptions } from './options'
import { createSetupPlugin } from './setups'
import VitePluginVueFactory, { VueFactoryResolver } from './factory'
import VitePluginServerRef from './server-ref'

export function ViteSlidevPlugin(pluginOptions: SlidevPluginOptions): Plugin[] {
export function ViteSlidevPlugin(options: ResolvedSlidevOptions, pluginOptions: SlidevPluginOptions): Plugin[] {
const {
vue: vueOptions = {},
markdown: mdOptions = {},
components: componentsOptions = {},
icons: iconsOptions = {},
remoteAssets: remoteAssetsOptions = {},
windicss: windiOptions = {},
slidev: options,
} = pluginOptions

const {
Expand Down
24 changes: 5 additions & 19 deletions packages/slidev/node/server.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
import { bold, cyan, dim, green, yellow } from 'kolorist'
import { createServer as createViteServer, InlineConfig, mergeConfig } from 'vite'
import { version } from '../package.json'
import { resolveOptions, SlidevEntryOptions, SlidevPluginOptions } from './plugins/options'
import { ResolvedSlidevOptions, SlidevPluginOptions } from './plugins/options'
import { ViteSlidevPlugin } from './plugins/preset'

export async function createServer(
entry: SlidevEntryOptions,
pluginConfig: Omit<SlidevPluginOptions, 'slidev'> = {},
options: ResolvedSlidevOptions,
pluginConfig: SlidevPluginOptions = {},
viteConfig: InlineConfig = {},
) {
const resolved = await resolveOptions(entry)
const server = await createViteServer(
mergeConfig(
viteConfig,
{
plugins: [
ViteSlidevPlugin({
...pluginConfig,
slidev: resolved,
}),
ViteSlidevPlugin(options, pluginConfig),
],
},
),
)

console.log()
console.log(cyan(bold(' Slidev ')) + yellow(`v${version}`))
console.log()
console.log(` theme ${green(resolved.theme)}`)
console.log(` entry ${dim(resolved.entry)}`)
console.log()

return {
server,
resolved,
}
return server
}
51 changes: 51 additions & 0 deletions packages/slidev/node/themes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { prompt } from 'enquirer'
import { parseNi, run } from '@antfu/ni'

const officialThemes: Record<string, string> = {
none: '',
default: '@slidev/theme-default',
seriph: '@slidev/theme-seriph',
}

export function packageExists(name: string) {
try {
if (require.resolve(`${name}/package.json`))
return true
}
catch {}
return false
}

export function resolveThemeName(name: string) {
if (!name)
return ''
if (name.startsWith('@slidev/theme-') || name.startsWith('slidev-theme-'))
return name
if (officialThemes[name])
return officialThemes[name]

return `slidev-theme-${name}`
}

export async function promptForThemeInstallation(name: string) {
name = resolveThemeName(name)
if (!name)
return name

if (packageExists(name))
return name

const { confirm } = await prompt<{ confirm: boolean }>({
name: 'confirm',
initial: 'Y',
type: 'confirm',
message: `Does not found theme "${name}" in your project, do you want to install it now?`,
})

if (!confirm)
return false

await run(parseNi, [name])

return name
}

0 comments on commit 13ffb69

Please sign in to comment.