vuepress-plugin-md-power 1.0.0-rc.180 → 1.0.0-rc.181
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/client/components/VPQRCode.vue +228 -0
- package/lib/node/index.d.ts +90 -1
- package/lib/node/index.js +39 -2
- package/lib/shared/index.d.ts +90 -1
- package/package.json +9 -7
|
@@ -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>
|
package/lib/node/index.d.ts
CHANGED
|
@@ -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";
|
|
@@ -3496,6 +3497,36 @@ const pdfPlugin = (md) => {
|
|
|
3496
3497
|
});
|
|
3497
3498
|
};
|
|
3498
3499
|
|
|
3500
|
+
//#endregion
|
|
3501
|
+
//#region src/node/embed/qrcode.ts
|
|
3502
|
+
const qrcodePlugin = (md) => {
|
|
3503
|
+
createEmbedRuleBlock(md, {
|
|
3504
|
+
type: "qrcode",
|
|
3505
|
+
syntaxPattern: /^@\[qrcode([^\]]*)\]\(([^)]*)\)/,
|
|
3506
|
+
meta([, info, text]) {
|
|
3507
|
+
const { attrs: attrs$1 } = resolveAttrs(info);
|
|
3508
|
+
const { card, ...rest } = omit(attrs$1, ["text"]);
|
|
3509
|
+
return {
|
|
3510
|
+
text,
|
|
3511
|
+
...rest,
|
|
3512
|
+
mode: rest.mode || (card ? "card" : "img")
|
|
3513
|
+
};
|
|
3514
|
+
},
|
|
3515
|
+
content(meta) {
|
|
3516
|
+
return `<VPQRCode${stringifyAttrs(meta)} />`;
|
|
3517
|
+
}
|
|
3518
|
+
});
|
|
3519
|
+
createContainerSyntaxPlugin(md, "qrcode", (tokens, index) => {
|
|
3520
|
+
const { content, meta } = tokens[index];
|
|
3521
|
+
const { card, ...rest } = omit(meta, ["text"]);
|
|
3522
|
+
return `<VPQRCode ${stringifyAttrs({
|
|
3523
|
+
text: content?.trim(),
|
|
3524
|
+
...rest,
|
|
3525
|
+
mode: rest.mode || (card ? "card" : "img")
|
|
3526
|
+
})} />`;
|
|
3527
|
+
});
|
|
3528
|
+
};
|
|
3529
|
+
|
|
3499
3530
|
//#endregion
|
|
3500
3531
|
//#region src/node/embed/video/acfun.ts
|
|
3501
3532
|
const AC_FUN_LINK = "https://www.acfun.cn/player";
|
|
@@ -3720,6 +3751,7 @@ function embedSyntaxPlugin(md, options) {
|
|
|
3720
3751
|
if (options.replit) md.use(replitPlugin);
|
|
3721
3752
|
if (options.codeSandbox) md.use(codeSandboxPlugin);
|
|
3722
3753
|
if (options.jsfiddle) md.use(jsfiddlePlugin);
|
|
3754
|
+
if (options.qrcode) md.use(qrcodePlugin);
|
|
3723
3755
|
}
|
|
3724
3756
|
|
|
3725
3757
|
//#endregion
|
|
@@ -4209,6 +4241,7 @@ const plotPlugin = (md) => {
|
|
|
4209
4241
|
//#endregion
|
|
4210
4242
|
//#region src/node/inline/index.ts
|
|
4211
4243
|
function inlineSyntaxPlugin(md, options) {
|
|
4244
|
+
md.use(cjsFriendly);
|
|
4212
4245
|
md.use(attrs);
|
|
4213
4246
|
md.use(mark);
|
|
4214
4247
|
md.use(sub);
|
|
@@ -4331,13 +4364,16 @@ async function prepareConfigFile(app, options) {
|
|
|
4331
4364
|
imports.add(`import VPTable from '${CLIENT_FOLDER}components/VPTable.vue'`);
|
|
4332
4365
|
enhances.add(`app.component('VPTable', VPTable)`);
|
|
4333
4366
|
}
|
|
4367
|
+
if (options.qrcode) {
|
|
4368
|
+
imports.add(`import VPQRCode from '${CLIENT_FOLDER}components/VPQRCode.vue'`);
|
|
4369
|
+
enhances.add(`app.component('VPQRCode', VPQRCode)`);
|
|
4370
|
+
}
|
|
4334
4371
|
const setupIcon = prepareIcon(imports, options.icon);
|
|
4335
4372
|
const setupStmts = [];
|
|
4336
4373
|
const iconSetup = setupIcon.trim();
|
|
4337
4374
|
if (iconSetup) setupStmts.push(iconSetup);
|
|
4338
|
-
const markMode = options.mark === "lazy" ? "lazy" : "eager";
|
|
4339
4375
|
imports.add(`import { setupMarkHighlight } from '${CLIENT_FOLDER}composables/mark.js'`);
|
|
4340
|
-
setupStmts.push(`setupMarkHighlight(${JSON.stringify(
|
|
4376
|
+
setupStmts.push(`setupMarkHighlight(${JSON.stringify(options.mark === "lazy" ? "lazy" : "eager")})`);
|
|
4341
4377
|
const setupContent = setupStmts.length ? ` ${setupStmts.join("\n ")}\n` : "";
|
|
4342
4378
|
return app.writeTemp("md-power/config.js", `\
|
|
4343
4379
|
import { defineClientConfig } from 'vuepress/client'
|
|
@@ -4396,6 +4432,7 @@ function markdownPowerPlugin(options = {}) {
|
|
|
4396
4432
|
"hls.js",
|
|
4397
4433
|
"mpegts.js/dist/mpegts.js"
|
|
4398
4434
|
]);
|
|
4435
|
+
if (options.qrcode) addViteOptimizeDepsInclude(bundlerOptions, app, ["qrcode"]);
|
|
4399
4436
|
},
|
|
4400
4437
|
extendsMarkdown: async (md, app) => {
|
|
4401
4438
|
linksPlugin(md);
|
package/lib/shared/index.d.ts
CHANGED
|
@@ -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.
|
|
4
|
+
"version": "1.0.0-rc.181",
|
|
5
5
|
"description": "The Plugin for VuePress 2 - markdown power",
|
|
6
6
|
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"artplayer": "^5.3.0",
|
|
35
35
|
"dashjs": "^5.1.0",
|
|
36
|
-
"esbuild": "^0.27.
|
|
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",
|
|
@@ -77,12 +77,12 @@
|
|
|
77
77
|
}
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
|
-
"@mdit/plugin-attrs": "^0.
|
|
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.
|
|
84
|
-
"@mdit/plugin-sup": "^0.
|
|
85
|
-
"@mdit/plugin-tab": "^0.
|
|
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
|
-
"
|
|
97
|
+
"qrcode": "^1.5.4",
|
|
98
|
+
"shiki": "^3.19.0",
|
|
97
99
|
"tm-grammars": "^1.26.0",
|
|
98
100
|
"tm-themes": "^1.10.13",
|
|
99
101
|
"vue": "^3.5.25"
|