YAML: dreistufiger Fix - Unit → Stack → best-effort
This commit is contained in:
@@ -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); };
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user