advanced-live-server-installer
Version:
Auto-installer for Advanced Live Server VS Code Extension
302 lines (260 loc) • 15.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.injectReloadScript = void 0;
function injectReloadScript(htmlContent, showOverlay = true) {
const reloadScript = generateReloadScript(showOverlay);
// Inject the script before the closing </head> tag
if (htmlContent.includes('</head>')) {
return htmlContent.replace('</head>', `${reloadScript}\n</head>`);
}
// If no </head> tag, inject at the beginning
return `${reloadScript}\n${htmlContent}`;
}
exports.injectReloadScript = injectReloadScript;
function generateReloadScript(showOverlay) {
return `
<script>
(function() {
'use strict';
// Advanced Live Server Reload Script
const RELOAD_SCRIPT_ID = 'advanced-live-server-reload';
// Prevent multiple injections
if (document.getElementById(RELOAD_SCRIPT_ID)) {
return;
}
const script = document.createElement('script');
script.id = RELOAD_SCRIPT_ID;
script.innerHTML = \`
(function() {
'use strict';
let ws = null;
let reconnectAttempts = 0;
const maxReconnectAttempts = 5;
const reconnectDelay = 1000;
let pingInterval = null;
// Expose WebSocket status globally for the test app
window.liveServerWebSocket = null;
window.liveServerStatus = 'disconnected';
// Overlay for notifications
let overlay = null;
${showOverlay
? `
function createOverlay() {
if (overlay) return overlay;
overlay = document.createElement('div');
overlay.id = 'advanced-live-server-overlay';
overlay.style.cssText = 'position: fixed; top: 20px; right: 20px; z-index: 999999; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; font-size: 14px; pointer-events: none;';
document.body.appendChild(overlay);
return overlay;
}
function showNotification(message, type, duration) {
duration = duration || 3000;
type = type || 'info';
const overlay = createOverlay();
const notification = document.createElement('div');
const bgColor = type === 'error' ? '#e74c3c' : type === 'success' ? '#27ae60' : '#3498db';
notification.style.cssText = 'background: ' + bgColor + '; color: white; padding: 12px 16px; border-radius: 6px; margin-bottom: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); pointer-events: auto; cursor: pointer; transition: opacity 0.3s ease; max-width: 300px; word-wrap: break-word;';
notification.textContent = message;
notification.addEventListener('click', function() {
notification.style.opacity = '0';
setTimeout(function() { notification.remove(); }, 300);
});
overlay.appendChild(notification);
setTimeout(function() {
if (notification.parentNode) {
notification.style.opacity = '0';
setTimeout(function() { notification.remove(); }, 300);
}
}, duration);
}
`
: `
function showNotification(message, type, duration) {
duration = duration || 3000;
type = type || 'info';
console.log('[' + type.toUpperCase() + '] ' + message);
}
`}
function connectWebSocket() {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsUrl = protocol + '//' + window.location.host;
console.log('🔧 Attempting WebSocket connection to:', wsUrl);
console.log('🔧 Current location:', window.location.href);
try {
ws = new WebSocket(wsUrl);
ws.onopen = function() {
console.log('🔗 Connected to Advanced Live Server');
console.log('🔗 WebSocket readyState:', ws.readyState);
reconnectAttempts = 0;
window.liveServerWebSocket = ws;
window.liveServerStatus = 'connected';
showNotification('Connected to Live Server', 'success', 2000);
// Start ping interval to keep connection alive
pingInterval = setInterval(function() {
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'ping', timestamp: Date.now() }));
}
}, 30000); // Send ping every 30 seconds
};
// --- Live Collaboration Client ---
window.liveCollab = {
ws: null,
docId: null,
userId: null,
state: {},
connect: function(docId, userId) {
this.docId = docId;
this.userId = userId;
if (!ws || ws.readyState !== WebSocket.OPEN) {
showNotification('Collab: Not connected to server', 'error', 3000);
return;
}
// Request current state
ws.send(JSON.stringify({ channel: 'collab', type: 'get-state', docId, userId }));
},
sendEdit: function(content) {
if (!ws || ws.readyState !== WebSocket.OPEN) return;
ws.send(JSON.stringify({ channel: 'collab', type: 'doc-sync', docId: this.docId, userId: this.userId, content }));
},
sendCursor: function(cursor) {
if (!ws || ws.readyState !== WebSocket.OPEN) return;
ws.send(JSON.stringify({ channel: 'collab', type: 'cursor-sync', docId: this.docId, userId: this.userId, cursor }));
},
addComment: function(comment) {
if (!ws || ws.readyState !== WebSocket.OPEN) return;
ws.send(JSON.stringify({ channel: 'collab', type: 'comment-add', docId: this.docId, userId: this.userId, comment }));
},
removeComment: function(comment) {
if (!ws || ws.readyState !== WebSocket.OPEN) return;
ws.send(JSON.stringify({ channel: 'collab', type: 'comment-remove', docId: this.docId, userId: this.userId, comment }));
},
onState: function(cb) { this._onState = cb; },
onEdit: function(cb) { this._onEdit = cb; },
onCursor: function(cb) { this._onCursor = cb; },
onComment: function(cb) { this._onComment = cb; },
};
// Listen for collab messages
function handleCollabMessage(data) {
if (!data || data.channel !== 'collab') return;
if (data.type === 'state' && window.liveCollab._onState) {
window.liveCollab.state = data;
window.liveCollab._onState(data);
} else if (data.type === 'doc-sync' && window.liveCollab._onEdit) {
window.liveCollab._onEdit(data);
} else if (data.type === 'cursor-sync' && window.liveCollab._onCursor) {
window.liveCollab._onCursor(data);
} else if ((data.type === 'comment-add' || data.type === 'comment-remove') && window.liveCollab._onComment) {
window.liveCollab._onComment(data);
}
}
ws.onmessage = function(event) {
try {
const data = JSON.parse(event.data);
// Handle collaboration messages
handleCollabMessage(data);
if (data.type === 'reload') {
console.log('📝 File changed: ' + data.file);
showNotification('Reloading... (' + data.file + ')', 'info', 2000);
// Force immediate reload without URL parameters
setTimeout(function() {
console.log('🔄 Executing reload...');
window.location.reload(true);
}, 100);
}
} catch (error) {
console.error('Failed to parse WebSocket message:', error);
}
};
ws.onclose = function(event) {
console.log('🔌 Disconnected from Advanced Live Server', event.code, event.reason);
window.liveServerWebSocket = null;
window.liveServerStatus = 'disconnected';
// Clear ping interval
if (pingInterval) {
clearInterval(pingInterval);
pingInterval = null;
}
// Don't reconnect if we're about to reload or if it's a normal close
if (window.location.href.includes('reload=true') || window.location.href.includes('_t=')) {
return;
}
if (reconnectAttempts < maxReconnectAttempts) {
reconnectAttempts++;
showNotification('Reconnecting... (attempt ' + reconnectAttempts + ')', 'info', 2000);
setTimeout(function() {
connectWebSocket();
}, reconnectDelay * reconnectAttempts);
} else {
showNotification('Connection lost. Please refresh the page.', 'error', 5000);
}
};
ws.onerror = function(error) {
console.error('WebSocket error:', error);
console.error('WebSocket readyState:', ws.readyState);
};
} catch (error) {
console.error('Failed to connect to WebSocket:', error);
showNotification('Failed to connect to Live Server', 'error', 3000);
}
}
// Connect when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', connectWebSocket);
} else {
connectWebSocket();
}
// Reconnect on page visibility change
document.addEventListener('visibilitychange', function() {
if (!document.hidden && (!ws || ws.readyState !== WebSocket.OPEN)) {
connectWebSocket();
}
});
// Error handling
window.addEventListener('error', function(event) {
showNotification('JavaScript Error: ' + event.message, 'error', 5000);
});
// Add a manual reload function for debugging
window.forceReload = function() {
console.log('🔄 Manual reload triggered');
window.location.reload(true);
};
// Add a test function to check WebSocket status
window.checkWebSocketStatus = function() {
console.log('WebSocket status:', window.liveServerStatus);
console.log('WebSocket object:', window.liveServerWebSocket);
console.log('WebSocket readyState:', ws ? ws.readyState : 'No WebSocket');
return {
status: window.liveServerStatus,
readyState: ws ? ws.readyState : null,
hasWebSocket: !!window.liveServerWebSocket
};
};
// Console log interceptor disabled - was too intrusive
// Uncomment the lines below if you want to see console errors as notifications
/*
const originalLog = console.log;
const originalError = console.error;
const originalWarn = console.warn;
console.log = function() {
originalLog.apply(console, arguments);
if (arguments.length > 0 && typeof arguments[0] === 'string' && arguments[0].includes('error')) {
showNotification(Array.prototype.join.call(arguments, ' '), 'error', 5000);
}
};
console.error = function() {
originalError.apply(console, arguments);
showNotification(Array.prototype.join.call(arguments, ' '), 'error', 5000);
};
console.warn = function() {
originalWarn.apply(console, arguments);
showNotification(Array.prototype.join.call(arguments, ' '), 'info', 3000);
};
*/
})();
\`;
document.head.appendChild(script);
})();
</script>
`;
}
//# sourceMappingURL=reload-script.js.map