vuepress-plugin-md-power 1.0.0-rc.132 → 1.0.0-rc.134

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.
@@ -34,18 +34,20 @@ watch(show, () => nextTick(() => {
34
34
  <template>
35
35
  <span class="vp-abbr" @mouseenter="show = true" @mouseleave="show = false">
36
36
  <slot />
37
- <Transition name="fade">
38
- <span v-show="show" ref="tooltip" class="vp-abbr-tooltip" :style="styles">
39
- <slot name="tooltip" />
40
- </span>
41
- </Transition>
37
+ <ClientOnly>
38
+ <Transition name="fade">
39
+ <span v-show="show" ref="tooltip" class="vp-abbr-tooltip ignore-header" :style="styles">
40
+ <slot name="tooltip" />
41
+ </span>
42
+ </Transition>
43
+ </ClientOnly>
42
44
  </span>
43
45
  </template>
44
46
 
45
47
  <style>
46
48
  :root {
47
49
  --vp-abbr-bg: var(--vp-c-bg);
48
- --vp-abbr-text: var(--vp-c-text-2);
50
+ --vp-abbr-text: var(--vp-c-text-1);
49
51
  --vp-abbr-border: var(--vp-c-divider);
50
52
  --vp-abbr-transform: translateX(-50%);
51
53
  --vp-abbr-space-transform: translateX(-50%);
@@ -66,7 +68,7 @@ watch(show, () => nextTick(() => {
66
68
  width: max-content;
67
69
  max-width: min(calc(100vw - 32px), 360px);
68
70
  padding: 8px 14px;
69
- font-size: 0.875em;
71
+ font-size: 14px;
70
72
  line-height: 1.7;
71
73
  color: var(--vp-abbr-text);
72
74
  cursor: auto;
@@ -24,32 +24,41 @@ function updatePosition() {
24
24
  return
25
25
  const { x: _x, y: _y, width: w, height: h } = button.value.getBoundingClientRect()
26
26
  const x = _x + w / 2
27
- const y = _y + h
27
+ const y = _y + h / 2
28
28
 
29
29
  const { width, height } = popover.value.getBoundingClientRect()
30
30
  const { clientWidth, clientHeight } = document.documentElement
31
31
  position.value.x = x + width + 16 > clientWidth ? clientWidth - x - width - 16 : 0
32
- position.value.y = y + height + 16 > clientHeight ? clientHeight - y - height - 16 : 0
32
+
33
+ if (y > clientHeight - 16) {
34
+ active.value = false
35
+ }
36
+ else {
37
+ position.value.y = y + height + 16 > clientHeight ? clientHeight - y - height - 16 : 0
38
+ }
33
39
  }
34
40
 
35
41
  watch(active, () => nextTick(updatePosition))
36
42
  useEventListener('resize', updatePosition)
43
+ useEventListener('scroll', updatePosition, { passive: true })
37
44
  </script>
38
45
 
39
46
  <template>
40
- <span class="vp-annotation" :class="{ active, [label]: true }" :aria-label="label">
47
+ <span class="vp-annotation ignore-header" :class="{ active, [label]: true }" :aria-label="label">
41
48
  <span ref="button" class="vpi-annotation" @click="active = !active" />
42
- <Transition name="fade">
43
- <div
44
- v-show="active" ref="popover"
45
- class="annotations-popover" :class="{ list: list.length > 1 }"
46
- :style="{ '--vp-annotation-x': `${position.x}px`, '--vp-annotation-y': `${position.y}px` }"
47
- >
48
- <div v-for="i in list" :key="label + i" class="annotation">
49
- <slot :name="`item-${i}`" />
49
+ <ClientOnly>
50
+ <Transition name="fade">
51
+ <div
52
+ v-show="active" ref="popover"
53
+ class="annotations-popover" :class="{ list: list.length > 1 }"
54
+ :style="{ '--vp-annotation-x': `${position.x}px`, '--vp-annotation-y': `${position.y}px` }"
55
+ >
56
+ <div v-for="i in list" :key="label + i" class="annotation">
57
+ <slot :name="`item-${i}`" />
58
+ </div>
50
59
  </div>
51
- </div>
52
- </Transition>
60
+ </Transition>
61
+ </ClientOnly>
53
62
  </span>
54
63
  </template>
55
64
 
@@ -73,6 +82,12 @@ useEventListener('resize', updatePosition)
73
82
  transform: rotate(0deg);
74
83
  }
75
84
 
85
+ @media print {
86
+ .vpi-annotation {
87
+ display: none;
88
+ }
89
+ }
90
+
76
91
  .vp-annotation.active {
77
92
  z-index: 10;
78
93
  }
@@ -94,13 +109,15 @@ useEventListener('resize', updatePosition)
94
109
  max-width: min(calc(100vw - 32px), 360px);
95
110
  max-height: 360px;
96
111
  padding: 8px 12px;
97
- overflow-y: auto;
112
+ overflow: auto;
98
113
  font-size: 14px;
114
+ font-weight: normal;
99
115
  background-color: var(--vp-c-bg);
100
116
  border: solid 1px var(--vp-c-divider);
101
117
  border-radius: 4px;
102
118
  box-shadow: var(--vp-shadow-2);
103
- transform: translateX(var(--vp-annotation-x, 0)) translateY(var(--vp-annotation-y, 0));
119
+ transform: translateX(var(--vp-annotation-x, 0)) translateY(var(--vp-annotation-y, 0)) translateZ(0);
120
+ will-change: transform;
104
121
  }
105
122
 
106
123
  .annotations-popover.list {
@@ -117,4 +134,25 @@ useEventListener('resize', updatePosition)
117
134
  border-radius: 4px;
118
135
  box-shadow: var(--vp-shadow-1);
119
136
  }
137
+
138
+ .annotations-popover :deep(p) {
139
+ margin: 12px 0;
140
+ line-height: 24px;
141
+ }
142
+
143
+ .annotations-popover :deep(:first-child) {
144
+ margin-top: 4px;
145
+ }
146
+
147
+ .annotations-popover :deep(:last-child) {
148
+ margin-bottom: 4px;
149
+ }
150
+
151
+ .annotations-popover.list :deep(:first-child) {
152
+ margin-top: 8px;
153
+ }
154
+
155
+ .annotations-popover.list :deep(:last-child) {
156
+ margin-bottom: 8px;
157
+ }
120
158
  </style>
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
+ import { useDarkMode } from '@vuepress/helper/client'
2
3
  import { useEventListener } from '@vueuse/core'
3
- import { computed, getCurrentInstance, ref } from 'vue'
4
+ import { computed, ref } from 'vue'
4
5
 
5
6
  interface MessageData {
6
7
  type: string
@@ -23,11 +24,10 @@ const props = withDefaults(defineProps<{
23
24
  })
24
25
 
25
26
  const url = 'https://caniuse.pengzhanbo.cn/'
26
- const current = getCurrentInstance()
27
27
 
28
28
  const height = ref('330px')
29
29
 
30
- const isDark = computed(() => current?.appContext.config.globalProperties.$isDark.value)
30
+ const isDark = useDarkMode()
31
31
  const source = computed(() => {
32
32
  const source = `${url}${props.feature}#past=${props.past}&future=${props.future}&meta=${props.meta}&theme=${isDark.value ? 'dark' : 'light'}`
33
33
 
@@ -0,0 +1,54 @@
1
+ <script setup lang="ts">
2
+ import { useDarkMode } from '@vuepress/helper/client'
3
+ import { computed } from 'vue'
4
+
5
+ const props = defineProps<{
6
+ user: string
7
+ slash: string
8
+ title?: string
9
+ preview?: boolean
10
+ editable?: boolean
11
+ tab?: string
12
+ theme?: 'light' | 'dark'
13
+ width?: string
14
+ height?: string
15
+ }>()
16
+
17
+ const CODEPEN_LINK = 'https://codepen.io/'
18
+
19
+ const isDark = useDarkMode()
20
+
21
+ const link = computed(() => {
22
+ const middle = props.preview ? '/embed/preview/' : '/embed/'
23
+ const params = new URLSearchParams()
24
+
25
+ props.editable && params.set('editable', 'true')
26
+ props.tab && params.set('default-tab', props.tab)
27
+
28
+ const theme = props.theme ?? (isDark.value ? 'dark' : 'light')
29
+ theme && params.set('theme-id', theme)
30
+
31
+ return `${CODEPEN_LINK}${props.user}${middle}${props.slash}?${params.toString()}`
32
+ })
33
+ </script>
34
+
35
+ <template>
36
+ <iframe
37
+ :src="link"
38
+ class="code-pen-iframe"
39
+ :title="title"
40
+ :style="{ width, height }"
41
+ frameborder="0"
42
+ loading="lazy"
43
+ allowtransparency="true"
44
+ allowfullscreen="true"
45
+ />
46
+ </template>
47
+
48
+ <style>
49
+ .code-pen-iframe {
50
+ margin: 16px auto;
51
+ border: none;
52
+ box-shadow: var(--vp-shadow-2);
53
+ }
54
+ </style>
@@ -0,0 +1,40 @@
1
+ <script setup lang="ts">
2
+ import { useDarkMode } from '@vuepress/helper/client'
3
+ import { computed } from 'vue'
4
+
5
+ const props = defineProps<{
6
+ source: string
7
+ title?: string
8
+ tab: string
9
+ theme?: 'light' | 'dark'
10
+ width?: string
11
+ height?: string
12
+ }>()
13
+
14
+ const isDark = useDarkMode()
15
+
16
+ const link = computed(() => {
17
+ const theme = props.theme === 'dark' ? '/dark/' : isDark.value ? '/dark/' : ''
18
+ return `https://jsfiddle.net/${props.source}/embedded/${props.tab}${theme}`
19
+ })
20
+ </script>
21
+
22
+ <template>
23
+ <iframe
24
+ class="js-fiddle-iframe"
25
+ :src="link"
26
+ :title="title"
27
+ :style="{ width, height }"
28
+ frameborder="0"
29
+ allowfullscreen="true"
30
+ allowpaymentrequest="true"
31
+ />
32
+ </template>
33
+
34
+ <style>
35
+ .js-fiddle-iframe {
36
+ margin: 16px auto;
37
+ border: none;
38
+ box-shadow: var(--vp-shadow-2);
39
+ }
40
+ </style>
@@ -1,18 +1,18 @@
1
1
  <script setup lang="ts">
2
2
  import type { ReplitTokenMeta } from '../../shared/index.js'
3
- import { computed, getCurrentInstance, ref } from 'vue'
3
+ import { useDarkMode } from '@vuepress/helper/client'
4
+ import { computed, ref } from 'vue'
4
5
  import Loading from './icons/Loading.vue'
5
6
 
6
7
  const props = defineProps<ReplitTokenMeta>()
7
8
 
8
- const current = getCurrentInstance()
9
9
  // magic height
10
10
  const height = ref('47px')
11
11
  const loaded = ref(false)
12
12
 
13
13
  const REPLIT_LINK = 'https://replit.com/'
14
14
 
15
- const isDark = computed(() => current?.appContext.config.globalProperties.$isDark.value)
15
+ const isDark = useDarkMode()
16
16
 
17
17
  const link = computed(() => {
18
18
  const url = new URL(`/${props.source}`, REPLIT_LINK)
@@ -50,7 +50,7 @@ function onload() {
50
50
  width: 100%;
51
51
  margin: 16px auto;
52
52
  border: none;
53
- border-top: 1px solid var(--vp-c-divider, #e2e2e3);
53
+ border-top: 1px solid var(--vp-c-divider);
54
54
  border-bottom-right-radius: 8px;
55
55
  border-bottom-left-radius: 8px;
56
56
  transition: border 0.25s;
@@ -1,8 +1,8 @@
1
1
  // src/client/composables/pdf.ts
2
+ import { checkIsiPad, checkIsMobile, checkIsSafari } from "@vuepress/helper/client";
2
3
  import { withBase } from "vuepress/client";
3
4
  import { ensureEndingSlash, isLinkHttp } from "vuepress/shared";
4
5
  import { pluginOptions } from "../options.js";
5
- import { checkIsiPad, checkIsMobile, checkIsSafari } from "../utils/is.js";
6
6
  function queryStringify(options) {
7
7
  const { page, noToolbar, zoom } = options;
8
8
  const params = [
@@ -99,8 +99,7 @@ interface IconsOptions {
99
99
  }
100
100
 
101
101
  interface JSFiddleTokenMeta extends SizeOptions {
102
- user?: string;
103
- id?: string;
102
+ source: string;
104
103
  title?: string;
105
104
  theme?: string;
106
105
  tab?: string;
package/lib/node/index.js CHANGED
@@ -111,7 +111,7 @@ async function imageSizePlugin(app, md, type2 = false) {
111
111
  if (!cache.has(filepath2)) {
112
112
  if (!fs.existsSync(filepath2))
113
113
  return false;
114
- const { width: w, height: h } = imageSize(filepath2);
114
+ const { width: w, height: h } = imageSize(fs.readFileSync(filepath2));
115
115
  if (!w || !h)
116
116
  return false;
117
117
  cache.set(filepath2, { width: w, height: h });
@@ -203,7 +203,7 @@ async function resolveImageSize(app, url, remote = false) {
203
203
  if (url[0] === "/") {
204
204
  const filepath2 = app.dir.public(url.slice(1));
205
205
  if (fs.existsSync(filepath2)) {
206
- const { width, height } = imageSize(filepath2);
206
+ const { width, height } = imageSize(fs.readFileSync(filepath2));
207
207
  return { width, height };
208
208
  }
209
209
  }
@@ -1160,9 +1160,9 @@ var codeTabs = (md, options = {}) => {
1160
1160
  };
1161
1161
  tab(md, {
1162
1162
  name: "code-tabs",
1163
- tabsOpenRenderer: ({ active, data }, tokens, index) => {
1163
+ tabsOpenRenderer: ({ active, data }, tokens, index, _, env) => {
1164
1164
  const { meta } = tokens[index];
1165
- const titles = data.map(({ title }) => md.renderInline(title));
1165
+ const titles = data.map(({ title }) => md.renderInline(title, env));
1166
1166
  const tabsData = data.map((item, dataIndex) => {
1167
1167
  const { id = titles[dataIndex] } = item;
1168
1168
  return { id };
@@ -1674,7 +1674,7 @@ function resolveNpmTo(lines, info, idx, tabs2) {
1674
1674
  ${newLines.join("")}
1675
1675
  \`\`\``);
1676
1676
  }
1677
- return `:::code-tabs#npm-to-${idx}
1677
+ return `:::code-tabs#npm-to-${tabs2.join("-")}
1678
1678
  ${res.join("\n")}
1679
1679
  :::`;
1680
1680
  }
@@ -1789,9 +1789,9 @@ import { tab as tab2 } from "@mdit/plugin-tab";
1789
1789
  var tabs = (md) => {
1790
1790
  tab2(md, {
1791
1791
  name: "tabs",
1792
- tabsOpenRenderer: ({ active, data }, tokens, index) => {
1792
+ tabsOpenRenderer: ({ active, data }, tokens, index, _, env) => {
1793
1793
  const { meta } = tokens[index];
1794
- const titles = data.map(({ title }) => md.renderInline(title));
1794
+ const titles = data.map(({ title }) => md.renderInline(title, env));
1795
1795
  const tabsData = data.map((item, dataIndex) => {
1796
1796
  const { id = titles[dataIndex] } = item;
1797
1797
  return { id };
@@ -2651,41 +2651,24 @@ function parseRect(str, unit = "px") {
2651
2651
  }
2652
2652
 
2653
2653
  // src/node/embed/code/codepen.ts
2654
- var CODEPEN_LINK = "https://codepen.io/";
2655
2654
  var codepenPlugin = (md) => {
2656
2655
  createEmbedRuleBlock(md, {
2657
2656
  type: "codepen",
2658
2657
  syntaxPattern: /^@\[codepen([^\]]*)\]\(([^)]*)\)/,
2659
2658
  meta: ([, info, source]) => {
2660
- const { attrs: attrs2 } = resolveAttrs(info);
2659
+ const { width, height, title, tab: tab3, ...rest } = resolveAttrs(info).attrs;
2661
2660
  const [user, slash] = source.split("/");
2662
2661
  return {
2663
- width: attrs2.width ? parseRect(attrs2.width) : "100%",
2664
- height: attrs2.height ? parseRect(attrs2.height) : "400px",
2662
+ width: width ? parseRect(width) : "100%",
2663
+ height: height ? parseRect(height) : "400px",
2665
2664
  user,
2666
2665
  slash,
2667
- title: attrs2.title,
2668
- preview: attrs2.preview,
2669
- editable: attrs2.editable,
2670
- tab: attrs2.tab || "result",
2671
- theme: attrs2.theme
2666
+ title: title || "Code Pen",
2667
+ tab: tab3 || "result",
2668
+ ...rest
2672
2669
  };
2673
2670
  },
2674
- content: (meta) => {
2675
- const { title = "Codepen", height, width } = meta;
2676
- const params = new URLSearchParams();
2677
- if (meta.editable) {
2678
- params.set("editable", "true");
2679
- }
2680
- params.set("default-tab", meta.tab);
2681
- if (meta.theme) {
2682
- params.set("theme-id", meta.theme);
2683
- }
2684
- const middle = meta.preview ? "/embed/preview/" : "/embed/";
2685
- const link = `${CODEPEN_LINK}${meta.user}${middle}${meta.slash}?${params.toString()}`;
2686
- const style = `width:${width};height:${height};margin:16px auto;border-radius:5px;`;
2687
- return `<iframe class="code-pen-iframe-wrapper" src="${link}" title="${title}" style="${style}" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">See the Pen <a href="${CODEPEN_LINK}${meta.user}/pen/${meta.slash}">${title}</a> by ${meta.user} (<a href="${CODEPEN_LINK}${meta.user}">@${meta.user}</a>) on <a href="${CODEPEN_LINK}">CodePen</a>.</iframe>`;
2688
- }
2671
+ content: ({ title, height, width, user, slash, preview, editable, tab: tab3, theme }) => `<CodePenViewer user="${user}" slash="${slash}" title="${title}"${preview ? " preview" : ""}${editable ? " editable" : ""} tab="${tab3}"${theme ? ` theme="${theme}"` : ""} width="${width}" height="${height}" />`
2689
2672
  });
2690
2673
  };
2691
2674
 
@@ -2723,24 +2706,17 @@ var jsfiddlePlugin = (md) => {
2723
2706
  type: "jsfiddle",
2724
2707
  syntaxPattern: /^@\[jsfiddle([^\]]*)\]\(([^)]*)\)/,
2725
2708
  meta([, info, source]) {
2726
- const { attrs: attrs2 } = resolveAttrs(info);
2727
- const [user, id] = source.split("/");
2709
+ const { width, height, title, tab: tab3, theme } = resolveAttrs(info).attrs;
2728
2710
  return {
2729
- width: attrs2.width ? parseRect(attrs2.width) : "100%",
2730
- height: attrs2.height ? parseRect(attrs2.height) : "400px",
2731
- user,
2732
- id,
2733
- title: attrs2.title || "JS Fiddle",
2734
- tab: attrs2.tab?.replace(/\s+/g, "") || "js,css,html,result",
2735
- theme: attrs2.theme || "dark"
2711
+ width: width ? parseRect(width) : "100%",
2712
+ height: height ? parseRect(height) : "400px",
2713
+ source,
2714
+ title: title || "JS Fiddle",
2715
+ tab: tab3?.replace(/\s+/g, "") || "js,css,html,result",
2716
+ theme
2736
2717
  };
2737
2718
  },
2738
- content: ({ title, height, width, user, id, tab: tab3, theme }) => {
2739
- theme = theme === "dark" ? "/dark/" : "";
2740
- const link = `https://jsfiddle.net/${user}/${id}/embedded/${tab3}${theme}`;
2741
- const style = `width:${width};height:${height};margin:16px auto;border:none;border-radius:5px;`;
2742
- return `<iframe class="js-fiddle-iframe-wrapper" style="${style}" title="${title}" src="${link}" allowfullscreen="true" allowpaymentrequest="true"></iframe>`;
2743
- }
2719
+ content: ({ title, height, width, source, tab: tab3, theme }) => `<JSFiddleViewer source="${source}" title="${title}" tab="${tab3}" width="${width}" height="${height}"${theme ? ` theme="${theme}"` : ""} />`
2744
2720
  });
2745
2721
  };
2746
2722
 
@@ -2857,7 +2833,7 @@ function checkSupportType(type2) {
2857
2833
  }
2858
2834
 
2859
2835
  // src/node/embed/video/bilibili.ts
2860
- import { URLSearchParams as URLSearchParams2 } from "node:url";
2836
+ import { URLSearchParams } from "node:url";
2861
2837
 
2862
2838
  // src/node/utils/timeToSeconds.ts
2863
2839
  function timeToSeconds(time) {
@@ -2896,7 +2872,7 @@ var bilibiliPlugin = (md) => {
2896
2872
  };
2897
2873
  },
2898
2874
  content(meta) {
2899
- const params = new URLSearchParams2();
2875
+ const params = new URLSearchParams();
2900
2876
  if (meta.bvid) {
2901
2877
  params.set("bvid", meta.bvid);
2902
2878
  }
@@ -2920,7 +2896,7 @@ var bilibiliPlugin = (md) => {
2920
2896
  };
2921
2897
 
2922
2898
  // src/node/embed/video/youtube.ts
2923
- import { URLSearchParams as URLSearchParams3 } from "node:url";
2899
+ import { URLSearchParams as URLSearchParams2 } from "node:url";
2924
2900
  var YOUTUBE_LINK = "https://www.youtube.com/embed/";
2925
2901
  var youtubePlugin = (md) => {
2926
2902
  createEmbedRuleBlock(md, {
@@ -2942,7 +2918,7 @@ var youtubePlugin = (md) => {
2942
2918
  };
2943
2919
  },
2944
2920
  content(meta) {
2945
- const params = new URLSearchParams3();
2921
+ const params = new URLSearchParams2();
2946
2922
  if (meta.autoplay) {
2947
2923
  params.set("autoplay", "1");
2948
2924
  }
@@ -3138,12 +3114,9 @@ var abbrPlugin = (md) => {
3138
3114
  alt: ["paragraph", "reference"]
3139
3115
  });
3140
3116
  md.core.ruler.after("linkify", "abbr_replace", abbrReplace);
3141
- md.renderer.rules.abbreviation = (tokens, idx) => {
3117
+ md.renderer.rules.abbreviation = (tokens, idx, _, env) => {
3142
3118
  const { content, info } = tokens[idx];
3143
- return `<Abbreviation>
3144
- ${content}
3145
- ${info ? `<template #tooltip>${md.renderInline(info)}</template>` : ""}
3146
- </Abbreviation>`;
3119
+ return `<Abbreviation>${content}${info ? `<template #tooltip>${md.renderInline(info, env)}</template>` : ""}</Abbreviation>`;
3147
3120
  };
3148
3121
  };
3149
3122
 
@@ -3166,7 +3139,7 @@ var annotationDef = (state, startLine, endLine, silent) => {
3166
3139
  pos++;
3167
3140
  }
3168
3141
  if (
3169
- // empty footnote label
3142
+ // empty annotation label
3170
3143
  pos === start + 2 || pos + 1 >= max || state.src.charAt(++pos) !== ":"
3171
3144
  ) {
3172
3145
  return false;
@@ -3174,12 +3147,23 @@ var annotationDef = (state, startLine, endLine, silent) => {
3174
3147
  if (silent)
3175
3148
  return true;
3176
3149
  pos++;
3177
- state.env.annotations ??= {};
3150
+ const data = state.env.annotations ??= {};
3178
3151
  const label = state.src.slice(start + 2, pos - 2);
3179
- const annotation = state.src.slice(pos, max).trim();
3180
- state.env.annotations[`:${label}`] ??= [];
3181
- state.env.annotations[`:${label}`].push(annotation);
3182
- state.line += 1;
3152
+ let annotation = state.src.slice(pos, max).trim();
3153
+ let nextLine = startLine + 1;
3154
+ while (nextLine < endLine) {
3155
+ const nextStart = state.bMarks[nextLine] + state.tShift[nextLine];
3156
+ const nextMax = state.eMarks[nextLine];
3157
+ const source = state.src.slice(nextStart, nextMax).trim();
3158
+ if (state.sCount[nextLine] < state.blkIndent + 2 && source !== "")
3159
+ break;
3160
+ annotation += `
3161
+ ${source}`;
3162
+ nextLine++;
3163
+ }
3164
+ const current = data[`:${label}`] ??= { sources: [], rendered: [] };
3165
+ current.sources.push(annotation);
3166
+ state.line = nextLine;
3183
3167
  return true;
3184
3168
  };
3185
3169
  var annotationRef = (state, silent) => {
@@ -3207,28 +3191,25 @@ var annotationRef = (state, silent) => {
3207
3191
  }
3208
3192
  pos++;
3209
3193
  const label = state.src.slice(start + 2, pos - 1);
3210
- const annotations = state.env.annotations?.[`:${label}`] ?? [];
3194
+ const annotations = state.env.annotations?.[`:${label}`]?.sources ?? [];
3211
3195
  if (annotations.length === 0)
3212
3196
  return false;
3213
3197
  if (!silent) {
3214
3198
  const refToken = state.push("annotation_ref", "", 0);
3215
- refToken.meta = {
3216
- label,
3217
- annotations
3218
- };
3199
+ refToken.meta = { label };
3219
3200
  }
3220
3201
  state.pos = pos;
3221
3202
  state.posMax = max;
3222
3203
  return true;
3223
3204
  };
3224
3205
  var annotationPlugin = (md) => {
3225
- md.renderer.rules.annotation_ref = (tokens, idx) => {
3226
- const { label = "", annotations = [] } = tokens[idx].meta ?? {};
3227
- return `<Annotation label="${label}" :total="${annotations.length}">
3228
- ${annotations.map((annotation, i) => {
3229
- return `<template #item-${i}>${md.renderInline(annotation)}</template>`;
3230
- }).join("\n")}
3231
- </Annotation>`;
3206
+ md.renderer.rules.annotation_ref = (tokens, idx, _, env) => {
3207
+ const label = tokens[idx].meta.label;
3208
+ const data = env.annotations[`:${label}`];
3209
+ return `<Annotation label="${label}" :total="${data.sources.length}">${data.sources.map((source, i) => {
3210
+ const annotation = data.rendered[i] ??= md.render(source, env);
3211
+ return `<template #item-${i}>${annotation}</template>`;
3212
+ }).join("")}</Annotation>`;
3232
3213
  };
3233
3214
  md.inline.ruler.before("image", "annotation_ref", annotationRef);
3234
3215
  md.block.ruler.before("reference", "annotation", annotationDef, {
@@ -3377,6 +3358,14 @@ async function prepareConfigFile(app, options) {
3377
3358
  imports.add(`import Youtube from '${CLIENT_FOLDER}components/Youtube.vue'`);
3378
3359
  enhances.add(`app.component('VideoYoutube', Youtube)`);
3379
3360
  }
3361
+ if (options.codepen) {
3362
+ imports.add(`import CodePen from '${CLIENT_FOLDER}components/CodePen.vue'`);
3363
+ enhances.add(`app.component('CodePenViewer', CodePen)`);
3364
+ }
3365
+ if (options.jsfiddle) {
3366
+ imports.add(`import JSFiddle from '${CLIENT_FOLDER}components/JSFiddle.vue'`);
3367
+ enhances.add(`app.component('JSFiddleViewer', JSFiddle)`);
3368
+ }
3380
3369
  if (options.replit) {
3381
3370
  imports.add(`import Replit from '${CLIENT_FOLDER}components/Replit.vue'`);
3382
3371
  enhances.add(`app.component('ReplitViewer', Replit)`);
@@ -98,8 +98,7 @@ interface IconsOptions {
98
98
  }
99
99
 
100
100
  interface JSFiddleTokenMeta extends SizeOptions {
101
- user?: string;
102
- id?: string;
101
+ source: string;
103
102
  title?: string;
104
103
  theme?: string;
105
104
  tab?: string;
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.132",
4
+ "version": "1.0.0-rc.134",
5
5
  "description": "The Plugin for VuePress 2 - markdown power",
6
6
  "author": "pengzhanbo <volodymyr@foxmail.com>",
7
7
  "license": "MIT",
@@ -71,14 +71,14 @@
71
71
  "@vuepress/helper": "2.0.0-rc.79",
72
72
  "@vueuse/core": "^12.7.0",
73
73
  "chokidar": "3.6.0",
74
- "image-size": "^1.2.0",
75
- "local-pkg": "^1.0.0",
74
+ "image-size": "^2.0.0",
75
+ "local-pkg": "^1.1.0",
76
76
  "lru-cache": "^11.0.2",
77
77
  "markdown-it-container": "^4.0.0",
78
78
  "nanoid": "^5.1.2",
79
- "shiki": "^3.0.0",
80
- "tm-grammars": "^1.22.17",
81
- "tm-themes": "^1.9.13",
79
+ "shiki": "^3.1.0",
80
+ "tm-grammars": "^1.22.19",
81
+ "tm-themes": "^1.9.14",
82
82
  "vue": "^3.5.13"
83
83
  },
84
84
  "devDependencies": {
@@ -1,5 +0,0 @@
1
- declare function checkIsMobile(ua: string): boolean;
2
- declare function checkIsSafari(ua: string): boolean;
3
- declare function checkIsiPad(ua: string): boolean;
4
-
5
- export { checkIsMobile, checkIsSafari, checkIsiPad };
@@ -1,19 +0,0 @@
1
- // src/client/utils/is.ts
2
- function checkIsMobile(ua) {
3
- return /\b(?:Android|iPhone)/i.test(ua);
4
- }
5
- function checkIsSafari(ua) {
6
- return /version\/[\w.]+ .*(?:mobile ?safari|safari)/i.test(ua);
7
- }
8
- function checkIsiPad(ua) {
9
- return [
10
- /\((ipad);[-\w),; ]+apple/i,
11
- /applecoremedia\/[\w.]+ \((ipad)/i,
12
- /\b(ipad)\d\d?,\d\d?[;\]].+ios/i
13
- ].some((item) => item.test(ua));
14
- }
15
- export {
16
- checkIsMobile,
17
- checkIsSafari,
18
- checkIsiPad
19
- };