fix(preview): bound rich-text run walks, fold format notices, match Excel number display

- richTextPrefix visits at most maxCellTextChars + 1 runs. An empty run adds
  no text, so a length check alone walked every run of a shared string for
  every cell referencing it, on every tile.
- Two or more unsupported number format warnings in a tile fold into one
  "N unsupported number formats" entry, and the notice bar has a max-height
  and scrolls.
- General-format and unsupported-format numbers render at 15 significant
  digits, as Excel does (0.1+0.2 shows 0.3).
- TIME_FORMAT accepts a trailing AM/PM, so h:mm AM/PM renders as 2:30 PM
  instead of falling back to a date.
- SPREADSHEET_ASSET_VERSION refreshed.
This commit is contained in:
Aamer Akhter
2026-10-05 09:51:04 -04:00
parent 0ae5ce017a
commit 51b6be3e7a
9 changed files with 142 additions and 11 deletions
+9
View File
@@ -176,6 +176,15 @@ describe('spreadsheet preview renderer', () => {
expect(document.body.textContent).toContain('Spreadsheet parser failed');
});
// The bar sits above the grid in a flex column; unbounded, enough warnings
// pushed the grid out of view.
it('clamps the notice bar height and scrolls its overflow', () => {
const css = readFileSync(resolve(import.meta.dirname, '../src/web/public/styles.css'), 'utf8');
const rule = /\.spreadsheet-preview-notice\s*\{([^}]*)\}/.exec(css)?.[1] || '';
expect(rule).toMatch(/max-height:\s*\d/);
expect(rule).toMatch(/overflow-y:\s*auto/);
});
it('shows an explicit empty-sheet state without dropping workbook warnings', async () => {
const fetchMock = vi.fn(async () => ({ ok: true, arrayBuffer: async () => new ArrayBuffer(8) }));
const renderer = loadRenderer(fetchMock);