Repository navigation
Expand file tree
/
Copy pathcontent.js
More file actions
222 lines (189 loc) · 6.59 KB
/
Copy pathcontent.js
File metadata and controls
222 lines (189 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/**
* @fileoverview Main initialization script for Lovable Add-ons Chrome extension.
* This file initializes all features and sets up observers for DOM changes.
*/
(() => {
'use strict';
/**
* Injects UI controls container for additional features
* @returns {void}
*/
function injectUIControls() {
const existingControls = document.querySelector('.lovable-controls');
if (existingControls) return;
const controlsContainer = document.createElement('div');
controlsContainer.className = 'lovable-controls';
controlsContainer.setAttribute('aria-label', 'Chat controls');
const targetElement = document.querySelector('nav');
if (targetElement) {
targetElement.appendChild(controlsContainer);
}
}
/**
* Initializes all extension features
* @returns {void}
*/
function initializeExtension() {
// Make sure LovableAddons namespace exists
if (!window.LovableAddons) {
console.error('LovableAddons namespace not found. Make sure namespace.js is loaded first.');
return;
}
// Initialize theme detection first
if (LovableAddons.utils && LovableAddons.utils.dom &&
typeof LovableAddons.utils.dom.applyTheme === 'function') {
LovableAddons.utils.dom.applyTheme();
}
// Check if UI should be injected
if (LovableAddons.utils.dom.shouldInjectUI()) {
injectUIControls();
}
// Initialize all features
try {
// Add enhance prompt button
if (LovableAddons.features.enhancePrompt && typeof LovableAddons.features.enhancePrompt.addButton === 'function') {
LovableAddons.features.enhancePrompt.addButton();
}
// Add SEO tools button
if (LovableAddons.features.seoTools && typeof LovableAddons.features.seoTools.addButton === 'function') {
LovableAddons.features.seoTools.addButton();
}
// Add prompt library button
if (LovableAddons.features.promptLibrary && typeof LovableAddons.features.promptLibrary.addButton === 'function') {
LovableAddons.features.promptLibrary.addButton();
}
// Initialize Prompt Queue feature (adds queue UI and button state machine)
if (LovableAddons.getFeature && LovableAddons.getFeature('promptQueue')) {
const promptQueue = LovableAddons.getFeature('promptQueue');
if (typeof promptQueue.init === 'function') {
promptQueue.init();
}
}
} catch (error) {
console.error('Error initializing Lovable Add-ons features:', error);
}
}
/**
* Sets up mutation observer to detect DOM changes
* @returns {MutationObserver} The mutation observer instance
*/
function setupMutationObserver() {
// Disconnect existing observer if it exists
if (window._lovableObserver) {
window._lovableObserver.disconnect();
}
// Create new observer
const observer = new MutationObserver((mutations) => {
// Check if UI should be injected
if (LovableAddons && LovableAddons.utils && LovableAddons.utils.dom &&
typeof LovableAddons.utils.dom.shouldInjectUI === 'function' &&
LovableAddons.utils.dom.shouldInjectUI()) {
injectUIControls();
}
// Re-initialize features on significant DOM changes
const significantChanges = mutations.some(mutation =>
mutation.type === 'childList' &&
(mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0)
);
if (significantChanges) {
initializeExtension();
}
});
// Start observing
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: false
});
// Store observer reference
window._lovableObserver = observer;
return observer;
}
/**
* Sets up theme detection and observation
* @returns {void}
*/
function setupThemeDetection() {
// Apply theme initially
if (LovableAddons && LovableAddons.utils && LovableAddons.utils.dom &&
typeof LovableAddons.utils.dom.applyTheme === 'function') {
LovableAddons.utils.dom.applyTheme();
}
// Set up theme change detection
const themeObserver = new MutationObserver(() => {
if (LovableAddons && LovableAddons.utils && LovableAddons.utils.dom &&
typeof LovableAddons.utils.dom.applyTheme === 'function') {
LovableAddons.utils.dom.applyTheme();
}
});
// Observe document and body for class and attribute changes
themeObserver.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class', 'data-theme', 'style']
});
themeObserver.observe(document.body, {
attributes: true,
attributeFilter: ['class', 'data-theme', 'style']
});
// Store observer reference
window._lovableThemeObserver = themeObserver;
// Also listen for system theme changes
if (window.matchMedia) {
const colorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
colorSchemeQuery.addEventListener('change', () => {
if (LovableAddons && LovableAddons.utils && LovableAddons.utils.dom &&
typeof LovableAddons.utils.dom.applyTheme === 'function') {
LovableAddons.utils.dom.applyTheme();
}
});
}
}
/**
* Prevents unwanted scrollbars on the page
* @returns {void}
*/
function preventScrollbars() {
// Add a style element to prevent scrollbars
const styleElement = document.createElement('style');
styleElement.id = 'lovable-scrollbar-fix';
styleElement.textContent = `
body {
overflow-x: hidden !important;
}
#root, main, .app-container, #__next, .flex.flex-col.min-h-screen, .flex.min-h-screen.flex-col {
overflow-x: hidden !important;
max-width: 100vw !important;
box-sizing: border-box !important;
}
/* Ensure no element causes horizontal overflow */
* {
max-width: 100vw;
}
`;
document.head.appendChild(styleElement);
}
/**
* Main initialization function
* @returns {void}
*/
function main() {
// Prevent scrollbars first
preventScrollbars();
// Initialize extension
initializeExtension();
// Set up mutation observer
setupMutationObserver();
// Set up theme detection
setupThemeDetection();
// Listen for navigation events
window.addEventListener('popstate', initializeExtension);
window.addEventListener('pushstate', initializeExtension);
window.addEventListener('replacestate', initializeExtension);
}
// Run main function when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', main);
} else {
main();
}
})();