vuepress-plugin-md-power 1.0.0-rc.102 → 1.0.0-rc.104

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/lib/node/index.js CHANGED
@@ -12,28 +12,28 @@ function resolveAttrs(info) {
12
12
  info = info.trim();
13
13
  if (!info)
14
14
  return { rawAttrs: "", attrs: {} };
15
- const attrs = {};
15
+ const attrs2 = {};
16
16
  const rawAttrs = info;
17
17
  let matched;
18
18
  while (matched = info.match(RE_ATTR_VALUE)) {
19
19
  const { attr, value } = matched.groups || {};
20
- attrs[attr] = value ?? true;
20
+ attrs2[attr] = value ?? true;
21
21
  info = info.slice(matched[0].length);
22
22
  }
23
- Object.keys(attrs).forEach((key) => {
24
- let value = attrs[key];
23
+ Object.keys(attrs2).forEach((key) => {
24
+ let value = attrs2[key];
25
25
  value = typeof value === "string" ? value.trim() : value;
26
26
  if (value === "true")
27
27
  value = true;
28
28
  else if (value === "false")
29
29
  value = false;
30
- attrs[key] = value;
30
+ attrs2[key] = value;
31
31
  if (key.includes("-")) {
32
32
  const _key = key.replace(/-(\w)/g, (_, c) => c.toUpperCase());
33
- attrs[_key] = value;
33
+ attrs2[_key] = value;
34
34
  }
35
35
  });
36
- return { attrs, rawAttrs };
36
+ return { attrs: attrs2, rawAttrs };
37
37
  }
38
38
 
39
39
  // src/node/enhance/imageSize.ts
@@ -80,14 +80,14 @@ async function imageSizePlugin(app, md, type2 = false) {
80
80
  return (tokens, idx, options, env, self) => {
81
81
  const token = tokens[idx];
82
82
  token.content = token.content.replace(REG_IMG_TAG, (raw, info) => {
83
- const { attrs } = resolveAttrs(info);
84
- const src = attrs.src || attrs.srcset;
85
- const size = resolveSize(src, attrs.width, attrs.height, env);
83
+ const { attrs: attrs2 } = resolveAttrs(info);
84
+ const src = attrs2.src || attrs2.srcset;
85
+ const size = resolveSize(src, attrs2.width, attrs2.height, env);
86
86
  if (!size)
87
87
  return raw;
88
- attrs.width = size.width;
89
- attrs.height = size.height;
90
- const imgAttrs = Object.entries(attrs).map(([key, value]) => typeof value === "boolean" ? key : `${key}="${value}"`).join(" ");
88
+ attrs2.width = size.width;
89
+ attrs2.height = size.height;
90
+ const imgAttrs = Object.entries(attrs2).map(([key, value]) => typeof value === "boolean" ? key : `${key}="${value}"`).join(" ");
91
91
  return `<img ${imgAttrs}>`;
92
92
  });
93
93
  return rawHtmlRule(tokens, idx, options, env, self);
@@ -209,117 +209,176 @@ async function resolveImageSize(app, url, remote = false) {
209
209
  // src/node/plugin.ts
210
210
  import { addViteOptimizeDepsInclude } from "@vuepress/helper";
211
211
 
212
- // src/node/container/fileTree/index.ts
212
+ // src/node/container/index.ts
213
+ import { isPlainObject as isPlainObject2 } from "@vuepress/helper";
214
+
215
+ // src/node/container/align.ts
213
216
  import container from "markdown-it-container";
217
+ var alignList = ["left", "center", "right", "justify"];
218
+ function alignPlugin(md) {
219
+ for (const name of alignList) {
220
+ md.use(container, name, {
221
+ validate: (info) => info.trim() === name,
222
+ render: (tokens, idx) => {
223
+ if (tokens[idx].nesting === 1) {
224
+ return `<div style="text-align:${name}">`;
225
+ } else {
226
+ return "</div>";
227
+ }
228
+ }
229
+ });
230
+ }
231
+ }
214
232
 
215
- // src/node/container/fileTree/definitions.ts
233
+ // src/node/container/codeTabs.ts
234
+ import { tab } from "@mdit/plugin-tab";
235
+ import { isPlainObject } from "@vuepress/helper";
236
+
237
+ // src/node/fileIcons/definitions.ts
216
238
  var defaultFolder = "vscode-icons:default-folder";
217
239
  var defaultFile = "vscode-icons:default-file";
218
240
  var definitions = {
219
241
  named: {
220
242
  // package manager
221
- pnpm: "vscode-icons:file-type-light-pnpm",
222
- PNPM: "vscode-icons:file-type-light-pnpm",
223
- npm: "vscode-icons:file-type-npm",
224
- NPM: "vscode-icons:file-type-npm",
225
- yarn: "vscode-icons:file-type-yarn",
226
- Yarn: "vscode-icons:file-type-yarn",
227
- bun: "vscode-icons:file-type-bun",
228
- Bun: "vscode-icons:file-type-bun",
229
- deno: "vscode-icons:file-type-light-deno",
230
- Deno: "vscode-icons:file-type-light-deno",
243
+ "pnpm": "vscode-icons:file-type-light-pnpm",
244
+ "PNPM": "vscode-icons:file-type-light-pnpm",
245
+ "npm": "logos:npm-icon",
246
+ "NPM": "logos:npm-icon",
247
+ "yarn": "vscode-icons:file-type-yarn",
248
+ "Yarn": "vscode-icons:file-type-yarn",
249
+ "bun": "vscode-icons:file-type-bun",
250
+ "Bun": "vscode-icons:file-type-bun",
251
+ "deno": "vscode-icons:file-type-light-deno",
252
+ "Deno": "vscode-icons:file-type-light-deno",
231
253
  // bundlers
232
- rollup: "vscode-icons:file-type-rollup",
233
- Rollup: "vscode-icons:file-type-rollup",
234
- webpack: "vscode-icons:file-type-webpack",
235
- Webpack: "vscode-icons:file-type-webpack",
236
- vite: "vscode-icons:file-type-vite",
237
- Vite: "vscode-icons:file-type-vite",
238
- esbuild: "vscode-icons:file-type-esbuild",
239
- Esbuild: "vscode-icons:file-type-esbuild",
254
+ "rollup": "vscode-icons:file-type-rollup",
255
+ "Rollup": "vscode-icons:file-type-rollup",
256
+ "webpack": "vscode-icons:file-type-webpack",
257
+ "Webpack": "vscode-icons:file-type-webpack",
258
+ "vite": "vscode-icons:file-type-vite",
259
+ "Vite": "vscode-icons:file-type-vite",
260
+ "esbuild": "vscode-icons:file-type-esbuild",
261
+ "Esbuild": "vscode-icons:file-type-esbuild",
240
262
  // frameworks
241
- vue: "vscode-icons:file-type-vue",
242
- Vue: "vscode-icons:file-type-vue",
243
- svelte: "vscode-icons:file-type-svelte",
244
- sveltekit: "vscode-icons:file-type-svelte",
245
- angular: "vscode-icons:file-type-angular",
246
- Angular: "vscode-icons:file-type-angular",
247
- react: "vscode-icons:file-type-reactjs",
248
- React: "vscode-icons:file-type-reactjs",
249
- next: "vscode-icons:file-type-light-next",
250
- Next: "vscode-icons:file-type-light-next",
251
- Nextjs: "vscode-icons:file-type-light-next",
252
- NextJS: "vscode-icons:file-type-light-next",
253
- nuxt: "vscode-icons:file-type-nuxt",
254
- Nuxt: "vscode-icons:file-type-nuxt",
255
- Nuxtjs: "vscode-icons:file-type-nuxt",
256
- NuxtJS: "vscode-icons:file-type-nuxt",
257
- solid: "logos:solidjs-icon",
258
- Solid: "logos:solidjs-icon",
259
- solidjs: "logos:solidjs-icon",
260
- astro: "vscode-icons:file-type-light-astro",
261
- Astro: "vscode-icons:file-type-light-astro",
262
- vitest: "vscode-icons:file-type-vitest",
263
- Vitest: "vscode-icons:file-type-vitest",
264
- playwright: "vscode-icons:file-type-playwright",
265
- Playwright: "vscode-icons:file-type-playwright",
266
- jest: "vscode-icons:file-type-jest",
267
- Jest: "vscode-icons:file-type-jest",
268
- cypress: "vscode-icons:file-type-cypress",
269
- Cypress: "vscode-icons:file-type-cypress",
270
- docker: "vscode-icons:file-type-docker",
271
- Docker: "vscode-icons:file-type-docker",
263
+ "vue": "vscode-icons:file-type-vue",
264
+ "Vue": "vscode-icons:file-type-vue",
265
+ "svelte": "vscode-icons:file-type-svelte",
266
+ "Svelte": "vscode-icons:file-type-svelte",
267
+ "sveltekit": "vscode-icons:file-type-svelte",
268
+ "SvelteKit": "vscode-icons:file-type-svelte",
269
+ "angular": "vscode-icons:file-type-angular",
270
+ "Angular": "vscode-icons:file-type-angular",
271
+ "react": "vscode-icons:file-type-reactjs",
272
+ "React": "vscode-icons:file-type-reactjs",
273
+ "next": "vscode-icons:file-type-light-next",
274
+ "Next": "vscode-icons:file-type-light-next",
275
+ "Nextjs": "vscode-icons:file-type-light-next",
276
+ "NextJS": "vscode-icons:file-type-light-next",
277
+ "nuxt": "vscode-icons:file-type-nuxt",
278
+ "Nuxt": "vscode-icons:file-type-nuxt",
279
+ "Nuxtjs": "vscode-icons:file-type-nuxt",
280
+ "NuxtJS": "vscode-icons:file-type-nuxt",
281
+ "solid": "logos:solidjs-icon",
282
+ "Solid": "logos:solidjs-icon",
283
+ "solidjs": "logos:solidjs-icon",
284
+ "astro": "vscode-icons:file-type-light-astro",
285
+ "Astro": "vscode-icons:file-type-light-astro",
286
+ "vitest": "vscode-icons:file-type-vitest",
287
+ "Vitest": "vscode-icons:file-type-vitest",
288
+ "playwright": "vscode-icons:file-type-playwright",
289
+ "Playwright": "vscode-icons:file-type-playwright",
290
+ "jest": "vscode-icons:file-type-jest",
291
+ "Jest": "vscode-icons:file-type-jest",
292
+ "cypress": "vscode-icons:file-type-cypress",
293
+ "Cypress": "vscode-icons:file-type-cypress",
294
+ "docker": "vscode-icons:file-type-docker",
295
+ "Docker": "vscode-icons:file-type-docker",
272
296
  // TODO: code group title icons
273
297
  // programming languages
274
- html: "vscode-icons:file-type-html",
275
- Html: "vscode-icons:file-type-html",
276
- HTML: "vscode-icons:file-type-html",
277
- javascript: "vscode-icons:file-type-js-official",
278
- Javascript: "vscode-icons:file-type-js-official",
279
- JavaScript: "vscode-icons:file-type-js-official",
280
- js: "vscode-icons:file-type-js-official",
281
- JS: "vscode-icons:file-type-js-official",
282
- typescript: "vscode-icons:file-type-typescript-official",
283
- Typescript: "vscode-icons:file-type-typescript-official",
284
- TypeScript: "vscode-icons:file-type-typescript-official",
285
- ts: "vscode-icons:file-type-typescript-official",
286
- TS: "vscode-icons:file-type-typescript-official",
287
- css: "vscode-icons:file-type-css",
288
- CSS: "vscode-icons:file-type-css",
289
- less: "vscode-icons:file-type-less",
290
- Less: "vscode-icons:file-type-less",
291
- scss: "vscode-icons:file-type-scss",
292
- Scss: "vscode-icons:file-type-scss",
293
- SCSS: "vscode-icons:file-type-scss",
294
- sass: "vscode-icons:file-type-sass",
295
- Sass: "vscode-icons:file-type-sass",
296
- SASS: "vscode-icons:file-type-sass",
297
- stylus: "vscode-icons:file-type-light-stylus",
298
- Stylus: "vscode-icons:file-type-light-stylus",
299
- postcss: "vscode-icons:file-type-postcss",
300
- Postcss: "vscode-icons:file-type-postcss",
301
- PostCSS: "vscode-icons:file-type-postcss",
302
- java: "vscode-icons:file-type-java",
303
- Java: "vscode-icons:file-type-java",
304
- JAVA: "vscode-icons:file-type-java",
305
- php: "vscode-icons:file-type-php3",
306
- PHP: "vscode-icons:file-type-php3",
307
- c: "vscode-icons:file-type-c",
308
- C: "vscode-icons:file-type-c",
309
- python: "vscode-icons:file-type-python",
310
- Python: "vscode-icons:file-type-python",
311
- kotlin: "vscode-icons:file-type-kotlin",
312
- Kotlin: "vscode-icons:file-type-kotlin",
313
- go: "vscode-icons:file-type-go-gopher",
314
- golang: "vscode-icons:file-type-go-gopher",
315
- Go: "vscode-icons:file-type-go-gopher",
316
- GoLang: "vscode-icons:file-type-go-gopher",
317
- rust: "vscode-icons:file-type-rust",
318
- Rust: "vscode-icons:file-type-rust",
319
- zig: "vscode-icons:file-type-zig",
320
- Zig: "vscode-icons:file-type-zig",
321
- swift: "vscode-icons:file-type-swift",
322
- Swift: "vscode-icons:file-type-swift"
298
+ "html": "vscode-icons:file-type-html",
299
+ "Html": "vscode-icons:file-type-html",
300
+ "HTML": "vscode-icons:file-type-html",
301
+ "javascript": "vscode-icons:file-type-js-official",
302
+ "Javascript": "vscode-icons:file-type-js-official",
303
+ "JavaScript": "vscode-icons:file-type-js-official",
304
+ "js": "vscode-icons:file-type-js-official",
305
+ "JS": "vscode-icons:file-type-js-official",
306
+ "typescript": "vscode-icons:file-type-typescript-official",
307
+ "Typescript": "vscode-icons:file-type-typescript-official",
308
+ "TypeScript": "vscode-icons:file-type-typescript-official",
309
+ "ts": "vscode-icons:file-type-typescript-official",
310
+ "TS": "vscode-icons:file-type-typescript-official",
311
+ "css": "vscode-icons:file-type-css",
312
+ "CSS": "vscode-icons:file-type-css",
313
+ "less": "vscode-icons:file-type-less",
314
+ "Less": "vscode-icons:file-type-less",
315
+ "scss": "vscode-icons:file-type-scss",
316
+ "Scss": "vscode-icons:file-type-scss",
317
+ "SCSS": "vscode-icons:file-type-scss",
318
+ "sass": "vscode-icons:file-type-sass",
319
+ "Sass": "vscode-icons:file-type-sass",
320
+ "SASS": "vscode-icons:file-type-sass",
321
+ "stylus": "vscode-icons:file-type-light-stylus",
322
+ "Stylus": "vscode-icons:file-type-light-stylus",
323
+ "postcss": "vscode-icons:file-type-postcss",
324
+ "Postcss": "vscode-icons:file-type-postcss",
325
+ "PostCSS": "vscode-icons:file-type-postcss",
326
+ "sh": "vscode-icons:file-type-shell",
327
+ "shell": "vscode-icons:file-type-shell",
328
+ "Shell": "vscode-icons:file-type-shell",
329
+ "bash": "vscode-icons:file-type-shell",
330
+ "Bash": "vscode-icons:file-type-shell",
331
+ "java": "vscode-icons:file-type-java",
332
+ "Java": "vscode-icons:file-type-java",
333
+ "JAVA": "vscode-icons:file-type-java",
334
+ "php": "vscode-icons:file-type-php3",
335
+ "PHP": "vscode-icons:file-type-php3",
336
+ "c": "vscode-icons:file-type-c",
337
+ "C": "vscode-icons:file-type-c",
338
+ "python": "vscode-icons:file-type-python",
339
+ "Python": "vscode-icons:file-type-python",
340
+ "kotlin": "vscode-icons:file-type-kotlin",
341
+ "Kotlin": "vscode-icons:file-type-kotlin",
342
+ "go": "vscode-icons:file-type-go-gopher",
343
+ "golang": "vscode-icons:file-type-go-gopher",
344
+ "Go": "vscode-icons:file-type-go-gopher",
345
+ "GoLang": "vscode-icons:file-type-go-gopher",
346
+ "rust": "vscode-icons:file-type-rust",
347
+ "Rust": "vscode-icons:file-type-rust",
348
+ "zig": "vscode-icons:file-type-zig",
349
+ "Zig": "vscode-icons:file-type-zig",
350
+ "swift": "vscode-icons:file-type-swift",
351
+ "Swift": "vscode-icons:file-type-swift",
352
+ "c#": "vscode-icons:file-type-csharp",
353
+ "CSharp": "vscode-icons:file-type-csharp",
354
+ "c++": "vscode-icons:file-type-cpp",
355
+ "C++": "vscode-icons:file-type-cpp",
356
+ "ruby": "vscode-icons:file-type-ruby",
357
+ "Ruby": "vscode-icons:file-type-ruby",
358
+ "makefile": "vscode-icons:file-type-makefile",
359
+ "Makefile": "vscode-icons:file-type-makefile",
360
+ "Object-C": "vscode-icons:file-type-objectivec",
361
+ "object-c": "vscode-icons:file-type-objectivec",
362
+ "SQL": "vscode-icons:file-type-sql",
363
+ "sql": "vscode-icons:file-type-sql",
364
+ "mysql": "vscode-icons:file-type-mysql",
365
+ "MySQL": "vscode-icons:file-type-mysql",
366
+ "MySql": "vscode-icons:file-type-mysql",
367
+ "pgsql": "vscode-icons:file-type-pgsql",
368
+ "PostgreSQL": "vscode-icons:file-type-pgsql",
369
+ "PGSQL": "vscode-icons:file-type-pgsql",
370
+ "xml": "vscode-icons:file-type-xml",
371
+ "XML": "vscode-icons:file-type-xml",
372
+ "wasm": "vscode-icons:file-type-wasm",
373
+ "webassembly": "vscode-icons:file-type-wasm",
374
+ "WebAssembly": "vscode-icons:file-type-wasm",
375
+ "WASM": "vscode-icons:file-type-wasm",
376
+ "toml": "vscode-icons:file-type-light-toml",
377
+ "Toml": "vscode-icons:file-type-light-toml",
378
+ "TOML": "vscode-icons:file-type-light-toml",
379
+ "yaml": "vscode-icons:file-type-light-yaml",
380
+ "Yaml": "vscode-icons:file-type-light-yaml",
381
+ "YAML": "vscode-icons:file-type-light-yaml"
323
382
  },
324
383
  folders: {
325
384
  "default": "vscode-icons:default-folder",
@@ -987,7 +1046,7 @@ var definitions = {
987
1046
  }
988
1047
  };
989
1048
 
990
- // src/node/container/fileTree/findIcon.ts
1049
+ // src/node/fileIcons/findIcon.ts
991
1050
  function getFileIcon(fileName, type2 = "file") {
992
1051
  const name = getFileIconName(fileName, type2);
993
1052
  if (!name)
@@ -1032,9 +1091,138 @@ function getFileIconTypeFromExtension(fileName) {
1032
1091
  return void 0;
1033
1092
  }
1034
1093
 
1035
- // src/node/container/fileTree/resolveTreeNodeInfo.ts
1094
+ // src/node/utils/stringifyProp.ts
1095
+ function stringifyProp(data) {
1096
+ return JSON.stringify(data).replace(/'/g, "&#39");
1097
+ }
1098
+
1099
+ // src/node/container/codeTabs.ts
1100
+ var codeTabs = (md, options = {}) => {
1101
+ const getIcon = (filename) => {
1102
+ if (options.icon === false)
1103
+ return void 0;
1104
+ const { named, extensions } = isPlainObject(options.icon) ? options.icon : {};
1105
+ if (named === false && definitions.named[filename])
1106
+ return void 0;
1107
+ if (extensions === false && getFileIconTypeFromExtension(filename)) {
1108
+ return void 0;
1109
+ }
1110
+ const hasNamed = named && named.length;
1111
+ const hasExt = extensions && extensions.length;
1112
+ if (hasNamed || hasExt) {
1113
+ if (hasNamed && named.includes(filename))
1114
+ return definitions.named[filename];
1115
+ if (hasExt && extensions.some((ext) => filename.endsWith(ext)))
1116
+ return getFileIconTypeFromExtension(filename);
1117
+ return void 0;
1118
+ }
1119
+ return getFileIconName(filename);
1120
+ };
1121
+ tab(md, {
1122
+ name: "code-tabs",
1123
+ tabsOpenRenderer: ({ active, data }, tokens, index) => {
1124
+ const { meta } = tokens[index];
1125
+ const titles = data.map(({ title }) => md.renderInline(title));
1126
+ const tabsData = data.map((item, dataIndex) => {
1127
+ const { id = titles[dataIndex] } = item;
1128
+ return { id };
1129
+ });
1130
+ const titlesContent = titles.map((title, index2) => {
1131
+ const icon = getIcon(title);
1132
+ return `<template #title${index2}="{ value, isActive }">${icon ? `<VPIcon name="${icon}"/>` : ""}<span>${title}</span></template>`;
1133
+ }).join("");
1134
+ return `<CodeTabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? "" : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id}"` : ""}>${titlesContent}`;
1135
+ },
1136
+ tabsCloseRenderer: () => `</CodeTabs>`,
1137
+ tabOpenRenderer: ({ index }, tokens, tokenIndex) => {
1138
+ let foundFence = false;
1139
+ for (let i = tokenIndex; i < tokens.length; i++) {
1140
+ const { block, type: type2 } = tokens[i];
1141
+ if (block) {
1142
+ if (type2 === "code-tabs_tab_close")
1143
+ break;
1144
+ if ((type2 === "fence" || type2 === "import_code") && !foundFence) {
1145
+ foundFence = true;
1146
+ continue;
1147
+ }
1148
+ tokens[i].type = "code_tab_empty";
1149
+ tokens[i].hidden = true;
1150
+ }
1151
+ }
1152
+ return `<template #tab${index}="{ value, isActive }">`;
1153
+ },
1154
+ tabCloseRenderer: () => `</template>`
1155
+ });
1156
+ };
1157
+
1158
+ // src/node/container/fileTree.ts
1036
1159
  import Token from "markdown-it/lib/token.mjs";
1160
+ import container2 from "markdown-it-container";
1037
1161
  import { removeEndingSlash, removeLeadingSlash } from "vuepress/shared";
1162
+ var type = "file-tree";
1163
+ var closeType = `container_${type}_close`;
1164
+ var componentName = "FileTreeItem";
1165
+ var itemOpen = "file_tree_item_open";
1166
+ var itemClose = "file_tree_item_close";
1167
+ var RE_SIMPLE_ICON = /:simple-icon\b/;
1168
+ var RE_COLORED_ICON = /:colored-icon\b/;
1169
+ function fileTreePlugin(md, options = {}) {
1170
+ const getIcon = (filename, type2, mode) => {
1171
+ mode ||= options.icon || "colored";
1172
+ if (mode === "simple")
1173
+ return type2 === "folder" ? defaultFolder : defaultFile;
1174
+ return getFileIcon(filename, type2);
1175
+ };
1176
+ const validate = (info) => info.trim().startsWith(type);
1177
+ const render = (tokens, idx) => {
1178
+ const mode = getFileIconMode(tokens[idx].info);
1179
+ if (tokens[idx].nesting === 1) {
1180
+ const hasRes = [];
1181
+ for (let i = idx + 1; !(tokens[i].nesting === -1 && tokens[i].type === closeType); ++i) {
1182
+ const token = tokens[i];
1183
+ if (token.type === "list_item_open") {
1184
+ const result = resolveTreeNodeInfo(tokens, token, i);
1185
+ if (result) {
1186
+ hasRes.push(token.level);
1187
+ const [info, inline] = result;
1188
+ const { filename, type: type2, expanded, empty } = info;
1189
+ const icon = getIcon(filename, type2, mode);
1190
+ token.type = itemOpen;
1191
+ token.tag = componentName;
1192
+ token.attrSet("type", type2);
1193
+ token.attrSet(":expanded", expanded ? "true" : "false");
1194
+ token.attrSet(":empty", empty ? "true" : "false");
1195
+ updateInlineToken(inline, info, icon);
1196
+ } else {
1197
+ hasRes.push(-1);
1198
+ }
1199
+ } else if (token.type === "list_item_close") {
1200
+ if (token.level === hasRes.pop()) {
1201
+ token.type = itemClose;
1202
+ token.tag = componentName;
1203
+ }
1204
+ }
1205
+ }
1206
+ const title = resolveTitle(tokens[idx].info);
1207
+ return `<div class="vp-file-tree">${title ? `<p class="vp-file-tree-title">${title}</p>` : ""}`;
1208
+ } else {
1209
+ return "</div>";
1210
+ }
1211
+ };
1212
+ md.use(container2, type, { validate, render });
1213
+ }
1214
+ function getFileIconMode(info) {
1215
+ if (RE_SIMPLE_ICON.test(info))
1216
+ return "simple";
1217
+ if (RE_COLORED_ICON.test(info))
1218
+ return "colored";
1219
+ return void 0;
1220
+ }
1221
+ function resolveTitle(info) {
1222
+ info = info.trim().slice(type.length).trim();
1223
+ info = info.replace(RE_SIMPLE_ICON, "").replace(RE_COLORED_ICON, "");
1224
+ return info.trim();
1225
+ }
1038
1226
  function resolveTreeNodeInfo(tokens, current, idx) {
1039
1227
  let hasInline = false;
1040
1228
  let hasChildren = false;
@@ -1089,17 +1277,19 @@ function updateInlineToken(inline, info, icon) {
1089
1277
  if (token.content.includes(" ")) {
1090
1278
  const [first, ...other] = token.content.split(" ");
1091
1279
  const text = new Token("text", "", 0);
1092
- text.content = first;
1280
+ text.content = removeEndingSlash(first);
1093
1281
  tokens.push(text);
1094
1282
  const comment = new Token("text", "", 0);
1095
1283
  comment.content = other.join(" ");
1096
1284
  children.unshift(comment);
1097
1285
  } else {
1286
+ token.content = removeEndingSlash(token.content);
1098
1287
  tokens.push(token);
1099
1288
  }
1100
1289
  if (!isStrongTag)
1101
1290
  break;
1102
1291
  } else if (token.tag === "strong") {
1292
+ token.content = removeEndingSlash(token.content);
1103
1293
  tokens.push(token);
1104
1294
  if (token.nesting === 1) {
1105
1295
  isStrongTag = true;
@@ -1122,54 +1312,8 @@ function updateInlineToken(inline, info, icon) {
1122
1312
  inline.children = tokens;
1123
1313
  }
1124
1314
 
1125
- // src/node/container/fileTree/index.ts
1126
- var type = "file-tree";
1127
- var closeType = `container_${type}_close`;
1128
- var componentName = "FileTreeItem";
1129
- var itemOpen = "file_tree_item_open";
1130
- var itemClose = "file_tree_item_close";
1131
- function fileTreePlugin(md) {
1132
- const validate = (info) => info.trim().startsWith(type);
1133
- const render = (tokens, idx) => {
1134
- if (tokens[idx].nesting === 1) {
1135
- const hasRes = [];
1136
- for (let i = idx + 1; !(tokens[i].nesting === -1 && tokens[i].type === closeType); ++i) {
1137
- const token = tokens[i];
1138
- if (token.type === "list_item_open") {
1139
- const result = resolveTreeNodeInfo(tokens, token, i);
1140
- if (result) {
1141
- hasRes.push(token.level);
1142
- const [info2, inline] = result;
1143
- const { filename, type: type2, expanded, empty } = info2;
1144
- const icon = getFileIcon(filename, type2);
1145
- token.type = itemOpen;
1146
- token.tag = componentName;
1147
- token.attrSet("type", type2);
1148
- token.attrSet(":expanded", expanded ? "true" : "false");
1149
- token.attrSet(":empty", empty ? "true" : "false");
1150
- updateInlineToken(inline, info2, icon);
1151
- } else {
1152
- hasRes.push(-1);
1153
- }
1154
- } else if (token.type === "list_item_close") {
1155
- if (token.level === hasRes.pop()) {
1156
- token.type = itemClose;
1157
- token.tag = componentName;
1158
- }
1159
- }
1160
- }
1161
- const info = tokens[idx].info.trim();
1162
- const title = info.slice(type.length).trim();
1163
- return `<div class="vp-file-tree">${title ? `<p class="vp-file-tree-title">${title}</p>` : ""}`;
1164
- } else {
1165
- return "</div>";
1166
- }
1167
- };
1168
- md.use(container, type, { validate, render });
1169
- }
1170
-
1171
1315
  // src/node/container/langRepl.ts
1172
- import container2 from "markdown-it-container";
1316
+ import container3 from "markdown-it-container";
1173
1317
  import { fs as fs2, getDirname, path as path2 } from "vuepress/utils";
1174
1318
  var RE_INFO = /^(#editable)?(.*)$/;
1175
1319
  function createReplContainer(md, lang) {
@@ -1184,7 +1328,7 @@ function createReplContainer(md, lang) {
1184
1328
  else
1185
1329
  return "</CodeRepl>";
1186
1330
  };
1187
- md.use(container2, type2, { validate, render });
1331
+ md.use(container3, type2, { validate, render });
1188
1332
  }
1189
1333
  async function langReplPlugin(app, md, {
1190
1334
  theme,
@@ -1235,17 +1379,43 @@ async function read(file) {
1235
1379
  return void 0;
1236
1380
  }
1237
1381
 
1382
+ // src/node/container/tabs.ts
1383
+ import { tab as tab2 } from "@mdit/plugin-tab";
1384
+ var tabs = (md) => {
1385
+ tab2(md, {
1386
+ name: "tabs",
1387
+ tabsOpenRenderer: ({ active, data }, tokens, index) => {
1388
+ const { meta } = tokens[index];
1389
+ const titles = data.map(({ title }) => md.renderInline(title));
1390
+ const tabsData = data.map((item, dataIndex) => {
1391
+ const { id = titles[dataIndex] } = item;
1392
+ return { id };
1393
+ });
1394
+ return `<Tabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? "" : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id}"` : ""}>
1395
+ ${titles.map(
1396
+ (title, titleIndex) => `<template #title${titleIndex}="{ value, isActive }">${title}</template>`
1397
+ ).join("")}`;
1398
+ },
1399
+ tabsCloseRenderer: () => `</Tabs>`,
1400
+ tabOpenRenderer: ({ index }) => `<template #tab${index}="{ value, isActive }">`,
1401
+ tabCloseRenderer: () => `</template>`
1402
+ });
1403
+ };
1404
+
1238
1405
  // src/node/container/index.ts
1239
1406
  async function containerPlugin(app, md, options) {
1407
+ alignPlugin(md);
1408
+ tabs(md);
1409
+ codeTabs(md, options.codeTabs);
1240
1410
  if (options.repl)
1241
1411
  await langReplPlugin(app, md, options.repl);
1242
1412
  if (options.fileTree) {
1243
- fileTreePlugin(md);
1413
+ fileTreePlugin(md, isPlainObject2(options.fileTree) ? options.fileTree : {});
1244
1414
  }
1245
1415
  }
1246
1416
 
1247
1417
  // src/node/embed/caniuse.ts
1248
- import container3 from "markdown-it-container";
1418
+ import container4 from "markdown-it-container";
1249
1419
  import { customAlphabet } from "nanoid";
1250
1420
 
1251
1421
  // src/node/embed/createEmbedRuleBlock.ts
@@ -1327,7 +1497,7 @@ function legacyCaniuse(md, { mode = "embed" } = {}) {
1327
1497
  return "";
1328
1498
  }
1329
1499
  };
1330
- md.use(container3, type2, { validate, render });
1500
+ md.use(container4, type2, { validate, render });
1331
1501
  }
1332
1502
  function resolveCanIUse({ feature, mode, versions }) {
1333
1503
  if (!feature)
@@ -1372,18 +1542,18 @@ var codepenPlugin = (md) => {
1372
1542
  type: "codepen",
1373
1543
  syntaxPattern: /^@\[codepen([^\]]*)\]\(([^)]*)\)/,
1374
1544
  meta: ([, info = "", source = ""]) => {
1375
- const { attrs } = resolveAttrs(info);
1545
+ const { attrs: attrs2 } = resolveAttrs(info);
1376
1546
  const [user, slash] = source.split("/");
1377
1547
  return {
1378
- width: attrs.width ? parseRect(attrs.width) : "100%",
1379
- height: attrs.height ? parseRect(attrs.height) : "400px",
1548
+ width: attrs2.width ? parseRect(attrs2.width) : "100%",
1549
+ height: attrs2.height ? parseRect(attrs2.height) : "400px",
1380
1550
  user,
1381
1551
  slash,
1382
- title: attrs.title,
1383
- preview: attrs.preview,
1384
- editable: attrs.editable,
1385
- tab: attrs.tab ?? "result",
1386
- theme: attrs.theme
1552
+ title: attrs2.title,
1553
+ preview: attrs2.preview,
1554
+ editable: attrs2.editable,
1555
+ tab: attrs2.tab ?? "result",
1556
+ theme: attrs2.theme
1387
1557
  };
1388
1558
  },
1389
1559
  content: (meta) => {
@@ -1412,18 +1582,18 @@ var codeSandboxPlugin = (md) => {
1412
1582
  type: "codesandbox",
1413
1583
  syntaxPattern: /^@\[codesandbox(?:\s+(embed|button))?([^\]]*)\]\(([^)]*)\)/,
1414
1584
  meta([, type2, info = "", source = ""]) {
1415
- const { attrs } = resolveAttrs(info);
1585
+ const { attrs: attrs2 } = resolveAttrs(info);
1416
1586
  const [profile, filepath2 = ""] = source.split("#");
1417
1587
  const [user, id] = profile.includes("/") ? profile.split("/") : ["", profile];
1418
1588
  return {
1419
- width: attrs.width ? parseRect(attrs.width) : "100%",
1420
- height: attrs.height ? parseRect(attrs.height) : "500px",
1589
+ width: attrs2.width ? parseRect(attrs2.width) : "100%",
1590
+ height: attrs2.height ? parseRect(attrs2.height) : "500px",
1421
1591
  user,
1422
1592
  id,
1423
- title: attrs.title ?? "",
1424
- console: attrs.console ?? false,
1425
- navbar: attrs.navbar ?? true,
1426
- layout: attrs.layout ?? "",
1593
+ title: attrs2.title ?? "",
1594
+ console: attrs2.console ?? false,
1595
+ navbar: attrs2.navbar ?? true,
1596
+ layout: attrs2.layout ?? "",
1427
1597
  type: type2 || "embed",
1428
1598
  filepath: filepath2
1429
1599
  };
@@ -1440,21 +1610,21 @@ var jsfiddlePlugin = (md) => {
1440
1610
  type: "jsfiddle",
1441
1611
  syntaxPattern: /^@\[jsfiddle([^\]]*)\]\(([^)]*)\)/,
1442
1612
  meta([, info = "", source]) {
1443
- const { attrs } = resolveAttrs(info);
1613
+ const { attrs: attrs2 } = resolveAttrs(info);
1444
1614
  const [user, id] = source.split("/");
1445
1615
  return {
1446
- width: attrs.width ? parseRect(attrs.width) : "100%",
1447
- height: attrs.height ? parseRect(attrs.height) : "400px",
1616
+ width: attrs2.width ? parseRect(attrs2.width) : "100%",
1617
+ height: attrs2.height ? parseRect(attrs2.height) : "400px",
1448
1618
  user,
1449
1619
  id,
1450
- title: attrs.title || "JS Fiddle",
1451
- tab: attrs.tab?.replace(/\s+/g, "") || "js,css,html,result",
1452
- theme: attrs.theme || "dark"
1620
+ title: attrs2.title || "JS Fiddle",
1621
+ tab: attrs2.tab?.replace(/\s+/g, "") || "js,css,html,result",
1622
+ theme: attrs2.theme || "dark"
1453
1623
  };
1454
1624
  },
1455
- content: ({ title = "JS Fiddle", height, width, user, id, tab, theme }) => {
1625
+ content: ({ title = "JS Fiddle", height, width, user, id, tab: tab3, theme }) => {
1456
1626
  theme = theme === "dark" ? "/dark/" : "";
1457
- const link = `https://jsfiddle.net/${user}/${id}/embedded/${tab}${theme}`;
1627
+ const link = `https://jsfiddle.net/${user}/${id}/embedded/${tab3}${theme}`;
1458
1628
  const style = `width:${width};height:${height};margin:16px auto;border:none;border-radius:5px;`;
1459
1629
  return `<iframe class="js-fiddle-iframe-wrapper" style="${style}" title="${title}" src="${link}" allowfullscreen="true" allowpaymentrequest="true"></iframe>`;
1460
1630
  }
@@ -1467,13 +1637,13 @@ var replitPlugin = (md) => {
1467
1637
  type: "replit",
1468
1638
  syntaxPattern: /^@\[replit([^\]]*)\]\(([^)]*)\)/,
1469
1639
  meta: ([, info = "", source = ""]) => {
1470
- const { attrs } = resolveAttrs(info);
1640
+ const { attrs: attrs2 } = resolveAttrs(info);
1471
1641
  return {
1472
- width: attrs.width ? parseRect(attrs.width) : "100%",
1473
- height: attrs.height ? parseRect(attrs.height) : "450px",
1642
+ width: attrs2.width ? parseRect(attrs2.width) : "100%",
1643
+ height: attrs2.height ? parseRect(attrs2.height) : "450px",
1474
1644
  source: source.startsWith("@") ? source : `@${source}`,
1475
- title: attrs.title,
1476
- theme: attrs.theme || ""
1645
+ title: attrs2.title,
1646
+ theme: attrs2.theme || ""
1477
1647
  };
1478
1648
  },
1479
1649
  content({ title, height, width, source, theme }) {
@@ -1490,15 +1660,15 @@ var pdfPlugin = (md) => {
1490
1660
  // eslint-disable-next-line regexp/no-super-linear-backtracking
1491
1661
  syntaxPattern: /^@\[pdf(?:\s+(\d+))?([^\]]*)\]\(([^)]*)\)/,
1492
1662
  meta([, page, info = "", src = ""]) {
1493
- const { attrs } = resolveAttrs(info);
1663
+ const { attrs: attrs2 } = resolveAttrs(info);
1494
1664
  return {
1495
1665
  src,
1496
1666
  page: +page || 1,
1497
- noToolbar: Boolean(attrs.noToolbar ?? false),
1498
- zoom: +attrs.zoom || 50,
1499
- width: attrs.width ? parseRect(attrs.width) : "100%",
1500
- height: attrs.height ? parseRect(attrs.height) : "",
1501
- ratio: attrs.ratio ? parseRect(attrs.ratio) : "",
1667
+ noToolbar: Boolean(attrs2.noToolbar ?? false),
1668
+ zoom: +attrs2.zoom || 50,
1669
+ width: attrs2.width ? parseRect(attrs2.width) : "100%",
1670
+ height: attrs2.height ? parseRect(attrs2.height) : "",
1671
+ ratio: attrs2.ratio ? parseRect(attrs2.ratio) : "",
1502
1672
  title: path3.basename(src || "")
1503
1673
  };
1504
1674
  },
@@ -1530,7 +1700,7 @@ var bilibiliPlugin = (md) => {
1530
1700
  // eslint-disable-next-line regexp/no-super-linear-backtracking
1531
1701
  syntaxPattern: /^@\[bilibili(?:\s+p(\d+))?([^\]]*)\]\(([^)]*)\)/,
1532
1702
  meta([, page, info = "", source = ""]) {
1533
- const { attrs } = resolveAttrs(info);
1703
+ const { attrs: attrs2 } = resolveAttrs(info);
1534
1704
  const ids = source.trim().split(/\s+/);
1535
1705
  const bvid = ids.find((id) => id.startsWith("BV"));
1536
1706
  const [aid, cid] = ids.filter((id) => !id.startsWith("BV"));
@@ -1539,12 +1709,12 @@ var bilibiliPlugin = (md) => {
1539
1709
  bvid,
1540
1710
  aid,
1541
1711
  cid,
1542
- autoplay: attrs.autoplay ?? false,
1543
- time: timeToSeconds(attrs.time),
1544
- title: attrs.title,
1545
- width: attrs.width ? parseRect(attrs.width) : "100%",
1546
- height: attrs.height ? parseRect(attrs.height) : "",
1547
- ratio: attrs.ratio ? parseRect(attrs.ratio) : ""
1712
+ autoplay: attrs2.autoplay ?? false,
1713
+ time: timeToSeconds(attrs2.time),
1714
+ title: attrs2.title,
1715
+ width: attrs2.width ? parseRect(attrs2.width) : "100%",
1716
+ height: attrs2.height ? parseRect(attrs2.height) : "",
1717
+ ratio: attrs2.ratio ? parseRect(attrs2.ratio) : ""
1548
1718
  };
1549
1719
  },
1550
1720
  content(meta) {
@@ -1580,17 +1750,17 @@ var youtubePlugin = (md) => {
1580
1750
  name: "video_youtube",
1581
1751
  syntaxPattern: /^@\[youtube([^\]]*)\]\(([^)]*)\)/,
1582
1752
  meta([, info = "", id = ""]) {
1583
- const { attrs } = resolveAttrs(info);
1753
+ const { attrs: attrs2 } = resolveAttrs(info);
1584
1754
  return {
1585
1755
  id,
1586
- autoplay: attrs.autoplay ?? false,
1587
- loop: attrs.loop ?? false,
1588
- start: timeToSeconds(attrs.start),
1589
- end: timeToSeconds(attrs.end),
1590
- title: attrs.title,
1591
- width: attrs.width ? parseRect(attrs.width) : "100%",
1592
- height: attrs.height ? parseRect(attrs.height) : "",
1593
- ratio: attrs.ratio ? parseRect(attrs.ratio) : ""
1756
+ autoplay: attrs2.autoplay ?? false,
1757
+ loop: attrs2.loop ?? false,
1758
+ start: timeToSeconds(attrs2.start),
1759
+ end: timeToSeconds(attrs2.end),
1760
+ title: attrs2.title,
1761
+ width: attrs2.width ? parseRect(attrs2.width) : "100%",
1762
+ height: attrs2.height ? parseRect(attrs2.height) : "",
1763
+ ratio: attrs2.ratio ? parseRect(attrs2.ratio) : ""
1594
1764
  };
1595
1765
  },
1596
1766
  content(meta) {
@@ -1643,10 +1813,19 @@ function embedSyntaxPlugin(md, options) {
1643
1813
  }
1644
1814
  }
1645
1815
 
1816
+ // src/node/inline/index.ts
1817
+ import { attrs } from "@mdit/plugin-attrs";
1818
+ import { footnote } from "@mdit/plugin-footnote";
1819
+ import { mark } from "@mdit/plugin-mark";
1820
+ import { sub } from "@mdit/plugin-sub";
1821
+ import { sup } from "@mdit/plugin-sup";
1822
+ import { tasklist } from "@mdit/plugin-tasklist";
1823
+ import { isPlainObject as isPlainObject3 } from "@vuepress/helper";
1824
+
1646
1825
  // src/node/inline/icons.ts
1647
1826
  var [openTag, endTag] = [":[", "]:"];
1648
- var iconsPlugin = (md) => md.inline.ruler.before("emphasis", "iconify", createTokenizer());
1649
- function createTokenizer() {
1827
+ var iconsPlugin = (md, options = {}) => md.inline.ruler.before("emphasis", "iconify", createTokenizer(options));
1828
+ function createTokenizer(options) {
1650
1829
  return (state, silent) => {
1651
1830
  let found = false;
1652
1831
  const max = state.posMax;
@@ -1676,14 +1855,14 @@ function createTokenizer() {
1676
1855
  }
1677
1856
  state.posMax = state.pos;
1678
1857
  state.pos = start + 2;
1679
- const [name, options = ""] = content.split(/\s+/);
1680
- const [size, color] = options.split("/");
1858
+ const [name, opt = ""] = content.split(/\s+/);
1859
+ const [size = options.size, color = options.color] = opt.split("/");
1681
1860
  const icon = state.push("vp_iconify_open", "VPIcon", 1);
1682
1861
  icon.markup = openTag;
1683
1862
  if (name)
1684
1863
  icon.attrSet("name", name);
1685
1864
  if (size)
1686
- icon.attrSet("size", size);
1865
+ icon.attrSet("size", String(size));
1687
1866
  if (color)
1688
1867
  icon.attrSet("color", color);
1689
1868
  const close = state.push("vp_iconify_close", "VPIcon", -1);
@@ -1741,10 +1920,16 @@ function createTokenizer2() {
1741
1920
 
1742
1921
  // src/node/inline/index.ts
1743
1922
  function inlineSyntaxPlugin(md, options) {
1923
+ md.use(attrs);
1924
+ md.use(mark);
1925
+ md.use(sub);
1926
+ md.use(sup);
1927
+ md.use(footnote);
1928
+ md.use(tasklist);
1744
1929
  if (options.icons) {
1745
- md.use(iconsPlugin);
1930
+ md.use(iconsPlugin, isPlainObject3(options.icons) ? options.icons : {});
1746
1931
  }
1747
- if (options.plot === true || typeof options.plot === "object" && options.plot.tag !== false) {
1932
+ if (options.plot === true || isPlainObject3(options.plot) && options.plot.tag !== false) {
1748
1933
  md.use(plotPlugin);
1749
1934
  }
1750
1935
  }
@@ -1760,6 +1945,10 @@ var CLIENT_FOLDER = ensureEndingSlash(
1760
1945
  async function prepareConfigFile(app, options) {
1761
1946
  const imports = /* @__PURE__ */ new Set();
1762
1947
  const enhances = /* @__PURE__ */ new Set();
1948
+ imports.add(`import Tabs from '${CLIENT_FOLDER}components/Tabs.vue'`);
1949
+ enhances.add(`app.component('Tabs', Tabs)`);
1950
+ imports.add(`import CodeTabs from '${CLIENT_FOLDER}components/CodeTabs.vue'`);
1951
+ enhances.add(`app.component('CodeTabs', CodeTabs)`);
1763
1952
  if (options.pdf) {
1764
1953
  imports.add(`import PDFViewer from '${CLIENT_FOLDER}components/PDFViewer.vue'`);
1765
1954
  enhances.add(`app.component('PDFViewer', PDFViewer)`);
@@ -1820,11 +2009,7 @@ function markdownPowerPlugin(options = {}) {
1820
2009
  },
1821
2010
  extendsBundlerOptions(bundlerOptions, app) {
1822
2011
  if (options.repl) {
1823
- addViteOptimizeDepsInclude(
1824
- bundlerOptions,
1825
- app,
1826
- ["shiki/core", "shiki/wasm"]
1827
- );
2012
+ addViteOptimizeDepsInclude(bundlerOptions, app, ["shiki/core", "shiki/wasm"]);
1828
2013
  }
1829
2014
  },
1830
2015
  extendsMarkdown: async (md, app) => {