clean: Remove as type casts and use runtime typechecks with fallback when possible
This commit is contained in:
parent
fe8365bcc1
commit
076e14400b
3 changed files with 74 additions and 35 deletions
|
|
@ -52,10 +52,13 @@ export class Diff2HtmlUI {
|
|||
|
||||
synchronisedScroll(): void {
|
||||
this.targetElement.querySelectorAll('.d2h-file-wrapper').forEach(wrapper => {
|
||||
const [left, right] = [].slice.call(wrapper.querySelectorAll('.d2h-file-side-diff')) as HTMLElement[];
|
||||
const [left, right] = Array<Element>().slice.call(wrapper.querySelectorAll('.d2h-file-side-diff'));
|
||||
|
||||
if (left === undefined || right === undefined) return;
|
||||
|
||||
const onScroll = (event: Event): void => {
|
||||
if (event === null || event.target === null) return;
|
||||
|
||||
if (event.target === left) {
|
||||
right.scrollTop = left.scrollTop;
|
||||
right.scrollLeft = left.scrollLeft;
|
||||
|
|
@ -70,29 +73,28 @@ export class Diff2HtmlUI {
|
|||
}
|
||||
|
||||
fileListToggle(startVisible: boolean): void {
|
||||
const hashTag = this.getHashTag();
|
||||
|
||||
const showBtn = this.targetElement.querySelector('.d2h-show') as HTMLElement;
|
||||
const hideBtn = this.targetElement.querySelector('.d2h-hide') as HTMLElement;
|
||||
const fileList = this.targetElement.querySelector('.d2h-file-list') as HTMLElement;
|
||||
const showBtn: HTMLElement | null = this.targetElement.querySelector('d2h-show');
|
||||
const hideBtn: HTMLElement | null = this.targetElement.querySelector('.d2h-hide');
|
||||
const fileList: HTMLElement | null = this.targetElement.querySelector('.d2h-file-list');
|
||||
|
||||
if (showBtn === null || hideBtn === null || fileList === null) return;
|
||||
|
||||
function show(): void {
|
||||
const show: () => void = () => {
|
||||
showBtn.style.display = 'none';
|
||||
hideBtn.style.display = 'inline';
|
||||
fileList.style.display = 'block';
|
||||
}
|
||||
};
|
||||
|
||||
function hide(): void {
|
||||
const hide: () => void = () => {
|
||||
showBtn.style.display = 'inline';
|
||||
hideBtn.style.display = 'none';
|
||||
fileList.style.display = 'none';
|
||||
}
|
||||
};
|
||||
|
||||
showBtn.addEventListener('click', () => show());
|
||||
hideBtn.addEventListener('click', () => hide());
|
||||
|
||||
const hashTag = this.getHashTag();
|
||||
if (hashTag === 'files-summary-show') show();
|
||||
else if (hashTag === 'files-summary-hide') hide();
|
||||
else if (startVisible) show();
|
||||
|
|
@ -117,11 +119,11 @@ export class Diff2HtmlUI {
|
|||
if (this.hljs === null) return;
|
||||
|
||||
const text = line.textContent;
|
||||
const lineParent = line.parentNode as HTMLElement;
|
||||
const lineParent = line.parentNode;
|
||||
|
||||
if (lineParent === null || text === null) return;
|
||||
if (text === null || lineParent === null || !this.isElement(lineParent)) return;
|
||||
|
||||
const lineState = lineParent.className.indexOf('d2h-del') !== -1 ? oldLinesState : newLinesState;
|
||||
const lineState = lineParent.classList.contains('d2h-del') ? oldLinesState : newLinesState;
|
||||
|
||||
const language = file.getAttribute('data-lang');
|
||||
const result =
|
||||
|
|
@ -130,9 +132,9 @@ export class Diff2HtmlUI {
|
|||
: this.hljs.highlightAuto(text);
|
||||
|
||||
if (this.instanceOfIHighlightResult(result)) {
|
||||
if (lineParent.className.indexOf('d2h-del') !== -1) {
|
||||
if (lineParent.classList.contains('d2h-del')) {
|
||||
oldLinesState = result.top;
|
||||
} else if (lineParent.className.indexOf('d2h-ins') !== -1) {
|
||||
} else if (lineParent.classList.contains('d2h-ins')) {
|
||||
newLinesState = result.top;
|
||||
} else {
|
||||
oldLinesState = result.top;
|
||||
|
|
@ -159,18 +161,15 @@ export class Diff2HtmlUI {
|
|||
const diffTable = body.getElementsByClassName('d2h-diff-table')[0];
|
||||
|
||||
diffTable.addEventListener('mousedown', event => {
|
||||
if (event === null || event.target === null) return;
|
||||
|
||||
const mouseEvent = event as MouseEvent;
|
||||
const target = mouseEvent.target as HTMLElement;
|
||||
const table = target.closest('.d2h-diff-table');
|
||||
if (event === null || !this.isElement(event.target)) return;
|
||||
|
||||
const table = event.target.closest('.d2h-diff-table');
|
||||
if (table !== null) {
|
||||
if (target.closest('.d2h-code-line,.d2h-code-side-line') !== null) {
|
||||
if (event.target.closest('.d2h-code-line,.d2h-code-side-line') !== null) {
|
||||
table.classList.remove('selecting-left');
|
||||
table.classList.add('selecting-right');
|
||||
this.currentSelectionColumnId = 1;
|
||||
} else if (target.closest('.d2h-code-linenumber,.d2h-code-side-linenumber') !== null) {
|
||||
} else if (event.target.closest('.d2h-code-linenumber,.d2h-code-side-linenumber') !== null) {
|
||||
table.classList.remove('selecting-right');
|
||||
table.classList.add('selecting-left');
|
||||
this.currentSelectionColumnId = 0;
|
||||
|
|
@ -179,8 +178,9 @@ export class Diff2HtmlUI {
|
|||
});
|
||||
|
||||
diffTable.addEventListener('copy', event => {
|
||||
const clipboardEvent = event as ClipboardEvent;
|
||||
const clipboardData = clipboardEvent.clipboardData;
|
||||
if (!this.isClipboardEvent(event)) return;
|
||||
|
||||
const clipboardData = event.clipboardData;
|
||||
const text = this.getSelectedText();
|
||||
|
||||
if (clipboardData === null || text === undefined) return;
|
||||
|
|
@ -231,4 +231,12 @@ export class Diff2HtmlUI {
|
|||
|
||||
return text;
|
||||
}
|
||||
|
||||
private isElement(arg?: unknown): arg is Element {
|
||||
return arg !== null && (arg as Element)?.classList !== undefined;
|
||||
}
|
||||
|
||||
private isClipboardEvent(arg?: unknown): arg is ClipboardEvent {
|
||||
return arg !== null && (arg as ClipboardEvent)?.clipboardData !== undefined;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,10 @@ export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], va
|
|||
let result = '';
|
||||
const nodeStack = [];
|
||||
|
||||
function isElement(arg?: unknown): arg is Element {
|
||||
return arg !== null && (arg as Element)?.attributes !== undefined;
|
||||
}
|
||||
|
||||
function selectStream(): NodeEvent[] {
|
||||
if (!original.length || !highlighted.length) {
|
||||
return original.length ? original : highlighted;
|
||||
|
|
@ -88,9 +92,12 @@ export function mergeStreams(original: NodeEvent[], highlighted: NodeEvent[], va
|
|||
}
|
||||
|
||||
function open(node: Node): void {
|
||||
const htmlNode = node as HTMLElement;
|
||||
result += `<${tag(node)} ${[].map
|
||||
.call(htmlNode.attributes, (attr: Attr) => `${attr.nodeName}="${escape(attr.value)}"`)
|
||||
if (!isElement(node)) {
|
||||
throw new Error('Node is not an Element');
|
||||
}
|
||||
|
||||
result += `<${tag(node)} ${Array<Attr>()
|
||||
.map.call(node.attributes, attr => `${attr.nodeName}="${escape(attr.value)}"`)
|
||||
.join(' ')}>`;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -208,6 +208,30 @@ type Elements = {
|
|||
};
|
||||
};
|
||||
|
||||
function isHTMLInputElement(arg?: unknown): arg is HTMLInputElement {
|
||||
return arg !== null && (arg as HTMLInputElement)?.value !== undefined;
|
||||
}
|
||||
|
||||
function getHTMLInputElementById(id: string): HTMLInputElement {
|
||||
const element = document.getElementById(id);
|
||||
|
||||
if (!isHTMLInputElement(element)) {
|
||||
throw new Error(`Could not find html input element with id '${id}'`);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
function getHTMLElementById(id: string): HTMLElement {
|
||||
const element = document.getElementById(id);
|
||||
|
||||
if (element === null) {
|
||||
throw new Error(`Could not find html element with id '${id}'`);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
// Improves browser compatibility
|
||||
require('whatwg-fetch');
|
||||
|
|
@ -226,20 +250,20 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
|
||||
const elements: Elements = {
|
||||
structure: {
|
||||
diffTarget: document.getElementById('url-diff-container') as HTMLElement,
|
||||
diffTarget: getHTMLElementById('url-diff-container'),
|
||||
},
|
||||
url: {
|
||||
input: document.getElementById('url') as HTMLInputElement,
|
||||
button: document.getElementById('url-btn') as HTMLElement,
|
||||
input: getHTMLInputElementById('url'),
|
||||
button: getHTMLElementById('url-btn'),
|
||||
},
|
||||
options: {
|
||||
outputFormat: document.getElementById('diff-url-options-output-format') as HTMLInputElement,
|
||||
matching: document.getElementById('diff-url-options-matching') as HTMLInputElement,
|
||||
wordsThreshold: document.getElementById('diff-url-options-match-words-threshold') as HTMLInputElement,
|
||||
matchingMaxComparisons: document.getElementById('diff-url-options-matching-max-comparisons') as HTMLInputElement,
|
||||
outputFormat: getHTMLInputElementById('diff-url-options-output-format'),
|
||||
matching: getHTMLInputElementById('diff-url-options-matching'),
|
||||
wordsThreshold: getHTMLInputElementById('diff-url-options-match-words-threshold'),
|
||||
matchingMaxComparisons: getHTMLInputElementById('diff-url-options-matching-max-comparisons'),
|
||||
},
|
||||
checkboxes: {
|
||||
drawFileList: document.getElementById('diff-url-options-show-files') as HTMLInputElement,
|
||||
drawFileList: getHTMLInputElementById('diff-url-options-show-files'),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue