vuepress-plugin-md-power 1.0.0-rc.152 → 1.0.0-rc.153

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.
@@ -11,7 +11,7 @@ let container: HTMLPreElement | null = null
11
11
  let lineNumbers: HTMLDivElement | null = null
12
12
  const { grammars, theme } = editorData
13
13
 
14
- const lang = ref<'go' | 'rust' | 'kotlin'>()
14
+ const lang = ref<'go' | 'rust' | 'kotlin' | 'python'>()
15
15
 
16
16
  const editorEl = shallowRef<HTMLDivElement>()
17
17
  const textAreaEl = shallowRef<HTMLTextAreaElement>()
@@ -36,5 +36,6 @@ interface UseAudioPlayerResult {
36
36
  setVolume: (volume: number) => void;
37
37
  destroy: () => void;
38
38
  }
39
- declare function useAudioPlayer(source: MaybeRef<string>, options?: AudioPlayerOptions): UseAudioPlayerResult; //#endregion
39
+ declare function useAudioPlayer(source: MaybeRef<string>, options?: AudioPlayerOptions): UseAudioPlayerResult;
40
+ //#endregion
40
41
  export { AudioPlayerOptions, BufferedRange, useAudioPlayer };
@@ -1,7 +1,7 @@
1
1
  import { Ref } from "vue";
2
2
 
3
3
  //#region src/client/composables/codeRepl.d.ts
4
- type Lang = "kotlin" | "go" | "rust";
4
+ type Lang = "kotlin" | "go" | "rust" | "python";
5
5
  declare function resolveCode(el: HTMLElement): string;
6
6
  declare function resolveCodeInfo(el: HTMLDivElement): {
7
7
  lang: Lang;
@@ -20,6 +20,5 @@ interface UseCodeReplResult {
20
20
  onRunCode: () => Promise<void>;
21
21
  }
22
22
  declare function useCodeRepl(el: Ref<HTMLDivElement | null>): UseCodeReplResult;
23
-
24
23
  //#endregion
25
24
  export { resolveCode, resolveCodeInfo, useCodeRepl };
@@ -10,17 +10,21 @@ const api = {
10
10
  go: "https://api.pengzhanbo.cn/repl/golang/run",
11
11
  kotlin: "https://api.pengzhanbo.cn/repl/kotlin/run"
12
12
  };
13
+ let pyodide = null;
13
14
  const langAlias = {
14
15
  kt: "kotlin",
15
16
  kotlin: "kotlin",
16
17
  go: "go",
17
18
  rust: "rust",
18
- rs: "rust"
19
+ rs: "rust",
20
+ py: "python",
21
+ python: "python"
19
22
  };
20
23
  const supportLang = [
21
24
  "kotlin",
22
25
  "go",
23
- "rust"
26
+ "rust",
27
+ "python"
24
28
  ];
25
29
  function resolveLang(lang) {
26
30
  return lang ? langAlias[lang] || lang : "";
@@ -59,7 +63,8 @@ function useCodeRepl(el) {
59
63
  const executeMap = {
60
64
  kotlin: executeKotlin,
61
65
  go: executeGolang,
62
- rust: executeRust
66
+ rust: executeRust,
67
+ python: executePython
63
68
  };
64
69
  function onCleanRun() {
65
70
  loaded.value = false;
@@ -142,6 +147,24 @@ function useCodeRepl(el) {
142
147
  }
143
148
  });
144
149
  }
150
+ async function executePython(code) {
151
+ loaded.value = false;
152
+ finished.value = false;
153
+ if (pyodide === null) {
154
+ const { loadPyodide, version } = await import(
155
+ /* webpackChunkName: "pyodide" */
156
+ "pyodide");
157
+ pyodide = await loadPyodide({ indexURL: `https://cdn.jsdelivr.net/pyodide/v${version}/full/` });
158
+ }
159
+ pyodide.setStdout({ batched: (msg) => stdout.value.push(msg) });
160
+ try {
161
+ stdout.value.push(pyodide.runPython(code));
162
+ } catch (e) {
163
+ stderr.value.push(String(e));
164
+ }
165
+ loaded.value = true;
166
+ finished.value = true;
167
+ }
145
168
  return {
146
169
  onRunCode,
147
170
  onCleanRun,
@@ -36,6 +36,5 @@ declare function useNormalDemo(draw: ShallowRef<HTMLIFrameElement | null>, title
36
36
  height: Ref<string>;
37
37
  };
38
38
  declare function parseData(data: any): any;
39
-
40
39
  //#endregion
41
40
  export { DemoConfig, parseData, useExpand, useFence, useNormalDemo, useResources };
@@ -13,6 +13,5 @@ interface RustExecuteOptions {
13
13
  onEnd?: () => void;
14
14
  onError?: (message: string) => void;
15
15
  }
16
-
17
16
  //#endregion
18
17
  export { rustExecute };
@@ -11,6 +11,5 @@ interface SizeInfo<T extends HTMLElement> {
11
11
  resize: () => void;
12
12
  }
13
13
  declare function useSize<T extends HTMLElement>(options: ToRefs<SizeOptions>, extraHeight?: MaybeRef$1<number>): SizeInfo<T>;
14
-
15
14
  //#endregion
16
15
  export { SizeInfo, useSize };
@@ -9,5 +9,6 @@ declare const installed: {
9
9
  };
10
10
  declare const ART_PLAYER_SUPPORTED_VIDEO_TYPES: string[];
11
11
  declare const INJECT_TIMELINE_KEY: symbol;
12
- declare const INJECT_COLLAPSE_KEY: symbol; //#endregion
12
+ declare const INJECT_COLLAPSE_KEY: symbol;
13
+ //#endregion
13
14
  export { ART_PLAYER_SUPPORTED_VIDEO_TYPES, INJECT_COLLAPSE_KEY, INJECT_TIMELINE_KEY, installed, pluginOptions };
@@ -3,6 +3,5 @@ declare const http: {
3
3
  get: <T extends object = object, R = any>(url: string, query?: T) => Promise<R>;
4
4
  post: <T extends object = object, R = any>(url: string, data?: T) => Promise<R>;
5
5
  };
6
-
7
6
  //#endregion
8
7
  export { http };
@@ -1,5 +1,4 @@
1
1
  //#region src/client/utils/link.d.ts
2
2
  declare function normalizeLink(url: string): string;
3
-
4
3
  //#endregion
5
4
  export { normalizeLink };
@@ -1,5 +1,4 @@
1
1
  //#region src/client/utils/sleep.d.ts
2
2
  declare function sleep(ms: number): Promise<void>;
3
-
4
3
  //#endregion
5
4
  export { sleep };
@@ -23,14 +23,14 @@ interface CanIUseOptions {
23
23
  * @default 'embed'
24
24
  */
25
25
  mode?: CanIUseMode;
26
- } //#endregion
26
+ }
27
+ //#endregion
27
28
  //#region src/shared/size.d.ts
28
29
  interface SizeOptions {
29
30
  width?: string;
30
31
  height?: string;
31
32
  ratio?: number | string;
32
33
  }
33
-
34
34
  //#endregion
35
35
  //#region src/shared/codepen.d.ts
36
36
  interface CodepenTokenMeta extends SizeOptions {
@@ -42,7 +42,6 @@ interface CodepenTokenMeta extends SizeOptions {
42
42
  preview?: boolean;
43
43
  editable?: boolean;
44
44
  }
45
-
46
45
  //#endregion
47
46
  //#region src/shared/codeSandbox.d.ts
48
47
  interface CodeSandboxTokenMeta extends SizeOptions {
@@ -55,7 +54,6 @@ interface CodeSandboxTokenMeta extends SizeOptions {
55
54
  navbar?: boolean;
56
55
  console?: boolean;
57
56
  }
58
-
59
57
  //#endregion
60
58
  //#region src/shared/codeTabs.d.ts
61
59
  interface CodeTabsOptions {
@@ -64,7 +62,6 @@ interface CodeTabsOptions {
64
62
  extensions?: false | string[];
65
63
  };
66
64
  }
67
-
68
65
  //#endregion
69
66
  //#region src/shared/demo.d.ts
70
67
  interface DemoFile {
@@ -89,14 +86,12 @@ interface DemoContainerRender {
89
86
  after: () => string;
90
87
  token?: (token: Token, tokens: Token[], index: number) => void;
91
88
  }
92
-
93
89
  //#endregion
94
90
  //#region src/shared/fileTree.d.ts
95
91
  type FileTreeIconMode = "simple" | "colored";
96
92
  interface FileTreeOptions {
97
93
  icon?: FileTreeIconMode;
98
94
  }
99
-
100
95
  //#endregion
101
96
  //#region src/shared/icon.d.ts
102
97
  type IconOptions = IconifyProvider | IconFontProvider | FontAwesomeProvider;
@@ -159,7 +154,6 @@ type IconifyPrefix = "material-symbols" | "material-symbols-light" | "ic" | "mdi
159
154
  type LiteralUnion<Union extends Base, Base = string> = Union | (Base & {
160
155
  zz_IGNORE_ME?: never;
161
156
  });
162
-
163
157
  //#endregion
164
158
  //#region src/shared/jsfiddle.d.ts
165
159
  interface JSFiddleTokenMeta extends SizeOptions {
@@ -168,14 +162,12 @@ interface JSFiddleTokenMeta extends SizeOptions {
168
162
  theme?: string;
169
163
  tab?: string;
170
164
  }
171
-
172
165
  //#endregion
173
166
  //#region src/shared/npmTo.d.ts
174
167
  type NpmToPackageManager = "npm" | "pnpm" | "yarn" | "bun" | "deno";
175
168
  type NpmToOptions = NpmToPackageManager[] | {
176
169
  tabs?: NpmToPackageManager[];
177
170
  };
178
-
179
171
  //#endregion
180
172
  //#region src/shared/pdf.d.ts
181
173
  type PDFEmbedType = "iframe" | "embed" | "pdfjs";
@@ -192,7 +184,6 @@ interface PDFOptions {
192
184
  */
193
185
  pdfjsUrl?: string;
194
186
  }
195
-
196
187
  //#endregion
197
188
  //#region src/shared/plot.d.ts
198
189
  interface PlotOptions {
@@ -222,14 +213,12 @@ interface PlotOptions {
222
213
  */
223
214
  trigger?: "hover" | "click";
224
215
  }
225
-
226
216
  //#endregion
227
217
  //#region src/shared/codeTree.d.ts
228
218
  interface CodeTreeOptions {
229
219
  icon?: FileTreeIconMode;
230
220
  height?: string | number;
231
221
  }
232
-
233
222
  //#endregion
234
223
  //#region src/shared/repl.d.ts
235
224
  type ThemeOptions = BuiltinTheme | {
@@ -241,19 +230,20 @@ interface ReplOptions {
241
230
  go?: boolean;
242
231
  kotlin?: boolean;
243
232
  rust?: boolean;
233
+ python?: boolean;
244
234
  }
245
235
  interface ReplEditorData {
246
236
  grammars: {
247
237
  go?: any;
248
238
  kotlin?: any;
249
239
  rust?: any;
240
+ python?: any;
250
241
  };
251
242
  theme: ThemeRegistration | {
252
243
  light: ThemeRegistration;
253
244
  dark: ThemeRegistration;
254
245
  };
255
246
  }
256
-
257
247
  //#endregion
258
248
  //#region src/shared/plugin.d.ts
259
249
  interface MarkdownPowerPluginOptions {
@@ -482,14 +472,14 @@ interface MarkdownPowerPluginOptions {
482
472
  * @default false
483
473
  */
484
474
  imageSize?: boolean | "local" | "all";
485
- } //#endregion
475
+ }
476
+ //#endregion
486
477
  //#region src/shared/replit.d.ts
487
478
  interface ReplitTokenMeta extends SizeOptions {
488
479
  title?: string;
489
480
  source?: string;
490
481
  theme?: string;
491
482
  }
492
-
493
483
  //#endregion
494
484
  //#region src/shared/video.d.ts
495
485
  interface VideoOptions {
@@ -523,11 +513,9 @@ interface ArtPlayerTokenMeta extends SizeOptions {
523
513
  url: string;
524
514
  type?: string;
525
515
  }
526
-
527
516
  //#endregion
528
517
  //#region src/node/container/codeTabs.d.ts
529
518
  declare function createCodeTabIconGetter(options?: CodeTabsOptions): (filename: string) => string | void;
530
-
531
519
  //#endregion
532
520
  //#region src/node/enhance/imageSize.d.ts
533
521
  interface ImgSize {
@@ -535,10 +523,8 @@ interface ImgSize {
535
523
  height: number;
536
524
  }
537
525
  declare function resolveImageSize(app: App, url: string, remote?: boolean): Promise<ImgSize>;
538
-
539
526
  //#endregion
540
527
  //#region src/node/plugin.d.ts
541
528
  declare function markdownPowerPlugin(options?: MarkdownPowerPluginOptions): Plugin;
542
-
543
529
  //#endregion
544
530
  export { ArtPlayerTokenMeta, BilibiliTokenMeta, CanIUseMode, CanIUseOptions, CanIUseTokenMeta, CodeSandboxTokenMeta, CodeTabsOptions, CodepenTokenMeta, DemoContainerRender, DemoFile, DemoMeta, FileTreeIconMode, FileTreeOptions, FontAwesomeAssetBuiltIn, FontAwesomePrefix, FontAwesomeProvider, IconAssetLink, IconFontProvider, IconOptions, IconProviderBase, IconifyPrefix, IconifyProvider, JSFiddleTokenMeta, LiteralUnion, MarkdownDemoEnv, MarkdownPowerPluginOptions, NpmToOptions, NpmToPackageManager, PDFEmbedType, PDFOptions, PDFTokenMeta, PlotOptions, ReplEditorData, ReplOptions, ReplitTokenMeta, SizeOptions, ThemeOptions, VideoOptions, YoutubeTokenMeta, createCodeTabIconGetter, markdownPowerPlugin, resolveImageSize };
package/lib/node/index.js CHANGED
@@ -6,7 +6,7 @@ import http from "node:https";
6
6
  import { URL, URLSearchParams } from "node:url";
7
7
  import { camelCase, isBoolean, isEmptyObject, isNull, isNumber, isPlainObject as isPlainObject$1, isString, isUndefined, kebabCase, notNullish, omit, toArray, uniqueBy, withTimeout } from "@pengzhanbo/utils";
8
8
  import imageSize from "image-size";
9
- import { colors, fs, getDirname, logger, path } from "vuepress/utils";
9
+ import { colors, fs, getDirname, logger, ora, path } from "vuepress/utils";
10
10
  import path$1 from "node:path";
11
11
  import { globSync } from "tinyglobby";
12
12
  import { isLinkHttp as isLinkHttp$1, removeEndingSlash, removeLeadingSlash } from "vuepress/shared";
@@ -908,7 +908,7 @@ const codeTabs = (md, options = {}) => {
908
908
  const getIcon = createCodeTabIconGetter(options);
909
909
  tab(md, {
910
910
  name: "code-tabs",
911
- tabsOpenRenderer: ({ active, data }, tokens, index, _, env) => {
911
+ openRender: ({ active, data }, tokens, index, _, env) => {
912
912
  const { meta } = tokens[index];
913
913
  const titles = data.map(({ title }) => md.renderInline(title, cleanMarkdownEnv(env)));
914
914
  const tabsData = data.map((item, dataIndex) => {
@@ -921,8 +921,8 @@ const codeTabs = (md, options = {}) => {
921
921
  }).join("");
922
922
  return `<CodeTabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? "" : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id}"` : ""}>${titlesContent}`;
923
923
  },
924
- tabsCloseRenderer: () => `</CodeTabs>`,
925
- tabOpenRenderer: ({ index }, tokens, tokenIndex) => {
924
+ closeRender: () => `</CodeTabs>`,
925
+ tabOpenRender: ({ index }, tokens, tokenIndex) => {
926
926
  let foundFence = false;
927
927
  for (let i = tokenIndex; i < tokens.length; i++) {
928
928
  const { type } = tokens[i];
@@ -936,7 +936,7 @@ const codeTabs = (md, options = {}) => {
936
936
  }
937
937
  return `<template #tab${index}="{ value, isActive }">`;
938
938
  },
939
- tabCloseRenderer: () => `</template>`
939
+ tabCloseRender: () => `</template>`
940
940
  });
941
941
  };
942
942
 
@@ -985,7 +985,7 @@ const BADGE_LIST = [
985
985
  "https://forthebadge.com",
986
986
  "https://vercel.com/button"
987
987
  ];
988
- const cache$1 = new Map();
988
+ const cache$1 = /* @__PURE__ */ new Map();
989
989
  async function imageSizePlugin(app, md, type = false) {
990
990
  if (!app.env.isBuild || !type) return;
991
991
  if (type === "all") {
@@ -1249,6 +1249,15 @@ function stringifyAttrs(attrs$1, withUndefined = false) {
1249
1249
 
1250
1250
  //#endregion
1251
1251
  //#region src/node/container/createContainer.ts
1252
+ /**
1253
+ * 创建 markdown-it 的自定义容器插件。
1254
+ *
1255
+ * @param md markdown-it 实例
1256
+ * @param type 容器类型(如 'tip', 'warning' 等)
1257
+ * @param options 可选的 before/after 渲染钩子
1258
+ * @param options.before 渲染容器起始标签时的回调函数
1259
+ * @param options.after 渲染容器结束标签时的回调函数
1260
+ */
1252
1261
  function createContainerPlugin(md, type, { before, after } = {}) {
1253
1262
  const render = (tokens, index, options, env) => {
1254
1263
  const token = tokens[index];
@@ -1278,6 +1287,14 @@ function createContainerPlugin(md, type, { before, after } = {}) {
1278
1287
  function createContainerSyntaxPlugin(md, type, render) {
1279
1288
  const maker = ":";
1280
1289
  const markerMinLen = 3;
1290
+ /**
1291
+ * 自定义容器的 block 规则定义。
1292
+ * @param state 当前 block 状态
1293
+ * @param startLine 起始行
1294
+ * @param endLine 结束行
1295
+ * @param silent 是否为静默模式
1296
+ * @returns 是否匹配到自定义容器
1297
+ */
1281
1298
  function defineContainer(state, startLine, endLine, silent) {
1282
1299
  const start = state.bMarks[startLine] + state.tShift[startLine];
1283
1300
  const max = state.eMarks[startLine];
@@ -1340,6 +1357,11 @@ const UNSUPPORTED_FILE_TYPES = [
1340
1357
  "xls",
1341
1358
  "xlsx"
1342
1359
  ];
1360
+ /**
1361
+ * 将文件路径数组解析为文件树节点结构
1362
+ * @param files 文件路径数组
1363
+ * @returns 文件树节点数组
1364
+ */
1343
1365
  function parseFileNodes(files) {
1344
1366
  const nodes = [];
1345
1367
  for (const file of files) {
@@ -1363,12 +1385,24 @@ function parseFileNodes(files) {
1363
1385
  }
1364
1386
  return nodes;
1365
1387
  }
1388
+ /**
1389
+ * 注册 code-tree 容器和嵌入语法的 markdown 插件
1390
+ * @param md markdown-it 实例
1391
+ * @param app vuepress app 实例
1392
+ * @param options code-tree 配置项
1393
+ */
1366
1394
  function codeTreePlugin(md, app, options = {}) {
1395
+ /**
1396
+ * 获取文件或文件夹的图标
1397
+ */
1367
1398
  const getIcon = (filename, type, mode) => {
1368
1399
  mode ||= options.icon || "colored";
1369
1400
  if (mode === "simple") return type === "folder" ? defaultFolder : defaultFile;
1370
1401
  return getFileIcon(filename, type);
1371
1402
  };
1403
+ /**
1404
+ * 渲染文件树节点为组件字符串
1405
+ */
1372
1406
  function renderFileTree(nodes, mode) {
1373
1407
  return nodes.map((node) => {
1374
1408
  const props = {
@@ -1457,6 +1491,10 @@ function codeTreePlugin(md, app, options = {}) {
1457
1491
  }
1458
1492
  });
1459
1493
  }
1494
+ /**
1495
+ * 扩展页面依赖,将 codeTreeFiles 添加到页面依赖中
1496
+ * @param page vuepress 页面对象
1497
+ */
1460
1498
  function extendsPageWithCodeTree(page) {
1461
1499
  const markdownEnv = page.markdownEnv;
1462
1500
  const codeTreeFiles = markdownEnv.codeTreeFiles ?? [];
@@ -1465,13 +1503,13 @@ function extendsPageWithCodeTree(page) {
1465
1503
 
1466
1504
  //#endregion
1467
1505
  //#region src/node/container/align.ts
1468
- const alignList = [
1469
- "left",
1470
- "center",
1471
- "right",
1472
- "justify"
1473
- ];
1474
1506
  function alignPlugin(md) {
1507
+ const alignList = [
1508
+ "left",
1509
+ "center",
1510
+ "right",
1511
+ "justify"
1512
+ ];
1475
1513
  for (const name of alignList) createContainerPlugin(md, name, { before: () => `<div style="text-align:${name}">` });
1476
1514
  createContainerPlugin(md, "flex", { before: (info) => {
1477
1515
  const { attrs: attrs$1 } = resolveAttrs(info);
@@ -1723,6 +1761,11 @@ function fieldPlugin(md) {
1723
1761
 
1724
1762
  //#endregion
1725
1763
  //#region src/node/container/fileTree.ts
1764
+ /**
1765
+ * 解析原始文件树内容为节点树结构
1766
+ * @param content 文件树的原始文本内容
1767
+ * @returns 文件树节点数组
1768
+ */
1726
1769
  function parseFileTreeRawContent(content) {
1727
1770
  const root = {
1728
1771
  info: "",
@@ -1749,6 +1792,11 @@ function parseFileTreeRawContent(content) {
1749
1792
  return root.children;
1750
1793
  }
1751
1794
  const RE_FOCUS = /^\*\*(.*)\*\*(?:$|\s+)/;
1795
+ /**
1796
+ * 解析单个节点的 info 字符串,提取文件名、注释、类型等属性
1797
+ * @param info 节点描述字符串
1798
+ * @returns 文件树节点属性
1799
+ */
1752
1800
  function parseFileTreeNodeInfo(info) {
1753
1801
  let filename = "";
1754
1802
  let comment = "";
@@ -1788,12 +1836,23 @@ function parseFileTreeNodeInfo(info) {
1788
1836
  diff
1789
1837
  };
1790
1838
  }
1839
+ /**
1840
+ * 文件树 markdown 插件主函数
1841
+ * @param md markdown 实例
1842
+ * @param options 文件树渲染选项
1843
+ */
1791
1844
  function fileTreePlugin(md, options = {}) {
1845
+ /**
1846
+ * 获取文件或文件夹的图标
1847
+ */
1792
1848
  const getIcon = (filename, type, mode) => {
1793
1849
  mode ||= options.icon || "colored";
1794
1850
  if (mode === "simple") return type === "folder" ? defaultFolder : defaultFile;
1795
1851
  return getFileIcon(filename, type);
1796
1852
  };
1853
+ /**
1854
+ * 递归渲染文件树节点
1855
+ */
1797
1856
  const renderFileTree = (nodes, meta) => nodes.map((node) => {
1798
1857
  const { info, level, children } = node;
1799
1858
  const { filename, comment, focus, expanded, type, diff } = parseFileTreeNodeInfo(info);
@@ -1828,7 +1887,7 @@ ${renderedIcon}${renderedComment}${children.length > 0 ? renderFileTree(children
1828
1887
 
1829
1888
  //#endregion
1830
1889
  //#region src/node/container/langRepl.ts
1831
- async function langReplPlugin(app, md, { theme, go = false, kotlin = false, rust = false }) {
1890
+ async function langReplPlugin(app, md, { theme, go = false, kotlin = false, rust = false, python = false }) {
1832
1891
  const container$1 = (lang) => createContainerPlugin(md, `${lang}-repl`, {
1833
1892
  before(info) {
1834
1893
  const { attrs: attrs$1 } = resolveAttrs(info);
@@ -1843,6 +1902,7 @@ async function langReplPlugin(app, md, { theme, go = false, kotlin = false, rust
1843
1902
  if (kotlin) container$1("kotlin");
1844
1903
  if (go) container$1("go");
1845
1904
  if (rust) container$1("rust");
1905
+ if (python) container$1("python");
1846
1906
  theme ??= {
1847
1907
  light: "github-light",
1848
1908
  dark: "github-dark"
@@ -1861,6 +1921,7 @@ async function langReplPlugin(app, md, { theme, go = false, kotlin = false, rust
1861
1921
  if (kotlin) data.grammars.kotlin = await readGrammar("kotlin");
1862
1922
  if (go) data.grammars.go = await readGrammar("go");
1863
1923
  if (rust) data.grammars.rust = await readGrammar("rust");
1924
+ if (python) data.grammars.python = await readGrammar("python");
1864
1925
  } catch {
1865
1926
  /* istanbul ignore next -- @preserve */
1866
1927
  logger.error("[vuepress-plugin-md-power]", `Failed to load packages: ${colors.green("tm-themes")}, ${colors.green("tm-grammars")}, Please install them manually.`);
@@ -1875,6 +1936,59 @@ async function read(file) {
1875
1936
  return void 0;
1876
1937
  }
1877
1938
 
1939
+ //#endregion
1940
+ //#region src/node/utils/logger.ts
1941
+ /**
1942
+ * Logger utils
1943
+ */
1944
+ var Logger = class {
1945
+ constructor(name = "") {
1946
+ this.name = name;
1947
+ }
1948
+ init(subname, text) {
1949
+ return ora({
1950
+ prefixText: colors.blue(`${this.name}${subname ? `:${subname}` : ""}: `),
1951
+ text
1952
+ });
1953
+ }
1954
+ /**
1955
+ * Create a loading spinner with text
1956
+ */
1957
+ load(subname, msg) {
1958
+ const instance = this.init(subname, msg);
1959
+ return {
1960
+ succeed: (text) => instance.succeed(text),
1961
+ fail: (text) => instance.succeed(text)
1962
+ };
1963
+ }
1964
+ info(subname, text = "", ...args) {
1965
+ this.init(subname, colors.blue(text)).info();
1966
+ if (args.length) console.info(...args);
1967
+ }
1968
+ /**
1969
+ * Log success msg
1970
+ */
1971
+ succeed(subname, text = "", ...args) {
1972
+ this.init(subname, colors.green(text)).succeed();
1973
+ if (args.length) console.log(...args);
1974
+ }
1975
+ /**
1976
+ * Log warning msg
1977
+ */
1978
+ warn(subname, text = "", ...args) {
1979
+ this.init(subname, colors.yellow(text)).warn();
1980
+ if (args.length) console.warn(...args);
1981
+ }
1982
+ /**
1983
+ * Log error msg
1984
+ */
1985
+ error(subname, text = "", ...args) {
1986
+ this.init(subname, colors.red(text)).fail();
1987
+ if (args.length) console.error(...args);
1988
+ }
1989
+ };
1990
+ const logger$1 = new Logger("vuepress-plugin-md-power");
1991
+
1878
1992
  //#endregion
1879
1993
  //#region src/node/container/npmToPreset.ts
1880
1994
  const ALLOW_LIST = [
@@ -2124,6 +2238,9 @@ const MANAGERS_CONFIG = {
2124
2238
 
2125
2239
  //#endregion
2126
2240
  //#region src/node/container/npmTo.ts
2241
+ /**
2242
+ * 注册 npm-to 容器插件,将 npm 代码块自动转换为多包管理器命令分组
2243
+ */
2127
2244
  function npmToPlugins(md, options = {}) {
2128
2245
  const opt = isArray(options) ? { tabs: options } : options;
2129
2246
  const defaultTabs = opt.tabs?.length ? opt.tabs : DEFAULT_TABS;
@@ -2140,12 +2257,19 @@ function npmToPlugins(md, options = {}) {
2140
2257
  const lines = content.split(/(\n|\s*&&\s*)/);
2141
2258
  return md.render(resolveNpmTo(lines, token.info.trim(), idx, tabs$1), cleanMarkdownEnv(env));
2142
2259
  }
2143
- console.warn(`${colors.yellow("[vuepress-plugin-md-power]")} Invalid npm-to container in ${colors.gray(env.filePathRelative || env.filePath)}`);
2260
+ logger$1.warn("npm-to", `Invalid npm-to container in ${colors.gray(env.filePathRelative || env.filePath)}`);
2144
2261
  return "";
2145
2262
  },
2146
2263
  after: () => ""
2147
2264
  });
2148
2265
  }
2266
+ /**
2267
+ * 将 npm 命令转换为各包管理器命令分组
2268
+ * @param lines 命令行数组
2269
+ * @param info 代码块类型
2270
+ * @param idx token 索引
2271
+ * @param tabs 需要支持的包管理器
2272
+ */
2149
2273
  function resolveNpmTo(lines, info, idx, tabs$1) {
2150
2274
  tabs$1 = validateTabs(tabs$1);
2151
2275
  const res = [];
@@ -2172,16 +2296,25 @@ function resolveNpmTo(lines, info, idx, tabs$1) {
2172
2296
  }
2173
2297
  return `:::code-tabs#npm-to-${tabs$1.join("-")}\n${res.join("\n")}\n:::`;
2174
2298
  }
2299
+ /**
2300
+ * 根据命令行内容查找对应的包管理器配置
2301
+ */
2175
2302
  function findConfig(line) {
2176
2303
  for (const { pattern,...config } of Object.values(MANAGERS_CONFIG)) if (pattern.test(line)) return config;
2177
2304
  return void 0;
2178
2305
  }
2306
+ /**
2307
+ * 校验 tabs 合法性,返回允许的包管理器列表
2308
+ */
2179
2309
  function validateTabs(tabs$1) {
2180
2310
  tabs$1 = tabs$1.filter((tab$1) => ALLOW_LIST.includes(tab$1));
2181
2311
  if (tabs$1.length === 0) return DEFAULT_TABS;
2182
2312
  return tabs$1;
2183
2313
  }
2184
2314
  const LINE_REG = /(.*)(npm|npx)\s+(.*)/;
2315
+ /**
2316
+ * 解析一行 npm/npx 命令,拆分出环境变量、命令、参数等
2317
+ */
2185
2318
  function parseLine(line) {
2186
2319
  const match = line.match(LINE_REG);
2187
2320
  if (!match) return false;
@@ -2212,6 +2345,9 @@ function parseLine(line) {
2212
2345
  ...parseArgs(rest.slice(idx + 1))
2213
2346
  };
2214
2347
  }
2348
+ /**
2349
+ * 解析 npm 命令参数,区分命令、参数、脚本参数
2350
+ */
2215
2351
  function parseArgs(line) {
2216
2352
  line = line?.trim();
2217
2353
  const [npmArgs, scriptArgs] = line.split(/\s+--\s+/);
@@ -2289,7 +2425,7 @@ function stepsPlugin(md) {
2289
2425
  const tabs = (md) => {
2290
2426
  tab(md, {
2291
2427
  name: "tabs",
2292
- tabsOpenRenderer: ({ active, data }, tokens, index, _, env) => {
2428
+ openRender: ({ active, data }, tokens, index, _, env) => {
2293
2429
  const { meta } = tokens[index];
2294
2430
  const titles = data.map(({ title }) => md.renderInline(title, cleanMarkdownEnv(env)));
2295
2431
  const tabsData = data.map((item, dataIndex) => {
@@ -2299,9 +2435,9 @@ const tabs = (md) => {
2299
2435
  return `<Tabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? "" : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id}"` : ""}>
2300
2436
  ${titles.map((title, titleIndex) => `<template #title${titleIndex}="{ value, isActive }">${title}</template>`).join("")}`;
2301
2437
  },
2302
- tabsCloseRenderer: () => `</Tabs>`,
2303
- tabOpenRenderer: ({ index }) => `<template #tab${index}="{ value, isActive }">`,
2304
- tabCloseRenderer: () => `</template>`
2438
+ closeRender: () => `</Tabs>`,
2439
+ tabOpenRender: ({ index }) => `<template #tab${index}="{ value, isActive }">`,
2440
+ tabCloseRender: () => `</template>`
2305
2441
  });
2306
2442
  };
2307
2443
 
@@ -2417,7 +2553,7 @@ function markdownEmbed(app, md, env, { url, title, desc, codeSetting = "", expan
2417
2553
  const filepath$1 = findFile(app, env, url);
2418
2554
  const code = readFileSync(filepath$1);
2419
2555
  if (code === false) {
2420
- console.warn("[vuepress-plugin-md-power] Cannot read markdown file:", filepath$1);
2556
+ logger$1.warn("demo-markdown", `Cannot read markdown file: ${colors.gray(filepath$1)}\n at: ${colors.gray(env.filePathRelative || "")}`);
2421
2557
  return "";
2422
2558
  }
2423
2559
  const demo = {
@@ -2692,7 +2828,7 @@ async function compileCode(code, output) {
2692
2828
  if (code.css) res.css = await compileStyle(code.css.trim(), code.cssType);
2693
2829
  if (code.html) res.html = code.html.trim();
2694
2830
  } catch (e) {
2695
- console.error("[vuepress-plugin-md-power] demo parse error: \n", e);
2831
+ logger$1.error("demo-normal", "demo parse error: \n", e);
2696
2832
  }
2697
2833
  writeFileSync(output, `import { ref } from "vue"\nexport default ref(${JSON.stringify(res, null, 2)})`);
2698
2834
  checkDemoRender();
@@ -2701,7 +2837,7 @@ function normalEmbed(app, md, env, { url, title, desc, codeSetting = "", expande
2701
2837
  const filepath$1 = findFile(app, env, url);
2702
2838
  const code = readFileSync(filepath$1);
2703
2839
  if (code === false) {
2704
- console.warn("[vuepress-plugin-md-power] Cannot read demo file:", filepath$1);
2840
+ logger$1.warn("demo-normal", `Cannot read demo file: ${colors.gray(filepath$1)}\n at: ${colors.gray(env.filePathRelative || "")}`);
2705
2841
  return "";
2706
2842
  }
2707
2843
  const source = parseEmbedCode(code);
@@ -2830,7 +2966,7 @@ function vueEmbed(app, md, env, { url, title, desc, codeSetting = "", expanded =
2830
2966
  const filepath$1 = findFile(app, env, url);
2831
2967
  const code = readFileSync(filepath$1);
2832
2968
  if (code === false) {
2833
- console.warn("[vuepress-plugin-md-power] Cannot read vue file:", filepath$1);
2969
+ logger$1.warn("demo-vue", `Cannot read vue demo file: ${colors.gray(filepath$1)}\n at: ${colors.gray(env.filePathRelative || "")}`);
2834
2970
  return "";
2835
2971
  }
2836
2972
  const basename = path$1.basename(filepath$1).replace(/-|\./g, "_");
@@ -2947,6 +3083,15 @@ function transformStyle(code) {
2947
3083
 
2948
3084
  //#endregion
2949
3085
  //#region src/node/demo/demo.ts
3086
+ const embedMap = {
3087
+ vue: vueEmbed,
3088
+ normal: normalEmbed,
3089
+ markdown: markdownEmbed
3090
+ };
3091
+ /**
3092
+ * 嵌入语法
3093
+ * @[demo type info](url)
3094
+ */
2950
3095
  function demoEmbed(app, md) {
2951
3096
  createEmbedRuleBlock(md, {
2952
3097
  type: "demo",
@@ -2959,12 +3104,10 @@ function demoEmbed(app, md) {
2959
3104
  content: (meta, content, env) => {
2960
3105
  const { url, type } = meta;
2961
3106
  if (!url) {
2962
- console.warn("[vuepress-plugin-md-power] Invalid demo url: ", url);
3107
+ logger$1.warn("demo-vue", `Invalid filepath: ${colors.gray(url)}`);
2963
3108
  return content;
2964
3109
  }
2965
- if (type === "vue") return vueEmbed(app, md, env, meta);
2966
- if (type === "normal") return normalEmbed(app, md, env, meta);
2967
- if (type === "markdown") return markdownEmbed(app, md, env, meta);
3110
+ if (embedMap[type]) return embedMap[type](app, md, env, meta);
2968
3111
  return content;
2969
3112
  }
2970
3113
  });
@@ -3074,7 +3217,7 @@ const audioReader = (state, silent) => {
3074
3217
  };
3075
3218
  const audioReaderPlugin = (md) => {
3076
3219
  md.renderer.rules.audio_reader = (tokens, idx) => {
3077
- const meta = tokens[idx].meta ?? {};
3220
+ const meta = tokens[idx].meta;
3078
3221
  if (meta.startTime) meta.startTime = Number(meta.startTime);
3079
3222
  if (meta.endTime) meta.endTime = Number(meta.endTime);
3080
3223
  if (meta.volume) meta.volume = Number(meta.volume);
@@ -3355,10 +3498,10 @@ function checkSupportType(type) {
3355
3498
  break;
3356
3499
  }
3357
3500
  /* istanbul ignore if -- @preserve */
3358
- if (name) console.warn(`${colors.yellow("[vuepress-plugin-md-power] artPlayer: ")} ${colors.cyan(name)} is not installed, please install it via npm or yarn or pnpm`);
3501
+ if (name) logger$1.warn("artPlayer", `${colors.cyan(name)} is not installed, please install it via npm or yarn or pnpm`);
3359
3502
  } else
3360
3503
  /* istanbul ignore next -- @preserve */
3361
- console.warn(`${colors.yellow("[vuepress-plugin-md-power] artPlayer: ")} unsupported video type: ${colors.cyan(type)}`);
3504
+ logger$1.warn("artPlayer", `unsupported video type: ${colors.cyan(type)}`);
3362
3505
  }
3363
3506
 
3364
3507
  //#endregion
@@ -3636,7 +3779,7 @@ const iconPlugin = (md, options = {}) => {
3636
3779
  const [name, opt = ""] = content.split(" ");
3637
3780
  const [size, color] = opt.trim().split("/");
3638
3781
  icon = `${name}${size ? ` =${size}` : ""}${color ? ` /${color}` : ""}`;
3639
- console.warn(`The icon syntax of \`${colors.yellow(`:[${content}]:`)}\` is deprecated, please use \`${colors.green(`::${icon}::`)}\` instead. (${colors.gray(env.filePathRelative || env.filePath)})`);
3782
+ logger$1.warn("icon", `The icon syntax of \`${colors.yellow(`:[${content}]:`)}\` is deprecated, please use \`${colors.green(`::${icon}::`)}\` instead. (${colors.gray(env.filePathRelative || env.filePath)})`);
3640
3783
  }
3641
3784
  return iconRender(icon, options);
3642
3785
  };
@@ -3689,7 +3832,7 @@ function normalizeAsset(asset, provide) {
3689
3832
  link,
3690
3833
  provide
3691
3834
  };
3692
- console.error(`[vuepress:icon] Can not recognize icon link: "${asset}"`);
3835
+ logger$1.error("icon", `Can not recognize icon link: "${asset}"`);
3693
3836
  return null;
3694
3837
  }
3695
3838
  function normalizeLink(link) {
@@ -3928,8 +4071,8 @@ const { url: filepath } = import.meta;
3928
4071
  const __dirname = getDirname(filepath);
3929
4072
  const CLIENT_FOLDER = ensureEndingSlash(path.resolve(__dirname, "../client"));
3930
4073
  async function prepareConfigFile(app, options) {
3931
- const imports = new Set();
3932
- const enhances = new Set();
4074
+ const imports = /* @__PURE__ */ new Set();
4075
+ const enhances = /* @__PURE__ */ new Set();
3933
4076
  imports.add(`import Tabs from '${CLIENT_FOLDER}components/Tabs.vue'`);
3934
4077
  enhances.add(`app.component('Tabs', Tabs)`);
3935
4078
  imports.add(`import CodeTabs from '${CLIENT_FOLDER}components/CodeTabs.vue'`);
@@ -4065,11 +4208,14 @@ function markdownPowerPlugin(options = {}) {
4065
4208
  clientConfigFile: (app) => prepareConfigFile(app, options),
4066
4209
  define: provideData(options),
4067
4210
  extendsBundlerOptions(bundlerOptions, app) {
4068
- if (options.repl) addViteOptimizeDepsInclude(bundlerOptions, app, [
4069
- "shiki/core",
4070
- "shiki/wasm",
4071
- "shiki/engine/oniguruma"
4072
- ]);
4211
+ if (options.repl) {
4212
+ addViteOptimizeDepsInclude(bundlerOptions, app, [
4213
+ "shiki/core",
4214
+ "shiki/wasm",
4215
+ "shiki/engine/oniguruma"
4216
+ ]);
4217
+ if (options.repl.python) addViteOptimizeDepsInclude(bundlerOptions, app, ["pyodide"]);
4218
+ }
4073
4219
  if (options.artPlayer) addViteOptimizeDepsInclude(bundlerOptions, app, [
4074
4220
  "artplayer",
4075
4221
  "dashjs",
@@ -21,14 +21,14 @@ interface CanIUseOptions {
21
21
  * @default 'embed'
22
22
  */
23
23
  mode?: CanIUseMode;
24
- } //#endregion
24
+ }
25
+ //#endregion
25
26
  //#region src/shared/size.d.ts
26
27
  interface SizeOptions {
27
28
  width?: string;
28
29
  height?: string;
29
30
  ratio?: number | string;
30
31
  }
31
-
32
32
  //#endregion
33
33
  //#region src/shared/codepen.d.ts
34
34
  interface CodepenTokenMeta extends SizeOptions {
@@ -40,7 +40,6 @@ interface CodepenTokenMeta extends SizeOptions {
40
40
  preview?: boolean;
41
41
  editable?: boolean;
42
42
  }
43
-
44
43
  //#endregion
45
44
  //#region src/shared/codeSandbox.d.ts
46
45
  interface CodeSandboxTokenMeta extends SizeOptions {
@@ -53,7 +52,6 @@ interface CodeSandboxTokenMeta extends SizeOptions {
53
52
  navbar?: boolean;
54
53
  console?: boolean;
55
54
  }
56
-
57
55
  //#endregion
58
56
  //#region src/shared/codeTabs.d.ts
59
57
  interface CodeTabsOptions {
@@ -62,7 +60,6 @@ interface CodeTabsOptions {
62
60
  extensions?: false | string[];
63
61
  };
64
62
  }
65
-
66
63
  //#endregion
67
64
  //#region src/shared/demo.d.ts
68
65
  interface DemoFile {
@@ -87,14 +84,12 @@ interface DemoContainerRender {
87
84
  after: () => string;
88
85
  token?: (token: Token, tokens: Token[], index: number) => void;
89
86
  }
90
-
91
87
  //#endregion
92
88
  //#region src/shared/fileTree.d.ts
93
89
  type FileTreeIconMode = "simple" | "colored";
94
90
  interface FileTreeOptions {
95
91
  icon?: FileTreeIconMode;
96
92
  }
97
-
98
93
  //#endregion
99
94
  //#region src/shared/icon.d.ts
100
95
  type IconOptions = IconifyProvider | IconFontProvider | FontAwesomeProvider;
@@ -157,7 +152,6 @@ type IconifyPrefix = "material-symbols" | "material-symbols-light" | "ic" | "mdi
157
152
  type LiteralUnion<Union extends Base, Base = string> = Union | (Base & {
158
153
  zz_IGNORE_ME?: never;
159
154
  });
160
-
161
155
  //#endregion
162
156
  //#region src/shared/jsfiddle.d.ts
163
157
  interface JSFiddleTokenMeta extends SizeOptions {
@@ -166,14 +160,12 @@ interface JSFiddleTokenMeta extends SizeOptions {
166
160
  theme?: string;
167
161
  tab?: string;
168
162
  }
169
-
170
163
  //#endregion
171
164
  //#region src/shared/npmTo.d.ts
172
165
  type NpmToPackageManager = "npm" | "pnpm" | "yarn" | "bun" | "deno";
173
166
  type NpmToOptions = NpmToPackageManager[] | {
174
167
  tabs?: NpmToPackageManager[];
175
168
  };
176
-
177
169
  //#endregion
178
170
  //#region src/shared/pdf.d.ts
179
171
  type PDFEmbedType = "iframe" | "embed" | "pdfjs";
@@ -190,7 +182,6 @@ interface PDFOptions {
190
182
  */
191
183
  pdfjsUrl?: string;
192
184
  }
193
-
194
185
  //#endregion
195
186
  //#region src/shared/plot.d.ts
196
187
  interface PlotOptions {
@@ -220,14 +211,12 @@ interface PlotOptions {
220
211
  */
221
212
  trigger?: "hover" | "click";
222
213
  }
223
-
224
214
  //#endregion
225
215
  //#region src/shared/codeTree.d.ts
226
216
  interface CodeTreeOptions {
227
217
  icon?: FileTreeIconMode;
228
218
  height?: string | number;
229
219
  }
230
-
231
220
  //#endregion
232
221
  //#region src/shared/repl.d.ts
233
222
  type ThemeOptions = BuiltinTheme | {
@@ -239,19 +228,20 @@ interface ReplOptions {
239
228
  go?: boolean;
240
229
  kotlin?: boolean;
241
230
  rust?: boolean;
231
+ python?: boolean;
242
232
  }
243
233
  interface ReplEditorData {
244
234
  grammars: {
245
235
  go?: any;
246
236
  kotlin?: any;
247
237
  rust?: any;
238
+ python?: any;
248
239
  };
249
240
  theme: ThemeRegistration | {
250
241
  light: ThemeRegistration;
251
242
  dark: ThemeRegistration;
252
243
  };
253
244
  }
254
-
255
245
  //#endregion
256
246
  //#region src/shared/plugin.d.ts
257
247
  interface MarkdownPowerPluginOptions {
@@ -480,14 +470,14 @@ interface MarkdownPowerPluginOptions {
480
470
  * @default false
481
471
  */
482
472
  imageSize?: boolean | "local" | "all";
483
- } //#endregion
473
+ }
474
+ //#endregion
484
475
  //#region src/shared/replit.d.ts
485
476
  interface ReplitTokenMeta extends SizeOptions {
486
477
  title?: string;
487
478
  source?: string;
488
479
  theme?: string;
489
480
  }
490
-
491
481
  //#endregion
492
482
  //#region src/shared/video.d.ts
493
483
  interface VideoOptions {
@@ -521,6 +511,5 @@ interface ArtPlayerTokenMeta extends SizeOptions {
521
511
  url: string;
522
512
  type?: string;
523
513
  }
524
-
525
514
  //#endregion
526
515
  export { ArtPlayerTokenMeta, BilibiliTokenMeta, CanIUseMode, CanIUseOptions, CanIUseTokenMeta, CodeSandboxTokenMeta, CodeTabsOptions, CodepenTokenMeta, DemoContainerRender, DemoFile, DemoMeta, FileTreeIconMode, FileTreeOptions, FontAwesomeAssetBuiltIn, FontAwesomePrefix, FontAwesomeProvider, IconAssetLink, IconFontProvider, IconOptions, IconProviderBase, IconifyPrefix, IconifyProvider, JSFiddleTokenMeta, LiteralUnion, MarkdownDemoEnv, MarkdownPowerPluginOptions, NpmToOptions, NpmToPackageManager, PDFEmbedType, PDFOptions, PDFTokenMeta, PlotOptions, ReplEditorData, ReplOptions, ReplitTokenMeta, SizeOptions, ThemeOptions, VideoOptions, YoutubeTokenMeta };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vuepress-plugin-md-power",
3
3
  "type": "module",
4
- "version": "1.0.0-rc.152",
4
+ "version": "1.0.0-rc.153",
5
5
  "description": "The Plugin for VuePress 2 - markdown power",
6
6
  "author": "pengzhanbo <volodymyr@foxmail.com>",
7
7
  "license": "MIT",
@@ -32,14 +32,15 @@
32
32
  ],
33
33
  "peerDependencies": {
34
34
  "artplayer": "^5.2.3",
35
- "dashjs": "^5.0.2",
35
+ "dashjs": "^5.0.3",
36
36
  "esbuild": "^0.25.5",
37
- "hls.js": "^1.6.2",
37
+ "hls.js": "^1.6.5",
38
38
  "less": "^4.3.0",
39
39
  "markdown-it": "^14.1.0",
40
40
  "mpegts.js": "^1.7.3",
41
- "sass": "^1.89.0",
42
- "sass-embedded": "^1.89.0",
41
+ "pyodide": "^0.27.7",
42
+ "sass": "^1.89.1",
43
+ "sass-embedded": "^1.89.1",
43
44
  "stylus": "^0.64.0",
44
45
  "vuepress": "2.0.0-rc.23"
45
46
  },
@@ -58,18 +59,21 @@
58
59
  },
59
60
  "mpegts.js": {
60
61
  "optional": true
62
+ },
63
+ "pyodide": {
64
+ "optional": true
61
65
  }
62
66
  },
63
67
  "dependencies": {
64
- "@mdit/plugin-attrs": "^0.19.0",
65
- "@mdit/plugin-footnote": "^0.19.0",
66
- "@mdit/plugin-mark": "^0.19.0",
67
- "@mdit/plugin-sub": "^0.19.0",
68
- "@mdit/plugin-sup": "^0.19.0",
69
- "@mdit/plugin-tab": "^0.19.0",
70
- "@mdit/plugin-tasklist": "^0.19.0",
68
+ "@mdit/plugin-attrs": "^0.21.0",
69
+ "@mdit/plugin-footnote": "^0.21.0",
70
+ "@mdit/plugin-mark": "^0.21.0",
71
+ "@mdit/plugin-sub": "^0.21.0",
72
+ "@mdit/plugin-sup": "^0.21.0",
73
+ "@mdit/plugin-tab": "^0.21.0",
74
+ "@mdit/plugin-tasklist": "^0.21.0",
71
75
  "@pengzhanbo/utils": "^2.1.0",
72
- "@vuepress/helper": "2.0.0-rc.106",
76
+ "@vuepress/helper": "2.0.0-rc.108",
73
77
  "@vueuse/core": "^13.3.0",
74
78
  "chokidar": "3.6.0",
75
79
  "image-size": "^2.0.2",
@@ -77,17 +81,17 @@
77
81
  "lru-cache": "^11.1.0",
78
82
  "markdown-it-container": "^4.0.0",
79
83
  "nanoid": "^5.1.5",
80
- "shiki": "^3.4.2",
84
+ "shiki": "^3.6.0",
81
85
  "tinyglobby": "0.2.13",
82
- "tm-grammars": "^1.23.24",
86
+ "tm-grammars": "^1.23.26",
83
87
  "tm-themes": "^1.10.6",
84
- "vue": "^3.5.15"
88
+ "vue": "^3.5.16"
85
89
  },
86
90
  "devDependencies": {
87
91
  "@types/markdown-it": "^14.1.2",
88
92
  "artplayer": "^5.2.3",
89
- "dashjs": "^5.0.2",
90
- "hls.js": "^1.6.2",
93
+ "dashjs": "^5.0.3",
94
+ "hls.js": "^1.6.5",
91
95
  "mpegts.js": "1.7.3"
92
96
  },
93
97
  "publishConfig": {