File size: 2,439 Bytes
4386567
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/* File Parser β€” Extracts files from model response */

export function parseFiles(responseText) {
  if (!responseText) return [];
  const files = [];
  const re = /```(\w+)?\s*\n([\s\S]*?)```/g;
  let m, idx = 0;
  while ((m = re.exec(responseText)) !== null) {
    const lang = (m[1] || '').toLowerCase();
    const code = m[2];
    const filename = detectFilename(code, lang, idx);
    files.push({ id: `file-${idx}`, path: filename, content: code, language: lang || detectLang(code) });
    idx++;
  }
  if (files.length === 0 && responseText.trim()) {
    files.push({ id: 'file-0', path: 'index.html', content: responseText, language: 'html' });
  }
  return files;
}

function detectFilename(code, lang, idx) {
  // Check for filename comments
  const fnMatch = code.match(/^\/\/\s*([\w/.-]+\.\w+)/m) || code.match(/^<!--\s*([\w/.-]+\.\w+)/m) || code.match(/^\/\*\s*([\w/.-]+\.\w+)/m);
  if (fnMatch) return fnMatch[1];
  const extMap = { html: 'index.html', markup: 'index.html', css: 'styles.css', javascript: 'script.js', js: 'script.js', typescript: 'index.ts', tsx: 'page.tsx', jsx: 'App.jsx', python: 'main.py', json: 'package.json', vue: 'App.vue' };
  if (idx === 0 && /<!doctype|<html/i.test(code)) return 'index.html';
  return extMap[lang] || `file${idx}.${lang || 'txt'}`;
}

function detectLang(code) {
  const t = code.trim();
  if (/^<!doctype|^<html/i.test(t)) return 'html';
  if (/^import.*from|^export|^const |^function /m.test(t)) return 'javascript';
  if (/^from |^import |^def |^class /m.test(t)) return 'python';
  if (/^\{[\s\S]*\}$/.test(t)) return 'json';
  return 'plaintext';
}

export function buildPreviewHTML(files) {
  const htmlFile = files.find(f => f.language === 'html' || f.path.endsWith('.html'));
  if (htmlFile) return htmlFile.content;
  const cssFile = files.find(f => f.language === 'css');
  const jsFile = files.find(f => f.language === 'javascript' || f.language === 'js');
  if (cssFile || jsFile) {
    return `<!DOCTYPE html><html><head><meta charset="UTF-8"><style>${cssFile?.content || ''}</style></head><body><script>${jsFile?.content || ''}<\/script></body></html>`;
  }
  return null;
}

export function getFileIcon(path) {
  const ext = path.split('.').pop().toLowerCase();
  const icons = { html: '🌐', css: '🎨', js: '⚑', jsx: 'βš›οΈ', tsx: 'βš›οΈ', ts: 'πŸ“˜', py: '🐍', json: 'πŸ“‹', vue: 'πŸ’š', md: 'πŸ“', svg: 'πŸ–ΌοΈ' };
  return icons[ext] || 'πŸ“„';
}