Skip to content

Commit b398272

Browse files
committed
docs: init Vitepress
1 parent 63ef040 commit b398272

File tree

118 files changed

+5624
-6255
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+5624
-6255
lines changed

.gitignore

+6-1
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,9 @@ dist
112112
.gen
113113

114114
# Node dependencies
115-
node_modules
115+
node_modules
116+
117+
# Vitepress
118+
119+
docs/.vitepress/dist
120+
docs/.vitepress/cache

docs/.postcssrc.mjs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export const plugins = {
2+
'tailwindcss': {},
3+
'postcss-prefix-selector': {
4+
prefix: ':not(:where(.vp-raw *))',
5+
includeFiles: [/vp-doc\.css/],
6+
transform(prefix, _selector) {
7+
const [selector, pseudo = ''] = _selector.split(/(:\S*)$/)
8+
return selector + prefix + pseudo
9+
},
10+
},
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import DemoBlock from './src/index.vue'
2+
3+
export default DemoBlock
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { ExtractPropTypes } from 'vue'
2+
3+
export const demoProps = {
4+
github: {
5+
type: String,
6+
default: 'https://github.com/selemondev/windi-ui',
7+
},
8+
codeSandBox: {
9+
type: String,
10+
default: 'https://codesandbox.io/',
11+
},
12+
highlightedCode: {
13+
type: String,
14+
default: '',
15+
},
16+
code: {
17+
type: String,
18+
default: '',
19+
},
20+
title: {
21+
type: String,
22+
default: '',
23+
},
24+
desc: {
25+
type: String,
26+
default: '',
27+
},
28+
lang: {
29+
type: String,
30+
default: 'vue',
31+
},
32+
expand: {
33+
type: Boolean,
34+
default: false,
35+
},
36+
} as const
37+
38+
export type DemoProps = ExtractPropTypes<typeof demoProps>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<script lang='ts' setup name="demo-block">
2+
import { useClipboard, useToggle } from '@vueuse/core'
3+
import { computed } from 'vue'
4+
import { demoProps } from './index'
5+
6+
const props = defineProps(demoProps)
7+
8+
const decodedHighlightedCode = computed(() =>
9+
decodeURIComponent(props.highlightedCode),
10+
)
11+
const { copy, copied } = useClipboard({ source: decodeURIComponent(props.code) })
12+
const [value, toggle] = useToggle()
13+
</script>
14+
15+
<template>
16+
<ClientOnly>
17+
<div v-bind="$attrs" class="mt-6">
18+
<div class="p-8 c-#282f38 overflow-x-scroll border border-light-700 rounded-sm dark:bg-[#000000] dark:border-#4C4D4F flex flex-wrap [&:o-button-base]:!c-context vp-raw bg">
19+
<slot />
20+
</div>
21+
<div class="relative">
22+
<div class="flex justify-end pt-3 gap-2">
23+
<a class="o-demo_action_item" group :href="github" target="_blank">
24+
<div class="o-demo_action_icon i-carbon-logo-github" />
25+
<div class="o-demo_tooltip" group-hover:opacity-100>
26+
Edit on GitHub
27+
</div>
28+
</a>
29+
<a class="o-demo_action_item" group @click="copy()">
30+
<div class="o-demo_action_icon i-carbon:copy" />
31+
<div class="o-demo_tooltip" group-hover:opacity-100>
32+
{{ copied ? 'Copied' : 'Copy code' }}
33+
</div>
34+
</a>
35+
<a class="o-demo_action_item" group @click="toggle()">
36+
<div class="o-demo_action_icon i-carbon:fit-to-width" />
37+
<div class="o-demo_tooltip" group-hover:opacity-100>
38+
{{ value ? 'Hide code' : 'Show code' }}
39+
</div>
40+
</a>
41+
</div>
42+
<div v-show="value" :class="`language-${lang} extra-class`" v-html="decodedHighlightedCode" />
43+
</div>
44+
</div>
45+
</ClientOnly>
46+
</template>

docs/.vitepress/config.mts

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { defineConfig } from 'vitepress'
2+
import { version } from '../../package.json'
3+
import { applyPlugins } from './plugins/code'
4+
5+
const components = [
6+
{ text: 'Accordion', link: '/guide/components/accordion.md' },
7+
{ text: 'Alert', link: '/guide/components/alert.md' },
8+
{ text: 'Avatar', link: '/guide/components/avatar.md' },
9+
{ text: 'Badge', link: '/guide/components/badge.md' },
10+
{ text: 'Button', link: '/guide/components/button.md' },
11+
{ text: 'Checkbox', link: '/guide/components/checkbox.md' },
12+
{ text: 'Divider', link: '/guide/components/divider.md' },
13+
{ text: 'Icon', link: '/guide/components/icon.md' },
14+
{ text: 'Input', link: '/guide/components/input.md' },
15+
{ text: 'Kbd', link: '/guide/components/kbd.md' },
16+
{ text: 'Modal', link: '/guide/components/modal.md' },
17+
{ text: 'Switch', link: '/guide/components/switch.md' },
18+
{ text: 'Tag', link: '/guide/components/tag.md' },
19+
]
20+
// https://vitepress.dev/reference/site-config
21+
export default defineConfig({
22+
vite: { plugins: [] },
23+
title: 'Spark UI',
24+
description: 'Experience The Magic Of Animated Components. Crafted With Vue, TypeScript, TailwindCss And Vueuse Motion ✨',
25+
head: [
26+
[
27+
'link',
28+
{
29+
rel: 'icon',
30+
type: 'image/svg+xml',
31+
href: '/icon.png',
32+
},
33+
],
34+
['meta', { property: 'og:type', content: 'website' }],
35+
[
36+
'link',
37+
{ href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' },
38+
],
39+
],
40+
themeConfig: {
41+
search: {
42+
provider: 'algolia',
43+
options: {
44+
appId: 'J80WVGDCRV',
45+
apiKey: 'ca4b17a48a4b73178c772c805c02a211',
46+
indexName: 'ui-windi',
47+
},
48+
},
49+
logo: '../icon.png',
50+
// https://vitepress.dev/reference/default-theme-config
51+
nav: [
52+
{ text: 'Guide', items: [
53+
{ text: 'Introduction', link: '/guide/getting-started/index.md' },
54+
{ text: 'Installation', link: '/guide/getting-started/installation.md' },
55+
{ text: 'Theme', link: '/guide/getting-started/theme.md' },
56+
] },
57+
{ text: 'Components', items: components },
58+
{ text: 'Showcase', link: '' },
59+
{ text: `v${version}`, link: '' },
60+
61+
],
62+
63+
sidebar: {
64+
'/guide/': [
65+
{
66+
text: '✨&nbsp;&nbsp; Getting Started',
67+
collapsed: true,
68+
items: [
69+
{ text: 'Introduction', link: '/guide/getting-started/index.md' },
70+
{ text: 'Installation', link: '/guide/getting-started/installation.md' },
71+
{ text: 'Theme', link: '/guide/getting-started/theme.md' },
72+
],
73+
},
74+
75+
{
76+
text: '📦&nbsp;&nbsp; Components',
77+
collapsed: true,
78+
items: components,
79+
},
80+
],
81+
},
82+
83+
socialLinks: [
84+
{ icon: 'github', link: 'https://github.com/selemondev/windi-ui' },
85+
],
86+
footer: {
87+
message: 'Released under the MIT License.',
88+
copyright: 'Copyright © 2023-PRESENT Selemon Brahanu',
89+
},
90+
},
91+
markdown: {
92+
config: (md) => {
93+
applyPlugins(md)
94+
},
95+
theme: {
96+
light: 'vitesse-light',
97+
dark: 'vitesse-dark',
98+
},
99+
},
100+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export const FenceDemoTag = 'vue:demo'
2+
export const DemoTag = 'demo'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { MarkdownRenderer } from 'vitepress'
2+
import { FenceDemoTag } from './constants'
3+
import { genDemoByCode } from './utils'
4+
5+
export function fencePlugin(md: MarkdownRenderer) {
6+
const defaultRender = md.renderer.rules.fence
7+
8+
md.renderer.rules.fence = (tokens, idx, options, env, self) => {
9+
const token = tokens[idx]
10+
if (token.info.trim() !== FenceDemoTag)
11+
return defaultRender!(tokens, idx, options, env, self)
12+
13+
const content = token.content
14+
const path = env.path
15+
16+
const demoScripts = genDemoByCode(md, env, path, content)
17+
return demoScripts
18+
}
19+
}

docs/.vitepress/plugins/code/index.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { fencePlugin } from './fencePlugin'
2+
import { demoBlockPlugin } from './plugin-demo-block'
3+
4+
export function applyPlugins(md: any) {
5+
md.use(fencePlugin)
6+
md.use(demoBlockPlugin)
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import type { AttributeNode, ElementNode } from '@vue/compiler-core'
2+
import type { MarkdownRenderer } from 'vitepress'
3+
import { dirname, resolve } from 'node:path'
4+
import { baseParse } from '@vue/compiler-core'
5+
import fsExtra from 'fs-extra'
6+
import { DemoTag } from './constants'
7+
import { getDemoComponent } from './utils'
8+
9+
function getPropsMap(attrs: AttributeNode[]) {
10+
const map: Record<string, string | undefined> = {}
11+
for (const { name, value } of attrs)
12+
map[name] = value?.content
13+
14+
return map
15+
}
16+
17+
export function parseProps(content: string) {
18+
const ast = baseParse(content)
19+
const demoElement = ast.children[0] as ElementNode
20+
21+
const props = getPropsMap(demoElement.props as AttributeNode[])
22+
23+
return props
24+
}
25+
26+
export function demoBlockPlugin(md: MarkdownRenderer) {
27+
const addRenderRule = (type: string) => {
28+
const defaultRender = md.renderer.rules[type]
29+
30+
md.renderer.rules[type] = (tokens, idx, options, env, self) => {
31+
const token = tokens[idx]
32+
const content = token.content.trim()
33+
34+
if (!content.startsWith(`<${DemoTag} `))
35+
return defaultRender!(tokens, idx, options, env, self)
36+
37+
const { path } = env
38+
39+
const props = parseProps(content)
40+
41+
if (!props.src)
42+
return defaultRender!(tokens, idx, options, env, self)
43+
44+
const frontmatter = env.frontmatter
45+
46+
const mdDir = dirname(frontmatter.realPath ?? path)
47+
const srcPath = resolve(mdDir, props.src)
48+
const code = fsExtra.readFileSync(srcPath, 'utf-8')
49+
50+
const demoScripts = getDemoComponent(md, env, {
51+
title: props.title,
52+
desc: props.desc,
53+
path: srcPath,
54+
code,
55+
...props,
56+
})
57+
58+
return demoScripts
59+
}
60+
}
61+
62+
addRenderRule('html_block')
63+
addRenderRule('html_inline')
64+
}

docs/.vitepress/plugins/code/types.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface DemoInfos {
2+
title?: string
3+
desc?: string
4+
path: string
5+
code: string
6+
lang?: string
7+
}

0 commit comments

Comments
 (0)