diff --git a/tailwind.config.ts b/tailwind.config.ts index 624ae47a5c..8693208e13 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -37,7 +37,7 @@ export default { './{build,models,modules,routers,services}/**/*.go', './templates/**/*.tmpl', './web_src/js/**/*.{ts,js,vue}', - ].filter(Boolean), + ].filter(Boolean as unknown as (x: T | boolean) => x is T), blocklist: [ // classes that don't work without CSS variables from "@tailwind base" which we don't use 'transform', 'shadow', 'ring', 'blur', 'grayscale', 'invert', '!invert', 'filter', '!filter', diff --git a/tests/e2e/utils_e2e.ts b/tests/e2e/utils_e2e.ts index 3e92e0d3c2..0973f0838c 100644 --- a/tests/e2e/utils_e2e.ts +++ b/tests/e2e/utils_e2e.ts @@ -33,15 +33,15 @@ export async function login_user(browser: Browser, workerInfo: WorkerInfo, user: } export async function load_logged_in_context(browser: Browser, workerInfo: WorkerInfo, user: string) { - let context; try { - context = await browser.newContext({storageState: `${ARTIFACTS_PATH}/state-${user}-${workerInfo.workerIndex}.json`}); + return await browser.newContext({storageState: `${ARTIFACTS_PATH}/state-${user}-${workerInfo.workerIndex}.json`}); } catch (err) { if (err.code === 'ENOENT') { throw new Error(`Could not find state for '${user}'. Did you call login_user(browser, workerInfo, '${user}') in test.beforeAll()?`); + } else { + throw err; } } - return context; } export async function save_visual(page: Page) { diff --git a/tools/generate-svg.ts b/tools/generate-svg.ts index b1dc46d451..c18eacc86f 100755 --- a/tools/generate-svg.ts +++ b/tools/generate-svg.ts @@ -47,6 +47,10 @@ function processAssetsSvgFiles(pattern: string, opts: Opts = {}) { return glob(pattern).map((path) => processAssetsSvgFile(path, opts)); } +function lowercaseKeys(obj: Record) { + return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key.toLowerCase(), value])); +} + async function processMaterialFileIcons() { const paths = glob('node_modules/material-icon-theme/icons/*.svg'); const svgSymbols: Record = {}; @@ -76,18 +80,30 @@ async function processMaterialFileIcons() { // * https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers // * https://github.com/microsoft/vscode/tree/1.98.0/extensions delete iconRules.iconDefinitions; - for (const [k, v] of Object.entries(iconRules.fileNames)) iconRules.fileNames[k.toLowerCase()] = v; - for (const [k, v] of Object.entries(iconRules.folderNames)) iconRules.folderNames[k.toLowerCase()] = v; - for (const [k, v] of Object.entries(iconRules.fileExtensions)) iconRules.fileExtensions[k.toLowerCase()] = v; + + if (iconRules.fileNames) { + iconRules.fileNames = lowercaseKeys(iconRules.fileNames); + } + if (iconRules.folderNames) { + iconRules.folderNames = lowercaseKeys(iconRules.folderNames); + } + if (iconRules.fileExtensions) { + iconRules.fileExtensions = lowercaseKeys(iconRules.fileExtensions); + } + // Use VSCode's "Language ID" mapping from its extensions for (const [_, langIdExtMap] of Object.entries(vscodeExtensions)) { for (const [langId, names] of Object.entries(langIdExtMap)) { for (const name of names) { const nameLower = name.toLowerCase(); if (nameLower[0] === '.') { - iconRules.fileExtensions[nameLower.substring(1)] ??= langId; + if (iconRules.fileExtensions) { + iconRules.fileExtensions[nameLower.substring(1)] ??= langId; + } } else { - iconRules.fileNames[nameLower] ??= langId; + if (iconRules.fileNames) { + iconRules.fileNames[nameLower] ??= langId; + } } } } diff --git a/tsconfig.json b/tsconfig.json index 3bc6065647..1daf4b7233 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -40,6 +40,7 @@ "strictBindCallApply": true, "strictBuiltinIteratorReturn": true, "strictFunctionTypes": true, + "strictNullChecks": false, "stripInternal": true, "verbatimModuleSyntax": true, "types": [ diff --git a/web_src/js/features/repo-issue.ts b/web_src/js/features/repo-issue.ts index 58274b95c0..bacdae5350 100644 --- a/web_src/js/features/repo-issue.ts +++ b/web_src/js/features/repo-issue.ts @@ -261,7 +261,7 @@ export function initRepoPullRequestReview() { if (commentDiv) { // get the name of the parent id const groupID = commentDiv.closest('div[id^="code-comments-"]')?.getAttribute('id'); - if (groupID && groupID.startsWith('code-comments-')) { + if (groupID?.startsWith('code-comments-')) { const id = groupID.slice(14); const ancestorDiffBox = commentDiv.closest('.diff-file-box'); diff --git a/web_src/js/features/repo-settings.ts b/web_src/js/features/repo-settings.ts index 43a236b0c6..7a8df8af0f 100644 --- a/web_src/js/features/repo-settings.ts +++ b/web_src/js/features/repo-settings.ts @@ -101,7 +101,7 @@ function initRepoSettingsBranches() { // show the `Matched` mark for the status checks that match the pattern const markMatchedStatusChecks = () => { const patterns = (document.querySelector('#status_check_contexts').value || '').split(/[\r\n]+/); - const validPatterns = patterns.map((item) => item.trim()).filter(Boolean); + const validPatterns = patterns.map((item) => item.trim()).filter(Boolean as unknown as (x: T | boolean) => x is T); const marks = document.querySelectorAll('.status-check-matched-mark'); for (const el of marks) { diff --git a/web_src/js/svg.ts b/web_src/js/svg.ts index 2ad9bffd51..3d3e653072 100644 --- a/web_src/js/svg.ts +++ b/web_src/js/svg.ts @@ -181,7 +181,7 @@ export function svg(name: SvgName, size = 16, classNames?: string | string[]): s svgNode.setAttribute('width', String(size)); svgNode.setAttribute('height', String(size)); } - if (className) svgNode.classList.add(...className.split(/\s+/).filter(Boolean)); + if (className) svgNode.classList.add(...className.split(/\s+/).filter(Boolean as unknown as (x: T | boolean) => x is T)); return serializeXml(svgNode); } diff --git a/webpack.config.ts b/webpack.config.ts index 9f31c01e88..f0528a7331 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -30,7 +30,7 @@ const isProduction = env.NODE_ENV !== 'development'; // false - all disabled let sourceMaps; if ('ENABLE_SOURCEMAP' in env) { - sourceMaps = ['true', 'false'].includes(env.ENABLE_SOURCEMAP) ? env.ENABLE_SOURCEMAP : 'reduced'; + sourceMaps = ['true', 'false'].includes(env.ENABLE_SOURCEMAP || '') ? env.ENABLE_SOURCEMAP : 'reduced'; } else { sourceMaps = isProduction ? 'reduced' : 'true'; } @@ -95,7 +95,7 @@ export default { path: fileURLToPath(new URL('public/assets', import.meta.url)), filename: () => 'js/[name].js', chunkFilename: ({chunk}) => { - const language = (/monaco.*languages?_.+?_(.+?)_/.exec(String(chunk.id)) || [])[1]; + const language = (/monaco.*languages?_.+?_(.+?)_/.exec(String(chunk?.id)) || [])[1]; return `js/${language ? `monaco-language-${language.toLowerCase()}` : `[name]`}.[contenthash:8].js`; }, }, @@ -270,7 +270,7 @@ export default { excludeAssets: [ /^js\/monaco-language-.+\.js$/, !isProduction && /^licenses.txt$/, - ].filter(Boolean), + ].filter(Boolean as unknown as (x: T | boolean) => x is T), groupAssetsByChunk: false, groupAssetsByEmitStatus: false, groupAssetsByInfo: false,