diff --git a/packages/client/package.json b/packages/client/package.json index 53814020d7..fefdacd888 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -27,6 +27,10 @@ "engines": { "node": ">=18.0.0" }, + "scripts": { + "build": "vite build", + "dev": "vite build --watch" + }, "dependencies": { "@antfu/utils": "^0.7.10", "@iconify-json/carbon": "^1.1.36", diff --git a/packages/client/uno.ts b/packages/client/uno.ts new file mode 100644 index 0000000000..b959ab4424 --- /dev/null +++ b/packages/client/uno.ts @@ -0,0 +1,5 @@ +import '@unocss/reset/tailwind.css' +import 'uno:preflights.css' +import 'uno:typography.css' +import 'uno:shortcuts.css' +import 'uno.css' diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts new file mode 100644 index 0000000000..0b88012e59 --- /dev/null +++ b/packages/client/vite.config.ts @@ -0,0 +1,114 @@ +import { fileURLToPath } from 'node:url' +import { basename } from 'node:path' +import { defineConfig, normalizePath } from 'vite' +import UnoCSS from 'unocss/vite' +import type { ResolvedSlidevOptions, SlidevPluginOptions } from '@slidev/types' +import IconsResolver from 'unplugin-icons/resolver' +import Components from 'unplugin-vue-components/vite' +import fg from 'fast-glob' +import { createInspectPlugin } from '../slidev/node/vite/inspect' +import { createIconsPlugin } from '../slidev/node/vite/icons' +import { createVuePlugin } from '../slidev/node/vite/vue' + +const absolute = (path: string) => normalizePath(fileURLToPath(new URL(path, import.meta.url))) +const clientRoot = absolute('.') + +const options = { + clientRoot, + roots: [], + mode: 'build', + inspect: true, +} as unknown as ResolvedSlidevOptions + +const pluginOptions = { + components: { + dts: false, + }, +} as SlidevPluginOptions + +const defines = [ + '__DEV__', + '__SLIDEV_CLIENT_ROOT__', + '__SLIDEV_HASH_ROUTE__', + '__SLIDEV_FEATURE_DRAWINGS__', + '__SLIDEV_FEATURE_EDITOR__', + '__SLIDEV_FEATURE_DRAWINGS_PERSIST__', + '__SLIDEV_FEATURE_RECORD__', + '__SLIDEV_FEATURE_PRESENTER__', + '__SLIDEV_FEATURE_PRINT__', + '__SLIDEV_FEATURE_WAKE_LOCK__', + '__SLIDEV_HAS_SERVER__', +] + +const builtinComponents = Object.fromEntries(fg.sync('*', { + cwd: absolute('./builtin'), + absolute: true, +}).map(i => [`components/${basename(i).replace(/\..*$/, '')}`, i])) + +const layoutComponents = Object.fromEntries(fg.sync('*', { + cwd: absolute('./layouts'), + absolute: true, +}).map(i => [`layouts/${basename(i).replace(/\..*$/, '')}`, i])) + +const externals = [ + '#slidev/', + '/@slidev/', + '@slidev/', + 'server-reactive:', + 'vue', + 'vue-router', + 'monaco-editor', + 'typescript', + 'mermaid', + '~icons/', +] + +export default defineConfig({ + plugins: [ + createInspectPlugin(options, pluginOptions), + UnoCSS(), + createVuePlugin(options, pluginOptions), + Components({ + extensions: ['vue', 'ts'], + dirs: [absolute('./builtin')], + resolvers: [ + IconsResolver({ + prefix: '', + customCollections: Object.keys(pluginOptions.icons?.customCollections || []), + }), + ], + dts: false, + }), + createIconsPlugin(options, pluginOptions), + { + name: 'slidev:flags', + enforce: 'pre', + transform(code, id) { + if (id.match(/\.vue($|\?)/)) { + const original = code + defines.forEach((name) => { + code = code.replaceAll(`_ctx.${name}`, name) + }) + if (original !== code) + return code + } + }, + }, + ], + build: { + lib: { + entry: { + 'main': absolute('./main.ts'), + 'index': absolute('./index.ts'), + 'uno.css': absolute('./uno.ts'), + ...builtinComponents, + ...layoutComponents, + }, + formats: ['es'], + }, + target: 'esnext', + rollupOptions: { + external: source => externals.some(i => source.startsWith(i)), + }, + }, +}) diff --git a/packages/slidev/node/commands/shared.ts b/packages/slidev/node/commands/shared.ts index c7f21f6c9c..69efd0ca13 100644 --- a/packages/slidev/node/commands/shared.ts +++ b/packages/slidev/node/commands/shared.ts @@ -66,7 +66,7 @@ export async function getIndexHtml({ mode, entry, clientRoot, roots, data }: Res head += `\n` main = main - .replace('__ENTRY__', toAtFS(join(clientRoot, 'main.ts'))) + .replace('__ENTRY__', toAtFS(join(clientRoot, 'dist/main.js'))) .replace('', head) .replace('', body) diff --git a/packages/slidev/node/options.ts b/packages/slidev/node/options.ts index a76e19635e..0c1e9ccca6 100644 --- a/packages/slidev/node/options.ts +++ b/packages/slidev/node/options.ts @@ -84,8 +84,8 @@ export async function createDataUtils(data: SlidevData, clientRoot: string, root const layouts: Record = {} - for (const root of [clientRoot, ...roots]) { - const layoutPaths = fg.sync('layouts/**/*.{vue,ts}', { + for (const root of [path.join(clientRoot, 'dist'), ...roots]) { + const layoutPaths = fg.sync('layouts/**/*.{vue,ts,js}', { cwd: root, absolute: true, suppressErrors: true, diff --git a/packages/slidev/node/virtual/styles.ts b/packages/slidev/node/virtual/styles.ts index 5cdc262927..c9c3fefe4c 100644 --- a/packages/slidev/node/virtual/styles.ts +++ b/packages/slidev/node/virtual/styles.ts @@ -17,6 +17,7 @@ export const templateStyle: VirtualModuleTemplate = { `import "${resolveUrlOfClient('styles/code.css')}"`, `import "${resolveUrlOfClient('styles/katex.css')}"`, `import "${resolveUrlOfClient('styles/transitions.css')}"`, + `import "${resolveUrlOfClient('dist/style.css')}"`, ] for (const root of roots) { diff --git a/packages/slidev/node/vite/compilerFlagsVue.ts b/packages/slidev/node/vite/compilerFlagsVue.ts index 7d70a38afe..26b4174789 100644 --- a/packages/slidev/node/vite/compilerFlagsVue.ts +++ b/packages/slidev/node/vite/compilerFlagsVue.ts @@ -15,10 +15,10 @@ export function createVueCompilerFlagsPlugin( name: 'slidev:flags', enforce: 'pre', transform(code, id) { - if (id.match(/\.vue($|\?)/)) { + if (id.match(/\.vue($|\?)/) || id.includes('client/dist')) { const original = code define.forEach(([from, to]) => { - code = code.replace(new RegExp(from, 'g'), to) + code = code.replaceAll(from, to) }) if (original !== code) return code diff --git a/packages/slidev/node/vite/components.ts b/packages/slidev/node/vite/components.ts index b7dfe2abdb..2ce8b01fc2 100644 --- a/packages/slidev/node/vite/components.ts +++ b/packages/slidev/node/vite/components.ts @@ -11,7 +11,7 @@ export function createComponentsPlugin( extensions: ['vue', 'md', 'js', 'ts', 'jsx', 'tsx'], dirs: [ - join(clientRoot, 'builtin'), + join(clientRoot, 'dist/components'), ...roots.map(i => join(i, 'components')), ], diff --git a/packages/slidev/node/vite/extendConfig.ts b/packages/slidev/node/vite/extendConfig.ts index 8a02be1c09..a5067565c8 100644 --- a/packages/slidev/node/vite/extendConfig.ts +++ b/packages/slidev/node/vite/extendConfig.ts @@ -68,7 +68,7 @@ export function createConfigPlugin(options: ResolvedSlidevOptions): Plugin { }) return { name: 'slidev:config', - async config(config) { + async config() { const injection: InlineConfig = { define: getDefine(options), resolve: { @@ -188,7 +188,7 @@ export function createConfigPlugin(options: ResolvedSlidevOptions): Plugin { injection.root = options.cliRoot } - return mergeConfig(injection, config) + return injection }, configureServer(server) { // serve our index.html after vite history fallback