vuepress-plugin-md-power 1.0.0-rc.180 → 1.0.0-rc.182

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.
@@ -97,8 +97,6 @@ function runCode() {
97
97
 
98
98
  .code-repl-output {
99
99
  position: relative;
100
- top: -20px;
101
- padding-top: 6px;
102
100
  margin: 0 -1.5rem;
103
101
  background-color: var(--vp-code-block-bg);
104
102
  transition: background-color var(--vp-t-color);
@@ -0,0 +1,228 @@
1
+ <script setup lang="ts">
2
+ import type { QRCodeToDataURLOptions, QRCodeToStringOptions } from 'qrcode'
3
+ import type { QRCodeProps } from '../../shared/index.js'
4
+ import { isLinkWithProtocol } from '@vuepress/helper/client'
5
+ import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
6
+ import { resolveRoute, usePage, withBase } from 'vuepress/client'
7
+
8
+ const { title, text, mode, align = 'left', reverse = false, svg = false, width, level, version, mask, margin = 2, scale = 4, light, dark } = defineProps<QRCodeProps>()
9
+
10
+ const page = usePage()
11
+
12
+ let qr: typeof import('qrcode') | null = null
13
+
14
+ const qrcode = ref('')
15
+ const parsedText = ref('')
16
+ const isLink = ref(false)
17
+
18
+ const styles = computed(() => {
19
+ const size = typeof width === 'number' ? width : width ? Number.parseInt(width) : undefined
20
+ return size ? { '--vp-qrcode-size': `${size}px` } : undefined
21
+ })
22
+
23
+ function parseText(): string | void {
24
+ isLink.value = false
25
+ if (!text || __VUEPRESS_SSR__)
26
+ return ''
27
+
28
+ if (text === '.') {
29
+ isLink.value = true
30
+ return location.href.split(/[?#]/)[0]
31
+ }
32
+
33
+ if (isLinkWithProtocol(text)) {
34
+ isLink.value = true
35
+ return text.startsWith('//') ? `${location.protocol}${text}` : text
36
+ }
37
+
38
+ if (text.startsWith('/') || text.startsWith('./')) {
39
+ const [routePath, ...rest] = text.split(/([?#])/)
40
+ const currentPath = page.value.filePathRelative ? `/${page.value.filePathRelative}` : undefined
41
+ const { notFound, path } = resolveRoute(routePath, currentPath)
42
+ if (notFound) {
43
+ return text
44
+ }
45
+ isLink.value = true
46
+ return new URL(`${withBase(path)}${rest.join('')}`, location.href).toString()
47
+ }
48
+
49
+ return text
50
+ }
51
+
52
+ onMounted(async () => {
53
+ const callback = (_: any, url: string) => qrcode.value = url
54
+
55
+ watch(
56
+ () => [text, svg, level, version, mask, margin, scale, light, dark],
57
+ async () => {
58
+ const text = parseText()
59
+ parsedText.value = text || ''
60
+ if (!text) {
61
+ qrcode.value = ''
62
+ return
63
+ }
64
+
65
+ qr ??= (await import(/* webpackChunkName: "qrcode" */ 'qrcode')).default
66
+ const opts: QRCodeToDataURLOptions & QRCodeToStringOptions = {
67
+ version,
68
+ maskPattern: mask,
69
+ errorCorrectionLevel: (level ? level.toUpperCase() : 'M') as any,
70
+ width: 300 * Math.round(window.devicePixelRatio || 1),
71
+ margin,
72
+ scale,
73
+ color: { dark, light },
74
+ }
75
+
76
+ if (svg)
77
+ qr.toString(text, { type: 'svg', ...opts }, callback)
78
+ else
79
+ qr.toDataURL(text, { type: 'image/png', ...opts }, callback)
80
+ },
81
+ { immediate: true },
82
+ )
83
+ })
84
+
85
+ onUnmounted(() => {
86
+ qr = null
87
+ })
88
+ </script>
89
+
90
+ <template>
91
+ <div v-if="qrcode" class="vp-qrcode" :class="{ card: mode === 'card', reverse, [align]: true }">
92
+ <div class="qrcode-content">
93
+ <div v-if="svg" class="qrcode-svg" :style="styles" :title="parsedText" v-html="qrcode" />
94
+ <img v-else class="qrcode-img" :src="qrcode" :alt="parsedText" :title="parsedText" :style="styles">
95
+ <div v-if="title && mode !== 'card'" class="qrcode-label">
96
+ {{ title }}
97
+ </div>
98
+ </div>
99
+
100
+ <div v-if="mode === 'card'" class="qrcode-info">
101
+ <p v-if="title" class="qrcode-title">
102
+ {{ title }}
103
+ </p>
104
+ <p v-if="parsedText">
105
+ <a v-if="isLink" :href="parsedText" rel="noopener noreferrer" target="_blank">
106
+ {{ parsedText }}
107
+ </a>
108
+ <span v-else v-html="parsedText.replaceAll('\n', '<br>')" />
109
+ </p>
110
+ </div>
111
+ </div>
112
+ </template>
113
+
114
+ <style scoped>
115
+ .vp-qrcode {
116
+ --vp-qrcode-size: 128px;
117
+
118
+ margin: 16px 0;
119
+ overflow: hidden;
120
+ }
121
+
122
+ @media (min-width: 768px) {
123
+ .vp-qrcode {
124
+ --vp-qrcode-size: 150px;
125
+ }
126
+ }
127
+
128
+ .vp-qrcode:not(.card).center {
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ }
133
+
134
+ .vp-qrcode:not(.card).right {
135
+ display: flex;
136
+ align-items: center;
137
+ justify-content: flex-end;
138
+ }
139
+
140
+ .vp-qrcode .qrcode-content {
141
+ display: flex;
142
+ flex-direction: column;
143
+ gap: 8px;
144
+ align-items: center;
145
+ justify-content: center;
146
+ width: max-content;
147
+ max-width: 100%;
148
+ overflow: hidden;
149
+ }
150
+
151
+ .vp-qrcode .qrcode-label {
152
+ font-size: 14px;
153
+ color: var(--vp-c-text-2);
154
+ text-align: center;
155
+ word-break: break-all;
156
+ }
157
+
158
+ .vp-qrcode.card {
159
+ display: flex;
160
+ flex-direction: column;
161
+ gap: 8px;
162
+ align-items: center;
163
+ justify-content: center;
164
+ padding: 16px 20px;
165
+ background-color: var(--vp-c-bg-soft);
166
+ border-radius: 8px;
167
+ }
168
+
169
+ .vp-qrcode .qrcode-svg,
170
+ .vp-qrcode .qrcode-img {
171
+ width: var(--vp-qrcode-size);
172
+ max-width: 100%;
173
+ height: var(--vp-qrcode-size);
174
+ aspect-ratio: 1/1;
175
+ }
176
+
177
+ .vp-qrcode .qrcode-svg :deep(svg) {
178
+ max-width: 100%;
179
+ max-height: 100%;
180
+ }
181
+
182
+ .vp-qrcode .qrcode-info {
183
+ display: flex;
184
+ flex: 1;
185
+ flex-direction: column;
186
+ min-width: 0;
187
+ text-align: center;
188
+ }
189
+
190
+ .vp-qrcode .qrcode-info > p {
191
+ margin: 0;
192
+ word-break: break-all;
193
+ }
194
+
195
+ .vp-qrcode .qrcode-info .qrcode-title {
196
+ font-weight: 600;
197
+ }
198
+
199
+ @media (min-width: 960px) {
200
+ .vp-qrcode.card {
201
+ flex-direction: row;
202
+ gap: 16px;
203
+ align-items: flex-start;
204
+ justify-content: flex-start;
205
+ }
206
+
207
+ .vp-qrcode.card .qrcode-info {
208
+ align-self: center;
209
+ text-align: left;
210
+ }
211
+
212
+ .vp-qrcode.card:where(.reverse, .right) {
213
+ flex-direction: row-reverse;
214
+ }
215
+
216
+ .vp-qrcode.card:where(.reverse, .right) .qrcode-info {
217
+ text-align: right;
218
+ }
219
+
220
+ .vp-qrcode.card.center {
221
+ align-items: center;
222
+ }
223
+
224
+ .vp-qrcode.card.center .qrcode-info {
225
+ flex: initial;
226
+ }
227
+ }
228
+ </style>
@@ -1,13 +1,11 @@
1
- import { onBeforeUnmount, onMounted } from "vue";
2
- import { onContentUpdated, useRouter } from "vuepress/client";
1
+ import { onContentUpdated } from "vuepress/client";
3
2
 
4
3
  //#region src/client/composables/mark.ts
5
4
  const MARK_MODE_ATTR = "data-mark-mode";
6
5
  const MARK_MODE_LAZY = "lazy";
7
6
  const MARK_VISIBLE_CLASS = "vp-mark-visible";
8
7
  const MARK_BOUND_ATTR = "data-vp-mark-bound";
9
- const MARK_SELECTOR = ".vp-doc mark";
10
- const DOC_SELECTOR = ".vp-doc";
8
+ const MARK_SELECTOR = "mark";
11
9
  const BOUND_SELECTOR = `${MARK_SELECTOR}[${MARK_BOUND_ATTR}="1"]`;
12
10
  function setupMarkHighlight(mode) {
13
11
  if (typeof window === "undefined" || __VUEPRESS_SSR__) return;
@@ -18,9 +16,7 @@ function setupMarkHighlight(mode) {
18
16
  }
19
17
  root.setAttribute(MARK_MODE_ATTR, MARK_MODE_LAZY);
20
18
  let intersectionObserver = null;
21
- let mutationObserver = null;
22
19
  let rafId = null;
23
- let removeAfterEach = null;
24
20
  const ensureObserver = () => {
25
21
  if (!intersectionObserver) intersectionObserver = new IntersectionObserver((entries, obs) => {
26
22
  for (const entry of entries) {
@@ -57,51 +53,18 @@ function setupMarkHighlight(mode) {
57
53
  bindMarks();
58
54
  });
59
55
  };
60
- const observeDocMutations = () => {
61
- const doc = document.querySelector(DOC_SELECTOR);
62
- if (!doc) return;
63
- if (mutationObserver) mutationObserver.disconnect();
64
- mutationObserver = new MutationObserver((mutations) => {
65
- if (mutations.some((mutation) => mutation.addedNodes.length > 0)) scheduleBind();
66
- });
67
- mutationObserver.observe(doc, {
68
- childList: true,
69
- subtree: true
70
- });
71
- };
72
56
  const resetObserver = () => {
73
- document.querySelectorAll(BOUND_SELECTOR).forEach((mark) => {
57
+ if (!intersectionObserver) return;
58
+ intersectionObserver.disconnect();
59
+ intersectionObserver = null;
60
+ Array.from(document.querySelectorAll(BOUND_SELECTOR) || []).forEach((mark) => {
74
61
  if (!mark.classList.contains(MARK_VISIBLE_CLASS)) mark.removeAttribute(MARK_BOUND_ATTR);
75
62
  });
76
- if (intersectionObserver) {
77
- intersectionObserver.disconnect();
78
- intersectionObserver = null;
79
- }
80
63
  };
81
- const router = useRouter();
82
- onMounted(() => {
83
- observeDocMutations();
84
- scheduleBind();
85
- });
86
64
  onContentUpdated(() => {
87
65
  resetObserver();
88
- observeDocMutations();
89
66
  scheduleBind();
90
67
  });
91
- if (router?.afterEach) removeAfterEach = router.afterEach(() => {
92
- resetObserver();
93
- observeDocMutations();
94
- scheduleBind();
95
- });
96
- if (router?.isReady) router.isReady().then(() => scheduleBind()).catch(() => {});
97
- onBeforeUnmount(() => {
98
- if (rafId !== null) cancelAnimationFrame(rafId);
99
- resetObserver();
100
- mutationObserver?.disconnect();
101
- mutationObserver = null;
102
- removeAfterEach?.();
103
- removeAfterEach = null;
104
- });
105
68
  }
106
69
 
107
70
  //#endregion
@@ -501,6 +501,12 @@ interface MarkdownPowerPluginOptions {
501
501
  * @default false
502
502
  */
503
503
  table?: boolean | TableContainerOptions;
504
+ /**
505
+ * 是否启用 二维码 嵌入语法
506
+ *
507
+ * @default false
508
+ */
509
+ qrcode?: boolean;
504
510
  /**
505
511
  * 是否启用 自动填充 图片宽高属性
506
512
  *
@@ -521,6 +527,89 @@ interface MarkdownPowerPluginOptions {
521
527
  imageSize?: boolean | 'local' | 'all';
522
528
  }
523
529
  //#endregion
530
+ //#region src/shared/qrcode.d.ts
531
+ interface QRCodeMeta extends QRCodeProps {
532
+ /**
533
+ * mode: 'card' 的别名
534
+ */
535
+ card?: boolean;
536
+ }
537
+ interface QRCodeProps {
538
+ /**
539
+ * 二维码标题
540
+ * 作为 HTML 标签的 `title` 属性、`alt` 属性
541
+ */
542
+ title?: string;
543
+ /**
544
+ * 二维码内容
545
+ */
546
+ text?: string;
547
+ /**
548
+ * 二维码宽度
549
+ */
550
+ width?: number | string;
551
+ /**
552
+ * 显示模式
553
+ * - img: 以图片的形式显示二维码
554
+ * - card: 以卡片的形式显示,卡片以左右布局,左侧二维码,右侧 标题 + 内容
555
+ * @default 'img'
556
+ */
557
+ mode?: 'img' | 'card';
558
+ /**
559
+ * 在 card 模式下是否翻转布局
560
+ */
561
+ reverse?: boolean;
562
+ /**
563
+ * 二维码的对齐方式
564
+ * @default 'left'
565
+ */
566
+ align?: 'left' | 'center' | 'right';
567
+ /**
568
+ * 是否渲染为 SVG 格式的二维码
569
+ * 默认输出为 PNG 格式的 dataURL
570
+ * @default false
571
+ */
572
+ svg?: boolean;
573
+ /**
574
+ * 纠错等级。
575
+ * 可能的取值为低、中、四分位、高,分别对应 L、M、Q、H。
576
+ * @default 'M'
577
+ */
578
+ level?: 'L' | 'M' | 'Q' | 'H' | 'l' | 'm' | 'q' | 'h';
579
+ /**
580
+ * 二维码版本。若未指定,将自动计算更合适的值。
581
+ * 取值范围 1-40
582
+ */
583
+ version?: number;
584
+ /**
585
+ * 用于遮蔽符号的掩码模式。
586
+ * 可能的取值为0、1、2、3、4、5、6、7。
587
+ * 若未指定,系统将自动计算更合适的值。
588
+ */
589
+ mask?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
590
+ /**
591
+ * 定义静区应有多宽。
592
+ * @default 4
593
+ */
594
+ margin?: number;
595
+ /**
596
+ * 缩放因子。值为1表示每个模块(黑点)对应1像素。
597
+ */
598
+ scale?: number;
599
+ /**
600
+ * 暗色模块的颜色。值必须为十六进制格式(RGBA)。
601
+ * 注意:暗色应始终比浅色模块的颜色更深。
602
+ * @default '#000000ff'
603
+ */
604
+ light?: string;
605
+ /**
606
+ * 亮色模块的颜色。值必须为十六进制格式(RGBA)。
607
+ * 注意:亮色应始终比暗色模块的颜色更浅。
608
+ * @default '#ffffffff'
609
+ */
610
+ dark?: string;
611
+ }
612
+ //#endregion
524
613
  //#region src/shared/replit.d.ts
525
614
  interface ReplitTokenMeta extends SizeOptions {
526
615
  title?: string;
@@ -578,4 +667,4 @@ declare function resolveImageSize(app: App, url: string, remote?: boolean): Prom
578
667
  //#region src/node/plugin.d.ts
579
668
  declare function markdownPowerPlugin(options?: MarkdownPowerPluginOptions): Plugin;
580
669
  //#endregion
581
- 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 };
670
+ 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, QRCodeMeta, QRCodeProps, ReplEditorData, ReplOptions, ReplitTokenMeta, SizeOptions, ThemeOptions, VideoOptions, YoutubeTokenMeta, createCodeTabIconGetter, markdownPowerPlugin, resolveImageSize };
package/lib/node/index.js CHANGED
@@ -24,6 +24,7 @@ import { mark } from "@mdit/plugin-mark";
24
24
  import { sub } from "@mdit/plugin-sub";
25
25
  import { sup } from "@mdit/plugin-sup";
26
26
  import { tasklist } from "@mdit/plugin-tasklist";
27
+ import cjsFriendly from "markdown-it-cjk-friendly";
27
28
 
28
29
  //#region src/node/fileIcons/definitions.ts
29
30
  const defaultFolder = "vscode-icons:default-folder";
@@ -1776,11 +1777,12 @@ function parseFileTreeRawContent(content) {
1776
1777
  children: []
1777
1778
  };
1778
1779
  const stack = [root];
1779
- const lines = content.trim().split("\n");
1780
+ const lines = content.trimEnd().split("\n");
1781
+ const spaceLength = lines[0].match(/^\s*/)?.[0].length ?? 0;
1780
1782
  for (const line of lines) {
1781
1783
  const match = line.match(/^(\s*)-(.*)$/);
1782
1784
  if (!match) continue;
1783
- const level = Math.floor(match[1].length / 2);
1785
+ const level = Math.floor((match[1].length - spaceLength) / 2);
1784
1786
  const info = match[2].trim();
1785
1787
  while (stack.length > 0 && stack[stack.length - 1].level >= level) stack.pop();
1786
1788
  const parent = stack[stack.length - 1];
@@ -3496,6 +3498,36 @@ const pdfPlugin = (md) => {
3496
3498
  });
3497
3499
  };
3498
3500
 
3501
+ //#endregion
3502
+ //#region src/node/embed/qrcode.ts
3503
+ const qrcodePlugin = (md) => {
3504
+ createEmbedRuleBlock(md, {
3505
+ type: "qrcode",
3506
+ syntaxPattern: /^@\[qrcode([^\]]*)\]\(([^)]*)\)/,
3507
+ meta([, info, text]) {
3508
+ const { attrs: attrs$1 } = resolveAttrs(info);
3509
+ const { card, ...rest } = omit(attrs$1, ["text"]);
3510
+ return {
3511
+ text,
3512
+ ...rest,
3513
+ mode: rest.mode || (card ? "card" : "img")
3514
+ };
3515
+ },
3516
+ content(meta) {
3517
+ return `<VPQRCode${stringifyAttrs(meta)} />`;
3518
+ }
3519
+ });
3520
+ createContainerSyntaxPlugin(md, "qrcode", (tokens, index) => {
3521
+ const { content, meta } = tokens[index];
3522
+ const { card, ...rest } = omit(meta, ["text"]);
3523
+ return `<VPQRCode ${stringifyAttrs({
3524
+ text: content?.trim(),
3525
+ ...rest,
3526
+ mode: rest.mode || (card ? "card" : "img")
3527
+ })} />`;
3528
+ });
3529
+ };
3530
+
3499
3531
  //#endregion
3500
3532
  //#region src/node/embed/video/acfun.ts
3501
3533
  const AC_FUN_LINK = "https://www.acfun.cn/player";
@@ -3720,6 +3752,7 @@ function embedSyntaxPlugin(md, options) {
3720
3752
  if (options.replit) md.use(replitPlugin);
3721
3753
  if (options.codeSandbox) md.use(codeSandboxPlugin);
3722
3754
  if (options.jsfiddle) md.use(jsfiddlePlugin);
3755
+ if (options.qrcode) md.use(qrcodePlugin);
3723
3756
  }
3724
3757
 
3725
3758
  //#endregion
@@ -4209,6 +4242,7 @@ const plotPlugin = (md) => {
4209
4242
  //#endregion
4210
4243
  //#region src/node/inline/index.ts
4211
4244
  function inlineSyntaxPlugin(md, options) {
4245
+ md.use(cjsFriendly);
4212
4246
  md.use(attrs);
4213
4247
  md.use(mark);
4214
4248
  md.use(sub);
@@ -4331,13 +4365,16 @@ async function prepareConfigFile(app, options) {
4331
4365
  imports.add(`import VPTable from '${CLIENT_FOLDER}components/VPTable.vue'`);
4332
4366
  enhances.add(`app.component('VPTable', VPTable)`);
4333
4367
  }
4368
+ if (options.qrcode) {
4369
+ imports.add(`import VPQRCode from '${CLIENT_FOLDER}components/VPQRCode.vue'`);
4370
+ enhances.add(`app.component('VPQRCode', VPQRCode)`);
4371
+ }
4334
4372
  const setupIcon = prepareIcon(imports, options.icon);
4335
4373
  const setupStmts = [];
4336
4374
  const iconSetup = setupIcon.trim();
4337
4375
  if (iconSetup) setupStmts.push(iconSetup);
4338
- const markMode = options.mark === "lazy" ? "lazy" : "eager";
4339
4376
  imports.add(`import { setupMarkHighlight } from '${CLIENT_FOLDER}composables/mark.js'`);
4340
- setupStmts.push(`setupMarkHighlight(${JSON.stringify(markMode)})`);
4377
+ setupStmts.push(`setupMarkHighlight(${JSON.stringify(options.mark === "lazy" ? "lazy" : "eager")})`);
4341
4378
  const setupContent = setupStmts.length ? ` ${setupStmts.join("\n ")}\n` : "";
4342
4379
  return app.writeTemp("md-power/config.js", `\
4343
4380
  import { defineClientConfig } from 'vuepress/client'
@@ -4396,6 +4433,7 @@ function markdownPowerPlugin(options = {}) {
4396
4433
  "hls.js",
4397
4434
  "mpegts.js/dist/mpegts.js"
4398
4435
  ]);
4436
+ if (options.qrcode) addViteOptimizeDepsInclude(bundlerOptions, app, ["qrcode"]);
4399
4437
  },
4400
4438
  extendsMarkdown: async (md, app) => {
4401
4439
  linksPlugin(md);
@@ -499,6 +499,12 @@ interface MarkdownPowerPluginOptions {
499
499
  * @default false
500
500
  */
501
501
  table?: boolean | TableContainerOptions;
502
+ /**
503
+ * 是否启用 二维码 嵌入语法
504
+ *
505
+ * @default false
506
+ */
507
+ qrcode?: boolean;
502
508
  /**
503
509
  * 是否启用 自动填充 图片宽高属性
504
510
  *
@@ -519,6 +525,89 @@ interface MarkdownPowerPluginOptions {
519
525
  imageSize?: boolean | 'local' | 'all';
520
526
  }
521
527
  //#endregion
528
+ //#region src/shared/qrcode.d.ts
529
+ interface QRCodeMeta extends QRCodeProps {
530
+ /**
531
+ * mode: 'card' 的别名
532
+ */
533
+ card?: boolean;
534
+ }
535
+ interface QRCodeProps {
536
+ /**
537
+ * 二维码标题
538
+ * 作为 HTML 标签的 `title` 属性、`alt` 属性
539
+ */
540
+ title?: string;
541
+ /**
542
+ * 二维码内容
543
+ */
544
+ text?: string;
545
+ /**
546
+ * 二维码宽度
547
+ */
548
+ width?: number | string;
549
+ /**
550
+ * 显示模式
551
+ * - img: 以图片的形式显示二维码
552
+ * - card: 以卡片的形式显示,卡片以左右布局,左侧二维码,右侧 标题 + 内容
553
+ * @default 'img'
554
+ */
555
+ mode?: 'img' | 'card';
556
+ /**
557
+ * 在 card 模式下是否翻转布局
558
+ */
559
+ reverse?: boolean;
560
+ /**
561
+ * 二维码的对齐方式
562
+ * @default 'left'
563
+ */
564
+ align?: 'left' | 'center' | 'right';
565
+ /**
566
+ * 是否渲染为 SVG 格式的二维码
567
+ * 默认输出为 PNG 格式的 dataURL
568
+ * @default false
569
+ */
570
+ svg?: boolean;
571
+ /**
572
+ * 纠错等级。
573
+ * 可能的取值为低、中、四分位、高,分别对应 L、M、Q、H。
574
+ * @default 'M'
575
+ */
576
+ level?: 'L' | 'M' | 'Q' | 'H' | 'l' | 'm' | 'q' | 'h';
577
+ /**
578
+ * 二维码版本。若未指定,将自动计算更合适的值。
579
+ * 取值范围 1-40
580
+ */
581
+ version?: number;
582
+ /**
583
+ * 用于遮蔽符号的掩码模式。
584
+ * 可能的取值为0、1、2、3、4、5、6、7。
585
+ * 若未指定,系统将自动计算更合适的值。
586
+ */
587
+ mask?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
588
+ /**
589
+ * 定义静区应有多宽。
590
+ * @default 4
591
+ */
592
+ margin?: number;
593
+ /**
594
+ * 缩放因子。值为1表示每个模块(黑点)对应1像素。
595
+ */
596
+ scale?: number;
597
+ /**
598
+ * 暗色模块的颜色。值必须为十六进制格式(RGBA)。
599
+ * 注意:暗色应始终比浅色模块的颜色更深。
600
+ * @default '#000000ff'
601
+ */
602
+ light?: string;
603
+ /**
604
+ * 亮色模块的颜色。值必须为十六进制格式(RGBA)。
605
+ * 注意:亮色应始终比暗色模块的颜色更浅。
606
+ * @default '#ffffffff'
607
+ */
608
+ dark?: string;
609
+ }
610
+ //#endregion
522
611
  //#region src/shared/replit.d.ts
523
612
  interface ReplitTokenMeta extends SizeOptions {
524
613
  title?: string;
@@ -563,4 +652,4 @@ interface ArtPlayerTokenMeta extends SizeOptions {
563
652
  type?: string;
564
653
  }
565
654
  //#endregion
566
- 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 };
655
+ 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, QRCodeMeta, QRCodeProps, 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.180",
4
+ "version": "1.0.0-rc.182",
5
5
  "description": "The Plugin for VuePress 2 - markdown power",
6
6
  "author": "pengzhanbo <volodymyr@foxmail.com>",
7
7
  "license": "MIT",
@@ -33,14 +33,14 @@
33
33
  "peerDependencies": {
34
34
  "artplayer": "^5.3.0",
35
35
  "dashjs": "^5.1.0",
36
- "esbuild": "^0.27.0",
36
+ "esbuild": "^0.27.1",
37
37
  "hls.js": "^1.6.15",
38
38
  "less": "^4.4.2",
39
39
  "markdown-it": "^14.1.0",
40
40
  "mpegts.js": "^1.7.3",
41
41
  "pyodide": "^0.29.0",
42
- "sass": "^1.94.2",
43
- "sass-embedded": "^1.93.3",
42
+ "sass": "^1.96.0",
43
+ "sass-embedded": "^1.96.0",
44
44
  "stylus": "^0.64.0",
45
45
  "vuepress": "2.0.0-rc.26"
46
46
  },
@@ -77,12 +77,12 @@
77
77
  }
78
78
  },
79
79
  "dependencies": {
80
- "@mdit/plugin-attrs": "^0.23.3",
80
+ "@mdit/plugin-attrs": "^0.24.1",
81
81
  "@mdit/plugin-footnote": "^0.22.3",
82
82
  "@mdit/plugin-mark": "^0.22.1",
83
- "@mdit/plugin-sub": "^0.22.2",
84
- "@mdit/plugin-sup": "^0.22.2",
85
- "@mdit/plugin-tab": "^0.22.3",
83
+ "@mdit/plugin-sub": "^0.23.0",
84
+ "@mdit/plugin-sup": "^0.23.0",
85
+ "@mdit/plugin-tab": "^0.23.0",
86
86
  "@mdit/plugin-tasklist": "^0.22.2",
87
87
  "@pengzhanbo/utils": "^2.1.2",
88
88
  "@vuepress/helper": "2.0.0-rc.120",
@@ -91,9 +91,11 @@
91
91
  "image-size": "^2.0.2",
92
92
  "local-pkg": "^1.1.2",
93
93
  "lru-cache": "^11.2.4",
94
+ "markdown-it-cjk-friendly": "^1.3.2",
94
95
  "markdown-it-container": "^4.0.0",
95
96
  "nanoid": "^5.1.6",
96
- "shiki": "^3.17.0",
97
+ "qrcode": "^1.5.4",
98
+ "shiki": "^3.20.0",
97
99
  "tm-grammars": "^1.26.0",
98
100
  "tm-themes": "^1.10.13",
99
101
  "vue": "^3.5.25"