Skip to content

Commit

Permalink
feat: support demo file
Browse files Browse the repository at this point in the history
  • Loading branch information
zuofenghua committed Aug 3, 2020
1 parent 5419abd commit 5695129
Show file tree
Hide file tree
Showing 12 changed files with 511 additions and 263 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"editor.tabSize": 2
}
2 changes: 2 additions & 0 deletions bin/vitepress.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
const chalk = require('chalk')
const argv = require('minimist')(process.argv.slice(2))

console.log(chalk.green('forked version~'))

console.log(chalk.cyan(`vitepress v${require('../package.json').version}`))
console.log(chalk.cyan(`vite v${require('vite/package.json').version}`))

Expand Down
24 changes: 24 additions & 0 deletions src/client/app/components/Demo/demo.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.demo {
background-color: #fff;
border: 1px solid #ebedf1;
border-radius: 1px;
}

.demo-slot {
padding: 40px 24px;
}

.demo-actions {
display: flex;
height: 40px;
padding: 0 1em;
align-items: center;
justify-content: space-between;
border-top: 1px dashed #ebedf1;
}

.demo-actions-expand, .demo-actions-copy {
margin: 0 8px;
cursor: pointer;
color: #666;
}
54 changes: 54 additions & 0 deletions src/client/app/components/Demo/demo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<template>
<article class="demo">
<div class="demo-slot">
<slot></slot>
</div>

<div class="demo-actions">
<div class="demo-platforms"></div>
<div>
<span class="demo-actions-copy" @click="toggleExpand()" title="复制">
<copySvg />
</span>
<span class="demo-actions-expand" @click="toggleExpand()" title="展开">
<codeSvg />
</span>
</div>
</div>
<div v-show="state.expand" class="language-vue">
{{ decodeURIComponent(htmlStr) }}
</div>
</article>
</template>

<script lang="ts">
import { reactive } from 'vue'
import './demo.css'
import copySvg from './icons/copy.vue'
import codeSvg from './icons/code.vue'
export default {
props: {
componentName: String,
htmlStr: String
},
components: {
copySvg,
codeSvg,
},
setup() {
const state = reactive({
expand: false
})
const toggleExpand = () => (state.expand = !state.expand)
// const copy = () =>
return {
state,
toggleExpand,
}
},
}
</script>
27 changes: 27 additions & 0 deletions src/client/app/components/Demo/icons/code.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<svg
t="1596458647160"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2840"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="22"
height="22"
>
<path
d="M311.1 739c-6.1 0-12.2-2.3-16.8-7L69.7 507.4l224.6-224.6c9.3-9.3 24.3-9.3 33.6 0s9.3 24.3 0 33.6l-191 191 191 191c9.3 9.3 9.3 24.3 0 33.6-4.6 4.7-10.7 7-16.8 7zM711.5 739c-6.1 0-12.2-2.3-16.8-7-9.3-9.3-9.3-24.3 0-33.6l191-191-191-191c-9.3-9.3-9.3-24.3 0-33.6s24.3-9.3 33.6 0L953 507.4 728.3 732c-4.6 4.7-10.7 7-16.8 7zM418.5 814.7c-2.4 0-4.8-0.4-7.2-1.1-12.5-4-19.4-17.3-15.5-29.8l179.6-567.1c4-12.5 17.3-19.4 29.8-15.5 12.5 4 19.4 17.3 15.5 29.8L441.1 798.1a23.73 23.73 0 0 1-22.6 16.6z"
fill=""
p-id="2841"
></path>
</svg>
</template>

<script lang="ts">
export default {
setup() {
return {}
}
}
</script>
30 changes: 30 additions & 0 deletions src/client/app/components/Demo/icons/copy.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<template>
<svg
t="1596458734865"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="4898"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="20"
height="20"
>
<path
d="M68.608 962.56V206.848h740.864V962.56H68.608zM746.496 271.36H131.584v629.248h614.912V271.36zM131.584 262.144"
p-id="4899"
></path>
<path
d="M219.136 65.024v116.224h62.976V129.536h614.912v629.248h-60.416v61.952h123.392V65.024z"
p-id="4900"
></path>
</svg>
</template>

<script lang="ts">
export default {
setup() {
return {}
}
}
</script>
1 change: 1 addition & 0 deletions src/client/app/components/Demo/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './demo.vue'
2 changes: 2 additions & 0 deletions src/client/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useUpdateHead } from './composables/head'
import { pageDataSymbol } from './composables/pageData'
import { Content } from './components/Content'
import Debug from './components/Debug.vue'
import Demo from './components/Demo'
import Theme from '/@theme/index'
import { inBrowser, pathToFile } from './utils'
import { useSiteDataByRoute } from './composables/siteDataByRoute'
Expand Down Expand Up @@ -75,6 +76,7 @@ export function createApp() {
'Debug',
process.env.NODE_ENV === 'production' ? () => null : Debug
)
app.component('Demo', Demo)

const siteDataByRouteRef = useSiteDataByRoute(router.route)

Expand Down
11 changes: 10 additions & 1 deletion src/node/markdown/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { hoistPlugin } from './plugins/hoist'
import { preWrapperPlugin } from './plugins/preWrapper'
import { linkPlugin } from './plugins/link'
import { extractHeaderPlugin } from './plugins/header'
import { demoPlugin } from './plugins/demo'
import { Header } from '../../../types/shared'

const emoji = require('markdown-it-emoji')
Expand All @@ -30,10 +31,17 @@ export interface MarkdownOptions extends MarkdownIt.Options {
externalLinks?: Record<string, string>
}

export interface DemoComponentData {
componentName: String
src: String
htmlStr: String
}

export interface MarkdownParsedData {
hoistedTags?: string[]
links?: string[]
headers?: Header[]
demoSrcs?: DemoComponentData[]
}

export interface MarkdownRenderer {
Expand All @@ -52,7 +60,8 @@ export const createMarkdownRenderer = (
})

// custom plugins
md.use(componentPlugin)
md.use(demoPlugin)
.use(componentPlugin)
.use(highlightLinePlugin)
.use(preWrapperPlugin)
.use(snippetPlugin)
Expand Down
44 changes: 44 additions & 0 deletions src/node/markdown/plugins/demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import MarkdownIt from 'markdown-it'
import { MarkdownParsedData } from '../markdown'
import fs from 'fs'
import path from 'path'

// hoist <script> and <style> tags out of the returned html
// so that they can be placed outside as SFC blocks.
export const demoPlugin = (md: MarkdownIt) => {
const RE = /<demo /i

md.renderer.rules.html_inline = (tokens, idx) => {
const content = tokens[idx].content
const data = (md as any).__data as MarkdownParsedData
const demoSrcs = data.demoSrcs || (data.demoSrcs = [])

if (RE.test(content.trim())) {
const componentName = 'demo1'
const src = (content.match(/src=("|')(.*)('|")/) || [])[2] ?? ''
const srcPath = path.resolve(process.cwd(), src)
if (!src || !fs.existsSync(srcPath)) {
console.warn(`[vitepress]: ${srcPath} is not exist!`)
return `<demo src="${src}" >`
}

console.log(`srcPath=${srcPath}`)
const htmlStr = fs.readFileSync(src).toString()
demoSrcs.push({
src,
componentName,
htmlStr
})
return content.replace(
'>',
` componentName="${componentName}" htmlStr="${encodeURIComponent(
htmlStr
)}" >
<${componentName}></${componentName}>
`
)
} else {
return content
}
}
}
41 changes: 40 additions & 1 deletion src/node/markdownToVue.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import path from 'path'
import matter from 'gray-matter'
import LRUCache from 'lru-cache'
import { createMarkdownRenderer, MarkdownOptions } from './markdown/markdown'
import {
createMarkdownRenderer,
MarkdownOptions,
DemoComponentData
} from './markdown/markdown'
import { deeplyParseHeader } from './utils/parseHeader'
import { PageData } from '../../types/shared'

Expand Down Expand Up @@ -50,12 +54,15 @@ export function createMarkdownToVueRenderFn(
? injectPageData(data.hoistedTags || [], pageData)
: data.hoistedTags || []

injectComponentData(additionalBlocks, data.demoSrcs || [])

const vueSrc =
additionalBlocks.join('\n') + `\n<template><div>${html}</div></template>`

debug(`[render] ${file} in ${Date.now() - start}ms.`)

const result = { vueSrc, pageData }
console.log(vueSrc)
cache.set(src, result)
return result
}
Expand All @@ -80,6 +87,38 @@ function injectPageData(tags: string[], data: PageData) {
return tags
}

function injectComponentData(tags: string[], demoSrcs: DemoComponentData[]) {
console.log(demoSrcs)

const importCode = demoSrcs
.map((componentData) => {
return `\n import ${componentData.componentName} from '${componentData.src}'`
})
.join(' ')

const exportCode = `\nexport default {
components: {
${demoSrcs.map((componentData) => componentData.componentName).join(', ')}
}
}`

const existingScriptIndex = tags.findIndex((tag) => scriptRE.test(tag))
if (existingScriptIndex > -1) {
tags[existingScriptIndex] = tags[existingScriptIndex].replace(
`<script>`,
`<script> ${importCode}`
)
tags[existingScriptIndex] = tags[existingScriptIndex].replace(
scriptRE,
exportCode + `</script>`
)
} else {
tags.push(`<script>${importCode} ${exportCode}</script>`)
}

return tags
}

const inferTitle = (frontmatter: any, content: string) => {
if (frontmatter.home) {
return 'Home'
Expand Down
Loading

0 comments on commit 5695129

Please sign in to comment.