+
diff --git a/plugins/plugin-md-power/src/client/components/VPDemoNormal.vue b/plugins/plugin-md-power/src/client/components/VPDemoNormal.vue
index 58ef38e6..35b3ec36 100644
--- a/plugins/plugin-md-power/src/client/components/VPDemoNormal.vue
+++ b/plugins/plugin-md-power/src/client/components/VPDemoNormal.vue
@@ -7,6 +7,7 @@ import '../styles/demo.css'
const props = defineProps<{
title?: string
desc?: string
+ expanded?: boolean
config?: {
html: string
css: string
@@ -48,7 +49,40 @@ onMounted(() => {
}, { immediate: true })
})
-const showCode = ref(false)
+const fence = useTemplateRef
('fence')
+const data = ref<{
+ js: string
+ css: string
+ html: string
+ jsType: string
+ cssType: string
+}>({ js: '', css: '', html: '', jsType: '', cssType: '' })
+
+onMounted(() => {
+ if (!fence.value)
+ return
+
+ data.value.html = props.config?.html ?? ''
+ const els = Array.from(fence.value.querySelectorAll('div[class*="language-"]'))
+ for (const el of els) {
+ const lang = el.className.match(/language-(\w+)/)?.[1] ?? ''
+ const content = (el.querySelector('pre')?.textContent ?? '')
+ if (lang === 'js' || lang === 'javascript') {
+ data.value.js = content
+ data.value.jsType = 'js'
+ }
+ if (lang === 'ts' || lang === 'typescript') {
+ data.value.js = content
+ data.value.jsType = 'ts'
+ }
+ if (lang === 'css' || lang === 'scss' || lang === 'less' || lang === 'stylus' || lang === 'styl') {
+ data.value.css = content
+ data.value.cssType = lang === 'styl' ? 'stylus' : lang
+ }
+ }
+})
+
+const showCode = ref(props.expanded ?? false)
function toggleCode() {
showCode.value = !showCode.value
}
@@ -68,9 +102,43 @@ function toggleCode() {
+
-
diff --git a/plugins/plugin-md-power/src/client/styles/demo.css b/plugins/plugin-md-power/src/client/styles/demo.css
index 8144bcc7..2f3a2448 100644
--- a/plugins/plugin-md-power/src/client/styles/demo.css
+++ b/plugins/plugin-md-power/src/client/styles/demo.css
@@ -56,17 +56,32 @@
transition: border-color var(--vp-t-color);
}
-.vp-demo-wrapper .demo-ctrl > [class*="vpi-"] {
- font-size: 1.2em;
+.vp-demo-wrapper .demo-ctrl .extra {
+ display: flex;
+ flex: 1;
+ gap: 16px;
+ align-items: center;
+ justify-content: flex-start;
+}
+
+.vp-demo-wrapper .demo-ctrl [class*="vpi-"] {
+ font-size: 20px;
color: var(--vp-c-text-2);
cursor: pointer;
transition: color var(--vp-t-color);
}
-.vp-demo-wrapper .demo-ctrl > [class*="vpi-"]:hover {
+.vp-demo-wrapper .demo-ctrl [class*="vpi-"]:hover {
color: var(--vp-c-text-1);
}
+.vp-demo-wrapper .demo-ctrl form,
+.vp-demo-wrapper .demo-ctrl button {
+ padding: 0;
+ margin: 0;
+ line-height: 1;
+}
+
.vp-demo-wrapper .demo-code {
border-top: 1px solid var(--vp-c-divider);
transition: border-color var(--vp-t-color);
@@ -91,3 +106,11 @@
.vpi-demo-code {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M14.18 4.276a.75.75 0 0 1 .531.918l-3.973 14.83a.75.75 0 0 1-1.45-.389l3.974-14.83a.75.75 0 0 1 .919-.53m2.262 3.053a.75.75 0 0 1 1.059-.056l1.737 1.564c.737.662 1.347 1.212 1.767 1.71c.44.525.754 1.088.754 1.784c0 .695-.313 1.258-.754 1.782c-.42.499-1.03 1.049-1.767 1.711l-1.737 1.564a.75.75 0 0 1-1.004-1.115l1.697-1.527c.788-.709 1.319-1.19 1.663-1.598c.33-.393.402-.622.402-.818s-.072-.424-.402-.817c-.344-.409-.875-.89-1.663-1.598l-1.697-1.527a.75.75 0 0 1-.056-1.06m-8.94 1.06a.75.75 0 1 0-1.004-1.115L4.761 8.836c-.737.662-1.347 1.212-1.767 1.71c-.44.525-.754 1.088-.754 1.784c0 .695.313 1.258.754 1.782c.42.499 1.03 1.049 1.767 1.711l1.737 1.564a.75.75 0 0 0 1.004-1.115l-1.697-1.527c-.788-.709-1.319-1.19-1.663-1.598c-.33-.393-.402-.622-.402-.818s.072-.424.402-.817c.344-.409.875-.89 1.663-1.598z'/%3E%3C/svg%3E");
}
+
+.vpi-demo-codepen {
+ --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1024' height='1024' viewBox='0 0 1024 1024'%3E%3Cpath fill='%23000' d='m911.7 385.3l-.3-1.5c-.2-1-.3-1.9-.6-2.9c-.2-.6-.4-1.1-.5-1.7c-.3-.8-.5-1.7-.9-2.5c-.2-.6-.5-1.1-.8-1.7c-.4-.8-.8-1.5-1.2-2.3c-.3-.5-.6-1.1-1-1.6c-.8-1.2-1.7-2.4-2.6-3.6c-.5-.6-1.1-1.3-1.7-1.9c-.4-.5-.9-.9-1.4-1.3c-.6-.6-1.3-1.1-1.9-1.6c-.5-.4-1-.8-1.6-1.2c-.2-.1-.4-.3-.6-.4L531.1 117.8a34.3 34.3 0 0 0-38.1 0L127.3 361.3c-.2.1-.4.3-.6.4c-.5.4-1 .8-1.6 1.2c-.7.5-1.3 1.1-1.9 1.6c-.5.4-.9.9-1.4 1.3c-.6.6-1.2 1.2-1.7 1.9c-1 1.1-1.8 2.3-2.6 3.6c-.3.5-.7 1-1 1.6c-.4.7-.8 1.5-1.2 2.3c-.3.5-.5 1.1-.8 1.7c-.3.8-.6 1.7-.9 2.5c-.2.6-.4 1.1-.5 1.7c-.2.9-.4 1.9-.6 2.9l-.3 1.5q-.3 2.25-.3 4.5v243.5q0 2.25.3 4.5l.3 1.5l.6 2.9c.2.6.3 1.1.5 1.7c.3.9.6 1.7.9 2.5c.2.6.5 1.1.8 1.7c.4.8.7 1.5 1.2 2.3c.3.5.6 1.1 1 1.6c.5.7.9 1.4 1.5 2.1l1.2 1.5c.5.6 1.1 1.3 1.7 1.9c.4.5.9.9 1.4 1.3c.6.6 1.3 1.1 1.9 1.6c.5.4 1 .8 1.6 1.2c.2.1.4.3.6.4L493 905.7c5.6 3.8 12.3 5.8 19.1 5.8c6.6 0 13.3-1.9 19.1-5.8l365.6-243.5c.2-.1.4-.3.6-.4c.5-.4 1-.8 1.6-1.2c.7-.5 1.3-1.1 1.9-1.6c.5-.4.9-.9 1.4-1.3c.6-.6 1.2-1.2 1.7-1.9l1.2-1.5l1.5-2.1c.3-.5.7-1 1-1.6c.4-.8.8-1.5 1.2-2.3c.3-.5.5-1.1.8-1.7c.3-.8.6-1.7.9-2.5c.2-.5.4-1.1.5-1.7c.3-.9.4-1.9.6-2.9l.3-1.5q.3-2.25.3-4.5V389.8c-.3-1.5-.4-3-.6-4.5M546.4 210.5l269.4 179.4l-120.3 80.4l-149-99.6V210.5zm-68.8 0v160.2l-149 99.6l-120.3-80.4zM180.7 454.1l86 57.5l-86 57.5zm296.9 358.5L208.3 633.2l120.3-80.4l149 99.6zM512 592.8l-121.6-81.2L512 430.3l121.6 81.2zm34.4 219.8V652.4l149-99.6l120.3 80.4zM843.3 569l-86-57.5l86-57.5z'/%3E%3C/svg%3E");
+}
+
+.vpi-demo-jsfiddle {
+ --icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='180' viewBox='0 0 256 180'%3E%3Cpath fill='%230084ff' d='M148.1 0c42.8 0 77.598 34.087 78.393 76.452l.014 1.481l-.011.866l1.46.76c16.183 8.773 26.938 25.332 27.964 44.018l.061 1.52l.019 1.418c0 29.117-23.397 52.75-52.428 53.295l-1.365.008H54.053C24.094 179.357 0 155.102 0 125.276c0-17.387 8.273-33.328 21.838-43.511l1.287-.938l.271-.19l-.135-.684a39 39 0 0 1-.438-3.347l-.11-1.694l-.037-1.705c0-21.519 17.547-38.95 39.173-38.95a39 39 0 0 1 16.063 3.445l1.483.706l.915.478l.978-1.623A78.37 78.37 0 0 1 144.718.072l1.721-.055zm0 11.13a67.24 67.24 0 0 0-60.69 38.113c-1.53 3.187-5.607 4.157-8.41 2c-4.908-3.776-10.875-5.856-17.151-5.856c-15.495 0-28.043 12.465-28.043 27.82c0 2.852.43 5.638 1.261 8.27a5.565 5.565 0 0 1-2.473 6.468c-13.215 7.815-21.464 21.854-21.464 37.33c0 23.308 18.526 42.367 41.76 43.376l1.249.038h148.103c23.526.144 42.628-18.783 42.628-42.174c0-17.244-10.49-32.572-26.266-39.1a5.57 5.57 0 0 1-3.43-4.87l.002-.586l.15-2.415l.047-1.246l-.012-1.798c-.768-36.225-30.578-65.37-67.262-65.37m16.167 70.493c17.519 0 31.876 13.362 31.876 30.052s-14.357 30.053-31.876 30.053c-10.548 0-19.386-5.284-31.203-16.729l-2.58-2.547l-3.436-3.525q-6.525-6.955-6.774-7.468l-1.321-1.363l-2.384-2.395a140 140 0 0 0-4.457-4.226l-2.087-1.835c-7.155-6.106-12.769-8.886-18.292-8.886c-11.543 0-20.746 8.564-20.746 18.921c0 10.358 9.203 18.922 20.746 18.922c6.002 0 10.482-1.965 14.584-5.612a35 35 0 0 0 1.57-1.491l2.941-3.133a5.565 5.565 0 0 1 8.5 7.161l-.51.591l-2.033 2.191a50 50 0 0 1-3.072 2.998c-6.013 5.348-13.03 8.426-21.98 8.426c-17.519 0-31.876-13.362-31.876-30.053c0-16.69 14.357-30.052 31.876-30.052c11.678 0 21.26 6.476 35.11 20.62q8.632 9.135 8.88 9.644l2.53 2.59c11.124 11.178 18.65 16.12 26.014 16.12c11.543 0 20.746-8.564 20.746-18.922c0-10.357-9.203-18.921-20.746-18.921c-6.002 0-10.482 1.965-14.584 5.612a35 35 0 0 0-1.57 1.49l-1.311 1.373l-1.63 1.76a5.565 5.565 0 0 1-8.108-7.625l2.15-2.318a50 50 0 0 1 3.073-2.998c6.013-5.347 13.03-8.425 21.98-8.425'/%3E%3C/svg%3E");
+}
diff --git a/plugins/plugin-md-power/src/node/demo/demo.ts b/plugins/plugin-md-power/src/node/demo/demo.ts
index e829890a..e53e7e41 100644
--- a/plugins/plugin-md-power/src/node/demo/demo.ts
+++ b/plugins/plugin-md-power/src/node/demo/demo.ts
@@ -6,6 +6,7 @@ import type { DemoContainerRender, DemoMeta, MarkdownDemoEnv } from '../../share
import container from 'markdown-it-container'
import { createEmbedRuleBlock } from '../embed/createEmbedRuleBlock.js'
import { resolveAttrs } from '../utils/resolveAttrs.js'
+import { markdownContainerRender, markdownEmbed } from './markdown.js'
import { normalContainerRender, normalEmbed } from './normal.js'
import { normalizeAlias } from './supports/alias.js'
import { vueContainerRender, vueEmbed } from './vue.js'
@@ -13,7 +14,7 @@ import { vueContainerRender, vueEmbed } from './vue.js'
export function demoEmbed(app: App, md: Markdown) {
createEmbedRuleBlock
(md, {
type: 'demo',
- syntaxPattern: /^@\[demo(?:\s(vue|normal))?\s?(.*)\]\((.*)\)/,
+ syntaxPattern: /^@\[demo(?:\s(vue|normal|markdown))?\s?(.*)\]\((.*)\)/,
meta: ([, type, info, url]) => ({
type: (type || 'normal') as DemoMeta['type'],
url,
@@ -33,15 +34,20 @@ export function demoEmbed(app: App, md: Markdown) {
return normalEmbed(app, md, env, meta)
}
+ if (type === 'markdown') {
+ return markdownEmbed(app, md, env, meta)
+ }
+
return content
},
})
}
-const INFO_RE = /(vue|normal)?\s?(.*)/
+const INFO_RE = /(vue|normal|markdown)?\s?(.*)/
const renderMap: Record = {
vue: vueContainerRender,
normal: normalContainerRender,
+ markdown: markdownContainerRender,
}
export function demoContainer(app: App, md: Markdown) {
diff --git a/plugins/plugin-md-power/src/node/demo/extendPage.ts b/plugins/plugin-md-power/src/node/demo/extendPage.ts
index 6a01792d..b643aa82 100644
--- a/plugins/plugin-md-power/src/node/demo/extendPage.ts
+++ b/plugins/plugin-md-power/src/node/demo/extendPage.ts
@@ -5,11 +5,11 @@ export function extendsPageWithDemo(page: Page): void {
const markdownEnv = page.markdownEnv as MarkdownDemoEnv
const demoFiles = markdownEnv.demoFiles ?? []
- // page.deps.push(
- // ...demoFiles
- // .filter(({ type }) => type !== 'vue')
- // .map(({ path }) => path),
- // )
+ page.deps.push(
+ ...demoFiles
+ .filter(({ type }) => type === 'markdown')
+ .map(({ path }) => path),
+ )
;((page.frontmatter.gitInclude as string[] | undefined) ??= []).push(
...demoFiles.filter(({ gitignore }) => !gitignore).map(({ path }) => path),
diff --git a/plugins/plugin-md-power/src/node/demo/markdown.ts b/plugins/plugin-md-power/src/node/demo/markdown.ts
new file mode 100644
index 00000000..5343e60f
--- /dev/null
+++ b/plugins/plugin-md-power/src/node/demo/markdown.ts
@@ -0,0 +1,43 @@
+import type { App } from 'vuepress'
+import type { Markdown } from 'vuepress/markdown'
+import type { DemoContainerRender, DemoFile, DemoMeta, MarkdownDemoEnv } from '../../shared/demo.js'
+import { findFile, readFileSync } from './supports/file.js'
+
+export function markdownEmbed(
+ app: App,
+ md: Markdown,
+ env: MarkdownDemoEnv,
+ { url, title, desc, codeSetting = '', expanded = false }: DemoMeta,
+): string {
+ const filepath = findFile(app, env, url)
+ const code = readFileSync(filepath)
+ if (code === false) {
+ console.warn('[vuepress-plugin-md-power] Cannot read markdown file:', filepath)
+ return ''
+ }
+ const demo: DemoFile = { type: 'markdown', path: filepath }
+
+ env.demoFiles ??= []
+
+ if (!env.demoFiles.some(d => d.path === filepath)) {
+ env.demoFiles.push(demo)
+ }
+
+ return `
+ ${md.render(code, { filepath: env.filePath, filepathRelative: env.filePathRelative })}
+
+ ${md.render(`\`\`\`md ${codeSetting}\n${code}\n\`\`\``, {})}
+
+ `
+}
+
+export const markdownContainerRender: DemoContainerRender = {
+ before(app, md, env, meta, codeMap) {
+ const { title, desc, expanded = false } = meta
+ const code = codeMap.md || ''
+ return `
+ ${md.render(code, { filepath: env.filePath, filepathRelative: env.filePathRelative })}
+ `
+ },
+ after: () => '',
+}
diff --git a/plugins/plugin-md-power/src/node/demo/normal.ts b/plugins/plugin-md-power/src/node/demo/normal.ts
index b47d774d..14e469ca 100644
--- a/plugins/plugin-md-power/src/node/demo/normal.ts
+++ b/plugins/plugin-md-power/src/node/demo/normal.ts
@@ -99,7 +99,7 @@ export function normalEmbed(
app: App,
md: Markdown,
env: MarkdownDemoEnv,
- { url, title, desc, codeSetting = '' }: DemoMeta,
+ { url, title, desc, codeSetting = '', expanded = false }: DemoMeta,
): string {
const filepath = findFile(app, env, url)
const code = readFileSync(filepath)
@@ -126,14 +126,14 @@ export function normalEmbed(
insertSetupScript({ ...demo, path: output }, env)
}
- return `
+ return `
${codeToHtml(md, source, codeSetting)}
`
}
export const normalContainerRender: DemoContainerRender = {
before(app, md, env, meta, codeMap) {
- const { url, title, desc } = meta
+ const { url, title, desc, expanded = false } = meta
const name = `DemoContainer${url}`
const prefix = (env.filePathRelative || '').replace(/\.md$/, '').replace(/\//g, '-')
const output = app.dir.temp(path.join(target, `${prefix}-${name}.js`))
@@ -148,7 +148,7 @@ export const normalContainerRender: DemoContainerRender = {
const source = parseContainerCode(codeMap)
compileCode(source, output)
- return ``
+ return ``
},
after: () => '',
diff --git a/plugins/plugin-md-power/src/node/demo/supports/alias.ts b/plugins/plugin-md-power/src/node/demo/supports/alias.ts
index 4007e620..0ab102df 100644
--- a/plugins/plugin-md-power/src/node/demo/supports/alias.ts
+++ b/plugins/plugin-md-power/src/node/demo/supports/alias.ts
@@ -12,6 +12,9 @@ export function normalizeAlias(info: string): string {
case 'stylus':
case 'styl':
return 'stylus'
+ case 'md':
+ case 'markdown':
+ return 'md'
}
return lang
}
diff --git a/plugins/plugin-md-power/src/node/demo/vue.ts b/plugins/plugin-md-power/src/node/demo/vue.ts
index 0ddb625b..00a108e7 100644
--- a/plugins/plugin-md-power/src/node/demo/vue.ts
+++ b/plugins/plugin-md-power/src/node/demo/vue.ts
@@ -9,7 +9,7 @@ export function vueEmbed(
app: App,
md: Markdown,
env: MarkdownDemoEnv,
- { url, title, desc, codeSetting = '' }: DemoMeta,
+ { url, title, desc, codeSetting = '', expanded = false }: DemoMeta,
): string {
const filepath = findFile(app, env, url)
const code = readFileSync(filepath)
@@ -29,19 +29,19 @@ export function vueEmbed(
insertSetupScript(demo, env)
}
- return `
+ return `
<${name} />
${md.render(`\`\`\`vue${codeSetting}\n${code}\n\`\`\``, {})}
- `
+ `
}
const target = 'md-power/demo/vue'
export const vueContainerRender: DemoContainerRender = {
before: (app, md, env, meta, codeMap) => {
- const { url, title, desc } = meta
+ const { url, title, desc, expanded = false } = meta
const componentName = `DemoContainer${url}`
const prefix = (env.filePathRelative || '').replace(/\.md$/, '').replace(/\//g, '-')
env.demoFiles ??= []
@@ -100,11 +100,11 @@ export const vueContainerRender: DemoContainerRender = {
}
}
- return `
+ return `
<${componentName} />
\n`
},
- after: () => '',
+ after: () => '',
}
const IMPORT_RE = /import\s+(?:\w+\s+from\s+)?['"]([^'"]+)['"]/g
diff --git a/plugins/plugin-md-power/src/node/prepareConfigFile.ts b/plugins/plugin-md-power/src/node/prepareConfigFile.ts
index 2324df67..2ebf288c 100644
--- a/plugins/plugin-md-power/src/node/prepareConfigFile.ts
+++ b/plugins/plugin-md-power/src/node/prepareConfigFile.ts
@@ -76,9 +76,9 @@ export async function prepareConfigFile(app: App, options: MarkdownPowerPluginOp
}
if (options.demo) {
- imports.add(`import VPDemoVue from '${CLIENT_FOLDER}components/VPDemoVue.vue'`)
+ imports.add(`import VPDemoBasic from '${CLIENT_FOLDER}components/VPDemoBasic.vue'`)
imports.add(`import VPDemoNormal from '${CLIENT_FOLDER}components/VPDemoNormal.vue'`)
- enhances.add(`app.component('VPDemoVue', VPDemoVue)`)
+ enhances.add(`app.component('VPDemoBasic', VPDemoBasic)`)
enhances.add(`app.component('VPDemoNormal', VPDemoNormal)`)
}
diff --git a/plugins/plugin-md-power/src/shared/demo.ts b/plugins/plugin-md-power/src/shared/demo.ts
index c8963466..2f600e1e 100644
--- a/plugins/plugin-md-power/src/shared/demo.ts
+++ b/plugins/plugin-md-power/src/shared/demo.ts
@@ -3,7 +3,7 @@ import type { App } from 'vuepress'
import type { Markdown, MarkdownEnv } from 'vuepress/markdown'
export interface DemoFile {
- type: 'vue' | 'normal' | 'css'
+ type: 'vue' | 'normal' | 'css' | 'markdown'
export?: string
path: string
gitignore?: boolean
@@ -14,11 +14,12 @@ export interface MarkdownDemoEnv extends MarkdownEnv {
}
export interface DemoMeta {
- type: 'vue' | 'normal'
+ type: 'vue' | 'normal' | 'markdown'
url: string
title?: string
desc?: string
codeSetting?: string
+ expanded?: boolean
}
export interface DemoContainerRender {