UNPKG

chrome-devtools-frontend

Version:
180 lines (164 loc) • 7.03 kB
// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /* eslint-disable rulesdir/no_underscored_properties */ import {Row, RowType} from './ChangesView.js'; // eslint-disable-line no-unused-vars interface ParserConfig { diffRows: Array<Row>; baselineLines: Array<string>; currentLines: Array<string>; mimeType: string; } // eslint-disable-next-line @typescript-eslint/naming-convention export function ChangesHighlighter(config: Object, parserConfig: ParserConfig): { startState: () => DiffState, token: (arg0: typeof CodeMirror.StringStream, arg1: DiffState) => string, blankLine: (arg0: DiffState) => string, copyState: (arg0: DiffState) => DiffState, } { const diffRows = parserConfig.diffRows; const baselineLines = parserConfig.baselineLines; const currentLines = parserConfig.currentLines; const syntaxHighlightMode = CodeMirror.getMode({}, parserConfig.mimeType); function fastForward(state: DiffState, baselineLineNumber: number, currentLineNumber: number): void { if (baselineLineNumber > state.baselineLineNumber) { fastForwardSyntaxHighlighter( state.baselineSyntaxState, state.baselineLineNumber, baselineLineNumber, baselineLines); state.baselineLineNumber = baselineLineNumber; } if (currentLineNumber > state.currentLineNumber) { fastForwardSyntaxHighlighter(state.currentSyntaxState, state.currentLineNumber, currentLineNumber, currentLines); state.currentLineNumber = currentLineNumber; } } function fastForwardSyntaxHighlighter(syntaxState: Object, from: number, to: number, lines: string[]): void { let lineNumber = from; while (lineNumber < to && lineNumber < lines.length) { const stream = new CodeMirror.StringStream(lines[lineNumber]); if (stream.eol() && syntaxHighlightMode.blankLine) { syntaxHighlightMode.blankLine(syntaxState); } while (!stream.eol()) { if (syntaxHighlightMode.token) { syntaxHighlightMode.token(stream, syntaxState); } stream.start = stream.pos; } lineNumber++; } } return { startState: function(): DiffState { return { rowNumber: 0, diffTokenIndex: 0, currentLineNumber: 0, baselineLineNumber: 0, currentSyntaxState: CodeMirror.startState(syntaxHighlightMode), baselineSyntaxState: CodeMirror.startState(syntaxHighlightMode), syntaxPosition: 0, diffPosition: 0, syntaxStyle: '', diffStyle: '', }; }, token: function(stream: typeof CodeMirror.StringStream, state: DiffState): string { const diffRow = diffRows[state.rowNumber]; if (!diffRow) { // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes stream.next(); return ''; } fastForward(state, diffRow.baselineLineNumber - 1, diffRow.currentLineNumber - 1); let classes = ''; // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes if (stream.pos === 0) { classes += ' line-background-' + diffRow.type + ' line-' + diffRow.type; } const syntaxHighlighterNeedsRefresh = state.diffPosition >= state.syntaxPosition; if (state.diffPosition <= state.syntaxPosition) { state.diffPosition += diffRow.tokens[state.diffTokenIndex].text.length; state.diffStyle = diffRow.tokens[state.diffTokenIndex].className; state.diffTokenIndex++; } if (syntaxHighlighterNeedsRefresh) { if (syntaxHighlightMode.token && (diffRow.type === RowType.Deletion || diffRow.type === RowType.Addition || diffRow.type === RowType.Equal)) { state.syntaxStyle = syntaxHighlightMode.token( // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes stream, diffRow.type === RowType.Deletion ? state.baselineSyntaxState : state.currentSyntaxState) || ''; // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes state.syntaxPosition = stream.pos; } else { state.syntaxStyle = ''; state.syntaxPosition = Infinity; } } // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes stream.pos = Math.min(state.syntaxPosition, state.diffPosition); classes += ' ' + state.syntaxStyle; classes += ' ' + state.diffStyle; // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes if (stream.eol()) { state.rowNumber++; if (diffRow.type === RowType.Deletion) { state.baselineLineNumber++; } else { state.currentLineNumber++; } state.diffPosition = 0; state.syntaxPosition = 0; state.diffTokenIndex = 0; } return classes; }, blankLine: function(state: DiffState): string { const diffRow = diffRows[state.rowNumber]; state.rowNumber++; state.syntaxPosition = 0; state.diffPosition = 0; state.diffTokenIndex = 0; if (!diffRow) { return ''; } let style: void|'' = ''; if (syntaxHighlightMode.blankLine) { if (diffRow.type === RowType.Equal || diffRow.type === RowType.Addition) { // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes style = syntaxHighlightMode.blankLine(state.currentSyntaxState); state.currentLineNumber++; } else if (diffRow.type === RowType.Deletion) { // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes style = syntaxHighlightMode.blankLine(state.baselineSyntaxState); state.baselineLineNumber++; } } return style + ' line-background-' + diffRow.type + ' line-' + diffRow.type; }, copyState: function(state: DiffState): DiffState { const newState = Object.assign({}, state); // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes newState.currentSyntaxState = CodeMirror.copyState(syntaxHighlightMode, state.currentSyntaxState); // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes newState.baselineSyntaxState = CodeMirror.copyState(syntaxHighlightMode, state.baselineSyntaxState); return /** @type {!DiffState} */ newState as DiffState; }, }; } // @ts-ignore TODO(crbug.com/1011811): Fix after upstream CodeMirror type fixes CodeMirror.defineMode('devtools-diff', ChangesHighlighter); export interface DiffState { rowNumber: number; diffTokenIndex: number; currentLineNumber: number; baselineLineNumber: number; currentSyntaxState: Object; baselineSyntaxState: Object; syntaxPosition: number; diffPosition: number; syntaxStyle: string; diffStyle: string; }