diff --git a/apps/www/package.json b/apps/www/package.json
index 8ffdde38..74167edc 100644
--- a/apps/www/package.json
+++ b/apps/www/package.json
@@ -12,7 +12,8 @@
"typecheck": "vue-tsc",
"typecheck:registry": "vue-tsc -p tsconfig.registry.json",
"build:registry": "tsx ./scripts/build-registry.ts",
- "build:registry-strict": "pnpm typecheck:registry && tsx ./scripts/build-registry.ts"
+ "build:registry-strict": "pnpm typecheck:registry && tsx ./scripts/build-registry.ts",
+ "docs:gen": "tsx ./scripts/autogen.ts"
},
"dependencies": {
"@formkit/auto-animate": "^0.8.2",
@@ -44,6 +45,7 @@
"zod": "^3.23.3"
},
"devDependencies": {
+ "@babel/traverse": "^7.24.1",
"@iconify-json/lucide": "^1.1.180",
"@iconify-json/ph": "^1.1.12",
"@iconify-json/radix-icons": "^1.1.14",
@@ -61,7 +63,9 @@
"@vue/compiler-dom": "^3.4.24",
"@vue/tsconfig": "^0.5.1",
"autoprefixer": "^10.4.19",
+ "fast-glob": "^3.3.2",
"lodash-es": "^4.17.21",
+ "markdown-it": "^14.1.0",
"pathe": "^1.1.2",
"rimraf": "^5.0.5",
"shiki": "^1.3.0",
@@ -71,6 +75,7 @@
"typescript": "^5.4.5",
"unplugin-icons": "^0.18.5",
"vitepress": "^1.1.3",
+ "vue-component-meta": "^2.0.13",
"vue-tsc": "^2.0.14"
}
}
diff --git a/apps/www/scripts/autogen.ts b/apps/www/scripts/autogen.ts
new file mode 100644
index 00000000..ca386e81
--- /dev/null
+++ b/apps/www/scripts/autogen.ts
@@ -0,0 +1,154 @@
+import { join, parse, resolve } from 'node:path'
+import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
+import { fileURLToPath } from 'node:url'
+import fg from 'fast-glob'
+import MarkdownIt from 'markdown-it'
+import type { ComponentMeta, MetaCheckerOptions, PropertyMeta, PropertyMetaSchema } from 'vue-component-meta'
+import { createComponentMetaChecker } from 'vue-component-meta'
+
+const __dirname = fileURLToPath(new URL('.', import.meta.url))
+
+const md = new MarkdownIt()
+
+const ROOTPATH = '../'
+const OUTPUTPATH = '../src/content/meta'
+
+const checkerOptions: MetaCheckerOptions = {
+ forceUseTs: true,
+ printer: { newLine: 1 },
+}
+
+const tsconfigChecker = createComponentMetaChecker(
+ resolve(__dirname, ROOTPATH, 'tsconfig.registry.json'),
+ checkerOptions,
+)
+
+const components = fg.sync(['chart/**/*.vue', 'chart*/**/*.vue'], {
+ cwd: resolve(__dirname, ROOTPATH, 'src/lib/registry/default/ui/'),
+ absolute: true,
+})
+
+components.forEach((componentPath) => {
+ try {
+ const componentName = parse(componentPath).name
+ const meta = parseMeta(tsconfigChecker.getComponentMeta(componentPath))
+
+ const metaDirPath = resolve(__dirname, OUTPUTPATH)
+ // if meta dir doesn't exist create
+ if (!existsSync(metaDirPath))
+ mkdirSync(metaDirPath)
+
+ const metaMdFilePath = join(metaDirPath, `${componentName}.md`)
+
+ let parsedString = '\n\n'
+ if (meta.props.length)
+ parsedString += `\n`
+
+ if (meta.events.length)
+ parsedString += `\n\n`
+
+ if (meta.slots.length)
+ parsedString += `\n\n`
+
+ if (meta.methods.length)
+ parsedString += `\n\n`
+
+ writeFileSync(metaMdFilePath, parsedString)
+ }
+ catch (err) {
+ console.log(err)
+ }
+})
+
+function parseTypeFromSchema(schema: PropertyMetaSchema): string {
+ if (typeof schema === 'object' && (schema.kind === 'enum' || schema.kind === 'array')) {
+ const isFlatEnum = schema.schema?.every(val => typeof val === 'string')
+ const enumValue = schema?.schema?.filter(i => i !== 'undefined') ?? []
+
+ if (isFlatEnum && /^[A-Z]/.test(schema.type))
+ return enumValue.join(' | ')
+ else if (typeof schema.schema?.[0] === 'object' && schema.schema?.[0].kind === 'enum')
+ return schema.schema.map((s: PropertyMetaSchema) => parseTypeFromSchema(s)).join(' | ')
+ else
+ return schema.type
+ }
+ else if (typeof schema === 'object' && schema.kind === 'object') {
+ return schema.type
+ }
+ else if (typeof schema === 'string') {
+ return schema
+ }
+ else {
+ return ''
+ }
+}
+
+// Utilities
+function parseMeta(meta: ComponentMeta) {
+ const props = meta.props
+ // Exclude global props
+ .filter(prop => !prop.global)
+ .map((prop) => {
+ let defaultValue = prop.default
+ let type = prop.type
+ const { name, description, required } = prop
+
+ if (name === 'as')
+ defaultValue = defaultValue ?? '"div"'
+
+ if (defaultValue === 'undefined')
+ defaultValue = undefined
+
+ if (!type.includes('AcceptableValue'))
+ type = parseTypeFromSchema(prop.schema) || type
+
+ return ({
+ name,
+ description: md.render(description),
+ type: type.replace(/\s*\|\s*undefined/g, ''),
+ required,
+ default: defaultValue ?? undefined,
+ })
+ })
+
+ const events = meta.events
+ .map((event) => {
+ const { name, type } = event
+ return ({
+ name,
+ type: type.replace(/\s*\|\s*undefined/g, ''),
+ })
+ })
+
+ const defaultSlot = meta.slots?.[0]
+ const slots: { name: string, description: string, type: string }[] = []
+
+ if (defaultSlot && defaultSlot.type !== '{}') {
+ const schema = defaultSlot.schema
+ if (typeof schema === 'object' && schema.schema) {
+ Object.values(schema.schema).forEach((childMeta: PropertyMeta) => {
+ slots.push({
+ name: childMeta.name,
+ description: md.render(childMeta.description),
+ type: parseTypeFromSchema(childMeta.schema),
+ })
+ })
+ }
+ }
+
+ // exposed method
+ const methods = meta.exposed
+ .filter(expose => typeof expose.schema === 'object' && expose.schema.kind === 'event')
+ .map(expose => ({
+ name: expose.name,
+ description: md.render(expose.description),
+ type: expose.type,
+ }))
+
+ return {
+ props,
+ events,
+ slots,
+ methods,
+ }
+}
diff --git a/apps/www/src/content/meta/AreaChart.md b/apps/www/src/content/meta/AreaChart.md
new file mode 100644
index 00000000..c709e645
--- /dev/null
+++ b/apps/www/src/content/meta/AreaChart.md
@@ -0,0 +1,116 @@
+
+
+
+
+
diff --git a/apps/www/src/content/meta/BarChart.md b/apps/www/src/content/meta/BarChart.md
new file mode 100644
index 00000000..1800c227
--- /dev/null
+++ b/apps/www/src/content/meta/BarChart.md
@@ -0,0 +1,116 @@
+
+
+
+
+
diff --git a/apps/www/src/content/meta/ChartCrosshair.md b/apps/www/src/content/meta/ChartCrosshair.md
new file mode 100644
index 00000000..b90a9c32
--- /dev/null
+++ b/apps/www/src/content/meta/ChartCrosshair.md
@@ -0,0 +1,29 @@
+
+
+
diff --git a/apps/www/src/content/meta/ChartLegend.md b/apps/www/src/content/meta/ChartLegend.md
new file mode 100644
index 00000000..de294215
--- /dev/null
+++ b/apps/www/src/content/meta/ChartLegend.md
@@ -0,0 +1,22 @@
+
+
+
+
+
diff --git a/apps/www/src/content/meta/ChartSingleTooltip.md b/apps/www/src/content/meta/ChartSingleTooltip.md
new file mode 100644
index 00000000..ddb8e99f
--- /dev/null
+++ b/apps/www/src/content/meta/ChartSingleTooltip.md
@@ -0,0 +1,43 @@
+
+
+
+
+
diff --git a/apps/www/src/content/meta/ChartTooltip.md b/apps/www/src/content/meta/ChartTooltip.md
new file mode 100644
index 00000000..9fc0fb40
--- /dev/null
+++ b/apps/www/src/content/meta/ChartTooltip.md
@@ -0,0 +1,16 @@
+
+
+
diff --git a/apps/www/src/content/meta/DonutChart.md b/apps/www/src/content/meta/DonutChart.md
new file mode 100644
index 00000000..bdaecbd6
--- /dev/null
+++ b/apps/www/src/content/meta/DonutChart.md
@@ -0,0 +1,82 @@
+
+
+
diff --git a/apps/www/src/content/meta/LineChart.md b/apps/www/src/content/meta/LineChart.md
new file mode 100644
index 00000000..c6f2ac09
--- /dev/null
+++ b/apps/www/src/content/meta/LineChart.md
@@ -0,0 +1,109 @@
+
+
+
+
+
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 79d339a9..96fa1de3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -123,6 +123,9 @@ importers:
specifier: ^3.23.3
version: 3.23.3
devDependencies:
+ '@babel/traverse':
+ specifier: ^7.24.1
+ version: 7.24.1
'@iconify-json/lucide':
specifier: ^1.1.180
version: 1.1.184
@@ -174,9 +177,15 @@ importers:
autoprefixer:
specifier: ^10.4.19
version: 10.4.19(postcss@8.4.38)
+ fast-glob:
+ specifier: ^3.3.2
+ version: 3.3.2
lodash-es:
specifier: ^4.17.21
version: 4.17.21
+ markdown-it:
+ specifier: ^14.1.0
+ version: 14.1.0
pathe:
specifier: ^1.1.2
version: 1.1.2
@@ -204,6 +213,9 @@ importers:
vitepress:
specifier: ^1.1.3
version: 1.1.3(@algolia/client-search@4.23.3)(@types/node@20.12.7)(axios@0.18.1)(postcss@8.4.38)(search-insights@2.13.0)(terser@5.30.4)(typescript@5.4.5)
+ vue-component-meta:
+ specifier: ^2.0.13
+ version: 2.0.14(typescript@5.4.5)
vue-tsc:
specifier: ^2.0.14
version: 2.0.14(typescript@5.4.5)
@@ -4846,6 +4858,9 @@ packages:
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ linkify-it@5.0.0:
+ resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
+
lint-staged@15.2.2:
resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==}
engines: {node: '>=18.12.0'}
@@ -5001,6 +5016,10 @@ packages:
mark.js@8.11.1:
resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==}
+ markdown-it@14.1.0:
+ resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
+ hasBin: true
+
mdast-util-from-markdown@0.8.5:
resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==}
@@ -5013,6 +5032,9 @@ packages:
mdn-data@2.0.30:
resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
+ mdurl@2.0.0:
+ resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
+
meow@12.1.1:
resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==}
engines: {node: '>=16.10'}
@@ -5917,6 +5939,10 @@ packages:
pumpify@1.5.1:
resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==}
+ punycode.js@2.3.1:
+ resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
+ engines: {node: '>=6'}
+
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
@@ -6761,6 +6787,9 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
+ uc.micro@2.1.0:
+ resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
+
ufo@1.5.3:
resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==}
@@ -7229,6 +7258,17 @@ packages:
vue-bundle-renderer@2.0.0:
resolution: {integrity: sha512-oYATTQyh8XVkUWe2kaKxhxKVuuzK2Qcehe+yr3bGiaQAhK3ry2kYE4FWOfL+KO3hVFwCdLmzDQTzYhTi9C+R2A==}
+ vue-component-meta@2.0.14:
+ resolution: {integrity: sha512-6ycN+5bkLLNsjno5pX+OFmFxrAXllJo95lk7jPD7g7cbtWsZY5F+pg+/YMXldHA36STrBHTfCu5QoklDV9Gynw==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ vue-component-type-helpers@2.0.14:
+ resolution: {integrity: sha512-DInfgOyXlMyliyqAAD9frK28tTfch0+tMi4qoWJcZlRxUf+NFAtraJBnAsKLep+FOyLMiajkhfyEb3xLK08i7w==}
+
vue-demi@0.14.7:
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
engines: {node: '>=12'}
@@ -12721,6 +12761,10 @@ snapshots:
lines-and-columns@1.2.4: {}
+ linkify-it@5.0.0:
+ dependencies:
+ uc.micro: 2.1.0
+
lint-staged@15.2.2:
dependencies:
chalk: 5.3.0
@@ -12946,6 +12990,15 @@ snapshots:
mark.js@8.11.1: {}
+ markdown-it@14.1.0:
+ dependencies:
+ argparse: 2.0.1
+ entities: 4.5.0
+ linkify-it: 5.0.0
+ mdurl: 2.0.0
+ punycode.js: 2.3.1
+ uc.micro: 2.1.0
+
mdast-util-from-markdown@0.8.5:
dependencies:
'@types/mdast': 3.0.15
@@ -12962,6 +13015,8 @@ snapshots:
mdn-data@2.0.30: {}
+ mdurl@2.0.0: {}
+
meow@12.1.1: {}
merge-stream@2.0.0: {}
@@ -14077,6 +14132,8 @@ snapshots:
inherits: 2.0.4
pump: 2.0.1
+ punycode.js@2.3.1: {}
+
punycode@2.3.1: {}
queue-microtask@1.2.3: {}
@@ -14962,6 +15019,8 @@ snapshots:
typescript@5.4.5: {}
+ uc.micro@2.1.0: {}
+
ufo@1.5.3: {}
ultrahtml@1.5.3: {}
@@ -15598,6 +15657,17 @@ snapshots:
dependencies:
ufo: 1.5.3
+ vue-component-meta@2.0.14(typescript@5.4.5):
+ dependencies:
+ '@volar/typescript': 2.2.0-alpha.10
+ '@vue/language-core': 2.0.14(typescript@5.4.5)
+ path-browserify: 1.0.1
+ vue-component-type-helpers: 2.0.14
+ optionalDependencies:
+ typescript: 5.4.5
+
+ vue-component-type-helpers@2.0.14: {}
+
vue-demi@0.14.7(vue@3.4.24(typescript@5.4.5)):
dependencies:
vue: 3.4.24(typescript@5.4.5)