Skip to content

Commit 5ac33ad

Browse files
author
mcarbonell
committed
fix: CSP violations and module exports in AI tools
1 parent 05f6fe4 commit 5ac33ad

File tree

9 files changed

+130
-44
lines changed

9 files changed

+130
-44
lines changed

extension/shared/gemini-api.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,22 @@ class GeminiAPI {
162162
return { text, image };
163163
}
164164

165+
/**
166+
* Genera contenido con imagen (wrapper para compatibilidad)
167+
* @param {string} prompt - Texto del usuario
168+
* @param {string} imageBase64 - Imagen en base64
169+
* @param {string} mimeType - Tipo MIME de la imagen
170+
* @returns {Promise<Object>} - {success: boolean, text: string, error?: string}
171+
*/
172+
async generateContentWithImage(prompt, imageBase64, mimeType) {
173+
try {
174+
const text = await this.chatWithImage(prompt, imageBase64, mimeType);
175+
return { success: true, text };
176+
} catch (error) {
177+
return { success: false, error: error.message, text: '' };
178+
}
179+
}
180+
165181
/**
166182
* Valida si la API key es correcta
167183
* @returns {Promise<boolean>}
@@ -226,3 +242,20 @@ const ChromeGeminiStorage = {
226242
return !!key;
227243
}
228244
};
245+
246+
// ====================
247+
// EXPORTS
248+
// ====================
249+
250+
// Detect environment and export appropriately
251+
if (typeof module !== 'undefined' && module.exports) {
252+
// Node.js / CommonJS
253+
module.exports = { GeminiAPI, GeminiStorage, ChromeGeminiStorage };
254+
} else {
255+
// ES6 modules (extension)
256+
if (typeof window !== 'undefined') {
257+
window.GeminiAPI = GeminiAPI;
258+
window.GeminiStorage = GeminiStorage;
259+
window.ChromeGeminiStorage = ChromeGeminiStorage;
260+
}
261+
}

extension/tools/ai/ai-meme-generator.html

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,10 @@ <h1>🎭 Generador de Memes con IA</h1>
167167
<p class="subtitle">Crea memes virales automáticamente con IA o añade tu propio texto</p>
168168

169169
<div class="mode-selector">
170-
<button class="mode-btn active" onclick="setMode('ai')">
170+
<button class="mode-btn active" data-mode="ai">
171171
🤖 Texto Automático con IA
172172
</button>
173-
<button class="mode-btn" onclick="setMode('custom')">
173+
<button class="mode-btn" data-mode="custom">
174174
✍️ Texto Personalizado
175175
</button>
176176
</div>
@@ -197,13 +197,14 @@ <h1>🎭 Generador de Memes con IA</h1>
197197
<canvas id="memeCanvas"></canvas>
198198
</div>
199199
<div style="text-align: center;">
200-
<button class="btn" onclick="downloadMeme()">💾 Descargar Meme</button>
201-
<button class="btn" onclick="regenerate()">🔄 Regenerar Texto</button>
202-
<button class="btn" onclick="reset()">🆕 Nueva Imagen</button>
200+
<button class="btn" id="downloadBtn">💾 Descargar Meme</button>
201+
<button class="btn" id="regenerateBtn">🔄 Regenerar Texto</button>
202+
<button class="btn" id="resetBtn">🆕 Nueva Imagen</button>
203203
</div>
204204
</div>
205205
</div>
206206

207-
<script type="module" src="ai-meme-generator.js"></script>
207+
<script src="../../shared/gemini-api.js"></script>
208+
<script src="ai-meme-generator.js"></script>
208209
</body>
209210
</html>

extension/tools/ai/ai-meme-generator.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// AI MEME GENERATOR
33
// ====================
44

5-
import { GeminiAPI } from '../../shared/gemini-api.js';
6-
75
let currentImage = null;
86
let currentMode = 'ai';
97
let memeText = { top: '', bottom: '' };
@@ -14,13 +12,26 @@ let memeText = { top: '', bottom: '' };
1412

1513
document.addEventListener('DOMContentLoaded', () => {
1614
setupUploadArea();
15+
setupEventListeners();
1716
});
1817

18+
function setupEventListeners() {
19+
// Mode buttons
20+
document.querySelectorAll('.mode-btn').forEach(btn => {
21+
btn.addEventListener('click', () => setMode(btn.dataset.mode));
22+
});
23+
24+
// Action buttons
25+
document.getElementById('downloadBtn')?.addEventListener('click', downloadMeme);
26+
document.getElementById('regenerateBtn')?.addEventListener('click', regenerate);
27+
document.getElementById('resetBtn')?.addEventListener('click', reset);
28+
}
29+
1930
// ====================
2031
// MODE SWITCHING
2132
// ====================
2233

23-
window.setMode = function(mode) {
34+
function setMode(mode) {
2435
currentMode = mode;
2536

2637
// Update buttons
@@ -100,7 +111,13 @@ async function generateMemeText(file) {
100111
error.style.display = 'none';
101112

102113
try {
103-
const gemini = new GeminiAPI();
114+
// Get API key
115+
const apiKey = await ChromeGeminiStorage.get();
116+
if (!apiKey) {
117+
throw new Error('No se encontró API key de Gemini. Por favor configúrala en las opciones de la extensión.');
118+
}
119+
120+
const gemini = new GeminiAPI(apiKey);
104121

105122
// Convert image to base64
106123
const base64 = await fileToBase64(file);
@@ -225,21 +242,21 @@ function drawText(ctx, text, x, y) {
225242
// ACTIONS
226243
// ====================
227244

228-
window.regenerate = async function() {
245+
async function regenerate() {
229246
if (currentImage && currentMode === 'ai') {
230247
await generateMemeText(currentImage);
231248
}
232249
};
233250

234-
window.downloadMeme = function() {
251+
function downloadMeme() {
235252
const canvas = document.getElementById('memeCanvas');
236253
const link = document.createElement('a');
237254
link.download = 'meme.png';
238255
link.href = canvas.toDataURL('image/png');
239256
link.click();
240257
};
241258

242-
window.reset = function() {
259+
function reset() {
243260
document.getElementById('memePreview').style.display = 'none';
244261
document.getElementById('error').style.display = 'none';
245262
document.getElementById('fileInput').value = '';

extension/tools/ai/alt-text-generator.html

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,12 @@ <h3>✨ Texto Alternativo Generado</h3>
176176
<span id="charCount">0 caracteres</span>
177177
<span id="wordCount">0 palabras</span>
178178
</div>
179-
<button class="btn" onclick="copyAltText()">📋 Copiar Alt Text</button>
180-
<button class="btn" onclick="reset()">🔄 Nueva Imagen</button>
179+
<button class="btn" id="copyBtn">📋 Copiar Alt Text</button>
180+
<button class="btn" id="resetBtn">🔄 Nueva Imagen</button>
181181
</div>
182182
</div>
183183

184-
<script type="module" src="alt-text-generator.js"></script>
184+
<script src="../../shared/gemini-api.js"></script>
185+
<script src="alt-text-generator.js"></script>
185186
</body>
186187
</html>

extension/tools/ai/alt-text-generator.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// ALT TEXT GENERATOR AI
33
// ====================
44

5-
import { GeminiAPI } from '../../shared/gemini-api.js';
6-
75
let currentImage = null;
86

97
// ====================
@@ -12,8 +10,14 @@ let currentImage = null;
1210

1311
document.addEventListener('DOMContentLoaded', () => {
1412
setupUploadArea();
13+
setupEventListeners();
1514
});
1615

16+
function setupEventListeners() {
17+
document.getElementById('copyBtn')?.addEventListener('click', copyAltText);
18+
document.getElementById('resetBtn')?.addEventListener('click', reset);
19+
}
20+
1721
// ====================
1822
// UPLOAD HANDLING
1923
// ====================
@@ -78,7 +82,13 @@ async function generateAltText(file) {
7882
resultArea.style.display = 'none';
7983

8084
try {
81-
const gemini = new GeminiAPI();
85+
// Get API key
86+
const apiKey = await ChromeGeminiStorage.get();
87+
if (!apiKey) {
88+
throw new Error('No se encontró API key de Gemini. Por favor configúrala en las opciones de la extensión.');
89+
}
90+
91+
const gemini = new GeminiAPI(apiKey);
8292

8393
// Convert image to base64
8494
const base64 = await fileToBase64(file);
@@ -141,7 +151,7 @@ function fileToBase64(file) {
141151
});
142152
}
143153

144-
window.copyAltText = async function() {
154+
async function copyAltText() {
145155
const altText = document.getElementById('altText').value;
146156
try {
147157
await navigator.clipboard.writeText(altText);
@@ -151,7 +161,7 @@ window.copyAltText = async function() {
151161
}
152162
};
153163

154-
window.reset = function() {
164+
function reset() {
155165
document.getElementById('preview').style.display = 'none';
156166
document.getElementById('resultArea').style.display = 'none';
157167
document.getElementById('fileInput').value = '';

extension/tools/ai/audio-transcription.html

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,13 @@ <h3>📝 Transcripción</h3>
195195
<span id="wordCount">0 palabras</span>
196196
<span id="charCount">0 caracteres</span>
197197
</div>
198-
<button class="btn" onclick="copyTranscription()">📋 Copiar Transcripción</button>
199-
<button class="btn" onclick="downloadTranscription()">💾 Descargar TXT</button>
200-
<button class="btn" onclick="reset()">🔄 Nuevo Audio</button>
198+
<button class="btn" id="copyBtn">📋 Copiar Transcripción</button>
199+
<button class="btn" id="downloadBtn">💾 Descargar TXT</button>
200+
<button class="btn" id="resetBtn">🔄 Nuevo Audio</button>
201201
</div>
202202
</div>
203203

204-
<script type="module" src="audio-transcription.js"></script>
204+
<script src="../../shared/gemini-api.js"></script>
205+
<script src="audio-transcription.js"></script>
205206
</body>
206207
</html>

extension/tools/ai/audio-transcription.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// AUDIO TRANSCRIPTION AI
33
// ====================
44

5-
import { GeminiAPI } from '../../shared/gemini-api.js';
6-
75
let currentAudio = null;
86

97
// ====================
@@ -12,8 +10,15 @@ let currentAudio = null;
1210

1311
document.addEventListener('DOMContentLoaded', () => {
1412
setupUploadArea();
13+
setupEventListeners();
1514
});
1615

16+
function setupEventListeners() {
17+
document.getElementById('copyBtn')?.addEventListener('click', copyTranscription);
18+
document.getElementById('downloadBtn')?.addEventListener('click', downloadTranscription);
19+
document.getElementById('resetBtn')?.addEventListener('click', reset);
20+
}
21+
1722
// ====================
1823
// UPLOAD HANDLING
1924
// ====================
@@ -147,7 +152,7 @@ function updateStats(text) {
147152
// ACTIONS
148153
// ====================
149154

150-
window.copyTranscription = async function() {
155+
async function copyTranscription() {
151156
const text = document.getElementById('transcription').value;
152157
try {
153158
await navigator.clipboard.writeText(text);
@@ -157,7 +162,7 @@ window.copyTranscription = async function() {
157162
}
158163
};
159164

160-
window.downloadTranscription = function() {
165+
function downloadTranscription() {
161166
const text = document.getElementById('transcription').value;
162167
const blob = new Blob([text], { type: 'text/plain' });
163168
const url = URL.createObjectURL(blob);
@@ -168,7 +173,7 @@ window.downloadTranscription = function() {
168173
URL.revokeObjectURL(url);
169174
};
170175

171-
window.reset = function() {
176+
function reset() {
172177
document.getElementById('audioPlayer').style.display = 'none';
173178
document.getElementById('resultArea').style.display = 'none';
174179
document.getElementById('error').style.display = 'none';

extension/tools/ai/image-to-text-ocr.html

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,19 +196,20 @@ <h3>🖼️ Imagen Original</h3>
196196
<div class="result-section">
197197
<h3>📄 Texto Extraído</h3>
198198
<div class="format-selector">
199-
<button class="format-btn active" data-format="plain" onclick="changeFormat('plain')">Texto Plano</button>
200-
<button class="format-btn" data-format="markdown" onclick="changeFormat('markdown')">Markdown</button>
201-
<button class="format-btn" data-format="json" onclick="changeFormat('json')">JSON</button>
199+
<button class="format-btn active" data-format="plain">Texto Plano</button>
200+
<button class="format-btn" data-format="markdown">Markdown</button>
201+
<button class="format-btn" data-format="json">JSON</button>
202202
</div>
203203
<textarea id="extractedText" placeholder="El texto extraído aparecerá aquí..."></textarea>
204204
<div class="stats" id="stats"></div>
205-
<button class="btn" onclick="copyText()">📋 Copiar Texto</button>
206-
<button class="btn" onclick="downloadText()">💾 Descargar</button>
207-
<button class="btn" onclick="reset()">🔄 Nueva Imagen</button>
205+
<button class="btn" id="copyBtn">📋 Copiar Texto</button>
206+
<button class="btn" id="downloadBtn">💾 Descargar</button>
207+
<button class="btn" id="resetBtn">🔄 Nueva Imagen</button>
208208
</div>
209209
</div>
210210
</div>
211211

212-
<script type="module" src="image-to-text-ocr.js"></script>
212+
<script src="../../shared/gemini-api.js"></script>
213+
<script src="image-to-text-ocr.js"></script>
213214
</body>
214215
</html>

0 commit comments

Comments
 (0)