1
1
mirror of https://github.com/go-gitea/gitea synced 2025-12-07 13:28:25 +00:00

Enable TypeScript strictNullChecks (#35843)

A big step towards enabling strict mode in Typescript.

There was definitely a good share of potential bugs while refactoring
this. When in doubt, I opted to keep the potentially broken behaviour.
Notably, the `DOMEvent` type is gone, it was broken and we're better of
with type assertions on `e.target`.

---------

Signed-off-by: silverwind <me@silverwind.io>
Signed-off-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
silverwind
2025-12-03 03:13:16 +01:00
committed by GitHub
parent 9f268edd2f
commit 46d7adefe0
108 changed files with 686 additions and 658 deletions

View File

@@ -7,7 +7,6 @@ type ArrayLikeIterable<T> = ArrayLike<T> & Iterable<T>; // for NodeListOf and Ar
type ElementArg = Element | string | ArrayLikeIterable<Element> | ReturnType<typeof $>;
type ElementsCallback<T extends Element> = (el: T) => Promisable<any>;
type ElementsCallbackWithArgs = (el: Element, ...args: any[]) => Promisable<any>;
export type DOMEvent<E extends Event, T extends Element = HTMLElement> = E & {target: Partial<T>;};
function elementsCall(el: ElementArg, func: ElementsCallbackWithArgs, ...args: any[]): ArrayLikeIterable<Element> {
if (typeof el === 'string' || el instanceof String) {
@@ -65,6 +64,7 @@ function applyElemsCallback<T extends Element>(elems: ArrayLikeIterable<T>, fn?:
}
export function queryElemSiblings<T extends Element>(el: Element, selector = '*', fn?: ElementsCallback<T>): ArrayLikeIterable<T> {
if (!el.parentNode) return [];
const elems = Array.from(el.parentNode.children) as T[];
return applyElemsCallback<T>(elems.filter((child: Element) => {
return child !== el && child.matches(selector);
@@ -125,10 +125,10 @@ export function isDocumentFragmentOrElementNode(el: Node) {
export function autosize(textarea: HTMLTextAreaElement, {viewportMarginBottom = 0}: {viewportMarginBottom?: number} = {}) {
let isUserResized = false;
// lastStyleHeight and initialStyleHeight are CSS values like '100px'
let lastMouseX: number;
let lastMouseY: number;
let lastStyleHeight: string;
let initialStyleHeight: string;
let lastMouseX: number | undefined;
let lastMouseY: number | undefined;
let lastStyleHeight: string | undefined;
let initialStyleHeight: string | undefined;
function onUserResize(event: MouseEvent) {
if (isUserResized) return;
@@ -153,7 +153,8 @@ export function autosize(textarea: HTMLTextAreaElement, {viewportMarginBottom =
el = el.offsetParent as HTMLTextAreaElement;
}
const top = offsetTop - document.defaultView.scrollY;
const scrollY = document.defaultView ? document.defaultView.scrollY : 0;
const top = offsetTop - scrollY;
const bottom = document.documentElement.clientHeight - (top + textarea.offsetHeight);
return {top, bottom};
}
@@ -265,10 +266,10 @@ export function submitEventSubmitter(e: any) {
return needSubmitEventPolyfill ? (e.target._submitter || null) : e.submitter;
}
function submitEventPolyfillListener(e: DOMEvent<Event>) {
const form = e.target.closest('form');
function submitEventPolyfillListener(e: Event) {
const form = (e.target as HTMLElement).closest('form');
if (!form) return;
form._submitter = e.target.closest('button:not([type]), button[type="submit"], input[type="submit"]');
form._submitter = (e.target as HTMLElement).closest('button:not([type]), button[type="submit"], input[type="submit"]');
}
export function initSubmitEventPolyfill() {
@@ -283,7 +284,7 @@ export function isElemVisible(el: HTMLElement): boolean {
// This function DOESN'T account for all possible visibility scenarios, its behavior is covered by the tests of "querySingleVisibleElem"
if (!el) return false;
// checking el.style.display is not necessary for browsers, but it is required by some tests with happy-dom because happy-dom doesn't really do layout
return !el.classList.contains('tw-hidden') && (el.offsetWidth || el.offsetHeight || el.getClientRects().length) && el.style.display !== 'none';
return Boolean(!el.classList.contains('tw-hidden') && (el.offsetWidth || el.offsetHeight || el.getClientRects().length) && el.style.display !== 'none');
}
export function createElementFromHTML<T extends HTMLElement>(htmlString: string): T {
@@ -293,14 +294,14 @@ export function createElementFromHTML<T extends HTMLElement>(htmlString: string)
if (htmlString.startsWith('<tr')) {
const container = document.createElement('table');
container.innerHTML = htmlString;
return container.querySelector<T>('tr');
return container.querySelector<T>('tr')!;
}
const div = document.createElement('div');
div.innerHTML = htmlString;
return div.firstChild as T;
}
export function createElementFromAttrs(tagName: string, attrs: Record<string, any>, ...children: (Node | string)[]): HTMLElement {
export function createElementFromAttrs(tagName: string, attrs: Record<string, any> | null, ...children: (Node | string)[]): HTMLElement {
const el = document.createElement(tagName);
for (const [key, value] of Object.entries(attrs || {})) {
if (value === undefined || value === null) continue;