chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
WebKit paints the diff's highlighting with live ranges again
web/src/lib/highlight.ts+21−5
| @@ -4,6 +4,23 @@ | ||
// page, and a pull's files hold tens of thousands, so each file drawn | ||
// as the reader scrolls cost more than the last. | ||
| ||
/** | ||
* Whether the page is drawn by WebKit: Safari, and every browser on iOS, | ||
* Chrome's (`CriOS`) included, which say no `Chrome/`. WebKit paints a | ||
* highlight of `StaticRange`s past their text, tinting whole diffs, so | ||
* there it gets live ranges, as before they were made static. | ||
*/ | ||
const webkit = typeof navigator !== 'undefined' && /AppleWebKit/.test(navigator.userAgent) && !/Chrome\/|Chromium|Edg\//.test(navigator.userAgent); | ||
| ||
/** A range over `t` from `start` to `end`: static, but live where WebKit draws. */ | ||
function rangeOver(t: Text, start: number, end: number): AbstractRange { | ||
if (!webkit) return new StaticRange({ startContainer: t, startOffset: start, endContainer: t, endOffset: end }); | ||
const r = document.createRange(); | ||
r.setStart(t, start); | ||
r.setEnd(t, end); | ||
return r; | ||
} | ||
| ||
/** The text in `el`, as one node, or nothing for an empty line. */ | ||
function textOf(el: Element): Text | null { | ||
el.normalize(); | ||
| @@ -29,7 +46,7 @@ function named(name: string): Highlight { | ||
* `name:start,length,start,length…;…`, each start counted from the | ||
* end of the range before it. | ||
*/ | ||
function paint(el: Element, ranges: string): [Highlight, StaticRange][] { | ||
function paint(el: Element, ranges: string): [Highlight, AbstractRange][] { | ||
const nodes: [number, Text][] = []; | ||
let at = 0; | ||
// Not what is said under a diff's lines, which is no part of its text. | ||
| @@ -38,7 +55,7 @@ function paint(el: Element, ranges: string): [Highlight, StaticRange][] { | ||
if (text) nodes.push([at, text]); | ||
at += (text ? text.length : 0) + 1; | ||
} | ||
const painted: [Highlight, StaticRange][] = []; | ||
const painted: [Highlight, AbstractRange][] = []; | ||
for (const group of ranges.split(';')) { | ||
if (!group) continue; | ||
const [name, list] = group.split(':'); | ||
| @@ -52,7 +69,7 @@ function paint(el: Element, ranges: string): [Highlight, StaticRange][] { | ||
while (j < nodes.length && nodes[j][0] + nodes[j][1].length <= o) j++; | ||
for (let k = j; k < nodes.length && nodes[k][0] < end; k++) { | ||
const [a, t] = nodes[k]; | ||
const r = new StaticRange({ startContainer: t, startOffset: Math.max(o, a) - a, endContainer: t, endOffset: Math.min(end, a + t.length) - a }); | ||
const r = rangeOver(t, Math.max(o, a) - a, Math.min(end, a + t.length) - a); | ||
h.add(r); | ||
painted.push([h, r]); | ||
} | ||
| @@ -108,6 +125,5 @@ export function target(el: Element | undefined, line: number | null) { | ||
if (!a) return; | ||
} | ||
const e = data.indexOf('\n', a); | ||
const r = new StaticRange({ startContainer: text, startOffset: a, endContainer: text, endOffset: e < 0 ? data.length : e + 1 }); | ||
CSS.highlights.set('target', new Highlight(r)); | ||
CSS.highlights.set('target', new Highlight(rangeOver(text, a, e < 0 ? data.length : e + 1))); | ||
} | ||