YAML: robustere Auto-Fix Einrückung mit Einheits-Erkennung
This commit is contained in:
@@ -122,45 +122,29 @@ function collectPaths(data, path='root', paths=[]) {
|
|||||||
|
|
||||||
// ── YAML Auto-Fix: normalisiert Einrückung bevor js-yaml parst ───────────────
|
// ── YAML Auto-Fix: normalisiert Einrückung bevor js-yaml parst ───────────────
|
||||||
function fixYamlIndentation(text) {
|
function fixYamlIndentation(text) {
|
||||||
// Normalisiert Tabs → Spaces, erkennt Einrückungs-Inkonsistenz
|
|
||||||
// Strategie: Einrückung auf Basis des ersten vorkommenden Levels normalisieren
|
|
||||||
const lines = text.split('\n');
|
const lines = text.split('\n');
|
||||||
const fixed = [];
|
|
||||||
|
// 1. Tabs → Spaces (4 oder 2)
|
||||||
for (const line of lines) {
|
const detabbed = lines.map(l => l.replace(/\t/g, ' '));
|
||||||
// Tabs zu 2 Spaces
|
|
||||||
const noTabs = line.replace(/\t/g, ' ');
|
// 2. Finde die kleinste vorkommende Einrückung > 0 (das ist die Einheit)
|
||||||
fixed.push(noTabs);
|
const indents = detabbed
|
||||||
}
|
.filter(l => l.trim() && !l.trim().startsWith('#'))
|
||||||
|
.map(l => l.search(/\S/))
|
||||||
// Normalisiere die Einrückungslevel auf gerade 2-Vielfache
|
.filter(n => n > 0);
|
||||||
const result = [];
|
const unit = indents.length ? Math.min(...indents) : 2;
|
||||||
const indentStack = [0]; // Stack der gültigen Einrück-Level
|
|
||||||
|
// 3. Remap: jede Einrückung → Niveau * 2 Spaces
|
||||||
for (const line of fixed) {
|
const remapped = detabbed.map(line => {
|
||||||
if (!line.trim()) { result.push(''); continue; }
|
if (!line.trim()) return '';
|
||||||
if (line.trim().startsWith('#')) { result.push(line); continue; }
|
if (line.trim().startsWith('#')) return line.trimEnd();
|
||||||
|
const spaces = line.search(/\S/);
|
||||||
const current = line.search(/\S/);
|
if (spaces <= 0) return line.trimEnd();
|
||||||
const content = line.trimStart();
|
const level = Math.round(spaces / unit);
|
||||||
|
return ' '.repeat(level) + line.trimStart().trimEnd();
|
||||||
// Finde den nächsten passenden Level im Stack
|
});
|
||||||
let level = indentStack.length - 1;
|
|
||||||
while (level > 0 && indentStack[level] > current) level--;
|
return remapped.join('\n');
|
||||||
|
|
||||||
if (current > indentStack[level]) {
|
|
||||||
// Neue Einrückungstiefe
|
|
||||||
indentStack.splice(level + 1); // alles nach level entfernen
|
|
||||||
indentStack.push(current);
|
|
||||||
level = indentStack.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize: depth * 2 spaces
|
|
||||||
const normalizedIndent = ' '.repeat(level);
|
|
||||||
result.push(normalizedIndent + content);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.join('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── YAML Tool ─────────────────────────────────────────────────────────────────
|
// ── YAML Tool ─────────────────────────────────────────────────────────────────
|
||||||
@@ -177,29 +161,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; }
|
||||||
|
|
||||||
// Erste Versuch: direkt parsen
|
let obj, parseError = null;
|
||||||
try {
|
|
||||||
const obj = jsyaml.load(text);
|
// Versuch 1: direkt parsen
|
||||||
setParsed(obj);
|
try { obj = jsyaml.load(text); }
|
||||||
setFormatted(jsyaml.dump(obj, { indent:2, lineWidth:-1, noRefs:true }));
|
catch(e) { parseError = e; }
|
||||||
setError(''); setWarning('');
|
|
||||||
setCollapsed(new Set());
|
// Versuch 2: wenn Fehler → Auto-Fix, dann nochmal
|
||||||
return;
|
if (parseError) {
|
||||||
} catch(e) {
|
|
||||||
// Zweiter Versuch: Auto-Fix und dann parsen
|
|
||||||
try {
|
try {
|
||||||
const fixed = fixYamlIndentation(text);
|
const fixed = fixYamlIndentation(text);
|
||||||
const obj = jsyaml.load(fixed);
|
obj = jsyaml.load(fixed);
|
||||||
setParsed(obj);
|
setWarning(`⚠ Einrückung automatisch korrigiert: ${parseError.message.split('\n')[0]}`);
|
||||||
setFormatted(jsyaml.dump(obj, { indent:2, lineWidth:-1, noRefs:true }));
|
|
||||||
setWarning(`⚠ Einrückung automatisch korrigiert: ${e.message.split('\n')[0]}`);
|
|
||||||
setError('');
|
|
||||||
setCollapsed(new Set());
|
|
||||||
} catch(e2) {
|
} catch(e2) {
|
||||||
setError(e.message);
|
// Fix hat auch nicht geholfen – originalen Fehler zeigen
|
||||||
|
setError(parseError.message);
|
||||||
setWarning('');
|
setWarning('');
|
||||||
setParsed(null); setFormatted('');
|
setParsed(null); setFormatted('');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
setWarning('');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setParsed(obj);
|
||||||
|
setFormatted(jsyaml.dump(obj, { indent:2, lineWidth:-1, noRefs:true }));
|
||||||
|
setError('');
|
||||||
|
setCollapsed(new Set());
|
||||||
|
} catch(e) {
|
||||||
|
setError(e.message);
|
||||||
|
setParsed(null); setFormatted('');
|
||||||
}
|
}
|
||||||
},[]);
|
},[]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user