) => { and ws => {)
code_string = code_string.replace(') => {', ')=> {\n')
code_string = code_string.replace('=> {', '=> {\n')
# Add newlines for keywords/declarations that typically start a new line.
# The (? ensures we don't add a newline at the very start
# or after an existing newline, and prevents splitting words like 'myfunction'.
code_string = re.sub(
r'(?}).on(, ].map(, ).then()
# This places the dot and subsequent method on a new line.
code_string = re.sub(r'([)}\]])\s*\.([a-zA-Z_]\w*\()', r'\1\n.\2', code_string)
# Ensure comments are on their own line
code_string = code_string.replace('//', '\n//')
# Clean up multiple empty lines created by too many replacements
code_string = re.sub(r'\n\n+', '\n', code_string).strip()
# Step 2: Apply indentation based on braces
lines = code_string.split('\n')
formatted_lines_with_indent = []
indent_level = 0
for i, line_raw in enumerate(lines):
stripped_line = line_raw.strip()
if not stripped_line:
continue
# Decrease indent if line starts with a closing brace (or similar block end)
if stripped_line.startswith('}') or stripped_line.startswith('])') or (stripped_line.startswith(')') and len(stripped_line) > 1 and not stripped_line.endswith('(')):
indent_level = max(0, indent_level - 1)
# Add the line with current indentation
formatted_lines_with_indent.append(' ' * indent_level + stripped_line)
# Increase indent if line ends with an opening brace
if stripped_line.endswith('{') and not stripped_line.startswith('//'):
indent_level += 1
# Step 3: Add strategic blank lines for better readability
final_output = []
for i, line in enumerate(formatted_lines_with_indent):
final_output.append(line)
stripped_line = line.strip()
# Add a blank line after top-level block endings like }); or }
# Conditions:
# - Ends with '});' or '}' (but not an object literal that opens and closes on the same line like {};)
# - Not a comment line
# - Not an opening brace itself (e.g., {)
# - Next line doesn't start with '}' (to avoid blank lines before closing braces)
# - Next line doesn't start with '.' (to avoid blank lines before chained calls)
if stripped_line.endswith('});') or (stripped_line.endswith('}') and
not stripped_line.startswith('//') and
not stripped_line.endswith('{') and
not stripped_line.endswith('{};') and
not stripped_line.endswith('} = {};')):
if i + 1 < len(formatted_lines_with_indent):
next_stripped = formatted_lines_with_indent[i+1].strip()
if next_stripped and not next_stripped.startswith('}') and \
not next_stripped.startswith(')') and not next_stripped.startswith('.'):
# Only add a blank line if the next line is not empty and not another closing block part
final_output.append('')
# Step 4: Final cleanup of multiple empty lines and leading/trailing empty lines
cleaned_output = []
last_was_empty = True # Treat beginning as "empty" to prevent initial blank line
for line in final_output:
if not line.strip():
if not last_was_empty:
cleaned_output.append('')
last_was_empty = True
else:
cleaned_output.append(line)
last_was_empty = False
return '\n'.join(cleaned_output).strip()
def format_html_code_blocks(html_content):
"""
Parses HTML content, finds ... blocks,
and formats the JavaScript code within them.
"""
def replacer(match):
original_code_content = match.group(1)
formatted_code_content = format_js_code(original_code_content)
# Reconstruct the block with the formatted content
return f"{formatted_code_content}
"
# Use re.sub with a callback function to find and replace the content
# The pattern targets content within tags that are themselves within `` tags.
# `(.*?)` uses a non-greedy match to capture the code content.
# `re.DOTALL` (re.S) allows `.` to match newlines, important if code was already broken.
formatted_html = re.sub(
r'\s*(.*?)\s*
',
replacer,
html_content,
flags=re.DOTALL
)
return formatted_html
The original HTML content string
html_content = """
In today's hyper-connected digital landscape, real-time communication is no longer a luxury but a fundamental expectation. From collaborative editing platforms and live dashboards to instant messaging and online gaming, users demand immediate feedback and seamless interactivity. At the heart of many of these experiences lies WebSockets, a powerful protocol providing full-duplex communication channels over a single TCP connection.
While Node.js excels at handling concurrent connections due to its event-driven, non-blocking I/O model, scaling real-time WebSocket applications to support millions of simultaneous users presents unique architectural challenges. This article will deep dive into the strategies, technologies, and best practices required to build high-performance, resilient, and scalable WebSocket applications with Node.js.
The Foundation: Understanding WebSockets
Before we embark on scaling, it's crucial to understand why WebSockets are superior to traditional HTTP for real-time scenarios.
HTTP vs. WebSockets: A Fundamental Shift
Traditional HTTP is a request-response protocol; clients initiate requests, and servers respond. For real-time updates, this typically involves polling (client repeatedly asking for updates) or long polling (server holds connection open until new data is available). Both are inefficient and resource-intensive for true real-time needs.
WebSockets, on the other hand, establish a persistent, bi-directional communication channel between a client and a server. After an initial HTTP handshake, the connection is upgraded to a WebSocket, allowing both client and server to send messages at any time without initiating a new request. This significantly reduces overhead and latency.
How WebSockets Work
- Handshake: A client sends an HTTP GET request with an
Upgrade: websocket header. - Upgrade: If the server supports WebSockets, it responds with a
101 Switching Protocols status, and the connection is upgraded. - Persistent Connection: The TCP connection remains open, allowing full-duplex message exchange until either side closes it.
Node.js, with its asynchronous nature, is an ideal runtime for handling the numerous concurrent connections inherent in WebSocket-based applications.
Core Technologies for Real-time in Node.js
Node.js offers excellent libraries for WebSocket implementation.
1. The ws Library
The ws library is a popular, fast, and feature-rich WebSocket client and server implementation for Node.js. It's a low-level library, providing direct control over the WebSocket protocol.
// server.js using 'ws' library (install with: npm install ws)import { WebSocketServer } from 'ws';import http from 'http';const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('WebSocket server is running');});const wss = new WebSocketServer({ server });wss.on('connection', ws => { console.log('Client connected!'); ws.on('message', message => { console.log(`Received message from client: ${message}`); // Echo the message back to the client ws.send(`Server received: ${message}`); }); ws.on('close', () => { console.log('Client disconnected.'); }); ws.on('error', error => { console.error('WebSocket error:', error); });});server.listen(8080, () => { console.log('WebSocket server listening on port 8080');});
2. Socket.IO
Socket.IO is a widely used library that builds on top of WebSockets, providing additional features and fallbacks for environments where WebSockets are not supported (e.g., older browsers). It offers auto-reconnection, packet buffering, multiplexing (namespaces), and broadcasting capabilities, making it easier to build robust real-time applications.
// server.js using Socket.IO (install with: npm install socket.io express)import express from 'express';import { createServer } from 'http';import { Server } from 'socket.io';const app = express();const httpServer = createServer(app);const io = new Server(httpServer, { cors: { origin: '*', // Adjust for production security }});io.on('connection', socket => { console.log(`Client connected with ID: ${socket.id}`); // Listen for 'chat message' events from the client socket.on('chat message', msg => { console.log(`Message from ${socket.id}: ${msg}`); // Emit the message to all connected clients (including sender) io.emit('chat message', { user: socket.id, message: msg }); }); // Listen for 'disconnect' event socket.on('disconnect', () => { console.log(`Client disconnected with ID: ${socket.id}`); }); socket.on('error', error => { console.error('Socket.IO error:', error); });});app.get('/', (req, res) => { res.send('Socket.IO Server is Running
');});httpServer.listen(3000, () => { console.log('Socket.IO server listening on port 3000');});
The Scalability Challenge for Real-time Applications
The fundamental challenge with scaling WebSockets lies in their stateful nature. Unlike stateless HTTP requests that can be routed to any available server, a WebSocket connection maintains state between a specific client and a specific server. This
"""
Call the formatter and print the result
formatted_html_content = format_html_code_blocks(html_content)
print(formatted_html_content)

