Files view: drop the ASCII column from the change-details hex views

- the modal's hex views carried a 16-byte ASCII column per row; file data is
  rarely text and the column halved the room for the two before/after views,
  so it is gone: `hexImageRows` no longer builds an `ascii` field,
  `hexImageHtml` no longer emits it and the `.hex-ascii` CSS rule is removed
- tests: the hex-row test asserts the field is gone (so it cannot come back
  silently); README/README_RUS wording updated
- SW cache simtrace-analyser-v67 (cosmetic, no version bump)
This commit is contained in:
catarrh committed 2026-10-17 21:29:31 +03:00
1 parent 407821ab3d
commit cbb73536f4
5 files changed
+11 -16

No files matched your search

+3 -3
View File
@@ -196,9 +196,9 @@ a row jumps to the APDU in the trace. Rows that carry a recorded change (a
card-side change, or an update that wrote or first observed bytes) also offer
**Details**: a modal showing the affected unit — the whole file, or the single
record that changed — **before and after** the change, as hex views (16 bytes
per row with an ASCII column, never-observed bytes drawn as `--`) with the
bytes that changed highlighted in one colour and the bytes the operation first
observed in another, plus the changed/new byte counts and the APDU reference.
per row, never-observed bytes drawn as `--`) with the bytes that changed
highlighted in one colour and the bytes the operation first observed in
another, plus the changed/new byte counts and the APDU reference.
The images come from `GET /api/sessions/<id>/files/image?key=…&change=…` and
are reconstructed from the current image by undoing the later changes
+3 -3
View File
@@ -201,9 +201,9 @@ Files — это таймлайн файловых операций по все
(изменение со стороны карты либо запись, изменившая или впервые показавшая
байты) есть кнопка **Details**: окно показывает затронутую единицу — файл
целиком или изменившуюся запись — **до и после** изменения в виде hex-вида
(16 байт в строке со столбцом ASCII, никогда не наблюдавшиеся байты — `--`),
причём изменённые байты подсвечены одним цветом, а впервые наблюдаемые —
другим; ниже — счётчики изменённых/новых байт и ссылка на APDU.
(16 байт в строке, никогда не наблюдавшиеся байты — `--`), причём изменённые
байты подсвечены одним цветом, а впервые наблюдаемые — другим; ниже —
счётчики изменённых/новых байт и ссылка на APDU.
Изображения отдаёт `GET /api/sessions/<id>/files/image?key=…&change=…`; они
восстанавливаются из текущего образа отменой более поздних изменений
+2 -7
View File
@@ -204,7 +204,6 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(-
.hex-cell.hex-changed { background: var(--warn); color: #1a1a1a; font-weight: 600; }
.hex-cell.hex-new { background: var(--accent); color: #fff; font-weight: 600; }
.hex-cell.hex-unknown { color: var(--text-muted); }
.hex-ascii { color: var(--text-muted); margin-left: 8px; }
.hex-note { font-size: 12px; color: var(--text-muted); margin-top: 6px; }
.hex-error { font-size: 12px; color: var(--error); }
.map-item { padding: 3px 8px; cursor: pointer; border-radius: 4px; font-size: 13px; color: var(--text); word-break: break-word; }
@@ -2136,22 +2135,18 @@ function hexImageRows(segments, ranges, observed, limit) {
break;
}
const cells = [];
let ascii = '';
for (let i = 0; i < 16; i++) {
const pos = off + i;
const hex = bytes.get(pos);
if (hex === undefined) {
cells.push({hex: '--', cls: 'hex-unknown'});
ascii += ' ';
continue;
}
const cls = covered(ranges, pos) ? 'hex-changed'
: covered(observed, pos) ? 'hex-new' : '';
const value = parseInt(hex, 16);
cells.push({hex: hex, cls: cls});
ascii += (value >= 0x20 && value < 0x7f) ? String.fromCharCode(value) : '.';
}
rows.push({offset: off, cells: cells, ascii: ascii});
rows.push({offset: off, cells: cells});
}
return {rows: rows, truncated: truncated, end: end};
}
@@ -2162,7 +2157,7 @@ function hexImageHtml(image, key) {
const body = view.rows.map(r =>
`<div class="hex-row"><span class="hex-addr">${r.offset.toString(16).toUpperCase().padStart(4, '0')}</span>` +
r.cells.map(c => `<span class="hex-cell ${c.cls}">${c.hex}</span>`).join('') +
`<span class="hex-ascii">${escapeHtml(r.ascii)}</span></div>`
'</div>'
).join('') || `<div class="hex-row hex-unknown">${t('never observed')}</div>`;
return `<div class="hex-view">${body}</div>` +
(view.truncated ? `<div class="hex-note">${t('Showing the first {n} bytes of the image').replace('{n}', 2048)}</div>` : '');
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE = 'simtrace-analyser-v66';
const CACHE = 'simtrace-analyser-v67';
const PRECACHE = [
'index.html',
+2 -2
View File
@@ -313,8 +313,8 @@ test('Files view: the hex image rows mark changed, new and unknown bytes', () =>
assert.deepEqual(cells[2], {hex: '43', cls: 'hex-changed'});
assert.deepEqual(cells[4], {hex: '--', cls: 'hex-unknown'}); // the gap
assert.deepEqual(cells[8], {hex: '65', cls: 'hex-new'});
// ASCII column: printable bytes stay, gaps and the unobserved tail are blank.
assert.equal(view.rows[0].ascii, 'ABCD ef ');
// No ASCII column any more (it wasted the modal's width).
assert.equal(view.rows[0].ascii, undefined);
});
test('Files view: the hex image respects the row limit', () => {