Julius MarmingeT3 Code Mobile [WIP] (#2013)b3e8c035 months agoHistory
266 lines · 6.5 KB · TypeScript
RawDownload
import { diffWordsWithSpace } from "diff"; import type { ReviewHighlightedToken } from "./shikiReviewHighlighter"; interface ReviewDiffOperation {  readonly value: string;  readonly added?: true;  readonly removed?: true;} interface ReviewDiffHighlightRange {  readonly start: number;  readonly end: number;} const REVIEW_MAX_WORD_ALT_LINE_LENGTH = 1_000; function cleanLineEnding(value: string): string {  return value.endsWith("\n") ? value.slice(0, -1) : value;} function pushOrJoinSpan(input: {  readonly operation: ReviewDiffOperation;  readonly spans: Array<[0 | 1, string]>;  readonly enableJoin: boolean;  readonly isNeutral?: boolean;  readonly isLastOperation?: boolean;}): void {  const { operation, spans, enableJoin, isNeutral = false, isLastOperation = false } = input;  const lastSpan = spans.at(-1);   if (!lastSpan || isLastOperation || !enableJoin) {    spans.push([isNeutral ? 0 : 1, operation.value]);    return;  }   const lastSpanIsNeutral = lastSpan[0] === 0;  if (    isNeutral === lastSpanIsNeutral ||    (isNeutral && operation.value.length === 1 && !lastSpanIsNeutral)  ) {    lastSpan[1] += operation.value;    return;  }   spans.push([isNeutral ? 0 : 1, operation.value]);} function spansToRanges(  spans: ReadonlyArray<readonly [0 | 1, string]>,): ReadonlyArray<ReviewDiffHighlightRange> {  const ranges: ReviewDiffHighlightRange[] = [];  let offset = 0;   spans.forEach(([kind, value]) => {    const nextOffset = offset + value.length;    if (kind === 1 && value.length > 0) {      ranges.push({ start: offset, end: nextOffset });    }    offset = nextOffset;  });   return ranges;} function mergeNearbyRanges(  ranges: ReadonlyArray<ReviewDiffHighlightRange>,): ReadonlyArray<ReviewDiffHighlightRange> {  if (ranges.length <= 1) {    return ranges;  }   const merged: ReviewDiffHighlightRange[] = [];   ranges.forEach((range) => {    const previous = merged.at(-1);    if (previous && range.start - previous.end <= 1) {      merged[merged.length - 1] = { start: previous.start, end: range.end };      return;    }    merged.push({ ...range });  });   return merged;} function appendTokenSegment(  target: ReviewHighlightedToken[],  source: ReviewHighlightedToken,  content: string,  diffHighlight: boolean,): void {  if (content.length === 0) {    return;  }   const previous = target.at(-1);  if (    previous &&    previous.color === source.color &&    previous.fontStyle === source.fontStyle &&    previous.diffHighlight === diffHighlight  ) {    previous.content += content;    return;  }   target.push({    content,    color: source.color,    fontStyle: source.fontStyle,    diffHighlight,  });} export function computeWordAltDiffRanges(input: {  readonly deletionLine: string;  readonly additionLine: string;}): {  readonly deletion: ReadonlyArray<ReviewDiffHighlightRange>;  readonly addition: ReadonlyArray<ReviewDiffHighlightRange>;} {  const deletionLine = cleanLineEnding(input.deletionLine);  const additionLine = cleanLineEnding(input.additionLine);   if (deletionLine.length === 0 && additionLine.length === 0) {    return { deletion: [], addition: [] };  }   if (    deletionLine.length > REVIEW_MAX_WORD_ALT_LINE_LENGTH ||    additionLine.length > REVIEW_MAX_WORD_ALT_LINE_LENGTH  ) {    return { deletion: [], addition: [] };  }   const operations = diffWordsWithSpace(    deletionLine,    additionLine,  ) as ReadonlyArray<ReviewDiffOperation>;  const deletionSpans: Array<[0 | 1, string]> = [];  const additionSpans: Array<[0 | 1, string]> = [];  const lastOperation = operations.at(-1);   operations.forEach((operation) => {    const isLastOperation = operation === lastOperation;    if (!operation.added && !operation.removed) {      pushOrJoinSpan({        operation,        spans: deletionSpans,        enableJoin: true,        isNeutral: true,        isLastOperation,      });      pushOrJoinSpan({        operation,        spans: additionSpans,        enableJoin: true,        isNeutral: true,        isLastOperation,      });      return;    }     if (operation.removed) {      pushOrJoinSpan({        operation,        spans: deletionSpans,        enableJoin: true,        isLastOperation,      });      return;    }     pushOrJoinSpan({      operation,      spans: additionSpans,      enableJoin: true,      isLastOperation,    });  });   return {    deletion: mergeNearbyRanges(spansToRanges(deletionSpans)),    addition: mergeNearbyRanges(spansToRanges(additionSpans)),  };} export function applyDiffRangesToTokens(  tokens: ReadonlyArray<ReviewHighlightedToken>,  ranges: ReadonlyArray<ReviewDiffHighlightRange>,): ReadonlyArray<ReviewHighlightedToken> {  if (tokens.length === 0 || ranges.length === 0) {    return tokens;  }   const nextTokens: ReviewHighlightedToken[] = [];  let tokenOffset = 0;  let rangeIndex = 0;   tokens.forEach((token) => {    const tokenStart = tokenOffset;    const tokenEnd = tokenStart + token.content.length;    tokenOffset = tokenEnd;     if (token.content.length === 0) {      nextTokens.push(token);      return;    }     while (rangeIndex < ranges.length && ranges[rangeIndex]!.end <= tokenStart) {      rangeIndex += 1;    }     if ((ranges[rangeIndex]?.start ?? Number.POSITIVE_INFINITY) >= tokenEnd) {      nextTokens.push(token.diffHighlight ? { ...token, diffHighlight: false } : token);      return;    }     let cursor = tokenStart;    let localRangeIndex = rangeIndex;     while ((ranges[localRangeIndex]?.start ?? Number.POSITIVE_INFINITY) < tokenEnd) {      const range = ranges[localRangeIndex];      if (!range) {        break;      }       if (range.start > cursor) {        appendTokenSegment(          nextTokens,          token,          token.content.slice(cursor - tokenStart, range.start - tokenStart),          false,        );      }       const highlightedStart = Math.max(cursor, range.start);      const highlightedEnd = Math.min(tokenEnd, range.end);       if (highlightedEnd > highlightedStart) {        appendTokenSegment(          nextTokens,          token,          token.content.slice(highlightedStart - tokenStart, highlightedEnd - tokenStart),          true,        );      }       cursor = highlightedEnd;      if (range.end <= tokenEnd) {        localRangeIndex += 1;      } else {        break;      }    }     if (cursor < tokenEnd) {      appendTokenSegment(nextTokens, token, token.content.slice(cursor - tokenStart), false);    }     rangeIndex = localRangeIndex;  });   return nextTokens;}