~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

WebKit paints the diff's highlighting with live ranges again

Closed chadtmiller.com asked to merge into main from chadtmiller.com/knotless:web/webkit-highlight-ranges
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)));
}