mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Update eslint to v9 (#35485)
Update eslint and all plugins. Many plugins still do not ship type definitions so I had to add stubs. Also, I had to put a few typescript error expectations because if some unknown error in the types. `eslint-plugin-no-jquery` is disabled because it's not compatible with eslint 9 flat config (https://github.com/wikimedia/eslint-plugin-no-jquery/issues/311).
This commit is contained in:
		
							
								
								
									
										1005
									
								
								.eslintrc.cjs
									
									
									
									
									
								
							
							
						
						
									
										1005
									
								
								.eslintrc.cjs
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										6
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
									
									
									
									
								
							| @@ -162,7 +162,7 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(DIST) | ||||
| GO_DIRS := build cmd models modules routers services tests | ||||
| WEB_DIRS := web_src/js web_src/css | ||||
|  | ||||
| ESLINT_FILES := web_src/js tools *.ts *.cjs tests/e2e | ||||
| ESLINT_FILES := web_src/js tools *.ts tests/e2e | ||||
| STYLELINT_FILES := web_src/css web_src/js/components/*.vue | ||||
| SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) templates options/locale/locale_en-US.ini .github $(filter-out CHANGELOG.md, $(wildcard *.go *.md *.yml *.yaml *.toml)) $(filter-out tools/misspellings.csv, $(wildcard tools/*)) | ||||
| EDITORCONFIG_FILES := templates .github/workflows options/locale/locale_en-US.ini | ||||
| @@ -346,12 +346,12 @@ lint-backend-fix: lint-go-fix lint-go-gitea-vet lint-editorconfig ## lint backen | ||||
|  | ||||
| .PHONY: lint-js | ||||
| lint-js: node_modules ## lint js files | ||||
| 	$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --ext js,ts,vue $(ESLINT_FILES) | ||||
| 	$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --flag unstable_native_nodejs_ts_config $(ESLINT_FILES) | ||||
| 	$(NODE_VARS) pnpm exec vue-tsc | ||||
|  | ||||
| .PHONY: lint-js-fix | ||||
| lint-js-fix: node_modules ## lint js files and fix issues | ||||
| 	$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --ext js,ts,vue $(ESLINT_FILES) --fix | ||||
| 	$(NODE_VARS) pnpm exec eslint --color --max-warnings=0 --flag unstable_native_nodejs_ts_config $(ESLINT_FILES) --fix | ||||
| 	$(NODE_VARS) pnpm exec vue-tsc | ||||
|  | ||||
| .PHONY: lint-css | ||||
|   | ||||
							
								
								
									
										1029
									
								
								eslint.config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1029
									
								
								eslint.config.ts
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										15
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								package.json
									
									
									
									
									
								
							| @@ -69,7 +69,7 @@ | ||||
|     "@eslint-community/eslint-plugin-eslint-comments": "4.5.0", | ||||
|     "@playwright/test": "1.55.0", | ||||
|     "@stoplight/spectral-cli": "6.15.0", | ||||
|     "@stylistic/eslint-plugin-js": "3.1.0", | ||||
|     "@stylistic/eslint-plugin": "5.3.1", | ||||
|     "@stylistic/stylelint-plugin": "4.0.0", | ||||
|     "@types/codemirror": "5.60.16", | ||||
|     "@types/dropzone": "5.7.9", | ||||
| @@ -82,24 +82,24 @@ | ||||
|     "@types/throttle-debounce": "5.0.2", | ||||
|     "@types/tinycolor2": "1.4.6", | ||||
|     "@types/toastify-js": "1.12.4", | ||||
|     "@typescript-eslint/eslint-plugin": "8.43.0", | ||||
|     "@typescript-eslint/parser": "8.43.0", | ||||
|     "@vitejs/plugin-vue": "6.0.1", | ||||
|     "@vitest/eslint-plugin": "1.3.9", | ||||
|     "eslint": "8.57.0", | ||||
|     "eslint": "9.35.0", | ||||
|     "eslint-import-resolver-typescript": "4.4.4", | ||||
|     "eslint-plugin-array-func": "4.0.0", | ||||
|     "eslint-plugin-github": "5.0.2", | ||||
|     "eslint-plugin-array-func": "5.0.2", | ||||
|     "eslint-plugin-github": "6.0.0", | ||||
|     "eslint-plugin-import-x": "4.16.1", | ||||
|     "eslint-plugin-no-jquery": "3.1.1", | ||||
|     "eslint-plugin-no-use-extend-native": "0.5.0", | ||||
|     "eslint-plugin-no-use-extend-native": "0.7.2", | ||||
|     "eslint-plugin-playwright": "2.2.2", | ||||
|     "eslint-plugin-regexp": "2.10.0", | ||||
|     "eslint-plugin-sonarjs": "3.0.5", | ||||
|     "eslint-plugin-unicorn": "56.0.1", | ||||
|     "eslint-plugin-unicorn": "61.0.2", | ||||
|     "eslint-plugin-vue": "10.4.0", | ||||
|     "eslint-plugin-vue-scoped-css": "2.12.0", | ||||
|     "eslint-plugin-wc": "3.0.1", | ||||
|     "globals": "16.4.0", | ||||
|     "happy-dom": "18.0.1", | ||||
|     "markdownlint-cli": "0.45.0", | ||||
|     "material-icon-theme": "5.27.0", | ||||
| @@ -112,6 +112,7 @@ | ||||
|     "stylelint-value-no-unknown-custom-properties": "6.0.1", | ||||
|     "svgo": "4.0.0", | ||||
|     "type-fest": "4.41.0", | ||||
|     "typescript-eslint": "8.43.0", | ||||
|     "updates": "16.7.0", | ||||
|     "vite-string-plugin": "1.4.6", | ||||
|     "vitest": "3.2.4", | ||||
|   | ||||
							
								
								
									
										789
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										789
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										27
									
								
								types.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								types.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1,29 @@ | ||||
| declare module '@techknowlogick/license-checker-webpack-plugin' { | ||||
|   const plugin: any; | ||||
|   export = plugin | ||||
|   export = plugin; | ||||
| } | ||||
| declare module 'eslint-plugin-no-use-extend-native' { | ||||
|   import type {Eslint} from 'eslint'; | ||||
|   const plugin: Eslint.Plugin; | ||||
|   export = plugin; | ||||
| } | ||||
| declare module 'eslint-plugin-array-func' { | ||||
|   import type {Eslint} from 'eslint'; | ||||
|   const plugin: Eslint.Plugin; | ||||
|   export = plugin; | ||||
| } | ||||
| declare module 'eslint-plugin-github' { | ||||
|   import type {Eslint} from 'eslint'; | ||||
|   const plugin: Eslint.Plugin; | ||||
|   export = plugin; | ||||
| } | ||||
| declare module 'eslint-plugin-no-jquery' { | ||||
|   import type {Eslint} from 'eslint'; | ||||
|   const plugin: Eslint.Plugin; | ||||
|   export = plugin; | ||||
| } | ||||
| declare module '@eslint-community/eslint-plugin-eslint-comments' { | ||||
|   import type {Eslint} from 'eslint'; | ||||
|   const plugin: Eslint.Plugin; | ||||
|   export = plugin; | ||||
| } | ||||
|   | ||||
| @@ -5,12 +5,6 @@ export default { | ||||
|     '@mcaptcha/vanilla-glue', // breaking changes in rc versions need to be handled | ||||
|     '@stylistic/eslint-plugin-js', // need to migrate to eslint 9 | ||||
|     'cropperjs', // need to migrate to v2 but v2 is not compatible with v1 | ||||
|     'eslint', // need to migrate to eslint flat config first | ||||
|     'eslint-plugin-array-func', // need to migrate to eslint flat config first | ||||
|     'eslint-plugin-github', // need to migrate to eslint 9 - https://github.com/github/eslint-plugin-github/issues/585 | ||||
|     'eslint-plugin-no-use-extend-native', // need to migrate to eslint flat config first | ||||
|     'eslint-plugin-unicorn', // need to migrate to eslint 9 | ||||
|     'eslint-plugin-vitest', // need to migrate to eslint flat config first | ||||
|     'tailwindcss', // need to migrate | ||||
|   ], | ||||
| } satisfies Config; | ||||
|   | ||||
| @@ -153,7 +153,7 @@ export default defineComponent({ | ||||
|       return -1; | ||||
|     }, | ||||
|     getActiveItem() { | ||||
|       const el = this.$refs[`listItem${this.activeItemIndex}`]; // eslint-disable-line no-jquery/variable-pattern | ||||
|       const el = this.$refs[`listItem${this.activeItemIndex}`]; | ||||
|       // @ts-expect-error - el is unknown type | ||||
|       return (el && el.length) ? el[0] : null; | ||||
|     }, | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import {pathEscapeSegments} from '../utils/url.ts'; | ||||
| import {createElementFromHTML} from '../utils/dom.ts'; | ||||
| import {html} from '../utils/html.ts'; | ||||
|  | ||||
| export function createViewFileTreeStore(props: { repoLink: string, treePath: string, currentRefNameSubURL: string}) { | ||||
| export function createViewFileTreeStore(props: {repoLink: string, treePath: string, currentRefNameSubURL: string}) { | ||||
|   const store = reactive({ | ||||
|     rootFiles: [], | ||||
|     selectedItem: props.treePath, | ||||
|   | ||||
| @@ -19,7 +19,7 @@ type EditorConfig = { | ||||
|   trim_trailing_whitespace?: boolean, | ||||
|   insert_final_newline?: boolean, | ||||
|   root?: boolean, | ||||
| } | ||||
| }; | ||||
|  | ||||
| const languagesByFilename: Record<string, string> = {}; | ||||
| const languagesByExt: Record<string, string> = {}; | ||||
|   | ||||
| @@ -112,7 +112,7 @@ function onHidePanelClick(el: HTMLElement, e: MouseEvent) { | ||||
| export type ElementWithAssignableProperties = { | ||||
|   getAttribute: (name: string) => string | null; | ||||
|   setAttribute: (name: string, value: string) => void; | ||||
| } & Record<string, any> | ||||
| } & Record<string, any>; | ||||
|  | ||||
| export function assignElementProperty(el: ElementWithAssignableProperties, kebabName: string, val: string) { | ||||
|   const camelizedName = camelize(kebabName); | ||||
|   | ||||
| @@ -9,7 +9,7 @@ type ConfirmModalOptions = { | ||||
|   header?: string; | ||||
|   content?: string; | ||||
|   confirmButtonColor?: 'primary' | 'red' | 'green' | 'blue'; | ||||
| } | ||||
| }; | ||||
|  | ||||
| export function createConfirmModal({header = '', content = '', confirmButtonColor = 'primary'}:ConfirmModalOptions = {}): HTMLElement { | ||||
|   const headerHtml = header ? html`<div class="header">${header}</div>` : ''; | ||||
|   | ||||
| @@ -4,7 +4,7 @@ type CropperOpts = { | ||||
|   container: HTMLElement, | ||||
|   imageSource: HTMLImageElement, | ||||
|   fileInput: HTMLInputElement, | ||||
| } | ||||
| }; | ||||
|  | ||||
| async function initCompCropper({container, fileInput, imageSource}: CropperOpts) { | ||||
|   const {default: Cropper} = await import(/* webpackChunkName: "cropperjs" */'cropperjs'); | ||||
|   | ||||
| @@ -169,7 +169,7 @@ test('EditorMarkdown', () => { | ||||
|   type ValueWithCursor = string | { | ||||
|     value: string; | ||||
|     pos: number; | ||||
|   } | ||||
|   }; | ||||
|   const testInput = (input: ValueWithCursor, result: ValueWithCursor) => { | ||||
|     const intputValue = typeof input === 'string' ? input : input.value; | ||||
|     const inputPos = typeof input === 'string' ? intputValue.length : input.pos; | ||||
|   | ||||
| @@ -18,7 +18,7 @@ type TextareaValueSelection = { | ||||
|   value: string; | ||||
|   selStart: number; | ||||
|   selEnd: number; | ||||
| } | ||||
| }; | ||||
|  | ||||
| function handleIndentSelection(textarea: HTMLTextAreaElement, e: KeyboardEvent) { | ||||
|   const selStart = textarea.selectionStart; | ||||
| @@ -65,14 +65,14 @@ function handleIndentSelection(textarea: HTMLTextAreaElement, e: KeyboardEvent) | ||||
| type MarkdownHandleIndentionResult = { | ||||
|   handled: boolean; | ||||
|   valueSelection?: TextareaValueSelection; | ||||
| } | ||||
| }; | ||||
|  | ||||
| type TextLinesBuffer = { | ||||
|   lines: string[]; | ||||
|   lengthBeforePosLine: number; | ||||
|   posLineIndex: number; | ||||
|   inlinePos: number | ||||
| } | ||||
| }; | ||||
|  | ||||
| export function textareaSplitLines(value: string, pos: number): TextLinesBuffer { | ||||
|   const lines = value.split('\n'); | ||||
|   | ||||
| @@ -64,7 +64,7 @@ function initRepoIssueLabelFilter(elDropdown: HTMLElement) { | ||||
|     selectedLabelIds.add(`${Math.abs(parseInt(id))}`); // "labels" contains negative ids, which are excluded | ||||
|   } | ||||
|  | ||||
|   const excludeLabel = (e: MouseEvent|KeyboardEvent, item: Element) => { | ||||
|   const excludeLabel = (e: MouseEvent | KeyboardEvent, item: Element) => { | ||||
|     e.preventDefault(); | ||||
|     e.stopPropagation(); | ||||
|     const labelId = item.getAttribute('data-label-id'); | ||||
|   | ||||
| @@ -4,13 +4,13 @@ type Processor = (el: HTMLElement) => string | HTMLElement | void; | ||||
|  | ||||
| type Processors = { | ||||
|   [tagName: string]: Processor; | ||||
| } | ||||
| }; | ||||
|  | ||||
| type ProcessorContext = { | ||||
|   elementIsFirst: boolean; | ||||
|   elementIsLast: boolean; | ||||
|   listNestingLevel: number; | ||||
| } | ||||
| }; | ||||
|  | ||||
| function prepareProcessors(ctx:ProcessorContext): Processors { | ||||
|   const processors: Processors = { | ||||
|   | ||||
| @@ -15,7 +15,7 @@ export type DiffTreeEntry = { | ||||
|   Children: DiffTreeEntry[], | ||||
|   FileIcon: string, | ||||
|   ParentEntry?: DiffTreeEntry, | ||||
| } | ||||
| }; | ||||
|  | ||||
| type DiffFileTreeData = { | ||||
|   TreeRoot: DiffTreeEntry, | ||||
| @@ -28,7 +28,7 @@ type DiffFileTree = { | ||||
|   fullNameMap?: Record<string, DiffTreeEntry> | ||||
|   fileTreeIsVisible: boolean; | ||||
|   selectedItem: string; | ||||
| } | ||||
| }; | ||||
|  | ||||
| let diffTreeStoreReactive: Reactive<DiffFileTree>; | ||||
| export function diffTreeStore() { | ||||
|   | ||||
| @@ -14,5 +14,4 @@ export function linkLabelAndInput(label: Element, input: Element) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| // eslint-disable-next-line no-jquery/variable-pattern | ||||
| export const fomanticQuery = $; | ||||
|   | ||||
| @@ -348,7 +348,7 @@ export function hideScopedEmptyDividers(container: Element) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| function onResponseKeepSelectedItem(dropdown: typeof $|HTMLElement, selectedValue: string) { | ||||
| function onResponseKeepSelectedItem(dropdown: typeof $ | HTMLElement, selectedValue: string) { | ||||
|   // There is a bug in fomantic dropdown when using "apiSettings" to fetch data | ||||
|   // * when there is a selected item, the dropdown insists on hiding the selected one from the list: | ||||
|   // * in the "filter" function: ('[data-value="'+value+'"]').addClass(className.filtered) | ||||
|   | ||||
| @@ -15,7 +15,7 @@ type ToastLevels = { | ||||
|     background: string, | ||||
|     duration: number, | ||||
|   } | ||||
| } | ||||
| }; | ||||
|  | ||||
| const levels: ToastLevels = { | ||||
|   info: { | ||||
| @@ -40,7 +40,7 @@ type ToastOpts = { | ||||
|   preventDuplicates?: boolean | string, | ||||
| } & Options; | ||||
|  | ||||
| type ToastifyElement = HTMLElement & {_giteaToastifyInstance?: Toast }; | ||||
| type ToastifyElement = HTMLElement & {_giteaToastifyInstance?: Toast}; | ||||
|  | ||||
| /** See https://github.com/apvarun/toastify-js#api for options */ | ||||
| function showToast(message: string, level: Intent, {gravity, position, duration, useHtmlBody, preventDuplicates = true, ...other}: ToastOpts = {}): Toast { | ||||
|   | ||||
| @@ -7,4 +7,4 @@ export type FileRenderPlugin = { | ||||
|  | ||||
|   // render file content | ||||
|   render: (container: HTMLElement, fileUrl: string, options?: any) => Promise<void>; | ||||
| } | ||||
| }; | ||||
|   | ||||
| @@ -166,7 +166,7 @@ export type SvgName = keyof typeof svgs; | ||||
| //  most of the SVG icons in assets couldn't be used directly. | ||||
|  | ||||
| // retrieve an HTML string for given SVG icon name, size and additional classes | ||||
| export function svg(name: SvgName, size = 16, classNames?: string|string[]): string { | ||||
| export function svg(name: SvgName, size = 16, classNames?: string | string[]): string { | ||||
|   const className = Array.isArray(classNames) ? classNames.join(' ') : classNames; | ||||
|   if (!(name in svgs)) throw new Error(`Unknown SVG icon: ${name}`); | ||||
|   if (size === 16 && !className) return svgs[name]; | ||||
|   | ||||
| @@ -4,7 +4,7 @@ export type MentionValue = { | ||||
|   name: string, | ||||
|   fullname: string, | ||||
|   avatar: string, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export type Config = { | ||||
|   appUrl: string, | ||||
| @@ -20,7 +20,7 @@ export type Config = { | ||||
|   mentionValues?: MentionValue[], | ||||
|   mermaidMaxSourceCharacters: number, | ||||
|   i18n: Record<string, string>, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export type IntervalId = ReturnType<typeof setInterval>; | ||||
|  | ||||
| @@ -35,21 +35,21 @@ export type RequestOpts = { | ||||
| export type RepoOwnerPathInfo = { | ||||
|   ownerName: string, | ||||
|   repoName: string, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export type IssuePathInfo = { | ||||
|   ownerName: string, | ||||
|   repoName: string, | ||||
|   pathType: string, | ||||
|   indexString?: string, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export type IssuePageInfo = { | ||||
|   repoLink: string, | ||||
|   repoId: number, | ||||
|   issueNumber: number, | ||||
|   issueDependencySearchType: string, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export type Issue = { | ||||
|   id: number; | ||||
| @@ -65,6 +65,6 @@ export type Issue = { | ||||
| export type FomanticInitFunction = { | ||||
|   settings?: Record<string, any>, | ||||
|   (...args: any[]): any, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export type GitRefType = 'branch' | 'tag'; | ||||
|   | ||||
| @@ -7,7 +7,7 @@ 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>; }; | ||||
| 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) { | ||||
| @@ -322,7 +322,7 @@ export function createElementFromHTML<T extends HTMLElement>(htmlString: string) | ||||
|   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>, ...children: (Node | string)[]): HTMLElement { | ||||
|   const el = document.createElement(tagName); | ||||
|   for (const [key, value] of Object.entries(attrs || {})) { | ||||
|     if (value === undefined || value === null) continue; | ||||
|   | ||||
| @@ -117,7 +117,7 @@ test('GlobCompiler', async () => { | ||||
|   for (const c of golangCases) { | ||||
|     const compiled = globCompile(c.pattern, c.separators); | ||||
|     const msg = `pattern: ${c.pattern}, input: ${c.input}, separators: ${c.separators || '(none)'}, compiled: ${compiled.regexpPattern}`; | ||||
|     // eslint-disable-next-line @vitest/valid-expect -- Unlike Jest, Vitest supports a message as the second argument | ||||
|     // eslint-disable-next-line vitest/valid-expect -- Unlike Jest, Vitest supports a message as the second argument | ||||
|     expect(compiled.regexp.test(c.input), msg).toBe(c.matched); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -23,7 +23,7 @@ export function html(tmpl: TemplateStringsArray, ...parts: Array<any>): string { | ||||
|   return output; | ||||
| } | ||||
|  | ||||
| export function htmlRaw(s: string|TemplateStringsArray, ...tmplParts: Array<any>): rawObject { | ||||
| export function htmlRaw(s: string | TemplateStringsArray, ...tmplParts: Array<any>): rawObject { | ||||
|   if (typeof s === 'string') { | ||||
|     if (tmplParts.length !== 0) throw new Error("either htmlRaw('str') or htmlRaw`tmpl`"); | ||||
|     return new rawObject(s); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| type PngChunk = { | ||||
|   name: string, | ||||
|   data: Uint8Array, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export async function pngChunks(blob: Blob): Promise<PngChunk[]> { | ||||
|   const uint8arr = new Uint8Array(await blob.arrayBuffer()); | ||||
| @@ -27,7 +27,7 @@ export async function pngChunks(blob: Blob): Promise<PngChunk[]> { | ||||
| type ImageInfo = { | ||||
|   width?: number, | ||||
|   dppx?: number, | ||||
| } | ||||
| }; | ||||
|  | ||||
| /** decode a image and try to obtain width and dppx. It will never throw but instead | ||||
|  *  return default values. */ | ||||
|   | ||||
| @@ -47,11 +47,11 @@ export type DayData = { | ||||
|   additions: number, | ||||
|   deletions: number, | ||||
|   commits: number, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export type DayDataObject = { | ||||
|   [timestamp: string]: DayData, | ||||
| } | ||||
| }; | ||||
|  | ||||
| export function fillEmptyStartDaysWithZeroes(startDays: number[], data: DayDataObject): DayData[] { | ||||
|   const result: Record<string, any> = {}; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user