From 457ddad8cc1dfc15ea50869af1deefe830c9dead Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" Date: Sat, 10 Oct 2026 12:17:58 +0200 Subject: [PATCH] fix(app): preserve highlighting within Android span limit Raise the native row cutoff to 51, derived from the five span operations per source token. Cover the boundary and an ordinary TypeScript statement that lost colors at the previous cutoff. Co-authored-by: ThePharmer --- .../src/file-pane/source/native-lines.test.ts | 18 ++++++++++++++---- .../app/src/file-pane/source/native-lines.ts | 8 ++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/packages/app/src/file-pane/source/native-lines.test.ts b/packages/app/src/file-pane/source/native-lines.test.ts index 0e3bdc7265..f9fbb0a36f 100644 --- a/packages/app/src/file-pane/source/native-lines.test.ts +++ b/packages/app/src/file-pane/source/native-lines.test.ts @@ -36,10 +36,10 @@ describe("native source lines", () => { expect(lines.map(lineText).join("\n")).toBe(content); }); it("falls back only for dense rows, without changing text or line numbering", () => { - const dense = JSON.stringify(Array.from({ length: 16 }, (_, i) => i)); + const dense = `${JSON.stringify(Array.from({ length: 25 }, (_, i) => i))} `; const content = `${dense}\n{"ok":true}\n`; const original = highlightCode(content, "data.json"); - expect(original[0]).toHaveLength(33); + expect(original[0]).toHaveLength(52); const lines = buildNativeSourceLines({ content, filename: "data.json", @@ -53,14 +53,24 @@ describe("native source lines", () => { }); it("keeps a row at the span budget highlighted", () => { - const content = `${JSON.stringify(Array.from({ length: 15 }, (_, i) => i))} `; + const content = JSON.stringify(Array.from({ length: 25 }, (_, i) => i)); const original = highlightCode(content, "data.json"); - expect(original[0]).toHaveLength(32); + expect(original[0]).toHaveLength(51); expect( buildNativeSourceLines({ content, filename: "data.json", presentation: "highlighted" }), ).toEqual([{ number: 1, tokens: original[0] }]); }); + it("keeps ordinary TypeScript statements within the span budget highlighted", () => { + const content = + 'const values = [{ id: 0, name: "item0" }, { id: 1, name: "item1" }, { id: 2, name: "item2" }];'; + const original = highlightCode(content, "ordinary.ts"); + expect(original[0]).toHaveLength(50); + expect( + buildNativeSourceLines({ content, filename: "ordinary.ts", presentation: "highlighted" }), + ).toEqual([{ number: 1, tokens: original[0] }]); + }); + it("keeps the plain tier and unknown languages lossless", () => { for (const presentation of ["highlighted", "plain"] as const) { const content = "hello\r\n\nworld\n"; diff --git a/packages/app/src/file-pane/source/native-lines.ts b/packages/app/src/file-pane/source/native-lines.ts index 5c8000910b..c436cebb56 100644 --- a/packages/app/src/file-pane/source/native-lines.ts +++ b/packages/app/src/file-pane/source/native-lines.ts @@ -1,9 +1,9 @@ import { highlightCode, type HighlightToken } from "@getpaseo/highlight"; -// Android gives text spans 256 priority slots. A colored token also inherits -// size, font family and line height and gets a tag span, so leave room for -// those operations instead of mounting an unbounded text tree in one row. -const MAX_HIGHLIGHTED_TOKENS_PER_LINE = 32; +// Android has 256 span-priority slots (indices 0–255). Each colored source +// token produces five operations: color, size, font family, line height and +// tag. 51 tokens use 255 operations; the 52nd exceeds the priority limit. +const MAX_HIGHLIGHTED_TOKENS_PER_LINE = 51; export interface SourceLine { number: number;