diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts index 9aed9138..7ce369de 100644 --- a/docs/.vuepress/theme.ts +++ b/docs/.vuepress/theme.ts @@ -73,6 +73,7 @@ export const theme: Theme = themePlume({ youtube: true, icons: true, codepen: true, + replit: true, }, comment: { provider: 'Giscus', diff --git a/docs/README.md b/docs/README.md index 47a20544..60737bc4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -77,8 +77,11 @@ config: title: 加密 description: 支持全站加密、部分加密(加密目录、加密文章)。 - - title: 代码复制 - description: 一键复制代码块中的内容 + title: 代码 + description: 代码复制,CodePen演示,Replit演示 + - + title: 资源嵌入 + description: 图表,视频,PDF - type: text-image title: 博客 diff --git a/docs/notes/theme/guide/markdown/进阶.md b/docs/notes/theme/guide/markdown/进阶.md index 4ff9981d..29c2f016 100644 --- a/docs/notes/theme/guide/markdown/进阶.md +++ b/docs/notes/theme/guide/markdown/进阶.md @@ -476,6 +476,63 @@ export default defineUserConfig({ @[codepen editable tab="html,result"](leimapapa/RwOZQOW) +## Replit + +主题支持在 Markdown 文件中嵌入 [Replit](https://replit.com/)。 + +### 配置 + +此功能默认不启用,你可以在配置文件中启用它。 + +::: code-tabs +@tab .vuepress/config.ts + +```ts +export default defineUserConfig({ + theme: plumeTheme({ + plugins: { + markdownPower: { + replit: true, // [!code highlight] + }, + } + }) +}) +``` + +::: + +### 语法 + +简单的语法 + +```md +@[replit](user/repl-name) +``` + +更多选项 + +```md +@[replit title="" width="100%" height="450px" theme="dark"](user/repl-name#filepath) +``` + +- `title`: 标题 +- `width`: 容器宽度 +- `height`: 容器高度 +- `theme`: 主题, 可选值 `dark` 和 `light` +- `user`: Replit 用户名 +- `repl-name`: Replit repl 名称 +- `filepath`: Replit 默认打开的文件路径 + +输入: + +```md +@[replit](@TechPandaPro/Cursor-Hangout#package.json) +```` + +输出: + +@[replit](@TechPandaPro/Cursor-Hangout#package.json) + ## 导入文件 主题支持在 Markdown 文件中导入文件切片。 diff --git a/docs/notes/theme/guide/介绍.md b/docs/notes/theme/guide/介绍.md index b9d3f751..d1b89e2f 100644 --- a/docs/notes/theme/guide/介绍.md +++ b/docs/notes/theme/guide/介绍.md @@ -42,3 +42,6 @@ VuePress 是一个 [静态站点生成器](https://en.wikipedia.org/wiki/Static_ - 👀 支持 搜索、文章评论 - 👨‍💻‍ 支持 浅色/深色 主题 (包括代码高亮) - 📠 markdown 增强,支持 代码块分组、提示容器、任务列表、数学公式、代码演示 等 +- 📚 代码演示,支持 CodePen, Replit +- 📊 嵌入图标,支持 chart.js,Echarts,Mermaid,flowchart +- 🎛 资源嵌入,支持 PDF, bilibili视频,youtube视频等 diff --git a/plugins/plugin-md-power/src/client/components/Youtube.vue b/plugins/plugin-md-power/src/client/components/Youtube.vue index ffb33b4e..04e2e8df 100644 --- a/plugins/plugin-md-power/src/client/components/Youtube.vue +++ b/plugins/plugin-md-power/src/client/components/Youtube.vue @@ -15,10 +15,6 @@ const IFRAME_ALLOW = 'accelerometer; autoplay; clipboard-write; encrypted-media; const options = toRefs(props) const { el, width, height, resize } = useSize(options) - -function onLoad() { - resize() -} diff --git a/plugins/plugin-md-power/src/client/config.ts b/plugins/plugin-md-power/src/client/config.ts index a29aeef0..7ab308c6 100644 --- a/plugins/plugin-md-power/src/client/config.ts +++ b/plugins/plugin-md-power/src/client/config.ts @@ -5,6 +5,7 @@ import { setupCanIUse } from './composables/setupCanIUse.js' import PDFViewer from './components/PDFViewer.vue' import Bilibili from './components/Bilibili.vue' import Youtube from './components/Youtube.vue' +import Replit from './components/Replit.vue' import '@internal/md-power/icons.css' @@ -21,6 +22,9 @@ export default defineClientConfig({ if (pluginOptions.youtube) app.component('VideoYoutube', Youtube) + if (pluginOptions.replit) + app.component('ReplitViewer', Replit) + if (__VUEPRESS_SSR__) return diff --git a/plugins/plugin-md-power/src/node/plugin.ts b/plugins/plugin-md-power/src/node/plugin.ts index 517cb23c..3604e7d5 100644 --- a/plugins/plugin-md-power/src/node/plugin.ts +++ b/plugins/plugin-md-power/src/node/plugin.ts @@ -7,6 +7,7 @@ import { createIconCSSWriter, iconsPlugin } from './features/icons/index.js' import { bilibiliPlugin } from './features/video/bilibili.js' import { youtubePlugin } from './features/video/youtube.js' import { codepenPlugin } from './features/codepen.js' +import { replitPlugin } from './features/replit.js' const __dirname = getDirname(import.meta.url) @@ -58,6 +59,11 @@ export function markdownPowerPlugin(options: MarkdownPowerPluginOptions = {}): P // @[codepen](user/slash) md.use(codepenPlugin) } + + if (options.replit) { + // @[replit](user/repl-name) + md.use(replitPlugin) + } }, } } diff --git a/plugins/plugin-md-power/src/shared/plugin.ts b/plugins/plugin-md-power/src/shared/plugin.ts index 17f8565d..31575788 100644 --- a/plugins/plugin-md-power/src/shared/plugin.ts +++ b/plugins/plugin-md-power/src/shared/plugin.ts @@ -3,16 +3,18 @@ import type { PDFOptions } from './pdf.js' import type { IconsOptions } from './icons.js' export interface MarkdownPowerPluginOptions { - pdf?: boolean | PDFOptions + + // new syntax icons?: boolean | IconsOptions - // video + // video embed bilibili?: boolean youtube?: boolean - // code + // code embed codepen?: boolean + replit?: boolean caniuse?: boolean | CanIUseOptions } diff --git a/theme/src/client/composables/darkMode.ts b/theme/src/client/composables/darkMode.ts index c0a7e153..fd3e37f9 100644 --- a/theme/src/client/composables/darkMode.ts +++ b/theme/src/client/composables/darkMode.ts @@ -1,5 +1,5 @@ -import { inject, onMounted, provide, ref } from 'vue' -import type { InjectionKey, Ref } from 'vue' +import { inject, onMounted, ref } from 'vue' +import type { App, InjectionKey, Ref } from 'vue' export type DarkModeRef = Ref @@ -22,10 +22,18 @@ export function useDarkMode(): DarkModeRef { * Create dark mode ref and provide as global computed in setup */ export function setupDarkMode(): void { - const isDark = ref(false) + const isDark = useDarkMode() onMounted(() => { if (document.documentElement.classList.contains('dark')) isDark.value = true }) - provide(darkModeSymbol, isDark) +} + +export function injectDarkMode(app: App): void { + const isDark = ref(false) + app.provide(darkModeSymbol, isDark) + + Object.defineProperty(app.config.globalProperties, '$isDark', { + get: () => isDark, + }) } diff --git a/theme/src/client/config.ts b/theme/src/client/config.ts index b2cf7e55..a14301ea 100644 --- a/theme/src/client/config.ts +++ b/theme/src/client/config.ts @@ -5,13 +5,15 @@ import type { ClientConfig } from 'vuepress/client' import { h } from 'vue' import Badge from './components/global/Badge.vue' import ExternalLinkIcon from './components/global/ExternalLinkIcon.vue' -import { setupDarkMode, useScrollPromise } from './composables/index.js' +import { injectDarkMode, setupDarkMode, useScrollPromise } from './composables/index.js' import Layout from './layouts/Layout.vue' import NotFound from './layouts/NotFound.vue' import HomeBox from './components/Home/HomeBox.vue' export default defineClientConfig({ enhance({ app, router }) { + injectDarkMode(app) + // global component app.component('Badge', Badge)