vitepress-plugin-toolkit 0.1.1 → 0.3.0

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.
@@ -37,16 +37,42 @@ interface SizeOptions {
37
37
  type __VLS_Props$1 = {
38
38
  text: string;
39
39
  };
40
- declare const __VLS_export$1: import("vue").DefineComponent<__VLS_Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props$1> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
- declare const _default: typeof __VLS_export$1;
40
+ declare const __VLS_export$2: import("vue").DefineComponent<__VLS_Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props$1> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const _default: typeof __VLS_export$2;
42
42
  //#endregion
43
43
  //#region src/client/components/VPLoading.vue.d.ts
44
44
  type __VLS_Props = {
45
45
  absolute?: boolean;
46
46
  height?: string;
47
47
  };
48
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
- declare const _default$1: typeof __VLS_export;
48
+ declare const __VLS_export$1: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
+ declare const _default$1: typeof __VLS_export$1;
50
+ //#endregion
51
+ //#region src/client/components/VPTabSwitch.vue.d.ts
52
+ interface Item<T> {
53
+ value: T;
54
+ label: string;
55
+ }
56
+ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
57
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<({
58
+ items: Item<T>[];
59
+ } & {
60
+ modelValue?: T;
61
+ }) & {
62
+ onUpdate?: ((tab: T) => any) | undefined;
63
+ "onUpdate:modelValue"?: ((value: T | undefined) => any) | undefined;
64
+ }> & (typeof globalThis extends {
65
+ __VLS_PROPS_FALLBACK: infer P;
66
+ } ? P : {});
67
+ expose: (exposed: {}) => void;
68
+ attrs: any;
69
+ slots: {};
70
+ emit: ((evt: "update", tab: T) => void) & ((event: "update:modelValue", value: T | undefined) => void);
71
+ }>) => import("vue").VNode & {
72
+ __ctx?: Awaited<typeof __VLS_setup>;
73
+ };
74
+ declare const _default$2: typeof __VLS_export;
75
+ type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
50
76
  //#endregion
51
77
  //#region src/client/composables/use-size.d.ts
52
78
  interface SizeInfo {
@@ -56,6 +82,21 @@ interface SizeInfo {
56
82
  }
57
83
  declare function useSize<T extends HTMLElement>(el: TemplateRef<T>, options: ToRefs<SizeOptions>, extraHeight?: MaybeRef<number>): SizeInfo;
58
84
  //#endregion
85
+ //#region src/client/composables/use-zoom-and-drag.d.ts
86
+ declare function useZoomAndDrag(parentEl: TemplateRef<HTMLDivElement>): {
87
+ actorStyle: import("vue").ComputedRef<{
88
+ left: string;
89
+ top: string;
90
+ width: string | undefined;
91
+ height: string;
92
+ }>;
93
+ zoom: import("vue").ComputedRef<string>;
94
+ reset: (isFullscreen?: boolean) => void;
95
+ zoomIn: () => void;
96
+ zoomOut: () => void;
97
+ resetZoom: () => void;
98
+ };
99
+ //#endregion
59
100
  //#region src/client/utils/env.d.ts
60
101
  interface NavigatorUAData {
61
102
  platform?: string;
@@ -123,4 +164,4 @@ declare function isMobile(): boolean;
123
164
  */
124
165
  declare function isSafari(): boolean;
125
166
  //#endregion
126
- export { EXTERNAL_URL_RE, SizeInfo, SizeOptions, URL_PROTOCOL_RE, _default as VPCopyButton, _default$1 as VPLoading, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize };
167
+ export { EXTERNAL_URL_RE, SizeInfo, SizeOptions, URL_PROTOCOL_RE, _default as VPCopyButton, _default$1 as VPLoading, _default$2 as VPTabSwitch, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize, useZoomAndDrag };
@@ -1,5 +1,5 @@
1
- import { computed, createElementBlock, createElementVNode, defineComponent, isRef, normalizeClass, normalizeStyle, onMounted, openBlock, ref, toValue, unref, watch } from "vue";
2
- import { useClipboard, useEventListener } from "@vueuse/core";
1
+ import { Fragment, computed, createElementBlock, createElementVNode, defineComponent, isRef, mergeModels, nextTick, normalizeClass, normalizeStyle, onMounted, openBlock, ref, renderList, shallowRef, toDisplayString, toValue, unref, useModel, watch } from "vue";
2
+ import { useClipboard, useEventListener, useMediaQuery, useMutationObserver } from "@vueuse/core";
3
3
  //#region src/shared/link.ts
4
4
  const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
5
5
  function isExternal(path) {
@@ -11,7 +11,7 @@ function isLinkWithProtocol(link) {
11
11
  }
12
12
  //#endregion
13
13
  //#region src/client/components/VPCopyButton.vue
14
- const _sfc_main = /* @__PURE__ */ defineComponent({
14
+ const _sfc_main = /*@__PURE__*/ defineComponent({
15
15
  __name: "VPCopyButton",
16
16
  props: { text: {} },
17
17
  setup(__props) {
@@ -28,7 +28,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
28
28
  });
29
29
  //#endregion
30
30
  //#region src/client/components/VPLoading.vue
31
- const _sfc_main$1 = /* @__PURE__ */ defineComponent({
31
+ const _sfc_main$1 = /*@__PURE__*/ defineComponent({
32
32
  __name: "VPLoading",
33
33
  props: {
34
34
  absolute: { type: Boolean },
@@ -68,6 +68,38 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
68
68
  }
69
69
  });
70
70
  //#endregion
71
+ //#region src/client/components/VPTabSwitch.vue
72
+ const _hoisted_1 = { class: "vp-tab-switch-list" };
73
+ const _hoisted_2 = ["onClick"];
74
+ const _sfc_main$2 = /*@__PURE__*/ defineComponent({
75
+ __name: "VPTabSwitch",
76
+ props: /*@__PURE__*/ mergeModels({ items: {} }, {
77
+ "modelValue": {},
78
+ "modelModifiers": {}
79
+ }),
80
+ emits: /*@__PURE__*/ mergeModels(["update"], ["update:modelValue"]),
81
+ setup(__props, { emit: __emit }) {
82
+ const emit = __emit;
83
+ const tab = useModel(__props, "modelValue");
84
+ watch(() => __props.items, () => {
85
+ tab.value = __props.items[0].value;
86
+ });
87
+ function onClick(item) {
88
+ tab.value = item;
89
+ emit("update", item);
90
+ }
91
+ return (_ctx, _cache) => {
92
+ return openBlock(), createElementBlock("div", _hoisted_1, [(openBlock(true), createElementBlock(Fragment, null, renderList(__props.items, (item) => {
93
+ return openBlock(), createElementBlock("button", {
94
+ key: item.label,
95
+ class: normalizeClass({ active: tab.value === item.value }),
96
+ onClick: ($event) => onClick(item.value)
97
+ }, toDisplayString(item.label), 11, _hoisted_2);
98
+ }), 128))]);
99
+ };
100
+ }
101
+ });
102
+ //#endregion
71
103
  //#region src/client/composables/use-size.ts
72
104
  function useSize(el, options, extraHeight = 0) {
73
105
  const width = computed(() => toValue(options.width) || "100%");
@@ -101,6 +133,160 @@ function getRadio(ratio) {
101
133
  return typeof ratio === "number" ? ratio : 16 / 9;
102
134
  }
103
135
  //#endregion
136
+ //#region src/client/composables/use-zoom-and-drag.ts
137
+ function useZoomAndDrag(parentEl) {
138
+ const actorEl = shallowRef();
139
+ let ratio = 0;
140
+ const x = ref(0);
141
+ const y = ref(0);
142
+ const width = ref(void 0);
143
+ let originalWidth = 0;
144
+ let initialState = {
145
+ width: 0,
146
+ x: 0,
147
+ y: 0
148
+ };
149
+ const isDesktop = useMediaQuery("(min-width: 640px)");
150
+ useMutationObserver(actorEl, (mutationList) => {
151
+ if (mutationList.some((mutation) => mutation.type === "childList")) nextTick(initialize);
152
+ }, {
153
+ subtree: true,
154
+ childList: true,
155
+ attributes: false
156
+ });
157
+ onMounted(() => nextTick(initialize));
158
+ function initialize(isFullscreen = false) {
159
+ if (!parentEl.value) return;
160
+ const actor = parentEl.value.querySelector(".content");
161
+ actorEl.value = actor;
162
+ if (!actor) return;
163
+ actor.style.width = "max-content";
164
+ actor.style.height = "";
165
+ const stage = parentEl.value;
166
+ const clientHeight = document.documentElement.clientHeight;
167
+ const maxHeight = isFullscreen ? clientHeight : isDesktop.value ? clientHeight * .75 : clientHeight / 2;
168
+ const { offsetWidth: actorWidth, offsetHeight: actorHeight } = actor;
169
+ const stageWidth = stage.offsetWidth;
170
+ ratio = actorWidth / actorHeight;
171
+ let tryZoom = 1;
172
+ let stageHeight = isFullscreen ? clientHeight : actorHeight;
173
+ let newActorHeight = actorHeight;
174
+ if (actorWidth > stageWidth) {
175
+ tryZoom = stageWidth / actorWidth;
176
+ newActorHeight = actorHeight * tryZoom;
177
+ }
178
+ if (newActorHeight > maxHeight) {
179
+ tryZoom = maxHeight / actorHeight;
180
+ stageHeight = maxHeight;
181
+ }
182
+ stage.style.height = `${stageHeight + 24}px`;
183
+ if (tryZoom === 1) {
184
+ width.value = actorWidth;
185
+ x.value = (stageWidth - width.value) / 2;
186
+ y.value = (stageHeight - actorHeight) / 2;
187
+ } else {
188
+ width.value = actorWidth * tryZoom;
189
+ const zoomHeight = width.value / ratio;
190
+ x.value = (stageWidth - width.value) / 2;
191
+ y.value = Math.max(0, ((isFullscreen ? clientHeight : stage.offsetHeight) - zoomHeight) / 2);
192
+ }
193
+ originalWidth = actorWidth;
194
+ initialState = {
195
+ width: width.value,
196
+ x: x.value,
197
+ y: y.value
198
+ };
199
+ }
200
+ let isDragging = false;
201
+ let startX = 0;
202
+ let startY = 0;
203
+ useEventListener(parentEl, "mousedown", (e) => {
204
+ if (e.target.matches("button,[class^=\"vpi-\"]")) return;
205
+ e.preventDefault();
206
+ startX = e.clientX;
207
+ startY = e.clientY;
208
+ isDragging = true;
209
+ parentEl.value.style.cursor = "move";
210
+ });
211
+ useEventListener(parentEl, "mousemove", (e) => {
212
+ if (isDragging) {
213
+ e.preventDefault();
214
+ x.value += e.clientX - startX;
215
+ y.value += e.clientY - startY;
216
+ startX = e.clientX;
217
+ startY = e.clientY;
218
+ }
219
+ });
220
+ useEventListener(parentEl, "mouseup", () => {
221
+ isDragging = false;
222
+ parentEl.value.style.cursor = "";
223
+ });
224
+ let startGap = 0;
225
+ let currentWidth = 0;
226
+ useEventListener(parentEl, "touchstart", (e) => {
227
+ if (e.target.matches("button,[class^=\"vpi-\"]")) return;
228
+ e.preventDefault();
229
+ const touches = e.touches;
230
+ startX = touches[0].clientX;
231
+ startY = touches[0].clientY;
232
+ isDragging = true;
233
+ if (touches[1]) {
234
+ startGap = Math.abs(touches[1].clientX - touches[0].clientX);
235
+ currentWidth = width.value || originalWidth;
236
+ }
237
+ }, { passive: false });
238
+ useEventListener(parentEl, "touchmove", (e) => {
239
+ if (!isDragging) return;
240
+ const touches = e.touches;
241
+ e.preventDefault();
242
+ x.value += touches[0].clientX - startX;
243
+ y.value += touches[0].clientY - startY;
244
+ startX = touches[0].clientX;
245
+ startY = touches[0].clientY;
246
+ if (touches[1]) width.value = currentWidth + Math.abs(touches[1].clientX - touches[0].clientX) - startGap;
247
+ }, { passive: false });
248
+ useEventListener(parentEl, "touchend", () => {
249
+ isDragging = false;
250
+ }, { passive: false });
251
+ function zoom(type) {
252
+ if (typeof width.value === "undefined" || !actorEl.value) return;
253
+ if (type === 0) {
254
+ zooming();
255
+ x.value = initialState.x;
256
+ y.value = initialState.y;
257
+ width.value = initialState.width;
258
+ } else {
259
+ const steps = initialState.width / 10 * type;
260
+ if (width.value + steps <= 100) return;
261
+ zooming();
262
+ width.value += steps;
263
+ x.value -= steps / 2;
264
+ y.value -= steps / ratio / 2;
265
+ }
266
+ }
267
+ let zoomTimer;
268
+ function zooming() {
269
+ actorEl.value?.classList.add("zooming");
270
+ if (zoomTimer) clearTimeout(zoomTimer);
271
+ zoomTimer = setTimeout(() => {
272
+ actorEl.value.classList.remove("zooming");
273
+ }, 250);
274
+ }
275
+ return {
276
+ actorStyle: computed(() => ({
277
+ left: `${Math.ceil(x.value)}px`,
278
+ top: `${Math.ceil(y.value)}px`,
279
+ width: width.value ? `${Math.ceil(width.value)}px` : void 0,
280
+ height: `${width.value ? Math.ceil(width.value / ratio) : void 0}px`
281
+ })),
282
+ zoom: computed(() => `${Math.round((width.value || originalWidth) / originalWidth * 100)}%`),
283
+ reset: initialize,
284
+ zoomIn: () => zoom(1),
285
+ zoomOut: () => zoom(-1),
286
+ resetZoom: () => zoom(0)
287
+ };
288
+ }
289
+ //#endregion
104
290
  //#region src/client/utils/env.ts
105
291
  function getPlatform() {
106
292
  return navigator.userAgentData?.platform ?? navigator.platform;
@@ -178,4 +364,4 @@ function isSafari() {
178
364
  return /safari/iu.test(ua) && !/chrome|crios|fxios|edgios|edg|opr|opera|ucbrowser|qqbrowser|baidubrowser/iu.test(ua);
179
365
  }
180
366
  //#endregion
181
- export { EXTERNAL_URL_RE, URL_PROTOCOL_RE, _sfc_main as VPCopyButton, _sfc_main$1 as VPLoading, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize };
367
+ export { EXTERNAL_URL_RE, URL_PROTOCOL_RE, _sfc_main as VPCopyButton, _sfc_main$1 as VPLoading, _sfc_main$2 as VPTabSwitch, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize, useZoomAndDrag };
@@ -37,16 +37,42 @@ interface SizeOptions {
37
37
  type __VLS_Props$1 = {
38
38
  text: string;
39
39
  };
40
- declare const __VLS_export$1: import("vue").DefineComponent<__VLS_Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props$1> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
- declare const _default: typeof __VLS_export$1;
40
+ declare const __VLS_export$2: import("vue").DefineComponent<__VLS_Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props$1> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
41
+ declare const _default: typeof __VLS_export$2;
42
42
  //#endregion
43
43
  //#region src/client/components/VPLoading.vue.d.ts
44
44
  type __VLS_Props = {
45
45
  absolute?: boolean;
46
46
  height?: string;
47
47
  };
48
- declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
- declare const _default$1: typeof __VLS_export;
48
+ declare const __VLS_export$1: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
+ declare const _default$1: typeof __VLS_export$1;
50
+ //#endregion
51
+ //#region src/client/components/VPTabSwitch.vue.d.ts
52
+ interface Item<T> {
53
+ value: T;
54
+ label: string;
55
+ }
56
+ declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
57
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<({
58
+ items: Item<T>[];
59
+ } & {
60
+ modelValue?: T;
61
+ }) & {
62
+ onUpdate?: ((tab: T) => any) | undefined;
63
+ "onUpdate:modelValue"?: ((value: T | undefined) => any) | undefined;
64
+ }> & (typeof globalThis extends {
65
+ __VLS_PROPS_FALLBACK: infer P;
66
+ } ? P : {});
67
+ expose: (exposed: {}) => void;
68
+ attrs: any;
69
+ slots: {};
70
+ emit: ((evt: "update", tab: T) => void) & ((event: "update:modelValue", value: T | undefined) => void);
71
+ }>) => import("vue").VNode & {
72
+ __ctx?: Awaited<typeof __VLS_setup>;
73
+ };
74
+ declare const _default$2: typeof __VLS_export;
75
+ type __VLS_PrettifyLocal<T> = (T extends any ? { [K in keyof T]: T[K] } : { [K in keyof T as K]: T[K] }) & {};
50
76
  //#endregion
51
77
  //#region src/client/composables/use-size.d.ts
52
78
  interface SizeInfo {
@@ -56,6 +82,21 @@ interface SizeInfo {
56
82
  }
57
83
  declare function useSize<T extends HTMLElement>(el: TemplateRef<T>, options: ToRefs<SizeOptions>, extraHeight?: MaybeRef<number>): SizeInfo;
58
84
  //#endregion
85
+ //#region src/client/composables/use-zoom-and-drag.d.ts
86
+ declare function useZoomAndDrag(parentEl: TemplateRef<HTMLDivElement>): {
87
+ actorStyle: import("vue").ComputedRef<{
88
+ left: string;
89
+ top: string;
90
+ width: string | undefined;
91
+ height: string;
92
+ }>;
93
+ zoom: import("vue").ComputedRef<string>;
94
+ reset: (isFullscreen?: boolean) => void;
95
+ zoomIn: () => void;
96
+ zoomOut: () => void;
97
+ resetZoom: () => void;
98
+ };
99
+ //#endregion
59
100
  //#region src/client/utils/env.d.ts
60
101
  interface NavigatorUAData {
61
102
  platform?: string;
@@ -123,4 +164,4 @@ declare function isMobile(): boolean;
123
164
  */
124
165
  declare function isSafari(): boolean;
125
166
  //#endregion
126
- export { EXTERNAL_URL_RE, SizeInfo, SizeOptions, URL_PROTOCOL_RE, _default as VPCopyButton, _default$1 as VPLoading, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize };
167
+ export { EXTERNAL_URL_RE, SizeInfo, SizeOptions, URL_PROTOCOL_RE, _default as VPCopyButton, _default$1 as VPLoading, _default$2 as VPTabSwitch, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize, useZoomAndDrag };
@@ -1,6 +1,6 @@
1
- import { computed, defineComponent, isRef, mergeProps, onMounted, ref, toValue, unref, useSSRContext, watch } from "vue";
2
- import { ssrRenderAttrs } from "vue/server-renderer";
3
- import { useClipboard, useEventListener } from "@vueuse/core";
1
+ import { computed, defineComponent, isRef, mergeModels, mergeProps, nextTick, onMounted, ref, shallowRef, toValue, unref, useModel, useSSRContext, watch } from "vue";
2
+ import { ssrInterpolate, ssrRenderAttrs, ssrRenderClass, ssrRenderList } from "vue/server-renderer";
3
+ import { useClipboard, useEventListener, useMediaQuery, useMutationObserver } from "@vueuse/core";
4
4
  //#region src/shared/link.ts
5
5
  const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
6
6
  function isExternal(path) {
@@ -12,7 +12,7 @@ function isLinkWithProtocol(link) {
12
12
  }
13
13
  //#endregion
14
14
  //#region src/client/components/VPCopyButton.vue
15
- const _sfc_main = /* @__PURE__ */ defineComponent({
15
+ const _sfc_main = /*@__PURE__*/ defineComponent({
16
16
  __name: "VPCopyButton",
17
17
  __ssrInlineRender: true,
18
18
  props: { text: {} },
@@ -27,15 +27,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
27
27
  };
28
28
  }
29
29
  });
30
- const _sfc_setup$1 = _sfc_main.setup;
30
+ const _sfc_setup$2 = _sfc_main.setup;
31
31
  _sfc_main.setup = (props, ctx) => {
32
32
  const ssrContext = useSSRContext();
33
33
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/client/components/VPCopyButton.vue");
34
- return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
34
+ return _sfc_setup$2 ? _sfc_setup$2(props, ctx) : void 0;
35
35
  };
36
36
  //#endregion
37
37
  //#region src/client/components/VPLoading.vue
38
- const _sfc_main$1 = /* @__PURE__ */ defineComponent({
38
+ const _sfc_main$1 = /*@__PURE__*/ defineComponent({
39
39
  __name: "VPLoading",
40
40
  __ssrInlineRender: true,
41
41
  props: {
@@ -51,10 +51,40 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
51
51
  };
52
52
  }
53
53
  });
54
- const _sfc_setup = _sfc_main$1.setup;
54
+ const _sfc_setup$1 = _sfc_main$1.setup;
55
55
  _sfc_main$1.setup = (props, ctx) => {
56
56
  const ssrContext = useSSRContext();
57
57
  (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/client/components/VPLoading.vue");
58
+ return _sfc_setup$1 ? _sfc_setup$1(props, ctx) : void 0;
59
+ };
60
+ //#endregion
61
+ //#region src/client/components/VPTabSwitch.vue
62
+ const _sfc_main$2 = /*@__PURE__*/ defineComponent({
63
+ __name: "VPTabSwitch",
64
+ __ssrInlineRender: true,
65
+ props: /*@__PURE__*/ mergeModels({ items: {} }, {
66
+ "modelValue": {},
67
+ "modelModifiers": {}
68
+ }),
69
+ emits: /*@__PURE__*/ mergeModels(["update"], ["update:modelValue"]),
70
+ setup(__props, { emit: __emit }) {
71
+ const tab = useModel(__props, "modelValue");
72
+ watch(() => __props.items, () => {
73
+ tab.value = __props.items[0].value;
74
+ });
75
+ return (_ctx, _push, _parent, _attrs) => {
76
+ _push(`<div${ssrRenderAttrs(mergeProps({ class: "vp-tab-switch-list" }, _attrs))}><!--[-->`);
77
+ ssrRenderList(__props.items, (item) => {
78
+ _push(`<button class="${ssrRenderClass({ active: tab.value === item.value })}">${ssrInterpolate(item.label)}</button>`);
79
+ });
80
+ _push(`<!--]--></div>`);
81
+ };
82
+ }
83
+ });
84
+ const _sfc_setup = _sfc_main$2.setup;
85
+ _sfc_main$2.setup = (props, ctx) => {
86
+ const ssrContext = useSSRContext();
87
+ (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("src/client/components/VPTabSwitch.vue");
58
88
  return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
59
89
  };
60
90
  //#endregion
@@ -91,6 +121,160 @@ function getRadio(ratio) {
91
121
  return typeof ratio === "number" ? ratio : 16 / 9;
92
122
  }
93
123
  //#endregion
124
+ //#region src/client/composables/use-zoom-and-drag.ts
125
+ function useZoomAndDrag(parentEl) {
126
+ const actorEl = shallowRef();
127
+ let ratio = 0;
128
+ const x = ref(0);
129
+ const y = ref(0);
130
+ const width = ref(void 0);
131
+ let originalWidth = 0;
132
+ let initialState = {
133
+ width: 0,
134
+ x: 0,
135
+ y: 0
136
+ };
137
+ const isDesktop = useMediaQuery("(min-width: 640px)");
138
+ useMutationObserver(actorEl, (mutationList) => {
139
+ if (mutationList.some((mutation) => mutation.type === "childList")) nextTick(initialize);
140
+ }, {
141
+ subtree: true,
142
+ childList: true,
143
+ attributes: false
144
+ });
145
+ onMounted(() => nextTick(initialize));
146
+ function initialize(isFullscreen = false) {
147
+ if (!parentEl.value) return;
148
+ const actor = parentEl.value.querySelector(".content");
149
+ actorEl.value = actor;
150
+ if (!actor) return;
151
+ actor.style.width = "max-content";
152
+ actor.style.height = "";
153
+ const stage = parentEl.value;
154
+ const clientHeight = document.documentElement.clientHeight;
155
+ const maxHeight = isFullscreen ? clientHeight : isDesktop.value ? clientHeight * .75 : clientHeight / 2;
156
+ const { offsetWidth: actorWidth, offsetHeight: actorHeight } = actor;
157
+ const stageWidth = stage.offsetWidth;
158
+ ratio = actorWidth / actorHeight;
159
+ let tryZoom = 1;
160
+ let stageHeight = isFullscreen ? clientHeight : actorHeight;
161
+ let newActorHeight = actorHeight;
162
+ if (actorWidth > stageWidth) {
163
+ tryZoom = stageWidth / actorWidth;
164
+ newActorHeight = actorHeight * tryZoom;
165
+ }
166
+ if (newActorHeight > maxHeight) {
167
+ tryZoom = maxHeight / actorHeight;
168
+ stageHeight = maxHeight;
169
+ }
170
+ stage.style.height = `${stageHeight + 24}px`;
171
+ if (tryZoom === 1) {
172
+ width.value = actorWidth;
173
+ x.value = (stageWidth - width.value) / 2;
174
+ y.value = (stageHeight - actorHeight) / 2;
175
+ } else {
176
+ width.value = actorWidth * tryZoom;
177
+ const zoomHeight = width.value / ratio;
178
+ x.value = (stageWidth - width.value) / 2;
179
+ y.value = Math.max(0, ((isFullscreen ? clientHeight : stage.offsetHeight) - zoomHeight) / 2);
180
+ }
181
+ originalWidth = actorWidth;
182
+ initialState = {
183
+ width: width.value,
184
+ x: x.value,
185
+ y: y.value
186
+ };
187
+ }
188
+ let isDragging = false;
189
+ let startX = 0;
190
+ let startY = 0;
191
+ useEventListener(parentEl, "mousedown", (e) => {
192
+ if (e.target.matches("button,[class^=\"vpi-\"]")) return;
193
+ e.preventDefault();
194
+ startX = e.clientX;
195
+ startY = e.clientY;
196
+ isDragging = true;
197
+ parentEl.value.style.cursor = "move";
198
+ });
199
+ useEventListener(parentEl, "mousemove", (e) => {
200
+ if (isDragging) {
201
+ e.preventDefault();
202
+ x.value += e.clientX - startX;
203
+ y.value += e.clientY - startY;
204
+ startX = e.clientX;
205
+ startY = e.clientY;
206
+ }
207
+ });
208
+ useEventListener(parentEl, "mouseup", () => {
209
+ isDragging = false;
210
+ parentEl.value.style.cursor = "";
211
+ });
212
+ let startGap = 0;
213
+ let currentWidth = 0;
214
+ useEventListener(parentEl, "touchstart", (e) => {
215
+ if (e.target.matches("button,[class^=\"vpi-\"]")) return;
216
+ e.preventDefault();
217
+ const touches = e.touches;
218
+ startX = touches[0].clientX;
219
+ startY = touches[0].clientY;
220
+ isDragging = true;
221
+ if (touches[1]) {
222
+ startGap = Math.abs(touches[1].clientX - touches[0].clientX);
223
+ currentWidth = width.value || originalWidth;
224
+ }
225
+ }, { passive: false });
226
+ useEventListener(parentEl, "touchmove", (e) => {
227
+ if (!isDragging) return;
228
+ const touches = e.touches;
229
+ e.preventDefault();
230
+ x.value += touches[0].clientX - startX;
231
+ y.value += touches[0].clientY - startY;
232
+ startX = touches[0].clientX;
233
+ startY = touches[0].clientY;
234
+ if (touches[1]) width.value = currentWidth + Math.abs(touches[1].clientX - touches[0].clientX) - startGap;
235
+ }, { passive: false });
236
+ useEventListener(parentEl, "touchend", () => {
237
+ isDragging = false;
238
+ }, { passive: false });
239
+ function zoom(type) {
240
+ if (typeof width.value === "undefined" || !actorEl.value) return;
241
+ if (type === 0) {
242
+ zooming();
243
+ x.value = initialState.x;
244
+ y.value = initialState.y;
245
+ width.value = initialState.width;
246
+ } else {
247
+ const steps = initialState.width / 10 * type;
248
+ if (width.value + steps <= 100) return;
249
+ zooming();
250
+ width.value += steps;
251
+ x.value -= steps / 2;
252
+ y.value -= steps / ratio / 2;
253
+ }
254
+ }
255
+ let zoomTimer;
256
+ function zooming() {
257
+ actorEl.value?.classList.add("zooming");
258
+ if (zoomTimer) clearTimeout(zoomTimer);
259
+ zoomTimer = setTimeout(() => {
260
+ actorEl.value.classList.remove("zooming");
261
+ }, 250);
262
+ }
263
+ return {
264
+ actorStyle: computed(() => ({
265
+ left: `${Math.ceil(x.value)}px`,
266
+ top: `${Math.ceil(y.value)}px`,
267
+ width: width.value ? `${Math.ceil(width.value)}px` : void 0,
268
+ height: `${width.value ? Math.ceil(width.value / ratio) : void 0}px`
269
+ })),
270
+ zoom: computed(() => `${Math.round((width.value || originalWidth) / originalWidth * 100)}%`),
271
+ reset: initialize,
272
+ zoomIn: () => zoom(1),
273
+ zoomOut: () => zoom(-1),
274
+ resetZoom: () => zoom(0)
275
+ };
276
+ }
277
+ //#endregion
94
278
  //#region src/client/utils/env.ts
95
279
  function getPlatform() {
96
280
  return navigator.userAgentData?.platform ?? navigator.platform;
@@ -168,4 +352,4 @@ function isSafari() {
168
352
  return /safari/iu.test(ua) && !/chrome|crios|fxios|edgios|edg|opr|opera|ucbrowser|qqbrowser|baidubrowser/iu.test(ua);
169
353
  }
170
354
  //#endregion
171
- export { EXTERNAL_URL_RE, URL_PROTOCOL_RE, _sfc_main as VPCopyButton, _sfc_main$1 as VPLoading, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize };
355
+ export { EXTERNAL_URL_RE, URL_PROTOCOL_RE, _sfc_main as VPCopyButton, _sfc_main$1 as VPLoading, _sfc_main$2 as VPTabSwitch, isExternal, isIOS, isLinkWithProtocol, isMacOS, isMobile, isSafari, isWindows, isiPad, isiPhone, useSize, useZoomAndDrag };
@@ -2,6 +2,7 @@
2
2
  display: flex;
3
3
  align-items: center;
4
4
  justify-content: center;
5
+ padding-block: 1em;
5
6
  font-size: 36px;
6
7
  color: currentcolor;
7
8
  background-color: inherit;
@@ -0,0 +1,31 @@
1
+ .vp-tab-switch-list {
2
+ display: flex;
3
+ gap: 8px;
4
+ align-items: center;
5
+ justify-content: center;
6
+ padding-block: 2px;
7
+ padding-inline: 4px;
8
+ background-color: var(--vp-c-gray-soft);
9
+ border-radius: 6px;
10
+ }
11
+
12
+ .vp-tab-switch-list button {
13
+ display: inline-block;
14
+ padding-block: 2px;
15
+ padding-inline: 6px;
16
+ font-size: 14px;
17
+ font-weight: 500;
18
+ line-height: 18px;
19
+ color: var(--vp-c-text-3);
20
+ cursor: pointer;
21
+ user-select: none;
22
+ background-color: transparent;
23
+ border-radius: 6px;
24
+ transition: background-color 0.25s ease-in-out;
25
+ }
26
+
27
+ .vp-tab-switch-list button.active {
28
+ color: var(--vp-c-text-1);
29
+ background-color: var(--vp-c-bg);
30
+ box-shadow: var(--vp-shadow-1);
31
+ }
@@ -1,7 +1,7 @@
1
1
  import MarkdownIt from "markdown-it";
2
2
  import { RenderRule } from "markdown-it/lib/renderer.mjs";
3
3
  import { RuleOptions } from "markdown-it/lib/ruler.mjs";
4
- import { MarkdownEnv, SiteConfig } from "vitepress";
4
+ import { MarkdownEnv, Plugin, SiteConfig } from "vitepress";
5
5
 
6
6
  //#region src/shared/link.d.ts
7
7
  declare const EXTERNAL_URL_RE: RegExp;
@@ -184,19 +184,24 @@ declare function createEmbedRuleBlock<Meta extends Record<string, any> = Record<
184
184
  }: EmbedRuleBlockOptions<Meta>): void;
185
185
  //#endregion
186
186
  //#region src/node/utils/constants.d.ts
187
+ declare const isBuild: boolean;
188
+ declare const isDev: boolean;
187
189
  /**
188
- * 支持的视频文件名扩展名
190
+ * 浏览器支持的视频文件名扩展名
189
191
  */
190
192
  declare const EXTENSION_VIDEOS: string[];
191
193
  /**
192
- * 支持的图片文件名扩展名
194
+ * 浏览器支持的图片文件名扩展名
193
195
  */
194
196
  declare const EXTENSION_IMAGES: string[];
195
197
  /**
196
- * 支持的音频文件名扩展名
198
+ * 浏览器支持的音频文件名扩展名
197
199
  */
198
200
  declare const EXTENSION_AUDIOS: string[];
199
201
  //#endregion
202
+ //#region src/node/utils/hash.d.ts
203
+ declare function genHash(data: unknown, length?: number): string;
204
+ //#endregion
200
205
  //#region src/node/utils/logger.d.ts
201
206
  type LogType = 'info' | 'warn' | 'error' | 'debug';
202
207
  type LogLevel = LogType | 'silent';
@@ -305,6 +310,14 @@ declare function stringifyAttrs<T extends object = object>(attrs: T, withUndefin
305
310
  //#region src/node/utils/treat-as-html.d.ts
306
311
  declare function treatAsHtml(filename: string): boolean;
307
312
  //#endregion
313
+ //#region src/node/vite-plugins/iconPlugin.d.ts
314
+ interface Icon {
315
+ name: string;
316
+ svg: string;
317
+ classname?: string;
318
+ }
319
+ declare function iconPlugin(icons: Icon[]): Plugin;
320
+ //#endregion
308
321
  //#region src/node/vitepress/createLocales.d.ts
309
322
  type BuiltinLocale<LocaleData extends Record<string, unknown>> = [langCodes: string[], localeData: LocaleData];
310
323
  type BuiltinLocales<LocaleData extends Record<string, unknown>> = BuiltinLocale<LocaleData>[];
@@ -328,4 +341,4 @@ declare function getVitepressConfig(): SiteConfig;
328
341
  //#region src/node/vitepress/resolve-route-link.d.ts
329
342
  declare function resolveRouteLink(url: string, env: MarkdownEnv): string;
330
343
  //#endregion
331
- export { BuiltinLocale, BuiltinLocales, ContainerOptions, EXTENSION_AUDIOS, EXTENSION_IMAGES, EXTENSION_VIDEOS, EXTERNAL_URL_RE, EmbedRuleBlockOptions, LogLevel, LogType, Logger, SizeOptions, URL_PROTOCOL_RE, createContainerPlugin, createContainerSyntaxPlugin, createEmbedRuleBlock, createLocales, createLogger, getLocaleWithPath, getVitepressConfig, isExternal, isLinkWithProtocol, logLevels, parseRect, resolveAttr, resolveAttrs, resolveRouteLink, slugify, stringifyAttrs, treatAsHtml };
344
+ export { BuiltinLocale, BuiltinLocales, ContainerOptions, EXTENSION_AUDIOS, EXTENSION_IMAGES, EXTENSION_VIDEOS, EXTERNAL_URL_RE, EmbedRuleBlockOptions, LogLevel, LogType, Logger, SizeOptions, URL_PROTOCOL_RE, createContainerPlugin, createContainerSyntaxPlugin, createEmbedRuleBlock, createLocales, createLogger, genHash, getLocaleWithPath, getVitepressConfig, iconPlugin, isBuild, isDev, isExternal, isLinkWithProtocol, logLevels, parseRect, resolveAttr, resolveAttrs, resolveRouteLink, slugify, stringifyAttrs, treatAsHtml };
@@ -1,7 +1,8 @@
1
1
  import container from "markdown-it-container";
2
- import { camelCase, deepMerge, isBoolean, isNull, isNumber, isString, isUndefined, kebabCase, objectEntries, objectKeys, slash } from "@pengzhanbo/utils";
3
- import ansis from "ansis";
2
+ import { camelCase, deepMerge, isBoolean, isNull, isNumber, isPrimitive, isString, isUndefined, kebabCase, objectEntries, objectKeys, omit, slash } from "@pengzhanbo/utils";
4
3
  import process from "node:process";
4
+ import { createHash } from "node:crypto";
5
+ import ansis from "ansis";
5
6
  //#region src/shared/link.ts
6
7
  const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
7
8
  function isExternal(path) {
@@ -137,6 +138,7 @@ function createContainerSyntaxPlugin(md, type, render) {
137
138
  const token = state.push(`${type}_container`, "", 0);
138
139
  token.meta = resolveAttrs(info.slice(type.length));
139
140
  token.content = content;
141
+ token.info = info.slice(type.length).trim();
140
142
  token.markup = `${markup} ${type}`;
141
143
  token.map = [startLine, line + 1];
142
144
  state.line = line + 1;
@@ -201,8 +203,10 @@ function createEmbedRuleBlock(md, { type, name = type, syntaxPattern, beforeName
201
203
  }
202
204
  //#endregion
203
205
  //#region src/node/utils/constants.ts
206
+ const isBuild = process.env.NODE_ENV === "production";
207
+ const isDev = process.env.NODE_ENV === "development";
204
208
  /**
205
- * 支持的视频文件名扩展名
209
+ * 浏览器支持的视频文件名扩展名
206
210
  */
207
211
  const EXTENSION_VIDEOS = [
208
212
  "mp4",
@@ -220,7 +224,7 @@ const EXTENSION_VIDEOS = [
220
224
  "ogv"
221
225
  ];
222
226
  /**
223
- * 支持的图片文件名扩展名
227
+ * 浏览器支持的图片文件名扩展名
224
228
  */
225
229
  const EXTENSION_IMAGES = [
226
230
  "jpg",
@@ -240,7 +244,7 @@ const EXTENSION_IMAGES = [
240
244
  "xbm"
241
245
  ];
242
246
  /**
243
- * 支持的音频文件名扩展名
247
+ * 浏览器支持的音频文件名扩展名
244
248
  */
245
249
  const EXTENSION_AUDIOS = [
246
250
  "mp3",
@@ -252,6 +256,13 @@ const EXTENSION_AUDIOS = [
252
256
  "acc"
253
257
  ];
254
258
  //#endregion
259
+ //#region src/node/utils/hash.ts
260
+ function genHash(data, length) {
261
+ const str = isPrimitive(data) ? String(data) : JSON.stringify(data);
262
+ const hash = createHash("sha256").update(str).digest("hex");
263
+ return length ? hash.slice(0, length) : hash;
264
+ }
265
+ //#endregion
255
266
  //#region src/node/utils/logger.ts
256
267
  /**
257
268
  * Log levels mapping
@@ -374,6 +385,44 @@ function treatAsHtml(filename) {
374
385
  return ext == null || !KNOWN_EXTENSIONS.has(ext.toLowerCase());
375
386
  }
376
387
  //#endregion
388
+ //#region src/node/vite-plugins/iconPlugin.ts
389
+ const name = "vitepress:tuck-icons";
390
+ const iconList = [];
391
+ let isProcessing = false;
392
+ function iconPlugin(icons) {
393
+ for (const icon of icons) {
394
+ const index = iconList.findIndex((item) => item.name === icon.name);
395
+ if (index === -1) iconList.push({
396
+ ...omit(icon, ["classname"]),
397
+ classname: new Set([icon.classname || icon.name])
398
+ });
399
+ else icon.classname && iconList[index].classname.add(icon.classname);
400
+ }
401
+ const moduleId = "virtual:tuck-icons.css";
402
+ const resolveId = `\0${moduleId}`;
403
+ return {
404
+ name,
405
+ enforce: "post",
406
+ resolveId(id) {
407
+ if (id === moduleId) {
408
+ isProcessing = true;
409
+ return resolveId;
410
+ }
411
+ },
412
+ load(id) {
413
+ if (id !== resolveId) return null;
414
+ if (!isProcessing) return null;
415
+ let css = "";
416
+ for (const icon of iconList) {
417
+ const classname = Array.from(icon.classname).map((name) => `.vpi-${name}`).join(",\n");
418
+ css += `${classname} {\n --icon: ${icon.svg};\n}\n`;
419
+ }
420
+ isProcessing = false;
421
+ return css;
422
+ }
423
+ };
424
+ }
425
+ //#endregion
377
426
  //#region src/node/vitepress/get-vitepress-config.ts
378
427
  function getVitepressConfig() {
379
428
  const config = globalThis.VITEPRESS_CONFIG;
@@ -443,4 +492,4 @@ function normalizeHash(str) {
443
492
  return str ? encodeURI(`#${slugify(decodeURI(str).slice(1))}`) : "";
444
493
  }
445
494
  //#endregion
446
- export { EXTENSION_AUDIOS, EXTENSION_IMAGES, EXTENSION_VIDEOS, EXTERNAL_URL_RE, URL_PROTOCOL_RE, createContainerPlugin, createContainerSyntaxPlugin, createEmbedRuleBlock, createLocales, createLogger, getLocaleWithPath, getVitepressConfig, isExternal, isLinkWithProtocol, logLevels, parseRect, resolveAttr, resolveAttrs, resolveRouteLink, slugify, stringifyAttrs, treatAsHtml };
495
+ export { EXTENSION_AUDIOS, EXTENSION_IMAGES, EXTENSION_VIDEOS, EXTERNAL_URL_RE, URL_PROTOCOL_RE, createContainerPlugin, createContainerSyntaxPlugin, createEmbedRuleBlock, createLocales, createLogger, genHash, getLocaleWithPath, getVitepressConfig, iconPlugin, isBuild, isDev, isExternal, isLinkWithProtocol, logLevels, parseRect, resolveAttr, resolveAttrs, resolveRouteLink, slugify, stringifyAttrs, treatAsHtml };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vitepress-plugin-toolkit",
3
3
  "type": "module",
4
- "version": "0.1.1",
4
+ "version": "0.3.0",
5
5
  "description": "Development toolkit for vitepress plugins",
6
6
  "author": "pengzhanbo <q942450674@outlook.com> (https://github.com/pengzhanbo/)",
7
7
  "license": "MIT",