Veroeffentlichung ueber Gitea, BOM-Toleranz, Tests fuer den YAML-Leser

Das Repo ist jetzt oeffentlich, die Pakete haengen an der Veroeffentlichung
`latest`. Damit funktioniert `abdulive update` ohne Token.

- config.example.yaml traegt die gepruefte Update-Adresse
- .gitea/workflows/release.yml baut beim Tag und ersetzt `latest`
- Byte Order Mark: Notepad und `Set-Content -Encoding utf8` schreiben eines,
  und ohne Behandlung hiess der erste Schluessel in der config.yaml
  "\ufeffchannel" - die Einstellung waere stillschweigend ignoriert worden
- Der YAML-Leser hatte gar keine Tests; er liest die Konfiguration, an der
  alles haengt. Jetzt acht.

Der Updater ist einmal komplett durchgelaufen: 0.4.0 erkannt, 119 MB geladen,
Pruefsumme geprueft, bereitgelegt, von launcher.ps1 getauscht.

93 Tests, Typpruefung sauber.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AhVSfMFdWnXKCv5JfLnArZ
This commit is contained in:
ZeasyAlexandClaude Opus 5 committed 2026-09-09 17:43:43 +02:00
1 parent 5f6301268a
commit 08f7c21450
8 files changed
+165 -33

No files matched your search

+55
View File
@@ -0,0 +1,55 @@
// Der YAML-Leser ist selbst geschrieben (ADR-0001: keine Abhaengigkeiten) und
// liest die Konfiguration, an der alles haengt - hatte aber bis hierher keinen
// einzigen Test. Geprueft wird genau der Sprachumfang, den config/*.yaml
// benutzt.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { parseYaml } from './yaml.ts';
test('verschachtelte Maps ueber Einrueckung', () => {
assert.deepEqual(parseYaml('channel:\n login: abdulive_\n language: de\n'),
{ channel: { login: 'abdulive_', language: 'de' } });
});
test('erkennt Zahlen, Wahrheitswerte und Leeres', () => {
const y = parseYaml([
'a: 42', 'b: -7', 'c: 3.5', 'd: true', 'e: false', 'f:', 'g: ~',
].join('\n'));
assert.deepEqual(y, { a: 42, b: -7, c: 3.5, d: true, e: false, f: null, g: null });
});
test('Anfuehrungszeichen bleiben Text', () => {
// Wichtig fuer update.url - sonst wuerde aus "0.5" eine Zahl
const y = parseYaml('update:\n url: "https://git.zeasy.dev/x"\n v: "0.5"\n');
assert.deepEqual(y, { update: { url: 'https://git.zeasy.dev/x', v: '0.5' } });
});
test('Inline-Maps, wie sie im Layout stehen', () => {
const y = parseYaml('crop: { x: 0, y: 0, w: 480, h: 270 }\n');
assert.deepEqual(y, { crop: { x: 0, y: 0, w: 480, h: 270 } });
});
test('Listen aus Skalaren', () => {
const y = parseYaml('chapterScenes: [Gameplay, "Just Chatting"]\n');
assert.deepEqual(y, { chapterScenes: ['Gameplay', 'Just Chatting'] });
});
test('Kommentare und Leerzeilen stoeren nicht', () => {
const y = parseYaml('# Kopfzeile\n\nobs:\n # dazwischen\n url: ws://127.0.0.1:4455\n');
assert.deepEqual(y, { obs: { url: 'ws://127.0.0.1:4455' } });
});
test('Zeilenenden nach Windows-Art', () => {
// config.yaml wird auf dem Stream-PC bearbeitet
assert.deepEqual(parseYaml('a:\r\n b: 1\r\n'), { a: { b: 1 } });
});
test('ein Byte Order Mark verstellt nicht den ersten Schluessel', () => {
// Notepad und `Set-Content -Encoding utf8` unter Windows PowerShell 5.1
// schreiben eines. Ohne Behandlung hiesse der erste Schluessel "channel",
// und die Einstellung wuerde stillschweigend ignoriert - ohne Fehlermeldung.
const y = parseYaml('\uFEFFchannel:\n login: abdulive_\n');
assert.deepEqual(y, { channel: { login: 'abdulive_' } });
assert.ok(!Object.keys(y).some((k) => k.charCodeAt(0) === 0xfeff));
});
+5 -1
View File
@@ -51,7 +51,11 @@ function stripComment(line: string): string {
type Frame = { indent: number; target: YamlMap; listKey?: string };
export function parseYaml(text: string): YamlMap {
const lines = text.split(/\r?\n/);
// Byte Order Mark abschneiden. Notepad und `Set-Content -Encoding utf8`
// unter Windows PowerShell 5.1 schreiben eines an den Dateianfang; ohne
// diese Zeile heisst der erste Schluessel dann "channel" und die
// Einstellung wird stillschweigend ignoriert.
const lines = text.replace(/^/, '').split(/\r?\n/);
const root: YamlMap = {};
const stack: Frame[] = [{ indent: -1, target: root }];
let i = 0;