mirror of
https://github.com/ant-design/ant-design-cli.git
synced 2026-09-14 19:07:15 +08:00
aad2fc0738
* docs: add antd v3 support design spec Design for adding antd 3.x support to enable migration assistance and legacy project queries. Covers data extraction, command support matrix, and enhanced v3→v4 migration knowledge. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add antd v3 support - Add v3 data extraction with demo format compatibility - Generate v3.json and v3.26.20.json data files - Add v3-to-v4 migration knowledge module - Return UNSUPPORTED_VERSION_FEATURE for token/semantic on v3 - Update spec.md with v3 support documentation Closes #66 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review comments - Fix regex \Z anchor to $ for JS compatibility in demo extractor - Fix v3 theming docs URL (3x.ant.design) - Remove redundant Tree filterTreeNode migration entry - Correct Table render description (signature unchanged) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update design spec for v3 support - Add language tag to code block - Fix v3 theming docs URL to 3x.ant.design - Update migration module path to match implementation - Correct BackTop and Less variables migration notes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address remaining PR review comments - Fix enMatch regex to use lookahead for zh-CN section - Make JSX code block regex more flexible (jsx or js) - Correct ConfigProvider migration description (introduced in v4) - Update design doc with correct module path and migration notes - Update snapshot for v3 Watermark component Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add comprehensive v3 test coverage - Add e2e tests for `antd migrate 3 4` command - Add v3 error tests for token and semantic commands - Add v3 version detection tests - Add v3 data loading tests (components, snapshots) - Add tests for v3-specific components (Mention, Icon, LocaleProvider) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
160 lines
5.4 KiB
JavaScript
160 lines
5.4 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Extract antd component metadata from source into a MetadataStore JSON file.
|
|
*
|
|
* Usage:
|
|
* npx tsx scripts/extract.ts --antd-dir ~/Projects/ant-design --output data/v6.json
|
|
*/
|
|
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import matter from 'gray-matter';
|
|
import { extractComponents } from './extractors/components.js';
|
|
import { extractProps } from './extractors/props.js';
|
|
import { extractDemos } from './extractors/demos.js';
|
|
import { extractTokens, extractGlobalTokens, resetTokenCache } from './extractors/tokens.js';
|
|
import { extractSemantic } from './extractors/semantic.js';
|
|
import { extractChangelog } from './extractors/changelog.js';
|
|
import { extractFaq } from './extractors/faq.js';
|
|
import type { MetadataStore, ComponentData } from '../src/types.js';
|
|
|
|
function parseArgs(args: string[]): { antdDir: string; output: string } {
|
|
let antdDir = '';
|
|
let output = '';
|
|
|
|
for (let i = 0; i < args.length; i++) {
|
|
if (args[i] === '--antd-dir' && args[i + 1]) {
|
|
antdDir = args[++i];
|
|
} else if (args[i] === '--output' && args[i + 1]) {
|
|
output = args[++i];
|
|
}
|
|
}
|
|
|
|
if (!antdDir) {
|
|
console.error('Usage: tsx scripts/extract.ts --antd-dir <path> --output <file>');
|
|
process.exit(1);
|
|
}
|
|
|
|
// Resolve paths
|
|
antdDir = path.resolve(antdDir);
|
|
output = output ? path.resolve(output) : '';
|
|
|
|
// Verify antd directory exists
|
|
if (!fs.existsSync(path.join(antdDir, 'components'))) {
|
|
console.error(`Error: ${antdDir}/components not found. Is this an antd source directory?`);
|
|
process.exit(1);
|
|
}
|
|
|
|
return { antdDir, output };
|
|
}
|
|
|
|
function getAntdVersion(antdDir: string): string {
|
|
const pkgPath = path.join(antdDir, 'package.json');
|
|
if (fs.existsSync(pkgPath)) {
|
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
return pkg.version || '';
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function getMajorVersion(version: string): string {
|
|
const major = version.split('.')[0];
|
|
return `v${major}`;
|
|
}
|
|
|
|
function main() {
|
|
const { antdDir, output } = parseArgs(process.argv.slice(2));
|
|
const version = getAntdVersion(antdDir);
|
|
const majorVersion = getMajorVersion(version);
|
|
|
|
console.log(`Extracting metadata from ${antdDir} (antd v${version})...`);
|
|
|
|
// Reset caches
|
|
resetTokenCache();
|
|
|
|
// 1. Discover all components
|
|
const componentMetas = extractComponents(antdDir);
|
|
console.log(`Found ${componentMetas.length} components`);
|
|
|
|
// 2. Build full ComponentData for each
|
|
const components: ComponentData[] = componentMetas.map((meta) => {
|
|
const { props, subComponentProps } = extractProps(antdDir, meta.dirName, meta.name);
|
|
const demos = extractDemos(antdDir, meta.dirName, majorVersion);
|
|
const tokens = extractTokens(antdDir, meta.name);
|
|
const semantic = extractSemantic(antdDir, meta.dirName);
|
|
const faq = extractFaq(antdDir, meta.dirName);
|
|
|
|
const hasSubComponentProps = Object.keys(subComponentProps).length > 0;
|
|
|
|
// Bundle raw markdown docs for `antd doc` command
|
|
const enDocPath = path.join(antdDir, 'components', meta.dirName, 'index.en-US.md');
|
|
const zhDocPath = path.join(antdDir, 'components', meta.dirName, 'index.zh-CN.md');
|
|
const doc = fs.existsSync(enDocPath) ? matter(fs.readFileSync(enDocPath, 'utf-8')).content : undefined;
|
|
const docZh = fs.existsSync(zhDocPath) ? matter(fs.readFileSync(zhDocPath, 'utf-8')).content : undefined;
|
|
|
|
const component: ComponentData = {
|
|
name: meta.name,
|
|
nameZh: meta.nameZh || undefined,
|
|
category: meta.category,
|
|
categoryZh: meta.categoryZh || undefined,
|
|
description: meta.description,
|
|
descriptionZh: meta.descriptionZh || undefined,
|
|
whenToUse: meta.whenToUse || undefined,
|
|
whenToUseZh: meta.whenToUseZh || undefined,
|
|
props,
|
|
demos: demos.length > 0 ? demos : undefined,
|
|
tokens: tokens.length > 0 ? tokens : undefined,
|
|
semanticStructure: semantic.length > 0 ? semantic : undefined,
|
|
faq: faq.length > 0 ? faq : undefined,
|
|
subComponents: meta.subComponents.length > 0 ? meta.subComponents : undefined,
|
|
subComponentProps: hasSubComponentProps ? subComponentProps : undefined,
|
|
doc: doc || undefined,
|
|
docZh: docZh || undefined,
|
|
};
|
|
|
|
return component;
|
|
});
|
|
|
|
// 3. Extract global tokens
|
|
const globalTokens = extractGlobalTokens(antdDir);
|
|
|
|
// 4. Extract changelog
|
|
const changelog = extractChangelog(antdDir);
|
|
|
|
// 5. Build final MetadataStore
|
|
const store: MetadataStore = {
|
|
version,
|
|
majorVersion,
|
|
components,
|
|
globalTokens: globalTokens.length > 0 ? globalTokens : undefined,
|
|
changelog: changelog.length > 0 ? changelog : undefined,
|
|
};
|
|
|
|
// 6. Output
|
|
const json = JSON.stringify(store, null, 2);
|
|
|
|
if (output) {
|
|
// Ensure output directory exists
|
|
const dir = path.dirname(output);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
fs.writeFileSync(output, json + '\n');
|
|
console.log(`Written to ${output}`);
|
|
|
|
// Print stats
|
|
console.log(` Components: ${components.length}`);
|
|
console.log(` Global tokens: ${globalTokens.length}`);
|
|
console.log(` Changelog entries: ${changelog.length}`);
|
|
const totalProps = components.reduce((sum, c) => sum + c.props.length, 0);
|
|
const totalDemos = components.reduce((sum, c) => sum + (c.demos?.length || 0), 0);
|
|
console.log(` Total props: ${totalProps}`);
|
|
console.log(` Total demos: ${totalDemos}`);
|
|
} else {
|
|
process.stdout.write(json + '\n');
|
|
}
|
|
}
|
|
|
|
main();
|