@@ -119,41 +39,35 @@ function render() {
-
-
@@ -183,6 +97,7 @@ function render() {
.caniuse-form-item:nth-child(3) {
align-items: baseline;
+ margin-bottom: 0;
}
.feature-input {
@@ -251,24 +166,40 @@ function render() {
.caniuse-browser-version {
flex: 1;
- flex-wrap: wrap;
margin-left: 10px;
}
-.caniuse-browser-version label {
- display: block;
+.caniuse-browser-version span {
+ display: none;
+}
+
+.caniuse-browser-version select {
+ flex: 1;
width: 100%;
- cursor: pointer;
+ padding: 3px 16px;
+ background-color: var(--vp-c-bg);
+ border: solid 1px var(--vp-c-divider);
+ transition: border var(--t-color), background-color var(--t-color);
+}
+
+.caniuse-browser-version select:first-of-type {
+ margin-bottom: 16px;
}
@media (min-width: 768px) {
.caniuse-browser-version {
display: flex;
- gap: 10px 0;
+ gap: 10px;
+ align-items: center;
+ justify-content: center;
}
- .caniuse-browser-version label {
- width: 50%;
+ .caniuse-browser-version span {
+ display: block;
+ }
+
+ .caniuse-browser-version select:first-of-type {
+ margin-bottom: 0;
}
}
diff --git a/docs/.vuepress/themes/composables/caniuse.ts b/docs/.vuepress/themes/composables/caniuse.ts
index 9ac85d3f..a6df2293 100644
--- a/docs/.vuepress/themes/composables/caniuse.ts
+++ b/docs/.vuepress/themes/composables/caniuse.ts
@@ -1,46 +1,164 @@
-export function resolveCanIUse(feature: string, mode: string, versions: string): string {
- if (!feature)
- return ''
+import { type Ref, computed, onMounted, readonly, ref, watch } from 'vue'
+import { onClickOutside, useDebounceFn, useEventListener, useLocalStorage } from '@vueuse/core'
- if (mode === 'image') {
- const link = 'https://caniuse.bitsofco.de/image/'
- const alt = `Data on support for the ${feature} feature across the major browsers from caniuse.com`
- return `
-
-
-
-
`
+interface Feature {
+ label: string
+ value: string
+}
+
+interface SelectItem {
+ label: string
+ value: string
+}
+
+const api = 'https://caniuse.pengzhanbo.cn/features.json'
+
+const pastVersions: SelectItem[] = [
+ { label: '不显示旧版本', value: '0' },
+ ...Array(5).fill(0).map((_, i) => ({
+ label: `旧版本(当前版本 - ${i + 1})`,
+ value: `${i + 1}`,
+ })),
+]
+
+const futureVersions: SelectItem[] = [
+ { label: '不显示未来版本', value: '0' },
+ ...Array(3).fill(0).map((_, i) => ({
+ label: `未来版本(当前版本 + ${i + 1})`,
+ value: `${i + 1}`,
+ })),
+]
+
+const embedTypes: SelectItem[] = [
+ { label: 'iframe', value: '' },
+ { label: 'image', value: 'image' },
+]
+
+export function useCaniuseVersionSelect() {
+ const past = ref('2')
+ const future = ref('1')
+ const embedType = ref('')
+
+ const pastList = readonly(pastVersions)
+ const futureList = readonly(futureVersions)
+ const embedTypeList = readonly(embedTypes)
+
+ return {
+ past,
+ future,
+ pastList,
+ futureList,
+ embedType,
+ embedTypeList,
+ }
+}
+
+export function useCaniuseFeaturesSearch(
+ inputEl: Ref
,
+ listEl: Ref,
+) {
+ const features = useLocalStorage('caniuse-features', [] as Feature[])
+ const featuresUpdated = useLocalStorage('caniuse-features-updated', Date.now())
+ const maxAge = 1000 * 60 * 60 * 24 * 3 // 3 days
+ onMounted(async () => {
+ if (typeof document === 'undefined')
+ return
+
+ if (features.value.length && Date.now() - featuresUpdated.value < maxAge)
+ return
+ const data = await fetch(api).then(res => res.json())
+ features.value = data || features.value || []
+ })
+
+ const input = ref('')
+ const isFocus = ref(false)
+ const searched = ref()
+
+ const selected = ref(null)
+
+ watch(() => [features.value, isFocus.value], () => {
+ if (!isFocus.value)
+ searched.value = features.value
+ }, { immediate: true })
+
+ onClickOutside(listEl, () => {
+ isFocus.value = false
+ }, { ignore: [inputEl] })
+
+ useEventListener(inputEl, 'input', useDebounceFn(() => {
+ selected.value = null
+ input.value = inputEl.value?.value || ''
+
+ if (!input.value) {
+ searched.value = features.value
+ }
+ else {
+ searched.value = features.value.filter(item => item.label.includes(input.value) || item.value.includes(input.value))
+ if (searched.value.length === 1)
+ selected.value = searched.value[0]
+ }
+ }, 500))
+
+ useEventListener(inputEl, 'focus', () => {
+ isFocus.value = true
+ })
+
+ function onSelect(item: Feature) {
+ selected.value = item
+ isFocus.value = false
+ if (inputEl.value)
+ inputEl.value.value = item.label
}
- const periods = resolveVersions(versions)
- const accessible = 'false'
- const image = 'none'
- const url = 'https://caniuse.bitsofco.de/embed/index.html'
- const src = `${url}?feat=${feature}&periods=${periods}&accessible-colours=${accessible}&image-base=${image}`
-
- return ``
+ return {
+ featureList: searched,
+ isFocus,
+ onSelect,
+ feature: computed(() => selected.value?.value || ''),
+ }
}
-function resolveVersions(versions: string): string {
- if (!versions)
- return 'future_1,current,past_1,past_2'
+export function useCaniuse({ feature, embedType, past, future }: {
+ feature: Ref
+ embedType: Ref
+ past: Ref
+ future: Ref
+}) {
+ const output = computed(() => {
+ let content = '@[caniuse'
+ if (embedType.value)
+ content += ` ${embedType.value}`
- const list = versions
- .split(',')
- .map(v => Number(v.trim()))
- .filter(v => !Number.isNaN(v) && v >= -5 && v <= 3)
+ if (past.value !== '-2' || future.value !== '1') {
+ if (past.value === '0' && future.value === '0')
+ content += '{0}'
+ else
+ content += `{-${past.value},${future.value}}`
+ }
- list.push(0)
+ content += ']('
- const uniq = [...new Set(list)].sort((a, b) => b - a)
- const result: string[] = []
- uniq.forEach((v) => {
- if (v < 0)
- result.push(`past_${Math.abs(v)}`)
- if (v === 0)
- result.push('current')
- if (v > 0)
- result.push(`future_${v}`)
+ if (feature.value)
+ content += feature.value
+
+ return `${content})`
})
- return result.join(',')
+
+ const rendered = computed(() => {
+ if (!feature.value || !embedType.value)
+ return ''
+ return resolveCanIUse(feature.value)
+ })
+
+ return { output, rendered }
+}
+
+function resolveCanIUse(feature: string): string {
+ const link = 'https://caniuse.bitsofco.de/image/'
+ const alt = `Data on support for the ${feature} feature across the major browsers from caniuse.com`
+ return `
+
+
+
+
`
}
diff --git a/docs/notes/plugins/caniuse.md b/docs/notes/plugins/caniuse.md
index b04ceb55..bf66ddae 100644
--- a/docs/notes/plugins/caniuse.md
+++ b/docs/notes/plugins/caniuse.md
@@ -5,6 +5,11 @@ createTime: 2024/03/11 17:22:52
permalink: /plugins/plugin-caniuse/
---
+:::warning Deprecated
+该插件功能已整合到 [vuepress-plugin-md-power](/plugins/plugin-md-power) 。
+因此,此插件不再更新维护,并标记为 弃用。
+:::
+
## 指南
为你的 vuepress 站点,在编写文章时, 提供嵌入 [can-i-use](https://caniuse.com/) WEB feature 各平台支持说明 的功能。
diff --git a/docs/notes/plugins/md-power.md b/docs/notes/plugins/md-power.md
index 4aa7243a..5b365579 100644
--- a/docs/notes/plugins/md-power.md
+++ b/docs/notes/plugins/md-power.md
@@ -41,7 +41,8 @@ pnpm add vuepress-plugin-md-power
```ts
// .vuepress/config.ts
import { markdownPowerPlugin } from 'vuepress-plugin-md-power'
-module.exports = {
+
+export default {
// ...
plugins: [
markdownPowerPlugin({
@@ -72,6 +73,7 @@ interface MarkdownPowerPluginOptions {
jsfiddle?: boolean
caniuse?: boolean | CanIUseOptions
+ repl?: boolean
}
```
@@ -85,23 +87,23 @@ interface MarkdownPowerPluginOptions {
```md
@[caniuse](feature)
-@[caniuse image](feature)
-@[caniuse embed{versions}](feature)
+@[caniuse image](feature) // 不再推荐使用
+@[caniuse embed{versionRange}](feature)
```
-你可以从 [caniuse](https://caniuse.bitsofco.de/) 获取 feature 的值。
+你可以从 [caniuse](https://caniuse.pengzhanbo.cn/) 获取 feature 的值。
默认情况下,插件通过 `iframe` 嵌入 `caniuse` 的支持情况查看器。
-你也可以使用 `@[caniuse image](feature)` 直接嵌入图片。
+~~你也可以使用 `@[caniuse image](feature)` 直接嵌入图片。~~
-caniuse 默认查看最近的5个浏览器版本。你可以通过 `{versions}` 手动设置查看的浏览器版本。
-格式为 `{number,number,...}`。取值范围为 `-5 ~ 3` 。
+caniuse 默认查看最近的5个浏览器版本。你可以通过 `{versionRange}` 手动设置查看的浏览器版本。
+格式为 `{past,future}` 表示 `{过去版本,未来版本}`。取值范围为 `-5 ~ 3` 。
- 小于0 表示低于当前浏览器版本的支持情况
- 0 表示当前浏览器版本的支持情况
- 大于0 表示高于当前浏览器版本的支持情况
-如 `{-2,-1,1,2}` 表示查看低于当前 2 个版本 到 高于当前 2 个版本的支持情况。
+如 `{-2,2}` 表示查看低于当前 2 个版本 到 高于当前 2 个版本的支持情况。
### pdf
@@ -280,3 +282,32 @@ pnpm add @iconify/json
- `tab`: 选项卡, 可选值:`"js" | "css" | "html" | "result"`, 多个用 `","` 分割,
顺序将决定选项卡的排序,默认为 `js,css,html,result`
- `height`: 高度
+
+### Repl
+
+插件默认不启用该功能,你需要手动设置 `repl` 为 `true`
+
+提供在 markdown 中为 `golang` 、`kotlin`、`rust` 语言的 在线代码演示 支持。
+在线编译执行代码,并输出结果。
+
+#### 语法
+
+````md
+::: go-repl
+```go
+// your go lang code
+```
+:::
+
+::: kotlin-repl
+```kotlin
+// your kotlin code
+```
+:::
+
+:::rust-repl
+```rust
+// your rust code
+```
+:::
+````
diff --git a/docs/notes/theme/config/plugins/markdownPower.md b/docs/notes/theme/config/plugins/markdownPower.md
index a49554f0..91000c87 100644
--- a/docs/notes/theme/config/plugins/markdownPower.md
+++ b/docs/notes/theme/config/plugins/markdownPower.md
@@ -31,6 +31,7 @@ export default defineUserConfig({
// codeSandbox: true, // @[codesandbox](id) 嵌入 CodeSandbox
// jsfiddle: true, // @[jsfiddle](id) 嵌入 jsfiddle
// caniuse: true, // @[caniuse](feature) 嵌入 caniuse
+ // repl: true, // :::go-repl :::kotlin-repl :::rust-repl
}
}
}),
diff --git a/docs/notes/theme/guide/markdown/进阶.md b/docs/notes/theme/guide/markdown/进阶.md
index 804ea107..5118752a 100644
--- a/docs/notes/theme/guide/markdown/进阶.md
+++ b/docs/notes/theme/guide/markdown/进阶.md
@@ -431,15 +431,15 @@ export default defineUserConfig({
- `feature`
- 必填。 正确取值请参考 [https://caniuse.bitsofco.de/](https://caniuse.bitsofco.de/)
+ 必填。 正确取值请参考 [caniuse-embed.vercel.app](https://caniuse-embed.vercel.app/zh-CN)
- `{browser_versions}`
可选。当前特性在多个版本中的支持情况。
- 默认值为: `{-2,-1,1}`
+ 默认值为: `{-2,1}`
- 格式: `{number,number,...}` 取值范围为 `-5 ~ 3`
+ 格式: `{past,future}` 取值范围为 `-5 ~ 3`
- 小于`0` 表示低于当前浏览器版本的支持情况
- `0` 表示当前浏览器版本的支持情况
@@ -453,6 +453,11 @@ export default defineUserConfig({
默认值为:`'embed'`
+:::caution
+不再推荐使用 image 类型,建议使用 embed 类型,主题更换了 embed 实现技术方案,
+现在的 embed 类型优势已远远超过 image 类型,加载速度更快,体积更小,交互体验更好。
+:::
+
### 示例
**获取 css 伪类选择器 `:dir()` 在各个浏览器的支持情况:**
@@ -478,12 +483,12 @@ export default defineUserConfig({
**获取 css 伪类选择器 `:dir()` 特定范围浏览器的支持情况:**
```md
-@[caniuse{-2,-1,1,2,3}](css-matches-pseudo)
+@[caniuse{-2,3}](css-matches-pseudo)
```
效果:
-@[caniuse{-2,-1,1,2,3}](css-matches-pseudo)
+@[caniuse{-2,3}](css-matches-pseudo)
## 导入文件
diff --git a/docs/notes/theme/guide/代码/codeSandbox.md b/docs/notes/theme/guide/代码演示/codeSandbox.md
similarity index 100%
rename from docs/notes/theme/guide/代码/codeSandbox.md
rename to docs/notes/theme/guide/代码演示/codeSandbox.md
diff --git a/docs/notes/theme/guide/代码/codepen.md b/docs/notes/theme/guide/代码演示/codepen.md
similarity index 100%
rename from docs/notes/theme/guide/代码/codepen.md
rename to docs/notes/theme/guide/代码演示/codepen.md
diff --git a/docs/notes/theme/guide/代码/jsFiddle.md b/docs/notes/theme/guide/代码演示/jsFiddle.md
similarity index 100%
rename from docs/notes/theme/guide/代码/jsFiddle.md
rename to docs/notes/theme/guide/代码演示/jsFiddle.md
diff --git a/docs/notes/theme/guide/代码/replit.md b/docs/notes/theme/guide/代码演示/replit.md
similarity index 100%
rename from docs/notes/theme/guide/代码/replit.md
rename to docs/notes/theme/guide/代码演示/replit.md
diff --git a/readme.md b/readme.md
index 34631cb0..7f45f34b 100644
--- a/readme.md
+++ b/readme.md
@@ -24,7 +24,7 @@
- 👀 支持 搜索、文章评论
- 👨💻 支持 浅色/深色 主题 (包括代码高亮)
- 📠 markdown 增强,支持 代码块分组、提示容器、任务列表、数学公式、代码演示 等
-- 📚 代码演示,支持 CodePen, Replit
+- 📚 代码演示,支持 CodePen, Replit, JSFiddle, CodeSandbox 等
- 📊 嵌入图标,支持 chart.js,Echarts,Mermaid,flowchart
- 🎛 资源嵌入,支持 PDF, bilibili视频,youtube视频等