Skip to content

Commit 4e5f8fb

Browse files
authored
feat(semantic): add component semantic structure query command (#17)
- Add ComponentSemanticStructureRecord interface to types - Extend ComponentRecord with semanticStructure field - Create loadComponent utility function in loader.ts - Implement semantic command with text/markdown/json output formats - Add tree-style and table-style display for semantic structure - Include error handling for missing components - Support capitalized component name matching
1 parent 4f3e6ad commit 4e5f8fb

3 files changed

Lines changed: 83 additions & 5 deletions

File tree

src/commands/semantic.ts

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,73 @@
1+
import type { ComponentSemanticStructureRecord } from '#/components.ts'
12
import { defineCommand } from 'citty'
3+
import { componentArgs } from '@/args/component.ts'
4+
import { defaultArgs } from '@/args/default.ts'
5+
import { resolveConfig } from '@/config.ts'
6+
import capitalize from '@/utils/capitalize.ts'
7+
import { loadComponent, loadVersionMetaData } from '@/utils/loader.ts'
8+
import { output } from '@/utils/output.ts'
9+
import { resolveVersion } from '@/utils/version.ts'
10+
11+
function outputTextSemantic(component: string, semantic: ComponentSemanticStructureRecord[]): string {
12+
let content = `${component} Semantic Structure:\n`
13+
14+
semantic.forEach((item, index, array) => {
15+
if (index === array.length - 1) {
16+
content += `└── ${item.key} # ${item.description}\n`
17+
}
18+
else {
19+
content += `├── ${item.key} # ${item.description}\n`
20+
}
21+
})
22+
23+
return content
24+
}
25+
26+
function outputMarkdownSemantic(component: string, semantic: ComponentSemanticStructureRecord[]): string {
27+
return [
28+
`## ${component} Semantic Structure:`,
29+
'',
30+
'| Key | Description |',
31+
'| --- | --- |',
32+
...semantic.map(item => `| ${item.key} | ${item.description} |`),
33+
].join('\n')
34+
}
235

336
export default defineCommand({
437
meta: {
538
name: 'semantic',
639
description: 'Query the semantic customization structure of a component',
740
},
8-
run({ args }) {
9-
// antd semantic <Component>
10-
// 语义化 classNames / styles 结构及用法示例
11-
console.log('Parsed args:', args)
41+
args: {
42+
...defaultArgs,
43+
...componentArgs,
44+
},
45+
async run({ args }) {
46+
const config = resolveConfig(args)
47+
const component = capitalize(args.component)
48+
49+
try {
50+
const version = await resolveVersion(config)
51+
const metaData = loadComponent(component, await loadVersionMetaData(version))
52+
53+
const semantic = metaData.semanticStructure
54+
55+
if (!semantic.length) {
56+
console.log(`No semantic structure data available for ${capitalize(component)}.`)
57+
return ''
58+
}
59+
60+
output({
61+
json: {
62+
name: component,
63+
semanticStructure: semantic,
64+
},
65+
text: outputTextSemantic(component, semantic),
66+
markdown: outputMarkdownSemantic(component, semantic),
67+
}, args.format)
68+
}
69+
catch (error) {
70+
console.log(`Error: Component ${component} not found!`)
71+
}
1272
},
1373
})

src/types/components.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ export interface ComponentDemoRecord {
3939
code: string
4040
}
4141

42+
export interface ComponentSemanticStructureRecord {
43+
key: string
44+
description: string
45+
descriptionZh: string
46+
}
47+
4248
export interface ComponentRecord {
4349
name: string
4450
nameZh: string
@@ -55,4 +61,5 @@ export interface ComponentRecord {
5561
tokens: ComponentPropRecord[]
5662
faq: ComponentFaqRecord[]
5763
demos: ComponentDemoRecord[]
64+
semanticStructure: ComponentSemanticStructureRecord[]
5865
}

src/utils/loader.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import type { ChangelogFile } from '#/components.ts'
1+
import type { ChangelogFile, ComponentRecord } from '#/components.ts'
22
import type { ResolvedVersion } from '@/types.ts'
33
import { readFile } from 'node:fs/promises'
44
import { join } from 'node:path'
55
import { __dirname } from '@/constants/dirname.ts'
6+
import capitalize from '@/utils/capitalize.ts'
67

78
export function getDataPath(): string {
89
return join(__dirname, '..', 'data')
@@ -16,3 +17,13 @@ export async function loadVersionMetaData(version: ResolvedVersion): Promise<Cha
1617
}
1718
return JSON.parse(await readFile(join(getDataPath(), `v${version.version}.json`), 'utf-8')) as ChangelogFile
1819
}
20+
21+
export function loadComponent(name: string, components: ChangelogFile): ComponentRecord {
22+
const component = components.components.filter(c => c.name === capitalize(name))?.at(0)
23+
24+
if (!component) {
25+
throw new Error(`Component ${name} not found`)
26+
}
27+
28+
return component
29+
}

0 commit comments

Comments
 (0)