mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-09-11 12:25:42 +03:00
make linter happy
This commit is contained in:
parent
eb935fb25c
commit
f75bc615d5
@ -22,182 +22,182 @@ import { vue } from '@codemirror/lang-vue';
|
||||
const t = tags;
|
||||
|
||||
export const highlightStyle: HighlightStyle = HighlightStyle.define([
|
||||
{ tag: t.variableName, class: 'token-variable' },
|
||||
{ tag: t.definition(t.variableName), class: 'token-definition' },
|
||||
{ tag: t.propertyName, class: 'token-property' },
|
||||
{ tag: [t.typeName, t.className, t.namespace, t.macroName], class: 'token-type' },
|
||||
{ tag: [t.special(t.name), t.constant(t.className)], class: 'token-variable-special' },
|
||||
{ tag: t.standard(t.variableName), class: 'token-builtin' },
|
||||
{ tag: t.variableName, class: 'token-variable' },
|
||||
{ tag: t.definition(t.variableName), class: 'token-definition' },
|
||||
{ tag: t.propertyName, class: 'token-property' },
|
||||
{ tag: [t.typeName, t.className, t.namespace, t.macroName], class: 'token-type' },
|
||||
{ tag: [t.special(t.name), t.constant(t.className)], class: 'token-variable-special' },
|
||||
{ tag: t.standard(t.variableName), class: 'token-builtin' },
|
||||
|
||||
{ tag: [t.number, t.literal, t.unit], class: 'token-number' },
|
||||
{ tag: t.string, class: 'token-string' },
|
||||
{ tag: [t.special(t.string), t.regexp, t.escape], class: 'token-string-special' },
|
||||
{ tag: [], class: 'token-atom' },
|
||||
{ tag: [t.number, t.literal, t.unit], class: 'token-number' },
|
||||
{ tag: t.string, class: 'token-string' },
|
||||
{ tag: [t.special(t.string), t.regexp, t.escape], class: 'token-string-special' },
|
||||
{ tag: [], class: 'token-atom' },
|
||||
|
||||
{ tag: t.keyword, class: 'token-keyword' },
|
||||
{ tag: [t.comment, t.quote], class: 'token-comment' },
|
||||
{ tag: t.meta, class: 'token-meta' },
|
||||
{ tag: t.invalid, class: 'token-invalid' },
|
||||
{ tag: t.keyword, class: 'token-keyword' },
|
||||
{ tag: [t.comment, t.quote], class: 'token-comment' },
|
||||
{ tag: t.meta, class: 'token-meta' },
|
||||
{ tag: t.invalid, class: 'token-invalid' },
|
||||
|
||||
{ tag: t.tagName, class: 'token-tag' },
|
||||
{ tag: t.attributeName, class: 'token-attribute' },
|
||||
{ tag: t.attributeValue, class: 'token-attribute-value' },
|
||||
{ tag: t.tagName, class: 'token-tag' },
|
||||
{ tag: t.attributeName, class: 'token-attribute' },
|
||||
{ tag: t.attributeValue, class: 'token-attribute-value' },
|
||||
|
||||
{ tag: t.inserted, class: 'token-inserted' },
|
||||
{ tag: t.deleted, class: 'token-deleted' },
|
||||
{ tag: t.heading, class: 'token-heading' },
|
||||
{ tag: t.link, class: 'token-link' },
|
||||
{ tag: t.strikethrough, class: 'token-strikethrough' },
|
||||
{ tag: t.strong, class: 'token-strong' },
|
||||
{ tag: t.emphasis, class: 'token-emphasis' }
|
||||
{ tag: t.inserted, class: 'token-inserted' },
|
||||
{ tag: t.deleted, class: 'token-deleted' },
|
||||
{ tag: t.heading, class: 'token-heading' },
|
||||
{ tag: t.link, class: 'token-link' },
|
||||
{ tag: t.strikethrough, class: 'token-strikethrough' },
|
||||
{ tag: t.strong, class: 'token-strong' },
|
||||
{ tag: t.emphasis, class: 'token-emphasis' }
|
||||
]);
|
||||
|
||||
export function create(code: string, mimeType: string): CodeHighlighter {
|
||||
const language = languageFromFilename(mimeType);
|
||||
let tree: Tree;
|
||||
if (language) {
|
||||
tree = language.language.parser.parse(code);
|
||||
} else {
|
||||
tree = new Tree(NodeType.none, [], [], code.length);
|
||||
}
|
||||
return new CodeHighlighter(code, tree);
|
||||
const language = languageFromFilename(mimeType);
|
||||
let tree: Tree;
|
||||
if (language) {
|
||||
tree = language.language.parser.parse(code);
|
||||
} else {
|
||||
tree = new Tree(NodeType.none, [], [], code.length);
|
||||
}
|
||||
return new CodeHighlighter(code, tree);
|
||||
}
|
||||
|
||||
export function highlightNode(node: Element, mimeType: string): void {
|
||||
const code = node.textContent || '';
|
||||
const highlighter = create(code, mimeType);
|
||||
if (node.firstChild) {
|
||||
node.textContent = '';
|
||||
}
|
||||
highlighter.highlight((text, style) => {
|
||||
let token: Node = document.createTextNode(text);
|
||||
if (style) {
|
||||
const span = document.createElement('span');
|
||||
span.className = style;
|
||||
span.appendChild(token);
|
||||
token = span;
|
||||
}
|
||||
node.appendChild(token);
|
||||
});
|
||||
const code = node.textContent || '';
|
||||
const highlighter = create(code, mimeType);
|
||||
if (node.firstChild) {
|
||||
node.textContent = '';
|
||||
}
|
||||
highlighter.highlight((text, style) => {
|
||||
let token: Node = document.createTextNode(text);
|
||||
if (style) {
|
||||
const span = document.createElement('span');
|
||||
span.className = style;
|
||||
span.appendChild(token);
|
||||
token = span;
|
||||
}
|
||||
node.appendChild(token);
|
||||
});
|
||||
}
|
||||
|
||||
export function languageFromFilename(filename: string): LanguageSupport | null {
|
||||
const ext = filename.split('.').pop();
|
||||
switch (ext) {
|
||||
case 'jsx':
|
||||
case 'js':
|
||||
// We intentionally allow JSX in normal .js as well as .jsx files,
|
||||
// because there are simply too many existing applications and
|
||||
// examples out there that use JSX within .js files, and we don't
|
||||
// want to break them.
|
||||
return javascript({ jsx: true });
|
||||
case 'ts':
|
||||
return javascript({ typescript: true });
|
||||
case 'tsx':
|
||||
return javascript({ typescript: true, jsx: true });
|
||||
const ext = filename.split('.').pop();
|
||||
switch (ext) {
|
||||
case 'jsx':
|
||||
case 'js':
|
||||
// We intentionally allow JSX in normal .js as well as .jsx files,
|
||||
// because there are simply too many existing applications and
|
||||
// examples out there that use JSX within .js files, and we don't
|
||||
// want to break them.
|
||||
return javascript({ jsx: true });
|
||||
case 'ts':
|
||||
return javascript({ typescript: true });
|
||||
case 'tsx':
|
||||
return javascript({ typescript: true, jsx: true });
|
||||
|
||||
case 'css':
|
||||
return css();
|
||||
case 'css':
|
||||
return css();
|
||||
|
||||
case 'html':
|
||||
return html({ selfClosingTags: true });
|
||||
case 'html':
|
||||
return html({ selfClosingTags: true });
|
||||
|
||||
case 'xml':
|
||||
return xml();
|
||||
case 'xml':
|
||||
return xml();
|
||||
|
||||
case 'wasm':
|
||||
return wast();
|
||||
case 'wasm':
|
||||
return wast();
|
||||
|
||||
case 'cpp':
|
||||
case 'c++':
|
||||
case 'hpp':
|
||||
case 'h++':
|
||||
return cpp();
|
||||
case 'cpp':
|
||||
case 'c++':
|
||||
case 'hpp':
|
||||
case 'h++':
|
||||
return cpp();
|
||||
|
||||
// case 'text/x-go':
|
||||
// return new LanguageSupport(await CodeMirror.go());
|
||||
// case 'text/x-go':
|
||||
// return new LanguageSupport(await CodeMirror.go());
|
||||
|
||||
case 'java':
|
||||
return java();
|
||||
case 'java':
|
||||
return java();
|
||||
|
||||
// case 'text/x-kotlin':
|
||||
// return new LanguageSupport(await CodeMirror.kotlin());
|
||||
// case 'text/x-kotlin':
|
||||
// return new LanguageSupport(await CodeMirror.kotlin());
|
||||
|
||||
case 'json':
|
||||
return json();
|
||||
case 'json':
|
||||
return json();
|
||||
|
||||
case 'php':
|
||||
return php();
|
||||
case 'php':
|
||||
return php();
|
||||
|
||||
case 'python':
|
||||
return python();
|
||||
case 'python':
|
||||
return python();
|
||||
|
||||
case 'md':
|
||||
return markdown();
|
||||
case 'md':
|
||||
return markdown();
|
||||
|
||||
// case 'text/x-sh':
|
||||
// return new LanguageSupport(await CodeMirror.shell());
|
||||
// case 'text/x-sh':
|
||||
// return new LanguageSupport(await CodeMirror.shell());
|
||||
|
||||
// case 'text/x-coffeescript':
|
||||
// return new LanguageSupport(await CodeMirror.coffeescript());
|
||||
// case 'text/x-coffeescript':
|
||||
// return new LanguageSupport(await CodeMirror.coffeescript());
|
||||
|
||||
// case 'text/x-clojure':
|
||||
// return new LanguageSupport(await CodeMirror.clojure());
|
||||
// case 'text/x-clojure':
|
||||
// return new LanguageSupport(await CodeMirror.clojure());
|
||||
|
||||
// case 'application/vnd.dart':
|
||||
// return new LanguageSupport(await CodeMirror.dart());
|
||||
// case 'application/vnd.dart':
|
||||
// return new LanguageSupport(await CodeMirror.dart());
|
||||
|
||||
// case 'text/x-gss':
|
||||
// return new LanguageSupport(await CodeMirror.gss());
|
||||
// case 'text/x-gss':
|
||||
// return new LanguageSupport(await CodeMirror.gss());
|
||||
|
||||
// case 'text/x-less':
|
||||
// return new CodeMirror.LanguageSupport(await CodeMirror.less());
|
||||
// case 'text/x-less':
|
||||
// return new CodeMirror.LanguageSupport(await CodeMirror.less());
|
||||
|
||||
// case 'text/x-sass':
|
||||
// return new LanguageSupport(await CodeMirror.sass());
|
||||
// case 'text/x-sass':
|
||||
// return new LanguageSupport(await CodeMirror.sass());
|
||||
|
||||
// case 'text/x-scala':
|
||||
// return new LanguageSupport(await CodeMirror.scala());
|
||||
// case 'text/x-scala':
|
||||
// return new LanguageSupport(await CodeMirror.scala());
|
||||
|
||||
// case 'text/x-scss':
|
||||
// return new LanguageSupport(await CodeMirror.scss());
|
||||
// case 'text/x-scss':
|
||||
// return new LanguageSupport(await CodeMirror.scss());
|
||||
|
||||
case 'svelte':
|
||||
return svelte();
|
||||
case 'svelte':
|
||||
return svelte();
|
||||
|
||||
case 'vue':
|
||||
return vue();
|
||||
case 'vue':
|
||||
return vue();
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export class CodeHighlighter {
|
||||
constructor(readonly code: string, readonly tree: Tree) { }
|
||||
constructor(readonly code: string, readonly tree: Tree) {}
|
||||
|
||||
highlight(token: (text: string, style: string) => void): void {
|
||||
this.highlightRange(0, this.code.length, token);
|
||||
}
|
||||
highlight(token: (text: string, style: string) => void): void {
|
||||
this.highlightRange(0, this.code.length, token);
|
||||
}
|
||||
|
||||
highlightRange(from: number, to: number, token: (text: string, style: string) => void): void {
|
||||
let pos = from;
|
||||
const flush = (to: number, style: string): void => {
|
||||
if (to > pos) {
|
||||
token(this.code.slice(pos, to), style);
|
||||
pos = to;
|
||||
}
|
||||
};
|
||||
highlightTree(
|
||||
this.tree,
|
||||
highlightStyle,
|
||||
(from, to, style) => {
|
||||
flush(from, '');
|
||||
flush(to, style);
|
||||
},
|
||||
from,
|
||||
to
|
||||
);
|
||||
flush(to, '');
|
||||
}
|
||||
highlightRange(from: number, to: number, token: (text: string, style: string) => void): void {
|
||||
let pos = from;
|
||||
const flush = (to: number, style: string): void => {
|
||||
if (to > pos) {
|
||||
token(this.code.slice(pos, to), style);
|
||||
pos = to;
|
||||
}
|
||||
};
|
||||
highlightTree(
|
||||
this.tree,
|
||||
highlightStyle,
|
||||
(from, to, style) => {
|
||||
flush(from, '');
|
||||
flush(to, style);
|
||||
},
|
||||
from,
|
||||
to
|
||||
);
|
||||
flush(to, '');
|
||||
}
|
||||
}
|
||||
|
@ -3,34 +3,34 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
export class CharacterIdMap<T> {
|
||||
readonly #elementToCharacter: Map<T, string>;
|
||||
readonly #characterToElement: Map<string, T>;
|
||||
#charCode: number;
|
||||
readonly #elementToCharacter: Map<T, string>;
|
||||
readonly #characterToElement: Map<string, T>;
|
||||
#charCode: number;
|
||||
|
||||
constructor() {
|
||||
this.#elementToCharacter = new Map();
|
||||
this.#characterToElement = new Map();
|
||||
this.#charCode = 33;
|
||||
}
|
||||
constructor() {
|
||||
this.#elementToCharacter = new Map();
|
||||
this.#characterToElement = new Map();
|
||||
this.#charCode = 33;
|
||||
}
|
||||
|
||||
toChar(object: T): string {
|
||||
let character = this.#elementToCharacter.get(object);
|
||||
if (!character) {
|
||||
if (this.#charCode >= 0xffff) {
|
||||
throw new Error('CharacterIdMap ran out of capacity!');
|
||||
}
|
||||
character = String.fromCharCode(this.#charCode++);
|
||||
this.#elementToCharacter.set(object, character);
|
||||
this.#characterToElement.set(character, object);
|
||||
}
|
||||
return character;
|
||||
}
|
||||
toChar(object: T): string {
|
||||
let character = this.#elementToCharacter.get(object);
|
||||
if (!character) {
|
||||
if (this.#charCode >= 0xffff) {
|
||||
throw new Error('CharacterIdMap ran out of capacity!');
|
||||
}
|
||||
character = String.fromCharCode(this.#charCode++);
|
||||
this.#elementToCharacter.set(object, character);
|
||||
this.#characterToElement.set(character, object);
|
||||
}
|
||||
return character;
|
||||
}
|
||||
|
||||
fromChar(character: string): T | null {
|
||||
const object = this.#characterToElement.get(character);
|
||||
if (object === undefined) {
|
||||
return null;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
fromChar(character: string): T | null {
|
||||
const object = this.#characterToElement.get(character);
|
||||
if (object === undefined) {
|
||||
return null;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
@ -2,43 +2,41 @@ import { CharacterIdMap } from './characterIdMap';
|
||||
import { diff_match_patch } from 'diff-match-patch';
|
||||
|
||||
export const charDiff = (
|
||||
text1: string,
|
||||
text2: string,
|
||||
cleanup?: boolean
|
||||
text1: string,
|
||||
text2: string,
|
||||
cleanup?: boolean
|
||||
): { 0: number; 1: string }[] => {
|
||||
const differ = new diff_match_patch();
|
||||
const diff = differ.diff_main(text1, text2);
|
||||
if (cleanup) {
|
||||
differ.diff_cleanupSemantic(diff);
|
||||
}
|
||||
return diff;
|
||||
const differ = new diff_match_patch();
|
||||
const diff = differ.diff_main(text1, text2);
|
||||
if (cleanup) {
|
||||
differ.diff_cleanupSemantic(diff);
|
||||
}
|
||||
return diff;
|
||||
};
|
||||
|
||||
export const lineDiff = (lines1: string[], lines2: string[]): DiffArray => {
|
||||
const idMap = new CharacterIdMap<string>();
|
||||
const text1 = lines1.map((line) => idMap.toChar(line)).join('');
|
||||
const text2 = lines2.map((line) => idMap.toChar(line)).join('');
|
||||
const idMap = new CharacterIdMap<string>();
|
||||
const text1 = lines1.map((line) => idMap.toChar(line)).join('');
|
||||
const text2 = lines2.map((line) => idMap.toChar(line)).join('');
|
||||
|
||||
const diff = charDiff(text1, text2);
|
||||
const lineDiff = [];
|
||||
for (let i = 0; i < diff.length; i++) {
|
||||
const lines = [];
|
||||
for (let j = 0; j < diff[i][1].length; j++) {
|
||||
lines.push(idMap.fromChar(diff[i][1][j]) || '');
|
||||
}
|
||||
const diff = charDiff(text1, text2);
|
||||
const lineDiff = [];
|
||||
for (let i = 0; i < diff.length; i++) {
|
||||
const lines = [];
|
||||
for (let j = 0; j < diff[i][1].length; j++) {
|
||||
lines.push(idMap.fromChar(diff[i][1][j]) || '');
|
||||
}
|
||||
|
||||
lineDiff.push({ 0: diff[i][0], 1: lines });
|
||||
}
|
||||
return lineDiff;
|
||||
lineDiff.push({ 0: diff[i][0], 1: lines });
|
||||
}
|
||||
return lineDiff;
|
||||
};
|
||||
|
||||
// TODO(crbug.com/1167717): Make this a const enum again
|
||||
// eslint-disable-next-line rulesdir/const_enum
|
||||
export enum Operation {
|
||||
Equal = 0,
|
||||
Insert = 1,
|
||||
Delete = -1,
|
||||
Edit = 2
|
||||
Equal = 0,
|
||||
Insert = 1,
|
||||
Delete = -1,
|
||||
Edit = 2
|
||||
}
|
||||
|
||||
export type DiffArray = { 0: Operation; 1: string[] }[];
|
||||
|
@ -1,155 +1,155 @@
|
||||
import { Operation, type DiffArray, charDiff } from './diff';
|
||||
|
||||
export interface Token {
|
||||
text: string;
|
||||
className: string;
|
||||
text: string;
|
||||
className: string;
|
||||
}
|
||||
|
||||
export interface Row {
|
||||
originalLineNumber: number;
|
||||
currentLineNumber: number;
|
||||
tokens: Token[];
|
||||
type: RowType;
|
||||
originalLineNumber: number;
|
||||
currentLineNumber: number;
|
||||
tokens: Token[];
|
||||
type: RowType;
|
||||
}
|
||||
|
||||
export const enum RowType {
|
||||
Deletion = 'deletion',
|
||||
Addition = 'addition',
|
||||
Equal = 'equal',
|
||||
Spacer = 'spacer'
|
||||
Deletion = 'deletion',
|
||||
Addition = 'addition',
|
||||
Equal = 'equal',
|
||||
Spacer = 'spacer'
|
||||
}
|
||||
|
||||
export function buildDiffRows(diff: DiffArray): {
|
||||
originalLines: readonly string[];
|
||||
currentLines: readonly string[];
|
||||
rows: readonly Row[];
|
||||
originalLines: readonly string[];
|
||||
currentLines: readonly string[];
|
||||
rows: readonly Row[];
|
||||
} {
|
||||
let currentLineNumber = 0;
|
||||
let originalLineNumber = 0;
|
||||
const paddingLines = 100000;
|
||||
let currentLineNumber = 0;
|
||||
let originalLineNumber = 0;
|
||||
const paddingLines = 100000;
|
||||
|
||||
const originalLines: string[] = [];
|
||||
const currentLines: string[] = [];
|
||||
const rows: Row[] = [];
|
||||
const originalLines: string[] = [];
|
||||
const currentLines: string[] = [];
|
||||
const rows: Row[] = [];
|
||||
|
||||
for (let i = 0; i < diff.length; ++i) {
|
||||
const token = diff[i];
|
||||
switch (token[0]) {
|
||||
case Operation.Equal:
|
||||
rows.push(...createEqualRows(token[1], i === 0, i === diff.length - 1));
|
||||
originalLines.push(...token[1]);
|
||||
currentLines.push(...token[1]);
|
||||
break;
|
||||
case Operation.Insert:
|
||||
for (const line of token[1]) {
|
||||
rows.push(createRow(line, RowType.Addition));
|
||||
}
|
||||
currentLines.push(...token[1]);
|
||||
break;
|
||||
case Operation.Delete:
|
||||
originalLines.push(...token[1]);
|
||||
if (diff[i + 1] && diff[i + 1][0] === Operation.Insert) {
|
||||
i++;
|
||||
rows.push(...createModifyRows(token[1].join('\n'), diff[i][1].join('\n')));
|
||||
currentLines.push(...diff[i][1]);
|
||||
} else {
|
||||
for (const line of token[1]) {
|
||||
rows.push(createRow(line, RowType.Deletion));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < diff.length; ++i) {
|
||||
const token = diff[i];
|
||||
switch (token[0]) {
|
||||
case Operation.Equal:
|
||||
rows.push(...createEqualRows(token[1], i === 0, i === diff.length - 1));
|
||||
originalLines.push(...token[1]);
|
||||
currentLines.push(...token[1]);
|
||||
break;
|
||||
case Operation.Insert:
|
||||
for (const line of token[1]) {
|
||||
rows.push(createRow(line, RowType.Addition));
|
||||
}
|
||||
currentLines.push(...token[1]);
|
||||
break;
|
||||
case Operation.Delete:
|
||||
originalLines.push(...token[1]);
|
||||
if (diff[i + 1] && diff[i + 1][0] === Operation.Insert) {
|
||||
i++;
|
||||
rows.push(...createModifyRows(token[1].join('\n'), diff[i][1].join('\n')));
|
||||
currentLines.push(...diff[i][1]);
|
||||
} else {
|
||||
for (const line of token[1]) {
|
||||
rows.push(createRow(line, RowType.Deletion));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { originalLines, currentLines, rows };
|
||||
return { originalLines, currentLines, rows };
|
||||
|
||||
function createEqualRows(lines: string[], atStart: boolean, atEnd: boolean): Row[] {
|
||||
const equalRows = [];
|
||||
if (!atStart) {
|
||||
for (let i = 0; i < paddingLines && i < lines.length; i++) {
|
||||
equalRows.push(createRow(lines[i], RowType.Equal));
|
||||
}
|
||||
if (lines.length > paddingLines * 2 + 1 && !atEnd) {
|
||||
equalRows.push(
|
||||
createRow(`skipping ${lines.length - paddingLines * 2} matching lines`, RowType.Spacer)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!atEnd) {
|
||||
const start = Math.max(lines.length - paddingLines - 1, atStart ? 0 : paddingLines);
|
||||
let skip = lines.length - paddingLines - 1;
|
||||
if (!atStart) {
|
||||
skip -= paddingLines;
|
||||
}
|
||||
if (skip > 0) {
|
||||
originalLineNumber += skip;
|
||||
currentLineNumber += skip;
|
||||
}
|
||||
function createEqualRows(lines: string[], atStart: boolean, atEnd: boolean): Row[] {
|
||||
const equalRows = [];
|
||||
if (!atStart) {
|
||||
for (let i = 0; i < paddingLines && i < lines.length; i++) {
|
||||
equalRows.push(createRow(lines[i], RowType.Equal));
|
||||
}
|
||||
if (lines.length > paddingLines * 2 + 1 && !atEnd) {
|
||||
equalRows.push(
|
||||
createRow(`skipping ${lines.length - paddingLines * 2} matching lines`, RowType.Spacer)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!atEnd) {
|
||||
const start = Math.max(lines.length - paddingLines - 1, atStart ? 0 : paddingLines);
|
||||
let skip = lines.length - paddingLines - 1;
|
||||
if (!atStart) {
|
||||
skip -= paddingLines;
|
||||
}
|
||||
if (skip > 0) {
|
||||
originalLineNumber += skip;
|
||||
currentLineNumber += skip;
|
||||
}
|
||||
|
||||
for (let i = start; i < lines.length; i++) {
|
||||
equalRows.push(createRow(lines[i], RowType.Equal));
|
||||
}
|
||||
}
|
||||
return equalRows;
|
||||
}
|
||||
for (let i = start; i < lines.length; i++) {
|
||||
equalRows.push(createRow(lines[i], RowType.Equal));
|
||||
}
|
||||
}
|
||||
return equalRows;
|
||||
}
|
||||
|
||||
function createModifyRows(before: string, after: string): Row[] {
|
||||
const internalDiff = charDiff(before, after, true /* cleanup diff */);
|
||||
const deletionRows = [createRow('', RowType.Deletion)];
|
||||
const insertionRows = [createRow('', RowType.Addition)];
|
||||
function createModifyRows(before: string, after: string): Row[] {
|
||||
const internalDiff = charDiff(before, after, true /* cleanup diff */);
|
||||
const deletionRows = [createRow('', RowType.Deletion)];
|
||||
const insertionRows = [createRow('', RowType.Addition)];
|
||||
|
||||
for (const token of internalDiff) {
|
||||
const text = token[1];
|
||||
const type = token[0];
|
||||
const className = type === Operation.Equal ? '' : 'inner-diff';
|
||||
const lines = text.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (i > 0 && type !== Operation.Insert) {
|
||||
deletionRows.push(createRow('', RowType.Deletion));
|
||||
}
|
||||
if (i > 0 && type !== Operation.Delete) {
|
||||
insertionRows.push(createRow('', RowType.Addition));
|
||||
}
|
||||
if (!lines[i]) {
|
||||
continue;
|
||||
}
|
||||
if (type !== Operation.Insert) {
|
||||
deletionRows[deletionRows.length - 1].tokens.push({ text: lines[i], className });
|
||||
}
|
||||
if (type !== Operation.Delete) {
|
||||
insertionRows[insertionRows.length - 1].tokens.push({ text: lines[i], className });
|
||||
}
|
||||
}
|
||||
}
|
||||
return deletionRows.concat(insertionRows);
|
||||
}
|
||||
for (const token of internalDiff) {
|
||||
const text = token[1];
|
||||
const type = token[0];
|
||||
const className = type === Operation.Equal ? '' : 'inner-diff';
|
||||
const lines = text.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (i > 0 && type !== Operation.Insert) {
|
||||
deletionRows.push(createRow('', RowType.Deletion));
|
||||
}
|
||||
if (i > 0 && type !== Operation.Delete) {
|
||||
insertionRows.push(createRow('', RowType.Addition));
|
||||
}
|
||||
if (!lines[i]) {
|
||||
continue;
|
||||
}
|
||||
if (type !== Operation.Insert) {
|
||||
deletionRows[deletionRows.length - 1].tokens.push({ text: lines[i], className });
|
||||
}
|
||||
if (type !== Operation.Delete) {
|
||||
insertionRows[insertionRows.length - 1].tokens.push({ text: lines[i], className });
|
||||
}
|
||||
}
|
||||
}
|
||||
return deletionRows.concat(insertionRows);
|
||||
}
|
||||
|
||||
function createRow(text: string, type: RowType): Row {
|
||||
if (type === RowType.Addition) {
|
||||
currentLineNumber++;
|
||||
}
|
||||
if (type === RowType.Deletion) {
|
||||
originalLineNumber++;
|
||||
}
|
||||
if (type === RowType.Equal) {
|
||||
originalLineNumber++;
|
||||
currentLineNumber++;
|
||||
}
|
||||
function createRow(text: string, type: RowType): Row {
|
||||
if (type === RowType.Addition) {
|
||||
currentLineNumber++;
|
||||
}
|
||||
if (type === RowType.Deletion) {
|
||||
originalLineNumber++;
|
||||
}
|
||||
if (type === RowType.Equal) {
|
||||
originalLineNumber++;
|
||||
currentLineNumber++;
|
||||
}
|
||||
|
||||
return {
|
||||
originalLineNumber,
|
||||
currentLineNumber,
|
||||
tokens: text ? [{ text, className: 'inner-diff' }] : [],
|
||||
type
|
||||
};
|
||||
}
|
||||
return {
|
||||
originalLineNumber,
|
||||
currentLineNumber,
|
||||
tokens: text ? [{ text, className: 'inner-diff' }] : [],
|
||||
type
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function documentMap(lines: readonly string[]): Map<number, number> {
|
||||
const map = new Map<number, number>();
|
||||
for (let pos = 0, lineNo = 0; lineNo < lines.length; lineNo++) {
|
||||
map.set(lineNo + 1, pos);
|
||||
pos += lines[lineNo].length + 1;
|
||||
}
|
||||
return map;
|
||||
const map = new Map<number, number>();
|
||||
for (let pos = 0, lineNo = 0; lineNo < lines.length; lineNo++) {
|
||||
map.set(lineNo + 1, pos);
|
||||
pos += lines[lineNo].length + 1;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
@ -299,30 +299,30 @@
|
||||
</div>
|
||||
{:else}
|
||||
<div id="player-page" class="flex h-full w-full">
|
||||
<div class="flex flex-col h-full w-full">
|
||||
<div class="flex h-full w-full flex-col">
|
||||
{#if fileFilter}
|
||||
<div class="w-full p-2 font-mono text-lg">{fileFilter}</div>
|
||||
{/if}
|
||||
<div class="flex flex-row h-full w-full">
|
||||
<div class="flex h-full w-full flex-row">
|
||||
<div id="left" class="flex h-full w-20 flex-shrink-0 flex-col p-2">
|
||||
<div class="overflow-y-auto">
|
||||
{#each Object.entries(sessionDays) as [day, sessions]}
|
||||
{#if day == currentDay}
|
||||
<div
|
||||
class="mb-2 flex cursor-pointer flex-col rounded bg-gb-700 border border-zinc-500 p-2 text-center text-white shadow"
|
||||
class="mb-2 flex cursor-pointer flex-col rounded border border-zinc-500 bg-gb-700 p-2 text-center text-white shadow"
|
||||
on:keydown={handleKey}
|
||||
on:click={selectDay(day)}
|
||||
>
|
||||
<div class="font-bold text-lg">{ymdToDay(day)}</div>
|
||||
<div class="text-lg font-bold">{ymdToDay(day)}</div>
|
||||
<div class="">{ymdToMonth(day)}</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div
|
||||
class="mb-2 flex cursor-pointer flex-col rounded bg-gb-800 border border-zinc-600 p-2 text-center shadow"
|
||||
class="mb-2 flex cursor-pointer flex-col rounded border border-zinc-600 bg-gb-800 p-2 text-center shadow"
|
||||
on:keydown={handleKey}
|
||||
on:click={selectDay(day)}
|
||||
>
|
||||
<div class="font-bold text-lg">{ymdToDay(day)}</div>
|
||||
<div class="text-lg font-bold">{ymdToDay(day)}</div>
|
||||
<div class="">{ymdToMonth(day)}</div>
|
||||
</div>
|
||||
{/if}
|
||||
@ -330,11 +330,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="right" class="w-80 xl:w-96 flex-shrink-0 p-2">
|
||||
<div class="border border-gb-700 bg-gb-900 rounded-t h-full overflow-auto">
|
||||
<div id="right" class="w-80 flex-shrink-0 p-2 xl:w-96">
|
||||
<div class="h-full overflow-auto rounded-t border border-gb-700 bg-gb-900">
|
||||
<div class="flex flex-row justify-between bg-gb-700">
|
||||
<div class="font-zinc-100 text-lg p-3">
|
||||
<div class="flex flex-row space-x-2 items-center">
|
||||
<div class="font-zinc-100 p-3 text-lg">
|
||||
<div class="flex flex-row items-center space-x-2">
|
||||
<div>Activities</div>
|
||||
{#if dayPlaylist[currentDay] !== undefined}
|
||||
<div class="text-sm text-zinc-400">
|
||||
@ -351,7 +351,7 @@
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-6 h-6"
|
||||
class="h-6 w-6"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
@ -363,21 +363,21 @@
|
||||
{/if}
|
||||
</div>
|
||||
{#if dayPlaylist[currentDay] !== undefined}
|
||||
<div class="flex flex-col bg-gb-900 h-full p-2 space-y-2">
|
||||
<div class="flex h-full flex-col space-y-2 bg-gb-900 p-2">
|
||||
{#each dayPlaylist[currentDay].chapters as chapter}
|
||||
{#if currentEdit !== null && currentEdit.sessionId == chapter.session}
|
||||
<div
|
||||
id="currentSession"
|
||||
class="mb-2 rounded border border-gb-700 text-white shadow"
|
||||
>
|
||||
<div class="flex flex-row justify-between px-3 pt-3 bg-gb-800">
|
||||
<div class="flex flex-row justify-between bg-gb-800 px-3 pt-3">
|
||||
<div class="">{dateRange(chapter)}</div>
|
||||
<div>
|
||||
{Math.round(chapter.totalDurationMs / 1000 / 60)} min
|
||||
</div>
|
||||
</div>
|
||||
{#if chapter.files}
|
||||
<div class="flex flex-row justify-between px-3 pb-3 bg-gb-800">
|
||||
<div class="flex flex-row justify-between bg-gb-800 px-3 pb-3">
|
||||
<div>{Object.entries(chapter.files).length} files</div>
|
||||
</div>
|
||||
<div class="bg-zinc-800 p-2 pb-3">
|
||||
@ -431,7 +431,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div id="info" class="p-2 bg-zinc-800 rounded-lg mx-4">
|
||||
<div id="info" class="mx-4 rounded-lg bg-zinc-800 p-2">
|
||||
{#if dayPlaylist[currentDay] !== undefined}
|
||||
<div class="flex flex-row justify-between">
|
||||
<div>{dayPlaylist[currentDay].chapters.length} sessions</div>
|
||||
|
@ -13,16 +13,16 @@ const config = {
|
||||
lg: '15px',
|
||||
xl: '22px',
|
||||
'2xl': '26px',
|
||||
'3xl': '30px',
|
||||
'3xl': '30px'
|
||||
},
|
||||
extend: {
|
||||
colors: {
|
||||
'gb': {
|
||||
gb: {
|
||||
700: '#52525B',
|
||||
800: '#3B3B3F',
|
||||
900: '#2F2F33',
|
||||
},
|
||||
},
|
||||
900: '#2F2F33'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user