Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6a288b7
Enable `strictNullChecks`
silverwind Nov 3, 2025
07e9577
fix lint
silverwind Nov 3, 2025
cdfdbd0
Merge branch 'main' into strictNullChecks2
silverwind Nov 5, 2025
7bdbd37
Merge branch 'main' into strictNullChecks2
silverwind Nov 10, 2025
18ef667
Merge branch 'main' into strictNullChecks2
silverwind Nov 27, 2025
05f9a6b
apply type narrowing in isObject
silverwind Dec 2, 2025
d6dc25a
Merge remote-tracking branch 'origin/main' into strictNullChecks2
silverwind Dec 2, 2025
8144b6f
adjust a few cases in RepoFileSearch.vue
silverwind Dec 2, 2025
9c332a1
Update web_src/js/features/user-auth-webauthn.ts
silverwind Dec 2, 2025
d5240a0
lint
silverwind Dec 2, 2025
16e24d8
fix TODO
silverwind Dec 2, 2025
5442aa3
fix elRoot cases
silverwind Dec 2, 2025
922568b
remove a few more !
silverwind Dec 2, 2025
e67240f
remove more !
silverwind Dec 2, 2025
36b5359
remove more !
silverwind Dec 2, 2025
c401dd0
fix
silverwind Dec 2, 2025
2e12b5e
final fixes
silverwind Dec 2, 2025
ba54ee5
Merge branch 'main' into strictNullChecks2
silverwind Dec 2, 2025
057536b
enable @typescript-eslint/no-redundant-type-constituents
silverwind Dec 2, 2025
187d63b
use type assertions to eliminate null
silverwind Dec 3, 2025
a94b9cb
revert remaining changes
silverwind Dec 3, 2025
32de412
Update web_src/js/components/RepoActionView.vue
silverwind Dec 3, 2025
f8ac948
remove unnecessary generics
silverwind Dec 3, 2025
b4d7aa6
clean up
wxiaoguang Dec 3, 2025
66c304a
remove useless assignement to null
silverwind Dec 3, 2025
6611c13
clean up: addLink
wxiaoguang Dec 3, 2025
760fbd0
fix comment
wxiaoguang Dec 3, 2025
9eb96ff
remove
silverwind Dec 3, 2025
64b263d
fix review comments
silverwind Dec 3, 2025
de80727
Update web_src/js/features/repo-issue.ts
wxiaoguang Dec 3, 2025
4a488d0
use ?
silverwind Dec 3, 2025
1c034eb
Update web_src/js/markup/codecopy.ts
wxiaoguang Dec 3, 2025
66b20f9
fix number check
silverwind Dec 3, 2025
d764899
Update web_src/js/modules/tippy.ts
wxiaoguang Dec 3, 2025
0bda971
remove if
silverwind Dec 3, 2025
ac5efc1
Merge branch 'main' into strictNullChecks2
GiteaBot Dec 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eslint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export default defineConfig([
'@typescript-eslint/no-non-null-asserted-optional-chain': [2],
'@typescript-eslint/no-non-null-assertion': [0],
'@typescript-eslint/no-redeclare': [0],
'@typescript-eslint/no-redundant-type-constituents': [0], // rule does not properly work without strickNullChecks
'@typescript-eslint/no-redundant-type-constituents': [2],
'@typescript-eslint/no-require-imports': [2],
'@typescript-eslint/no-restricted-imports': [0],
'@typescript-eslint/no-restricted-types': [0],
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"strictBindCallApply": true,
"strictBuiltinIteratorReturn": true,
"strictFunctionTypes": true,
"strictNullChecks": false,
"strictNullChecks": true,
"stripInternal": true,
"verbatimModuleSyntax": true,
"types": [
Expand Down
2 changes: 1 addition & 1 deletion web_src/js/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function showGlobalErrorMessage(msg: string, msgType: Intent = 'error') {
const msgCount = Number(msgDiv.getAttribute(`data-global-error-msg-count`)) + 1;
msgDiv.setAttribute(`data-global-error-msg-compact`, msgCompact);
msgDiv.setAttribute(`data-global-error-msg-count`, msgCount.toString());
msgDiv.querySelector('.ui.message').textContent = msg + (msgCount > 1 ? ` (${msgCount})` : '');
msgDiv.querySelector('.ui.message')!.textContent = msg + (msgCount > 1 ? ` (${msgCount})` : '');
msgContainer.prepend(msgDiv);
}

Expand Down
4 changes: 2 additions & 2 deletions web_src/js/components/ActivityHeatmap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {onMounted, shallowRef} from 'vue';
import type {Value as HeatmapValue, Locale as HeatmapLocale} from '@silverwind/vue3-calendar-heatmap';

defineProps<{
values?: HeatmapValue[];
values: HeatmapValue[];
locale: {
textTotalContributions: string;
heatMapLocale: Partial<HeatmapLocale>;
Expand All @@ -28,7 +28,7 @@ const endDate = shallowRef(new Date());

onMounted(() => {
// work around issue with first legend color being rendered twice and legend cut off
const legend = document.querySelector<HTMLElement>('.vch__external-legend-wrapper');
const legend = document.querySelector<HTMLElement>('.vch__external-legend-wrapper')!;
legend.setAttribute('viewBox', '12 0 80 10');
legend.style.marginRight = '-12px';
});
Expand Down
4 changes: 3 additions & 1 deletion web_src/js/components/ContextPopup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ const props = defineProps<{
}>();

const loading = shallowRef(false);
const issue = shallowRef<Issue>(null);
const issue = shallowRef<Issue | null>(null);
const renderedLabels = shallowRef('');
const errorMessage = shallowRef('');

const createdAt = computed(() => {
if (!issue?.value) return '';
return new Date(issue.value.created_at).toLocaleDateString(undefined, {year: 'numeric', month: 'short', day: 'numeric'});
});

const body = computed(() => {
if (!issue?.value) return '';
const body = issue.value.body.replace(/\n+/g, ' ');
return body.length > 85 ? `${body.substring(0, 85)}…` : body;
});
Expand Down
4 changes: 2 additions & 2 deletions web_src/js/components/DashboardRepoList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,9 @@ export default defineComponent({
},

mounted() {
const el = document.querySelector('#dashboard-repo-list');
const el = document.querySelector('#dashboard-repo-list')!;
this.changeReposFilter(this.reposFilter);
fomanticQuery(el.querySelector('.ui.dropdown')).dropdown();
fomanticQuery(el.querySelector('.ui.dropdown')!).dropdown();

this.textArchivedFilterTitles = {
'archived': this.textShowOnlyArchived,
Expand Down
10 changes: 5 additions & 5 deletions web_src/js/components/DiffCommitSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type CommitListResult = {
export default defineComponent({
components: {SvgIcon},
data: () => {
const el = document.querySelector('#diff-commit-select');
const el = document.querySelector('#diff-commit-select')!;
return {
menuVisible: false,
isLoading: false,
Expand All @@ -35,7 +35,7 @@ export default defineComponent({
mergeBase: el.getAttribute('data-merge-base'),
commits: [] as Array<Commit>,
hoverActivated: false,
lastReviewCommitSha: '',
lastReviewCommitSha: '' as string | null,
uniqueIdMenu: generateElemId('diff-commit-selector-menu-'),
uniqueIdShowAll: generateElemId('diff-commit-selector-show-all-'),
};
Expand Down Expand Up @@ -165,7 +165,7 @@ export default defineComponent({
},
/** Called when user clicks on since last review */
changesSinceLastReviewClick() {
window.location.assign(`${this.issueLink}/files/${this.lastReviewCommitSha}..${this.commits.at(-1).id}${this.queryParams}`);
window.location.assign(`${this.issueLink}/files/${this.lastReviewCommitSha}..${this.commits.at(-1)!.id}${this.queryParams}`);
},
/** Clicking on a single commit opens this specific commit */
commitClicked(commitId: string, newWindow = false) {
Expand Down Expand Up @@ -193,7 +193,7 @@ export default defineComponent({
// find all selected commits and generate a link
const firstSelected = this.commits.findIndex((x) => x.selected);
const lastSelected = this.commits.findLastIndex((x) => x.selected);
let beforeCommitID: string;
let beforeCommitID: string | null = null;
if (firstSelected === 0) {
beforeCommitID = this.mergeBase;
} else {
Expand All @@ -204,7 +204,7 @@ export default defineComponent({
if (firstSelected === lastSelected) {
// if the start and end are the same, we show this single commit
window.location.assign(`${this.issueLink}/commits/${afterCommitID}${this.queryParams}`);
} else if (beforeCommitID === this.mergeBase && afterCommitID === this.commits.at(-1).id) {
} else if (beforeCommitID === this.mergeBase && afterCommitID === this.commits.at(-1)!.id) {
// if the first commit is selected and the last commit is selected, we show all commits
window.location.assign(`${this.issueLink}/files${this.queryParams}`);
} else {
Expand Down
12 changes: 6 additions & 6 deletions web_src/js/components/DiffFileTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ const store = diffTreeStore();
onMounted(() => {
// Default to true if unset
store.fileTreeIsVisible = localStorage.getItem(LOCAL_STORAGE_KEY) !== 'false';
document.querySelector('.diff-toggle-file-tree-button').addEventListener('click', toggleVisibility);
document.querySelector('.diff-toggle-file-tree-button')!.addEventListener('click', toggleVisibility);

hashChangeListener();
window.addEventListener('hashchange', hashChangeListener);
});

onUnmounted(() => {
document.querySelector('.diff-toggle-file-tree-button').removeEventListener('click', toggleVisibility);
document.querySelector('.diff-toggle-file-tree-button')!.removeEventListener('click', toggleVisibility);
window.removeEventListener('hashchange', hashChangeListener);
});

Expand All @@ -33,7 +33,7 @@ function expandSelectedFile() {
if (store.selectedItem) {
const box = document.querySelector(store.selectedItem);
const folded = box?.getAttribute('data-folded') === 'true';
if (folded) setFileFolding(box, box.querySelector('.fold-file'), false);
if (folded) setFileFolding(box, box.querySelector('.fold-file')!, false);
}
}

Expand All @@ -48,10 +48,10 @@ function updateVisibility(visible: boolean) {
}

function updateState(visible: boolean) {
const btn = document.querySelector('.diff-toggle-file-tree-button');
const btn = document.querySelector('.diff-toggle-file-tree-button')!;
const [toShow, toHide] = btn.querySelectorAll('.icon');
const tree = document.querySelector('#diff-file-tree');
const newTooltip = btn.getAttribute(visible ? 'data-hide-text' : 'data-show-text');
const tree = document.querySelector('#diff-file-tree')!;
const newTooltip = btn.getAttribute(visible ? 'data-hide-text' : 'data-show-text')!;
btn.setAttribute('data-tooltip-content', newTooltip);
toggleElem(tree, visible);
toggleElem(toShow, !visible);
Expand Down
4 changes: 2 additions & 2 deletions web_src/js/components/RepoActionView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ export default defineComponent({
}

// auto-scroll to the last log line of the last step
let autoScrollJobStepElement: HTMLElement;
let autoScrollJobStepElement: HTMLElement | undefined;
for (let stepIndex = 0; stepIndex < this.currentJob.steps.length; stepIndex++) {
if (!autoScrollStepIndexes.get(stepIndex)) continue;
autoScrollJobStepElement = this.getJobStepLogsContainer(stepIndex);
Expand Down Expand Up @@ -468,7 +468,7 @@ export default defineComponent({
}
const logLine = this.elStepsContainer().querySelector(selectedLogStep);
if (!logLine) return;
logLine.querySelector<HTMLAnchorElement>('.line-num').click();
logLine.querySelector<HTMLAnchorElement>('.line-num')!.click();
},
},
});
Expand Down
6 changes: 3 additions & 3 deletions web_src/js/components/RepoActivityTopAuthors.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts" setup>
// @ts-expect-error - module exports no types
import {VueBarGraph} from 'vue-bar-graph';
import {computed, onMounted, shallowRef, useTemplateRef} from 'vue';
import {computed, onMounted, shallowRef, useTemplateRef, type ShallowRef} from 'vue';

const colors = shallowRef({
barColor: 'green',
Expand Down Expand Up @@ -41,8 +41,8 @@ const graphWidth = computed(() => {
return activityTopAuthors.length * 40;
});

const styleElement = useTemplateRef('styleElement');
const altStyleElement = useTemplateRef('altStyleElement');
const styleElement = useTemplateRef('styleElement') as Readonly<ShallowRef<HTMLDivElement>>;
const altStyleElement = useTemplateRef('altStyleElement') as Readonly<ShallowRef<HTMLDivElement>>;

onMounted(() => {
const refStyle = window.getComputedStyle(styleElement.value);
Expand Down
45 changes: 24 additions & 21 deletions web_src/js/components/RepoBranchTagSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ type TabLoadingStates = Record<SelectedTab, '' | 'loading' | 'done'>
export default defineComponent({
components: {SvgIcon},
props: {
elRoot: HTMLElement,
elRoot: {
type: HTMLElement,
required: true,
},
},
data() {
const shouldShowTabBranches = this.elRoot.getAttribute('data-show-tab-branches') === 'true';
Expand All @@ -33,28 +36,28 @@ export default defineComponent({
activeItemIndex: 0,
tabLoadingStates: {} as TabLoadingStates,

textReleaseCompare: this.elRoot.getAttribute('data-text-release-compare'),
textBranches: this.elRoot.getAttribute('data-text-branches'),
textTags: this.elRoot.getAttribute('data-text-tags'),
textFilterBranch: this.elRoot.getAttribute('data-text-filter-branch'),
textFilterTag: this.elRoot.getAttribute('data-text-filter-tag'),
textDefaultBranchLabel: this.elRoot.getAttribute('data-text-default-branch-label'),
textCreateTag: this.elRoot.getAttribute('data-text-create-tag'),
textCreateBranch: this.elRoot.getAttribute('data-text-create-branch'),
textCreateRefFrom: this.elRoot.getAttribute('data-text-create-ref-from'),
textNoResults: this.elRoot.getAttribute('data-text-no-results'),
textViewAllBranches: this.elRoot.getAttribute('data-text-view-all-branches'),
textViewAllTags: this.elRoot.getAttribute('data-text-view-all-tags'),
textReleaseCompare: this.elRoot.getAttribute('data-text-release-compare')!,
textBranches: this.elRoot.getAttribute('data-text-branches')!,
textTags: this.elRoot.getAttribute('data-text-tags')!,
textFilterBranch: this.elRoot.getAttribute('data-text-filter-branch')!,
textFilterTag: this.elRoot.getAttribute('data-text-filter-tag')!,
textDefaultBranchLabel: this.elRoot.getAttribute('data-text-default-branch-label')!,
textCreateTag: this.elRoot.getAttribute('data-text-create-tag')!,
textCreateBranch: this.elRoot.getAttribute('data-text-create-branch')!,
textCreateRefFrom: this.elRoot.getAttribute('data-text-create-ref-from')!,
textNoResults: this.elRoot.getAttribute('data-text-no-results')!,
textViewAllBranches: this.elRoot.getAttribute('data-text-view-all-branches')!,
textViewAllTags: this.elRoot.getAttribute('data-text-view-all-tags')!,

currentRepoDefaultBranch: this.elRoot.getAttribute('data-current-repo-default-branch'),
currentRepoLink: this.elRoot.getAttribute('data-current-repo-link'),
currentTreePath: this.elRoot.getAttribute('data-current-tree-path'),
currentRepoDefaultBranch: this.elRoot.getAttribute('data-current-repo-default-branch')!,
currentRepoLink: this.elRoot.getAttribute('data-current-repo-link')!,
currentTreePath: this.elRoot.getAttribute('data-current-tree-path')!,
currentRefType: this.elRoot.getAttribute('data-current-ref-type') as GitRefType,
currentRefShortName: this.elRoot.getAttribute('data-current-ref-short-name'),
currentRefShortName: this.elRoot.getAttribute('data-current-ref-short-name')!,

refLinkTemplate: this.elRoot.getAttribute('data-ref-link-template'),
refFormActionTemplate: this.elRoot.getAttribute('data-ref-form-action-template'),
dropdownFixedText: this.elRoot.getAttribute('data-dropdown-fixed-text'),
refLinkTemplate: this.elRoot.getAttribute('data-ref-link-template')!,
refFormActionTemplate: this.elRoot.getAttribute('data-ref-form-action-template')!,
dropdownFixedText: this.elRoot.getAttribute('data-dropdown-fixed-text')!,
showTabBranches: shouldShowTabBranches,
showTabTags: this.elRoot.getAttribute('data-show-tab-tags') === 'true',
allowCreateNewRef: this.elRoot.getAttribute('data-allow-create-new-ref') === 'true',
Expand Down Expand Up @@ -92,7 +95,7 @@ export default defineComponent({
}).length;
},
createNewRefFormActionUrl() {
return `${this.currentRepoLink}/branches/_new/${this.currentRefType}/${pathEscapeSegments(this.currentRefShortName)}`;
return `${this.currentRepoLink}/branches/_new/${this.currentRefType}/${pathEscapeSegments(this.currentRefShortName!)}`;
},
},
watch: {
Expand Down
14 changes: 7 additions & 7 deletions web_src/js/components/RepoContributors.vue
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export default defineComponent({
user.max_contribution_type = 0;
const filteredWeeks = user.weeks.filter((week: Record<string, number>) => {
const oneWeek = 7 * 24 * 60 * 60 * 1000;
if (week.week >= this.xAxisMin - oneWeek && week.week <= this.xAxisMax + oneWeek) {
if (week.week >= this.xAxisMin! - oneWeek && week.week <= this.xAxisMax! + oneWeek) {
user.total_commits += week.commits;
user.total_additions += week.additions;
user.total_deletions += week.deletions;
Expand Down Expand Up @@ -238,8 +238,8 @@ export default defineComponent({
},

updateOtherCharts({chart}: {chart: Chart}, reset: boolean = false) {
const minVal = Number(chart.options.scales.x.min);
const maxVal = Number(chart.options.scales.x.max);
const minVal = Number(chart.options.scales?.x?.min);
const maxVal = Number(chart.options.scales?.x?.max);
if (reset) {
this.xAxisMin = this.xAxisStart;
this.xAxisMax = this.xAxisEnd;
Expand Down Expand Up @@ -302,8 +302,8 @@ export default defineComponent({
},
scales: {
x: {
min: this.xAxisMin,
max: this.xAxisMax,
min: this.xAxisMin ?? undefined,
max: this.xAxisMax ?? undefined,
type: 'time',
grid: {
display: false,
Expand Down Expand Up @@ -334,7 +334,7 @@ export default defineComponent({
<div class="ui header tw-flex tw-items-center tw-justify-between">
<div>
<relative-time
v-if="xAxisMin > 0"
v-if="xAxisMin && xAxisMin > 0"
format="datetime"
year="numeric"
month="short"
Expand All @@ -346,7 +346,7 @@ export default defineComponent({
</relative-time>
{{ isLoading ? locale.loadingTitle : errorText ? locale.loadingTitleFailed: "-" }}
<relative-time
v-if="xAxisMax > 0"
v-if="xAxisMax && xAxisMax > 0"
format="datetime"
year="numeric"
month="short"
Expand Down
14 changes: 7 additions & 7 deletions web_src/js/components/RepoFileSearch.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script lang="ts" setup>
import { ref, computed, watch, nextTick, useTemplateRef, onMounted, onUnmounted } from 'vue';
import {ref, computed, watch, nextTick, useTemplateRef, onMounted, onUnmounted, type ShallowRef} from 'vue';
import {generateElemId} from '../utils/dom.ts';
import { GET } from '../modules/fetch.ts';
import { filterRepoFilesWeighted } from '../features/repo-findfile.ts';
import { pathEscapeSegments } from '../utils/url.ts';
import { SvgIcon } from '../svg.ts';
import {GET} from '../modules/fetch.ts';
import {filterRepoFilesWeighted} from '../features/repo-findfile.ts';
import {pathEscapeSegments} from '../utils/url.ts';
import {SvgIcon} from '../svg.ts';
import {throttle} from 'throttle-debounce';

const props = defineProps({
Expand All @@ -15,8 +15,8 @@ const props = defineProps({
placeholder: { type: String, required: true },
});

const refElemInput = useTemplateRef<HTMLInputElement>('searchInput');
const refElemPopup = useTemplateRef<HTMLElement>('searchPopup');
const refElemInput = useTemplateRef('searchInput') as Readonly<ShallowRef<HTMLInputElement>>;
const refElemPopup = useTemplateRef('searchPopup') as Readonly<ShallowRef<HTMLDivElement>>;

const searchQuery = ref('');
const allFiles = ref<string[]>([]);
Expand Down
6 changes: 3 additions & 3 deletions web_src/js/components/ViewFileTree.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts" setup>
import ViewFileTreeItem from './ViewFileTreeItem.vue';
import {onMounted, useTemplateRef} from 'vue';
import {onMounted, useTemplateRef, type ShallowRef} from 'vue';
import {createViewFileTreeStore} from './ViewFileTreeStore.ts';

const elRoot = useTemplateRef('elRoot');
const elRoot = useTemplateRef('elRoot') as Readonly<ShallowRef<HTMLDivElement>>;;

const props = defineProps({
repoLink: {type: String, required: true},
Expand All @@ -24,7 +24,7 @@ onMounted(async () => {

<template>
<div class="view-file-tree-items" ref="elRoot">
<ViewFileTreeItem v-for="item in store.rootFiles" :key="item.name" :item="item" :store="store"/>
<ViewFileTreeItem v-for="item in store.rootFiles" :key="item.entryName" :item="item" :store="store"/>
</div>
</template>

Expand Down
2 changes: 1 addition & 1 deletion web_src/js/components/ViewFileTreeItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {isPlainClick} from '../utils/dom.ts';
import {shallowRef} from 'vue';
import {type createViewFileTreeStore} from './ViewFileTreeStore.ts';

type Item = {
export type Item = {
entryName: string;
entryMode: 'blob' | 'exec' | 'tree' | 'commit' | 'symlink' | 'unknown';
entryIcon: string;
Expand Down
Loading