UNPKG

@lobehub/ui

Version:

Lobe UI is an open-source UI component library for building AIGC web apps

1 lines 5.82 kB
{"version":3,"file":"scan.mjs","names":[],"sources":["../../src/static-css/scan.ts"],"sourcesContent":["import { readdirSync, readFileSync, statSync } from 'node:fs';\nimport path from 'node:path';\n\nexport interface ScanAntdUsageOptions {\n cwd?: string;\n exclude?: RegExp[];\n extensions?: string[];\n roots?: string[];\n}\n\nexport interface AntdUsageScanResult {\n /** PascalCase antd export names found in value imports */\n components: string[];\n importsLobeUi: boolean;\n scannedFiles: number;\n /** a namespace/default antd import was found — usage is not statically enumerable */\n wildcard: boolean;\n}\n\nconst DEFAULT_EXTENSIONS = ['ts', 'tsx', 'js', 'jsx', 'mjs', 'mts', 'cjs', 'cts'];\nconst DEFAULT_EXCLUDE = [/node_modules/, /\\.test\\./, /\\.spec\\./, /\\.d\\.[cm]?ts$/, /__tests__/];\n\n// clause alternatives ({named} / Default / Default, {named} / * as ns) deliberately\n// exclude statement-crossing text so one match never spans two imports\nconst NAMED_IMPORT_RE =\n /import\\s+(type\\s+)?((?:[\\w$]+\\s*,\\s*)?\\{[^}]*\\}|[\\w$]+|\\*\\s+as\\s+[\\w$]+)\\s+from\\s+['\"]antd['\"]/g;\n// type-only deep imports are included too — over-approximation is harmless here\nconst DEEP_IMPORT_RE = /from\\s+['\"]antd\\/(?:es|lib)\\/([\\w-]+)/g;\nconst LOBE_UI_RE = /from\\s+['\"]@lobehub\\/ui(?:['\"]|\\/)/;\n\nconst kebabToPascal = (name: string) =>\n name\n .split('-')\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('');\n\nconst parseImportClause = (clause: string, components: Set<string>): boolean => {\n const braceStart = clause.indexOf('{');\n\n const bare = (braceStart === -1 ? clause : clause.slice(0, braceStart)).trim();\n const wildcard = bare.length > 0;\n\n if (braceStart === -1) return wildcard;\n\n const inner = clause.slice(braceStart + 1, clause.lastIndexOf('}'));\n for (const rawSpecifier of inner.split(',')) {\n const specifier = rawSpecifier.trim();\n if (!specifier || specifier.startsWith('type ')) continue;\n const name = specifier.split(/\\s+as\\s+/)[0]!.trim();\n if (/^[A-Za-z_$][\\w$]*$/.test(name)) components.add(name);\n }\n\n return wildcard;\n};\n\nconst listFiles = (root: string, extensions: Set<string>, exclude: RegExp[]): string[] => {\n let entries: string[];\n try {\n entries = readdirSync(root, { recursive: true }) as string[];\n } catch {\n return [];\n }\n\n return entries\n .map((entry) => path.join(root, entry))\n .filter((path) => {\n if (exclude.some((pattern) => pattern.test(path))) return false;\n const extension = path.split('.').pop();\n if (!extension || !extensions.has(extension)) return false;\n try {\n return statSync(path).isFile();\n } catch {\n return false;\n }\n });\n};\n\nexport const scanAntdUsage = (options: ScanAntdUsageOptions = {}): AntdUsageScanResult => {\n const {\n cwd = process.cwd(),\n roots = ['src'],\n extensions = DEFAULT_EXTENSIONS,\n exclude = DEFAULT_EXCLUDE,\n } = options;\n\n const components = new Set<string>();\n let importsLobeUi = false;\n let wildcard = false;\n let scannedFiles = 0;\n\n for (const root of roots) {\n for (const file of listFiles(path.resolve(cwd, root), new Set(extensions), exclude)) {\n let source: string;\n try {\n source = readFileSync(file, 'utf8');\n } catch {\n continue;\n }\n scannedFiles += 1;\n\n if (!importsLobeUi && LOBE_UI_RE.test(source)) importsLobeUi = true;\n\n for (const match of source.matchAll(NAMED_IMPORT_RE)) {\n if (match[1]) continue;\n if (parseImportClause(match[2]!, components)) wildcard = true;\n }\n\n for (const match of source.matchAll(DEEP_IMPORT_RE)) {\n components.add(kebabToPascal(match[1]!));\n }\n }\n }\n\n return { components: [...components].sort(), importsLobeUi, scannedFiles, wildcard };\n};\n"],"mappings":";;;AAmBA,MAAM,qBAAqB;CAAC;CAAM;CAAO;CAAM;CAAO;CAAO;CAAO;CAAO;AAAK;AAChF,MAAM,kBAAkB;CAAC;CAAgB;CAAY;CAAY;CAAiB;AAAW;AAI7F,MAAM,kBACJ;AAEF,MAAM,iBAAiB;AACvB,MAAM,aAAa;AAEnB,MAAM,iBAAiB,SACrB,KACG,MAAM,GAAG,CAAC,CACV,KAAK,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAC3D,KAAK,EAAE;AAEZ,MAAM,qBAAqB,QAAgB,eAAqC;CAC9E,MAAM,aAAa,OAAO,QAAQ,GAAG;CAGrC,MAAM,YADQ,eAAe,KAAK,SAAS,OAAO,MAAM,GAAG,UAAU,EAAA,CAAG,KACpD,CAAC,CAAC,SAAS;CAE/B,IAAI,eAAe,IAAI,OAAO;CAE9B,MAAM,QAAQ,OAAO,MAAM,aAAa,GAAG,OAAO,YAAY,GAAG,CAAC;CAClE,KAAK,MAAM,gBAAgB,MAAM,MAAM,GAAG,GAAG;EAC3C,MAAM,YAAY,aAAa,KAAK;EACpC,IAAI,CAAC,aAAa,UAAU,WAAW,OAAO,GAAG;EACjD,MAAM,OAAO,UAAU,MAAM,UAAU,CAAC,CAAC,EAAE,CAAE,KAAK;EAClD,IAAI,qBAAqB,KAAK,IAAI,GAAG,WAAW,IAAI,IAAI;CAC1D;CAEA,OAAO;AACT;AAEA,MAAM,aAAa,MAAc,YAAyB,YAAgC;CACxF,IAAI;CACJ,IAAI;EACF,UAAU,YAAY,MAAM,EAAE,WAAW,KAAK,CAAC;CACjD,QAAQ;EACN,OAAO,CAAC;CACV;CAEA,OAAO,QACJ,KAAK,UAAU,KAAK,KAAK,MAAM,KAAK,CAAC,CAAC,CACtC,QAAQ,SAAS;EAChB,IAAI,QAAQ,MAAM,YAAY,QAAQ,KAAK,IAAI,CAAC,GAAG,OAAO;EAC1D,MAAM,YAAY,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI;EACtC,IAAI,CAAC,aAAa,CAAC,WAAW,IAAI,SAAS,GAAG,OAAO;EACrD,IAAI;GACF,OAAO,SAAS,IAAI,CAAC,CAAC,OAAO;EAC/B,QAAQ;GACN,OAAO;EACT;CACF,CAAC;AACL;AAEA,MAAa,iBAAiB,UAAgC,CAAC,MAA2B;CACxF,MAAM,EACJ,MAAM,QAAQ,IAAI,GAClB,QAAQ,CAAC,KAAK,GACd,aAAa,oBACb,UAAU,oBACR;CAEJ,MAAM,6BAAa,IAAI,IAAY;CACnC,IAAI,gBAAgB;CACpB,IAAI,WAAW;CACf,IAAI,eAAe;CAEnB,KAAK,MAAM,QAAQ,OACjB,KAAK,MAAM,QAAQ,UAAU,KAAK,QAAQ,KAAK,IAAI,GAAG,IAAI,IAAI,UAAU,GAAG,OAAO,GAAG;EACnF,IAAI;EACJ,IAAI;GACF,SAAS,aAAa,MAAM,MAAM;EACpC,QAAQ;GACN;EACF;EACA,gBAAgB;EAEhB,IAAI,CAAC,iBAAiB,WAAW,KAAK,MAAM,GAAG,gBAAgB;EAE/D,KAAK,MAAM,SAAS,OAAO,SAAS,eAAe,GAAG;GACpD,IAAI,MAAM,IAAI;GACd,IAAI,kBAAkB,MAAM,IAAK,UAAU,GAAG,WAAW;EAC3D;EAEA,KAAK,MAAM,SAAS,OAAO,SAAS,cAAc,GAChD,WAAW,IAAI,cAAc,MAAM,EAAG,CAAC;CAE3C;CAGF,OAAO;EAAE,YAAY,CAAC,GAAG,UAAU,CAAC,CAAC,KAAK;EAAG;EAAe;EAAc;CAAS;AACrF"}