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

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.
@@ -16,7 +16,7 @@ const activeFileTreeNode = inject<Ref<string>>('active-file-tree-node', ref(''))
16
16
 
17
17
  const onNodeClick = inject<
18
18
  (filename: string, type: 'file' | 'folder') => void
19
- >('on-file-tree-node-click', () => {})
19
+ >('on-file-tree-node-click', () => {})
20
20
 
21
21
  const active = ref(props.expanded)
22
22
 
@@ -1,61 +1,46 @@
1
1
  <script setup lang="ts">
2
2
  import type { PlotOptions } from '../../shared/index.js'
3
3
  import { onClickOutside, useMediaQuery } from '@vueuse/core'
4
- import { computed, ref, shallowRef } from 'vue'
4
+ import { computed, onMounted, ref, useTemplateRef } from 'vue'
5
5
  import { usePageFrontmatter } from 'vuepress/client'
6
6
  import { pluginOptions } from '../options.js'
7
7
 
8
- const props = defineProps<Omit<PlotOptions, 'tag'>>()
8
+ const props = defineProps<PlotOptions>()
9
9
 
10
10
  const matter = usePageFrontmatter()
11
+ const isMobile = useMediaQuery('(max-width: 768px)')
11
12
 
12
- const options = computed(() => {
13
- const plot = typeof pluginOptions.plot === 'object' ? pluginOptions.plot : {}
14
-
13
+ const plot = computed(() => {
14
+ const global = typeof pluginOptions.plot === 'object' ? pluginOptions.plot : {}
15
+ const current = (typeof matter.value.plot === 'object' ? matter.value.plot : {}) as PlotOptions
15
16
  return {
16
- trigger: props.trigger || matter.value.plotTrigger || plot.trigger || 'hover',
17
- color: props.color || plot.color,
18
- mask: props.mask || plot.mask,
17
+ trigger: isMobile.value ? 'click' : props.trigger ?? current.trigger ?? global.trigger ?? 'hover',
18
+ effect: props.effect ?? current.effect ?? global.effect ?? 'mask',
19
19
  }
20
20
  })
21
+ const active = ref(false)
22
+ const el = useTemplateRef<HTMLElement>('el')
23
+ const classes = ref<string[]>([])
21
24
 
22
- const styles = computed(() => {
23
- const plot = options.value
24
- if (!plot.color && !plot.mask)
25
- return {}
26
- const style: Record<string, string> = {}
27
- if (plot.color) {
28
- if (typeof plot.color === 'string') {
29
- style['--vp-c-plot-light'] = plot.color
30
- }
31
- else {
32
- style['--vp-c-plot-light'] = plot.color.light
33
- style['--vp-c-plot-dark'] = plot.color.dark
34
- }
25
+ onMounted(() => {
26
+ if (!el.value)
27
+ return
28
+ const classList = el.value.classList
29
+ if (!classList.contains('hover') && !classList.contains('click')) {
30
+ classes.value.push(plot.value.trigger)
35
31
  }
36
- if (plot.mask) {
37
- if (typeof plot.mask === 'string') {
38
- style['--vp-c-bg-plot-light'] = plot.mask
39
- }
40
- else {
41
- style['--vp-c-bg-plot-light'] = plot.mask.light
42
- style['--vp-c-bg-plot-dark'] = plot.mask.dark
43
- }
32
+ if (!classList.contains('mask') && !classList.contains('blur')) {
33
+ classes.value.push(plot.value.effect)
44
34
  }
45
- return style
46
35
  })
47
36
 
48
- const isMobile = useMediaQuery('(max-width: 768px)')
49
- const active = ref(false)
50
- const el = shallowRef<HTMLElement>()
51
-
52
37
  onClickOutside(el, () => {
53
- if (options.value.trigger === 'click' || isMobile.value)
38
+ if (plot.value.trigger === 'click' || el.value?.classList.contains('click'))
54
39
  active.value = false
55
40
  })
56
41
 
57
42
  function onClick() {
58
- if (props.trigger === 'click' || isMobile.value)
43
+ if (plot.value.trigger === 'click' || el.value?.classList.contains('click'))
59
44
  active.value = !active.value
60
45
  }
61
46
  </script>
@@ -64,8 +49,7 @@ function onClick() {
64
49
  <span
65
50
  ref="el"
66
51
  class="vp-plot"
67
- :class="{ hover: options.trigger !== 'click', active }"
68
- :style="styles"
52
+ :class="[{ active }, ...classes]"
69
53
  @click="onClick"
70
54
  >
71
55
  <slot />
@@ -73,25 +57,39 @@ function onClick() {
73
57
  </template>
74
58
 
75
59
  <style>
60
+ :root {
61
+ --vp-plot-bg: var(--vp-c-text-1);
62
+ --vp-plot-c-text: var(--vp-c-neutral-inverse);
63
+ --vp-plot-blur: 0.2rem;
64
+ }
65
+
76
66
  .vp-plot {
77
67
  padding-right: 2px;
78
68
  padding-left: 2px;
79
- color: transparent;
80
- background-color: var(--vp-c-bg-plot-light, #000);
81
- transition: color ease 0.25s, background-color ease 0.25s;
82
69
  }
83
70
 
84
- [data-theme="dark"] .vp-plot {
85
- background-color: var(--vp-c-bg-plot-dark, #fff);
71
+ .vp-plot.click {
72
+ cursor: pointer;
73
+ }
74
+
75
+ .vp-plot:where(.blur) {
76
+ filter: blur(var(--vp-plot-blur));
77
+ transition: filter var(--vp-t-color);
78
+ }
79
+
80
+ .vp-plot:where(.mask) {
81
+ color: transparent;
82
+ background-color: var(--vp-plot-bg);
83
+ transition: color var(--vp-t-color), background-color var(--vp-t-color);
86
84
  }
87
85
 
88
- .vp-plot.hover:hover,
89
- .vp-plot.active {
90
- color: var(--vp-c-plot-light, #fff);
86
+ .vp-plot:where(.blur.hover):hover,
87
+ .vp-plot:where(.blur).active {
88
+ filter: blur(0);
91
89
  }
92
90
 
93
- [data-theme="dark"] .vp-plot.hover:hover,
94
- [data-theme="dark"] .vp-plot.active {
95
- color: var(--vp-c-plot-dark, #000);
91
+ .vp-plot:where(.mask.hover):hover,
92
+ .vp-plot:where(.mask).active {
93
+ color: var(--vp-plot-c-text);
96
94
  }
97
95
  </style>
@@ -4,15 +4,17 @@ defineProps<{
4
4
  type?: string
5
5
  required?: boolean
6
6
  optional?: boolean
7
+ deprecated?: boolean
7
8
  defaultValue?: string
8
9
  }>()
9
10
  </script>
10
11
 
11
12
  <template>
12
- <div class="vp-field">
13
+ <div class="vp-field" :class="{ required, optional, deprecated }">
13
14
  <p class="field-meta">
14
15
  <span class="name">{{ name }}</span>
15
16
  <span v-if="required || optional" :class="{ required, optional }">{{ required ? 'Required' : optional ? 'Optional' : '' }}</span>
17
+ <span v-if="deprecated" class="deprecated">Deprecated</span>
16
18
  <span v-if="type" class="type"><code>{{ type }}</code></span>
17
19
  </p>
18
20
  <p v-if="defaultValue" class="default-value">
@@ -48,8 +50,13 @@ defineProps<{
48
50
  font-weight: 500;
49
51
  }
50
52
 
53
+ .vp-field.deprecated .field-meta .name {
54
+ text-decoration: line-through;
55
+ }
56
+
51
57
  .vp-field .field-meta .required,
52
- .vp-field .field-meta .optional {
58
+ .vp-field .field-meta .optional,
59
+ .vp-field .field-meta .deprecated {
53
60
  display: inline-block;
54
61
  padding: 2px 8px;
55
62
  font-size: 12px;
@@ -68,6 +75,11 @@ defineProps<{
68
75
  border: solid 1px var(--vp-c-divider);
69
76
  }
70
77
 
78
+ .vp-field .field-meta .deprecated {
79
+ color: var(--vp-c-danger-2);
80
+ border: solid 1px var(--vp-c-danger-2);
81
+ }
82
+
71
83
  .vp-field .field-meta .type {
72
84
  flex: 1 2;
73
85
  text-align: right;
@@ -76,7 +88,8 @@ defineProps<{
76
88
  .vp-field .default-value {
77
89
  margin: 0;
78
90
  font-size: 14px;
79
- line-height: 1;
91
+ line-height: 1.7;
92
+ transform: translateY(-4px);
80
93
  }
81
94
 
82
95
  .vp-field .description :where(p, ul, ol) {
@@ -5,6 +5,7 @@ import { useSize } from '../composables/size.js'
5
5
  const props = defineProps<{
6
6
  src: string
7
7
  title: string
8
+ type?: string
8
9
  width?: string
9
10
  height?: string
10
11
  ratio?: string
@@ -21,9 +22,9 @@ const { el, width, height, resize } = useSize(options)
21
22
  <ClientOnly>
22
23
  <iframe
23
24
  ref="el"
24
- class="video-youtube-iframe"
25
+ class="video-iframe" :class="type"
25
26
  :src="src"
26
- :title="title || 'Youtube'"
27
+ :title="title || type"
27
28
  :style="{ width, height }"
28
29
  :allow="IFRAME_ALLOW"
29
30
  @load="resize"
@@ -32,7 +33,7 @@ const { el, width, height, resize } = useSize(options)
32
33
  </template>
33
34
 
34
35
  <style>
35
- .video-youtube-iframe {
36
+ .video-iframe {
36
37
  width: 100%;
37
38
  margin: 16px auto;
38
39
  border: none;
@@ -186,32 +186,22 @@ interface PDFOptions {
186
186
  }
187
187
  //#endregion
188
188
  //#region src/shared/plot.d.ts
189
+ /**
190
+ * 是否启用 `!! !!` markdown (该标记为非标准标记,脱离插件将不生效)
191
+ */
189
192
  interface PlotOptions {
190
- /**
191
- * 是否启用 `!! !!` markdown (该标记为非标准标记,脱离插件将不生效)
192
- * @default true
193
- */
194
- tag?: boolean;
195
- /**
196
- * 遮罩层颜色
197
- */
198
- mask?: string | {
199
- light: string;
200
- dark: string;
201
- };
202
- /**
203
- * 文本颜色
204
- */
205
- color?: string | {
206
- light: string;
207
- dark: string;
208
- };
209
193
  /**
210
194
  * 触发方式
211
195
  *
212
196
  * @default 'hover'
213
197
  */
214
198
  trigger?: "hover" | "click";
199
+ /**
200
+ * 遮罩层效果
201
+ *
202
+ * @default 'mask'
203
+ */
204
+ effect?: "mask" | "blur";
215
205
  }
216
206
  //#endregion
217
207
  //#region src/shared/codeTree.d.ts
@@ -358,6 +348,14 @@ interface MarkdownPowerPluginOptions {
358
348
  field?: boolean;
359
349
  // video embed
360
350
  /**
351
+ * 是否启用 acfun 视频嵌入
352
+ *
353
+ * `@[acfun](acid)`
354
+ *
355
+ * @default false
356
+ */
357
+ acfun?: boolean;
358
+ /**
361
359
  * 是否启用 bilibili 视频嵌入
362
360
  *
363
361
  * `@[bilibili](bid)`
@@ -486,6 +484,10 @@ interface VideoOptions {
486
484
  bilibili?: boolean;
487
485
  youtube?: boolean;
488
486
  }
487
+ interface AcFunTokenMeta extends SizeOptions {
488
+ title?: string;
489
+ id: string;
490
+ }
489
491
  interface BilibiliTokenMeta extends SizeOptions {
490
492
  title?: string;
491
493
  bvid?: string;
@@ -527,4 +529,4 @@ declare function resolveImageSize(app: App, url: string, remote?: boolean): Prom
527
529
  //#region src/node/plugin.d.ts
528
530
  declare function markdownPowerPlugin(options?: MarkdownPowerPluginOptions): Plugin;
529
531
  //#endregion
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 };
532
+ export { AcFunTokenMeta, 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
@@ -9,7 +9,7 @@ import imageSize from "image-size";
9
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
- import { isLinkHttp as isLinkHttp$1, removeEndingSlash, removeLeadingSlash } from "vuepress/shared";
12
+ import { isLinkHttp as isLinkHttp$1, isLinkWithProtocol, removeEndingSlash, removeLeadingSlash } from "vuepress/shared";
13
13
  import fs$1, { promises } from "node:fs";
14
14
  import process from "node:process";
15
15
  import container from "markdown-it-container";
@@ -17,6 +17,8 @@ import { isPackageExists, resolveModule } from "local-pkg";
17
17
  import { LRUCache } from "lru-cache";
18
18
  import { watch } from "chokidar";
19
19
  import { customAlphabet } from "nanoid";
20
+ import { removeLeadingSlash as removeLeadingSlash$1 } from "@vuepress/shared";
21
+ import { path as path$2 } from "@vuepress/utils";
20
22
  import { attrs } from "@mdit/plugin-attrs";
21
23
  import { footnote } from "@mdit/plugin-footnote";
22
24
  import { mark } from "@mdit/plugin-mark";
@@ -968,7 +970,7 @@ function resolveAttrs(info) {
968
970
  };
969
971
  }
970
972
  function resolveAttr(info, key) {
971
- const pattern = new RegExp(`(?:^|\\s+)${key}(?:=(?<quote>['"])(?<valueWithQuote>.+?)\\k<quote>|=(?<valueWithoutQuote>\\S+))?(?:\\s+|$)`);
973
+ const pattern = /* @__PURE__ */ new RegExp(`(?:^|\\s+)${key}(?:=(?<quote>['"])(?<valueWithQuote>.+?)\\k<quote>|=(?<valueWithoutQuote>\\S+))?(?:\\s+|$)`);
972
974
  const groups = info.match(pattern)?.groups;
973
975
  return groups?.valueWithQuote || groups?.valueWithoutQuote;
974
976
  }
@@ -1113,18 +1115,25 @@ function fetchImageSize(src) {
1113
1115
  for await (const chunk of stream) {
1114
1116
  chunks.push(chunk);
1115
1117
  try {
1116
- const { width: width$1, height: height$1 } = imageSize(Buffer.concat(chunks));
1117
- if (width$1 && height$1) return resolve({
1118
- width: width$1,
1119
- height: height$1
1118
+ const { width, height } = imageSize(Buffer.concat(chunks));
1119
+ if (width && height) return resolve({
1120
+ width,
1121
+ height
1120
1122
  });
1121
1123
  } catch {}
1122
1124
  }
1123
- const { width, height } = imageSize(Buffer.concat(chunks));
1124
- resolve({
1125
- width,
1126
- height
1127
- });
1125
+ try {
1126
+ const { width, height } = imageSize(Buffer.concat(chunks));
1127
+ resolve({
1128
+ width,
1129
+ height
1130
+ });
1131
+ } catch {
1132
+ resolve({
1133
+ width: 0,
1134
+ height: 0
1135
+ });
1136
+ }
1128
1137
  }).on("error", () => resolve({
1129
1138
  width: 0,
1130
1139
  height: 0
@@ -1144,13 +1153,13 @@ async function resolveImageSize(app, url, remote = false) {
1144
1153
  if (isLinkHttp(url) && remote) return await fetchImageSize(url);
1145
1154
  if (url[0] === "/") {
1146
1155
  const filepath$1 = app.dir.public(url.slice(1));
1147
- if (fs.existsSync(filepath$1)) {
1156
+ if (fs.existsSync(filepath$1)) try {
1148
1157
  const { width, height } = imageSize(fs.readFileSync(filepath$1));
1149
1158
  return {
1150
1159
  width,
1151
1160
  height
1152
1161
  };
1153
- }
1162
+ } catch {}
1154
1163
  }
1155
1164
  return {
1156
1165
  width: 0,
@@ -1746,11 +1755,12 @@ function fieldPlugin(md) {
1746
1755
  createContainerPlugin(md, "field", {
1747
1756
  before: (info) => {
1748
1757
  const { attrs: attrs$1 } = resolveAttrs(info);
1749
- const { name, type, required, optional, default: defaultValue } = attrs$1;
1758
+ const { name, type, required, optional, deprecated, default: defaultValue } = attrs$1;
1750
1759
  const props = stringifyAttrs({
1751
1760
  name,
1752
1761
  required,
1753
- optional
1762
+ optional,
1763
+ deprecated
1754
1764
  });
1755
1765
  return `<VPField${props}${!isUndefined(type) ? ` type="${type}"` : ""}${!isUndefined(defaultValue) ? ` default-value="${defaultValue}"` : ""}>`;
1756
1766
  },
@@ -2667,8 +2677,8 @@ function importer(func) {
2667
2677
  //#endregion
2668
2678
  //#region src/node/demo/supports/insertScript.ts
2669
2679
  const SCRIPT_RE$1 = /<script.*?>/;
2670
- function insertSetupScript({ export: name, path: path$2 }, env) {
2671
- const imports = `import ${name ? `${name} from ` : ""}'${path$2}';`;
2680
+ function insertSetupScript({ export: name, path: path$3 }, env) {
2681
+ const imports = `import ${name ? `${name} from ` : ""}'${path$3}';`;
2672
2682
  const scriptSetup = env.sfcBlocks.scriptSetup ??= {
2673
2683
  type: "script",
2674
2684
  content: "<script setup>\n</script>",
@@ -2716,39 +2726,39 @@ const tasks = {};
2716
2726
  const target$2 = "md-power/demo/watcher.txt";
2717
2727
  function demoWatcher(app, watchers) {
2718
2728
  if (!watcher) watcher = watch([], { ignoreInitial: true });
2719
- Object.keys(tasks).forEach((path$2) => {
2720
- watcher.add(path$2);
2729
+ Object.keys(tasks).forEach((path$3) => {
2730
+ watcher.add(path$3);
2721
2731
  });
2722
2732
  const code = readFileSync(app.dir.temp(target$2));
2723
2733
  if (code) {
2724
2734
  const paths = JSON.parse(code || "{}");
2725
- Object.entries(paths).forEach(([path$2, output]) => {
2726
- watcher.add(path$2);
2727
- tasks[path$2] = output;
2735
+ Object.entries(paths).forEach(([path$3, output]) => {
2736
+ watcher.add(path$3);
2737
+ tasks[path$3] = output;
2728
2738
  });
2729
2739
  }
2730
2740
  updateWatchFiles(app);
2731
- watcher.on("change", (path$2) => {
2732
- if (tasks[path$2]) {
2733
- const code$1 = readFileSync(path$2);
2741
+ watcher.on("change", (path$3) => {
2742
+ if (tasks[path$3]) {
2743
+ const code$1 = readFileSync(path$3);
2734
2744
  if (code$1 === false) return;
2735
2745
  const source = parseEmbedCode(code$1);
2736
- compileCode(source, tasks[path$2]);
2746
+ compileCode(source, tasks[path$3]);
2737
2747
  }
2738
2748
  });
2739
- watcher.on("unlink", (path$2) => {
2740
- delete tasks[path$2];
2741
- watcher.unwatch(path$2);
2749
+ watcher.on("unlink", (path$3) => {
2750
+ delete tasks[path$3];
2751
+ watcher.unwatch(path$3);
2742
2752
  });
2743
2753
  watchers.push({ close: () => {
2744
2754
  watcher.close();
2745
2755
  watcher = null;
2746
2756
  } });
2747
2757
  }
2748
- function addTask(app, path$2, output) {
2749
- if (tasks[path$2]) return;
2750
- tasks[path$2] = output;
2751
- if (watcher) watcher.add(path$2);
2758
+ function addTask(app, path$3, output) {
2759
+ if (tasks[path$3]) return;
2760
+ tasks[path$3] = output;
2761
+ if (watcher) watcher.add(path$3);
2752
2762
  updateWatchFiles(app);
2753
2763
  }
2754
2764
  async function updateWatchFiles(app) {
@@ -3161,8 +3171,8 @@ function getContainerMeta(info) {
3161
3171
  function extendsPageWithDemo(page) {
3162
3172
  const markdownEnv = page.markdownEnv;
3163
3173
  const demoFiles = markdownEnv.demoFiles ?? [];
3164
- page.deps.push(...demoFiles.filter(({ type }) => type === "markdown").map(({ path: path$2 }) => path$2));
3165
- (page.frontmatter.gitInclude ??= []).push(...demoFiles.filter(({ gitignore }) => !gitignore).map(({ path: path$2 }) => path$2));
3174
+ page.deps.push(...demoFiles.filter(({ type }) => type === "markdown").map(({ path: path$3 }) => path$3));
3175
+ (page.frontmatter.gitInclude ??= []).push(...demoFiles.filter(({ gitignore }) => !gitignore).map(({ path: path$3 }) => path$3));
3166
3176
  }
3167
3177
 
3168
3178
  //#endregion
@@ -3429,6 +3439,39 @@ const pdfPlugin = (md) => {
3429
3439
  });
3430
3440
  };
3431
3441
 
3442
+ //#endregion
3443
+ //#region src/node/embed/video/acfun.ts
3444
+ const AC_FUN_LINK = "https://www.acfun.cn/player";
3445
+ const acfunPlugin = (md) => {
3446
+ createEmbedRuleBlock(md, {
3447
+ type: "acfun",
3448
+ name: "video_acfun",
3449
+ syntaxPattern: /^@\[acfun([^\]]*)\]\(([^)]*)\)/,
3450
+ meta([, info, id]) {
3451
+ const { attrs: attrs$1 } = resolveAttrs(info);
3452
+ return {
3453
+ id,
3454
+ title: attrs$1.title || "AcFun",
3455
+ width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
3456
+ height: attrs$1.height ? parseRect(attrs$1.height) : void 0,
3457
+ ratio: attrs$1.ratio ?? "16:10"
3458
+ };
3459
+ },
3460
+ content(meta) {
3461
+ const { id, width, height, ratio, title } = meta;
3462
+ const src = `${AC_FUN_LINK}/${id}`;
3463
+ return `<VPVideoEmbed${stringifyAttrs({
3464
+ src,
3465
+ width,
3466
+ height,
3467
+ ratio,
3468
+ title,
3469
+ type: "acfun"
3470
+ })} />`;
3471
+ }
3472
+ });
3473
+ };
3474
+
3432
3475
  //#endregion
3433
3476
  //#region src/node/embed/video/artPlayer.ts
3434
3477
  const installed = {
@@ -3533,10 +3576,10 @@ const bilibiliPlugin = (md) => {
3533
3576
  cid,
3534
3577
  autoplay: attrs$1.autoplay ?? false,
3535
3578
  time: timeToSeconds(attrs$1.time),
3536
- title: attrs$1.title,
3579
+ title: attrs$1.title || "Bilibili",
3537
3580
  width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
3538
3581
  height: attrs$1.height ? parseRect(attrs$1.height) : void 0,
3539
- ratio: attrs$1.ratio ? parseRect(attrs$1.ratio) : void 0
3582
+ ratio: attrs$1.ratio
3540
3583
  };
3541
3584
  },
3542
3585
  content(meta) {
@@ -3548,14 +3591,15 @@ const bilibiliPlugin = (md) => {
3548
3591
  if (meta.time) params.set("t", meta.time.toString());
3549
3592
  params.set("autoplay", meta.autoplay ? "1" : "0");
3550
3593
  params.set("high_quality", "1");
3551
- const source = `${BILIBILI_LINK}?${params.toString()}`;
3594
+ const src = `${BILIBILI_LINK}?${params.toString()}`;
3552
3595
  const { width, height, ratio, title } = meta;
3553
- return `<VideoBilibili${stringifyAttrs({
3554
- src: source,
3596
+ return `<VPVideoEmbed${stringifyAttrs({
3597
+ src,
3555
3598
  width,
3556
3599
  height,
3557
3600
  ratio,
3558
- title
3601
+ title,
3602
+ type: "bilibili"
3559
3603
  })} />`;
3560
3604
  }
3561
3605
  });
@@ -3577,10 +3621,10 @@ const youtubePlugin = (md) => {
3577
3621
  loop: attrs$1.loop ?? false,
3578
3622
  start: timeToSeconds(attrs$1.start),
3579
3623
  end: timeToSeconds(attrs$1.end),
3580
- title: attrs$1.title,
3624
+ title: attrs$1.title || "YouTube",
3581
3625
  width: attrs$1.width ? parseRect(attrs$1.width) : "100%",
3582
3626
  height: attrs$1.height ? parseRect(attrs$1.height) : void 0,
3583
- ratio: attrs$1.ratio ? parseRect(attrs$1.ratio) : void 0
3627
+ ratio: attrs$1.ratio
3584
3628
  };
3585
3629
  },
3586
3630
  content(meta) {
@@ -3589,14 +3633,15 @@ const youtubePlugin = (md) => {
3589
3633
  if (meta.loop) params.set("loop", "1");
3590
3634
  if (meta.start) params.set("start", meta.start.toString());
3591
3635
  if (meta.end) params.set("end", meta.end.toString());
3592
- const source = `${YOUTUBE_LINK}/${meta.id}?${params.toString()}`;
3636
+ const src = `${YOUTUBE_LINK}/${meta.id}?${params.toString()}`;
3593
3637
  const { width, height, ratio, title } = meta;
3594
- return `<VideoYoutube${stringifyAttrs({
3595
- src: source,
3638
+ return `<VPVideoEmbed${stringifyAttrs({
3639
+ src,
3596
3640
  width,
3597
3641
  height,
3598
3642
  ratio,
3599
- title
3643
+ title,
3644
+ type: "youtube"
3600
3645
  })} />`;
3601
3646
  }
3602
3647
  });
@@ -3611,6 +3656,7 @@ function embedSyntaxPlugin(md, options) {
3611
3656
  legacyCaniuse(md, caniuse);
3612
3657
  }
3613
3658
  if (options.pdf) md.use(pdfPlugin);
3659
+ if (options.acfun) md.use(acfunPlugin);
3614
3660
  if (options.bilibili) md.use(bilibiliPlugin);
3615
3661
  if (options.youtube) md.use(youtubePlugin);
3616
3662
  if (options.artPlayer) md.use(artPlayerPlugin);
@@ -3655,7 +3701,7 @@ function parseSource(source) {
3655
3701
  };
3656
3702
  else {
3657
3703
  const end = source.indexOf(`\n${char}`);
3658
- const len = char.length + 1;
3704
+ const len = 4;
3659
3705
  return {
3660
3706
  matter: source.slice(0, end + len),
3661
3707
  content: source.slice(end + len)
@@ -3663,6 +3709,81 @@ function parseSource(source) {
3663
3709
  }
3664
3710
  }
3665
3711
 
3712
+ //#endregion
3713
+ //#region src/node/enhance/links.ts
3714
+ function linksPlugin(md) {
3715
+ const externalAttrs = {
3716
+ target: "_blank",
3717
+ rel: "noopener noreferrer"
3718
+ };
3719
+ let hasOpenInternalLink = false;
3720
+ const internalTag = "VPLink";
3721
+ function handleLinkOpen(tokens, idx, env) {
3722
+ hasOpenInternalLink = false;
3723
+ const token = tokens[idx];
3724
+ const hrefIndex = token.attrIndex("href");
3725
+ /* istanbul ignore if -- @preserve */
3726
+ if (hrefIndex < 0) return;
3727
+ const hrefAttr = token.attrs[hrefIndex];
3728
+ const hrefLink = hrefAttr[1];
3729
+ if (isLinkWithProtocol(hrefLink)) {
3730
+ Object.entries(externalAttrs).forEach(([key, val]) => {
3731
+ token.attrSet(key, val);
3732
+ });
3733
+ return;
3734
+ }
3735
+ if (hrefLink[0] === "#") return;
3736
+ hasOpenInternalLink = true;
3737
+ token.tag = internalTag;
3738
+ const matched = hrefLink.match(/^([^#?]*?(?:\/|\.md|\.html))([#?].*)?$/);
3739
+ if (matched) {
3740
+ const rawPath = matched[1];
3741
+ const { absolutePath, relativePath } = resolvePaths(rawPath, env.base || "/", env.filePathRelative ?? null);
3742
+ (env.links ??= []).push({
3743
+ raw: rawPath,
3744
+ absolute: absolutePath,
3745
+ relative: relativePath
3746
+ });
3747
+ }
3748
+ }
3749
+ md.renderer.rules.link_open = (tokens, idx, opts, env, self) => {
3750
+ handleLinkOpen(tokens, idx, env);
3751
+ return self.renderToken(tokens, idx, opts);
3752
+ };
3753
+ md.renderer.rules.link_close = (tokens, idx, opts, _env, self) => {
3754
+ if (hasOpenInternalLink) {
3755
+ hasOpenInternalLink = false;
3756
+ tokens[idx].tag = internalTag;
3757
+ }
3758
+ return self.renderToken(tokens, idx, opts);
3759
+ };
3760
+ }
3761
+ /**
3762
+ * Resolve relative and absolute paths according to the `base` and `filePathRelative`
3763
+ */
3764
+ function resolvePaths(rawPath, base, filePathRelative) {
3765
+ let absolutePath;
3766
+ let relativePath;
3767
+ if (rawPath.startsWith("/")) if (rawPath.endsWith(".md")) {
3768
+ absolutePath = path$2.join(base, rawPath);
3769
+ relativePath = removeLeadingSlash$1(rawPath);
3770
+ } else {
3771
+ absolutePath = rawPath;
3772
+ relativePath = path$2.relative(base, absolutePath);
3773
+ }
3774
+ else if (filePathRelative) {
3775
+ relativePath = path$2.join(path$2.dirname(encodeURI(filePathRelative)), rawPath);
3776
+ absolutePath = path$2.join(base, relativePath);
3777
+ } else {
3778
+ relativePath = rawPath.replace(/^(?:\.\/)?(.*)$/, "$1");
3779
+ absolutePath = null;
3780
+ }
3781
+ return {
3782
+ absolutePath,
3783
+ relativePath
3784
+ };
3785
+ }
3786
+
3666
3787
  //#endregion
3667
3788
  //#region src/node/icon/createIconRule.ts
3668
3789
  function createIconRule([l1, l2, r1, r2], deprecated) {
@@ -3878,7 +3999,7 @@ const abbrPlugin = (md) => {
3878
3999
  const { abbreviations } = state.env;
3879
4000
  if (!abbreviations) return;
3880
4001
  const abbreviationsRegExpText = Object.keys(abbreviations).map((x) => x.substring(1)).sort((a, b) => b.length - a.length).map(escapeRE).join("|");
3881
- const regexpSimple = new RegExp(`(?:${abbreviationsRegExpText})`);
4002
+ const regexpSimple = /* @__PURE__ */ new RegExp(`(?:${abbreviationsRegExpText})`);
3882
4003
  const regExp = new RegExp(`(^|${WORDING_REGEXP_TEXT})(${abbreviationsRegExpText})($|${WORDING_REGEXP_TEXT})`, "g");
3883
4004
  for (const token of tokens) {
3884
4005
  if (token.type !== "inline") continue;
@@ -4024,18 +4145,18 @@ const plotDef = (state, silent) => {
4024
4145
  const content = state.src.slice(start + 2, state.pos);
4025
4146
  state.posMax = state.pos;
4026
4147
  state.pos = start + 2;
4027
- const token = state.push("plot_inline", "Plot", 0);
4028
- token.markup = "!!";
4029
- token.content = content;
4148
+ const openToken = state.push("plot_inline_open", "Plot", 1);
4149
+ openToken.markup = "!!";
4150
+ openToken.content = content;
4151
+ const contentToken = state.push("text", "", 0);
4152
+ contentToken.content = content;
4153
+ const closeToken = state.push("plot_inline_close", "Plot", -1);
4154
+ closeToken.markup = "!!";
4030
4155
  state.pos = state.posMax + 2;
4031
4156
  state.posMax = max;
4032
4157
  return true;
4033
4158
  };
4034
4159
  const plotPlugin = (md) => {
4035
- md.renderer.rules.plot_inline = (tokens, idx) => {
4036
- const token = tokens[idx];
4037
- return `<Plot>${token.content}</Plot>`;
4038
- };
4039
4160
  md.inline.ruler.before("emphasis", "plot", plotDef);
4040
4161
  };
4041
4162
 
@@ -4081,13 +4202,9 @@ async function prepareConfigFile(app, options) {
4081
4202
  imports.add(`import PDFViewer from '${CLIENT_FOLDER}components/PDFViewer.vue'`);
4082
4203
  enhances.add(`app.component('PDFViewer', PDFViewer)`);
4083
4204
  }
4084
- if (options.bilibili) {
4085
- imports.add(`import Bilibili from '${CLIENT_FOLDER}components/Bilibili.vue'`);
4086
- enhances.add(`app.component('VideoBilibili', Bilibili)`);
4087
- }
4088
- if (options.youtube) {
4089
- imports.add(`import Youtube from '${CLIENT_FOLDER}components/Youtube.vue'`);
4090
- enhances.add(`app.component('VideoYoutube', Youtube)`);
4205
+ if (options.acfun || options.bilibili || options.youtube) {
4206
+ imports.add(`import VPVideoEmbed from '${CLIENT_FOLDER}components/VPVideoEmbed.vue'`);
4207
+ enhances.add(`app.component('VPVideoEmbed', VPVideoEmbed)`);
4091
4208
  }
4092
4209
  if (options.codepen) {
4093
4210
  imports.add(`import CodePen from '${CLIENT_FOLDER}components/CodePen.vue'`);
@@ -4224,6 +4341,7 @@ function markdownPowerPlugin(options = {}) {
4224
4341
  ]);
4225
4342
  },
4226
4343
  extendsMarkdown: async (md, app) => {
4344
+ linksPlugin(md);
4227
4345
  docsTitlePlugin(md);
4228
4346
  embedSyntaxPlugin(md, options);
4229
4347
  inlineSyntaxPlugin(md, options);
@@ -184,32 +184,22 @@ interface PDFOptions {
184
184
  }
185
185
  //#endregion
186
186
  //#region src/shared/plot.d.ts
187
+ /**
188
+ * 是否启用 `!! !!` markdown (该标记为非标准标记,脱离插件将不生效)
189
+ */
187
190
  interface PlotOptions {
188
- /**
189
- * 是否启用 `!! !!` markdown (该标记为非标准标记,脱离插件将不生效)
190
- * @default true
191
- */
192
- tag?: boolean;
193
- /**
194
- * 遮罩层颜色
195
- */
196
- mask?: string | {
197
- light: string;
198
- dark: string;
199
- };
200
- /**
201
- * 文本颜色
202
- */
203
- color?: string | {
204
- light: string;
205
- dark: string;
206
- };
207
191
  /**
208
192
  * 触发方式
209
193
  *
210
194
  * @default 'hover'
211
195
  */
212
196
  trigger?: "hover" | "click";
197
+ /**
198
+ * 遮罩层效果
199
+ *
200
+ * @default 'mask'
201
+ */
202
+ effect?: "mask" | "blur";
213
203
  }
214
204
  //#endregion
215
205
  //#region src/shared/codeTree.d.ts
@@ -356,6 +346,14 @@ interface MarkdownPowerPluginOptions {
356
346
  field?: boolean;
357
347
  // video embed
358
348
  /**
349
+ * 是否启用 acfun 视频嵌入
350
+ *
351
+ * `@[acfun](acid)`
352
+ *
353
+ * @default false
354
+ */
355
+ acfun?: boolean;
356
+ /**
359
357
  * 是否启用 bilibili 视频嵌入
360
358
  *
361
359
  * `@[bilibili](bid)`
@@ -484,6 +482,10 @@ interface VideoOptions {
484
482
  bilibili?: boolean;
485
483
  youtube?: boolean;
486
484
  }
485
+ interface AcFunTokenMeta extends SizeOptions {
486
+ title?: string;
487
+ id: string;
488
+ }
487
489
  interface BilibiliTokenMeta extends SizeOptions {
488
490
  title?: string;
489
491
  bvid?: string;
@@ -512,4 +514,4 @@ interface ArtPlayerTokenMeta extends SizeOptions {
512
514
  type?: string;
513
515
  }
514
516
  //#endregion
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 };
517
+ export { AcFunTokenMeta, 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.153",
4
+ "version": "1.0.0-rc.155",
5
5
  "description": "The Plugin for VuePress 2 - markdown power",
6
6
  "author": "pengzhanbo <volodymyr@foxmail.com>",
7
7
  "license": "MIT",
@@ -39,8 +39,8 @@
39
39
  "markdown-it": "^14.1.0",
40
40
  "mpegts.js": "^1.7.3",
41
41
  "pyodide": "^0.27.7",
42
- "sass": "^1.89.1",
43
- "sass-embedded": "^1.89.1",
42
+ "sass": "^1.89.2",
43
+ "sass-embedded": "^1.89.2",
44
44
  "stylus": "^0.64.0",
45
45
  "vuepress": "2.0.0-rc.23"
46
46
  },
@@ -54,6 +54,9 @@
54
54
  "hls.js": {
55
55
  "optional": true
56
56
  },
57
+ "less": {
58
+ "optional": true
59
+ },
57
60
  "markdown-it": {
58
61
  "optional": true
59
62
  },
@@ -62,30 +65,39 @@
62
65
  },
63
66
  "pyodide": {
64
67
  "optional": true
68
+ },
69
+ "sass": {
70
+ "optional": true
71
+ },
72
+ "sass-embedded": {
73
+ "optional": true
74
+ },
75
+ "stylus": {
76
+ "optional": true
65
77
  }
66
78
  },
67
79
  "dependencies": {
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",
80
+ "@mdit/plugin-attrs": "^0.23.1",
81
+ "@mdit/plugin-footnote": "^0.22.2",
82
+ "@mdit/plugin-mark": "^0.22.1",
83
+ "@mdit/plugin-sub": "^0.22.1",
84
+ "@mdit/plugin-sup": "^0.22.1",
85
+ "@mdit/plugin-tab": "^0.22.2",
86
+ "@mdit/plugin-tasklist": "^0.22.1",
75
87
  "@pengzhanbo/utils": "^2.1.0",
76
- "@vuepress/helper": "2.0.0-rc.108",
77
- "@vueuse/core": "^13.3.0",
78
- "chokidar": "3.6.0",
88
+ "@vuepress/helper": "2.0.0-rc.110",
89
+ "@vueuse/core": "^13.4.0",
90
+ "chokidar": "4.0.3",
79
91
  "image-size": "^2.0.2",
80
92
  "local-pkg": "^1.1.1",
81
93
  "lru-cache": "^11.1.0",
82
94
  "markdown-it-container": "^4.0.0",
83
95
  "nanoid": "^5.1.5",
84
- "shiki": "^3.6.0",
96
+ "shiki": "^3.7.0",
85
97
  "tinyglobby": "0.2.13",
86
98
  "tm-grammars": "^1.23.26",
87
99
  "tm-themes": "^1.10.6",
88
- "vue": "^3.5.16"
100
+ "vue": "^3.5.17"
89
101
  },
90
102
  "devDependencies": {
91
103
  "@types/markdown-it": "^14.1.2",
@@ -1,45 +0,0 @@
1
- <script setup lang="ts">
2
- import { toRefs } from 'vue'
3
- import { useSize } from '../composables/size.js'
4
-
5
- const props = defineProps<{
6
- src: string
7
- title: string
8
- width?: string
9
- height?: string
10
- ratio?: string
11
- }>()
12
-
13
- const IFRAME_ALLOW = 'accelerometer; autoplay; clipboard-write; encrypted-media; fullscreen; gyroscope; picture-in-picture'
14
-
15
- const options = toRefs(props)
16
-
17
- const { el, width, height, resize } = useSize(options)
18
-
19
- function onLoad() {
20
- resize()
21
- }
22
- </script>
23
-
24
- <template>
25
- <ClientOnly>
26
- <iframe
27
- ref="el"
28
- class="video_bilibili_iframe"
29
- :src="src"
30
- :title="title || 'Bilibili'"
31
- :style="{ width, height }"
32
- :allow="IFRAME_ALLOW"
33
- @load="onLoad"
34
- />
35
- </ClientOnly>
36
- </template>
37
-
38
- <style>
39
- .video_bilibili_iframe {
40
- width: 100%;
41
- margin: 16px auto;
42
- border: none;
43
- border-radius: 5px;
44
- }
45
- </style>