diff --git a/docs/.vuepress/notes.ts b/docs/.vuepress/notes.ts index 89bd91ce..456e6bc4 100644 --- a/docs/.vuepress/notes.ts +++ b/docs/.vuepress/notes.ts @@ -29,13 +29,13 @@ export const zhNotes = definePlumeNotesConfig({ text: '代码块', dir: '代码', icon: 'ph:code-bold', - items: ['介绍', '特性支持', '代码组', '导入代码', 'codepen', 'jsFiddle', 'codeSandbox', 'replit', 'twoslash', '代码演示'], + items: ['介绍', '特性支持', '代码组', '导入代码', 'twoslash'], }, { text: '代码演示', dir: '代码演示', icon: 'carbon:demo', - items: ['前端', 'rust', 'golang', 'kotlin'], + items: ['前端', 'rust', 'golang', 'kotlin', 'codepen', 'jsFiddle', 'codeSandbox', 'replit'], }, { text: '图表', diff --git a/docs/.vuepress/themes/components/CanIUseConfig.vue b/docs/.vuepress/themes/components/CanIUseConfig.vue index b4306e55..3f714a30 100644 --- a/docs/.vuepress/themes/components/CanIUseConfig.vue +++ b/docs/.vuepress/themes/components/CanIUseConfig.vue @@ -1,101 +1,14 @@ @@ -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 `

- - - ${alt} -

` +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 `

+ + + ${alt} +

` } 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视频等