YAML: dreistufiger Fix - Unit → Stack → best-effort

This commit is contained in:
2026-05-30 00:34:36 +02:00
parent e8e1ca9fae
commit f246e1e438

View File

@@ -120,40 +120,49 @@ function collectPaths(data, path='root', paths=[]) {
return paths; return paths;
} }
// ── YAML Auto-Fix: Stack-basierter Strukturerhalter ────────────────────────── // ── YAML Auto-Fix Stufe 1: Einheits-Normalisierung (kleine Fehler) ────────────
function fixYamlIndentation(text) { function fixByUnit(text) {
const lines = text.split('\n').map(l => l.replace(/\t/g, ' '));
const indents = lines
.filter(l => l.trim() && !l.trim().startsWith('#'))
.map(l => l.search(/\S/))
.filter(n => n > 0);
if (!indents.length) return text;
const unit = Math.min(...indents);
if (unit === 2) return lines.join('\n'); // bereits 2-space
return lines.map(line => {
if (!line.trim()) return '';
if (line.trim().startsWith('#')) return line.trimEnd();
const spaces = line.search(/\S/);
if (spaces <= 0) return line.trimEnd();
return ' '.repeat(Math.round(spaces / unit)) + line.trimStart().trimEnd();
}).join('\n');
}
// ── YAML Auto-Fix Stufe 2: Stack-basiert (starke Schäden) ────────────────────
function fixByStack(text) {
const lines = text.split('\n').map(l => l.replace(/\t/g, ' ')); const lines = text.split('\n').map(l => l.replace(/\t/g, ' '));
const stack = [{ indent: -1, depth: -1 }]; const stack = [{ indent: -1, depth: -1 }];
const result = []; const result = [];
for (const line of lines) { for (const line of lines) {
if (!line.trim()) { result.push(''); continue; } if (!line.trim()) { result.push(''); continue; }
const indent = line.search(/\S/); const indent = line.search(/\S/);
const content = line.trim(); const content = line.trim();
if (content.startsWith('#')) { if (content.startsWith('#')) {
result.push(' '.repeat(Math.max(0, stack[stack.length-1].depth + 1)) + content); result.push(' '.repeat(Math.max(0, stack[stack.length-1].depth + 1)) + content);
continue; continue;
} }
while (stack.length > 1 && stack[stack.length-1].indent >= indent) stack.pop();
// Pop stack-Einträge die >= aktuelle Einrückung haben
while (stack.length > 1 && stack[stack.length-1].indent >= indent) {
stack.pop();
}
const depth = stack[stack.length-1].depth + 1; const depth = stack[stack.length-1].depth + 1;
stack.push({ indent, depth }); stack.push({ indent, depth });
result.push(' '.repeat(depth) + content); result.push(' '.repeat(depth) + content);
} }
return result.join('\n'); return result.join('\n');
} }
// Versucht einen lesbaren Fehler aus dem js-yaml Fehler zu bauen
function shortError(e) { function shortError(e) {
const first = e.message.split('\n')[0]; const first = e.message.split('\n')[0];
return first.length > 120 ? first.slice(0,120)+'…' : first; return first.length > 120 ? first.slice(0, 120) + '…' : first;
} }
// ── YAML Tool ───────────────────────────────────────────────────────────────── // ── YAML Tool ─────────────────────────────────────────────────────────────────
@@ -170,40 +179,37 @@ function YamlTool({ mobile }) {
const process = useCallback((text) => { const process = useCallback((text) => {
if (!text.trim()) { setParsed(null); setFormatted(''); setError(''); setWarning(''); return; } if (!text.trim()) { setParsed(null); setFormatted(''); setError(''); setWarning(''); return; }
let obj, parseError = null; const tryParse = (t) => { try { return { obj: jsyaml.load(t), err: null }; } catch(e) { return { obj: null, err: e }; } };
// Versuch 1: direkt parsen // Stufe 1: direkt
try { obj = jsyaml.load(text); } const r1 = tryParse(text);
catch(e) { parseError = e; } if (!r1.err) {
setParsed(r1.obj); setFormatted(jsyaml.dump(r1.obj, {indent:2,lineWidth:-1,noRefs:true}));
// Versuch 2: Auto-Fix, dann nochmal setError(''); setWarning(''); setCollapsed(new Set()); return;
if (parseError) {
const fixed = fixYamlIndentation(text);
try {
obj = jsyaml.load(fixed);
setWarning(`⚠ Einrückung automatisch korrigiert bitte Ergebnis prüfen`);
} catch(e2) {
// Auch nach Fix nicht parsebar → best-effort Text trotzdem anzeigen
setError(shortError(parseError));
setWarning('Struktur zu stark beschädigt nur Einrückung wurde normalisiert. Bitte manuell korrigieren.');
setParsed(null);
setFormatted(fixed); // zeige korrigierten Text zum manuellen Nachbessern
return;
}
} else {
setWarning('');
} }
try { // Stufe 2: Unit-Normalisierung (für kleine Fehler wie 4-space statt 2-space)
setParsed(obj); const fixed1 = fixByUnit(text);
setFormatted(jsyaml.dump(obj, { indent:2, lineWidth:-1, noRefs:true })); const r2 = tryParse(fixed1);
setError(''); if (!r2.err) {
setCollapsed(new Set()); setParsed(r2.obj); setFormatted(jsyaml.dump(r2.obj, {indent:2,lineWidth:-1,noRefs:true}));
} catch(e) { setWarning('✓ Einrückung normalisiert'); setError(''); setCollapsed(new Set()); return;
setError(e.message);
setParsed(null); setFormatted('');
} }
},[]);
// Stufe 3: Stack-Fix (für stärker beschädigte Struktur)
const fixed2 = fixByStack(text);
const r3 = tryParse(fixed2);
if (!r3.err) {
setParsed(r3.obj); setFormatted(jsyaml.dump(r3.obj, {indent:2,lineWidth:-1,noRefs:true}));
setWarning('⚠ Einrückung stark korrigiert bitte Ergebnis prüfen'); setError(''); setCollapsed(new Set()); return;
}
// Stufe 4: best-effort zeige korrigierten Text zum manuellen Nachbessern
setError(shortError(r1.err));
setWarning('Struktur nicht automatisch reparierbar normalisierter Text zum manuellen Korrigieren:');
setParsed(null);
setFormatted(fixed2);
}, []);
const onInput = v => { setInput(v); process(v); }; const onInput = v => { setInput(v); process(v); };