Skip to content

Commit b372cad

Browse files
fix: detect dev server URLs with ANSI color codes
- Add stripAnsiCodes() to remove color escape codes from output - Reorganize URL patterns by server type for better maintainability - Process output line-by-line to handle chunked stdout - Support Vite Unicode arrow (➜) with proper regex flag Fixes issue where Vite and other dev servers output ANSI color codes even with FORCE_COLOR=0, preventing URL detection. Now strips color codes before pattern matching. URL patterns are now organized into separate constants: - VITE_PATTERNS (Unicode and ASCII arrows) - CRA_PATTERNS (Create React App) - NEXTJS_PATTERNS (Next.js) - GENERIC_PATTERNS (fallback for custom servers) This makes it easy to add support for new dev servers. Work Item: W-20274055
1 parent 32c79d7 commit b372cad

File tree

1 file changed

+62
-25
lines changed

1 file changed

+62
-25
lines changed

src/server/DevServerManager.ts

Lines changed: 62 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,38 @@ import { Logger } from '../utils/Logger.js';
2424
* URL detection patterns for various dev servers
2525
* These patterns extract URLs from different dev server outputs
2626
*/
27-
const URL_PATTERNS = [
28-
// Vite with Unicode arrow: " ➜ Local: http://localhost:5173/"
29-
/\s*[>]\s*Local:\s+(https?:\/\/[^\s]+)/i,
30-
// Generic Local pattern with optional prefix: "Local: http://localhost:5173"
31-
/\s*Local:\s+(https?:\/\/[^\s]+)/i,
32-
// Create React App: "On Your Network: http://192.168.1.1:3000"
33-
/On Your Network:\s+(https?:\/\/[^\s]+)/i,
34-
// Next.js: "ready - started server on 0.0.0.0:3000, url: http://localhost:3000"
35-
/url:\s+(https?:\/\/[^\s,]+)/i,
36-
// Next.js alternative: "- Local: http://localhost:3000"
37-
/-\s*Local:\s+(https?:\/\/[^\s]+)/i,
38-
// Generic: "Server running at http://localhost:8080"
27+
/**
28+
* URL detection patterns organized by dev server type
29+
* Add new server patterns here for easy maintenance
30+
*/
31+
32+
// Vite dev server patterns
33+
// Example: " ➜ Local: http://localhost:5173/"
34+
const VITE_PATTERNS = [
35+
/\s*Local:\s+(https?:\/\/[^\s]+)/iu, // Unicode arrow (with colors)
36+
/>\s*Local:\s+(https?:\/\/[^\s]+)/i, // ASCII arrow fallback
37+
];
38+
39+
// Create React App (Webpack) patterns
40+
// Example: "On Your Network: http://192.168.1.1:3000"
41+
const CRA_PATTERNS = [/On Your Network:\s+(https?:\/\/[^\s]+)/i, /Local:\s+(https?:\/\/[^\s]+)/i];
42+
43+
// Next.js dev server patterns
44+
// Example: "ready - started server on 0.0.0.0:3000, url: http://localhost:3000"
45+
const NEXTJS_PATTERNS = [/url:\s+(https?:\/\/[^\s,]+)/i, /-\s*Local:\s+(https?:\/\/[^\s]+)/i];
46+
47+
// Generic patterns for custom/unknown servers
48+
// Example: "Server running at http://localhost:8080"
49+
const GENERIC_PATTERNS = [
3950
/(?:Server|server|Running|running|started|Started).*?(https?:\/\/[^\s]+)/i,
40-
// Port-based: "localhost:3000" or "http://localhost:3000"
4151
/(https?:\/\/localhost:[0-9]+)/i,
42-
// Generic URL anywhere in the output
4352
/(https?:\/\/(?:localhost|127\.0\.0\.1|0\.0\.0\.0):[0-9]+)/i,
4453
];
4554

55+
// Combined patterns in priority order
56+
// Specific patterns first, generic fallbacks last
57+
const URL_PATTERNS = [...VITE_PATTERNS, ...CRA_PATTERNS, ...NEXTJS_PATTERNS, ...GENERIC_PATTERNS];
58+
4659
/**
4760
* Default configuration values for DevServerManager
4861
*/
@@ -134,23 +147,47 @@ export class DevServerManager extends EventEmitter {
134147
}
135148

136149
/**
137-
* Detects a dev server URL from process output
150+
* Strips ANSI color codes from a string
138151
*
139-
* Tries multiple regex patterns to match various dev server formats
140-
* (Vite, Create React App, Next.js, etc.)
152+
* @param text - Text with potential ANSI codes
153+
* @returns Clean text without ANSI codes
154+
*/
155+
private static stripAnsiCodes(text: string): string {
156+
// eslint-disable-next-line no-control-regex
157+
return text.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
158+
}
159+
160+
/**
161+
* Detects dev server URL from process output
141162
*
142-
* @param output The output string to analyze
143-
* @returns Detected URL or null if not found
163+
* Attempts to match common dev server URL patterns like Vite,
164+
* Create React App, Next.js, etc. Processes line-by-line for robustness.
165+
*
166+
* @param output - The output string to search for URLs
167+
* @returns Detected URL or null if none found
144168
*/
145169
private static detectUrlFromOutput(output: string): string | null {
146-
for (const pattern of URL_PATTERNS) {
147-
const match = output.match(pattern);
148-
if (match?.[1]) {
149-
const url = match[1].trim();
150-
// Normalize 0.0.0.0 to localhost for better usability
151-
return url.replace('0.0.0.0', 'localhost');
170+
// Split by newlines and check each line separately
171+
// This is more robust against chunked output
172+
const lines = output.split('\n');
173+
174+
for (const line of lines) {
175+
// Strip ANSI color codes first (some tools ignore FORCE_COLOR=0)
176+
const cleanLine = DevServerManager.stripAnsiCodes(line);
177+
const trimmedLine = cleanLine.trim();
178+
if (!trimmedLine) continue;
179+
180+
for (const pattern of URL_PATTERNS) {
181+
const match = trimmedLine.match(pattern);
182+
183+
if (match?.[1]) {
184+
const url = match[1].trim();
185+
// Normalize 0.0.0.0 to localhost for better usability
186+
return url.replace('0.0.0.0', 'localhost');
187+
}
152188
}
153189
}
190+
154191
return null;
155192
}
156193

0 commit comments

Comments
 (0)