codesummary 1.2.0 → 1.2.2

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.
@@ -0,0 +1,196 @@
1
+ import path from 'path';
2
+
3
+ /**
4
+ * RepositorySignals
5
+ * Shared heuristics that can be reused by multiple output generators.
6
+ */
7
+ export default class RepositorySignals {
8
+ /**
9
+ * Extract file tags based on path and filename heuristics.
10
+ * @param {string} relativePath - Relative file path
11
+ * @param {string} extension - File extension
12
+ * @returns {Array} Array of tags
13
+ */
14
+ extractFileTags(relativePath, extension) {
15
+ const tags = [];
16
+ const pathLower = relativePath.toLowerCase();
17
+ const fileName = path.basename(relativePath, extension).toLowerCase();
18
+ const fullPath = relativePath.toLowerCase();
19
+
20
+ if (pathLower.includes('/test/') || pathLower.includes('\\test\\')) tags.push('test');
21
+ if (pathLower.includes('/spec/') || pathLower.includes('\\spec\\')) tags.push('test');
22
+ if (pathLower.includes('/__tests__/') || pathLower.includes('\\__tests__\\')) tags.push('test');
23
+ if (pathLower.includes('/scripts/') || pathLower.includes('\\scripts\\')) tags.push('script');
24
+ if (pathLower.includes('/config/') || pathLower.includes('\\config\\')) tags.push('config');
25
+ if (pathLower.includes('/lib/') || pathLower.includes('\\lib\\')) tags.push('library');
26
+ if (pathLower.includes('/utils/') || pathLower.includes('\\utils\\')) tags.push('utility');
27
+ if (pathLower.includes('/helpers/') || pathLower.includes('\\helpers\\')) tags.push('utility');
28
+
29
+ if (pathLower.includes('/pages/') || pathLower.includes('\\pages\\')) tags.push('page');
30
+ if (pathLower.includes('/components/') || pathLower.includes('\\components\\')) tags.push('component');
31
+ if (pathLower.includes('/shared/') || pathLower.includes('\\shared\\')) tags.push('shared');
32
+ if (pathLower.includes('/common/') || pathLower.includes('\\common\\')) tags.push('shared');
33
+ if (pathLower.includes('/hooks/') || pathLower.includes('\\hooks\\')) tags.push('hook');
34
+ if (pathLower.includes('/services/') || pathLower.includes('\\services\\')) tags.push('service');
35
+ if (pathLower.includes('/api/') || pathLower.includes('\\api\\')) tags.push('api');
36
+ if (pathLower.includes('/routes/') || pathLower.includes('\\routes\\')) tags.push('route');
37
+ if (pathLower.includes('/controllers/') || pathLower.includes('\\controllers\\')) tags.push('controller');
38
+ if (pathLower.includes('/models/') || pathLower.includes('\\models\\')) tags.push('model');
39
+ if (pathLower.includes('/views/') || pathLower.includes('\\views\\')) tags.push('view');
40
+ if (pathLower.includes('/layouts/') || pathLower.includes('\\layouts\\')) tags.push('layout');
41
+ if (pathLower.includes('/middleware/') || pathLower.includes('\\middleware\\')) tags.push('middleware');
42
+
43
+ if (pathLower.includes('/build/') || pathLower.includes('\\build\\')) tags.push('build');
44
+ if (pathLower.includes('/dist/') || pathLower.includes('\\dist\\')) tags.push('build');
45
+ if (pathLower.includes('/.github/') || pathLower.includes('\\.github\\')) tags.push('ci');
46
+ if (pathLower.includes('/workflows/') || pathLower.includes('\\workflows\\')) tags.push('ci');
47
+
48
+ if (fileName.includes('config')) tags.push('config');
49
+ if (fileName.includes('test') || fileName.includes('spec')) tags.push('test');
50
+ if (fileName.includes('index')) tags.push('entry');
51
+ if (fileName.includes('main')) tags.push('entry');
52
+ if (fileName.includes('app')) tags.push('application');
53
+ if (fileName.includes('component')) tags.push('component');
54
+ if (fileName.includes('page')) tags.push('page');
55
+ if (fileName.includes('layout')) tags.push('layout');
56
+ if (fileName.includes('service')) tags.push('service');
57
+ if (fileName.includes('util') || fileName.includes('helper')) tags.push('utility');
58
+ if (fileName.includes('hook')) tags.push('hook');
59
+ if (fileName.includes('api')) tags.push('api');
60
+ if (fileName.includes('route')) tags.push('route');
61
+ if (fileName.includes('model')) tags.push('model');
62
+ if (fileName.includes('controller')) tags.push('controller');
63
+ if (fileName.includes('middleware')) tags.push('middleware');
64
+ if (fileName.includes('store') || fileName.includes('state')) tags.push('state');
65
+ if (fileName.includes('context')) tags.push('context');
66
+ if (fileName.includes('provider')) tags.push('provider');
67
+
68
+ if (['.test.js', '.spec.js', '.test.ts', '.spec.ts', '.test.tsx', '.spec.tsx'].some(ext => fullPath.endsWith(ext))) {
69
+ tags.push('test');
70
+ }
71
+ if (['.d.ts'].some(ext => fullPath.endsWith(ext))) {
72
+ tags.push('types');
73
+ }
74
+ if (['.stories.js', '.stories.ts', '.stories.tsx'].some(ext => fullPath.endsWith(ext))) {
75
+ tags.push('storybook');
76
+ }
77
+ if (['.cy.js', '.cy.ts'].some(ext => fullPath.endsWith(ext))) {
78
+ tags.push('e2e');
79
+ }
80
+
81
+ if (extension === '.tsx' || extension === '.jsx') {
82
+ tags.push('react');
83
+ }
84
+ if (fullPath.includes('vue') || extension === '.vue') {
85
+ tags.push('vue');
86
+ }
87
+ if (fullPath.includes('angular') || fullPath.includes('.component.') || fullPath.includes('.service.')) {
88
+ tags.push('angular');
89
+ }
90
+ if (fullPath.includes('next') || fullPath.includes('_app.') || fullPath.includes('_document.')) {
91
+ tags.push('nextjs');
92
+ }
93
+
94
+ if (['readme', 'license', 'changelog', 'contributing'].includes(fileName)) {
95
+ tags.push('documentation');
96
+ }
97
+ if (['dockerfile', 'docker-compose', '.dockerignore'].includes(fileName)) {
98
+ tags.push('docker');
99
+ }
100
+ if (['package.json', 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml'].includes(path.basename(relativePath))) {
101
+ tags.push('package');
102
+ }
103
+ if (['tsconfig.json', 'jsconfig.json', 'webpack.config.js', 'vite.config.js'].includes(path.basename(relativePath))) {
104
+ tags.push('config');
105
+ }
106
+
107
+ if (extension === '.bat' || extension === '.cmd') {
108
+ tags.push('infrastructure', 'script', 'windows');
109
+ }
110
+ if (extension === '.sh') {
111
+ tags.push('infrastructure', 'script', 'unix');
112
+ }
113
+ if (extension === '.json' && (fileName.includes('config') || fileName.includes('settings') || fileName.includes('.config.'))) {
114
+ tags.push('infrastructure', 'config');
115
+ }
116
+ if (['makefile', 'makefile.am', 'cmake', 'cmakelists.txt'].includes(fileName)) {
117
+ tags.push('infrastructure', 'build');
118
+ }
119
+ if (['readme', 'license', 'changelog', 'contributing'].includes(fileName)) {
120
+ tags.push('documentation');
121
+ }
122
+
123
+ return [...new Set(tags)];
124
+ }
125
+
126
+ /**
127
+ * Extract imports from content using simple regex.
128
+ * @param {string} content - File content
129
+ * @param {string} extension - File extension
130
+ * @returns {Array} Array of import statements
131
+ */
132
+ extractImports(content, extension) {
133
+ const imports = [];
134
+
135
+ switch (extension) {
136
+ case '.js':
137
+ case '.jsx':
138
+ case '.ts':
139
+ case '.tsx': {
140
+ const importRegex = /import\s+.*?from\s+['"]([^'"]+)['"]/g;
141
+ let match;
142
+ while ((match = importRegex.exec(content)) !== null) {
143
+ imports.push(match[1]);
144
+ }
145
+
146
+ const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
147
+ while ((match = requireRegex.exec(content)) !== null) {
148
+ imports.push(match[1]);
149
+ }
150
+ break;
151
+ }
152
+ case '.py': {
153
+ const pyImportRegex = /(?:from\s+(\S+)\s+import|import\s+(\S+))/g;
154
+ let match;
155
+ while ((match = pyImportRegex.exec(content)) !== null) {
156
+ imports.push(match[1] || match[2]);
157
+ }
158
+ break;
159
+ }
160
+ case '.c':
161
+ case '.cpp':
162
+ case '.h': {
163
+ const includeRegex = /#include\s*[<"]([^>"]+)[>"]/g;
164
+ let match;
165
+ while ((match = includeRegex.exec(content)) !== null) {
166
+ imports.push(match[1]);
167
+ }
168
+ break;
169
+ }
170
+ }
171
+
172
+ return [...new Set(imports)];
173
+ }
174
+
175
+ /**
176
+ * Extract function/method calls using simple regex.
177
+ * @param {string} content - File content
178
+ * @returns {Array} Array of function calls
179
+ */
180
+ extractCalls(content) {
181
+ const calls = [];
182
+ const callRegex = /\b([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/g;
183
+ let match;
184
+
185
+ while ((match = callRegex.exec(content)) !== null) {
186
+ const funcName = match[1];
187
+ const keywords = ['if', 'for', 'while', 'switch', 'catch', 'typeof', 'return', 'new'];
188
+
189
+ if (!keywords.includes(funcName) && funcName.length > 1) {
190
+ calls.push(funcName);
191
+ }
192
+ }
193
+
194
+ return [...new Set(calls)].slice(0, 20);
195
+ }
196
+ }