@slidev/cli 0.48.0-beta.3 → 0.48.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  createServer,
3
- getAddonRoots,
4
- getClientRoot,
5
- getThemeRoots,
6
- getUserRoot,
7
- isPath,
3
+ getThemeMeta,
8
4
  parser,
5
+ resolveAddons,
9
6
  resolveOptions,
10
- resolveThemeName,
7
+ resolveTheme
8
+ } from "./chunk-CV7O37IO.mjs";
9
+ import {
11
10
  version
12
- } from "./chunk-HESHEOWV.mjs";
13
- import "./chunk-JORVSTMS.mjs";
11
+ } from "./chunk-U44GKKNH.mjs";
14
12
  import {
15
13
  loadSetups
16
- } from "./chunk-CTBVOVLQ.mjs";
17
- import "./chunk-DWXI5WEO.mjs";
14
+ } from "./chunk-O6TYYGU6.mjs";
15
+ import {
16
+ getRoots
17
+ } from "./chunk-7HOZGSL4.mjs";
18
18
  import "./chunk-BXO7ZPPU.mjs";
19
19
 
20
20
  // node/cli.ts
@@ -26,12 +26,12 @@ import process from "node:process";
26
26
  import fs from "fs-extra";
27
27
  import openBrowser from "open";
28
28
  import yargs from "yargs";
29
- import prompts from "prompts";
30
29
  import { blue, bold, cyan, dim, gray, green, underline, yellow } from "kolorist";
31
30
  import isInstalledGlobally from "is-installed-globally";
32
31
  import equal from "fast-deep-equal";
33
32
  import { verifyConfig } from "@slidev/parser";
34
33
  import { injectPreparserExtensionLoader } from "@slidev/parser/fs";
34
+ import { uniq } from "@antfu/utils";
35
35
  import { checkPort } from "get-port-please";
36
36
  var CONFIG_RESTART_FIELDS = [
37
37
  "highlighter",
@@ -40,20 +40,19 @@ var CONFIG_RESTART_FIELDS = [
40
40
  "fonts",
41
41
  "css",
42
42
  "mdc",
43
- "editor"
43
+ "editor",
44
+ "theme"
44
45
  ];
45
46
  injectPreparserExtensionLoader(async (headmatter, filepath) => {
46
47
  const addons = headmatter?.addons ?? [];
47
- const roots = (
48
- /* uniq */
49
- [
50
- getUserRoot({}).userRoot,
51
- ...await getAddonRoots(addons, ""),
52
- await getClientRoot()
53
- ]
54
- );
48
+ const { clientRoot, userRoot } = await getRoots();
49
+ const roots = uniq([
50
+ clientRoot,
51
+ userRoot,
52
+ ...await resolveAddons(addons)
53
+ ]);
55
54
  const mergeArrays = (a, b) => a.concat(b);
56
- return await loadSetups(roots, "preparser.ts", { filepath, headmatter }, [], mergeArrays);
55
+ return await loadSetups(clientRoot, roots, "preparser.ts", { filepath, headmatter }, [], mergeArrays);
57
56
  });
58
57
  var cli = yargs(process.argv.slice(2)).scriptName("slidev").usage("$0 [args]").version(version).strict().showHelpOnFail(false).alias("h", "help").alias("v", "version");
59
58
  cli.command(
@@ -95,20 +94,6 @@ cli.command(
95
94
  describe: "specify which IP addresses the server should listen on in remote mode"
96
95
  }).strict().help(),
97
96
  async ({ entry, theme, port: userPort, open, log, remote, tunnel, force, inspect, bind }) => {
98
- if (!fs.existsSync(entry) && !entry.endsWith(".md"))
99
- entry = `${entry}.md`;
100
- if (!fs.existsSync(entry)) {
101
- const { create } = await prompts({
102
- name: "create",
103
- type: "confirm",
104
- initial: "Y",
105
- message: `Entry file ${yellow(`"${entry}"`)} does not exist, do you want to create it?`
106
- });
107
- if (create)
108
- await fs.copyFile(new URL("../template.md", import.meta.url), entry);
109
- else
110
- process.exit(0);
111
- }
112
97
  let server;
113
98
  let port = 3030;
114
99
  let lastRemoteUrl;
@@ -135,14 +120,27 @@ cli.command(
135
120
  logLevel: log
136
121
  },
137
122
  {
138
- async onDataReload(newData, data) {
139
- if (!theme && await resolveThemeName(newData.config.theme) !== await resolveThemeName(data.config.theme)) {
123
+ async loadData() {
124
+ const { data: oldData, entry: entry2 } = options;
125
+ const loaded = await parser.load(options.userRoot, entry2);
126
+ const themeRaw = theme || loaded.headmatter.theme || "default";
127
+ if (options.themeRaw !== themeRaw) {
140
128
  console.log(yellow("\n restarting on theme change\n"));
141
129
  initServer();
142
- } else if (CONFIG_RESTART_FIELDS.some((i) => !equal(newData.config[i], data.config[i]))) {
130
+ return false;
131
+ }
132
+ const themeMeta = options.themeRoots[0] ? await getThemeMeta(themeRaw, options.themeRoots[0]) : void 0;
133
+ const newData = {
134
+ ...loaded,
135
+ themeMeta,
136
+ config: parser.resolveConfig(loaded.headmatter, themeMeta, entry2)
137
+ };
138
+ if (CONFIG_RESTART_FIELDS.some((i) => !equal(newData.config[i], oldData.config[i]))) {
143
139
  console.log(yellow("\n restarting on config change\n"));
144
140
  initServer();
141
+ return false;
145
142
  }
143
+ return newData;
146
144
  }
147
145
  }
148
146
  );
@@ -273,7 +271,7 @@ cli.command(
273
271
  }).strict().help(),
274
272
  async (args) => {
275
273
  const { entry, theme, watch, base, download, out, inspect } = args;
276
- const { build } = await import("./build-VKH7FQSN.mjs");
274
+ const { build } = await import("./build-C6G7F24X.mjs");
277
275
  for (const entryFile of entry) {
278
276
  const options = await resolveOptions({ entry: entryFile, theme, inspect }, "build");
279
277
  if (download && !options.data.config.download)
@@ -313,23 +311,18 @@ cli.command(
313
311
  default: "theme"
314
312
  }),
315
313
  async ({ entry, dir, theme: themeInput }) => {
316
- const { userRoot } = getUserRoot({ entry });
317
- const data = await parser.load(userRoot, entry);
318
- const theme = await resolveThemeName(themeInput || data.config.theme);
319
- if (theme === "none") {
314
+ const roots = await getRoots();
315
+ const data = await parser.load(roots.userRoot, entry);
316
+ const themeRaw = themeInput || data.headmatter.theme || "default";
317
+ if (themeRaw === "none") {
320
318
  console.error('Cannot eject theme "none"');
321
319
  process.exit(1);
322
320
  }
323
- if (isPath(theme)) {
321
+ if ("/.".includes(themeRaw[0]) || themeRaw[0] !== "@" && themeRaw.includes("/")) {
324
322
  console.error("Theme is already ejected");
325
323
  process.exit(1);
326
324
  }
327
- const roots = await getThemeRoots(theme, entry);
328
- if (!roots.length) {
329
- console.error(`Could not find theme "${theme}"`);
330
- process.exit(1);
331
- }
332
- const root = roots[0];
325
+ const [name, root] = await resolveTheme(themeRaw, entry);
333
326
  await fs.copy(root, path.resolve(dir), {
334
327
  filter: (i) => !/node_modules|.git/.test(path.relative(root, i))
335
328
  });
@@ -338,7 +331,7 @@ cli.command(
338
331
  firstSlide.frontmatter.theme = dirPath;
339
332
  parser.prettifySlide(firstSlide);
340
333
  await parser.save(data.entry);
341
- console.log(`Theme "${theme}" ejected successfully to "${dirPath}"`);
334
+ console.log(`Theme "${name}" ejected successfully to "${dirPath}"`);
342
335
  }
343
336
  );
344
337
  },
@@ -353,7 +346,7 @@ cli.command(
353
346
  (args) => exportOptions(commonOptions(args)).strict().help(),
354
347
  async (args) => {
355
348
  const { entry, theme } = args;
356
- const { exportSlides, getExportOptions } = await import("./export-MLH55TH5.mjs");
349
+ const { exportSlides, getExportOptions } = await import("./export-SM2ZATWB.mjs");
357
350
  const port = await findFreePort(12445);
358
351
  for (const entryFile of entry) {
359
352
  const options = await resolveOptions({ entry: entryFile, theme }, "export");
@@ -397,7 +390,7 @@ cli.command(
397
390
  output,
398
391
  timeout
399
392
  }) => {
400
- const { exportNotes } = await import("./export-MLH55TH5.mjs");
393
+ const { exportNotes } = await import("./export-SM2ZATWB.mjs");
401
394
  const port = await findFreePort(12445);
402
395
  for (const entryFile of entry) {
403
396
  const options = await resolveOptions({ entry: entryFile }, "export");
@@ -1,7 +1,6 @@
1
1
  import {
2
- packageExists,
3
- resolveGlobalImportPath
4
- } from "./chunk-DWXI5WEO.mjs";
2
+ getRoots
3
+ } from "./chunk-7HOZGSL4.mjs";
5
4
  import "./chunk-BXO7ZPPU.mjs";
6
5
 
7
6
  // node/export.ts
@@ -14,7 +13,7 @@ import { parseRangeString } from "@slidev/parser/core";
14
13
  import { outlinePdfFactory } from "@lillallol/outline-pdf";
15
14
  import * as pdfLib from "pdf-lib";
16
15
  import { PDFDocument } from "pdf-lib";
17
- import isInstalledGlobally from "is-installed-globally";
16
+ import { resolve } from "mlly";
18
17
  function addToTree(tree, info, slideIndexes, level = 1) {
19
18
  const titleLevel = info.level;
20
19
  if (titleLevel && titleLevel > level && tree.length > 0) {
@@ -384,18 +383,27 @@ function getExportOptions(args, options, outDir, outFilename) {
384
383
  };
385
384
  }
386
385
  async function importPlaywright() {
387
- if (await packageExists("playwright-chromium"))
388
- return await import("playwright-chromium");
389
- let globalPath = isInstalledGlobally ? await resolveGlobalImportPath("playwright-chromium") : void 0;
390
- if (globalPath)
391
- return await import(globalPath);
386
+ const { userRoot, userWorkspaceRoot } = await getRoots();
387
+ try {
388
+ return await import(await resolve("playwright-chromium", { url: userRoot }));
389
+ } catch {
390
+ }
391
+ if (userWorkspaceRoot !== userRoot) {
392
+ try {
393
+ return await import(await resolve("playwright-chromium", { url: userWorkspaceRoot }));
394
+ } catch {
395
+ }
396
+ }
392
397
  const { resolveGlobal } = await import("resolve-global");
393
398
  try {
394
- globalPath = resolveGlobal("playwright-chromium");
399
+ const imported = await import(resolveGlobal("playwright-chromium"));
400
+ return imported.default ?? imported;
401
+ } catch {
402
+ }
403
+ try {
404
+ return await import("playwright-chromium");
395
405
  } catch {
396
406
  }
397
- if (globalPath)
398
- return await import(globalPath);
399
407
  throw new Error("The exporting for Slidev is powered by Playwright, please install it via `npm i -D playwright-chromium`");
400
408
  }
401
409
  export {
package/dist/index.d.mts CHANGED
@@ -13,6 +13,14 @@ import { InlineConfig, Plugin } from 'vite';
13
13
  import * as fs from '@slidev/parser/fs';
14
14
  export { fs as parser };
15
15
 
16
+ interface RootsInfo {
17
+ cliRoot: string;
18
+ clientRoot: string;
19
+ userRoot: string;
20
+ userPkgJson: Record<string, any>;
21
+ userWorkspaceRoot: string;
22
+ }
23
+
16
24
  interface SlidevEntryOptions {
17
25
  /**
18
26
  * Markdown entry
@@ -28,26 +36,21 @@ interface SlidevEntryOptions {
28
36
  * Remote password
29
37
  */
30
38
  remote?: string;
31
- /**
32
- * Root path
33
- *
34
- * @default process.cwd()
35
- */
36
- userRoot?: string;
37
39
  /**
38
40
  * Enable inspect plugin
39
41
  */
40
42
  inspect?: boolean;
41
43
  }
42
- interface ResolvedSlidevOptions {
44
+ interface ResolvedSlidevOptions extends RootsInfo {
43
45
  data: SlidevData;
44
46
  entry: string;
45
- userRoot: string;
46
- cliRoot: string;
47
- clientRoot: string;
47
+ themeRaw: string;
48
48
  theme: string;
49
49
  themeRoots: string[];
50
50
  addonRoots: string[];
51
+ /**
52
+ * =`[...themeRoots, ...addonRoots, userRoot]` (`clientRoot` excluded)
53
+ */
51
54
  roots: string[];
52
55
  mode: 'dev' | 'build' | 'export';
53
56
  remote?: string;
@@ -64,19 +67,12 @@ interface SlidevPluginOptions extends SlidevEntryOptions {
64
67
  unocss?: VitePluginConfig;
65
68
  }
66
69
  interface SlidevServerOptions {
67
- onDataReload?: (newData: SlidevData, data: SlidevData) => void;
70
+ /**
71
+ * @returns `false` if server should be restarted
72
+ */
73
+ loadData?: () => Promise<SlidevData | false>;
68
74
  }
69
- declare function getClientRoot(): Promise<string>;
70
- declare function getCLIRoot(): string;
71
- declare function isPath(name: string): boolean;
72
- declare function getThemeRoots(name: string, entry: string): Promise<string[]>;
73
- declare function getAddonRoots(addons: string[], entry: string): Promise<string[]>;
74
- declare function getRoot(name: string, entry: string): Promise<string>;
75
- declare function getUserRoot(options: SlidevEntryOptions): {
76
- entry: string;
77
- userRoot: string;
78
- };
79
- declare function resolveOptions(options: SlidevEntryOptions, mode: ResolvedSlidevOptions['mode'], promptForInstallation?: boolean): Promise<ResolvedSlidevOptions>;
75
+ declare function resolveOptions(options: SlidevEntryOptions, mode: ResolvedSlidevOptions['mode']): Promise<ResolvedSlidevOptions>;
80
76
 
81
77
  declare module 'vite' {
82
78
  interface UserConfig {
@@ -93,4 +89,4 @@ declare function createServer(options: ResolvedSlidevOptions, viteConfig?: Inlin
93
89
 
94
90
  declare function ViteSlidevPlugin(options: ResolvedSlidevOptions, pluginOptions: SlidevPluginOptions, serverOptions?: SlidevServerOptions): Promise<Plugin[]>;
95
91
 
96
- export { type ResolvedSlidevOptions, type SlidevEntryOptions, type SlidevPluginOptions, type SlidevServerOptions, ViteSlidevPlugin, createServer, getAddonRoots, getCLIRoot, getClientRoot, getRoot, getThemeRoots, getUserRoot, isPath, resolveOptions };
92
+ export { type ResolvedSlidevOptions, type SlidevEntryOptions, type SlidevPluginOptions, type SlidevServerOptions, ViteSlidevPlugin, createServer, resolveOptions };
package/dist/index.mjs CHANGED
@@ -1,31 +1,17 @@
1
1
  import {
2
2
  createServer,
3
- getAddonRoots,
4
- getCLIRoot,
5
- getClientRoot,
6
- getRoot,
7
- getThemeRoots,
8
- getUserRoot,
9
- isPath,
10
3
  parser,
11
4
  resolveOptions
12
- } from "./chunk-HESHEOWV.mjs";
5
+ } from "./chunk-CV7O37IO.mjs";
13
6
  import {
14
7
  ViteSlidevPlugin
15
- } from "./chunk-JORVSTMS.mjs";
16
- import "./chunk-CTBVOVLQ.mjs";
17
- import "./chunk-DWXI5WEO.mjs";
8
+ } from "./chunk-U44GKKNH.mjs";
9
+ import "./chunk-O6TYYGU6.mjs";
10
+ import "./chunk-7HOZGSL4.mjs";
18
11
  import "./chunk-BXO7ZPPU.mjs";
19
12
  export {
20
13
  ViteSlidevPlugin,
21
14
  createServer,
22
- getAddonRoots,
23
- getCLIRoot,
24
- getClientRoot,
25
- getRoot,
26
- getThemeRoots,
27
- getUserRoot,
28
- isPath,
29
15
  parser,
30
16
  resolveOptions
31
17
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadSetups
3
- } from "./chunk-CTBVOVLQ.mjs";
3
+ } from "./chunk-O6TYYGU6.mjs";
4
4
  import "./chunk-BXO7ZPPU.mjs";
5
5
 
6
6
  // node/plugins/unocss.ts
@@ -11,7 +11,7 @@ import { uniq } from "@antfu/utils";
11
11
  import { mergeConfigs } from "unocss";
12
12
  import jiti from "jiti";
13
13
  import UnoCSS from "unocss/vite";
14
- async function createUnocssPlugin({ themeRoots, addonRoots, clientRoot, roots, userRoot, data }, { unocss: unoOptions = {} }) {
14
+ async function createUnocssPlugin({ themeRoots, addonRoots, clientRoot, roots, data, userRoot }, { unocss: unoOptions = {} }) {
15
15
  const configFiles = uniq([
16
16
  resolve(userRoot, "uno.config.ts"),
17
17
  resolve(userRoot, "unocss.config.ts"),
@@ -29,7 +29,7 @@ async function createUnocssPlugin({ themeRoots, addonRoots, clientRoot, roots, u
29
29
  }).filter(Boolean);
30
30
  configs.reverse();
31
31
  let config = mergeConfigs([...configs, unoOptions]);
32
- config = await loadSetups(roots, "unocss.ts", {}, config, (a, b) => mergeConfigs([a, b]));
32
+ config = await loadSetups(clientRoot, roots, "unocss.ts", {}, config, (a, b) => mergeConfigs([a, b]));
33
33
  config.theme ||= {};
34
34
  config.theme.fontFamily ||= {};
35
35
  config.theme.fontFamily.sans ||= data.config.fonts.sans.join(",");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slidev/cli",
3
- "version": "0.48.0-beta.3",
3
+ "version": "0.48.0-beta.5",
4
4
  "description": "Presentation slides for developers",
5
5
  "author": "antfu <anthonyfu117@hotmail.com>",
6
6
  "license": "MIT",
@@ -47,9 +47,9 @@
47
47
  "@iconify-json/ph": "^1.1.11",
48
48
  "@lillallol/outline-pdf": "^4.0.0",
49
49
  "@mrdrogdrog/optional": "^1.2.1",
50
- "@shikijs/markdown-it": "^1.1.5",
51
- "@shikijs/twoslash": "^1.1.5",
52
- "@shikijs/vitepress-twoslash": "^1.1.5",
50
+ "@shikijs/markdown-it": "^1.1.6",
51
+ "@shikijs/twoslash": "^1.1.6",
52
+ "@shikijs/vitepress-twoslash": "^1.1.6",
53
53
  "@unocss/extractor-mdc": "^0.58.5",
54
54
  "@unocss/reset": "^0.58.5",
55
55
  "@vitejs/plugin-vue": "^5.0.4",
@@ -76,7 +76,7 @@
76
76
  "markdown-it-mdc": "^0.2.3",
77
77
  "mlly": "^1.5.0",
78
78
  "monaco-editor": "^0.37.1",
79
- "nanoid": "^5.0.5",
79
+ "nanoid": "^5.0.6",
80
80
  "open": "^10.0.3",
81
81
  "pdf-lib": "^1.17.1",
82
82
  "plantuml-encoder": "^1.4.0",
@@ -87,7 +87,7 @@
87
87
  "resolve": "^1.22.8",
88
88
  "resolve-from": "^5.0.0",
89
89
  "resolve-global": "^2.0.0",
90
- "shiki": "^1.1.5",
90
+ "shiki": "^1.1.6",
91
91
  "sirv": "^2.0.4",
92
92
  "typescript": "^5.3.3",
93
93
  "unocss": "^0.58.5",
@@ -104,9 +104,9 @@
104
104
  "vitefu": "^0.2.5",
105
105
  "vue": "^3.4.19",
106
106
  "yargs": "^17.7.2",
107
- "@slidev/client": "0.48.0-beta.3",
108
- "@slidev/parser": "0.48.0-beta.3",
109
- "@slidev/types": "0.48.0-beta.3"
107
+ "@slidev/client": "0.48.0-beta.5",
108
+ "@slidev/parser": "0.48.0-beta.5",
109
+ "@slidev/types": "0.48.0-beta.5"
110
110
  },
111
111
  "devDependencies": {
112
112
  "@hedgedoc/markdown-it-plugins": "^2.1.4",
package/template.md CHANGED
@@ -14,6 +14,9 @@ info: |
14
14
  Presentation slides for developers.
15
15
 
16
16
  Learn more at [Sli.dev](https://sli.dev)
17
+ transition: slide-left
18
+ title: Welcome to Slidev
19
+ mdc: true
17
20
  ---
18
21
 
19
22
  # Welcome to Slidev
@@ -21,20 +24,27 @@ info: |
21
24
  Presentation slides for developers
22
25
 
23
26
  <div class="pt-12">
24
- <span @click="$slidev.nav.next" class="px-2 p-1 rounded cursor-pointer" hover="bg-white bg-opacity-10">
27
+ <span @click="$slidev.nav.next" class="px-2 py-1 rounded cursor-pointer" hover="bg-white bg-opacity-10">
25
28
  Press Space for next page <carbon:arrow-right class="inline"/>
26
29
  </span>
27
30
  </div>
28
31
 
29
- <a href="https://github.com/slidevjs/slidev" target="_blank" alt="GitHub" title="Open in GitHub"
30
- class="abs-br m-6 text-xl slidev-icon-btn opacity-50 !border-none !hover:text-white">
31
- <carbon-logo-github />
32
- </a>
32
+ <div class="abs-br m-6 flex gap-2">
33
+ <button @click="$slidev.nav.openInEditor()" title="Open in Editor" class="text-xl slidev-icon-btn opacity-50 !border-none !hover:text-white">
34
+ <carbon:edit />
35
+ </button>
36
+ <a href="https://github.com/slidevjs/slidev" target="_blank" alt="GitHub" title="Open in GitHub"
37
+ class="text-xl slidev-icon-btn opacity-50 !border-none !hover:text-white">
38
+ <carbon-logo-github />
39
+ </a>
40
+ </div>
33
41
 
34
42
  <!--
35
43
  The last comment block of each slide will be treated as slide notes. It will be visible and editable in Presenter Mode along with the slide. [Read more in the docs](https://sli.dev/guide/syntax.html#notes)
36
44
  -->
37
45
 
46
+ ---
47
+ transition: fade-out
38
48
  ---
39
49
 
40
50
  # What is Slidev?
@@ -71,6 +81,25 @@ h1 {
71
81
  }
72
82
  </style>
73
83
 
84
+ <!--
85
+ Here is another comment.
86
+ -->
87
+
88
+ ---
89
+ layout: default
90
+ ---
91
+
92
+ # Table of contents
93
+
94
+ ```html
95
+ <Toc minDepth="1" maxDepth="1"></Toc>
96
+ ```
97
+
98
+ <Toc maxDepth="1"></Toc>
99
+
100
+ ---
101
+ transition: slide-up
102
+ level: 2
74
103
  ---
75
104
 
76
105
  # Navigation
@@ -82,7 +111,7 @@ Hover on the bottom-left corner to see the navigation's controls panel, [learn m
82
111
  | | |
83
112
  | --- | --- |
84
113
  | <kbd>right</kbd> / <kbd>space</kbd>| next animation or slide |
85
- | <kbd>left</kbd> / <kbd>shift</kbd><kbd>space</kbd>| previous animation or slide |
114
+ | <kbd>left</kbd> / <kbd>shift</kbd><kbd>space</kbd> | previous animation or slide |
86
115
  | <kbd>up</kbd> | previous slide |
87
116
  | <kbd>down</kbd> | next slide |
88
117
 
@@ -102,26 +131,41 @@ image: https://source.unsplash.com/collection/94734566/1920x1080
102
131
 
103
132
  # Code
104
133
 
105
- Use code snippets and get the highlighting directly!
134
+ Use code snippets and get the highlighting directly, and even types hover![^1]
106
135
 
107
- <!-- https://sli.dev/guide/syntax.html#line-highlighting -->
136
+ ```ts {all|5|7|7-8|10|all} twoslash
137
+ // TwoSlash enables TypeScript hover information
138
+ // and errors in markdown code blocks
139
+ // More at https://shiki.style/packages/twoslash
108
140
 
109
- ```ts {all|2|1-6|9|all}
110
- interface User {
111
- id: number
112
- firstName: string
113
- lastName: string
114
- role: string
115
- }
141
+ import { computed, ref } from 'vue'
116
142
 
117
- function updateUser(id: number, update: User) {
118
- const user = getUser(id)
119
- const newUser = { ...user, ...update }
120
- saveUser(id, newUser)
121
- }
143
+ const count = ref(0)
144
+ const doubled = computed(() => count.value * 2)
145
+
146
+ doubled.value = 2
122
147
  ```
123
148
 
124
- <arrow v-click="[3, 4]" x1="400" y1="420" x2="230" y2="330" color="#564" width="3" arrowSize="1" />
149
+ <arrow v-click="[4, 5]" x1="350" y1="310" x2="195" y2="334" color="#953" width="2" arrowSize="1" />
150
+
151
+ <!-- This allow you to embed external code blocks -->
152
+ <!-- <<< @/snippets/external.ts#snippet -->
153
+
154
+ <!-- Footer -->
155
+ [^1]: [Learn More](https://sli.dev/guide/syntax.html#line-highlighting)
156
+
157
+ <!-- Inline style -->
158
+ <style>
159
+ .footnotes-sep {
160
+ @apply mt-5 opacity-10;
161
+ }
162
+ .footnotes {
163
+ @apply text-sm opacity-75;
164
+ }
165
+ .footnote-backref {
166
+ display: none;
167
+ }
168
+ </style>
125
169
 
126
170
  ---
127
171
 
@@ -155,13 +199,23 @@ Check out [the guides](https://sli.dev/builtin/components.html) for more.
155
199
  </div>
156
200
  </div>
157
201
 
202
+ <!--
203
+ Presenter note with **bold**, *italic*, and ~~striked~~ text.
204
+
205
+ Also, HTML elements are valid:
206
+ <div class="flex w-full">
207
+ <span style="flex-grow: 1;">Left content</span>
208
+ <span>Right content</span>
209
+ </div>
210
+ -->
211
+
158
212
  ---
159
213
  class: px-20
160
214
  ---
161
215
 
162
216
  # Themes
163
217
 
164
- Slidev comes with powerful theming support. Themes are able to provide styles, layouts, components, or even configurations for tools. Switching between themes by just **one edit** in your frontmatter:
218
+ Slidev comes with powerful theming support. Themes can provide styles, layouts, components, or even configurations for tools. Switching between themes by just **one edit** in your frontmatter:
165
219
 
166
220
  <div grid="~ cols-2 gap-2" m="t-2">
167
221
 
@@ -276,7 +330,7 @@ LaTeX is supported out-of-box powered by [KaTeX](https://katex.org/).
276
330
  Inline $\sqrt{3x-1}+(1+x)^2$
277
331
 
278
332
  Block
279
- $$
333
+ $$ {1|3|all}
280
334
  \begin{array}{c}
281
335
 
282
336
  \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} &
@@ -299,9 +353,9 @@ $$
299
353
 
300
354
  You can create diagrams / graphs from textual descriptions, directly in your Markdown.
301
355
 
302
- <div class="grid grid-cols-2 gap-4 pt-4 -mb-6">
356
+ <div class="grid grid-cols-4 gap-5 pt-4 -mb-6">
303
357
 
304
- ```mermaid {scale: 0.9}
358
+ ```mermaid {scale: 0.5, alt: 'A simple sequence diagram'}
305
359
  sequenceDiagram
306
360
  Alice->John: Hello John, how are you?
307
361
  Note over Alice,John: A typical interaction
@@ -314,6 +368,59 @@ C -->|One| D[Result 1]
314
368
  C -->|Two| E[Result 2]
315
369
  ```
316
370
 
371
+ ```mermaid
372
+ mindmap
373
+ root((mindmap))
374
+ Origins
375
+ Long history
376
+ ::icon(fa fa-book)
377
+ Popularisation
378
+ British popular psychology author Tony Buzan
379
+ Research
380
+ On effectivness<br/>and features
381
+ On Automatic creation
382
+ Uses
383
+ Creative techniques
384
+ Strategic planning
385
+ Argument mapping
386
+ Tools
387
+ Pen and paper
388
+ Mermaid
389
+ ```
390
+
391
+ ```plantuml {scale: 0.7}
392
+ @startuml
393
+
394
+ package "Some Group" {
395
+ HTTP - [First Component]
396
+ [Another Component]
397
+ }
398
+
399
+ node "Other Groups" {
400
+ FTP - [Second Component]
401
+ [First Component] --> FTP
402
+ }
403
+
404
+ cloud {
405
+ [Example 1]
406
+ }
407
+
408
+ database "MySql" {
409
+ folder "This is my folder" {
410
+ [Folder 3]
411
+ }
412
+ frame "Foo" {
413
+ [Frame 4]
414
+ }
415
+ }
416
+
417
+ [Another Component] --> [Example 1]
418
+ [Example 1] --> [Folder 3]
419
+ [Folder 3] --> [Frame 4]
420
+
421
+ @enduml
422
+ ```
423
+
317
424
  </div>
318
425
 
319
426
  [Learn More](https://sli.dev/guide/syntax.html#diagrams)
@@ -325,4 +432,4 @@ class: text-center
325
432
 
326
433
  # Learn More
327
434
 
328
- [Documentations](https://sli.dev) / [GitHub Repo](https://github.com/slidevjs/slidev)
435
+ [Documentations](https://sli.dev) · [GitHub](https://github.com/slidevjs/slidev) · [Showcases](https://sli.dev/showcases.html)