@ui-entropy/scanner-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +6 -0
- package/README.md +263 -0
- package/dist/analyze.d.ts +31 -0
- package/dist/analyze.d.ts.map +1 -0
- package/dist/analyze.js +65 -0
- package/dist/config.d.ts +41 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +123 -0
- package/dist/crawl.d.ts +51 -0
- package/dist/crawl.d.ts.map +1 -0
- package/dist/crawl.js +153 -0
- package/dist/extract-usage.d.ts +38 -0
- package/dist/extract-usage.d.ts.map +1 -0
- package/dist/extract-usage.js +118 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/parse-css.d.ts +35 -0
- package/dist/parse-css.d.ts.map +1 -0
- package/dist/parse-css.js +186 -0
- package/dist/report.d.ts +55 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +137 -0
- package/dist/scan.d.ts +48 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +72 -0
- package/package.json +69 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# Scanner Core
|
|
2
|
+
|
|
3
|
+
The core CSS waste analysis engine for UI Entropy Scanner.
|
|
4
|
+
|
|
5
|
+
## ✅ What We Built (Days 1-5)
|
|
6
|
+
|
|
7
|
+
### **Complete CSS Waste Detection System**
|
|
8
|
+
|
|
9
|
+
A production-ready TypeScript library that scans entire projects and detects unused CSS.
|
|
10
|
+
|
|
11
|
+
**Day 1-2: CSS Parsing**
|
|
12
|
+
- ✓ Extracts class & ID selectors from stylesheets
|
|
13
|
+
- ✓ Supports Bootstrap, Tailwind, custom CSS
|
|
14
|
+
- ✓ Handles complex selectors (pseudo-classes, compound, grouped)
|
|
15
|
+
|
|
16
|
+
**Day 3: Usage Detection & Analysis**
|
|
17
|
+
- ✓ Scans HTML/JSX/Vue/Angular for class usage
|
|
18
|
+
- ✓ Compares CSS selectors vs. actual usage
|
|
19
|
+
- ✓ Calculates waste percentage
|
|
20
|
+
- ✓ Generates detailed reports (JSON + Text)
|
|
21
|
+
- ✓ Identifies specific unused selectors
|
|
22
|
+
|
|
23
|
+
**Day 4-5: File System Scanner** 🔥
|
|
24
|
+
- ✓ Recursive directory scanning with glob patterns
|
|
25
|
+
- ✓ Config file support (`.ui-entropy.json`)
|
|
26
|
+
- ✓ `.gitignore` integration
|
|
27
|
+
- ✓ Automatic CSS/source file detection
|
|
28
|
+
- ✓ Complete scan orchestration
|
|
29
|
+
- ✓ **Ready for real projects!**
|
|
30
|
+
|
|
31
|
+
### 📊 Test Results
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
✓ 76 tests passing (6 test suites)
|
|
35
|
+
✓ End-to-end scanning validated
|
|
36
|
+
✓ Real directory structure tested
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Scan Any Project (New!)
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { scan } from '@ui-entropy/scanner-core';
|
|
45
|
+
|
|
46
|
+
// Scan entire project directory
|
|
47
|
+
const result = scan({
|
|
48
|
+
baseDir: '/path/to/your/project',
|
|
49
|
+
format: 'text', // or 'json' or 'summary'
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
console.log(result.report);
|
|
53
|
+
// Output:
|
|
54
|
+
// 🔍 UI Entropy Analysis Report
|
|
55
|
+
// Waste Percentage: 34.4%
|
|
56
|
+
// ...
|
|
57
|
+
|
|
58
|
+
console.log(result.analysis.unusedClasses);
|
|
59
|
+
// Set { 'btn-lg', 'alert-danger', ... }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### With Config File
|
|
63
|
+
|
|
64
|
+
Create `.ui-entropy.json` in your project root:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"cssPatterns": ["src/**/*.css", "styles/**/*.scss"],
|
|
69
|
+
"sourcePatterns": ["src/**/*.{tsx,ts,jsx,js}"],
|
|
70
|
+
"ignorePatterns": ["**/*.test.*"],
|
|
71
|
+
"respectGitignore": true,
|
|
72
|
+
"thresholds": {
|
|
73
|
+
"wastePercentage": 50
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Then simply:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { scan } from '@ui-entropy/scanner-core';
|
|
82
|
+
|
|
83
|
+
const result = scan(); // Uses config file + current directory
|
|
84
|
+
console.log(result.report);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Complete Analysis Pipeline
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import {
|
|
91
|
+
extractSelectors,
|
|
92
|
+
extractUsageFromMultiple,
|
|
93
|
+
analyzeWaste,
|
|
94
|
+
generateTextReport,
|
|
95
|
+
} from '@ui-entropy/scanner-core';
|
|
96
|
+
|
|
97
|
+
// 1. Extract CSS selectors
|
|
98
|
+
const cssContent = fs.readFileSync('styles.css', 'utf-8');
|
|
99
|
+
const selectors = extractSelectors(cssContent);
|
|
100
|
+
|
|
101
|
+
// 2. Extract usage from source files
|
|
102
|
+
const sourceFiles = [
|
|
103
|
+
fs.readFileSync('App.tsx', 'utf-8'),
|
|
104
|
+
fs.readFileSync('index.html', 'utf-8'),
|
|
105
|
+
];
|
|
106
|
+
const usage = extractUsageFromMultiple(sourceFiles);
|
|
107
|
+
|
|
108
|
+
// 3. Analyze waste
|
|
109
|
+
const analysis = analyzeWaste(selectors, usage);
|
|
110
|
+
|
|
111
|
+
// 4. Generate report
|
|
112
|
+
console.log(generateTextReport(analysis));
|
|
113
|
+
// Output:
|
|
114
|
+
// 🔍 UI Entropy Analysis Report
|
|
115
|
+
// Waste Percentage: 34.4%
|
|
116
|
+
// Estimated Wasted Bytes: 1,411 bytes
|
|
117
|
+
// ...
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Quick Start
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Run the demo (Days 1-3 features)
|
|
124
|
+
pnpm demo
|
|
125
|
+
|
|
126
|
+
# Run file scanner demo (Days 4-5)
|
|
127
|
+
pnpm scan-demo
|
|
128
|
+
|
|
129
|
+
# Run tests
|
|
130
|
+
pnpm test
|
|
131
|
+
|
|
132
|
+
# Watch mode
|
|
133
|
+
pnpm test:watch
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Real-World Results
|
|
137
|
+
|
|
138
|
+
**Bootstrap + HTML Example:**
|
|
139
|
+
- 20 classes defined, 10 used → **45.5% waste** 🚨
|
|
140
|
+
- ~1,077 bytes of unused CSS
|
|
141
|
+
|
|
142
|
+
**Tailwind + React Example:**
|
|
143
|
+
- 38 utility classes, 24 used → **35.9% waste**
|
|
144
|
+
- ~621 bytes wasted
|
|
145
|
+
|
|
146
|
+
**Multi-Framework Project:**
|
|
147
|
+
- 61 selectors total, 40 used → **34.4% waste**
|
|
148
|
+
- ~1,411 bytes wasted across Bootstrap + Tailwind
|
|
149
|
+
|
|
150
|
+
## Architecture
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
src/
|
|
154
|
+
├── parse-css.ts # CSS selector extraction
|
|
155
|
+
├── extract-usage.ts # Source file scanning (HTML/JSX/Vue)
|
|
156
|
+
├── analyze.ts # Waste calculation engine
|
|
157
|
+
├── report.ts # Report generation (JSON/Text)
|
|
158
|
+
├── crawl.ts # File system scanner (NEW!)
|
|
159
|
+
├── config.ts # Config file support (NEW!)
|
|
160
|
+
├── scan.ts # Scan orchestrator (NEW!)
|
|
161
|
+
├── index.ts # Public API
|
|
162
|
+
├── demo.ts # Interactive demo
|
|
163
|
+
├── scan-demo.ts # File scanner demo (NEW!)
|
|
164
|
+
├── *.test.ts # Comprehensive tests (76 tests)
|
|
165
|
+
└── test-fixtures/
|
|
166
|
+
├── bootstrap-sample.css
|
|
167
|
+
├── tailwind-sample.css
|
|
168
|
+
├── sample.html
|
|
169
|
+
├── sample.tsx
|
|
170
|
+
└── sample.vue
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Supported Frameworks
|
|
174
|
+
|
|
175
|
+
### CSS Frameworks
|
|
176
|
+
- Bootstrap
|
|
177
|
+
- Tailwind
|
|
178
|
+
- Custom CSS
|
|
179
|
+
- Any PostCSS-compatible stylesheet
|
|
180
|
+
|
|
181
|
+
### Template Languages
|
|
182
|
+
- HTML
|
|
183
|
+
- JSX/TSX (React)
|
|
184
|
+
- Vue templates
|
|
185
|
+
- Angular templates
|
|
186
|
+
- Basic support for `clsx`, `classnames` utilities
|
|
187
|
+
|
|
188
|
+
## API Reference
|
|
189
|
+
|
|
190
|
+
### CSS Extraction
|
|
191
|
+
```typescript
|
|
192
|
+
extractSelectors(cssText: string): ExtractedSelectors
|
|
193
|
+
extractSelectorsFromMultiple(cssFiles: string[]): ExtractedSelectors
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Usage Detection
|
|
197
|
+
```typescript
|
|
198
|
+
extractUsage(sourceText: string): { classes: Set<string>, ids: Set<string> }
|
|
199
|
+
extractUsageFromMultiple(sourceFiles: string[]): UsageExtractionResult
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Analysis
|
|
203
|
+
```typescript
|
|
204
|
+
analyzeWaste(selectors: ExtractedSelectors, usage: UsageExtractionResult): AnalysisResult
|
|
205
|
+
estimateWastedBytes(analysis: AnalysisResult): number
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Reporting
|
|
209
|
+
```typescript
|
|
210
|
+
generateReport(analysis: AnalysisResult, format: 'json' | 'text' | 'summary'): string
|
|
211
|
+
generateJsonReport(analysis: AnalysisResult): JsonReport
|
|
212
|
+
generateTextReport(analysis: AnalysisResult): string
|
|
213
|
+
generateSummaryReport(analysis: AnalysisResult): string
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### File System (NEW!)
|
|
217
|
+
```typescript
|
|
218
|
+
scan(options?: ScanOptions): ScanResult
|
|
219
|
+
quickScan(baseDir?: string): string
|
|
220
|
+
crawl(options: CrawlOptions): Promise<CrawlResult>
|
|
221
|
+
crawlSync(options: CrawlOptions): CrawlResult
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Configuration (NEW!)
|
|
225
|
+
```typescript
|
|
226
|
+
loadConfig(baseDir?: string): Config
|
|
227
|
+
getConfig(baseDir?: string): Config
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Next Steps (Week 2)
|
|
231
|
+
|
|
232
|
+
**Day 6-7: CLI Development**
|
|
233
|
+
- [ ] Build `ui-entropy` CLI command
|
|
234
|
+
- [ ] Progress indicators & spinners
|
|
235
|
+
- [ ] Colored terminal output
|
|
236
|
+
- [ ] Watch mode for development
|
|
237
|
+
- [ ] Exit codes based on thresholds
|
|
238
|
+
- [ ] CI/CD integration support
|
|
239
|
+
|
|
240
|
+
**Week 3: GitHub Integration**
|
|
241
|
+
- [ ] GitHub App authentication
|
|
242
|
+
- [ ] Automated PR comments
|
|
243
|
+
- [ ] Trend tracking over time
|
|
244
|
+
- [ ] Badge generation
|
|
245
|
+
|
|
246
|
+
## Tech Stack
|
|
247
|
+
|
|
248
|
+
- **TypeScript** - Type safety & developer experience
|
|
249
|
+
- **PostCSS** - Industry-standard CSS parsing
|
|
250
|
+
- **Vitest** - Fast, modern testing
|
|
251
|
+
- **tsx** - TypeScript execution
|
|
252
|
+
|
|
253
|
+
## Why This Matters
|
|
254
|
+
|
|
255
|
+
This engine is the **foundation** for:
|
|
256
|
+
- ✅ **Scan any project** - Works on real codebases today!
|
|
257
|
+
- ✅ CLI tool (coming Days 6-7)
|
|
258
|
+
- ✅ GitHub integration (automated PR comments)
|
|
259
|
+
- ✅ SaaS dashboard (continuous monitoring)
|
|
260
|
+
- ✅ Real-time waste alerts
|
|
261
|
+
|
|
262
|
+
**Current State:** Fully functional scanner - **ready for production use!**
|
|
263
|
+
**Next Milestone:** CLI tool with colored output, watch mode, CI/CD integration
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ExtractedSelectors } from './parse-css.js';
|
|
2
|
+
import type { UsageExtractionResult } from './extract-usage.js';
|
|
3
|
+
/**
|
|
4
|
+
* Analysis result showing CSS waste metrics
|
|
5
|
+
*/
|
|
6
|
+
export interface AnalysisResult {
|
|
7
|
+
totalClasses: number;
|
|
8
|
+
totalIds: number;
|
|
9
|
+
usedClasses: number;
|
|
10
|
+
usedIds: number;
|
|
11
|
+
unusedClasses: Set<string>;
|
|
12
|
+
unusedIds: Set<string>;
|
|
13
|
+
totalCssBytes: number;
|
|
14
|
+
totalRules: number;
|
|
15
|
+
wastePercentage: number;
|
|
16
|
+
filesScanned: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Analyze CSS waste by comparing extracted selectors against actual usage
|
|
20
|
+
*
|
|
21
|
+
* @param extractedSelectors - Selectors found in CSS files
|
|
22
|
+
* @param usage - Classes/IDs found in source files
|
|
23
|
+
* @returns Analysis with waste metrics
|
|
24
|
+
*/
|
|
25
|
+
export declare function analyzeWaste(extractedSelectors: ExtractedSelectors, usage: UsageExtractionResult): AnalysisResult;
|
|
26
|
+
/**
|
|
27
|
+
* Calculate estimated bytes wasted
|
|
28
|
+
* Simple heuristic: average bytes per rule * number of unused selectors
|
|
29
|
+
*/
|
|
30
|
+
export declare function estimateWastedBytes(analysis: AnalysisResult): number;
|
|
31
|
+
//# sourceMappingURL=analyze.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE;;GAEG;AACH,MAAM,WAAW,cAAc;IAE7B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAGvB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IAGxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,kBAAkB,EAAE,kBAAkB,EACtC,KAAK,EAAE,qBAAqB,GAC3B,cAAc,CA+ChB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAUpE"}
|
package/dist/analyze.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analyze CSS waste by comparing extracted selectors against actual usage
|
|
3
|
+
*
|
|
4
|
+
* @param extractedSelectors - Selectors found in CSS files
|
|
5
|
+
* @param usage - Classes/IDs found in source files
|
|
6
|
+
* @returns Analysis with waste metrics
|
|
7
|
+
*/
|
|
8
|
+
export function analyzeWaste(extractedSelectors, usage) {
|
|
9
|
+
// Find unused selectors
|
|
10
|
+
const unusedClasses = new Set();
|
|
11
|
+
const unusedIds = new Set();
|
|
12
|
+
let usedClassCount = 0;
|
|
13
|
+
let usedIdCount = 0;
|
|
14
|
+
// Check which classes are unused
|
|
15
|
+
for (const className of extractedSelectors.classes) {
|
|
16
|
+
if (usage.classes.has(className)) {
|
|
17
|
+
usedClassCount++;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
unusedClasses.add(className);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Check which IDs are unused
|
|
24
|
+
for (const idName of extractedSelectors.ids) {
|
|
25
|
+
if (usage.ids.has(idName)) {
|
|
26
|
+
usedIdCount++;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
unusedIds.add(idName);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Calculate waste percentage
|
|
33
|
+
const totalSelectors = extractedSelectors.classes.size + extractedSelectors.ids.size;
|
|
34
|
+
// const usedSelectors = usedClassCount + usedIdCount;
|
|
35
|
+
const unusedSelectors = unusedClasses.size + unusedIds.size;
|
|
36
|
+
const wastePercentage = totalSelectors > 0
|
|
37
|
+
? (unusedSelectors / totalSelectors) * 100
|
|
38
|
+
: 0;
|
|
39
|
+
return {
|
|
40
|
+
totalClasses: extractedSelectors.classes.size,
|
|
41
|
+
totalIds: extractedSelectors.ids.size,
|
|
42
|
+
usedClasses: usedClassCount,
|
|
43
|
+
usedIds: usedIdCount,
|
|
44
|
+
unusedClasses,
|
|
45
|
+
unusedIds,
|
|
46
|
+
totalCssBytes: extractedSelectors.totalBytes,
|
|
47
|
+
totalRules: extractedSelectors.totalRules,
|
|
48
|
+
wastePercentage: Math.round(wastePercentage * 10) / 10, // Round to 1 decimal
|
|
49
|
+
filesScanned: usage.filesScanned,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Calculate estimated bytes wasted
|
|
54
|
+
* Simple heuristic: average bytes per rule * number of unused selectors
|
|
55
|
+
*/
|
|
56
|
+
export function estimateWastedBytes(analysis) {
|
|
57
|
+
const totalSelectors = analysis.totalClasses + analysis.totalIds;
|
|
58
|
+
const unusedSelectors = analysis.unusedClasses.size + analysis.unusedIds.size;
|
|
59
|
+
if (totalSelectors === 0 || analysis.totalRules === 0) {
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
const avgBytesPerSelector = analysis.totalCssBytes / totalSelectors;
|
|
63
|
+
return Math.round(avgBytesPerSelector * unusedSelectors);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=analyze.js.map
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Configuration schema for UI Entropy Scanner
|
|
4
|
+
*/
|
|
5
|
+
declare const ConfigSchema: z.ZodObject<{
|
|
6
|
+
cssPatterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
7
|
+
sourcePatterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
8
|
+
ignorePatterns: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
9
|
+
respectGitignore: z.ZodOptional<z.ZodBoolean>;
|
|
10
|
+
output: z.ZodOptional<z.ZodObject<{
|
|
11
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
12
|
+
json: "json";
|
|
13
|
+
text: "text";
|
|
14
|
+
summary: "summary";
|
|
15
|
+
}>>;
|
|
16
|
+
file: z.ZodOptional<z.ZodString>;
|
|
17
|
+
}, z.core.$strip>>;
|
|
18
|
+
thresholds: z.ZodOptional<z.ZodObject<{
|
|
19
|
+
wastePercentage: z.ZodOptional<z.ZodNumber>;
|
|
20
|
+
unusedSelectors: z.ZodOptional<z.ZodNumber>;
|
|
21
|
+
}, z.core.$strip>>;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
24
|
+
/**
|
|
25
|
+
* Default configuration
|
|
26
|
+
*/
|
|
27
|
+
export declare const DEFAULT_CONFIG: Required<Omit<Config, 'output' | 'thresholds'>>;
|
|
28
|
+
/**
|
|
29
|
+
* Load configuration from file
|
|
30
|
+
*/
|
|
31
|
+
export declare function loadConfig(baseDir?: string): Config;
|
|
32
|
+
/**
|
|
33
|
+
* Merge user config with defaults
|
|
34
|
+
*/
|
|
35
|
+
export declare function mergeConfig(userConfig: Config): Required<Omit<Config, 'output' | 'thresholds'>> & Pick<Config, 'output' | 'thresholds'>;
|
|
36
|
+
/**
|
|
37
|
+
* Load and merge config
|
|
38
|
+
*/
|
|
39
|
+
export declare function getConfig(baseDir?: string): ReturnType<typeof mergeConfig>;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;iBAoChB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,YAAY,CAAC,CAyB1E,CAAC;AAYF;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,GAAE,MAAsB,GAAG,MAAM,CA2BlE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,YAAY,CAAC,CASvI;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,MAAsB,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAGzF"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration schema for UI Entropy Scanner
|
|
6
|
+
*/
|
|
7
|
+
const ConfigSchema = z.object({
|
|
8
|
+
/**
|
|
9
|
+
* Glob patterns for CSS files
|
|
10
|
+
*/
|
|
11
|
+
cssPatterns: z.array(z.string()).optional(),
|
|
12
|
+
/**
|
|
13
|
+
* Glob patterns for source files
|
|
14
|
+
*/
|
|
15
|
+
sourcePatterns: z.array(z.string()).optional(),
|
|
16
|
+
/**
|
|
17
|
+
* Patterns to ignore
|
|
18
|
+
*/
|
|
19
|
+
ignorePatterns: z.array(z.string()).optional(),
|
|
20
|
+
/**
|
|
21
|
+
* Whether to respect .gitignore
|
|
22
|
+
*/
|
|
23
|
+
respectGitignore: z.boolean().optional(),
|
|
24
|
+
/**
|
|
25
|
+
* Custom output format
|
|
26
|
+
*/
|
|
27
|
+
output: z.object({
|
|
28
|
+
format: z.enum(['text', 'json', 'summary']).optional(),
|
|
29
|
+
file: z.string().optional(),
|
|
30
|
+
}).optional(),
|
|
31
|
+
/**
|
|
32
|
+
* Thresholds for warnings/errors
|
|
33
|
+
*/
|
|
34
|
+
thresholds: z.object({
|
|
35
|
+
wastePercentage: z.number().min(0).max(100).optional(),
|
|
36
|
+
unusedSelectors: z.number().min(0).optional(),
|
|
37
|
+
}).optional(),
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Default configuration
|
|
41
|
+
*/
|
|
42
|
+
export const DEFAULT_CONFIG = {
|
|
43
|
+
cssPatterns: ['**/*.css', '**/*.scss', '**/*.sass'],
|
|
44
|
+
sourcePatterns: [
|
|
45
|
+
'**/*.html',
|
|
46
|
+
'**/*.tsx',
|
|
47
|
+
'**/*.ts',
|
|
48
|
+
'**/*.jsx',
|
|
49
|
+
'**/*.js',
|
|
50
|
+
'**/*.vue',
|
|
51
|
+
'**/*.svelte',
|
|
52
|
+
],
|
|
53
|
+
ignorePatterns: [
|
|
54
|
+
'node_modules/**',
|
|
55
|
+
'dist/**',
|
|
56
|
+
'build/**',
|
|
57
|
+
'.git/**',
|
|
58
|
+
'coverage/**',
|
|
59
|
+
'.next/**',
|
|
60
|
+
'.nuxt/**',
|
|
61
|
+
'out/**',
|
|
62
|
+
'public/**',
|
|
63
|
+
'**/*.min.css',
|
|
64
|
+
'**/*.min.js',
|
|
65
|
+
],
|
|
66
|
+
respectGitignore: true,
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Config file names to search for
|
|
70
|
+
*/
|
|
71
|
+
const CONFIG_FILES = [
|
|
72
|
+
'.ui-entropy.json',
|
|
73
|
+
'.ui-entropyrc',
|
|
74
|
+
'.ui-entropyrc.json',
|
|
75
|
+
'ui-entropy.config.json',
|
|
76
|
+
];
|
|
77
|
+
/**
|
|
78
|
+
* Load configuration from file
|
|
79
|
+
*/
|
|
80
|
+
export function loadConfig(baseDir = process.cwd()) {
|
|
81
|
+
// Try to find config file
|
|
82
|
+
for (const filename of CONFIG_FILES) {
|
|
83
|
+
const configPath = join(baseDir, filename);
|
|
84
|
+
if (existsSync(configPath)) {
|
|
85
|
+
try {
|
|
86
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
87
|
+
const rawConfig = JSON.parse(content);
|
|
88
|
+
// Validate with zod
|
|
89
|
+
const config = ConfigSchema.parse(rawConfig);
|
|
90
|
+
return config;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (error instanceof z.ZodError) {
|
|
94
|
+
throw new Error(`Invalid config file ${filename}:\n${error.issues.map(issue => ` - ${issue.path.join('.')}: ${issue.message}`).join('\n')}`);
|
|
95
|
+
}
|
|
96
|
+
throw new Error(`Failed to parse config file ${filename}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// No config file found, return empty config
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Merge user config with defaults
|
|
105
|
+
*/
|
|
106
|
+
export function mergeConfig(userConfig) {
|
|
107
|
+
return {
|
|
108
|
+
cssPatterns: userConfig.cssPatterns ?? DEFAULT_CONFIG.cssPatterns,
|
|
109
|
+
sourcePatterns: userConfig.sourcePatterns ?? DEFAULT_CONFIG.sourcePatterns,
|
|
110
|
+
ignorePatterns: userConfig.ignorePatterns ?? DEFAULT_CONFIG.ignorePatterns,
|
|
111
|
+
respectGitignore: userConfig.respectGitignore ?? DEFAULT_CONFIG.respectGitignore,
|
|
112
|
+
output: userConfig.output,
|
|
113
|
+
thresholds: userConfig.thresholds,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Load and merge config
|
|
118
|
+
*/
|
|
119
|
+
export function getConfig(baseDir = process.cwd()) {
|
|
120
|
+
const userConfig = loadConfig(baseDir);
|
|
121
|
+
return mergeConfig(userConfig);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=config.js.map
|
package/dist/crawl.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface CrawlOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Base directory to scan from
|
|
4
|
+
*/
|
|
5
|
+
baseDir: string;
|
|
6
|
+
/**
|
|
7
|
+
* Glob patterns for CSS files
|
|
8
|
+
* @default ['**\/*.css', '**\/*.scss', '**\/*.sass']
|
|
9
|
+
*/
|
|
10
|
+
cssPatterns?: string[];
|
|
11
|
+
/**
|
|
12
|
+
* Glob patterns for source files
|
|
13
|
+
* @default ['**\/*.html', '**\/*.tsx', '**\/*.ts', '**\/*.jsx', '**\/*.js', '**\/*.vue']
|
|
14
|
+
*/
|
|
15
|
+
sourcePatterns?: string[];
|
|
16
|
+
/**
|
|
17
|
+
* Patterns to ignore (in addition to .gitignore)
|
|
18
|
+
* @default ['node_modules/**', 'dist/**', 'build/**', '.git/**']
|
|
19
|
+
*/
|
|
20
|
+
ignorePatterns?: string[];
|
|
21
|
+
/**
|
|
22
|
+
* Whether to respect .gitignore file
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
respectGitignore?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface CrawlResult {
|
|
28
|
+
cssFiles: Array<{
|
|
29
|
+
path: string;
|
|
30
|
+
content: string;
|
|
31
|
+
}>;
|
|
32
|
+
sourceFiles: Array<{
|
|
33
|
+
path: string;
|
|
34
|
+
content: string;
|
|
35
|
+
}>;
|
|
36
|
+
stats: {
|
|
37
|
+
totalCssFiles: number;
|
|
38
|
+
totalSourceFiles: number;
|
|
39
|
+
totalCssBytes: number;
|
|
40
|
+
totalSourceBytes: number;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Crawl directory for CSS and source files
|
|
45
|
+
*/
|
|
46
|
+
export declare function crawl(options: CrawlOptions): Promise<CrawlResult>;
|
|
47
|
+
/**
|
|
48
|
+
* Synchronous version of crawl (useful for CLI/simple use cases)
|
|
49
|
+
*/
|
|
50
|
+
export declare function crawlSync(options: CrawlOptions): CrawlResult;
|
|
51
|
+
//# sourceMappingURL=crawl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../src/crawl.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,KAAK,EAAE;QACL,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;QACzB,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAkDD;;GAEG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA8DvE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,CA8D5D"}
|