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] || 'π';
}
|