Jak jsem vyvinul binární editor běžící v prohlížeči
Co je binární editor?
Binární editor je nástroj, který umožňuje upravovat soubory přímo v šestnáctkové nebo ASCII podobě. Zatímco běžný textový editor pracuje s „řetězci“, binární editor zpřístupňuje syrové byty, z nichž se soubor skládá, a dovolí vám změnit libovolný bit či byte na zvoleném offsetu.
V analýze softwaru, při obnově dat nebo zkoumání protokolů je nepostradatelný.
Mezi desktopovými aplikacemi jsou známé například HxD
nebo Binary Ninja
.
Tentokrát jsem si ale stanovil jiný cíl – vytvořit binární editor v podobě jediného souboru, který běží pouze v prohlížeči.
Jaký byl plán implementace
- Kompletně klientská aplikace (žádný přenos dat)
- Načítání lokálních souborů pomocí API
FileReader
- Levý sloupec zobrazí šestnáctkové hodnoty (Hex), pravý ASCII
- Kliknutím se přepne do editačního režimu a hodnotu lze okamžitě přepsat
- Upravená místa budou zvýrazněna červeně
- Přepínač mezi režimy HEX a ASCII
- Výsledek půjde znovu stáhnout jako soubor
Kde jsem zakopnul a jak jsem to opravil
1. Posunutý rámeček při editaci
V prvních verzích se žlutý rámeček kolem editované buňky zobrazoval trochu mimo střed.
Mohl za to line-height
a rozložení přes flex
, které posunuly referenční bod mezi textem a rámečkem.
Problém se objevil zejména u monospace fontů – jednotlivé prohlížeče totiž s různými fonty pracují jinak a baseline se liší.
Výsledkem byla buňka vizuálně posunutá nahoru nebo dolů.
Stačilo nastavit vertical-align: middle
a zároveň použít display: inline-block
, aby se výška sjednotila.
.hex-cell.editing {
outline: 2px solid yellow;
vertical-align: middle;
}
2. Klávesa ESC vkládala znaky
V rané implementaci se po stisku ESC v editačním režimu objevovala v buňce třeba dvojice EE
.
Důvodem bylo, že jsme neposlouchali událost keydown
, takže prohlížeč poslal stisknutou klávesu do stejné cesty jako běžný vstup.
Zatímco pro validní vstup jsem počítal jen s 0–9 a A–F, klávesa Escape
má také vlastní kód (keyCode=27
, nově key="Escape"
).
Ten pak logika vyhodnotila jako "E"
a uložila do buňky.
Řešení je jednoduché: v keydown
zachytit Escape
, zrušit výchozí chování a vyvolat zrušení editace.
document.addEventListener("keydown", e => {
if (e.key === "Escape") {
cancelEdit();
e.preventDefault(); // Nepředávat dál do vstupní logiky
}
});
Od té chvíle ESC funguje jen jako „ukončit editaci“ a žádné znaky nepropadne.
3. Červené zvýraznění zůstávalo po opětovném načtení
Po načtení souboru, úpravě a následném načtení jiného souboru zůstávaly červené highlighty z předchozí relace.
Příčina byla prostá – pole či stav, který sledoval změněné buňky, se při načtení nového souboru nevymazal. Zobrazovací část se sice resetovala, ale interní „flag“ zůstal a nový soubor tak převzal staré zvýraznění.
Fix spočíval v tom, že se hned po načtení souboru zavolá clearModifiedState()
a stav se kompletně vynuluje.
4. Přepínání mezi režimy HEX/ASCII
V první verzi šlo editovat Hex i ASCII zároveň, což vedlo k chaosu. Jeden byte totiž najednou ovládaly dva různé vstupy. Pokud jste psali do ASCII, okamžitě se přepsala hexadecimální reprezentace – ale během zadávání vznikaly dočasně neplatné hodnoty.
Abych se vyhnul zmatku, přidal jsem jednoduchý select s režimem editace a výchozí nastavení nechal na HEX. Uživatel tak přesně ví, které pole je „zdroj pravdy“, a synchronizační logika se zpřehlednila.
Kousek kódu
Samotnou zápisovou logiku jsem postavil takto:
function applyEdit(offset, newValue) {
if (mode === "hex") {
buffer[offset] = parseInt(newValue, 16);
} else {
buffer[offset] = newValue.charCodeAt(0);
}
markModified(offset);
render();
}
markModified(offset)
se stará o červené zvýraznění – porovná původní a novou hodnotu a podle výsledku přidá CSS třídu.
Shrnutí
Výsledný binární editor běží offline, je tedy bezpečný a tvoří z něj „čistě klientský“ nástroj.
- Hodí se pro drobné zásahy do binárních souborů
- Pomůže tam, kde není možné instalovat specializovanou aplikaci
- Využijete ho i při výuce, když chcete intuitivně vysvětlit, co znamená „řetězec bytů“
Přesně v těchto situacích se osvědčil.