@girardelli/architect 5.0.0 → 8.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/dist/{cli.d.ts → src/adapters/cli.d.ts} +1 -2
- package/dist/{cli.js → src/adapters/cli.js} +191 -213
- package/dist/src/adapters/cli.js.map +1 -0
- package/dist/src/adapters/github-action.d.ts +9 -0
- package/dist/src/adapters/github-action.js +94 -0
- package/dist/src/adapters/github-action.js.map +1 -0
- package/dist/src/adapters/html-reporter/scripts.d.ts +5 -0
- package/dist/src/adapters/html-reporter/scripts.js +400 -0
- package/dist/src/adapters/html-reporter/scripts.js.map +1 -0
- package/dist/src/adapters/html-reporter/sections/agents.d.ts +2 -0
- package/dist/src/adapters/html-reporter/sections/agents.js +260 -0
- package/dist/src/adapters/html-reporter/sections/agents.js.map +1 -0
- package/dist/src/adapters/html-reporter/sections/anti-patterns.d.ts +13 -0
- package/dist/src/adapters/html-reporter/sections/anti-patterns.js +64 -0
- package/dist/src/adapters/html-reporter/sections/anti-patterns.js.map +1 -0
- package/dist/src/adapters/html-reporter/sections/header.d.ts +3 -0
- package/dist/src/adapters/html-reporter/sections/header.js +30 -0
- package/dist/src/adapters/html-reporter/sections/header.js.map +1 -0
- package/dist/src/adapters/html-reporter/sections/layers.d.ts +9 -0
- package/dist/src/adapters/html-reporter/sections/layers.js +143 -0
- package/dist/src/adapters/html-reporter/sections/layers.js.map +1 -0
- package/dist/src/adapters/html-reporter/sections/overview.d.ts +2 -0
- package/dist/src/adapters/html-reporter/sections/overview.js +58 -0
- package/dist/src/adapters/html-reporter/sections/overview.js.map +1 -0
- package/dist/src/adapters/html-reporter/sections/refactoring-plan.d.ts +3 -0
- package/dist/src/adapters/html-reporter/sections/refactoring-plan.js +151 -0
- package/dist/src/adapters/html-reporter/sections/refactoring-plan.js.map +1 -0
- package/dist/src/adapters/html-reporter/sections/score.d.ts +7 -0
- package/dist/src/adapters/html-reporter/sections/score.js +70 -0
- package/dist/src/adapters/html-reporter/sections/score.js.map +1 -0
- package/dist/src/adapters/html-reporter/sections/suggestions.d.ts +7 -0
- package/dist/src/adapters/html-reporter/sections/suggestions.js +34 -0
- package/dist/src/adapters/html-reporter/sections/suggestions.js.map +1 -0
- package/dist/src/adapters/html-reporter/styles.d.ts +1 -0
- package/dist/src/adapters/html-reporter/styles.js +526 -0
- package/dist/src/adapters/html-reporter/styles.js.map +1 -0
- package/dist/src/adapters/html-reporter/utils_adapters.d.ts +20 -0
- package/dist/src/adapters/html-reporter/utils_adapters.js +32 -0
- package/dist/src/adapters/html-reporter/utils_adapters.js.map +1 -0
- package/dist/src/adapters/html-reporter/utils_sections.d.ts +7 -0
- package/dist/src/adapters/html-reporter/utils_sections.js +58 -0
- package/dist/src/adapters/html-reporter/utils_sections.js.map +1 -0
- package/dist/src/adapters/html-reporter.d.ts +10 -0
- package/dist/src/adapters/html-reporter.js +97 -0
- package/dist/src/adapters/html-reporter.js.map +1 -0
- package/dist/src/adapters/progress-logger.d.ts +55 -0
- package/dist/src/adapters/progress-logger.js +200 -0
- package/dist/src/adapters/progress-logger.js.map +1 -0
- package/dist/{refactor-reporter.d.ts → src/adapters/refactor-reporter.d.ts} +1 -2
- package/dist/{refactor-reporter.js → src/adapters/refactor-reporter.js} +1 -1
- package/dist/src/adapters/refactor-reporter.js.map +1 -0
- package/dist/{reporter.d.ts → src/adapters/reporter.d.ts} +1 -2
- package/dist/src/adapters/reporter.js.map +1 -0
- package/dist/src/core/GenesisTerminal.d.ts +8 -0
- package/dist/src/core/GenesisTerminal.js +105 -0
- package/dist/src/core/GenesisTerminal.js.map +1 -0
- package/dist/{index.d.ts → src/core/architect.d.ts} +4 -18
- package/dist/{index.js → src/core/architect.js} +22 -21
- package/dist/src/core/architect.js.map +1 -0
- package/dist/tests/architect-adapter-enrichment.test.d.ts +1 -0
- package/dist/tests/architect-adapter-enrichment.test.js +11 -0
- package/dist/tests/architect-adapter-enrichment.test.js.map +1 -0
- package/dist/tests/github-action.test.d.ts +1 -0
- package/dist/tests/github-action.test.js +92 -0
- package/dist/tests/github-action.test.js.map +1 -0
- package/package.json +15 -65
- package/src/adapters/cli.ts +492 -0
- package/src/adapters/github-action.ts +109 -0
- package/src/adapters/html-reporter/scripts.ts +402 -0
- package/src/adapters/html-reporter/sections/agents.ts +267 -0
- package/src/adapters/html-reporter/sections/anti-patterns.ts +81 -0
- package/src/adapters/html-reporter/sections/header.ts +35 -0
- package/src/adapters/html-reporter/sections/layers.ts +165 -0
- package/src/adapters/html-reporter/sections/overview.ts +64 -0
- package/src/adapters/html-reporter/sections/refactoring-plan.ts +166 -0
- package/src/adapters/html-reporter/sections/score.ts +80 -0
- package/src/adapters/html-reporter/sections/suggestions.ts +39 -0
- package/src/adapters/html-reporter/styles.ts +525 -0
- package/src/adapters/html-reporter/utils_adapters.ts +39 -0
- package/src/adapters/html-reporter/utils_sections.ts +55 -0
- package/src/adapters/html-reporter.ts +102 -0
- package/src/adapters/progress-logger.ts +236 -0
- package/src/{refactor-reporter.ts → adapters/refactor-reporter.ts} +2 -2
- package/src/{reporter.ts → adapters/reporter.ts} +1 -1
- package/src/core/GenesisTerminal.ts +127 -0
- package/src/{index.ts → core/architect.ts} +27 -45
- package/tests/github-action.test.ts +109 -0
- package/tsconfig.json +12 -19
- package/CONTRIBUTING.md +0 -140
- package/LICENSE +0 -21
- package/PROJECT_STRUCTURE.txt +0 -168
- package/README.md +0 -257
- package/architect-run.sh +0 -431
- package/assets/banner-v3.html +0 -561
- package/dist/agent-generator/context-enricher.d.ts +0 -58
- package/dist/agent-generator/context-enricher.d.ts.map +0 -1
- package/dist/agent-generator/context-enricher.js +0 -613
- package/dist/agent-generator/context-enricher.js.map +0 -1
- package/dist/agent-generator/domain-inferrer.d.ts +0 -52
- package/dist/agent-generator/domain-inferrer.d.ts.map +0 -1
- package/dist/agent-generator/domain-inferrer.js +0 -585
- package/dist/agent-generator/domain-inferrer.js.map +0 -1
- package/dist/agent-generator/framework-detector.d.ts +0 -40
- package/dist/agent-generator/framework-detector.d.ts.map +0 -1
- package/dist/agent-generator/framework-detector.js +0 -611
- package/dist/agent-generator/framework-detector.js.map +0 -1
- package/dist/agent-generator/index.d.ts +0 -47
- package/dist/agent-generator/index.d.ts.map +0 -1
- package/dist/agent-generator/index.js +0 -545
- package/dist/agent-generator/index.js.map +0 -1
- package/dist/agent-generator/stack-detector.d.ts +0 -14
- package/dist/agent-generator/stack-detector.d.ts.map +0 -1
- package/dist/agent-generator/stack-detector.js +0 -124
- package/dist/agent-generator/stack-detector.js.map +0 -1
- package/dist/agent-generator/templates/core/agents.d.ts +0 -17
- package/dist/agent-generator/templates/core/agents.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/agents.js +0 -1256
- package/dist/agent-generator/templates/core/agents.js.map +0 -1
- package/dist/agent-generator/templates/core/architecture-rules.d.ts +0 -7
- package/dist/agent-generator/templates/core/architecture-rules.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/architecture-rules.js +0 -274
- package/dist/agent-generator/templates/core/architecture-rules.js.map +0 -1
- package/dist/agent-generator/templates/core/general-rules.d.ts +0 -8
- package/dist/agent-generator/templates/core/general-rules.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/general-rules.js +0 -301
- package/dist/agent-generator/templates/core/general-rules.js.map +0 -1
- package/dist/agent-generator/templates/core/hooks-generator.d.ts +0 -21
- package/dist/agent-generator/templates/core/hooks-generator.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/hooks-generator.js +0 -233
- package/dist/agent-generator/templates/core/hooks-generator.js.map +0 -1
- package/dist/agent-generator/templates/core/index-md.d.ts +0 -7
- package/dist/agent-generator/templates/core/index-md.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/index-md.js +0 -246
- package/dist/agent-generator/templates/core/index-md.js.map +0 -1
- package/dist/agent-generator/templates/core/orchestrator.d.ts +0 -8
- package/dist/agent-generator/templates/core/orchestrator.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/orchestrator.js +0 -422
- package/dist/agent-generator/templates/core/orchestrator.js.map +0 -1
- package/dist/agent-generator/templates/core/preflight.d.ts +0 -8
- package/dist/agent-generator/templates/core/preflight.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/preflight.js +0 -213
- package/dist/agent-generator/templates/core/preflight.js.map +0 -1
- package/dist/agent-generator/templates/core/quality-gates.d.ts +0 -11
- package/dist/agent-generator/templates/core/quality-gates.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/quality-gates.js +0 -254
- package/dist/agent-generator/templates/core/quality-gates.js.map +0 -1
- package/dist/agent-generator/templates/core/security-rules.d.ts +0 -7
- package/dist/agent-generator/templates/core/security-rules.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/security-rules.js +0 -528
- package/dist/agent-generator/templates/core/security-rules.js.map +0 -1
- package/dist/agent-generator/templates/core/skills-generator.d.ts +0 -19
- package/dist/agent-generator/templates/core/skills-generator.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/skills-generator.js +0 -546
- package/dist/agent-generator/templates/core/skills-generator.js.map +0 -1
- package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts +0 -7
- package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/workflow-fix-bug.js +0 -237
- package/dist/agent-generator/templates/core/workflow-fix-bug.js.map +0 -1
- package/dist/agent-generator/templates/core/workflow-new-feature.d.ts +0 -8
- package/dist/agent-generator/templates/core/workflow-new-feature.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/workflow-new-feature.js +0 -321
- package/dist/agent-generator/templates/core/workflow-new-feature.js.map +0 -1
- package/dist/agent-generator/templates/core/workflow-review.d.ts +0 -7
- package/dist/agent-generator/templates/core/workflow-review.d.ts.map +0 -1
- package/dist/agent-generator/templates/core/workflow-review.js +0 -104
- package/dist/agent-generator/templates/core/workflow-review.js.map +0 -1
- package/dist/agent-generator/templates/domain/index.d.ts +0 -22
- package/dist/agent-generator/templates/domain/index.d.ts.map +0 -1
- package/dist/agent-generator/templates/domain/index.js +0 -1176
- package/dist/agent-generator/templates/domain/index.js.map +0 -1
- package/dist/agent-generator/templates/stack/index.d.ts +0 -8
- package/dist/agent-generator/templates/stack/index.d.ts.map +0 -1
- package/dist/agent-generator/templates/stack/index.js +0 -695
- package/dist/agent-generator/templates/stack/index.js.map +0 -1
- package/dist/agent-generator/templates/template-helpers.d.ts +0 -75
- package/dist/agent-generator/templates/template-helpers.d.ts.map +0 -1
- package/dist/agent-generator/templates/template-helpers.js +0 -726
- package/dist/agent-generator/templates/template-helpers.js.map +0 -1
- package/dist/agent-generator/types.d.ts +0 -196
- package/dist/agent-generator/types.d.ts.map +0 -1
- package/dist/agent-generator/types.js +0 -27
- package/dist/agent-generator/types.js.map +0 -1
- package/dist/analyzer.d.ts +0 -38
- package/dist/analyzer.d.ts.map +0 -1
- package/dist/analyzer.js +0 -383
- package/dist/analyzer.js.map +0 -1
- package/dist/analyzers/forecast.d.ts +0 -85
- package/dist/analyzers/forecast.d.ts.map +0 -1
- package/dist/analyzers/forecast.js +0 -337
- package/dist/analyzers/forecast.js.map +0 -1
- package/dist/analyzers/git-cache.d.ts +0 -7
- package/dist/analyzers/git-cache.d.ts.map +0 -1
- package/dist/analyzers/git-cache.js +0 -41
- package/dist/analyzers/git-cache.js.map +0 -1
- package/dist/analyzers/git-history.d.ts +0 -113
- package/dist/analyzers/git-history.d.ts.map +0 -1
- package/dist/analyzers/git-history.js +0 -333
- package/dist/analyzers/git-history.js.map +0 -1
- package/dist/analyzers/index.d.ts +0 -10
- package/dist/analyzers/index.d.ts.map +0 -1
- package/dist/analyzers/index.js +0 -7
- package/dist/analyzers/index.js.map +0 -1
- package/dist/analyzers/temporal-scorer.d.ts +0 -72
- package/dist/analyzers/temporal-scorer.d.ts.map +0 -1
- package/dist/analyzers/temporal-scorer.js +0 -140
- package/dist/analyzers/temporal-scorer.js.map +0 -1
- package/dist/anti-patterns.d.ts +0 -24
- package/dist/anti-patterns.d.ts.map +0 -1
- package/dist/anti-patterns.js +0 -230
- package/dist/anti-patterns.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/config.d.ts +0 -12
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -110
- package/dist/config.js.map +0 -1
- package/dist/diagram.d.ts +0 -9
- package/dist/diagram.d.ts.map +0 -1
- package/dist/diagram.js +0 -116
- package/dist/diagram.js.map +0 -1
- package/dist/html-reporter.d.ts +0 -47
- package/dist/html-reporter.d.ts.map +0 -1
- package/dist/html-reporter.js +0 -1747
- package/dist/html-reporter.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/project-summarizer.d.ts +0 -38
- package/dist/project-summarizer.d.ts.map +0 -1
- package/dist/project-summarizer.js +0 -463
- package/dist/project-summarizer.js.map +0 -1
- package/dist/refactor-engine.d.ts +0 -18
- package/dist/refactor-engine.d.ts.map +0 -1
- package/dist/refactor-engine.js +0 -86
- package/dist/refactor-engine.js.map +0 -1
- package/dist/refactor-reporter.d.ts.map +0 -1
- package/dist/refactor-reporter.js.map +0 -1
- package/dist/reporter.d.ts.map +0 -1
- package/dist/reporter.js.map +0 -1
- package/dist/rules/barrel-optimizer.d.ts +0 -13
- package/dist/rules/barrel-optimizer.d.ts.map +0 -1
- package/dist/rules/barrel-optimizer.js +0 -77
- package/dist/rules/barrel-optimizer.js.map +0 -1
- package/dist/rules/dead-code-detector.d.ts +0 -21
- package/dist/rules/dead-code-detector.d.ts.map +0 -1
- package/dist/rules/dead-code-detector.js +0 -117
- package/dist/rules/dead-code-detector.js.map +0 -1
- package/dist/rules/hub-splitter.d.ts +0 -13
- package/dist/rules/hub-splitter.d.ts.map +0 -1
- package/dist/rules/hub-splitter.js +0 -110
- package/dist/rules/hub-splitter.js.map +0 -1
- package/dist/rules/import-organizer.d.ts +0 -13
- package/dist/rules/import-organizer.d.ts.map +0 -1
- package/dist/rules/import-organizer.js +0 -85
- package/dist/rules/import-organizer.js.map +0 -1
- package/dist/rules/module-grouper.d.ts +0 -13
- package/dist/rules/module-grouper.d.ts.map +0 -1
- package/dist/rules/module-grouper.js +0 -110
- package/dist/rules/module-grouper.js.map +0 -1
- package/dist/scanner.d.ts +0 -31
- package/dist/scanner.d.ts.map +0 -1
- package/dist/scanner.js +0 -328
- package/dist/scanner.js.map +0 -1
- package/dist/scorer.d.ts +0 -27
- package/dist/scorer.d.ts.map +0 -1
- package/dist/scorer.js +0 -229
- package/dist/scorer.js.map +0 -1
- package/dist/types.d.ts +0 -186
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/examples/sample-report.md +0 -207
- package/jest.config.js +0 -18
- package/src/agent-generator/context-enricher.ts +0 -672
- package/src/agent-generator/domain-inferrer.ts +0 -635
- package/src/agent-generator/framework-detector.ts +0 -669
- package/src/agent-generator/index.ts +0 -634
- package/src/agent-generator/stack-detector.ts +0 -115
- package/src/agent-generator/templates/core/agents.ts +0 -1296
- package/src/agent-generator/templates/core/architecture-rules.ts +0 -287
- package/src/agent-generator/templates/core/general-rules.ts +0 -306
- package/src/agent-generator/templates/core/hooks-generator.ts +0 -242
- package/src/agent-generator/templates/core/index-md.ts +0 -260
- package/src/agent-generator/templates/core/orchestrator.ts +0 -459
- package/src/agent-generator/templates/core/preflight.ts +0 -215
- package/src/agent-generator/templates/core/quality-gates.ts +0 -256
- package/src/agent-generator/templates/core/security-rules.ts +0 -543
- package/src/agent-generator/templates/core/skills-generator.ts +0 -585
- package/src/agent-generator/templates/core/workflow-fix-bug.ts +0 -239
- package/src/agent-generator/templates/core/workflow-new-feature.ts +0 -323
- package/src/agent-generator/templates/core/workflow-review.ts +0 -106
- package/src/agent-generator/templates/domain/index.ts +0 -1201
- package/src/agent-generator/templates/stack/index.ts +0 -705
- package/src/agent-generator/templates/template-helpers.ts +0 -776
- package/src/agent-generator/types.ts +0 -232
- package/src/analyzer.ts +0 -447
- package/src/analyzers/forecast.ts +0 -496
- package/src/analyzers/git-cache.ts +0 -52
- package/src/analyzers/git-history.ts +0 -488
- package/src/analyzers/index.ts +0 -33
- package/src/analyzers/temporal-scorer.ts +0 -227
- package/src/anti-patterns.ts +0 -287
- package/src/cli.ts +0 -517
- package/src/config.ts +0 -123
- package/src/diagram.ts +0 -144
- package/src/html-reporter.ts +0 -1830
- package/src/project-summarizer.ts +0 -521
- package/src/refactor-engine.ts +0 -117
- package/src/rules/barrel-optimizer.ts +0 -97
- package/src/rules/dead-code-detector.ts +0 -132
- package/src/rules/hub-splitter.ts +0 -123
- package/src/rules/import-organizer.ts +0 -98
- package/src/rules/module-grouper.ts +0 -124
- package/src/scanner.ts +0 -344
- package/src/scorer.ts +0 -254
- package/src/types.ts +0 -193
- package/tests/agent-generator.test.ts +0 -427
- package/tests/analyzers-integration.test.ts +0 -174
- package/tests/anti-patterns.test.ts +0 -94
- package/tests/context-enricher.test.ts +0 -971
- package/tests/fixtures/monorepo/package.json +0 -6
- package/tests/fixtures/monorepo/packages/app/package.json +0 -12
- package/tests/fixtures/monorepo/packages/app/src/index.ts +0 -6
- package/tests/fixtures/monorepo/packages/core/package.json +0 -7
- package/tests/fixtures/monorepo/packages/core/src/index.ts +0 -7
- package/tests/forecast.test.ts +0 -509
- package/tests/framework-detector.test.ts +0 -1172
- package/tests/git-history.test.ts +0 -254
- package/tests/monorepo-scan.test.ts +0 -170
- package/tests/scanner.test.ts +0 -54
- package/tests/scorer.test.ts +0 -674
- package/tests/stack-detector.test.ts +0 -241
- package/tests/template-generation.test.ts +0 -706
- package/tests/template-helpers.test.ts +0 -1152
- package/tests/temporal-scorer.test.ts +0 -307
- /package/dist/{reporter.js → src/adapters/reporter.js} +0 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { AnalysisReport} from '@girardelli/architect-core/src/core/types/core.js';
|
|
2
|
+
|
|
3
|
+
import { escapeHtml } from "../utils_sections.js";
|
|
4
|
+
|
|
5
|
+
export function renderAntiPatternBubbles(
|
|
6
|
+
report: AnalysisReport,
|
|
7
|
+
grouped: Record<string, { count: number; severity: string; locations: string[]; suggestion: string }>
|
|
8
|
+
): string {
|
|
9
|
+
if (report.antiPatterns.length === 0) {
|
|
10
|
+
return `
|
|
11
|
+
<h2 class="section-title">✅ Anti-Patterns</h2>
|
|
12
|
+
<div class="card success-card">
|
|
13
|
+
<p>No significant anti-patterns detected. Excellent architecture!</p>
|
|
14
|
+
</div>`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const severityWeight: Record<string, number> = {
|
|
18
|
+
CRITICAL: 80, HIGH: 60, MEDIUM: 40, LOW: 25,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const severityColor: Record<string, string> = {
|
|
22
|
+
CRITICAL: '#ef4444', HIGH: '#f59e0b', MEDIUM: '#60a5fa', LOW: '#22c55e',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const bubbles = Object.entries(grouped).map(([name, data]) => ({
|
|
26
|
+
name,
|
|
27
|
+
count: data.count,
|
|
28
|
+
severity: data.severity,
|
|
29
|
+
radius: (severityWeight[data.severity] || 30) + data.count * 8,
|
|
30
|
+
color: severityColor[data.severity] || '#64748b',
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
return `
|
|
34
|
+
<h2 class="section-title">🫧 Anti-Pattern Impact Map</h2>
|
|
35
|
+
<div class="card" style="display:flex; justify-content:center;">
|
|
36
|
+
<div id="bubble-chart" style="width:100%; min-height:300px;"></div>
|
|
37
|
+
</div>
|
|
38
|
+
<script type="application/json" id="bubble-data">${JSON.stringify(bubbles)}<\/script>`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
export function renderAntiPatterns(
|
|
43
|
+
report: AnalysisReport,
|
|
44
|
+
grouped: Record<string, { count: number; severity: string; locations: string[]; suggestion: string }>
|
|
45
|
+
): string {
|
|
46
|
+
if (report.antiPatterns.length === 0) return '';
|
|
47
|
+
|
|
48
|
+
const rows = Object.entries(grouped)
|
|
49
|
+
.sort((a, b) => b[1].count - a[1].count)
|
|
50
|
+
.map(
|
|
51
|
+
([name, data]) => `
|
|
52
|
+
<tr>
|
|
53
|
+
<td><strong>${escapeHtml(name)}</strong></td>
|
|
54
|
+
<td class="count-cell">${data.count}</td>
|
|
55
|
+
<td><span class="severity-badge severity-${data.severity}">${data.severity}</span></td>
|
|
56
|
+
<td><small class="suggestion">${escapeHtml(data.suggestion)}</small></td>
|
|
57
|
+
<td><div class="locations">${data.locations
|
|
58
|
+
.slice(0, 5)
|
|
59
|
+
.map((l) => `<code>${escapeHtml(l)}</code>`)
|
|
60
|
+
.join(' ')}${data.locations.length > 5 ? ` <em>+${data.count - 5} more</em>` : ''}</div></td>
|
|
61
|
+
</tr>`
|
|
62
|
+
)
|
|
63
|
+
.join('');
|
|
64
|
+
|
|
65
|
+
return `
|
|
66
|
+
<h2 class="section-title">⚠️ Anti-Pattern Details (${report.antiPatterns.length})</h2>
|
|
67
|
+
<div class="card">
|
|
68
|
+
<table>
|
|
69
|
+
<thead>
|
|
70
|
+
<tr>
|
|
71
|
+
<th>Pattern</th>
|
|
72
|
+
<th>Count</th>
|
|
73
|
+
<th>Severity</th>
|
|
74
|
+
<th>Suggestion</th>
|
|
75
|
+
<th>Locations</th>
|
|
76
|
+
</tr>
|
|
77
|
+
</thead>
|
|
78
|
+
<tbody>${rows}</tbody>
|
|
79
|
+
</table>
|
|
80
|
+
</div>`;
|
|
81
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
|
|
2
|
+
|
|
3
|
+
import { escapeHtml } from "../utils_sections.js";
|
|
4
|
+
|
|
5
|
+
export function renderHeader(report: AnalysisReport): string {
|
|
6
|
+
const date = new Date(report.timestamp).toLocaleDateString('en-US', {
|
|
7
|
+
year: 'numeric',
|
|
8
|
+
month: 'long',
|
|
9
|
+
day: 'numeric',
|
|
10
|
+
});
|
|
11
|
+
return `
|
|
12
|
+
<div class="header">
|
|
13
|
+
<h1>🏗️ Architect</h1>
|
|
14
|
+
<p class="subtitle">Architecture Analysis Report</p>
|
|
15
|
+
<div class="meta">
|
|
16
|
+
<span>📂 <strong>${escapeHtml(report.projectInfo.name)}</strong></span>
|
|
17
|
+
<span>📁 <strong>${report.projectInfo.totalFiles}</strong> files</span>
|
|
18
|
+
<span>📝 <strong>${report.projectInfo.totalLines.toLocaleString()}</strong> lines</span>
|
|
19
|
+
<span>💻 <strong>${report.projectInfo.primaryLanguages.join(', ')}</strong></span>
|
|
20
|
+
${report.projectInfo.frameworks.length > 0 ? `<span>🔧 <strong>${report.projectInfo.frameworks.join(', ')}</strong></span>` : ''}
|
|
21
|
+
<span>📅 <strong>${date}</strong></span>
|
|
22
|
+
</div>
|
|
23
|
+
</div>`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
export function renderFooter(): string {
|
|
28
|
+
return `
|
|
29
|
+
<div class="footer">
|
|
30
|
+
<p>Generated by <a href="https://github.com/camilooscargbaptista/architect">⚡ Architect v8.1</a> — Enterprise Architecture Intelligence</p>
|
|
31
|
+
<p>By <strong>Camilo Girardelli</strong> · <a href="https://www.girardellitecnologia.com">Girardelli Tecnologia</a></p>
|
|
32
|
+
</div>`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ── Refactoring Plan Section ──
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
|
|
2
|
+
|
|
3
|
+
import { escapeHtml } from "../utils_sections.js";
|
|
4
|
+
|
|
5
|
+
export function renderLayers(report: AnalysisReport): string {
|
|
6
|
+
if (report.layers.length === 0) return '';
|
|
7
|
+
|
|
8
|
+
const layerColors: Record<string, string> = {
|
|
9
|
+
API: '#ec4899',
|
|
10
|
+
Service: '#3b82f6',
|
|
11
|
+
Data: '#10b981',
|
|
12
|
+
UI: '#f59e0b',
|
|
13
|
+
Infrastructure: '#8b5cf6',
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const cards = report.layers
|
|
17
|
+
.map((l) => {
|
|
18
|
+
const color = layerColors[l.name] || '#64748b';
|
|
19
|
+
return `
|
|
20
|
+
<div class="layer-card" style="--layer-color: ${color}">
|
|
21
|
+
<div class="count" style="color: ${color}">${l.files.length}</div>
|
|
22
|
+
<div class="name">${l.name}</div>
|
|
23
|
+
<div class="desc">${escapeHtml(l.description)}</div>
|
|
24
|
+
</div>`;
|
|
25
|
+
})
|
|
26
|
+
.join('');
|
|
27
|
+
|
|
28
|
+
return `
|
|
29
|
+
<h2 class="section-title">📐 Architectural Layers</h2>
|
|
30
|
+
<div class="layers-grid">${cards}</div>`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Interactive D3.js force-directed dependency graph
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
export function renderDependencyGraph(report: AnalysisReport): string {
|
|
38
|
+
if (report.dependencyGraph.edges.length === 0) return '';
|
|
39
|
+
|
|
40
|
+
// Build real file set — only files that appear as SOURCE in edges (these are real scanned files)
|
|
41
|
+
const realFiles = new Set(report.dependencyGraph.edges.map(e => e.from));
|
|
42
|
+
|
|
43
|
+
// Count connections only for real files
|
|
44
|
+
const connectionCount: Record<string, number> = {};
|
|
45
|
+
for (const edge of report.dependencyGraph.edges) {
|
|
46
|
+
if (realFiles.has(edge.from)) {
|
|
47
|
+
connectionCount[edge.from] = (connectionCount[edge.from] || 0) + 1;
|
|
48
|
+
}
|
|
49
|
+
if (realFiles.has(edge.to)) {
|
|
50
|
+
connectionCount[edge.to] = (connectionCount[edge.to] || 0) + 1;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Build layer map from report layers
|
|
55
|
+
const layerMap: Record<string, string> = {};
|
|
56
|
+
for (const layer of report.layers) {
|
|
57
|
+
for (const file of layer.files) {
|
|
58
|
+
layerMap[file] = layer.name;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Create nodes only from real files
|
|
63
|
+
const allNodes = [...realFiles].map(n => ({
|
|
64
|
+
id: n,
|
|
65
|
+
name: n.split('/').pop() || n,
|
|
66
|
+
connections: connectionCount[n] || 0,
|
|
67
|
+
layer: layerMap[n] || 'Other',
|
|
68
|
+
}));
|
|
69
|
+
|
|
70
|
+
// ── Fallback: color by module/directory when layer detection is weak ──
|
|
71
|
+
const otherCount = allNodes.filter(n => n.layer === 'Other').length;
|
|
72
|
+
const useModuleColoring = allNodes.length > 0 && (otherCount / allNodes.length) > 0.7;
|
|
73
|
+
|
|
74
|
+
// Palette for module-based coloring (10 distinct, vibrant colors)
|
|
75
|
+
const modulePalette = [
|
|
76
|
+
'#3b82f6', '#ec4899', '#10b981', '#f59e0b', '#8b5cf6',
|
|
77
|
+
'#06b6d4', '#ef4444', '#84cc16', '#f97316', '#6366f1',
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
let moduleColorMap: Record<string, string> = {};
|
|
81
|
+
if (useModuleColoring) {
|
|
82
|
+
// Extract module (first meaningful directory) from each node path
|
|
83
|
+
const getModule = (filePath: string): string => {
|
|
84
|
+
const parts = filePath.split('/');
|
|
85
|
+
if (parts.length < 2) return 'root';
|
|
86
|
+
const first = parts[0];
|
|
87
|
+
// If first dir is common source dir, use second level
|
|
88
|
+
if (['src', 'lib', 'app', 'packages', 'modules', 'features', 'apps'].includes(first)) {
|
|
89
|
+
return parts.length > 2 ? parts[1] : first;
|
|
90
|
+
}
|
|
91
|
+
return first;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Assign colors to modules
|
|
95
|
+
const moduleNames = [...new Set(allNodes.map(n => getModule(n.id)))];
|
|
96
|
+
moduleNames.forEach((mod, i) => {
|
|
97
|
+
moduleColorMap[mod] = modulePalette[i % modulePalette.length];
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Reassign layer field to module name for coloring
|
|
101
|
+
for (const node of allNodes) {
|
|
102
|
+
node.layer = getModule(node.id);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Build links only between real files
|
|
107
|
+
const allLinks = report.dependencyGraph.edges
|
|
108
|
+
.filter(e => realFiles.has(e.from) && realFiles.has(e.to))
|
|
109
|
+
.map(e => ({ source: e.from, target: e.to }));
|
|
110
|
+
|
|
111
|
+
// Limit to top N most-connected nodes for large projects
|
|
112
|
+
const maxNodes = 60;
|
|
113
|
+
const sortedNodes = [...allNodes].sort((a, b) => b.connections - a.connections);
|
|
114
|
+
const limitedNodes = sortedNodes.slice(0, maxNodes);
|
|
115
|
+
const limitedNodeIds = new Set(limitedNodes.map(n => n.id));
|
|
116
|
+
const limitedLinks = allLinks.filter(l => limitedNodeIds.has(l.source) && limitedNodeIds.has(l.target));
|
|
117
|
+
const isLimited = allNodes.length > maxNodes;
|
|
118
|
+
|
|
119
|
+
// Collect unique layers/modules from limited nodes
|
|
120
|
+
const uniqueLayers = [...new Set(limitedNodes.map(n => n.layer))];
|
|
121
|
+
|
|
122
|
+
// Build dynamic color map for legend and D3
|
|
123
|
+
const colorMap: Record<string, string> = useModuleColoring
|
|
124
|
+
? moduleColorMap
|
|
125
|
+
: { API: '#ec4899', Service: '#3b82f6', Data: '#10b981', UI: '#f59e0b', Infrastructure: '#8b5cf6', Other: '#64748b' };
|
|
126
|
+
|
|
127
|
+
const legendLabel = useModuleColoring ? 'Colored by module' : 'Colored by layer';
|
|
128
|
+
|
|
129
|
+
const legendHtml = uniqueLayers.map(l => {
|
|
130
|
+
const color = colorMap[l] || '#64748b';
|
|
131
|
+
return `<span class="legend-item"><span class="legend-dot" style="background: ${color}"></span> ${l}</span>`;
|
|
132
|
+
}).join('');
|
|
133
|
+
|
|
134
|
+
const filterHtml = uniqueLayers.map(l => {
|
|
135
|
+
const color = colorMap[l] || '#64748b';
|
|
136
|
+
return `<label class="graph-filter-check"><input type="checkbox" checked data-layer="${l}" onchange="toggleGraphLayer('${l}', checked)"><span class="legend-dot" style="background: ${color}"></span> ${l}</label>`;
|
|
137
|
+
}).join('');
|
|
138
|
+
|
|
139
|
+
return `
|
|
140
|
+
<h2 class="section-title">🔗 Dependency Graph</h2>
|
|
141
|
+
<div class="card graph-card">
|
|
142
|
+
<div class="graph-controls">
|
|
143
|
+
<div class="graph-legend">
|
|
144
|
+
<span class="legend-label" style="color:#94a3b8;font-size:11px;margin-right:8px;">${legendLabel}:</span>
|
|
145
|
+
${legendHtml}
|
|
146
|
+
</div>
|
|
147
|
+
<div class="graph-filters">
|
|
148
|
+
<input type="text" id="graphSearch" class="graph-search" placeholder="🔍 Search node..." oninput="filterGraphNodes(value)">
|
|
149
|
+
<div class="graph-layer-filters">
|
|
150
|
+
${filterHtml}
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
${isLimited ? `<div class="graph-limit-notice">Showing top ${maxNodes} of ${allNodes.length} source files (most connected) · ${limitedLinks.length} links</div>` : ''}
|
|
154
|
+
</div>
|
|
155
|
+
<div id="dep-graph" style="width:100%; min-height:500px;"></div>
|
|
156
|
+
<div class="graph-hint">🖱️ Drag nodes • Scroll to zoom • Double-click to reset • Node size = connections</div>
|
|
157
|
+
</div>
|
|
158
|
+
<script type="application/json" id="graph-nodes">${JSON.stringify(limitedNodes)}${'</'+'script>'}
|
|
159
|
+
<script type="application/json" id="graph-links">${JSON.stringify(limitedLinks)}${'</'+'script>'}
|
|
160
|
+
<script type="application/json" id="graph-colors">${JSON.stringify(colorMap)}${'</'+'script>'}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Bubble chart for anti-patterns — bigger = more severe
|
|
165
|
+
*/
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
|
|
2
|
+
|
|
3
|
+
import { esc } from "../utils_sections.js";
|
|
4
|
+
|
|
5
|
+
export function renderProjectOverview(report: AnalysisReport): string {
|
|
6
|
+
const summary = report.projectSummary;
|
|
7
|
+
if (!summary) return '';
|
|
8
|
+
|
|
9
|
+
const modulesHtml = summary.modules.length > 0
|
|
10
|
+
? summary.modules.map(m => `
|
|
11
|
+
<div class="overview-module">
|
|
12
|
+
<div class="overview-module-name">${esc(m.name)}</div>
|
|
13
|
+
<div class="overview-module-desc">${esc(m.description)}</div>
|
|
14
|
+
<div class="overview-module-files">${m.files} file${m.files > 1 ? 's' : ''}</div>
|
|
15
|
+
</div>`).join('')
|
|
16
|
+
: '<div class="overview-empty">Nenhum módulo detectado</div>';
|
|
17
|
+
|
|
18
|
+
const techHtml = summary.techStack
|
|
19
|
+
.map(t => `<span class="overview-tag tech-tag">${esc(t)}</span>`)
|
|
20
|
+
.join('');
|
|
21
|
+
|
|
22
|
+
const keywordsHtml = summary.keywords
|
|
23
|
+
.map(k => `<span class="overview-tag keyword-tag">${esc(k)}</span>`)
|
|
24
|
+
.join('');
|
|
25
|
+
|
|
26
|
+
const entryHtml = summary.entryPoints.length > 0
|
|
27
|
+
? summary.entryPoints.map(e => `<code class="overview-entry">${esc(e)}</code>`).join(' ')
|
|
28
|
+
: '<span class="overview-empty">—</span>';
|
|
29
|
+
|
|
30
|
+
return `
|
|
31
|
+
<details class="section-accordion" id="overview" open>
|
|
32
|
+
<summary class="section-accordion-header">📋 Project Overview</summary>
|
|
33
|
+
<div class="section-accordion-body">
|
|
34
|
+
<div class="overview-grid">
|
|
35
|
+
<div class="overview-card overview-main">
|
|
36
|
+
<div class="overview-label">O que é</div>
|
|
37
|
+
<div class="overview-description">${esc(summary.description)}</div>
|
|
38
|
+
<div class="overview-purpose-row">
|
|
39
|
+
<span class="overview-purpose-label">Tipo:</span>
|
|
40
|
+
<span class="overview-purpose-value">${esc(summary.purpose)}</span>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
<div class="overview-card">
|
|
44
|
+
<div class="overview-label">Tech Stack</div>
|
|
45
|
+
<div class="overview-tags">${techHtml || '<span class="overview-empty">—</span>'}</div>
|
|
46
|
+
</div>
|
|
47
|
+
<div class="overview-card">
|
|
48
|
+
<div class="overview-label">Keywords</div>
|
|
49
|
+
<div class="overview-tags">${keywordsHtml || '<span class="overview-empty">—</span>'}</div>
|
|
50
|
+
</div>
|
|
51
|
+
<div class="overview-card">
|
|
52
|
+
<div class="overview-label">Entry Points</div>
|
|
53
|
+
<div class="overview-entries">${entryHtml}</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="overview-modules-section">
|
|
57
|
+
<div class="overview-label">Módulos Detectados (${summary.modules.length})</div>
|
|
58
|
+
<div class="overview-modules-grid">
|
|
59
|
+
${modulesHtml}
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</details>`;
|
|
64
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { RefactoringPlan, RefactorStep } from '@girardelli/architect-core/src/core/types/rules.js';
|
|
2
|
+
|
|
3
|
+
import { scoreColor, opColor, opIcon, escapeHtml } from "../utils_sections.js";
|
|
4
|
+
|
|
5
|
+
export function renderRefactoringPlan(plan: RefactoringPlan): string {
|
|
6
|
+
if (plan.steps.length === 0) {
|
|
7
|
+
return `
|
|
8
|
+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
|
|
9
|
+
<h2 class="section-title" style="margin-bottom: 0;">✅ Refactoring Plan</h2>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="card success-card">
|
|
12
|
+
<p>No refactoring needed! Your architecture is already in great shape.</p>
|
|
13
|
+
</div>`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const improvement = plan.estimatedScoreAfter.overall - plan.currentScore.overall;
|
|
17
|
+
|
|
18
|
+
const metrics = Object.keys(plan.currentScore.breakdown) as Array<keyof typeof plan.currentScore.breakdown>;
|
|
19
|
+
const bars = metrics.map(metric => {
|
|
20
|
+
const before = plan.currentScore.breakdown[metric];
|
|
21
|
+
const after = plan.estimatedScoreAfter.breakdown[metric] ?? before;
|
|
22
|
+
const diff = after - before;
|
|
23
|
+
return `
|
|
24
|
+
<div class="comparison-row">
|
|
25
|
+
<div class="refactor-metric-name">${metric}</div>
|
|
26
|
+
<div class="refactor-metric-bars">
|
|
27
|
+
<div class="rbar-before" style="width: ${before}%; background: ${scoreColor(before)}40"><span>${before}</span></div>
|
|
28
|
+
<div class="rbar-after" style="width: ${after}%; background: ${scoreColor(after)}"><span>${after}</span></div>
|
|
29
|
+
</div>
|
|
30
|
+
<div class="refactor-metric-diff" style="color: ${diff > 0 ? '#22c55e' : '#64748b'}">
|
|
31
|
+
${diff > 0 ? `+${diff}` : diff === 0 ? '—' : String(diff)}
|
|
32
|
+
</div>
|
|
33
|
+
</div>`;
|
|
34
|
+
}).join('');
|
|
35
|
+
|
|
36
|
+
const stepsHtml = plan.steps.map(step => renderRefactorStep(step)).join('');
|
|
37
|
+
|
|
38
|
+
const criticalCount = plan.steps.filter(s => s.priority === 'CRITICAL').length;
|
|
39
|
+
const highCount = plan.steps.filter(s => s.priority === 'HIGH').length;
|
|
40
|
+
const mediumCount = plan.steps.filter(s => s.priority === 'MEDIUM').length;
|
|
41
|
+
const lowCount = plan.steps.filter(s => s.priority === 'LOW').length;
|
|
42
|
+
|
|
43
|
+
return `
|
|
44
|
+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem; flex-wrap: wrap; gap: 1rem;">
|
|
45
|
+
<h2 class="section-title" style="margin-bottom: 0;">🔧 Refactoring Plan</h2>
|
|
46
|
+
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer; color: #10b981; font-weight: 600; font-size: 0.9rem; background: #10b98115; padding: 0.4rem 0.8rem; border-radius: 6px; border: 1px solid #10b98140;">
|
|
47
|
+
<input type="checkbox" id="select-all-prompts" style="width: 1.1rem; height: 1.1rem; accent-color: #10b981; cursor: pointer;" onchange="window.toggleAllPrompts(this.checked)">
|
|
48
|
+
Selecionar Todos
|
|
49
|
+
</label>
|
|
50
|
+
</div>
|
|
51
|
+
<button id="download-selected-prompts-btn" onclick="window.downloadSelectedPrompts()" style="display: none; position: fixed; bottom: 30px; right: 30px; background: #10b981; color: white; border: none; padding: 1rem 2rem; border-radius: 50px; font-weight: bold; font-size: 1rem; cursor: pointer; box-shadow: 0 10px 25px rgba(16,185,129,0.4); z-index: 9999; transition: all 0.3s; align-items: center; gap: 0.5rem;">
|
|
52
|
+
📥 Criar <span id="prompt-count-badge" style="background: white; color: #10b981; padding: 0.1rem 0.5rem; border-radius: 10px; font-size: 0.9rem;">0</span> Prompts p/ IA
|
|
53
|
+
</button>
|
|
54
|
+
<p>Below are action-items ordered by impact and safety. Implementing these gives an estimated score of <strong>${plan.estimatedScoreAfter.overall}/100</strong> (+${improvement}).</p>
|
|
55
|
+
|
|
56
|
+
<div class="card refactor-score">
|
|
57
|
+
<div class="refactor-score-pair">
|
|
58
|
+
<div class="rscore-box">
|
|
59
|
+
<div class="rscore-num" style="color: ${scoreColor(plan.currentScore.overall)}">${plan.currentScore.overall}</div>
|
|
60
|
+
<div class="rscore-label">Current</div>
|
|
61
|
+
</div>
|
|
62
|
+
<div class="rscore-arrow">
|
|
63
|
+
<svg width="60" height="30" viewBox="0 0 60 30">
|
|
64
|
+
<path d="M5 15 L45 15 M40 8 L48 15 L40 22" stroke="#818cf8" stroke-width="2.5" fill="none"/>
|
|
65
|
+
</svg>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="rscore-box">
|
|
68
|
+
<div class="rscore-num" style="color: ${scoreColor(plan.estimatedScoreAfter.overall)}">${plan.estimatedScoreAfter.overall}</div>
|
|
69
|
+
<div class="rscore-label">Estimated</div>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="rscore-improvement" style="color: #22c55e">+${improvement} pts</div>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="refactor-bars-section">
|
|
74
|
+
<div class="refactor-legend">
|
|
75
|
+
<span class="rlegend-tag rbefore">Before</span>
|
|
76
|
+
<span class="rlegend-tag rafter">After</span>
|
|
77
|
+
</div>
|
|
78
|
+
${bars}
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div class="refactor-stats-row">
|
|
83
|
+
<div class="rstat">${plan.steps.length} steps</div>
|
|
84
|
+
<div class="rstat">${plan.totalOperations} operations</div>
|
|
85
|
+
<div class="rstat">Tier 1: ${plan.tier1Steps}</div>
|
|
86
|
+
<div class="rstat">Tier 2: ${plan.tier2Steps}</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div class="priority-bar">
|
|
90
|
+
${criticalCount ? `<div class="prio-seg prio-critical" style="flex: ${criticalCount}">🔴 ${criticalCount}</div>` : ''}
|
|
91
|
+
${highCount ? `<div class="prio-seg prio-high" style="flex: ${highCount}">🟠 ${highCount}</div>` : ''}
|
|
92
|
+
${mediumCount ? `<div class="prio-seg prio-medium" style="flex: ${mediumCount}">🔵 ${mediumCount}</div>` : ''}
|
|
93
|
+
${lowCount ? `<div class="prio-seg prio-low" style="flex: ${lowCount}">🟢 ${lowCount}</div>` : ''}
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<div class="refactor-roadmap">
|
|
97
|
+
${stepsHtml}
|
|
98
|
+
</div>`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
export function renderRefactorStep(step: RefactorStep): string {
|
|
103
|
+
const operationsHtml = step.operations.map(op => `
|
|
104
|
+
<div class="rop">
|
|
105
|
+
<span class="rop-icon">${opIcon(op.type)}</span>
|
|
106
|
+
<span class="rop-badge" style="background: ${opColor(op.type)}20; color: ${opColor(op.type)}; border: 1px solid ${opColor(op.type)}40">${op.type}</span>
|
|
107
|
+
<code class="rop-path">${escapeHtml(op.path)}</code>
|
|
108
|
+
${op.newPath ? `<span class="rop-arrow">→</span> <code class="rop-path">${escapeHtml(op.newPath)}</code>` : ''}
|
|
109
|
+
<div class="rop-desc">${escapeHtml(op.description)}</div>
|
|
110
|
+
</div>
|
|
111
|
+
`).join('');
|
|
112
|
+
|
|
113
|
+
const impactHtml = step.scoreImpact.map(i =>
|
|
114
|
+
`<span class="rimpact-tag">${i.metric}: ${i.before}→${i.after} <strong>+${i.after - i.before}</strong></span>`
|
|
115
|
+
).join('');
|
|
116
|
+
|
|
117
|
+
const promptHtml = step.aiPrompt ? `
|
|
118
|
+
<div class="ai-prompt-box">
|
|
119
|
+
<div class="ai-prompt-header">
|
|
120
|
+
<label style="display: flex; align-items: center; gap: 0.5rem; cursor: pointer;">
|
|
121
|
+
<input type="checkbox" class="prompt-export-cb" data-filename="step-${step.id}-${step.rule.replace(/[^a-zA-Z0-9-]/g, '-')}.md" onchange="window.updatePromptSelection()">
|
|
122
|
+
<div>
|
|
123
|
+
<h4>🤖 Auto-Execute in AI</h4>
|
|
124
|
+
<p class="ai-prompt-desc">Select to batch-download this prompt for your IDE.</p>
|
|
125
|
+
</div>
|
|
126
|
+
</label>
|
|
127
|
+
<button class="ai-prompt-btn" onclick="window.downloadAIPrompt(this, 'step-${step.id}-refactor.md')">
|
|
128
|
+
📥 Download Single
|
|
129
|
+
</button>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="ai-prompt-pre">
|
|
132
|
+
<pre><code>${escapeHtml(step.aiPrompt)}</code></pre>
|
|
133
|
+
</div>
|
|
134
|
+
</div>` : '';
|
|
135
|
+
|
|
136
|
+
return `
|
|
137
|
+
<div class="rstep-card">
|
|
138
|
+
<div class="rstep-header">
|
|
139
|
+
<div class="rstep-number">${step.id}</div>
|
|
140
|
+
<div class="rstep-info">
|
|
141
|
+
<div class="rstep-title-row">
|
|
142
|
+
<h3>${escapeHtml(step.title)}</h3>
|
|
143
|
+
<span class="severity-badge severity-${step.priority}">${step.priority}</span>
|
|
144
|
+
<span class="tier-badge">Tier ${step.tier}</span>
|
|
145
|
+
</div>
|
|
146
|
+
<p class="rstep-desc">${escapeHtml(step.description)}</p>
|
|
147
|
+
<details class="rstep-details">
|
|
148
|
+
<summary>📖 Why?</summary>
|
|
149
|
+
<p class="rstep-rationale">${escapeHtml(step.rationale)}</p>
|
|
150
|
+
</details>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
<details class="rstep-ops-accordion">
|
|
154
|
+
<summary class="rstep-ops-toggle">📋 Operations (${step.operations.length})</summary>
|
|
155
|
+
<div class="rstep-ops">
|
|
156
|
+
${operationsHtml}
|
|
157
|
+
</div>
|
|
158
|
+
</details>
|
|
159
|
+
<div class="rstep-impact">
|
|
160
|
+
<h4>📈 Score Impact</h4>
|
|
161
|
+
<div class="rimpact-tags">${impactHtml}</div>
|
|
162
|
+
</div>
|
|
163
|
+
${promptHtml}
|
|
164
|
+
</div>`;
|
|
165
|
+
}
|
|
166
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { AnalysisReport } from '@girardelli/architect-core/src/core/types/core.js';
|
|
2
|
+
|
|
3
|
+
import { scoreColor, scoreEmoji, scoreLabel } from "../utils_sections.js";
|
|
4
|
+
|
|
5
|
+
export function renderScoreHero(report: AnalysisReport): string {
|
|
6
|
+
const overall = report.score.overall;
|
|
7
|
+
const circumference = 2 * Math.PI * 85;
|
|
8
|
+
const offset = circumference * (1 - overall / 100);
|
|
9
|
+
|
|
10
|
+
const breakdownItems = Object.entries(report.score.breakdown)
|
|
11
|
+
.map(
|
|
12
|
+
([name, score]) => `
|
|
13
|
+
<div class="score-item">
|
|
14
|
+
<div class="name">${name}</div>
|
|
15
|
+
<div class="val" style="color: ${scoreColor(score)}">${score} ${scoreEmoji(score)}</div>
|
|
16
|
+
<div class="bar-container">
|
|
17
|
+
<div class="bar" style="width: ${score}%; background: ${scoreColor(score)}"></div>
|
|
18
|
+
</div>
|
|
19
|
+
</div>`
|
|
20
|
+
)
|
|
21
|
+
.join('');
|
|
22
|
+
|
|
23
|
+
return `
|
|
24
|
+
<div class="score-hero">
|
|
25
|
+
<div class="score-circle">
|
|
26
|
+
<svg viewBox="0 0 200 200" width="180" height="180">
|
|
27
|
+
<circle class="bg" cx="100" cy="100" r="85" />
|
|
28
|
+
<circle class="fg" cx="100" cy="100" r="85"
|
|
29
|
+
stroke="${scoreColor(overall)}"
|
|
30
|
+
stroke-dasharray="${circumference}"
|
|
31
|
+
stroke-dashoffset="${offset}" />
|
|
32
|
+
</svg>
|
|
33
|
+
<div class="score-value">
|
|
34
|
+
<div class="number score-counter" data-target="${overall}" style="color: ${scoreColor(overall)}">0</div>
|
|
35
|
+
<div class="label">/ 100</div>
|
|
36
|
+
<div class="grade">${scoreLabel(overall)}</div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="score-breakdown">
|
|
40
|
+
${breakdownItems}
|
|
41
|
+
</div>
|
|
42
|
+
</div>`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Radar chart for the 4 score components
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
export function renderRadarChart(report: AnalysisReport): string {
|
|
50
|
+
// @ts-ignore - Audit cleanup unused variable
|
|
51
|
+
const entries = Object.entries(report.score.breakdown);
|
|
52
|
+
return `
|
|
53
|
+
<h2 class="section-title">🎯 Health Radar</h2>
|
|
54
|
+
<div class="card" style="display: flex; justify-content: center;">
|
|
55
|
+
<svg id="radar-chart" width="350" height="350" viewBox="0 0 350 350"></svg>
|
|
56
|
+
</div>`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
export function renderStats(report: AnalysisReport): string {
|
|
61
|
+
return `
|
|
62
|
+
<div class="stats-grid">
|
|
63
|
+
<div class="stat-card">
|
|
64
|
+
<div class="value stat-counter" data-target="${report.projectInfo.totalFiles}">0</div>
|
|
65
|
+
<div class="label">Files Scanned</div>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="stat-card">
|
|
68
|
+
<div class="value stat-counter" data-target="${report.projectInfo.totalLines}">0</div>
|
|
69
|
+
<div class="label">Lines of Code</div>
|
|
70
|
+
</div>
|
|
71
|
+
<div class="stat-card">
|
|
72
|
+
<div class="value stat-counter" data-target="${report.antiPatterns.length}">0</div>
|
|
73
|
+
<div class="label">Anti-Patterns</div>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="stat-card">
|
|
76
|
+
<div class="value stat-counter" data-target="${report.dependencyGraph.edges.length}">0</div>
|
|
77
|
+
<div class="label">Dependencies</div>
|
|
78
|
+
</div>
|
|
79
|
+
</div>`;
|
|
80
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { escapeHtml } from "../utils_sections.js";
|
|
2
|
+
|
|
3
|
+
export function renderSuggestions(
|
|
4
|
+
suggestions: Array<{ priority: string; title: string; description: string; impact: string; count: number }>
|
|
5
|
+
): string {
|
|
6
|
+
if (suggestions.length === 0) return '';
|
|
7
|
+
|
|
8
|
+
const rows = suggestions
|
|
9
|
+
.map(
|
|
10
|
+
(s, i) => `
|
|
11
|
+
<tr>
|
|
12
|
+
<td>${i + 1}</td>
|
|
13
|
+
<td><span class="severity-badge severity-${s.priority}">${s.priority}</span></td>
|
|
14
|
+
<td>
|
|
15
|
+
<strong>${escapeHtml(s.title)}</strong>
|
|
16
|
+
${s.count > 1 ? `<span class="count-badge">×${s.count}</span>` : ''}
|
|
17
|
+
<br/><small class="suggestion">${escapeHtml(s.description)}</small>
|
|
18
|
+
</td>
|
|
19
|
+
<td class="impact">${escapeHtml(s.impact)}</td>
|
|
20
|
+
</tr>`
|
|
21
|
+
)
|
|
22
|
+
.join('');
|
|
23
|
+
|
|
24
|
+
return `
|
|
25
|
+
<h2 class="section-title">💡 Refactoring Suggestions</h2>
|
|
26
|
+
<div class="card">
|
|
27
|
+
<table>
|
|
28
|
+
<thead>
|
|
29
|
+
<tr>
|
|
30
|
+
<th>#</th>
|
|
31
|
+
<th>Priority</th>
|
|
32
|
+
<th>Suggestion</th>
|
|
33
|
+
<th>Impact</th>
|
|
34
|
+
</tr>
|
|
35
|
+
</thead>
|
|
36
|
+
<tbody>${rows}</tbody>
|
|
37
|
+
</table>
|
|
38
|
+
</div>`;
|
|
39
|
+
}
|