luguog commited on
Commit
fcac8fd
·
verified ·
1 Parent(s): f3828fa

Upload index.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.js +219 -171
index.js CHANGED
@@ -10,11 +10,14 @@ const generateBtn = document.getElementById('generate-btn');
10
  const loadingSection = document.getElementById('loading-section');
11
  const progressBar = document.getElementById('progress-bar');
12
  const loadingText = document.getElementById('loading-text');
 
13
  const errorSection = document.getElementById('error-section');
14
  const errorText = document.getElementById('error-text');
 
15
  const outputSection = document.getElementById('output-section');
16
  const generatedCodeElement = document.getElementById('generated-code');
17
  const copyBtn = document.getElementById('copy-btn');
 
18
 
19
  // Application state
20
  let isModelLoaded = false;
@@ -23,238 +26,283 @@ let worker = null;
23
 
24
  // Initialize the application
25
  function init() {
26
- // Create and setup Web Worker
 
 
 
 
 
 
 
27
  worker = new Worker('worker.js', { type: 'module' });
28
-
29
- // Listen for messages from worker
30
- worker.onmessage = handleWorkerMessage;
31
-
32
- // Setup event listeners
33
- generateBtn.addEventListener('click', handleGenerate);
34
- copyBtn.addEventListener('click', handleCopy);
35
- promptInput.addEventListener('keydown', (e) => {
36
- if (e.key === 'Enter' && e.ctrlKey) {
37
- handleGenerate();
38
- }
39
- });
40
-
41
- // Load model on page load
42
- loadModel();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
44
 
45
  // Handle messages from Web Worker
46
  function handleWorkerMessage(event) {
47
- const { type, data } = event.data;
48
-
49
- switch (type) {
50
- case 'progress':
51
- updateProgress(data);
52
- break;
53
- case 'modelLoaded':
54
- onModelLoaded();
55
- break;
56
- case 'generationComplete':
57
- onGenerationComplete(data);
58
- break;
59
- case 'error':
60
- onError(data);
61
- break;
62
- default:
63
- console.warn('Unknown message type from worker:', type);
64
- }
65
  }
66
 
67
  // Load the model
68
  function loadModel() {
69
- loadingSection.style.display = 'block';
70
- loadingText.textContent = 'Initializing model...';
71
-
72
- // Send load command to worker
73
- worker.postMessage({ type: 'loadModel' });
 
74
  }
75
 
76
  // Update progress bar
77
  function updateProgress(progress) {
78
- const percent = Math.round(progress * 100);
79
- progressBar.style.width = `${percent}%`;
80
- loadingText.textContent = `Loading model... ${percent}%`;
 
 
 
 
81
  }
82
 
83
  // Called when model is loaded
84
  function onModelLoaded() {
85
- isModelLoaded = true;
86
- loadingSection.style.display = 'none';
87
- progressBar.style.width = '0%';
88
- generateBtn.disabled = false;
89
- console.log('Model loaded successfully');
 
 
90
  }
91
 
92
  // Handle generate button click
93
  async function handleGenerate() {
94
- const prompt = promptInput.value.trim();
95
-
96
- if (!prompt) {
97
- showError('Please enter a description of what you want to generate.');
98
- return;
99
- }
100
-
101
- if (!isModelLoaded) {
102
- showError('Model is still loading. Please wait...');
103
- return;
104
- }
105
-
106
- if (isGenerating) {
107
- return;
108
- }
109
-
110
- // Clear previous errors and output
111
- hideError();
112
- outputSection.style.display = 'none';
113
-
114
- // Update UI state
115
- isGenerating = true;
116
- generateBtn.disabled = true;
117
- generateBtn.querySelector('.btn-text').textContent = 'Generating...';
118
- generateBtn.querySelector('.btn-spinner').style.display = 'block';
119
-
120
- // Prepare the prompt with language context
121
- const language = languageSelect.value;
122
- const enhancedPrompt = `Generate ${language} code: ${prompt}\n\n\`\`\`${language}\n`;
123
-
124
- // Send generation request to worker
125
- worker.postMessage({
126
- type: 'generate',
127
- data: { prompt: enhancedPrompt, language }
128
- });
129
  }
130
 
131
  // Called when generation is complete
132
  function onGenerationComplete(result) {
133
- const { generatedText, language } = result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
- // Extract code between code fences if present
136
- let code = generatedText;
137
- const codeFenceMatch = generatedText.match(/```(?:\w+)?\n([\s\S]*?)```/);
138
- if (codeFenceMatch) {
139
- code = codeFenceMatch[1];
140
- } else {
141
- // If no code fences, try to extract code after the prompt
142
- const promptEnd = `Generate ${language} code:`;
143
- const promptIndex = generatedText.indexOf(promptEnd);
144
- if (promptIndex !== -1) {
145
- code = generatedText.substring(promptIndex + promptEnd.length).trim();
146
- // Remove any trailing text after code
147
- const lines = code.split('\n');
148
- const codeLines = [];
149
- for (let line of lines) {
150
- if (line.trim().startsWith('//') || line.trim().startsWith('#') || line.trim().startsWith('--')) {
151
- codeLines.push(line);
152
- } else if (line.trim() && !line.includes('Here is') && !line.includes('This code')) {
153
- codeLines.push(line);
154
- } else if (line.trim() === '') {
155
- codeLines.push(line);
156
- } else {
157
- break;
158
- }
159
- }
160
- code = codeLines.join('\n');
161
- }
162
- }
163
 
164
- // Clean up the code
165
- code = code.trim();
 
166
 
167
- // Update the UI
168
- displayGeneratedCode(code, language);
 
 
 
 
 
 
169
 
170
- // Reset UI state
171
- resetUIState();
 
 
172
  }
173
 
174
  // Display generated code with syntax highlighting
175
  function displayGeneratedCode(code, language) {
176
- // Set the code content
177
- generatedCodeElement.textContent = code;
178
-
179
- // Update language class
180
- generatedCodeElement.className = `language-${getPrismLanguage(language)}`;
181
-
182
- // Highlight the code
 
183
  Prism.highlightElement(generatedCodeElement);
184
-
185
- // Show output section
186
- outputSection.style.display = 'block';
187
-
188
- // Scroll to output
 
 
189
  outputSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
 
190
  }
191
 
192
  // Get Prism.js language identifier
193
  function getPrismLanguage(language) {
194
- const languageMap = {
195
- 'javascript': 'javascript',
196
- 'python': 'python',
197
- 'html': 'markup',
198
- 'react': 'jsx',
199
- 'sql': 'sql',
200
- 'bash': 'bash',
201
- 'other': 'javascript'
202
- };
203
- return languageMap[language] || 'javascript';
204
  }
205
 
206
  // Handle copy button click
207
  async function handleCopy() {
208
- const code = generatedCodeElement.textContent;
209
-
210
- try {
211
- await navigator.clipboard.writeText(code);
212
- const originalText = copyBtn.textContent;
213
- copyBtn.textContent = 'Copied!';
214
- copyBtn.style.backgroundColor = 'var(--accent-success)';
215
-
216
- setTimeout(() => {
217
- copyBtn.textContent = originalText;
218
- copyBtn.style.backgroundColor = '';
219
- }, 2000);
220
- } catch (err) {
221
- console.error('Failed to copy code:', err);
222
- showError('Failed to copy code to clipboard');
223
- }
224
  }
225
 
226
  // Show error message
227
  function showError(message) {
228
- errorText.textContent = message;
229
- errorSection.style.display = 'block';
230
-
231
- // Auto-hide after 5 seconds
232
- setTimeout(hideError, 5000);
233
  }
234
 
235
  // Hide error message
236
  function hideError() {
237
- errorSection.style.display = 'none';
238
  }
239
 
240
  // Reset UI state after generation
241
  function resetUIState() {
242
- isGenerating = false;
243
- generateBtn.disabled = false;
244
- generateBtn.querySelector('.btn-text').textContent = 'Generate Code';
245
- generateBtn.querySelector('.btn-spinner').style.display = 'none';
246
  }
247
 
248
  // Handle errors from worker
249
  function onError(error) {
250
- console.error('Worker error:', error);
251
- showError(`An error occurred: ${error.message || 'Unknown error'}`);
252
- resetUIState();
253
  }
254
 
255
  // Initialize the app when DOM is ready
256
  if (document.readyState === 'loading') {
257
- document.addEventListener('DOMContentLoaded', init);
258
  } else {
259
- init();
260
- }
 
 
 
 
 
 
 
 
10
  const loadingSection = document.getElementById('loading-section');
11
  const progressBar = document.getElementById('progress-bar');
12
  const loadingText = document.getElementById('loading-text');
13
+ const loadingSubtext = document.getElementById('loading-subtext');
14
  const errorSection = document.getElementById('error-section');
15
  const errorText = document.getElementById('error-text');
16
+ const dismissErrorBtn = document.getElementById('dismiss-error');
17
  const outputSection = document.getElementById('output-section');
18
  const generatedCodeElement = document.getElementById('generated-code');
19
  const copyBtn = document.getElementById('copy-btn');
20
+ const modelInfo = document.getElementById('model-info');
21
 
22
  // Application state
23
  let isModelLoaded = false;
 
26
 
27
  // Initialize the application
28
  function init() {
29
+ // Check for HTTPS requirement
30
+ if (window.location.protocol === 'http:' && window.location.hostname !== 'localhost') {
31
+ showError('This application requires HTTPS for full functionality. Please use a secure connection.');
32
+ return;
33
+ }
34
+
35
+ // Create and setup Web Worker
36
+ try {
37
  worker = new Worker('worker.js', { type: 'module' });
38
+ } catch (error) {
39
+ console.error('Failed to create worker:', error);
40
+ showError('Failed to initialize worker. Please ensure the site is served over HTTP/HTTPS (not file://).');
41
+ return;
42
+ }
43
+
44
+ // Listen for messages from worker
45
+ worker.onmessage = handleWorkerMessage;
46
+ worker.onerror = (error) => {
47
+ console.error('Worker error:', error);
48
+ showError(`Worker error: ${error.message || 'Unknown error'}. Check console for details.`);
49
+ };
50
+
51
+ // Setup event listeners
52
+ generateBtn.addEventListener('click', handleGenerate);
53
+ copyBtn.addEventListener('click', handleCopy);
54
+ dismissErrorBtn.addEventListener('click', hideError);
55
+
56
+ promptInput.addEventListener('keydown', (e) => {
57
+ if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
58
+ e.preventDefault();
59
+ handleGenerate();
60
+ }
61
+ });
62
+
63
+ // Show model info
64
+ modelInfo.style.display = 'block';
65
+
66
+ // Load model on page load
67
+ loadModel();
68
  }
69
 
70
  // Handle messages from Web Worker
71
  function handleWorkerMessage(event) {
72
+ const { type, data } = event.data;
73
+
74
+ switch (type) {
75
+ case 'progress':
76
+ updateProgress(data);
77
+ break;
78
+ case 'modelLoaded':
79
+ onModelLoaded();
80
+ break;
81
+ case 'generationComplete':
82
+ onGenerationComplete(data);
83
+ break;
84
+ case 'error':
85
+ onError(data);
86
+ break;
87
+ default:
88
+ console.warn('Unknown message type from worker:', type);
89
+ }
90
  }
91
 
92
  // Load the model
93
  function loadModel() {
94
+ loadingSection.style.display = 'block';
95
+ loadingText.textContent = 'Initializing model...';
96
+ loadingSubtext.textContent = 'This may take several minutes on first load';
97
+
98
+ // Send load command to worker
99
+ worker.postMessage({ type: 'loadModel' });
100
  }
101
 
102
  // Update progress bar
103
  function updateProgress(progress) {
104
+ const percent = Math.round(progress * 100);
105
+ progressBar.style.width = `${percent}%`;
106
+ loadingText.textContent = `Loading model... ${percent}%`;
107
+
108
+ if (percent > 50) {
109
+ loadingSubtext.textContent = 'Almost there...';
110
+ }
111
  }
112
 
113
  // Called when model is loaded
114
  function onModelLoaded() {
115
+ isModelLoaded = true;
116
+ loadingSection.style.display = 'none';
117
+ progressBar.style.width = '0%';
118
+ generateBtn.disabled = false;
119
+ generateBtn.querySelector('.btn-text').textContent = 'Generate Code';
120
+ modelInfo.style.display = 'none';
121
+ console.log('Model loaded successfully');
122
  }
123
 
124
  // Handle generate button click
125
  async function handleGenerate() {
126
+ const prompt = promptInput.value.trim();
127
+
128
+ if (!prompt) {
129
+ showError('Please enter a description of what you want to generate.');
130
+ return;
131
+ }
132
+
133
+ if (!isModelLoaded) {
134
+ showError('Model is still loading. Please wait...');
135
+ return;
136
+ }
137
+
138
+ if (isGenerating) {
139
+ return;
140
+ }
141
+
142
+ // Clear previous errors and output
143
+ hideError();
144
+ outputSection.style.display = 'none';
145
+
146
+ // Update UI state
147
+ isGenerating = true;
148
+ generateBtn.disabled = true;
149
+ generateBtn.querySelector('.btn-text').textContent = 'Generating...';
150
+ generateBtn.querySelector('.btn-spinner').style.display = 'block';
151
+
152
+ // Prepare the prompt with language context
153
+ const language = languageSelect.value;
154
+ const enhancedPrompt = `Generate ${language} code: ${prompt}\n\n\`\`\`${language}\n`;
155
+
156
+ // Send generation request to worker
157
+ worker.postMessage({
158
+ type: 'generate',
159
+ data: { prompt: enhancedPrompt, language }
160
+ });
161
  }
162
 
163
  // Called when generation is complete
164
  function onGenerationComplete(result) {
165
+ const { generatedText, language } = result;
166
+
167
+ // Extract code between code fences if present
168
+ let code = extractCodeFromResponse(generatedText, language);
169
+
170
+ // Update the UI
171
+ displayGeneratedCode(code, language);
172
+
173
+ // Reset UI state
174
+ resetUIState();
175
+ }
176
+
177
+ // Extract code from model response
178
+ function extractCodeFromResponse(generatedText, language) {
179
+ // Try to extract code between fences first
180
+ const codeFenceMatch = generatedText.match(/```(?:\w+)?\n([\s\S]*?)```/);
181
+ if (codeFenceMatch) {
182
+ return codeFenceMatch[1].trim();
183
+ }
184
+
185
+ // If no fences, try to extract code after the prompt
186
+ const promptMarker = `Generate ${language} code:`;
187
+ const promptIndex = generatedText.indexOf(promptMarker);
188
+
189
+ if (promptIndex !== -1) {
190
+ let code = generatedText.substring(promptIndex + promptMarker.length).trim();
191
 
192
+ // Remove common prefixes
193
+ code = code.replace(/^(Here is|This is|Below is|Here's)\s+(the\s+)?(code|example|function)/i, '').trim();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
 
195
+ // Clean up trailing text
196
+ const lines = code.split('\n');
197
+ const codeLines = [];
198
 
199
+ for (let line of lines) {
200
+ const trimmed = line.trim();
201
+ // Stop at common explanation markers
202
+ if (trimmed.match(/^(Here is|This code|Explanation:|Note:|The code|This function)/i)) {
203
+ break;
204
+ }
205
+ codeLines.push(line);
206
+ }
207
 
208
+ return codeLines.join('\n').trim();
209
+ }
210
+
211
+ return generatedText.trim();
212
  }
213
 
214
  // Display generated code with syntax highlighting
215
  function displayGeneratedCode(code, language) {
216
+ // Set the code content
217
+ generatedCodeElement.textContent = code;
218
+
219
+ // Update language class
220
+ generatedCodeElement.className = `language-${getPrismLanguage(language)}`;
221
+
222
+ // Highlight the code
223
+ if (typeof Prism !== 'undefined') {
224
  Prism.highlightElement(generatedCodeElement);
225
+ }
226
+
227
+ // Show output section
228
+ outputSection.style.display = 'block';
229
+
230
+ // Scroll to output
231
+ setTimeout(() => {
232
  outputSection.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
233
+ }, 100);
234
  }
235
 
236
  // Get Prism.js language identifier
237
  function getPrismLanguage(language) {
238
+ const languageMap = {
239
+ 'javascript': 'javascript',
240
+ 'python': 'python',
241
+ 'html': 'markup',
242
+ 'react': 'jsx',
243
+ 'sql': 'sql',
244
+ 'bash': 'bash',
245
+ 'other': 'javascript'
246
+ };
247
+ return languageMap[language] || 'javascript';
248
  }
249
 
250
  // Handle copy button click
251
  async function handleCopy() {
252
+ const code = generatedCodeElement.textContent;
253
+
254
+ try {
255
+ await navigator.clipboard.writeText(code);
256
+ const originalText = copyBtn.textContent;
257
+ copyBtn.textContent = 'Copied!';
258
+ copyBtn.style.backgroundColor = 'var(--accent-success)';
259
+
260
+ setTimeout(() => {
261
+ copyBtn.textContent = originalText;
262
+ copyBtn.style.backgroundColor = '';
263
+ }, 2000);
264
+ } catch (err) {
265
+ console.error('Failed to copy code:', err);
266
+ showError('Failed to copy code to clipboard');
267
+ }
268
  }
269
 
270
  // Show error message
271
  function showError(message) {
272
+ errorText.textContent = message;
273
+ errorSection.style.display = 'block';
 
 
 
274
  }
275
 
276
  // Hide error message
277
  function hideError() {
278
+ errorSection.style.display = 'none';
279
  }
280
 
281
  // Reset UI state after generation
282
  function resetUIState() {
283
+ isGenerating = false;
284
+ generateBtn.disabled = false;
285
+ generateBtn.querySelector('.btn-text').textContent = 'Generate Code';
286
+ generateBtn.querySelector('.btn-spinner').style.display = 'none';
287
  }
288
 
289
  // Handle errors from worker
290
  function onError(error) {
291
+ console.error('Worker error:', error);
292
+ showError(`An error occurred: ${error.message || 'Unknown error'}. Please check the console and try again.`);
293
+ resetUIState();
294
  }
295
 
296
  // Initialize the app when DOM is ready
297
  if (document.readyState === 'loading') {
298
+ document.addEventListener('DOMContentLoaded', init);
299
  } else {
300
+ init();
301
+ }
302
+
303
+ // Handle page unload to terminate worker
304
+ window.addEventListener('beforeunload', () => {
305
+ if (worker) {
306
+ worker.terminate();
307
+ }
308
+ });