const BOOL_FIELDS = new Set([ 'isSystemField', 'isRequired', 'isAdmin', 'adminOnly', 'hidden', '_detailPage', '_disableAdd', '_disableDelete' ]); const INT_FIELDS = new Set(['order', 'menuOrder', 'maxRecords', 'maxUploads']); function stripPhpLine(ini) { return ini.replace(/^<\?php.*?\?>\s*\n?/, ''); } function coerceValue(key, value) { if (BOOL_FIELDS.has(key)) return value === '1'; if (INT_FIELDS.has(key)) { const n = parseInt(value, 10); return isNaN(n) ? 0 : n; } return value; } export function parseIniMeta(iniContent) { const clean = stripPhpLine(iniContent); const meta = {}; for (const line of clean.split('\n')) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith(';') || trimmed.startsWith('#')) continue; if (trimmed.startsWith('[')) break; const m = trimmed.match(/^([^\s=]+)\s*=\s*(.*)$/); if (m) { const key = m[1]; const value = m[2].trim().replace(/^"|"$/g, ''); meta[key] = coerceValue(key, value); } } return meta; } export function parseIniSchema(iniContent) { const clean = stripPhpLine(iniContent); const result = {}; const fields = {}; let currentSection = null; for (const line of clean.split('\n')) { const trimmed = line.trim(); if (!trimmed || trimmed.startsWith(';') || trimmed.startsWith('#')) continue; const sectionMatch = trimmed.match(/^\[(.+)\]$/); if (sectionMatch) { currentSection = sectionMatch[1]; fields[currentSection] = {}; continue; } const kvMatch = trimmed.match(/^([^\s=]+)\s*=\s*(.*)$/); if (kvMatch) { const key = kvMatch[1]; const value = kvMatch[2].trim().replace(/^"|"$/g, ''); if (currentSection) { fields[currentSection][key] = coerceValue(key, value); } else { result[key] = coerceValue(key, value); } } } result.fields = fields; return result; }