@slidev/cli 51.0.1 → 51.1.0

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveViteConfigs
3
- } from "./chunk-3JQYTPPL.js";
3
+ } from "./chunk-UAXJBAYZ.js";
4
4
  import "./chunk-UNQ5DBLZ.js";
5
5
 
6
6
  // node/commands/build.ts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveViteConfigs
3
- } from "./chunk-3JQYTPPL.js";
3
+ } from "./chunk-UAXJBAYZ.js";
4
4
 
5
5
  // node/commands/serve.ts
6
6
  import { join } from "node:path";
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-UNQ5DBLZ.js";
10
10
 
11
11
  // package.json
12
- var version = "51.0.1";
12
+ var version = "51.1.0";
13
13
 
14
14
  // node/integrations/themes.ts
15
15
  import { join } from "node:path";
@@ -80,7 +80,7 @@ import { escapeHtml } from "markdown-it/lib/common/utils.mjs";
80
80
  // node/commands/shared.ts
81
81
  import { existsSync as existsSync7 } from "node:fs";
82
82
  import { join as join12 } from "node:path";
83
- import MarkdownIt from "markdown-it";
83
+ import MarkdownIt2 from "markdown-it";
84
84
  import { loadConfigFromFile, mergeConfig as mergeConfig2 } from "vite";
85
85
 
86
86
  // node/syntax/markdown-it/markdown-it-link.ts
@@ -119,10 +119,16 @@ function loadModule(absolutePath) {
119
119
  function stringifyMarkdownTokens(tokens) {
120
120
  return tokens.map((token) => token.children?.filter((t) => ["text", "code_inline"].includes(t.type) && !t.content.match(/^\s*$/)).map((t) => t.content.trim()).join(" ")).filter(Boolean).join(" ");
121
121
  }
122
- function generateGoogleFontsUrl(options) {
122
+ function generateFontParams(options) {
123
123
  const weights = options.weights.flatMap((i) => options.italic ? [`0,${i}`, `1,${i}`] : [`${i}`]).sort().join(";");
124
- const fonts = options.webfonts.map((i) => `family=${i.replace(/^(['"])(.*)\1$/, "$1").replace(/\s+/g, "+")}:${options.italic ? "ital," : ""}wght@${weights}`).join("&");
125
- return `https://fonts.googleapis.com/css2?${fonts}&display=swap`;
124
+ const fontParams = options.webfonts.map((i) => `family=${i.replace(/^(['"])(.*)\1$/, "$1").replace(/\s+/g, "+")}:${options.italic ? "ital," : ""}wght@${weights}`).join("&");
125
+ return fontParams;
126
+ }
127
+ function generateGoogleFontsUrl(options) {
128
+ return `https://fonts.googleapis.com/css2?${generateFontParams(options)}&display=swap`;
129
+ }
130
+ function generateCoollabsFontsUrl(options) {
131
+ return `https://api.fonts.coollabs.io/fonts?${generateFontParams(options)}&display=swap`;
126
132
  }
127
133
  function updateFrontmatterPatch(slide, frontmatter) {
128
134
  const source = slide.source;
@@ -538,8 +544,154 @@ ${body}
538
544
  import { notNullish, range } from "@antfu/utils";
539
545
  import * as parser2 from "@slidev/parser/fs";
540
546
  import equal from "fast-deep-equal";
547
+ import MarkdownIt from "markdown-it";
541
548
  import YAML2 from "yaml";
542
549
 
550
+ // node/syntax/markdown-it/markdown-it-katex.ts
551
+ import katex from "katex";
552
+ function isValidDelim(state, pos) {
553
+ const max = state.posMax;
554
+ let can_open = true;
555
+ let can_close = true;
556
+ const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
557
+ const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
558
+ if (prevChar === 32 || prevChar === 9 || /* \t */
559
+ nextChar >= 48 && nextChar <= 57)
560
+ can_close = false;
561
+ if (nextChar === 32 || nextChar === 9)
562
+ can_open = false;
563
+ return {
564
+ can_open,
565
+ can_close
566
+ };
567
+ }
568
+ function math_inline(state, silent) {
569
+ let match, token, res, pos;
570
+ if (state.src[state.pos] !== "$")
571
+ return false;
572
+ res = isValidDelim(state, state.pos);
573
+ if (!res.can_open) {
574
+ if (!silent)
575
+ state.pending += "$";
576
+ state.pos += 1;
577
+ return true;
578
+ }
579
+ const start = state.pos + 1;
580
+ match = start;
581
+ while ((match = state.src.indexOf("$", match)) !== -1) {
582
+ pos = match - 1;
583
+ while (state.src[pos] === "\\") pos -= 1;
584
+ if ((match - pos) % 2 === 1)
585
+ break;
586
+ match += 1;
587
+ }
588
+ if (match === -1) {
589
+ if (!silent)
590
+ state.pending += "$";
591
+ state.pos = start;
592
+ return true;
593
+ }
594
+ if (match - start === 0) {
595
+ if (!silent)
596
+ state.pending += "$$";
597
+ state.pos = start + 1;
598
+ return true;
599
+ }
600
+ res = isValidDelim(state, match);
601
+ if (!res.can_close) {
602
+ if (!silent)
603
+ state.pending += "$";
604
+ state.pos = start;
605
+ return true;
606
+ }
607
+ if (!silent) {
608
+ token = state.push("math_inline", "math", 0);
609
+ token.markup = "$";
610
+ token.content = state.src.slice(start, match);
611
+ }
612
+ state.pos = match + 1;
613
+ return true;
614
+ }
615
+ function math_block(state, start, end, silent) {
616
+ let firstLine;
617
+ let lastLine;
618
+ let next;
619
+ let lastPos;
620
+ let found = false;
621
+ let pos = state.bMarks[start] + state.tShift[start];
622
+ let max = state.eMarks[start];
623
+ if (pos + 2 > max)
624
+ return false;
625
+ if (state.src.slice(pos, pos + 2) !== "$$")
626
+ return false;
627
+ pos += 2;
628
+ firstLine = state.src.slice(pos, max);
629
+ if (silent)
630
+ return true;
631
+ if (firstLine.trim().slice(-2) === "$$") {
632
+ firstLine = firstLine.trim().slice(0, -2);
633
+ found = true;
634
+ }
635
+ for (next = start; !found; ) {
636
+ next++;
637
+ if (next >= end)
638
+ break;
639
+ pos = state.bMarks[next] + state.tShift[next];
640
+ max = state.eMarks[next];
641
+ if (pos < max && state.tShift[next] < state.blkIndent) {
642
+ break;
643
+ }
644
+ if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
645
+ lastPos = state.src.slice(0, max).lastIndexOf("$$");
646
+ lastLine = state.src.slice(pos, lastPos);
647
+ found = true;
648
+ }
649
+ }
650
+ state.line = next + 1;
651
+ const token = state.push("math_block", "math", 0);
652
+ token.block = true;
653
+ token.content = (firstLine && firstLine.trim() ? `${firstLine}
654
+ ` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
655
+ token.map = [start, state.line];
656
+ token.markup = "$$";
657
+ return true;
658
+ }
659
+ function MarkdownItKatex(md, options) {
660
+ const katexInline = function(latex) {
661
+ options.displayMode = false;
662
+ try {
663
+ return katex.renderToString(latex, options);
664
+ } catch (error) {
665
+ if (options.throwOnError)
666
+ console.warn(error);
667
+ return latex;
668
+ }
669
+ };
670
+ const inlineRenderer = function(tokens, idx) {
671
+ return katexInline(tokens[idx].content);
672
+ };
673
+ const katexBlock = function(latex) {
674
+ options.displayMode = true;
675
+ try {
676
+ return `<p>${katex.renderToString(latex, options)}</p>`;
677
+ } catch (error) {
678
+ if (options.throwOnError)
679
+ console.warn(error);
680
+ return latex;
681
+ }
682
+ };
683
+ const blockRenderer = function(tokens, idx) {
684
+ return `${katexBlock(tokens[idx].content)}
685
+ `;
686
+ };
687
+ md.inline.ruler.after("escape", "math_inline", math_inline);
688
+ md.block.ruler.after("blockquote", "math_block", math_block, {
689
+ alt: ["paragraph", "reference", "blockquote", "list"]
690
+ });
691
+ md.renderer.rules.math_inline = inlineRenderer;
692
+ md.renderer.rules.math_block = blockRenderer;
693
+ }
694
+
543
695
  // node/virtual/configs.ts
544
696
  import { isString } from "@antfu/utils";
545
697
  var templateConfigs = {
@@ -788,13 +940,14 @@ var templateShiki = {
788
940
  const lines = [];
789
941
  lines.push(
790
942
  `import { createHighlighterCore } from "${await resolveImportUrl("shiki/core")}"`,
943
+ `import { createJavaScriptRegexEngine } from "${await resolveImportUrl("@shikijs/engine-javascript")}"`,
791
944
  `export { shikiToMonaco } from "${await resolveImportUrl("@shikijs/monaco")}"`,
792
945
  `export const languages = ${JSON.stringify(langNames)}`,
793
946
  `export const themes = ${JSON.stringify(themeOptionsNames.themes || themeOptionsNames.theme)}`,
794
947
  "export const shiki = createHighlighterCore({",
795
948
  ` themes: [${themesInit.join(",")}],`,
796
949
  ` langs: [${langsInit.join(",")}],`,
797
- ` loadWasm: import('${await resolveImportUrl("shiki/wasm")}'),`,
950
+ ` engine: createJavaScriptRegexEngine(),`,
798
951
  "})",
799
952
  "let highlight",
800
953
  "export async function getHighlighter() {",
@@ -960,24 +1113,12 @@ var templates = [
960
1113
  ];
961
1114
 
962
1115
  // node/vite/loaders.ts
963
- function renderNote(text = "") {
964
- let clickCount = 0;
965
- const html = sharedMd.render(
966
- text.replace(/\[click(?::(\d+))?\]/gi, (_, count = 1) => {
967
- clickCount += Number(count);
968
- return `<span class="slidev-note-click-mark" data-clicks="${clickCount}"></span>`;
969
- })
970
- );
971
- return html;
972
- }
973
- function withRenderedNote(data) {
974
- return {
975
- ...data,
976
- noteHTML: renderNote(data?.note)
977
- };
978
- }
979
1116
  function createSlidesLoader(options, serverOptions) {
980
1117
  const { data, mode, utils } = options;
1118
+ const notesMd = MarkdownIt({ html: true });
1119
+ notesMd.use(MarkdownItLink);
1120
+ if (data.features.katex)
1121
+ notesMd.use(MarkdownItKatex, utils.katexOptions);
981
1122
  const hmrSlidesIndexes = /* @__PURE__ */ new Set();
982
1123
  let server;
983
1124
  let skipHmr = null;
@@ -1252,6 +1393,22 @@ function createSlidesLoader(options, serverOptions) {
1252
1393
  return "";
1253
1394
  }
1254
1395
  };
1396
+ function renderNote(text = "") {
1397
+ let clickCount = 0;
1398
+ const html = notesMd.render(
1399
+ text.replace(/\[click(?::(\d+))?\]/gi, (_, count = 1) => {
1400
+ clickCount += Number(count);
1401
+ return `<span class="slidev-note-click-mark" data-clicks="${clickCount}"></span>`;
1402
+ })
1403
+ );
1404
+ return html;
1405
+ }
1406
+ function withRenderedNote(data2) {
1407
+ return {
1408
+ ...data2,
1409
+ noteHTML: renderNote(data2?.note)
1410
+ };
1411
+ }
1255
1412
  }
1256
1413
 
1257
1414
  // node/vite/markdown.ts
@@ -1387,35 +1544,6 @@ function startsWithTodoMarkdown(token) {
1387
1544
  import MarkdownItFootnote from "markdown-it-footnote";
1388
1545
  import MarkdownItMdc from "markdown-it-mdc";
1389
1546
 
1390
- // node/setups/load.ts
1391
- import { resolve as resolve4 } from "node:path";
1392
- import { deepMergeWithArray } from "@antfu/utils";
1393
- import fs3 from "fs-extra";
1394
- async function loadSetups(roots, filename, args, extraLoader) {
1395
- const returns = [];
1396
- for (const root of roots) {
1397
- const path4 = resolve4(root, "setup", filename);
1398
- if (fs3.existsSync(path4)) {
1399
- const { default: setup } = await loadModule(path4);
1400
- const ret = await setup(...args);
1401
- if (ret)
1402
- returns.push(ret);
1403
- }
1404
- if (extraLoader)
1405
- returns.push(...await extraLoader(root));
1406
- }
1407
- return returns;
1408
- }
1409
-
1410
- // node/setups/katex.ts
1411
- async function setupKatex(roots) {
1412
- const options = await loadSetups(roots, "katex.ts", []);
1413
- return Object.assign(
1414
- { strict: false },
1415
- ...options
1416
- );
1417
- }
1418
-
1419
1547
  // node/syntax/markdown-it/markdown-it-escape-code.ts
1420
1548
  function MarkdownItEscapeInlineCode(md) {
1421
1549
  const codeInline = md.renderer.rules.code_inline;
@@ -1425,151 +1553,6 @@ function MarkdownItEscapeInlineCode(md) {
1425
1553
  };
1426
1554
  }
1427
1555
 
1428
- // node/syntax/markdown-it/markdown-it-katex.ts
1429
- import katex from "katex";
1430
- function isValidDelim(state, pos) {
1431
- const max = state.posMax;
1432
- let can_open = true;
1433
- let can_close = true;
1434
- const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
1435
- const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
1436
- if (prevChar === 32 || prevChar === 9 || /* \t */
1437
- nextChar >= 48 && nextChar <= 57)
1438
- can_close = false;
1439
- if (nextChar === 32 || nextChar === 9)
1440
- can_open = false;
1441
- return {
1442
- can_open,
1443
- can_close
1444
- };
1445
- }
1446
- function math_inline(state, silent) {
1447
- let match, token, res, pos;
1448
- if (state.src[state.pos] !== "$")
1449
- return false;
1450
- res = isValidDelim(state, state.pos);
1451
- if (!res.can_open) {
1452
- if (!silent)
1453
- state.pending += "$";
1454
- state.pos += 1;
1455
- return true;
1456
- }
1457
- const start = state.pos + 1;
1458
- match = start;
1459
- while ((match = state.src.indexOf("$", match)) !== -1) {
1460
- pos = match - 1;
1461
- while (state.src[pos] === "\\") pos -= 1;
1462
- if ((match - pos) % 2 === 1)
1463
- break;
1464
- match += 1;
1465
- }
1466
- if (match === -1) {
1467
- if (!silent)
1468
- state.pending += "$";
1469
- state.pos = start;
1470
- return true;
1471
- }
1472
- if (match - start === 0) {
1473
- if (!silent)
1474
- state.pending += "$$";
1475
- state.pos = start + 1;
1476
- return true;
1477
- }
1478
- res = isValidDelim(state, match);
1479
- if (!res.can_close) {
1480
- if (!silent)
1481
- state.pending += "$";
1482
- state.pos = start;
1483
- return true;
1484
- }
1485
- if (!silent) {
1486
- token = state.push("math_inline", "math", 0);
1487
- token.markup = "$";
1488
- token.content = state.src.slice(start, match);
1489
- }
1490
- state.pos = match + 1;
1491
- return true;
1492
- }
1493
- function math_block(state, start, end, silent) {
1494
- let firstLine;
1495
- let lastLine;
1496
- let next;
1497
- let lastPos;
1498
- let found = false;
1499
- let pos = state.bMarks[start] + state.tShift[start];
1500
- let max = state.eMarks[start];
1501
- if (pos + 2 > max)
1502
- return false;
1503
- if (state.src.slice(pos, pos + 2) !== "$$")
1504
- return false;
1505
- pos += 2;
1506
- firstLine = state.src.slice(pos, max);
1507
- if (silent)
1508
- return true;
1509
- if (firstLine.trim().slice(-2) === "$$") {
1510
- firstLine = firstLine.trim().slice(0, -2);
1511
- found = true;
1512
- }
1513
- for (next = start; !found; ) {
1514
- next++;
1515
- if (next >= end)
1516
- break;
1517
- pos = state.bMarks[next] + state.tShift[next];
1518
- max = state.eMarks[next];
1519
- if (pos < max && state.tShift[next] < state.blkIndent) {
1520
- break;
1521
- }
1522
- if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
1523
- lastPos = state.src.slice(0, max).lastIndexOf("$$");
1524
- lastLine = state.src.slice(pos, lastPos);
1525
- found = true;
1526
- }
1527
- }
1528
- state.line = next + 1;
1529
- const token = state.push("math_block", "math", 0);
1530
- token.block = true;
1531
- token.content = (firstLine && firstLine.trim() ? `${firstLine}
1532
- ` : "") + state.getLines(start + 1, next, state.tShift[start], true) + (lastLine && lastLine.trim() ? lastLine : "");
1533
- token.map = [start, state.line];
1534
- token.markup = "$$";
1535
- return true;
1536
- }
1537
- function MarkdownItKatex(md, options) {
1538
- const katexInline = function(latex) {
1539
- options.displayMode = false;
1540
- try {
1541
- return katex.renderToString(latex, options);
1542
- } catch (error) {
1543
- if (options.throwOnError)
1544
- console.warn(error);
1545
- return latex;
1546
- }
1547
- };
1548
- const inlineRenderer = function(tokens, idx) {
1549
- return katexInline(tokens[idx].content);
1550
- };
1551
- const katexBlock = function(latex) {
1552
- options.displayMode = true;
1553
- try {
1554
- return `<p>${katex.renderToString(latex, options)}</p>`;
1555
- } catch (error) {
1556
- if (options.throwOnError)
1557
- console.warn(error);
1558
- return latex;
1559
- }
1560
- };
1561
- const blockRenderer = function(tokens, idx) {
1562
- return `${katexBlock(tokens[idx].content)}
1563
- `;
1564
- };
1565
- md.inline.ruler.after("escape", "math_inline", math_inline);
1566
- md.block.ruler.after("blockquote", "math_block", math_block, {
1567
- alt: ["paragraph", "reference", "blockquote", "list"]
1568
- });
1569
- md.renderer.rules.math_inline = inlineRenderer;
1570
- md.renderer.rules.math_block = blockRenderer;
1571
- }
1572
-
1573
1556
  // node/syntax/markdown-it/markdown-it-shiki.ts
1574
1557
  import { isTruthy } from "@antfu/utils";
1575
1558
  import { fromHighlighter } from "@shikijs/markdown-it/core";
@@ -1687,7 +1670,7 @@ function MarkdownItVDrag(md, markdownTransformMap) {
1687
1670
 
1688
1671
  // node/syntax/markdown-it/index.ts
1689
1672
  async function useMarkdownItPlugins(md, options, markdownTransformMap) {
1690
- const { roots, data: { features, config } } = options;
1673
+ const { data: { features, config }, utils: { katexOptions } } = options;
1691
1674
  if (config.highlighter === "shiki") {
1692
1675
  md.use(await MarkdownItShiki(options));
1693
1676
  }
@@ -1696,12 +1679,32 @@ async function useMarkdownItPlugins(md, options, markdownTransformMap) {
1696
1679
  md.use(MarkdownItFootnote);
1697
1680
  md.use(taskLists, { enabled: true, lineNumber: true, label: true });
1698
1681
  if (features.katex)
1699
- md.use(MarkdownItKatex, await setupKatex(roots));
1682
+ md.use(MarkdownItKatex, katexOptions);
1700
1683
  md.use(MarkdownItVDrag, markdownTransformMap);
1701
1684
  if (config.mdc)
1702
1685
  md.use(MarkdownItMdc);
1703
1686
  }
1704
1687
 
1688
+ // node/setups/load.ts
1689
+ import { resolve as resolve4 } from "node:path";
1690
+ import { deepMergeWithArray } from "@antfu/utils";
1691
+ import fs3 from "fs-extra";
1692
+ async function loadSetups(roots, filename, args, extraLoader) {
1693
+ const returns = [];
1694
+ for (const root of roots) {
1695
+ const path4 = resolve4(root, "setup", filename);
1696
+ if (fs3.existsSync(path4)) {
1697
+ const { default: setup } = await loadModule(path4);
1698
+ const ret = await setup(...args);
1699
+ if (ret)
1700
+ returns.push(ret);
1701
+ }
1702
+ if (extraLoader)
1703
+ returns.push(...await extraLoader(root));
1704
+ }
1705
+ return returns;
1706
+ }
1707
+
1705
1708
  // node/setups/transformers.ts
1706
1709
  async function setupTransformers(roots) {
1707
1710
  const returns = await loadSetups(roots, "transformers.ts", []);
@@ -2086,10 +2089,10 @@ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
2086
2089
  },
2087
2090
  transforms: {
2088
2091
  ...mdOptions?.transforms,
2089
- before(code, id) {
2092
+ async before(code, id) {
2090
2093
  if (options.data.markdownFiles[id])
2091
2094
  return "";
2092
- code = mdOptions?.transforms?.before?.(code, id) ?? code;
2095
+ code = await mdOptions?.transforms?.before?.(code, id) ?? code;
2093
2096
  const match = id.match(regexSlideSourceId);
2094
2097
  if (!match)
2095
2098
  return code;
@@ -2103,7 +2106,7 @@ async function createMarkdownPlugin(options, { markdown: mdOptions }) {
2103
2106
  for (const transformer of transformers) {
2104
2107
  if (!transformer)
2105
2108
  continue;
2106
- transformer(ctx);
2109
+ await transformer(ctx);
2107
2110
  if (!ctx.s.isEmpty())
2108
2111
  ctx.s.commit();
2109
2112
  }
@@ -2449,7 +2452,7 @@ function ViteSlidevPlugin(options, pluginOptions = {}, serverOptions = {}) {
2449
2452
  }
2450
2453
 
2451
2454
  // node/commands/shared.ts
2452
- var sharedMd = MarkdownIt({ html: true });
2455
+ var sharedMd = MarkdownIt2({ html: true });
2453
2456
  sharedMd.use(MarkdownItLink);
2454
2457
  function getSlideTitle(data) {
2455
2458
  const tokens = sharedMd.parseInline(data.config.title, {});
@@ -2488,7 +2491,7 @@ async function resolveViteConfigs(options, baseConfig, overrideConfigs, command,
2488
2491
  function toAttrValue(unsafe) {
2489
2492
  return JSON.stringify(escapeHtml(String(unsafe)));
2490
2493
  }
2491
- function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data }) {
2494
+ function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data, base }) {
2492
2495
  let main = readFileSync2(join13(clientRoot, "index.html"), "utf-8");
2493
2496
  let head = "";
2494
2497
  let body = "";
@@ -2519,15 +2522,31 @@ ${(index.match(/<body>([\s\S]*?)<\/body>/i)?.[1] || "").trim()}`;
2519
2522
  }
2520
2523
  if (data.features.tweet)
2521
2524
  body += '\n<script async src="https://platform.twitter.com/widgets.js"></script>';
2522
- if (data.config.fonts.webfonts.length && data.config.fonts.provider !== "none")
2523
- head += `
2525
+ if (data.config.fonts.webfonts.length) {
2526
+ const { provider } = data.config.fonts;
2527
+ if (provider === "google")
2528
+ head += `
2524
2529
  <link rel="stylesheet" href="${generateGoogleFontsUrl(data.config.fonts)}" type="text/css">`;
2530
+ else if (provider === "coollabs")
2531
+ head += `
2532
+ <link rel="stylesheet" href="${generateCoollabsFontsUrl(data.config.fonts)}" type="text/css">`;
2533
+ }
2525
2534
  if (data.headmatter.lang)
2526
2535
  main = main.replace('<html lang="en">', `<html lang="${data.headmatter.lang}">`);
2527
- main = main.replace("__ENTRY__", toAtFS(join13(clientRoot, "main.ts"))).replace("<!-- head -->", head).replace("<!-- body -->", body);
2536
+ const baseInDev = mode === "dev" && base ? base.slice(0, -1) : "";
2537
+ main = main.replace("__ENTRY__", baseInDev + toAtFS(join13(clientRoot, "main.ts"))).replace("<!-- head -->", head).replace("<!-- body -->", body);
2528
2538
  return main;
2529
2539
  }
2530
2540
 
2541
+ // node/setups/katex.ts
2542
+ async function setupKatex(roots) {
2543
+ const options = await loadSetups(roots, "katex.ts", []);
2544
+ return Object.assign(
2545
+ { strict: false },
2546
+ ...options
2547
+ );
2548
+ }
2549
+
2531
2550
  // node/setups/shiki.ts
2532
2551
  import fs9 from "node:fs/promises";
2533
2552
  import { bundledLanguages, createHighlighter } from "shiki";
@@ -2631,6 +2650,7 @@ async function createDataUtils(resolved) {
2631
2650
  let _layouts_cache = {};
2632
2651
  return {
2633
2652
  ...await setupShiki(resolved.roots),
2653
+ katexOptions: await setupKatex(resolved.roots),
2634
2654
  indexHtml: setupIndexHtml(resolved),
2635
2655
  define: getDefine(resolved),
2636
2656
  iconsResolvePath: [resolved.clientRoot, ...resolved.roots].reverse(),
package/dist/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-UF7FZDYU.js";
3
+ } from "./chunk-HPAG2I6S.js";
4
4
  import {
5
5
  getThemeMeta,
6
6
  loadSetups,
@@ -9,7 +9,7 @@ import {
9
9
  resolveOptions,
10
10
  resolveTheme,
11
11
  version
12
- } from "./chunk-3JQYTPPL.js";
12
+ } from "./chunk-UAXJBAYZ.js";
13
13
  import {
14
14
  getRoots,
15
15
  isInstalledGlobally,
@@ -103,13 +103,17 @@ cli.command(
103
103
  alias: "f",
104
104
  default: false,
105
105
  type: "boolean",
106
- describe: "force the optimizer to ignore the cache and re-bundle "
106
+ describe: "force the optimizer to ignore the cache and re-bundle"
107
107
  }).option("bind", {
108
108
  type: "string",
109
109
  default: "0.0.0.0",
110
110
  describe: "specify which IP addresses the server should listen on in remote mode"
111
+ }).option("base", {
112
+ type: "string",
113
+ describe: "base URL. Example: /demo/",
114
+ default: "/"
111
115
  }).strict().help(),
112
- async ({ entry, theme, port: userPort, open, log, remote, tunnel, force, inspect, bind }) => {
116
+ async ({ entry, theme, port: userPort, open, log, remote, tunnel, force, inspect, bind, base }) => {
113
117
  let server;
114
118
  let port = 3030;
115
119
  let lastRemoteUrl;
@@ -124,7 +128,7 @@ cli.command(
124
128
  async function initServer() {
125
129
  if (server)
126
130
  await server.close();
127
- const options = await resolveOptions({ entry, remote, theme, inspect }, "dev");
131
+ const options = await resolveOptions({ entry, remote, theme, inspect, base }, "dev");
128
132
  const host = remote !== void 0 ? bind : "localhost";
129
133
  port = userPort || await getPort({
130
134
  port: 3030,
@@ -147,7 +151,8 @@ cli.command(
147
151
  // Vite 5
148
152
  force
149
153
  },
150
- logLevel: log
154
+ logLevel: log,
155
+ base
151
156
  },
152
157
  {
153
158
  async loadData(loadedSource) {
@@ -190,7 +195,7 @@ cli.command(
190
195
  let publicIp;
191
196
  if (remote)
192
197
  publicIp = await import("public-ip").then((r) => r.publicIpv4());
193
- lastRemoteUrl = printInfo(options, port, remote, tunnelUrl, publicIp);
198
+ lastRemoteUrl = printInfo(options, port, base, remote, tunnelUrl, publicIp);
194
199
  }
195
200
  async function openTunnel(port2) {
196
201
  const { startTunnel } = await import("untun");
@@ -212,7 +217,7 @@ cli.command(
212
217
  name: "o",
213
218
  fullname: "open",
214
219
  action() {
215
- openBrowser(`http://localhost:${port}`);
220
+ openBrowser(`http://localhost:${port}${base}`);
216
221
  }
217
222
  },
218
223
  {
@@ -320,7 +325,7 @@ cli.command(
320
325
  describe: "output dir"
321
326
  }).option("base", {
322
327
  type: "string",
323
- describe: "output base"
328
+ describe: "output base. Example: /demo/"
324
329
  }).option("download", {
325
330
  alias: "d",
326
331
  type: "boolean",
@@ -332,9 +337,9 @@ cli.command(
332
337
  }).strict().help(),
333
338
  async (args) => {
334
339
  const { entry, theme, base, download, out, inspect } = args;
335
- const { build } = await import("./build-47SVPVZN.js");
340
+ const { build } = await import("./build-5CO2TPP4.js");
336
341
  for (const entryFile of entry) {
337
- const options = await resolveOptions({ entry: entryFile, theme, inspect, download }, "build");
342
+ const options = await resolveOptions({ entry: entryFile, theme, inspect, download, base }, "build");
338
343
  printInfo(options);
339
344
  await build(
340
345
  options,
@@ -552,7 +557,8 @@ function exportOptions(args) {
552
557
  describe: "export png pages without the default browser background"
553
558
  });
554
559
  }
555
- function printInfo(options, port, remote, tunnelUrl, publicIp) {
560
+ function printInfo(options, port, base, remote, tunnelUrl, publicIp) {
561
+ const baseUrl = port && `http://localhost:${bold(port + (base?.slice(0, -1) || ""))}`;
556
562
  console.log();
557
563
  console.log();
558
564
  console.log(` ${cyan("\u25CF") + blue("\u25A0") + yellow("\u25B2")}`);
@@ -562,22 +568,22 @@ function printInfo(options, port, remote, tunnelUrl, publicIp) {
562
568
  console.log(dim(" theme ") + (options.theme ? green(options.theme) : gray("none")));
563
569
  console.log(dim(" css engine ") + blue("unocss"));
564
570
  console.log(dim(" entry ") + dim(path.normalize(path.dirname(options.entry)) + path.sep) + path.basename(options.entry));
565
- if (port) {
571
+ if (baseUrl) {
566
572
  const query = remote ? `?password=${remote}` : "";
567
573
  const presenterPath = `${options.data.config.routerMode === "hash" ? "/#/" : "/"}presenter/${query}`;
568
574
  const entryPath = `${options.data.config.routerMode === "hash" ? "/#/" : "/"}entry${query}/`;
569
575
  const overviewPath = `${options.data.config.routerMode === "hash" ? "/#/" : "/"}overview${query}/`;
570
576
  console.log();
571
- console.log(`${dim(" public slide show ")} > ${cyan(`http://localhost:${bold(port)}/`)}`);
577
+ console.log(`${dim(" public slide show ")} > ${cyan(`${baseUrl}/`)}`);
572
578
  if (query)
573
- console.log(`${dim(" private slide show ")} > ${cyan(`http://localhost:${bold(port)}/${query}`)}`);
579
+ console.log(`${dim(" private slide show ")} > ${cyan(`${baseUrl}/${query}`)}`);
574
580
  if (options.utils.define.__SLIDEV_FEATURE_PRESENTER__)
575
- console.log(`${dim(" presenter mode ")} > ${blue(`http://localhost:${bold(port)}${presenterPath}`)}`);
576
- console.log(`${dim(" slides overview ")} > ${blue(`http://localhost:${bold(port)}${overviewPath}`)}`);
581
+ console.log(`${dim(" presenter mode ")} > ${blue(`${baseUrl}${presenterPath}`)}`);
582
+ console.log(`${dim(" slides overview ")} > ${blue(`${baseUrl}${overviewPath}`)}`);
577
583
  if (options.utils.define.__SLIDEV_FEATURE_BROWSER_EXPORTER__)
578
- console.log(`${dim(" export slides")} > ${blue(`http://localhost:${bold(port)}/export/`)}`);
584
+ console.log(`${dim(" export slides")} > ${blue(`${baseUrl}/export/`)}`);
579
585
  if (options.inspect)
580
- console.log(`${dim(" vite inspector")} > ${yellow(`http://localhost:${bold(port)}/__inspect/`)}`);
586
+ console.log(`${dim(" vite inspector")} > ${yellow(`${baseUrl}/__inspect/`)}`);
581
587
  let lastRemoteUrl = "";
582
588
  if (remote !== void 0) {
583
589
  Object.values(os.networkInterfaces()).forEach((v) => (v || []).filter((details) => String(details.family).slice(-1) === "4" && !details.address.includes("127.0.0.1")).forEach(({ address }) => {
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  createServer
3
- } from "./chunk-UF7FZDYU.js";
3
+ } from "./chunk-HPAG2I6S.js";
4
4
  import {
5
5
  ViteSlidevPlugin,
6
6
  createDataUtils,
7
7
  parser,
8
8
  resolveOptions
9
- } from "./chunk-3JQYTPPL.js";
9
+ } from "./chunk-UAXJBAYZ.js";
10
10
  import "./chunk-UNQ5DBLZ.js";
11
11
  export {
12
12
  ViteSlidevPlugin,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@slidev/cli",
3
3
  "type": "module",
4
- "version": "51.0.1",
4
+ "version": "51.1.0",
5
5
  "description": "Presentation slides for developers",
6
6
  "author": "antfu <anthonyfu117@hotmail.com>",
7
7
  "license": "MIT",
@@ -42,17 +42,17 @@
42
42
  }
43
43
  },
44
44
  "dependencies": {
45
- "@antfu/ni": "^23.2.0",
46
- "@antfu/utils": "^8.0.0",
45
+ "@antfu/ni": "^23.3.0",
46
+ "@antfu/utils": "^8.1.0",
47
47
  "@iconify-json/carbon": "^1.2.5",
48
48
  "@iconify-json/ph": "^1.2.2",
49
49
  "@iconify-json/svg-spinners": "^1.2.2",
50
50
  "@lillallol/outline-pdf": "^4.0.0",
51
- "@shikijs/markdown-it": "^1.26.1",
52
- "@shikijs/twoslash": "^1.26.1",
53
- "@shikijs/vitepress-twoslash": "^1.26.1",
54
- "@unocss/extractor-mdc": "^65.4.0",
55
- "@unocss/reset": "^65.4.0",
51
+ "@shikijs/markdown-it": "^2.1.0",
52
+ "@shikijs/twoslash": "^2.1.0",
53
+ "@shikijs/vitepress-twoslash": "^2.1.0",
54
+ "@unocss/extractor-mdc": "^65.4.3",
55
+ "@unocss/reset": "^65.4.3",
56
56
  "@vitejs/plugin-vue": "^5.2.1",
57
57
  "@vitejs/plugin-vue-jsx": "^4.1.1",
58
58
  "chokidar": "^4.0.3",
@@ -61,18 +61,18 @@
61
61
  "debug": "^4.4.0",
62
62
  "fast-deep-equal": "^3.1.3",
63
63
  "fast-glob": "^3.3.3",
64
- "fs-extra": "^11.2.0",
64
+ "fs-extra": "^11.3.0",
65
65
  "get-port-please": "^3.1.2",
66
66
  "global-directory": "^4.0.1",
67
67
  "htmlparser2": "^10.0.0",
68
68
  "is-installed-globally": "^1.0.0",
69
69
  "jiti": "^2.4.2",
70
- "katex": "^0.16.20",
70
+ "katex": "^0.16.21",
71
71
  "kolorist": "^1.8.0",
72
72
  "local-pkg": "^1.0.0",
73
73
  "lz-string": "^1.5.0",
74
74
  "magic-string": "^0.30.17",
75
- "magic-string-stack": "^0.1.1",
75
+ "magic-string-stack": "^1.0.0",
76
76
  "markdown-it": "^14.1.0",
77
77
  "markdown-it-footnote": "^4.0.0",
78
78
  "markdown-it-mdc": "^0.2.5",
@@ -88,20 +88,20 @@
88
88
  "public-ip": "^7.0.1",
89
89
  "resolve-from": "^5.0.0",
90
90
  "resolve-global": "^2.0.0",
91
- "semver": "^7.6.3",
92
- "shiki": "^1.26.1",
93
- "shiki-magic-move": "^0.5.2",
91
+ "semver": "^7.7.0",
92
+ "shiki": "^2.1.0",
93
+ "shiki-magic-move": "^1.0.0",
94
94
  "sirv": "^3.0.0",
95
95
  "source-map-js": "^1.2.1",
96
96
  "typescript": "^5.7.3",
97
- "unocss": "^65.4.0",
97
+ "unocss": "^65.4.3",
98
98
  "unplugin-icons": "^22.0.0",
99
99
  "unplugin-vue-components": "^28.0.0",
100
- "unplugin-vue-markdown": "^28.0.0",
100
+ "unplugin-vue-markdown": "^28.2.0",
101
101
  "untun": "^0.1.3",
102
102
  "uqr": "^0.1.2",
103
- "vite": "^6.0.7",
104
- "vite-plugin-inspect": "^10.0.6",
103
+ "vite": "^6.0.11",
104
+ "vite-plugin-inspect": "^10.1.0",
105
105
  "vite-plugin-remote-assets": "^0.6.0",
106
106
  "vite-plugin-static-copy": "^2.2.0",
107
107
  "vite-plugin-vue-server-ref": "^0.4.2",
@@ -109,9 +109,9 @@
109
109
  "vue": "^3.5.13",
110
110
  "yaml": "^2.7.0",
111
111
  "yargs": "^17.7.2",
112
- "@slidev/parser": "51.0.1",
113
- "@slidev/client": "51.0.1",
114
- "@slidev/types": "51.0.1"
112
+ "@slidev/client": "51.1.0",
113
+ "@slidev/parser": "51.1.0",
114
+ "@slidev/types": "51.1.0"
115
115
  },
116
116
  "devDependencies": {
117
117
  "@hedgedoc/markdown-it-plugins": "^2.1.4",