react-code-smell-detector 1.4.2 → 1.5.1
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/README.md +227 -22
- package/dist/__tests__/aiRefactoring.test.d.ts +2 -0
- package/dist/__tests__/aiRefactoring.test.d.ts.map +1 -0
- package/dist/__tests__/aiRefactoring.test.js +86 -0
- package/dist/__tests__/analyzer-real.test.d.ts +2 -0
- package/dist/__tests__/analyzer-real.test.d.ts.map +1 -0
- package/dist/__tests__/analyzer-real.test.js +149 -0
- package/dist/__tests__/analyzer.test.d.ts +2 -0
- package/dist/__tests__/analyzer.test.d.ts.map +1 -0
- package/dist/__tests__/analyzer.test.js +173 -0
- package/dist/__tests__/baseline.test.d.ts +2 -0
- package/dist/__tests__/baseline.test.d.ts.map +1 -0
- package/dist/__tests__/baseline.test.js +136 -0
- package/dist/__tests__/bundleAnalyzer.test.d.ts +2 -0
- package/dist/__tests__/bundleAnalyzer.test.d.ts.map +1 -0
- package/dist/__tests__/bundleAnalyzer.test.js +182 -0
- package/dist/__tests__/customRules.test.d.ts +2 -0
- package/dist/__tests__/customRules.test.d.ts.map +1 -0
- package/dist/__tests__/customRules.test.js +283 -0
- package/dist/__tests__/detectors/index.test.d.ts +2 -0
- package/dist/__tests__/detectors/index.test.d.ts.map +1 -0
- package/dist/__tests__/detectors/index.test.js +1012 -0
- package/dist/__tests__/detectors/newDetectors.test.d.ts +2 -0
- package/dist/__tests__/detectors/newDetectors.test.d.ts.map +1 -0
- package/dist/__tests__/detectors/newDetectors.test.js +333 -0
- package/dist/__tests__/docGenerator.test.d.ts +2 -0
- package/dist/__tests__/docGenerator.test.d.ts.map +1 -0
- package/dist/__tests__/docGenerator.test.js +157 -0
- package/dist/__tests__/fixer.test.d.ts +2 -0
- package/dist/__tests__/fixer.test.d.ts.map +1 -0
- package/dist/__tests__/fixer.test.js +193 -0
- package/dist/__tests__/git.test.d.ts +2 -0
- package/dist/__tests__/git.test.d.ts.map +1 -0
- package/dist/__tests__/git.test.js +38 -0
- package/dist/__tests__/graphGenerator.test.d.ts +2 -0
- package/dist/__tests__/graphGenerator.test.d.ts.map +1 -0
- package/dist/__tests__/graphGenerator.test.js +190 -0
- package/dist/__tests__/htmlReporter.test.d.ts +2 -0
- package/dist/__tests__/htmlReporter.test.d.ts.map +1 -0
- package/dist/__tests__/htmlReporter.test.js +258 -0
- package/dist/__tests__/interactiveFixer.test.d.ts +2 -0
- package/dist/__tests__/interactiveFixer.test.d.ts.map +1 -0
- package/dist/__tests__/interactiveFixer.test.js +231 -0
- package/dist/__tests__/parser.test.d.ts +2 -0
- package/dist/__tests__/parser.test.d.ts.map +1 -0
- package/dist/__tests__/parser.test.js +56 -0
- package/dist/__tests__/performanceBudget.test.d.ts +2 -0
- package/dist/__tests__/performanceBudget.test.d.ts.map +1 -0
- package/dist/__tests__/performanceBudget.test.js +242 -0
- package/dist/__tests__/prComments.test.d.ts +2 -0
- package/dist/__tests__/prComments.test.d.ts.map +1 -0
- package/dist/__tests__/prComments.test.js +118 -0
- package/dist/__tests__/reporter.test.d.ts +2 -0
- package/dist/__tests__/reporter.test.d.ts.map +1 -0
- package/dist/__tests__/reporter.test.js +136 -0
- package/dist/__tests__/watcher.test.d.ts +2 -0
- package/dist/__tests__/watcher.test.d.ts.map +1 -0
- package/dist/__tests__/watcher.test.js +161 -0
- package/dist/__tests__/webhooks.test.d.ts +2 -0
- package/dist/__tests__/webhooks.test.d.ts.map +1 -0
- package/dist/__tests__/webhooks.test.js +209 -0
- package/dist/aiRefactoring.d.ts +29 -0
- package/dist/aiRefactoring.d.ts.map +1 -0
- package/dist/aiRefactoring.js +290 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +33 -1
- package/dist/cli.js +123 -1
- package/dist/detectors/contextApi.d.ts +11 -0
- package/dist/detectors/contextApi.d.ts.map +1 -0
- package/dist/detectors/contextApi.js +151 -0
- package/dist/detectors/errorBoundary.d.ts +11 -0
- package/dist/detectors/errorBoundary.d.ts.map +1 -0
- package/dist/detectors/errorBoundary.js +167 -0
- package/dist/detectors/formValidation.d.ts +11 -0
- package/dist/detectors/formValidation.d.ts.map +1 -0
- package/dist/detectors/formValidation.js +193 -0
- package/dist/detectors/index.d.ts +6 -0
- package/dist/detectors/index.d.ts.map +1 -1
- package/dist/detectors/index.js +12 -0
- package/dist/detectors/serverComponents.d.ts +11 -0
- package/dist/detectors/serverComponents.d.ts.map +1 -0
- package/dist/detectors/serverComponents.js +222 -0
- package/dist/detectors/stateManagement.d.ts +11 -0
- package/dist/detectors/stateManagement.d.ts.map +1 -0
- package/dist/detectors/stateManagement.js +193 -0
- package/dist/detectors/testingGaps.d.ts +15 -0
- package/dist/detectors/testingGaps.d.ts.map +1 -0
- package/dist/detectors/testingGaps.js +182 -0
- package/dist/docGenerator.d.ts +37 -0
- package/dist/docGenerator.d.ts.map +1 -0
- package/dist/docGenerator.js +306 -0
- package/dist/guide.d.ts +9 -0
- package/dist/guide.d.ts.map +1 -0
- package/dist/guide.js +922 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/interactiveFixer.d.ts +20 -0
- package/dist/interactiveFixer.d.ts.map +1 -0
- package/dist/interactiveFixer.js +178 -0
- package/dist/performanceBudget.d.ts +54 -0
- package/dist/performanceBudget.d.ts.map +1 -0
- package/dist/performanceBudget.js +218 -0
- package/dist/prComments.d.ts +47 -0
- package/dist/prComments.d.ts.map +1 -0
- package/dist/prComments.js +233 -0
- package/dist/types/index.d.ts +12 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +18 -0
- package/package.json +10 -4
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
/**
|
|
4
|
+
* Generate documentation from component analysis
|
|
5
|
+
*/
|
|
6
|
+
export async function generateComponentDocs(result, rootDir, options = { format: 'markdown' }) {
|
|
7
|
+
const docs = extractComponentDocs(result, rootDir);
|
|
8
|
+
switch (options.format) {
|
|
9
|
+
case 'html':
|
|
10
|
+
return generateHTMLDocs(docs, result, options);
|
|
11
|
+
case 'json':
|
|
12
|
+
return JSON.stringify(docs, null, 2);
|
|
13
|
+
case 'markdown':
|
|
14
|
+
default:
|
|
15
|
+
return generateMarkdownDocs(docs, result, options);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Extract documentation data from analysis
|
|
20
|
+
*/
|
|
21
|
+
function extractComponentDocs(result, rootDir) {
|
|
22
|
+
const docs = [];
|
|
23
|
+
for (const file of result.files) {
|
|
24
|
+
for (const component of file.components) {
|
|
25
|
+
const relativePath = file.file.replace(rootDir, '').replace(/^\//, '');
|
|
26
|
+
const componentSmells = file.smells.filter(s => s.line >= component.startLine && s.line <= component.endLine);
|
|
27
|
+
// Determine complexity rating
|
|
28
|
+
const complexity = getComplexityRating(component);
|
|
29
|
+
const maintainability = getMaintainabilityRating(componentSmells.length, component.lineCount);
|
|
30
|
+
docs.push({
|
|
31
|
+
name: component.name,
|
|
32
|
+
file: file.file,
|
|
33
|
+
relativePath,
|
|
34
|
+
lineCount: component.lineCount,
|
|
35
|
+
props: [], // Would need parser enhancement to get prop names
|
|
36
|
+
hooks: {
|
|
37
|
+
useState: component.useStateCount,
|
|
38
|
+
useEffect: component.useEffectCount,
|
|
39
|
+
useMemo: component.useMemoCount,
|
|
40
|
+
useCallback: component.useCallbackCount,
|
|
41
|
+
useRef: 0, // Would need parser enhancement
|
|
42
|
+
custom: [],
|
|
43
|
+
},
|
|
44
|
+
smells: componentSmells,
|
|
45
|
+
metrics: {
|
|
46
|
+
complexity,
|
|
47
|
+
maintainability,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return docs.sort((a, b) => a.name.localeCompare(b.name));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Generate Markdown documentation
|
|
56
|
+
*/
|
|
57
|
+
function generateMarkdownDocs(docs, result, options) {
|
|
58
|
+
let md = '# Component Documentation\n\n';
|
|
59
|
+
md += `*Generated by react-code-smell-detector*\n\n`;
|
|
60
|
+
md += `---\n\n`;
|
|
61
|
+
// Summary
|
|
62
|
+
md += '## Summary\n\n';
|
|
63
|
+
md += `| Metric | Value |\n`;
|
|
64
|
+
md += `|--------|-------|\n`;
|
|
65
|
+
md += `| Total Components | ${docs.length} |\n`;
|
|
66
|
+
md += `| Total Files | ${result.summary.totalFiles} |\n`;
|
|
67
|
+
md += `| Technical Debt Grade | ${result.debtScore.grade} |\n`;
|
|
68
|
+
md += `| Estimated Refactor Time | ${result.debtScore.estimatedRefactorTime} |\n\n`;
|
|
69
|
+
// Table of contents
|
|
70
|
+
md += '## Components\n\n';
|
|
71
|
+
if (options.groupByFolder) {
|
|
72
|
+
const grouped = groupByFolder(docs);
|
|
73
|
+
for (const [folder, folderDocs] of Object.entries(grouped)) {
|
|
74
|
+
md += `### 📁 ${folder || 'Root'}\n\n`;
|
|
75
|
+
for (const doc of folderDocs) {
|
|
76
|
+
md += formatComponentMarkdown(doc, options);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
for (const doc of docs) {
|
|
82
|
+
md += formatComponentMarkdown(doc, options);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Index
|
|
86
|
+
md += '\n---\n\n';
|
|
87
|
+
md += '## Index\n\n';
|
|
88
|
+
md += '| Component | File | Lines | Hooks | Issues |\n';
|
|
89
|
+
md += '|-----------|------|-------|-------|--------|\n';
|
|
90
|
+
for (const doc of docs) {
|
|
91
|
+
const totalHooks = doc.hooks.useState + doc.hooks.useEffect + doc.hooks.useMemo + doc.hooks.useCallback;
|
|
92
|
+
md += `| [${doc.name}](#${doc.name.toLowerCase()}) | \`${doc.relativePath}\` | ${doc.lineCount} | ${totalHooks} | ${doc.smells.length} |\n`;
|
|
93
|
+
}
|
|
94
|
+
return md;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Format a single component as Markdown
|
|
98
|
+
*/
|
|
99
|
+
function formatComponentMarkdown(doc, options) {
|
|
100
|
+
let md = `#### ${doc.name}\n\n`;
|
|
101
|
+
md += `📄 \`${doc.relativePath}\`\n\n`;
|
|
102
|
+
// Metrics table
|
|
103
|
+
if (options.includeMetrics !== false) {
|
|
104
|
+
md += `| Metric | Value |\n`;
|
|
105
|
+
md += `|--------|-------|\n`;
|
|
106
|
+
md += `| Lines | ${doc.lineCount} |\n`;
|
|
107
|
+
md += `| Complexity | ${doc.metrics.complexity} |\n`;
|
|
108
|
+
md += `| Maintainability | ${doc.metrics.maintainability} |\n`;
|
|
109
|
+
}
|
|
110
|
+
// Hooks
|
|
111
|
+
const hooks = [];
|
|
112
|
+
if (doc.hooks.useState > 0)
|
|
113
|
+
hooks.push(`useState (${doc.hooks.useState})`);
|
|
114
|
+
if (doc.hooks.useEffect > 0)
|
|
115
|
+
hooks.push(`useEffect (${doc.hooks.useEffect})`);
|
|
116
|
+
if (doc.hooks.useMemo > 0)
|
|
117
|
+
hooks.push(`useMemo (${doc.hooks.useMemo})`);
|
|
118
|
+
if (doc.hooks.useCallback > 0)
|
|
119
|
+
hooks.push(`useCallback (${doc.hooks.useCallback})`);
|
|
120
|
+
if (hooks.length > 0) {
|
|
121
|
+
md += `\n**Hooks:** ${hooks.join(', ')}\n`;
|
|
122
|
+
}
|
|
123
|
+
// Issues
|
|
124
|
+
if (options.includeSmells !== false && doc.smells.length > 0) {
|
|
125
|
+
md += `\n**Issues (${doc.smells.length}):**\n`;
|
|
126
|
+
for (const smell of doc.smells.slice(0, 5)) {
|
|
127
|
+
const emoji = smell.severity === 'error' ? '🔴' : smell.severity === 'warning' ? '🟡' : '🔵';
|
|
128
|
+
md += `- ${emoji} ${smell.type}: ${smell.message}\n`;
|
|
129
|
+
}
|
|
130
|
+
if (doc.smells.length > 5) {
|
|
131
|
+
md += `- *... and ${doc.smells.length - 5} more*\n`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
md += '\n---\n\n';
|
|
135
|
+
return md;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Generate HTML documentation
|
|
139
|
+
*/
|
|
140
|
+
function generateHTMLDocs(docs, result, options) {
|
|
141
|
+
return `<!DOCTYPE html>
|
|
142
|
+
<html lang="en">
|
|
143
|
+
<head>
|
|
144
|
+
<meta charset="UTF-8">
|
|
145
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
146
|
+
<title>Component Documentation</title>
|
|
147
|
+
<style>
|
|
148
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
149
|
+
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.6; color: #333; background: #f5f5f5; }
|
|
150
|
+
.container { max-width: 1200px; margin: 0 auto; padding: 20px; }
|
|
151
|
+
header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px 20px; margin-bottom: 30px; border-radius: 10px; }
|
|
152
|
+
h1 { font-size: 2.5rem; margin-bottom: 10px; }
|
|
153
|
+
.subtitle { opacity: 0.9; }
|
|
154
|
+
.summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
|
|
155
|
+
.summary-card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); text-align: center; }
|
|
156
|
+
.summary-value { font-size: 2rem; font-weight: bold; color: #667eea; }
|
|
157
|
+
.summary-label { color: #666; font-size: 0.9rem; }
|
|
158
|
+
.components { display: grid; gap: 20px; }
|
|
159
|
+
.component-card { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
|
160
|
+
.component-name { font-size: 1.3rem; color: #333; margin-bottom: 5px; }
|
|
161
|
+
.component-path { color: #666; font-size: 0.85rem; font-family: monospace; background: #f0f0f0; padding: 2px 8px; border-radius: 4px; }
|
|
162
|
+
.metrics { display: flex; gap: 15px; margin: 15px 0; flex-wrap: wrap; }
|
|
163
|
+
.metric { background: #f0f0f0; padding: 5px 12px; border-radius: 20px; font-size: 0.85rem; }
|
|
164
|
+
.hooks { display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0; }
|
|
165
|
+
.hook { background: #e3f2fd; color: #1976d2; padding: 4px 10px; border-radius: 4px; font-size: 0.8rem; }
|
|
166
|
+
.issues { margin-top: 15px; }
|
|
167
|
+
.issue { padding: 8px; margin: 5px 0; border-radius: 4px; font-size: 0.9rem; }
|
|
168
|
+
.issue.error { background: #ffebee; color: #c62828; }
|
|
169
|
+
.issue.warning { background: #fff3e0; color: #ef6c00; }
|
|
170
|
+
.issue.info { background: #e3f2fd; color: #1565c0; }
|
|
171
|
+
.search { margin-bottom: 20px; }
|
|
172
|
+
.search input { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 1rem; }
|
|
173
|
+
.grade { font-size: 3rem; }
|
|
174
|
+
footer { text-align: center; padding: 20px; color: #666; font-size: 0.85rem; }
|
|
175
|
+
</style>
|
|
176
|
+
</head>
|
|
177
|
+
<body>
|
|
178
|
+
<div class="container">
|
|
179
|
+
<header>
|
|
180
|
+
<h1>📚 Component Documentation</h1>
|
|
181
|
+
<p class="subtitle">Generated by react-code-smell-detector</p>
|
|
182
|
+
</header>
|
|
183
|
+
|
|
184
|
+
<div class="summary">
|
|
185
|
+
<div class="summary-card">
|
|
186
|
+
<div class="summary-value">${docs.length}</div>
|
|
187
|
+
<div class="summary-label">Components</div>
|
|
188
|
+
</div>
|
|
189
|
+
<div class="summary-card">
|
|
190
|
+
<div class="summary-value">${result.summary.totalFiles}</div>
|
|
191
|
+
<div class="summary-label">Files</div>
|
|
192
|
+
</div>
|
|
193
|
+
<div class="summary-card">
|
|
194
|
+
<div class="summary-value grade">${result.debtScore.grade}</div>
|
|
195
|
+
<div class="summary-label">Debt Grade</div>
|
|
196
|
+
</div>
|
|
197
|
+
<div class="summary-card">
|
|
198
|
+
<div class="summary-value">${result.debtScore.score}</div>
|
|
199
|
+
<div class="summary-label">Score</div>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<div class="search">
|
|
204
|
+
<input type="text" placeholder="Search components..." id="search" onkeyup="filterComponents()">
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<div class="components" id="components">
|
|
208
|
+
${docs.map(doc => `
|
|
209
|
+
<div class="component-card" data-name="${doc.name.toLowerCase()}">
|
|
210
|
+
<div class="component-name">${doc.name}</div>
|
|
211
|
+
<span class="component-path">${doc.relativePath}</span>
|
|
212
|
+
|
|
213
|
+
<div class="metrics">
|
|
214
|
+
<span class="metric">📏 ${doc.lineCount} lines</span>
|
|
215
|
+
<span class="metric">⚡ ${doc.metrics.complexity}</span>
|
|
216
|
+
<span class="metric">🔧 ${doc.metrics.maintainability}</span>
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
<div class="hooks">
|
|
220
|
+
${doc.hooks.useState > 0 ? `<span class="hook">useState ×${doc.hooks.useState}</span>` : ''}
|
|
221
|
+
${doc.hooks.useEffect > 0 ? `<span class="hook">useEffect ×${doc.hooks.useEffect}</span>` : ''}
|
|
222
|
+
${doc.hooks.useMemo > 0 ? `<span class="hook">useMemo ×${doc.hooks.useMemo}</span>` : ''}
|
|
223
|
+
${doc.hooks.useCallback > 0 ? `<span class="hook">useCallback ×${doc.hooks.useCallback}</span>` : ''}
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
${doc.smells.length > 0 ? `
|
|
227
|
+
<div class="issues">
|
|
228
|
+
${doc.smells.slice(0, 3).map(s => `
|
|
229
|
+
<div class="issue ${s.severity}">${s.type}: ${s.message}</div>
|
|
230
|
+
`).join('')}
|
|
231
|
+
${doc.smells.length > 3 ? `<div class="issue info">... and ${doc.smells.length - 3} more</div>` : ''}
|
|
232
|
+
</div>
|
|
233
|
+
` : ''}
|
|
234
|
+
</div>
|
|
235
|
+
`).join('')}
|
|
236
|
+
</div>
|
|
237
|
+
|
|
238
|
+
<footer>
|
|
239
|
+
Generated by <a href="https://github.com/vsthakur101/react-code-smell-detector">react-code-smell-detector</a>
|
|
240
|
+
</footer>
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
<script>
|
|
244
|
+
function filterComponents() {
|
|
245
|
+
const query = document.getElementById('search').value.toLowerCase();
|
|
246
|
+
const cards = document.querySelectorAll('.component-card');
|
|
247
|
+
cards.forEach(card => {
|
|
248
|
+
const name = card.dataset.name;
|
|
249
|
+
card.style.display = name.includes(query) ? 'block' : 'none';
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
</script>
|
|
253
|
+
</body>
|
|
254
|
+
</html>`;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Group components by folder
|
|
258
|
+
*/
|
|
259
|
+
function groupByFolder(docs) {
|
|
260
|
+
const grouped = {};
|
|
261
|
+
for (const doc of docs) {
|
|
262
|
+
const parts = doc.relativePath.split('/');
|
|
263
|
+
const folder = parts.length > 1 ? parts.slice(0, -1).join('/') : '';
|
|
264
|
+
if (!grouped[folder]) {
|
|
265
|
+
grouped[folder] = [];
|
|
266
|
+
}
|
|
267
|
+
grouped[folder].push(doc);
|
|
268
|
+
}
|
|
269
|
+
return grouped;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Get complexity rating based on component metrics
|
|
273
|
+
*/
|
|
274
|
+
function getComplexityRating(component) {
|
|
275
|
+
const hookCount = component.useEffectCount + component.useStateCount +
|
|
276
|
+
component.useMemoCount + component.useCallbackCount;
|
|
277
|
+
if (component.lineCount > 300 || hookCount > 10)
|
|
278
|
+
return '🔴 High';
|
|
279
|
+
if (component.lineCount > 150 || hookCount > 5)
|
|
280
|
+
return '🟡 Medium';
|
|
281
|
+
return '🟢 Low';
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get maintainability rating based on smells and size
|
|
285
|
+
*/
|
|
286
|
+
function getMaintainabilityRating(smellCount, lineCount) {
|
|
287
|
+
const ratio = smellCount / Math.max(lineCount / 50, 1);
|
|
288
|
+
if (ratio > 2 || smellCount > 5)
|
|
289
|
+
return '🔴 Poor';
|
|
290
|
+
if (ratio > 1 || smellCount > 2)
|
|
291
|
+
return '🟡 Fair';
|
|
292
|
+
return '🟢 Good';
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Write documentation to file
|
|
296
|
+
*/
|
|
297
|
+
export async function writeComponentDocs(result, rootDir, options) {
|
|
298
|
+
const content = await generateComponentDocs(result, rootDir, options);
|
|
299
|
+
const ext = options.format === 'html' ? 'html' : options.format === 'json' ? 'json' : 'md';
|
|
300
|
+
const filename = `COMPONENTS.${ext}`;
|
|
301
|
+
const outputPath = options.outputDir
|
|
302
|
+
? path.join(options.outputDir, filename)
|
|
303
|
+
: path.join(rootDir, filename);
|
|
304
|
+
await fs.writeFile(outputPath, content, 'utf-8');
|
|
305
|
+
return outputPath;
|
|
306
|
+
}
|
package/dist/guide.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive guide for React Code Smell Detector
|
|
3
|
+
*/
|
|
4
|
+
export declare function runGuide(): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Create a demo project with examples of all detectable smells
|
|
7
|
+
*/
|
|
8
|
+
export declare function createDemoProject(targetDir: string): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=guide.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guide.d.ts","sourceRoot":"","sources":["../src/guide.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAmF9C;AAmWD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiFxE"}
|