mirror of
https://github.com/antd-tiny-vue/antd-tiny-vue.git
synced 2024-11-10 09:39:15 +08:00
feat: add locale
This commit is contained in:
parent
f394f48853
commit
9f19ed8c74
42
.vitepress/config.ts
Normal file
42
.vitepress/config.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
import { resolve } from 'path'
|
||||||
|
import { defineConfig } from 'vitepress'
|
||||||
|
import vueJsxPlugin from '@vitejs/plugin-vue-jsx'
|
||||||
|
import VitePluginVitepressDemo from 'vite-plugin-vitepress-demo'
|
||||||
|
import getEnUSConfig from './config/en-US'
|
||||||
|
import getZhCNConfig from './config/zh-CN'
|
||||||
|
import { getRewrites } from './config/rewrites'
|
||||||
|
const baseSrc = fileURLToPath(new URL('./', import.meta.url))
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
rewrites: getRewrites(),
|
||||||
|
mpa: true,
|
||||||
|
lang: 'en-US',
|
||||||
|
locales: {
|
||||||
|
'zh-CN': {
|
||||||
|
lang: 'zh-CN',
|
||||||
|
title: 'vue3组件库站点',
|
||||||
|
label: '简体中文',
|
||||||
|
description: 'vue3组件库站点',
|
||||||
|
themeConfig: getZhCNConfig()
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
lang: 'en-US',
|
||||||
|
title: 'vue3 component library site',
|
||||||
|
label: 'English',
|
||||||
|
description: 'vue3 component library site',
|
||||||
|
themeConfig: getEnUSConfig()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
vite: {
|
||||||
|
plugins: [vueJsxPlugin(), VitePluginVitepressDemo()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'antd-tiny-vue': resolve(baseSrc, '../components')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
server: {
|
||||||
|
port: 1199
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
9
.vitepress/config/en-US/index.ts
Normal file
9
.vitepress/config/en-US/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { DefaultTheme } from 'vitepress'
|
||||||
|
import { getNav } from './nav'
|
||||||
|
import { getSidebar } from './sidebar'
|
||||||
|
|
||||||
|
export default (): DefaultTheme.Config => ({
|
||||||
|
nav: getNav(),
|
||||||
|
sidebar: getSidebar(),
|
||||||
|
i18nRouting: true
|
||||||
|
})
|
@ -3,7 +3,7 @@ import type { DefaultTheme } from 'vitepress'
|
|||||||
export const getNav = (): DefaultTheme.NavItem[] => {
|
export const getNav = (): DefaultTheme.NavItem[] => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
text: '组件',
|
text: 'Components',
|
||||||
link: '/components/'
|
link: '/components/'
|
||||||
}
|
}
|
||||||
]
|
]
|
18
.vitepress/config/en-US/sidebar.ts
Normal file
18
.vitepress/config/en-US/sidebar.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import type { DefaultTheme } from 'vitepress'
|
||||||
|
|
||||||
|
const componentsDir = `/components/`
|
||||||
|
|
||||||
|
export const getSidebar = (): DefaultTheme.Sidebar => {
|
||||||
|
return {
|
||||||
|
'/components/': [
|
||||||
|
{
|
||||||
|
text: 'Button',
|
||||||
|
link: `${componentsDir}button/`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'ConfigProvider',
|
||||||
|
link: `${componentsDir}config-provider/`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
9
.vitepress/config/rewrites.ts
Normal file
9
.vitepress/config/rewrites.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export const getRewrites = (): Record<string, string> => {
|
||||||
|
return {
|
||||||
|
'site/index.md': 'index.md',
|
||||||
|
'site/index.zh-CN.md': 'zh-CN/index.md',
|
||||||
|
'site/components/index.md': 'components/index.md',
|
||||||
|
'site/components/index.zh-CN.md': 'zh-CN/components/index.md',
|
||||||
|
'components/:btn/index.zh-CN.md': 'zh-CN/components/:btn/index.md'
|
||||||
|
}
|
||||||
|
}
|
9
.vitepress/config/zh-CN/index.ts
Normal file
9
.vitepress/config/zh-CN/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import type { DefaultTheme } from 'vitepress'
|
||||||
|
import { getNav } from './nav'
|
||||||
|
import { getSidebar } from './sidebar'
|
||||||
|
|
||||||
|
export default (): DefaultTheme.Config => ({
|
||||||
|
nav: getNav(),
|
||||||
|
sidebar: getSidebar(),
|
||||||
|
i18nRouting: true
|
||||||
|
})
|
10
.vitepress/config/zh-CN/nav.ts
Normal file
10
.vitepress/config/zh-CN/nav.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import type { DefaultTheme } from 'vitepress'
|
||||||
|
|
||||||
|
export const getNav = (): DefaultTheme.NavItem[] => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
text: '组件',
|
||||||
|
link: '/zh-CN/components/'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
17
.vitepress/config/zh-CN/sidebar.ts
Normal file
17
.vitepress/config/zh-CN/sidebar.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import type { DefaultTheme } from 'vitepress'
|
||||||
|
const componentsDir = `/zh-CN/components/`
|
||||||
|
|
||||||
|
export const getSidebar = (): DefaultTheme.Sidebar => {
|
||||||
|
return {
|
||||||
|
'/zh-CN/components/': [
|
||||||
|
{
|
||||||
|
text: 'Button 按钮',
|
||||||
|
link: `${componentsDir}button/`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'ConfigProvider',
|
||||||
|
link: `${componentsDir}config-provider/`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,12 @@
|
|||||||
import { computed, defineComponent, onMounted, shallowRef } from 'vue'
|
import { computed, defineComponent, onMounted, shallowRef } from 'vue'
|
||||||
import { tryOnBeforeUnmount } from '@vueuse/core'
|
import { tryOnBeforeUnmount } from '@vueuse/core'
|
||||||
import { classNames, filterEmpty, getSlotsProps, runEvent, useState } from '@v-c/utils'
|
import {
|
||||||
|
classNames,
|
||||||
|
filterEmpty,
|
||||||
|
getSlotsProps,
|
||||||
|
runEvent,
|
||||||
|
useState
|
||||||
|
} from '@v-c/utils'
|
||||||
import { useProviderConfigState } from '../config-provider/context'
|
import { useProviderConfigState } from '../config-provider/context'
|
||||||
import warning from '../_util/warning'
|
import warning from '../_util/warning'
|
||||||
import Wave from '../_util/wave'
|
import Wave from '../_util/wave'
|
||||||
@ -24,7 +30,7 @@ function getLoadingConfig(loading: ButtonProps['loading']): LoadingConfigType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loading: !!loading,
|
loading,
|
||||||
delay: 0
|
delay: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,11 +43,15 @@ const Button = defineComponent({
|
|||||||
...buttonProps
|
...buttonProps
|
||||||
},
|
},
|
||||||
setup(props, { slots, attrs }) {
|
setup(props, { slots, attrs }) {
|
||||||
const { getPrefixCls, autoInsertSpaceInButton, direction } = useProviderConfigState()
|
const { getPrefixCls, autoInsertSpaceInButton, direction } =
|
||||||
|
useProviderConfigState()
|
||||||
const prefixCls = computed(() => getPrefixCls('btn', props.prefixCls))
|
const prefixCls = computed(() => getPrefixCls('btn', props.prefixCls))
|
||||||
const [wrapSSR, hashId] = useStyle(prefixCls)
|
const [wrapSSR, hashId] = useStyle(prefixCls)
|
||||||
const size = useSize(props)
|
const size = useSize(props)
|
||||||
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction)
|
const { compactSize, compactItemClassnames } = useCompactItemContext(
|
||||||
|
prefixCls,
|
||||||
|
direction
|
||||||
|
)
|
||||||
const sizeCls = computed(() => {
|
const sizeCls = computed(() => {
|
||||||
const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined }
|
const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined }
|
||||||
const sizeFullname = compactSize?.value || size.value
|
const sizeFullname = compactSize?.value || size.value
|
||||||
@ -54,7 +64,9 @@ const Button = defineComponent({
|
|||||||
return getLoadingConfig(props.loading)
|
return getLoadingConfig(props.loading)
|
||||||
})
|
})
|
||||||
|
|
||||||
const [innerLoading, setLoading] = useState<Loading>(loadingOrDelay.value.loading)
|
const [innerLoading, setLoading] = useState<Loading>(
|
||||||
|
loadingOrDelay.value.loading
|
||||||
|
)
|
||||||
const [hasTwoCNChar, setHasTwoCNChar] = useState(false)
|
const [hasTwoCNChar, setHasTwoCNChar] = useState(false)
|
||||||
|
|
||||||
let delayTimer: number | null = null
|
let delayTimer: number | null = null
|
||||||
@ -95,9 +107,17 @@ const Button = defineComponent({
|
|||||||
|
|
||||||
const icon = getSlotsProps(slots, props, 'icon')
|
const icon = getSlotsProps(slots, props, 'icon')
|
||||||
|
|
||||||
warning(!(typeof icon === 'string' && icon.length > 2), 'Button', `\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`)
|
warning(
|
||||||
|
!(typeof icon === 'string' && icon.length > 2),
|
||||||
|
'Button',
|
||||||
|
`\`icon\` is using ReactNode instead of string naming in v4. Please check \`${icon}\` at https://ant.design/components/icon`
|
||||||
|
)
|
||||||
|
|
||||||
warning(!(ghost && isUnBorderedButtonType(type)), 'Button', "`link` or `text` button can't be a `ghost` button.")
|
warning(
|
||||||
|
!(ghost && isUnBorderedButtonType(type)),
|
||||||
|
'Button',
|
||||||
|
"`link` or `text` button can't be a `ghost` button."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -105,7 +125,11 @@ const Button = defineComponent({
|
|||||||
const icon = getSlotsProps(slots, props, 'icon')
|
const icon = getSlotsProps(slots, props, 'icon')
|
||||||
const children = filterEmpty(slots.default?.())
|
const children = filterEmpty(slots.default?.())
|
||||||
const isNeedInserted = () => {
|
const isNeedInserted = () => {
|
||||||
return children.length === 1 && !slots.icon && isUnBorderedButtonType(props.type)
|
return (
|
||||||
|
children.length === 1 &&
|
||||||
|
!slots.icon &&
|
||||||
|
isUnBorderedButtonType(props.type)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fixTwoCNChar = () => {
|
const fixTwoCNChar = () => {
|
||||||
@ -137,10 +161,13 @@ const Button = defineComponent({
|
|||||||
[`${prefixCls.value}-${shape}`]: shape !== 'default' && shape,
|
[`${prefixCls.value}-${shape}`]: shape !== 'default' && shape,
|
||||||
[`${prefixCls.value}-${type}`]: type,
|
[`${prefixCls.value}-${type}`]: type,
|
||||||
[`${prefixCls.value}-${sizeCls.value}`]: sizeCls.value,
|
[`${prefixCls.value}-${sizeCls.value}`]: sizeCls.value,
|
||||||
[`${prefixCls.value}-icon-only`]: !children && children !== 0 && !!iconType,
|
[`${prefixCls.value}-icon-only`]:
|
||||||
[`${prefixCls.value}-background-ghost`]: ghost && !isUnBorderedButtonType(type),
|
!children && children !== 0 && !!iconType,
|
||||||
|
[`${prefixCls.value}-background-ghost`]:
|
||||||
|
ghost && !isUnBorderedButtonType(type),
|
||||||
[`${prefixCls.value}-loading`]: innerLoading.value,
|
[`${prefixCls.value}-loading`]: innerLoading.value,
|
||||||
[`${prefixCls.value}-two-chinese-chars`]: hasTwoCNChar.value && autoInsertSpace && !innerLoading.value,
|
[`${prefixCls.value}-two-chinese-chars`]:
|
||||||
|
hasTwoCNChar.value && autoInsertSpace && !innerLoading.value,
|
||||||
[`${prefixCls.value}-block`]: block,
|
[`${prefixCls.value}-block`]: block,
|
||||||
[`${prefixCls.value}-dangerous`]: !!danger,
|
[`${prefixCls.value}-dangerous`]: !!danger,
|
||||||
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
|
||||||
@ -167,11 +194,7 @@ const Button = defineComponent({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
let buttonNode = (
|
let buttonNode = (
|
||||||
<button
|
<button {...attrs} onClick={handleClick} class={classes}>
|
||||||
{...attrs}
|
|
||||||
onClick={handleClick}
|
|
||||||
class={classes}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
21
components/button/demos/basic.vue
Normal file
21
components/button/demos/basic.vue
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<docs lang="zh-CN">
|
||||||
|
---
|
||||||
|
title: 基础用法
|
||||||
|
---
|
||||||
|
|
||||||
|
基础用法测试
|
||||||
|
</docs>
|
||||||
|
|
||||||
|
<docs lang="en-US">
|
||||||
|
---
|
||||||
|
title: Basic Usage
|
||||||
|
---
|
||||||
|
|
||||||
|
Basic Usage Test
|
||||||
|
</docs>
|
||||||
|
|
||||||
|
<script lang="ts" setup></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>Test</div>
|
||||||
|
</template>
|
4
components/button/index.md
Normal file
4
components/button/index.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Button
|
||||||
|
|
||||||
|
|
||||||
|
<demo src="./demos/basic.vue"></demo>
|
4
components/button/index.zh-CN.md
Normal file
4
components/button/index.zh-CN.md
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# 按钮
|
||||||
|
|
||||||
|
|
||||||
|
<demo src="./demos/basic.vue"></demo>
|
1
components/config-provider/index.md
Normal file
1
components/config-provider/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# ConfigProvider
|
1
components/config-provider/index.zh-CN.md
Normal file
1
components/config-provider/index.zh-CN.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# ConfigProvider 全局配置
|
@ -1,5 +1,6 @@
|
|||||||
import type { App } from 'vue'
|
import type { App } from 'vue'
|
||||||
import * as components from './components'
|
import * as components from './components'
|
||||||
|
import version from './version'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(app: App) {
|
install(app: App) {
|
||||||
@ -9,5 +10,6 @@ export default {
|
|||||||
app.use(component)
|
app.use(component)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
version
|
||||||
}
|
}
|
||||||
|
20
package.json
20
package.json
@ -1,11 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "antd-tiny-vue",
|
"name": "antd-tiny-vue",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "this is a tiny antd components for vue3",
|
||||||
"keywords": [],
|
"keywords": [
|
||||||
|
"antd",
|
||||||
|
"ant-design-vue",
|
||||||
|
"ant-design",
|
||||||
|
"vue3",
|
||||||
|
"vue3-components",
|
||||||
|
"components"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"author": "aibayanyu",
|
"author": "aibayanyu",
|
||||||
"main": "index.js",
|
"main": "dist/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "vitest",
|
"test": "vitest",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
@ -24,7 +31,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^17.5.0",
|
"@commitlint/cli": "^17.5.0",
|
||||||
"@commitlint/config-conventional": "^17.4.4",
|
"@commitlint/config-conventional": "^17.4.4",
|
||||||
"@mistjs/eslint-config-vue-jsx": "^0.0.3",
|
"@mistjs/eslint-config-vue-jsx": "^0.0.7",
|
||||||
"@mistjs/tsconfig": "^1.0.0",
|
"@mistjs/tsconfig": "^1.0.0",
|
||||||
"@mistjs/tsconfig-vue": "^0.0.3",
|
"@mistjs/tsconfig-vue": "^0.0.3",
|
||||||
"@types/node": "^18.15.10",
|
"@types/node": "^18.15.10",
|
||||||
@ -34,9 +41,10 @@
|
|||||||
"lint-staged": "^13.2.0",
|
"lint-staged": "^13.2.0",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
|
"unbuild": "^1.1.2",
|
||||||
"vite": "^4.2.1",
|
"vite": "^4.2.1",
|
||||||
"vite-plugin-vitepress-demo": "2.0.0-alpha.8",
|
"vite-plugin-vitepress-demo": "2.0.0-beta.28",
|
||||||
"vitepress": "1.0.0-alpha.63",
|
"vitepress": "1.0.0-alpha.69",
|
||||||
"vitest": "^0.28.5"
|
"vitest": "^0.28.5"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
|
2070
pnpm-lock.yaml
2070
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -1,33 +0,0 @@
|
|||||||
import { fileURLToPath } from 'url'
|
|
||||||
import { resolve } from 'path'
|
|
||||||
import { defineConfig } from 'vitepress'
|
|
||||||
import vueJsxPlugin from '@vitejs/plugin-vue-jsx'
|
|
||||||
import { VitePluginVitepressDemo } from 'vite-plugin-vitepress-demo'
|
|
||||||
import { getNav } from './config/nav'
|
|
||||||
import { getSidebar } from './config/sidebar'
|
|
||||||
import { getRewrites } from './config/rewrites'
|
|
||||||
const baseSrc = fileURLToPath(new URL('./', import.meta.url))
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
title: 'vue3组件库站点',
|
|
||||||
rewrites: getRewrites(),
|
|
||||||
srcExclude: ['**/node_modules/**', '**/demos/**', '**/tests/**', '**/README.md'],
|
|
||||||
mpa: true,
|
|
||||||
themeConfig: {
|
|
||||||
nav: getNav(),
|
|
||||||
sidebar: getSidebar()
|
|
||||||
},
|
|
||||||
vite: {
|
|
||||||
plugins: [
|
|
||||||
vueJsxPlugin(),
|
|
||||||
VitePluginVitepressDemo({
|
|
||||||
glob: ['**/demos/**/*.vue']
|
|
||||||
})
|
|
||||||
],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'antd-tiny-vue': resolve(baseSrc, '../../components')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,5 +0,0 @@
|
|||||||
export const getRewrites = (): Record<string, string> => {
|
|
||||||
return {
|
|
||||||
// '/site/index.md': '/index.md'
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
import type { DefaultTheme } from 'vitepress'
|
|
||||||
|
|
||||||
export const getSidebar = (): DefaultTheme.Sidebar => {
|
|
||||||
return {
|
|
||||||
'/components/': [
|
|
||||||
{
|
|
||||||
text: 'Button 按钮',
|
|
||||||
link: '/components/button/'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
1
site/components/index.md
Normal file
1
site/components/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Components
|
1
site/components/index.zh-CN.md
Normal file
1
site/components/index.zh-CN.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# 组件
|
@ -10,7 +10,7 @@ hero:
|
|||||||
tagline: Simple, powerful, and performant. Meet the modern SSG framework you've always wanted.
|
tagline: Simple, powerful, and performant. Meet the modern SSG framework you've always wanted.
|
||||||
actions:
|
actions:
|
||||||
- theme: brand
|
- theme: brand
|
||||||
text: 组件
|
text: Components
|
||||||
link: /components/
|
link: /components/
|
||||||
- theme: alt
|
- theme: alt
|
||||||
text: View on GitHub
|
text: View on GitHub
|
||||||
|
28
site/index.zh-CN.md
Normal file
28
site/index.zh-CN.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
layout: home
|
||||||
|
|
||||||
|
title: Antd Tiny Vue
|
||||||
|
titleTemplate: Vite & Vue Powered Static Site Generator
|
||||||
|
|
||||||
|
hero:
|
||||||
|
name: Antd Tiny Vue
|
||||||
|
text: Vite & Vue Powered Static Site Generator
|
||||||
|
tagline: Simple, powerful, and performant. Meet the modern SSG framework you've always wanted.
|
||||||
|
actions:
|
||||||
|
- theme: brand
|
||||||
|
text: 组件
|
||||||
|
link: /zh-CN/components/
|
||||||
|
- theme: alt
|
||||||
|
text: View on GitHub
|
||||||
|
link: https://github.com/antd-tiny-vue/antd-tiny-vue
|
||||||
|
|
||||||
|
features:
|
||||||
|
- title: "Vite: The DX that can't be beat"
|
||||||
|
details: Feel the speed of Vite. Instant server start and lightning fast HMR that stays fast regardless of the app size.
|
||||||
|
- title: Designed to be simplicity first
|
||||||
|
details: With Markdown-centered content, it's built to help you focus on writing and deployed with minimum configuration.
|
||||||
|
- title: Power of Vue meets Markdown
|
||||||
|
details: Enhance your content with all the features of Vue in Markdown, while being able to customize your site with Vue.
|
||||||
|
- title: Fully static yet still dynamic
|
||||||
|
details: Go wild with true SSG + SPA architecture. Static on page load, but engage users with 100% interactivity from there.
|
||||||
|
---
|
Loading…
Reference in New Issue
Block a user