diff --git a/src/ui/js/diff2html-ui-base.ts b/src/ui/js/diff2html-ui-base.ts
index 031d008..20b10e8 100644
--- a/src/ui/js/diff2html-ui-base.ts
+++ b/src/ui/js/diff2html-ui-base.ts
@@ -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().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;
+ }
}
diff --git a/src/ui/js/highlight.js-helpers.ts b/src/ui/js/highlight.js-helpers.ts
index 24e9a38..f1fdccc 100644
--- a/src/ui/js/highlight.js-helpers.ts
+++ b/src/ui/js/highlight.js-helpers.ts
@@ -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()
+ .map.call(node.attributes, attr => `${attr.nodeName}="${escape(attr.value)}"`)
.join(' ')}>`;
}
diff --git a/website/templates/pages/demo/demo.ts b/website/templates/pages/demo/demo.ts
index 82010ca..2739fd2 100644
--- a/website/templates/pages/demo/demo.ts
+++ b/website/templates/pages/demo/demo.ts
@@ -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'),
},
};