skrypt-ai 0.5.0 → 0.6.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/auth/index.js +8 -1
- package/dist/autofix/index.d.ts +0 -4
- package/dist/autofix/index.js +0 -21
- package/dist/capture/browser.d.ts +11 -0
- package/dist/capture/browser.js +173 -0
- package/dist/capture/diff.d.ts +23 -0
- package/dist/capture/diff.js +52 -0
- package/dist/capture/index.d.ts +23 -0
- package/dist/capture/index.js +210 -0
- package/dist/capture/naming.d.ts +17 -0
- package/dist/capture/naming.js +45 -0
- package/dist/capture/parser.d.ts +15 -0
- package/dist/capture/parser.js +80 -0
- package/dist/capture/types.d.ts +57 -0
- package/dist/capture/types.js +1 -0
- package/dist/cli.js +4 -0
- package/dist/commands/autofix.js +136 -120
- package/dist/commands/cron.js +58 -47
- package/dist/commands/deploy.js +123 -102
- package/dist/commands/generate.js +88 -6
- package/dist/commands/heal.d.ts +10 -0
- package/dist/commands/heal.js +201 -0
- package/dist/commands/i18n.js +146 -111
- package/dist/commands/lint.js +50 -44
- package/dist/commands/llms-txt.js +59 -49
- package/dist/commands/login.js +61 -43
- package/dist/commands/mcp.js +6 -0
- package/dist/commands/monitor.js +13 -8
- package/dist/commands/qa.d.ts +2 -0
- package/dist/commands/qa.js +43 -0
- package/dist/commands/review-pr.js +108 -102
- package/dist/commands/sdk.js +128 -122
- package/dist/commands/security.js +86 -80
- package/dist/commands/test.js +91 -92
- package/dist/commands/version.js +104 -75
- package/dist/commands/watch.js +130 -114
- package/dist/config/types.js +2 -2
- package/dist/context-hub/index.d.ts +23 -0
- package/dist/context-hub/index.js +179 -0
- package/dist/context-hub/mappings.d.ts +8 -0
- package/dist/context-hub/mappings.js +55 -0
- package/dist/context-hub/types.d.ts +33 -0
- package/dist/context-hub/types.js +1 -0
- package/dist/generator/generator.js +39 -6
- package/dist/generator/types.d.ts +7 -0
- package/dist/generator/writer.d.ts +3 -1
- package/dist/generator/writer.js +24 -4
- package/dist/llm/anthropic-client.d.ts +1 -0
- package/dist/llm/anthropic-client.js +3 -1
- package/dist/llm/index.d.ts +6 -4
- package/dist/llm/index.js +76 -261
- package/dist/llm/openai-client.d.ts +1 -0
- package/dist/llm/openai-client.js +7 -2
- package/dist/qa/checks.d.ts +10 -0
- package/dist/qa/checks.js +492 -0
- package/dist/qa/fixes.d.ts +30 -0
- package/dist/qa/fixes.js +277 -0
- package/dist/qa/index.d.ts +29 -0
- package/dist/qa/index.js +187 -0
- package/dist/qa/types.d.ts +24 -0
- package/dist/qa/types.js +1 -0
- package/dist/scanner/csharp.d.ts +23 -0
- package/dist/scanner/csharp.js +421 -0
- package/dist/scanner/index.js +16 -2
- package/dist/scanner/java.d.ts +39 -0
- package/dist/scanner/java.js +318 -0
- package/dist/scanner/kotlin.d.ts +23 -0
- package/dist/scanner/kotlin.js +389 -0
- package/dist/scanner/php.d.ts +57 -0
- package/dist/scanner/php.js +351 -0
- package/dist/scanner/ruby.d.ts +36 -0
- package/dist/scanner/ruby.js +431 -0
- package/dist/scanner/swift.d.ts +25 -0
- package/dist/scanner/swift.js +392 -0
- package/dist/scanner/types.d.ts +1 -1
- package/dist/template/content/docs/_navigation.json +46 -0
- package/dist/template/content/docs/_sidebars.json +684 -0
- package/dist/template/content/docs/core.md +4544 -0
- package/dist/template/content/docs/index.mdx +89 -0
- package/dist/template/content/docs/integrations.md +1158 -0
- package/dist/template/content/docs/llms-full.md +403 -0
- package/dist/template/content/docs/llms.txt +4588 -0
- package/dist/template/content/docs/other.md +10379 -0
- package/dist/template/content/docs/tools.md +746 -0
- package/dist/template/content/docs/types.md +531 -0
- package/dist/template/docs.json +13 -11
- package/dist/template/mdx-components.tsx +27 -2
- package/dist/template/package.json +6 -0
- package/dist/template/public/search-index.json +1 -1
- package/dist/template/scripts/build-search-index.mjs +84 -6
- package/dist/template/src/app/api/chat/route.ts +83 -128
- package/dist/template/src/app/docs/[...slug]/page.tsx +75 -20
- package/dist/template/src/app/docs/llms-full.md +151 -4
- package/dist/template/src/app/docs/llms.txt +2464 -847
- package/dist/template/src/app/docs/page.mdx +48 -38
- package/dist/template/src/app/layout.tsx +3 -1
- package/dist/template/src/app/page.tsx +22 -8
- package/dist/template/src/components/ai-chat.tsx +73 -64
- package/dist/template/src/components/breadcrumbs.tsx +21 -23
- package/dist/template/src/components/copy-button.tsx +13 -9
- package/dist/template/src/components/copy-page-button.tsx +54 -0
- package/dist/template/src/components/docs-layout.tsx +37 -25
- package/dist/template/src/components/header.tsx +51 -10
- package/dist/template/src/components/mdx/card.tsx +17 -3
- package/dist/template/src/components/mdx/code-block.tsx +13 -9
- package/dist/template/src/components/mdx/code-group.tsx +13 -8
- package/dist/template/src/components/mdx/heading.tsx +15 -2
- package/dist/template/src/components/mdx/highlighted-code.tsx +13 -8
- package/dist/template/src/components/mdx/index.tsx +2 -0
- package/dist/template/src/components/mdx/mermaid.tsx +110 -0
- package/dist/template/src/components/mdx/screenshot.tsx +150 -0
- package/dist/template/src/components/scroll-to-hash.tsx +48 -0
- package/dist/template/src/components/sidebar.tsx +12 -18
- package/dist/template/src/components/table-of-contents.tsx +9 -0
- package/dist/template/src/lib/highlight.ts +3 -88
- package/dist/template/src/lib/navigation.ts +159 -0
- package/dist/template/src/styles/globals.css +17 -6
- package/dist/utils/validation.d.ts +0 -3
- package/dist/utils/validation.js +0 -26
- package/package.json +3 -2
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
/**
|
|
3
|
+
* Scanner for PHP source files
|
|
4
|
+
* Extracts: classes, interfaces, enums, traits, abstract classes,
|
|
5
|
+
* public functions, public methods, public static methods
|
|
6
|
+
*/
|
|
7
|
+
export class PHPScanner {
|
|
8
|
+
languages = ['php'];
|
|
9
|
+
canHandle(filePath) {
|
|
10
|
+
return (/\.php$/.test(filePath) &&
|
|
11
|
+
!filePath.includes('Test.php') &&
|
|
12
|
+
!filePath.includes('/tests/') &&
|
|
13
|
+
!filePath.includes('/test/'));
|
|
14
|
+
}
|
|
15
|
+
async scanFile(filePath) {
|
|
16
|
+
try {
|
|
17
|
+
const source = readFileSync(filePath, 'utf-8');
|
|
18
|
+
const elements = [];
|
|
19
|
+
const errors = [];
|
|
20
|
+
const lines = source.split('\n');
|
|
21
|
+
// Extract namespace as package name
|
|
22
|
+
const namespaceMatch = source.match(/^namespace\s+([\w\\]+)\s*;/m);
|
|
23
|
+
const packageName = namespaceMatch?.[1] ?? 'global';
|
|
24
|
+
// Extract use/import statements for context
|
|
25
|
+
const imports = this.extractImports(source);
|
|
26
|
+
// Find all public API elements
|
|
27
|
+
this.extractTypes(source, lines, filePath, packageName, imports, elements);
|
|
28
|
+
this.extractMethods(source, lines, filePath, packageName, imports, elements);
|
|
29
|
+
this.extractFunctions(source, lines, filePath, packageName, imports, elements);
|
|
30
|
+
return {
|
|
31
|
+
filePath,
|
|
32
|
+
language: 'php',
|
|
33
|
+
elements,
|
|
34
|
+
errors
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
return {
|
|
39
|
+
filePath,
|
|
40
|
+
language: 'php',
|
|
41
|
+
elements: [],
|
|
42
|
+
errors: [`Failed to parse: ${err}`]
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
extractImports(source) {
|
|
47
|
+
const imports = [];
|
|
48
|
+
const useMatches = source.matchAll(/^use\s+([\w\\]+)(?:\s+as\s+\w+)?;/gm);
|
|
49
|
+
for (const m of useMatches) {
|
|
50
|
+
if (m[1])
|
|
51
|
+
imports.push(m[1]);
|
|
52
|
+
}
|
|
53
|
+
return imports;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Extract classes, interfaces, enums, traits, abstract classes
|
|
57
|
+
*/
|
|
58
|
+
extractTypes(source, lines, filePath, packageName, imports, elements) {
|
|
59
|
+
// Match: class, abstract class, final class, readonly class, final readonly class, interface, enum, trait
|
|
60
|
+
const typeRegex = /^(?:(?:abstract|final|readonly)\s+)*(?:class|interface|enum|trait)\s+(\w+)/gm;
|
|
61
|
+
let match;
|
|
62
|
+
while ((match = typeRegex.exec(source)) !== null) {
|
|
63
|
+
const name = match[1];
|
|
64
|
+
if (!name)
|
|
65
|
+
continue;
|
|
66
|
+
const fullMatch = match[0];
|
|
67
|
+
const lineNumber = this.getLineNumber(source, match.index);
|
|
68
|
+
const docstring = this.getDocComment(lines, lineNumber - 1);
|
|
69
|
+
const signature = fullMatch.trim();
|
|
70
|
+
elements.push({
|
|
71
|
+
kind: 'class',
|
|
72
|
+
name,
|
|
73
|
+
signature,
|
|
74
|
+
parameters: [],
|
|
75
|
+
docstring,
|
|
76
|
+
filePath,
|
|
77
|
+
lineNumber,
|
|
78
|
+
isExported: true,
|
|
79
|
+
isPublic: true,
|
|
80
|
+
imports,
|
|
81
|
+
packageName,
|
|
82
|
+
sourceContext: this.getSourceContext(lines, lineNumber, 15)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Extract the content between matching parentheses, handling nested parens.
|
|
88
|
+
* Starts at the given index which must point to an opening '('.
|
|
89
|
+
*/
|
|
90
|
+
extractParenContent(source, openIndex) {
|
|
91
|
+
if (source[openIndex] !== '(')
|
|
92
|
+
return null;
|
|
93
|
+
let depth = 0;
|
|
94
|
+
for (let i = openIndex; i < source.length; i++) {
|
|
95
|
+
if (source[i] === '(')
|
|
96
|
+
depth++;
|
|
97
|
+
else if (source[i] === ')') {
|
|
98
|
+
depth--;
|
|
99
|
+
if (depth === 0)
|
|
100
|
+
return source.slice(openIndex + 1, i);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Extract public methods (instance and static) from classes/interfaces/traits
|
|
107
|
+
* Skips private and protected methods
|
|
108
|
+
*/
|
|
109
|
+
extractMethods(source, lines, filePath, packageName, imports, elements) {
|
|
110
|
+
// First, build a map of class boundaries to determine parentClass
|
|
111
|
+
const classBoundaries = this.getClassBoundaries(source);
|
|
112
|
+
// Match public methods up to and including the opening paren
|
|
113
|
+
// Supports: public function, public static function, public final function,
|
|
114
|
+
// final public function, final public static function, etc.
|
|
115
|
+
const methodRegex = /^[ \t]+(?:final\s+)?public\s+(?:(?:static|abstract|final)\s+)*function\s+(\w+)\s*\(/gm;
|
|
116
|
+
let match;
|
|
117
|
+
while ((match = methodRegex.exec(source)) !== null) {
|
|
118
|
+
const name = match[1];
|
|
119
|
+
if (!name)
|
|
120
|
+
continue;
|
|
121
|
+
// Extract params using balanced-paren helper
|
|
122
|
+
const openParenIndex = match.index + match[0].length - 1;
|
|
123
|
+
const paramsStr = this.extractParenContent(source, openParenIndex);
|
|
124
|
+
if (paramsStr === null)
|
|
125
|
+
continue;
|
|
126
|
+
// Look for return type after the closing paren
|
|
127
|
+
const closeParenIndex = openParenIndex + 1 + paramsStr.length; // index of ')'
|
|
128
|
+
const afterParen = source.slice(closeParenIndex + 1);
|
|
129
|
+
const returnTypeMatch = afterParen.match(/^\s*:\s*([\w\\|?]+)/);
|
|
130
|
+
const returnType = returnTypeMatch?.[1]?.trim() || undefined;
|
|
131
|
+
const lineNumber = this.getLineNumber(source, match.index);
|
|
132
|
+
const docstring = this.getDocComment(lines, lineNumber - 1);
|
|
133
|
+
const parameters = this.parsePHPParams(paramsStr);
|
|
134
|
+
const parentClass = this.findParentClass(match.index, classBoundaries);
|
|
135
|
+
// Build signature including params and return type
|
|
136
|
+
const sigBase = match[0] + paramsStr + ')';
|
|
137
|
+
const signature = (returnType ? sigBase + ': ' + returnType : sigBase).trim();
|
|
138
|
+
elements.push({
|
|
139
|
+
kind: 'method',
|
|
140
|
+
name,
|
|
141
|
+
signature,
|
|
142
|
+
parameters,
|
|
143
|
+
returnType,
|
|
144
|
+
docstring,
|
|
145
|
+
filePath,
|
|
146
|
+
lineNumber,
|
|
147
|
+
parentClass,
|
|
148
|
+
isExported: true,
|
|
149
|
+
isPublic: true,
|
|
150
|
+
imports,
|
|
151
|
+
packageName,
|
|
152
|
+
sourceContext: this.getSourceContext(lines, lineNumber)
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Extract standalone functions (not inside a class/interface/trait)
|
|
158
|
+
*/
|
|
159
|
+
extractFunctions(source, lines, filePath, packageName, imports, elements) {
|
|
160
|
+
const classBoundaries = this.getClassBoundaries(source);
|
|
161
|
+
// Match top-level functions up to and including the opening paren
|
|
162
|
+
// Must start at the beginning of a line (no leading whitespace = not a method)
|
|
163
|
+
const funcRegex = /^function\s+(\w+)\s*\(/gm;
|
|
164
|
+
let match;
|
|
165
|
+
while ((match = funcRegex.exec(source)) !== null) {
|
|
166
|
+
const name = match[1];
|
|
167
|
+
if (!name)
|
|
168
|
+
continue;
|
|
169
|
+
// Skip if inside a class boundary
|
|
170
|
+
const parentClass = this.findParentClass(match.index, classBoundaries);
|
|
171
|
+
if (parentClass)
|
|
172
|
+
continue;
|
|
173
|
+
// Extract params using balanced-paren helper
|
|
174
|
+
const openParenIndex = match.index + match[0].length - 1;
|
|
175
|
+
const paramsStr = this.extractParenContent(source, openParenIndex);
|
|
176
|
+
if (paramsStr === null)
|
|
177
|
+
continue;
|
|
178
|
+
// Look for return type after the closing paren
|
|
179
|
+
const closeParenIndex = openParenIndex + 1 + paramsStr.length;
|
|
180
|
+
const afterParen = source.slice(closeParenIndex + 1);
|
|
181
|
+
const returnTypeMatch = afterParen.match(/^\s*:\s*([\w\\|?]+)/);
|
|
182
|
+
const returnType = returnTypeMatch?.[1]?.trim() || undefined;
|
|
183
|
+
const lineNumber = this.getLineNumber(source, match.index);
|
|
184
|
+
const docstring = this.getDocComment(lines, lineNumber - 1);
|
|
185
|
+
const parameters = this.parsePHPParams(paramsStr);
|
|
186
|
+
// Build signature including params and return type
|
|
187
|
+
const sigBase = match[0] + paramsStr + ')';
|
|
188
|
+
const signature = (returnType ? sigBase + ': ' + returnType : sigBase).trim();
|
|
189
|
+
elements.push({
|
|
190
|
+
kind: 'function',
|
|
191
|
+
name,
|
|
192
|
+
signature,
|
|
193
|
+
parameters,
|
|
194
|
+
returnType,
|
|
195
|
+
docstring,
|
|
196
|
+
filePath,
|
|
197
|
+
lineNumber,
|
|
198
|
+
isExported: true,
|
|
199
|
+
isPublic: true,
|
|
200
|
+
imports,
|
|
201
|
+
packageName,
|
|
202
|
+
sourceContext: this.getSourceContext(lines, lineNumber)
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Build a map of class/interface/trait/enum boundaries (start offset, end offset, name)
|
|
208
|
+
*/
|
|
209
|
+
getClassBoundaries(source) {
|
|
210
|
+
const boundaries = [];
|
|
211
|
+
const typeRegex = /^(?:(?:abstract|final|readonly)\s+)*(?:class|interface|enum|trait)\s+(\w+)[^{]*\{/gm;
|
|
212
|
+
let match;
|
|
213
|
+
while ((match = typeRegex.exec(source)) !== null) {
|
|
214
|
+
const name = match[1];
|
|
215
|
+
if (!name)
|
|
216
|
+
continue;
|
|
217
|
+
const start = match.index;
|
|
218
|
+
const braceStart = source.indexOf('{', start + match[0].length - 1);
|
|
219
|
+
const end = this.findMatchingBrace(source, braceStart);
|
|
220
|
+
boundaries.push({ name, start, end });
|
|
221
|
+
}
|
|
222
|
+
return boundaries;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Find the matching closing brace for an opening brace
|
|
226
|
+
*/
|
|
227
|
+
findMatchingBrace(source, openPos) {
|
|
228
|
+
let depth = 0;
|
|
229
|
+
for (let i = openPos; i < source.length; i++) {
|
|
230
|
+
if (source[i] === '{')
|
|
231
|
+
depth++;
|
|
232
|
+
else if (source[i] === '}') {
|
|
233
|
+
depth--;
|
|
234
|
+
if (depth === 0)
|
|
235
|
+
return i;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return source.length;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Find which class/interface/trait contains the given source offset
|
|
242
|
+
*/
|
|
243
|
+
findParentClass(offset, boundaries) {
|
|
244
|
+
for (const b of boundaries) {
|
|
245
|
+
if (offset > b.start && offset < b.end) {
|
|
246
|
+
return b.name;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Parse PHP function parameters into Parameter objects
|
|
253
|
+
* Handles: type hints (?string, int|string, array), default values
|
|
254
|
+
*/
|
|
255
|
+
parsePHPParams(paramsStr) {
|
|
256
|
+
if (!paramsStr.trim())
|
|
257
|
+
return [];
|
|
258
|
+
const params = [];
|
|
259
|
+
const parts = this.splitParams(paramsStr);
|
|
260
|
+
for (const part of parts) {
|
|
261
|
+
const trimmed = part.trim();
|
|
262
|
+
if (!trimmed)
|
|
263
|
+
continue;
|
|
264
|
+
// PHP param format: [?]Type $name [= default]
|
|
265
|
+
// or: Type|Type2 $name
|
|
266
|
+
// or: $name (no type hint)
|
|
267
|
+
const paramMatch = trimmed.match(/^((?:[\w\\|?]+\s+)?)(\$\w+)(?:\s*=\s*(.+))?$/);
|
|
268
|
+
if (paramMatch) {
|
|
269
|
+
const type = paramMatch[1]?.trim() || undefined;
|
|
270
|
+
const name = paramMatch[2]?.replace(/^\$/, '') ?? '';
|
|
271
|
+
const defaultValue = paramMatch[3]?.trim() || undefined;
|
|
272
|
+
if (name) {
|
|
273
|
+
params.push({ name, type, default: defaultValue });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return params;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Split parameter string by commas, respecting nested brackets
|
|
281
|
+
*/
|
|
282
|
+
splitParams(str) {
|
|
283
|
+
const parts = [];
|
|
284
|
+
let depth = 0;
|
|
285
|
+
let current = '';
|
|
286
|
+
for (const char of str) {
|
|
287
|
+
if (char === '(' || char === '[' || char === '{' || char === '<')
|
|
288
|
+
depth++;
|
|
289
|
+
else if (char === ')' || char === ']' || char === '}' || char === '>')
|
|
290
|
+
depth--;
|
|
291
|
+
else if (char === ',' && depth === 0) {
|
|
292
|
+
parts.push(current);
|
|
293
|
+
current = '';
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
current += char;
|
|
297
|
+
}
|
|
298
|
+
if (current.trim())
|
|
299
|
+
parts.push(current);
|
|
300
|
+
return parts;
|
|
301
|
+
}
|
|
302
|
+
getLineNumber(source, index) {
|
|
303
|
+
return source.slice(0, index).split('\n').length;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Extract PHPDoc block comment above a given line
|
|
307
|
+
*/
|
|
308
|
+
getDocComment(lines, lineIndex) {
|
|
309
|
+
// Look for a closing */ above the declaration line
|
|
310
|
+
let i = lineIndex - 1;
|
|
311
|
+
// Skip blank lines and PHP 8 attribute lines (#[...])
|
|
312
|
+
while (i >= 0) {
|
|
313
|
+
const trimmed = lines[i]?.trim() ?? '';
|
|
314
|
+
if (trimmed === '') {
|
|
315
|
+
i--;
|
|
316
|
+
}
|
|
317
|
+
else if (trimmed.startsWith('#[')) {
|
|
318
|
+
i--;
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
if (i < 0)
|
|
325
|
+
return undefined;
|
|
326
|
+
const closeLine = lines[i];
|
|
327
|
+
if (!closeLine || !closeLine.trim().endsWith('*/'))
|
|
328
|
+
return undefined;
|
|
329
|
+
// Walk up to find the opening /**
|
|
330
|
+
let start = i;
|
|
331
|
+
while (start >= 0 && !lines[start]?.includes('/**')) {
|
|
332
|
+
start--;
|
|
333
|
+
}
|
|
334
|
+
if (start < 0 || !lines[start]?.includes('/**'))
|
|
335
|
+
return undefined;
|
|
336
|
+
const block = lines.slice(start, i + 1).join('\n');
|
|
337
|
+
const cleaned = block
|
|
338
|
+
.replace(/\/\*\*/, '')
|
|
339
|
+
.replace(/\*\//, '')
|
|
340
|
+
.split('\n')
|
|
341
|
+
.map(l => l.trim().replace(/^\*\s?/, ''))
|
|
342
|
+
.filter(Boolean)
|
|
343
|
+
.join('\n');
|
|
344
|
+
return cleaned || undefined;
|
|
345
|
+
}
|
|
346
|
+
getSourceContext(lines, lineNumber, context = 5) {
|
|
347
|
+
const start = Math.max(0, lineNumber - context - 1);
|
|
348
|
+
const end = Math.min(lines.length, lineNumber + context);
|
|
349
|
+
return lines.slice(start, end).join('\n');
|
|
350
|
+
}
|
|
351
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Scanner, ScanResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Scanner for Ruby source files
|
|
4
|
+
* Extracts: classes, modules, methods (public only)
|
|
5
|
+
*/
|
|
6
|
+
export declare class RubyScanner implements Scanner {
|
|
7
|
+
languages: string[];
|
|
8
|
+
canHandle(filePath: string): boolean;
|
|
9
|
+
scanFile(filePath: string): Promise<ScanResult>;
|
|
10
|
+
private extractImports;
|
|
11
|
+
private extractModuleNesting;
|
|
12
|
+
private extractClasses;
|
|
13
|
+
private extractModules;
|
|
14
|
+
/**
|
|
15
|
+
* Get the body of a module/class starting at the given source index.
|
|
16
|
+
* Returns the text between the opening line and its matching `end`, or null.
|
|
17
|
+
*/
|
|
18
|
+
private getModuleBody;
|
|
19
|
+
private extractMethods;
|
|
20
|
+
/**
|
|
21
|
+
* Build a map of lineNumber → visibility for every `def` line.
|
|
22
|
+
* Ruby's `private` / `protected` markers apply to all subsequent defs
|
|
23
|
+
* within the same class/module scope until another visibility marker.
|
|
24
|
+
*/
|
|
25
|
+
private buildVisibilityMap;
|
|
26
|
+
private findParentClass;
|
|
27
|
+
private parseRubyParams;
|
|
28
|
+
private splitParams;
|
|
29
|
+
private getDocComment;
|
|
30
|
+
/**
|
|
31
|
+
* Extract @return type from YARD comments above a method.
|
|
32
|
+
*/
|
|
33
|
+
private extractReturnType;
|
|
34
|
+
private getLineNumber;
|
|
35
|
+
private getSourceContext;
|
|
36
|
+
}
|